Add 'qcom/opensource/display-drivers/' from commit '5ff96e683134b356ebe6c37069b4197034502ef9'
git-subtree-dir: qcom/opensource/display-drivers git-subtree-mainline:2d61911ef6
git-subtree-split:5ff96e6831
Change-Id: repo: https://git.codelinaro.org/clo/la/platform/vendor/opensource/display-drivers tag: DISPLAY.LA.4.0.r2-07600-lanai.0
This commit is contained in:
commit
1841c0f616
40
qcom/opensource/display-drivers/Android.bp
Normal file
40
qcom/opensource/display-drivers/Android.bp
Normal file
@ -0,0 +1,40 @@
|
||||
headers_src = [
|
||||
"include/uapi/*/**/*.h",
|
||||
]
|
||||
|
||||
display_headers_out = [
|
||||
"display/drm/msm_drm_pp.h",
|
||||
"display/drm/sde_drm.h",
|
||||
"display/hdcp/msm_hdmi_hdcp_mgr.h",
|
||||
"display/media/mmm_color_fmt.h",
|
||||
"display/media/msm_sde_rotator.h",
|
||||
]
|
||||
|
||||
display_kernel_headers_verbose = "--verbose "
|
||||
genrule {
|
||||
name: "qti_generate_display_kernel_headers",
|
||||
tools: [
|
||||
"headers_install.sh",
|
||||
"unifdef"
|
||||
],
|
||||
tool_files: [
|
||||
"display_kernel_headers.py",
|
||||
],
|
||||
srcs: headers_src,
|
||||
cmd: "python3 $(location display_kernel_headers.py) " +
|
||||
display_kernel_headers_verbose +
|
||||
"--header_arch arm64 " +
|
||||
"--gen_dir $(genDir) " +
|
||||
"--display_include_uapi $(locations include/uapi/*/**/*.h) " +
|
||||
"--unifdef $(location unifdef) " +
|
||||
"--headers_install $(location headers_install.sh)",
|
||||
out: display_headers_out,
|
||||
}
|
||||
|
||||
cc_library_headers {
|
||||
name: "qti_display_kernel_headers",
|
||||
generated_headers: ["qti_generate_display_kernel_headers"],
|
||||
export_generated_headers: ["qti_generate_display_kernel_headers"],
|
||||
vendor: true,
|
||||
recovery_available: true
|
||||
}
|
12
qcom/opensource/display-drivers/Android.mk
Normal file
12
qcom/opensource/display-drivers/Android.mk
Normal file
@ -0,0 +1,12 @@
|
||||
# Android makefile for display kernel modules
|
||||
DISPLAY_DLKM_ENABLE := true
|
||||
ifeq ($(TARGET_KERNEL_DLKM_DISABLE), true)
|
||||
ifeq ($(TARGET_KERNEL_DLKM_DISPLAY_OVERRIDE), false)
|
||||
DISPLAY_DLKM_ENABLE := false
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(DISPLAY_DLKM_ENABLE), true)
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(LOCAL_PATH)/msm/Android.mk
|
||||
endif
|
72
qcom/opensource/display-drivers/BUILD.bazel
Normal file
72
qcom/opensource/display-drivers/BUILD.bazel
Normal file
@ -0,0 +1,72 @@
|
||||
load("//build/kernel/kleaf:kernel.bzl", "ddk_headers")
|
||||
|
||||
package(
|
||||
default_visibility = [
|
||||
"//visibility:public"],
|
||||
)
|
||||
|
||||
ddk_headers(
|
||||
name = "linux_includes",
|
||||
hdrs = glob([
|
||||
"include/linux/*.h",
|
||||
]),
|
||||
includes = ["include"]
|
||||
)
|
||||
|
||||
ddk_headers(
|
||||
name = "uapi_headers",
|
||||
hdrs = glob([
|
||||
"include/uapi/display/drm/*.h",
|
||||
"include/uapi/display/hdcp/*.h",
|
||||
"include/uapi/display/media/*.h",
|
||||
]),
|
||||
includes = ["include/uapi/display"]
|
||||
)
|
||||
|
||||
ddk_headers(
|
||||
name = "dp_headers",
|
||||
hdrs = glob([
|
||||
"msm/dp/*.h",
|
||||
]),
|
||||
includes = ["msm/dp"]
|
||||
)
|
||||
|
||||
ddk_headers(
|
||||
name = "dsi_headers",
|
||||
hdrs = glob([
|
||||
"msm/dsi/*.h",
|
||||
]),
|
||||
includes = ["msm/dsi"]
|
||||
)
|
||||
|
||||
ddk_headers(
|
||||
name = "sde_headers",
|
||||
hdrs = glob([
|
||||
"msm/sde/*.h",
|
||||
]),
|
||||
includes = ["msm/sde"]
|
||||
)
|
||||
|
||||
ddk_headers(
|
||||
name = "rotator_headers",
|
||||
hdrs = glob([
|
||||
"rotator/*.h",
|
||||
]),
|
||||
includes = ["rotator"]
|
||||
)
|
||||
|
||||
ddk_headers(
|
||||
name = "msm_headers",
|
||||
hdrs = glob([
|
||||
"msm/*.h",
|
||||
]),
|
||||
includes = ["msm"]
|
||||
)
|
||||
|
||||
ddk_headers(
|
||||
name = "display_drivers_headers",
|
||||
hdrs = [ ":linux_includes", ":uapi_headers", ":msm_headers",":dp_headers",":dsi_headers",":sde_headers",":rotator_headers"]
|
||||
)
|
||||
|
||||
load(":target.bzl", "define_display_target")
|
||||
define_display_target()
|
@ -0,0 +1,58 @@
|
||||
QTI Snapdragon Display Engine (SDE) DP-MST sideband message emulation driver
|
||||
|
||||
Required properties:
|
||||
- compatible: "qcom,dp-mst-sim"
|
||||
|
||||
Each child node represents a port at root branch, with properties:
|
||||
- qcom,mode-h-active: A u32 property defines the horizontal active size.
|
||||
- qcom,mode-h-front-porch: A u32 property defines the horizontal front porch.
|
||||
- qcom,mode-h-pulse-width: A u32 property defines the horizontal pulse.
|
||||
- qcom,mode-h-back-porch: A u32 property defines the horizontal back porch.
|
||||
- qcom,mode-h-active-high: A boolean property if horizontal polarity is high.
|
||||
- qcom,mode-v-active: A u32 property defines the vertical active size.
|
||||
- qcom,mode-v-front-porch: A u32 property defines the vertical front portch.
|
||||
- qcom,mode-v-pulse-width: A u32 property defines the vertical pulse width.
|
||||
- qcom,mode-v-back-porch: A u32 property defines the vertical back porch.
|
||||
- qcom,mode-v-active-high: A boolean property if vertical polarity is high.
|
||||
- qcom,mode-refresh-rate: A u32 property defines vertial refresh rate.
|
||||
- qcom,mode-clock-in-khz: A u32 property defines clock in kHz.
|
||||
|
||||
Example:
|
||||
|
||||
/ {
|
||||
...
|
||||
|
||||
sde_dp_mst_sim: qcom,dp-mst-sim {
|
||||
compatible = "qcom,dp-mst-sim";
|
||||
|
||||
port@0 {
|
||||
qcom,mode-h-active = <1920>;
|
||||
qcom,mode-h-front-porch = <88>;
|
||||
qcom,mode-h-pulse-width = <44>;
|
||||
qcom,mode-h-back-porch = <148>;
|
||||
qcom,mode-h-active-high;
|
||||
qcom,mode-v-active = <1080>;
|
||||
qcom,mode-v-front-porch = <4>;
|
||||
qcom,mode-v-pulse-width = <5>;
|
||||
qcom,mode-v-back-porch = <36>;
|
||||
qcom,mode-v-active-high;
|
||||
qcom,mode-refresh-rate = <60>;
|
||||
qcom,mode-clock-in-khz = <148500>;
|
||||
};
|
||||
|
||||
port@1 {
|
||||
qcom,mode-h-active = <1920>;
|
||||
qcom,mode-h-front-porch = <88>;
|
||||
qcom,mode-h-pulse-width = <44>;
|
||||
qcom,mode-h-back-porch = <148>;
|
||||
qcom,mode-h-active-high;
|
||||
qcom,mode-v-active = <1080>;
|
||||
qcom,mode-v-front-porch = <4>;
|
||||
qcom,mode-v-pulse-width = <5>;
|
||||
qcom,mode-v-back-porch = <36>;
|
||||
qcom,mode-v-active-high;
|
||||
qcom,mode-refresh-rate = <60>;
|
||||
qcom,mode-clock-in-khz = <148500>;
|
||||
};
|
||||
};
|
||||
};
|
12
qcom/opensource/display-drivers/Kbuild
Normal file
12
qcom/opensource/display-drivers/Kbuild
Normal file
@ -0,0 +1,12 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
ifeq ($(DISPLAY_ROOT),)
|
||||
DISPLAY_ROOT=$(srctree)/techpack/display
|
||||
endif
|
||||
|
||||
LINUXINCLUDE += \
|
||||
-I$(DISPLAY_ROOT)/include/uapi/display \
|
||||
-I$(DISPLAY_ROOT)/include
|
||||
USERINCLUDE += -I$(DISPLAY_ROOT)/include/uapi/display
|
||||
|
||||
obj-$(CONFIG_DRM_MSM) += msm/
|
16
qcom/opensource/display-drivers/Makefile
Normal file
16
qcom/opensource/display-drivers/Makefile
Normal file
@ -0,0 +1,16 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
KBUILD_OPTIONS+= DISPLAY_ROOT=$(KERNEL_SRC)/$(M)
|
||||
|
||||
all:
|
||||
$(MAKE) -C $(KERNEL_SRC) M=$(M) modules $(KBUILD_OPTIONS)
|
||||
|
||||
modules_install:
|
||||
$(MAKE) INSTALL_MOD_STRIP=1 -C $(KERNEL_SRC) M=$(M) modules_install
|
||||
|
||||
%:
|
||||
$(MAKE) -C $(KERNEL_SRC) M=$(M) $@ $(KBUILD_OPTIONS)
|
||||
|
||||
clean:
|
||||
rm -f *.o *.ko *.mod.c *.mod.o *~ .*.cmd Module.symvers
|
||||
rm -rf .tmp_versions
|
24
qcom/opensource/display-drivers/Makefile.am
Normal file
24
qcom/opensource/display-drivers/Makefile.am
Normal file
@ -0,0 +1,24 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
DISPLAY_ROOT=$(ROOTDIR)display/vendor/qcom/opensource/display-drivers
|
||||
CONFIG_DRM_MSM=$(MODULE_DRM_MSM)
|
||||
KBUILD_OPTIONS := DISPLAY_ROOT=$(DISPLAY_ROOT) CONFIG_DRM_MSM=$(CONFIG_DRM_MSM)
|
||||
|
||||
ifeq ($(TARGET_SUPPORT),genericarmv8)
|
||||
KBUILD_OPTIONS += CONFIG_ARCH_PINEAPPLE=y
|
||||
endif
|
||||
|
||||
obj-m += msm/
|
||||
|
||||
all:
|
||||
$(MAKE) -C $(KERNEL_SRC) M=$(M) modules $(KBUILD_OPTIONS)
|
||||
|
||||
modules_install:
|
||||
$(MAKE) INSTALL_MOD_STRIP=1 -C $(KERNEL_SRC) M=$(M) modules_install
|
||||
|
||||
%:
|
||||
$(MAKE) -C $(KERNEL_SRC) M=$(M) $@ $(KBUILD_OPTIONS)
|
||||
|
||||
clean:
|
||||
rm -f *.o *.ko *.mod.c *.mod.o *~ .*.cmd Module.symvers
|
||||
rm -rf .tmp_versions
|
93
qcom/opensource/display-drivers/NOTICE
Normal file
93
qcom/opensource/display-drivers/NOTICE
Normal file
@ -0,0 +1,93 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (C) 2013 Red Hat
|
||||
* Copyright (C) 2014 Red Hat
|
||||
* Copyright (C) 2016 Red Hat
|
||||
* Author: Rob Clark <robdclark@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Keith Packard
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008 Keith Packard
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Copyright © 2014 Red Hatt.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
1030
qcom/opensource/display-drivers/bridge-drivers/lt9611uxc.c
Normal file
1030
qcom/opensource/display-drivers/bridge-drivers/lt9611uxc.c
Normal file
File diff suppressed because it is too large
Load Diff
18
qcom/opensource/display-drivers/config/augen3disp.conf
Normal file
18
qcom/opensource/display-drivers/config/augen3disp.conf
Normal file
@ -0,0 +1,18 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
export CONFIG_DRM_MSM=y
|
||||
export CONFIG_DRM_MSM_SDE=y
|
||||
export CONFIG_SYNC_FILE=y
|
||||
export CONFIG_DRM_MSM_DSI=y
|
||||
export CONFIG_DRM_MSM_DP=n
|
||||
export CONFIG_DRM_MSM_DP_MST=n
|
||||
export CONFIG_QCOM_MDSS_PLL=y
|
||||
export CONFIG_DRM_SDE_RSC=n
|
||||
export CONFIG_DRM_SDE_WB=n
|
||||
export CONFIG_DRM_MSM_REGISTER_LOGGING=n
|
||||
export CONFIG_SDE_RECOVERY_MANAGER=n
|
||||
export CONFIG_DRM_SDE_SHD=n
|
||||
export CONFIG_DRM_SDE_SHP=n
|
||||
export CONFIG_DRM_SDE_ROI_MISR=n
|
||||
export CONFIG_DRM_MSM_LEASE=n
|
||||
export CONFIG_DISPLAY_BUILD=m
|
22
qcom/opensource/display-drivers/config/augen3dispconf.h
Normal file
22
qcom/opensource/display-drivers/config/augen3dispconf.h
Normal file
@ -0,0 +1,22 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#define CONFIG_DRM_MSM 1
|
||||
#define CONFIG_DRM_MSM_SDE 1
|
||||
#define CONFIG_SYNC_FILE 1
|
||||
#define CONFIG_DRM_MSM_DSI 1
|
||||
#define CONFIG_DRM_MSM_DP 0
|
||||
#define CONFIG_DRM_MSM_DP_MST 0
|
||||
#define CONFIG_DRM_SDE_WB 0
|
||||
#define CONFIG_DRM_SDE_RSC 0
|
||||
#define CONFIG_DRM_MSM_REGISTER_LOGGING 0
|
||||
#define CONFIG_DRM_SDE_EVTLOG_DEBUG 1
|
||||
#define CONFIG_QCOM_MDSS_PLL 1
|
||||
#define CONFIG_GKI_DISPLAY 1
|
||||
#define CONFIG_MSM_EXT_DISPLAY 1
|
||||
#define CONFIG_DRM_SDE_ROI_MISR 0
|
||||
#define CONFIG_DRM_SDE_SHD 0
|
||||
#define CONFIG_DRM_SDE_SHP 0
|
||||
#define CONFIG_DRM_MSM_LEASE 0
|
16
qcom/opensource/display-drivers/config/bengaldisp.conf
Normal file
16
qcom/opensource/display-drivers/config/bengaldisp.conf
Normal file
@ -0,0 +1,16 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
# Copyright (c) 2019, The Linux Foundation. All rights reserved.
|
||||
|
||||
export CONFIG_DRM_MSM=y
|
||||
export CONFIG_DRM_MSM_SDE=y
|
||||
export CONFIG_SYNC_FILE=y
|
||||
export CONFIG_DRM_MSM_DSI=y
|
||||
export CONFIG_DRM_MSM_DP=n
|
||||
export CONFIG_QCOM_MDSS_DP_PLL=n
|
||||
export CONFIG_DSI_PARSER=y
|
||||
export CONFIG_DRM_SDE_WB=n
|
||||
export CONFIG_DRM_MSM_REGISTER_LOGGING=y
|
||||
export CONFIG_QCOM_MDSS_PLL=y
|
||||
export CONFIG_MSM_SDE_ROTATOR=y
|
||||
export CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
|
||||
export CONFIG_DRM_SDE_RSC=n
|
15
qcom/opensource/display-drivers/config/bengaldispconf.h
Normal file
15
qcom/opensource/display-drivers/config/bengaldispconf.h
Normal file
@ -0,0 +1,15 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#define CONFIG_DRM_MSM 1
|
||||
#define CONFIG_DRM_MSM_SDE 1
|
||||
#define CONFIG_SYNC_FILE 1
|
||||
#define CONFIG_DRM_MSM_DSI 1
|
||||
#define CONFIG_DSI_PARSER 1
|
||||
#define CONFIG_DRM_MSM_REGISTER_LOGGING 1
|
||||
#define CONFIG_DRM_SDE_EVTLOG_DEBUG 1
|
||||
#define CONFIG_QCOM_MDSS_PLL 1
|
||||
#define CONFIG_MSM_SDE_ROTATOR 1
|
||||
#define CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG 1
|
18
qcom/opensource/display-drivers/config/gki_holidisp.conf
Normal file
18
qcom/opensource/display-drivers/config/gki_holidisp.conf
Normal file
@ -0,0 +1,18 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
# Copyright (c) 2020, The Linux Foundation. All rights reserved.
|
||||
|
||||
export CONFIG_DRM_MSM=y
|
||||
export CONFIG_DRM_MSM_SDE=y
|
||||
export CONFIG_DRM_MSM_DP=n
|
||||
export CONFIG_DRM_MSM_DP_MST=n
|
||||
export CONFIG_SYNC_FILE=y
|
||||
export CONFIG_DRM_MSM_DSI=y
|
||||
export CONFIG_DSI_PARSER=y
|
||||
export CONFIG_DRM_SDE_WB=n
|
||||
export CONFIG_DRM_MSM_REGISTER_LOGGING=y
|
||||
export CONFIG_QCOM_MDSS_PLL=y
|
||||
export CONFIG_DRM_SDE_RSC=n
|
||||
export CONFIG_DISPLAY_BUILD=m
|
||||
export CONFIG_MSM_SDE_ROTATOR=y
|
||||
export CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
|
||||
export CONFIG_MSM_SDE_ROTATOR_INIT_ONLY=y
|
17
qcom/opensource/display-drivers/config/gki_holidispconf.h
Normal file
17
qcom/opensource/display-drivers/config/gki_holidispconf.h
Normal file
@ -0,0 +1,17 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#define CONFIG_DRM_MSM 1
|
||||
#define CONFIG_DRM_MSM_SDE 1
|
||||
#define CONFIG_SYNC_FILE 1
|
||||
#define CONFIG_DRM_MSM_DSI 1
|
||||
#define CONFIG_DSI_PARSER 1
|
||||
#define CONFIG_DRM_MSM_REGISTER_LOGGING 1
|
||||
#define CONFIG_DRM_SDE_EVTLOG_DEBUG 1
|
||||
#define CONFIG_QCOM_MDSS_PLL 1
|
||||
#define CONFIG_GKI_DISPLAY 1
|
||||
#define CONFIG_MSM_SDE_ROTATOR 1
|
||||
#define CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG 1
|
||||
#define CONFIG_MSM_SDE_ROTATOR_INIT_ONLY 1
|
18
qcom/opensource/display-drivers/config/gki_kalamadisp.conf
Normal file
18
qcom/opensource/display-drivers/config/gki_kalamadisp.conf
Normal file
@ -0,0 +1,18 @@
|
||||
export CONFIG_DRM_MSM=y
|
||||
export CONFIG_DRM_MSM_SDE=y
|
||||
export CONFIG_SYNC_FILE=y
|
||||
export CONFIG_DRM_MSM_DSI=y
|
||||
export CONFIG_DRM_MSM_DP=y
|
||||
export CONFIG_DRM_MSM_DP_MST=y
|
||||
export CONFIG_DSI_PARSER=y
|
||||
export CONFIG_QCOM_MDSS_PLL=y
|
||||
export CONFIG_DRM_SDE_RSC=y
|
||||
export CONFIG_DRM_SDE_WB=y
|
||||
export CONFIG_DRM_MSM_REGISTER_LOGGING=y
|
||||
export CONFIG_MSM_MMRM=y
|
||||
export CONFIG_DISPLAY_BUILD=m
|
||||
export CONFIG_HDCP_QSEECOM=y
|
||||
export CONFIG_DRM_SDE_VM=y
|
||||
export CONFIG_QTI_HW_FENCE=y
|
||||
export CONFIG_QCOM_SPEC_SYNC=y
|
||||
export CONFIG_QCOM_FSA4480_I2C=y
|
26
qcom/opensource/display-drivers/config/gki_kalamadispconf.h
Normal file
26
qcom/opensource/display-drivers/config/gki_kalamadispconf.h
Normal file
@ -0,0 +1,26 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#define CONFIG_DRM_MSM 1
|
||||
#define CONFIG_DRM_MSM_SDE 1
|
||||
#define CONFIG_SYNC_FILE 1
|
||||
#define CONFIG_DRM_MSM_DSI 1
|
||||
#define CONFIG_DRM_MSM_DP 1
|
||||
#define CONFIG_DRM_MSM_DP_MST 1
|
||||
#define CONFIG_DSI_PARSER 1
|
||||
#define CONFIG_DRM_SDE_WB 1
|
||||
#define CONFIG_DRM_SDE_RSC 1
|
||||
#define CONFIG_DRM_MSM_REGISTER_LOGGING 1
|
||||
#define CONFIG_MSM_MMRM 1
|
||||
#define CONFIG_DRM_SDE_EVTLOG_DEBUG 1
|
||||
#define CONFIG_QCOM_MDSS_PLL 1
|
||||
#define CONFIG_GKI_DISPLAY 1
|
||||
#define CONFIG_MSM_EXT_DISPLAY 1
|
||||
#define CONFIG_HDCP_QSEECOM 1
|
||||
#define CONFIG_DRM_SDE_VM 1
|
||||
#define CONFIG_QTI_HW_FENCE 1
|
||||
#define CONFIG_QCOM_SPEC_SYNC 1
|
||||
#define CONFIG_QCOM_FSA4480_I2C 1
|
@ -0,0 +1,10 @@
|
||||
export CONFIG_DRM_MSM=y
|
||||
export CONFIG_DRM_MSM_SDE=y
|
||||
export CONFIG_SYNC_FILE=y
|
||||
export CONFIG_DRM_MSM_DSI=y
|
||||
export CONFIG_DSI_PARSER=y
|
||||
export CONFIG_QCOM_MDSS_PLL=y
|
||||
export CONFIG_DRM_MSM_REGISTER_LOGGING=y
|
||||
export CONFIG_DISPLAY_BUILD=m
|
||||
export CONFIG_DRM_SDE_VM=y
|
||||
export CONFIG_DRM_LOW_MSM_MEM_FOOTPRINT=y
|
@ -0,0 +1,17 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#define CONFIG_DRM_MSM 1
|
||||
#define CONFIG_DRM_MSM_SDE 1
|
||||
#define CONFIG_SYNC_FILE 1
|
||||
#define CONFIG_DRM_MSM_DSI 1
|
||||
#define CONFIG_DSI_PARSER 1
|
||||
#define CONFIG_DRM_MSM_REGISTER_LOGGING 1
|
||||
#define CONFIG_DRM_SDE_EVTLOG_DEBUG 1
|
||||
#define CONFIG_QCOM_MDSS_PLL 1
|
||||
#define CONFIG_GKI_DISPLAY 1
|
||||
#define CONFIG_DRM_SDE_VM 1
|
||||
#define CONFIG_DRM_MSM_LOW_MEM_FOOTPRINT 1
|
12
qcom/opensource/display-drivers/config/gki_lahainadisp.conf
Normal file
12
qcom/opensource/display-drivers/config/gki_lahainadisp.conf
Normal file
@ -0,0 +1,12 @@
|
||||
export CONFIG_DRM_MSM=y
|
||||
export CONFIG_DRM_MSM_SDE=y
|
||||
export CONFIG_SYNC_FILE=y
|
||||
export CONFIG_DRM_MSM_DSI=y
|
||||
export CONFIG_DRM_MSM_DP=y
|
||||
export CONFIG_DRM_MSM_DP_MST=y
|
||||
export CONFIG_DSI_PARSER=y
|
||||
export CONFIG_QCOM_MDSS_PLL=y
|
||||
export CONFIG_DRM_SDE_WB=y
|
||||
export CONFIG_DRM_MSM_REGISTER_LOGGING=y
|
||||
export CONFIG_DRM_SDE_RSC=y
|
||||
export CONFIG_DISPLAY_BUILD=m
|
19
qcom/opensource/display-drivers/config/gki_lahainadispconf.h
Normal file
19
qcom/opensource/display-drivers/config/gki_lahainadispconf.h
Normal file
@ -0,0 +1,19 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#define CONFIG_DRM_MSM 1
|
||||
#define CONFIG_DRM_MSM_SDE 1
|
||||
#define CONFIG_SYNC_FILE 1
|
||||
#define CONFIG_DRM_MSM_DSI 1
|
||||
#define CONFIG_DRM_MSM_DP 1
|
||||
#define CONFIG_DRM_MSM_DP_MST 1
|
||||
#define CONFIG_DSI_PARSER 1
|
||||
#define CONFIG_DRM_SDE_WB 1
|
||||
#define CONFIG_DRM_MSM_REGISTER_LOGGING 1
|
||||
#define CONFIG_DRM_SDE_EVTLOG_DEBUG 1
|
||||
#define CONFIG_QCOM_MDSS_PLL 1
|
||||
#define CONFIG_GKI_DISPLAY 1
|
||||
#define CONFIG_DRM_SDE_RSC 1
|
||||
|
11
qcom/opensource/display-drivers/config/gki_neodisp.conf
Normal file
11
qcom/opensource/display-drivers/config/gki_neodisp.conf
Normal file
@ -0,0 +1,11 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
# Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
|
||||
export CONFIG_DRM_MSM=y
|
||||
export CONFIG_DRM_MSM_SDE=y
|
||||
export CONFIG_SYNC_FILE=y
|
||||
export CONFIG_DRM_MSM_DSI=y
|
||||
export CONFIG_DSI_PARSER=y
|
||||
export CONFIG_QCOM_MDSS_PLL=y
|
||||
export CONFIG_DRM_MSM_REGISTER_LOGGING=y
|
||||
export CONFIG_DISPLAY_BUILD=m
|
14
qcom/opensource/display-drivers/config/gki_neodispconf.h
Normal file
14
qcom/opensource/display-drivers/config/gki_neodispconf.h
Normal file
@ -0,0 +1,14 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#define CONFIG_DRM_MSM 1
|
||||
#define CONFIG_DRM_MSM_SDE 1
|
||||
#define CONFIG_SYNC_FILE 1
|
||||
#define CONFIG_DRM_MSM_DSI 1
|
||||
#define CONFIG_DSI_PARSER 1
|
||||
#define CONFIG_DRM_MSM_REGISTER_LOGGING 1
|
||||
#define CONFIG_DRM_SDE_EVTLOG_DEBUG 1
|
||||
#define CONFIG_QCOM_MDSS_PLL 1
|
||||
#define CONFIG_GKI_DISPLAY 1
|
16
qcom/opensource/display-drivers/config/gki_niobedisp.conf
Normal file
16
qcom/opensource/display-drivers/config/gki_niobedisp.conf
Normal file
@ -0,0 +1,16 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
export CONFIG_DRM_MSM=y
|
||||
export CONFIG_DRM_MSM_SDE=y
|
||||
export CONFIG_SYNC_FILE=y
|
||||
export CONFIG_DRM_MSM_DSI=y
|
||||
export CONFIG_DSI_PARSER=y
|
||||
export CONFIG_QCOM_MDSS_PLL=y
|
||||
export CONFIG_DRM_SDE_RSC=y
|
||||
export CONFIG_DRM_SDE_WB=y
|
||||
export CONFIG_DRM_MSM_REGISTER_LOGGING=y
|
||||
export CONFIG_MSM_MMRM=y
|
||||
export CONFIG_DISPLAY_BUILD=m
|
||||
export CONFIG_DRM_SDE_SYSTEM_SLEEP_DISABLE=y
|
||||
export CONFIG_DRM_SDE_IPCC=y
|
||||
export CONFIG_DRM_SDE_MINIDUMP_DISABLE=y
|
22
qcom/opensource/display-drivers/config/gki_niobedispconf.h
Normal file
22
qcom/opensource/display-drivers/config/gki_niobedispconf.h
Normal file
@ -0,0 +1,22 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#define CONFIG_DRM_MSM 1
|
||||
#define CONFIG_DRM_MSM_SDE 1
|
||||
#define CONFIG_SYNC_FILE 1
|
||||
#define CONFIG_DRM_MSM_DSI 1
|
||||
#define CONFIG_DSI_PARSER 1
|
||||
#define CONFIG_DRM_SDE_WB 1
|
||||
#define CONFIG_DRM_SDE_RSC 1
|
||||
#define CONFIG_DRM_MSM_REGISTER_LOGGING 1
|
||||
#define CONFIG_MSM_MMRM 1
|
||||
#define CONFIG_DRM_SDE_EVTLOG_DEBUG 1
|
||||
#define CONFIG_QCOM_MDSS_PLL 1
|
||||
#define CONFIG_GKI_DISPLAY 1
|
||||
#define CONFIG_MSM_EXT_DISPLAY 1
|
||||
#define CONFIG_DRM_SDE_SYSTEM_SLEEP_DISABLE 1
|
||||
#define CONFIG_DRM_SDE_IPCC 1
|
||||
#define CONFIG_DRM_SDE_MINIDUMP_DISABLE 1
|
11
qcom/opensource/display-drivers/config/gki_parrotdisp.conf
Normal file
11
qcom/opensource/display-drivers/config/gki_parrotdisp.conf
Normal file
@ -0,0 +1,11 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
export CONFIG_DRM_MSM=y
|
||||
export CONFIG_DRM_MSM_SDE=y
|
||||
export CONFIG_SYNC_FILE=y
|
||||
export CONFIG_DRM_MSM_DSI=y
|
||||
export CONFIG_DSI_PARSER=y
|
||||
export CONFIG_DRM_SDE_WB=y
|
||||
export CONFIG_QCOM_MDSS_PLL=y
|
||||
export CONFIG_DRM_MSM_REGISTER_LOGGING=y
|
||||
export CONFIG_DISPLAY_BUILD=m
|
16
qcom/opensource/display-drivers/config/gki_parrotdispconf.h
Normal file
16
qcom/opensource/display-drivers/config/gki_parrotdispconf.h
Normal file
@ -0,0 +1,16 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#define CONFIG_DRM_MSM 1
|
||||
#define CONFIG_DRM_MSM_SDE 1
|
||||
#define CONFIG_SYNC_FILE 1
|
||||
#define CONFIG_DRM_MSM_DSI 1
|
||||
#define CONFIG_DSI_PARSER 1
|
||||
#define CONFIG_DRM_SDE_WB 1
|
||||
#define CONFIG_DRM_MSM_REGISTER_LOGGING 1
|
||||
#define CONFIG_DRM_SDE_EVTLOG_DEBUG 1
|
||||
#define CONFIG_QCOM_MDSS_PLL 1
|
||||
#define CONFIG_GKI_DISPLAY 1
|
@ -0,0 +1,18 @@
|
||||
export CONFIG_DRM_MSM=y
|
||||
export CONFIG_DRM_MSM_SDE=y
|
||||
export CONFIG_SYNC_FILE=y
|
||||
export CONFIG_DRM_MSM_DSI=y
|
||||
export CONFIG_DRM_MSM_DP=y
|
||||
export CONFIG_DRM_MSM_DP_MST=y
|
||||
export CONFIG_DSI_PARSER=y
|
||||
export CONFIG_QCOM_MDSS_PLL=y
|
||||
export CONFIG_DRM_SDE_RSC=y
|
||||
export CONFIG_DRM_SDE_WB=y
|
||||
export CONFIG_DRM_MSM_REGISTER_LOGGING=y
|
||||
export CONFIG_MSM_MMRM=y
|
||||
export CONFIG_DISPLAY_BUILD=m
|
||||
export CONFIG_HDCP_QSEECOM=y
|
||||
export CONFIG_DRM_SDE_VM=y
|
||||
export CONFIG_QTI_HW_FENCE=y
|
||||
export CONFIG_QCOM_SPEC_SYNC=y
|
||||
export CONFIG_QCOM_WCD939X_I2C=y
|
@ -0,0 +1,26 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#define CONFIG_DRM_MSM 1
|
||||
#define CONFIG_DRM_MSM_SDE 1
|
||||
#define CONFIG_SYNC_FILE 1
|
||||
#define CONFIG_DRM_MSM_DSI 1
|
||||
#define CONFIG_DRM_MSM_DP 1
|
||||
#define CONFIG_DRM_MSM_DP_MST 1
|
||||
#define CONFIG_DSI_PARSER 1
|
||||
#define CONFIG_DRM_SDE_WB 1
|
||||
#define CONFIG_DRM_SDE_RSC 1
|
||||
#define CONFIG_DRM_MSM_REGISTER_LOGGING 1
|
||||
#define CONFIG_MSM_MMRM 1
|
||||
#define CONFIG_DRM_SDE_EVTLOG_DEBUG 1
|
||||
#define CONFIG_QCOM_MDSS_PLL 1
|
||||
#define CONFIG_GKI_DISPLAY 1
|
||||
#define CONFIG_MSM_EXT_DISPLAY 1
|
||||
#define CONFIG_HDCP_QSEECOM 1
|
||||
#define CONFIG_DRM_SDE_VM 1
|
||||
#define CONFIG_QTI_HW_FENCE 1
|
||||
#define CONFIG_QCOM_SPEC_SYNC 1
|
||||
#define CONFIG_QCOM_WCD939X_I2C 1
|
@ -0,0 +1,10 @@
|
||||
export CONFIG_DRM_MSM=y
|
||||
export CONFIG_DRM_MSM_SDE=y
|
||||
export CONFIG_SYNC_FILE=y
|
||||
export CONFIG_DRM_MSM_DSI=y
|
||||
export CONFIG_DSI_PARSER=y
|
||||
export CONFIG_QCOM_MDSS_PLL=y
|
||||
export CONFIG_DRM_MSM_REGISTER_LOGGING=y
|
||||
export CONFIG_DISPLAY_BUILD=m
|
||||
export CONFIG_DRM_SDE_VM=y
|
||||
export CONFIG_DRM_LOW_MSM_MEM_FOOTPRINT=y
|
@ -0,0 +1,17 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#define CONFIG_DRM_MSM 1
|
||||
#define CONFIG_DRM_MSM_SDE 1
|
||||
#define CONFIG_SYNC_FILE 1
|
||||
#define CONFIG_DRM_MSM_DSI 1
|
||||
#define CONFIG_DSI_PARSER 1
|
||||
#define CONFIG_DRM_MSM_REGISTER_LOGGING 1
|
||||
#define CONFIG_DRM_SDE_EVTLOG_DEBUG 1
|
||||
#define CONFIG_QCOM_MDSS_PLL 1
|
||||
#define CONFIG_GKI_DISPLAY 1
|
||||
#define CONFIG_DRM_SDE_VM 1
|
||||
#define CONFIG_DRM_MSM_LOW_MEM_FOOTPRINT 1
|
11
qcom/opensource/display-drivers/config/gki_pittidisp.conf
Normal file
11
qcom/opensource/display-drivers/config/gki_pittidisp.conf
Normal file
@ -0,0 +1,11 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
export CONFIG_DRM_MSM=y
|
||||
export CONFIG_DRM_MSM_SDE=y
|
||||
export CONFIG_SYNC_FILE=y
|
||||
export CONFIG_DRM_MSM_DSI=y
|
||||
export CONFIG_DSI_PARSER=y
|
||||
export CONFIG_QCOM_MDSS_PLL=y
|
||||
export CONFIG_DRM_MSM_REGISTER_LOGGING=y
|
||||
export CONFIG_DISPLAY_BUILD=m
|
||||
export CONFIG_QCOM_SPEC_SYNC=y
|
17
qcom/opensource/display-drivers/config/gki_pittidispconf.h
Normal file
17
qcom/opensource/display-drivers/config/gki_pittidispconf.h
Normal file
@ -0,0 +1,17 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#define CONFIG_DRM_MSM 1
|
||||
#define CONFIG_DRM_MSM_SDE 1
|
||||
#define CONFIG_SYNC_FILE 1
|
||||
#define CONFIG_DRM_MSM_DSI 1
|
||||
#define CONFIG_DSI_PARSER 1
|
||||
#define CONFIG_DRM_MSM_REGISTER_LOGGING 1
|
||||
#define CONFIG_DRM_SDE_EVTLOG_DEBUG 1
|
||||
#define CONFIG_QCOM_MDSS_PLL 1
|
||||
#define CONFIG_GKI_DISPLAY 1
|
||||
#define CONFIG_MSM_EXT_DISPLAY 1
|
||||
#define CONFIG_QCOM_SPEC_SYNC 1
|
15
qcom/opensource/display-drivers/config/gki_waipiodisp.conf
Normal file
15
qcom/opensource/display-drivers/config/gki_waipiodisp.conf
Normal file
@ -0,0 +1,15 @@
|
||||
export CONFIG_DRM_MSM=y
|
||||
export CONFIG_DRM_MSM_SDE=y
|
||||
export CONFIG_SYNC_FILE=y
|
||||
export CONFIG_DRM_MSM_DSI=y
|
||||
export CONFIG_DRM_MSM_DP=y
|
||||
export CONFIG_DRM_MSM_DP_MST=y
|
||||
export CONFIG_DSI_PARSER=y
|
||||
export CONFIG_QCOM_MDSS_PLL=y
|
||||
export CONFIG_DRM_SDE_RSC=y
|
||||
export CONFIG_DRM_SDE_WB=y
|
||||
export CONFIG_DRM_MSM_REGISTER_LOGGING=y
|
||||
export CONFIG_MSM_MMRM=y
|
||||
export CONFIG_DISPLAY_BUILD=m
|
||||
export CONFIG_DRM_SDE_VM=y
|
||||
export CONFIG_HDCP_QSEECOM=y
|
22
qcom/opensource/display-drivers/config/gki_waipiodispconf.h
Normal file
22
qcom/opensource/display-drivers/config/gki_waipiodispconf.h
Normal file
@ -0,0 +1,22 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#define CONFIG_DRM_MSM 1
|
||||
#define CONFIG_DRM_MSM_SDE 1
|
||||
#define CONFIG_SYNC_FILE 1
|
||||
#define CONFIG_DRM_MSM_DSI 1
|
||||
#define CONFIG_DRM_MSM_DP 1
|
||||
#define CONFIG_DRM_MSM_DP_MST 1
|
||||
#define CONFIG_DSI_PARSER 1
|
||||
#define CONFIG_DRM_SDE_WB 1
|
||||
#define CONFIG_DRM_SDE_RSC 1
|
||||
#define CONFIG_DRM_MSM_REGISTER_LOGGING 1
|
||||
#define CONFIG_MSM_MMRM 1
|
||||
#define CONFIG_DRM_SDE_EVTLOG_DEBUG 1
|
||||
#define CONFIG_QCOM_MDSS_PLL 1
|
||||
#define CONFIG_GKI_DISPLAY 1
|
||||
#define CONFIG_MSM_EXT_DISPLAY 1
|
||||
#define CONFIG_DRM_SDE_VM 1
|
||||
#define CONFIG_HDCP_QSEECOM 1
|
@ -0,0 +1,10 @@
|
||||
export CONFIG_DRM_MSM=y
|
||||
export CONFIG_DRM_MSM_SDE=y
|
||||
export CONFIG_SYNC_FILE=y
|
||||
export CONFIG_DRM_MSM_DSI=y
|
||||
export CONFIG_DSI_PARSER=y
|
||||
export CONFIG_QCOM_MDSS_PLL=y
|
||||
export CONFIG_DRM_MSM_REGISTER_LOGGING=y
|
||||
export CONFIG_DISPLAY_BUILD=m
|
||||
export CONFIG_DRM_SDE_VM=y
|
||||
export CONFIG_DRM_LOW_MSM_MEM_FOOTPRINT=y
|
@ -0,0 +1,16 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#define CONFIG_DRM_MSM 1
|
||||
#define CONFIG_DRM_MSM_SDE 1
|
||||
#define CONFIG_SYNC_FILE 1
|
||||
#define CONFIG_DRM_MSM_DSI 1
|
||||
#define CONFIG_DSI_PARSER 1
|
||||
#define CONFIG_DRM_MSM_REGISTER_LOGGING 1
|
||||
#define CONFIG_DRM_SDE_EVTLOG_DEBUG 1
|
||||
#define CONFIG_QCOM_MDSS_PLL 1
|
||||
#define CONFIG_GKI_DISPLAY 1
|
||||
#define CONFIG_DRM_SDE_VM 1
|
||||
#define CONFIG_DRM_MSM_LOW_MEM_FOOTPRINT 1
|
17
qcom/opensource/display-drivers/config/holidisp.conf
Normal file
17
qcom/opensource/display-drivers/config/holidisp.conf
Normal file
@ -0,0 +1,17 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
# Copyright (c) 2020, The Linux Foundation. All rights reserved.
|
||||
|
||||
export CONFIG_DRM_MSM=y
|
||||
export CONFIG_DRM_MSM_SDE=y
|
||||
export CONFIG_DRM_MSM_DP=n
|
||||
export CONFIG_DRM_MSM_DP_MST=n
|
||||
export CONFIG_SYNC_FILE=y
|
||||
export CONFIG_DRM_MSM_DSI=y
|
||||
export CONFIG_DSI_PARSER=y
|
||||
export CONFIG_DRM_SDE_WB=n
|
||||
export CONFIG_DRM_MSM_REGISTER_LOGGING=y
|
||||
export CONFIG_QCOM_MDSS_PLL=y
|
||||
export CONFIG_DRM_SDE_RSC=n
|
||||
export CONFIG_MSM_SDE_ROTATOR=y
|
||||
export CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
|
||||
export CONFIG_DISPLAY_BUILD=y
|
15
qcom/opensource/display-drivers/config/holidispconf.h
Normal file
15
qcom/opensource/display-drivers/config/holidispconf.h
Normal file
@ -0,0 +1,15 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#define CONFIG_DRM_MSM 1
|
||||
#define CONFIG_DRM_MSM_SDE 1
|
||||
#define CONFIG_SYNC_FILE 1
|
||||
#define CONFIG_DRM_MSM_DSI 1
|
||||
#define CONFIG_DSI_PARSER 1
|
||||
#define CONFIG_DRM_MSM_REGISTER_LOGGING 1
|
||||
#define CONFIG_DRM_SDE_EVTLOG_DEBUG 1
|
||||
#define CONFIG_QCOM_MDSS_PLL 1
|
||||
#define CONFIG_MSM_SDE_ROTATOR 1
|
||||
#define CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG 1
|
13
qcom/opensource/display-drivers/config/konadisp.conf
Normal file
13
qcom/opensource/display-drivers/config/konadisp.conf
Normal file
@ -0,0 +1,13 @@
|
||||
export CONFIG_DRM_MSM=y
|
||||
export CONFIG_DRM_MSM_SDE=y
|
||||
export CONFIG_SYNC_FILE=y
|
||||
export CONFIG_DRM_MSM_DSI=y
|
||||
export CONFIG_DRM_MSM_DP=y
|
||||
export CONFIG_QCOM_MDSS_DP_PLL=y
|
||||
export CONFIG_DSI_PARSER=y
|
||||
export CONFIG_DRM_SDE_WB=y
|
||||
export CONFIG_DRM_MSM_REGISTER_LOGGING=y
|
||||
export CONFIG_QCOM_MDSS_PLL=y
|
||||
export CONFIG_MSM_SDE_ROTATOR=y
|
||||
export CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
|
||||
export CONFIG_DRM_SDE_RSC=y
|
20
qcom/opensource/display-drivers/config/konadispconf.h
Normal file
20
qcom/opensource/display-drivers/config/konadispconf.h
Normal file
@ -0,0 +1,20 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#define CONFIG_DRM_MSM 1
|
||||
#define CONFIG_DRM_MSM_SDE 1
|
||||
#define CONFIG_SYNC_FILE 1
|
||||
#define CONFIG_DRM_MSM_DSI 1
|
||||
#define CONFIG_DRM_MSM_DP 1
|
||||
#define CONFIG_QCOM_MDSS_DP_PLL 1
|
||||
#define CONFIG_DSI_PARSER 1
|
||||
#define CONFIG_DRM_SDE_WB 1
|
||||
#define CONFIG_DRM_MSM_REGISTER_LOGGING 1
|
||||
#define CONFIG_DRM_SDE_EVTLOG_DEBUG 1
|
||||
#define CONFIG_QCOM_MDSS_PLL 1
|
||||
#define CONFIG_MSM_SDE_ROTATOR 1
|
||||
#define CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG 1
|
||||
#define CONFIG_DRM_SDE_RSC 1
|
||||
|
13
qcom/opensource/display-drivers/config/lahainadisp.conf
Normal file
13
qcom/opensource/display-drivers/config/lahainadisp.conf
Normal file
@ -0,0 +1,13 @@
|
||||
export CONFIG_DRM_MSM=y
|
||||
export CONFIG_DRM_MSM_SDE=y
|
||||
export CONFIG_DRM_MSM_DP=y
|
||||
export CONFIG_DRM_MSM_DP_MST=y
|
||||
export CONFIG_SYNC_FILE=y
|
||||
export CONFIG_DRM_MSM_DSI=y
|
||||
export CONFIG_DSI_PARSER=y
|
||||
export CONFIG_DRM_SDE_WB=y
|
||||
export CONFIG_DRM_MSM_REGISTER_LOGGING=y
|
||||
export CONFIG_QCOM_MDSS_PLL=y
|
||||
export CONFIG_DRM_SDE_RSC=y
|
||||
export CONFIG_DISPLAY_BUILD=y
|
||||
export CONFIG_DRM_SDE_VM=y
|
18
qcom/opensource/display-drivers/config/lahainadispconf.h
Normal file
18
qcom/opensource/display-drivers/config/lahainadispconf.h
Normal file
@ -0,0 +1,18 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#define CONFIG_DRM_MSM 1
|
||||
#define CONFIG_DRM_MSM_DP 1
|
||||
#define CONFIG_DRM_MSM_DP_MST 1
|
||||
#define CONFIG_DRM_MSM_SDE 1
|
||||
#define CONFIG_SYNC_FILE 1
|
||||
#define CONFIG_DRM_MSM_DSI 1
|
||||
#define CONFIG_DSI_PARSER 1
|
||||
#define CONFIG_DRM_SDE_WB 1
|
||||
#define CONFIG_DRM_MSM_REGISTER_LOGGING 1
|
||||
#define CONFIG_DRM_SDE_EVTLOG_DEBUG 1
|
||||
#define CONFIG_QCOM_MDSS_PLL 1
|
||||
#define CONFIG_DRM_SDE_RSC 1
|
||||
#define CONFIG_DRM_SDE_VM 1
|
13
qcom/opensource/display-drivers/config/saipdisp.conf
Normal file
13
qcom/opensource/display-drivers/config/saipdisp.conf
Normal file
@ -0,0 +1,13 @@
|
||||
export CONFIG_DRM_MSM=y
|
||||
export CONFIG_DRM_MSM_SDE=y
|
||||
export CONFIG_SYNC_FILE=y
|
||||
export CONFIG_DRM_MSM_DSI=y
|
||||
export CONFIG_DRM_MSM_DP=y
|
||||
export CONFIG_QCOM_MDSS_DP_PLL=y
|
||||
export CONFIG_DSI_PARSER=y
|
||||
export CONFIG_DRM_SDE_WB=y
|
||||
export CONFIG_DRM_MSM_REGISTER_LOGGING=y
|
||||
export CONFIG_QCOM_MDSS_PLL=y
|
||||
export CONFIG_MSM_SDE_ROTATOR=y
|
||||
export CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
|
||||
export CONFIG_DRM_SDE_RSC=y
|
19
qcom/opensource/display-drivers/config/saipdispconf.h
Normal file
19
qcom/opensource/display-drivers/config/saipdispconf.h
Normal file
@ -0,0 +1,19 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#define CONFIG_DRM_MSM 1
|
||||
#define CONFIG_DRM_MSM_SDE 1
|
||||
#define CONFIG_SYNC_FILE 1
|
||||
#define CONFIG_DRM_MSM_DSI 1
|
||||
#define CONFIG_DRM_MSM_DP 1
|
||||
#define CONFIG_QCOM_MDSS_DP_PLL 1
|
||||
#define CONFIG_DSI_PARSER 1
|
||||
#define CONFIG_DRM_SDE_WB 1
|
||||
#define CONFIG_DRM_MSM_REGISTER_LOGGING 1
|
||||
#define CONFIG_DRM_SDE_EVTLOG_DEBUG 1
|
||||
#define CONFIG_QCOM_MDSS_PLL 1
|
||||
#define CONFIG_MSM_SDE_ROTATOR 1
|
||||
#define CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG 1
|
||||
#define CONFIG_DRM_SDE_RSC 1
|
15
qcom/opensource/display-drivers/display_driver_board.mk
Normal file
15
qcom/opensource/display-drivers/display_driver_board.mk
Normal file
@ -0,0 +1,15 @@
|
||||
#SPDX-License-Identifier: GPL-2.0-only
|
||||
DISPLAY_DLKM_ENABLE := true
|
||||
ifeq ($(TARGET_KERNEL_DLKM_DISABLE), true)
|
||||
ifeq ($(TARGET_KERNEL_DLKM_DISPLAY_OVERRIDE), false)
|
||||
DISPLAY_DLKM_ENABLE := false
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(DISPLAY_DLKM_ENABLE), true)
|
||||
ifeq ($(call is-board-platform-in-list,$(TARGET_BOARD_PLATFORM)),true)
|
||||
BOARD_VENDOR_KERNEL_MODULES += $(KERNEL_MODULES_OUT)/msm_drm.ko
|
||||
BOARD_VENDOR_RAMDISK_KERNEL_MODULES += $(KERNEL_MODULES_OUT)/msm_drm.ko
|
||||
BOARD_VENDOR_RAMDISK_RECOVERY_KERNEL_MODULES_LOAD += $(KERNEL_MODULES_OUT)/msm_drm.ko
|
||||
endif
|
||||
endif
|
124
qcom/opensource/display-drivers/display_driver_build.bzl
Normal file
124
qcom/opensource/display-drivers/display_driver_build.bzl
Normal file
@ -0,0 +1,124 @@
|
||||
load("//build/kernel/kleaf:kernel.bzl", "ddk_module", "ddk_submodule")
|
||||
load("//build/bazel_common_rules/dist:dist.bzl", "copy_to_dist_dir")
|
||||
|
||||
def _register_module_to_map(module_map, name, path, config_option, srcs, config_srcs, deps, config_deps):
|
||||
processed_config_srcs = {}
|
||||
nested_config = {}
|
||||
processed_config_deps = {}
|
||||
|
||||
for config_src_name in config_srcs:
|
||||
config_src = config_srcs[config_src_name]
|
||||
|
||||
if type(config_src) == "list":
|
||||
processed_config_srcs[config_src_name] = {True: config_src}
|
||||
else:
|
||||
processed_config_srcs[config_src_name] = config_src
|
||||
if type(config_src) == "dict":
|
||||
nested_config = config_src
|
||||
|
||||
for nested_src, nest_name in nested_config.items():
|
||||
if nested_src == True:
|
||||
processed_config_srcs[config_src_name] = {True: nest_name}
|
||||
else:
|
||||
processed_config_srcs[nested_src] = {True: nest_name}
|
||||
|
||||
for config_deps_name in config_deps:
|
||||
config_dep = config_deps[config_deps_name]
|
||||
|
||||
if type(config_dep) == "list":
|
||||
processed_config_deps[config_deps_name] = {True: config_dep}
|
||||
else:
|
||||
processed_config_deps[config_deps_name] = config_dep
|
||||
module = struct(
|
||||
name = name,
|
||||
path = path,
|
||||
srcs = srcs,
|
||||
config_srcs = processed_config_srcs,
|
||||
config_option = config_option,
|
||||
deps = deps,
|
||||
config_deps = processed_config_deps
|
||||
)
|
||||
|
||||
module_map[name] = module
|
||||
|
||||
def _get_config_choices(map, options):
|
||||
choices = []
|
||||
for option in map:
|
||||
choices.extend(map[option].get(option in options,[]))
|
||||
return choices
|
||||
|
||||
def _get_kernel_build_options(modules, config_options):
|
||||
all_options = {option: True for option in config_options}
|
||||
all_options = all_options | {module.config_option: True for module in modules if module.config_option}
|
||||
return all_options
|
||||
|
||||
def _get_kernel_build_module_srcs(module, options, formatter):
|
||||
srcs = module.srcs + _get_config_choices(module.config_srcs, options)
|
||||
module_path = "{}/".format(module.path) if module.path else ""
|
||||
return ["{}{}".format(module_path, formatter(src)) for src in srcs]
|
||||
|
||||
def _get_kernel_build_module_deps(module, options, formatter):
|
||||
deps = module.deps + _get_config_choices(module.config_deps, options)
|
||||
return [formatter(dep) for dep in deps]
|
||||
|
||||
def display_module_entry(hdrs = []):
|
||||
module_map = {}
|
||||
|
||||
def register(name, path = None, config_option = None, srcs = [], config_srcs = {}, deps = [], config_deps = {}):
|
||||
_register_module_to_map(module_map, name, path, config_option, srcs, config_srcs, deps, config_deps)
|
||||
return struct(
|
||||
register = register,
|
||||
get = module_map.get,
|
||||
hdrs = hdrs,
|
||||
module_map = module_map
|
||||
)
|
||||
|
||||
def define_target_variant_modules(target, variant, registry, modules, config_options = [], lunch_target=None):
|
||||
|
||||
kernel_build_hdr = "{}_{}".format(target, variant)
|
||||
kernel_build_label = "//msm-kernel:{}".format(kernel_build_hdr)
|
||||
|
||||
if lunch_target != None:
|
||||
kernel_build = "{}_{}_{}".format(target, variant, lunch_target)
|
||||
else:
|
||||
kernel_build = "{}_{}".format(target, variant)
|
||||
|
||||
modules = [registry.get(module_name) for module_name in modules]
|
||||
options = _get_kernel_build_options(modules, config_options)
|
||||
build_print = lambda message : print("{}: {}".format(kernel_build, message))
|
||||
formatter = lambda s : s.replace("%b", kernel_build).replace("%t", target)
|
||||
formatter_hdr = lambda s : s.replace("%b", kernel_build_hdr).replace("%t", target)
|
||||
headers = ["//msm-kernel:all_headers"] + registry.hdrs
|
||||
all_module_rules = []
|
||||
|
||||
for module in modules:
|
||||
rule_name = "{}_{}".format(kernel_build, module.name)
|
||||
module_srcs = _get_kernel_build_module_srcs(module, options, formatter)
|
||||
print(rule_name)
|
||||
if not module_srcs:
|
||||
continue
|
||||
|
||||
ddk_submodule(
|
||||
name = rule_name,
|
||||
srcs = module_srcs,
|
||||
out = "{}.ko".format(module.name),
|
||||
deps = headers + _get_kernel_build_module_deps(module, options, formatter_hdr),
|
||||
local_defines = options.keys(),
|
||||
)
|
||||
all_module_rules.append(rule_name)
|
||||
|
||||
ddk_module(
|
||||
name = "{}_display_drivers".format(kernel_build),
|
||||
kernel_build = kernel_build_label,
|
||||
deps = all_module_rules,
|
||||
)
|
||||
copy_to_dist_dir(
|
||||
name = "{}_display_drivers_dist".format(kernel_build),
|
||||
data = [":{}_display_drivers".format(kernel_build)],
|
||||
dist_dir = "out/target/product/{}/dlkm/lib/modules/".format(target),
|
||||
flat = True,
|
||||
wipe_dist_dir = False,
|
||||
allow_duplicate_filenames = False,
|
||||
mode_overrides = {"**/*": "644"},
|
||||
log = "info",
|
||||
)
|
14
qcom/opensource/display-drivers/display_driver_product.mk
Normal file
14
qcom/opensource/display-drivers/display_driver_product.mk
Normal file
@ -0,0 +1,14 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
DISPLAY_DLKM_ENABLE := true
|
||||
ifeq ($(TARGET_KERNEL_DLKM_DISABLE), true)
|
||||
ifeq ($(TARGET_KERNEL_DLKM_DISPLAY_OVERRIDE), false)
|
||||
DISPLAY_DLKM_ENABLE := false
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(DISPLAY_DLKM_ENABLE), true)
|
||||
PRODUCT_PACKAGES += msm_drm.ko
|
||||
endif
|
||||
|
||||
DISPLAY_MODULES_DRIVER := msm_drm.ko
|
93
qcom/opensource/display-drivers/display_kernel_headers.py
Normal file
93
qcom/opensource/display-drivers/display_kernel_headers.py
Normal file
@ -0,0 +1,93 @@
|
||||
# Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 as published by
|
||||
# the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import argparse
|
||||
import filecmp
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
def run_headers_install(verbose, gen_dir, headers_install, unifdef, prefix, h):
|
||||
if not h.startswith(prefix):
|
||||
print('error: expected prefix [%s] on header [%s]' % (prefix, h))
|
||||
return False
|
||||
|
||||
out_h = os.path.join(gen_dir, h[len(prefix):])
|
||||
(out_h_dirname, out_h_basename) = os.path.split(out_h)
|
||||
env = os.environ.copy()
|
||||
env["LOC_UNIFDEF"] = unifdef
|
||||
cmd = ["sh", headers_install, h, out_h]
|
||||
|
||||
if verbose:
|
||||
print('run_headers_install: cmd is %s' % cmd)
|
||||
|
||||
result = subprocess.call(cmd, env=env)
|
||||
|
||||
if result != 0:
|
||||
print('error: run_headers_install: cmd %s failed %d' % (cmd, result))
|
||||
return False
|
||||
return True
|
||||
|
||||
def gen_display_headers(verbose, gen_dir, headers_install, unifdef, display_include_uapi):
|
||||
error_count = 0
|
||||
for h in display_include_uapi:
|
||||
display_uapi_include_prefix = os.path.join(h.split('/include/uapi')[0], 'include', 'uapi') + os.sep
|
||||
if not run_headers_install(
|
||||
verbose, gen_dir, headers_install, unifdef,
|
||||
display_uapi_include_prefix, h): error_count += 1
|
||||
return error_count
|
||||
|
||||
def main():
|
||||
"""Parse command line arguments and perform top level control."""
|
||||
parser = argparse.ArgumentParser(
|
||||
description=__doc__,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||
|
||||
# Arguments that apply to every invocation of this script.
|
||||
parser.add_argument(
|
||||
'--verbose', action='store_true',
|
||||
help='Print output that describes the workings of this script.')
|
||||
parser.add_argument(
|
||||
'--header_arch', required=True,
|
||||
help='The arch for which to generate headers.')
|
||||
parser.add_argument(
|
||||
'--gen_dir', required=True,
|
||||
help='Where to place the generated files.')
|
||||
parser.add_argument(
|
||||
'--display_include_uapi', required=True, nargs='*',
|
||||
help='The list of techpack/*/include/uapi header files.')
|
||||
parser.add_argument(
|
||||
'--headers_install', required=True,
|
||||
help='The headers_install tool to process input headers.')
|
||||
parser.add_argument(
|
||||
'--unifdef',
|
||||
required=True,
|
||||
help='The unifdef tool used by headers_install.')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.verbose:
|
||||
print('header_arch [%s]' % args.header_arch)
|
||||
print('gen_dir [%s]' % args.gen_dir)
|
||||
print('display_include_uapi [%s]' % args.display_include_uapi)
|
||||
print('headers_install [%s]' % args.headers_install)
|
||||
print('unifdef [%s]' % args.unifdef)
|
||||
|
||||
return gen_display_headers(args.verbose, args.gen_dir,
|
||||
args.headers_install, args.unifdef, args.display_include_uapi)
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
|
195
qcom/opensource/display-drivers/display_modules.bzl
Normal file
195
qcom/opensource/display-drivers/display_modules.bzl
Normal file
@ -0,0 +1,195 @@
|
||||
load(":display_driver_build.bzl", "display_module_entry")
|
||||
|
||||
display_driver_modules = display_module_entry([":display_drivers_headers"])
|
||||
module_entry = display_driver_modules.register
|
||||
|
||||
#---------- MSM-DRM MODULE -------------------------
|
||||
|
||||
module_entry(
|
||||
name = "msm_drm",
|
||||
config_option = "CONFIG_DRM_MSM",
|
||||
path = None,
|
||||
config_srcs = {
|
||||
"CONFIG_HDCP_QSEECOM": [
|
||||
"hdcp/msm_hdcp.c",
|
||||
"msm/dp/dp_hdcp2p2.c",
|
||||
"msm/sde_hdcp_1x.c",
|
||||
"msm/sde_hdcp_2x.c",
|
||||
],
|
||||
"CONFIG_DRM_SDE_VM" : [
|
||||
"msm/sde/sde_vm_common.c",
|
||||
"msm/sde/sde_vm_primary.c",
|
||||
"msm/sde/sde_vm_trusted.c",
|
||||
"msm/sde/sde_vm_msgq.c",
|
||||
],
|
||||
"CONFIG_DRM_MSM_DP" : [
|
||||
"msm/dp/dp_altmode.c",
|
||||
"msm/dp/dp_parser.c",
|
||||
"msm/dp/dp_power.c",
|
||||
"msm/dp/dp_catalog.c",
|
||||
"msm/dp/dp_catalog_v420.c",
|
||||
"msm/dp/dp_catalog_v200.c",
|
||||
"msm/dp/dp_aux.c",
|
||||
"msm/dp/dp_panel.c",
|
||||
"msm/dp/dp_link.c",
|
||||
"msm/dp/dp_ctrl.c",
|
||||
"msm/dp/dp_audio.c",
|
||||
"msm/dp/dp_debug.c",
|
||||
"msm/dp/dp_hpd.c",
|
||||
"msm/dp/dp_aux_bridge.c",
|
||||
"msm/dp/dp_bridge_hpd.c",
|
||||
"msm/dp/dp_mst_sim.c",
|
||||
"msm/dp/dp_mst_sim_helper.c",
|
||||
"msm/dp/dp_gpio_hpd.c",
|
||||
"msm/dp/dp_lphw_hpd.c",
|
||||
"msm/dp/dp_display.c",
|
||||
"msm/dp/dp_drm.c",
|
||||
"msm/dp/dp_pll.c",
|
||||
"msm/dp/dp_pll_5nm.c",
|
||||
"msm/dp/dp_pll_4nm.c",
|
||||
],
|
||||
"CONFIG_DRM_MSM_DP_MST" : [
|
||||
"msm/dp/dp_mst_drm.c",
|
||||
],
|
||||
"CONFIG_DRM_MSM_DP_USBPD_LEGACY" : [
|
||||
"msm/dp/dp_usbpd.c",
|
||||
],
|
||||
"CONFIG_DRM_MSM_SDE" : [
|
||||
"msm/sde/sde_crtc.c",
|
||||
"msm/sde/sde_encoder.c",
|
||||
"msm/sde/sde_encoder_dce.c",
|
||||
"msm/sde/sde_encoder_phys_vid.c",
|
||||
"msm/sde/sde_encoder_phys_cmd.c",
|
||||
"msm/sde/sde_irq.c",
|
||||
"msm/sde/sde_core_irq.c",
|
||||
"msm/sde/sde_core_perf.c",
|
||||
"msm/sde/sde_rm.c",
|
||||
"msm/sde/sde_kms_utils.c",
|
||||
"msm/sde/sde_kms.c",
|
||||
"msm/sde/sde_plane.c",
|
||||
"msm/sde/sde_connector.c",
|
||||
"msm/sde/sde_color_processing.c",
|
||||
"msm/sde/sde_vbif.c",
|
||||
"msm/sde_dbg.c",
|
||||
"msm/sde_dbg_evtlog.c",
|
||||
"msm/sde_io_util.c",
|
||||
"msm/sde_vm_event.c",
|
||||
"msm/sde/sde_hw_reg_dma_v1_color_proc.c",
|
||||
"msm/sde/sde_hw_color_proc_v4.c",
|
||||
"msm/sde/sde_hw_ad4.c",
|
||||
"msm/sde/sde_hw_uidle.c",
|
||||
"msm/sde_edid_parser.c",
|
||||
"msm/sde/sde_hw_catalog.c",
|
||||
"msm/sde/sde_hw_cdm.c",
|
||||
"msm/sde/sde_hw_dspp.c",
|
||||
"msm/sde/sde_hw_intf.c",
|
||||
"msm/sde/sde_hw_lm.c",
|
||||
"msm/sde/sde_hw_ctl.c",
|
||||
"msm/sde/sde_hw_util.c",
|
||||
"msm/sde/sde_hw_sspp.c",
|
||||
"msm/sde/sde_hw_wb.c",
|
||||
"msm/sde/sde_hw_pingpong.c",
|
||||
"msm/sde/sde_hw_top.c",
|
||||
"msm/sde/sde_hw_interrupts.c",
|
||||
"msm/sde/sde_hw_vbif.c",
|
||||
"msm/sde/sde_formats.c",
|
||||
"msm/sde_power_handle.c",
|
||||
"msm/sde/sde_hw_color_processing_v1_7.c",
|
||||
"msm/sde/sde_reg_dma.c",
|
||||
"msm/sde/sde_hw_reg_dma_v1.c",
|
||||
"msm/sde/sde_hw_dsc.c",
|
||||
"msm/sde/sde_hw_dsc_1_2.c",
|
||||
"msm/sde/sde_hw_vdc.c",
|
||||
"msm/sde/sde_hw_ds.c",
|
||||
"msm/sde/sde_fence.c",
|
||||
"msm/sde/sde_hw_qdss.c",
|
||||
"msm/sde_dsc_helper.c",
|
||||
"msm/sde_vdc_helper.c",
|
||||
"msm/sde/sde_hw_dnsc_blur.c",
|
||||
"msm/sde/sde_hw_rc.c",
|
||||
],
|
||||
"CONFIG_DRM_SDE_WB" : [
|
||||
"msm/sde/sde_wb.c",
|
||||
"msm/sde/sde_encoder_phys_wb.c"
|
||||
],
|
||||
"CONFIG_DRM_SDE_RSC" : [
|
||||
"msm/sde_rsc.c",
|
||||
"msm/sde_rsc_hw.c",
|
||||
"msm/sde_rsc_hw_v3.c",
|
||||
],
|
||||
"CONFIG_DRM_MSM_DSI" : [
|
||||
"msm/dsi/dsi_phy.c",
|
||||
"msm/dsi/dsi_pwr.c",
|
||||
"msm/dsi/dsi_phy_hw_v3_0.c",
|
||||
"msm/dsi/dsi_phy_hw_v4_0.c",
|
||||
"msm/dsi/dsi_phy_hw_v5_0.c",
|
||||
"msm/dsi/dsi_phy_timing_calc.c",
|
||||
"msm/dsi/dsi_phy_timing_v3_0.c",
|
||||
"msm/dsi/dsi_phy_timing_v4_0.c",
|
||||
"msm/dsi/dsi_pll.c",
|
||||
"msm/dsi/dsi_pll_5nm.c",
|
||||
"msm/dsi/dsi_pll_4nm.c",
|
||||
"msm/dsi/dsi_ctrl_hw_cmn.c",
|
||||
"msm/dsi/dsi_ctrl_hw_2_2.c",
|
||||
"msm/dsi/dsi_ctrl.c",
|
||||
"msm/dsi/dsi_catalog.c",
|
||||
"msm/dsi/dsi_drm.c",
|
||||
"msm/dsi/dsi_display.c",
|
||||
"msm/dsi/dsi_panel.c",
|
||||
"msm/dsi/dsi_clk_manager.c",
|
||||
"msm/dsi/dsi_display_test.c",
|
||||
],
|
||||
"CONFIG_DSI_PARSER" : [
|
||||
"msm/dsi/dsi_parser.c",
|
||||
],
|
||||
"CONFIG_THERMAL_OF" : [
|
||||
"msm/msm_cooling_device.c",
|
||||
],
|
||||
"CONFIG_DRM_MSM" : [
|
||||
"msm/msm_atomic.c",
|
||||
"msm/msm_fb.c",
|
||||
"msm/msm_drv.c",
|
||||
"msm/msm_gem.c",
|
||||
"msm/msm_gem_prime.c",
|
||||
"msm/msm_gem_vma.c",
|
||||
"msm/msm_smmu.c",
|
||||
"msm/msm_prop.c",
|
||||
],
|
||||
"CONFIG_MSM_SDE_ROTATOR":{
|
||||
True: [
|
||||
"rotator/sde_rotator_dev.c",
|
||||
"rotator/sde_rotator_core.c",
|
||||
"rotator/sde_rotator_base.c",
|
||||
"rotator/sde_rotator_formats.c",
|
||||
"rotator/sde_rotator_util.c",
|
||||
"rotator/sde_rotator_io_util.c",
|
||||
"rotator/sde_rotator_smmu.c",
|
||||
"rotator/sde_rotator_r1_wb.c",
|
||||
"rotator/sde_rotator_r1_pipe.c",
|
||||
"rotator/sde_rotator_r1_ctl.c",
|
||||
"rotator/sde_rotator_r1.c",
|
||||
"rotator/sde_rotator_r3.c"],
|
||||
"CONFIG_SYNC_FILE":["rotator/sde_rotator_sync.c"],
|
||||
"CONFIG_DEBUG_FS":["rotator/sde_rotator_debug.c",
|
||||
"rotator/sde_rotator_r1_debug.c",
|
||||
"rotator/sde_rotator_r3_debug.c"],
|
||||
},
|
||||
},
|
||||
config_deps = {
|
||||
"CONFIG_HDCP_QSEECOM" : [
|
||||
"//vendor/qcom/opensource/securemsm-kernel:%b_hdcp_qseecom_dlkm"
|
||||
],
|
||||
"CONFIG_MSM_MMRM" : [
|
||||
"//vendor/qcom/opensource/mmrm-driver:%b_mmrm_driver"
|
||||
],
|
||||
"CONFIG_QCOM_SPEC_SYNC" : [
|
||||
"//vendor/qcom/opensource/mm-drivers/sync_fence:%b_sync_fence"
|
||||
],
|
||||
"CONFIG_QTI_HW_FENCE" : [
|
||||
"//vendor/qcom/opensource/mm-drivers/hw_fence:%b_msm_hw_fence"
|
||||
],
|
||||
"CONFIG_MSM_EXT_DISPLAY" : [
|
||||
"//vendor/qcom/opensource/mm-drivers/msm_ext_display:%b_msm_ext_display"
|
||||
],
|
||||
}
|
||||
)
|
342
qcom/opensource/display-drivers/hdcp/msm_hdcp.c
Normal file
342
qcom/opensource/display-drivers/hdcp/msm_hdcp.c
Normal file
@ -0,0 +1,342 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "[msm-hdcp] %s: " fmt, __func__
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/msm_hdcp.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#define CLASS_NAME "hdcp"
|
||||
#define DRIVER_NAME "msm_hdcp"
|
||||
|
||||
struct msm_hdcp {
|
||||
struct platform_device *pdev;
|
||||
dev_t dev_num;
|
||||
struct cdev cdev;
|
||||
struct class *class;
|
||||
struct device *device;
|
||||
struct HDCP_V2V1_MSG_TOPOLOGY cached_tp;
|
||||
u32 tp_msgid;
|
||||
void *client_ctx;
|
||||
void (*cb)(void *ctx, u8 data);
|
||||
};
|
||||
|
||||
void msm_hdcp_register_cb(struct device *dev, void *ctx,
|
||||
void (*cb)(void *ctx, u8 data))
|
||||
{
|
||||
struct msm_hdcp *hdcp = NULL;
|
||||
|
||||
if (!dev) {
|
||||
pr_err("invalid device pointer\n");
|
||||
return;
|
||||
}
|
||||
|
||||
hdcp = dev_get_drvdata(dev);
|
||||
if (!hdcp) {
|
||||
pr_err("invalid driver pointer\n");
|
||||
return;
|
||||
}
|
||||
|
||||
hdcp->cb = cb;
|
||||
hdcp->client_ctx = ctx;
|
||||
}
|
||||
EXPORT_SYMBOL(msm_hdcp_register_cb);
|
||||
|
||||
void msm_hdcp_notify_topology(struct device *dev)
|
||||
{
|
||||
char *envp[4];
|
||||
char tp[SZ_16];
|
||||
char ver[SZ_16];
|
||||
struct msm_hdcp *hdcp = NULL;
|
||||
|
||||
if (!dev) {
|
||||
pr_err("invalid device pointer\n");
|
||||
return;
|
||||
}
|
||||
|
||||
hdcp = dev_get_drvdata(dev);
|
||||
if (!hdcp) {
|
||||
pr_err("invalid driver pointer\n");
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(tp, SZ_16, "%d", DOWN_CHECK_TOPOLOGY);
|
||||
snprintf(ver, SZ_16, "%d", HDCP_V1_TX);
|
||||
|
||||
envp[0] = "HDCP_MGR_EVENT=MSG_READY";
|
||||
envp[1] = tp;
|
||||
envp[2] = ver;
|
||||
envp[3] = NULL;
|
||||
|
||||
kobject_uevent_env(&hdcp->device->kobj, KOBJ_CHANGE, envp);
|
||||
}
|
||||
EXPORT_SYMBOL(msm_hdcp_notify_topology);
|
||||
|
||||
void msm_hdcp_cache_repeater_topology(struct device *dev,
|
||||
struct HDCP_V2V1_MSG_TOPOLOGY *tp)
|
||||
{
|
||||
struct msm_hdcp *hdcp = NULL;
|
||||
|
||||
if (!dev || !tp) {
|
||||
pr_err("invalid input\n");
|
||||
return;
|
||||
}
|
||||
|
||||
hdcp = dev_get_drvdata(dev);
|
||||
if (!hdcp) {
|
||||
pr_err("invalid driver pointer\n");
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(&hdcp->cached_tp, tp,
|
||||
sizeof(struct HDCP_V2V1_MSG_TOPOLOGY));
|
||||
}
|
||||
EXPORT_SYMBOL(msm_hdcp_cache_repeater_topology);
|
||||
|
||||
static ssize_t tp_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
ssize_t ret = 0;
|
||||
struct msm_hdcp *hdcp = NULL;
|
||||
|
||||
if (!dev) {
|
||||
pr_err("invalid device pointer\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
hdcp = dev_get_drvdata(dev);
|
||||
if (!hdcp) {
|
||||
pr_err("invalid driver pointer\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
switch (hdcp->tp_msgid) {
|
||||
case DOWN_CHECK_TOPOLOGY:
|
||||
case DOWN_REQUEST_TOPOLOGY:
|
||||
buf[MSG_ID_IDX] = hdcp->tp_msgid;
|
||||
buf[RET_CODE_IDX] = HDCP_AUTHED;
|
||||
ret = HEADER_LEN;
|
||||
|
||||
memcpy(buf + HEADER_LEN, &hdcp->cached_tp,
|
||||
sizeof(struct HDCP_V2V1_MSG_TOPOLOGY));
|
||||
|
||||
ret += sizeof(struct HDCP_V2V1_MSG_TOPOLOGY);
|
||||
|
||||
/* reset the flag once the data is written back to user space */
|
||||
hdcp->tp_msgid = DOWN_REQUEST_TOPOLOGY;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t tp_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int msgid = 0;
|
||||
ssize_t ret = count;
|
||||
struct msm_hdcp *hdcp = NULL;
|
||||
|
||||
if (!dev) {
|
||||
pr_err("invalid device pointer\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
hdcp = dev_get_drvdata(dev);
|
||||
if (!hdcp) {
|
||||
pr_err("invalid driver pointer\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
msgid = buf[0];
|
||||
|
||||
switch (msgid) {
|
||||
case DOWN_CHECK_TOPOLOGY:
|
||||
case DOWN_REQUEST_TOPOLOGY:
|
||||
hdcp->tp_msgid = msgid;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t min_level_change_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
int rc;
|
||||
int min_enc_lvl;
|
||||
ssize_t ret = count;
|
||||
struct msm_hdcp *hdcp = NULL;
|
||||
|
||||
if (!dev) {
|
||||
pr_err("invalid device pointer\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
hdcp = dev_get_drvdata(dev);
|
||||
if (!hdcp) {
|
||||
pr_err("invalid driver pointer\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
rc = kstrtoint(buf, 10, &min_enc_lvl);
|
||||
if (rc) {
|
||||
pr_err("kstrtoint failed. rc=%d\n", rc);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (hdcp->cb && hdcp->client_ctx)
|
||||
hdcp->cb(hdcp->client_ctx, min_enc_lvl);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RW(tp);
|
||||
|
||||
static DEVICE_ATTR_WO(min_level_change);
|
||||
|
||||
static struct attribute *msm_hdcp_fs_attrs[] = {
|
||||
&dev_attr_tp.attr,
|
||||
&dev_attr_min_level_change.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group msm_hdcp_fs_attr_group = {
|
||||
.attrs = msm_hdcp_fs_attrs
|
||||
};
|
||||
|
||||
static int msm_hdcp_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_hdcp_close(struct inode *inode, struct file *file)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct file_operations msm_hdcp_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = msm_hdcp_open,
|
||||
.release = msm_hdcp_close,
|
||||
};
|
||||
|
||||
static const struct of_device_id msm_hdcp_dt_match[] = {
|
||||
{ .compatible = "qcom,msm-hdcp",},
|
||||
{}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, msm_hdcp_dt_match);
|
||||
|
||||
static int msm_hdcp_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
struct msm_hdcp *hdcp;
|
||||
|
||||
hdcp = devm_kzalloc(&pdev->dev, sizeof(struct msm_hdcp), GFP_KERNEL);
|
||||
if (!hdcp)
|
||||
return -ENOMEM;
|
||||
|
||||
hdcp->pdev = pdev;
|
||||
|
||||
platform_set_drvdata(pdev, hdcp);
|
||||
|
||||
ret = alloc_chrdev_region(&hdcp->dev_num, 0, 1, DRIVER_NAME);
|
||||
if (ret < 0) {
|
||||
pr_err("alloc_chrdev_region failed ret = %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
hdcp->class = class_create(THIS_MODULE, CLASS_NAME);
|
||||
if (IS_ERR(hdcp->class)) {
|
||||
ret = PTR_ERR(hdcp->class);
|
||||
pr_err("couldn't create class rc = %d\n", ret);
|
||||
goto error_class_create;
|
||||
}
|
||||
|
||||
hdcp->device = device_create(hdcp->class, NULL,
|
||||
hdcp->dev_num, hdcp, DRIVER_NAME);
|
||||
if (IS_ERR(hdcp->device)) {
|
||||
ret = PTR_ERR(hdcp->device);
|
||||
pr_err("device_create failed %d\n", ret);
|
||||
goto error_class_device_create;
|
||||
}
|
||||
|
||||
cdev_init(&hdcp->cdev, &msm_hdcp_fops);
|
||||
ret = cdev_add(&hdcp->cdev, MKDEV(MAJOR(hdcp->dev_num), 0), 1);
|
||||
if (ret < 0) {
|
||||
pr_err("cdev_add failed %d\n", ret);
|
||||
goto error_cdev_add;
|
||||
}
|
||||
|
||||
ret = sysfs_create_group(&hdcp->device->kobj, &msm_hdcp_fs_attr_group);
|
||||
if (ret)
|
||||
pr_err("unable to register msm_hdcp sysfs nodes\n");
|
||||
|
||||
hdcp->tp_msgid = DOWN_REQUEST_TOPOLOGY;
|
||||
|
||||
return 0;
|
||||
error_cdev_add:
|
||||
device_destroy(hdcp->class, hdcp->dev_num);
|
||||
error_class_device_create:
|
||||
class_destroy(hdcp->class);
|
||||
error_class_create:
|
||||
unregister_chrdev_region(hdcp->dev_num, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int msm_hdcp_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct msm_hdcp *hdcp;
|
||||
|
||||
hdcp = platform_get_drvdata(pdev);
|
||||
if (!hdcp)
|
||||
return -ENODEV;
|
||||
|
||||
sysfs_remove_group(&hdcp->device->kobj,
|
||||
&msm_hdcp_fs_attr_group);
|
||||
cdev_del(&hdcp->cdev);
|
||||
device_destroy(hdcp->class, hdcp->dev_num);
|
||||
class_destroy(hdcp->class);
|
||||
unregister_chrdev_region(hdcp->dev_num, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver msm_hdcp_driver = {
|
||||
.probe = msm_hdcp_probe,
|
||||
.remove = msm_hdcp_remove,
|
||||
.driver = {
|
||||
.name = "msm_hdcp",
|
||||
.of_match_table = msm_hdcp_dt_match,
|
||||
.pm = NULL,
|
||||
}
|
||||
};
|
||||
|
||||
void __init msm_hdcp_register(void)
|
||||
{
|
||||
platform_driver_register(&msm_hdcp_driver);
|
||||
}
|
||||
|
||||
void __exit msm_hdcp_unregister(void)
|
||||
{
|
||||
platform_driver_unregister(&msm_hdcp_driver);
|
||||
}
|
2
qcom/opensource/display-drivers/include/Kbuild
Normal file
2
qcom/opensource/display-drivers/include/Kbuild
Normal file
@ -0,0 +1,2 @@
|
||||
# Top-level Makefile calls into asm-$(ARCH)
|
||||
# List only non-arch directories below
|
6
qcom/opensource/display-drivers/include/linux/Kbuild
Normal file
6
qcom/opensource/display-drivers/include/linux/Kbuild
Normal file
@ -0,0 +1,6 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note
|
||||
|
||||
header-y += msm_hdcp.h
|
||||
header-y += sde_io_util.h
|
||||
header-y += sde_rsc.h
|
||||
|
33
qcom/opensource/display-drivers/include/linux/msm_hdcp.h
Normal file
33
qcom/opensource/display-drivers/include/linux/msm_hdcp.h
Normal file
@ -0,0 +1,33 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __MSM_HDCP_H
|
||||
#define __MSM_HDCP_H
|
||||
#include <linux/types.h>
|
||||
#include "hdcp/msm_hdmi_hdcp_mgr.h"
|
||||
|
||||
#if IS_ENABLED(CONFIG_HDCP_QSEECOM)
|
||||
void msm_hdcp_notify_topology(struct device *dev);
|
||||
void msm_hdcp_cache_repeater_topology(struct device *dev,
|
||||
struct HDCP_V2V1_MSG_TOPOLOGY *tp);
|
||||
void msm_hdcp_register_cb(struct device *dev, void *ctx,
|
||||
void (*cb)(void *ctx, u8 data));
|
||||
#else
|
||||
static inline void msm_hdcp_notify_topology(struct device *dev)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void msm_hdcp_cache_repeater_topology(struct device *dev,
|
||||
struct HDCP_V2V1_MSG_TOPOLOGY *tp)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void msm_hdcp_register_cb(struct device *dev, void *ctx,
|
||||
void (*cb)(void *ctx, u8 data))
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_HDCP_QSEECOM*/
|
||||
|
||||
#endif /* __MSM_HDCP_H */
|
136
qcom/opensource/display-drivers/include/linux/sde_io_util.h
Normal file
136
qcom/opensource/display-drivers/include/linux/sde_io_util.h
Normal file
@ -0,0 +1,136 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2012, 2017-2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __SDE_IO_UTIL_H__
|
||||
#define __SDE_IO_UTIL_H__
|
||||
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/soc/qcom/msm_mmrm.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DEV_DBG(fmt, args...) pr_err(fmt, ##args)
|
||||
#else
|
||||
#define DEV_DBG(fmt, args...) pr_debug(fmt, ##args)
|
||||
#endif
|
||||
#define DEV_INFO(fmt, args...) pr_info(fmt, ##args)
|
||||
#define DEV_WARN(fmt, args...) pr_warn(fmt, ##args)
|
||||
#define DEV_ERR(fmt, args...) pr_err(fmt, ##args)
|
||||
|
||||
struct dss_io_data {
|
||||
u32 len;
|
||||
void __iomem *base;
|
||||
};
|
||||
|
||||
void dss_reg_w(struct dss_io_data *io, u32 offset, u32 value, u32 debug);
|
||||
u32 dss_reg_r(struct dss_io_data *io, u32 offset, u32 debug);
|
||||
void dss_reg_dump(void __iomem *base, u32 len, const char *prefix, u32 debug);
|
||||
|
||||
#define DSS_REG_W_ND(io, offset, val) dss_reg_w(io, offset, val, false)
|
||||
#define DSS_REG_W(io, offset, val) dss_reg_w(io, offset, val, true)
|
||||
#define DSS_REG_R_ND(io, offset) dss_reg_r(io, offset, false)
|
||||
#define DSS_REG_R(io, offset) dss_reg_r(io, offset, true)
|
||||
|
||||
enum dss_vreg_type {
|
||||
DSS_REG_LDO,
|
||||
DSS_REG_VS,
|
||||
};
|
||||
|
||||
struct dss_vreg {
|
||||
struct regulator *vreg; /* vreg handle */
|
||||
char vreg_name[32];
|
||||
int min_voltage;
|
||||
int max_voltage;
|
||||
int enable_load;
|
||||
int disable_load;
|
||||
int pre_on_sleep;
|
||||
int post_on_sleep;
|
||||
int pre_off_sleep;
|
||||
int post_off_sleep;
|
||||
};
|
||||
|
||||
struct dss_gpio {
|
||||
unsigned int gpio;
|
||||
unsigned int value;
|
||||
char gpio_name[32];
|
||||
};
|
||||
|
||||
enum dss_clk_type {
|
||||
DSS_CLK_AHB, /* no set rate. rate controlled through rpm */
|
||||
DSS_CLK_PCLK,
|
||||
DSS_CLK_MMRM, /* set rate called through mmrm driver */
|
||||
DSS_CLK_OTHER,
|
||||
};
|
||||
|
||||
struct dss_clk_mmrm_cb {
|
||||
void *phandle;
|
||||
struct dss_clk *clk;
|
||||
};
|
||||
|
||||
struct dss_clk_mmrm {
|
||||
unsigned int clk_id;
|
||||
unsigned int flags;
|
||||
struct mmrm_client *mmrm_client;
|
||||
struct dss_clk_mmrm_cb *mmrm_cb_data;
|
||||
unsigned long mmrm_requested_clk;
|
||||
wait_queue_head_t mmrm_cb_wq;
|
||||
};
|
||||
|
||||
struct dss_clk {
|
||||
struct clk *clk; /* clk handle */
|
||||
char clk_name[32];
|
||||
enum dss_clk_type type;
|
||||
unsigned long rate;
|
||||
unsigned long max_rate;
|
||||
struct dss_clk_mmrm mmrm;
|
||||
};
|
||||
|
||||
struct dss_module_power {
|
||||
unsigned int num_vreg;
|
||||
struct dss_vreg *vreg_config;
|
||||
unsigned int num_gpio;
|
||||
struct dss_gpio *gpio_config;
|
||||
unsigned int num_clk;
|
||||
struct dss_clk *clk_config;
|
||||
};
|
||||
|
||||
int msm_dss_ioremap_byname(struct platform_device *pdev,
|
||||
struct dss_io_data *io_data, const char *name);
|
||||
void msm_dss_iounmap(struct dss_io_data *io_data);
|
||||
int msm_dss_get_io_mem(struct platform_device *pdev,
|
||||
struct list_head *mem_list);
|
||||
void msm_dss_clean_io_mem(struct list_head *mem_list);
|
||||
int msm_dss_get_pmic_io_mem(struct platform_device *pdev,
|
||||
struct list_head *mem_list);
|
||||
int msm_dss_get_gpio_io_mem(const int gpio_pin, struct list_head *mem_list);
|
||||
int msm_dss_get_io_irq(struct platform_device *pdev,
|
||||
struct list_head *irq_list, u32 label);
|
||||
void msm_dss_clean_io_irq(struct list_head *irq_list);
|
||||
int msm_dss_enable_gpio(struct dss_gpio *in_gpio, int num_gpio, int enable);
|
||||
int msm_dss_gpio_enable(struct dss_gpio *in_gpio, int num_gpio, int enable);
|
||||
|
||||
int msm_dss_get_vreg(struct device *dev, struct dss_vreg *in_vreg,
|
||||
int num_vreg, int enable);
|
||||
int msm_dss_enable_vreg(struct dss_vreg *in_vreg, int num_vreg, int enable);
|
||||
|
||||
int msm_dss_get_clk(struct device *dev, struct dss_clk *clk_arry, int num_clk);
|
||||
int msm_dss_mmrm_register(struct device *dev, struct dss_module_power *mp,
|
||||
int (*cb_fnc)(struct mmrm_client_notifier_data *data), void *phandle,
|
||||
bool *mmrm_enable);
|
||||
void msm_dss_mmrm_deregister(struct device *dev, struct dss_module_power *mp);
|
||||
void msm_dss_put_clk(struct dss_clk *clk_arry, int num_clk);
|
||||
int msm_dss_clk_set_rate(struct dss_clk *clk_arry, int num_clk);
|
||||
int msm_dss_single_clk_set_rate(struct dss_clk *clk);
|
||||
int msm_dss_enable_clk(struct dss_clk *clk_arry, int num_clk, int enable);
|
||||
|
||||
int sde_i2c_byte_read(struct i2c_client *client, uint8_t slave_addr,
|
||||
uint8_t reg_offset, uint8_t *read_buf);
|
||||
int sde_i2c_byte_write(struct i2c_client *client, uint8_t slave_addr,
|
||||
uint8_t reg_offset, uint8_t *value);
|
||||
|
||||
#endif /* __SDE_IO_UTIL_H__ */
|
360
qcom/opensource/display-drivers/include/linux/sde_rsc.h
Normal file
360
qcom/opensource/display-drivers/include/linux/sde_rsc.h
Normal file
@ -0,0 +1,360 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _SDE_RSC_H_
|
||||
#define _SDE_RSC_H_
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
||||
/* primary display rsc index */
|
||||
#define SDE_RSC_INDEX 0
|
||||
|
||||
#define MAX_RSC_CLIENT_NAME_LEN 128
|
||||
#define NUM_RSC_PROFILING_COUNTERS 3
|
||||
|
||||
/* DRM Object IDs are numbered excluding 0, use 0 to indicate invalid CRTC */
|
||||
#define SDE_RSC_INVALID_CRTC_ID 0
|
||||
|
||||
/**
|
||||
* event will be triggered before sde core power collapse,
|
||||
* mdss gdsc is still on
|
||||
*/
|
||||
#define SDE_RSC_EVENT_PRE_CORE_PC 0x1
|
||||
/**
|
||||
* event will be triggered after sde core collapse complete,
|
||||
* mdss gdsc is off now
|
||||
*/
|
||||
#define SDE_RSC_EVENT_POST_CORE_PC 0x2
|
||||
/**
|
||||
* event will be triggered before restoring the sde core from power collapse,
|
||||
* mdss gdsc is still off
|
||||
*/
|
||||
#define SDE_RSC_EVENT_PRE_CORE_RESTORE 0x4
|
||||
/**
|
||||
* event will be triggered after restoring the sde core from power collapse,
|
||||
* mdss gdsc is on now
|
||||
*/
|
||||
#define SDE_RSC_EVENT_POST_CORE_RESTORE 0x8
|
||||
/**
|
||||
* event attached with solver state enabled
|
||||
* all clients in clk_state or cmd_state
|
||||
*/
|
||||
#define SDE_RSC_EVENT_SOLVER_ENABLED 0x10
|
||||
/**
|
||||
* event attached with solver state disabled
|
||||
* one of the client requested for vid state
|
||||
*/
|
||||
#define SDE_RSC_EVENT_SOLVER_DISABLED 0x20
|
||||
|
||||
/**
|
||||
* sde_rsc_client_type: sde rsc client type information
|
||||
* SDE_RSC_PRIMARY_DISP_CLIENT: A primary display client which can request
|
||||
* vid or cmd state switch.
|
||||
* SDE_RSC_EXTERNAL_DISPLAY_CLIENT:An external display client which can
|
||||
* request only clk state switch.
|
||||
* SDE_RSC_CLK_CLIENT: A clk client request for only rsc clocks
|
||||
* enabled and mode_2 exit state.
|
||||
*/
|
||||
enum sde_rsc_client_type {
|
||||
SDE_RSC_PRIMARY_DISP_CLIENT,
|
||||
SDE_RSC_EXTERNAL_DISP_CLIENT,
|
||||
SDE_RSC_CLK_CLIENT,
|
||||
SDE_RSC_INVALID_CLIENT,
|
||||
};
|
||||
|
||||
/**
|
||||
* sde_rsc_state: sde rsc state information
|
||||
* SDE_RSC_IDLE_STATE: A client requests for idle state when there is no
|
||||
* pixel or cmd transfer expected. An idle vote from
|
||||
* all clients lead to power collapse state.
|
||||
* SDE_RSC_CLK_STATE: A client requests for clk state when it wants to
|
||||
* only avoid mode-2 entry/exit. For ex: V4L2 driver,
|
||||
* sde power handle, etc.
|
||||
* SDE_RSC_CMD_STATE: A client requests for cmd state when it wants to
|
||||
* enable the solver mode.
|
||||
* SDE_RSC_VID_STATE: A client requests for vid state it wants to avoid
|
||||
* solver enable because client is fetching data from
|
||||
* continuously.
|
||||
*/
|
||||
enum sde_rsc_state {
|
||||
SDE_RSC_IDLE_STATE,
|
||||
SDE_RSC_CLK_STATE,
|
||||
SDE_RSC_CMD_STATE,
|
||||
SDE_RSC_VID_STATE,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sde_rsc_client: stores the rsc client for sde driver
|
||||
* @name: name of the client
|
||||
* @current_state: current client state
|
||||
* @crtc_id: crtc_id associated with this rsc client.
|
||||
* @rsc_index: rsc index of a client - only index "0" valid.
|
||||
* @id: Index of client. It will be assigned during client_create call
|
||||
* @client_type: check sde_rsc_client_type information
|
||||
* @list: list to attach client master list
|
||||
*/
|
||||
struct sde_rsc_client {
|
||||
char name[MAX_RSC_CLIENT_NAME_LEN];
|
||||
short current_state;
|
||||
int crtc_id;
|
||||
u32 rsc_index;
|
||||
u32 id;
|
||||
enum sde_rsc_client_type client_type;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sde_rsc_event: local event registration entry structure
|
||||
* @cb_func: Pointer to desired callback function
|
||||
* @usr: User pointer to pass to callback on event trigger
|
||||
* @rsc_index: rsc index of a client - only index "0" valid.
|
||||
* @event_type: refer comments in event_register
|
||||
* @list: list to attach event master list
|
||||
*/
|
||||
struct sde_rsc_event {
|
||||
void (*cb_func)(uint32_t event_type, void *usr);
|
||||
void *usr;
|
||||
u32 rsc_index;
|
||||
uint32_t event_type;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sde_rsc_cmd_config: provides panel configuration to rsc
|
||||
* when client is command mode. It is not required to set it during
|
||||
* video mode.
|
||||
*
|
||||
* @fps: panel te interval
|
||||
* @vtotal: current vertical total (height + vbp + vfp)
|
||||
* @jitter_numer: panel jitter numerator value. This config causes rsc/solver
|
||||
* early before te. Default is 0.8% jitter.
|
||||
* @jitter_denom: panel jitter denominator.
|
||||
* @prefill_lines: max prefill lines based on panel
|
||||
*/
|
||||
struct sde_rsc_cmd_config {
|
||||
u32 fps;
|
||||
u32 vtotal;
|
||||
u32 jitter_numer;
|
||||
u32 jitter_denom;
|
||||
u32 prefill_lines;
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_DRM_SDE_RSC)
|
||||
/**
|
||||
* sde_rsc_client_create() - create the client for sde rsc.
|
||||
* Different displays like DSI, HDMI, DP, WB, etc should call this
|
||||
* api to register their vote for rpmh. They still need to vote for
|
||||
* power handle to get the clocks.
|
||||
|
||||
* @rsc_index: A client will be created on this RSC. As of now only
|
||||
* SDE_RSC_INDEX is valid rsc index.
|
||||
* @name: Caller needs to provide some valid string to identify
|
||||
* the client. "primary", "dp", "hdmi" are suggested name.
|
||||
* @client_type: check client_type enum for information
|
||||
* @vsync_source: This parameter is only valid for primary display. It provides
|
||||
* vsync source information
|
||||
*
|
||||
* Return: client node pointer.
|
||||
*/
|
||||
struct sde_rsc_client *sde_rsc_client_create(u32 rsc_index, char *name,
|
||||
enum sde_rsc_client_type client_type, u32 vsync_source);
|
||||
|
||||
/**
|
||||
* sde_rsc_client_destroy() - Destroy the sde rsc client.
|
||||
*
|
||||
* @client: Client pointer provided by sde_rsc_client_create().
|
||||
*
|
||||
* Return: none
|
||||
*/
|
||||
void sde_rsc_client_destroy(struct sde_rsc_client *client);
|
||||
|
||||
/**
|
||||
* sde_rsc_client_state_update() - rsc client state update
|
||||
* Video mode, cmd mode and clk state are supported as modes. A client need to
|
||||
* set this property during panel time. A switching client can set the
|
||||
* property to change the state
|
||||
*
|
||||
* @client: Client pointer provided by sde_rsc_client_create().
|
||||
* @state: Client state - video/cmd
|
||||
* @config: fps, vtotal, porches, etc configuration for command mode
|
||||
* panel
|
||||
* @crtc_id: current client's crtc id
|
||||
* @wait_vblank_crtc_id: Output parameter. If set to non-zero, rsc hw
|
||||
* state update requires a wait for one vblank on
|
||||
* the primary crtc. In that case, this output
|
||||
* param will be set to the crtc on which to wait.
|
||||
* If SDE_RSC_INVALID_CRTC_ID, no wait necessary
|
||||
*
|
||||
* Return: error code.
|
||||
*/
|
||||
int sde_rsc_client_state_update(struct sde_rsc_client *client,
|
||||
enum sde_rsc_state state,
|
||||
struct sde_rsc_cmd_config *config, int crtc_id,
|
||||
int *wait_vblank_crtc_id);
|
||||
|
||||
/**
|
||||
* sde_rsc_client_get_vsync_refcount() - returns the status of the vsync
|
||||
* refcount, to signal if the client needs to reset the refcounting logic
|
||||
* @client: Client pointer provided by sde_rsc_client_create().
|
||||
*
|
||||
* Return: true if the state update has completed.
|
||||
*/
|
||||
int sde_rsc_client_get_vsync_refcount(
|
||||
struct sde_rsc_client *caller_client);
|
||||
|
||||
/**
|
||||
* sde_rsc_client_reset_vsync_refcount() - reduces the refcounting
|
||||
* logic that waits for the vsync.
|
||||
* @client: Client pointer provided by sde_rsc_client_create().
|
||||
*
|
||||
* Return: true if the state update has completed.
|
||||
*/
|
||||
int sde_rsc_client_reset_vsync_refcount(
|
||||
struct sde_rsc_client *caller_client);
|
||||
|
||||
/**
|
||||
* sde_rsc_client_is_state_update_complete() - check if state update is complete
|
||||
* RSC state transition is not complete until HW receives VBLANK signal. This
|
||||
* function checks RSC HW to determine whether that signal has been received.
|
||||
* @client: Client pointer provided by sde_rsc_client_create().
|
||||
*
|
||||
* Return: true if the state update has completed.
|
||||
*/
|
||||
bool sde_rsc_client_is_state_update_complete(
|
||||
struct sde_rsc_client *caller_client);
|
||||
|
||||
/**
|
||||
* sde_rsc_client_vote() - stores ab/ib vote for rsc client
|
||||
*
|
||||
* @client: Client pointer provided by sde_rsc_client_create().
|
||||
* @bus_id: data bus identifier
|
||||
* @ab: aggregated bandwidth vote from client.
|
||||
* @ib: instant bandwidth vote from client.
|
||||
*
|
||||
* Return: error code.
|
||||
*/
|
||||
int sde_rsc_client_vote(struct sde_rsc_client *caller_client,
|
||||
u32 bus_id, u64 ab_vote, u64 ib_vote);
|
||||
|
||||
/**
|
||||
* sde_rsc_register_event - register a callback function for an event
|
||||
* @rsc_index: A client will be created on this RSC. As of now only
|
||||
* SDE_RSC_INDEX is valid rsc index.
|
||||
* @event_type: event type to register; client sets 0x3 if it wants
|
||||
* to register for CORE_PC and CORE_RESTORE - both events.
|
||||
* @cb_func: Pointer to desired callback function
|
||||
* @usr: User pointer to pass to callback on event trigger
|
||||
* Returns: sde_rsc_event pointer on success
|
||||
*/
|
||||
struct sde_rsc_event *sde_rsc_register_event(int rsc_index, uint32_t event_type,
|
||||
void (*cb_func)(uint32_t event_type, void *usr), void *usr);
|
||||
|
||||
/**
|
||||
* sde_rsc_unregister_event - unregister callback for an event
|
||||
* @sde_rsc_event: event returned by sde_rsc_register_event
|
||||
*/
|
||||
void sde_rsc_unregister_event(struct sde_rsc_event *event);
|
||||
|
||||
/**
|
||||
* is_sde_rsc_available - check if display rsc available.
|
||||
* @rsc_index: A client will be created on this RSC. As of now only
|
||||
* SDE_RSC_INDEX is valid rsc index.
|
||||
* Returns: true if rsc is available; false in all other cases
|
||||
*/
|
||||
bool is_sde_rsc_available(int rsc_index);
|
||||
|
||||
/**
|
||||
* get_sde_rsc_current_state - gets the current state of sde rsc.
|
||||
* @rsc_index: A client will be created on this RSC. As of now only
|
||||
* SDE_RSC_INDEX is valid rsc index.
|
||||
* Returns: current state if rsc available; SDE_RSC_IDLE_STATE for
|
||||
* all other cases
|
||||
*/
|
||||
enum sde_rsc_state get_sde_rsc_current_state(int rsc_index);
|
||||
|
||||
/**
|
||||
* sde_rsc_client_trigger_vote() - triggers ab/ib vote for rsc client
|
||||
*
|
||||
* @client: Client pointer provided by sde_rsc_client_create().
|
||||
* @delta_vote: if bw vote is increased or decreased
|
||||
*
|
||||
* Return: error code.
|
||||
*/
|
||||
int sde_rsc_client_trigger_vote(struct sde_rsc_client *caller_client,
|
||||
bool delta_vote);
|
||||
|
||||
#else
|
||||
|
||||
static inline struct sde_rsc_client *sde_rsc_client_create(u32 rsc_index,
|
||||
char *name, enum sde_rsc_client_type client_type, u32 vsync_source)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void sde_rsc_client_destroy(struct sde_rsc_client *client)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int sde_rsc_client_state_update(struct sde_rsc_client *client,
|
||||
enum sde_rsc_state state,
|
||||
struct sde_rsc_cmd_config *config, int crtc_id,
|
||||
int *wait_vblank_crtc_id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int sde_rsc_client_get_vsync_refcount(
|
||||
struct sde_rsc_client *caller_client)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int sde_rsc_client_reset_vsync_refcount(
|
||||
struct sde_rsc_client *caller_client)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool sde_rsc_client_is_state_update_complete(
|
||||
struct sde_rsc_client *caller_client)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline int sde_rsc_client_vote(struct sde_rsc_client *caller_client,
|
||||
u32 bus_id, u64 ab_vote, u64 ib_vote)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct sde_rsc_event *sde_rsc_register_event(int rsc_index,
|
||||
uint32_t event_type,
|
||||
void (*cb_func)(uint32_t event_type, void *usr), void *usr)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void sde_rsc_unregister_event(struct sde_rsc_event *event)
|
||||
{
|
||||
}
|
||||
|
||||
static inline bool is_sde_rsc_available(int rsc_index)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline enum sde_rsc_state get_sde_rsc_current_state(int rsc_index)
|
||||
{
|
||||
return SDE_RSC_IDLE_STATE;
|
||||
}
|
||||
|
||||
static inline int sde_rsc_client_trigger_vote(
|
||||
struct sde_rsc_client *caller_client, bool delta_vote)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_DRM_SDE_RSC */
|
||||
|
||||
#endif /* _SDE_RSC_H_ */
|
97
qcom/opensource/display-drivers/include/linux/sde_vm_event.h
Normal file
97
qcom/opensource/display-drivers/include/linux/sde_vm_event.h
Normal file
@ -0,0 +1,97 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __SDE_VM_EVENT_H__
|
||||
#define __SDE_VM_EVENT_H__
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <drm/drm_device.h>
|
||||
|
||||
/**
|
||||
* struct - msm_io_irq_entry - define irq item
|
||||
* @label: gh_irq_label for the irq
|
||||
* @irq_num: linux mapped irq num
|
||||
* @list: list head pointer
|
||||
*/
|
||||
struct msm_io_irq_entry {
|
||||
u32 label;
|
||||
u32 irq_num;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct - msm_io_mem_entry - define io memory item
|
||||
* @base: reg base
|
||||
* @size: size of the reg range
|
||||
* @list: list head pointer
|
||||
*/
|
||||
struct msm_io_mem_entry {
|
||||
phys_addr_t base;
|
||||
phys_addr_t size;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct - msm_io_res - represents the hw resources for vm sharing
|
||||
* @irq: list of IRQ's of all the dislay sub-devices
|
||||
* @mem: list of IO memory ranges of all the display sub-devices
|
||||
*/
|
||||
struct msm_io_res {
|
||||
struct list_head irq;
|
||||
struct list_head mem;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct msm_vm_ops - hooks for communication with vm clients
|
||||
* @vm_pre_hw_release: invoked before releasing the HW
|
||||
* @vm_post_hw_acquire: invoked before pushing the first commit
|
||||
* @vm_check: invoked to check the readiness of the vm_clients
|
||||
* before releasing the HW
|
||||
* @vm_get_io_resources: invoked to collect HW resources
|
||||
*/
|
||||
struct msm_vm_ops {
|
||||
int (*vm_pre_hw_release)(void *priv_data);
|
||||
int (*vm_post_hw_acquire)(void *priv_data);
|
||||
int (*vm_check)(void *priv_data);
|
||||
int (*vm_get_io_resources)(struct msm_io_res *io_res, void *priv_data);
|
||||
};
|
||||
|
||||
/**
|
||||
* msm_vm_client_entry - defines the vm client info
|
||||
* @ops: client vm_ops
|
||||
* @dev: clients device id. Used in unregister
|
||||
* @data: client custom data
|
||||
* @list: linked list entry
|
||||
*/
|
||||
struct msm_vm_client_entry {
|
||||
struct msm_vm_ops ops;
|
||||
struct device *dev;
|
||||
void *data;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
/**
|
||||
* msm_register_vm_event - api for display dependent drivers(clients) to
|
||||
* register for vm events
|
||||
* @dev: msm device
|
||||
* @client_dev: client device
|
||||
* @ops: vm event hooks
|
||||
* @priv_data: client custom data
|
||||
*/
|
||||
int msm_register_vm_event(struct device *dev, struct device *client_dev,
|
||||
struct msm_vm_ops *ops, void *priv_data);
|
||||
|
||||
/**
|
||||
* msm_unregister_vm_event - api for display dependent drivers(clients) to
|
||||
* unregister from vm events
|
||||
* @dev: msm device
|
||||
* @client_dev: client device
|
||||
*/
|
||||
void msm_unregister_vm_event(struct device *dev, struct device *client_dev);
|
||||
|
||||
#endif //__SDE_VM_EVENT_H__
|
6
qcom/opensource/display-drivers/include/uapi/Kbuild
Normal file
6
qcom/opensource/display-drivers/include/uapi/Kbuild
Normal file
@ -0,0 +1,6 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note
|
||||
|
||||
# Top-level Makefile calls into asm-$(ARCH)
|
||||
# List only non-arch directories below
|
||||
|
||||
header-y += display/
|
@ -0,0 +1,5 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note
|
||||
|
||||
header-y += media/
|
||||
header-y += drm/
|
||||
header-y += hdcp/
|
@ -0,0 +1,5 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note
|
||||
|
||||
header-y += msm_drm_pp.h
|
||||
header-y += sde_drm.h
|
||||
|
@ -0,0 +1,817 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
|
||||
/*
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _MSM_DRM_PP_H_
|
||||
#define _MSM_DRM_PP_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <drm/drm.h>
|
||||
|
||||
#define ENABLE_EVENT_SPR_OPR_VALUE
|
||||
#define ENABLE_EVENT_INTF_MISR_SIGNATURE
|
||||
#define MAX_DSI_DISPLAY 4
|
||||
|
||||
/**
|
||||
* struct drm_msm_pcc_coeff - PCC coefficient structure for each color
|
||||
* component.
|
||||
* @c: constant coefficient.
|
||||
* @r: red coefficient.
|
||||
* @g: green coefficient.
|
||||
* @b: blue coefficient.
|
||||
* @rg: red green coefficient.
|
||||
* @gb: green blue coefficient.
|
||||
* @rb: red blue coefficient.
|
||||
* @rgb: red blue green coefficient.
|
||||
*/
|
||||
|
||||
struct drm_msm_pcc_coeff {
|
||||
__u32 c;
|
||||
__u32 r;
|
||||
__u32 g;
|
||||
__u32 b;
|
||||
__u32 rg;
|
||||
__u32 gb;
|
||||
__u32 rb;
|
||||
__u32 rgb;
|
||||
};
|
||||
|
||||
#define PCC_BEFORE (1 << 0)
|
||||
|
||||
/**
|
||||
* struct drm_msm_pcc - pcc feature structure
|
||||
* @flags: for customizing operations. Values can be
|
||||
* - PCC_BEFORE: Operate PCC using a 'before' arrangement
|
||||
* @r: red coefficients.
|
||||
* @g: green coefficients.
|
||||
* @b: blue coefficients.
|
||||
* @r_rr: second order coefficients
|
||||
* @r_gg: second order coefficients
|
||||
* @r_bb: second order coefficients
|
||||
* @g_rr: second order coefficients
|
||||
* @g_gg: second order coefficients
|
||||
* @g_bb: second order coefficients
|
||||
* @b_rr: second order coefficients
|
||||
* @b_gg: second order coefficients
|
||||
* @b_bb: second order coefficients
|
||||
*/
|
||||
#define DRM_MSM_PCC3
|
||||
struct drm_msm_pcc {
|
||||
__u64 flags;
|
||||
struct drm_msm_pcc_coeff r;
|
||||
struct drm_msm_pcc_coeff g;
|
||||
struct drm_msm_pcc_coeff b;
|
||||
__u32 r_rr;
|
||||
__u32 r_gg;
|
||||
__u32 r_bb;
|
||||
__u32 g_rr;
|
||||
__u32 g_gg;
|
||||
__u32 g_bb;
|
||||
__u32 b_rr;
|
||||
__u32 b_gg;
|
||||
__u32 b_bb;
|
||||
};
|
||||
|
||||
/* struct drm_msm_pa_vlut - picture adjustment vLUT structure
|
||||
* flags: for customizing vlut operation
|
||||
* val: vLUT values
|
||||
*/
|
||||
#define PA_VLUT_SIZE 256
|
||||
struct drm_msm_pa_vlut {
|
||||
__u64 flags;
|
||||
__u32 val[PA_VLUT_SIZE];
|
||||
};
|
||||
|
||||
#define PA_HSIC_HUE_ENABLE (1 << 0)
|
||||
#define PA_HSIC_SAT_ENABLE (1 << 1)
|
||||
#define PA_HSIC_VAL_ENABLE (1 << 2)
|
||||
#define PA_HSIC_CONT_ENABLE (1 << 3)
|
||||
/**
|
||||
* struct drm_msm_pa_hsic - pa hsic feature structure
|
||||
* @flags: flags for the feature customization, values can be:
|
||||
* - PA_HSIC_HUE_ENABLE: Enable hue adjustment
|
||||
* - PA_HSIC_SAT_ENABLE: Enable saturation adjustment
|
||||
* - PA_HSIC_VAL_ENABLE: Enable value adjustment
|
||||
* - PA_HSIC_CONT_ENABLE: Enable contrast adjustment
|
||||
*
|
||||
* @hue: hue setting
|
||||
* @saturation: saturation setting
|
||||
* @value: value setting
|
||||
* @contrast: contrast setting
|
||||
*/
|
||||
#define DRM_MSM_PA_HSIC
|
||||
struct drm_msm_pa_hsic {
|
||||
__u64 flags;
|
||||
__u32 hue;
|
||||
__u32 saturation;
|
||||
__u32 value;
|
||||
__u32 contrast;
|
||||
};
|
||||
|
||||
#define MEMCOL_PROT_HUE (1 << 0)
|
||||
#define MEMCOL_PROT_SAT (1 << 1)
|
||||
#define MEMCOL_PROT_VAL (1 << 2)
|
||||
#define MEMCOL_PROT_CONT (1 << 3)
|
||||
#define MEMCOL_PROT_SIXZONE (1 << 4)
|
||||
#define MEMCOL_PROT_BLEND (1 << 5)
|
||||
/* struct drm_msm_memcol - Memory color feature structure.
|
||||
* Skin, sky, foliage features are supported.
|
||||
* @prot_flags: Bit mask for enabling protection feature.
|
||||
* @color_adjust_p0: Adjustment curve.
|
||||
* @color_adjust_p1: Adjustment curve.
|
||||
* @color_adjust_p2: Adjustment curve.
|
||||
* @blend_gain: Blend gain weightage from othe PA features.
|
||||
* @sat_hold: Saturation hold value.
|
||||
* @val_hold: Value hold info.
|
||||
* @hue_region: Hue qualifier.
|
||||
* @sat_region: Saturation qualifier.
|
||||
* @val_region: Value qualifier.
|
||||
*/
|
||||
#define DRM_MSM_MEMCOL
|
||||
struct drm_msm_memcol {
|
||||
__u64 prot_flags;
|
||||
__u32 color_adjust_p0;
|
||||
__u32 color_adjust_p1;
|
||||
__u32 color_adjust_p2;
|
||||
__u32 blend_gain;
|
||||
__u32 sat_hold;
|
||||
__u32 val_hold;
|
||||
__u32 hue_region;
|
||||
__u32 sat_region;
|
||||
__u32 val_region;
|
||||
};
|
||||
|
||||
#define DRM_MSM_SIXZONE
|
||||
#define SIXZONE_LUT_SIZE 384
|
||||
#define SIXZONE_HUE_ENABLE (1 << 0)
|
||||
#define SIXZONE_SAT_ENABLE (1 << 1)
|
||||
#define SIXZONE_VAL_ENABLE (1 << 2)
|
||||
#define SIXZONE_SV_ENABLE (1 << 3)
|
||||
/* struct drm_msm_sixzone_curve - Sixzone HSV adjustment curve structure.
|
||||
* @p0: Hue adjustment.
|
||||
* @p1: Saturation/Value adjustment.
|
||||
*/
|
||||
struct drm_msm_sixzone_curve {
|
||||
__u32 p1;
|
||||
__u32 p0;
|
||||
};
|
||||
|
||||
/* struct drm_msm_sixzone - Sixzone feature structure.
|
||||
* @flags: for feature customization, values can be:
|
||||
* - SIXZONE_HUE_ENABLE: Enable hue adjustment
|
||||
* - SIXZONE_SAT_ENABLE: Enable saturation adjustment
|
||||
* - SIXZONE_VAL_ENABLE: Enable value adjustment
|
||||
* - SIXZONE_SV_ENABLE: Enable SV feature
|
||||
* @threshold: threshold qualifier.
|
||||
* @adjust_p0: Adjustment curve.
|
||||
* @adjust_p1: Adjustment curve.
|
||||
* @sat_hold: Saturation hold info.
|
||||
* @val_hold: Value hold info.
|
||||
* @curve: HSV adjustment curve lut.
|
||||
* @sat_adjust_p0: Saturation adjustment curve.
|
||||
* @sat_adjust_p1: Saturation adjustment curve.
|
||||
* @curve_p2: Saturation Mid/Saturation High adjustment
|
||||
*/
|
||||
struct drm_msm_sixzone {
|
||||
__u64 flags;
|
||||
__u32 threshold;
|
||||
__u32 adjust_p0;
|
||||
__u32 adjust_p1;
|
||||
__u32 sat_hold;
|
||||
__u32 val_hold;
|
||||
struct drm_msm_sixzone_curve curve[SIXZONE_LUT_SIZE];
|
||||
__u32 sat_adjust_p0;
|
||||
__u32 sat_adjust_p1;
|
||||
__u32 curve_p2[SIXZONE_LUT_SIZE];
|
||||
};
|
||||
|
||||
#define GAMUT_3D_MODE_17 1
|
||||
#define GAMUT_3D_MODE_5 2
|
||||
#define GAMUT_3D_MODE_13 3
|
||||
|
||||
#define GAMUT_3D_MODE17_TBL_SZ 1229
|
||||
#define GAMUT_3D_MODE5_TBL_SZ 32
|
||||
#define GAMUT_3D_MODE13_TBL_SZ 550
|
||||
#define GAMUT_3D_SCALE_OFF_SZ 16
|
||||
#define GAMUT_3D_SCALEB_OFF_SZ 12
|
||||
#define GAMUT_3D_TBL_NUM 4
|
||||
#define GAMUT_3D_SCALE_OFF_TBL_NUM 3
|
||||
#define GAMUT_3D_MAP_EN (1 << 0)
|
||||
|
||||
/**
|
||||
* struct drm_msm_3d_col - 3d gamut color component structure
|
||||
* @c0: Holds c0 value
|
||||
* @c2_c1: Holds c2/c1 values
|
||||
*/
|
||||
struct drm_msm_3d_col {
|
||||
__u32 c2_c1;
|
||||
__u32 c0;
|
||||
};
|
||||
/**
|
||||
* struct drm_msm_3d_gamut - 3d gamut feature structure
|
||||
* @flags: flags for the feature values are:
|
||||
* 0 - no map
|
||||
* GAMUT_3D_MAP_EN - enable map
|
||||
* @mode: lut mode can take following values:
|
||||
* - GAMUT_3D_MODE_17
|
||||
* - GAMUT_3D_MODE_5
|
||||
* - GAMUT_3D_MODE_13
|
||||
* @scale_off: Scale offset table
|
||||
* @col: Color component tables
|
||||
*/
|
||||
struct drm_msm_3d_gamut {
|
||||
__u64 flags;
|
||||
__u32 mode;
|
||||
__u32 scale_off[GAMUT_3D_SCALE_OFF_TBL_NUM][GAMUT_3D_SCALE_OFF_SZ];
|
||||
struct drm_msm_3d_col col[GAMUT_3D_TBL_NUM][GAMUT_3D_MODE17_TBL_SZ];
|
||||
};
|
||||
|
||||
#define PGC_TBL_LEN 512
|
||||
#define PGC_8B_ROUND (1 << 0)
|
||||
/**
|
||||
* struct drm_msm_pgc_lut - pgc lut feature structure
|
||||
* @flags: flags for the featue values can be:
|
||||
* - PGC_8B_ROUND
|
||||
* @c0: color0 component lut
|
||||
* @c1: color1 component lut
|
||||
* @c2: color2 component lut
|
||||
*/
|
||||
struct drm_msm_pgc_lut {
|
||||
__u64 flags;
|
||||
__u32 c0[PGC_TBL_LEN];
|
||||
__u32 c1[PGC_TBL_LEN];
|
||||
__u32 c2[PGC_TBL_LEN];
|
||||
};
|
||||
|
||||
#define IGC_TBL_LEN 256
|
||||
#define IGC_DITHER_ENABLE (1 << 0)
|
||||
/**
|
||||
* struct drm_msm_igc_lut - igc lut feature structure
|
||||
* @flags: flags for the feature customization, values can be:
|
||||
* - IGC_DITHER_ENABLE: Enable dither functionality
|
||||
* @c0: color0 component lut
|
||||
* @c1: color1 component lut
|
||||
* @c2: color2 component lut
|
||||
* @strength: dither strength, considered valid when IGC_DITHER_ENABLE
|
||||
* is set in flags. Strength value based on source bit width.
|
||||
* @c0_last: color0 lut_last component
|
||||
* @c1_last: color1 lut_last component
|
||||
* @c2_last: color2 lut_last component
|
||||
*/
|
||||
struct drm_msm_igc_lut {
|
||||
__u64 flags;
|
||||
__u32 c0[IGC_TBL_LEN];
|
||||
__u32 c1[IGC_TBL_LEN];
|
||||
__u32 c2[IGC_TBL_LEN];
|
||||
__u32 strength;
|
||||
__u32 c0_last;
|
||||
__u32 c1_last;
|
||||
__u32 c2_last;
|
||||
};
|
||||
#define LAST_LUT 2
|
||||
|
||||
#define HIST_V_SIZE 256
|
||||
/**
|
||||
* struct drm_msm_hist - histogram feature structure
|
||||
* @flags: for customizing operations
|
||||
* @data: histogram data
|
||||
*/
|
||||
struct drm_msm_hist {
|
||||
__u64 flags;
|
||||
__u32 data[HIST_V_SIZE];
|
||||
};
|
||||
|
||||
#define AD4_LUT_GRP0_SIZE 33
|
||||
#define AD4_LUT_GRP1_SIZE 32
|
||||
/*
|
||||
* struct drm_msm_ad4_init - ad4 init structure set by user-space client.
|
||||
* Init param values can change based on tuning
|
||||
* hence it is passed by user-space clients.
|
||||
*/
|
||||
struct drm_msm_ad4_init {
|
||||
__u32 init_param_001[AD4_LUT_GRP0_SIZE];
|
||||
__u32 init_param_002[AD4_LUT_GRP0_SIZE];
|
||||
__u32 init_param_003[AD4_LUT_GRP0_SIZE];
|
||||
__u32 init_param_004[AD4_LUT_GRP0_SIZE];
|
||||
__u32 init_param_005[AD4_LUT_GRP1_SIZE];
|
||||
__u32 init_param_006[AD4_LUT_GRP1_SIZE];
|
||||
__u32 init_param_007[AD4_LUT_GRP0_SIZE];
|
||||
__u32 init_param_008[AD4_LUT_GRP0_SIZE];
|
||||
__u32 init_param_009;
|
||||
__u32 init_param_010;
|
||||
__u32 init_param_011;
|
||||
__u32 init_param_012;
|
||||
__u32 init_param_013;
|
||||
__u32 init_param_014;
|
||||
__u32 init_param_015;
|
||||
__u32 init_param_016;
|
||||
__u32 init_param_017;
|
||||
__u32 init_param_018;
|
||||
__u32 init_param_019;
|
||||
__u32 init_param_020;
|
||||
__u32 init_param_021;
|
||||
__u32 init_param_022;
|
||||
__u32 init_param_023;
|
||||
__u32 init_param_024;
|
||||
__u32 init_param_025;
|
||||
__u32 init_param_026;
|
||||
__u32 init_param_027;
|
||||
__u32 init_param_028;
|
||||
__u32 init_param_029;
|
||||
__u32 init_param_030;
|
||||
__u32 init_param_031;
|
||||
__u32 init_param_032;
|
||||
__u32 init_param_033;
|
||||
__u32 init_param_034;
|
||||
__u32 init_param_035;
|
||||
__u32 init_param_036;
|
||||
__u32 init_param_037;
|
||||
__u32 init_param_038;
|
||||
__u32 init_param_039;
|
||||
__u32 init_param_040;
|
||||
__u32 init_param_041;
|
||||
__u32 init_param_042;
|
||||
__u32 init_param_043;
|
||||
__u32 init_param_044;
|
||||
__u32 init_param_045;
|
||||
__u32 init_param_046;
|
||||
__u32 init_param_047;
|
||||
__u32 init_param_048;
|
||||
__u32 init_param_049;
|
||||
__u32 init_param_050;
|
||||
__u32 init_param_051;
|
||||
__u32 init_param_052;
|
||||
__u32 init_param_053;
|
||||
__u32 init_param_054;
|
||||
__u32 init_param_055;
|
||||
__u32 init_param_056;
|
||||
__u32 init_param_057;
|
||||
__u32 init_param_058;
|
||||
__u32 init_param_059;
|
||||
__u32 init_param_060;
|
||||
__u32 init_param_061;
|
||||
__u32 init_param_062;
|
||||
__u32 init_param_063;
|
||||
__u32 init_param_064;
|
||||
__u32 init_param_065;
|
||||
__u32 init_param_066;
|
||||
__u32 init_param_067;
|
||||
__u32 init_param_068;
|
||||
__u32 init_param_069;
|
||||
__u32 init_param_070;
|
||||
__u32 init_param_071;
|
||||
__u32 init_param_072;
|
||||
__u32 init_param_073;
|
||||
__u32 init_param_074;
|
||||
__u32 init_param_075;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct drm_msm_ad4_cfg - ad4 config structure set by user-space client.
|
||||
* Config param values can vary based on tuning,
|
||||
* hence it is passed by user-space clients.
|
||||
*/
|
||||
struct drm_msm_ad4_cfg {
|
||||
__u32 cfg_param_001;
|
||||
__u32 cfg_param_002;
|
||||
__u32 cfg_param_003;
|
||||
__u32 cfg_param_004;
|
||||
__u32 cfg_param_005;
|
||||
__u32 cfg_param_006;
|
||||
__u32 cfg_param_007;
|
||||
__u32 cfg_param_008;
|
||||
__u32 cfg_param_009;
|
||||
__u32 cfg_param_010;
|
||||
__u32 cfg_param_011;
|
||||
__u32 cfg_param_012;
|
||||
__u32 cfg_param_013;
|
||||
__u32 cfg_param_014;
|
||||
__u32 cfg_param_015;
|
||||
__u32 cfg_param_016;
|
||||
__u32 cfg_param_017;
|
||||
__u32 cfg_param_018;
|
||||
__u32 cfg_param_019;
|
||||
__u32 cfg_param_020;
|
||||
__u32 cfg_param_021;
|
||||
__u32 cfg_param_022;
|
||||
__u32 cfg_param_023;
|
||||
__u32 cfg_param_024;
|
||||
__u32 cfg_param_025;
|
||||
__u32 cfg_param_026;
|
||||
__u32 cfg_param_027;
|
||||
__u32 cfg_param_028;
|
||||
__u32 cfg_param_029;
|
||||
__u32 cfg_param_030;
|
||||
__u32 cfg_param_031;
|
||||
__u32 cfg_param_032;
|
||||
__u32 cfg_param_033;
|
||||
__u32 cfg_param_034;
|
||||
__u32 cfg_param_035;
|
||||
__u32 cfg_param_036;
|
||||
__u32 cfg_param_037;
|
||||
__u32 cfg_param_038;
|
||||
__u32 cfg_param_039;
|
||||
__u32 cfg_param_040;
|
||||
__u32 cfg_param_041;
|
||||
__u32 cfg_param_042;
|
||||
__u32 cfg_param_043;
|
||||
__u32 cfg_param_044;
|
||||
__u32 cfg_param_045;
|
||||
__u32 cfg_param_046;
|
||||
__u32 cfg_param_047;
|
||||
__u32 cfg_param_048;
|
||||
__u32 cfg_param_049;
|
||||
__u32 cfg_param_050;
|
||||
__u32 cfg_param_051;
|
||||
__u32 cfg_param_052;
|
||||
__u32 cfg_param_053;
|
||||
};
|
||||
|
||||
#define DITHER_MATRIX_SZ 16
|
||||
#define DITHER_LUMA_MODE (1 << 0)
|
||||
|
||||
/**
|
||||
* struct drm_msm_dither - dither feature structure
|
||||
* @flags: flags for the feature customization, values can be:
|
||||
-DITHER_LUMA_MODE: Enable LUMA dither mode
|
||||
* @temporal_en: temperal dither enable
|
||||
* @c0_bitdepth: c0 component bit depth
|
||||
* @c1_bitdepth: c1 component bit depth
|
||||
* @c2_bitdepth: c2 component bit depth
|
||||
* @c3_bitdepth: c2 component bit depth
|
||||
* @matrix: dither strength matrix
|
||||
*/
|
||||
struct drm_msm_dither {
|
||||
__u64 flags;
|
||||
__u32 temporal_en;
|
||||
__u32 c0_bitdepth;
|
||||
__u32 c1_bitdepth;
|
||||
__u32 c2_bitdepth;
|
||||
__u32 c3_bitdepth;
|
||||
__u32 matrix[DITHER_MATRIX_SZ];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct drm_msm_pa_dither - dspp dither feature structure
|
||||
* @flags: for customizing operations
|
||||
* @strength: dither strength
|
||||
* @offset_en: offset enable bit
|
||||
* @matrix: dither data matrix
|
||||
*/
|
||||
#define DRM_MSM_PA_DITHER
|
||||
struct drm_msm_pa_dither {
|
||||
__u64 flags;
|
||||
__u32 strength;
|
||||
__u32 offset_en;
|
||||
__u32 matrix[DITHER_MATRIX_SZ];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct drm_msm_ad4_roi_cfg - ad4 roi params config set
|
||||
* by user-space client.
|
||||
* @h_x - hotizontal direction start
|
||||
* @h_y - hotizontal direction end
|
||||
* @v_x - vertical direction start
|
||||
* @v_y - vertical direction end
|
||||
* @factor_in - the alpha value for inside roi region
|
||||
* @factor_out - the alpha value for outside roi region
|
||||
*/
|
||||
#define DRM_MSM_AD4_ROI
|
||||
struct drm_msm_ad4_roi_cfg {
|
||||
__u32 h_x;
|
||||
__u32 h_y;
|
||||
__u32 v_x;
|
||||
__u32 v_y;
|
||||
__u32 factor_in;
|
||||
__u32 factor_out;
|
||||
};
|
||||
|
||||
#define LTM_FEATURE_DEF 1
|
||||
#define LTM_DATA_SIZE_0 32
|
||||
#define LTM_DATA_SIZE_1 128
|
||||
#define LTM_DATA_SIZE_2 256
|
||||
#define LTM_DATA_SIZE_3 33
|
||||
#define LTM_BUFFER_SIZE 5
|
||||
#define LTM_GUARD_BYTES 255
|
||||
#define LTM_BLOCK_SIZE 4
|
||||
|
||||
#define LTM_STATS_SAT (1 << 1)
|
||||
#define LTM_STATS_MERGE_SAT (1 << 2)
|
||||
#define LTM_HIST_CHECKSUM_SUPPORT (1 << 0)
|
||||
|
||||
/*
|
||||
* struct drm_msm_ltm_stats_data - LTM stats data structure
|
||||
*/
|
||||
struct drm_msm_ltm_stats_data {
|
||||
__u32 stats_01[LTM_DATA_SIZE_0][LTM_DATA_SIZE_1];
|
||||
__u32 stats_02[LTM_DATA_SIZE_2];
|
||||
__u32 stats_03[LTM_DATA_SIZE_0];
|
||||
__u32 stats_04[LTM_DATA_SIZE_0];
|
||||
__u32 stats_05[LTM_DATA_SIZE_0];
|
||||
__u32 status_flag;
|
||||
__u32 display_h;
|
||||
__u32 display_v;
|
||||
__u32 init_h[LTM_BLOCK_SIZE];
|
||||
__u32 init_v;
|
||||
__u32 inc_h;
|
||||
__u32 inc_v;
|
||||
__u32 portrait_en;
|
||||
__u32 merge_en;
|
||||
__u32 cfg_param_01;
|
||||
__u32 cfg_param_02;
|
||||
__u32 cfg_param_03;
|
||||
__u32 cfg_param_04;
|
||||
__u32 feature_flag;
|
||||
__u32 checksum;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct drm_msm_ltm_init_param - LTM init param structure
|
||||
*/
|
||||
struct drm_msm_ltm_init_param {
|
||||
__u32 init_param_01;
|
||||
__u32 init_param_02;
|
||||
__u32 init_param_03;
|
||||
__u32 init_param_04;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct drm_msm_ltm_cfg_param - LTM config param structure
|
||||
*/
|
||||
struct drm_msm_ltm_cfg_param {
|
||||
__u32 cfg_param_01;
|
||||
__u32 cfg_param_02;
|
||||
__u32 cfg_param_03;
|
||||
__u32 cfg_param_04;
|
||||
__u32 cfg_param_05;
|
||||
__u32 cfg_param_06;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct drm_msm_ltm_data - LTM data structure
|
||||
*/
|
||||
struct drm_msm_ltm_data {
|
||||
__u32 data[LTM_DATA_SIZE_0][LTM_DATA_SIZE_3];
|
||||
};
|
||||
|
||||
/*
|
||||
* struct drm_msm_ltm_buffers_crtl - LTM buffer control structure.
|
||||
* This struct will be used to init and
|
||||
* de-init the LTM buffers in driver.
|
||||
* @num_of_buffers: valid number of buffers used
|
||||
* @fds: fd array to for all the valid buffers
|
||||
*/
|
||||
struct drm_msm_ltm_buffers_ctrl {
|
||||
__u32 num_of_buffers;
|
||||
__u32 fds[LTM_BUFFER_SIZE];
|
||||
};
|
||||
|
||||
/*
|
||||
* struct drm_msm_ltm_buffer - LTM buffer structure.
|
||||
* This struct will be passed from driver to user
|
||||
* space for LTM stats data notification.
|
||||
* @fd: fd assicated with the buffer that has LTM stats data
|
||||
* @offset: offset from base address that used for alignment
|
||||
* @status status flag for error indication
|
||||
*/
|
||||
struct drm_msm_ltm_buffer {
|
||||
__u32 fd;
|
||||
__u32 offset;
|
||||
__u32 status;
|
||||
};
|
||||
|
||||
#define SPR_INIT_PARAM_SIZE_1 4
|
||||
#define SPR_INIT_PARAM_SIZE_2 5
|
||||
#define SPR_INIT_PARAM_SIZE_3 16
|
||||
#define SPR_INIT_PARAM_SIZE_4 24
|
||||
#define SPR_INIT_PARAM_SIZE_5 32
|
||||
#define SPR_INIT_PARAM_SIZE_6 7
|
||||
#define SPR_FLAG_BYPASS (1 << 0)
|
||||
|
||||
/**
|
||||
* struct drm_msm_spr_init_cfg - SPR initial configuration structure
|
||||
*/
|
||||
struct drm_msm_spr_init_cfg {
|
||||
__u64 flags;
|
||||
__u16 cfg0;
|
||||
__u16 cfg1;
|
||||
__u16 cfg2;
|
||||
__u16 cfg3;
|
||||
__u16 cfg4;
|
||||
__u16 cfg5;
|
||||
__u16 cfg6;
|
||||
__u16 cfg7;
|
||||
__u16 cfg8;
|
||||
__u16 cfg9;
|
||||
__u32 cfg10;
|
||||
__u16 cfg11[SPR_INIT_PARAM_SIZE_1];
|
||||
__u16 cfg12[SPR_INIT_PARAM_SIZE_1];
|
||||
__u16 cfg13[SPR_INIT_PARAM_SIZE_1];
|
||||
__u16 cfg14[SPR_INIT_PARAM_SIZE_2];
|
||||
__u16 cfg15[SPR_INIT_PARAM_SIZE_5];
|
||||
int cfg16[SPR_INIT_PARAM_SIZE_3];
|
||||
int cfg17[SPR_INIT_PARAM_SIZE_4];
|
||||
__u16 cfg18_en;
|
||||
__u8 cfg18[SPR_INIT_PARAM_SIZE_6];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct drm_msm_spr_udc_cfg - SPR UDC configuration structure
|
||||
*/
|
||||
|
||||
#define SPR_UDC_PARAM_SIZE_1 27
|
||||
#define SPR_UDC_PARAM_SIZE_2 1536
|
||||
struct drm_msm_spr_udc_cfg {
|
||||
__u64 flags;
|
||||
__u16 init_cfg4;
|
||||
__u16 init_cfg11[SPR_INIT_PARAM_SIZE_1];
|
||||
__u16 cfg1[SPR_UDC_PARAM_SIZE_1];
|
||||
__u16 cfg2[SPR_UDC_PARAM_SIZE_2];
|
||||
};
|
||||
|
||||
|
||||
#define FEATURE_DEM
|
||||
#define CFG0_PARAM_LEN 8
|
||||
#define CFG1_PARAM_LEN 8
|
||||
#define CFG1_PARAM0_LEN 153
|
||||
#define CFG0_PARAM2_LEN 256
|
||||
#define CFG5_PARAM01_LEN 4
|
||||
#define CFG3_PARAM01_LEN 4
|
||||
#define DEMURA_FLAG_0 (1 << 0)
|
||||
#define DEMURA_FLAG_1 (1 << 1)
|
||||
#define DEMURA_FLAG_2 (3 << 2)
|
||||
#define DEMURA_SKIP_CFG0_PARAM2 (1 << 4)
|
||||
#define DEMURA_PRECISION_0 (0 << 2)
|
||||
#define DEMURA_PRECISION_1 (1 << 2)
|
||||
#define DEMURA_PRECISION_2 (2 << 2)
|
||||
|
||||
struct drm_msm_dem_cfg {
|
||||
__u64 flags;
|
||||
__u32 pentile;
|
||||
__u32 cfg0_en;
|
||||
__u32 cfg0_param0_len;
|
||||
__u32 cfg0_param0[CFG0_PARAM_LEN];
|
||||
__u32 cfg0_param1_len;
|
||||
__u32 cfg0_param1[CFG0_PARAM_LEN];
|
||||
__u32 cfg0_param2_len;
|
||||
__u64 cfg0_param2_c0[CFG0_PARAM2_LEN];
|
||||
__u64 cfg0_param2_c1[CFG0_PARAM2_LEN];
|
||||
__u64 cfg0_param2_c2[CFG0_PARAM2_LEN];
|
||||
__u32 cfg0_param3_len;
|
||||
__u32 cfg0_param3_c0[CFG0_PARAM_LEN];
|
||||
__u32 cfg0_param3_c1[CFG0_PARAM_LEN];
|
||||
__u32 cfg0_param3_c2[CFG0_PARAM_LEN];
|
||||
__u32 cfg0_param4_len;
|
||||
__u32 cfg0_param4[CFG0_PARAM_LEN];
|
||||
|
||||
__u32 cfg1_en;
|
||||
__u32 cfg1_high_idx;
|
||||
__u32 cfg1_low_idx;
|
||||
__u32 cfg01_param0_len;
|
||||
__u32 cfg01_param0[CFG1_PARAM_LEN];
|
||||
__u32 cfg1_param0_len;
|
||||
__u32 cfg1_param0_c0[CFG1_PARAM0_LEN];
|
||||
__u32 cfg1_param0_c1[CFG1_PARAM0_LEN];
|
||||
__u32 cfg1_param0_c2[CFG1_PARAM0_LEN];
|
||||
|
||||
__u32 cfg2_en;
|
||||
__u32 cfg3_en;
|
||||
__u32 cfg3_param0_len;
|
||||
__u32 cfg3_param0_a[CFG3_PARAM01_LEN];
|
||||
__u32 cfg3_param0_b[CFG3_PARAM01_LEN];
|
||||
__u32 cfg3_ab_adj;
|
||||
__u32 cfg4_en;
|
||||
__u32 cfg5_en;
|
||||
__u32 cfg5_param0_len;
|
||||
__u32 cfg5_param0[CFG5_PARAM01_LEN];
|
||||
__u32 cfg5_param1_len;
|
||||
__u32 cfg5_param1[CFG5_PARAM01_LEN];
|
||||
|
||||
__u32 c0_depth;
|
||||
__u32 c1_depth;
|
||||
__u32 c2_depth;
|
||||
__u32 src_id;
|
||||
__u32 cfg0_param2_idx;
|
||||
};
|
||||
|
||||
struct drm_msm_dem_cfg0_param2 {
|
||||
__u32 cfg0_param2_len;
|
||||
__u64 cfg0_param2_c0[CFG0_PARAM2_LEN];
|
||||
__u64 cfg0_param2_c1[CFG0_PARAM2_LEN];
|
||||
__u64 cfg0_param2_c2[CFG0_PARAM2_LEN];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct drm_msm_ad4_manual_str_cfg - ad4 manual strength config set
|
||||
* by user-space client.
|
||||
* @in_str - strength for inside roi region
|
||||
* @out_str - strength for outside roi region
|
||||
*/
|
||||
#define DRM_MSM_AD4_MANUAL_STRENGTH
|
||||
struct drm_msm_ad4_manual_str_cfg {
|
||||
__u32 in_str;
|
||||
__u32 out_str;
|
||||
};
|
||||
|
||||
#define RC_DATA_SIZE_MAX 2720
|
||||
#define RC_CFG_SIZE_MAX 4
|
||||
|
||||
struct drm_msm_rc_mask_cfg {
|
||||
__u64 flags;
|
||||
__u32 cfg_param_01;
|
||||
__u32 cfg_param_02;
|
||||
__u32 cfg_param_03;
|
||||
__u32 cfg_param_04[RC_CFG_SIZE_MAX];
|
||||
__u32 cfg_param_05[RC_CFG_SIZE_MAX];
|
||||
__u32 cfg_param_06[RC_CFG_SIZE_MAX];
|
||||
__u64 cfg_param_07;
|
||||
__u32 cfg_param_08;
|
||||
__u64 cfg_param_09[RC_DATA_SIZE_MAX];
|
||||
__u32 height;
|
||||
__u32 width;
|
||||
};
|
||||
|
||||
#define FP16_SUPPORTED
|
||||
#define FP16_GC_FLAG_ALPHA_EN (1 << 0)
|
||||
|
||||
/* FP16 GC mode options */
|
||||
#define FP16_GC_MODE_INVALID 0
|
||||
#define FP16_GC_MODE_SRGB 1
|
||||
#define FP16_GC_MODE_PQ 2
|
||||
|
||||
/**
|
||||
* struct drm_msm_fp16_gc - FP16 GC configuration structure
|
||||
* @in flags - Settings flags for FP16 GC
|
||||
* @in mode - Gamma correction mode to use for FP16 GC
|
||||
*/
|
||||
struct drm_msm_fp16_gc {
|
||||
__u64 flags;
|
||||
__u64 mode;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct drm_msm_fp16_csc - FP16 CSC configuration structure
|
||||
* @in flags - Settings flags for FP16 CSC. Currently unused
|
||||
* @in cfg_param_0_len - Length of data for cfg_param_0
|
||||
* @in cfg_param_0 - Data for param 0. Max size is FP16_CSC_CFG0_PARAM_LEN
|
||||
* @in cfg_param_1_len - Length of data for cfg_param_1
|
||||
* @in cfg_param_1 - Data for param 1. Max size is FP16_CSC_CFG1_PARAM_LEN
|
||||
*/
|
||||
#define FP16_CSC_CFG0_PARAM_LEN 12
|
||||
#define FP16_CSC_CFG1_PARAM_LEN 8
|
||||
struct drm_msm_fp16_csc {
|
||||
__u64 flags;
|
||||
__u32 cfg_param_0_len;
|
||||
__u32 cfg_param_0[FP16_CSC_CFG0_PARAM_LEN];
|
||||
__u32 cfg_param_1_len;
|
||||
__u32 cfg_param_1[FP16_CSC_CFG1_PARAM_LEN];
|
||||
};
|
||||
|
||||
#define DIMMING_ENABLE (1 << 0)
|
||||
#define DIMMING_MIN_BL_VALID (1 << 1)
|
||||
struct drm_msm_backlight_info {
|
||||
__u32 brightness_max;
|
||||
__u32 brightness;
|
||||
__u32 bl_level_max;
|
||||
__u32 bl_level;
|
||||
__u32 bl_scale;
|
||||
__u32 bl_scale_sv;
|
||||
__u32 status;
|
||||
__u32 min_bl;
|
||||
__u32 bl_scale_max;
|
||||
__u32 bl_scale_sv_max;
|
||||
};
|
||||
|
||||
#define DIMMING_BL_LUT_LEN 8192
|
||||
struct drm_msm_dimming_bl_lut {
|
||||
__u32 length;
|
||||
__u32 mapped_bl[DIMMING_BL_LUT_LEN];
|
||||
};
|
||||
|
||||
struct drm_msm_opr_value {
|
||||
__u32 num_valid_opr;
|
||||
__u32 opr_value[MAX_DSI_DISPLAY];
|
||||
};
|
||||
|
||||
#define SDE_MAX_ROI 4
|
||||
struct drm_msm_roi {
|
||||
__u32 num_rects;
|
||||
struct drm_clip_rect roi[SDE_MAX_ROI];
|
||||
};
|
||||
|
||||
struct drm_msm_misr_sign {
|
||||
__u64 num_valid_misr;
|
||||
struct drm_msm_roi roi_list;
|
||||
__u64 misr_sign_value[MAX_DSI_DISPLAY];
|
||||
};
|
||||
|
||||
#define UCSC_SUPPORTED
|
||||
|
||||
#define UCSC_CSC_CFG0_PARAM_LEN FP16_CSC_CFG0_PARAM_LEN
|
||||
#define UCSC_CSC_CFG1_PARAM_LEN FP16_CSC_CFG1_PARAM_LEN
|
||||
|
||||
typedef struct drm_msm_fp16_csc drm_msm_ucsc_csc;
|
||||
|
||||
#endif /* _MSM_DRM_PP_H_ */
|
@ -0,0 +1,974 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
|
||||
/*
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _SDE_DRM_H_
|
||||
#define _SDE_DRM_H_
|
||||
|
||||
#include <drm/drm.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Total number of supported color planes */
|
||||
#define SDE_MAX_PLANES 4
|
||||
|
||||
/* Total number of parameterized detail enhancer mapping curves */
|
||||
#define SDE_MAX_DE_CURVES 3
|
||||
|
||||
/* Y/RGB and UV filter configuration */
|
||||
#define FILTER_EDGE_DIRECTED_2D 0x0
|
||||
#define FILTER_CIRCULAR_2D 0x1
|
||||
#define FILTER_SEPARABLE_1D 0x2
|
||||
#define FILTER_BILINEAR 0x3
|
||||
|
||||
/* Alpha filters */
|
||||
#define FILTER_ALPHA_DROP_REPEAT 0x0
|
||||
#define FILTER_ALPHA_BILINEAR 0x1
|
||||
#define FILTER_ALPHA_2D 0x3
|
||||
|
||||
/* Blend filters */
|
||||
#define FILTER_BLEND_CIRCULAR_2D 0x0
|
||||
#define FILTER_BLEND_SEPARABLE_1D 0x1
|
||||
|
||||
/* LUT configuration flags */
|
||||
#define SCALER_LUT_SWAP 0x1
|
||||
#define SCALER_LUT_DIR_WR 0x2
|
||||
#define SCALER_LUT_Y_CIR_WR 0x4
|
||||
#define SCALER_LUT_UV_CIR_WR 0x8
|
||||
#define SCALER_LUT_Y_SEP_WR 0x10
|
||||
#define SCALER_LUT_UV_SEP_WR 0x20
|
||||
|
||||
/**
|
||||
* DRM format modifier tokens
|
||||
*
|
||||
* @DRM_FORMAT_MOD_QCOM_DX: Refers to a DX variant of the base format.
|
||||
* Implementation may be platform and
|
||||
* base-format specific.
|
||||
*/
|
||||
#define DRM_FORMAT_MOD_QCOM_DX fourcc_mod_code(QCOM, 0x2)
|
||||
|
||||
/**
|
||||
* @DRM_FORMAT_MOD_QCOM_TIGHT: Refers to a tightly packed variant of the
|
||||
* base variant. Implementation may be
|
||||
* platform and base-format specific.
|
||||
*/
|
||||
#define DRM_FORMAT_MOD_QCOM_TIGHT fourcc_mod_code(QCOM, 0x4)
|
||||
|
||||
/**
|
||||
* @DRM_FORMAT_MOD_QCOM_TILE: Refers to a tile variant of the base format.
|
||||
* Implementation may be platform and
|
||||
* base-format specific.
|
||||
*/
|
||||
#define DRM_FORMAT_MOD_QCOM_TILE fourcc_mod_code(QCOM, 0x8)
|
||||
|
||||
/**
|
||||
* @DRM_FORMAT_MOD_QCOM_ALPHA_SWAP: Refers to a pixel format for which
|
||||
* its alpha ordering has been reversed.
|
||||
* Implementation may be platform and
|
||||
* base-format specific.
|
||||
*/
|
||||
#define DRM_FORMAT_MOD_QCOM_ALPHA_SWAP fourcc_mod_code(QCOM, 0x10)
|
||||
|
||||
/**
|
||||
* Blend operations for "blend_op" property
|
||||
*
|
||||
* @SDE_DRM_BLEND_OP_NOT_DEFINED: No blend operation defined for the layer.
|
||||
* @SDE_DRM_BLEND_OP_OPAQUE: Apply a constant blend operation. The layer
|
||||
* would appear opaque in case fg plane alpha
|
||||
* is 0xff.
|
||||
* @SDE_DRM_BLEND_OP_PREMULTIPLIED: Apply source over blend rule. Layer already
|
||||
* has alpha pre-multiplication done. If the fg
|
||||
* plane alpha is less than 0xff, apply
|
||||
* modulation as well. This operation is
|
||||
* intended on layers having alpha channel.
|
||||
* @SDE_DRM_BLEND_OP_COVERAGE: Apply source over blend rule. Layer is not
|
||||
* alpha pre-multiplied. Apply
|
||||
* pre-multiplication. If fg plane alpha is
|
||||
* less than 0xff, apply modulation as well.
|
||||
* @SDE_DRM_BLEND_OP_MAX: Used to track maximum blend operation
|
||||
* possible by mdp.
|
||||
* @SDE_DRM_BLEND_OP_SKIP: Skip staging the layer in the layer mixer.
|
||||
*/
|
||||
#define SDE_DRM_BLEND_OP_NOT_DEFINED 0
|
||||
#define SDE_DRM_BLEND_OP_OPAQUE 1
|
||||
#define SDE_DRM_BLEND_OP_PREMULTIPLIED 2
|
||||
#define SDE_DRM_BLEND_OP_COVERAGE 3
|
||||
#define SDE_DRM_BLEND_OP_MAX 4
|
||||
#define SDE_DRM_BLEND_OP_SKIP 5
|
||||
|
||||
/**
|
||||
* Bit masks for "src_config" property
|
||||
* construct bitmask via (1UL << SDE_DRM_<flag>)
|
||||
*/
|
||||
#define SDE_DRM_DEINTERLACE 0 /* Specifies interlaced input */
|
||||
|
||||
/* DRM bitmasks are restricted to 0..63 */
|
||||
#define SDE_DRM_BITMASK_COUNT 64
|
||||
|
||||
/**
|
||||
* Framebuffer modes for "fb_translation_mode" PLANE and CONNECTOR property
|
||||
*
|
||||
* @SDE_DRM_FB_NON_SEC: IOMMU configuration for this framebuffer mode
|
||||
* is non-secure domain and requires
|
||||
* both stage I and stage II translations when
|
||||
* this buffer is accessed by the display HW.
|
||||
* This is the default mode of all frambuffers.
|
||||
* @SDE_DRM_FB_SEC: IOMMU configuration for this framebuffer mode
|
||||
* is secure domain and requires
|
||||
* both stage I and stage II translations when
|
||||
* this buffer is accessed by the display HW.
|
||||
* @SDE_DRM_FB_NON_SEC_DIR_TRANS: IOMMU configuration for this framebuffer mode
|
||||
* is non-secure domain and requires
|
||||
* only stage II translation when
|
||||
* this buffer is accessed by the display HW.
|
||||
* @SDE_DRM_FB_SEC_DIR_TRANS: IOMMU configuration for this framebuffer mode
|
||||
* is secure domain and requires
|
||||
* only stage II translation when
|
||||
* this buffer is accessed by the display HW.
|
||||
*/
|
||||
|
||||
#define SDE_DRM_FB_NON_SEC 0
|
||||
#define SDE_DRM_FB_SEC 1
|
||||
#define SDE_DRM_FB_NON_SEC_DIR_TRANS 2
|
||||
#define SDE_DRM_FB_SEC_DIR_TRANS 3
|
||||
|
||||
/**
|
||||
* Secure levels for "security_level" CRTC property.
|
||||
* CRTC property which specifies what plane types
|
||||
* can be attached to this CRTC. Plane component
|
||||
* derives the plane type based on the FB_MODE.
|
||||
* @ SDE_DRM_SEC_NON_SEC: Both Secure and non-secure plane types can be
|
||||
* attached to this CRTC. This is the default state of
|
||||
* the CRTC.
|
||||
* @ SDE_DRM_SEC_ONLY: Only secure planes can be added to this CRTC. If a
|
||||
* CRTC is instructed to be in this mode it follows the
|
||||
* platform dependent restrictions.
|
||||
*/
|
||||
#define SDE_DRM_SEC_NON_SEC 0
|
||||
#define SDE_DRM_SEC_ONLY 1
|
||||
|
||||
/**
|
||||
* struct sde_drm_pix_ext_v1 - version 1 of pixel ext structure
|
||||
* @num_ext_pxls_lr: Number of total horizontal pixels
|
||||
* @num_ext_pxls_tb: Number of total vertical lines
|
||||
* @left_ftch: Number of extra pixels to overfetch from left
|
||||
* @right_ftch: Number of extra pixels to overfetch from right
|
||||
* @top_ftch: Number of extra lines to overfetch from top
|
||||
* @btm_ftch: Number of extra lines to overfetch from bottom
|
||||
* @left_rpt: Number of extra pixels to repeat from left
|
||||
* @right_rpt: Number of extra pixels to repeat from right
|
||||
* @top_rpt: Number of extra lines to repeat from top
|
||||
* @btm_rpt: Number of extra lines to repeat from bottom
|
||||
*/
|
||||
struct sde_drm_pix_ext_v1 {
|
||||
/*
|
||||
* Number of pixels ext in left, right, top and bottom direction
|
||||
* for all color components.
|
||||
*/
|
||||
__s32 num_ext_pxls_lr[SDE_MAX_PLANES];
|
||||
__s32 num_ext_pxls_tb[SDE_MAX_PLANES];
|
||||
|
||||
/*
|
||||
* Number of pixels needs to be overfetched in left, right, top
|
||||
* and bottom directions from source image for scaling.
|
||||
*/
|
||||
__s32 left_ftch[SDE_MAX_PLANES];
|
||||
__s32 right_ftch[SDE_MAX_PLANES];
|
||||
__s32 top_ftch[SDE_MAX_PLANES];
|
||||
__s32 btm_ftch[SDE_MAX_PLANES];
|
||||
/*
|
||||
* Number of pixels needs to be repeated in left, right, top and
|
||||
* bottom directions for scaling.
|
||||
*/
|
||||
__s32 left_rpt[SDE_MAX_PLANES];
|
||||
__s32 right_rpt[SDE_MAX_PLANES];
|
||||
__s32 top_rpt[SDE_MAX_PLANES];
|
||||
__s32 btm_rpt[SDE_MAX_PLANES];
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sde_drm_scaler_v1 - version 1 of struct sde_drm_scaler
|
||||
* @lr: Pixel extension settings for left/right
|
||||
* @tb: Pixel extension settings for top/botton
|
||||
* @init_phase_x: Initial scaler phase values for x
|
||||
* @phase_step_x: Phase step values for x
|
||||
* @init_phase_y: Initial scaler phase values for y
|
||||
* @phase_step_y: Phase step values for y
|
||||
* @horz_filter: Horizontal filter array
|
||||
* @vert_filter: Vertical filter array
|
||||
*/
|
||||
struct sde_drm_scaler_v1 {
|
||||
/*
|
||||
* Pix ext settings
|
||||
*/
|
||||
struct sde_drm_pix_ext_v1 pe;
|
||||
/*
|
||||
* Phase settings
|
||||
*/
|
||||
__s32 init_phase_x[SDE_MAX_PLANES];
|
||||
__s32 phase_step_x[SDE_MAX_PLANES];
|
||||
__s32 init_phase_y[SDE_MAX_PLANES];
|
||||
__s32 phase_step_y[SDE_MAX_PLANES];
|
||||
|
||||
/*
|
||||
* Filter type to be used for scaling in horizontal and vertical
|
||||
* directions
|
||||
*/
|
||||
__u32 horz_filter[SDE_MAX_PLANES];
|
||||
__u32 vert_filter[SDE_MAX_PLANES];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sde_drm_de_v1 - version 1 of detail enhancer structure
|
||||
* @enable: Enables/disables detail enhancer
|
||||
* @sharpen_level1: Sharpening strength for noise
|
||||
* @sharpen_level2: Sharpening strength for context
|
||||
* @clip: Clip coefficient
|
||||
* @limit: Detail enhancer limit factor
|
||||
* @thr_quiet: Quite zone threshold
|
||||
* @thr_dieout: Die-out zone threshold
|
||||
* @thr_low: Linear zone left threshold
|
||||
* @thr_high: Linear zone right threshold
|
||||
* @prec_shift: Detail enhancer precision
|
||||
* @adjust_a: Mapping curves A coefficients
|
||||
* @adjust_b: Mapping curves B coefficients
|
||||
* @adjust_c: Mapping curves C coefficients
|
||||
*/
|
||||
struct sde_drm_de_v1 {
|
||||
__u32 enable;
|
||||
__s16 sharpen_level1;
|
||||
__s16 sharpen_level2;
|
||||
__u16 clip;
|
||||
__u16 limit;
|
||||
__u16 thr_quiet;
|
||||
__u16 thr_dieout;
|
||||
__u16 thr_low;
|
||||
__u16 thr_high;
|
||||
__u16 prec_shift;
|
||||
__s16 adjust_a[SDE_MAX_DE_CURVES];
|
||||
__s16 adjust_b[SDE_MAX_DE_CURVES];
|
||||
__s16 adjust_c[SDE_MAX_DE_CURVES];
|
||||
};
|
||||
|
||||
/*
|
||||
* Scaler configuration flags
|
||||
*/
|
||||
|
||||
/* Disable dynamic expansion */
|
||||
#define SDE_DYN_EXP_DISABLE 0x1
|
||||
|
||||
#define SDE_DE_LPF_BLEND_FILT
|
||||
#define SDE_DE_LPF_BLEND_FLAG_EN (1 << 0)
|
||||
|
||||
#define SDE_DRM_QSEED3LITE
|
||||
#define SDE_DRM_QSEED4
|
||||
#define SDE_DRM_INLINE_PREDOWNSCALE
|
||||
#define SDE_DRM_QSEED6
|
||||
|
||||
/**
|
||||
* struct sde_drm_scaler_v2 - version 2 of struct sde_drm_scaler
|
||||
* @enable: Scaler enable
|
||||
* @dir_en: Detail enhancer enable
|
||||
* @pe: Pixel extension settings
|
||||
* @horz_decimate: Horizontal decimation factor
|
||||
* @vert_decimate: Vertical decimation factor
|
||||
* @init_phase_x: Initial scaler phase values for x
|
||||
* @phase_step_x: Phase step values for x
|
||||
* @init_phase_y: Initial scaler phase values for y
|
||||
* @phase_step_y: Phase step values for y
|
||||
* @preload_x: Horizontal preload value
|
||||
* @preload_y: Vertical preload value
|
||||
* @src_width: Source width
|
||||
* @src_height: Source height
|
||||
* @dst_width: Destination width
|
||||
* @dst_height: Destination height
|
||||
* @y_rgb_filter_cfg: Y/RGB plane filter configuration
|
||||
* @uv_filter_cfg: UV plane filter configuration
|
||||
* @alpha_filter_cfg: Alpha filter configuration
|
||||
* @blend_cfg: Selection of blend coefficients
|
||||
* @lut_flag: LUT configuration flags
|
||||
* @dir_lut_idx: 2d 4x4 LUT index
|
||||
* @y_rgb_cir_lut_idx: Y/RGB circular LUT index
|
||||
* @uv_cir_lut_idx: UV circular LUT index
|
||||
* @y_rgb_sep_lut_idx: Y/RGB separable LUT index
|
||||
* @uv_sep_lut_idx: UV separable LUT index
|
||||
* @de: Detail enhancer settings
|
||||
* @dir_weight: Directional Weight
|
||||
* @unsharp_mask_blend: Unsharp Blend Filter Ratio
|
||||
* @de_blend: Ratio of two unsharp mask filters
|
||||
* @flags: Scaler configuration flags
|
||||
* @pre_downscale_x_0 Pre-downscale ratio, x-direction, plane 0(Y/RGB)
|
||||
* @pre_downscale_x_1 Pre-downscale ratio, x-direction, plane 1(UV)
|
||||
* @pre_downscale_y_0 Pre-downscale ratio, y-direction, plane 0(Y/RGB)
|
||||
* @pre_downscale_y_1 Pre-downscale ratio, y-direction, plane 1(UV)
|
||||
* @de_lpf_flags: Detail enhancer lpf blned configuration flags
|
||||
* @de_lpf_h: Detail enhancer lpf blend high
|
||||
* @de_lpf_l: Detail enhancer lpf blend low
|
||||
* @de_lpf_m: Detail enhancer lpf blend medium
|
||||
* @dir45_en: 45/-45 degree direction filtering enable
|
||||
* @cor_en: corner enhancer enable
|
||||
*/
|
||||
struct sde_drm_scaler_v2 {
|
||||
/*
|
||||
* General definitions
|
||||
*/
|
||||
__u32 enable;
|
||||
__u32 dir_en;
|
||||
|
||||
/*
|
||||
* Pix ext settings
|
||||
*/
|
||||
struct sde_drm_pix_ext_v1 pe;
|
||||
|
||||
/*
|
||||
* Decimation settings
|
||||
*/
|
||||
__u32 horz_decimate;
|
||||
__u32 vert_decimate;
|
||||
|
||||
/*
|
||||
* Phase settings
|
||||
*/
|
||||
__s32 init_phase_x[SDE_MAX_PLANES];
|
||||
__s32 phase_step_x[SDE_MAX_PLANES];
|
||||
__s32 init_phase_y[SDE_MAX_PLANES];
|
||||
__s32 phase_step_y[SDE_MAX_PLANES];
|
||||
|
||||
__u32 preload_x[SDE_MAX_PLANES];
|
||||
__u32 preload_y[SDE_MAX_PLANES];
|
||||
__u32 src_width[SDE_MAX_PLANES];
|
||||
__u32 src_height[SDE_MAX_PLANES];
|
||||
|
||||
__u32 dst_width;
|
||||
__u32 dst_height;
|
||||
|
||||
__u32 y_rgb_filter_cfg;
|
||||
__u32 uv_filter_cfg;
|
||||
__u32 alpha_filter_cfg;
|
||||
__u32 blend_cfg;
|
||||
|
||||
__u32 lut_flag;
|
||||
__u32 dir_lut_idx;
|
||||
|
||||
/* for Y(RGB) and UV planes*/
|
||||
__u32 y_rgb_cir_lut_idx;
|
||||
__u32 uv_cir_lut_idx;
|
||||
__u32 y_rgb_sep_lut_idx;
|
||||
__u32 uv_sep_lut_idx;
|
||||
|
||||
/*
|
||||
* Detail enhancer settings
|
||||
*/
|
||||
struct sde_drm_de_v1 de;
|
||||
__u32 dir_weight;
|
||||
__u32 unsharp_mask_blend;
|
||||
__u32 de_blend;
|
||||
__u32 flags;
|
||||
|
||||
/*
|
||||
* Inline pre-downscale settings
|
||||
*/
|
||||
__u32 pre_downscale_x_0;
|
||||
__u32 pre_downscale_x_1;
|
||||
__u32 pre_downscale_y_0;
|
||||
__u32 pre_downscale_y_1;
|
||||
|
||||
__u32 de_lpf_flags;
|
||||
__u32 de_lpf_h;
|
||||
__u32 de_lpf_l;
|
||||
__u32 de_lpf_m;
|
||||
__u32 dir45_en;
|
||||
__u32 cor_en;
|
||||
};
|
||||
|
||||
/* Number of dest scalers supported */
|
||||
#define SDE_MAX_DS_COUNT 4
|
||||
|
||||
/*
|
||||
* Destination scaler flag config
|
||||
*/
|
||||
#define SDE_DRM_DESTSCALER_ENABLE 0x1
|
||||
#define SDE_DRM_DESTSCALER_SCALE_UPDATE 0x2
|
||||
#define SDE_DRM_DESTSCALER_ENHANCER_UPDATE 0x4
|
||||
#define SDE_DRM_DESTSCALER_PU_ENABLE 0x8
|
||||
|
||||
/**
|
||||
* struct sde_drm_dest_scaler_cfg - destination scaler config structure
|
||||
* @flags: Flag to switch between mode for destination scaler
|
||||
* refer to destination scaler flag config
|
||||
* @index: Destination scaler selection index
|
||||
* @lm_width: Layer mixer width configuration
|
||||
* @lm_height: Layer mixer height configuration
|
||||
* @scaler_cfg: The scaling parameters for all the mode except disable
|
||||
* Userspace pointer to struct sde_drm_scaler_v2
|
||||
*/
|
||||
struct sde_drm_dest_scaler_cfg {
|
||||
__u32 flags;
|
||||
__u32 index;
|
||||
__u32 lm_width;
|
||||
__u32 lm_height;
|
||||
__u64 scaler_cfg;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sde_drm_dest_scaler_data - destination scaler data struct
|
||||
* @num_dest_scaler: Number of dest scalers to be configured
|
||||
* @ds_cfg: Destination scaler block configuration
|
||||
*/
|
||||
struct sde_drm_dest_scaler_data {
|
||||
__u32 num_dest_scaler;
|
||||
struct sde_drm_dest_scaler_cfg ds_cfg[SDE_MAX_DS_COUNT];
|
||||
};
|
||||
|
||||
/*
|
||||
* Define constants for struct sde_drm_csc
|
||||
*/
|
||||
#define SDE_CSC_MATRIX_COEFF_SIZE 9
|
||||
#define SDE_CSC_CLAMP_SIZE 6
|
||||
#define SDE_CSC_BIAS_SIZE 3
|
||||
|
||||
/**
|
||||
* struct sde_drm_csc_v1 - version 1 of struct sde_drm_csc
|
||||
* @ctm_coeff: Matrix coefficients, in S31.32 format
|
||||
* @pre_bias: Pre-bias array values
|
||||
* @post_bias: Post-bias array values
|
||||
* @pre_clamp: Pre-clamp array values
|
||||
* @post_clamp: Post-clamp array values
|
||||
*/
|
||||
struct sde_drm_csc_v1 {
|
||||
__s64 ctm_coeff[SDE_CSC_MATRIX_COEFF_SIZE];
|
||||
__u32 pre_bias[SDE_CSC_BIAS_SIZE];
|
||||
__u32 post_bias[SDE_CSC_BIAS_SIZE];
|
||||
__u32 pre_clamp[SDE_CSC_CLAMP_SIZE];
|
||||
__u32 post_clamp[SDE_CSC_CLAMP_SIZE];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sde_drm_color - struct to store the color and alpha values
|
||||
* @color_0: Color 0 value
|
||||
* @color_1: Color 1 value
|
||||
* @color_2: Color 2 value
|
||||
* @color_3: Color 3 value
|
||||
*/
|
||||
struct sde_drm_color {
|
||||
__u32 color_0;
|
||||
__u32 color_1;
|
||||
__u32 color_2;
|
||||
__u32 color_3;
|
||||
};
|
||||
|
||||
/* Total number of supported dim layers */
|
||||
#define SDE_MAX_DIM_LAYERS 7
|
||||
|
||||
/* SDE_DRM_DIM_LAYER_CONFIG_FLAG - flags for Dim Layer */
|
||||
/* Color fill inside of the rect, including border */
|
||||
#define SDE_DRM_DIM_LAYER_INCLUSIVE 0x1
|
||||
/* Color fill outside of the rect, excluding border */
|
||||
#define SDE_DRM_DIM_LAYER_EXCLUSIVE 0x2
|
||||
|
||||
/* bitmask for allowed_dsc_reservation_switch property */
|
||||
#define SDE_DP_DSC_RESERVATION_SWITCH (1 << 0)
|
||||
|
||||
/**
|
||||
* struct sde_drm_dim_layer - dim layer cfg struct
|
||||
* @flags: Refer SDE_DRM_DIM_LAYER_CONFIG_FLAG for possible values
|
||||
* @stage: Blending stage of the dim layer
|
||||
* @color_fill: Color fill for dim layer
|
||||
* @rect: Dim layer coordinates
|
||||
*/
|
||||
struct sde_drm_dim_layer_cfg {
|
||||
__u32 flags;
|
||||
__u32 stage;
|
||||
struct sde_drm_color color_fill;
|
||||
struct drm_clip_rect rect;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sde_drm_dim_layer_v1 - version 1 of dim layer struct
|
||||
* @num_layers: Numer of Dim Layers
|
||||
* @layer: Dim layer user cfgs ptr for the num_layers
|
||||
*/
|
||||
struct sde_drm_dim_layer_v1 {
|
||||
__u32 num_layers;
|
||||
struct sde_drm_dim_layer_cfg layer_cfg[SDE_MAX_DIM_LAYERS];
|
||||
};
|
||||
|
||||
/* Writeback Config version definition */
|
||||
#define SDE_DRM_WB_CFG 0x1
|
||||
|
||||
/* SDE_DRM_WB_CONFIG_FLAGS - Writeback configuration flags */
|
||||
#define SDE_DRM_WB_CFG_FLAGS_CONNECTED (1<<0)
|
||||
|
||||
/**
|
||||
* struct sde_drm_wb_cfg - Writeback configuration structure
|
||||
* @flags: see DRM_MSM_WB_CONFIG_FLAGS
|
||||
* @connector_id: writeback connector identifier
|
||||
* @count_modes: Count of modes in modes_ptr
|
||||
* @modes: Pointer to struct drm_mode_modeinfo
|
||||
*/
|
||||
struct sde_drm_wb_cfg {
|
||||
__u32 flags;
|
||||
__u32 connector_id;
|
||||
__u32 count_modes;
|
||||
__u64 modes;
|
||||
};
|
||||
|
||||
#define SDE_MAX_ROI_V1 4
|
||||
#define SDE_DRM_SPR_ROI 1
|
||||
/* DRM_ROI_CONFIG_FLAGS */
|
||||
#define SDE_DRM_ROI_SPR_FLAG_EN (1 << 0)
|
||||
|
||||
/**
|
||||
* struct sde_drm_roi_v1 - list of regions of interest for a drm object
|
||||
* @num_rects: number of valid rectangles in the roi array
|
||||
* @roi: list of roi rectangles
|
||||
* @roi_feature_flags: flags indicates that specific roi rect is valid or not
|
||||
* @spr_roi: list of roi rectangles for spr
|
||||
*/
|
||||
struct sde_drm_roi_v1 {
|
||||
__u32 num_rects;
|
||||
struct drm_clip_rect roi[SDE_MAX_ROI_V1];
|
||||
__u32 roi_feature_flags;
|
||||
struct drm_clip_rect spr_roi[SDE_MAX_ROI_V1];
|
||||
};
|
||||
|
||||
/**
|
||||
* Define extended power modes supported by the SDE connectors.
|
||||
*/
|
||||
#define SDE_MODE_DPMS_ON 0
|
||||
#define SDE_MODE_DPMS_LP1 1
|
||||
#define SDE_MODE_DPMS_LP2 2
|
||||
#define SDE_MODE_DPMS_STANDBY 3
|
||||
#define SDE_MODE_DPMS_SUSPEND 4
|
||||
#define SDE_MODE_DPMS_OFF 5
|
||||
|
||||
/**
|
||||
* sde recovery events for notifying client
|
||||
*/
|
||||
#define SDE_RECOVERY_SUCCESS 0
|
||||
#define SDE_RECOVERY_CAPTURE 1
|
||||
#define SDE_RECOVERY_HARD_RESET 2
|
||||
|
||||
/**
|
||||
* Define UBWC statistics config
|
||||
*/
|
||||
#define UBWC_STATS_MAX_ROI 0x3
|
||||
|
||||
/**
|
||||
* struct sde_drm_ubwc_stats_roi - region of interest for ubwc stats
|
||||
* y_coord0: first y offset from top of display
|
||||
* y_coord1: second y offset from top of display
|
||||
*/
|
||||
struct sde_drm_ubwc_stats_roi {
|
||||
__u16 y_coord0;
|
||||
__u16 y_coord1;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sde_drm_ubwc_stats_data: ubwc statistics
|
||||
* roi: region of interest
|
||||
* worst_bw: worst bandwidth, per roi
|
||||
* worst_bw_y_coord: y offset (row) location of worst bandwidth, per roi
|
||||
* total_bw: total bandwidth, per roi
|
||||
* error: error status
|
||||
* meta_error: meta error data
|
||||
*/
|
||||
struct sde_drm_ubwc_stats_data {
|
||||
struct sde_drm_ubwc_stats_roi roi;
|
||||
__u16 worst_bw[UBWC_STATS_MAX_ROI];
|
||||
__u16 worst_bw_y_coord[UBWC_STATS_MAX_ROI];
|
||||
__u32 total_bw[UBWC_STATS_MAX_ROI];
|
||||
__u32 error;
|
||||
__u32 meta_error;
|
||||
};
|
||||
|
||||
/**
|
||||
* Define frame data config
|
||||
*/
|
||||
#define SDE_FRAME_DATA_BUFFER_MAX 0x3
|
||||
#define SDE_FRAME_DATA_GUARD_BYTES 0xFF
|
||||
#define SDE_FRAME_DATA_MAX_PLANES 0x14
|
||||
|
||||
/**
|
||||
* struct sde_drm_frame_data_buffers_ctrl - control frame data buffers
|
||||
* num_buffers: number of allocated buffers
|
||||
* fds: fd list for allocated buffers
|
||||
*/
|
||||
struct sde_drm_frame_data_buffers_ctrl {
|
||||
__u32 num_buffers;
|
||||
__u32 fds[SDE_FRAME_DATA_BUFFER_MAX];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sde_drm_frame_data_buf - frame data buffer info sent to userspace
|
||||
* fd: buffer fd
|
||||
* offset: offset from buffer address
|
||||
* status: status flag
|
||||
*/
|
||||
struct sde_drm_frame_data_buf {
|
||||
__u32 fd;
|
||||
__u32 offset;
|
||||
__u32 status;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sde_drm_plane_frame_data - definition of plane frame data struct
|
||||
* plane_id: drm plane id
|
||||
* ubwc_stats: ubwc statistics
|
||||
*/
|
||||
struct sde_drm_plane_frame_data {
|
||||
__u32 plane_id;
|
||||
|
||||
struct sde_drm_ubwc_stats_data ubwc_stats;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sde_drm_frame_data_packet - definition of frame data struct
|
||||
* frame_count: interface frame count
|
||||
* commit_count: sw commit count
|
||||
* plane_frame_data: data available per plane
|
||||
*/
|
||||
struct sde_drm_frame_data_packet {
|
||||
__u32 frame_count;
|
||||
__u64 commit_count;
|
||||
|
||||
struct sde_drm_plane_frame_data plane_frame_data[SDE_FRAME_DATA_MAX_PLANES];
|
||||
};
|
||||
|
||||
/*
|
||||
* Colorimetry Data Block values
|
||||
* These bit nums are defined as per the CTA spec
|
||||
* and indicate the colorspaces supported by the sink
|
||||
*/
|
||||
#define DRM_EDID_CLRMETRY_xvYCC_601 (1 << 0)
|
||||
#define DRM_EDID_CLRMETRY_xvYCC_709 (1 << 1)
|
||||
#define DRM_EDID_CLRMETRY_sYCC_601 (1 << 2)
|
||||
#define DRM_EDID_CLRMETRY_ADOBE_YCC_601 (1 << 3)
|
||||
#define DRM_EDID_CLRMETRY_ADOBE_RGB (1 << 4)
|
||||
#define DRM_EDID_CLRMETRY_BT2020_CYCC (1 << 5)
|
||||
#define DRM_EDID_CLRMETRY_BT2020_YCC (1 << 6)
|
||||
#define DRM_EDID_CLRMETRY_BT2020_RGB (1 << 7)
|
||||
#define DRM_EDID_CLRMETRY_DCI_P3 (1 << 15)
|
||||
|
||||
/*
|
||||
* HDR Metadata
|
||||
* These are defined as per EDID spec and shall be used by the sink
|
||||
* to set the HDR metadata for playback from userspace.
|
||||
*/
|
||||
|
||||
#define HDR_PRIMARIES_COUNT 3
|
||||
|
||||
/* HDR EOTF */
|
||||
#define HDR_EOTF_SDR_LUM_RANGE 0x0
|
||||
#define HDR_EOTF_HDR_LUM_RANGE 0x1
|
||||
#define HDR_EOTF_SMTPE_ST2084 0x2
|
||||
#define HDR_EOTF_HLG 0x3
|
||||
|
||||
#define DRM_MSM_EXT_HDR_METADATA
|
||||
#define DRM_MSM_EXT_HDR_PLUS_METADATA
|
||||
struct drm_msm_ext_hdr_metadata {
|
||||
__u32 hdr_state; /* HDR state */
|
||||
__u32 eotf; /* electro optical transfer function */
|
||||
__u32 hdr_supported; /* HDR supported */
|
||||
__u32 display_primaries_x[HDR_PRIMARIES_COUNT]; /* Primaries x */
|
||||
__u32 display_primaries_y[HDR_PRIMARIES_COUNT]; /* Primaries y */
|
||||
__u32 white_point_x; /* white_point_x */
|
||||
__u32 white_point_y; /* white_point_y */
|
||||
__u32 max_luminance; /* Max luminance */
|
||||
__u32 min_luminance; /* Min Luminance */
|
||||
__u32 max_content_light_level; /* max content light level */
|
||||
__u32 max_average_light_level; /* max average light level */
|
||||
|
||||
__u64 hdr_plus_payload; /* user pointer to dynamic HDR payload */
|
||||
__u32 hdr_plus_payload_size;/* size of dynamic HDR payload data */
|
||||
};
|
||||
|
||||
/**
|
||||
* HDR sink properties
|
||||
* These are defined as per EDID spec and shall be used by the userspace
|
||||
* to determine the HDR properties to be set to the sink.
|
||||
*/
|
||||
#define DRM_MSM_EXT_HDR_PROPERTIES
|
||||
#define DRM_MSM_EXT_HDR_PLUS_PROPERTIES
|
||||
struct drm_msm_ext_hdr_properties {
|
||||
__u8 hdr_metadata_type_one; /* static metadata type one */
|
||||
__u32 hdr_supported; /* HDR supported */
|
||||
__u32 hdr_eotf; /* electro optical transfer function */
|
||||
__u32 hdr_max_luminance; /* Max luminance */
|
||||
__u32 hdr_avg_luminance; /* Avg luminance */
|
||||
__u32 hdr_min_luminance; /* Min Luminance */
|
||||
|
||||
__u32 hdr_plus_supported; /* HDR10+ supported */
|
||||
};
|
||||
|
||||
/* HDR WRGB x and y index */
|
||||
#define DISPLAY_PRIMARIES_WX 0
|
||||
#define DISPLAY_PRIMARIES_WY 1
|
||||
#define DISPLAY_PRIMARIES_RX 2
|
||||
#define DISPLAY_PRIMARIES_RY 3
|
||||
#define DISPLAY_PRIMARIES_GX 4
|
||||
#define DISPLAY_PRIMARIES_GY 5
|
||||
#define DISPLAY_PRIMARIES_BX 6
|
||||
#define DISPLAY_PRIMARIES_BY 7
|
||||
#define DISPLAY_PRIMARIES_MAX 8
|
||||
|
||||
struct drm_panel_hdr_properties {
|
||||
__u32 hdr_enabled;
|
||||
|
||||
/* WRGB X and y values arrayed in format */
|
||||
/* [WX, WY, RX, RY, GX, GY, BX, BY] */
|
||||
__u32 display_primaries[DISPLAY_PRIMARIES_MAX];
|
||||
|
||||
/* peak brightness supported by panel */
|
||||
__u32 peak_brightness;
|
||||
/* Blackness level supported by panel */
|
||||
__u32 blackness_level;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct drm_msm_event_req - Payload to event enable/disable ioctls.
|
||||
* @object_id: DRM object id. e.g.: for crtc pass crtc id.
|
||||
* @object_type: DRM object type. e.g.: for crtc set it to DRM_MODE_OBJECT_CRTC.
|
||||
* @event: Event for which notification is being enabled/disabled.
|
||||
* e.g.: for Histogram set - DRM_EVENT_HISTOGRAM.
|
||||
* @client_context: Opaque pointer that will be returned during event response
|
||||
* notification.
|
||||
* @index: Object index(e.g.: crtc index), optional for user-space to set.
|
||||
* Driver will override value based on object_id and object_type.
|
||||
*/
|
||||
struct drm_msm_event_req {
|
||||
__u32 object_id;
|
||||
__u32 object_type;
|
||||
__u32 event;
|
||||
__u64 client_context;
|
||||
__u32 index;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct drm_msm_event_resp - payload returned when read is called for
|
||||
* custom notifications.
|
||||
* @base: Event type and length of complete notification payload.
|
||||
* @info: Contains information about DRM that which raised this event.
|
||||
* @data: Custom payload that driver returns for event type.
|
||||
* size of data = base.length - (sizeof(base) + sizeof(info))
|
||||
*/
|
||||
struct drm_msm_event_resp {
|
||||
struct drm_event base;
|
||||
struct drm_msm_event_req info;
|
||||
__u8 data[];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct drm_msm_power_ctrl: Payload to enable/disable the power vote
|
||||
* @enable: enable/disable the power vote
|
||||
* @flags: operation control flags, for future use
|
||||
*/
|
||||
struct drm_msm_power_ctrl {
|
||||
__u32 enable;
|
||||
__u32 flags;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct drm_msm_early_wakeup: Payload to early wake up display
|
||||
* @wakeup_hint: early wakeup hint.
|
||||
* @connector_id: connector id. e.g.: for connector pass connector id.
|
||||
*/
|
||||
struct drm_msm_early_wakeup {
|
||||
__u32 wakeup_hint;
|
||||
__u32 connector_id;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct drm_msm_display_hint: Payload for display hint
|
||||
* @hint_flags: display hint flags.
|
||||
* @data: data struct. e.g.: for display hint parameter.
|
||||
* Userspace pointer to struct base on hint flags.
|
||||
*/
|
||||
struct drm_msm_display_hint {
|
||||
__u64 data;
|
||||
__u32 hint_flags;
|
||||
};
|
||||
|
||||
#define DRM_NOISE_LAYER_CFG
|
||||
#define DRM_NOISE_TEMPORAL_FLAG (1 << 0)
|
||||
#define DRM_NOISE_ATTN_MAX 255
|
||||
#define DRM_NOISE_STREN_MAX 6
|
||||
|
||||
/**
|
||||
* struct drm_msm_noise_layer_cfg: Payload to enable/disable noise blend
|
||||
* @flags: operation control flags, for future use
|
||||
* @zposn: noise zorder
|
||||
* @zposattn: attenuation zorder
|
||||
* @attn_factor: attenuation factor in range of 1 to 255
|
||||
* @stength: strength in range of 0 to 6
|
||||
* @alpha_noise: attenuation in range of 1 to 255
|
||||
*/
|
||||
struct drm_msm_noise_layer_cfg {
|
||||
__u64 flags;
|
||||
__u32 zposn;
|
||||
__u32 zposattn;
|
||||
__u32 attn_factor;
|
||||
__u32 strength;
|
||||
__u32 alpha_noise;
|
||||
};
|
||||
|
||||
#define FEATURE_DNSC_BLUR
|
||||
/* Downscale Blur - number of gaussian coefficient LUTs */
|
||||
#define DNSC_BLUR_COEF_NUM 64
|
||||
|
||||
/* Downscale Blur flags */
|
||||
#define DNSC_BLUR_EN (1 << 0)
|
||||
#define DNSC_BLUR_RND_8B_EN (1 << 1)
|
||||
#define DNSC_BLUR_DITHER_EN (1 << 2)
|
||||
|
||||
#define DNSC_BLUR_MIRROR_BLK_CFG (1 << 16)
|
||||
#define DNSC_BLUR_INDEPENDENT_BLK_CFG (1 << 17)
|
||||
|
||||
/* Downscale Blur horizontal/vertical filter flags */
|
||||
#define DNSC_BLUR_GAUS_FILTER (1 << 0)
|
||||
#define DNSC_BLUR_PCMN_FILTER (1 << 1)
|
||||
|
||||
/* Downscale Blur Dither matrix size */
|
||||
#define DNSC_BLUR_DITHER_MATRIX_SZ 16
|
||||
|
||||
/* Downscale Blur Dither flags */
|
||||
#define DNSC_BLUR_DITHER_LUMA_MODE (1 << 0)
|
||||
|
||||
/**
|
||||
* struct sde_drm_dnsc_blur_cfg - Downscale Blur config structure
|
||||
* @flags: Flags to indicate features enabled, values are
|
||||
* based on "Downscale Blur flags"
|
||||
* @num_blocks: Active dnsc_blur blocks used for the display
|
||||
* @src_width: Source width configuration
|
||||
* @src_height: Source height configuration
|
||||
* @dst_width: Destination width configuration
|
||||
* @dst_height: Destination height configuration
|
||||
* @flags_h: Flags for horizontal downscaling, values are
|
||||
* based on "Downscale Blur horizontal/vertical filter flags"
|
||||
* @flags_v: Flags for veritcal downscaling
|
||||
* @phase_init_h: Initial phase value for horizontal downscaling
|
||||
* @phase_step_h: Phase step value for horizontal downscaling
|
||||
* @phase_init_v: Initial phase value for vertical downscaling
|
||||
* @phase_step_v: Phase step value for vertical downscaling
|
||||
* @norm_h: Horizontal downscale normalization downshift value
|
||||
* @ratio_h: Horizontal downscale ratio value
|
||||
* @norm_v: Vertical downscale normalization downshift value
|
||||
* @ratio_v: Vertical downscale ratio value
|
||||
* @coef_hori: Horizontal downscale LUT coefficients
|
||||
* @coef_vert: Vertical downscale LUT coefficients
|
||||
* @dither_flags: Flags for dither customization, values are
|
||||
* based on "Downscale Blur Dither flags"
|
||||
* @temporal_en: Temperal dither enable
|
||||
* @c0_bitdepth: c0 component bit depth
|
||||
* @c1_bitdepth: c1 component bit depth
|
||||
* @c2_bitdepth: c2 component bit depth
|
||||
* @c3_bitdepth: c2 component bit depth
|
||||
* @dither_matrix: Dither strength matrix
|
||||
*/
|
||||
struct sde_drm_dnsc_blur_cfg {
|
||||
__u64 flags;
|
||||
__u32 num_blocks;
|
||||
|
||||
__u32 src_width;
|
||||
__u32 src_height;
|
||||
__u32 dst_width;
|
||||
__u32 dst_height;
|
||||
|
||||
__u32 flags_h;
|
||||
__u32 flags_v;
|
||||
|
||||
/* pcmn filter parameters */
|
||||
__u32 phase_init_h;
|
||||
__u32 phase_step_h;
|
||||
__u32 phase_init_v;
|
||||
__u32 phase_step_v;
|
||||
|
||||
/* gaussian filter parameters */
|
||||
__u32 norm_h;
|
||||
__u32 ratio_h;
|
||||
__u32 norm_v;
|
||||
__u32 ratio_v;
|
||||
__u32 coef_hori[DNSC_BLUR_COEF_NUM];
|
||||
__u32 coef_vert[DNSC_BLUR_COEF_NUM];
|
||||
|
||||
/* dither configs */
|
||||
__u64 dither_flags;
|
||||
__u32 temporal_en;
|
||||
__u32 c0_bitdepth;
|
||||
__u32 c1_bitdepth;
|
||||
__u32 c2_bitdepth;
|
||||
__u32 c3_bitdepth;
|
||||
__u32 dither_matrix[DNSC_BLUR_DITHER_MATRIX_SZ];
|
||||
};
|
||||
|
||||
#define DRM_SDE_WB_CONFIG 0x40
|
||||
#define DRM_MSM_REGISTER_EVENT 0x41
|
||||
#define DRM_MSM_DEREGISTER_EVENT 0x42
|
||||
#define DRM_MSM_RMFB2 0x43
|
||||
#define DRM_MSM_POWER_CTRL 0x44
|
||||
#define DRM_MSM_DISPLAY_HINT 0x45
|
||||
|
||||
/* sde custom events */
|
||||
#define DRM_EVENT_HISTOGRAM 0x80000000
|
||||
#define DRM_EVENT_AD_BACKLIGHT 0x80000001
|
||||
#define DRM_EVENT_CRTC_POWER 0x80000002
|
||||
#define DRM_EVENT_SYS_BACKLIGHT 0x80000003
|
||||
#define DRM_EVENT_SDE_POWER 0x80000004
|
||||
#define DRM_EVENT_IDLE_NOTIFY 0x80000005
|
||||
#define DRM_EVENT_PANEL_DEAD 0x80000006 /* ESD event */
|
||||
#define DRM_EVENT_SDE_HW_RECOVERY 0X80000007
|
||||
#define DRM_EVENT_LTM_HIST 0X80000008
|
||||
#define DRM_EVENT_LTM_WB_PB 0X80000009
|
||||
#define DRM_EVENT_LTM_OFF 0X8000000A
|
||||
#define DRM_EVENT_MMRM_CB 0X8000000B
|
||||
#define DRM_EVENT_FRAME_DATA 0x8000000C
|
||||
#define DRM_EVENT_DIMMING_BL 0X8000000D
|
||||
#define DRM_EVENT_VM_RELEASE 0X8000000E
|
||||
#define DRM_EVENT_OPR_VALUE 0X8000000F
|
||||
#define DRM_EVENT_MISR_SIGN 0X80000010
|
||||
|
||||
#ifndef DRM_MODE_FLAG_VID_MODE_PANEL
|
||||
#define DRM_MODE_FLAG_VID_MODE_PANEL 0x01
|
||||
#endif
|
||||
#ifndef DRM_MODE_FLAG_CMD_MODE_PANEL
|
||||
#define DRM_MODE_FLAG_CMD_MODE_PANEL 0x02
|
||||
#endif
|
||||
|
||||
#ifndef DRM_MODE_FLAG_DSI_24BPP
|
||||
#define DRM_MODE_FLAG_DSI_24BPP 0x01
|
||||
#endif
|
||||
#ifndef DRM_MODE_FLAG_DSI_30BPP
|
||||
#define DRM_MODE_FLAG_DSI_30BPP 0x02
|
||||
#endif
|
||||
|
||||
/* display hint flags*/
|
||||
#define DRM_MSM_DISPLAY_EARLY_WAKEUP_HINT 0x01
|
||||
#define DRM_MSM_DISPLAY_POWER_COLLAPSE_HINT 0x02
|
||||
#define DRM_MSM_DISPLAY_IDLE_TIMEOUT_HINT 0x04
|
||||
#define DRM_MSM_DISPLAY_MODE_CHANGE_HINT 0x08
|
||||
|
||||
#define DRM_MSM_WAKE_UP_ALL_DISPLAYS 0xFFFFFFFF
|
||||
|
||||
#define DRM_IOCTL_SDE_WB_CONFIG \
|
||||
DRM_IOW((DRM_COMMAND_BASE + DRM_SDE_WB_CONFIG), struct sde_drm_wb_cfg)
|
||||
#define DRM_IOCTL_MSM_REGISTER_EVENT DRM_IOW((DRM_COMMAND_BASE + \
|
||||
DRM_MSM_REGISTER_EVENT), struct drm_msm_event_req)
|
||||
#define DRM_IOCTL_MSM_DEREGISTER_EVENT DRM_IOW((DRM_COMMAND_BASE + \
|
||||
DRM_MSM_DEREGISTER_EVENT), struct drm_msm_event_req)
|
||||
#define DRM_IOCTL_MSM_RMFB2 DRM_IOW((DRM_COMMAND_BASE + \
|
||||
DRM_MSM_RMFB2), unsigned int)
|
||||
#define DRM_IOCTL_MSM_POWER_CTRL DRM_IOW((DRM_COMMAND_BASE + \
|
||||
DRM_MSM_POWER_CTRL), struct drm_msm_power_ctrl)
|
||||
#define DRM_IOCTL_MSM_DISPLAY_HINT DRM_IOW((DRM_COMMAND_BASE + \
|
||||
DRM_MSM_DISPLAY_HINT), struct drm_msm_display_hint)
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _SDE_DRM_H_ */
|
@ -0,0 +1,3 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note
|
||||
|
||||
header-y += msm_hdmi_hdcp_mgr.h
|
@ -0,0 +1,61 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
|
||||
/*
|
||||
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _UAPI__MSM_HDMI_HDCP_MGR_H
|
||||
#define _UAPI__MSM_HDMI_HDCP_MGR_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
enum DS_TYPE { /* type of downstream device */
|
||||
DS_UNKNOWN,
|
||||
DS_RECEIVER,
|
||||
DS_REPEATER,
|
||||
};
|
||||
|
||||
enum {
|
||||
MSG_ID_IDX,
|
||||
RET_CODE_IDX,
|
||||
HEADER_LEN,
|
||||
};
|
||||
|
||||
enum RET_CODE {
|
||||
HDCP_NOT_AUTHED,
|
||||
HDCP_AUTHED,
|
||||
HDCP_DISABLE,
|
||||
};
|
||||
|
||||
enum MSG_ID { /* List of functions expected to be called after it */
|
||||
DOWN_CHECK_TOPOLOGY,
|
||||
UP_REQUEST_TOPOLOGY,
|
||||
UP_SEND_TOPOLOGY,
|
||||
DOWN_REQUEST_TOPOLOGY,
|
||||
MSG_NUM,
|
||||
};
|
||||
|
||||
enum SOURCE_ID {
|
||||
HDCP_V1_TX,
|
||||
HDCP_V1_RX,
|
||||
HDCP_V2_RX,
|
||||
HDCP_V2_TX,
|
||||
SRC_NUM,
|
||||
};
|
||||
|
||||
/*
|
||||
* how to parse sysfs params buffer
|
||||
* from hdcp_tx driver.
|
||||
*/
|
||||
|
||||
struct HDCP_V2V1_MSG_TOPOLOGY {
|
||||
/* indicates downstream's type */
|
||||
__u32 ds_type;
|
||||
__u8 bksv[5];
|
||||
__u8 dev_count;
|
||||
__u8 depth;
|
||||
__u8 ksv_list[5 * 127];
|
||||
__u32 max_cascade_exceeded;
|
||||
__u32 max_dev_exceeded;
|
||||
};
|
||||
|
||||
#endif /* _UAPI__MSM_HDMI_HDCP_MGR_H */
|
@ -0,0 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note
|
||||
|
||||
header-y += msm_sde_rotator.h
|
||||
header-y += mmm_color_fmt.h
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,180 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
|
||||
/*
|
||||
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __UAPI_MSM_SDE_ROTATOR_H__
|
||||
#define __UAPI_MSM_SDE_ROTATOR_H__
|
||||
|
||||
#include <linux/videodev2.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/ioctl.h>
|
||||
|
||||
/* SDE Rotator pixel format definitions */
|
||||
#define SDE_PIX_FMT_XRGB_8888 \
|
||||
v4l2_fourcc('X', 'R', '2', '4') /* 32 BGRX-8-8-8-8 */
|
||||
#define SDE_PIX_FMT_ARGB_8888 \
|
||||
v4l2_fourcc('A', 'R', '2', '4') /* 32 BGRA-8-8-8-8 */
|
||||
#define SDE_PIX_FMT_ABGR_8888 \
|
||||
v4l2_fourcc('R', 'A', '2', '4') /* 32-bit ABGR 8:8:8:8 */
|
||||
#define SDE_PIX_FMT_RGBA_8888 \
|
||||
v4l2_fourcc('A', 'B', '2', '4') /* 32-bit RGBA 8:8:8:8 */
|
||||
#define SDE_PIX_FMT_BGRA_8888 \
|
||||
v4l2_fourcc('B', 'A', '2', '4') /* 32 ARGB-8-8-8-8 */
|
||||
#define SDE_PIX_FMT_RGBX_8888 \
|
||||
v4l2_fourcc('X', 'B', '2', '4') /* 32-bit RGBX 8:8:8:8 */
|
||||
#define SDE_PIX_FMT_BGRX_8888 \
|
||||
v4l2_fourcc('B', 'X', '2', '4') /* 32 XRGB-8-8-8-8 */
|
||||
#define SDE_PIX_FMT_XBGR_8888 \
|
||||
v4l2_fourcc('R', 'X', '2', '4') /* 32-bit XBGR 8:8:8:8 */
|
||||
#define SDE_PIX_FMT_RGBA_5551 \
|
||||
v4l2_fourcc('R', 'A', '1', '5') /* 16-bit RGBA 5:5:5:1 */
|
||||
#define SDE_PIX_FMT_ARGB_1555 \
|
||||
v4l2_fourcc('A', 'R', '1', '5') /* 16 ARGB-1-5-5-5 */
|
||||
#define SDE_PIX_FMT_ABGR_1555 \
|
||||
v4l2_fourcc('A', 'B', '1', '5') /* 16-bit ABGR 1:5:5:5 */
|
||||
#define SDE_PIX_FMT_BGRA_5551 \
|
||||
v4l2_fourcc('B', 'A', '1', '5') /* 16-bit BGRA 5:5:5:1 */
|
||||
#define SDE_PIX_FMT_BGRX_5551 \
|
||||
v4l2_fourcc('B', 'X', '1', '5') /* 16-bit BGRX 5:5:5:1 */
|
||||
#define SDE_PIX_FMT_RGBX_5551 \
|
||||
v4l2_fourcc('R', 'X', '1', '5') /* 16-bit RGBX 5:5:5:1 */
|
||||
#define SDE_PIX_FMT_XBGR_1555 \
|
||||
v4l2_fourcc('X', 'B', '1', '5') /* 16-bit XBGR 1:5:5:5 */
|
||||
#define SDE_PIX_FMT_XRGB_1555 \
|
||||
v4l2_fourcc('X', 'R', '1', '5') /* 16 XRGB-1-5-5-5 */
|
||||
#define SDE_PIX_FMT_ARGB_4444 \
|
||||
v4l2_fourcc('A', 'R', '1', '2') /* 16 aaaarrrr ggggbbbb */
|
||||
#define SDE_PIX_FMT_RGBA_4444 \
|
||||
v4l2_fourcc('R', 'A', '1', '2') /* 16-bit RGBA 4:4:4:4 */
|
||||
#define SDE_PIX_FMT_BGRA_4444 \
|
||||
v4l2_fourcc('b', 'A', '1', '2') /* 16-bit BGRA 4:4:4:4 */
|
||||
#define SDE_PIX_FMT_ABGR_4444 \
|
||||
v4l2_fourcc('A', 'B', '1', '2') /* 16-bit ABGR 4:4:4:4 */
|
||||
#define SDE_PIX_FMT_RGBX_4444 \
|
||||
v4l2_fourcc('R', 'X', '1', '2') /* 16-bit RGBX 4:4:4:4 */
|
||||
#define SDE_PIX_FMT_XRGB_4444 \
|
||||
v4l2_fourcc('X', 'R', '1', '2') /* 16 xxxxrrrr ggggbbbb */
|
||||
#define SDE_PIX_FMT_BGRX_4444 \
|
||||
v4l2_fourcc('B', 'X', '1', '2') /* 16-bit BGRX 4:4:4:4 */
|
||||
#define SDE_PIX_FMT_XBGR_4444 \
|
||||
v4l2_fourcc('X', 'B', '1', '2') /* 16-bit XBGR 4:4:4:4 */
|
||||
#define SDE_PIX_FMT_RGB_888 \
|
||||
v4l2_fourcc('R', 'G', 'B', '3') /* 24 RGB-8-8-8 */
|
||||
#define SDE_PIX_FMT_BGR_888 \
|
||||
v4l2_fourcc('B', 'G', 'R', '3') /* 24 BGR-8-8-8 */
|
||||
#define SDE_PIX_FMT_RGB_565 \
|
||||
v4l2_fourcc('R', 'G', 'B', 'P') /* 16 RGB-5-6-5 */
|
||||
#define SDE_PIX_FMT_BGR_565 \
|
||||
v4l2_fourcc('B', 'G', '1', '6') /* 16-bit BGR 5:6:5 */
|
||||
#define SDE_PIX_FMT_Y_CB_CR_H2V2 \
|
||||
v4l2_fourcc('Y', 'U', '1', '2') /* 12 YUV 4:2:0 */
|
||||
#define SDE_PIX_FMT_Y_CR_CB_H2V2 \
|
||||
v4l2_fourcc('Y', 'V', '1', '2') /* 12 YVU 4:2:0 */
|
||||
#define SDE_PIX_FMT_Y_CR_CB_GH2V2 \
|
||||
v4l2_fourcc('Y', 'U', '4', '2') /* Planar YVU 4:2:0 A16 */
|
||||
#define SDE_PIX_FMT_Y_CBCR_H2V2 \
|
||||
v4l2_fourcc('N', 'V', '1', '2') /* 12 Y/CbCr 4:2:0 */
|
||||
#define SDE_PIX_FMT_Y_CRCB_H2V2 \
|
||||
v4l2_fourcc('N', 'V', '2', '1') /* 12 Y/CrCb 4:2:0 */
|
||||
#define SDE_PIX_FMT_Y_CBCR_H1V2 \
|
||||
v4l2_fourcc('N', 'H', '1', '6') /* Y/CbCr 4:2:2 */
|
||||
#define SDE_PIX_FMT_Y_CRCB_H1V2 \
|
||||
v4l2_fourcc('N', 'H', '6', '1') /* Y/CrCb 4:2:2 */
|
||||
#define SDE_PIX_FMT_Y_CBCR_H2V1 \
|
||||
v4l2_fourcc('N', 'V', '1', '6') /* 16 Y/CbCr 4:2:2 */
|
||||
#define SDE_PIX_FMT_Y_CRCB_H2V1 \
|
||||
v4l2_fourcc('N', 'V', '6', '1') /* 16 Y/CrCb 4:2:2 */
|
||||
#define SDE_PIX_FMT_YCBYCR_H2V1 \
|
||||
v4l2_fourcc('Y', 'U', 'Y', 'V') /* 16 YUV 4:2:2 */
|
||||
#define SDE_PIX_FMT_Y_CBCR_H2V2_VENUS \
|
||||
v4l2_fourcc('Q', 'N', 'V', '2') /* Y/CbCr 4:2:0 Venus */
|
||||
#define SDE_PIX_FMT_Y_CRCB_H2V2_VENUS \
|
||||
v4l2_fourcc('Q', 'N', 'V', '1') /* Y/CrCb 4:2:0 Venus */
|
||||
#define SDE_PIX_FMT_RGBA_8888_UBWC \
|
||||
v4l2_fourcc('Q', 'R', 'G', 'B') /* RGBA 8:8:8:8 UBWC */
|
||||
#define SDE_PIX_FMT_RGBX_8888_UBWC \
|
||||
v4l2_fourcc('Q', 'X', 'B', '4') /* RGBX 8:8:8:8 UBWC */
|
||||
#define SDE_PIX_FMT_RGB_565_UBWC \
|
||||
v4l2_fourcc('Q', 'R', 'G', '6') /* RGB 5:6:5 UBWC */
|
||||
#define SDE_PIX_FMT_Y_CBCR_H2V2_UBWC \
|
||||
v4l2_fourcc('Q', '1', '2', '8') /* UBWC 8-bit Y/CbCr 4:2:0 */
|
||||
#define SDE_PIX_FMT_RGBA_1010102 \
|
||||
v4l2_fourcc('A', 'B', '3', '0') /* RGBA 10:10:10:2 */
|
||||
#define SDE_PIX_FMT_RGBX_1010102 \
|
||||
v4l2_fourcc('X', 'B', '3', '0') /* RGBX 10:10:10:2 */
|
||||
#define SDE_PIX_FMT_ARGB_2101010 \
|
||||
v4l2_fourcc('A', 'R', '3', '0') /* ARGB 2:10:10:10 */
|
||||
#define SDE_PIX_FMT_XRGB_2101010 \
|
||||
v4l2_fourcc('X', 'R', '3', '0') /* XRGB 2:10:10:10 */
|
||||
#define SDE_PIX_FMT_BGRA_1010102 \
|
||||
v4l2_fourcc('B', 'A', '3', '0') /* BGRA 10:10:10:2 */
|
||||
#define SDE_PIX_FMT_BGRX_1010102 \
|
||||
v4l2_fourcc('B', 'X', '3', '0') /* BGRX 10:10:10:2 */
|
||||
#define SDE_PIX_FMT_ABGR_2101010 \
|
||||
v4l2_fourcc('R', 'A', '3', '0') /* ABGR 2:10:10:10 */
|
||||
#define SDE_PIX_FMT_XBGR_2101010 \
|
||||
v4l2_fourcc('R', 'X', '3', '0') /* XBGR 2:10:10:10 */
|
||||
#define SDE_PIX_FMT_RGBA_1010102_UBWC \
|
||||
v4l2_fourcc('Q', 'R', 'B', 'A') /* RGBA 10:10:10:2 UBWC */
|
||||
#define SDE_PIX_FMT_RGBX_1010102_UBWC \
|
||||
v4l2_fourcc('Q', 'X', 'B', 'A') /* RGBX 10:10:10:2 UBWC */
|
||||
#define SDE_PIX_FMT_Y_CBCR_H2V2_P010 \
|
||||
v4l2_fourcc('P', '0', '1', '0') /* Y/CbCr 4:2:0 P10 */
|
||||
#define SDE_PIX_FMT_Y_CBCR_H2V2_P010_VENUS \
|
||||
v4l2_fourcc('Q', 'P', '1', '0') /* Y/CbCr 4:2:0 P10 Venus*/
|
||||
#define SDE_PIX_FMT_Y_CBCR_H2V2_TP10 \
|
||||
v4l2_fourcc('T', 'P', '1', '0') /* Y/CbCr 4:2:0 TP10 */
|
||||
#define SDE_PIX_FMT_Y_CBCR_H2V2_TP10_UBWC \
|
||||
v4l2_fourcc('Q', '1', '2', 'A') /* UBWC Y/CbCr 4:2:0 TP10 */
|
||||
#define SDE_PIX_FMT_Y_CBCR_H2V2_P010_UBWC \
|
||||
v4l2_fourcc('Q', '1', '2', 'B') /* UBWC Y/CbCr 4:2:0 P10 */
|
||||
|
||||
/*
|
||||
* struct msm_sde_rotator_fence - v4l2 buffer fence info
|
||||
* @index: id number of the buffer
|
||||
* @type: enum v4l2_buf_type; buffer type
|
||||
* @fd: file descriptor of the fence associated with this buffer
|
||||
*/
|
||||
struct msm_sde_rotator_fence {
|
||||
__u32 index;
|
||||
__u32 type;
|
||||
__s32 fd;
|
||||
__u32 reserved[5];
|
||||
};
|
||||
|
||||
/*
|
||||
* struct msm_sde_rotator_comp_ratio - v4l2 buffer compression ratio
|
||||
* @index: id number of the buffer
|
||||
* @type: enum v4l2_buf_type; buffer type
|
||||
* @numer: numerator of the ratio
|
||||
* @denom: denominator of the ratio
|
||||
*/
|
||||
struct msm_sde_rotator_comp_ratio {
|
||||
__u32 index;
|
||||
__u32 type;
|
||||
__u32 numer;
|
||||
__u32 denom;
|
||||
__u32 reserved[4];
|
||||
};
|
||||
|
||||
/* SDE Rotator private ioctl ID */
|
||||
#define VIDIOC_G_SDE_ROTATOR_FENCE \
|
||||
_IOWR('V', BASE_VIDIOC_PRIVATE + 10, struct msm_sde_rotator_fence)
|
||||
#define VIDIOC_S_SDE_ROTATOR_FENCE \
|
||||
_IOWR('V', BASE_VIDIOC_PRIVATE + 11, struct msm_sde_rotator_fence)
|
||||
#define VIDIOC_G_SDE_ROTATOR_COMP_RATIO \
|
||||
_IOWR('V', BASE_VIDIOC_PRIVATE + 12, struct msm_sde_rotator_comp_ratio)
|
||||
#define VIDIOC_S_SDE_ROTATOR_COMP_RATIO \
|
||||
_IOWR('V', BASE_VIDIOC_PRIVATE + 13, struct msm_sde_rotator_comp_ratio)
|
||||
|
||||
/* SDE Rotator private control ID's */
|
||||
#define V4L2_CID_SDE_ROTATOR_SECURE (V4L2_CID_USER_BASE + 0x1000)
|
||||
|
||||
/*
|
||||
* This control Id indicates this context is associated with the
|
||||
* secure camera.
|
||||
*/
|
||||
#define V4L2_CID_SDE_ROTATOR_SECURE_CAMERA (V4L2_CID_USER_BASE + 0x2000)
|
||||
|
||||
#endif /* __UAPI_MSM_SDE_ROTATOR_H__ */
|
75
qcom/opensource/display-drivers/msm/Android.mk
Normal file
75
qcom/opensource/display-drivers/msm/Android.mk
Normal file
@ -0,0 +1,75 @@
|
||||
DISPLAY_SELECT := CONFIG_DRM_MSM=m
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
ifeq ($(TARGET_BOARD_PLATFORM), niobe)
|
||||
LOCAL_MODULE_DDK_BUILD := false
|
||||
else
|
||||
LOCAL_MODULE_DDK_BUILD := true
|
||||
endif
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE_DDK_SUBTARGET_REGEX := "display_drivers*"
|
||||
ifeq ($(TARGET_BOARD_PLATFORM), volcano)
|
||||
LOCAL_MODULE_DDK_SUBTARGET_REGEX := "$(TARGET_BOARD_PLATFORM)_display_drivers.*"
|
||||
endif
|
||||
|
||||
# This makefile is only for DLKM
|
||||
ifneq ($(findstring vendor,$(LOCAL_PATH)),)
|
||||
|
||||
ifneq ($(findstring opensource,$(LOCAL_PATH)),)
|
||||
DISPLAY_BLD_DIR := $(TOP)/vendor/qcom/opensource/display-drivers
|
||||
endif # opensource
|
||||
|
||||
DLKM_DIR := $(TOP)/device/qcom/common/dlkm
|
||||
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*)
|
||||
|
||||
# Build display.ko as msm_drm.ko
|
||||
###########################################################
|
||||
# This is set once per LOCAL_PATH, not per (kernel) module
|
||||
KBUILD_OPTIONS := DISPLAY_ROOT=$(DISPLAY_BLD_DIR)
|
||||
KBUILD_OPTIONS += MODNAME=msm_drm
|
||||
KBUILD_OPTIONS += BOARD_PLATFORM=$(TARGET_BOARD_PLATFORM)
|
||||
KBUILD_OPTIONS += $(DISPLAY_SELECT)
|
||||
|
||||
ifneq ($(TARGET_BOARD_AUTO),true)
|
||||
ifneq ($(TARGET_BOARD_PLATFORM), pitti)
|
||||
KBUILD_OPTIONS += KBUILD_EXTRA_SYMBOLS+=$(PWD)/$(call intermediates-dir-for,DLKM,mmrm-module-symvers)/Module.symvers
|
||||
endif
|
||||
ifneq ($(TARGET_BOARD_PLATFORM), taro)
|
||||
KBUILD_OPTIONS += KBUILD_EXTRA_SYMBOLS+=$(PWD)/$(call intermediates-dir-for,DLKM,sync-fence-module-symvers)/Module.symvers
|
||||
KBUILD_OPTIONS += KBUILD_EXTRA_SYMBOLS+=$(PWD)/$(call intermediates-dir-for,DLKM,msm-ext-disp-module-symvers)/Module.symvers
|
||||
KBUILD_OPTIONS += KBUILD_EXTRA_SYMBOLS+=$(PWD)/$(call intermediates-dir-for,DLKM,hw-fence-module-symvers)/Module.symvers
|
||||
KBUILD_OPTIONS += KBUILD_EXTRA_SYMBOLS+=$(PWD)/$(call intermediates-dir-for,DLKM,sec-module-symvers)/Module.symvers
|
||||
endif
|
||||
endif
|
||||
|
||||
###########################################################
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*)
|
||||
LOCAL_MODULE := msm_drm.ko
|
||||
LOCAL_MODULE_KBUILD_NAME := msm_drm.ko
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE_DEBUG_ENABLE := true
|
||||
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
|
||||
|
||||
ifneq ($(TARGET_BOARD_AUTO),true)
|
||||
ifneq ($(TARGET_BOARD_PLATFORM), pitti)
|
||||
LOCAL_REQUIRED_MODULES += mmrm-module-symvers
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES += $(call intermediates-dir-for,DLKM,mmrm-module-symvers)/Module.symvers
|
||||
endif
|
||||
ifneq ($(TARGET_BOARD_PLATFORM), taro)
|
||||
LOCAL_REQUIRED_MODULES += sync-fence-module-symvers
|
||||
LOCAL_REQUIRED_MODULES += msm-ext-disp-module-symvers
|
||||
LOCAL_REQUIRED_MODULES += hw-fence-module-symvers
|
||||
LOCAL_REQUIRED_MODULES += sec-module-symvers
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES += $(call intermediates-dir-for,DLKM,sync-fence-module-symvers)/Module.symvers
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES += $(call intermediates-dir-for,DLKM,msm-ext-disp-module-symvers)/Module.symvers
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES += $(call intermediates-dir-for,DLKM,hw-fence-module-symvers)/Module.symvers
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES += $(call intermediates-dir-for,DLKM,sec-module-symvers)/Module.symvers
|
||||
endif
|
||||
endif
|
||||
|
||||
include $(DLKM_DIR)/Build_external_kernelmodule.mk
|
||||
###########################################################
|
||||
endif # DLKM check
|
267
qcom/opensource/display-drivers/msm/Kbuild
Normal file
267
qcom/opensource/display-drivers/msm/Kbuild
Normal file
@ -0,0 +1,267 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
KDIR := $(TOP)/kernel_platform/msm-kernel
|
||||
|
||||
ifeq ($(CONFIG_ARCH_WAIPIO), y)
|
||||
ifeq ($(CONFIG_ARCH_QTI_VM), y)
|
||||
include $(DISPLAY_ROOT)/config/gki_waipiodisptui.conf
|
||||
LINUX_INC += -include $(DISPLAY_ROOT)/config/gki_waipiodisptuiconf.h
|
||||
else
|
||||
include $(DISPLAY_ROOT)/config/gki_waipiodisp.conf
|
||||
LINUX_INC += -include $(DISPLAY_ROOT)/config/gki_waipiodispconf.h
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ARCH_NEO), y)
|
||||
include $(DISPLAY_ROOT)/config/gki_neodisp.conf
|
||||
LINUX_INC += -include $(DISPLAY_ROOT)/config/gki_neodispconf.h
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ARCH_PARROT), y)
|
||||
include $(DISPLAY_ROOT)/config/gki_parrotdisp.conf
|
||||
LINUX_INC += -include $(DISPLAY_ROOT)/config/gki_parrotdispconf.h
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ARCH_PITTI), y)
|
||||
include $(DISPLAY_ROOT)/config/gki_pittidisp.conf
|
||||
LINUX_INC += -include $(DISPLAY_ROOT)/config/gki_pittidispconf.h
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ARCH_NIOBE), y)
|
||||
include $(DISPLAY_ROOT)/config/gki_niobedisp.conf
|
||||
LINUX_INC += -include $(DISPLAY_ROOT)/config/gki_niobedispconf.h
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ARCH_PINEAPPLE), y)
|
||||
ifeq ($(CONFIG_ARCH_QTI_VM), y)
|
||||
include $(DISPLAY_ROOT)/config/gki_pineappledisptui.conf
|
||||
LINUX_INC += -include $(DISPLAY_ROOT)/config/gki_pineappledisptuiconf.h
|
||||
else
|
||||
include $(DISPLAY_ROOT)/config/gki_pineappledisp.conf
|
||||
LINUX_INC += -include $(DISPLAY_ROOT)/config/gki_pineappledispconf.h
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ARCH_KALAMA), y)
|
||||
ifeq ($(CONFIG_ARCH_QTI_VM), y)
|
||||
include $(DISPLAY_ROOT)/config/gki_kalamadisptui.conf
|
||||
LINUX_INC += -include $(DISPLAY_ROOT)/config/gki_kalamadisptuiconf.h
|
||||
else
|
||||
include $(DISPLAY_ROOT)/config/gki_kalamadisp.conf
|
||||
LINUX_INC += -include $(DISPLAY_ROOT)/config/gki_kalamadispconf.h
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq (y, $(findstring y, $(CONFIG_ARCH_SA8155) $(CONFIG_ARCH_SA6155) $(CONFIG_ARCH_SA8195)))
|
||||
include $(DISPLAY_ROOT)/config/augen3disp.conf
|
||||
LINUX_INC += -include $(DISPLAY_ROOT)/config/augen3dispconf.h
|
||||
endif
|
||||
|
||||
LINUX_INC += -I$(KERNEL_SRC)/include/linux \
|
||||
-I$(KERNEL_SRC)/include/linux/drm
|
||||
|
||||
LINUX_INC += -I$(DISPLAY_ROOT) \
|
||||
-I$(DISPLAY_ROOT)/include \
|
||||
-I$(KERNEL_ROOT)/drivers/clk/qcom \
|
||||
-I$(KERNEL_SRC)/drivers/clk/qcom \
|
||||
-I$(DISPLAY_ROOT)/include/linux \
|
||||
-I$(DISPLAY_ROOT)/rotator \
|
||||
-I$(DISPLAY_ROOT)/msm \
|
||||
-I$(DISPLAY_ROOT)/msm/dp \
|
||||
-I$(DISPLAY_ROOT)/msm/dsi \
|
||||
-I$(DISPLAY_ROOT)/msm/sde \
|
||||
-I$(DISPLAY_ROOT)/include/uapi/display \
|
||||
|
||||
CDEFINES += -DANI_LITTLE_BYTE_ENDIAN \
|
||||
-DANI_LITTLE_BIT_ENDIAN \
|
||||
-DDOT11F_LITTLE_ENDIAN_HOST \
|
||||
-DANI_COMPILER_TYPE_GCC \
|
||||
-DANI_OS_TYPE_ANDROID=6 \
|
||||
-DPTT_SOCK_SVC_ENABLE \
|
||||
-Wall\
|
||||
-Werror\
|
||||
-D__linux__
|
||||
|
||||
KBUILD_CPPFLAGS += $(CDEFINES)
|
||||
|
||||
ccflags-y += $(LINUX_INC)
|
||||
|
||||
ifeq ($(call cc-option-yn, -Wmaybe-uninitialized),y)
|
||||
EXTRA_CFLAGS += -Wmaybe-uninitialized
|
||||
endif
|
||||
|
||||
KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/display-drivers/hdcp/Module.symvers
|
||||
KBUILD_EXTRA_SYMBOLS +=$(OUT)/obj/vendor/qcom/opensource/display-drivers/msm/Module.symvers
|
||||
|
||||
ifeq ($(call cc-option-yn, -Wheader-guard),y)
|
||||
EXTRA_CFLAGS += -Wheader-guard
|
||||
endif
|
||||
|
||||
ccflags-y += -Wformat-extra-args -Wstrict-prototypes -Wformat-insufficient-args \
|
||||
-Wformat-invalid-specifier -Wformat-zero-length -Wnonnull
|
||||
|
||||
ifneq ($(MODNAME), qdsp6v2)
|
||||
CHIP_NAME ?= $(MODNAME)
|
||||
CDEFINES += -DMULTI_IF_NAME=\"$(CHIP_NAME)\"
|
||||
endif
|
||||
|
||||
######### CONFIG_DRM_MSM ########
|
||||
obj-m += msm_drm.o
|
||||
|
||||
msm_drm-$(CONFIG_HDCP_QSEECOM) := ../hdcp/msm_hdcp.o \
|
||||
dp/dp_hdcp2p2.o \
|
||||
sde_hdcp_1x.o \
|
||||
sde_hdcp_2x.o
|
||||
|
||||
msm_drm-$(CONFIG_MSM_SDE_ROTATOR) += ../rotator/sde_rotator_dev.o \
|
||||
../rotator/sde_rotator_dev.o \
|
||||
../rotator/sde_rotator_core.o \
|
||||
../rotator/sde_rotator_base.o \
|
||||
../rotator/sde_rotator_formats.o \
|
||||
../rotator/sde_rotator_util.o \
|
||||
../rotator/sde_rotator_io_util.o \
|
||||
../rotator/sde_rotator_smmu.o \
|
||||
../rotator/sde_rotator_r1_wb.o \
|
||||
../rotator/sde_rotator_r1_pipe.o \
|
||||
../rotator/sde_rotator_r1_ctl.o \
|
||||
../rotator/sde_rotator_r1.o \
|
||||
../rotator/sde_rotator_r3.o
|
||||
|
||||
ifeq ($(CONFIG_MSM_SDE_ROTATOR), y)
|
||||
msm_drm-$(CONFIG_SYNC_FILE) += ../rotator/sde_rotator_sync.o
|
||||
|
||||
msm_drm-$(CONFIG_DEBUG_FS) += ../rotator/sde_rotator_debug.o \
|
||||
../rotator/sde_rotator_r1_debug.o \
|
||||
../rotator/sde_rotator_r3_debug.o
|
||||
endif
|
||||
|
||||
msm_drm-$(CONFIG_DRM_SDE_VM) += sde/sde_vm_common.o \
|
||||
sde/sde_vm_primary.o \
|
||||
sde/sde_vm_trusted.o \
|
||||
sde/sde_vm_msgq.o
|
||||
|
||||
msm_drm-$(CONFIG_DRM_MSM_DP) += dp/dp_altmode.o \
|
||||
dp/dp_parser.o \
|
||||
dp/dp_power.o \
|
||||
dp/dp_catalog.o \
|
||||
dp/dp_catalog_v420.o \
|
||||
dp/dp_catalog_v200.o \
|
||||
dp/dp_aux.o \
|
||||
dp/dp_panel.o \
|
||||
dp/dp_link.o \
|
||||
dp/dp_ctrl.o \
|
||||
dp/dp_audio.o \
|
||||
dp/dp_debug.o \
|
||||
dp/dp_hpd.o \
|
||||
dp/dp_aux_bridge.o \
|
||||
dp/dp_bridge_hpd.o \
|
||||
dp/dp_mst_sim.o \
|
||||
dp/dp_mst_sim_helper.o \
|
||||
dp/dp_gpio_hpd.o \
|
||||
dp/dp_lphw_hpd.o \
|
||||
dp/dp_display.o \
|
||||
dp/dp_drm.o \
|
||||
dp/dp_pll.o \
|
||||
dp/dp_pll_5nm.o \
|
||||
dp/dp_pll_4nm.o
|
||||
|
||||
msm_drm-$(CONFIG_DRM_MSM_DP_MST) += dp/dp_mst_drm.o
|
||||
|
||||
msm_drm-$(CONFIG_DRM_MSM_DP_USBPD_LEGACY) += dp/dp_usbpd.o
|
||||
|
||||
msm_drm-$(CONFIG_DRM_MSM_SDE) += sde/sde_crtc.o \
|
||||
sde/sde_encoder.o \
|
||||
sde/sde_encoder_dce.o \
|
||||
sde/sde_encoder_phys_vid.o \
|
||||
sde/sde_encoder_phys_cmd.o \
|
||||
sde/sde_irq.o sde/sde_core_irq.o \
|
||||
sde/sde_core_perf.o \
|
||||
sde/sde_rm.o \
|
||||
sde/sde_kms_utils.o \
|
||||
sde/sde_kms.o \
|
||||
sde/sde_plane.o \
|
||||
sde/sde_connector.o \
|
||||
sde/sde_color_processing.o \
|
||||
sde/sde_vbif.o \
|
||||
sde_dbg.o \
|
||||
sde_dbg_evtlog.o \
|
||||
sde_io_util.o \
|
||||
sde_vm_event.o \
|
||||
sde/sde_hw_reg_dma_v1_color_proc.o \
|
||||
sde/sde_hw_color_proc_v4.o \
|
||||
sde/sde_hw_ad4.o \
|
||||
sde/sde_hw_uidle.o \
|
||||
sde_edid_parser.o \
|
||||
sde/sde_hw_catalog.o \
|
||||
sde/sde_hw_cdm.o \
|
||||
sde/sde_hw_dspp.o \
|
||||
sde/sde_hw_intf.o \
|
||||
sde/sde_hw_lm.o \
|
||||
sde/sde_hw_ctl.o \
|
||||
sde/sde_hw_util.o \
|
||||
sde/sde_hw_sspp.o \
|
||||
sde/sde_hw_wb.o \
|
||||
sde/sde_hw_pingpong.o \
|
||||
sde/sde_hw_top.o \
|
||||
sde/sde_hw_interrupts.o \
|
||||
sde/sde_hw_vbif.o \
|
||||
sde/sde_formats.o \
|
||||
sde_power_handle.o \
|
||||
sde/sde_hw_color_processing_v1_7.o \
|
||||
sde/sde_reg_dma.o \
|
||||
sde/sde_hw_reg_dma_v1.o \
|
||||
sde/sde_hw_dsc.o \
|
||||
sde/sde_hw_dsc_1_2.o \
|
||||
sde/sde_hw_vdc.o \
|
||||
sde/sde_hw_ds.o \
|
||||
sde/sde_fence.o \
|
||||
sde/sde_hw_qdss.o \
|
||||
sde_dsc_helper.o \
|
||||
sde_vdc_helper.o \
|
||||
sde/sde_hw_dnsc_blur.o \
|
||||
sde/sde_hw_rc.o
|
||||
|
||||
msm_drm-$(CONFIG_DRM_SDE_WB) += sde/sde_wb.o \
|
||||
sde/sde_encoder_phys_wb.o
|
||||
|
||||
msm_drm-$(CONFIG_DRM_SDE_RSC) += sde_rsc.o \
|
||||
sde_rsc_hw.o \
|
||||
sde_rsc_hw_v3.o
|
||||
|
||||
msm_drm-$(CONFIG_DRM_MSM_DSI) += dsi/dsi_phy.o \
|
||||
dsi/dsi_pwr.o \
|
||||
dsi/dsi_phy.o \
|
||||
dsi/dsi_phy_hw_v3_0.o \
|
||||
dsi/dsi_phy_hw_v4_0.o \
|
||||
dsi/dsi_phy_hw_v5_0.o \
|
||||
dsi/dsi_phy_timing_calc.o \
|
||||
dsi/dsi_phy_timing_v3_0.o \
|
||||
dsi/dsi_phy_timing_v4_0.o \
|
||||
dsi/dsi_pll.o \
|
||||
dsi/dsi_pll_5nm.o \
|
||||
dsi/dsi_pll_4nm.o \
|
||||
dsi/dsi_ctrl_hw_cmn.o \
|
||||
dsi/dsi_ctrl_hw_2_2.o \
|
||||
dsi/dsi_ctrl.o \
|
||||
dsi/dsi_catalog.o \
|
||||
dsi/dsi_drm.o \
|
||||
dsi/dsi_display.o \
|
||||
dsi/dsi_panel.o \
|
||||
dsi/dsi_clk_manager.o \
|
||||
dsi/dsi_display_test.o
|
||||
|
||||
msm_drm-$(CONFIG_DSI_PARSER) += dsi/dsi_parser.o
|
||||
|
||||
msm_drm-$(CONFIG_THERMAL_OF) += msm_cooling_device.o
|
||||
|
||||
msm_drm-$(CONFIG_DRM_MSM) += msm_atomic.o \
|
||||
msm_fb.o \
|
||||
msm_drv.o \
|
||||
msm_gem.o \
|
||||
msm_gem_prime.o \
|
||||
msm_gem_vma.o \
|
||||
msm_smmu.o \
|
||||
msm_prop.o
|
||||
|
||||
CDEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\"
|
||||
|
16
qcom/opensource/display-drivers/msm/Makefile
Normal file
16
qcom/opensource/display-drivers/msm/Makefile
Normal file
@ -0,0 +1,16 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
KBUILD_OPTIONS+= DISPLAY_ROOT=$(KERNEL_SRC)/$(M)/../
|
||||
|
||||
all: modules
|
||||
|
||||
modules_install:
|
||||
$(MAKE) INSTALL_MOD_STRIP=1 -C $(KERNEL_SRC) M=$(M) modules_install
|
||||
|
||||
%:
|
||||
$(MAKE) -C $(KERNEL_SRC) M=$(M) $@ $(KBUILD_OPTIONS)
|
||||
|
||||
clean:
|
||||
rm -f *.o *.ko *.mod.c *.mod.o *~ .*.cmd Module.symvers
|
||||
rm -rf .tmp_versions
|
||||
|
325
qcom/opensource/display-drivers/msm/dp/dp_altmode.c
Normal file
325
qcom/opensource/display-drivers/msm/dp/dp_altmode.c
Normal file
@ -0,0 +1,325 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/soc/qcom/altmode-glink.h>
|
||||
#include <linux/usb/dwc3-msm.h>
|
||||
#include <linux/usb/pd_vdo.h>
|
||||
|
||||
#include "dp_altmode.h"
|
||||
#include "dp_debug.h"
|
||||
#include "sde_dbg.h"
|
||||
|
||||
|
||||
#define ALTMODE_CONFIGURE_MASK (0x3f)
|
||||
#define ALTMODE_HPD_STATE_MASK (0x40)
|
||||
#define ALTMODE_HPD_IRQ_MASK (0x80)
|
||||
|
||||
struct dp_altmode_private {
|
||||
bool forced_disconnect;
|
||||
struct device *dev;
|
||||
struct dp_hpd_cb *dp_cb;
|
||||
struct dp_altmode dp_altmode;
|
||||
struct altmode_client *amclient;
|
||||
bool connected;
|
||||
u32 lanes;
|
||||
};
|
||||
|
||||
enum dp_altmode_pin_assignment {
|
||||
DPAM_HPD_OUT,
|
||||
DPAM_HPD_A,
|
||||
DPAM_HPD_B,
|
||||
DPAM_HPD_C,
|
||||
DPAM_HPD_D,
|
||||
DPAM_HPD_E,
|
||||
DPAM_HPD_F,
|
||||
};
|
||||
|
||||
static int dp_altmode_set_usb_dp_mode(struct dp_altmode_private *altmode)
|
||||
{
|
||||
int rc = 0;
|
||||
struct device_node *np;
|
||||
struct device_node *usb_node;
|
||||
struct platform_device *usb_pdev;
|
||||
int timeout = 250;
|
||||
|
||||
if (!altmode || !altmode->dev) {
|
||||
DP_ERR("invalid args\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
np = altmode->dev->of_node;
|
||||
|
||||
usb_node = of_parse_phandle(np, "usb-controller", 0);
|
||||
if (!usb_node) {
|
||||
DP_ERR("unable to get usb node\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
usb_pdev = of_find_device_by_node(usb_node);
|
||||
if (!usb_pdev) {
|
||||
of_node_put(usb_node);
|
||||
DP_ERR("unable to get usb pdev\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
while (timeout) {
|
||||
rc = dwc3_msm_set_dp_mode(&usb_pdev->dev, altmode->connected, altmode->lanes);
|
||||
if (rc != -EBUSY && rc != -EAGAIN)
|
||||
break;
|
||||
|
||||
DP_WARN("USB busy, retry\n");
|
||||
|
||||
/* wait for hw recommended delay for usb */
|
||||
msleep(20);
|
||||
timeout--;
|
||||
}
|
||||
of_node_put(usb_node);
|
||||
platform_device_put(usb_pdev);
|
||||
|
||||
if (rc)
|
||||
DP_ERR("Error releasing SS lanes: %d\n", rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void dp_altmode_send_pan_ack(struct altmode_client *amclient,
|
||||
u8 port_index)
|
||||
{
|
||||
int rc;
|
||||
struct altmode_pan_ack_msg ack;
|
||||
|
||||
ack.cmd_type = ALTMODE_PAN_ACK;
|
||||
ack.port_index = port_index;
|
||||
|
||||
rc = altmode_send_data(amclient, &ack, sizeof(ack));
|
||||
if (rc < 0) {
|
||||
DP_ERR("failed: %d\n", rc);
|
||||
return;
|
||||
}
|
||||
|
||||
DP_DEBUG("port=%d\n", port_index);
|
||||
}
|
||||
|
||||
static int dp_altmode_notify(void *priv, void *data, size_t len)
|
||||
{
|
||||
int rc = 0;
|
||||
struct dp_altmode_private *altmode =
|
||||
(struct dp_altmode_private *) priv;
|
||||
u8 port_index, dp_data, orientation;
|
||||
u8 *payload = (u8 *) data;
|
||||
u8 pin, hpd_state, hpd_irq;
|
||||
bool force_multi_func = altmode->dp_altmode.base.force_multi_func;
|
||||
|
||||
port_index = payload[0];
|
||||
orientation = payload[1];
|
||||
dp_data = payload[8];
|
||||
|
||||
pin = dp_data & ALTMODE_CONFIGURE_MASK;
|
||||
hpd_state = (dp_data & ALTMODE_HPD_STATE_MASK) >> 6;
|
||||
hpd_irq = (dp_data & ALTMODE_HPD_IRQ_MASK) >> 7;
|
||||
|
||||
altmode->dp_altmode.base.hpd_high = !!hpd_state;
|
||||
altmode->dp_altmode.base.hpd_irq = !!hpd_irq;
|
||||
altmode->dp_altmode.base.multi_func = force_multi_func ? true :
|
||||
!(pin == DPAM_HPD_C || pin == DPAM_HPD_E || pin == DPAM_HPD_OUT);
|
||||
|
||||
DP_DEBUG("payload=0x%x\n", dp_data);
|
||||
DP_DEBUG("port_index=%d, orientation=%d, pin=%d, hpd_state=%d\n",
|
||||
port_index, orientation, pin, hpd_state);
|
||||
DP_DEBUG("multi_func=%d, hpd_high=%d, hpd_irq=%d\n",
|
||||
altmode->dp_altmode.base.multi_func,
|
||||
altmode->dp_altmode.base.hpd_high,
|
||||
altmode->dp_altmode.base.hpd_irq);
|
||||
DP_DEBUG("connected=%d\n", altmode->connected);
|
||||
SDE_EVT32_EXTERNAL(dp_data, port_index, orientation, pin, hpd_state,
|
||||
altmode->dp_altmode.base.multi_func,
|
||||
altmode->dp_altmode.base.hpd_high,
|
||||
altmode->dp_altmode.base.hpd_irq, altmode->connected);
|
||||
|
||||
if (!pin) {
|
||||
/* Cable detach */
|
||||
if (altmode->connected) {
|
||||
altmode->connected = false;
|
||||
altmode->dp_altmode.base.alt_mode_cfg_done = false;
|
||||
altmode->dp_altmode.base.orientation = ORIENTATION_NONE;
|
||||
if (altmode->dp_cb && altmode->dp_cb->disconnect)
|
||||
altmode->dp_cb->disconnect(altmode->dev);
|
||||
|
||||
rc = dp_altmode_set_usb_dp_mode(altmode);
|
||||
if (rc)
|
||||
DP_ERR("failed to clear usb dp mode, rc: %d\n", rc);
|
||||
}
|
||||
goto ack;
|
||||
}
|
||||
|
||||
/* Configure */
|
||||
if (!altmode->connected) {
|
||||
altmode->connected = true;
|
||||
altmode->dp_altmode.base.alt_mode_cfg_done = true;
|
||||
altmode->forced_disconnect = false;
|
||||
altmode->lanes = 4;
|
||||
|
||||
if (altmode->dp_altmode.base.multi_func)
|
||||
altmode->lanes = 2;
|
||||
|
||||
DP_DEBUG("Connected=%d, lanes=%d\n",altmode->connected,altmode->lanes);
|
||||
|
||||
switch (orientation) {
|
||||
case 0:
|
||||
orientation = ORIENTATION_CC1;
|
||||
break;
|
||||
case 1:
|
||||
orientation = ORIENTATION_CC2;
|
||||
break;
|
||||
case 2:
|
||||
orientation = ORIENTATION_NONE;
|
||||
break;
|
||||
default:
|
||||
orientation = ORIENTATION_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
altmode->dp_altmode.base.orientation = orientation;
|
||||
|
||||
rc = dp_altmode_set_usb_dp_mode(altmode);
|
||||
if (rc)
|
||||
goto ack;
|
||||
|
||||
if (altmode->dp_cb && altmode->dp_cb->configure)
|
||||
altmode->dp_cb->configure(altmode->dev);
|
||||
goto ack;
|
||||
}
|
||||
|
||||
/* Attention */
|
||||
if (altmode->forced_disconnect)
|
||||
goto ack;
|
||||
|
||||
if (altmode->dp_cb && altmode->dp_cb->attention)
|
||||
altmode->dp_cb->attention(altmode->dev);
|
||||
ack:
|
||||
dp_altmode_send_pan_ack(altmode->amclient, port_index);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void dp_altmode_register(void *priv)
|
||||
{
|
||||
struct dp_altmode_private *altmode = priv;
|
||||
struct altmode_client_data cd = {
|
||||
.callback = &dp_altmode_notify,
|
||||
};
|
||||
|
||||
cd.name = "displayport";
|
||||
cd.svid = USB_SID_DISPLAYPORT;
|
||||
cd.priv = altmode;
|
||||
|
||||
altmode->amclient = altmode_register_client(altmode->dev, &cd);
|
||||
if (IS_ERR_OR_NULL(altmode->amclient))
|
||||
DP_ERR("failed to register as client: %ld\n",
|
||||
PTR_ERR(altmode->amclient));
|
||||
else
|
||||
DP_DEBUG("success\n");
|
||||
}
|
||||
|
||||
static int dp_altmode_simulate_connect(struct dp_hpd *dp_hpd, bool hpd)
|
||||
{
|
||||
struct dp_altmode *dp_altmode;
|
||||
struct dp_altmode_private *altmode;
|
||||
|
||||
dp_altmode = container_of(dp_hpd, struct dp_altmode, base);
|
||||
altmode = container_of(dp_altmode, struct dp_altmode_private,
|
||||
dp_altmode);
|
||||
|
||||
dp_altmode->base.hpd_high = hpd;
|
||||
altmode->forced_disconnect = !hpd;
|
||||
altmode->dp_altmode.base.alt_mode_cfg_done = hpd;
|
||||
|
||||
if (hpd)
|
||||
altmode->dp_cb->configure(altmode->dev);
|
||||
else
|
||||
altmode->dp_cb->disconnect(altmode->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dp_altmode_simulate_attention(struct dp_hpd *dp_hpd, int vdo)
|
||||
{
|
||||
struct dp_altmode *dp_altmode;
|
||||
struct dp_altmode_private *altmode;
|
||||
struct dp_altmode *status;
|
||||
|
||||
dp_altmode = container_of(dp_hpd, struct dp_altmode, base);
|
||||
altmode = container_of(dp_altmode, struct dp_altmode_private,
|
||||
dp_altmode);
|
||||
|
||||
status = &altmode->dp_altmode;
|
||||
|
||||
status->base.hpd_high = (vdo & BIT(7)) ? true : false;
|
||||
status->base.hpd_irq = (vdo & BIT(8)) ? true : false;
|
||||
|
||||
if (altmode->dp_cb && altmode->dp_cb->attention)
|
||||
altmode->dp_cb->attention(altmode->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct dp_hpd *dp_altmode_get(struct device *dev, struct dp_hpd_cb *cb)
|
||||
{
|
||||
int rc = 0;
|
||||
struct dp_altmode_private *altmode;
|
||||
struct dp_altmode *dp_altmode;
|
||||
|
||||
if (!cb) {
|
||||
DP_ERR("invalid cb data\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
altmode = kzalloc(sizeof(*altmode), GFP_KERNEL);
|
||||
if (!altmode)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
altmode->dev = dev;
|
||||
altmode->dp_cb = cb;
|
||||
|
||||
dp_altmode = &altmode->dp_altmode;
|
||||
dp_altmode->base.register_hpd = NULL;
|
||||
dp_altmode->base.simulate_connect = dp_altmode_simulate_connect;
|
||||
dp_altmode->base.simulate_attention = dp_altmode_simulate_attention;
|
||||
|
||||
rc = altmode_register_notifier(dev, dp_altmode_register, altmode);
|
||||
if (rc < 0) {
|
||||
DP_ERR("altmode probe notifier registration failed: %d\n", rc);
|
||||
goto error;
|
||||
}
|
||||
|
||||
DP_DEBUG("success\n");
|
||||
|
||||
return &dp_altmode->base;
|
||||
error:
|
||||
kfree(altmode);
|
||||
return ERR_PTR(rc);
|
||||
}
|
||||
|
||||
void dp_altmode_put(struct dp_hpd *dp_hpd)
|
||||
{
|
||||
struct dp_altmode *dp_altmode;
|
||||
struct dp_altmode_private *altmode;
|
||||
|
||||
dp_altmode = container_of(dp_hpd, struct dp_altmode, base);
|
||||
if (!dp_altmode)
|
||||
return;
|
||||
|
||||
altmode = container_of(dp_altmode, struct dp_altmode_private,
|
||||
dp_altmode);
|
||||
|
||||
altmode_deregister_client(altmode->amclient);
|
||||
altmode_deregister_notifier(altmode->dev, altmode);
|
||||
|
||||
kfree(altmode);
|
||||
}
|
22
qcom/opensource/display-drivers/msm/dp/dp_altmode.h
Normal file
22
qcom/opensource/display-drivers/msm/dp/dp_altmode.h
Normal file
@ -0,0 +1,22 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _DP_ALTMODE_H_
|
||||
#define _DP_ALTMODE_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include "dp_hpd.h"
|
||||
|
||||
struct device;
|
||||
|
||||
struct dp_altmode {
|
||||
struct dp_hpd base;
|
||||
};
|
||||
|
||||
struct dp_hpd *dp_altmode_get(struct device *dev, struct dp_hpd_cb *cb);
|
||||
|
||||
void dp_altmode_put(struct dp_hpd *pd);
|
||||
#endif /* _DP_ALTMODE_H_ */
|
||||
|
915
qcom/opensource/display-drivers/msm/dp/dp_audio.c
Normal file
915
qcom/opensource/display-drivers/msm/dp/dp_audio.c
Normal file
@ -0,0 +1,915 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/soc/qcom/msm_ext_display.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0))
|
||||
#include <drm/display/drm_dp_helper.h>
|
||||
#else
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#endif
|
||||
|
||||
#include "dp_catalog.h"
|
||||
#include "dp_audio.h"
|
||||
#include "dp_panel.h"
|
||||
#include "dp_debug.h"
|
||||
|
||||
struct dp_audio_private {
|
||||
struct platform_device *ext_pdev;
|
||||
struct platform_device *pdev;
|
||||
struct dp_catalog_audio *catalog;
|
||||
struct msm_ext_disp_init_data ext_audio_data;
|
||||
struct dp_panel *panel;
|
||||
|
||||
bool ack_enabled;
|
||||
atomic_t session_on;
|
||||
bool engine_on;
|
||||
|
||||
u32 channels;
|
||||
|
||||
struct completion hpd_comp;
|
||||
struct workqueue_struct *notify_workqueue;
|
||||
struct delayed_work notify_delayed_work;
|
||||
struct mutex ops_lock;
|
||||
|
||||
struct dp_audio dp_audio;
|
||||
|
||||
atomic_t acked;
|
||||
};
|
||||
|
||||
static u32 dp_audio_get_header(struct dp_catalog_audio *catalog,
|
||||
enum dp_catalog_audio_sdp_type sdp,
|
||||
enum dp_catalog_audio_header_type header)
|
||||
{
|
||||
catalog->sdp_type = sdp;
|
||||
catalog->sdp_header = header;
|
||||
catalog->get_header(catalog);
|
||||
|
||||
return catalog->data;
|
||||
}
|
||||
|
||||
static void dp_audio_set_header(struct dp_catalog_audio *catalog,
|
||||
u32 data,
|
||||
enum dp_catalog_audio_sdp_type sdp,
|
||||
enum dp_catalog_audio_header_type header)
|
||||
{
|
||||
catalog->sdp_type = sdp;
|
||||
catalog->sdp_header = header;
|
||||
catalog->data = data;
|
||||
catalog->set_header(catalog);
|
||||
}
|
||||
|
||||
static void dp_audio_stream_sdp(struct dp_audio_private *audio)
|
||||
{
|
||||
struct dp_catalog_audio *catalog = audio->catalog;
|
||||
u32 value, new_value;
|
||||
u8 parity_byte;
|
||||
|
||||
/* Config header and parity byte 1 */
|
||||
value = dp_audio_get_header(catalog,
|
||||
DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_1);
|
||||
value &= 0x0000ffff;
|
||||
|
||||
new_value = 0x02;
|
||||
parity_byte = dp_header_get_parity(new_value);
|
||||
value |= ((new_value << HEADER_BYTE_1_BIT)
|
||||
| (parity_byte << PARITY_BYTE_1_BIT));
|
||||
DP_DEBUG("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n",
|
||||
value, parity_byte);
|
||||
dp_audio_set_header(catalog, value,
|
||||
DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_1);
|
||||
|
||||
/* Config header and parity byte 2 */
|
||||
value = dp_audio_get_header(catalog,
|
||||
DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_2);
|
||||
value &= 0xffff0000;
|
||||
new_value = 0x0;
|
||||
parity_byte = dp_header_get_parity(new_value);
|
||||
value |= ((new_value << HEADER_BYTE_2_BIT)
|
||||
| (parity_byte << PARITY_BYTE_2_BIT));
|
||||
DP_DEBUG("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n",
|
||||
value, parity_byte);
|
||||
|
||||
dp_audio_set_header(catalog, value,
|
||||
DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_2);
|
||||
|
||||
/* Config header and parity byte 3 */
|
||||
value = dp_audio_get_header(catalog,
|
||||
DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_3);
|
||||
value &= 0x0000ffff;
|
||||
|
||||
new_value = audio->channels - 1;
|
||||
parity_byte = dp_header_get_parity(new_value);
|
||||
value |= ((new_value << HEADER_BYTE_3_BIT)
|
||||
| (parity_byte << PARITY_BYTE_3_BIT));
|
||||
DP_DEBUG("Header Byte 3: value = 0x%x, parity_byte = 0x%x\n",
|
||||
value, parity_byte);
|
||||
|
||||
dp_audio_set_header(catalog, value,
|
||||
DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_3);
|
||||
}
|
||||
|
||||
static void dp_audio_timestamp_sdp(struct dp_audio_private *audio)
|
||||
{
|
||||
struct dp_catalog_audio *catalog = audio->catalog;
|
||||
u32 value, new_value;
|
||||
u8 parity_byte;
|
||||
|
||||
/* Config header and parity byte 1 */
|
||||
value = dp_audio_get_header(catalog,
|
||||
DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_1);
|
||||
value &= 0x0000ffff;
|
||||
|
||||
new_value = 0x1;
|
||||
parity_byte = dp_header_get_parity(new_value);
|
||||
value |= ((new_value << HEADER_BYTE_1_BIT)
|
||||
| (parity_byte << PARITY_BYTE_1_BIT));
|
||||
DP_DEBUG("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n",
|
||||
value, parity_byte);
|
||||
dp_audio_set_header(catalog, value,
|
||||
DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_1);
|
||||
|
||||
/* Config header and parity byte 2 */
|
||||
value = dp_audio_get_header(catalog,
|
||||
DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_2);
|
||||
value &= 0xffff0000;
|
||||
|
||||
new_value = 0x17;
|
||||
parity_byte = dp_header_get_parity(new_value);
|
||||
value |= ((new_value << HEADER_BYTE_2_BIT)
|
||||
| (parity_byte << PARITY_BYTE_2_BIT));
|
||||
DP_DEBUG("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n",
|
||||
value, parity_byte);
|
||||
dp_audio_set_header(catalog, value,
|
||||
DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_2);
|
||||
|
||||
/* Config header and parity byte 3 */
|
||||
value = dp_audio_get_header(catalog,
|
||||
DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_3);
|
||||
value &= 0x0000ffff;
|
||||
|
||||
new_value = (0x0 | (0x11 << 2));
|
||||
parity_byte = dp_header_get_parity(new_value);
|
||||
value |= ((new_value << HEADER_BYTE_3_BIT)
|
||||
| (parity_byte << PARITY_BYTE_3_BIT));
|
||||
DP_DEBUG("Header Byte 3: value = 0x%x, parity_byte = 0x%x\n",
|
||||
value, parity_byte);
|
||||
dp_audio_set_header(catalog, value,
|
||||
DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_3);
|
||||
}
|
||||
|
||||
static void dp_audio_infoframe_sdp(struct dp_audio_private *audio)
|
||||
{
|
||||
struct dp_catalog_audio *catalog = audio->catalog;
|
||||
u32 value, new_value;
|
||||
u8 parity_byte;
|
||||
|
||||
/* Config header and parity byte 1 */
|
||||
value = dp_audio_get_header(catalog,
|
||||
DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_1);
|
||||
value &= 0x0000ffff;
|
||||
|
||||
new_value = 0x84;
|
||||
parity_byte = dp_header_get_parity(new_value);
|
||||
value |= ((new_value << HEADER_BYTE_1_BIT)
|
||||
| (parity_byte << PARITY_BYTE_1_BIT));
|
||||
DP_DEBUG("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n",
|
||||
value, parity_byte);
|
||||
dp_audio_set_header(catalog, value,
|
||||
DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_1);
|
||||
|
||||
/* Config header and parity byte 2 */
|
||||
value = dp_audio_get_header(catalog,
|
||||
DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_2);
|
||||
value &= 0xffff0000;
|
||||
|
||||
new_value = 0x1b;
|
||||
parity_byte = dp_header_get_parity(new_value);
|
||||
value |= ((new_value << HEADER_BYTE_2_BIT)
|
||||
| (parity_byte << PARITY_BYTE_2_BIT));
|
||||
DP_DEBUG("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n",
|
||||
value, parity_byte);
|
||||
dp_audio_set_header(catalog, value,
|
||||
DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_2);
|
||||
|
||||
/* Config header and parity byte 3 */
|
||||
value = dp_audio_get_header(catalog,
|
||||
DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_3);
|
||||
value &= 0x0000ffff;
|
||||
|
||||
new_value = (0x0 | (0x11 << 2));
|
||||
parity_byte = dp_header_get_parity(new_value);
|
||||
value |= ((new_value << HEADER_BYTE_3_BIT)
|
||||
| (parity_byte << PARITY_BYTE_3_BIT));
|
||||
DP_DEBUG("Header Byte 3: value = 0x%x, parity_byte = 0x%x\n",
|
||||
new_value, parity_byte);
|
||||
dp_audio_set_header(catalog, value,
|
||||
DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_3);
|
||||
}
|
||||
|
||||
static void dp_audio_copy_management_sdp(struct dp_audio_private *audio)
|
||||
{
|
||||
struct dp_catalog_audio *catalog = audio->catalog;
|
||||
u32 value, new_value;
|
||||
u8 parity_byte;
|
||||
|
||||
/* Config header and parity byte 1 */
|
||||
value = dp_audio_get_header(catalog,
|
||||
DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_1);
|
||||
value &= 0x0000ffff;
|
||||
|
||||
new_value = 0x05;
|
||||
parity_byte = dp_header_get_parity(new_value);
|
||||
value |= ((new_value << HEADER_BYTE_1_BIT)
|
||||
| (parity_byte << PARITY_BYTE_1_BIT));
|
||||
DP_DEBUG("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n",
|
||||
value, parity_byte);
|
||||
dp_audio_set_header(catalog, value,
|
||||
DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_1);
|
||||
|
||||
/* Config header and parity byte 2 */
|
||||
value = dp_audio_get_header(catalog,
|
||||
DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_2);
|
||||
value &= 0xffff0000;
|
||||
|
||||
new_value = 0x0F;
|
||||
parity_byte = dp_header_get_parity(new_value);
|
||||
value |= ((new_value << HEADER_BYTE_2_BIT)
|
||||
| (parity_byte << PARITY_BYTE_2_BIT));
|
||||
DP_DEBUG("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n",
|
||||
value, parity_byte);
|
||||
dp_audio_set_header(catalog, value,
|
||||
DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_2);
|
||||
|
||||
/* Config header and parity byte 3 */
|
||||
value = dp_audio_get_header(catalog,
|
||||
DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_3);
|
||||
value &= 0x0000ffff;
|
||||
|
||||
new_value = 0x0;
|
||||
parity_byte = dp_header_get_parity(new_value);
|
||||
value |= ((new_value << HEADER_BYTE_3_BIT)
|
||||
| (parity_byte << PARITY_BYTE_3_BIT));
|
||||
DP_DEBUG("Header Byte 3: value = 0x%x, parity_byte = 0x%x\n",
|
||||
value, parity_byte);
|
||||
dp_audio_set_header(catalog, value,
|
||||
DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_3);
|
||||
}
|
||||
|
||||
static void dp_audio_isrc_sdp(struct dp_audio_private *audio)
|
||||
{
|
||||
struct dp_catalog_audio *catalog = audio->catalog;
|
||||
u32 value, new_value;
|
||||
u8 parity_byte;
|
||||
|
||||
/* Config header and parity byte 1 */
|
||||
value = dp_audio_get_header(catalog,
|
||||
DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_1);
|
||||
value &= 0x0000ffff;
|
||||
|
||||
new_value = 0x06;
|
||||
parity_byte = dp_header_get_parity(new_value);
|
||||
value |= ((new_value << HEADER_BYTE_1_BIT)
|
||||
| (parity_byte << PARITY_BYTE_1_BIT));
|
||||
DP_DEBUG("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n",
|
||||
value, parity_byte);
|
||||
dp_audio_set_header(catalog, value,
|
||||
DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_1);
|
||||
|
||||
/* Config header and parity byte 2 */
|
||||
value = dp_audio_get_header(catalog,
|
||||
DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_2);
|
||||
value &= 0xffff0000;
|
||||
|
||||
new_value = 0x0F;
|
||||
parity_byte = dp_header_get_parity(new_value);
|
||||
value |= ((new_value << HEADER_BYTE_2_BIT)
|
||||
| (parity_byte << PARITY_BYTE_2_BIT));
|
||||
DP_DEBUG("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n",
|
||||
value, parity_byte);
|
||||
dp_audio_set_header(catalog, value,
|
||||
DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_2);
|
||||
}
|
||||
|
||||
static void dp_audio_setup_sdp(struct dp_audio_private *audio)
|
||||
{
|
||||
if (!atomic_read(&audio->session_on)) {
|
||||
DP_WARN("session inactive\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* always program stream 0 first before actual stream cfg */
|
||||
audio->catalog->stream_id = DP_STREAM_0;
|
||||
audio->catalog->config_sdp(audio->catalog);
|
||||
|
||||
if (audio->panel->stream_id == DP_STREAM_1) {
|
||||
audio->catalog->stream_id = DP_STREAM_1;
|
||||
audio->catalog->config_sdp(audio->catalog);
|
||||
}
|
||||
|
||||
dp_audio_stream_sdp(audio);
|
||||
dp_audio_timestamp_sdp(audio);
|
||||
dp_audio_infoframe_sdp(audio);
|
||||
dp_audio_copy_management_sdp(audio);
|
||||
dp_audio_isrc_sdp(audio);
|
||||
}
|
||||
|
||||
static void dp_audio_setup_acr(struct dp_audio_private *audio)
|
||||
{
|
||||
u32 select = 0;
|
||||
struct dp_catalog_audio *catalog = audio->catalog;
|
||||
|
||||
if (!atomic_read(&audio->session_on)) {
|
||||
DP_WARN("session inactive\n");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (audio->dp_audio.bw_code) {
|
||||
case DP_LINK_BW_1_62:
|
||||
select = 0;
|
||||
break;
|
||||
case DP_LINK_BW_2_7:
|
||||
select = 1;
|
||||
break;
|
||||
case DP_LINK_BW_5_4:
|
||||
select = 2;
|
||||
break;
|
||||
case DP_LINK_BW_8_1:
|
||||
select = 3;
|
||||
break;
|
||||
default:
|
||||
DP_DEBUG("Unknown link rate\n");
|
||||
select = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
catalog->data = select;
|
||||
catalog->config_acr(catalog);
|
||||
}
|
||||
|
||||
static void dp_audio_enable(struct dp_audio_private *audio, bool enable)
|
||||
{
|
||||
struct dp_catalog_audio *catalog = audio->catalog;
|
||||
|
||||
audio->engine_on = enable;
|
||||
if (!atomic_read(&audio->session_on)) {
|
||||
DP_WARN("session inactive. enable=%d\n", enable);
|
||||
return;
|
||||
}
|
||||
catalog->data = enable;
|
||||
|
||||
if (audio->panel->get_panel_on(audio->panel))
|
||||
catalog->enable(catalog);
|
||||
|
||||
}
|
||||
|
||||
static struct dp_audio_private *dp_audio_get_data(struct platform_device *pdev)
|
||||
{
|
||||
struct msm_ext_disp_data *ext_data;
|
||||
struct dp_audio *dp_audio;
|
||||
|
||||
if (!pdev) {
|
||||
DP_ERR("invalid input\n");
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
ext_data = platform_get_drvdata(pdev);
|
||||
if (!ext_data) {
|
||||
DP_ERR("invalid ext disp data\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
dp_audio = ext_data->intf_data;
|
||||
if (!dp_audio) {
|
||||
DP_ERR("invalid intf data\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
return container_of(dp_audio, struct dp_audio_private, dp_audio);
|
||||
}
|
||||
|
||||
static int dp_audio_info_setup(struct platform_device *pdev,
|
||||
struct msm_ext_disp_audio_setup_params *params)
|
||||
{
|
||||
int rc = 0;
|
||||
struct dp_audio_private *audio;
|
||||
|
||||
audio = dp_audio_get_data(pdev);
|
||||
if (IS_ERR(audio)) {
|
||||
rc = PTR_ERR(audio);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (audio->dp_audio.tui_active) {
|
||||
DP_DEBUG("TUI session active\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
mutex_lock(&audio->ops_lock);
|
||||
|
||||
audio->channels = params->num_of_channels;
|
||||
|
||||
if (audio->panel->stream_id >= DP_STREAM_MAX) {
|
||||
DP_ERR("invalid stream id: %d\n",
|
||||
audio->panel->stream_id);
|
||||
rc = -EINVAL;
|
||||
mutex_unlock(&audio->ops_lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
dp_audio_setup_sdp(audio);
|
||||
dp_audio_setup_acr(audio);
|
||||
dp_audio_enable(audio, true);
|
||||
|
||||
mutex_unlock(&audio->ops_lock);
|
||||
|
||||
DP_DEBUG("audio stream configured\n");
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int dp_audio_get_edid_blk(struct platform_device *pdev,
|
||||
struct msm_ext_disp_audio_edid_blk *blk)
|
||||
{
|
||||
int rc = 0;
|
||||
struct dp_audio_private *audio;
|
||||
struct sde_edid_ctrl *edid;
|
||||
|
||||
if (!blk) {
|
||||
DP_ERR("invalid input\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
audio = dp_audio_get_data(pdev);
|
||||
if (IS_ERR(audio)) {
|
||||
rc = PTR_ERR(audio);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!audio->panel || !audio->panel->edid_ctrl) {
|
||||
DP_ERR("invalid panel data\n");
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
edid = audio->panel->edid_ctrl;
|
||||
|
||||
blk->audio_data_blk = edid->audio_data_block;
|
||||
blk->audio_data_blk_size = edid->adb_size;
|
||||
|
||||
blk->spk_alloc_data_blk = edid->spkr_alloc_data_block;
|
||||
blk->spk_alloc_data_blk_size = edid->sadb_size;
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int dp_audio_get_cable_status(struct platform_device *pdev, u32 vote)
|
||||
{
|
||||
int rc = 0;
|
||||
struct dp_audio_private *audio;
|
||||
|
||||
audio = dp_audio_get_data(pdev);
|
||||
if (IS_ERR(audio)) {
|
||||
rc = PTR_ERR(audio);
|
||||
goto end;
|
||||
}
|
||||
|
||||
return atomic_read(&audio->session_on);
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int dp_audio_get_intf_id(struct platform_device *pdev)
|
||||
{
|
||||
int rc = 0;
|
||||
struct dp_audio_private *audio;
|
||||
|
||||
audio = dp_audio_get_data(pdev);
|
||||
if (IS_ERR(audio)) {
|
||||
rc = PTR_ERR(audio);
|
||||
goto end;
|
||||
}
|
||||
|
||||
return EXT_DISPLAY_TYPE_DP;
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void dp_audio_teardown_done(struct platform_device *pdev)
|
||||
{
|
||||
struct dp_audio_private *audio;
|
||||
|
||||
audio = dp_audio_get_data(pdev);
|
||||
if (IS_ERR(audio))
|
||||
return;
|
||||
|
||||
if (audio->dp_audio.tui_active) {
|
||||
DP_DEBUG("TUI session active\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (audio->panel->stream_id >= DP_STREAM_MAX) {
|
||||
DP_WARN("invalid stream id: %d\n",
|
||||
audio->panel->stream_id);
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_lock(&audio->ops_lock);
|
||||
dp_audio_enable(audio, false);
|
||||
mutex_unlock(&audio->ops_lock);
|
||||
|
||||
atomic_set(&audio->acked, 1);
|
||||
complete_all(&audio->hpd_comp);
|
||||
|
||||
DP_DEBUG("audio engine disabled\n");
|
||||
}
|
||||
|
||||
static int dp_audio_ack_done(struct platform_device *pdev, u32 ack)
|
||||
{
|
||||
int rc = 0, ack_hpd;
|
||||
struct dp_audio_private *audio;
|
||||
|
||||
audio = dp_audio_get_data(pdev);
|
||||
if (IS_ERR(audio)) {
|
||||
rc = PTR_ERR(audio);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (ack & AUDIO_ACK_SET_ENABLE) {
|
||||
audio->ack_enabled = ack & AUDIO_ACK_ENABLE ?
|
||||
true : false;
|
||||
|
||||
DP_DEBUG("audio ack feature %s\n",
|
||||
audio->ack_enabled ? "enabled" : "disabled");
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!audio->ack_enabled)
|
||||
goto end;
|
||||
|
||||
ack_hpd = ack & AUDIO_ACK_CONNECT;
|
||||
|
||||
DP_DEBUG("acknowledging audio (%d)\n", ack_hpd);
|
||||
|
||||
if (!audio->engine_on) {
|
||||
atomic_set(&audio->acked, 1);
|
||||
complete_all(&audio->hpd_comp);
|
||||
}
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int dp_audio_codec_ready(struct platform_device *pdev)
|
||||
{
|
||||
int rc = 0;
|
||||
struct dp_audio_private *audio;
|
||||
|
||||
audio = dp_audio_get_data(pdev);
|
||||
if (IS_ERR(audio)) {
|
||||
DP_ERR("invalid input\n");
|
||||
rc = PTR_ERR(audio);
|
||||
goto end;
|
||||
}
|
||||
|
||||
queue_delayed_work(audio->notify_workqueue,
|
||||
&audio->notify_delayed_work, HZ/4);
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int dp_audio_register_ext_disp(struct dp_audio_private *audio)
|
||||
{
|
||||
int rc = 0;
|
||||
struct device_node *pd = NULL;
|
||||
const char *phandle = "qcom,ext-disp";
|
||||
struct msm_ext_disp_init_data *ext;
|
||||
struct msm_ext_disp_audio_codec_ops *ops;
|
||||
|
||||
ext = &audio->ext_audio_data;
|
||||
ops = &ext->codec_ops;
|
||||
|
||||
ext->codec.type = EXT_DISPLAY_TYPE_DP;
|
||||
ext->codec.ctrl_id = 0;
|
||||
ext->codec.stream_id = audio->panel->stream_id;
|
||||
ext->pdev = audio->pdev;
|
||||
ext->intf_data = &audio->dp_audio;
|
||||
|
||||
ops->audio_info_setup = dp_audio_info_setup;
|
||||
ops->get_audio_edid_blk = dp_audio_get_edid_blk;
|
||||
ops->cable_status = dp_audio_get_cable_status;
|
||||
ops->get_intf_id = dp_audio_get_intf_id;
|
||||
ops->teardown_done = dp_audio_teardown_done;
|
||||
ops->acknowledge = dp_audio_ack_done;
|
||||
ops->ready = dp_audio_codec_ready;
|
||||
|
||||
if (!audio->pdev->dev.of_node) {
|
||||
DP_ERR("cannot find audio dev.of_node\n");
|
||||
rc = -ENODEV;
|
||||
goto end;
|
||||
}
|
||||
|
||||
pd = of_parse_phandle(audio->pdev->dev.of_node, phandle, 0);
|
||||
if (!pd) {
|
||||
DP_ERR("cannot parse %s handle\n", phandle);
|
||||
rc = -ENODEV;
|
||||
goto end;
|
||||
}
|
||||
|
||||
audio->ext_pdev = of_find_device_by_node(pd);
|
||||
if (!audio->ext_pdev) {
|
||||
DP_ERR("cannot find %s pdev\n", phandle);
|
||||
rc = -ENODEV;
|
||||
goto end;
|
||||
}
|
||||
#if IS_ENABLED(CONFIG_MSM_EXT_DISPLAY)
|
||||
rc = msm_ext_disp_register_intf(audio->ext_pdev, ext);
|
||||
if (rc)
|
||||
DP_ERR("failed to register disp\n");
|
||||
#endif
|
||||
end:
|
||||
if (pd)
|
||||
of_node_put(pd);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int dp_audio_deregister_ext_disp(struct dp_audio_private *audio)
|
||||
{
|
||||
int rc = 0;
|
||||
struct device_node *pd = NULL;
|
||||
const char *phandle = "qcom,ext-disp";
|
||||
struct msm_ext_disp_init_data *ext;
|
||||
|
||||
ext = &audio->ext_audio_data;
|
||||
|
||||
if (!audio->pdev->dev.of_node) {
|
||||
DP_ERR("cannot find audio dev.of_node\n");
|
||||
rc = -ENODEV;
|
||||
goto end;
|
||||
}
|
||||
|
||||
pd = of_parse_phandle(audio->pdev->dev.of_node, phandle, 0);
|
||||
if (!pd) {
|
||||
DP_ERR("cannot parse %s handle\n", phandle);
|
||||
rc = -ENODEV;
|
||||
goto end;
|
||||
}
|
||||
|
||||
audio->ext_pdev = of_find_device_by_node(pd);
|
||||
if (!audio->ext_pdev) {
|
||||
DP_ERR("cannot find %s pdev\n", phandle);
|
||||
rc = -ENODEV;
|
||||
goto end;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_MSM_EXT_DISPLAY)
|
||||
rc = msm_ext_disp_deregister_intf(audio->ext_pdev, ext);
|
||||
if (rc)
|
||||
DP_ERR("failed to deregister disp\n");
|
||||
#endif
|
||||
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int dp_audio_notify(struct dp_audio_private *audio, u32 state)
|
||||
{
|
||||
int rc = 0;
|
||||
struct msm_ext_disp_init_data *ext = &audio->ext_audio_data;
|
||||
|
||||
atomic_set(&audio->acked, 0);
|
||||
|
||||
if (!ext->intf_ops.audio_notify) {
|
||||
DP_ERR("audio notify not defined\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
reinit_completion(&audio->hpd_comp);
|
||||
rc = ext->intf_ops.audio_notify(audio->ext_pdev,
|
||||
&ext->codec, state);
|
||||
if (rc)
|
||||
goto end;
|
||||
|
||||
if (atomic_read(&audio->acked))
|
||||
goto end;
|
||||
|
||||
if (state == EXT_DISPLAY_CABLE_DISCONNECT && !audio->engine_on)
|
||||
goto end;
|
||||
|
||||
if (state == EXT_DISPLAY_CABLE_CONNECT)
|
||||
goto end;
|
||||
|
||||
rc = wait_for_completion_timeout(&audio->hpd_comp, HZ * 4);
|
||||
if (!rc) {
|
||||
DP_ERR("timeout. state=%d err=%d\n", state, rc);
|
||||
rc = -ETIMEDOUT;
|
||||
goto end;
|
||||
}
|
||||
|
||||
DP_DEBUG("success\n");
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int dp_audio_config(struct dp_audio_private *audio, u32 state)
|
||||
{
|
||||
int rc = 0;
|
||||
struct msm_ext_disp_init_data *ext = &audio->ext_audio_data;
|
||||
|
||||
if (!ext || !ext->intf_ops.audio_config) {
|
||||
DP_ERR("audio_config not defined\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
* DP Audio sets default STREAM_0 only, other streams are
|
||||
* set by audio driver based on the hardware/software support.
|
||||
*/
|
||||
if (audio->panel->stream_id == DP_STREAM_0) {
|
||||
rc = ext->intf_ops.audio_config(audio->ext_pdev,
|
||||
&ext->codec, state);
|
||||
if (rc)
|
||||
DP_ERR("failed to config audio, err=%d\n",
|
||||
rc);
|
||||
}
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int dp_audio_on(struct dp_audio *dp_audio)
|
||||
{
|
||||
int rc = 0;
|
||||
struct dp_audio_private *audio;
|
||||
struct msm_ext_disp_init_data *ext;
|
||||
|
||||
if (!dp_audio) {
|
||||
DP_ERR("invalid input\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
audio = container_of(dp_audio, struct dp_audio_private, dp_audio);
|
||||
if (IS_ERR(audio)) {
|
||||
DP_ERR("invalid input\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dp_audio_register_ext_disp(audio);
|
||||
|
||||
ext = &audio->ext_audio_data;
|
||||
|
||||
atomic_set(&audio->session_on, 1);
|
||||
|
||||
rc = dp_audio_config(audio, EXT_DISPLAY_CABLE_CONNECT);
|
||||
if (rc)
|
||||
goto end;
|
||||
|
||||
rc = dp_audio_notify(audio, EXT_DISPLAY_CABLE_CONNECT);
|
||||
if (rc)
|
||||
goto end;
|
||||
|
||||
DP_DEBUG("success\n");
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int dp_audio_off(struct dp_audio *dp_audio, bool skip_wait)
|
||||
{
|
||||
int rc = 0;
|
||||
struct dp_audio_private *audio;
|
||||
struct msm_ext_disp_init_data *ext;
|
||||
bool work_pending = false;
|
||||
|
||||
if (!dp_audio) {
|
||||
DP_ERR("invalid input\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
audio = container_of(dp_audio, struct dp_audio_private, dp_audio);
|
||||
|
||||
if (!atomic_read(&audio->session_on)) {
|
||||
DP_DEBUG("audio already off\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
ext = &audio->ext_audio_data;
|
||||
|
||||
work_pending = cancel_delayed_work_sync(&audio->notify_delayed_work);
|
||||
if (work_pending)
|
||||
DP_DEBUG("pending notification work completed\n");
|
||||
|
||||
if (!skip_wait) {
|
||||
rc = dp_audio_notify(audio, EXT_DISPLAY_CABLE_DISCONNECT);
|
||||
if (rc)
|
||||
goto end;
|
||||
}
|
||||
|
||||
DP_DEBUG("success\n");
|
||||
end:
|
||||
dp_audio_config(audio, EXT_DISPLAY_CABLE_DISCONNECT);
|
||||
|
||||
atomic_set(&audio->session_on, 0);
|
||||
audio->engine_on = false;
|
||||
|
||||
dp_audio_deregister_ext_disp(audio);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void dp_audio_notify_work_fn(struct work_struct *work)
|
||||
{
|
||||
struct dp_audio_private *audio;
|
||||
struct delayed_work *dw = to_delayed_work(work);
|
||||
|
||||
audio = container_of(dw, struct dp_audio_private, notify_delayed_work);
|
||||
|
||||
dp_audio_notify(audio, EXT_DISPLAY_CABLE_CONNECT);
|
||||
}
|
||||
|
||||
static int dp_audio_create_notify_workqueue(struct dp_audio_private *audio)
|
||||
{
|
||||
audio->notify_workqueue = create_workqueue("sdm_dp_audio_notify");
|
||||
if (IS_ERR_OR_NULL(audio->notify_workqueue)) {
|
||||
DP_ERR("Error creating notify_workqueue\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
INIT_DELAYED_WORK(&audio->notify_delayed_work, dp_audio_notify_work_fn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dp_audio_destroy_notify_workqueue(struct dp_audio_private *audio)
|
||||
{
|
||||
if (audio->notify_workqueue)
|
||||
destroy_workqueue(audio->notify_workqueue);
|
||||
}
|
||||
|
||||
struct dp_audio *dp_audio_get(struct platform_device *pdev,
|
||||
struct dp_panel *panel,
|
||||
struct dp_catalog_audio *catalog)
|
||||
{
|
||||
int rc = 0;
|
||||
struct dp_audio_private *audio;
|
||||
struct dp_audio *dp_audio;
|
||||
|
||||
if (!pdev || !panel || !catalog) {
|
||||
DP_ERR("invalid input\n");
|
||||
rc = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
audio = devm_kzalloc(&pdev->dev, sizeof(*audio), GFP_KERNEL);
|
||||
if (!audio) {
|
||||
rc = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = dp_audio_create_notify_workqueue(audio);
|
||||
if (rc)
|
||||
goto error_notify_workqueue;
|
||||
|
||||
init_completion(&audio->hpd_comp);
|
||||
|
||||
audio->pdev = pdev;
|
||||
audio->panel = panel;
|
||||
audio->catalog = catalog;
|
||||
|
||||
atomic_set(&audio->acked, 0);
|
||||
|
||||
dp_audio = &audio->dp_audio;
|
||||
|
||||
mutex_init(&audio->ops_lock);
|
||||
|
||||
dp_audio->on = dp_audio_on;
|
||||
dp_audio->off = dp_audio_off;
|
||||
|
||||
catalog->init(catalog);
|
||||
|
||||
return dp_audio;
|
||||
|
||||
error_notify_workqueue:
|
||||
devm_kfree(&pdev->dev, audio);
|
||||
error:
|
||||
return ERR_PTR(rc);
|
||||
}
|
||||
|
||||
void dp_audio_put(struct dp_audio *dp_audio)
|
||||
{
|
||||
struct dp_audio_private *audio;
|
||||
|
||||
if (!dp_audio)
|
||||
return;
|
||||
|
||||
audio = container_of(dp_audio, struct dp_audio_private, dp_audio);
|
||||
|
||||
mutex_destroy(&audio->ops_lock);
|
||||
|
||||
dp_audio_destroy_notify_workqueue(audio);
|
||||
|
||||
devm_kfree(&audio->pdev->dev, audio);
|
||||
}
|
76
qcom/opensource/display-drivers/msm/dp/dp_audio.h
Normal file
76
qcom/opensource/display-drivers/msm/dp/dp_audio.h
Normal file
@ -0,0 +1,76 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _DP_AUDIO_H_
|
||||
#define _DP_AUDIO_H_
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "dp_panel.h"
|
||||
#include "dp_catalog.h"
|
||||
|
||||
/**
|
||||
* struct dp_audio
|
||||
* @lane_count: number of lanes configured in current session
|
||||
* @bw_code: link rate's bandwidth code for current session
|
||||
* @tui_active: set to true if TUI is active in the system
|
||||
*/
|
||||
struct dp_audio {
|
||||
u32 lane_count;
|
||||
u32 bw_code;
|
||||
bool tui_active;
|
||||
|
||||
/**
|
||||
* on()
|
||||
*
|
||||
* Notifies user mode clients that DP is powered on, and that audio
|
||||
* playback can start on the external display.
|
||||
*
|
||||
* @dp_audio: an instance of struct dp_audio.
|
||||
*
|
||||
* Returns the error code in case of failure, 0 in success case.
|
||||
*/
|
||||
int (*on)(struct dp_audio *dp_audio);
|
||||
|
||||
/**
|
||||
* off()
|
||||
*
|
||||
* Notifies user mode clients that DP is shutting down, and audio
|
||||
* playback should be stopped on the external display.
|
||||
*
|
||||
* @dp_audio: an instance of struct dp_audio.
|
||||
* @skip_wait: flag to skip any waits
|
||||
*
|
||||
* Returns the error code in case of failure, 0 in success case.
|
||||
*/
|
||||
int (*off)(struct dp_audio *dp_audio, bool skip_wait);
|
||||
};
|
||||
|
||||
/**
|
||||
* dp_audio_get()
|
||||
*
|
||||
* Creates and instance of dp audio.
|
||||
*
|
||||
* @pdev: caller's platform device instance.
|
||||
* @panel: an instance of dp_panel module.
|
||||
* @catalog: an instance of dp_catalog_audio module.
|
||||
*
|
||||
* Returns the error code in case of failure, otherwize
|
||||
* an instance of newly created dp_module.
|
||||
*/
|
||||
struct dp_audio *dp_audio_get(struct platform_device *pdev,
|
||||
struct dp_panel *panel,
|
||||
struct dp_catalog_audio *catalog);
|
||||
|
||||
/**
|
||||
* dp_audio_put()
|
||||
*
|
||||
* Cleans the dp_audio instance.
|
||||
*
|
||||
* @dp_audio: an instance of dp_audio.
|
||||
*/
|
||||
void dp_audio_put(struct dp_audio *dp_audio);
|
||||
#endif /* _DP_AUDIO_H_ */
|
958
qcom/opensource/display-drivers/msm/dp/dp_aux.c
Normal file
958
qcom/opensource/display-drivers/msm/dp/dp_aux.c
Normal file
@ -0,0 +1,958 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2021-2023, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
|
||||
#if IS_ENABLED(CONFIG_QCOM_FSA4480_I2C)
|
||||
#include <linux/soc/qcom/fsa4480-i2c.h>
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_QCOM_WCD939X_I2C)
|
||||
#include <linux/soc/qcom/wcd939x-i2c.h>
|
||||
#endif
|
||||
|
||||
#include "dp_aux.h"
|
||||
#include "dp_hpd.h"
|
||||
#include "dp_debug.h"
|
||||
|
||||
#define DP_AUX_ENUM_STR(x) #x
|
||||
#define DP_AUX_IPC_NUM_PAGES 10
|
||||
|
||||
#define DP_AUX_DEBUG(dp_aux, fmt, ...) \
|
||||
do { \
|
||||
if (dp_aux) \
|
||||
ipc_log_string(dp_aux->ipc_log_context, "[d][%-4d]"fmt,\
|
||||
current->pid, ##__VA_ARGS__); \
|
||||
DP_DEBUG_V(fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define DP_AUX_WARN(dp_aux, fmt, ...) \
|
||||
do { \
|
||||
if (dp_aux) \
|
||||
ipc_log_string(dp_aux->ipc_log_context, "[w][%-4d]"fmt,\
|
||||
current->pid, ##__VA_ARGS__); \
|
||||
DP_WARN_V(fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define DP_AUX_WARN_RATELIMITED(dp_aux, fmt, ...) \
|
||||
do { \
|
||||
if (dp_aux) \
|
||||
ipc_log_string(dp_aux->ipc_log_context, "[w][%-4d]"fmt,\
|
||||
current->pid, ##__VA_ARGS__); \
|
||||
DP_WARN_RATELIMITED_V(fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define DP_AUX_ERR(dp_aux, fmt, ...) \
|
||||
do { \
|
||||
if (dp_aux) \
|
||||
ipc_log_string(dp_aux->ipc_log_context, "[e][%-4d]"fmt,\
|
||||
current->pid, ##__VA_ARGS__); \
|
||||
DP_ERR_V(fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define DP_AUX_ERR_RATELIMITED(dp_aux, fmt, ...) \
|
||||
do { \
|
||||
if (dp_aux) \
|
||||
ipc_log_string(dp_aux->ipc_log_context, "[e][%-4d]"fmt,\
|
||||
current->pid, ##__VA_ARGS__); \
|
||||
DP_ERR_RATELIMITED_V(fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
enum {
|
||||
DP_AUX_DATA_INDEX_WRITE = BIT(31),
|
||||
};
|
||||
|
||||
struct dp_aux_private {
|
||||
struct device *dev;
|
||||
struct dp_aux dp_aux;
|
||||
struct dp_catalog_aux *catalog;
|
||||
struct dp_aux_cfg *cfg;
|
||||
struct device_node *aux_switch_node;
|
||||
struct mutex mutex;
|
||||
struct completion comp;
|
||||
struct drm_dp_aux drm_aux;
|
||||
|
||||
struct dp_aux_bridge *aux_bridge;
|
||||
struct dp_aux_bridge *sim_bridge;
|
||||
bool bridge_in_transfer;
|
||||
bool sim_in_transfer;
|
||||
|
||||
bool cmd_busy;
|
||||
bool native;
|
||||
bool read;
|
||||
bool no_send_addr;
|
||||
bool no_send_stop;
|
||||
bool enabled;
|
||||
|
||||
u32 offset;
|
||||
u32 segment;
|
||||
u32 aux_error_num;
|
||||
u32 retry_cnt;
|
||||
|
||||
bool switch_enable;
|
||||
int switch_orientation;
|
||||
|
||||
atomic_t aborted;
|
||||
};
|
||||
|
||||
static void dp_aux_hex_dump(struct drm_dp_aux *drm_aux,
|
||||
struct drm_dp_aux_msg *msg)
|
||||
{
|
||||
char prefix[64];
|
||||
int i, linelen, remaining = msg->size;
|
||||
const int rowsize = 16;
|
||||
u8 linebuf[64];
|
||||
struct dp_aux_private *aux = container_of(drm_aux,
|
||||
struct dp_aux_private, drm_aux);
|
||||
struct dp_aux *dp_aux = &aux->dp_aux;
|
||||
|
||||
snprintf(prefix, sizeof(prefix), "%s %s %4xh(%2zu): ",
|
||||
(msg->request & DP_AUX_I2C_MOT) ? "I2C" : "NAT",
|
||||
(msg->request & DP_AUX_I2C_READ) ? "RD" : "WR",
|
||||
msg->address, msg->size);
|
||||
|
||||
for (i = 0; i < msg->size; i += rowsize) {
|
||||
linelen = min(remaining, rowsize);
|
||||
remaining -= rowsize;
|
||||
|
||||
hex_dump_to_buffer(msg->buffer + i, linelen, rowsize, 1,
|
||||
linebuf, sizeof(linebuf), false);
|
||||
|
||||
if (msg->size == 1 && msg->address == 0)
|
||||
DP_DEBUG_V("%s%s\n", prefix, linebuf);
|
||||
else
|
||||
DP_AUX_DEBUG(dp_aux, "%s%s\n", prefix, linebuf);
|
||||
}
|
||||
}
|
||||
|
||||
static char *dp_aux_get_error(u32 aux_error)
|
||||
{
|
||||
switch (aux_error) {
|
||||
case DP_AUX_ERR_NONE:
|
||||
return DP_AUX_ENUM_STR(DP_AUX_ERR_NONE);
|
||||
case DP_AUX_ERR_ADDR:
|
||||
return DP_AUX_ENUM_STR(DP_AUX_ERR_ADDR);
|
||||
case DP_AUX_ERR_TOUT:
|
||||
return DP_AUX_ENUM_STR(DP_AUX_ERR_TOUT);
|
||||
case DP_AUX_ERR_NACK:
|
||||
return DP_AUX_ENUM_STR(DP_AUX_ERR_NACK);
|
||||
case DP_AUX_ERR_DEFER:
|
||||
return DP_AUX_ENUM_STR(DP_AUX_ERR_DEFER);
|
||||
case DP_AUX_ERR_NACK_DEFER:
|
||||
return DP_AUX_ENUM_STR(DP_AUX_ERR_NACK_DEFER);
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static u32 dp_aux_write(struct dp_aux_private *aux,
|
||||
struct drm_dp_aux_msg *msg)
|
||||
{
|
||||
u32 data[4], reg, len;
|
||||
u8 *msgdata = msg->buffer;
|
||||
int const aux_cmd_fifo_len = 128;
|
||||
int i = 0;
|
||||
struct dp_aux *dp_aux = &aux->dp_aux;
|
||||
|
||||
if (aux->read)
|
||||
len = 4;
|
||||
else
|
||||
len = msg->size + 4;
|
||||
|
||||
/*
|
||||
* cmd fifo only has depth of 144 bytes
|
||||
* limit buf length to 128 bytes here
|
||||
*/
|
||||
if (len > aux_cmd_fifo_len) {
|
||||
DP_AUX_ERR(dp_aux, "buf len error\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Pack cmd and write to HW */
|
||||
data[0] = (msg->address >> 16) & 0xf; /* addr[19:16] */
|
||||
if (aux->read)
|
||||
data[0] |= BIT(4); /* R/W */
|
||||
|
||||
data[1] = (msg->address >> 8) & 0xff; /* addr[15:8] */
|
||||
data[2] = msg->address & 0xff; /* addr[7:0] */
|
||||
data[3] = (msg->size - 1) & 0xff; /* len[7:0] */
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
reg = (i < 4) ? data[i] : msgdata[i - 4];
|
||||
reg = ((reg) << 8) & 0x0000ff00; /* index = 0, write */
|
||||
if (i == 0)
|
||||
reg |= DP_AUX_DATA_INDEX_WRITE;
|
||||
aux->catalog->data = reg;
|
||||
aux->catalog->write_data(aux->catalog);
|
||||
}
|
||||
|
||||
aux->catalog->clear_trans(aux->catalog, false);
|
||||
aux->catalog->clear_hw_interrupts(aux->catalog);
|
||||
|
||||
reg = 0; /* Transaction number == 1 */
|
||||
if (!aux->native) { /* i2c */
|
||||
reg |= BIT(8);
|
||||
|
||||
if (aux->no_send_addr)
|
||||
reg |= BIT(10);
|
||||
|
||||
if (aux->no_send_stop)
|
||||
reg |= BIT(11);
|
||||
}
|
||||
|
||||
reg |= BIT(9);
|
||||
aux->catalog->data = reg;
|
||||
aux->catalog->write_trans(aux->catalog);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int dp_aux_cmd_fifo_tx(struct dp_aux_private *aux,
|
||||
struct drm_dp_aux_msg *msg)
|
||||
{
|
||||
u32 ret = 0, len = 0, timeout;
|
||||
int const aux_timeout_ms = HZ/4;
|
||||
struct dp_aux *dp_aux = &aux->dp_aux;
|
||||
char prefix[64];
|
||||
|
||||
snprintf(prefix, sizeof(prefix), "%s %s %4xh(%2zu): ",
|
||||
(msg->request & DP_AUX_I2C_MOT) ? "I2C" : "NAT",
|
||||
(msg->request & DP_AUX_I2C_READ) ? "RD" : "WR",
|
||||
msg->address, msg->size);
|
||||
|
||||
reinit_completion(&aux->comp);
|
||||
|
||||
len = dp_aux_write(aux, msg);
|
||||
if (len == 0) {
|
||||
DP_AUX_ERR(dp_aux, "DP AUX write failed: %s\n", prefix);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
timeout = wait_for_completion_timeout(&aux->comp, aux_timeout_ms);
|
||||
if (!timeout) {
|
||||
DP_AUX_WARN_RATELIMITED(dp_aux, "aux timeout during [%s]\n", prefix);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
if (aux->aux_error_num == DP_AUX_ERR_NONE) {
|
||||
ret = len;
|
||||
} else {
|
||||
DP_AUX_WARN_RATELIMITED(dp_aux, "aux err [%s] during [%s]\n",
|
||||
dp_aux_get_error(aux->aux_error_num), prefix);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void dp_aux_cmd_fifo_rx(struct dp_aux_private *aux,
|
||||
struct drm_dp_aux_msg *msg)
|
||||
{
|
||||
u32 data;
|
||||
u8 *dp;
|
||||
u32 i, actual_i;
|
||||
u32 len = msg->size;
|
||||
struct dp_aux *dp_aux = &aux->dp_aux;
|
||||
|
||||
aux->catalog->clear_trans(aux->catalog, true);
|
||||
|
||||
data = 0;
|
||||
data |= DP_AUX_DATA_INDEX_WRITE; /* INDEX_WRITE */
|
||||
data |= BIT(0); /* read */
|
||||
|
||||
aux->catalog->data = data;
|
||||
aux->catalog->write_data(aux->catalog);
|
||||
|
||||
dp = msg->buffer;
|
||||
|
||||
/* discard first byte */
|
||||
data = aux->catalog->read_data(aux->catalog);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
data = aux->catalog->read_data(aux->catalog);
|
||||
*dp++ = (u8)((data >> 8) & 0xff);
|
||||
|
||||
actual_i = (data >> 16) & 0xFF;
|
||||
if (i != actual_i)
|
||||
DP_AUX_WARN(dp_aux, "Index mismatch: expected %d, found %d\n",
|
||||
i, actual_i);
|
||||
}
|
||||
}
|
||||
|
||||
static void dp_aux_native_handler(struct dp_aux_private *aux)
|
||||
{
|
||||
u32 isr = aux->catalog->isr;
|
||||
|
||||
if (isr & DP_INTR_AUX_I2C_DONE)
|
||||
aux->aux_error_num = DP_AUX_ERR_NONE;
|
||||
else if (isr & DP_INTR_WRONG_ADDR)
|
||||
aux->aux_error_num = DP_AUX_ERR_ADDR;
|
||||
else if (isr & DP_INTR_TIMEOUT)
|
||||
aux->aux_error_num = DP_AUX_ERR_TOUT;
|
||||
if (isr & DP_INTR_NACK_DEFER)
|
||||
aux->aux_error_num = DP_AUX_ERR_NACK;
|
||||
if (isr & DP_INTR_AUX_ERROR) {
|
||||
aux->aux_error_num = DP_AUX_ERR_PHY;
|
||||
aux->catalog->clear_hw_interrupts(aux->catalog);
|
||||
}
|
||||
|
||||
complete(&aux->comp);
|
||||
}
|
||||
|
||||
static void dp_aux_i2c_handler(struct dp_aux_private *aux)
|
||||
{
|
||||
u32 isr = aux->catalog->isr;
|
||||
|
||||
if (isr & DP_INTR_AUX_I2C_DONE) {
|
||||
if (isr & (DP_INTR_I2C_NACK | DP_INTR_I2C_DEFER))
|
||||
aux->aux_error_num = DP_AUX_ERR_NACK;
|
||||
else
|
||||
aux->aux_error_num = DP_AUX_ERR_NONE;
|
||||
} else {
|
||||
if (isr & DP_INTR_WRONG_ADDR)
|
||||
aux->aux_error_num = DP_AUX_ERR_ADDR;
|
||||
else if (isr & DP_INTR_TIMEOUT)
|
||||
aux->aux_error_num = DP_AUX_ERR_TOUT;
|
||||
if (isr & DP_INTR_NACK_DEFER)
|
||||
aux->aux_error_num = DP_AUX_ERR_NACK_DEFER;
|
||||
if (isr & DP_INTR_I2C_NACK)
|
||||
aux->aux_error_num = DP_AUX_ERR_NACK;
|
||||
if (isr & DP_INTR_I2C_DEFER)
|
||||
aux->aux_error_num = DP_AUX_ERR_DEFER;
|
||||
if (isr & DP_INTR_AUX_ERROR) {
|
||||
aux->aux_error_num = DP_AUX_ERR_PHY;
|
||||
aux->catalog->clear_hw_interrupts(aux->catalog);
|
||||
}
|
||||
}
|
||||
|
||||
complete(&aux->comp);
|
||||
}
|
||||
|
||||
static void dp_aux_isr(struct dp_aux *dp_aux)
|
||||
{
|
||||
struct dp_aux_private *aux;
|
||||
|
||||
if (!dp_aux) {
|
||||
DP_AUX_ERR(dp_aux, "invalid input\n");
|
||||
return;
|
||||
}
|
||||
|
||||
aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
|
||||
|
||||
aux->catalog->get_irq(aux->catalog, aux->cmd_busy);
|
||||
|
||||
if (!aux->cmd_busy)
|
||||
return;
|
||||
|
||||
if (aux->native)
|
||||
dp_aux_native_handler(aux);
|
||||
else
|
||||
dp_aux_i2c_handler(aux);
|
||||
}
|
||||
|
||||
static void dp_aux_reconfig(struct dp_aux *dp_aux)
|
||||
{
|
||||
struct dp_aux_private *aux;
|
||||
|
||||
if (!dp_aux) {
|
||||
DP_AUX_ERR(dp_aux, "invalid input\n");
|
||||
return;
|
||||
}
|
||||
|
||||
aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
|
||||
|
||||
aux->catalog->update_aux_cfg(aux->catalog,
|
||||
aux->cfg, PHY_AUX_CFG1);
|
||||
aux->catalog->reset(aux->catalog);
|
||||
}
|
||||
|
||||
static void dp_aux_abort_transaction(struct dp_aux *dp_aux, bool abort)
|
||||
{
|
||||
struct dp_aux_private *aux;
|
||||
|
||||
if (!dp_aux) {
|
||||
DP_AUX_ERR(dp_aux, "invalid input\n");
|
||||
return;
|
||||
}
|
||||
|
||||
aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
|
||||
|
||||
atomic_set(&aux->aborted, abort);
|
||||
}
|
||||
|
||||
static void dp_aux_update_offset_and_segment(struct dp_aux_private *aux,
|
||||
struct drm_dp_aux_msg *input_msg)
|
||||
{
|
||||
u32 const edid_address = 0x50;
|
||||
u32 const segment_address = 0x30;
|
||||
bool i2c_read = input_msg->request &
|
||||
(DP_AUX_I2C_READ & DP_AUX_NATIVE_READ);
|
||||
u8 *data = NULL;
|
||||
|
||||
if (aux->native || i2c_read || ((input_msg->address != edid_address) &&
|
||||
(input_msg->address != segment_address)))
|
||||
return;
|
||||
|
||||
|
||||
data = input_msg->buffer;
|
||||
if (input_msg->address == segment_address)
|
||||
aux->segment = *data;
|
||||
else
|
||||
aux->offset = *data;
|
||||
}
|
||||
|
||||
/**
|
||||
* dp_aux_transfer_helper() - helper function for EDID read transactions
|
||||
*
|
||||
* @aux: DP AUX private structure
|
||||
* @input_msg: input message from DRM upstream APIs
|
||||
* @send_seg: send the seg to sink
|
||||
*
|
||||
* return: void
|
||||
*
|
||||
* This helper function is used to fix EDID reads for non-compliant
|
||||
* sinks that do not handle the i2c middle-of-transaction flag correctly.
|
||||
*/
|
||||
static void dp_aux_transfer_helper(struct dp_aux_private *aux,
|
||||
struct drm_dp_aux_msg *input_msg, bool send_seg)
|
||||
{
|
||||
struct drm_dp_aux_msg helper_msg;
|
||||
u32 const message_size = 0x10;
|
||||
u32 const segment_address = 0x30;
|
||||
u32 const edid_block_length = 0x80;
|
||||
bool i2c_mot = input_msg->request & DP_AUX_I2C_MOT;
|
||||
bool i2c_read = input_msg->request &
|
||||
(DP_AUX_I2C_READ & DP_AUX_NATIVE_READ);
|
||||
|
||||
if (!i2c_mot || !i2c_read || (input_msg->size == 0))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Sending the segment value and EDID offset will be performed
|
||||
* from the DRM upstream EDID driver for each block. Avoid
|
||||
* duplicate AUX transactions related to this while reading the
|
||||
* first 16 bytes of each block.
|
||||
*/
|
||||
if (!(aux->offset % edid_block_length) || !send_seg)
|
||||
goto end;
|
||||
|
||||
aux->read = false;
|
||||
aux->cmd_busy = true;
|
||||
aux->no_send_addr = true;
|
||||
aux->no_send_stop = true;
|
||||
|
||||
/*
|
||||
* Send the segment address for i2c reads for segment > 0 and for which
|
||||
* the middle-of-transaction flag is set. This is required to support
|
||||
* EDID reads of more than 2 blocks as the segment address is reset to 0
|
||||
* since we are overriding the middle-of-transaction flag for read
|
||||
* transactions.
|
||||
*/
|
||||
if (aux->segment) {
|
||||
memset(&helper_msg, 0, sizeof(helper_msg));
|
||||
helper_msg.address = segment_address;
|
||||
helper_msg.buffer = &aux->segment;
|
||||
helper_msg.size = 1;
|
||||
dp_aux_cmd_fifo_tx(aux, &helper_msg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send the offset address for every i2c read in which the
|
||||
* middle-of-transaction flag is set. This will ensure that the sink
|
||||
* will update its read pointer and return the correct portion of the
|
||||
* EDID buffer in the subsequent i2c read trasntion triggered in the
|
||||
* native AUX transfer function.
|
||||
*/
|
||||
memset(&helper_msg, 0, sizeof(helper_msg));
|
||||
helper_msg.address = input_msg->address;
|
||||
helper_msg.buffer = &aux->offset;
|
||||
helper_msg.size = 1;
|
||||
dp_aux_cmd_fifo_tx(aux, &helper_msg);
|
||||
end:
|
||||
aux->offset += message_size;
|
||||
if (aux->offset == 0x80 || aux->offset == 0x100)
|
||||
aux->segment = 0x0; /* reset segment at end of block */
|
||||
}
|
||||
|
||||
static int dp_aux_transfer_ready(struct dp_aux_private *aux,
|
||||
struct drm_dp_aux_msg *msg, bool send_seg)
|
||||
{
|
||||
int ret = 0;
|
||||
int const aux_cmd_native_max = 16;
|
||||
int const aux_cmd_i2c_max = 128;
|
||||
struct dp_aux *dp_aux = &aux->dp_aux;
|
||||
|
||||
if (atomic_read(&aux->aborted)) {
|
||||
ret = -ETIMEDOUT;
|
||||
goto error;
|
||||
}
|
||||
|
||||
aux->native = msg->request & (DP_AUX_NATIVE_WRITE & DP_AUX_NATIVE_READ);
|
||||
|
||||
/* Ignore address only message */
|
||||
if ((msg->size == 0) || (msg->buffer == NULL)) {
|
||||
msg->reply = aux->native ?
|
||||
DP_AUX_NATIVE_REPLY_ACK : DP_AUX_I2C_REPLY_ACK;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* msg sanity check */
|
||||
if ((aux->native && (msg->size > aux_cmd_native_max)) ||
|
||||
(msg->size > aux_cmd_i2c_max)) {
|
||||
DP_AUX_ERR(dp_aux, "%s: invalid msg: size(%zu), request(%x)\n",
|
||||
__func__, msg->size, msg->request);
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
dp_aux_update_offset_and_segment(aux, msg);
|
||||
|
||||
dp_aux_transfer_helper(aux, msg, send_seg);
|
||||
|
||||
aux->read = msg->request & (DP_AUX_I2C_READ & DP_AUX_NATIVE_READ);
|
||||
|
||||
if (aux->read) {
|
||||
aux->no_send_addr = true;
|
||||
aux->no_send_stop = false;
|
||||
} else {
|
||||
aux->no_send_addr = true;
|
||||
aux->no_send_stop = true;
|
||||
}
|
||||
|
||||
aux->cmd_busy = true;
|
||||
error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline bool dp_aux_is_sideband_msg(u32 address, size_t size)
|
||||
{
|
||||
return (address >= 0x1000 && address + size < 0x1800) ||
|
||||
(address >= 0x2000 && address + size < 0x2200);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function does the real job to process an AUX transaction.
|
||||
* It will call aux_reset() function to reset the AUX channel,
|
||||
* if the waiting is timeout.
|
||||
*/
|
||||
static ssize_t dp_aux_transfer(struct drm_dp_aux *drm_aux,
|
||||
struct drm_dp_aux_msg *msg)
|
||||
{
|
||||
ssize_t ret;
|
||||
int const retry_count = 5;
|
||||
struct dp_aux_private *aux = container_of(drm_aux,
|
||||
struct dp_aux_private, drm_aux);
|
||||
|
||||
mutex_lock(&aux->mutex);
|
||||
|
||||
ret = dp_aux_transfer_ready(aux, msg, true);
|
||||
if (ret)
|
||||
goto unlock_exit;
|
||||
|
||||
if (!aux->cmd_busy) {
|
||||
ret = msg->size;
|
||||
goto unlock_exit;
|
||||
}
|
||||
|
||||
ret = dp_aux_cmd_fifo_tx(aux, msg);
|
||||
if ((ret < 0) && !atomic_read(&aux->aborted)) {
|
||||
aux->retry_cnt++;
|
||||
if (!(aux->retry_cnt % retry_count))
|
||||
aux->catalog->update_aux_cfg(aux->catalog,
|
||||
aux->cfg, PHY_AUX_CFG1);
|
||||
aux->catalog->reset(aux->catalog);
|
||||
goto unlock_exit;
|
||||
} else if (ret < 0) {
|
||||
goto unlock_exit;
|
||||
}
|
||||
|
||||
if (aux->aux_error_num == DP_AUX_ERR_NONE) {
|
||||
if (aux->read)
|
||||
dp_aux_cmd_fifo_rx(aux, msg);
|
||||
|
||||
dp_aux_hex_dump(drm_aux, msg);
|
||||
|
||||
msg->reply = aux->native ?
|
||||
DP_AUX_NATIVE_REPLY_ACK : DP_AUX_I2C_REPLY_ACK;
|
||||
} else {
|
||||
/* Reply defer to retry */
|
||||
msg->reply = aux->native ?
|
||||
DP_AUX_NATIVE_REPLY_DEFER : DP_AUX_I2C_REPLY_DEFER;
|
||||
}
|
||||
|
||||
/* Return requested size for success or retry */
|
||||
ret = msg->size;
|
||||
aux->retry_cnt = 0;
|
||||
|
||||
unlock_exit:
|
||||
aux->cmd_busy = false;
|
||||
mutex_unlock(&aux->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t dp_aux_bridge_transfer(struct drm_dp_aux *drm_aux,
|
||||
struct drm_dp_aux_msg *msg)
|
||||
{
|
||||
struct dp_aux_private *aux = container_of(drm_aux,
|
||||
struct dp_aux_private, drm_aux);
|
||||
ssize_t size;
|
||||
|
||||
if (aux->bridge_in_transfer) {
|
||||
size = dp_aux_transfer(drm_aux, msg);
|
||||
} else {
|
||||
aux->bridge_in_transfer = true;
|
||||
size = aux->aux_bridge->transfer(aux->aux_bridge,
|
||||
drm_aux, msg);
|
||||
aux->bridge_in_transfer = false;
|
||||
dp_aux_hex_dump(drm_aux, msg);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t dp_aux_transfer_debug(struct drm_dp_aux *drm_aux,
|
||||
struct drm_dp_aux_msg *msg)
|
||||
{
|
||||
struct dp_aux_private *aux = container_of(drm_aux,
|
||||
struct dp_aux_private, drm_aux);
|
||||
ssize_t size;
|
||||
int aborted;
|
||||
|
||||
mutex_lock(&aux->mutex);
|
||||
aborted = atomic_read(&aux->aborted);
|
||||
mutex_unlock(&aux->mutex);
|
||||
if (aborted) {
|
||||
size = -ETIMEDOUT;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (aux->sim_in_transfer) {
|
||||
if (aux->aux_bridge && aux->aux_bridge->transfer)
|
||||
size = dp_aux_bridge_transfer(drm_aux, msg);
|
||||
else
|
||||
size = dp_aux_transfer(drm_aux, msg);
|
||||
} else {
|
||||
aux->sim_in_transfer = true;
|
||||
size = aux->sim_bridge->transfer(aux->sim_bridge,
|
||||
drm_aux, msg);
|
||||
aux->sim_in_transfer = false;
|
||||
dp_aux_hex_dump(drm_aux, msg);
|
||||
}
|
||||
end:
|
||||
return size;
|
||||
}
|
||||
|
||||
static void dp_aux_reset_phy_config_indices(struct dp_aux_cfg *aux_cfg)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < PHY_AUX_CFG_MAX; i++)
|
||||
aux_cfg[i].current_index = 0;
|
||||
}
|
||||
|
||||
static void dp_aux_init(struct dp_aux *dp_aux, struct dp_aux_cfg *aux_cfg)
|
||||
{
|
||||
struct dp_aux_private *aux;
|
||||
|
||||
if (!dp_aux || !aux_cfg) {
|
||||
DP_AUX_ERR(dp_aux, "invalid input\n");
|
||||
return;
|
||||
}
|
||||
|
||||
aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
|
||||
|
||||
if (aux->enabled)
|
||||
return;
|
||||
|
||||
dp_aux_reset_phy_config_indices(aux_cfg);
|
||||
aux->catalog->setup(aux->catalog, aux_cfg);
|
||||
aux->catalog->reset(aux->catalog);
|
||||
aux->catalog->enable(aux->catalog, true);
|
||||
atomic_set(&aux->aborted, 0);
|
||||
aux->retry_cnt = 0;
|
||||
aux->enabled = true;
|
||||
}
|
||||
|
||||
static void dp_aux_deinit(struct dp_aux *dp_aux)
|
||||
{
|
||||
struct dp_aux_private *aux;
|
||||
|
||||
if (!dp_aux) {
|
||||
DP_AUX_ERR(dp_aux, "invalid input\n");
|
||||
return;
|
||||
}
|
||||
|
||||
aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
|
||||
|
||||
if (!aux->enabled)
|
||||
return;
|
||||
|
||||
atomic_set(&aux->aborted, 1);
|
||||
aux->catalog->enable(aux->catalog, false);
|
||||
aux->enabled = false;
|
||||
}
|
||||
|
||||
static int dp_aux_register(struct dp_aux *dp_aux, struct drm_device *drm_dev)
|
||||
{
|
||||
struct dp_aux_private *aux;
|
||||
int ret = 0;
|
||||
|
||||
if (!dp_aux) {
|
||||
DP_AUX_ERR(dp_aux, "invalid input\n");
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
|
||||
|
||||
aux->drm_aux.name = "sde_dp_aux";
|
||||
aux->drm_aux.dev = aux->dev;
|
||||
aux->drm_aux.transfer = dp_aux_transfer;
|
||||
#if (KERNEL_VERSION(5, 15, 0) <= LINUX_VERSION_CODE)
|
||||
aux->drm_aux.drm_dev = drm_dev;
|
||||
#endif
|
||||
atomic_set(&aux->aborted, 1);
|
||||
ret = drm_dp_aux_register(&aux->drm_aux);
|
||||
if (ret) {
|
||||
DP_AUX_ERR(dp_aux, "%s: failed to register drm aux: %d\n", __func__, ret);
|
||||
goto exit;
|
||||
}
|
||||
dp_aux->drm_aux = &aux->drm_aux;
|
||||
|
||||
/* if bridge is defined, override transfer function */
|
||||
if (aux->aux_bridge && aux->aux_bridge->transfer)
|
||||
aux->drm_aux.transfer = dp_aux_bridge_transfer;
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void dp_aux_deregister(struct dp_aux *dp_aux)
|
||||
{
|
||||
struct dp_aux_private *aux;
|
||||
|
||||
if (!dp_aux) {
|
||||
DP_AUX_ERR(dp_aux, "invalid input\n");
|
||||
return;
|
||||
}
|
||||
|
||||
aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
|
||||
drm_dp_aux_unregister(&aux->drm_aux);
|
||||
}
|
||||
|
||||
static void dp_aux_set_sim_mode(struct dp_aux *dp_aux,
|
||||
struct dp_aux_bridge *sim_bridge)
|
||||
{
|
||||
struct dp_aux_private *aux;
|
||||
|
||||
if (!dp_aux) {
|
||||
DP_AUX_ERR(dp_aux, "invalid input\n");
|
||||
return;
|
||||
}
|
||||
|
||||
aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
|
||||
|
||||
mutex_lock(&aux->mutex);
|
||||
|
||||
aux->sim_bridge = sim_bridge;
|
||||
|
||||
if (sim_bridge) {
|
||||
atomic_set(&aux->aborted, 0);
|
||||
aux->drm_aux.transfer = dp_aux_transfer_debug;
|
||||
} else if (aux->aux_bridge && aux->aux_bridge->transfer) {
|
||||
aux->drm_aux.transfer = dp_aux_bridge_transfer;
|
||||
} else {
|
||||
aux->drm_aux.transfer = dp_aux_transfer;
|
||||
}
|
||||
|
||||
mutex_unlock(&aux->mutex);
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_QCOM_FSA4480_I2C)
|
||||
static int dp_aux_configure_fsa_switch(struct dp_aux *dp_aux,
|
||||
bool enable, int orientation)
|
||||
{
|
||||
struct dp_aux_private *aux;
|
||||
int rc = 0;
|
||||
enum fsa_function event = FSA_USBC_DISPLAYPORT_DISCONNECTED;
|
||||
|
||||
if (!dp_aux) {
|
||||
DP_AUX_ERR(dp_aux, "invalid input\n");
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
|
||||
|
||||
if (!aux->aux_switch_node) {
|
||||
DP_AUX_DEBUG(dp_aux, "undefined fsa4480 handle\n");
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
switch (orientation) {
|
||||
case ORIENTATION_CC1:
|
||||
event = FSA_USBC_ORIENTATION_CC1;
|
||||
break;
|
||||
case ORIENTATION_CC2:
|
||||
event = FSA_USBC_ORIENTATION_CC2;
|
||||
break;
|
||||
default:
|
||||
DP_AUX_ERR(dp_aux, "invalid orientation\n");
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
DP_AUX_DEBUG(dp_aux, "enable=%d, orientation=%d, event=%d\n",
|
||||
enable, orientation, event);
|
||||
|
||||
rc = fsa4480_switch_event(aux->aux_switch_node, event);
|
||||
|
||||
if (rc)
|
||||
DP_AUX_ERR(dp_aux, "failed to configure fsa4480 i2c device (%d)\n", rc);
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_QCOM_WCD939X_I2C)
|
||||
static int dp_aux_configure_wcd_switch(struct dp_aux *dp_aux,
|
||||
bool enable, int orientation)
|
||||
{
|
||||
struct dp_aux_private *aux;
|
||||
int rc = 0;
|
||||
enum wcd_usbss_cable_status status = WCD_USBSS_CABLE_DISCONNECT;
|
||||
enum wcd_usbss_cable_types event = WCD_USBSS_DP_AUX_CC1;
|
||||
|
||||
if (!dp_aux) {
|
||||
DP_AUX_ERR(dp_aux, "invalid input\n");
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
|
||||
|
||||
if (!aux->aux_switch_node) {
|
||||
DP_AUX_DEBUG(dp_aux, "undefined wcd939x switch handle\n");
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if ((aux->switch_enable == enable) && (aux->switch_orientation == orientation))
|
||||
goto end;
|
||||
|
||||
if (enable) {
|
||||
status = WCD_USBSS_CABLE_CONNECT;
|
||||
|
||||
switch (orientation) {
|
||||
case ORIENTATION_CC1:
|
||||
event = WCD_USBSS_DP_AUX_CC1;
|
||||
break;
|
||||
case ORIENTATION_CC2:
|
||||
event = WCD_USBSS_DP_AUX_CC2;
|
||||
break;
|
||||
default:
|
||||
DP_AUX_ERR(dp_aux, "invalid orientation\n");
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
DP_AUX_DEBUG(dp_aux, "enable=%d, orientation=%d, event=%d\n",
|
||||
enable, orientation, event);
|
||||
|
||||
rc = wcd_usbss_switch_update(event, status);
|
||||
if (rc) {
|
||||
DP_AUX_ERR(dp_aux, "failed to configure wcd939x i2c device (%d)\n", rc);
|
||||
} else {
|
||||
aux->switch_enable = enable;
|
||||
aux->switch_orientation = orientation;
|
||||
}
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct dp_aux *dp_aux_get(struct device *dev, struct dp_catalog_aux *catalog,
|
||||
struct dp_parser *parser, struct device_node *aux_switch,
|
||||
struct dp_aux_bridge *aux_bridge, void *ipc_log_context,
|
||||
enum dp_aux_switch_type switch_type)
|
||||
{
|
||||
int rc = 0;
|
||||
struct dp_aux_private *aux;
|
||||
struct dp_aux *dp_aux = NULL;
|
||||
|
||||
if (!catalog || !parser) {
|
||||
DP_AUX_ERR(dp_aux, "invalid input\n");
|
||||
rc = -ENODEV;
|
||||
goto error;
|
||||
}
|
||||
|
||||
aux = devm_kzalloc(dev, sizeof(*aux), GFP_KERNEL);
|
||||
if (!aux) {
|
||||
rc = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
init_completion(&aux->comp);
|
||||
aux->cmd_busy = false;
|
||||
mutex_init(&aux->mutex);
|
||||
|
||||
aux->dev = dev;
|
||||
aux->catalog = catalog;
|
||||
aux->cfg = parser->aux_cfg;
|
||||
aux->aux_switch_node = aux_switch;
|
||||
aux->aux_bridge = aux_bridge;
|
||||
dp_aux = &aux->dp_aux;
|
||||
aux->retry_cnt = 0;
|
||||
aux->switch_orientation = -1;
|
||||
|
||||
dp_aux->isr = dp_aux_isr;
|
||||
dp_aux->init = dp_aux_init;
|
||||
dp_aux->deinit = dp_aux_deinit;
|
||||
dp_aux->drm_aux_register = dp_aux_register;
|
||||
dp_aux->drm_aux_deregister = dp_aux_deregister;
|
||||
dp_aux->reconfig = dp_aux_reconfig;
|
||||
dp_aux->abort = dp_aux_abort_transaction;
|
||||
dp_aux->set_sim_mode = dp_aux_set_sim_mode;
|
||||
dp_aux->ipc_log_context = ipc_log_context;
|
||||
|
||||
/*Condition to avoid allocating function pointers for aux bypass mode*/
|
||||
if (switch_type != DP_AUX_SWITCH_BYPASS) {
|
||||
#if IS_ENABLED(CONFIG_QCOM_FSA4480_I2C)
|
||||
if (switch_type == DP_AUX_SWITCH_FSA4480) {
|
||||
dp_aux->switch_configure = dp_aux_configure_fsa_switch;
|
||||
dp_aux->switch_register_notifier = fsa4480_reg_notifier;
|
||||
dp_aux->switch_unregister_notifier = fsa4480_unreg_notifier;
|
||||
}
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_QCOM_WCD939X_I2C)
|
||||
if (switch_type == DP_AUX_SWITCH_WCD939x) {
|
||||
dp_aux->switch_configure = dp_aux_configure_wcd_switch;
|
||||
dp_aux->switch_register_notifier = wcd_usbss_reg_notifier;
|
||||
dp_aux->switch_unregister_notifier = wcd_usbss_unreg_notifier;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return dp_aux;
|
||||
error:
|
||||
return ERR_PTR(rc);
|
||||
}
|
||||
|
||||
void dp_aux_put(struct dp_aux *dp_aux)
|
||||
{
|
||||
struct dp_aux_private *aux;
|
||||
|
||||
if (!dp_aux)
|
||||
return;
|
||||
|
||||
aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
|
||||
|
||||
mutex_destroy(&aux->mutex);
|
||||
|
||||
devm_kfree(aux->dev, aux);
|
||||
}
|
77
qcom/opensource/display-drivers/msm/dp/dp_aux.h
Normal file
77
qcom/opensource/display-drivers/msm/dp/dp_aux.h
Normal file
@ -0,0 +1,77 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _DP_AUX_H_
|
||||
#define _DP_AUX_H_
|
||||
|
||||
#include "dp_catalog.h"
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0))
|
||||
#include <drm/display/drm_dp_helper.h>
|
||||
#else
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#endif
|
||||
#include "dp_aux_bridge.h"
|
||||
|
||||
#define DP_STATE_NOTIFICATION_SENT BIT(0)
|
||||
#define DP_STATE_TRAIN_1_STARTED BIT(1)
|
||||
#define DP_STATE_TRAIN_1_SUCCEEDED BIT(2)
|
||||
#define DP_STATE_TRAIN_1_FAILED BIT(3)
|
||||
#define DP_STATE_TRAIN_2_STARTED BIT(4)
|
||||
#define DP_STATE_TRAIN_2_SUCCEEDED BIT(5)
|
||||
#define DP_STATE_TRAIN_2_FAILED BIT(6)
|
||||
#define DP_STATE_CTRL_POWERED_ON BIT(7)
|
||||
#define DP_STATE_CTRL_POWERED_OFF BIT(8)
|
||||
#define DP_STATE_LINK_MAINTENANCE_STARTED BIT(9)
|
||||
#define DP_STATE_LINK_MAINTENANCE_COMPLETED BIT(10)
|
||||
#define DP_STATE_LINK_MAINTENANCE_FAILED BIT(11)
|
||||
#define DP_STATE_AUX_TIMEOUT BIT(12)
|
||||
#define DP_STATE_PLL_LOCKED BIT(13)
|
||||
|
||||
enum dp_aux_switch_type {
|
||||
DP_AUX_SWITCH_BYPASS,
|
||||
DP_AUX_SWITCH_FSA4480,
|
||||
DP_AUX_SWITCH_WCD939x,
|
||||
};
|
||||
|
||||
enum dp_aux_error {
|
||||
DP_AUX_ERR_NONE = 0,
|
||||
DP_AUX_ERR_ADDR = -1,
|
||||
DP_AUX_ERR_TOUT = -2,
|
||||
DP_AUX_ERR_NACK = -3,
|
||||
DP_AUX_ERR_DEFER = -4,
|
||||
DP_AUX_ERR_NACK_DEFER = -5,
|
||||
DP_AUX_ERR_PHY = -6,
|
||||
};
|
||||
|
||||
struct dp_aux {
|
||||
u32 state;
|
||||
|
||||
bool read;
|
||||
|
||||
struct mutex *access_lock;
|
||||
void *ipc_log_context;
|
||||
|
||||
struct drm_dp_aux *drm_aux;
|
||||
int (*drm_aux_register)(struct dp_aux *aux, struct drm_device *drm_dev);
|
||||
void (*drm_aux_deregister)(struct dp_aux *aux);
|
||||
void (*isr)(struct dp_aux *aux);
|
||||
void (*init)(struct dp_aux *aux, struct dp_aux_cfg *aux_cfg);
|
||||
void (*deinit)(struct dp_aux *aux);
|
||||
void (*reconfig)(struct dp_aux *aux);
|
||||
void (*abort)(struct dp_aux *aux, bool abort);
|
||||
void (*set_sim_mode)(struct dp_aux *aux, struct dp_aux_bridge *sim_bridge);
|
||||
int (*switch_configure)(struct dp_aux *aux, bool enable, int orientation);
|
||||
int (*switch_register_notifier)(struct notifier_block *nb, struct device_node *node);
|
||||
int (*switch_unregister_notifier)(struct notifier_block *nb, struct device_node *node);
|
||||
};
|
||||
|
||||
struct dp_aux *dp_aux_get(struct device *dev, struct dp_catalog_aux *catalog,
|
||||
struct dp_parser *parser, struct device_node *aux_switch,
|
||||
struct dp_aux_bridge *aux_bridge, void *ipc_log_context,
|
||||
enum dp_aux_switch_type switch_type);
|
||||
void dp_aux_put(struct dp_aux *aux);
|
||||
|
||||
#endif /*__DP_AUX_H_*/
|
71
qcom/opensource/display-drivers/msm/dp/dp_aux_bridge.c
Normal file
71
qcom/opensource/display-drivers/msm/dp/dp_aux_bridge.c
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2014 Samsung Electronics Co., Ltd
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sub license,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "dp_aux_bridge.h"
|
||||
|
||||
static DEFINE_MUTEX(dp_aux_bridge_lock);
|
||||
static LIST_HEAD(du_aux_bridge_list);
|
||||
|
||||
int dp_aux_add_bridge(struct dp_aux_bridge *bridge)
|
||||
{
|
||||
mutex_lock(&dp_aux_bridge_lock);
|
||||
list_add_tail(&bridge->head, &du_aux_bridge_list);
|
||||
mutex_unlock(&dp_aux_bridge_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_OF)
|
||||
struct dp_aux_bridge *of_dp_aux_find_bridge(struct device_node *np)
|
||||
{
|
||||
struct dp_aux_bridge *bridge;
|
||||
|
||||
mutex_lock(&dp_aux_bridge_lock);
|
||||
|
||||
list_for_each_entry(bridge, &du_aux_bridge_list, head) {
|
||||
if (bridge->of_node == np) {
|
||||
mutex_unlock(&dp_aux_bridge_lock);
|
||||
return bridge;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&dp_aux_bridge_lock);
|
||||
return NULL;
|
||||
}
|
||||
#endif /* CONFIG_OF */
|
||||
|
135
qcom/opensource/display-drivers/msm/dp/dp_aux_bridge.h
Normal file
135
qcom/opensource/display-drivers/msm/dp/dp_aux_bridge.h
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _DP_AUX_BRIDGE_H_
|
||||
#define _DP_AUX_BRIDGE_H_
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/types.h>
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0))
|
||||
#include <drm/display/drm_dp_helper.h>
|
||||
#else
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* enum dp_aux_bridge_flag - DP aux bridge capability flag
|
||||
* DP_AUX_BRIDGE_HPD: HPD will be generated by DP aux bridge
|
||||
* DP_AUX_BRIDGE_MST: MST simulator is used by DP aux bridge
|
||||
*/
|
||||
enum dp_aux_bridge_flag {
|
||||
DP_AUX_BRIDGE_HPD = (1 << 0),
|
||||
DP_AUX_BRIDGE_MST = (1 << 1),
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dp_aux_bridge - DP aux bridge control structure
|
||||
* @of_node: device node pointer to the bridge
|
||||
* @dev_priv: pointer to the bridge driver's internal context
|
||||
* @flag: flag for capability
|
||||
* @mst_ctx: pointer to mst context when DP_AUX_BRIDGE_MST is set
|
||||
* @head: to keep track of all added bridges
|
||||
*/
|
||||
struct dp_aux_bridge {
|
||||
#if IS_ENABLED(CONFIG_OF)
|
||||
struct device_node *of_node;
|
||||
#endif /* CONFIG_OF */
|
||||
void *dev_priv;
|
||||
u32 flag;
|
||||
void *mst_ctx;
|
||||
struct list_head head;
|
||||
|
||||
/**
|
||||
* @register_hpd:
|
||||
*
|
||||
* This callback is invoked whenever bridge is registered
|
||||
* for HPD handling
|
||||
*
|
||||
* The attach callback is optional.
|
||||
*
|
||||
* Host will pass HPD callback handle to bridge, with
|
||||
* arguments @hpd_cb(void* dev, bool hpd, bool hpd_irq):
|
||||
*
|
||||
* @dev: private handle passed in register_hpd
|
||||
* @hpd: true if HPD is high, false if HPD is low
|
||||
* @hpd_irq: true if this is a HPD irq. @hpd will be
|
||||
* ignored when hpd_irq is true.
|
||||
*
|
||||
* RETURNS:
|
||||
*
|
||||
* Zero on success, error code on failure.
|
||||
*/
|
||||
int (*register_hpd)(struct dp_aux_bridge *bridge,
|
||||
int (*hpd_cb)(void *, bool, bool), void *dev);
|
||||
|
||||
/**
|
||||
* @transfer:
|
||||
*
|
||||
* This callback is invoked whenever dp_aux transfer
|
||||
* is called from host. Inside @transfer bridge can still
|
||||
* call @drm_aux->transfer to trigger the actual
|
||||
* DPCD/I2C transfer at host side.
|
||||
*
|
||||
* The attach callback is optional.
|
||||
*
|
||||
* RETURNS:
|
||||
*
|
||||
* Size of the bytes transferred, error code on failure.
|
||||
*/
|
||||
ssize_t (*transfer)(struct dp_aux_bridge *bridge,
|
||||
struct drm_dp_aux *drm_aux,
|
||||
struct drm_dp_aux_msg *msg);
|
||||
};
|
||||
|
||||
/**
|
||||
* dp_aux_add_bridge - Register DP aux bridge
|
||||
* @bridge: bridge pointer
|
||||
* return: 0 if successful
|
||||
*/
|
||||
int dp_aux_add_bridge(struct dp_aux_bridge *bridge);
|
||||
|
||||
#if IS_ENABLED(CONFIG_OF)
|
||||
/**
|
||||
* of_dp_aux_find_bridge - Find registered DP aux bridge
|
||||
* @np: device node pointer to the bridge
|
||||
* return: DP aux bridge pointer, NULL if not found
|
||||
*/
|
||||
struct dp_aux_bridge *of_dp_aux_find_bridge(struct device_node *np);
|
||||
#endif /* CONFIG_OF */
|
||||
|
||||
#endif /* _DP_AUX_BRIDGE_H_ */
|
||||
|
208
qcom/opensource/display-drivers/msm/dp/dp_bridge_hpd.c
Normal file
208
qcom/opensource/display-drivers/msm/dp/dp_bridge_hpd.c
Normal file
@ -0,0 +1,208 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/device.h>
|
||||
#include "dp_bridge_hpd.h"
|
||||
|
||||
struct dp_bridge_hpd_private {
|
||||
struct device *dev;
|
||||
struct dp_hpd base;
|
||||
struct dp_aux_bridge *bridge;
|
||||
struct delayed_work work;
|
||||
struct dp_hpd_cb *cb;
|
||||
bool hpd;
|
||||
bool hpd_irq;
|
||||
struct mutex hpd_lock;
|
||||
};
|
||||
|
||||
static int dp_bridge_hpd_connect(struct dp_bridge_hpd_private *bridge_hpd,
|
||||
bool hpd)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!bridge_hpd) {
|
||||
pr_err("invalid input\n");
|
||||
rc = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
bridge_hpd->base.hpd_high = hpd;
|
||||
bridge_hpd->base.alt_mode_cfg_done = hpd;
|
||||
bridge_hpd->base.hpd_irq = false;
|
||||
|
||||
if (!bridge_hpd->cb ||
|
||||
!bridge_hpd->cb->configure ||
|
||||
!bridge_hpd->cb->disconnect) {
|
||||
pr_err("invalid cb\n");
|
||||
rc = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (hpd)
|
||||
rc = bridge_hpd->cb->configure(bridge_hpd->dev);
|
||||
else
|
||||
rc = bridge_hpd->cb->disconnect(bridge_hpd->dev);
|
||||
|
||||
error:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int dp_bridge_hpd_attention(struct dp_bridge_hpd_private *bridge_hpd)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!bridge_hpd) {
|
||||
pr_err("invalid input\n");
|
||||
rc = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
bridge_hpd->base.hpd_irq = true;
|
||||
|
||||
if (bridge_hpd->cb && bridge_hpd->cb->attention)
|
||||
rc = bridge_hpd->cb->attention(bridge_hpd->dev);
|
||||
|
||||
error:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void dp_bridge_hpd_work(struct work_struct *work)
|
||||
{
|
||||
struct delayed_work *dw = to_delayed_work(work);
|
||||
struct dp_bridge_hpd_private *bridge_hpd = container_of(dw,
|
||||
struct dp_bridge_hpd_private, work);
|
||||
|
||||
mutex_lock(&bridge_hpd->hpd_lock);
|
||||
|
||||
if (bridge_hpd->hpd_irq)
|
||||
dp_bridge_hpd_attention(bridge_hpd);
|
||||
else
|
||||
dp_bridge_hpd_connect(bridge_hpd, bridge_hpd->hpd);
|
||||
|
||||
mutex_unlock(&bridge_hpd->hpd_lock);
|
||||
}
|
||||
|
||||
static int dp_bridge_hpd_simulate_connect(struct dp_hpd *dp_hpd, bool hpd)
|
||||
{
|
||||
int rc = 0;
|
||||
struct dp_bridge_hpd_private *bridge_hpd;
|
||||
|
||||
if (!dp_hpd) {
|
||||
pr_err("invalid input\n");
|
||||
rc = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
bridge_hpd = container_of(dp_hpd, struct dp_bridge_hpd_private, base);
|
||||
|
||||
dp_bridge_hpd_connect(bridge_hpd, hpd);
|
||||
error:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int dp_bridge_hpd_simulate_attention(struct dp_hpd *dp_hpd, int vdo)
|
||||
{
|
||||
int rc = 0;
|
||||
struct dp_bridge_hpd_private *bridge_hpd;
|
||||
|
||||
if (!dp_hpd) {
|
||||
pr_err("invalid input\n");
|
||||
rc = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
bridge_hpd = container_of(dp_hpd, struct dp_bridge_hpd_private, base);
|
||||
|
||||
dp_bridge_hpd_attention(bridge_hpd);
|
||||
error:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int dp_bridge_hpd_cb(void *dp_hpd, bool hpd, bool hpd_irq)
|
||||
{
|
||||
struct dp_bridge_hpd_private *bridge_hpd = dp_hpd;
|
||||
|
||||
mutex_lock(&bridge_hpd->hpd_lock);
|
||||
|
||||
bridge_hpd->hpd = hpd;
|
||||
bridge_hpd->hpd_irq = hpd_irq;
|
||||
queue_delayed_work(system_wq, &bridge_hpd->work, 0);
|
||||
|
||||
mutex_unlock(&bridge_hpd->hpd_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dp_bridge_hpd_register(struct dp_hpd *dp_hpd)
|
||||
{
|
||||
struct dp_bridge_hpd_private *bridge_hpd;
|
||||
|
||||
if (!dp_hpd)
|
||||
return -EINVAL;
|
||||
|
||||
bridge_hpd = container_of(dp_hpd, struct dp_bridge_hpd_private, base);
|
||||
|
||||
return bridge_hpd->bridge->register_hpd(bridge_hpd->bridge,
|
||||
dp_bridge_hpd_cb, bridge_hpd);
|
||||
}
|
||||
|
||||
struct dp_hpd *dp_bridge_hpd_get(struct device *dev,
|
||||
struct dp_hpd_cb *cb, struct dp_aux_bridge *aux_bridge)
|
||||
{
|
||||
int rc = 0;
|
||||
struct dp_bridge_hpd_private *bridge_hpd;
|
||||
|
||||
if (!dev || !cb) {
|
||||
pr_err("invalid device\n");
|
||||
rc = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
bridge_hpd = devm_kzalloc(dev, sizeof(*bridge_hpd), GFP_KERNEL);
|
||||
if (!bridge_hpd) {
|
||||
rc = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
bridge_hpd->dev = dev;
|
||||
bridge_hpd->cb = cb;
|
||||
bridge_hpd->bridge = aux_bridge;
|
||||
mutex_init(&bridge_hpd->hpd_lock);
|
||||
INIT_DELAYED_WORK(&bridge_hpd->work, dp_bridge_hpd_work);
|
||||
bridge_hpd->base.simulate_connect = dp_bridge_hpd_simulate_connect;
|
||||
bridge_hpd->base.simulate_attention = dp_bridge_hpd_simulate_attention;
|
||||
bridge_hpd->base.register_hpd = dp_bridge_hpd_register;
|
||||
|
||||
return &bridge_hpd->base;
|
||||
error:
|
||||
return ERR_PTR(rc);
|
||||
}
|
||||
|
||||
void dp_bridge_hpd_put(struct dp_hpd *dp_hpd)
|
||||
{
|
||||
struct dp_bridge_hpd_private *bridge_hpd;
|
||||
|
||||
if (!dp_hpd)
|
||||
return;
|
||||
|
||||
bridge_hpd = container_of(dp_hpd, struct dp_bridge_hpd_private, base);
|
||||
|
||||
devm_kfree(bridge_hpd->dev, bridge_hpd);
|
||||
}
|
42
qcom/opensource/display-drivers/msm/dp/dp_bridge_hpd.h
Normal file
42
qcom/opensource/display-drivers/msm/dp/dp_bridge_hpd.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DP_BRIDGE_HPD_H_
|
||||
#define _DP_BRIDGE_HPD_H_
|
||||
|
||||
#include "dp_hpd.h"
|
||||
|
||||
/**
|
||||
* dp_bridge_hpd_get() - configure and get the DisplayPlot HPD module data
|
||||
*
|
||||
* @dev: device instance of the caller
|
||||
* @cb: callback function for HPD response
|
||||
* @aux_bridge: handle for aux_bridge driver data
|
||||
* return: pointer to allocated gpio hpd module data
|
||||
*
|
||||
* This function sets up the gpio hpd module
|
||||
*/
|
||||
struct dp_hpd *dp_bridge_hpd_get(struct device *dev,
|
||||
struct dp_hpd_cb *cb, struct dp_aux_bridge *aux_bridge);
|
||||
|
||||
/**
|
||||
* dp_bridge_hpd_put()
|
||||
*
|
||||
* Cleans up dp_hpd instance
|
||||
*
|
||||
* @hpd: instance of gpio_hpd
|
||||
*/
|
||||
void dp_bridge_hpd_put(struct dp_hpd *hpd);
|
||||
|
||||
#endif /* _DP_BRIDGE_HPD_H_ */
|
3130
qcom/opensource/display-drivers/msm/dp/dp_catalog.c
Normal file
3130
qcom/opensource/display-drivers/msm/dp/dp_catalog.c
Normal file
File diff suppressed because it is too large
Load Diff
376
qcom/opensource/display-drivers/msm/dp/dp_catalog.h
Normal file
376
qcom/opensource/display-drivers/msm/dp/dp_catalog.h
Normal file
@ -0,0 +1,376 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _DP_CATALOG_H_
|
||||
#define _DP_CATALOG_H_
|
||||
|
||||
#include <linux/version.h>
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0))
|
||||
#include <drm/display/drm_dp_helper.h>
|
||||
#else
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#endif
|
||||
#include <drm/sde_drm.h>
|
||||
|
||||
#include "dp_parser.h"
|
||||
|
||||
/* interrupts */
|
||||
#define DP_INTR_HPD BIT(0)
|
||||
#define DP_INTR_AUX_I2C_DONE BIT(3)
|
||||
#define DP_INTR_WRONG_ADDR BIT(6)
|
||||
#define DP_INTR_TIMEOUT BIT(9)
|
||||
#define DP_INTR_NACK_DEFER BIT(12)
|
||||
#define DP_INTR_WRONG_DATA_CNT BIT(15)
|
||||
#define DP_INTR_I2C_NACK BIT(18)
|
||||
#define DP_INTR_I2C_DEFER BIT(21)
|
||||
#define DP_INTR_PLL_UNLOCKED BIT(24)
|
||||
#define DP_INTR_AUX_ERROR BIT(27)
|
||||
|
||||
#define DP_INTR_READY_FOR_VIDEO BIT(0)
|
||||
#define DP_INTR_IDLE_PATTERN_SENT BIT(3)
|
||||
#define DP_INTR_FRAME_END BIT(6)
|
||||
#define DP_INTR_CRC_UPDATED BIT(9)
|
||||
#define DP_INTR_SST_FIFO_UNDERFLOW BIT(28)
|
||||
|
||||
#define DP_INTR_MST_DP0_VCPF_SENT BIT(0)
|
||||
#define DP_INTR_MST_DP1_VCPF_SENT BIT(3)
|
||||
|
||||
#define DP_INTR_SST_ML_FIFO_OVERFLOW BIT(12)
|
||||
#define DP_INTR_MST0_ML_FIFO_OVERFLOW BIT(15)
|
||||
#define DP_INTR_MST1_ML_FIFO_OVERFLOW BIT(18)
|
||||
#define DP_INTR_DP1_FRAME_END BIT(21)
|
||||
#define DP_INTR_SDP0_COLLISION BIT(24)
|
||||
#define DP_INTR_SDP1_COLLISION BIT(27)
|
||||
|
||||
#define DP_INTR_DP0_BACKPRESSURE_ERROR (BIT(1) | BIT(0))
|
||||
#define DP_INTR_DP1_BACKPRESSURE_ERROR (BIT(5) | BIT(4))
|
||||
#define DP_INTR_SST_BS_LATE BIT(8)
|
||||
|
||||
|
||||
#define DP_MAX_TIME_SLOTS 64
|
||||
|
||||
/* stream id */
|
||||
enum dp_stream_id {
|
||||
DP_STREAM_0,
|
||||
DP_STREAM_1,
|
||||
DP_STREAM_MAX,
|
||||
};
|
||||
|
||||
struct dp_catalog_vsc_sdp_colorimetry {
|
||||
struct dp_sdp_header header;
|
||||
u8 data[32];
|
||||
};
|
||||
|
||||
struct dp_misr40_data {
|
||||
u32 ctrl_misr[8];
|
||||
u32 phy_misr[8];
|
||||
};
|
||||
|
||||
struct dp_catalog_aux {
|
||||
u32 data;
|
||||
u32 isr;
|
||||
|
||||
u32 (*read_data)(struct dp_catalog_aux *aux);
|
||||
int (*write_data)(struct dp_catalog_aux *aux);
|
||||
int (*write_trans)(struct dp_catalog_aux *aux);
|
||||
int (*clear_trans)(struct dp_catalog_aux *aux, bool read);
|
||||
void (*reset)(struct dp_catalog_aux *aux);
|
||||
void (*enable)(struct dp_catalog_aux *aux, bool enable);
|
||||
void (*update_aux_cfg)(struct dp_catalog_aux *aux,
|
||||
struct dp_aux_cfg *cfg, enum dp_phy_aux_config_type type);
|
||||
void (*setup)(struct dp_catalog_aux *aux,
|
||||
struct dp_aux_cfg *aux_cfg);
|
||||
void (*get_irq)(struct dp_catalog_aux *aux, bool cmd_busy);
|
||||
void (*clear_hw_interrupts)(struct dp_catalog_aux *aux);
|
||||
};
|
||||
|
||||
struct dp_catalog_ctrl {
|
||||
u32 isr;
|
||||
u32 isr3;
|
||||
u32 isr5;
|
||||
u32 isr6;
|
||||
|
||||
u8 *swing_hbr2_3;
|
||||
u8 *pre_emp_hbr2_3;
|
||||
u8 *swing_hbr_rbr;
|
||||
u8 *pre_emp_hbr_rbr;
|
||||
bool valid_lt_params;
|
||||
|
||||
void (*state_ctrl)(struct dp_catalog_ctrl *ctrl, u32 state);
|
||||
void (*config_ctrl)(struct dp_catalog_ctrl *ctrl, u8 ln_cnt);
|
||||
void (*lane_mapping)(struct dp_catalog_ctrl *ctrl, bool flipped,
|
||||
char *lane_map);
|
||||
void (*lane_pnswap)(struct dp_catalog_ctrl *ctrl, u8 ln_pnswap);
|
||||
void (*mainlink_ctrl)(struct dp_catalog_ctrl *ctrl, bool enable);
|
||||
void (*set_pattern)(struct dp_catalog_ctrl *ctrl, u32 pattern);
|
||||
void (*reset)(struct dp_catalog_ctrl *ctrl);
|
||||
void (*usb_reset)(struct dp_catalog_ctrl *ctrl, bool flip);
|
||||
bool (*mainlink_ready)(struct dp_catalog_ctrl *ctrl);
|
||||
void (*enable_irq)(struct dp_catalog_ctrl *ctrl, bool enable);
|
||||
void (*phy_reset)(struct dp_catalog_ctrl *ctrl);
|
||||
void (*phy_lane_cfg)(struct dp_catalog_ctrl *ctrl, bool flipped,
|
||||
u8 lane_cnt);
|
||||
void (*update_vx_px)(struct dp_catalog_ctrl *ctrl, u8 v_level,
|
||||
u8 p_level, bool high);
|
||||
void (*get_interrupt)(struct dp_catalog_ctrl *ctrl);
|
||||
u32 (*read_hdcp_status)(struct dp_catalog_ctrl *ctrl);
|
||||
void (*send_phy_pattern)(struct dp_catalog_ctrl *ctrl,
|
||||
u32 pattern);
|
||||
u32 (*read_phy_pattern)(struct dp_catalog_ctrl *ctrl);
|
||||
void (*mst_config)(struct dp_catalog_ctrl *ctrl, bool enable);
|
||||
void (*trigger_act)(struct dp_catalog_ctrl *ctrl);
|
||||
void (*read_act_complete_sts)(struct dp_catalog_ctrl *ctrl, bool *sts);
|
||||
void (*channel_alloc)(struct dp_catalog_ctrl *ctrl,
|
||||
u32 ch, u32 ch_start_timeslot, u32 tot_ch_cnt);
|
||||
void (*update_rg)(struct dp_catalog_ctrl *ctrl, u32 ch, u32 x_int,
|
||||
u32 y_frac_enum);
|
||||
void (*channel_dealloc)(struct dp_catalog_ctrl *ctrl,
|
||||
u32 ch, u32 ch_start_timeslot, u32 tot_ch_cnt);
|
||||
void (*fec_config)(struct dp_catalog_ctrl *ctrl, bool enable);
|
||||
void (*mainlink_levels)(struct dp_catalog_ctrl *ctrl, u8 lane_cnt);
|
||||
|
||||
int (*late_phy_init)(struct dp_catalog_ctrl *ctrl,
|
||||
u8 lane_cnt, bool flipped);
|
||||
int (*setup_misr)(struct dp_catalog_ctrl *ctrl);
|
||||
int (*read_misr)(struct dp_catalog_ctrl *ctrl, struct dp_misr40_data *data);
|
||||
};
|
||||
|
||||
struct dp_catalog_hpd {
|
||||
void (*config_hpd)(struct dp_catalog_hpd *hpd, bool en);
|
||||
u32 (*get_interrupt)(struct dp_catalog_hpd *hpd);
|
||||
};
|
||||
|
||||
#define HEADER_BYTE_2_BIT 0
|
||||
#define PARITY_BYTE_2_BIT 8
|
||||
#define HEADER_BYTE_1_BIT 16
|
||||
#define PARITY_BYTE_1_BIT 24
|
||||
#define HEADER_BYTE_3_BIT 16
|
||||
#define PARITY_BYTE_3_BIT 24
|
||||
|
||||
enum dp_catalog_audio_sdp_type {
|
||||
DP_AUDIO_SDP_STREAM,
|
||||
DP_AUDIO_SDP_TIMESTAMP,
|
||||
DP_AUDIO_SDP_INFOFRAME,
|
||||
DP_AUDIO_SDP_COPYMANAGEMENT,
|
||||
DP_AUDIO_SDP_ISRC,
|
||||
DP_AUDIO_SDP_MAX,
|
||||
};
|
||||
|
||||
enum dp_catalog_audio_header_type {
|
||||
DP_AUDIO_SDP_HEADER_1,
|
||||
DP_AUDIO_SDP_HEADER_2,
|
||||
DP_AUDIO_SDP_HEADER_3,
|
||||
DP_AUDIO_SDP_HEADER_MAX,
|
||||
};
|
||||
|
||||
struct dp_catalog_audio {
|
||||
enum dp_catalog_audio_sdp_type sdp_type;
|
||||
enum dp_catalog_audio_header_type sdp_header;
|
||||
u32 data;
|
||||
|
||||
enum dp_stream_id stream_id;
|
||||
|
||||
void (*init)(struct dp_catalog_audio *audio);
|
||||
void (*enable)(struct dp_catalog_audio *audio);
|
||||
void (*config_acr)(struct dp_catalog_audio *audio);
|
||||
void (*config_sdp)(struct dp_catalog_audio *audio);
|
||||
void (*set_header)(struct dp_catalog_audio *audio);
|
||||
void (*get_header)(struct dp_catalog_audio *audio);
|
||||
};
|
||||
|
||||
struct dp_dsc_cfg_data {
|
||||
bool dsc_en;
|
||||
bool continuous_pps;
|
||||
char pps[128];
|
||||
u32 pps_len;
|
||||
u32 pps_word[32];
|
||||
u32 pps_word_len;
|
||||
u8 parity[32];
|
||||
u8 parity_len;
|
||||
u32 parity_word[8];
|
||||
u32 parity_word_len;
|
||||
u32 slice_per_pkt;
|
||||
u32 bytes_per_pkt;
|
||||
u32 eol_byte_num;
|
||||
u32 be_in_lane;
|
||||
u32 dto_en;
|
||||
u32 dto_n;
|
||||
u32 dto_d;
|
||||
u32 dto_count;
|
||||
};
|
||||
|
||||
struct dp_catalog_panel {
|
||||
u32 total;
|
||||
u32 sync_start;
|
||||
u32 width_blanking;
|
||||
u32 dp_active;
|
||||
u8 *spd_vendor_name;
|
||||
u8 *spd_product_description;
|
||||
|
||||
struct dp_catalog_vsc_sdp_colorimetry vsc_colorimetry;
|
||||
struct dp_sdp_header dhdr_vsif_sdp;
|
||||
struct dp_sdp_header shdr_if_sdp;
|
||||
struct drm_msm_ext_hdr_metadata hdr_meta;
|
||||
|
||||
/* TPG */
|
||||
u32 hsync_period;
|
||||
u32 vsync_period;
|
||||
u32 display_v_start;
|
||||
u32 display_v_end;
|
||||
u32 v_sync_width;
|
||||
u32 hsync_ctl;
|
||||
u32 display_hctl;
|
||||
|
||||
/* TU */
|
||||
u32 dp_tu;
|
||||
u32 valid_boundary;
|
||||
u32 valid_boundary2;
|
||||
|
||||
u32 misc_val;
|
||||
|
||||
enum dp_stream_id stream_id;
|
||||
|
||||
bool widebus_en;
|
||||
struct dp_dsc_cfg_data dsc;
|
||||
|
||||
int (*timing_cfg)(struct dp_catalog_panel *panel);
|
||||
void (*config_hdr)(struct dp_catalog_panel *panel, bool en,
|
||||
u32 dhdr_max_pkts, bool flush);
|
||||
void (*config_sdp)(struct dp_catalog_panel *panel, bool en);
|
||||
int (*set_colorspace)(struct dp_catalog_panel *panel,
|
||||
bool vsc_supported);
|
||||
void (*tpg_config)(struct dp_catalog_panel *panel, u32 pattern);
|
||||
void (*config_spd)(struct dp_catalog_panel *panel);
|
||||
void (*config_misc)(struct dp_catalog_panel *panel);
|
||||
void (*config_msa)(struct dp_catalog_panel *panel,
|
||||
u32 rate, u32 stream_rate_khz);
|
||||
void (*update_transfer_unit)(struct dp_catalog_panel *panel);
|
||||
void (*config_ctrl)(struct dp_catalog_panel *panel, u32 cfg);
|
||||
void (*config_dto)(struct dp_catalog_panel *panel, bool ack);
|
||||
void (*dsc_cfg)(struct dp_catalog_panel *panel);
|
||||
void (*pps_flush)(struct dp_catalog_panel *panel);
|
||||
void (*dhdr_flush)(struct dp_catalog_panel *panel);
|
||||
bool (*dhdr_busy)(struct dp_catalog_panel *panel);
|
||||
int (*get_src_crc)(struct dp_catalog_panel *panel, u16 *crc);
|
||||
};
|
||||
|
||||
struct dp_catalog;
|
||||
struct dp_catalog_sub {
|
||||
u32 (*read)(struct dp_catalog *dp_catalog,
|
||||
struct dp_io_data *io_data, u32 offset);
|
||||
void (*write)(struct dp_catalog *dp_catalog,
|
||||
struct dp_io_data *io_data, u32 offset, u32 data);
|
||||
|
||||
void (*put)(struct dp_catalog *catalog);
|
||||
};
|
||||
|
||||
struct dp_catalog_io {
|
||||
struct dp_io_data *dp_ahb;
|
||||
struct dp_io_data *dp_aux;
|
||||
struct dp_io_data *dp_link;
|
||||
struct dp_io_data *dp_p0;
|
||||
struct dp_io_data *dp_phy;
|
||||
struct dp_io_data *dp_ln_tx0;
|
||||
struct dp_io_data *dp_ln_tx1;
|
||||
struct dp_io_data *dp_mmss_cc;
|
||||
struct dp_io_data *dp_pll;
|
||||
struct dp_io_data *usb3_dp_com;
|
||||
struct dp_io_data *hdcp_physical;
|
||||
struct dp_io_data *dp_p1;
|
||||
struct dp_io_data *dp_tcsr;
|
||||
};
|
||||
|
||||
struct dp_catalog {
|
||||
struct dp_catalog_aux aux;
|
||||
struct dp_catalog_ctrl ctrl;
|
||||
struct dp_catalog_audio audio;
|
||||
struct dp_catalog_panel panel;
|
||||
struct dp_catalog_hpd hpd;
|
||||
|
||||
struct dp_catalog_sub *sub;
|
||||
|
||||
void (*set_exe_mode)(struct dp_catalog *dp_catalog, char *mode);
|
||||
int (*get_reg_dump)(struct dp_catalog *dp_catalog,
|
||||
char *mode, u8 **out_buf, u32 *out_buf_len);
|
||||
};
|
||||
|
||||
static inline u8 dp_ecc_get_g0_value(u8 data)
|
||||
{
|
||||
u8 c[4];
|
||||
u8 g[4];
|
||||
u8 ret_data = 0;
|
||||
u8 i;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
c[i] = (data >> i) & 0x01;
|
||||
|
||||
g[0] = c[3];
|
||||
g[1] = c[0] ^ c[3];
|
||||
g[2] = c[1];
|
||||
g[3] = c[2];
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
ret_data = ((g[i] & 0x01) << i) | ret_data;
|
||||
|
||||
return ret_data;
|
||||
}
|
||||
|
||||
static inline u8 dp_ecc_get_g1_value(u8 data)
|
||||
{
|
||||
u8 c[4];
|
||||
u8 g[4];
|
||||
u8 ret_data = 0;
|
||||
u8 i;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
c[i] = (data >> i) & 0x01;
|
||||
|
||||
g[0] = c[0] ^ c[3];
|
||||
g[1] = c[0] ^ c[1] ^ c[3];
|
||||
g[2] = c[1] ^ c[2];
|
||||
g[3] = c[2] ^ c[3];
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
ret_data = ((g[i] & 0x01) << i) | ret_data;
|
||||
|
||||
return ret_data;
|
||||
}
|
||||
|
||||
static inline u8 dp_header_get_parity(u32 data)
|
||||
{
|
||||
u8 x0 = 0;
|
||||
u8 x1 = 0;
|
||||
u8 ci = 0;
|
||||
u8 iData = 0;
|
||||
u8 i = 0;
|
||||
u8 parity_byte;
|
||||
u8 num_byte = (data > 0xFF) ? 8 : 2;
|
||||
|
||||
for (i = 0; i < num_byte; i++) {
|
||||
iData = (data >> i*4) & 0xF;
|
||||
|
||||
ci = iData ^ x1;
|
||||
x1 = x0 ^ dp_ecc_get_g1_value(ci);
|
||||
x0 = dp_ecc_get_g0_value(ci);
|
||||
}
|
||||
|
||||
parity_byte = x1 | (x0 << 4);
|
||||
|
||||
return parity_byte;
|
||||
}
|
||||
|
||||
struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_parser *parser);
|
||||
void dp_catalog_put(struct dp_catalog *catalog);
|
||||
|
||||
struct dp_catalog_sub *dp_catalog_get_v420(struct device *dev,
|
||||
struct dp_catalog *catalog, struct dp_catalog_io *io);
|
||||
|
||||
struct dp_catalog_sub *dp_catalog_get_v200(struct device *dev,
|
||||
struct dp_catalog *catalog, struct dp_catalog_io *io);
|
||||
|
||||
u32 dp_catalog_get_dp_core_version(struct dp_catalog *dp_catalog);
|
||||
u32 dp_catalog_get_dp_phy_version(struct dp_catalog *dp_catalog);
|
||||
#endif /* _DP_CATALOG_H_ */
|
272
qcom/opensource/display-drivers/msm/dp/dp_catalog_v200.c
Normal file
272
qcom/opensource/display-drivers/msm/dp/dp_catalog_v200.c
Normal file
@ -0,0 +1,272 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "dp_catalog.h"
|
||||
#include "dp_reg.h"
|
||||
#include "dp_debug.h"
|
||||
|
||||
#define dp_catalog_get_priv_v200(x) ({ \
|
||||
struct dp_catalog *catalog; \
|
||||
catalog = container_of(x, struct dp_catalog, x); \
|
||||
container_of(catalog->sub, \
|
||||
struct dp_catalog_private_v200, sub); \
|
||||
})
|
||||
|
||||
#define dp_read(x) ({ \
|
||||
catalog->sub.read(catalog->dpc, io_data, x); \
|
||||
})
|
||||
|
||||
#define dp_write(x, y) ({ \
|
||||
catalog->sub.write(catalog->dpc, io_data, x, y); \
|
||||
})
|
||||
|
||||
struct dp_catalog_private_v200 {
|
||||
struct device *dev;
|
||||
struct dp_catalog_io *io;
|
||||
struct dp_catalog *dpc;
|
||||
struct dp_catalog_sub sub;
|
||||
};
|
||||
|
||||
static void dp_catalog_aux_clear_hw_int_v200(struct dp_catalog_aux *aux)
|
||||
{
|
||||
struct dp_catalog_private_v200 *catalog;
|
||||
struct dp_io_data *io_data;
|
||||
u32 data = 0;
|
||||
|
||||
if (!aux) {
|
||||
DP_ERR("invalid input\n");
|
||||
return;
|
||||
}
|
||||
|
||||
catalog = dp_catalog_get_priv_v200(aux);
|
||||
io_data = catalog->io->dp_phy;
|
||||
|
||||
data = dp_read(DP_PHY_AUX_INTERRUPT_STATUS_V200);
|
||||
|
||||
dp_write(DP_PHY_AUX_INTERRUPT_CLEAR_V200, 0x1f);
|
||||
wmb(); /* make sure 0x1f is written before next write */
|
||||
|
||||
dp_write(DP_PHY_AUX_INTERRUPT_CLEAR_V200, 0x9f);
|
||||
wmb(); /* make sure 0x9f is written before next write */
|
||||
|
||||
dp_write(DP_PHY_AUX_INTERRUPT_CLEAR_V200, 0);
|
||||
wmb(); /* make sure register is cleared */
|
||||
}
|
||||
|
||||
static void dp_catalog_aux_setup_v200(struct dp_catalog_aux *aux,
|
||||
struct dp_aux_cfg *cfg)
|
||||
{
|
||||
struct dp_catalog_private_v200 *catalog;
|
||||
struct dp_io_data *io_data;
|
||||
int i = 0, sw_reset = 0;
|
||||
|
||||
if (!aux || !cfg) {
|
||||
DP_ERR("invalid input\n");
|
||||
return;
|
||||
}
|
||||
|
||||
catalog = dp_catalog_get_priv_v200(aux);
|
||||
io_data = catalog->io->dp_ahb;
|
||||
|
||||
sw_reset = dp_read(DP_SW_RESET);
|
||||
|
||||
sw_reset |= BIT(0);
|
||||
dp_write(DP_SW_RESET, sw_reset);
|
||||
usleep_range(1000, 1010); /* h/w recommended delay */
|
||||
|
||||
sw_reset &= ~BIT(0);
|
||||
dp_write(DP_SW_RESET, sw_reset);
|
||||
|
||||
dp_write(DP_PHY_CTRL, 0x4); /* bit 2 */
|
||||
udelay(1000);
|
||||
dp_write(DP_PHY_CTRL, 0x0); /* bit 2 */
|
||||
wmb(); /* make sure programming happened */
|
||||
|
||||
io_data = catalog->io->dp_tcsr;
|
||||
dp_write(0x4c, 0x1); /* bit 0 & 2 */
|
||||
wmb(); /* make sure programming happened */
|
||||
|
||||
io_data = catalog->io->dp_phy;
|
||||
dp_write(DP_PHY_PD_CTL, 0x3c);
|
||||
wmb(); /* make sure PD programming happened */
|
||||
dp_write(DP_PHY_PD_CTL, 0x3d);
|
||||
wmb(); /* make sure PD programming happened */
|
||||
|
||||
/* DP AUX CFG register programming */
|
||||
io_data = catalog->io->dp_phy;
|
||||
for (i = 0; i < PHY_AUX_CFG_MAX; i++)
|
||||
dp_write(cfg[i].offset, cfg[i].lut[cfg[i].current_index]);
|
||||
|
||||
dp_write(DP_PHY_AUX_INTERRUPT_MASK_V200, 0x1F);
|
||||
wmb(); /* make sure AUX configuration is done before enabling it */
|
||||
}
|
||||
|
||||
static void dp_catalog_panel_config_msa_v200(struct dp_catalog_panel *panel,
|
||||
u32 rate, u32 stream_rate_khz)
|
||||
{
|
||||
u32 pixel_m, pixel_n;
|
||||
u32 mvid, nvid;
|
||||
u32 const nvid_fixed = 0x8000;
|
||||
u32 const link_rate_hbr2 = 540000;
|
||||
u32 const link_rate_hbr3 = 810000;
|
||||
struct dp_catalog_private_v200 *catalog;
|
||||
struct dp_io_data *io_data;
|
||||
u32 strm_reg_off = 0;
|
||||
u32 mvid_reg_off = 0, nvid_reg_off = 0;
|
||||
|
||||
if (!panel) {
|
||||
DP_ERR("invalid input\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (panel->stream_id >= DP_STREAM_MAX) {
|
||||
DP_ERR("invalid stream_id:%d\n", panel->stream_id);
|
||||
return;
|
||||
}
|
||||
|
||||
catalog = dp_catalog_get_priv_v200(panel);
|
||||
io_data = catalog->io->dp_mmss_cc;
|
||||
|
||||
if (panel->stream_id == DP_STREAM_1)
|
||||
strm_reg_off = MMSS_DP_PIXEL1_M_V200 -
|
||||
MMSS_DP_PIXEL_M_V200;
|
||||
|
||||
pixel_m = dp_read(MMSS_DP_PIXEL_M_V200 + strm_reg_off);
|
||||
pixel_n = dp_read(MMSS_DP_PIXEL_N_V200 + strm_reg_off);
|
||||
DP_DEBUG("pixel_m=0x%x, pixel_n=0x%x\n", pixel_m, pixel_n);
|
||||
|
||||
mvid = (pixel_m & 0xFFFF) * 5;
|
||||
nvid = (0xFFFF & (~pixel_n)) + (pixel_m & 0xFFFF);
|
||||
|
||||
if (nvid < nvid_fixed) {
|
||||
u32 temp;
|
||||
|
||||
temp = (nvid_fixed / nvid) * nvid;
|
||||
mvid = (nvid_fixed / nvid) * mvid;
|
||||
nvid = temp;
|
||||
}
|
||||
|
||||
DP_DEBUG("rate = %d\n", rate);
|
||||
|
||||
if (panel->widebus_en)
|
||||
mvid <<= 1;
|
||||
|
||||
if (link_rate_hbr2 == rate)
|
||||
nvid *= 2;
|
||||
|
||||
if (link_rate_hbr3 == rate)
|
||||
nvid *= 3;
|
||||
|
||||
io_data = catalog->io->dp_link;
|
||||
|
||||
if (panel->stream_id == DP_STREAM_1) {
|
||||
mvid_reg_off = DP1_SOFTWARE_MVID - DP_SOFTWARE_MVID;
|
||||
nvid_reg_off = DP1_SOFTWARE_NVID - DP_SOFTWARE_NVID;
|
||||
}
|
||||
|
||||
DP_DEBUG("mvid=0x%x, nvid=0x%x\n", mvid, nvid);
|
||||
dp_write(DP_SOFTWARE_MVID + mvid_reg_off, mvid);
|
||||
dp_write(DP_SOFTWARE_NVID + nvid_reg_off, nvid);
|
||||
}
|
||||
|
||||
static void dp_catalog_ctrl_lane_mapping_v200(struct dp_catalog_ctrl *ctrl,
|
||||
bool flipped, char *lane_map)
|
||||
{
|
||||
struct dp_catalog_private_v200 *catalog;
|
||||
struct dp_io_data *io_data;
|
||||
u8 l_map[4] = { 0 }, i = 0, j = 0;
|
||||
u32 lane_map_reg = 0;
|
||||
|
||||
if (!ctrl) {
|
||||
DP_ERR("invalid input\n");
|
||||
return;
|
||||
}
|
||||
|
||||
catalog = dp_catalog_get_priv_v200(ctrl);
|
||||
io_data = catalog->io->dp_link;
|
||||
|
||||
/* For flip case, swap phy lanes with ML0 and ML3, ML1 and ML2 */
|
||||
if (flipped) {
|
||||
for (i = 0; i < DP_MAX_PHY_LN; i++) {
|
||||
if (lane_map[i] == DP_ML0) {
|
||||
for (j = 0; j < DP_MAX_PHY_LN; j++) {
|
||||
if (lane_map[j] == DP_ML3) {
|
||||
l_map[i] = DP_ML3;
|
||||
l_map[j] = DP_ML0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (lane_map[i] == DP_ML1) {
|
||||
for (j = 0; j < DP_MAX_PHY_LN; j++) {
|
||||
if (lane_map[j] == DP_ML2) {
|
||||
l_map[i] = DP_ML2;
|
||||
l_map[j] = DP_ML1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Normal orientation */
|
||||
for (i = 0; i < DP_MAX_PHY_LN; i++)
|
||||
l_map[i] = lane_map[i];
|
||||
}
|
||||
|
||||
lane_map_reg = ((l_map[3]&3)<<6)|((l_map[2]&3)<<4)|((l_map[1]&3)<<2)
|
||||
|(l_map[0]&3);
|
||||
|
||||
dp_write(DP_LOGICAL2PHYSICAL_LANE_MAPPING, lane_map_reg);
|
||||
}
|
||||
|
||||
static void dp_catalog_ctrl_usb_reset_v200(struct dp_catalog_ctrl *ctrl,
|
||||
bool flip)
|
||||
{
|
||||
}
|
||||
|
||||
static void dp_catalog_put_v200(struct dp_catalog *catalog)
|
||||
{
|
||||
struct dp_catalog_private_v200 *catalog_priv;
|
||||
|
||||
if (!catalog)
|
||||
return;
|
||||
|
||||
catalog_priv = container_of(catalog->sub,
|
||||
struct dp_catalog_private_v200, sub);
|
||||
|
||||
devm_kfree(catalog_priv->dev, catalog_priv);
|
||||
}
|
||||
|
||||
struct dp_catalog_sub *dp_catalog_get_v200(struct device *dev,
|
||||
struct dp_catalog *catalog, struct dp_catalog_io *io)
|
||||
{
|
||||
struct dp_catalog_private_v200 *catalog_priv;
|
||||
|
||||
if (!dev || !catalog) {
|
||||
DP_ERR("invalid input\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
catalog_priv = devm_kzalloc(dev, sizeof(*catalog_priv), GFP_KERNEL);
|
||||
if (!catalog_priv)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
catalog_priv->dev = dev;
|
||||
catalog_priv->io = io;
|
||||
catalog_priv->dpc = catalog;
|
||||
|
||||
catalog_priv->sub.put = dp_catalog_put_v200;
|
||||
|
||||
catalog->aux.clear_hw_interrupts = dp_catalog_aux_clear_hw_int_v200;
|
||||
catalog->aux.setup = dp_catalog_aux_setup_v200;
|
||||
|
||||
catalog->panel.config_msa = dp_catalog_panel_config_msa_v200;
|
||||
|
||||
catalog->ctrl.lane_mapping = dp_catalog_ctrl_lane_mapping_v200;
|
||||
catalog->ctrl.usb_reset = dp_catalog_ctrl_usb_reset_v200;
|
||||
|
||||
return &catalog_priv->sub;
|
||||
}
|
346
qcom/opensource/display-drivers/msm/dp/dp_catalog_v420.c
Normal file
346
qcom/opensource/display-drivers/msm/dp/dp_catalog_v420.c
Normal file
@ -0,0 +1,346 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
|
||||
#include "dp_catalog.h"
|
||||
#include "dp_reg.h"
|
||||
#include "dp_debug.h"
|
||||
#include "dp_pll.h"
|
||||
#include <linux/rational.h>
|
||||
#include <drm/drm_fixed.h>
|
||||
|
||||
#define dp_catalog_get_priv_v420(x) ({ \
|
||||
struct dp_catalog *catalog; \
|
||||
catalog = container_of(x, struct dp_catalog, x); \
|
||||
container_of(catalog->sub, \
|
||||
struct dp_catalog_private_v420, sub); \
|
||||
})
|
||||
|
||||
#define dp_read(x) ({ \
|
||||
catalog->sub.read(catalog->dpc, io_data, x); \
|
||||
})
|
||||
|
||||
#define dp_write(x, y) ({ \
|
||||
catalog->sub.write(catalog->dpc, io_data, x, y); \
|
||||
})
|
||||
|
||||
#define MAX_VOLTAGE_LEVELS 4
|
||||
#define MAX_PRE_EMP_LEVELS 4
|
||||
|
||||
static u8 const vm_pre_emphasis[MAX_VOLTAGE_LEVELS][MAX_PRE_EMP_LEVELS] = {
|
||||
{0x00, 0x0E, 0x16, 0xFF}, /* pe0, 0 db */
|
||||
{0x00, 0x0E, 0x16, 0xFF}, /* pe1, 3.5 db */
|
||||
{0x00, 0x0E, 0xFF, 0xFF}, /* pe2, 6.0 db */
|
||||
{0xFF, 0xFF, 0xFF, 0xFF} /* pe3, 9.5 db */
|
||||
};
|
||||
|
||||
/* voltage swing, 0.2v and 1.0v are not support */
|
||||
static u8 const vm_voltage_swing[MAX_VOLTAGE_LEVELS][MAX_PRE_EMP_LEVELS] = {
|
||||
{0x07, 0x0F, 0x16, 0xFF}, /* sw0, 0.4v */
|
||||
{0x11, 0x1E, 0x1F, 0xFF}, /* sw1, 0.6 v */
|
||||
{0x1A, 0x1F, 0xFF, 0xFF}, /* sw1, 0.8 v */
|
||||
{0xFF, 0xFF, 0xFF, 0xFF} /* sw1, 1.2 v, optional */
|
||||
};
|
||||
|
||||
struct dp_catalog_private_v420 {
|
||||
struct device *dev;
|
||||
struct dp_catalog_sub sub;
|
||||
struct dp_catalog_io *io;
|
||||
struct dp_catalog *dpc;
|
||||
};
|
||||
|
||||
static void dp_catalog_aux_setup_v420(struct dp_catalog_aux *aux,
|
||||
struct dp_aux_cfg *cfg)
|
||||
{
|
||||
struct dp_catalog_private_v420 *catalog;
|
||||
struct dp_io_data *io_data;
|
||||
int i = 0;
|
||||
u32 phy_version;
|
||||
if (!aux || !cfg) {
|
||||
DP_ERR("invalid input\n");
|
||||
return;
|
||||
}
|
||||
|
||||
catalog = dp_catalog_get_priv_v420(aux);
|
||||
|
||||
io_data = catalog->io->dp_phy;
|
||||
dp_write(DP_PHY_PD_CTL, 0x67);
|
||||
wmb(); /* make sure PD programming happened */
|
||||
|
||||
phy_version = dp_catalog_get_dp_phy_version(catalog->dpc);
|
||||
if (phy_version >= 0x60000000) {
|
||||
/* Turn on BIAS current for PHY/PLL */
|
||||
io_data = catalog->io->dp_pll;
|
||||
dp_write(QSERDES_COM_BIAS_EN_CLKBUFLR_EN_V600, 0x17);
|
||||
wmb(); /* make sure BIAS programming happened */
|
||||
} else {
|
||||
/* Turn on BIAS current for PHY/PLL */
|
||||
io_data = catalog->io->dp_pll;
|
||||
dp_write(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x17);
|
||||
wmb(); /* make sure BIAS programming happened */
|
||||
}
|
||||
|
||||
io_data = catalog->io->dp_phy;
|
||||
/* DP AUX CFG register programming */
|
||||
for (i = 0; i < PHY_AUX_CFG_MAX; i++) {
|
||||
DP_DEBUG("%s: offset=0x%08x, value=0x%08x\n",
|
||||
dp_phy_aux_config_type_to_string(i),
|
||||
cfg[i].offset, cfg[i].lut[cfg[i].current_index]);
|
||||
dp_write(cfg[i].offset, cfg[i].lut[cfg[i].current_index]);
|
||||
}
|
||||
wmb(); /* make sure DP AUX CFG programming happened */
|
||||
|
||||
dp_write(DP_PHY_AUX_INTERRUPT_MASK_V420, 0x1F);
|
||||
}
|
||||
|
||||
static void dp_catalog_aux_clear_hw_int_v420(struct dp_catalog_aux *aux)
|
||||
{
|
||||
struct dp_catalog_private_v420 *catalog;
|
||||
struct dp_io_data *io_data;
|
||||
u32 data = 0;
|
||||
u32 phy_version;
|
||||
if (!aux) {
|
||||
DP_ERR("invalid input\n");
|
||||
return;
|
||||
}
|
||||
|
||||
catalog = dp_catalog_get_priv_v420(aux);
|
||||
phy_version = dp_catalog_get_dp_phy_version(catalog->dpc);
|
||||
io_data = catalog->io->dp_phy;
|
||||
if (phy_version >= 0x60000000)
|
||||
data = dp_read(DP_PHY_AUX_INTERRUPT_STATUS_V600);
|
||||
else
|
||||
data = dp_read(DP_PHY_AUX_INTERRUPT_STATUS_V420);
|
||||
|
||||
dp_write(DP_PHY_AUX_INTERRUPT_CLEAR_V420, 0x1f);
|
||||
wmb(); /* make sure 0x1f is written before next write */
|
||||
|
||||
dp_write(DP_PHY_AUX_INTERRUPT_CLEAR_V420, 0x9f);
|
||||
wmb(); /* make sure 0x9f is written before next write */
|
||||
|
||||
dp_write(DP_PHY_AUX_INTERRUPT_CLEAR_V420, 0);
|
||||
wmb(); /* make sure register is cleared */
|
||||
}
|
||||
|
||||
static void dp_catalog_panel_config_msa_v420(struct dp_catalog_panel *panel,
|
||||
u32 rate, u32 stream_rate_khz)
|
||||
{
|
||||
u32 mvid, nvid, mvid_off = 0, nvid_off = 0;
|
||||
u32 const nvid_fixed = 0x8000;
|
||||
struct dp_catalog *dp_catalog;
|
||||
struct dp_catalog_private_v420 *catalog;
|
||||
struct dp_io_data *io_data;
|
||||
unsigned long num, den;
|
||||
u32 const input_scale = 10;
|
||||
u64 f1, f2;
|
||||
|
||||
if (!panel || !rate) {
|
||||
DP_ERR("invalid input\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (panel->stream_id >= DP_STREAM_MAX) {
|
||||
DP_ERR("invalid stream id:%d\n", panel->stream_id);
|
||||
return;
|
||||
}
|
||||
|
||||
dp_catalog = container_of(panel, struct dp_catalog, panel);
|
||||
catalog = container_of(dp_catalog->sub, struct dp_catalog_private_v420, sub);
|
||||
|
||||
/*
|
||||
* MND calculator requires the target clock to be less than half the input clock. To meet
|
||||
* this requirement, the input clock is scaled here and then the resulting M value is
|
||||
* scaled by the same factor to offset the pre-scale.
|
||||
*/
|
||||
rational_best_approximation(rate * input_scale, stream_rate_khz,
|
||||
(unsigned long)(1 << 16) - 1,
|
||||
(unsigned long)(1 << 16) - 1, &den, &num);
|
||||
|
||||
mvid = (num & 0xFFFF);
|
||||
nvid = (den & 0xFFFF);
|
||||
mvid *= input_scale;
|
||||
|
||||
if (nvid < nvid_fixed) {
|
||||
f1 = drm_fixp_from_fraction(nvid_fixed, nvid);
|
||||
f2 = drm_fixp_from_fraction(mvid, 1);
|
||||
f1 = drm_fixp_mul(f1, f2);
|
||||
mvid = drm_fixp2int(f1);
|
||||
nvid = nvid_fixed;
|
||||
}
|
||||
|
||||
io_data = catalog->io->dp_link;
|
||||
|
||||
if (panel->stream_id == DP_STREAM_1) {
|
||||
mvid_off = DP1_SOFTWARE_MVID - DP_SOFTWARE_MVID;
|
||||
nvid_off = DP1_SOFTWARE_NVID - DP_SOFTWARE_NVID;
|
||||
}
|
||||
|
||||
DP_DEBUG("pclk=%ld, lclk=%ld, mvid=0x%x, nvid=0x%x\n", stream_rate_khz, rate, mvid, nvid);
|
||||
dp_write(DP_SOFTWARE_MVID + mvid_off, mvid);
|
||||
dp_write(DP_SOFTWARE_NVID + nvid_off, nvid);
|
||||
}
|
||||
|
||||
static void dp_catalog_ctrl_phy_lane_cfg_v420(struct dp_catalog_ctrl *ctrl,
|
||||
bool flipped, u8 ln_cnt)
|
||||
{
|
||||
u32 info = 0x0;
|
||||
struct dp_catalog_private_v420 *catalog;
|
||||
struct dp_io_data *io_data;
|
||||
u8 orientation = BIT(!!flipped);
|
||||
|
||||
if (!ctrl) {
|
||||
DP_ERR("invalid input\n");
|
||||
return;
|
||||
}
|
||||
|
||||
catalog = dp_catalog_get_priv_v420(ctrl);
|
||||
io_data = catalog->io->dp_phy;
|
||||
|
||||
info |= (ln_cnt & 0x0F);
|
||||
info |= ((orientation & 0x0F) << 4);
|
||||
DP_DEBUG("Shared Info = 0x%x\n", info);
|
||||
|
||||
dp_write(DP_PHY_SPARE0_V420, info);
|
||||
}
|
||||
|
||||
static void dp_catalog_ctrl_update_vx_px_v420(struct dp_catalog_ctrl *ctrl,
|
||||
u8 v_level, u8 p_level, bool high)
|
||||
{
|
||||
struct dp_catalog_private_v420 *catalog;
|
||||
struct dp_io_data *io_data;
|
||||
u8 value0, value1;
|
||||
u32 version;
|
||||
u32 phy_version;
|
||||
int idx;
|
||||
|
||||
if (!ctrl || !((v_level < MAX_VOLTAGE_LEVELS)
|
||||
&& (p_level < MAX_PRE_EMP_LEVELS))) {
|
||||
DP_ERR("invalid input\n");
|
||||
return;
|
||||
}
|
||||
|
||||
DP_DEBUG("hw: v=%d p=%d, high=%d\n", v_level, p_level, high);
|
||||
|
||||
catalog = dp_catalog_get_priv_v420(ctrl);
|
||||
phy_version = dp_catalog_get_dp_phy_version(catalog->dpc);
|
||||
|
||||
io_data = catalog->io->dp_ahb;
|
||||
version = dp_read(DP_HW_VERSION);
|
||||
DP_DEBUG("version: 0x%x\n", version);
|
||||
|
||||
/*
|
||||
* For DP controller versions >= 1.2.3
|
||||
*/
|
||||
if (version >= 0x10020003 && ctrl->valid_lt_params) {
|
||||
idx = v_level * MAX_VOLTAGE_LEVELS + p_level;
|
||||
if (high) {
|
||||
value0 = ctrl->swing_hbr2_3[idx];
|
||||
value1 = ctrl->pre_emp_hbr2_3[idx];
|
||||
} else {
|
||||
value0 = ctrl->swing_hbr_rbr[idx];
|
||||
value1 = ctrl->pre_emp_hbr_rbr[idx];
|
||||
}
|
||||
} else {
|
||||
value0 = vm_voltage_swing[v_level][p_level];
|
||||
value1 = vm_pre_emphasis[v_level][p_level];
|
||||
}
|
||||
|
||||
/* program default setting first */
|
||||
io_data = catalog->io->dp_ln_tx0;
|
||||
dp_write(TXn_TX_DRV_LVL_V420, 0x2A);
|
||||
dp_write(TXn_TX_EMP_POST1_LVL, 0x20);
|
||||
|
||||
io_data = catalog->io->dp_ln_tx1;
|
||||
dp_write(TXn_TX_DRV_LVL_V420, 0x2A);
|
||||
dp_write(TXn_TX_EMP_POST1_LVL, 0x20);
|
||||
|
||||
/* Enable MUX to use Cursor values from these registers */
|
||||
value0 |= BIT(5);
|
||||
value1 |= BIT(5);
|
||||
|
||||
/* Configure host and panel only if both values are allowed */
|
||||
if (value0 != 0xFF && value1 != 0xFF) {
|
||||
io_data = catalog->io->dp_ln_tx0;
|
||||
dp_write(TXn_TX_DRV_LVL_V420, value0);
|
||||
dp_write(TXn_TX_EMP_POST1_LVL, value1);
|
||||
|
||||
io_data = catalog->io->dp_ln_tx1;
|
||||
dp_write(TXn_TX_DRV_LVL_V420, value0);
|
||||
dp_write(TXn_TX_EMP_POST1_LVL, value1);
|
||||
|
||||
DP_DEBUG("hw: vx_value=0x%x px_value=0x%x\n",
|
||||
value0, value1);
|
||||
} else {
|
||||
DP_ERR("invalid vx (0x%x=0x%x), px (0x%x=0x%x\n",
|
||||
v_level, value0, p_level, value1);
|
||||
}
|
||||
}
|
||||
|
||||
static void dp_catalog_ctrl_lane_pnswap_v420(struct dp_catalog_ctrl *ctrl,
|
||||
u8 ln_pnswap)
|
||||
{
|
||||
struct dp_catalog_private_v420 *catalog;
|
||||
struct dp_io_data *io_data;
|
||||
u32 cfg0, cfg1;
|
||||
|
||||
catalog = dp_catalog_get_priv_v420(ctrl);
|
||||
|
||||
cfg0 = 0x0a;
|
||||
cfg1 = 0x0a;
|
||||
|
||||
cfg0 |= ((ln_pnswap >> 0) & 0x1) << 0;
|
||||
cfg0 |= ((ln_pnswap >> 1) & 0x1) << 2;
|
||||
cfg1 |= ((ln_pnswap >> 2) & 0x1) << 0;
|
||||
cfg1 |= ((ln_pnswap >> 3) & 0x1) << 2;
|
||||
|
||||
io_data = catalog->io->dp_ln_tx0;
|
||||
dp_write(TXn_TX_POL_INV_V420, cfg0);
|
||||
|
||||
io_data = catalog->io->dp_ln_tx1;
|
||||
dp_write(TXn_TX_POL_INV_V420, cfg1);
|
||||
}
|
||||
|
||||
static void dp_catalog_put_v420(struct dp_catalog *catalog)
|
||||
{
|
||||
struct dp_catalog_private_v420 *catalog_priv;
|
||||
|
||||
if (!catalog)
|
||||
return;
|
||||
|
||||
catalog_priv = container_of(catalog->sub,
|
||||
struct dp_catalog_private_v420, sub);
|
||||
devm_kfree(catalog_priv->dev, catalog_priv);
|
||||
}
|
||||
|
||||
struct dp_catalog_sub *dp_catalog_get_v420(struct device *dev,
|
||||
struct dp_catalog *catalog, struct dp_catalog_io *io)
|
||||
{
|
||||
struct dp_catalog_private_v420 *catalog_priv;
|
||||
|
||||
if (!dev || !catalog) {
|
||||
DP_ERR("invalid input\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
catalog_priv = devm_kzalloc(dev, sizeof(*catalog_priv), GFP_KERNEL);
|
||||
if (!catalog_priv)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
catalog_priv->dev = dev;
|
||||
catalog_priv->io = io;
|
||||
catalog_priv->dpc = catalog;
|
||||
|
||||
catalog_priv->sub.put = dp_catalog_put_v420;
|
||||
|
||||
catalog->aux.setup = dp_catalog_aux_setup_v420;
|
||||
catalog->aux.clear_hw_interrupts = dp_catalog_aux_clear_hw_int_v420;
|
||||
catalog->panel.config_msa = dp_catalog_panel_config_msa_v420;
|
||||
catalog->ctrl.phy_lane_cfg = dp_catalog_ctrl_phy_lane_cfg_v420;
|
||||
catalog->ctrl.update_vx_px = dp_catalog_ctrl_update_vx_px_v420;
|
||||
catalog->ctrl.lane_pnswap = dp_catalog_ctrl_lane_pnswap_v420;
|
||||
|
||||
return &catalog_priv->sub;
|
||||
}
|
1617
qcom/opensource/display-drivers/msm/dp/dp_ctrl.c
Normal file
1617
qcom/opensource/display-drivers/msm/dp/dp_ctrl.c
Normal file
File diff suppressed because it is too large
Load Diff
54
qcom/opensource/display-drivers/msm/dp/dp_ctrl.h
Normal file
54
qcom/opensource/display-drivers/msm/dp/dp_ctrl.h
Normal file
@ -0,0 +1,54 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _DP_CTRL_H_
|
||||
#define _DP_CTRL_H_
|
||||
|
||||
#include "dp_aux.h"
|
||||
#include "dp_panel.h"
|
||||
#include "dp_link.h"
|
||||
#include "dp_parser.h"
|
||||
#include "dp_power.h"
|
||||
#include "dp_catalog.h"
|
||||
#include "dp_debug.h"
|
||||
|
||||
struct dp_ctrl {
|
||||
int (*init)(struct dp_ctrl *dp_ctrl, bool flip, bool reset);
|
||||
void (*deinit)(struct dp_ctrl *dp_ctrl);
|
||||
int (*on)(struct dp_ctrl *dp_ctrl, bool mst_mode, bool fec_en,
|
||||
bool dsc_en, bool shallow);
|
||||
void (*off)(struct dp_ctrl *dp_ctrl);
|
||||
void (*abort)(struct dp_ctrl *dp_ctrl, bool abort);
|
||||
void (*isr)(struct dp_ctrl *dp_ctrl);
|
||||
bool (*handle_sink_request)(struct dp_ctrl *dp_ctrl);
|
||||
void (*process_phy_test_request)(struct dp_ctrl *dp_ctrl);
|
||||
int (*link_maintenance)(struct dp_ctrl *dp_ctrl);
|
||||
int (*stream_on)(struct dp_ctrl *dp_ctrl, struct dp_panel *panel);
|
||||
void (*stream_off)(struct dp_ctrl *dp_ctrl, struct dp_panel *panel);
|
||||
void (*stream_pre_off)(struct dp_ctrl *dp_ctrl, struct dp_panel *panel);
|
||||
void (*set_mst_channel_info)(struct dp_ctrl *dp_ctrl,
|
||||
enum dp_stream_id strm,
|
||||
u32 ch_start_slot, u32 ch_tot_slots);
|
||||
void (*set_sim_mode)(struct dp_ctrl *dp_ctrl, bool en);
|
||||
int (*setup_misr)(struct dp_ctrl *dp_ctrl);
|
||||
int (*read_misr)(struct dp_ctrl *dp_ctrl, struct dp_misr40_data *data);
|
||||
};
|
||||
|
||||
struct dp_ctrl_in {
|
||||
struct device *dev;
|
||||
struct dp_panel *panel;
|
||||
struct dp_aux *aux;
|
||||
struct dp_link *link;
|
||||
struct dp_parser *parser;
|
||||
struct dp_power *power;
|
||||
struct dp_catalog_ctrl *catalog;
|
||||
struct dp_pll *pll;
|
||||
};
|
||||
|
||||
struct dp_ctrl *dp_ctrl_get(struct dp_ctrl_in *in);
|
||||
void dp_ctrl_put(struct dp_ctrl *dp_ctrl);
|
||||
|
||||
#endif /* _DP_CTRL_H_ */
|
2598
qcom/opensource/display-drivers/msm/dp/dp_debug.c
Normal file
2598
qcom/opensource/display-drivers/msm/dp/dp_debug.c
Normal file
File diff suppressed because it is too large
Load Diff
175
qcom/opensource/display-drivers/msm/dp/dp_debug.h
Normal file
175
qcom/opensource/display-drivers/msm/dp/dp_debug.h
Normal file
@ -0,0 +1,175 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _DP_DEBUG_H_
|
||||
#define _DP_DEBUG_H_
|
||||
|
||||
#include "dp_panel.h"
|
||||
#include "dp_ctrl.h"
|
||||
#include "dp_link.h"
|
||||
#include "dp_aux.h"
|
||||
#include "dp_display.h"
|
||||
#include "dp_pll.h"
|
||||
#include <linux/ipc_logging.h>
|
||||
|
||||
#define DP_IPC_LOG(fmt, ...) \
|
||||
do { \
|
||||
void *ipc_logging_context = get_ipc_log_context(); \
|
||||
ipc_log_string(ipc_logging_context, fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define DP_DEBUG(fmt, ...) \
|
||||
do { \
|
||||
DP_IPC_LOG("[d][%-4d]"fmt, current->pid, ##__VA_ARGS__); \
|
||||
DP_DEBUG_V(fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define DP_INFO(fmt, ...) \
|
||||
do { \
|
||||
DP_IPC_LOG("[i][%-4d]"fmt, current->pid, ##__VA_ARGS__); \
|
||||
DP_INFO_V(fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define DP_WARN(fmt, ...) \
|
||||
do { \
|
||||
DP_IPC_LOG("[w][%-4d]"fmt, current->pid, ##__VA_ARGS__); \
|
||||
DP_WARN_V(fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define DP_ERR(fmt, ...) \
|
||||
do { \
|
||||
DP_IPC_LOG("[e][%-4d]"fmt, current->pid, ##__VA_ARGS__); \
|
||||
DP_ERR_V(fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define DP_DEBUG_V(fmt, ...) \
|
||||
do { \
|
||||
if (drm_debug_enabled(DRM_UT_KMS)) \
|
||||
DRM_DEBUG("[msm-dp-debug][%-4d]"fmt, current->pid, \
|
||||
##__VA_ARGS__); \
|
||||
else \
|
||||
pr_debug("[drm:%s][msm-dp-debug][%-4d]"fmt, __func__,\
|
||||
current->pid, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define DP_INFO_V(fmt, ...) \
|
||||
do { \
|
||||
if (drm_debug_enabled(DRM_UT_KMS)) \
|
||||
DRM_INFO("[msm-dp-info][%-4d]"fmt, current->pid, \
|
||||
##__VA_ARGS__); \
|
||||
else \
|
||||
pr_info("[drm:%s][msm-dp-info][%-4d]"fmt, __func__, \
|
||||
current->pid, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define DP_WARN_V(fmt, ...) \
|
||||
pr_warn("[drm:%s][msm-dp-warn][%-4d]"fmt, __func__, \
|
||||
current->pid, ##__VA_ARGS__)
|
||||
|
||||
#define DP_WARN_RATELIMITED_V(fmt, ...) \
|
||||
pr_warn_ratelimited("[drm:%s][msm-dp-warn][%-4d]"fmt, __func__, \
|
||||
current->pid, ##__VA_ARGS__)
|
||||
|
||||
#define DP_ERR_V(fmt, ...) \
|
||||
pr_err("[drm:%s][msm-dp-err][%-4d]"fmt, __func__, \
|
||||
current->pid, ##__VA_ARGS__)
|
||||
|
||||
#define DP_ERR_RATELIMITED_V(fmt, ...) \
|
||||
pr_err_ratelimited("[drm:%s][msm-dp-err][%-4d]"fmt, __func__, \
|
||||
current->pid, ##__VA_ARGS__)
|
||||
|
||||
#define DEFAULT_DISCONNECT_DELAY_MS 0
|
||||
#define MAX_DISCONNECT_DELAY_MS 10000
|
||||
#define DEFAULT_CONNECT_NOTIFICATION_DELAY_MS 150
|
||||
#define MAX_CONNECT_NOTIFICATION_DELAY_MS 5000
|
||||
|
||||
/**
|
||||
* struct dp_debug
|
||||
* @sim_mode: specifies whether sim mode enabled
|
||||
* @psm_enabled: specifies whether psm enabled
|
||||
* @hdcp_disabled: specifies if hdcp is disabled
|
||||
* @hdcp_wait_sink_sync: used to wait for sink synchronization before HDCP auth
|
||||
* @tpg_pattern: selects tpg pattern on the controller
|
||||
* @max_pclk_khz: max pclk supported
|
||||
* @force_encryption: enable/disable forced encryption for HDCP 2.2
|
||||
* @skip_uevent: skip hotplug uevent to the user space
|
||||
* @hdcp_status: string holding hdcp status information
|
||||
* @mst_sim_add_con: specifies whether new sim connector is to be added
|
||||
* @mst_sim_remove_con: specifies whether sim connector is to be removed
|
||||
* @mst_sim_remove_con_id: specifies id of sim connector to be removed
|
||||
* @connect_notification_delay_ms: time (in ms) to wait for any attention
|
||||
* messages before sending the connect notification uevent
|
||||
* @disconnect_delay_ms: time (in ms) to wait before turning off the mainlink
|
||||
* in response to HPD low of cable disconnect event
|
||||
*/
|
||||
struct dp_debug {
|
||||
bool sim_mode;
|
||||
bool psm_enabled;
|
||||
bool hdcp_disabled;
|
||||
bool hdcp_wait_sink_sync;
|
||||
u32 tpg_pattern;
|
||||
u32 max_pclk_khz;
|
||||
bool force_encryption;
|
||||
bool skip_uevent;
|
||||
char hdcp_status[SZ_128];
|
||||
bool mst_sim_add_con;
|
||||
bool mst_sim_remove_con;
|
||||
int mst_sim_remove_con_id;
|
||||
unsigned long connect_notification_delay_ms;
|
||||
u32 disconnect_delay_ms;
|
||||
|
||||
void (*abort)(struct dp_debug *dp_debug);
|
||||
void (*set_mst_con)(struct dp_debug *dp_debug, int con_id);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dp_debug_in
|
||||
* @dev: device instance of the caller
|
||||
* @panel: instance of panel module
|
||||
* @hpd: instance of hpd module
|
||||
* @link: instance of link module
|
||||
* @aux: instance of aux module
|
||||
* @connector: double pointer to display connector
|
||||
* @catalog: instance of catalog module
|
||||
* @parser: instance of parser module
|
||||
* @ctrl: instance of controller module
|
||||
* @pll: instance of pll module
|
||||
* @display: instance of display module
|
||||
*/
|
||||
struct dp_debug_in {
|
||||
struct device *dev;
|
||||
struct dp_panel *panel;
|
||||
struct dp_hpd *hpd;
|
||||
struct dp_link *link;
|
||||
struct dp_aux *aux;
|
||||
struct drm_connector **connector;
|
||||
struct dp_catalog *catalog;
|
||||
struct dp_parser *parser;
|
||||
struct dp_ctrl *ctrl;
|
||||
struct dp_pll *pll;
|
||||
struct dp_display *display;
|
||||
};
|
||||
|
||||
/**
|
||||
* dp_debug_get() - configure and get the DisplayPlot debug module data
|
||||
*
|
||||
* @in: input structure containing data to initialize the debug module
|
||||
* return: pointer to allocated debug module data
|
||||
*
|
||||
* This function sets up the debug module and provides a way
|
||||
* for debugfs input to be communicated with existing modules
|
||||
*/
|
||||
struct dp_debug *dp_debug_get(struct dp_debug_in *in);
|
||||
|
||||
/**
|
||||
* dp_debug_put()
|
||||
*
|
||||
* Cleans up dp_debug instance
|
||||
*
|
||||
* @dp_debug: instance of dp_debug
|
||||
*/
|
||||
void dp_debug_put(struct dp_debug *dp_debug);
|
||||
#endif /* _DP_DEBUG_H_ */
|
3993
qcom/opensource/display-drivers/msm/dp/dp_display.c
Normal file
3993
qcom/opensource/display-drivers/msm/dp/dp_display.c
Normal file
File diff suppressed because it is too large
Load Diff
144
qcom/opensource/display-drivers/msm/dp/dp_display.h
Normal file
144
qcom/opensource/display-drivers/msm/dp/dp_display.h
Normal file
@ -0,0 +1,144 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2021-2023, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _DP_DISPLAY_H_
|
||||
#define _DP_DISPLAY_H_
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <drm/sde_drm.h>
|
||||
|
||||
#include "dp_panel.h"
|
||||
|
||||
|
||||
enum dp_drv_state {
|
||||
PM_DEFAULT,
|
||||
PM_SUSPEND,
|
||||
};
|
||||
|
||||
struct dp_mst_drm_cbs {
|
||||
void (*hpd)(void *display, bool hpd_status);
|
||||
void (*hpd_irq)(void *display);
|
||||
void (*set_drv_state)(void *dp_display,
|
||||
enum dp_drv_state mst_state);
|
||||
int (*set_mgr_state)(void *dp_display, bool state);
|
||||
void (*set_mst_mode_params)(void *dp_display, struct dp_display_mode *mode);
|
||||
};
|
||||
|
||||
struct dp_mst_drm_install_info {
|
||||
void *dp_mst_prv_info;
|
||||
const struct dp_mst_drm_cbs *cbs;
|
||||
};
|
||||
|
||||
struct dp_mst_caps {
|
||||
bool has_mst;
|
||||
u32 max_streams_supported;
|
||||
u32 max_dpcd_transaction_bytes;
|
||||
struct drm_dp_aux *drm_aux;
|
||||
};
|
||||
|
||||
struct dp_display {
|
||||
struct drm_device *drm_dev;
|
||||
struct dp_bridge *bridge;
|
||||
struct drm_connector *base_connector;
|
||||
void *base_dp_panel;
|
||||
bool is_sst_connected;
|
||||
bool is_mst_supported;
|
||||
bool dsc_cont_pps;
|
||||
u32 max_pclk_khz;
|
||||
void *dp_mst_prv_info;
|
||||
u32 max_mixer_count;
|
||||
u32 max_dsc_count;
|
||||
void *dp_ipc_log;
|
||||
void *dp_aux_ipc_log;
|
||||
|
||||
int (*enable)(struct dp_display *dp_display, void *panel);
|
||||
int (*post_enable)(struct dp_display *dp_display, void *panel);
|
||||
|
||||
int (*pre_disable)(struct dp_display *dp_display, void *panel);
|
||||
int (*disable)(struct dp_display *dp_display, void *panel);
|
||||
|
||||
int (*set_mode)(struct dp_display *dp_display, void *panel,
|
||||
struct dp_display_mode *mode);
|
||||
enum drm_mode_status (*validate_mode)(struct dp_display *dp_display,
|
||||
void *panel, struct drm_display_mode *mode,
|
||||
const struct msm_resource_caps_info *avail_res);
|
||||
int (*get_modes)(struct dp_display *dp_display, void *panel,
|
||||
struct dp_display_mode *dp_mode);
|
||||
int (*prepare)(struct dp_display *dp_display, void *panel);
|
||||
int (*unprepare)(struct dp_display *dp_display, void *panel);
|
||||
int (*request_irq)(struct dp_display *dp_display);
|
||||
struct dp_debug *(*get_debug)(struct dp_display *dp_display);
|
||||
void (*post_open)(struct dp_display *dp_display);
|
||||
int (*config_hdr)(struct dp_display *dp_display, void *panel,
|
||||
struct drm_msm_ext_hdr_metadata *hdr_meta,
|
||||
bool dhdr_update);
|
||||
int (*set_colorspace)(struct dp_display *dp_display, void *panel,
|
||||
u32 colorspace);
|
||||
int (*post_init)(struct dp_display *dp_display);
|
||||
int (*mst_install)(struct dp_display *dp_display,
|
||||
struct dp_mst_drm_install_info *mst_install_info);
|
||||
int (*mst_uninstall)(struct dp_display *dp_display);
|
||||
int (*mst_connector_install)(struct dp_display *dp_display,
|
||||
struct drm_connector *connector);
|
||||
int (*mst_connector_uninstall)(struct dp_display *dp_display,
|
||||
struct drm_connector *connector);
|
||||
int (*mst_connector_update_edid)(struct dp_display *dp_display,
|
||||
struct drm_connector *connector,
|
||||
struct edid *edid);
|
||||
int (*mst_connector_update_link_info)(struct dp_display *dp_display,
|
||||
struct drm_connector *connector);
|
||||
int (*mst_get_fixed_topology_port)(struct dp_display *dp_display,
|
||||
u32 strm_id, u32 *port_num);
|
||||
int (*get_mst_caps)(struct dp_display *dp_display,
|
||||
struct dp_mst_caps *mst_caps);
|
||||
int (*set_stream_info)(struct dp_display *dp_display, void *panel,
|
||||
u32 strm_id, u32 start_slot, u32 num_slots, u32 pbn,
|
||||
int vcpi);
|
||||
void (*convert_to_dp_mode)(struct dp_display *dp_display, void *panel,
|
||||
const struct drm_display_mode *drm_mode,
|
||||
struct dp_display_mode *dp_mode);
|
||||
int (*update_pps)(struct dp_display *dp_display,
|
||||
struct drm_connector *connector, char *pps_cmd);
|
||||
void (*wakeup_phy_layer)(struct dp_display *dp_display,
|
||||
bool wakeup);
|
||||
int (*get_available_dp_resources)(struct dp_display *dp_display,
|
||||
const struct msm_resource_caps_info *avail_res,
|
||||
struct msm_resource_caps_info *max_dp_avail_res);
|
||||
void (*clear_reservation)(struct dp_display *dp, struct dp_panel *panel);
|
||||
int (*get_mst_pbn_div)(struct dp_display *dp);
|
||||
};
|
||||
|
||||
void *get_ipc_log_context(void);
|
||||
|
||||
#if IS_ENABLED(CONFIG_DRM_MSM_DP)
|
||||
int dp_display_get_num_of_displays(void);
|
||||
int dp_display_get_displays(void **displays, int count);
|
||||
int dp_display_get_num_of_streams(void);
|
||||
int dp_display_mmrm_callback(struct mmrm_client_notifier_data *notifier_data);
|
||||
#else
|
||||
static inline int dp_display_get_num_of_displays(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline int dp_display_get_displays(void **displays, int count)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline int dp_display_get_num_of_streams(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline int dp_connector_update_pps(struct drm_connector *connector,
|
||||
char *pps_cmd, void *display)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline int dp_display_mmrm_callback(struct mmrm_client_notifier_data *notifier_data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_DRM_MSM_DP */
|
||||
#endif /* _DP_DISPLAY_H_ */
|
794
qcom/opensource/display-drivers/msm/dp/dp_drm.c
Normal file
794
qcom/opensource/display-drivers/msm/dp/dp_drm.c
Normal file
@ -0,0 +1,794 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
|
||||
#include "msm_drv.h"
|
||||
#include "msm_kms.h"
|
||||
#include "sde_connector.h"
|
||||
#include "dp_drm.h"
|
||||
#include "dp_mst_drm.h"
|
||||
#include "dp_debug.h"
|
||||
|
||||
#define DP_MST_DEBUG(fmt, ...) DP_DEBUG(fmt, ##__VA_ARGS__)
|
||||
|
||||
#define to_dp_bridge(x) container_of((x), struct dp_bridge, base)
|
||||
|
||||
void convert_to_drm_mode(const struct dp_display_mode *dp_mode,
|
||||
struct drm_display_mode *drm_mode)
|
||||
{
|
||||
u32 flags = 0;
|
||||
|
||||
memset(drm_mode, 0, sizeof(*drm_mode));
|
||||
|
||||
drm_mode->hdisplay = dp_mode->timing.h_active;
|
||||
drm_mode->hsync_start = drm_mode->hdisplay +
|
||||
dp_mode->timing.h_front_porch;
|
||||
drm_mode->hsync_end = drm_mode->hsync_start +
|
||||
dp_mode->timing.h_sync_width;
|
||||
drm_mode->htotal = drm_mode->hsync_end + dp_mode->timing.h_back_porch;
|
||||
drm_mode->hskew = dp_mode->timing.h_skew;
|
||||
|
||||
drm_mode->vdisplay = dp_mode->timing.v_active;
|
||||
drm_mode->vsync_start = drm_mode->vdisplay +
|
||||
dp_mode->timing.v_front_porch;
|
||||
drm_mode->vsync_end = drm_mode->vsync_start +
|
||||
dp_mode->timing.v_sync_width;
|
||||
drm_mode->vtotal = drm_mode->vsync_end + dp_mode->timing.v_back_porch;
|
||||
|
||||
drm_mode->clock = dp_mode->timing.pixel_clk_khz;
|
||||
|
||||
if (dp_mode->timing.h_active_low)
|
||||
flags |= DRM_MODE_FLAG_NHSYNC;
|
||||
else
|
||||
flags |= DRM_MODE_FLAG_PHSYNC;
|
||||
|
||||
if (dp_mode->timing.v_active_low)
|
||||
flags |= DRM_MODE_FLAG_NVSYNC;
|
||||
else
|
||||
flags |= DRM_MODE_FLAG_PVSYNC;
|
||||
|
||||
drm_mode->flags = flags;
|
||||
|
||||
drm_mode->type = 0x48;
|
||||
drm_mode_set_name(drm_mode);
|
||||
}
|
||||
|
||||
static int dp_bridge_attach(struct drm_bridge *dp_bridge,
|
||||
enum drm_bridge_attach_flags flags)
|
||||
{
|
||||
struct dp_bridge *bridge = to_dp_bridge(dp_bridge);
|
||||
|
||||
if (!dp_bridge) {
|
||||
DP_ERR("Invalid params\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
DP_DEBUG("[%d] attached\n", bridge->id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dp_bridge_pre_enable(struct drm_bridge *drm_bridge)
|
||||
{
|
||||
int rc = 0;
|
||||
struct dp_bridge *bridge;
|
||||
struct dp_display *dp;
|
||||
|
||||
if (!drm_bridge) {
|
||||
DP_ERR("Invalid params\n");
|
||||
return;
|
||||
}
|
||||
|
||||
bridge = to_dp_bridge(drm_bridge);
|
||||
dp = bridge->display;
|
||||
|
||||
if (!bridge->connector) {
|
||||
DP_ERR("Invalid connector\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!bridge->dp_panel) {
|
||||
DP_ERR("Invalid dp_panel\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* By this point mode should have been validated through mode_fixup */
|
||||
rc = dp->set_mode(dp, bridge->dp_panel, &bridge->dp_mode);
|
||||
if (rc) {
|
||||
DP_ERR("[%d] failed to perform a mode set, rc=%d\n",
|
||||
bridge->id, rc);
|
||||
return;
|
||||
}
|
||||
|
||||
rc = dp->prepare(dp, bridge->dp_panel);
|
||||
if (rc) {
|
||||
DP_ERR("[%d] DP display prepare failed, rc=%d\n",
|
||||
bridge->id, rc);
|
||||
return;
|
||||
}
|
||||
|
||||
/* for SST force stream id, start slot and total slots to 0 */
|
||||
dp->set_stream_info(dp, bridge->dp_panel, 0, 0, 0, 0, 0);
|
||||
|
||||
rc = dp->enable(dp, bridge->dp_panel);
|
||||
if (rc)
|
||||
DP_ERR("[%d] DP display enable failed, rc=%d\n",
|
||||
bridge->id, rc);
|
||||
}
|
||||
|
||||
static void dp_bridge_enable(struct drm_bridge *drm_bridge)
|
||||
{
|
||||
int rc = 0;
|
||||
struct dp_bridge *bridge;
|
||||
struct dp_display *dp;
|
||||
|
||||
if (!drm_bridge) {
|
||||
DP_ERR("Invalid params\n");
|
||||
return;
|
||||
}
|
||||
|
||||
bridge = to_dp_bridge(drm_bridge);
|
||||
if (!bridge->connector) {
|
||||
DP_ERR("Invalid connector\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!bridge->dp_panel) {
|
||||
DP_ERR("Invalid dp_panel\n");
|
||||
return;
|
||||
}
|
||||
|
||||
dp = bridge->display;
|
||||
|
||||
rc = dp->post_enable(dp, bridge->dp_panel);
|
||||
if (rc)
|
||||
DP_ERR("[%d] DP display post enable failed, rc=%d\n",
|
||||
bridge->id, rc);
|
||||
}
|
||||
|
||||
static void dp_bridge_disable(struct drm_bridge *drm_bridge)
|
||||
{
|
||||
int rc = 0;
|
||||
struct dp_bridge *bridge;
|
||||
struct dp_display *dp;
|
||||
|
||||
if (!drm_bridge) {
|
||||
DP_ERR("Invalid params\n");
|
||||
return;
|
||||
}
|
||||
|
||||
bridge = to_dp_bridge(drm_bridge);
|
||||
if (!bridge->connector) {
|
||||
DP_ERR("Invalid connector\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!bridge->dp_panel) {
|
||||
DP_ERR("Invalid dp_panel\n");
|
||||
return;
|
||||
}
|
||||
|
||||
dp = bridge->display;
|
||||
|
||||
if (!dp) {
|
||||
DP_ERR("dp is null\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (dp)
|
||||
sde_connector_helper_bridge_disable(bridge->connector);
|
||||
|
||||
rc = dp->pre_disable(dp, bridge->dp_panel);
|
||||
if (rc) {
|
||||
DP_ERR("[%d] DP display pre disable failed, rc=%d\n",
|
||||
bridge->id, rc);
|
||||
}
|
||||
}
|
||||
|
||||
static void dp_bridge_post_disable(struct drm_bridge *drm_bridge)
|
||||
{
|
||||
int rc = 0;
|
||||
struct dp_bridge *bridge;
|
||||
struct dp_display *dp;
|
||||
|
||||
if (!drm_bridge) {
|
||||
DP_ERR("Invalid params\n");
|
||||
return;
|
||||
}
|
||||
|
||||
bridge = to_dp_bridge(drm_bridge);
|
||||
if (!bridge->connector) {
|
||||
DP_ERR("Invalid connector\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!bridge->dp_panel) {
|
||||
DP_ERR("Invalid dp_panel\n");
|
||||
return;
|
||||
}
|
||||
|
||||
dp = bridge->display;
|
||||
|
||||
rc = dp->disable(dp, bridge->dp_panel);
|
||||
if (rc) {
|
||||
DP_ERR("[%d] DP display disable failed, rc=%d\n",
|
||||
bridge->id, rc);
|
||||
return;
|
||||
}
|
||||
|
||||
rc = dp->unprepare(dp, bridge->dp_panel);
|
||||
if (rc) {
|
||||
DP_ERR("[%d] DP display unprepare failed, rc=%d\n",
|
||||
bridge->id, rc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void dp_bridge_mode_set(struct drm_bridge *drm_bridge,
|
||||
const struct drm_display_mode *mode,
|
||||
const struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
struct dp_bridge *bridge;
|
||||
struct dp_display *dp;
|
||||
|
||||
if (!drm_bridge || !mode || !adjusted_mode) {
|
||||
DP_ERR("Invalid params\n");
|
||||
return;
|
||||
}
|
||||
|
||||
bridge = to_dp_bridge(drm_bridge);
|
||||
if (!bridge->connector) {
|
||||
DP_ERR("Invalid connector\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!bridge->dp_panel) {
|
||||
DP_ERR("Invalid dp_panel\n");
|
||||
return;
|
||||
}
|
||||
|
||||
dp = bridge->display;
|
||||
|
||||
dp->convert_to_dp_mode(dp, bridge->dp_panel, adjusted_mode,
|
||||
&bridge->dp_mode);
|
||||
|
||||
dp->clear_reservation(dp, bridge->dp_panel);
|
||||
}
|
||||
|
||||
static bool dp_bridge_mode_fixup(struct drm_bridge *drm_bridge,
|
||||
const struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
bool ret = true;
|
||||
struct dp_display_mode dp_mode;
|
||||
struct dp_bridge *bridge;
|
||||
struct dp_display *dp;
|
||||
|
||||
if (!drm_bridge || !mode || !adjusted_mode) {
|
||||
DP_ERR("Invalid params\n");
|
||||
ret = false;
|
||||
goto end;
|
||||
}
|
||||
|
||||
bridge = to_dp_bridge(drm_bridge);
|
||||
if (!bridge->connector) {
|
||||
DP_ERR("Invalid connector\n");
|
||||
ret = false;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!bridge->dp_panel) {
|
||||
DP_ERR("Invalid dp_panel\n");
|
||||
ret = false;
|
||||
goto end;
|
||||
}
|
||||
|
||||
dp = bridge->display;
|
||||
|
||||
dp->convert_to_dp_mode(dp, bridge->dp_panel, mode, &dp_mode);
|
||||
dp->clear_reservation(dp, bridge->dp_panel);
|
||||
convert_to_drm_mode(&dp_mode, adjusted_mode);
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct drm_bridge_funcs dp_bridge_ops = {
|
||||
.attach = dp_bridge_attach,
|
||||
.mode_fixup = dp_bridge_mode_fixup,
|
||||
.pre_enable = dp_bridge_pre_enable,
|
||||
.enable = dp_bridge_enable,
|
||||
.disable = dp_bridge_disable,
|
||||
.post_disable = dp_bridge_post_disable,
|
||||
.mode_set = dp_bridge_mode_set,
|
||||
};
|
||||
|
||||
int dp_connector_add_custom_mode(struct drm_connector *conn, struct dp_display_mode *dp_mode)
|
||||
{
|
||||
struct drm_display_mode *m, drm_mode;
|
||||
|
||||
memset(&drm_mode, 0x0, sizeof(drm_mode));
|
||||
convert_to_drm_mode(dp_mode, &drm_mode);
|
||||
m = drm_mode_duplicate(conn->dev, &drm_mode);
|
||||
if (!m) {
|
||||
DP_ERR("failed to add mode %ux%u\n", drm_mode.hdisplay, drm_mode.vdisplay);
|
||||
return 0;
|
||||
}
|
||||
m->width_mm = conn->display_info.width_mm;
|
||||
m->height_mm = conn->display_info.height_mm;
|
||||
drm_mode_probed_add(conn, m);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void init_failsafe_mode(struct dp_display_mode *dp_mode)
|
||||
{
|
||||
static const struct dp_panel_info fail_safe = {
|
||||
.h_active = 640,
|
||||
.v_active = 480,
|
||||
.h_back_porch = 48,
|
||||
.h_front_porch = 16,
|
||||
.h_sync_width = 96,
|
||||
.h_active_low = 1,
|
||||
.v_back_porch = 33,
|
||||
.v_front_porch = 10,
|
||||
.v_sync_width = 2,
|
||||
.v_active_low = 1,
|
||||
.h_skew = 0,
|
||||
.refresh_rate = 60,
|
||||
.pixel_clk_khz = 25175,
|
||||
.bpp = 24,
|
||||
.widebus_en = true,
|
||||
};
|
||||
|
||||
memcpy(&dp_mode->timing, &fail_safe, sizeof(fail_safe));
|
||||
}
|
||||
|
||||
int dp_connector_config_hdr(struct drm_connector *connector, void *display,
|
||||
struct sde_connector_state *c_state)
|
||||
{
|
||||
struct dp_display *dp = display;
|
||||
struct sde_connector *sde_conn;
|
||||
|
||||
if (!display || !c_state || !connector) {
|
||||
DP_ERR("invalid params\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sde_conn = to_sde_connector(connector);
|
||||
if (!sde_conn->drv_panel) {
|
||||
DP_ERR("invalid dp panel\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return dp->config_hdr(dp, sde_conn->drv_panel, &c_state->hdr_meta,
|
||||
c_state->dyn_hdr_meta.dynamic_hdr_update);
|
||||
}
|
||||
|
||||
int dp_connector_set_colorspace(struct drm_connector *connector,
|
||||
void *display)
|
||||
{
|
||||
struct dp_display *dp_display = display;
|
||||
struct sde_connector *sde_conn;
|
||||
|
||||
if (!dp_display || !connector)
|
||||
return -EINVAL;
|
||||
|
||||
sde_conn = to_sde_connector(connector);
|
||||
if (!sde_conn->drv_panel) {
|
||||
pr_err("invalid dp panel\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return dp_display->set_colorspace(dp_display,
|
||||
sde_conn->drv_panel, connector->state->colorspace);
|
||||
}
|
||||
|
||||
int dp_connector_post_init(struct drm_connector *connector, void *display)
|
||||
{
|
||||
int rc;
|
||||
struct dp_display *dp_display = display;
|
||||
struct sde_connector *sde_conn;
|
||||
|
||||
if (!dp_display || !connector)
|
||||
return -EINVAL;
|
||||
|
||||
dp_display->base_connector = connector;
|
||||
dp_display->bridge->connector = connector;
|
||||
|
||||
if (dp_display->post_init) {
|
||||
rc = dp_display->post_init(dp_display);
|
||||
if (rc)
|
||||
goto end;
|
||||
}
|
||||
|
||||
sde_conn = to_sde_connector(connector);
|
||||
dp_display->bridge->dp_panel = sde_conn->drv_panel;
|
||||
|
||||
rc = dp_mst_init(dp_display);
|
||||
|
||||
if (dp_display->dsc_cont_pps)
|
||||
sde_conn->ops.update_pps = NULL;
|
||||
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int dp_connector_get_mode_info(struct drm_connector *connector,
|
||||
const struct drm_display_mode *drm_mode,
|
||||
struct msm_sub_mode *sub_mode,
|
||||
struct msm_mode_info *mode_info,
|
||||
void *display, const struct msm_resource_caps_info *avail_res)
|
||||
{
|
||||
const u32 single_intf = 1;
|
||||
const u32 no_enc = 0;
|
||||
struct msm_display_topology *topology;
|
||||
struct sde_connector *sde_conn;
|
||||
struct dp_panel *dp_panel;
|
||||
struct dp_display_mode dp_mode;
|
||||
struct dp_display *dp_disp = display;
|
||||
struct msm_drm_private *priv;
|
||||
struct msm_resource_caps_info avail_dp_res;
|
||||
int rc = 0;
|
||||
|
||||
if (!drm_mode || !mode_info || !avail_res ||
|
||||
!avail_res->max_mixer_width || !connector || !display ||
|
||||
!connector->dev || !connector->dev->dev_private) {
|
||||
DP_ERR("invalid params\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(mode_info, 0, sizeof(*mode_info));
|
||||
|
||||
sde_conn = to_sde_connector(connector);
|
||||
dp_panel = sde_conn->drv_panel;
|
||||
priv = connector->dev->dev_private;
|
||||
|
||||
topology = &mode_info->topology;
|
||||
|
||||
rc = dp_disp->get_available_dp_resources(dp_disp, avail_res,
|
||||
&avail_dp_res);
|
||||
if (rc) {
|
||||
DP_ERR("error getting max dp resources. rc:%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = msm_get_mixer_count(priv, drm_mode, &avail_dp_res,
|
||||
&topology->num_lm);
|
||||
if (rc) {
|
||||
DP_ERR("error getting mixer count. rc:%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
/* reset dp connector lm_mask for every connection event and
|
||||
* this will get re-populated in resource manager based on
|
||||
* resolution and topology of dp display.
|
||||
*/
|
||||
sde_conn->lm_mask = 0;
|
||||
|
||||
topology->num_enc = no_enc;
|
||||
topology->num_intf = single_intf;
|
||||
|
||||
mode_info->frame_rate = drm_mode_vrefresh(drm_mode);
|
||||
mode_info->vtotal = drm_mode->vtotal;
|
||||
|
||||
mode_info->wide_bus_en = dp_panel->widebus_en;
|
||||
|
||||
dp_disp->convert_to_dp_mode(dp_disp, dp_panel, drm_mode, &dp_mode);
|
||||
|
||||
if (dp_mode.timing.comp_info.enabled) {
|
||||
memcpy(&mode_info->comp_info,
|
||||
&dp_mode.timing.comp_info,
|
||||
sizeof(mode_info->comp_info));
|
||||
|
||||
topology->num_enc = topology->num_lm;
|
||||
topology->comp_type = mode_info->comp_info.comp_type;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dp_connector_get_info(struct drm_connector *connector,
|
||||
struct msm_display_info *info, void *data)
|
||||
{
|
||||
struct dp_display *display = data;
|
||||
|
||||
if (!info || !display || !display->drm_dev) {
|
||||
DP_ERR("invalid params\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
info->intf_type = DRM_MODE_CONNECTOR_DisplayPort;
|
||||
|
||||
info->num_of_h_tiles = 1;
|
||||
info->h_tile_instance[0] = 0;
|
||||
info->is_connected = display->is_sst_connected;
|
||||
info->curr_panel_mode = MSM_DISPLAY_VIDEO_MODE;
|
||||
info->capabilities = MSM_DISPLAY_CAP_VID_MODE | MSM_DISPLAY_CAP_EDID |
|
||||
MSM_DISPLAY_CAP_HOT_PLUG;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum drm_connector_status dp_connector_detect(struct drm_connector *conn,
|
||||
bool force,
|
||||
void *display)
|
||||
{
|
||||
enum drm_connector_status status = connector_status_unknown;
|
||||
struct msm_display_info info;
|
||||
int rc;
|
||||
|
||||
if (!conn || !display)
|
||||
return status;
|
||||
|
||||
/* get display dp_info */
|
||||
memset(&info, 0x0, sizeof(info));
|
||||
rc = dp_connector_get_info(conn, &info, display);
|
||||
if (rc) {
|
||||
DP_ERR("failed to get display info, rc=%d\n", rc);
|
||||
return connector_status_disconnected;
|
||||
}
|
||||
|
||||
if (info.capabilities & MSM_DISPLAY_CAP_HOT_PLUG)
|
||||
status = (info.is_connected ? connector_status_connected :
|
||||
connector_status_disconnected);
|
||||
else
|
||||
status = connector_status_connected;
|
||||
|
||||
conn->display_info.width_mm = info.width_mm;
|
||||
conn->display_info.height_mm = info.height_mm;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void dp_connector_post_open(struct drm_connector *connector, void *display)
|
||||
{
|
||||
struct dp_display *dp;
|
||||
|
||||
if (!display) {
|
||||
DP_ERR("invalid input\n");
|
||||
return;
|
||||
}
|
||||
|
||||
dp = display;
|
||||
|
||||
if (dp->post_open)
|
||||
dp->post_open(dp);
|
||||
}
|
||||
|
||||
int dp_connector_atomic_check(struct drm_connector *connector,
|
||||
void *display,
|
||||
struct drm_atomic_state *a_state)
|
||||
{
|
||||
struct sde_connector *sde_conn;
|
||||
struct drm_connector_state *old_state;
|
||||
struct drm_connector_state *c_state;
|
||||
|
||||
if (!connector || !display || !a_state)
|
||||
return -EINVAL;
|
||||
|
||||
c_state = drm_atomic_get_new_connector_state(a_state, connector);
|
||||
old_state =
|
||||
drm_atomic_get_old_connector_state(a_state, connector);
|
||||
|
||||
if (!old_state || !c_state)
|
||||
return -EINVAL;
|
||||
|
||||
sde_conn = to_sde_connector(connector);
|
||||
|
||||
/*
|
||||
* Marking the colorspace has been changed
|
||||
* the flag shall be checked in the pre_kickoff
|
||||
* to configure the new colorspace in HW
|
||||
*/
|
||||
if (c_state->colorspace != old_state->colorspace) {
|
||||
DP_DEBUG("colorspace has been updated\n");
|
||||
sde_conn->colorspace_updated = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dp_connector_get_modes(struct drm_connector *connector,
|
||||
void *display, const struct msm_resource_caps_info *avail_res)
|
||||
{
|
||||
int rc = 0;
|
||||
struct dp_display *dp;
|
||||
struct dp_display_mode *dp_mode = NULL;
|
||||
struct sde_connector *sde_conn;
|
||||
|
||||
if (!connector || !display)
|
||||
return 0;
|
||||
|
||||
sde_conn = to_sde_connector(connector);
|
||||
if (!sde_conn->drv_panel) {
|
||||
DP_ERR("invalid dp panel\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
dp = display;
|
||||
|
||||
dp_mode = kzalloc(sizeof(*dp_mode), GFP_KERNEL);
|
||||
if (!dp_mode)
|
||||
return 0;
|
||||
|
||||
/* pluggable case assumes EDID is read when HPD */
|
||||
if (dp->is_sst_connected) {
|
||||
/*
|
||||
* 1. for test request, rc = 1, and dp_mode will have test mode populated
|
||||
* 2. During normal operation, dp_mode will be untouched
|
||||
* a. if mode query succeeds rc >= 0, valid modes will be added to connector
|
||||
* b. if edid read failed, then connector mode list will be empty and rc <= 0
|
||||
*/
|
||||
rc = dp->get_modes(dp, sde_conn->drv_panel, dp_mode);
|
||||
if (!rc) {
|
||||
DP_WARN("failed to get DP sink modes, adding failsafe");
|
||||
init_failsafe_mode(dp_mode);
|
||||
}
|
||||
if (dp_mode->timing.pixel_clk_khz) /* valid DP mode */
|
||||
rc = dp_connector_add_custom_mode(connector, dp_mode);
|
||||
} else {
|
||||
DP_ERR("No sink connected\n");
|
||||
}
|
||||
kfree(dp_mode);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int dp_drm_bridge_init(void *data, struct drm_encoder *encoder,
|
||||
u32 max_mixer_count, u32 max_dsc_count)
|
||||
{
|
||||
int rc = 0;
|
||||
struct dp_bridge *bridge;
|
||||
struct drm_device *dev;
|
||||
struct dp_display *display = data;
|
||||
struct msm_drm_private *priv = NULL;
|
||||
|
||||
bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
|
||||
if (!bridge) {
|
||||
rc = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
dev = display->drm_dev;
|
||||
bridge->display = display;
|
||||
bridge->base.funcs = &dp_bridge_ops;
|
||||
bridge->base.encoder = encoder;
|
||||
|
||||
priv = dev->dev_private;
|
||||
|
||||
rc = drm_bridge_attach(encoder, &bridge->base, NULL, 0);
|
||||
if (rc) {
|
||||
DP_ERR("failed to attach bridge, rc=%d\n", rc);
|
||||
goto error_free_bridge;
|
||||
}
|
||||
|
||||
rc = display->request_irq(display);
|
||||
if (rc) {
|
||||
DP_ERR("request_irq failed, rc=%d\n", rc);
|
||||
goto error_free_bridge;
|
||||
}
|
||||
|
||||
priv->bridges[priv->num_bridges++] = &bridge->base;
|
||||
display->bridge = bridge;
|
||||
display->max_mixer_count = max_mixer_count;
|
||||
display->max_dsc_count = max_dsc_count;
|
||||
|
||||
return 0;
|
||||
error_free_bridge:
|
||||
kfree(bridge);
|
||||
error:
|
||||
return rc;
|
||||
}
|
||||
|
||||
void dp_drm_bridge_deinit(void *data)
|
||||
{
|
||||
struct dp_display *display = data;
|
||||
struct dp_bridge *bridge = display->bridge;
|
||||
|
||||
kfree(bridge);
|
||||
}
|
||||
|
||||
enum drm_mode_status dp_connector_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode, void *display,
|
||||
const struct msm_resource_caps_info *avail_res)
|
||||
{
|
||||
int rc = 0, vrefresh;
|
||||
struct dp_display *dp_disp;
|
||||
struct sde_connector *sde_conn;
|
||||
struct msm_resource_caps_info avail_dp_res;
|
||||
struct dp_panel *dp_panel;
|
||||
|
||||
if (!mode || !display || !connector) {
|
||||
DP_ERR("invalid params\n");
|
||||
return MODE_ERROR;
|
||||
}
|
||||
|
||||
sde_conn = to_sde_connector(connector);
|
||||
if (!sde_conn->drv_panel) {
|
||||
DP_ERR("invalid dp panel\n");
|
||||
return MODE_ERROR;
|
||||
}
|
||||
|
||||
dp_disp = display;
|
||||
dp_panel = sde_conn->drv_panel;
|
||||
|
||||
vrefresh = drm_mode_vrefresh(mode);
|
||||
|
||||
rc = dp_disp->get_available_dp_resources(dp_disp, avail_res,
|
||||
&avail_dp_res);
|
||||
if (rc) {
|
||||
DP_ERR("error getting max dp resources. rc:%d\n", rc);
|
||||
return MODE_ERROR;
|
||||
}
|
||||
|
||||
/* As per spec, failsafe mode should always be present */
|
||||
if ((mode->hdisplay == 640) && (mode->vdisplay == 480) && (mode->clock == 25175))
|
||||
goto validate_mode;
|
||||
|
||||
if (dp_panel->mode_override && (mode->hdisplay != dp_panel->hdisplay ||
|
||||
mode->vdisplay != dp_panel->vdisplay ||
|
||||
vrefresh != dp_panel->vrefresh ||
|
||||
mode->picture_aspect_ratio != dp_panel->aspect_ratio))
|
||||
return MODE_BAD;
|
||||
|
||||
validate_mode:
|
||||
return dp_disp->validate_mode(dp_disp, sde_conn->drv_panel,
|
||||
mode, &avail_dp_res);
|
||||
}
|
||||
|
||||
int dp_connector_update_pps(struct drm_connector *connector,
|
||||
char *pps_cmd, void *display)
|
||||
{
|
||||
struct dp_display *dp_disp;
|
||||
struct sde_connector *sde_conn;
|
||||
|
||||
if (!display || !connector) {
|
||||
DP_ERR("invalid params\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sde_conn = to_sde_connector(connector);
|
||||
if (!sde_conn->drv_panel) {
|
||||
DP_ERR("invalid dp panel\n");
|
||||
return MODE_ERROR;
|
||||
}
|
||||
|
||||
dp_disp = display;
|
||||
return dp_disp->update_pps(dp_disp, connector, pps_cmd);
|
||||
}
|
||||
|
||||
int dp_connector_install_properties(void *display, struct drm_connector *conn)
|
||||
{
|
||||
struct dp_display *dp_display = display;
|
||||
struct drm_connector *base_conn;
|
||||
int rc;
|
||||
|
||||
if (!display || !conn) {
|
||||
DP_ERR("invalid params\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
base_conn = dp_display->base_connector;
|
||||
|
||||
/*
|
||||
* Create the property on the base connector during probe time and then
|
||||
* attach the same property onto new connector objects created for MST
|
||||
*/
|
||||
if (!base_conn->colorspace_property) {
|
||||
/* This is the base connector. create the drm property */
|
||||
rc = drm_mode_create_dp_colorspace_property(base_conn);
|
||||
if (rc)
|
||||
return rc;
|
||||
} else {
|
||||
conn->colorspace_property = base_conn->colorspace_property;
|
||||
}
|
||||
|
||||
drm_object_attach_property(&conn->base, conn->colorspace_property, 0);
|
||||
|
||||
return 0;
|
||||
}
|
275
qcom/opensource/display-drivers/msm/dp/dp_drm.h
Normal file
275
qcom/opensource/display-drivers/msm/dp/dp_drm.h
Normal file
@ -0,0 +1,275 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _DP_DRM_H_
|
||||
#define _DP_DRM_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_bridge.h>
|
||||
|
||||
#include "msm_drv.h"
|
||||
#include "dp_display.h"
|
||||
|
||||
struct dp_bridge {
|
||||
struct drm_bridge base;
|
||||
u32 id;
|
||||
|
||||
struct drm_connector *connector;
|
||||
struct dp_display *display;
|
||||
struct dp_display_mode dp_mode;
|
||||
void *dp_panel;
|
||||
};
|
||||
|
||||
|
||||
#if IS_ENABLED(CONFIG_DRM_MSM_DP)
|
||||
/**
|
||||
* dp_connector_config_hdr - callback to configure HDR
|
||||
* @connector: Pointer to drm connector structure
|
||||
* @display: Pointer to private display handle
|
||||
* @c_state: connect state data
|
||||
* Returns: Zero on success
|
||||
*/
|
||||
int dp_connector_config_hdr(struct drm_connector *connector,
|
||||
void *display,
|
||||
struct sde_connector_state *c_state);
|
||||
|
||||
/**
|
||||
* dp_connector_atomic_check - callback to perform atomic
|
||||
* check for DP
|
||||
* @connector: Pointer to drm connector structure
|
||||
* @display: Pointer to private display handle
|
||||
* @c_state: connect state data
|
||||
* Returns: Zero on success
|
||||
*/
|
||||
int dp_connector_atomic_check(struct drm_connector *connector,
|
||||
void *display,
|
||||
struct drm_atomic_state *state);
|
||||
|
||||
/**
|
||||
* dp_connector_set_colorspace - callback to set new colorspace
|
||||
* @connector: Pointer to drm connector structure
|
||||
* @display: Pointer to private display handle
|
||||
* Returns: Zero on success
|
||||
*/
|
||||
int dp_connector_set_colorspace(struct drm_connector *connector,
|
||||
void *display);
|
||||
|
||||
/**
|
||||
* dp_connector_post_init - callback to perform additional initialization steps
|
||||
* @connector: Pointer to drm connector structure
|
||||
* @display: Pointer to private display handle
|
||||
* Returns: Zero on success
|
||||
*/
|
||||
int dp_connector_post_init(struct drm_connector *connector, void *display);
|
||||
|
||||
/**
|
||||
* dp_connector_detect - callback to determine if connector is connected
|
||||
* @connector: Pointer to drm connector structure
|
||||
* @force: Force detect setting from drm framework
|
||||
* @display: Pointer to private display handle
|
||||
* Returns: Connector 'is connected' status
|
||||
*/
|
||||
enum drm_connector_status dp_connector_detect(struct drm_connector *conn,
|
||||
bool force,
|
||||
void *display);
|
||||
|
||||
/**
|
||||
* dp_connector_get_modes - callback to add drm modes via drm_mode_probed_add()
|
||||
* @connector: Pointer to drm connector structure
|
||||
* @display: Pointer to private display handle
|
||||
* @avail_res: Pointer with curr available resources
|
||||
* Returns: Number of modes added
|
||||
*/
|
||||
int dp_connector_get_modes(struct drm_connector *connector,
|
||||
void *display, const struct msm_resource_caps_info *avail_res);
|
||||
|
||||
/**
|
||||
* dp_connector_mode_valid - callback to determine if specified mode is valid
|
||||
* @connector: Pointer to drm connector structure
|
||||
* @mode: Pointer to drm mode structure
|
||||
* @display: Pointer to private display handle
|
||||
* @avail_res: Pointer with curr available resources
|
||||
* Returns: Validity status for specified mode
|
||||
*/
|
||||
enum drm_mode_status dp_connector_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode,
|
||||
void *display, const struct msm_resource_caps_info *avail_res);
|
||||
|
||||
/**
|
||||
* dp_connector_get_mode_info - retrieve information of the mode selected
|
||||
* @connector: Pointer to drm connector structure
|
||||
* @drm_mode: Display mode set for the display
|
||||
* @mode_info: Out parameter. Information of the mode
|
||||
* @sub_mode: Additional mode info to drm display mode
|
||||
* @display: Pointer to private display structure
|
||||
* @avail_res: Pointer with curr available resources
|
||||
* Returns: zero on success
|
||||
*/
|
||||
int dp_connector_get_mode_info(struct drm_connector *connector,
|
||||
const struct drm_display_mode *drm_mode,
|
||||
struct msm_sub_mode *sub_mode,
|
||||
struct msm_mode_info *mode_info,
|
||||
void *display, const struct msm_resource_caps_info *avail_res);
|
||||
|
||||
/**
|
||||
* dp_connector_get_info - retrieve connector display info
|
||||
* @connector: Pointer to drm connector structure
|
||||
* @info: Out parameter. Information of the connected display
|
||||
* @display: Pointer to private display structure
|
||||
* Returns: zero on success
|
||||
*/
|
||||
int dp_connector_get_info(struct drm_connector *connector,
|
||||
struct msm_display_info *info, void *display);
|
||||
|
||||
/**
|
||||
* dp_connector_post_open - handle the post open functionalities
|
||||
* @connector: Pointer to drm connector structure
|
||||
* @display: Pointer to private display structure
|
||||
*/
|
||||
void dp_connector_post_open(struct drm_connector *connector, void *display);
|
||||
|
||||
/**
|
||||
* dp_drm_bridge_init- drm dp bridge initialize
|
||||
* @display: Pointer to private display structure
|
||||
* @encoder: encoder for this dp bridge
|
||||
* @max_mixer_count: max available mixers for dp display
|
||||
* @max_dsc_count: max available dsc for dp display
|
||||
*/
|
||||
int dp_drm_bridge_init(void *display, struct drm_encoder *encoder,
|
||||
u32 max_mixer_count, u32 max_dsc_count);
|
||||
|
||||
void dp_drm_bridge_deinit(void *display);
|
||||
|
||||
/**
|
||||
* convert_to_drm_mode - convert dp mode to drm mode
|
||||
* @dp_mode: Point to dp mode
|
||||
* @drm_mode: Pointer to drm mode
|
||||
*/
|
||||
void convert_to_drm_mode(const struct dp_display_mode *dp_mode,
|
||||
struct drm_display_mode *drm_mode);
|
||||
|
||||
/**
|
||||
* dp_connector_update_pps - update pps for given connector
|
||||
* @dp_mode: Point to dp mode
|
||||
* @pps_cmd: PPS packet
|
||||
* @display: Pointer to private display structure
|
||||
*/
|
||||
int dp_connector_update_pps(struct drm_connector *connector,
|
||||
char *pps_cmd, void *display);
|
||||
|
||||
/**
|
||||
* dp_connector_install_properties - install drm properties
|
||||
* @display: Pointer to private display structure
|
||||
* @conn: Pointer to connector
|
||||
*/
|
||||
int dp_connector_install_properties(void *display,
|
||||
struct drm_connector *conn);
|
||||
|
||||
/**
|
||||
* init_failsafe_mode - add failsafe edid mode
|
||||
* @dp_mode: Pointer to mode
|
||||
*/
|
||||
void init_failsafe_mode(struct dp_display_mode *dp_mode);
|
||||
|
||||
/**
|
||||
* dp_connector_add_custom_mode - add edid mode to connector
|
||||
* @conn: Pointer to connector
|
||||
* @dp_mode: Pointer to mode
|
||||
*/
|
||||
int dp_connector_add_custom_mode(struct drm_connector *conn, struct dp_display_mode *dp_mode);
|
||||
|
||||
#else
|
||||
static inline int dp_connector_config_hdr(struct drm_connector *connector,
|
||||
void *display, struct sde_connector_state *c_state)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int dp_connector_atomic_check(struct drm_connector *connector,
|
||||
void *display, struct drm_atomic_state *state)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int dp_connector_set_colorspace(struct drm_connector *connector,
|
||||
void *display)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int dp_connector_post_init(struct drm_connector *connector,
|
||||
void *display)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline enum drm_connector_status dp_connector_detect(
|
||||
struct drm_connector *conn,
|
||||
bool force,
|
||||
void *display)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static inline int dp_connector_get_modes(struct drm_connector *connector,
|
||||
void *display, const struct msm_resource_caps_info *avail_res)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline enum drm_mode_status dp_connector_mode_valid(
|
||||
struct drm_connector *connector,
|
||||
struct drm_display_mode *mode,
|
||||
void *display, const struct msm_resource_caps_info *avail_res)
|
||||
{
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static inline int dp_connector_get_mode_info(struct drm_connector *connector,
|
||||
const struct drm_display_mode *drm_mode,
|
||||
struct msm_sub_mode *sub_mode,
|
||||
struct msm_mode_info *mode_info,
|
||||
void *display, const struct msm_resource_caps_info *avail_res)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int dp_connector_get_info(struct drm_connector *connector,
|
||||
struct msm_display_info *info, void *display)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void dp_connector_post_open(struct drm_connector *connector,
|
||||
void *display)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int dp_drm_bridge_init(void *display, struct drm_encoder *encoder,
|
||||
u32 max_mixer_count, u32 max_dsc_count)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void dp_drm_bridge_deinit(void *display)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void convert_to_drm_mode(const struct dp_display_mode *dp_mode,
|
||||
struct drm_display_mode *drm_mode)
|
||||
{
|
||||
}
|
||||
|
||||
static int dp_connector_install_properties(void *display,
|
||||
struct drm_connector *conn)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_DRM_MSM_DP */
|
||||
|
||||
#endif /* _DP_DRM_H_ */
|
298
qcom/opensource/display-drivers/msm/dp/dp_gpio_hpd.c
Normal file
298
qcom/opensource/display-drivers/msm/dp/dp_gpio_hpd.c
Normal file
@ -0,0 +1,298 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/sde_io_util.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include "dp_gpio_hpd.h"
|
||||
#include "dp_debug.h"
|
||||
|
||||
struct dp_gpio_hpd_private {
|
||||
struct device *dev;
|
||||
struct dp_hpd base;
|
||||
struct dss_gpio gpio_cfg;
|
||||
struct delayed_work work;
|
||||
struct dp_hpd_cb *cb;
|
||||
int irq;
|
||||
bool hpd;
|
||||
};
|
||||
|
||||
static int dp_gpio_hpd_connect(struct dp_gpio_hpd_private *gpio_hpd, bool hpd)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!gpio_hpd) {
|
||||
DP_ERR("invalid input\n");
|
||||
rc = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
gpio_hpd->base.hpd_high = hpd;
|
||||
gpio_hpd->base.alt_mode_cfg_done = hpd;
|
||||
gpio_hpd->base.hpd_irq = false;
|
||||
|
||||
if (!gpio_hpd->cb ||
|
||||
!gpio_hpd->cb->configure ||
|
||||
!gpio_hpd->cb->disconnect) {
|
||||
DP_ERR("invalid cb\n");
|
||||
rc = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (hpd)
|
||||
rc = gpio_hpd->cb->configure(gpio_hpd->dev);
|
||||
else
|
||||
rc = gpio_hpd->cb->disconnect(gpio_hpd->dev);
|
||||
|
||||
error:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int dp_gpio_hpd_attention(struct dp_gpio_hpd_private *gpio_hpd)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!gpio_hpd) {
|
||||
DP_ERR("invalid input\n");
|
||||
rc = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
gpio_hpd->base.hpd_irq = true;
|
||||
|
||||
if (gpio_hpd->cb && gpio_hpd->cb->attention)
|
||||
rc = gpio_hpd->cb->attention(gpio_hpd->dev);
|
||||
|
||||
error:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static irqreturn_t dp_gpio_isr(int unused, void *data)
|
||||
{
|
||||
struct dp_gpio_hpd_private *gpio_hpd = data;
|
||||
u32 const disconnect_timeout_retry = 50;
|
||||
bool hpd;
|
||||
int i;
|
||||
|
||||
if (!gpio_hpd)
|
||||
return IRQ_NONE;
|
||||
|
||||
hpd = gpio_get_value_cansleep(gpio_hpd->gpio_cfg.gpio);
|
||||
|
||||
if (!gpio_hpd->hpd && hpd) {
|
||||
gpio_hpd->hpd = true;
|
||||
queue_delayed_work(system_wq, &gpio_hpd->work, 0);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
if (!gpio_hpd->hpd)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
/* In DP 1.2 spec, 100msec is recommended for the detection
|
||||
* of HPD connect event. Here we'll poll HPD status for
|
||||
* 50x2ms = 100ms and if HPD is always low, we know DP is
|
||||
* disconnected. If HPD is high, HPD_IRQ will be handled
|
||||
*/
|
||||
for (i = 0; i < disconnect_timeout_retry; i++) {
|
||||
if (hpd) {
|
||||
dp_gpio_hpd_attention(gpio_hpd);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
usleep_range(2000, 2100);
|
||||
hpd = gpio_get_value_cansleep(gpio_hpd->gpio_cfg.gpio);
|
||||
}
|
||||
|
||||
gpio_hpd->hpd = false;
|
||||
queue_delayed_work(system_wq, &gpio_hpd->work, 0);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void dp_gpio_hpd_work(struct work_struct *work)
|
||||
{
|
||||
struct delayed_work *dw = to_delayed_work(work);
|
||||
struct dp_gpio_hpd_private *gpio_hpd = container_of(dw,
|
||||
struct dp_gpio_hpd_private, work);
|
||||
int ret;
|
||||
|
||||
if (gpio_hpd->hpd) {
|
||||
devm_free_irq(gpio_hpd->dev,
|
||||
gpio_hpd->irq, gpio_hpd);
|
||||
ret = devm_request_threaded_irq(gpio_hpd->dev,
|
||||
gpio_hpd->irq, NULL,
|
||||
dp_gpio_isr,
|
||||
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
||||
"dp-gpio-intp", gpio_hpd);
|
||||
dp_gpio_hpd_connect(gpio_hpd, true);
|
||||
} else {
|
||||
devm_free_irq(gpio_hpd->dev,
|
||||
gpio_hpd->irq, gpio_hpd);
|
||||
ret = devm_request_threaded_irq(gpio_hpd->dev,
|
||||
gpio_hpd->irq, NULL,
|
||||
dp_gpio_isr,
|
||||
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
|
||||
"dp-gpio-intp", gpio_hpd);
|
||||
dp_gpio_hpd_connect(gpio_hpd, false);
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
DP_ERR("Cannot claim IRQ dp-gpio-intp\n");
|
||||
}
|
||||
|
||||
static int dp_gpio_hpd_simulate_connect(struct dp_hpd *dp_hpd, bool hpd)
|
||||
{
|
||||
int rc = 0;
|
||||
struct dp_gpio_hpd_private *gpio_hpd;
|
||||
|
||||
if (!dp_hpd) {
|
||||
DP_ERR("invalid input\n");
|
||||
rc = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
gpio_hpd = container_of(dp_hpd, struct dp_gpio_hpd_private, base);
|
||||
|
||||
dp_gpio_hpd_connect(gpio_hpd, hpd);
|
||||
error:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int dp_gpio_hpd_simulate_attention(struct dp_hpd *dp_hpd, int vdo)
|
||||
{
|
||||
int rc = 0;
|
||||
struct dp_gpio_hpd_private *gpio_hpd;
|
||||
|
||||
if (!dp_hpd) {
|
||||
DP_ERR("invalid input\n");
|
||||
rc = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
gpio_hpd = container_of(dp_hpd, struct dp_gpio_hpd_private, base);
|
||||
|
||||
dp_gpio_hpd_attention(gpio_hpd);
|
||||
error:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int dp_gpio_hpd_register(struct dp_hpd *dp_hpd)
|
||||
{
|
||||
struct dp_gpio_hpd_private *gpio_hpd;
|
||||
int edge;
|
||||
int rc = 0;
|
||||
|
||||
if (!dp_hpd)
|
||||
return -EINVAL;
|
||||
|
||||
gpio_hpd = container_of(dp_hpd, struct dp_gpio_hpd_private, base);
|
||||
|
||||
gpio_hpd->hpd = gpio_get_value_cansleep(gpio_hpd->gpio_cfg.gpio);
|
||||
|
||||
edge = gpio_hpd->hpd ? IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
|
||||
rc = devm_request_threaded_irq(gpio_hpd->dev, gpio_hpd->irq, NULL,
|
||||
dp_gpio_isr,
|
||||
edge | IRQF_ONESHOT,
|
||||
"dp-gpio-intp", gpio_hpd);
|
||||
if (rc) {
|
||||
DP_ERR("Failed to request INTP threaded IRQ: %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (gpio_hpd->hpd)
|
||||
queue_delayed_work(system_wq, &gpio_hpd->work, 0);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
struct dp_hpd *dp_gpio_hpd_get(struct device *dev,
|
||||
struct dp_hpd_cb *cb)
|
||||
{
|
||||
int rc = 0;
|
||||
const char *hpd_gpio_name = "qcom,dp-hpd-gpio";
|
||||
struct dp_gpio_hpd_private *gpio_hpd;
|
||||
struct dp_pinctrl pinctrl = {0};
|
||||
unsigned int gpio;
|
||||
|
||||
if (!dev || !cb) {
|
||||
DP_ERR("invalid device\n");
|
||||
rc = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
gpio = of_get_named_gpio(dev->of_node, hpd_gpio_name, 0);
|
||||
if (!gpio_is_valid(gpio)) {
|
||||
DP_DEBUG("%s gpio not specified\n", hpd_gpio_name);
|
||||
rc = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
gpio_hpd = devm_kzalloc(dev, sizeof(*gpio_hpd), GFP_KERNEL);
|
||||
if (!gpio_hpd) {
|
||||
rc = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
pinctrl.pin = devm_pinctrl_get(dev);
|
||||
if (!IS_ERR_OR_NULL(pinctrl.pin)) {
|
||||
pinctrl.state_hpd_active = pinctrl_lookup_state(pinctrl.pin,
|
||||
"mdss_dp_hpd_active");
|
||||
if (!IS_ERR_OR_NULL(pinctrl.state_hpd_active)) {
|
||||
rc = pinctrl_select_state(pinctrl.pin,
|
||||
pinctrl.state_hpd_active);
|
||||
if (rc) {
|
||||
DP_ERR("failed to set hpd active state\n");
|
||||
goto gpio_error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gpio_hpd->gpio_cfg.gpio = gpio;
|
||||
strlcpy(gpio_hpd->gpio_cfg.gpio_name, hpd_gpio_name,
|
||||
sizeof(gpio_hpd->gpio_cfg.gpio_name));
|
||||
gpio_hpd->gpio_cfg.value = 0;
|
||||
|
||||
rc = gpio_request(gpio_hpd->gpio_cfg.gpio,
|
||||
gpio_hpd->gpio_cfg.gpio_name);
|
||||
if (rc) {
|
||||
DP_ERR("%s: failed to request gpio\n", hpd_gpio_name);
|
||||
goto gpio_error;
|
||||
}
|
||||
gpio_direction_input(gpio_hpd->gpio_cfg.gpio);
|
||||
|
||||
gpio_hpd->dev = dev;
|
||||
gpio_hpd->cb = cb;
|
||||
gpio_hpd->irq = gpio_to_irq(gpio_hpd->gpio_cfg.gpio);
|
||||
INIT_DELAYED_WORK(&gpio_hpd->work, dp_gpio_hpd_work);
|
||||
|
||||
gpio_hpd->base.simulate_connect = dp_gpio_hpd_simulate_connect;
|
||||
gpio_hpd->base.simulate_attention = dp_gpio_hpd_simulate_attention;
|
||||
gpio_hpd->base.register_hpd = dp_gpio_hpd_register;
|
||||
|
||||
return &gpio_hpd->base;
|
||||
|
||||
gpio_error:
|
||||
devm_kfree(dev, gpio_hpd);
|
||||
error:
|
||||
return ERR_PTR(rc);
|
||||
}
|
||||
|
||||
void dp_gpio_hpd_put(struct dp_hpd *dp_hpd)
|
||||
{
|
||||
struct dp_gpio_hpd_private *gpio_hpd;
|
||||
|
||||
if (!dp_hpd)
|
||||
return;
|
||||
|
||||
gpio_hpd = container_of(dp_hpd, struct dp_gpio_hpd_private, base);
|
||||
|
||||
gpio_free(gpio_hpd->gpio_cfg.gpio);
|
||||
devm_kfree(gpio_hpd->dev, gpio_hpd);
|
||||
}
|
32
qcom/opensource/display-drivers/msm/dp/dp_gpio_hpd.h
Normal file
32
qcom/opensource/display-drivers/msm/dp/dp_gpio_hpd.h
Normal file
@ -0,0 +1,32 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _DP_GPIO_HPD_H_
|
||||
#define _DP_GPIO_HPD_H_
|
||||
|
||||
#include "dp_hpd.h"
|
||||
|
||||
/**
|
||||
* dp_gpio_hpd_get() - configure and get the DisplayPlot HPD module data
|
||||
*
|
||||
* @dev: device instance of the caller
|
||||
* return: pointer to allocated gpio hpd module data
|
||||
*
|
||||
* This function sets up the gpio hpd module
|
||||
*/
|
||||
struct dp_hpd *dp_gpio_hpd_get(struct device *dev,
|
||||
struct dp_hpd_cb *cb);
|
||||
|
||||
/**
|
||||
* dp_gpio_hpd_put()
|
||||
*
|
||||
* Cleans up dp_hpd instance
|
||||
*
|
||||
* @hpd: instance of gpio_hpd
|
||||
*/
|
||||
void dp_gpio_hpd_put(struct dp_hpd *hpd);
|
||||
|
||||
#endif /* _DP_GPIO_HPD_H_ */
|
1039
qcom/opensource/display-drivers/msm/dp/dp_hdcp2p2.c
Normal file
1039
qcom/opensource/display-drivers/msm/dp/dp_hdcp2p2.c
Normal file
File diff suppressed because it is too large
Load Diff
123
qcom/opensource/display-drivers/msm/dp/dp_hpd.c
Normal file
123
qcom/opensource/display-drivers/msm/dp/dp_hpd.c
Normal file
@ -0,0 +1,123 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#include "dp_hpd.h"
|
||||
#include "dp_altmode.h"
|
||||
#include "dp_usbpd.h"
|
||||
#include "dp_gpio_hpd.h"
|
||||
#include "dp_lphw_hpd.h"
|
||||
#include "dp_debug.h"
|
||||
#include "dp_bridge_hpd.h"
|
||||
|
||||
static void dp_hpd_host_init(struct dp_hpd *dp_hpd,
|
||||
struct dp_catalog_hpd *catalog)
|
||||
{
|
||||
if (!catalog) {
|
||||
DP_ERR("invalid input\n");
|
||||
return;
|
||||
}
|
||||
catalog->config_hpd(catalog, true);
|
||||
}
|
||||
|
||||
static void dp_hpd_host_deinit(struct dp_hpd *dp_hpd,
|
||||
struct dp_catalog_hpd *catalog)
|
||||
{
|
||||
if (!catalog) {
|
||||
DP_ERR("invalid input\n");
|
||||
return;
|
||||
}
|
||||
catalog->config_hpd(catalog, false);
|
||||
}
|
||||
|
||||
static void dp_hpd_isr(struct dp_hpd *dp_hpd)
|
||||
{
|
||||
}
|
||||
|
||||
struct dp_hpd *dp_hpd_get(struct device *dev, struct dp_parser *parser,
|
||||
struct dp_catalog_hpd *catalog,
|
||||
struct dp_aux_bridge *aux_bridge,
|
||||
struct dp_hpd_cb *cb)
|
||||
{
|
||||
struct dp_hpd *dp_hpd = NULL;
|
||||
|
||||
if (aux_bridge && (aux_bridge->flag & DP_AUX_BRIDGE_HPD)) {
|
||||
dp_hpd = dp_bridge_hpd_get(dev, cb, aux_bridge);
|
||||
if (!IS_ERR(dp_hpd)) {
|
||||
dp_hpd->type = DP_HPD_BRIDGE;
|
||||
goto config;
|
||||
}
|
||||
}
|
||||
|
||||
dp_hpd = dp_lphw_hpd_get(dev, parser, catalog, cb);
|
||||
if (!IS_ERR_OR_NULL(dp_hpd)) {
|
||||
dp_hpd->type = DP_HPD_LPHW;
|
||||
goto config;
|
||||
}
|
||||
|
||||
dp_hpd = dp_gpio_hpd_get(dev, cb);
|
||||
if (!IS_ERR_OR_NULL(dp_hpd)) {
|
||||
dp_hpd->type = DP_HPD_GPIO;
|
||||
goto config;
|
||||
}
|
||||
|
||||
dp_hpd = dp_altmode_get(dev, cb);
|
||||
if (!IS_ERR_OR_NULL(dp_hpd)) {
|
||||
dp_hpd->type = DP_HPD_ALTMODE;
|
||||
goto config;
|
||||
}
|
||||
|
||||
dp_hpd = dp_usbpd_get(dev, cb);
|
||||
if (!IS_ERR_OR_NULL(dp_hpd)) {
|
||||
dp_hpd->type = DP_HPD_USBPD;
|
||||
goto config;
|
||||
}
|
||||
|
||||
DP_ERR("Failed to detect HPD type\n");
|
||||
goto end;
|
||||
|
||||
config:
|
||||
if (!dp_hpd->host_init)
|
||||
dp_hpd->host_init = dp_hpd_host_init;
|
||||
if (!dp_hpd->host_deinit)
|
||||
dp_hpd->host_deinit = dp_hpd_host_deinit;
|
||||
if (!dp_hpd->isr)
|
||||
dp_hpd->isr = dp_hpd_isr;
|
||||
|
||||
end:
|
||||
return dp_hpd;
|
||||
}
|
||||
|
||||
void dp_hpd_put(struct dp_hpd *dp_hpd)
|
||||
{
|
||||
if (!dp_hpd)
|
||||
return;
|
||||
|
||||
switch (dp_hpd->type) {
|
||||
case DP_HPD_USBPD:
|
||||
dp_usbpd_put(dp_hpd);
|
||||
break;
|
||||
case DP_HPD_ALTMODE:
|
||||
dp_altmode_put(dp_hpd);
|
||||
break;
|
||||
case DP_HPD_GPIO:
|
||||
dp_gpio_hpd_put(dp_hpd);
|
||||
break;
|
||||
case DP_HPD_LPHW:
|
||||
dp_lphw_hpd_put(dp_hpd);
|
||||
break;
|
||||
case DP_HPD_BRIDGE:
|
||||
dp_bridge_hpd_put(dp_hpd);
|
||||
break;
|
||||
default:
|
||||
DP_ERR("unknown hpd type %d\n", dp_hpd->type);
|
||||
break;
|
||||
}
|
||||
}
|
122
qcom/opensource/display-drivers/msm/dp/dp_hpd.h
Normal file
122
qcom/opensource/display-drivers/msm/dp/dp_hpd.h
Normal file
@ -0,0 +1,122 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _DP_HPD_H_
|
||||
#define _DP_HPD_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include "dp_parser.h"
|
||||
#include "dp_catalog.h"
|
||||
#include "dp_aux_bridge.h"
|
||||
|
||||
struct device;
|
||||
|
||||
/**
|
||||
* enum dp_hpd_plug_orientation - plug orientation
|
||||
* @ORIENTATION_NONE: Undefined or unspecified
|
||||
* @ORIENTATION_CC1: CC1
|
||||
* @ORIENTATION_CC2: CC2
|
||||
*/
|
||||
enum dp_hpd_plug_orientation {
|
||||
ORIENTATION_NONE,
|
||||
ORIENTATION_CC1,
|
||||
ORIENTATION_CC2,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum dp_hpd_type - dp hpd type
|
||||
* @DP_HPD_ALTMODE: AltMode over G-Link based HPD
|
||||
* @DP_HPD_USBPD: USB type-c based HPD
|
||||
* @DP_HPD_GPIO: GPIO based HPD
|
||||
* @DP_HPD_LPHW: LPHW based HPD
|
||||
* @DP_HPD_BRIDGE: External bridge HPD
|
||||
*/
|
||||
|
||||
enum dp_hpd_type {
|
||||
DP_HPD_ALTMODE,
|
||||
DP_HPD_USBPD,
|
||||
DP_HPD_GPIO,
|
||||
DP_HPD_LPHW,
|
||||
DP_HPD_BRIDGE,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dp_hpd_cb - callback functions provided by the client
|
||||
*
|
||||
* @configure: called when dp connection is ready.
|
||||
* @disconnect: notify the cable disconnect event.
|
||||
* @attention: notify any attention message event.
|
||||
*/
|
||||
struct dp_hpd_cb {
|
||||
int (*configure)(struct device *dev);
|
||||
int (*disconnect)(struct device *dev);
|
||||
int (*attention)(struct device *dev);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dp_hpd - DisplayPort HPD status
|
||||
*
|
||||
* @type: type of HPD
|
||||
* @orientation: plug orientation configuration, USBPD type only.
|
||||
* @hpd_high: Hot Plug Detect signal is high.
|
||||
* @hpd_irq: Change in the status since last message
|
||||
* @alt_mode_cfg_done: bool to specify alt mode status
|
||||
* @multi_func: multi-function preferred, USBPD type only
|
||||
* @peer_usb_com: downstream supports usb data communication
|
||||
* @force_multi_func: force multi-function preferred
|
||||
* @isr: event interrupt, BUILTIN and LPHW type only
|
||||
* @register_hpd: register hardware callback
|
||||
* @host_init: source or host side setup for hpd
|
||||
* @host_deinit: source or host side de-initializations
|
||||
* @simulate_connect: simulate disconnect or connect for debug mode
|
||||
* @simulate_attention: simulate attention messages for debug mode
|
||||
* @wakeup_phy: wakeup USBPD phy layer
|
||||
*/
|
||||
struct dp_hpd {
|
||||
enum dp_hpd_type type;
|
||||
u32 orientation;
|
||||
bool hpd_high;
|
||||
bool hpd_irq;
|
||||
bool alt_mode_cfg_done;
|
||||
bool multi_func;
|
||||
bool peer_usb_comm;
|
||||
bool force_multi_func;
|
||||
|
||||
void (*isr)(struct dp_hpd *dp_hpd);
|
||||
int (*register_hpd)(struct dp_hpd *dp_hpd);
|
||||
void (*host_init)(struct dp_hpd *hpd, struct dp_catalog_hpd *catalog);
|
||||
void (*host_deinit)(struct dp_hpd *hpd, struct dp_catalog_hpd *catalog);
|
||||
int (*simulate_connect)(struct dp_hpd *dp_hpd, bool hpd);
|
||||
int (*simulate_attention)(struct dp_hpd *dp_hpd, int vdo);
|
||||
void (*wakeup_phy)(struct dp_hpd *dp_hpd, bool wakeup);
|
||||
};
|
||||
|
||||
/**
|
||||
* dp_hpd_get() - configure and get the DisplayPlot HPD module data
|
||||
*
|
||||
* @dev: device instance of the caller
|
||||
* @parser: pointer to DP parser module
|
||||
* @catalog: pointer to DP catalog module
|
||||
* @aux_bridge: handle for aux_bridge driver data
|
||||
* @cb: callback function for HPD response
|
||||
* return: pointer to allocated hpd module data
|
||||
*
|
||||
* This function sets up the hpd module
|
||||
*/
|
||||
struct dp_hpd *dp_hpd_get(struct device *dev, struct dp_parser *parser,
|
||||
struct dp_catalog_hpd *catalog,
|
||||
struct dp_aux_bridge *aux_bridge,
|
||||
struct dp_hpd_cb *cb);
|
||||
|
||||
/**
|
||||
* dp_hpd_put()
|
||||
*
|
||||
* Cleans up dp_hpd instance
|
||||
*
|
||||
* @dp_hpd: instance of dp_hpd
|
||||
*/
|
||||
void dp_hpd_put(struct dp_hpd *dp_hpd);
|
||||
|
||||
#endif /* _DP_HPD_H_ */
|
1691
qcom/opensource/display-drivers/msm/dp/dp_link.c
Normal file
1691
qcom/opensource/display-drivers/msm/dp/dp_link.c
Normal file
File diff suppressed because it is too large
Load Diff
248
qcom/opensource/display-drivers/msm/dp/dp_link.h
Normal file
248
qcom/opensource/display-drivers/msm/dp/dp_link.h
Normal file
@ -0,0 +1,248 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Copyright (c) 2008 Keith Packard
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _DP_LINK_H_
|
||||
#define _DP_LINK_H_
|
||||
|
||||
#include "dp_aux.h"
|
||||
|
||||
#define DS_PORT_STATUS_CHANGED 0x200
|
||||
#define DP_TEST_BIT_DEPTH_UNKNOWN 0xFFFFFFFF
|
||||
#define DP_LINK_ENUM_STR(x) #x
|
||||
|
||||
#define DP_PHY_TEST_PATTERN_CP2520_2 0x6
|
||||
#define DP_PHY_TEST_PATTERN_CP2520_3 0x7
|
||||
|
||||
struct drm_dp_aux;
|
||||
|
||||
#define DP_LINK_CAP_ENHANCED_FRAMING (1 << 0)
|
||||
#define DP_LINK_CAP_CRC (1 << 1)
|
||||
|
||||
struct drm_dp_link {
|
||||
unsigned char revision;
|
||||
unsigned int rate;
|
||||
unsigned int num_lanes;
|
||||
unsigned long capabilities;
|
||||
};
|
||||
|
||||
int dp_link_probe(struct drm_dp_aux *aux, struct drm_dp_link *link);
|
||||
int dp_link_power_up(struct drm_dp_aux *aux, struct drm_dp_link *link);
|
||||
int dp_link_power_down(struct drm_dp_aux *aux, struct drm_dp_link *link);
|
||||
int dp_link_configure(struct drm_dp_aux *aux, struct drm_dp_link *link);
|
||||
|
||||
enum dp_link_voltage_level {
|
||||
DP_LINK_VOLTAGE_LEVEL_0,
|
||||
DP_LINK_VOLTAGE_LEVEL_1,
|
||||
DP_LINK_VOLTAGE_LEVEL_2,
|
||||
DP_LINK_VOLTAGE_LEVEL_3,
|
||||
};
|
||||
|
||||
enum dp_link_preemaphasis_level {
|
||||
DP_LINK_PRE_EMPHASIS_LEVEL_0,
|
||||
DP_LINK_PRE_EMPHASIS_LEVEL_1,
|
||||
DP_LINK_PRE_EMPHASIS_LEVEL_2,
|
||||
DP_LINK_PRE_EMPHASIS_LEVEL_3,
|
||||
};
|
||||
|
||||
struct dp_link_sink_count {
|
||||
u32 count;
|
||||
bool cp_ready;
|
||||
};
|
||||
|
||||
struct dp_link_test_video {
|
||||
u32 test_video_pattern;
|
||||
u32 test_bit_depth;
|
||||
u32 test_dyn_range;
|
||||
u32 test_h_total;
|
||||
u32 test_v_total;
|
||||
u32 test_h_start;
|
||||
u32 test_v_start;
|
||||
u32 test_hsync_pol;
|
||||
u32 test_hsync_width;
|
||||
u32 test_vsync_pol;
|
||||
u32 test_vsync_width;
|
||||
u32 test_h_width;
|
||||
u32 test_v_height;
|
||||
u32 test_rr_d;
|
||||
u32 test_rr_n;
|
||||
};
|
||||
|
||||
struct dp_link_test_audio {
|
||||
u32 test_audio_sampling_rate;
|
||||
u32 test_audio_channel_count;
|
||||
u32 test_audio_pattern_type;
|
||||
u32 test_audio_period_ch_1;
|
||||
u32 test_audio_period_ch_2;
|
||||
u32 test_audio_period_ch_3;
|
||||
u32 test_audio_period_ch_4;
|
||||
u32 test_audio_period_ch_5;
|
||||
u32 test_audio_period_ch_6;
|
||||
u32 test_audio_period_ch_7;
|
||||
u32 test_audio_period_ch_8;
|
||||
};
|
||||
|
||||
struct dp_link_hdcp_status {
|
||||
int hdcp_state;
|
||||
int hdcp_version;
|
||||
};
|
||||
|
||||
struct dp_link_phy_params {
|
||||
u32 phy_test_pattern_sel;
|
||||
u8 v_level;
|
||||
u8 p_level;
|
||||
u8 max_v_level;
|
||||
u8 max_p_level;
|
||||
};
|
||||
|
||||
struct dp_link_params {
|
||||
u32 lane_count;
|
||||
u32 bw_code;
|
||||
};
|
||||
|
||||
static inline char *dp_link_get_test_name(u32 test_requested)
|
||||
{
|
||||
switch (test_requested) {
|
||||
case DP_TEST_LINK_TRAINING:
|
||||
return DP_LINK_ENUM_STR(DP_TEST_LINK_TRAINING);
|
||||
case DP_TEST_LINK_VIDEO_PATTERN:
|
||||
return DP_LINK_ENUM_STR(DP_TEST_LINK_VIDEO_PATTERN);
|
||||
case DP_TEST_LINK_EDID_READ:
|
||||
return DP_LINK_ENUM_STR(DP_TEST_LINK_EDID_READ);
|
||||
case DP_TEST_LINK_PHY_TEST_PATTERN:
|
||||
return DP_LINK_ENUM_STR(DP_TEST_LINK_PHY_TEST_PATTERN);
|
||||
case DP_TEST_LINK_AUDIO_PATTERN:
|
||||
return DP_LINK_ENUM_STR(DP_TEST_LINK_AUDIO_PATTERN);
|
||||
case DS_PORT_STATUS_CHANGED:
|
||||
return DP_LINK_ENUM_STR(DS_PORT_STATUS_CHANGED);
|
||||
case DP_LINK_STATUS_UPDATED:
|
||||
return DP_LINK_ENUM_STR(DP_LINK_STATUS_UPDATED);
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
struct dp_link {
|
||||
u32 sink_request;
|
||||
u32 test_response;
|
||||
|
||||
struct dp_link_sink_count sink_count;
|
||||
struct dp_link_test_video test_video;
|
||||
struct dp_link_test_audio test_audio;
|
||||
struct dp_link_phy_params phy_params;
|
||||
struct dp_link_params link_params;
|
||||
struct dp_link_hdcp_status hdcp_status;
|
||||
|
||||
u32 (*get_test_bits_depth)(struct dp_link *dp_link, u32 bpp);
|
||||
int (*process_request)(struct dp_link *dp_link);
|
||||
int (*get_colorimetry_config)(struct dp_link *dp_link);
|
||||
int (*adjust_levels)(struct dp_link *dp_link, u8 *link_status);
|
||||
int (*send_psm_request)(struct dp_link *dp_link, bool req);
|
||||
void (*send_test_response)(struct dp_link *dp_link);
|
||||
int (*psm_config)(struct dp_link *dp_link,
|
||||
struct drm_dp_link *link_info, bool enable);
|
||||
void (*send_edid_checksum)(struct dp_link *dp_link, u8 checksum);
|
||||
};
|
||||
|
||||
static inline char *dp_link_get_phy_test_pattern(u32 phy_test_pattern_sel)
|
||||
{
|
||||
switch (phy_test_pattern_sel) {
|
||||
case DP_PHY_TEST_PATTERN_NONE:
|
||||
return DP_LINK_ENUM_STR(DP_PHY_TEST_PATTERN_NONE);
|
||||
case DP_PHY_TEST_PATTERN_D10_2:
|
||||
return DP_LINK_ENUM_STR(
|
||||
DP_PHY_TEST_PATTERN_D10_2);
|
||||
case DP_PHY_TEST_PATTERN_ERROR_COUNT:
|
||||
return DP_LINK_ENUM_STR(
|
||||
DP_PHY_TEST_PATTERN_ERROR_COUNT);
|
||||
case DP_PHY_TEST_PATTERN_PRBS7:
|
||||
return DP_LINK_ENUM_STR(DP_PHY_TEST_PATTERN_PRBS7);
|
||||
case DP_PHY_TEST_PATTERN_80BIT_CUSTOM:
|
||||
return DP_LINK_ENUM_STR(
|
||||
DP_PHY_TEST_PATTERN_80BIT_CUSTOM);
|
||||
case DP_PHY_TEST_PATTERN_CP2520:
|
||||
return DP_LINK_ENUM_STR(DP_PHY_TEST_PATTERN_CP2520);
|
||||
case DP_PHY_TEST_PATTERN_CP2520_2:
|
||||
return DP_LINK_ENUM_STR(DP_PHY_TEST_PATTERN_CP2520_2);
|
||||
case DP_PHY_TEST_PATTERN_CP2520_3:
|
||||
return DP_LINK_ENUM_STR(DP_PHY_TEST_PATTERN_CP2520_3);
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mdss_dp_test_bit_depth_to_bpp() - convert test bit depth to bpp
|
||||
* @tbd: test bit depth
|
||||
*
|
||||
* Returns the bits per pixel (bpp) to be used corresponding to the
|
||||
* git bit depth value. This function assumes that bit depth has
|
||||
* already been validated.
|
||||
*/
|
||||
static inline u32 dp_link_bit_depth_to_bpp(u32 tbd)
|
||||
{
|
||||
u32 bpp;
|
||||
|
||||
/*
|
||||
* Few simplistic rules and assumptions made here:
|
||||
* 1. Bit depth is per color component
|
||||
* 2. If bit depth is unknown return 0
|
||||
* 3. Assume 3 color components
|
||||
*/
|
||||
switch (tbd) {
|
||||
case DP_TEST_BIT_DEPTH_6:
|
||||
bpp = 18;
|
||||
break;
|
||||
case DP_TEST_BIT_DEPTH_8:
|
||||
bpp = 24;
|
||||
break;
|
||||
case DP_TEST_BIT_DEPTH_10:
|
||||
bpp = 30;
|
||||
break;
|
||||
case DP_TEST_BIT_DEPTH_UNKNOWN:
|
||||
default:
|
||||
bpp = 0;
|
||||
}
|
||||
|
||||
return bpp;
|
||||
}
|
||||
|
||||
/**
|
||||
* dp_link_get() - get the functionalities of dp test module
|
||||
*
|
||||
*
|
||||
* return: a pointer to dp_link struct
|
||||
*/
|
||||
struct dp_link *dp_link_get(struct device *dev, struct dp_aux *aux, u32 dp_core_revision);
|
||||
|
||||
/**
|
||||
* dp_link_put() - releases the dp test module's resources
|
||||
*
|
||||
* @dp_link: an instance of dp_link module
|
||||
*
|
||||
*/
|
||||
void dp_link_put(struct dp_link *dp_link);
|
||||
|
||||
#endif /* _DP_LINK_H_ */
|
424
qcom/opensource/display-drivers/msm/dp/dp_lphw_hpd.c
Normal file
424
qcom/opensource/display-drivers/msm/dp/dp_lphw_hpd.c
Normal file
@ -0,0 +1,424 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/sde_io_util.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include "dp_lphw_hpd.h"
|
||||
#include "dp_debug.h"
|
||||
|
||||
struct dp_lphw_hpd_private {
|
||||
struct device *dev;
|
||||
struct dp_hpd base;
|
||||
struct dp_parser *parser;
|
||||
struct dp_catalog_hpd *catalog;
|
||||
struct dss_gpio gpio_cfg;
|
||||
struct workqueue_struct *connect_wq;
|
||||
struct delayed_work work;
|
||||
struct work_struct connect;
|
||||
struct work_struct disconnect;
|
||||
struct work_struct attention;
|
||||
struct dp_hpd_cb *cb;
|
||||
int irq;
|
||||
bool hpd;
|
||||
};
|
||||
|
||||
static void dp_lphw_hpd_attention(struct work_struct *work)
|
||||
{
|
||||
struct dp_lphw_hpd_private *lphw_hpd = container_of(work,
|
||||
struct dp_lphw_hpd_private, attention);
|
||||
|
||||
if (!lphw_hpd) {
|
||||
DP_ERR("invalid input\n");
|
||||
return;
|
||||
}
|
||||
|
||||
lphw_hpd->base.hpd_irq = true;
|
||||
|
||||
if (lphw_hpd->cb && lphw_hpd->cb->attention)
|
||||
lphw_hpd->cb->attention(lphw_hpd->dev);
|
||||
}
|
||||
|
||||
static void dp_lphw_hpd_connect(struct work_struct *work)
|
||||
{
|
||||
struct dp_lphw_hpd_private *lphw_hpd = container_of(work,
|
||||
struct dp_lphw_hpd_private, connect);
|
||||
|
||||
if (!lphw_hpd) {
|
||||
DP_ERR("invalid input\n");
|
||||
return;
|
||||
}
|
||||
|
||||
lphw_hpd->base.hpd_high = true;
|
||||
lphw_hpd->base.alt_mode_cfg_done = true;
|
||||
lphw_hpd->base.hpd_irq = false;
|
||||
|
||||
if (lphw_hpd->cb && lphw_hpd->cb->configure)
|
||||
lphw_hpd->cb->configure(lphw_hpd->dev);
|
||||
}
|
||||
|
||||
static void dp_lphw_hpd_disconnect(struct work_struct *work)
|
||||
{
|
||||
struct dp_lphw_hpd_private *lphw_hpd = container_of(work,
|
||||
struct dp_lphw_hpd_private, disconnect);
|
||||
|
||||
if (!lphw_hpd) {
|
||||
DP_ERR("invalid input\n");
|
||||
return;
|
||||
}
|
||||
|
||||
lphw_hpd->base.hpd_high = false;
|
||||
lphw_hpd->base.alt_mode_cfg_done = false;
|
||||
lphw_hpd->base.hpd_irq = false;
|
||||
|
||||
if (lphw_hpd->cb && lphw_hpd->cb->disconnect)
|
||||
lphw_hpd->cb->disconnect(lphw_hpd->dev);
|
||||
}
|
||||
|
||||
static irqreturn_t dp_tlmm_isr(int unused, void *data)
|
||||
{
|
||||
struct dp_lphw_hpd_private *lphw_hpd = data;
|
||||
bool hpd;
|
||||
|
||||
if (!lphw_hpd)
|
||||
return IRQ_NONE;
|
||||
|
||||
/*
|
||||
* According to the DP spec, HPD high event can be confirmed only after
|
||||
* the HPD line has een asserted continuously for more than 100ms
|
||||
*/
|
||||
usleep_range(99000, 100000);
|
||||
|
||||
hpd = gpio_get_value_cansleep(lphw_hpd->gpio_cfg.gpio);
|
||||
|
||||
DP_DEBUG("lphw_hpd state = %d, new hpd state = %d\n",
|
||||
lphw_hpd->hpd, hpd);
|
||||
if (!lphw_hpd->hpd && hpd) {
|
||||
lphw_hpd->hpd = true;
|
||||
queue_work(lphw_hpd->connect_wq, &lphw_hpd->connect);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void dp_lphw_hpd_host_init(struct dp_hpd *dp_hpd,
|
||||
struct dp_catalog_hpd *catalog)
|
||||
{
|
||||
struct dp_lphw_hpd_private *lphw_hpd;
|
||||
|
||||
if (!dp_hpd) {
|
||||
DP_ERR("invalid input\n");
|
||||
return;
|
||||
}
|
||||
|
||||
lphw_hpd = container_of(dp_hpd, struct dp_lphw_hpd_private, base);
|
||||
|
||||
lphw_hpd->catalog->config_hpd(lphw_hpd->catalog, true);
|
||||
|
||||
/*
|
||||
* Changing the gpio function to dp controller for the hpd line is not
|
||||
* stopping the tlmm interrupts generation on function 0.
|
||||
* So, as an additional step, disable the gpio interrupt irq also
|
||||
*/
|
||||
disable_irq(lphw_hpd->irq);
|
||||
}
|
||||
|
||||
static void dp_lphw_hpd_host_deinit(struct dp_hpd *dp_hpd,
|
||||
struct dp_catalog_hpd *catalog)
|
||||
{
|
||||
struct dp_lphw_hpd_private *lphw_hpd;
|
||||
|
||||
if (!dp_hpd) {
|
||||
DP_ERR("invalid input\n");
|
||||
return;
|
||||
}
|
||||
|
||||
lphw_hpd = container_of(dp_hpd, struct dp_lphw_hpd_private, base);
|
||||
|
||||
/* Enable the tlmm interrupt irq which was disabled in host_init */
|
||||
enable_irq(lphw_hpd->irq);
|
||||
|
||||
lphw_hpd->catalog->config_hpd(lphw_hpd->catalog, false);
|
||||
}
|
||||
|
||||
static void dp_lphw_hpd_isr(struct dp_hpd *dp_hpd)
|
||||
{
|
||||
struct dp_lphw_hpd_private *lphw_hpd;
|
||||
u32 isr = 0;
|
||||
int rc = 0;
|
||||
|
||||
if (!dp_hpd) {
|
||||
DP_ERR("invalid input\n");
|
||||
return;
|
||||
}
|
||||
|
||||
lphw_hpd = container_of(dp_hpd, struct dp_lphw_hpd_private, base);
|
||||
|
||||
isr = lphw_hpd->catalog->get_interrupt(lphw_hpd->catalog);
|
||||
|
||||
if (isr & DP_HPD_UNPLUG_INT_STATUS) { /* disconnect interrupt */
|
||||
|
||||
DP_DEBUG("disconnect interrupt, hpd isr state: 0x%x\n", isr);
|
||||
|
||||
if (lphw_hpd->base.hpd_high) {
|
||||
lphw_hpd->hpd = false;
|
||||
lphw_hpd->base.hpd_high = false;
|
||||
lphw_hpd->base.alt_mode_cfg_done = false;
|
||||
lphw_hpd->base.hpd_irq = false;
|
||||
|
||||
rc = queue_work(lphw_hpd->connect_wq,
|
||||
&lphw_hpd->disconnect);
|
||||
if (!rc)
|
||||
DP_DEBUG("disconnect not queued\n");
|
||||
} else {
|
||||
DP_ERR("already disconnected\n");
|
||||
}
|
||||
|
||||
} else if (isr & DP_IRQ_HPD_INT_STATUS) { /* attention interrupt */
|
||||
|
||||
DP_DEBUG("hpd_irq interrupt, hpd isr state: 0x%x\n", isr);
|
||||
|
||||
rc = queue_work(lphw_hpd->connect_wq, &lphw_hpd->attention);
|
||||
if (!rc)
|
||||
DP_DEBUG("attention not queued\n");
|
||||
}
|
||||
}
|
||||
|
||||
static int dp_lphw_hpd_simulate_connect(struct dp_hpd *dp_hpd, bool hpd)
|
||||
{
|
||||
struct dp_lphw_hpd_private *lphw_hpd;
|
||||
|
||||
if (!dp_hpd) {
|
||||
DP_ERR("invalid input\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
lphw_hpd = container_of(dp_hpd, struct dp_lphw_hpd_private, base);
|
||||
|
||||
lphw_hpd->base.hpd_high = hpd;
|
||||
lphw_hpd->base.alt_mode_cfg_done = hpd;
|
||||
lphw_hpd->base.hpd_irq = false;
|
||||
|
||||
if (!lphw_hpd->cb || !lphw_hpd->cb->configure ||
|
||||
!lphw_hpd->cb->disconnect) {
|
||||
DP_ERR("invalid callback\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (hpd)
|
||||
lphw_hpd->cb->configure(lphw_hpd->dev);
|
||||
else
|
||||
lphw_hpd->cb->disconnect(lphw_hpd->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dp_lphw_hpd_simulate_attention(struct dp_hpd *dp_hpd, int vdo)
|
||||
{
|
||||
struct dp_lphw_hpd_private *lphw_hpd;
|
||||
|
||||
if (!dp_hpd) {
|
||||
DP_ERR("invalid input\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
lphw_hpd = container_of(dp_hpd, struct dp_lphw_hpd_private, base);
|
||||
|
||||
lphw_hpd->base.hpd_irq = true;
|
||||
|
||||
if (lphw_hpd->cb && lphw_hpd->cb->attention)
|
||||
lphw_hpd->cb->attention(lphw_hpd->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dp_lphw_hpd_register(struct dp_hpd *dp_hpd)
|
||||
{
|
||||
struct dp_lphw_hpd_private *lphw_hpd;
|
||||
int rc = 0;
|
||||
|
||||
if (!dp_hpd)
|
||||
return -EINVAL;
|
||||
|
||||
lphw_hpd = container_of(dp_hpd, struct dp_lphw_hpd_private, base);
|
||||
|
||||
lphw_hpd->hpd = gpio_get_value_cansleep(lphw_hpd->gpio_cfg.gpio);
|
||||
|
||||
rc = devm_request_threaded_irq(lphw_hpd->dev, lphw_hpd->irq, NULL,
|
||||
dp_tlmm_isr,
|
||||
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
|
||||
"dp-gpio-intp", lphw_hpd);
|
||||
if (rc) {
|
||||
DP_ERR("Failed to request INTP threaded IRQ: %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
enable_irq_wake(lphw_hpd->irq);
|
||||
|
||||
if (lphw_hpd->hpd)
|
||||
queue_work(lphw_hpd->connect_wq, &lphw_hpd->connect);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void dp_lphw_hpd_deinit(struct dp_lphw_hpd_private *lphw_hpd)
|
||||
{
|
||||
struct dp_parser *parser = lphw_hpd->parser;
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < parser->mp[DP_PHY_PM].num_vreg; i++) {
|
||||
|
||||
if (!strcmp(parser->mp[DP_PHY_PM].vreg_config[i].vreg_name,
|
||||
"hpd-pwr")) {
|
||||
/* disable the hpd-pwr voltage regulator */
|
||||
if (msm_dss_enable_vreg(
|
||||
&parser->mp[DP_PHY_PM].vreg_config[i], 1,
|
||||
false))
|
||||
DP_ERR("hpd-pwr vreg not disabled\n");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void dp_lphw_hpd_init(struct dp_lphw_hpd_private *lphw_hpd)
|
||||
{
|
||||
struct dp_pinctrl pinctrl = {0};
|
||||
struct dp_parser *parser = lphw_hpd->parser;
|
||||
int i = 0, rc = 0;
|
||||
|
||||
for (i = 0; i < parser->mp[DP_PHY_PM].num_vreg; i++) {
|
||||
|
||||
if (!strcmp(parser->mp[DP_PHY_PM].vreg_config[i].vreg_name,
|
||||
"hpd-pwr")) {
|
||||
/* enable the hpd-pwr voltage regulator */
|
||||
if (msm_dss_enable_vreg(
|
||||
&parser->mp[DP_PHY_PM].vreg_config[i], 1,
|
||||
true))
|
||||
DP_ERR("hpd-pwr vreg not enabled\n");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pinctrl.pin = devm_pinctrl_get(lphw_hpd->dev);
|
||||
|
||||
if (!IS_ERR_OR_NULL(pinctrl.pin)) {
|
||||
pinctrl.state_hpd_active = pinctrl_lookup_state(pinctrl.pin,
|
||||
"mdss_dp_hpd_active");
|
||||
|
||||
if (!IS_ERR_OR_NULL(pinctrl.state_hpd_active)) {
|
||||
rc = pinctrl_select_state(pinctrl.pin,
|
||||
pinctrl.state_hpd_active);
|
||||
if (rc)
|
||||
DP_ERR("failed to set hpd_active state\n");
|
||||
}
|
||||
pinctrl.state_hpd_tlmm = pinctrl.state_hpd_ctrl = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int dp_lphw_hpd_create_workqueue(struct dp_lphw_hpd_private *lphw_hpd)
|
||||
{
|
||||
lphw_hpd->connect_wq = create_singlethread_workqueue("dp_lphw_work");
|
||||
if (IS_ERR_OR_NULL(lphw_hpd->connect_wq)) {
|
||||
DP_ERR("Error creating connect_wq\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
INIT_WORK(&lphw_hpd->connect, dp_lphw_hpd_connect);
|
||||
INIT_WORK(&lphw_hpd->disconnect, dp_lphw_hpd_disconnect);
|
||||
INIT_WORK(&lphw_hpd->attention, dp_lphw_hpd_attention);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct dp_hpd *dp_lphw_hpd_get(struct device *dev, struct dp_parser *parser,
|
||||
struct dp_catalog_hpd *catalog, struct dp_hpd_cb *cb)
|
||||
{
|
||||
int rc = 0;
|
||||
const char *hpd_gpio_name = "qcom,dp-hpd-gpio";
|
||||
struct dp_lphw_hpd_private *lphw_hpd = NULL;
|
||||
unsigned int gpio;
|
||||
|
||||
if (!dev || !parser || !cb) {
|
||||
DP_ERR("invalid device\n");
|
||||
rc = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
gpio = of_get_named_gpio(dev->of_node, hpd_gpio_name, 0);
|
||||
if (!gpio_is_valid(gpio)) {
|
||||
DP_DEBUG("%s gpio not specified\n", hpd_gpio_name);
|
||||
rc = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
lphw_hpd = devm_kzalloc(dev, sizeof(*lphw_hpd), GFP_KERNEL);
|
||||
if (!lphw_hpd) {
|
||||
rc = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
lphw_hpd->gpio_cfg.gpio = gpio;
|
||||
strlcpy(lphw_hpd->gpio_cfg.gpio_name, hpd_gpio_name,
|
||||
sizeof(lphw_hpd->gpio_cfg.gpio_name));
|
||||
lphw_hpd->gpio_cfg.value = 0;
|
||||
|
||||
rc = gpio_request(lphw_hpd->gpio_cfg.gpio,
|
||||
lphw_hpd->gpio_cfg.gpio_name);
|
||||
if (rc) {
|
||||
DP_ERR("%s: failed to request gpio\n", hpd_gpio_name);
|
||||
goto gpio_error;
|
||||
}
|
||||
gpio_direction_input(lphw_hpd->gpio_cfg.gpio);
|
||||
|
||||
lphw_hpd->dev = dev;
|
||||
lphw_hpd->cb = cb;
|
||||
lphw_hpd->irq = gpio_to_irq(lphw_hpd->gpio_cfg.gpio);
|
||||
|
||||
rc = dp_lphw_hpd_create_workqueue(lphw_hpd);
|
||||
if (rc) {
|
||||
DP_ERR("Failed to create a dp_hpd workqueue\n");
|
||||
goto gpio_error;
|
||||
}
|
||||
|
||||
lphw_hpd->parser = parser;
|
||||
lphw_hpd->catalog = catalog;
|
||||
lphw_hpd->base.isr = dp_lphw_hpd_isr;
|
||||
lphw_hpd->base.host_init = dp_lphw_hpd_host_init;
|
||||
lphw_hpd->base.host_deinit = dp_lphw_hpd_host_deinit;
|
||||
lphw_hpd->base.simulate_connect = dp_lphw_hpd_simulate_connect;
|
||||
lphw_hpd->base.simulate_attention = dp_lphw_hpd_simulate_attention;
|
||||
lphw_hpd->base.register_hpd = dp_lphw_hpd_register;
|
||||
|
||||
dp_lphw_hpd_init(lphw_hpd);
|
||||
|
||||
return &lphw_hpd->base;
|
||||
|
||||
gpio_error:
|
||||
devm_kfree(dev, lphw_hpd);
|
||||
error:
|
||||
return ERR_PTR(rc);
|
||||
}
|
||||
|
||||
void dp_lphw_hpd_put(struct dp_hpd *dp_hpd)
|
||||
{
|
||||
struct dp_lphw_hpd_private *lphw_hpd;
|
||||
|
||||
if (!dp_hpd)
|
||||
return;
|
||||
|
||||
lphw_hpd = container_of(dp_hpd, struct dp_lphw_hpd_private, base);
|
||||
|
||||
dp_lphw_hpd_deinit(lphw_hpd);
|
||||
gpio_free(lphw_hpd->gpio_cfg.gpio);
|
||||
devm_kfree(lphw_hpd->dev, lphw_hpd);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user