From cbaf4c5ae35023434c42edfe4cff64bf3d866d6b Mon Sep 17 00:00:00 2001 From: Arun Kannan Date: Tue, 31 Jan 2012 00:17:14 +0200 Subject: [PATCH] Addition of the OTM HDMI driver for Medfield. This is a modular, reusable driver for HDMI used across platforms. This driver has already achieved HDMI certification on the Greenridge platform, and was also reused on the Medfield honeycomb stack. Signed-off-by: Arun Kannan Signed-off-by: Kirill A. Shutemov --- drivers/staging/mrst/Kconfig | 25 + drivers/staging/mrst/drv/otm_hdmi/Makefile | 242 +++ .../mrst/drv/otm_hdmi/ipil/common/ipil_hdcp.c | 139 ++ .../mrst/drv/otm_hdmi/ipil/common/ipil_internal.h | 146 ++ .../mrst/drv/otm_hdmi/ipil/common/otm_ipil_main.c | 755 +++++++ .../mrst/drv/otm_hdmi/ipil/include/hdcp_rx_defs.h | 146 ++ .../mrst/drv/otm_hdmi/ipil/include/hdmi_hal.h | 1207 +++++++++++ .../mrst/drv/otm_hdmi/ipil/include/ipil_hdcp_api.h | 84 + .../mrst/drv/otm_hdmi/ipil/include/ipil_hdmi.h | 288 +++ .../otm_hdmi/ipil/specific/include/ips_hdcp_api.h | 86 + .../drv/otm_hdmi/ipil/specific/include/ips_hdmi.h | 209 ++ .../drv/otm_hdmi/ipil/specific/mfld/ips_hdcp.c | 369 ++++ .../drv/otm_hdmi/ipil/specific/mfld/ips_hdmi.c | 815 +++++++ .../otm_hdmi/ipil/specific/mfld/mfld_hdcp_reg.h | 188 ++ .../otm_hdmi/ipil/specific/mfld/mfld_hdmi_reg.h | 110 + .../drv/otm_hdmi/ipil/specific/mfld/mfld_utils.h | 71 + .../mrst/drv/otm_hdmi/os/android/android_hdmi.c | 1538 ++++++++++++++ .../drv/otm_hdmi/os/android/include/android_hdmi.h | 397 ++++ .../staging/mrst/drv/otm_hdmi/pil/common/edid.c | 1365 ++++++++++++ .../staging/mrst/drv/otm_hdmi/pil/common/edid.h | 151 ++ .../mrst/drv/otm_hdmi/pil/common/edid_internal.h | 180 ++ .../mrst/drv/otm_hdmi/pil/common/edid_print.c | 358 ++++ .../staging/mrst/drv/otm_hdmi/pil/common/hdcp.c | 859 ++++++++ .../mrst/drv/otm_hdmi/pil/common/hdmi_internal.h | 306 +++ .../mrst/drv/otm_hdmi/pil/common/hdmi_timings.h | 121 ++ .../mrst/drv/otm_hdmi/pil/common/infoframes.c | 275 +++ .../mrst/drv/otm_hdmi/pil/common/infoframes_api.h | 89 + .../mrst/drv/otm_hdmi/pil/common/mode_info.c | 1151 ++++++++++ .../mrst/drv/otm_hdmi/pil/common/otm_hdmi.c | 2235 ++++++++++++++++++++ .../mrst/drv/otm_hdmi/pil/include/hdcp_api.h | 81 + .../mrst/drv/otm_hdmi/pil/include/otm_hdmi.h | 358 ++++ .../mrst/drv/otm_hdmi/pil/include/otm_hdmi_defs.h | 1167 ++++++++++ .../mrst/drv/otm_hdmi/pil/include/otm_hdmi_types.h | 463 ++++ .../drv/otm_hdmi/pil/specific/include/ps_hdmi.h | 91 + .../mrst/drv/otm_hdmi/pil/specific/mfld/ps_hdmi.c | 186 ++ .../otm_hdmi/pil/specific/mfld/ps_hdmi_tablet.c | 89 + 36 files changed, 16340 insertions(+) create mode 100644 drivers/staging/mrst/drv/otm_hdmi/Makefile create mode 100644 drivers/staging/mrst/drv/otm_hdmi/ipil/common/ipil_hdcp.c create mode 100644 drivers/staging/mrst/drv/otm_hdmi/ipil/common/ipil_internal.h create mode 100644 drivers/staging/mrst/drv/otm_hdmi/ipil/common/otm_ipil_main.c create mode 100644 drivers/staging/mrst/drv/otm_hdmi/ipil/include/hdcp_rx_defs.h create mode 100644 drivers/staging/mrst/drv/otm_hdmi/ipil/include/hdmi_hal.h create mode 100644 drivers/staging/mrst/drv/otm_hdmi/ipil/include/ipil_hdcp_api.h create mode 100644 drivers/staging/mrst/drv/otm_hdmi/ipil/include/ipil_hdmi.h create mode 100644 drivers/staging/mrst/drv/otm_hdmi/ipil/specific/include/ips_hdcp_api.h create mode 100644 drivers/staging/mrst/drv/otm_hdmi/ipil/specific/include/ips_hdmi.h create mode 100644 drivers/staging/mrst/drv/otm_hdmi/ipil/specific/mfld/ips_hdcp.c create mode 100644 drivers/staging/mrst/drv/otm_hdmi/ipil/specific/mfld/ips_hdmi.c create mode 100644 drivers/staging/mrst/drv/otm_hdmi/ipil/specific/mfld/mfld_hdcp_reg.h create mode 100644 drivers/staging/mrst/drv/otm_hdmi/ipil/specific/mfld/mfld_hdmi_reg.h create mode 100644 drivers/staging/mrst/drv/otm_hdmi/ipil/specific/mfld/mfld_utils.h create mode 100644 drivers/staging/mrst/drv/otm_hdmi/os/android/android_hdmi.c create mode 100644 drivers/staging/mrst/drv/otm_hdmi/os/android/include/android_hdmi.h create mode 100644 drivers/staging/mrst/drv/otm_hdmi/pil/common/edid.c create mode 100644 drivers/staging/mrst/drv/otm_hdmi/pil/common/edid.h create mode 100644 drivers/staging/mrst/drv/otm_hdmi/pil/common/edid_internal.h create mode 100644 drivers/staging/mrst/drv/otm_hdmi/pil/common/edid_print.c create mode 100644 drivers/staging/mrst/drv/otm_hdmi/pil/common/hdcp.c create mode 100644 drivers/staging/mrst/drv/otm_hdmi/pil/common/hdmi_internal.h create mode 100644 drivers/staging/mrst/drv/otm_hdmi/pil/common/hdmi_timings.h create mode 100644 drivers/staging/mrst/drv/otm_hdmi/pil/common/infoframes.c create mode 100644 drivers/staging/mrst/drv/otm_hdmi/pil/common/infoframes_api.h create mode 100644 drivers/staging/mrst/drv/otm_hdmi/pil/common/mode_info.c create mode 100644 drivers/staging/mrst/drv/otm_hdmi/pil/common/otm_hdmi.c create mode 100644 drivers/staging/mrst/drv/otm_hdmi/pil/include/hdcp_api.h create mode 100644 drivers/staging/mrst/drv/otm_hdmi/pil/include/otm_hdmi.h create mode 100644 drivers/staging/mrst/drv/otm_hdmi/pil/include/otm_hdmi_defs.h create mode 100644 drivers/staging/mrst/drv/otm_hdmi/pil/include/otm_hdmi_types.h create mode 100644 drivers/staging/mrst/drv/otm_hdmi/pil/specific/include/ps_hdmi.h create mode 100644 drivers/staging/mrst/drv/otm_hdmi/pil/specific/mfld/ps_hdmi.c create mode 100644 drivers/staging/mrst/drv/otm_hdmi/pil/specific/mfld/ps_hdmi_tablet.c diff --git a/drivers/staging/mrst/Kconfig b/drivers/staging/mrst/Kconfig index 41ca4ab..e61f0a2 100644 --- a/drivers/staging/mrst/Kconfig +++ b/drivers/staging/mrst/Kconfig @@ -88,6 +88,31 @@ config MDFD_HDMI help xxxxxx +choice + prompt "HDMI board support" + depends on MDFD_HDMI + default MDFD_HDMI_REDRIDGE + +config MDFD_HDMI_GREENRIDGE + bool "Greenridge HDMI support" + depends on MDFD_HDMI + help + HDMI support for Greenridge. + +config MDFD_HDMI_REDRIDGE + bool "Red Ridge HDMI support" + depends on MDFD_HDMI + help + HDMI support for Red Ridge. + +config MDFD_HDMI_PR2 + bool "PR2 HDMI support" + depends on MDFD_HDMI + help + HDMI support for PR2. + +endchoice + config MDFD_GL3 bool "Enable GL3 Cache for GUNIT" depends on DRM_MDFLD diff --git a/drivers/staging/mrst/drv/otm_hdmi/Makefile b/drivers/staging/mrst/drv/otm_hdmi/Makefile new file mode 100644 index 0000000..24ac818 --- /dev/null +++ b/drivers/staging/mrst/drv/otm_hdmi/Makefile @@ -0,0 +1,242 @@ +######################################################################## +# +# This file is provided under a dual BSD/GPLv2 license. When using or +# redistributing this file, you may do so under either license. +# +# GPL LICENSE SUMMARY +# +# Copyright(c) 2011 Intel Corporation. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of version 2 of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +# The full GNU General Public License is included in this distribution +# in the file called LICENSE.GPL. +# +# Contact Information: +# Intel Corporation +# 2200 Mission College Blvd. +# Santa Clara, CA 97052 +# +# BSD LICENSE +# +# Copyright(c) 2011 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +######################################################################## + +DISP_ROOT=$(CURDIR) + +TARGET = otm_hdmi + +INCDIR = drivers/staging/mrst/ +OTM_HDMI_INCDIR = $(INCDIR)/drv/otm_hdmi + +include_dirs := \ + -I$(INCDIR)/pvr/include4 \ + -I$(INCDIR)/pvr/services4/include \ + -I$(INCDIR)/pvr/services4/include/env/linux \ + -I$(INCDIR)/pvr/services4/srvkm/env/linux \ + -I$(INCDIR)/pvr/services4/srvkm/include \ + -I$(INCDIR)/pvr/services4/srvkm/bridged \ + -I$(INCDIR)/pvr/services4/system/include \ + -I$(INCDIR)/pvr/services4/srvkm/hwdefs \ + -I$(INCDIR)/pvr/services4/srvkm/bridged/sgx \ + -I$(INCDIR)/pvr/services4/srvkm/devices/sgx \ + -I$(INCDIR)/pvr/services4/srvkm/common \ + -I$(INCDIR)/pvr/services4/3rdparty/linux_framebuffer_drm \ + -I$(INCDIR)/ \ + -I$(INCDIR)/drv \ + -I$(INCDIR)/bc_video \ + -I$(INCDIR)/imgv \ + -Iinclude/linux \ + -Iinclude/drm \ + -I$(OTM_HDMI_INCDIR)/os/include \ + -I$(OTM_HDMI_INCDIR)/os/android/include \ + -I$(OTM_HDMI_INCDIR)/pil/include \ + -I$(OTM_HDMI_INCDIR)/pil/common \ + -I$(OTM_HDMI_INCDIR)/pil/specific/include \ + -I$(OTM_HDMI_INCDIR)/ipil/include \ + -I$(OTM_HDMI_INCDIR)/ipil/common \ + -I$(OTM_HDMI_INCDIR)/ipil/specific/include \ + +ccflags-y += $(include_dirs) +ifeq ($(CONFIG_MDFD_HDMI_GREENRIDGE),y) + ccflags-y += -I$(INCDIR)/pvr/services4/system/intel_drm -DSGX535 -DSUPPORT_SGX535 -DSGX_CORE_REV=121 -DANDROID -D_linux_ -D__KERNEL__ -DMRST +else ifeq ($(CONFIG_MDFD_HDMI_REDRIDGE),y) + ccflags-y += -I$(INCDIR)/pvr/services4/system/intel_drm -I$(INCDIR)/pvr/services4/system/unified -DSGX540 -DSUPPORT_SGX540 -DSGX_CORE_REV=121 -DANDROID -D_linux_ -D__KERNEL__ +else ifeq ($(CONFIG_MDFD_HDMI_PR2),y) + ccflags-y += -I$(INCDIR)/pvr/services4/system/intel_drm -DSGX540 -DSUPPORT_SGX540 -DSGX_CORE_REV=121 -DANDROID -D_linux_ -D__KERNEL__ +endif + +ccflags-y += \ + -DLINUX \ + -DPVRSRV_MODNAME="\"pvrsrvkm\"" +ifeq ($(CONFIG_MDFD_HDMI_GREENRIDGE),y) +ccflags-y += \ + -DPVR_BUILD_DIR="\"pc_i686_moorestown_linux\"" +endif +ifeq ($(CONFIG_MDFD_HDMI_REDRIDGE),y) +ccflags-y += \ + -DPVR_BUILD_DIR="\"pc_i686_medfield_linux\"" \ + -DMFLD_HDMI_DV1 \ + -UOTM_HDMI_HDCP_ENABLE # enable HDCP by defining this flag +endif +ifeq ($(CONFIG_MDFD_HDMI_PR2),y) +ccflags-y += \ + -DPVR_BUILD_DIR="\"pc_i686_medfield_linux\"" \ + -DMFLD_HDMI_PR3 \ + -UOTM_HDMI_HDCP_ENABLE # enable HDCP by defining this flag +endif +ccflags-y += \ + -DPVR_LINUX_MISR_USING_WORKQUEUE \ + -DSERVICES4 \ + -D_XOPEN_SOURCE=600 \ + -DPVR2D_VALIDATE_INPUT_PARAMS \ + -DDISPLAY_CONTROLLER=mrstlfb \ + -UDEBUG_LOG_PATH_TRUNCATE \ + -DSUPPORT_LIBDRM_LITE \ + -DOPK_FALLBACK="" \ + -DSUPPORT_ANDROID_PLATFORM \ + -DPROFILE_COMM \ + -DSUPPORT_ANDROID_PLATFORM \ + -DSUPPORT_GRAPHICS_HAL \ + -DPVR_SECURE_FD_EXPORT \ + -DSUPPORT_SRVINIT \ + -DSUPPORT_SGX \ + -DSUPPORT_PERCONTEXT_PB \ + -DSUPPORT_LINUX_X86_WRITECOMBINE \ + -DTRANSFER_QUEUE \ + -DSUPPORT_DRI_DRM \ + -DSUPPORT_DRI_DRM_EXT \ + -DSUPPORT_DRI_DRM_NO_DROPMASTER \ + -DSYS_USING_INTERRUPTS \ + -DSUPPORT_HW_RECOVERY \ + -DSUPPORT_ACTIVE_POWER_MANAGEMENT \ + -DPVR_SECURE_HANDLES \ + -DLDM_PCI \ + -DUSE_PTHREADS \ + -DSUPPORT_SGX_EVENT_OBJECT \ + -DSUPPORT_SGX_HWPERF \ + -DSUPPORT_SGX_LOW_LATENCY_SCHEDULING \ + -DSUPPORT_LINUX_X86_PAT \ + -DPVR_PROC_USE_SEQ_FILE \ + -DSUPPORT_CPU_CACHED_BUFFERS \ + -DDRM_PVR_RESERVED_INTEL_ORDER \ + -DDRM_PVR_USE_INTEL_FB \ + -DSUPPORT_MEMINFO_IDS \ + -DSUPPORT_SGX_NEW_STATUS_VALS + +ccflags-$(CONFIG_DRM_MID_RELEASE) += -DBUILD="\"release\"" -DPVR_BUILD_TYPE="\"release\"" -DRELEASE +ccflags-$(CONFIG_DRM_MID_DEBUG) += -DBUILD="\"debug\"" -DPVR_BUILD_TYPE="\"debug\"" -DDEBUG -DDEBUG_LINUX_MEM_AREAS -DDEBUG_LINUX_MEMORY_ALLOCATIONS -DDEBUG_LINUX_MMAP_AREAS -DDEBUG_BRIDGE_KM +ccflags-$(CONFIG_PCI_MSI) += -DCONFIG_PCI_MSI + +ifeq ($(CONFIG_MDFD_HDMI_REDRIDGE),y) + GL3_EXTERNAL_SYSTEM_CACHE ?=1 + ifeq ($(GL3_EXTERNAL_SYSTEM_CACHE),1) + SUPPORT_EXTERNAL_SYSTEM_CACHE = y + CONFIG_MDFD_GL3 = y + else + SUPPORT_EXTERNAL_SYSTEM_CACHE = + CONFIG_MDFD_GL3 = + endif +endif + +ifeq ($(CONFIG_MDFD_HDMI_PR2),y) + GL3_EXTERNAL_SYSTEM_CACHE ?=1 + ifeq ($(GL3_EXTERNAL_SYSTEM_CACHE),1) + SUPPORT_EXTERNAL_SYSTEM_CACHE = y + CONFIG_MDFD_GL3 = y + else + SUPPORT_EXTERNAL_SYSTEM_CACHE = + CONFIG_MDFD_GL3 = + endif +endif + +ccflags-$(SUPPORT_EXTERNAL_SYSTEM_CACHE) += -DSUPPORT_EXTERNAL_SYSTEM_CACHE -DCONFIG_MDFD_GL3 +ccflags-y += $(INCLUDE_PATH) $(include_dirs) +#uncomment for debug prints +#ccflags-y += -DDEBUG + +ifeq ($(CONFIG_MDFD_HDMI_GREENRIDGE),y) + INCLUDE_PATH += -I$(OTM_HDMI_INCDIR)/pil/specific/oktl + INCLUDE_PATH += -I$(OTM_HDMI_INCDIR)/ipil/specific/oktl-sdv +else ifeq ($(CONFIG_MDFD_HDMI_REDRIDGE),y) + INCLUDE_PATH += -I$(OTM_HDMI_INCDIR)/pil/specific/mfld + INCLUDE_PATH += -I$(OTM_HDMI_INCDIR)/ipil/specific/mfld +else ifeq ($(CONFIG_MDFD_HDMI_PR2),y) + INCLUDE_PATH += -I$(OTM_HDMI_INCDIR)/pil/specific/mfld + INCLUDE_PATH += -I$(OTM_HDMI_INCDIR)/ipil/specific/mfld +endif + +# Platform independent library +$(TARGET)-y := pil/common/otm_hdmi.o +$(TARGET)-y += pil/common/mode_info.o +$(TARGET)-y += pil/common/hdcp.o +$(TARGET)-y += pil/common/edid.o +$(TARGET)-y += pil/common/edid_print.o +$(TARGET)-y += pil/common/infoframes.o + +# IP independent library +$(TARGET)-y += ipil/common/otm_ipil_main.o +$(TARGET)-y += ipil/common/ipil_hdcp.o + +# OS specific library +$(TARGET)-y += os/android/android_hdmi.o +ifneq ($(CONFIG_MDFD_HDMI_REDRIDGE),y) +$(TARGET)-y += os/android/android_hdmi_sw_scale.o +endif + +ifeq ($(CONFIG_MDFD_HDMI_GREENRIDGE),y) + $(TARGET)-y += ipil/specific/oktl-sdv/ips_hdmi.o + $(TARGET)-y += ipil/specific/oktl-sdv/ips_hdcp.o + $(TARGET)-y += pil/specific/oktl/ps_hdmi.o + obj-$(CONFIG_DRM_MRST) += $(TARGET).o +else ifeq ($(CONFIG_MDFD_HDMI_REDRIDGE),y) + $(TARGET)-y += ipil/specific/mfld/ips_hdmi.o + $(TARGET)-y += ipil/specific/mfld/ips_hdcp.o + $(TARGET)-y += pil/specific/mfld/ps_hdmi.o + $(TARGET)-y += pil/specific/mfld/ps_hdmi_tablet.o + obj-$(CONFIG_DRM_MDFLD) += $(TARGET).o +else ifeq ($(CONFIG_MDFD_HDMI_PR2),y) + $(TARGET)-y += ipil/specific/mfld/ips_hdmi.o + $(TARGET)-y += ipil/specific/mfld/ips_hdcp.o + $(TARGET)-y += pil/specific/mfld/ps_hdmi.o + $(TARGET)-y += pil/specific/mfld/ps_hdmi_phone.o + obj-$(CONFIG_DRM_MDFLD) += $(TARGET).o +endif diff --git a/drivers/staging/mrst/drv/otm_hdmi/ipil/common/ipil_hdcp.c b/drivers/staging/mrst/drv/otm_hdmi/ipil/common/ipil_hdcp.c new file mode 100644 index 0000000..146759e --- /dev/null +++ b/drivers/staging/mrst/drv/otm_hdmi/ipil/common/ipil_hdcp.c @@ -0,0 +1,139 @@ +/* + + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2011 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + + Intel Corporation + 2200 Mission College Blvd. + Santa Clara, CA 95054 + + BSD LICENSE + + Copyright(c) 2011 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + + +#include +#include "hdcp_rx_defs.h" +#include "ips_hdcp_api.h" + + +bool ipil_hdcp_is_ready(void) +{ + return ips_hdcp_is_ready(); +} + +bool ipil_hdcp_get_an(uint8_t *an, uint32_t size) +{ + bool ret = false; + if (an != NULL && size == HDCP_AN_SIZE) { + ips_hdcp_get_an(an); + ret = true; + } + return ret; +} + +bool ipil_hdcp_get_aksv(uint8_t *aksv, uint32_t size) +{ + bool ret = false; + if (aksv != NULL && size == HDCP_KSV_SIZE) { + ips_hdcp_get_aksv(aksv); + ret = true; + } + return ret; +} + +bool ipil_hdcp_set_repeater(bool present) +{ + return ips_hdcp_set_repeater(present); +} + +bool ipil_hdcp_set_bksv(uint8_t *bksv) +{ + return ips_hdcp_set_bksv(bksv); +} + +bool ipil_hdcp_start_authentication(void) +{ + return ips_hdcp_start_authentication(); +} + +bool ipil_hdcp_is_r0_ready(void) +{ + return ips_hdcp_is_r0_ready(); +} + +bool ipil_hdcp_does_ri_match(uint16_t rx_ri) +{ + return ips_hdcp_does_ri_match(rx_ri); +} + +bool ipil_hdcp_enable_encryption(void) +{ + return ips_hdcp_enable_encryption(); +} + +bool ipil_hdcp_disable(void) +{ + return ips_hdcp_disable(); +} + +bool ipil_hdcp_device_can_authenticate(void) +{ + return ips_hdcp_device_can_authenticate(); +} + +bool ipil_hdcp_init(void) +{ + return ips_hdcp_init(); +} + diff --git a/drivers/staging/mrst/drv/otm_hdmi/ipil/common/ipil_internal.h b/drivers/staging/mrst/drv/otm_hdmi/ipil/common/ipil_internal.h new file mode 100644 index 0000000..ad79512 --- /dev/null +++ b/drivers/staging/mrst/drv/otm_hdmi/ipil/common/ipil_internal.h @@ -0,0 +1,146 @@ +/* + + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2011 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + + Intel Corporation + 2200 Mission College Blvd. + Santa Clara, CA 95054 + + BSD LICENSE + + Copyright(c) 2011 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef __IPIL_INTERNAL_H +#define __IPIL_INTERNAL_H + +#include "ips_hdmi.h" + +/* hdmi display related registers */ +#define IPIL_DSPBASE IPS_DSPBASE +#define IPIL_DSPBSIZE IPS_DSPBSIZE +#define IPIL_PIPEBSRC IPS_PIPEBSRC +#define IPIL_DSPBPOS IPS_DSPBPOS +#define IPIL_PFIT_CONTROL IPS_PFIT_CONTROL +#define IPIL_HTOTAL_B IPS_HTOTAL_B +#define IPIL_VTOTAL_B IPS_VTOTAL_B +#define IPIL_HBLANK_B IPS_HBLANK_B +#define IPIL_VBLANK_B IPS_VBLANK_B +#define IPIL_HSYNC_B IPS_HSYNC_B +#define IPIL_VSYNC_B IPS_VSYNC_B +#define IPIL_DPLL_B IPS_DPLL_B +#define IPIL_DPLL_DIV0 IPS_DPLL_DIV0 +#define IPIL_PIPEBCONF IPS_PIPEBCONF +#define IPIL_DSPBCNTR IPS_DSPBCNTR +#define IPIL_HDMIB_CONTROL IPS_HDMIB_CONTROL +#define IPIL_DSPBSTRIDE IPS_DSPBSTRIDE +#define IPIL_DSPBLINOFF IPS_DSPBLINOFF +#define IPIL_DSPBTILEOFF IPS_DSPBTILEOFF +#define IPIL_DSPBSURF IPS_DSPBSURF +#define IPIL_DSPBSTAT IPS_DSPBSTAT +#define IPIL_PALETTE_B IPS_PALETTE_B +#define IPIL_PFIT_PGM_RATIOS IPS_PFIT_PGM_RATIOS +#define IPIL_HDMIPHYMISCCTL IPS_HDMIPHYMISCCTL + +#define IPIL_VGACNTRL 0x71400 +#define IPIL_DPLL_PWR_GATE_EN (1<<30) +#define IPIL_DPLL_VCO_ENABLE (1<<31) +#define IPIL_VGA_DISP_DISABLE (1<<31) + +/* TODO: revisit this. make then IP specific */ +#define IPIL_PFIT_ENABLE (1 << 31) +#define IPIL_PFIT_PIPE_SHIFT 29 +#define IPIL_PFIT_PIPE_SELECT_B (1 << IPIL_PFIT_PIPE_SHIFT) +#define IPIL_PFIT_SCALING_AUTO (0 << 26) +#define IPIL_PFIT_SCALING_PILLARBOX (1 << 27) +#define IPIL_PFIT_SCALING_LETTERBOX (3 << 26) + +#define IPIL_DPLL_VCO_ENABLE (1 << 31) +#define IPIL_PWR_GATE_EN (1 << 30) +#define IPIL_PIPECONF_PLL_LOCK (1<<29) +#define IPIL_DSP_PLANE_PIPE_POS 24 +#define IPIL_DSP_PLANE_ENABLE (1<<31) +#define IPIL_PIPEACONF_ENABLE (1<<31) +#define IPIL_PIPEACONF_PIPE_STATE (1<<30) +#define IPIL_PIPECONF_PLANE_OFF (1<<19) +#define IPIL_PIPECONF_CURSOR_OFF (1<<18) +#define IPIL_P1_MASK (0x1FF << 17) +#define IPIL_HDMIB_PORT_EN (1 << 31) +#define IPIL_HDMIB_PIPE_B_SELECT (1 << 30) +#define IPIL_HDMIB_NULL_PACKET (1 << 9) +#define IPIL_HDMIB_AUDIO_ENABLE (1 << 6) +#define IPIL_HDMI_PHY_POWER_DOWN 0x7f + +#define IPIL_TIMING_FLAG_PHSYNC (1<<0) +#define IPIL_TIMING_FLAG_NHSYNC (1<<1) +#define IPIL_TIMING_FLAG_PVSYNC (1<<2) +#define IPIL_TIMING_FLAG_NVSYNC (1<<3) + +struct ipil_clock_t { + int dot; + int m; + int p1; +}; + +struct ipil_range_t { + int min, max; +}; + +struct ipil_clock_limits_t { + struct ipil_range_t dot, m, p1; +}; + +void hdmi_write32(uint32_t reg, uint32_t val); +uint32_t hdmi_read32(uint32_t reg); + +#endif /* __IPIL_INTERNAL_H */ diff --git a/drivers/staging/mrst/drv/otm_hdmi/ipil/common/otm_ipil_main.c b/drivers/staging/mrst/drv/otm_hdmi/ipil/common/otm_ipil_main.c new file mode 100644 index 0000000..34b1529 --- /dev/null +++ b/drivers/staging/mrst/drv/otm_hdmi/ipil/common/otm_ipil_main.c @@ -0,0 +1,755 @@ +/* + + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2011 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + + Intel Corporation + 2200 Mission College Blvd. + Santa Clara, CA 95054 + + BSD LICENSE + + Copyright(c) 2011 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ +#include +#include +#include +#include +#include +#include "ipil_internal.h" + +#include "otm_hdmi.h" +#include "otm_hdmi_types.h" + +#include "ips_hdmi.h" + +static hdmi_device_t *hdmi_dev; + +otm_hdmi_ret_t ipil_hdmi_set_hdmi_dev(hdmi_device_t *dev) +{ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + if (!dev) + rc = OTM_HDMI_ERR_NULL_ARG; + else + hdmi_dev = dev; + return rc; +} + +uint32_t hdmi_read32(uint32_t reg) +{ + if (hdmi_dev) + return readl((const void *)(hdmi_dev->io_address + reg)); + + return 0; +} + +void hdmi_write32(uint32_t reg, uint32_t val) +{ + if (hdmi_dev) + writel(val, (void *)(hdmi_dev->io_address + reg)); +} + +otm_hdmi_ret_t ipil_hdmi_decide_I2C_HW(hdmi_context_t *ctx) +{ + return ips_hdmi_decide_I2C_HW(ctx); +} + +otm_hdmi_ret_t ipil_hdmi_general_5V_enable(hdmi_device_t *dev) +{ + return ips_hdmi_general_5V_enable(dev); +} + +otm_hdmi_ret_t ipil_hdmi_general_5V_disable(hdmi_device_t *dev) +{ + return ips_hdmi_general_5V_disable(dev); +} + +otm_hdmi_ret_t ipil_hdmi_set_program_clocks(hdmi_context_t *ctx, + unsigned int dclk) +{ + return ips_hdmi_set_program_clocks(ctx, dclk); +} + +otm_hdmi_ret_t ipil_hdmi_audio_init(hdmi_context_t *ctx) +{ + return ips_hdmi_audio_init(ctx); +} + +otm_hdmi_ret_t ipil_hdmi_audio_deinit(hdmi_context_t *ctx) +{ + return ips_hdmi_audio_deinit(ctx); +} + +otm_hdmi_ret_t ipil_hdmi_general_unit_enable(hdmi_device_t *dev) +{ + return ips_hdmi_general_unit_enable(dev); +} + +otm_hdmi_ret_t ipil_hdmi_general_unit_disable(hdmi_device_t *dev) +{ + return ips_hdmi_general_unit_disable(dev); +} + +otm_hdmi_ret_t ipil_hdmi_general_hdcp_clock_enable(hdmi_device_t *dev) +{ + return ips_hdmi_general_hdcp_clock_enable(dev); +} + +otm_hdmi_ret_t ipil_hdmi_general_hdcp_clock_disable(hdmi_device_t *dev) +{ + return ips_hdmi_general_hdcp_clock_disable(dev); +} + +otm_hdmi_ret_t ipil_hdmi_general_audio_clock_enable(hdmi_device_t *dev) +{ + return ips_hdmi_general_audio_clock_enable(dev); +} + +otm_hdmi_ret_t ipil_hdmi_general_audio_clock_disable(hdmi_device_t *dev) +{ + return ips_hdmi_general_audio_clock_disable(dev); +} + +otm_hdmi_ret_t ipil_hdmi_general_pixel_clock_enable(hdmi_device_t *dev) +{ + return ips_hdmi_general_pixel_clock_enable(dev); +} + +otm_hdmi_ret_t ipil_hdmi_general_pixel_clock_disable(hdmi_device_t *dev) +{ + return ips_hdmi_general_pixel_clock_disable(dev); +} + +otm_hdmi_ret_t ipil_hdmi_general_tdms_clock_enable(hdmi_device_t *dev) +{ + return ips_hdmi_general_tdms_clock_enable(dev); +} + +otm_hdmi_ret_t ipil_hdmi_general_tdms_clock_disable(hdmi_device_t *dev) +{ + return ips_hdmi_general_tdms_clock_disable(dev); +} + +otm_hdmi_ret_t ipil_hdmi_i2c_disable(hdmi_device_t *dev) +{ + return ips_hdmi_i2c_disable(dev); +} + +bool ipil_hdmi_power_rails_on() +{ + return ips_hdmi_power_rails_on(); +} + +/* + * Description: hdmi interrupt handler (upper half). + * handles the interrupts by reading hdmi status register + * and waking up bottom half if needed. + * + * @dev: hdmi_device_t + * + * Returns: IRQ_HANDLED on NULL input arguments, and if the + * interrupt is not HDMI HPD interrupts. + * IRQ_WAKE_THREAD if this is a HDMI HPD interrupt. + */ +irqreturn_t ipil_hdmi_irq_handler(hdmi_device_t *dev) +{ + /* NULL checks */ + if (dev == NULL) { + pr_debug("\ninvalid argument\n"); + return IRQ_HANDLED; + } + + return ips_hdmi_irq_handler((void *)dev->irq_io_address); +} + +/* + * Description: enable infoframes + * + * @dev: hdmi_device_t + * @type: type of infoframe packet + * @pkt: infoframe packet data + * @freq: number of times packet needs to be sent + * + * Returns: OTM_HDMI_ERR_NULL_ARG on NULL parameters + * OTM_HDMI_ERR_INVAL on invalid packet type + * OTM_HDMI_SUCCESS on success + */ +otm_hdmi_ret_t ipil_hdmi_enable_infoframe(hdmi_device_t *dev, + unsigned int type, otm_hdmi_packet_t *pkt, unsigned int freq) +{ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + + if (!dev || !pkt) + return OTM_HDMI_ERR_NULL_ARG; + + switch (type) { + case HDMI_PACKET_AVI: + case HDMI_PACKET_VS: + case HDMI_PACKET_SPD: + rc = ips_hdmi_enable_vid_infoframe(dev, type, pkt, freq); + break; + default:/* TODO: Revisit for Other Infoframes */ + rc = OTM_HDMI_ERR_INVAL; + break; + } + + return rc; +} + +/* + * Description: disable particular infoframe + * + * @dev: hdmi_device_t + * @type: type of infoframe packet + * + * Returns: OTM_HDMI_ERR_NULL_ARG on NULL parameters + * OTM_HDMI_ERR_INVAL on invalid packet type + * OTM_HDMI_SUCCESS on success +*/ +otm_hdmi_ret_t ipil_hdmi_disable_infoframe(hdmi_device_t *dev, + unsigned int type) +{ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + + if (!dev) + return OTM_HDMI_ERR_NULL_ARG; + + switch (type) { + case HDMI_PACKET_AVI: + case HDMI_PACKET_VS: + case HDMI_PACKET_SPD: + rc = ips_hdmi_disable_vid_infoframe(dev, type); + break; + default:/* TODO: Revisit for Other Infoframes */ + rc = OTM_HDMI_ERR_INVAL; + break; + } + + return rc; +} + +/* + * Description: disable all infoframes + * + * @dev: hdmi_device_t + * + * Returns: OTM_HDMI_ERR_NULL_ARG on NULL parameters + * OTM_HDMI_SUCCESS on success +*/ +otm_hdmi_ret_t ipil_hdmi_disable_all_infoframes(hdmi_device_t *dev) +{ + if (!dev) + return OTM_HDMI_ERR_NULL_ARG; + + return ips_hdmi_disable_all_infoframes(dev); +} + +/* + * Description: programs hdmi pipe src and size of the input. + * + * @dev: hdmi_device_t + * @scalingtype: scaling type (FULL_SCREEN, CENTER, NO_SCALE etc.) + * @mode: mode requested + * @adjusted_mode: adjusted mode + * @fb_width, fb_height:allocated frame buffer dimensions + * + * Returns: OTM_HDMI_SUCCESS on success + * OTM_HDMI_ERR_INVAL on NULL input arguments + */ +otm_hdmi_ret_t ipil_hdmi_crtc_mode_set_program_dspregs(hdmi_device_t *dev, + int scalingtype, + ipil_timings_t *mode, + ipil_timings_t *adjusted_mode, + int fb_width, int fb_height) +{ + int sprite_pos_x = 0, sprite_pos_y = 0; + int sprite_width = 0, sprite_height = 0; + int src_image_hor = 0, src_image_vert = 0; + + /* NULL checks */ + if (dev == NULL || mode == NULL || adjusted_mode == NULL) { + pr_debug("\ninvalid argument\n"); + return OTM_HDMI_ERR_INVAL; + } + + /* + * TODO: update these values based on scaling type, + * rotation and HDMI mode. + */ + sprite_width = fb_width; + sprite_height = fb_height; + src_image_hor = fb_width; + src_image_vert = fb_height; + sprite_pos_x = 0; + sprite_pos_y = 0; + + /* + * pipesrc and dspsize control the size that is scaled from, + * which should always be the user's requested size. + */ + switch (scalingtype) { + case IPIL_TIMING_SCALE_NONE: + case IPIL_TIMING_SCALE_CENTER: + /* TODO: implement this */ + break; + + case IPIL_TIMING_SCALE_FULLSCREEN: + if ((adjusted_mode->width != sprite_width) || + (adjusted_mode->height != sprite_height)) + hdmi_write32(IPIL_PFIT_CONTROL, + IPIL_PFIT_ENABLE | + IPIL_PFIT_PIPE_SELECT_B | + IPIL_PFIT_SCALING_AUTO); + + break; + + case IPIL_TIMING_SCALE_ASPECT: + if ((adjusted_mode->width != fb_width) || + (adjusted_mode->height != fb_height)) { + if ((adjusted_mode->width * fb_height) == + (fb_width * adjusted_mode->height)) + hdmi_write32(IPIL_PFIT_CONTROL, + IPIL_PFIT_ENABLE | + IPIL_PFIT_PIPE_SELECT_B); + else if ((adjusted_mode->width * + fb_height) > (fb_width * + adjusted_mode->height)) + hdmi_write32(IPIL_PFIT_CONTROL, + IPIL_PFIT_ENABLE | + IPIL_PFIT_PIPE_SELECT_B | + IPIL_PFIT_SCALING_PILLARBOX); + else + hdmi_write32(IPIL_PFIT_CONTROL, + IPIL_PFIT_ENABLE | + IPIL_PFIT_PIPE_SELECT_B | + IPIL_PFIT_SCALING_LETTERBOX); + } + break; + + default: + if ((adjusted_mode->width != fb_width) || + (adjusted_mode->height != fb_height)) + hdmi_write32(IPIL_PFIT_CONTROL, + IPIL_PFIT_ENABLE | + IPIL_PFIT_PIPE_SELECT_B); + + break; + } + + hdmi_write32(IPIL_DSPBSIZE, ((sprite_height - 1) << 16) | + (sprite_width - 1)); + + hdmi_write32(IPIL_PIPEBSRC, ((src_image_hor - 1) << 16) | + (src_image_vert - 1)); + + hdmi_write32(IPIL_DSPBPOS, (sprite_pos_y << 16) | sprite_pos_x); + + return OTM_HDMI_SUCCESS; +} + +/* + * Description: this is pre-modeset configuration. This can be + * resetting HDMI unit, disabling/enabling dpll etc + * on the need basis. + * + * @dev: hdmi_device_t + * + * Returns: OTM_HDMI_SUCCESS on success + * OTM_HDMI_ERR_INVAL on NULL input arguments + */ +otm_hdmi_ret_t ipil_hdmi_crtc_mode_set_prepare(hdmi_device_t *dev) +{ + /* NULL checks */ + if (dev == NULL) { + pr_debug("\ninvalid argument\n"); + return OTM_HDMI_ERR_INVAL; + } + + /* Nothing needed as of now for medfield */ + + return OTM_HDMI_SUCCESS; +} + +/* + * Description: programs all the timing registers based on scaling type. + * + * @dev: hdmi_device_t + * @scalingtype: scaling type (FULL_SCREEN, CENTER, NO_SCALE etc.) + * @mode: mode requested + * @adjusted_mode: adjusted mode + * + * Returns: OTM_HDMI_SUCCESS on success + * OTM_HDMI_ERR_INVAL on NULL input arguments + */ +otm_hdmi_ret_t ipil_hdmi_crtc_mode_set_program_timings(hdmi_device_t *dev, + int scalingtype, + otm_hdmi_timing_t *mode, + otm_hdmi_timing_t *adjusted_mode) +{ + /* NULL checks */ + if (dev == NULL || mode == NULL || adjusted_mode == NULL) { + pr_debug("\ninvalid argument\n"); + return OTM_HDMI_ERR_INVAL; + } + + /* TODO: get adjusted htotal */ + /* ips_hdmi_get_htotal(); */ + + if (scalingtype == IPIL_TIMING_SCALE_NONE) { + /* Moorestown doesn't have register support for centering so we + * need to mess with the h/vblank and h/vsync start and ends + * to get centering + */ + int offsetX = 0, offsetY = 0; + + offsetX = (adjusted_mode->width - mode->width) / 2; + offsetY = (adjusted_mode->height - mode->height) / 2; + + hdmi_write32(IPIL_HTOTAL_B, (mode->width - 1) | + ((adjusted_mode->htotal - 1) << 16)); + + hdmi_write32(IPIL_VTOTAL_B, (mode->height - 1) | + ((adjusted_mode->vtotal - 1) << 16)); + + hdmi_write32(IPIL_HBLANK_B, + (adjusted_mode->hblank_start - offsetX - 1) | + ((adjusted_mode->hblank_end - offsetX - 1) << 16)); + + hdmi_write32(IPIL_HSYNC_B, + (adjusted_mode->hsync_start - offsetX - 1) | + ((adjusted_mode->hsync_end - offsetX - 1) << 16)); + + hdmi_write32(IPIL_VBLANK_B, + (adjusted_mode->vblank_start - offsetY - 1) | + ((adjusted_mode->vblank_end - offsetY - 1) << 16)); + + hdmi_write32(IPIL_VSYNC_B, + (adjusted_mode->vsync_start - offsetY - 1) | + ((adjusted_mode->vsync_end - offsetY - 1) << 16)); + } else { + hdmi_write32(IPIL_HTOTAL_B, + (adjusted_mode->width - 1) | + ((adjusted_mode->htotal - 1) << 16)); + + hdmi_write32(IPIL_VTOTAL_B, + (adjusted_mode->height - 1) | + ((adjusted_mode->vtotal - 1) << 16)); + + hdmi_write32(IPIL_HBLANK_B, + (adjusted_mode->hblank_start - 1) | + ((adjusted_mode->hblank_end - 1) << 16)); + + hdmi_write32(IPIL_HSYNC_B, + (adjusted_mode->hsync_start - 1) | + ((adjusted_mode->hsync_end - 1) << 16)); + + hdmi_write32(IPIL_VBLANK_B, + (adjusted_mode->vblank_start - 1) | + ((adjusted_mode->vblank_end - 1) << 16)); + + hdmi_write32(IPIL_VSYNC_B, + (adjusted_mode->vsync_start - 1) | + ((adjusted_mode->vsync_end - 1) << 16)); + } + + return OTM_HDMI_SUCCESS; +} + +/* + * Description: programs dpll clocks, enables dpll and waits + * till it locks with DSI PLL + * + * @dev: hdmi_device_t + * @dclk: refresh rate dot clock in kHz of current mode + * + * Returns: OTM_HDMI_SUCCESS on success + * OTM_HDMI_ERR_INVAL on NULL input arguments + */ +otm_hdmi_ret_t ipil_hdmi_crtc_mode_set_program_dpll(hdmi_device_t *dev, + unsigned long dclk) +{ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + u32 dpll_adj, fp; + u32 dpll; + int timeout = 0; + + /* NULL checks */ + if (dev == NULL) { + pr_debug("\ninvalid argument\n"); + return OTM_HDMI_ERR_INVAL; + } + + /* get the adjusted clock value */ + rc = ips_hdmi_get_adjusted_clk(dclk, &dpll_adj, &fp, &dev->clock_khz); + if (rc != OTM_HDMI_SUCCESS) { + pr_debug("\nfailed to calculate adjusted clock\n"); + return rc; + } + + dpll = hdmi_read32(IPIL_DPLL_B); + if (dpll & IPIL_DPLL_VCO_ENABLE) { + dpll &= ~IPIL_DPLL_VCO_ENABLE; + hdmi_write32(IPIL_DPLL_B, dpll); + hdmi_read32(IPIL_DPLL_B); + + /* reset M1, N1 & P1 */ + hdmi_write32(IPIL_DPLL_DIV0, 0); + dpll &= ~IPIL_P1_MASK; + hdmi_write32(IPIL_DPLL_B, dpll); + } + + /* + * When ungating power of DPLL, needs to wait 0.5us + * before enable the VCO + */ + if (dpll & IPIL_PWR_GATE_EN) { + dpll &= ~IPIL_PWR_GATE_EN; + hdmi_write32(IPIL_DPLL_B, dpll); + udelay(1); + } + + dpll = dpll_adj; + hdmi_write32(IPIL_DPLL_DIV0, fp); + hdmi_write32(IPIL_DPLL_B, dpll); + udelay(1); + + dpll |= IPIL_DPLL_VCO_ENABLE; + hdmi_write32(IPIL_DPLL_B, dpll); + hdmi_read32(IPIL_DPLL_B); + + /* wait for DSI PLL to lock */ + while ((timeout < 20000) && !(hdmi_read32(IPIL_PIPEBCONF) & + IPIL_PIPECONF_PLL_LOCK)) { + udelay(150); + timeout++; + } + + return OTM_HDMI_SUCCESS; +} + +/* + * Description: configures the display plane register and enables + * pipeconf. + * + * @dev: hdmi_device_t + * + * Returns: OTM_HDMI_SUCCESS on success + * OTM_HDMI_ERR_INVAL on NULL input arguments + */ +otm_hdmi_ret_t ipil_hdmi_crtc_mode_set_program_pipeconf(hdmi_device_t *dev) +{ + u32 dspcntr; + u32 pipeconf; + + /* NULL checks */ + if (dev == NULL) { + pr_debug("\ninvalid argument\n"); + return OTM_HDMI_ERR_INVAL; + } + + /* Set up the display plane register */ + dspcntr = hdmi_read32(IPIL_DSPBCNTR); + dspcntr |= 1 << IPIL_DSP_PLANE_PIPE_POS; + dspcntr |= IPIL_DSP_PLANE_ENABLE; + + /* setup pipeconf */ + pipeconf = IPIL_PIPEACONF_ENABLE; + + + hdmi_write32(IPIL_PIPEBCONF, pipeconf); + hdmi_read32(IPIL_PIPEBCONF); + + hdmi_write32(IPIL_DSPBCNTR, dspcntr); + + return OTM_HDMI_SUCCESS; +} + +/* + * Description: encoder mode set function for hdmi. enables phy. + * set correct polarity for the current mode, sets + * correct panel fitting. + * + * + * @dev: hdmi_device_t + * @mode: mode requested + * @adjusted_mode: adjusted mode + * @is_monitor_hdmi: is monitor type is hdmi or not + * + * Returns: OTM_HDMI_SUCCESS on success + * OTM_HDMI_ERR_INVAL on NULL input arguments + */ +otm_hdmi_ret_t ipil_hdmi_enc_mode_set(hdmi_device_t *dev, + otm_hdmi_timing_t *mode, + otm_hdmi_timing_t *adjusted_mode, + bool is_monitor_hdmi) +{ + u32 hdmib, hdmi_phy_misc; + bool phsync; + bool pvsync; + + /* NULL checks */ + if (dev == NULL || mode == NULL || adjusted_mode == NULL) { + pr_debug("\ninvalid argument\n"); + return OTM_HDMI_ERR_INVAL; + } + + if (is_monitor_hdmi) { + hdmib = hdmi_read32(IPIL_HDMIB_CONTROL) | IPIL_HDMIB_PORT_EN + | IPIL_HDMIB_PIPE_B_SELECT + | IPIL_HDMIB_NULL_PACKET + | IPIL_HDMIB_AUDIO_ENABLE; + } else { + hdmib = hdmi_read32(IPIL_HDMIB_CONTROL) | IPIL_HDMIB_PORT_EN + | IPIL_HDMIB_PIPE_B_SELECT; + hdmib &= ~IPIL_HDMIB_NULL_PACKET; + hdmib &= ~IPIL_HDMIB_AUDIO_ENABLE; + } + + /* set output polarity */ + phsync = adjusted_mode->mode_info_flags & IPIL_TIMING_FLAG_PHSYNC; + pvsync = adjusted_mode->mode_info_flags & IPIL_TIMING_FLAG_PVSYNC; + pr_debug("enc_mode_set %dx%d (%c,%c)\n", adjusted_mode->width, + adjusted_mode->height, + phsync ? '+' : '-', + pvsync ? '+' : '-'); + /* TODO: define macros for hard coded values */ + hdmib &= ~0x18; /* clean bit 3 and 4 */ + hdmib |= phsync ? 0x8 : 0x0; /* bit 3 */ + hdmib |= pvsync ? 0x10 : 0x0; /* bit 4 */ + + hdmi_phy_misc = hdmi_read32(IPIL_HDMIPHYMISCCTL) & + ~IPIL_HDMI_PHY_POWER_DOWN; + + hdmi_write32(IPIL_HDMIPHYMISCCTL, hdmi_phy_misc); + hdmi_write32(IPIL_HDMIB_CONTROL, hdmib); + hdmi_read32(IPIL_HDMIB_CONTROL); + + return OTM_HDMI_SUCCESS; +} + +/* + * Description: save HDMI display registers + * + * @dev: hdmi_device_t + * + * Returns: none + */ +void ipil_hdmi_save_display_registers(hdmi_device_t *dev) +{ + if (NULL != dev) + ips_hdmi_save_display_registers(dev); +} + +/* + * Description: save HDMI data island packets + * + * @dev: hdmi_device_t + * + * Returns: none + */ +void ipil_hdmi_save_data_island(hdmi_device_t *dev) +{ + if (NULL != dev) + ips_hdmi_save_data_island(dev); +} + +/* + * Description: destroys any saved HDMI data + * + * @dev: hdmi_device_t + * + * Returns: none + */ +void ipil_hdmi_destroy_saved_data(hdmi_device_t *dev) +{ + if (NULL != dev) + ips_hdmi_destroy_saved_data(dev); +} + +/* + * Description: disable HDMI display + * + * @dev: hdmi_device_t + * + * Returns: none + */ +void ipil_disable_hdmi(hdmi_device_t *dev) +{ + if (NULL != dev) + ips_disable_hdmi(dev); +} + +/* + * Description: restore HDMI display registers and enable display + * + * @dev: hdmi_device_t + * + * Returns: none + */ +void ipil_hdmi_restore_and_enable_display(hdmi_device_t *dev) +{ + if (NULL != dev) + ips_hdmi_restore_and_enable_display(dev); +} + +/* + * Description: restore HDMI data island packets + * + * @dev: hdmi_device_t + * + * Returns: none + */ +void ipil_hdmi_restore_data_island(hdmi_device_t *dev) +{ + if (NULL != dev) + ips_hdmi_restore_data_island(dev); +} diff --git a/drivers/staging/mrst/drv/otm_hdmi/ipil/include/hdcp_rx_defs.h b/drivers/staging/mrst/drv/otm_hdmi/ipil/include/hdcp_rx_defs.h new file mode 100644 index 0000000..2326ba0 --- /dev/null +++ b/drivers/staging/mrst/drv/otm_hdmi/ipil/include/hdcp_rx_defs.h @@ -0,0 +1,146 @@ +/* + + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2011 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + + Intel Corporation + 2200 Mission College Blvd. + Santa Clara, CA 95054 + + BSD LICENSE + + Copyright(c) 2011 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef HDCP_RX_DEFS_H +#define HDCP_RX_DEFS_H + +#include "hdmi_internal.h" + +#define HDCP_PRIMARY_I2C_ADDR 0x3A + +#define HDCP_KSV_SIZE 0x05 +#define HDCP_KSV_HAMMING_WT (20) +#define HDCP_AN_SIZE 0x08 +#define HDCP_RI_SIZE 0x02 +#define HDCP_PJ_SIZE 0x01 +#define HDCP_V_H_SIZE (20) + + +#define HDCP_RX_BKSV_ADDR 0x00 +#define HDCP_RX_RI_ADDR 0x08 +#define HDCP_RX_PJ_ADDR 0x0A +#define HDCP_RX_AKSV_ADDR 0x10 + +#define HDCP_RX_AINFO_ADDR 0x15 +#define HDCP_RX_AINFO_SIZE 0x01 + +#define HDCP_RX_AN_ADDR 0x18 + +#define HDCP_RX_V_H_ADDR 0x20 + +#define HDCP_RX_V_H0_ADDR 0x20 +#define HDCP_RX_V_H0_SIZE 0x04 + +#define HDCP_RX_V_H1_ADDR 0x24 +#define HDCP_RX_V_H1_SIZE 0x04 + +#define HDCP_RX_V_H2_ADDR 0x28 +#define HDCP_RX_V_H2_SIZE 0x04 + +#define HDCP_RX_V_H3_ADDR 0x2C +#define HDCP_RX_V_H3_SIZE 0x04 + +#define HDCP_RX_V_H4_ADDR 0x30 +#define HDCP_RX_V_H4_SIZE 0x04 + +#define HDCP_RX_BCAPS_ADDR 0x40 +#define HDCP_RX_BCAPS_SIZE 0x01 + +#define HDCP_RX_BSTATUS_ADDR 0x41 +#define HDCP_RX_BSTATUS_SIZE 0x02 + +#define HDCP_RX_KSV_FIFO_ADDR 0x43 + +struct hdcp_rx_bcaps_t { + union { + uint8_t value; + struct { + uint8_t fast_reauthentication:1 ; + uint8_t b1_1_features:1 ; + uint8_t reserved:2 ; + uint8_t fast_transfer:1 ; + uint8_t ksv_fifo_ready:1 ; + uint8_t is_repeater:1 ; + uint8_t hdmi_reserved:1 ; + }; + }; +}; + +struct hdcp_rx_bstatus_t { + union { + uint16_t value; + struct { + uint16_t device_count:7 ; + uint16_t max_devs_exceeded:1 ; + uint16_t depth:3 ; + uint16_t max_cascade_exceeded:1 ; + uint16_t hdmi_mode:1 ; + uint16_t reserved2:1 ; + uint16_t rsvd:2 ; + }; + }; +}; + + +#endif /* HDCP_RX_DEFS_H */ + diff --git a/drivers/staging/mrst/drv/otm_hdmi/ipil/include/hdmi_hal.h b/drivers/staging/mrst/drv/otm_hdmi/ipil/include/hdmi_hal.h new file mode 100644 index 0000000..a753907 --- /dev/null +++ b/drivers/staging/mrst/drv/otm_hdmi/ipil/include/hdmi_hal.h @@ -0,0 +1,1207 @@ +/* + + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2011 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + + Intel Corporation + 2200 Mission College Blvd. + Santa Clara, CA 95054 + + BSD LICENSE + + Copyright(c) 2011 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +/* + * GENERAL ASSUMPTIONS / REQUIREMENTS + * + * 1. HAL entries mentioned in this document are intended to be simple wrappers + * on top of register reads and writes. They should not keep any state + * and should not implement any policies. It is completely up to higher + * levels when and how to use these entries. The only safety checks HAL + * entries should do is for NULL pointers and (in very few cases) for + * correctness of values supplied for register writes (range and alignment + * checks). + * 2. HAL should be implemented in such a way that they can be used in both + * both user and kernel space code. + * 3. HAL should hide actual register layout where appropriate (infoframes, csc + * coefficients, etc). This objective is not met at the moment since in some + * cases (DMA configuration) we assume that end user knows the register + * layout (at least for now). + * + * ABBREVIATIONS + * + * GCP - General Control Packet + * AVI - Auxiliaty Video Information + * ACP - Audio Content Protection + * ISRC - International Standard Recording Code + * SPD - Source Product Description + */ + +#ifndef __HDMI_HAL_H__ +#define __HDMI_HAL_H__ + + +#include + +#include "otm_hdmi_types.h" +#include "otm_hdmi_defs.h" + +/* + * This enumeration represents HDMI unit revision + */ +typedef enum { + HDMI_PCI_REV_CE3100 = 0, + HDMI_PCI_REV_CE4100_A0 = 1, + HDMI_PCI_REV_CE4100_B012 = 2, + HDMI_PCI_REV_CE4200_A0 = 3, + HDMI_PCI_REV_CE4200_B0 = 4, +} hdmi_unit_revision_id_t; + +/* + * HDMI register state + */ +typedef struct { + bool valid; + uint32_t saveDPLL; + uint32_t saveFPA0; + uint32_t savePIPEBCONF; + uint32_t saveHTOTAL_B; + uint32_t saveHBLANK_B; + uint32_t saveHSYNC_B; + uint32_t saveVTOTAL_B; + uint32_t saveVBLANK_B; + uint32_t saveVSYNC_B; + uint32_t savePIPEBSRC; + uint32_t saveDSPBSTRIDE; + uint32_t saveDSPBLINOFF; + uint32_t saveDSPBTILEOFF; + uint32_t saveDSPBSIZE; + uint32_t saveDSPBPOS; + uint32_t saveDSPBSURF; + uint32_t saveDSPBCNTR; + uint32_t saveDSPBSTATUS; + uint32_t save_palette_b[256]; + uint32_t savePFIT_CONTROL; + uint32_t savePFIT_PGM_RATIOS; + uint32_t saveHDMIPHYMISCCTL; + uint32_t saveHDMIB_CONTROL; +} hdmi_register_state_t; + +/* + * HDMI infoframe information + */ +struct hdmi_infoframe_info_t { + bool valid; + uint32_t freq; + otm_hdmi_packet_t pkt; +}; + +/* + * This structure is used by HAL user to configure and use HAL + */ +typedef struct { + /* Base address of mapped registers */ + unsigned int io_address; + + /* Base address of mapped interrupt registers */ + unsigned int irq_io_address; + + /* Pointer to register read routine */ + unsigned int (*io_read) (void *uhandle, /* User provided data */ + unsigned int base, /* Base address */ + unsigned int offset); /* Register offset */ + + /* Pointer to register write routine */ + void (*io_write) (void *uhandle, /* User provided data */ + unsigned int base, /* Base address */ + unsigned int offset, /* Register offset */ + unsigned int value); /* Value */ + + /* Pointer to delay routine */ + /* Number of usec to sleep */ + void (*usleep) (unsigned long usec); + + /* Pointer to the data that will be + * passed to both io_read and io_write */ + void *uhandle; + + /* Pointer to the routine invoked at the beginning of every + * HAL call */ + void (*log_entry) (void *uhandle, /* User provided data */ + char *foo); /* Name of the routine */ + + /* Pointer to the routine invoked at the end of every + * HAL call */ + void (*log_exit) (void *uhandle, /* User provided data */ + char *foo, /* Name of the routine */ + int rc); /* Return code */ + + /* HDMI unit identifier */ + hdmi_unit_revision_id_t id; + + /* Pointer to opaque polling timer */ + void *poll_timer; + + /* Pointer to the polling timer initialization routine */ + void (*poll_start) (void *poll_timer); + + /* Pointer to the timeout verification routine */ + bool(*poll_timeout) (void *poll_timer); + + /* Interrupt status to interrupt handling function */ + unsigned int isr_status; + + /* + * TODO: tmds clk value for the best pll found and is needed for audio. + * This field has to be moved into OTM audio interfaces + * when implemented. + */ + uint32_t clock_khz; + + /* HDMI register value */ + hdmi_register_state_t reg_state; + /* AVI Infoframe - used for suspend resume */ + struct hdmi_infoframe_info_t avi; +} hdmi_device_t; + +/* + * Description: Infoframe handling facility supports two sending rates: one time + * send and every frame send + */ +typedef enum { + HDMI_INFOFRAME_SEND_ONCE, + HDMI_INFOFRAME_SEND_EVERY +} hdmi_infoframe_frequency_t; + +/* + * Description: CE 3100 provides SW with 4 slots for infoframes which can be + * sent as often as every frame. This routine loads given + * infoframe into given slot. + * + * @param [in] slot_number : number of slot; valid range is [1..4] + * @param [in] frame : pointer to the structure representing infoframe + */ +otm_hdmi_ret_t hdmi_infoframe_set(hdmi_device_t *dev, + unsigned int slot_number, + otm_hdmi_packet_t *frame); + +/* + * Description: Setting up sending frequency attribute for given slot + * + * @param [in] slot_number : slot number; valid range is [1..4] + * @param [in] frequency : sending frequency + */ +otm_hdmi_ret_t hdmi_infoframe_set_frequency(hdmi_device_t *dev, + unsigned int slot_number, + hdmi_infoframe_frequency_t frequency); + +/* + * Description: Enables/disables sending of infoframe from the given slot + * + * @param [in] slot_number : slot number; valid range is [1..4] + */ +otm_hdmi_ret_t hdmi_infoframe_enable(hdmi_device_t *dev, + unsigned int slot_number); +otm_hdmi_ret_t hdmi_infoframe_disable(hdmi_device_t *dev, + unsigned int slot_number); + +/* + * AUDIO UNIT + */ + +/* + * Description: Turns transmission of audio data and CTS/N packets on/off + */ +otm_hdmi_ret_t hdmi_audio_enable(hdmi_device_t *dev); +otm_hdmi_ret_t hdmi_audio_disable(hdmi_device_t *dev); + +/* + * Description: List of audio formats supported + */ +typedef enum { + HDMI_AUDIO_FORMAT_LPCM, + HDMI_AUDIO_FORMAT_HBR, + HDMI_AUDIO_FORMAT_OBA, + HDMI_AUDIO_FORMAT_DTS +} hdmi_audio_format_t; + +/* + * Description: Setting up given format + * + * @param [in] format : audio format + */ +otm_hdmi_ret_t hdmi_audio_set_format(hdmi_device_t *dev, + hdmi_audio_format_t format); + +/* + * Description: Number of channels supported + */ +typedef enum { + HDMI_AUDIO_NUM_CHANNELS_2, + HDMI_AUDIO_NUM_CHANNELS_4, + HDMI_AUDIO_NUM_CHANNELS_6, + HDMI_AUDIO_NUM_CHANNELS_8 +} hdmi_audio_num_channels_t; + +/* + * Description: Setting up number of channels + * + * @param [in] nchannels : number of channels + */ +otm_hdmi_ret_t hdmi_audio_set_num_channels(hdmi_device_t *dev, + hdmi_audio_num_channels_t nchannels); + +/* + * Description: Specifying if sampling frequensy is larger than 192KHz + * Looks like this call is not really needed at the moment. + * + * @param [in] high_freq : GDL_TRUE - sampling frequency is larger than + * 192 KHz + * GDL_FALSE - sampling frequency is smaller that + * 192 KHz + */ +otm_hdmi_ret_t hdmi_audio_set_high_frequency(hdmi_device_t *dev, + bool high_freq); + +/* + * Description: Setting up clock recovery value N + * + * @param [in] n - N value + */ +otm_hdmi_ret_t hdmi_audio_set_clock_recovery_n(hdmi_device_t *dev, + unsigned int n); + +/* + * Description: HW computes CTS value based on current N value. CE3100 can + * bypass automatic CTS calculation. + * + * @param [in] bypass : GDL_FALSE - CTS calculation is done by HW + * GDL_TRUE - CTS calculation is done by SW + */ +otm_hdmi_ret_t hdmi_audio_set_clock_recovery_cts_bypass(hdmi_device_t *dev, + bool bypass); + +/* + * Description: Setting up clock recovery CTS value when CTS bypass is enabled + * + * @param [in] cts : CTS value + */ +otm_hdmi_ret_t hdmi_audio_set_clock_recovery_cts(hdmi_device_t *dev, + unsigned int cts); + +/* + * Description: Setting up audio clock divider register + * End user should compute it as (128 * FS) / 1000 + * + * @param [in] clock_divider : clock divider + */ +otm_hdmi_ret_t hdmi_audio_set_clock_divider(hdmi_device_t *dev, + unsigned int clock_divider); + +/* + * Description: Setting up FIFO threshold level (in 32 bit words) + * Should be set to FIFO_SIZE - DMA_BURST_SIZE + * + * @param [in] threshold : FIFO threshold level + */ +otm_hdmi_ret_t hdmi_audio_set_fifo_threshold(hdmi_device_t *dev, + unsigned int threshold); + +/* + * Description: Audio FIFO size is 192 32 bit words. This routine reads current + * number of words in the FIFO. + * + * @param [out] level : valid buffer to store number of 32bit words in the FIFO + */ +otm_hdmi_ret_t hdmi_audio_get_fifo_level(hdmi_device_t *dev, + unsigned int *level); + +/* + * Description: Layout of subpackets in the audio packet + */ +typedef enum { + HDMI_AUDIO_LAYOUT_0, + HDMI_AUDIO_LAYOUT_1 +} hdmi_audio_packet_layout_t; + +/* + * Description: Setting up subpackets layout bit. Refer to HDMI specs + * version 1.3 section 5.3.4 for details. + * + * @param [in] layout : audio subpackets layout + */ +otm_hdmi_ret_t hdmi_audio_set_packets_layout(hdmi_device_t *dev, + hdmi_audio_packet_layout_t layout); + +/* + * Description: Setting up VR and VL bits in all audio subpackets + * Refer to HDMI specs version 1.3 section 5.3.4 for details + * + * @param [in] valid : GDL_TRUE - bit is on, GDL_FALSE - bit is off + */ +otm_hdmi_ret_t hdmi_audio_set_packets_valid_bits(hdmi_device_t *dev, + bool valid); + +/* + * Descripton: Setting up B bit for the first or for all subpackets + * + * @param [in] all : GDL_TRUE - sets B bit for all valid subpackets + * GDL_FALSE - sets B bit for the first subpacket only + */ +otm_hdmi_ret_t hdmi_audio_set_packets_b_bits(hdmi_device_t *dev, + bool all); + +/* + * Description: Setting up flat bits in all audio packets header + * Refer to HDMI specs version 1.3 section 5.3.4 for details + * + * @param [in] flat : GDL_TRUE - bit is on, GDL_FALSE - bit is off + */ +otm_hdmi_ret_t hdmi_audio_set_packets_flat_bits(hdmi_device_t *dev, + bool flat); + +/* + * Description: Setting up UR and UL bits in outgoing packets + * When packet layout is set to 0 then UR and UL in all subpackets + * are affected by a pair of bits. Hence 192 packets are affected + * in total. When packet layout is set to 1 then UR and UL in + * individual subpackets are affected. Hence at least 48 packets + * are affected. + * + * @param [in] data : valid buffer with 12 32-bit words each representing + * 16 packets + */ +otm_hdmi_ret_t hdmi_audio_set_packets_user_bits(hdmi_device_t *dev, + unsigned int *data); + +/* + * Description: Triggers insertion of user bits into outgoing audio packets + */ +otm_hdmi_ret_t hdmi_audio_send_packets_user_bits(hdmi_device_t *dev); + +/* + * Description: Setting up CR and CL bits in outgoing packets. + * Rules of how many packets are affected are the same as in + * hdmi_audio_set_packets_user_bits call. + * 152 subsequent subpackets will have CR and CL set to 0 (??) + * + * @param [in] data : valid buffer with 2 32-bit words lower 40 bits of which + * are considered + */ +otm_hdmi_ret_t hdmi_audio_set_packets_channel_bits(hdmi_device_t *dev, + unsigned int *data); + +/* + * Description: Reading the CR and CL bits in channel status registers. + * 152 subsequent subpackets will have CR and CL set to 0 (??) + * + * @param [out] data : valid buffer with 2 32-bit words lower 40 bits of which + * are considered + */ +otm_hdmi_ret_t hdmi_audio_get_packets_channel_bits(hdmi_device_t *dev, + unsigned int *data); + +/* + * Description: Triggers insertion of channle bits into outgoing audio packets + */ +otm_hdmi_ret_t hdmi_audio_send_packets_channel_bits(hdmi_device_t *dev); + +/* + * DMA UNIT + * + * DMA can be configured to program itself by fetching series of + * descriptors. Each descriptor represents data transfer to be done. So + * transfering of audio data from audio buffers to the HDMI FIFO involves the + * following: + * - Audio buffer is devided into number of transfers + * - Each transfer is represented by the node in the linked list of descriptors + * - DMA NEXT_DESCR reg is set to the address of first descriptor in the list + * - Linked-list mode, burst size and other stuff is set in DMA FLAGS register + * + * SRC_INT and DST_INT interrupts are available to help HAL user monitoring + * what transfer from the list is currently in progress. Enabling them requires + * hitting SRC_INT/DST_INT bits in FLAGS_MODE register of DMA unit and + * bits 5/6 in HDMI interrupt control register. + * + * HAL provides three levels of DMA access. + * 1. End user controls address of first descriptor + * 2. End user controls flags register and address of first descriptor + * 3. End user has complete control + * + * Levels 1 and 2 are enough for DMA usage. Level 3 is included in case there + * are some cases where levels 1 and 2 are not covering the needs. + */ + +/* + * Description: DMA can be programmed to fetch series of descriptors, each of + * which specifies data transfer parameters. The following + * structure represents such a descriptor. + */ +typedef struct { + /* address of the the next descriptor */ + unsigned int next_address; + /* number of bytes in the current transfer */ + unsigned int transfer_size; + /* address of the user input buffer */ + unsigned int src_start_address; + /* HDMI FIFO address, should be 0x10101010 */ + unsigned int dst_start_address; + unsigned int flags; + /* Misc data associated with descriptor */ + unsigned int misc_data; +} hdmi_dma_descriptor_t; + +/* + * Description: Programs DMA with default configuration and start fetching + * sequence. This call is supposed to hide all configuration + * details from end user. + * + * @param [in] dscr_ph_addr : physical address of first descriptor to fetch + */ +otm_hdmi_ret_t hdmi_dma_default_start(hdmi_device_t *dev, + unsigned int dscr_ph_addr); + +/* + * Description: Stop transfer sequence by hitting BIT0 of OTHER_MODE register + * in DMA unit. + */ +otm_hdmi_ret_t hdmi_dma_stop(hdmi_device_t *dev); + +/* + * Description: Gives end user a default configuration (i.e. the same + * configuration as hdmi_dma_defalt_start sets) so he can apply + * it to every entry of linked list of descriptors. + */ +otm_hdmi_ret_t hdmi_dma_get_default_flags(hdmi_device_t *dev, + unsigned int *flags); + +/* + * Description: Setting up given configuration of DMA unit and starting the + * fetching sequence. The intention of this call is to give + * end user more control over the DMA unit than in + * hdmi_dma_default_start so user can tweak things a little bit + * + * @param [in] descr_phys_addr : physical address of first descriptor to fetch + * @param [in] flags : setting for the DMA flags register + */ +otm_hdmi_ret_t hdmi_dma_custom_start(hdmi_device_t *dev, + unsigned int descr_phys_addr, + unsigned int flags); + +/* + * Description: Structure below represtent DMA configuration + */ +typedef struct { + unsigned int curr_descr; + unsigned int next_descr; + unsigned int srcdma_start; + unsigned int dstdma_start; + unsigned int srcdma_size; + unsigned int flags_mode; + unsigned int other_mode; + unsigned int srcdma_bot; + unsigned int srcdma_top; + unsigned int dstdma_bot; + unsigned int dstdma_top; + unsigned int dstdma_size; + unsigned int srcdma_stop; + unsigned int dstdma_stop; +} hdmi_dma_config_t; + +/* + * Description: Providing end user with full control over the DMA + * + * @param [in] dma_config : pointer to dma configuration structure + */ +otm_hdmi_ret_t hdmi_dma_config(hdmi_device_t *dev, + hdmi_dma_config_t *dma_config); + +/* + * VIDEO + */ + +/* + * Description: HDMI unit can operate in both HDMI and DVI modes + */ +typedef enum {MODE_HDMI, MODE_DVI} hdmi_operation_mode_t; + +/* + * Description: Selecting mode of operation + * + * @param [in] mode: mode of operation + */ +otm_hdmi_ret_t hdmi_video_set_operation_mode(hdmi_device_t *dev, + hdmi_operation_mode_t mode); + +/* + * Description: Setting up pixel depth + * + * @param [in] pixel_depth : pixel depth + */ +otm_hdmi_ret_t hdmi_video_set_pixel_depth(hdmi_device_t *dev, + otm_hdmi_output_pixel_depth_t pixel_depth); + +/* + * Description: HDMI unit supports dithering from 12 to 10 and 8 bits + */ +typedef enum { + HDMI_DITHER_OUTPUT_8BITS, + HDMI_DITHER_OUTPUT_10BITS +} hdmi_dither_output_t; + +/* + * Description: Selecting dither output + * + * @param [in] output : rounding from 12 bits to 10 or 8 bits + */ +otm_hdmi_ret_t hdmi_video_set_dither_output(hdmi_device_t *dev, + hdmi_dither_output_t output); + +/* + * Description: HDMI unit can dither, round or don't do anything at all + */ +typedef enum { + HDMI_DITHER_DITHER, + HDMI_DITHER_ROUND, + HDMI_DITHER_BYPASS +} hdmi_dither_t; + +/* + * Description: Choosing dithering + * + * @param [in] dither - selection of particular dithering + */ +otm_hdmi_ret_t hdmi_video_set_dither(hdmi_device_t *dev, hdmi_dither_t dither); + +/* + * Description: Enables/disables CSC + * + * @param [in] state : GDL_TRUE - CSC is ON, GDL_FALSE - CSC is off + */ +otm_hdmi_ret_t hdmi_video_set_csc(hdmi_device_t *dev, bool state); + +/* + * Descripton: Set additional 444 to 422 conversion. Assumption is that either + * pipe outputs 444 or we already convert to 444 prior to this 422 + * conversion. Note that dithering is bypassed when 422 conversion + * is on. + * + * @param [in] state : GDL_TRUE - perform additional 422 conversion + * GDL_FALSE - do not perform additional 422 conversion + * + * @param [in] sd : GDL_TRUE - Current mode is SD + * GDL_FALSE - Current mode is HD + */ +otm_hdmi_ret_t hdmi_video_set_csc_422(hdmi_device_t *dev, + bool state, + bool sd); + +/* + * Description: offset setup + * + * @param [in] in : + * @param [in] out : + */ +otm_hdmi_ret_t hdmi_video_set_csc_offset_YG(hdmi_device_t *dev, + int in, int out); +otm_hdmi_ret_t hdmi_video_set_csc_offset_CbB(hdmi_device_t *dev, + int in, int out); +otm_hdmi_ret_t hdmi_video_set_csc_offset_CrR(hdmi_device_t *dev, + int in, int out); + +/* + * Description: this structure reflects clamp configuration register + */ +typedef struct { + bool full_overrun; + bool shift_output; + bool output_clamp_960; + bool output_clamp_enable; + bool input_clamp_960; + bool input_clamp_enable; +} hdmi_csc_clamp_t; + +/* + * Description: Clamp setup + * + * @param [in] clamp : user supplied buffer with clamp configuration + */ +otm_hdmi_ret_t hdmi_video_set_csc_clamp(hdmi_device_t *dev, + hdmi_csc_clamp_t *clamp); + +/* + * Color space conversion coefficients are exposed keeping the following + * conversion formula in mind (in matrix representation): + * + * | R/Cr | | CC0 CC1 CC2 | | Cr/R | + * | G/Y | = | CC3 CC4 CC5 | | Y /G | + * | B/Cb | | CC6 CC7 CC8 | | Cb/B | + * + * Description: conversion coefficients setup + * + * @param [in] c0..c8 : coefficients from formula above + */ +otm_hdmi_ret_t hdmi_video_set_csc_012(hdmi_device_t *dev, float c0, float c1, + float c2); +otm_hdmi_ret_t hdmi_video_set_csc_345(hdmi_device_t *dev, float c3, float c4, + float c5); +otm_hdmi_ret_t hdmi_video_set_csc_678(hdmi_device_t *dev, float c6, float c7, + float c8); + +/* + * Description: conversion coefficients setup. Format details are specified + * near each argument + * + * @param [in] c0..c8 : coefficients from folmula above (signed fixed point) + */ +otm_hdmi_ret_t hdmi_video_set_csc_012_fixed(hdmi_device_t *dev, + unsigned int c0, /* 3.10 */ + unsigned int c1, /* 3.10 */ + unsigned int c2); /* 3.10 */ +otm_hdmi_ret_t hdmi_video_set_csc_345_fixed(hdmi_device_t *dev, + unsigned int c3, /* 3.10 */ + unsigned int c4, /* 3.10 */ + unsigned int c5); /* 3.10 */ +otm_hdmi_ret_t hdmi_video_set_csc_678_fixed(hdmi_device_t *dev, + unsigned int c6, /* 3.10 */ + unsigned int c7, /* 3.10 */ + unsigned int c8); /* 3.10 */ + +/* + * Description: Programs htotal/hblank values. See EAS for details as + * to how exactly to program these values + */ +otm_hdmi_ret_t hdmi_video_set_tv_timings(hdmi_device_t *dev, + unsigned int hactive, + unsigned int hblank); + +/* + * Description: Programs VSYNC and HSYNC polarity bit of Video Output Format + * Register + * + * @param [in] v : vertical polarity; GDL_TRUE -positive, + GDL_FALSE -negative + * @param [in] h : horizontal polarity; GDL_TRUE -positive, + GDL_FALSE -negative + */ +otm_hdmi_ret_t hdmi_video_set_output_polarity(hdmi_device_t *dev, + bool v, bool h); + +/* + * Description: Controls settings of PP (pixel packing) bits in GCP packets + * + * @param [in] pp : GDL_FALSE - pp controlled phase is 0; + * GDL_TRUE - pp controlled phase is 1; + */ +otm_hdmi_ret_t hdmi_video_set_gcp_packet_pp_bits(hdmi_device_t *dev, + bool pp); + +/* + * Description: Controls setting of CD (color depth) bits in GCP packet + * + * @param [in] cd : GDL_FALSE - cd bits are zero; + * GDL_TRUE - cd bits depend on color depth settings; + */ +otm_hdmi_ret_t hdmi_video_set_gcp_packet_cd_bits(hdmi_device_t *dev, + bool cd); + +/* + * Description: Controls pixel data source + * + * @param [in] pipe : GDL_TRUE - pixel data comes from the pipe + * GDL_FALSE - pixel data comes from the register + */ +otm_hdmi_ret_t hdmi_video_set_pixel_source(hdmi_device_t *dev, + bool pipe); + +/* + * Description: Sets the color of the fixed pixel source + * + * @param [in] color : lower 24 bits represent RGB / CrYCb data to be shown + */ +otm_hdmi_ret_t hdmi_video_set_pixel_color(hdmi_device_t *dev, + unsigned int color); + +/* + * hdmi_video_set_video_indicator() + * + * @param [in] on : GDL_TRUE - enable video indicator bit + * : GDL_FALSE - disable video indicator bit + */ +otm_hdmi_ret_t hdmi_video_set_video_indicator(hdmi_device_t *dev, + bool on); + +/* + * INTERRUPTS + * + * Interrupts listed in the enumeration represent actual bits to be written in + * in the Interrupt Control Register. As of now interrupt status register has + * the same layout and these value can be used directly to look for incoming + * interupts in the interrupt handler. + */ + +/* + * Description: The following interrupts are avalable + */ +typedef enum { + /* Keys are loaded from SEC */ + HDMI_INTERRUPT_HDCP_KEYS_READY = 0x00100000, + /* Ri is available (128th frame) */ + HDMI_INTERRUPT_HDCP_RI = 0x00080000, + /* Pre Ri is available (127th frame) */ + HDMI_INTERRUPT_HDCP_RI_PRE = 0x00040000, + /* Pi is available ( 16th frame) */ + HDMI_INTERRUPT_HDCP_PI = 0x00020000, + /* Pre Pi is available ( 15th frame) */ + HDMI_INTERRUPT_HDCP_PI_PRE = 0x00010000, + /* Encrypted frame is sent */ + HDMI_INTERRUPT_HDCP_FRAME = 0x00008000, + /* M0 is available for SEC access */ + HDMI_INTERRUPT_HDCP_M0 = 0x00004000, + /* R0 computation is done */ + HDMI_INTERRUPT_HDCP_R0 = 0x00002000, + /* Key buffer is ready after reset */ + HDMI_INTERRUPT_HDCP_KEY_BUFFER_RESET = 0x00001000, + /* HW has transmitted 192 bytes block */ + HDMI_INTERRUPT_AUDIO_BLOCK_DONE = 0x00000100, + /* FIFO is emtpy */ + HDMI_INTERRUPT_AUDIO_FIFO_UNDERFLOW = 0x00000080, + /* DMA completed write to DST */ + HDMI_INTERRUPT_DMA_DST_COMPLETE = 0x00000040, + /* DMA completed read from SRC */ + HDMI_INTERRUPT_DMA_SRC_COMPLETE = 0x00000020, + /* I2C bus error */ + HDMI_INTERRUPT_I2C_BUS_ERROR = 0x00000010, + /* Internal 64 bytes buffer is full */ + HDMI_INTERRUPT_I2C_BUFFER_FULL = 0x00000008, + /* Current I2C transaction done */ + HDMI_INTERRUPT_I2C_TRANSACTION_DONE = 0x00000004, + /* Detection of Hot Plug */ + HDMI_INTERRUPT_HOTPLUG_DETECT = 0x00000001 +} hdmi_interrupt_t; + +/* + * Description: Enabling/disabling interrupts of interest. + * + * @param [in] mask : user provided mask with OR'ed hdmi_interrupt_t values + */ +otm_hdmi_ret_t hdmi_interrupts_set_mask(hdmi_device_t *dev, + unsigned int mask); + +/* + * Description: Reading current interrupts settings + * + * @param [in] mask : user provided mask to store current interupts settings + */ +otm_hdmi_ret_t hdmi_interrupts_get_mask(hdmi_device_t *dev, + unsigned int *mask); + +/* + * Description: Reading current interrupts status + * + * @param [in] mask : user provided buffer to store current interrupts status + */ +otm_hdmi_ret_t hdmi_interrupts_get_status(hdmi_device_t *dev, + unsigned int *mask); + +/* + * Description: Acknowledgement of given interrupts. + * + * @param [in] mask : user provided mask with OR'ed hdmi_interrupt_t values + */ +otm_hdmi_ret_t hdmi_interrupts_acknowledge(hdmi_device_t *dev, + unsigned int mask); + +/* + * I2C + * + * Model of use: + * - higher level uses hdmi_i2c_transaction_* and hdmi_i2c_buffer_* calls + * to manipulate data and start/stop transfers + * - higher level is responsible for handling reads more than 64 bytes + */ + +/* + * Description: HDMI I2C unit support the following transactions + */ +typedef enum { + HDMI_I2C_TRANSACTION_HDCP_READ, + HDMI_I2C_TRANSACTION_HDCP_READ_RI, + HDMI_I2C_TRANSACTION_HDCP_WRITE, + HDMI_I2C_TRANSACTION_EDID_READ +} hdmi_i2c_transaction_type_t; + +/* + * Description: This structure describes I2C transaction + */ +typedef struct { + hdmi_i2c_transaction_type_t type; + unsigned int sp; + unsigned int offset; + unsigned int size; +} hdmi_i2c_transaction_t; + +/* + * Description: Size of HW I2C buffer. Higher level routines should use this + * constant when implementing reads larger than buffer size + */ +#define HDMI_I2C_BUFFER_SIZE 64 + +/* + * Description: Initiates HW accelerated I2C transaction + * + * @param [in] transaction : pointer to transaction descriptor + */ +otm_hdmi_ret_t hdmi_i2c_transaction_start(hdmi_device_t *dev, + hdmi_i2c_transaction_t *transaction); + +/* + * Description: Continues current transaction + */ +otm_hdmi_ret_t hdmi_i2c_transaction_continue(hdmi_device_t *dev); + +/* + * Description: Stops current transaction + */ +otm_hdmi_ret_t hdmi_i2c_transaction_stop(hdmi_device_t *dev); + +/* + * Description: Writes user supplied data into the internal i2c unit buffer + * User supplies up to 8 consecutive bytes. This call is + * responsible for positioning these bytes properly in the + * internal i2c buffer. + * + * The following data can be written into hdcp port: An [8 bytes], + * Ainfo [1 byte] and Aksv [5 bytes]. Keeping this in mind + * supported write size is limited to 1, 5 and 8 bytes + * + * Aksv should be provided as 5 consecutive bytes. + * An should be provided as 8 bytes word + * + * @param [in] buffer : user supplied buffer with data + * @param [in] size : size of content in user buffer + */ +otm_hdmi_ret_t hdmi_i2c_buffer_write(hdmi_device_t *dev, + void *buffer, unsigned int size); + +/* + * Description: Reads data from internal i2c buffer into user specified location + * Bytes are positioned in the user supplied buffer in the same + * order they reside at the specified offset. + * + * @param [out] buffer : user supplied buffer for data + * @param [in] size : number of requested bytes; valid range is [1..64] + */ +otm_hdmi_ret_t hdmi_i2c_buffer_read(hdmi_device_t *dev, + void *buffer, unsigned int size); + +/* + * Description: I2C speed + */ +typedef enum {HDMI_I2C_SPEED_100KBPS, + HDMI_I2C_SPEED_400KBPS +} hdmi_i2c_speed_t; + +/* + * Description: Resets, configures and enables I2C unit. + * + * @param [in] speed : operation speed + */ +otm_hdmi_ret_t hdmi_i2c_enable(hdmi_device_t *dev, hdmi_i2c_speed_t speed); + +/* + * Description: Disables I2C unit. + */ +otm_hdmi_ret_t ipil_hdmi_i2c_disable(hdmi_device_t *dev); + +/* + * Description: Alters DDC bus speed + */ +otm_hdmi_ret_t hdmi_i2c_set_ddc_speed(hdmi_device_t *dev, + bool slow); + +/* + * Description: Gets I2C unit bus monitor + */ +otm_hdmi_ret_t hdmi_i2c_get_bus_monitor(hdmi_device_t *dev, + unsigned int *value); + +/* + * Description: Gets I2C unis status + */ +otm_hdmi_ret_t hdmi_i2c_get_status(hdmi_device_t *dev, unsigned int *status); + +/* + * Non HW accelerated I2C read + */ +otm_hdmi_ret_t hdmi_i2c_sw_read(hdmi_device_t *dev, + hdmi_i2c_transaction_t *t, unsigned char *buffer); + +/* + * Non HW accelerated I2C write + */ +otm_hdmi_ret_t hdmi_i2c_sw_write(hdmi_device_t *dev, + hdmi_i2c_transaction_t *t, unsigned char *buffer); + +/* + * Configure SCL line + */ +otm_hdmi_ret_t hdmi_hal_i2c_scl_line_config(hdmi_device_t *dev, + bool bool); + +/* + * Set SCL line + */ +otm_hdmi_ret_t hdmi_hal_i2c_scl_line_set(hdmi_device_t *dev, bool b); + +/* + * Set GCP line number and pixel offset in GCPLINE register. + */ +otm_hdmi_ret_t hdmi_hal_gcp_line_set(hdmi_device_t *dev, int line_no, + int pel_off); + +/* + * Set / clear avmute flag in GCP descriptor register. + */ +otm_hdmi_ret_t hdmi_hal_gcp_avmute_set(hdmi_device_t *dev, + bool flag); + +/* + * HDCP + */ + +/* + * Description: Sets RND register of HDMI Tx + * + * @param [in] rnd : random 64 bits value + */ +otm_hdmi_ret_t hdmi_hdcp_tx_set_rnd(hdmi_device_t *dev, void *rnd); + +/* + * Description: Triggers computation of An + */ +otm_hdmi_ret_t hdmi_hdcp_tx_compute_an(hdmi_device_t *dev); + +/* + * Description: Reads An from the HDMI Tx + * + * @param [out] an : user supplied 64 bit buffer for An + */ +otm_hdmi_ret_t hdmi_hdcp_tx_get_an(hdmi_device_t *dev, void *an); + +/* + * Description: Writes An to the HDMI Tx + * + * @param [in] an : user supplied 64 bit buffer with An + */ +otm_hdmi_ret_t hdmi_hdcp_tx_set_an(hdmi_device_t *dev, void *an); + +/* + * Description: Writes HDMI Tx KSV + * + * @param [out] aksv : user supplied buffer with 40bit KSV + */ +otm_hdmi_ret_t hdmi_hdcp_tx_set_aksv(hdmi_device_t *dev, void *aksv); + +/* + * Description: Toggles REPEATER bit in HDMI Tx + * + * @param [in] repeater : GDL_TRUE - on, GDL_FALSE - off + */ +otm_hdmi_ret_t hdmi_hdcp_tx_set_repeater(hdmi_device_t *dev, + bool repeater); + +/* + * Descriptor: Loads BKSV into the HDMI Tx + * + * @param [in] bksv : user supplied buffer with BKSV + */ +otm_hdmi_ret_t hdmi_hdcp_tx_set_bksv(hdmi_device_t *dev, void *bksv); + +/* + * Descriptor: Triggers computation of M0, R0 and K0 + */ +otm_hdmi_ret_t hdmi_hdcp_tx_compute_mrk(hdmi_device_t *dev); + +/* + * Description: Makes M0 available for SEC usage + */ +otm_hdmi_ret_t hdmi_hdcp_tx_push_m0(hdmi_device_t *dev); + +/* + * Description: Toggles ENCRYPTION bit in Tx + * + * @param [in] state : GDL_TRUE - on, GDL_FALSE - off + */ +otm_hdmi_ret_t hdmi_hdcp_tx_set_encryption(hdmi_device_t *dev, + bool state); + +/* + * Description: Queries current state of ENCRYPTION bit in Tx + * + * @param [out] state : GDL_TRUE - on, GDL_FALSE - off + */ +otm_hdmi_ret_t hdmi_hdcp_tx_get_encryption(hdmi_device_t *dev, + bool *state); + +/* + * Description: Toggles AUTHENTICATON_STATE bit in Tx + * + * @param [in] state : GDL_TRUE - on, GDL_FALSE - off + */ +otm_hdmi_ret_t hdmi_hdcp_tx_set_auth(hdmi_device_t *dev, bool state); + +/* + * Description: Toggles 1.1_FEATURES bit in Tx + * + * @param [in] state : GDL_TRUE - on, GDL_FALSE - off + */ +otm_hdmi_ret_t hdmi_hdcp_tx_set_1p1_features(hdmi_device_t *dev, + bool state); + +/* + * Description: Toggles EESS bit in Tx + * + * @param [in] state : GDL_TRUE - on, GDL_FALSE - off + */ +otm_hdmi_ret_t hdmi_hdcp_tx_set_eess(hdmi_device_t *dev, bool state); + +/* + * Description: Toggles OESS bit in Tx + * + * @param [in] state : GDL_TRUE - on, GDL_FALSE - off + */ +otm_hdmi_ret_t hdmi_hdcp_tx_set_oess(hdmi_device_t *dev, bool state); + +/* + * Description: Toggles RING_CIPHER bit in Tx + * + * @param [in] state : GDL_TRUE - on, GDL_FALSE - off + */ +otm_hdmi_ret_t hdmi_hdcp_tx_set_rc(hdmi_device_t *dev, bool state); + +/* + * Description: Reads Ri from Tx + * + * @param [out] r : user supplied buffer for Ri + */ +otm_hdmi_ret_t hdmi_hdcp_tx_get_r(hdmi_device_t *dev, unsigned int *r); +otm_hdmi_ret_t hdmi_hdcp_tx_get_r_pre(hdmi_device_t *dev, unsigned int *r_pre); + +/* + * Description: Reads Pi from Tx + * + * @param [out] p : user supplied buffer for Pi + */ +otm_hdmi_ret_t hdmi_hdcp_tx_get_p(hdmi_device_t *dev, unsigned int *p); +otm_hdmi_ret_t hdmi_hdcp_tx_get_p_pre(hdmi_device_t *dev, unsigned int *p_pre); + +/* + * Description: Clears M0, R0 and An related triggers + */ +otm_hdmi_ret_t hdmi_hdcp_reset_triggers(hdmi_device_t *dev); + +/* + * OTHER STUFF + */ + +/* + * Description: Querying of unit status register + */ +otm_hdmi_ret_t hdmi_general_get_status(hdmi_device_t *dev, + unsigned int *status); + +/* + * Description: Enable/disable analog portion of HDMI phy + */ +otm_hdmi_ret_t hdmi_phy_enable(hdmi_device_t *dev, bool enable); + +/* + * Description: Set equalization + */ +otm_hdmi_ret_t hdmi_phy_set_equalization(hdmi_device_t *dev, + otm_hdmi_equalize_t eq1, + otm_hdmi_equalize_t eq2); + +/* + * Description: Set transmit level + */ +otm_hdmi_ret_t hdmi_phy_set_transmit_level(hdmi_device_t *dev, + otm_hdmi_transmit_level_t tl1, + otm_hdmi_transmit_level_t tl2); + +/* + * Description: Set termination + */ +otm_hdmi_ret_t hdmi_phy_set_termination(hdmi_device_t *dev, + otm_hdmi_termination_t t1, + otm_hdmi_termination_t t2); + +/* + * Description: Set Current Adjustment + */ +otm_hdmi_ret_t hdmi_phy_set_current(hdmi_device_t *dev, + otm_hdmi_current_t c1, + otm_hdmi_current_t c2); + +/* + * Description: Set band gap level + */ +otm_hdmi_ret_t hdmi_phy_set_bglvl(hdmi_device_t *dev, otm_hdmi_bglvl_t t); + +/* + * Description: Alternates between sending real signal and dummy pattern + */ +otm_hdmi_ret_t hdmi_misc_set_output(hdmi_device_t *dev, bool output); + +#endif /* __HDMI_HAL_H__*/ diff --git a/drivers/staging/mrst/drv/otm_hdmi/ipil/include/ipil_hdcp_api.h b/drivers/staging/mrst/drv/otm_hdmi/ipil/include/ipil_hdcp_api.h new file mode 100644 index 0000000..d504786 --- /dev/null +++ b/drivers/staging/mrst/drv/otm_hdmi/ipil/include/ipil_hdcp_api.h @@ -0,0 +1,84 @@ +/* + + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2011 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + + Intel Corporation + 2200 Mission College Blvd. + Santa Clara, CA 95054 + + BSD LICENSE + + Copyright(c) 2011 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef IPIL_HDCP_API_H +#define IPIL_HDCP_API_H + + +#include +#include "hdmi_internal.h" + +extern bool ipil_hdcp_init(void); +extern bool ipil_hdcp_is_ready(void); +extern bool ipil_hdcp_get_an(uint8_t *an, uint32_t size); +extern bool ipil_hdcp_get_aksv(uint8_t *aksv, uint32_t size); +extern bool ipil_hdcp_set_repeater(bool present); +extern bool ipil_hdcp_set_bksv(uint8_t *bksv); +extern bool ipil_hdcp_start_authentication(void); +extern bool ipil_hdcp_is_r0_ready(void); +extern bool ipil_hdcp_does_ri_match(uint16_t rx_ri); +extern bool ipil_hdcp_enable_encryption(void); +extern bool ipil_hdcp_disable(void); +extern bool ipil_hdcp_device_can_authenticate(void); + +#endif /* IPIL_HDCP_API_H */ diff --git a/drivers/staging/mrst/drv/otm_hdmi/ipil/include/ipil_hdmi.h b/drivers/staging/mrst/drv/otm_hdmi/ipil/include/ipil_hdmi.h new file mode 100644 index 0000000..843e73f --- /dev/null +++ b/drivers/staging/mrst/drv/otm_hdmi/ipil/include/ipil_hdmi.h @@ -0,0 +1,288 @@ +/* + + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2011 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + + Intel Corporation + 2200 Mission College Blvd. + Santa Clara, CA 95054 + + BSD LICENSE + + Copyright(c) 2011 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef __IPIL_HDMI_H +#define __IPIL_HDMI_H + +#include +#include +#include "otm_hdmi.h" + +#include "hdmi_internal.h" +#include "hdmi_hal.h" + +#define PCI_VENDOR_INTEL 0x8086 +#define PCI_RESOURCE_REGISTERS 0 +#define IPIL_MIN_PIXEL_CLOCK IPS_MIN_PIXEL_CLOCK +#define IPIL_MAX_PIXEL_CLOCK IPS_MAX_PIXEL_CLOCK +#define IPIL_PREFERRED_HDISPLAY IPS_PREFERRED_HDISPLAY +#define IPIL_PREFERRED_VDISPLAY IPS_PREFERRED_VDISPLAY +#define IPIL_PREFERRED_REFRESH_RATE IPS_PREFERRED_REFRESH_RATE + + +otm_hdmi_ret_t ipil_hdmi_set_hdmi_dev(hdmi_device_t *dev); + +otm_hdmi_ret_t ipil_hdmi_decide_I2C_HW(hdmi_context_t *ctx); + +/* + * Description: Enable/disable assertion of 5V signal + */ +otm_hdmi_ret_t ipil_hdmi_general_5V_enable(hdmi_device_t *dev); +otm_hdmi_ret_t ipil_hdmi_general_5V_disable(hdmi_device_t *dev); + +otm_hdmi_ret_t ipil_hdmi_set_program_clocks(hdmi_context_t *ctx, + unsigned int dclk); + +/* + * Description: Initialize/Deinitialize audio + */ +otm_hdmi_ret_t ipil_hdmi_audio_init(hdmi_context_t *ctx); +otm_hdmi_ret_t ipil_hdmi_audio_deinit(hdmi_context_t *ctx); + +/* Description: Enable/disable HDCP clock. When HDCP clock is disabled + * unencrypted data can still be transmitted + */ +otm_hdmi_ret_t ipil_hdmi_general_hdcp_clock_enable(hdmi_device_t *dev); +otm_hdmi_ret_t ipil_hdmi_general_hdcp_clock_disable(hdmi_device_t *dev); + +/* + * Description: Enable/disable audio and infoframe handling logic. This is + * useful when operating in DVI mode + */ +otm_hdmi_ret_t ipil_hdmi_general_audio_clock_enable(hdmi_device_t *dev); +otm_hdmi_ret_t ipil_hdmi_general_audio_clock_disable(hdmi_device_t *dev); + +/* + * Description: Enable/disable pixel data path from VDC. + */ +otm_hdmi_ret_t ipil_hdmi_general_pixel_clock_enable(hdmi_device_t *dev); +otm_hdmi_ret_t ipil_hdmi_general_pixel_clock_disable(hdmi_device_t *dev); + +/* + * Description: Enable/disable TDMS clock, i.e. output path from Tx is off and + * hence unit is off. + */ +otm_hdmi_ret_t ipil_hdmi_general_tdms_clock_enable(hdmi_device_t *dev); +otm_hdmi_ret_t ipil_hdmi_general_tdms_clock_disable(hdmi_device_t *dev); + +/* + * Description: Enable/disable HDMI unit + */ +otm_hdmi_ret_t ipil_hdmi_general_unit_enable(hdmi_device_t *dev); +otm_hdmi_ret_t ipil_hdmi_general_unit_disable(hdmi_device_t *dev); + +/* + * Description: Turn HDMI power rails on + */ +bool ipil_hdmi_power_rails_on(); + +/* + * Description: hdmi interrupt handler (upper half). + * handles the interrupts by reading hdmi status register + * and waking up bottom half if needed. + * + * @dev: hdmi_device_t + * + * Returns: IRQ_HANDLED on NULL input arguments, and if the + * interrupt is not HDMI HPD interrupts. + * IRQ_WAKE_THREAD if this is a HDMI HPD interrupt. + */ +irqreturn_t ipil_hdmi_irq_handler(hdmi_device_t *dev); + +/* + * Description: programs hdmi pipe src and size of the input. + * + * @dev: hdmi_device_t + * @scalingtype: scaling type (FULL_SCREEN, CENTER, NO_SCALE etc.) + * @mode: mode requested + * @adjusted_mode: adjusted mode + * @fb_width, fb_height:allocated frame buffer dimensions + * + * Returns: OTM_HDMI_SUCCESS on success + * OTM_HDMI_ERR_INVAL on NULL input arguments + */ +otm_hdmi_ret_t ipil_hdmi_crtc_mode_set_program_dspregs(hdmi_device_t *dev, + int scalingtype, + ipil_timings_t *mode, + ipil_timings_t *adjusted_mode, + int fb_width, int fb_height); + +/* + * Description: this is pre-modeset configuration. This can be + * resetting HDMI unit, disabling/enabling dpll etc + * on the need basis. + * + * @dev: hdmi_device_t + * + * Returns: OTM_HDMI_SUCCESS on success + * OTM_HDMI_ERR_INVAL on NULL input arguments + */ +otm_hdmi_ret_t ipil_hdmi_crtc_mode_set_prepare(hdmi_device_t *dev); + +/* + * Description: programs all the timing registers based on scaling type. + * + * @dev: hdmi_device_t + * @scalingtype: scaling type (FULL_SCREEN, CENTER, NO_SCALE etc.) + * @mode: mode requested + * @adjusted_mode: adjusted mode + * + * Returns: OTM_HDMI_SUCCESS on success + * OTM_HDMI_ERR_INVAL on NULL input arguments + */ +otm_hdmi_ret_t ipil_hdmi_crtc_mode_set_program_timings(hdmi_device_t *dev, + int scalingtype, + otm_hdmi_timing_t *mode, + otm_hdmi_timing_t *adjusted_mode); + +/* + * Description: programs dpll clocks, enables dpll and waits + * till it locks with DSI PLL + * + * @dev: hdmi_device_t + * @dclk: refresh rate dot clock in kHz of current mode + * + * Returns: OTM_HDMI_SUCCESS on success + * OTM_HDMI_ERR_INVAL on NULL input arguments + */ +otm_hdmi_ret_t ipil_hdmi_crtc_mode_set_program_dpll(hdmi_device_t *dev, + unsigned long dclk); + +/* + * Description: configures the display plane register and enables + * pipeconf. + * + * @dev: hdmi_device_t + * + * Returns: OTM_HDMI_SUCCESS on success + * OTM_HDMI_ERR_INVAL on NULL input arguments + */ +otm_hdmi_ret_t ipil_hdmi_crtc_mode_set_program_pipeconf(hdmi_device_t *dev); + +otm_hdmi_ret_t ipil_hdmi_enable_infoframe(hdmi_device_t *dev, + unsigned int type, + otm_hdmi_packet_t *pkt, + unsigned int freq); + +otm_hdmi_ret_t ipil_hdmi_disable_infoframe(hdmi_device_t *dev, + unsigned int type); + +otm_hdmi_ret_t ipil_hdmi_disable_all_infoframes(hdmi_device_t *dev); + +/* + * Description: encoder mode set function for hdmi. enables phy. + * set correct polarity for the current mode, sets + * correct panel fitting. + * + * + * @dev: hdmi_device_t + * @mode: mode requested + * @adjusted_mode: adjusted mode + * @is_monitor_hdmi: is monitor type is hdmi or not + * + * Returns: OTM_HDMI_SUCCESS on success + * OTM_HDMI_ERR_INVAL on NULL input arguments + */ +otm_hdmi_ret_t ipil_hdmi_enc_mode_set(hdmi_device_t *dev, + otm_hdmi_timing_t *mode, + otm_hdmi_timing_t *adjusted_mode, + bool is_monitor_hdmi); +/* + * Description: save HDMI display registers + * + * @dev: hdmi_device_t + * + * Returns: none + */ +void ipil_hdmi_save_display_registers(hdmi_device_t *dev); +void ipil_hdmi_save_data_island(hdmi_device_t *dev); + +/* + * Description: restore HDMI display registers and enable display + * + * @dev: hdmi_device_t + * + * Returns: none + */ +void ipil_hdmi_restore_and_enable_display(hdmi_device_t *dev); +void ipil_hdmi_restore_data_island(hdmi_device_t *dev); + +/* + * Description: destroys any saved HDMI data + * + * @dev: hdmi_device_t + * + * Returns: none + */ +void ipil_hdmi_destroy_saved_data(hdmi_device_t *dev); + +/* + * Description: disable HDMI display + * + * @dev: hdmi_device_t + * + * Returns: none + */ +void ipil_disable_hdmi(hdmi_device_t *dev); + +#endif /* __IPIL_HDMI_H */ diff --git a/drivers/staging/mrst/drv/otm_hdmi/ipil/specific/include/ips_hdcp_api.h b/drivers/staging/mrst/drv/otm_hdmi/ipil/specific/include/ips_hdcp_api.h new file mode 100644 index 0000000..3b94b02 --- /dev/null +++ b/drivers/staging/mrst/drv/otm_hdmi/ipil/specific/include/ips_hdcp_api.h @@ -0,0 +1,86 @@ +/* + + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2011 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + + Intel Corporation + 2200 Mission College Blvd. + Santa Clara, CA 95054 + + BSD LICENSE + + Copyright(c) 2011 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + + +#ifndef IPS_HDCP_API_H +#define IPS_HDCP_API_H + + +#include + +extern bool ips_hdcp_init(void); +extern bool ips_hdcp_is_ready(void); +extern void ips_hdcp_off(void); + +extern void ips_hdcp_get_an(uint8_t *an); +extern void ips_hdcp_get_aksv(uint8_t *aksv); +extern bool ips_hdcp_set_bksv(uint8_t *bksv); +extern bool ips_hdcp_is_r0_ready(void); +extern bool ips_hdcp_set_repeater(bool present); +extern bool ips_hdcp_start_authentication(void); +extern bool ips_hdcp_enable_encryption(void); +extern bool ips_hdcp_does_ri_match(uint16_t rx_ri); +extern bool ips_hdcp_disable(void); +extern bool ips_hdcp_device_can_authenticate(void); + +#endif /* IPS_HDCP_API_H */ diff --git a/drivers/staging/mrst/drv/otm_hdmi/ipil/specific/include/ips_hdmi.h b/drivers/staging/mrst/drv/otm_hdmi/ipil/specific/include/ips_hdmi.h new file mode 100644 index 0000000..5f446b9 --- /dev/null +++ b/drivers/staging/mrst/drv/otm_hdmi/ipil/specific/include/ips_hdmi.h @@ -0,0 +1,209 @@ +/* + + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2011 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + + Intel Corporation + 2200 Mission College Blvd. + Santa Clara, CA 95054 + + BSD LICENSE + + Copyright(c) 2011 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef __IPS_HDMI_H +#define __IPS_HDMI_H + +#include +#include +#include "otm_hdmi_types.h" +#include "hdmi_internal.h" + +/* FIXME: Make them IP specific */ +#define PCI_DEVICE_HDMI 0x080D +#define PCI_LENGTH_HDMI 0x7000 +#define IPS_MIN_PIXEL_CLOCK 25175 +#define IPS_MAX_PIXEL_CLOCK 74250 +#define IPS_PREFERRED_HDISPLAY 1920 +#define IPS_PREFERRED_VDISPLAY 1080 +#define IPS_PREFERRED_REFRESH_RATE 30 + +/* TODO: revisit these. make them IP specific */ +#define IPS_DPLL_B (0x0f018) +#define IPS_DPLL_DIV0 (0x0f048) +#define IPS_PIPEBCONF (0x71008) +#define IPS_HTOTAL_B (0x61000) +#define IPS_HBLANK_B (0x61004) +#define IPS_HSYNC_B (0x61008) +#define IPS_VTOTAL_B (0x6100c) +#define IPS_VBLANK_B (0x61010) +#define IPS_VSYNC_B (0x61014) +#define IPS_PIPEBSRC (0x6101c) +#define IPS_DSPBSTRIDE (0x71188) +#define IPS_DSPBLINOFF (0X71184) +#define IPS_DSPBTILEOFF (0x711A4) +#define IPS_DSPBSIZE (0x71190) +#define IPS_DSPBPOS (0x7118C) +#define IPS_DSPBSURF (0x7119C) +#define IPS_DSPBCNTR (0x71180) +#define IPS_DSPBSTAT (0x71024) +#define IPS_PALETTE_B (0x0a800) +#define IPS_PFIT_CONTROL (0x61230) +#define IPS_PFIT_PGM_RATIOS (0x61234) +#define IPS_HDMIPHYMISCCTL (0x61134) +#define IPS_HDMIB_CONTROL (0x61140) +#define IPS_PFIT_ENABLE (1 << 31) + +otm_hdmi_ret_t ips_hdmi_decide_I2C_HW(hdmi_context_t *ctx); + +otm_hdmi_ret_t ips_hdmi_general_5V_enable(hdmi_device_t *dev); + +otm_hdmi_ret_t ips_hdmi_general_5V_disable(hdmi_device_t *dev); + +otm_hdmi_ret_t ips_hdmi_set_program_clocks(hdmi_context_t *ctx, + unsigned int dclk); + +otm_hdmi_ret_t ips_hdmi_audio_init(hdmi_context_t *ctx); + +otm_hdmi_ret_t ips_hdmi_audio_deinit(hdmi_context_t *ctx); + +otm_hdmi_ret_t ips_hdmi_general_unit_enable(hdmi_device_t *dev); + +otm_hdmi_ret_t ips_hdmi_general_unit_disable(hdmi_device_t *dev); + +otm_hdmi_ret_t ips_hdmi_general_hdcp_clock_enable(hdmi_device_t *dev); + +otm_hdmi_ret_t ips_hdmi_general_hdcp_clock_disable(hdmi_device_t *dev); + +otm_hdmi_ret_t ips_hdmi_general_audio_clock_enable(hdmi_device_t *dev); + +otm_hdmi_ret_t ips_hdmi_general_audio_clock_disable(hdmi_device_t *dev); + +otm_hdmi_ret_t ips_hdmi_general_pixel_clock_enable(hdmi_device_t *dev); + +otm_hdmi_ret_t ips_hdmi_general_pixel_clock_disable(hdmi_device_t *dev); + +otm_hdmi_ret_t ips_hdmi_general_tdms_clock_enable(hdmi_device_t *dev); + +otm_hdmi_ret_t ips_hdmi_general_tdms_clock_disable(hdmi_device_t *dev); + +otm_hdmi_ret_t ips_hdmi_i2c_disable(hdmi_device_t *dev); + +bool ips_hdmi_power_rails_on(); + +irqreturn_t ips_hdmi_irq_handler(void *io_address); + +otm_hdmi_ret_t ips_hdmi_disable_vid_infoframe(hdmi_device_t *dev, + unsigned int type); + +otm_hdmi_ret_t ips_hdmi_enable_vid_infoframe(hdmi_device_t *dev, + unsigned int type, + otm_hdmi_packet_t *pkt, + unsigned int freq); + +otm_hdmi_ret_t ips_hdmi_disable_all_infoframes(hdmi_device_t *dev); + +/* + * Description: gets the best dpll clock value based on + * current timing mode clock. + * + * @clk: refresh rate dot clock in kHz of current mode + * @pdpll, pfp: will be set to adjusted dpll values. + * @pclock_khz: tmds clk value for the best pll and is needed for audio. + * This field has to be moved into OTM audio + * interfaces when implemented + * + * Returns: OTM_HDMI_SUCCESS on success + * OTM_HDMI_ERR_INVAL on NULL input arguments. + */ +otm_hdmi_ret_t ips_hdmi_get_adjusted_clk(unsigned long clk, + u32 *pdpll, u32 *pfp, uint32_t *pclock_khz); + +/* + * Description: restore HDMI display registers and enable display + * + * @dev: hdmi_device_t + * + * Returns: none + */ +void ips_hdmi_restore_and_enable_display(hdmi_device_t *dev); +void ips_hdmi_restore_data_island(hdmi_device_t *dev); + +/* + * Description: save HDMI display registers + * + * @dev: hdmi_device_t + * + * Returns: none + */ +void ips_hdmi_save_display_registers(hdmi_device_t *dev); +void ips_hdmi_save_data_island(hdmi_device_t *dev); + +/* + * Description: destroys any saved HDMI data + * + * @dev: hdmi_device_t + * + * Returns: none + */ +void ips_hdmi_destroy_saved_data(hdmi_device_t *dev); + +/* + * Description: disable HDMI display + * + * @dev: hdmi_device_t + * + * Returns: none + */ +void ips_disable_hdmi(hdmi_device_t *dev); +#endif /* __IPS_HDMI_H */ diff --git a/drivers/staging/mrst/drv/otm_hdmi/ipil/specific/mfld/ips_hdcp.c b/drivers/staging/mrst/drv/otm_hdmi/ipil/specific/mfld/ips_hdcp.c new file mode 100644 index 0000000..d2426f7 --- /dev/null +++ b/drivers/staging/mrst/drv/otm_hdmi/ipil/specific/mfld/ips_hdcp.c @@ -0,0 +1,369 @@ +/* + + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2011 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + + Intel Corporation + 2200 Mission College Blvd. + Santa Clara, CA 95054 + + BSD LICENSE + + Copyright(c) 2011 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + + +#include +#include +#include "hdcp_rx_defs.h" +#include "mfld_hdcp_reg.h" +#include "mfld_utils.h" + +static void ips_hdcp_capture_an(void); +static bool ips_hdcp_is_hdcp_on(void); +static bool ips_hdcp_is_an_ready(void); +static void ips_hdcp_read_an(uint8_t *an); +static void ips_hdcp_write_rx_ri(uint16_t rx_ri); +static void ips_hdcp_set_config(int val); +static int ips_hdcp_get_config(void); +static bool ips_hdcp_is_encrypting(void); +static uint8_t ips_hdcp_get_repeater_control(void); +static void ips_hdcp_set_repeater_control(int value); +static uint8_t ips_hdcp_get_repeater_status(void); +static int ips_hdcp_repeater_v_match_check(void); +static bool ips_hdcp_repeater_is_busy(void); +static int ips_hdcp_repeater_rdy_for_nxt_data(void); + +static uint32_t ips_hdcp_get_status(void) +{ + return hdmi_read32(MDFLD_HDCP_STATUS_REG); +} + +static void ips_hdcp_enable_port(bool enable) +{ + uint32_t hdmib_reg = hdmi_read32(MDFLD_HDMIB_CNTRL_REG); + if (enable) + hdmib_reg |= MDFLD_HDMIB_HDCP_PORT_SEL; + else + hdmib_reg &= ~MDFLD_HDMIB_HDCP_PORT_SEL; + hdmi_write32(MDFLD_HDMIB_CNTRL_REG, hdmib_reg); +} + +static void ips_hdcp_capture_an(void) +{ + hdmi_write32(MDFLD_HDCP_INIT_REG, (uint32_t) jiffies); + hdmi_write32(MDFLD_HDCP_INIT_REG, (uint32_t) (jiffies >> 1)); + hdmi_write32(MDFLD_HDCP_CONFIG_REG, HDCP_CAPTURE_AN); +} + +static bool ips_hdcp_is_hdcp_on(void) +{ + struct ips_hdcp_status_reg_t status; + status.value = ips_hdcp_get_status(); + + if (status.hdcp_on) + return true; + + return false; +} + +static bool ips_hdcp_is_an_ready(void) +{ + struct ips_hdcp_status_reg_t status; + status.value = ips_hdcp_get_status(); + + if (status.an_ready) + return true; + + return false; +} + +static void ips_hdcp_read_an(uint8_t *an) +{ + uint8_t i = 0; + struct double_word_t temp; + temp.value = 0; + temp.low = hdmi_read32(MDFLD_HDCP_AN_LOW_REG); + temp.high = hdmi_read32(MDFLD_HDCP_AN_HI_REG); + for (i = 0; i < HDCP_AN_SIZE; i++) + an[i] = temp.byte[i]; +} + +static void ips_hdcp_write_rx_ri(uint16_t rx_ri) +{ + hdmi_write32(MDFLD_HDCP_RECEIVER_RI_REG, rx_ri); +} + +static void ips_hdcp_set_config(int val) +{ + struct ips_hdcp_config_reg_t config; + config.value = hdmi_read32(MDFLD_HDCP_CONFIG_REG); + config.hdcp_config = val; + hdmi_write32(MDFLD_HDCP_CONFIG_REG, config.value); +} + +static int ips_hdcp_get_config(void) +{ + struct ips_hdcp_config_reg_t config; + config.value = hdmi_read32(MDFLD_HDCP_CONFIG_REG); + return config.hdcp_config; +} + +static bool ips_hdcp_config_is_encrypting(void) +{ + if (ips_hdcp_get_config() == HDCP_AUTHENTICATE_AND_ENCRYPT) + return true; + return false; +} + +static bool ips_hdcp_is_encrypting(void) +{ + struct ips_hdcp_status_reg_t status; + status.value = ips_hdcp_get_status(); + + if (status.encrypting) + return true; + + return false; +} + +static uint8_t ips_hdcp_get_repeater_control(void) +{ + struct ips_hdcp_repeater_reg_t repeater; + repeater.value = hdmi_read32(MDFLD_HDCP_REP_REG); + return repeater.control; +} + +static void ips_hdcp_set_repeater_control(int value) +{ + struct ips_hdcp_repeater_reg_t repeater; + repeater.value = hdmi_read32(MDFLD_HDCP_REP_REG); + repeater.control = value; + hdmi_write32(MDFLD_HDCP_REP_REG, repeater.value); +} + +static uint8_t ips_hdcp_get_repeater_status(void) +{ + struct ips_hdcp_repeater_reg_t repeater; + repeater.value = hdmi_read32(MDFLD_HDCP_REP_REG); + return repeater.status; +} + +static int ips_hdcp_repeater_v_match_check(void) +{ + uint8_t status = ips_hdcp_get_repeater_status(); + switch (status) { + case HDCP_REPEATER_STATUS_COMPLETE_MATCH: + return 1; + case HDCP_REPEATER_STATUS_BUSY: + return -1; + default: + return 0; + } +} + +static bool ips_hdcp_repeater_is_busy(void) +{ + uint8_t status = ips_hdcp_get_repeater_status(); + if (status == HDCP_REPEATER_STATUS_BUSY) + return true; + return false; +} + +static int ips_hdcp_repeater_rdy_for_nxt_data(void) +{ + uint8_t status = ips_hdcp_get_repeater_status(); + if (status == HDCP_REPEATER_STATUS_RDY_NEXT_DATA) + return true; + return false; +} + +bool ips_hdcp_is_ready(void) +{ + struct ips_hdcp_status_reg_t status; + status.value = ips_hdcp_get_status(); + + if (status.fus_success && status.fus_complete) + return true; + + return false; +} + +void ips_hdcp_off(void) +{ + ips_hdcp_set_config(HDCP_Off); + msleep(30); +} + +void ips_hdcp_get_an(uint8_t *an) +{ + bool ret = false; + ips_hdcp_off(); + ips_hdcp_capture_an(); + do { + ret = ips_hdcp_is_an_ready(); + } while (ret == false); + ips_hdcp_read_an(an); +} + +void ips_hdcp_get_aksv(uint8_t *aksv) +{ + static uint8_t save_aksv[HDCP_KSV_SIZE] = {0, 0, 0, 0, 0}; + static bool aksv_read_once = false; + uint8_t i = 0; + struct double_word_t temp; + if (aksv_read_once == false) { + temp.value = 0; + temp.low = hdmi_read32(MDFLD_HDCP_AKSV_LOW_REG); + temp.high = hdmi_read32(MDFLD_HDCP_AKSV_HI_REG); + aksv_read_once = true; + for (i = 0; i < HDCP_KSV_SIZE; i++) + save_aksv[i] = temp.byte[i]; + } + for (i = 0; i < HDCP_KSV_SIZE; i++) + aksv[i] = save_aksv[i]; +} + +bool ips_hdcp_set_bksv(uint8_t *bksv) +{ + uint8_t i = 0; + struct double_word_t temp; + if (bksv == NULL) + return false; + temp.value = 0; + for (i = 0; i < HDCP_KSV_SIZE; i++) + temp.byte[i] = bksv[i]; + + hdmi_write32(MDFLD_HDCP_BKSV_LOW_REG, temp.low); + hdmi_write32(MDFLD_HDCP_BKSV_HI_REG, temp.high); + return true; +} + +bool ips_hdcp_set_repeater(bool present) +{ + struct ips_hdcp_repeater_reg_t repeater; + repeater.value = hdmi_read32(MDFLD_HDCP_REP_REG); + repeater.present = present; + hdmi_write32(MDFLD_HDCP_REP_REG, repeater.value); + return true; +} + +bool ips_hdcp_start_authentication(void) +{ + ips_hdcp_enable_port(true); + ips_hdcp_set_config(HDCP_AUTHENTICATE_AND_ENCRYPT); + return true; +} + +bool ips_hdcp_is_r0_ready(void) +{ + struct ips_hdcp_status_reg_t status; + status.value = ips_hdcp_get_status(); + + if (status.ri_ready) { + /* Set Ri to 0 */ + ips_hdcp_write_rx_ri(0); + /* Set Repeater to Not Present */ + ips_hdcp_set_repeater(0); + return true; + } + return false; +} + +bool ips_hdcp_enable_encryption(void) +{ + struct ips_hdcp_status_reg_t status; + uint32_t hdmib_reg = hdmi_read32(MDFLD_HDMIB_CNTRL_REG); + status.value = ips_hdcp_get_status(); + + if (ips_hdcp_is_hdcp_on() && + ips_hdcp_config_is_encrypting() && + status.ri_match && + (hdmib_reg & MDFLD_HDMIB_HDCP_PORT_SEL)) + return true; + return false; +} + + +bool ips_hdcp_does_ri_match(uint16_t rx_ri) +{ + struct ips_hdcp_status_reg_t status; + + ips_hdcp_write_rx_ri(rx_ri); + status.value = ips_hdcp_get_status(); + if (status.ri_match) + return true; + return false; +} + +bool ips_hdcp_disable(void) +{ + ips_hdcp_off(); + /* Set Rx_Ri to 0 */ + ips_hdcp_write_rx_ri(0); + /* Set Repeater to Not Present */ + ips_hdcp_set_repeater(false); + /* Disable HDCP on this Port */ + /* ips_hdcp_enable_port(false); */ + return true; +} + +bool ips_hdcp_init(void) +{ + return true; +} + +bool ips_hdcp_device_can_authenticate(void) +{ + return true; +} + diff --git a/drivers/staging/mrst/drv/otm_hdmi/ipil/specific/mfld/ips_hdmi.c b/drivers/staging/mrst/drv/otm_hdmi/ipil/specific/mfld/ips_hdmi.c new file mode 100644 index 0000000..cc879e3 --- /dev/null +++ b/drivers/staging/mrst/drv/otm_hdmi/ipil/specific/mfld/ips_hdmi.c @@ -0,0 +1,815 @@ +/* + + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2011 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + + Intel Corporation + 2200 Mission College Blvd. + Santa Clara, CA 95054 + + BSD LICENSE + + Copyright(c) 2011 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + + +#include +#include +#include +#include +#include + +#include "otm_hdmi.h" +#include "hdmi_internal.h" +#include "ips_hdmi.h" +#include "mfld_hdmi_reg.h" +#include "ipil_internal.h" +#include "mfld_utils.h" + +static unsigned char vrint_data; + +otm_hdmi_ret_t ips_hdmi_decide_I2C_HW(hdmi_context_t *ctx) +{ + /* TODO: TO BE IMPLEMENTED */ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + return rc; +} + +otm_hdmi_ret_t ips_hdmi_general_5V_enable(hdmi_device_t *dev) +{ + /* TODO: TO BE IMPLEMENTED */ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + return rc; +} + +otm_hdmi_ret_t ips_hdmi_general_5V_disable(hdmi_device_t *dev) +{ + /* TODO: TO BE IMPLEMENTED */ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + return rc; +} + +otm_hdmi_ret_t ips_hdmi_set_program_clocks(hdmi_context_t *ctx, + unsigned int dclk) +{ + /* TODO: TO BE IMPLEMENTED */ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + return rc; +} + +otm_hdmi_ret_t ips_hdmi_audio_init(hdmi_context_t *ctx) +{ + /* TODO: TO BE IMPLEMENTED */ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + return rc; +} + +otm_hdmi_ret_t ips_hdmi_audio_deinit(hdmi_context_t *ctx) +{ + /* TODO: TO BE IMPLEMENTED */ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + return rc; +} + +otm_hdmi_ret_t ips_hdmi_general_unit_enable(hdmi_device_t *dev) +{ + /* TODO: TO BE IMPLEMENTED */ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + return rc; +} + +otm_hdmi_ret_t ips_hdmi_general_unit_disable(hdmi_device_t *dev) +{ + /* TODO: TO BE IMPLEMENTED */ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + return rc; +} + +otm_hdmi_ret_t ips_hdmi_general_hdcp_clock_enable(hdmi_device_t *dev) +{ + /* TODO: TO BE IMPLEMENTED */ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + return rc; +} + +otm_hdmi_ret_t ips_hdmi_general_hdcp_clock_disable(hdmi_device_t *dev) +{ + /* TODO: TO BE IMPLEMENTED */ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + return rc; +} + +otm_hdmi_ret_t ips_hdmi_general_audio_clock_enable(hdmi_device_t *dev) +{ + /* TODO: TO BE IMPLEMENTED */ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + return rc; +} + +otm_hdmi_ret_t ips_hdmi_general_audio_clock_disable(hdmi_device_t *dev) +{ + /* TODO: TO BE IMPLEMENTED */ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + return rc; +} + +otm_hdmi_ret_t ips_hdmi_general_pixel_clock_enable(hdmi_device_t *dev) +{ + /* TODO: TO BE IMPLEMENTED */ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + return rc; +} + +otm_hdmi_ret_t ips_hdmi_general_pixel_clock_disable(hdmi_device_t *dev) +{ + /* TODO: TO BE IMPLEMENTED */ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + return rc; +} + +otm_hdmi_ret_t ips_hdmi_general_tdms_clock_enable(hdmi_device_t *dev) +{ + /* TODO: TO BE IMPLEMENTED */ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + return rc; +} + +otm_hdmi_ret_t ips_hdmi_general_tdms_clock_disable(hdmi_device_t *dev) +{ + /* TODO: TO BE IMPLEMENTED */ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + return rc; +} + +otm_hdmi_ret_t ips_hdmi_i2c_disable(hdmi_device_t *dev) +{ + /* TODO: TO BE IMPLEMENTED */ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + return rc; +} + +bool ips_hdmi_power_rails_on() +{ + /* Turn on HDMI power rails. These will be on in all non-S0iX + * states so that HPD and connection status will work. VCC330 + * will have ~1.7mW usage during idle states when the display + * is active + */ + intel_scu_ipc_iowrite8(IPS_MSIC_VCC330CNT, IPS_VCC330_ON); + + if (vrint_data & IPS_HDMI_OCP_STATUS) { + /* When there occurs overcurrent in MSIC HDMI HDP, + * need to reset VHDMIEN by clearing to 0 then set to 1 + */ + intel_scu_ipc_iowrite8(IPS_MSIC_VHDMICNT, + IPS_VHDMI_OFF); + + /* MSIC documentation requires that there be a 500us + * delay after enabling VCC330 before you can enable + * VHDMI + */ + usleep_range(500, 1000); + + /* Extend VHDMI switch de-bounce time, to avoid + * redundant MSIC VREG/HDMI interrupt during HDMI + * cable plugged in/out + */ + intel_scu_ipc_iowrite8(IPS_MSIC_VHDMICNT, + IPS_VHDMI_ON | + IPS_VHDMI_DB_30MS); + } + + if (vrint_data & IPS_HDMI_HPD_STATUS_BIT) + return true; + return false; +} + +irqreturn_t ips_hdmi_irq_handler(void *io_address) +{ + /* Read interrupt status register */ + if (io_address != NULL) { + vrint_data = readb(io_address); + + /* handle HDMI HPD interrupts. */ + if (vrint_data & (IPS_HDMI_HPD_STATUS_BIT|IPS_HDMI_OCP_STATUS)) + return IRQ_WAKE_THREAD; + } + return IRQ_HANDLED; +} + +otm_hdmi_ret_t ips_hdmi_disable_vid_infoframe(hdmi_device_t *dev, + unsigned int type) +{ + uint32_t vid_dip_ctl = 0; + uint32_t dip_type = 0; + uint32_t index = 0; + + if (!dev) + return OTM_HDMI_ERR_NULL_ARG; + + /* Enable Particular Packet Type */ + switch (type) { + case HDMI_PACKET_AVI: + dip_type = IPS_HDMI_EN_DIP_TYPE_AVI; + index = IPS_HDMI_DIP_BUFF_INDX_AVI; + break; + case HDMI_PACKET_VS: + dip_type = IPS_HDMI_EN_DIP_TYPE_VS; + index = IPS_HDMI_DIP_BUFF_INDX_VS; + break; + case HDMI_PACKET_SPD: + dip_type = IPS_HDMI_EN_DIP_TYPE_SPD; + index = IPS_HDMI_DIP_BUFF_INDX_SPD; + break; + default: + return OTM_HDMI_ERR_INVAL; + } + + /* Disable DIP type & set the buffer index & reset access address */ + vid_dip_ctl = hdmi_read32(IPS_HDMI_VID_DIP_CTL_ADDR); + vid_dip_ctl &= ~(dip_type | + IPS_HDMI_DIP_BUFF_INDX_MASK | + IPS_HDMI_DIP_ACCESS_ADDR_MASK | + IPS_HDMI_DIP_TRANSMISSION_FREQ_MASK); + vid_dip_ctl |= (index | + IPS_HDMI_VID_PORT_B_SELECT | + IPS_HDMI_VID_EN_DIP); + hdmi_write32(IPS_HDMI_VID_DIP_CTL_ADDR, vid_dip_ctl); + + return OTM_HDMI_SUCCESS; +} + +/* TODO: REVISIT FOR OPTIMIZATION */ +otm_hdmi_ret_t ips_hdmi_enable_vid_infoframe(hdmi_device_t *dev, + unsigned int type, otm_hdmi_packet_t *pkt, unsigned int freq) +{ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + uint32_t vid_dip_ctl = 0; + uint32_t index = 0; + uint32_t dip_type = 0; + uint32_t dip_data = 0; + + if (!dev || !pkt) + return OTM_HDMI_ERR_NULL_ARG; + + if (freq > HDMI_DIP_SEND_ATLEAST_EVERY_OTHER_VSYNC) + return OTM_HDMI_ERR_INVAL; + + rc = ips_hdmi_disable_vid_infoframe(dev, type); + if (rc != OTM_HDMI_SUCCESS) + return rc; + + /* Add delay for any Pending transmissions ~ 2 VSync + 3 HSync */ + msleep_interruptible(32 + 8); + + /* Enable Particular Packet Type */ + switch (type) { + case HDMI_PACKET_AVI: + dip_type = IPS_HDMI_EN_DIP_TYPE_AVI; + index = IPS_HDMI_DIP_BUFF_INDX_AVI; + break; + case HDMI_PACKET_VS: + dip_type = IPS_HDMI_EN_DIP_TYPE_VS; + index = IPS_HDMI_DIP_BUFF_INDX_VS; + break; + case HDMI_PACKET_SPD: + dip_type = IPS_HDMI_EN_DIP_TYPE_SPD; + index = IPS_HDMI_DIP_BUFF_INDX_SPD; + break; + default: + return OTM_HDMI_ERR_INVAL; + } + + /* Disable DIP type & set the buffer index & reset access address */ + vid_dip_ctl = hdmi_read32(IPS_HDMI_VID_DIP_CTL_ADDR); + vid_dip_ctl &= ~(dip_type | + IPS_HDMI_DIP_BUFF_INDX_MASK | + IPS_HDMI_DIP_ACCESS_ADDR_MASK | + IPS_HDMI_DIP_TRANSMISSION_FREQ_MASK); + vid_dip_ctl |= (index | + IPS_HDMI_VID_PORT_B_SELECT | + IPS_HDMI_VID_EN_DIP); + hdmi_write32(IPS_HDMI_VID_DIP_CTL_ADDR, vid_dip_ctl); + + /* Write Packet Data */ + dip_data = 0; + dip_data = (pkt->header[0] << 0) | + (pkt->header[1] << 8) | + (pkt->header[2] << 16); + hdmi_write32(IPS_HDMI_VIDEO_DIP_DATA_ADDR, dip_data); + + for (index = 0; index < (HDMI_DIP_PACKET_DATA_LEN/4); index++) { + dip_data = pkt->data32[index]; + hdmi_write32(IPS_HDMI_VIDEO_DIP_DATA_ADDR, dip_data); + } + + /* Enable Packet Type & Transmission Frequency */ + vid_dip_ctl = hdmi_read32(IPS_HDMI_VID_DIP_CTL_ADDR); + vid_dip_ctl &= ~IPS_HDMI_VID_PORT_SELECT_MASK; + vid_dip_ctl |= (IPS_HDMI_VID_PORT_B_SELECT | IPS_HDMI_VID_EN_DIP); + vid_dip_ctl |= (dip_type | (freq << IPS_HDMI_DIP_TX_FREQ_SHIFT)); + pr_debug("vid_dip_ctl %x\n", vid_dip_ctl); + hdmi_write32(IPS_HDMI_VID_DIP_CTL_ADDR, vid_dip_ctl); + + return rc; +} + +/* + * Description: disable all infoframes + * + * @dev: hdmi_device + * + * Returns: OTM_HDMI_ERR_NULL_ARG on NULL parameters + * OTM_HDMI_SUCCESS on success + */ +otm_hdmi_ret_t ips_hdmi_disable_all_infoframes(hdmi_device_t *dev) +{ + if (!dev) + return OTM_HDMI_ERR_NULL_ARG; + + /* Disable Video Related Infoframes */ + hdmi_write32(IPS_HDMI_VID_DIP_CTL_ADDR, 0x0); + /* Disable Audio Related Infoframes */ + hdmi_write32(IPS_HDMI_AUD_DIP_CTL_ADDR, 0x0); + + /* TODO: Disable other infoframes? */ + + return OTM_HDMI_SUCCESS; +} + +/* TODO: revisit: mode into a .h file */ +#define IPS_DOT_MIN 19750 +#define IPS_DOT_MAX 120000 +/* Min/Max value based on DPLL parameter interface table + * from Penwell Display HAS + */ +#define IPS_DPLL_M_MIN_19 105 +#define IPS_DPLL_M_MAX_19 197 +#define IPS_DPLL_P1_MIN_19 2 +#define IPS_DPLL_P1_MAX_19 10 +#define IPS_LIMIT_DPLL_19 0 +#define IPS_VCO_SEL (1 << 16) + +static const struct ipil_clock_limits_t ipil_clock_limits[] = { + { /* CRYSTAL_19 */ + .dot = {.min = IPS_DOT_MIN, .max = IPS_DOT_MAX}, + .m = {.min = IPS_DPLL_M_MIN_19, .max = IPS_DPLL_M_MAX_19}, + .p1 = {.min = IPS_DPLL_P1_MIN_19, .max = IPS_DPLL_P1_MAX_19}, + }, +}; + +/* TODO: revisit: mode into a .h file */ +#define IPS_M_MIN 21 +#define IPS_M_MAX 197 + +static const u32 ips_m_converts[] = { +/* M configuration table from 9-bit LFSR table */ + 224, 368, 440, 220, 366, 439, 219, 365, 182, 347, /* 21 - 30 */ + 173, 342, 171, 85, 298, 149, 74, 37, 18, 265, /* 31 - 40 */ + 388, 194, 353, 432, 216, 108, 310, 155, 333, 166, /* 41 - 50 */ + 83, 41, 276, 138, 325, 162, 337, 168, 340, 170, /* 51 - 60 */ + 341, 426, 469, 234, 373, 442, 221, 110, 311, 411, /* 61 - 70 */ + 461, 486, 243, 377, 188, 350, 175, 343, 427, 213, /* 71 - 80 */ + 106, 53, 282, 397, 354, 227, 113, 56, 284, 142, /* 81 - 90 */ + 71, 35, 273, 136, 324, 418, 465, 488, 500, 506, /* 91 - 100 */ + 253, 126, 63, 287, 399, 455, 483, 241, 376, 444, /* 101 - 110 */ + 478, 495, 503, 251, 381, 446, 479, 239, 375, 443, /* 111 - 120 */ + 477, 238, 119, 315, 157, 78, 295, 147, 329, 420, /* 121 - 130 */ + 210, 105, 308, 154, 77, 38, 275, 137, 68, 290, /* 131 - 140 */ + 145, 328, 164, 82, 297, 404, 458, 485, 498, 249, /* 141 - 150 */ + 380, 190, 351, 431, 471, 235, 117, 314, 413, 206, /* 151 - 160 */ + 103, 51, 25, 12, 262, 387, 193, 96, 48, 280, /* 161 - 170 */ + 396, 198, 99, 305, 152, 76, 294, 403, 457, 228, /* 171 - 180 */ + 114, 313, 156, 334, 423, 467, 489, 244, 378, 445, /*181 - 190 */ + 222, 367, 183, 91, 45, 22, 11, 261, 130, 321, /* 191 - 200 */ +}; + +/* + * Derive the pixel clock for the given refclk and + * divisors for 8xx chips. + */ +static void __ips_hdmi_derive_dot_clock(int refclk, struct ipil_clock_t *clock) +{ + clock->dot = (refclk * clock->m) / clock->p1; +} + +static const struct ipil_clock_limits_t *__ips_hdmi_clk_limits(void) +{ + const struct ipil_clock_limits_t *limit = NULL; + + /* + * CRYSTAL_19 is enabled for medfield. + * Expand this logic for other types. + */ + limit = &ipil_clock_limits[IPS_LIMIT_DPLL_19]; + return limit; +} + +static bool __ips_hdmi_find_bestPll(int target, int refclk, + struct ipil_clock_t *best_clock) +{ + struct ipil_clock_t clock; + const struct ipil_clock_limits_t *limit = __ips_hdmi_clk_limits(); + int err = target; + + memset(best_clock, 0, sizeof(*best_clock)); + for (clock.m = limit->m.min; clock.m <= limit->m.max; clock.m++) { + for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max; + clock.p1++) { + int this_err; + + __ips_hdmi_derive_dot_clock(refclk, &clock); + + this_err = abs(clock.dot - target); + if (this_err < err) { + *best_clock = clock; + err = this_err; + } + } + } + return err != target; +} + +/* + * Description: gets the best dpll clock value based on + * current timing mode clock. + * + * @clk: refresh rate dot clock in kHz of current mode + * @pdpll, pfp: will be set to adjusted dpll values. + * @pclock_khz: tmds clk value for the best pll and is needed for audio. + * This field has to be moved into OTM audio + * interfaces when implemented + * + * Returns: OTM_HDMI_SUCCESS on success + * OTM_HDMI_ERR_INVAL on NULL input arguments. + */ +otm_hdmi_ret_t ips_hdmi_get_adjusted_clk(unsigned long clk, + u32 *pdpll, u32 *pfp, + uint32_t *pclock_khz) +{ + int refclk; + int clk_n; + int clk_p2; + int clk_byte = 1; + int m_conv = 0; + int clk_tmp; + u32 dpll, fp; + bool ret; + struct ipil_clock_t clock; + + /* NULL checks */ + if (pdpll == NULL || pfp == NULL || pclock_khz == NULL) { + pr_debug("\ninvalid argument\n"); + return OTM_HDMI_ERR_INVAL; + } + + /* values corresponds to CRYSTAL_19, as this is enabled on mdfld */ + refclk = 19200; + clk_n = 1; + clk_p2 = 10; + + clk_tmp = clk * clk_n * clk_p2 * clk_byte; + ret = __ips_hdmi_find_bestPll(clk_tmp, refclk, &clock); + /* + * TODO: tmds clk value for the best pll found and is needed for audio. + * This field has to be moved into OTM audio interfaces + * when implemented. + */ + *pclock_khz = clock.dot / (clk_n * clk_p2 * clk_byte); + if (ret) + m_conv = ips_m_converts[(clock.m - IPS_M_MIN)]; + + dpll = 0; + dpll |= IPS_VCO_SEL; + /* compute bitmask from p1 value */ + dpll |= (1 << (clock.p1 - 2)) << 17; + + fp = (clk_n / 2) << 16; + fp |= m_conv; + + /* update the pointers */ + *pdpll = dpll; + *pfp = fp; + + return OTM_HDMI_SUCCESS; +} + +/* + * Description: save HDMI display registers + * + * @dev: hdmi_device_t + * + * Returns: none + */ +void ips_hdmi_save_display_registers(hdmi_device_t *dev) +{ + int i; + if (NULL == dev) { + pr_debug("\n%s invalid argument\n", __func__); + return; + } + + dev->reg_state.saveDPLL = hdmi_read32(IPS_DPLL_B); + dev->reg_state.saveFPA0 = hdmi_read32(IPS_DPLL_DIV0); + dev->reg_state.savePIPEBCONF = hdmi_read32(IPS_PIPEBCONF); + dev->reg_state.saveHTOTAL_B = hdmi_read32(IPS_HTOTAL_B); + dev->reg_state.saveHBLANK_B = hdmi_read32(IPS_HBLANK_B); + dev->reg_state.saveHSYNC_B = hdmi_read32(IPS_HSYNC_B); + dev->reg_state.saveVTOTAL_B = hdmi_read32(IPS_VTOTAL_B); + dev->reg_state.saveVBLANK_B = hdmi_read32(IPS_VBLANK_B); + dev->reg_state.saveVSYNC_B = hdmi_read32(IPS_VSYNC_B); + dev->reg_state.savePIPEBSRC = hdmi_read32(IPS_PIPEBSRC); + dev->reg_state.saveDSPBSTRIDE = hdmi_read32(IPS_DSPBSTRIDE); + dev->reg_state.saveDSPBLINOFF = hdmi_read32(IPS_DSPBLINOFF); + dev->reg_state.saveDSPBTILEOFF = hdmi_read32(IPS_DSPBTILEOFF); + dev->reg_state.saveDSPBSIZE = hdmi_read32(IPS_DSPBSIZE); + dev->reg_state.saveDSPBPOS = hdmi_read32(IPS_DSPBPOS); + dev->reg_state.saveDSPBSURF = hdmi_read32(IPS_DSPBSURF); + dev->reg_state.saveDSPBCNTR = hdmi_read32(IPS_DSPBCNTR); + dev->reg_state.saveDSPBSTATUS = hdmi_read32(IPS_DSPBSTAT); + + /*save palette (gamma) */ + for (i = 0; i < 256; i++) + dev->reg_state.save_palette_b[i] = + hdmi_read32(IPS_PALETTE_B + (i<<2)); + + dev->reg_state.savePFIT_CONTROL = hdmi_read32(IPS_PFIT_CONTROL); + dev->reg_state.savePFIT_PGM_RATIOS = hdmi_read32(IPS_PFIT_PGM_RATIOS); + dev->reg_state.saveHDMIPHYMISCCTL = hdmi_read32(IPS_HDMIPHYMISCCTL); + dev->reg_state.saveHDMIB_CONTROL = hdmi_read32(IPS_HDMIB_CONTROL); + + dev->reg_state.valid = true; +} + +/* + * Description: saves HDMI data island packets + * + * @dev: hdmi_device_t + * + * Returns: none + */ +void ips_hdmi_save_data_island(hdmi_device_t *dev) +{ + uint32_t index = 0; + uint32_t reg_val = 0; + + if (NULL == dev) { + pr_debug("\n%s invalid argument\n", __func__); + return; + } + + /* Save AVI Infoframe Data */ + reg_val = hdmi_read32(IPS_HDMI_VID_DIP_CTL_ADDR); + if ((reg_val & IPS_HDMI_VID_EN_DIP) && + (reg_val & IPS_HDMI_EN_DIP_TYPE_AVI)) { + /* set DIP buffer index to AVI */ + reg_val &= ~IPS_HDMI_DIP_BUFF_INDX_MASK; + reg_val |= IPS_HDMI_DIP_BUFF_INDX_AVI; + hdmi_write32(IPS_HDMI_VID_DIP_CTL_ADDR, reg_val); + /* set DIP RAM Access Address to 0 */ + reg_val &= ~IPS_HDMI_DIP_ACCESS_ADDR_MASK; + hdmi_write32(IPS_HDMI_VID_DIP_CTL_ADDR, reg_val); + reg_val = hdmi_read32(IPS_HDMI_VID_DIP_CTL_ADDR); + /* copy transmission frequency */ + dev->avi.freq = + ((reg_val & IPS_HDMI_DIP_TRANSMISSION_FREQ_MASK) >> + IPS_HDMI_DIP_TX_FREQ_SHIFT); + /* copy header */ + reg_val = hdmi_read32(IPS_HDMI_VIDEO_DIP_DATA_ADDR); + dev->avi.pkt.header[0] = reg_val & 0xFF; + dev->avi.pkt.header[1] = (reg_val >> 8) & 0xFF; + dev->avi.pkt.header[2] = (reg_val >> 16) & 0xFF; + /* copy data */ + for (index = 0; index < (HDMI_DIP_PACKET_DATA_LEN/4); index++) { + dev->avi.pkt.data32[index] = + hdmi_read32(IPS_HDMI_VIDEO_DIP_DATA_ADDR); + } + /* set data valid */ + dev->avi.valid = true; + } else + dev->avi.valid = false; +} + +/* + * Description: disable HDMI display + * + * @dev: hdmi_device_t + * + * Returns: none + */ +void ips_disable_hdmi(hdmi_device_t *dev) +{ + int count = 0; + u32 temp; + + if (NULL == dev) { + pr_debug("\n%s invalid argument\n", __func__); + return; + } + + /* Disable display plane */ + temp = hdmi_read32(IPS_DSPBCNTR); + if ((temp & IPIL_DSP_PLANE_ENABLE) != 0) { + hdmi_write32(IPS_DSPBCNTR, temp & ~IPIL_DSP_PLANE_ENABLE); + /* Flush the plane changes */ + hdmi_write32(IPS_DSPBSURF, hdmi_read32(IPS_DSPBSURF)); + hdmi_read32(IPS_DSPBSURF); + } + + /* Next, disable display pipes */ + temp = hdmi_read32(IPS_PIPEBCONF); + if ((temp & IPIL_PIPEACONF_ENABLE) != 0) { + temp &= ~IPIL_PIPEACONF_ENABLE; + temp |= IPIL_PIPECONF_PLANE_OFF | IPIL_PIPECONF_CURSOR_OFF; + hdmi_write32(IPS_PIPEBCONF, temp); + hdmi_read32(IPS_PIPEBCONF); + + /* Wait for for the pipe disable to take effect. */ + for (count = 0; count < 1000; count++) { + temp = hdmi_read32(IPS_PIPEBCONF); + if (!(temp & IPIL_PIPEACONF_PIPE_STATE)) + break; + + udelay(20); + } + } + +} + +/* + * Description: restore HDMI display registers and enable display + * + * @dev: hdmi_device_t + * + * Returns: none + */ +void ips_hdmi_restore_and_enable_display(hdmi_device_t *dev) +{ + int i; + u32 dpll = 0; + u32 dpll_val; + if (NULL == dev) { + pr_debug("\n%s invalid argument\n", __func__); + return; + } + if (dev->reg_state.valid == false) { + pr_debug("\nhdmi no data to restore\n"); + return; + } + + /*make sure VGA plane is off. it initializes to on after reset!*/ + hdmi_write32(IPIL_VGACNTRL, IPIL_VGA_DISP_DISABLE); + + dpll = hdmi_read32(IPS_DPLL_B); + if (!(dpll & IPIL_DPLL_VCO_ENABLE)) { + /** + * When ungating power of DPLL, needs to wait 0.5us + * before enable the VCO + */ + if (dpll & IPIL_DPLL_PWR_GATE_EN) { + dpll &= ~IPIL_DPLL_PWR_GATE_EN; + hdmi_write32(IPS_DPLL_B, dpll); + udelay(1); + } + + hdmi_write32(IPS_DPLL_DIV0, dev->reg_state.saveFPA0); + + dpll_val = dev->reg_state.saveDPLL & ~IPIL_DPLL_VCO_ENABLE; + hdmi_write32(IPS_DPLL_B, dpll_val); + udelay(1); + + dpll_val |= IPIL_DPLL_VCO_ENABLE; + hdmi_write32(IPS_DPLL_B, dpll_val); + hdmi_read32(IPS_DPLL_B); + + } + + /* Restore mode */ + hdmi_write32(IPS_HTOTAL_B, dev->reg_state.saveHTOTAL_B); + hdmi_write32(IPS_HBLANK_B, dev->reg_state.saveHBLANK_B); + hdmi_write32(IPS_HSYNC_B, dev->reg_state.saveHSYNC_B); + hdmi_write32(IPS_VTOTAL_B, dev->reg_state.saveVTOTAL_B); + hdmi_write32(IPS_VBLANK_B, dev->reg_state.saveVBLANK_B); + hdmi_write32(IPS_VSYNC_B, dev->reg_state.saveVSYNC_B); + hdmi_write32(IPS_PIPEBSRC, dev->reg_state.savePIPEBSRC); + hdmi_write32(IPS_DSPBSTAT, dev->reg_state.saveDSPBSTATUS); + + /*set up the plane*/ + hdmi_write32(IPS_DSPBSTRIDE, dev->reg_state.saveDSPBSTRIDE); + hdmi_write32(IPS_DSPBLINOFF, dev->reg_state.saveDSPBLINOFF); + hdmi_write32(IPS_DSPBTILEOFF, dev->reg_state.saveDSPBTILEOFF); + hdmi_write32(IPS_DSPBSIZE, dev->reg_state.saveDSPBSIZE); + hdmi_write32(IPS_DSPBPOS, dev->reg_state.saveDSPBPOS); + hdmi_write32(IPS_DSPBSURF, dev->reg_state.saveDSPBSURF); + + hdmi_write32(IPS_PFIT_CONTROL, dev->reg_state.savePFIT_CONTROL); + hdmi_write32(IPS_PFIT_PGM_RATIOS, dev->reg_state.savePFIT_PGM_RATIOS); + hdmi_write32(IPS_HDMIPHYMISCCTL, dev->reg_state.saveHDMIPHYMISCCTL); + hdmi_write32(IPS_HDMIB_CONTROL, dev->reg_state.saveHDMIB_CONTROL); + + /*enable the plane*/ + hdmi_write32(IPS_DSPBCNTR, dev->reg_state.saveDSPBCNTR); + + if (in_atomic() || in_interrupt()) + udelay(20000); + else + msleep_interruptible(20); + + /*enable the pipe */ + hdmi_write32(IPS_PIPEBCONF, dev->reg_state.savePIPEBCONF); + + /* restore palette (gamma) */ + for (i = 0; i < 256; i++) + hdmi_write32(IPS_PALETTE_B + (i<<2), + dev->reg_state.save_palette_b[i]); + + dev->reg_state.valid = false; +} + +/* + * Description: restore HDMI data island packets + * + * @dev: hdmi_device_t + * + * Returns: none + */ +void ips_hdmi_restore_data_island(hdmi_device_t *dev) +{ + if (NULL == dev) { + pr_debug("\n%s invalid argument\n", __func__); + return; + } + + /* restore AVI infoframe */ + if (dev->avi.valid) { + if (ips_hdmi_enable_vid_infoframe(dev, HDMI_PACKET_AVI, + &dev->avi.pkt, dev->avi.freq) != + OTM_HDMI_SUCCESS) + pr_debug("\nfailed to program avi infoframe\n"); + dev->avi.valid = false; + } +} + +/* + * Description: destroys any saved HDMI data + * + * @dev: hdmi_device_t + * + * Returns: none + */ +void ips_hdmi_destroy_saved_data(hdmi_device_t *dev) +{ + if (NULL != dev) { + dev->reg_state.valid = false; + dev->avi.valid = false; + } +} diff --git a/drivers/staging/mrst/drv/otm_hdmi/ipil/specific/mfld/mfld_hdcp_reg.h b/drivers/staging/mrst/drv/otm_hdmi/ipil/specific/mfld/mfld_hdcp_reg.h new file mode 100644 index 0000000..a2bd817 --- /dev/null +++ b/drivers/staging/mrst/drv/otm_hdmi/ipil/specific/mfld/mfld_hdcp_reg.h @@ -0,0 +1,188 @@ +/* + + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2011 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + + Intel Corporation + 2200 Mission College Blvd. + Santa Clara, CA 95054 + + BSD LICENSE + + Copyright(c) 2011 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef MFLD_HDCP_REG_H +#define MFLD_HDCP_REG_H + + +/* Register Definitions */ +#define MDFLD_HDMIB_CNTRL_REG 0x61140 +#define MDFLD_HDMIB_HDCP_PORT_SEL (0x1 << 5) + +/* HDCP Config & Status */ +#define MDFLD_HDCP_CONFIG_REG 0x61400 +#define MDFLD_HDCP_STATUS_REG 0x61448 +/* AN & AKSV */ +#define MDFLD_HDCP_INIT_REG 0x61404 +#define MDFLD_HDCP_AN_LOW_REG 0x61410 +#define MDFLD_HDCP_AN_HI_REG 0x61414 +#define MDFLD_HDCP_AKSV_HI_REG 0x61450 +#define MDFLD_HDCP_AKSV_LOW_REG 0x61454 +/* BKSV */ +#define MDFLD_HDCP_BKSV_LOW_REG 0x61408 +#define MDFLD_HDCP_BKSV_HI_REG 0x6140C +/* Rx-Ri */ +#define MDFLD_HDCP_RECEIVER_RI_REG 0x61418 +/* Repeater Control & Status */ +#define MDFLD_HDCP_REP_REG 0x61444 +/* Repeater SHA */ +#define MDFLD_HDCP_VPRIME_H0 0x6142C +#define MDFLD_HDCP_VPRIME_H1 0x61430 +#define MDFLD_HDCP_VPRIME_H2 0x61434 +#define MDFLD_HDCP_VPRIME_H3 0x61438 +#define MDFLD_HDCP_VPRIME_H4 0x6143C +#define MDFLD_HDCP_SHA1_IN 0x61440 +/* Akey */ +#define MDFLD_HDCP_AKEY_LO_REG 0x6141C +#define MDFLD_HDCP_AKEY_MED_REG 0x61420 +#define MDFLD_HDCP_AKEY_HI_REG 0x61424 + + +struct double_word_t { + union { + uint64_t value; + struct { + uint32_t low; + uint32_t high; + }; + struct { + uint8_t byte[8]; + }; + }; +}; + + +enum ips_hdcp_config_enum { + HDCP_Off = 0, + HDCP_CAPTURE_AN = 1, + HDCP_DECRYPT_KEYS = 2, + HDCP_AUTHENTICATE_AND_ENCRYPT = 3, + HDCP_UNIQUE_MCH_ID = 5, + HDCP_ENCRYPT_KEYS = 6, + HDCP_CYPHER_CHECK_MODE = 7 +}; + +struct ips_hdcp_config_reg_t { + union { + uint32_t value; + struct { + uint32_t hdcp_config:3; + uint32_t reserved:29; + }; + }; +}; + +struct ips_hdcp_status_reg_t { + union { + uint32_t value; + struct { + uint32_t ainfo:8; + uint32_t frame_count:8; + uint32_t hdcp_on:1; + uint32_t an_ready:1; + uint32_t ri_ready:1; + uint32_t ri_match:1; + uint32_t encrypting:1; + uint32_t ready_for_encr:1; + uint32_t umch_id_ready:1; + uint32_t mac_status:1; + uint32_t fus_complete:1; + uint32_t fus_success:1; + uint32_t reserved:6; + }; + }; +}; + +/* Repeater Control register */ +enum ips_hdcp_repeater_status_enum { + HDCP_REPEATER_STATUS_IDLE = 0, + HDCP_REPEATER_STATUS_BUSY = 1, + HDCP_REPEATER_STATUS_RDY_NEXT_DATA = 2, + HDCP_REPEATER_STATUS_COMPLETE_NO_MATCH = 4, + HDCP_REPEATER_STATUS_COMPLETE_MATCH = 12 +}; + +enum ips_hdcp_repeater_ctrl_enum { + HDCP_REPEATER_CTRL_IDLE = 0, + HDCP_REPEATER_32BIT_TEXT_IP = 1, + HDCP_REPEATER_COMPLETE_SHA1 = 2, + HDCP_REPEATER_24BIT_TEXT_8BIT_MO_IP = 4, + HDCP_REPEATER_16BIT_TEXT_16BIT_MO_IP = 5, + HDCP_REPEATER_8BIT_TEXT_24BIT_MO_IP = 6, + HDCP_REPEATER_32BIT_MO_IP = 7 +}; + +struct ips_hdcp_repeater_reg_t { + union { + uint32_t value; + struct { + uint32_t present:1; + uint32_t control:3; + uint32_t reserved1:12; + const uint32_t status:4; + uint32_t reserved2:12; + }; + }; +}; + +#endif /* MFLD_HDCP_REG_H */ diff --git a/drivers/staging/mrst/drv/otm_hdmi/ipil/specific/mfld/mfld_hdmi_reg.h b/drivers/staging/mrst/drv/otm_hdmi/ipil/specific/mfld/mfld_hdmi_reg.h new file mode 100644 index 0000000..ea720d1 --- /dev/null +++ b/drivers/staging/mrst/drv/otm_hdmi/ipil/specific/mfld/mfld_hdmi_reg.h @@ -0,0 +1,110 @@ +/* + + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2011 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + + Intel Corporation + 2200 Mission College Blvd. + Santa Clara, CA 95054 + + BSD LICENSE + + Copyright(c) 2011 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef __MFLD_HDMI_REG_H +#define __MFLD_HDMI_REG_H + +#define IPS_HDMI_OCP_STATUS (1 << 2) +#define IPS_HDMI_HPD_STATUS_BIT (1 << 3) + +#define IPS_MSIC_VCC330CNT 0xd3 +#define IPS_VCC330_OFF 0x24 +#define IPS_VCC330_ON 0x37 +#define IPS_MSIC_VHDMICNT 0xde +#define IPS_VHDMI_OFF 0x24 +#define IPS_VHDMI_ON 0xa4 +#define IPS_VHDMI_DB_30MS 0x60 + +/* Video Data Island Packet Control */ +#define IPS_HDMI_VID_DIP_CTL_ADDR (0x61170) + +#define IPS_HDMI_VID_EN_DIP ((1) << 31) +#define IPS_HDMI_VID_PORT_SELECT_MASK ((0x3) << 29) +#define IPS_HDMI_VID_PORT_B_SELECT ((1) << 29) + +/* Video DIP Type Values Bits 24:21 */ +#define IPS_HDMI_EN_DIP_TYPE_MASK ((0xF) << 21) +#define IPS_HDMI_EN_DIP_TYPE_AVI ((1) << 21) +#define IPS_HDMI_EN_DIP_TYPE_VS ((1) << 22) +#define IPS_HDMI_EN_DIP_TYPE_SPD ((1) << 24) + +/* Video DIP Type Buffer Index Bits 20:19 */ +#define IPS_HDMI_DIP_BUFF_INDX_MASK ((0x3) << 19) +#define IPS_HDMI_DIP_BUFF_INDX_AVI ((0x0) << 19) +#define IPS_HDMI_DIP_BUFF_INDX_VS ((0x1) << 19) +#define IPS_HDMI_DIP_BUFF_INDX_SPD ((0x3) << 19) + +/* Video Dip Transmission Frequency 17:16 */ +#define IPS_HDMI_DIP_TX_FREQ_SHIFT (16) +#define IPS_HDMI_DIP_TRANSMISSION_FREQ_MASK ((0x3) << 16) + +/* Video Dip Access Address 3:0 */ +#define IPS_HDMI_DIP_ACCESS_ADDR_MASK (0xF) + +/* Video Dip Data Register */ +#define IPS_HDMI_VIDEO_DIP_DATA_ADDR (0x61178) + +/* Audio Data Island Packet Control */ +#define IPS_HDMI_AUD_DIP_CTL_ADDR (0x69060) + +#endif /* MFLD_HDMI_REG_H */ diff --git a/drivers/staging/mrst/drv/otm_hdmi/ipil/specific/mfld/mfld_utils.h b/drivers/staging/mrst/drv/otm_hdmi/ipil/specific/mfld/mfld_utils.h new file mode 100644 index 0000000..0ca05d7 --- /dev/null +++ b/drivers/staging/mrst/drv/otm_hdmi/ipil/specific/mfld/mfld_utils.h @@ -0,0 +1,71 @@ +/* + + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2011 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + + Intel Corporation + 2200 Mission College Blvd. + Santa Clara, CA 95054 + + BSD LICENSE + + Copyright(c) 2011 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef IPS_API_H +#define IPS_API_H + +extern uint32_t hdmi_read32(uint32_t reg); +extern void hdmi_write32(uint32_t reg, uint32_t val); +extern int intel_scu_ipc_iowrite8(u16 addr, u8 data); + +#endif /* IPS_API_H */ diff --git a/drivers/staging/mrst/drv/otm_hdmi/os/android/android_hdmi.c b/drivers/staging/mrst/drv/otm_hdmi/os/android/android_hdmi.c new file mode 100644 index 0000000..60e3acd --- /dev/null +++ b/drivers/staging/mrst/drv/otm_hdmi/os/android/android_hdmi.c @@ -0,0 +1,1538 @@ +/* + + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2011 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + + Intel Corporation + 2200 Mission College Blvd. + Santa Clara, CA 95054 + + BSD LICENSE + + Copyright(c) 2011 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +/* Definition for debug print format */ +#define pr_fmt(fmt) "[otm_hdmi]: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "psb_intel_drv.h" +#include "psb_intel_reg.h" +#include "psb_drv.h" + +#include "otm_hdmi_types.h" +#include "otm_hdmi.h" +#include "android_hdmi.h" +#ifdef OTM_HDMI_HDCP_ENABLE +#include "hdcp_api.h" +#endif + +/* TODO: need to remove this, once I2C issue is worked out. */ +#include +#include "psb_intel_hdmi.h" +#include "psb_powermgmt.h" + +/* TODO: metadata should be populated using table from mode_info.c */ +static const struct { + int width, height, htotal, vtotal, dclk, vrefr, vic; +} vic_formats[11] = { + { 640, 480, 800, 525, 25200, 60, 1 }, /* 640x480p60 4:3 */ + { 720, 480, 858, 525, 27027, 60, 2 }, /* 720x480p60 4:3 */ + { 720, 480, 858, 525, 27027, 60, 3 }, /* 720x480p60 16:9 */ + { 1280, 720, 1650, 750, 74250, 60, 4 }, /* 1280x720p60 16:9 */ + { 1920, 1080, 2200, 1125, 148500, 60, 16 }, /* 1920x1080p60 16:9 */ + { 720, 576, 864, 625, 27000, 50, 17 }, /* 720x576p50 4:3 */ + { 720, 576, 864, 625, 27000, 50, 18 }, /* 720x576p50 16:9 */ + { 1280, 720, 1980, 750, 74250, 50, 19 }, /* 1280x720p50 16:9 */ + { 1920, 1080, 2750, 1125, 74250, 24, 32 }, /* 1920x1080p24 16:9 */ + { 1920, 1080, 2640, 1125, 74250, 25, 33 }, /* 1920x1080p25 16:9 */ + { 1920, 1080, 2200, 1125, 74250, 30, 34 }, /* 1920x1080p30 16:9 */ +}; + +/* Function declarations for interrupt routines */ +/* + * android_hdmi_irq_callback: + * Description:IRQ interrupt bottomhalf handler callback. This callback + * will be called for hdmi plug/unplug interrupts. + * Parameters : irq: IRQ number + * data: hdmi_priv data + * Return : IRQ_HANDLED + */ +static irqreturn_t android_hdmi_irq_callback(int irq, void *data); +static irqreturn_t __hdmi_irq_handler_bottomhalf(void *data); + +static int calculate_refresh_rate(struct drm_display_mode *mode); + +/* + * TODO: Remove this structure and counter afer EDID Parse + * for established modes is implemented + */ +#define DEBUG_MODES 100 +struct debug_modes__t { + int clk; + int frq; + char name[DRM_DISPLAY_MODE_LEN + 1]; +} arr_modes[DEBUG_MODES]; + +u32 debug_modes_count; + +#define SWITCH_DEV_HDMI_NAME "hdmi" +#define SWITCH_DEV_DVI_NAME "dvi" + +#define WPT_IOBAR_OFFSET_BASE 0x1F0000 +#define WPT_IOBAR_INDEX_REGISTER 0x2110 +#define WPT_IOBAR_DATA_REGISTER 0x2114 + +/* Default HDMI Edid - 640x480p 720x480p 1280x720p */ +static unsigned char default_edid[] = { + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, + 0x25, 0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x14, 0x01, 0x03, 0x80, 0x00, 0x00, 0xFF, + 0x2A, 0xBA, 0x45, 0xA1, 0x59, 0x55, 0x9D, 0x28, + 0x0D, 0x50, 0x54, 0x20, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1D, + 0x00, 0x72, 0x51, 0xD0, 0x1E, 0x20, 0x6E, 0x28, + 0x55, 0x00, 0xC4, 0x8E, 0x21, 0x00, 0x00, 0x1E, + 0x8F, 0x0A, 0xD0, 0x8A, 0x20, 0xE0, 0x2D, 0x10, + 0x10, 0x3E, 0x96, 0x00, 0xC4, 0x8E, 0x21, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x49, + 0x4E, 0x54, 0x45, 0x4C, 0x2D, 0x54, 0x56, 0x0A, + 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xFD, + 0x0C, 0x37, 0x3D, 0x1F, 0x31, 0x0F, 0x00, 0x0A, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0xCE, + 0x02, 0x03, 0x13, 0x41, 0x42, 0x04, 0x02, 0x23, + 0x09, 0x07, 0x07, 0x67, 0x03, 0x0C, 0x00, 0x10, + 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B +}; + +/*store the state whether the edid is ready + *in HPD (1) or not (0)*/ +static int edid_ready_in_hpd = 0; + +static irqreturn_t __hdmi_irq_handler_bottomhalf(void *data) +{ + struct android_hdmi_priv *hdmi_priv = data; + bool hpd = otm_hdmi_power_rails_on(); + + if ((true == hpd) && (hdmi_priv != NULL)) { + /* Get monitor type. This is required to appropriately + * issue switch class event to the user space depending + * on the monitor type - HDMI or DVI. + */ + struct drm_mode_config *mode_config = NULL; + struct edid *edid = NULL; + struct drm_connector *connector = NULL; + struct i2c_adapter *adapter = NULL; + u8 hdmi_status = 0; +#ifndef OTM_HDMI_FIXME + /*OTM_HDMI_FIXME: this should be from get attribute interface*/ + int adapter_num = 3; +#endif + + if (!hdmi_priv->dev) + return IRQ_HANDLED; + + /* Check HDMI status, read EDID only if connected */ + intel_scu_ipc_ioread8(MSIC_HDMI_STATUS, &hdmi_status); +#ifdef OTM_HDMI_HDCP_ENABLE + otm_hdmi_hdcp_set_hpd_state(hdmi_priv->context, + (hdmi_status & HPD_SIGNAL_STATUS)); +#endif + if (!(hdmi_status & HPD_SIGNAL_STATUS)) + goto exit; + + adapter = i2c_get_adapter(adapter_num); + if (!adapter) { + pr_err("Unable to get i2c adapter for HDMI"); + goto exit; + } + + mode_config = &hdmi_priv->dev->mode_config; + list_for_each_entry(connector, + &mode_config->connector_list, + head) { + if (!connector) + continue; + if (DRM_MODE_CONNECTOR_DVID == + connector->connector_type) { + edid = (struct edid *) + drm_get_edid(connector, adapter); + if (edid) { + if (drm_detect_hdmi_monitor(edid)) + /* MONITOR_TYPE_HDMI */ + hdmi_priv->monitor_type = 1; + else + /* MONITOR_TYPE_DVI */ + hdmi_priv->monitor_type = 2; + /* Store raw edid in HDMI context */ + otm_hdmi_set_raw_edid( + hdmi_priv->context, + (char *)edid); + /* Raw edid is ready in HDMI context */ + edid_ready_in_hpd = 1; + kfree(edid); + } else { + pr_err("Edid Read failed"); + /* Retry in next get modes */ + edid_ready_in_hpd = 0; + } + break; + } + } +exit: + /* Notify user space */ + drm_helper_hpd_irq_event(hdmi_priv->dev); + } + + return IRQ_HANDLED; +} + +#ifdef OTM_HDMI_FIXME +gdl_ret_t android_hdmi_audio_control(void *context, bool flag) +{ + hdmi_context_t *ctx = (hdmi_context_t *)context; + hdmi_device_t *dev = &ctx->dev; + gdl_ret_t rc = GDL_SUCCESS; + + if (flag) { + /* Enable audio */ + IOW(HDMI_UNIT_CONTROL, 0x67); + IOR(HDMI_UNIT_CONTROL); + + IOW(0x51a8, 0x10); + IOR(0x51a8); + + IOW(HDMI_AUDIO_CONTROL, 0x1); + IOR(HDMI_AUDIO_CONTROL); + } else { + /* Disable audio */ + IOW(0x51a8, 0x0); + IOR(0x51a8); + + IOW(HDMI_AUDIO_CONTROL, 0x0); + IOR(HDMI_AUDIO_CONTROL); + + IOW(HDMI_UNIT_CONTROL, 0x47); + IOR(HDMI_UNIT_CONTROL); + } + + return rc; +} +#endif + +static int hdmi_ddc_read_write(bool read, + uint8_t i2c_addr, + uint8_t offset, + uint8_t *buffer, + int size) +{ +#ifndef OTM_HDMI_FIXME + /* OTM_HDMI_FIXME: this should be from get attribute interface */ + int adapter_num = 3; +#endif + struct i2c_adapter *adapter = i2c_get_adapter(adapter_num); + struct i2c_msg msgs[] = { + { + .addr = i2c_addr, + .flags = 0, + .len = 1, + .buf = &offset, + }, { + .addr = i2c_addr, + .flags = ((read) ? I2C_M_RD : 0), + .len = size, + .buf = buffer, + } + }; + + if (adapter != NULL && i2c_transfer(adapter, msgs, 2) == 2) + return 1; + + return 0; +} + +#define android_hdmi_connector_funcs mdfld_hdmi_connector_funcs +#define android_hdmi_connector_helper_funcs mdfld_hdmi_connector_helper_funcs +#define android_hdmi_enc_helper_funcs mdfld_hdmi_helper_funcs +#define android_hdmi_enc_funcs psb_intel_lvds_enc_funcs + +void android_hdmi_driver_init(struct drm_device *dev, + void *mode_dev) +{ + struct drm_psb_private *dev_priv = dev->dev_private; + struct android_hdmi_priv *hdmi_priv = dev_priv->hdmi_priv; + struct psb_intel_output *psb_intel_output; + struct drm_connector *connector; + struct drm_encoder *encoder; + + pr_debug("%s E", __func__); + + psb_intel_output = kzalloc(sizeof(struct psb_intel_output), GFP_KERNEL); + if (!psb_intel_output) + return; + + psb_intel_output->mode_dev = mode_dev; + connector = &psb_intel_output->base; + encoder = &psb_intel_output->enc; + drm_connector_init(dev, &psb_intel_output->base, + &android_hdmi_connector_funcs, + DRM_MODE_CONNECTOR_DVID); + + drm_encoder_init(dev, &psb_intel_output->enc, &android_hdmi_enc_funcs, + DRM_MODE_ENCODER_TMDS); + + drm_mode_connector_attach_encoder(&psb_intel_output->base, + &psb_intel_output->enc); + psb_intel_output->type = INTEL_OUTPUT_HDMI; + + psb_intel_output->dev_priv = hdmi_priv; + + drm_encoder_helper_add(encoder, &android_hdmi_enc_helper_funcs); + drm_connector_helper_add(connector, + &android_hdmi_connector_helper_funcs); + + drm_connector_attach_property(connector, + dev->mode_config.scaling_mode_property, + DRM_MODE_SCALE_ASPECT); + + connector->display_info.subpixel_order = SubPixelHorizontalRGB; + connector->interlace_allowed = false; + connector->doublescan_allowed = false; + + /* Enable polling */ + connector->polled = DRM_CONNECTOR_POLL_HPD; + + /* hard-coded the HDMI_I2C_ADAPTER_ID to be 3, Should get from GCT*/ + /* TODO: remove this once all code moved into OTM */ + psb_intel_output->hdmi_i2c_adapter = i2c_get_adapter(3); + + if (psb_intel_output->hdmi_i2c_adapter) + /* HACKS_JLIU7 */ + pr_debug("Enter mdfld_hdmi_init, i2c_adapter is availabe.\n"); + else + printk(KERN_ALERT "No ddc adapter available!\n"); + hdmi_priv->hdmi_i2c_adapter = psb_intel_output->hdmi_i2c_adapter; +#ifdef OTM_HDMI_HDCP_ENABLE + otm_hdmi_hdcp_init(hdmi_priv->context, &hdmi_ddc_read_write); +#endif + mdfld_hdmi_audio_init(hdmi_priv); + mdfld_msic_init(hdmi_priv); + + pr_debug("%s X", __func__); +} + +void android_hdmi_enable_hotplug(struct drm_device *dev) +{ + struct drm_psb_private *dev_priv = dev->dev_private; + struct android_hdmi_priv *hdmi_priv = dev_priv->hdmi_priv; + + /* Drm is ready for incoming HPD now */ + if (otm_hdmi_setup_irq(hdmi_priv->context, dev->pdev, + &android_hdmi_irq_callback, + (void *)hdmi_priv)) { + pr_err("failed to initialize hdmi HPD IRQ\n"); + return; + } +} + +/* + * android_hdmi_irq_callback: + * Description: IRQ interrupt bottomhalf handler callback. This callback + * will be called for hdmi plug/unplug interrupts. + * Parameters : irq: IRQ number + * data: hdmi_priv data + * Return : IRQ_HANDLED + */ +static irqreturn_t android_hdmi_irq_callback(int irq, void *data) +{ + pr_debug("%s: IRQ Interrupt callback", __func__); + + return __hdmi_irq_handler_bottomhalf(data); +} + +void android_hdmi_driver_setup(struct drm_device *dev) +{ + struct drm_psb_private *dev_priv = dev->dev_private; + struct android_hdmi_priv *hdmi_priv; + int ret; + + pr_debug("%s E", __func__); + + /* HDMI private data */ + hdmi_priv = kzalloc(sizeof(struct android_hdmi_priv), GFP_KERNEL); + if (!hdmi_priv) { + pr_err("failed to allocate memory"); + goto out; + } + + pr_debug("%s: Initialize the HDMI device", __func__); + /* Initialize the HDMI context */ + if (otm_hdmi_device_init(&(hdmi_priv->context), dev->pdev)) { + pr_err("failed to initialize hdmi device\n"); + goto free; + } + + hdmi_priv->dev = dev; + + /* TODO: No need to expose these values to outside. + * keeping for now as oktl psb files are referring these. + * has to be removed when cleaning up the oktl psb files. + * medfield psb files don't need this, hence disabling + */ + /* hdmi_priv->regs = ctx->io_address; */ + + /*FIXME: May need to get this somewhere, + * but CG code seems hard coded it + */ + hdmi_priv->hdmib_reg = HDMIB_CONTROL; + hdmi_priv->has_hdmi_sink = false; + /* TODO: get this from get/set attribute table. + */ + hdmi_priv->monitor_type = 1;/* MONITOR_TYPE_HDMI */ + /* TODO: set this to false for oaktrail */ + /* TODO: get this from get/set attribute table. + */ + hdmi_priv->is_hdcp_supported = true; + + dev_priv->hdmi_priv = (void *)hdmi_priv; + dev_priv->hdmi_present = 1; + + pr_debug("%s: Register switch class devices", __func__); + /* Register as a switch class device */ + g_switch_hdmi_dev.name = SWITCH_DEV_HDMI_NAME; + ret = switch_dev_register(&g_switch_hdmi_dev); + if (ret) { + pr_debug("Failed to register switch class device %s (%d)", + SWITCH_DEV_HDMI_NAME, ret); + goto free; + } + + g_switch_dvi_dev.name = SWITCH_DEV_DVI_NAME; + ret = switch_dev_register(&g_switch_dvi_dev); + if (ret) { + pr_debug("Failed to register switch class device %s (%d)", + SWITCH_DEV_DVI_NAME, ret); + goto free; + } + +#ifdef OTM_HDMI_FIXME + android_hdmi_audio_control(hdmi_priv->context, false); + /* request io port region for audio configuration */ + res = request_region(WPT_IOBAR_INDEX_REGISTER, + WPT_IOBAR_DATA_REGISTER - WPT_IOBAR_INDEX_REGISTER + 1, + "OKTLHDMI"); + if (res == NULL) { + pr_err("Failed to allocate io port region\n"); + goto free; + } +#endif + pr_debug("%s X", __func__); + return; +free: + kfree(hdmi_priv); +out: + dev_priv->hdmi_present = 0; + return; +} + +/* structure for hdmi cmdline module + * don't upstream the code + */ +typedef struct { + int hdisplay, vdisplay; + int refresh; + int refresh_specified; + int vic; + int vic_specified; + int specified; /* 1: cmdline_mode is set */ +} otm_cmdline_mode; + +static otm_cmdline_mode cmdline_mode = { 0, 0, 0, 0, 0, 0, 0 }; + +int otm_cmdline_parse_option(char *cmdoption) +{ + int ret = 0; + int namelen = 0; + int i; + int v_spec = 0; + char *name; + if (NULL == cmdoption) + return -1; + + cmdline_mode.specified = 0; + cmdline_mode.refresh_specified = 0; + cmdline_mode.vic_specified = 0; + + name = cmdoption; + namelen = strlen(name); + for (i = namelen-1; i >= 0; i--) { + switch (name[i]) { + case '@': + namelen = i; + cmdline_mode.refresh = + simple_strtol(&name[i+1], NULL, 10); + cmdline_mode.refresh_specified = 1; + break; + case 'x': + case 'X': + cmdline_mode.vdisplay = + simple_strtol(&name[i+1], NULL, 10); + v_spec = 1; + break; + case '0' ... '9': + break; + default: + /* invalid input */ + return -2; + } + } + + if ((i < 0) && (1 == v_spec)) + cmdline_mode.hdisplay = simple_strtol(name, NULL, 10); + + cmdline_mode.specified = 1; + return ret; +} +EXPORT_SYMBOL_GPL(otm_cmdline_parse_option); + +int otm_cmdline_set_vic_option(int vic) +{ + int i = 0; + + cmdline_mode.specified = 0; + cmdline_mode.refresh_specified = 0; + cmdline_mode.vic_specified = 0; + + for (i = 0; i < ARRAY_SIZE(vic_formats); i++) { + if (vic == vic_formats[i].vic) { + cmdline_mode.refresh = vic_formats[i].vrefr; + cmdline_mode.hdisplay = vic_formats[i].width; + cmdline_mode.vdisplay = vic_formats[i].height; + cmdline_mode.vic = vic; + cmdline_mode.specified = 1; + cmdline_mode.refresh_specified = 1; + cmdline_mode.vic_specified = 1; + return 0; + } + } + + printk(KERN_INFO "HDMI cmdline: Unsupported VIC(%d) specified\n", vic); + return -1; +} +EXPORT_SYMBOL_GPL(otm_cmdline_set_vic_option); + +void otm_print_cmdline_option() +{ + if (1 == cmdline_mode.specified) { + if (1 == cmdline_mode.vic_specified) + printk(KERN_INFO "HDMI cmdline option: %dx%d@%d (%d)\n", + cmdline_mode.hdisplay, + cmdline_mode.vdisplay, + cmdline_mode.refresh, + cmdline_mode.vic); + else if (1 == cmdline_mode.refresh_specified) + printk(KERN_INFO "HDMI cmdline option: %dx%d@%d\n", + cmdline_mode.hdisplay, + cmdline_mode.vdisplay, + cmdline_mode.refresh); + else + printk(KERN_INFO "HDMI cmdline option: %dx%d\n", + cmdline_mode.hdisplay, cmdline_mode.vdisplay); + } else + printk(KERN_INFO "HDMI cmdline option is not set\n"); +} +EXPORT_SYMBOL_GPL(otm_print_cmdline_option); + +/* + * DRM connector helper routine. + */ +int android_hdmi_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + unsigned int pc_min, pc_max; + + pr_debug("display info. hdisplay = %d, vdisplay = %d, clock = %d.\n", + mode->hdisplay, mode->vdisplay, mode->clock); + + /* Restricting modes within the supported pixel clock */ + if (OTM_HDMI_SUCCESS == otm_hdmi_get_pixel_clock_range( + &pc_min, &pc_max)) { + if (mode->clock < pc_min) { + pr_debug("pruned mode %dx%d@%d.\n", + mode->hdisplay, + mode->vdisplay, + mode->clock); + return MODE_CLOCK_LOW; + } + if (mode->clock > pc_max) { + pr_debug("pruned mode %dx%d@%d.\n", + mode->hdisplay, + mode->vdisplay, + mode->clock); + return MODE_CLOCK_HIGH; + } + } + +#ifdef MFLD_HDMI_PR3 + /* if cmdline_mode is set, prune all other modes.*/ + if (1 == cmdline_mode.specified) { + if ((cmdline_mode.hdisplay != mode->hdisplay) || + (cmdline_mode.vdisplay != mode->vdisplay) || + ((1 == cmdline_mode.refresh_specified) && + (cmdline_mode.refresh != + calculate_refresh_rate(mode)))) { + return MODE_BAD; + } + } +#endif + + if (mode->type == DRM_MODE_TYPE_USERDEF) + return MODE_OK; + + if (mode->flags & DRM_MODE_FLAG_DBLSCAN) + return MODE_NO_DBLESCAN; + + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + return MODE_NO_INTERLACE; + + return MODE_OK; +} + +static struct drm_display_mode +*android_hdmi_get_drm_mode_from_pdt(otm_hdmi_timing_t *timings, + struct drm_device *dev) +{ + struct drm_display_mode *mode; + int i; + static const struct { + int w, h; + } cea_interlaced[7] = { + { 1920, 1080 }, + { 720, 480 }, + { 1440, 480 }, + { 2880, 480 }, + { 720, 576 }, + { 1440, 576 }, + { 2880, 576 }, + }; + + if (timings == NULL || dev == NULL) + return NULL; + + mode = drm_mode_create(dev); + if (mode == NULL) + return NULL; + + mode->type = DRM_MODE_TYPE_DRIVER; + mode->clock = timings->dclk; + + mode->hdisplay = timings->width; + mode->hsync_start = timings->hsync_start; + mode->hsync_end = timings->hsync_end; + mode->htotal = timings->htotal; + + mode->vdisplay = timings->height; + mode->vsync_start = timings->vsync_start; + mode->vsync_end = timings->vsync_end; + mode->vtotal = timings->vtotal; + + if (timings->mode_info_flags & PD_SCAN_INTERLACE) { + + mode->flags |= DRM_MODE_FLAG_INTERLACE; + + for (i = 0; i < ARRAY_SIZE(cea_interlaced); i++) { + if ((mode->hdisplay == cea_interlaced[i].w) && + (mode->vdisplay == cea_interlaced[i].h / 2)) { + mode->vdisplay *= 2; + mode->vsync_start *= 2; + mode->vsync_end *= 2; + mode->vtotal *= 2; + mode->vtotal |= 1; + } + } + } + + drm_mode_set_name(mode); + + mode->flags |= (timings->mode_info_flags & PD_HSYNC_HIGH) ? + DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC; + mode->flags |= (timings->mode_info_flags & PD_VSYNC_HIGH) ? + DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC; + + return mode; +} + +static int android_hdmi_add_cea_edid_modes(struct drm_connector *connector, + struct edid *edid) +{ + struct drm_display_mode *newmode = NULL; + int count = 0, i = 0, ret_count = 0; + u8 *default_edid = (u8 *)edid; + static otm_hdmi_timing_t pdt[30]; + + if (connector == NULL || edid == NULL) + return 0; + + for (i = 1; i <= default_edid[0x7e]; i++) { + u8 *ext = default_edid + (i * EDID_LENGTH); + switch (*ext) { + case CEA_EXT: + count += otm_hdmi_timing_from_cea_modes(ext, + &pdt[count]); + break; + default: + break; + } + } + + /* Do Mapping from PDT to drm_display_mode */ + for (i = 0; i < count; i++) { + newmode = android_hdmi_get_drm_mode_from_pdt(&pdt[i], + connector->dev); + if (!newmode) + continue; + drm_mode_probed_add(connector, newmode); + ret_count++; + } + + return ret_count; +} + +#ifdef OTM_HDMI_UNIT_TEST +static bool android_hdmi_probed_mode_exists( + struct drm_connector *connector, + int hdisplay, int vdisplay, int vrefresh) +{ + struct drm_display_mode *mode, *t; + if (!connector || hdisplay < 0 || vdisplay < 0 || vrefresh < 0) + goto exit; + + /* loop through all probed modes to match */ + list_for_each_entry_safe(mode, t, &connector->probed_modes, head) { + if (mode->hdisplay == hdisplay && + mode->vdisplay == vdisplay && + vrefresh == drm_mode_vrefresh(mode)) { + return true; + } + } +exit: + return false; +} + +static bool android_hdmi_add_noedid_mode( + void *context, + struct drm_connector *connector, + int hdisplay, int vdisplay, int vrefresh) +{ + struct drm_display_mode *newmode = NULL; + otm_hdmi_timing_t *pdt = NULL; + + if (!context || !connector || hdisplay < 0 || + vdisplay < 0 || vrefresh < 0) + goto exit; + + /* get mode timings */ + pdt = otm_hdmi_get_mode_timings(context, hdisplay, vdisplay, vrefresh); + if (!pdt) + goto exit; + + /* add mode */ + newmode = android_hdmi_get_drm_mode_from_pdt(pdt, connector->dev); + if (newmode) { + drm_mode_probed_add(connector, newmode); + return true; + } +exit: + return false; +} +#endif + +/* Calculate refresh rate from mode */ +static int calculate_refresh_rate(struct drm_display_mode *mode) +{ + int refresh_rate = 0; + + if (!mode) + return refresh_rate; + + refresh_rate = (((mode->flags & DRM_MODE_FLAG_INTERLACE) ? 2 : 1) * + mode->clock * 1000) / + (mode->htotal * mode->vtotal); + + return refresh_rate; +} + +int android_hdmi_get_modes(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct drm_psb_private *dev_priv = dev->dev_private; + struct android_hdmi_priv *hdmi_priv = dev_priv->hdmi_priv; + struct edid *edid = NULL; + /* Edid address in HDMI context */ + struct edid *ctx_edid = NULL; + struct drm_display_mode *mode, *t; + int i = 0, j = 0, ret = 0; + int refresh_rate = 0; + int pref_mode_found = -1; + debug_modes_count = 0; + struct i2c_adapter *adapter = NULL; +#ifndef OTM_HDMI_FIXME + /* OTM_HDMI_FIXME: this should be from get attribute interface */ + int adapter_num = 3; +#endif + pr_debug("%s E\n", __func__); + + /* Lazy edid read feature, which can save I2C transactions largely. + * Basically, HPD will do edid read and store to HDMI context. + * Therefore, get modes should read edid with the condition + * whether the edid is ready in HDP or not in a lazy way. */ + if (edid_ready_in_hpd) + goto edid_is_ready; + + adapter = i2c_get_adapter(adapter_num); + + /* FIXME: drm_get_edid cause the system hung at DV1 boot up */ + /* Read edid blocks from i2c device */ + if (NULL != adapter) + edid = (struct edid *)drm_get_edid(connector, adapter); + + if (edid == NULL) { + pr_err("%s Edid Read failed -use default edid", __func__); + /* OTM_HDMI_FIXME: this should provide by OTM */ + edid = (struct edid *)default_edid; + } else + pr_debug("Edid Read Done in get modes\n"); + + /* Store raw edid into HDMI context */ + otm_hdmi_set_raw_edid(hdmi_priv->context, (char *)edid); + + /* Release edid */ + if (edid && ((unsigned char *)edid != (unsigned char *)default_edid)) + kfree(edid); + +edid_is_ready: + /* Get the edid stored in HDMI context */ + otm_hdmi_get_raw_edid(hdmi_priv->context, (char **)&ctx_edid); + + /* Parse the edid */ + otm_hdmi_edid_parse(hdmi_priv->context, OTM_HDMI_USE_EDID_REAL); + + /* Add modes into DRM mode list */ + drm_mode_connector_update_edid_property(connector, ctx_edid); + ret = drm_add_edid_modes(connector, ctx_edid); + ret += android_hdmi_add_cea_edid_modes(connector, ctx_edid); + +#ifdef OTM_HDMI_UNIT_TEST + if (1 == cmdline_mode.specified) { + /* Add cmdline mode if it does not exist in EDID */ + if (!android_hdmi_probed_mode_exists(connector, + cmdline_mode.hdisplay, + cmdline_mode.vdisplay, + cmdline_mode.refresh)) + if (android_hdmi_add_noedid_mode( + hdmi_priv->context, + connector, + cmdline_mode.hdisplay, + cmdline_mode.vdisplay, + cmdline_mode.refresh)) + ret++; + } +#endif + connector->display_info.raw_edid = NULL; + /* TODO: MUST REVERT + * monitor_type is being used by mdfld_hdmi_set_property + * to switch state between HDMI & DVI + * That mechnism will be changed to use get attribute + * and at that time this code must be removed */ + if (otm_hdmi_is_monitor_hdmi(hdmi_priv->context)) + hdmi_priv->monitor_type = 1;/* MONITOR_TYPE_HDMI */ + else + hdmi_priv->monitor_type = 2;/* MONITOR_TYPE_DVI */ + + j = 0; + list_for_each_entry_safe(mode, t, &connector->probed_modes, head) { + refresh_rate = calculate_refresh_rate(mode); + pr_debug("Mode %02d: %s %dHz\t Clk: %dKHz H/V: %c,%c" + "flags: 0x%08x", + j, mode->name, refresh_rate, mode->clock, + (mode->flags & DRM_MODE_FLAG_PHSYNC) ? '+' : '-', + (mode->flags & DRM_MODE_FLAG_PVSYNC) ? '+' : '-', + mode->flags); + + if (debug_modes_count < DEBUG_MODES) { + strncpy(arr_modes[debug_modes_count].name, mode->name, + strlen(mode->name)); + arr_modes[debug_modes_count].name[strlen(mode->name)] = '\0'; + arr_modes[debug_modes_count].frq = refresh_rate; + arr_modes[debug_modes_count].clk = mode->clock; + debug_modes_count++; + } else { + pr_err("Increase size of DEBUG_MODES, some modes not" + " listed in report_edid.sh\n"); + } + +#ifdef OTM_HDMI_FIXME + /* + * prune modes that don't have proper stall values + */ + if (otm_hdmi_is_monitor_hdmi(hdmi_priv->context) && + (get_stall_value(mode) == -1)) { + pr_debug("%s: mode %dx%d@%dHz don't have stall" + " value configured\n", __func__, + mode->hdisplay, mode->vdisplay, + refresh_rate); + i++; + drm_mode_remove(connector, mode); + } +#endif + j++; + } + + /* choose a preferred mode and set the mode type accordingly */ + list_for_each_entry_safe(mode, t, &connector->probed_modes, head) { + /* check whether the display has support for 720P. + * 720P is the minimum requirement expected from + * external display. + * (extend this if condition to set other modes as preferred). + */ + refresh_rate = calculate_refresh_rate(mode); + if (otm_hdmi_is_preferred_mode(mode->hdisplay, mode->vdisplay, + refresh_rate)) { + pr_debug("External display has %dx%d support\n", + mode->hdisplay, mode->vdisplay); + mode->type |= DRM_MODE_TYPE_PREFERRED; + pref_mode_found = 1; + break; + } + } + + /* clear any other preferred modes*/ + if (pref_mode_found == 1) { + list_for_each_entry_safe(mode, t, &connector->probed_modes, + head) { + refresh_rate = calculate_refresh_rate(mode); + if (otm_hdmi_is_preferred_mode(mode->hdisplay, + mode->vdisplay, + refresh_rate)) + continue; + mode->type &= ~DRM_MODE_TYPE_PREFERRED; + } + } + + pr_debug("%s X (%d)", __func__, (ret - i)); + + return ret - i; +} + +/* + * Description: helper function to print the display mode details. + * + * @mode: drm display mode to print + * + * Returns: none. + */ +static void __android_hdmi_dump_crtc_mode(struct drm_display_mode *mode) +{ + if (mode == NULL) + return; + + pr_debug("hdisplay = %d\n", mode->hdisplay); + pr_debug("vdisplay = %d\n", mode->vdisplay); + pr_debug("hsync_start = %d\n", mode->hsync_start); + pr_debug("hsync_end = %d\n", mode->hsync_end); + pr_debug("htotal = %d\n", mode->htotal); + pr_debug("vsync_start = %d\n", mode->vsync_start); + pr_debug("vsync_end = %d\n", mode->vsync_end); + pr_debug("vtotal = %d\n", mode->vtotal); + pr_debug("clock = %d\n", mode->clock); + pr_debug("flags = 0x%x\n", mode->flags); +} + +/* Derive 59.94Hz dot clock from 60Hz dot clock + */ +static int __f5994(int dotclock) +{ + return DIV_ROUND_UP(dotclock*1000, 1001); +} + +/* + * Description: helper function to convert drm_display_mode to + * otm_hdmi_timing. + * + * @otm_mode: otm hdmi mode to be populated + * @drm_mode: drm_display_mode + * + * Returns: none. + */ +static void __android_hdmi_drm_mode_to_otm_timing(otm_hdmi_timing_t *otm_mode, + struct drm_display_mode *drm_mode) +{ + uint8_t i = 0; + + if (otm_mode == NULL || drm_mode == NULL) + return; + + otm_mode->width = (unsigned short) + drm_mode->crtc_hdisplay; + otm_mode->height = (unsigned short) + drm_mode->crtc_vdisplay; + otm_mode->dclk = (unsigned long) + drm_mode->clock; + otm_mode->htotal = (unsigned short) + drm_mode->crtc_htotal; + otm_mode->hblank_start = (unsigned short) + drm_mode->crtc_hblank_start; + otm_mode->hblank_end = (unsigned short) + drm_mode->crtc_hblank_end; + otm_mode->hsync_start = (unsigned short) + drm_mode->crtc_hsync_start; + otm_mode->hsync_end = (unsigned short) + drm_mode->crtc_hsync_end; + otm_mode->vtotal = (unsigned short) + drm_mode->crtc_vtotal; + otm_mode->vblank_start = (unsigned short) + drm_mode->crtc_vblank_start; + otm_mode->vblank_end = (unsigned short) + drm_mode->crtc_vblank_end; + otm_mode->vsync_start = (unsigned short) + drm_mode->crtc_vsync_start; + otm_mode->vsync_end = (unsigned short) + drm_mode->crtc_vsync_end; + otm_mode->mode_info_flags = (unsigned long) + drm_mode->flags; + + /* TODO: metadata should be populated using table from mode_info.c */ + otm_mode->metadata = 0; + for (i = 0; i < ARRAY_SIZE(vic_formats); i++) { + if (otm_mode->width == vic_formats[i].width && + otm_mode->height == vic_formats[i].height && + otm_mode->htotal == vic_formats[i].htotal && + otm_mode->vtotal == vic_formats[i].vtotal && + (otm_mode->dclk == vic_formats[i].dclk || + otm_mode->dclk == __f5994(vic_formats[i].dclk))) { + if (1 == cmdline_mode.specified && + 1 == cmdline_mode.vic_specified) { + if (cmdline_mode.vic == vic_formats[i].vic) { + otm_mode->metadata = cmdline_mode.vic; + break; + } + /* else continue */ + } else { + otm_mode->metadata = vic_formats[i].vic; + break; + } + } + } +} + +/* TODO: get these values depending on the platform */ +#define OTM_HDMI_MDFLD_MIPI_NATIVE_HDISPLAY 1280 +#define OTM_HDMI_MDFLD_MIPI_NATIVE_VDISPLAY 800 +#define OTM_HDMI_MDFLD_PFIT_WIDTH_LIMIT 1024 + +/* + * Description: crtc mode set for hdmi pipe. + * + * @crtc: crtc + * @mode: mode requested + * @adjusted_mode: adjusted mode + * @x, y, old_fb: old frame buffer values used for flushing old plane. + * + * Returns: 0 on success + * -EINVAL on NULL input arguments + */ +int android_hdmi_crtc_mode_set(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode, + int x, int y, + struct drm_framebuffer *old_fb) +{ + struct drm_device *dev; + struct psb_intel_crtc *psb_intel_crtc; + struct drm_psb_private *dev_priv; + struct drm_framebuffer *fb; + struct android_hdmi_priv *hdmi_priv; + struct drm_mode_config *mode_config; + struct psb_intel_output *psb_intel_output = NULL; + struct drm_encoder *encoder; + struct drm_connector *connector; + uint64_t scalingType = DRM_MODE_SCALE_CENTER; + int pipe; + otm_hdmi_timing_t otm_mode, otm_adjusted_mode; + uint32_t clock_khz; + int fb_width, fb_height; +#ifndef MFLD_HDMI_PR3 + u32 width_align, pipebstride; +#endif + pr_debug("%s E", __func__); + + if (crtc == NULL || mode == NULL || adjusted_mode == NULL) + return -EINVAL; + + /* get handles for required data */ + dev = crtc->dev; + psb_intel_crtc = to_psb_intel_crtc(crtc); + pipe = psb_intel_crtc->pipe; + dev_priv = dev->dev_private; + fb = crtc->fb; + fb_width = fb->width; + fb_height = fb->height; + hdmi_priv = dev_priv->hdmi_priv; + mode_config = &dev->mode_config; + + if (pipe != 1) { + pr_err("%s: Invalid pipe %d", __func__, pipe); + return 0; + } + + pr_debug("%s mode info:\n", __func__); + __android_hdmi_dump_crtc_mode(mode); + pr_debug("%s adjusted mode info:\n", __func__); + __android_hdmi_dump_crtc_mode(adjusted_mode); + + memcpy(&psb_intel_crtc->saved_mode, mode, + sizeof(struct drm_display_mode)); + memcpy(&psb_intel_crtc->saved_adjusted_mode, adjusted_mode, + sizeof(struct drm_display_mode)); + + __android_hdmi_drm_mode_to_otm_timing(&otm_mode, mode); + __android_hdmi_drm_mode_to_otm_timing(&otm_adjusted_mode, + adjusted_mode); + +#ifdef MFLD_HDMI_PR3 + list_for_each_entry(connector, &mode_config->connector_list, head) { + if (!connector) + continue; + encoder = connector->encoder; + if (!encoder) + continue; + if (encoder->crtc != crtc) + continue; + psb_intel_output = to_psb_intel_output(connector); + } + + if (psb_intel_output) + drm_connector_property_get_value(&psb_intel_output->base, + dev->mode_config.scaling_mode_property, &scalingType); + + psb_intel_crtc->scaling_type = scalingType; +#endif + /* Disable the VGA plane that we never use */ + REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); + + /* Disable the panel fitter if it was on our pipe */ + /* TODO: do this down the layers. */ + if (psb_intel_panel_fitter_pipe(dev) == pipe) + REG_WRITE(PFIT_CONTROL, 0); + + /* Flush the plane changes */ + { + struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; + crtc_funcs->mode_set_base(crtc, x, y, old_fb); + } + +#if !defined(MFLD_HDMI_PR3) && !defined(MFLD_HDMI_DV1) + if (OTM_HDMI_MDFLD_MIPI_NATIVE_HDISPLAY == fb->width + && otm_adjusted_mode.width < OTM_HDMI_MDFLD_PFIT_WIDTH_LIMIT) { + /* setup HDMI buffers for SW downscaling. + * The scenario where this SW downscaling will be executed has + * a very low probability. The likely scenario is, where the + * external display can only support modes less than + * 1024x768, which has very less probability, as most of the + * monitors has atleast 1024x768 support. + */ + android_hdmi_setup_hdmibuffers(dev, otm_adjusted_mode.width, + otm_adjusted_mode.height, 2, + fb->bits_per_pixel, fb->width, fb->height); + + width_align = (otm_adjusted_mode.width + 31) & ~31; + pipebstride = 4 * width_align; + REG_WRITE(DSPBSTRIDE, pipebstride); + fb_width = otm_adjusted_mode.width; + fb_height = otm_adjusted_mode.height; + } +#endif + + /* + * TODO: clock_khz: is used in mdfld_hdmi_audio.c + * while returning hdmi audio capabilities. + * remove this field from mode_set interfaces and move + * into audio interfaces of OTM when implemented + */ + if (otm_hdmi_crtc_mode_set(hdmi_priv->context, &otm_mode, + &otm_adjusted_mode, fb_width, + fb_height, &clock_khz)) { + pr_err("%s: failed to perform hdmi crtc mode set", + __func__); + return 0; + } + + /* + * TODO: this field is used in mdfld_hdmi_audio.c + * while returning hdmi audio capabilities. + * Remove this and move into audio interfaces of OTM when implemented. + */ + dev_priv->tmds_clock_khz = clock_khz; + +#ifdef MFLD_HDMI_PR3 + /* + * SW workaround for Compliance 7-29 ACR test on 576p@50 + * use the nominal pixel clock, instead of the actual clock + */ + if (otm_adjusted_mode.metadata == 17 || + otm_adjusted_mode.metadata == 18) + dev_priv->tmds_clock_khz = otm_adjusted_mode.dclk; +#endif + + psb_intel_wait_for_vblank(dev); + + pr_debug("%s X", __func__); + return 0; +} + +/* + * Description: encoder mode set for hdmi pipe. + * + * @encoder: hdmi encoder + * @mode: mode requested + * @adjusted_mode: adjusted mode + * + * Returns: none. + */ +void android_hdmi_enc_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct drm_device *dev; + struct android_hdmi_priv *hdmi_priv; + struct drm_psb_private *dev_priv; +#ifdef CONFIG_SND_INTELMID_HDMI_AUDIO + void *had_pvt_data; + enum had_event_type event_type = HAD_EVENT_MODE_CHANGING; +#endif + otm_hdmi_timing_t otm_mode, otm_adjusted_mode; + + pr_debug("%s E", __func__); + + if (encoder == NULL || mode == NULL || adjusted_mode == NULL) + return; + + /* get handles for required data */ + dev = encoder->dev; + dev_priv = dev->dev_private; + hdmi_priv = dev_priv->hdmi_priv; +#ifdef CONFIG_SND_INTELMID_HDMI_AUDIO + had_pvt_data = dev_priv->had_pvt_data; +#endif + + __android_hdmi_drm_mode_to_otm_timing(&otm_mode, mode); + __android_hdmi_drm_mode_to_otm_timing(&otm_adjusted_mode, + adjusted_mode); + + if (otm_hdmi_enc_mode_set(hdmi_priv->context, &otm_mode, + &otm_adjusted_mode)) { + pr_err("%s: failed to perform hdmi enc mode set", + __func__); + return; + } + +#ifdef CONFIG_SND_INTELMID_HDMI_AUDIO + /* Send MODE_CHANGE event to Audio driver */ + if (dev_priv->mdfld_had_event_callbacks) + (*dev_priv->mdfld_had_event_callbacks)(event_type, + had_pvt_data); +#endif + +#ifdef OTM_HDMI_HDCP_ENABLE + /* enable hdcp */ + if (otm_hdmi_hdcp_enable(hdmi_priv->context)) + pr_debug("hdcp enabled"); + else + pr_err("hdcp could not be enabled"); +#endif + return; +} + +/* + * Description: save the register for HDMI display + * + * @dev: drm device + * + * Returns: none. + */ +void android_hdmi_save_display_registers(struct drm_device *dev) +{ + struct drm_psb_private *dev_priv; + struct android_hdmi_priv *hdmi_priv; + uint8_t data; + if (NULL == dev) + return; + dev_priv = dev->dev_private; + if (NULL == dev_priv) + return; + hdmi_priv = dev_priv->hdmi_priv; + if (NULL == hdmi_priv) + return; + /* TODO: get hpd status using get attribute */ + /* Check if monitor is attached to HDMI connector. */ + intel_scu_ipc_ioread8(MSIC_HDMI_STATUS, &data); + otm_hdmi_save_display_registers(hdmi_priv->context, + (data & HPD_SIGNAL_STATUS)); + return; +} + +/* + * Description: restore the register and enable the HDMI display + * + * @dev: drm device + * + * Returns: none. + */ +void android_hdmi_restore_and_enable_display(struct drm_device *dev) +{ + struct drm_psb_private *dev_priv; + struct android_hdmi_priv *hdmi_priv; + uint8_t data; + if (NULL == dev) + return; + dev_priv = dev->dev_private; + if (NULL == dev_priv) + return; + hdmi_priv = dev_priv->hdmi_priv; + if (NULL == hdmi_priv) + return; + /* TODO: get hpd status using get attribute */ + /* Check if monitor is attached to HDMI connector. */ + intel_scu_ipc_ioread8(MSIC_HDMI_STATUS, &data); + otm_hdmi_restore_and_enable_display(hdmi_priv->context, + (data & HPD_SIGNAL_STATUS)); +} + +/* + * Description: disable HDMI display + * + * @dev: drm device + * + * Returns: none. + */ +void android_disable_hdmi(struct drm_device *dev) +{ + struct drm_psb_private *dev_priv; + struct android_hdmi_priv *hdmi_priv; + if (NULL == dev) + return; + dev_priv = dev->dev_private; + if (NULL == dev_priv) + return; + hdmi_priv = dev_priv->hdmi_priv; + if (NULL == hdmi_priv) + return; + otm_disable_hdmi(hdmi_priv->context); + return; +} + +/* + * Description: hdmi helper function to detect whether hdmi/dvi + * is connected or not. + * + * @connector: hdmi connector + * + * Returns: connector_status_connected if hdmi/dvi is connected. + * connector_status_disconnected if hdmi/dvi is not connected. + */ +enum drm_connector_status android_hdmi_detect(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct drm_psb_private *dev_priv = + (struct drm_psb_private *)dev->dev_private; + struct android_hdmi_priv *hdmi_priv = dev_priv->hdmi_priv; + u8 data = 0; + +#ifndef OTM_HDMI_FIXME + /* OTM_HDMI_FIXME: this should be from get attribute interface */ + int adapter_num = 3; +#endif + struct i2c_adapter *adapter = i2c_get_adapter(adapter_num); + + if (NULL == connector || NULL == adapter) + return connector_status_disconnected; + + /* Check if monitor is attached to HDMI connector. */ + intel_scu_ipc_ioread8(MSIC_HDMI_STATUS, &data); + pr_debug("%s: HPD connected data = 0x%x.\n", __func__, data); + +#ifdef OTM_HDMI_HDCP_ENABLE + otm_hdmi_hdcp_set_hpd_state(hdmi_priv->context, + (data & HPD_SIGNAL_STATUS)); +#endif + + if (data & HPD_SIGNAL_STATUS) { + /* + * Handle Hot-plug of HDMI. Display B would be power-gated + * by ospm_post_init if HDMI is not detected during driver load. + * This will power-up Display B if HDMI is + * connected post driver load. + */ + /* + * If pmu_nc_set_power_state fails then accessing HW + * reg would result in a crash - IERR/Fabric error. + */ + if (pmu_nc_set_power_state(OSPM_DISPLAY_B_ISLAND, + OSPM_ISLAND_UP, OSPM_REG_TYPE)) + BUG(); + + dev_priv->panel_desc |= DISPLAY_B; + return connector_status_connected; + } else { + /* + * Clean up the HDMI connector attached encoder, to make + * drm_crtc_helper_set_config() do mode setting each time, + * especially when plug out and plug in HDMI. + */ + drm_helper_disable_unused_functions(dev); + +#ifdef OTM_HDMI_HDCP_ENABLE + /* TODO: HPD status should be used by HDCP through attributes */ + if (otm_hdmi_hdcp_disable(hdmi_priv->context)) + pr_debug("hdcp disabled\n"); + else + pr_debug("failed to disable hdcp\n"); +#endif + return connector_status_disconnected; + } +} + +/* + * Description: hdmi helper function to manage power to the display (dpms) + * + * @encoder: hdmi encoder + * @mode: dpms on or off + * + * Returns: none + */ +void android_hdmi_dpms(struct drm_encoder *encoder, int mode) +{ + struct drm_device *dev; + struct drm_psb_private *dev_priv; + struct android_hdmi_priv *hdmi_priv; + + if (encoder == NULL) + return; + + dev = encoder->dev; + dev_priv = dev->dev_private; + hdmi_priv = dev_priv->hdmi_priv; + + /* TODO: Move entire mdfld_hdmi_dpms function into OTM */ +#ifdef OTM_HDMI_HDCP_ENABLE + otm_hdmi_hdcp_set_dpms(hdmi_priv->context, (mode == DRM_MODE_DPMS_ON)); +#endif +} + +/** + * + * Internal scripts wrapper functions. + * + */ +/* + * TODO: Remove this function afer EDID Parse + * for established modes is implemented + */ + +/* Starting this off, but all scripts/unit test helpers should move + * to another file. + */ + +#ifdef OTM_HDMI_UNIT_TEST + +/** + * test_otm_hdmi_report_edid_full() - Report current EDID information + * + * This routine simply dumps the EDID information + * + * Returns - nothing + */ +void test_otm_hdmi_report_edid_full() +{ + int i = 0; + printk(KERN_ALERT "\n*** Supported Modes ***\n"); + + for (i = 0; i < debug_modes_count; i++) + printk(KERN_ALERT "Mode %02d: %s @%dHz Clk: %dKHz\n", i, + arr_modes[i].name, arr_modes[i].frq, arr_modes[i].clk); + + printk(KERN_ALERT "\n"); +} +EXPORT_SYMBOL_GPL(test_otm_hdmi_report_edid_full); +#endif diff --git a/drivers/staging/mrst/drv/otm_hdmi/os/android/include/android_hdmi.h b/drivers/staging/mrst/drv/otm_hdmi/os/android/include/android_hdmi.h new file mode 100644 index 0000000..bfa0cb2 --- /dev/null +++ b/drivers/staging/mrst/drv/otm_hdmi/os/android/include/android_hdmi.h @@ -0,0 +1,397 @@ +/* + + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2011 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + + Intel Corporation + 2200 Mission College Blvd. + Santa Clara, CA 95054 + + BSD LICENSE + + Copyright(c) 2011 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef __ANDROID_HDMI_H +#define __ANDROID_HDMI_H + +#include + +#define CEA_EXT 0x02 +#define VTB_EXT 0x10 +#define DI_EXT 0x40 +#define LS_EXT 0x50 +#define MI_EXT 0x60 + +/* TODO: move cea_861b_adb_t and hdmi_eeld_t into PIL */ +/* Header = 4, Baseline Data = 80 and Vendor (INTEL) specific = 2 as per + * EELD spec + * 4 + 80 + = 84 + */ +#define HDMI_EELD_SIZE 84 +typedef union _hdmi_eeld { + uint8_t eeld[HDMI_EELD_SIZE]; + #pragma pack(1) + struct { + /* Byte[0] = ELD Version Number */ + union { + uint8_t byte0; + struct { + uint8_t reserved:3; /* Reserf */ + uint8_t eld_ver:5; /* ELD Version Number */ + /* 00000b - reserved + * 00001b - first rev + * 00010b:11111b - reserved + * for future + */ + }; + }; + + /* Byte[1] = Vendor Version Field */ + union { + uint8_t vendor_version; + struct { + uint8_t reserved1:3; + uint8_t veld_ver:5; /* Version number of the ELD + * extension. This value is + * provisioned and unique to + * each vendor. + */ + }; + }; + + /* Byte[2] = Baseline Lenght field */ + uint8_t baseline_eld_length; /* Length of the Baseline structure + * divided by Four. + */ + + /* Byte [3] = Reserved for future use */ + uint8_t byte3; + + /* Starting of the BaseLine EELD structure + * Byte[4] = Monitor Name Length + */ + union { + uint8_t byte4; + struct { + uint8_t mnl:5; + uint8_t cea_edid_rev_id:3; + }; + }; + + /* Byte[5] = Capabilities */ + union { + uint8_t capabilities; + struct { + uint8_t hdcp:1; /* HDCP support */ + uint8_t ai_support:1; /* AI support */ + uint8_t connection_type:2; /* Connection type + * 00 - HDMI + * 01 - DP + * 10 -11 Reserved + * for future + * connection types + */ + uint8_t sadc:4; /* Indicates number of 3 bytes + * Short Audio Descriptors. + */ + }; + }; + + /* Byte[6] = Audio Synch Delay */ + uint8_t audio_synch_delay; /* Amount of time reported by the + * sink that the video trails audio + * in milliseconds. + */ + + /* Byte[7] = Speaker Allocation Block */ + union { + uint8_t speaker_allocation_block; + struct { + uint8_t flr:1; /*Front Left and Right channels*/ + uint8_t lfe:1; /*Low Frequency Effect channel*/ + uint8_t fc:1; /*Center transmission channel*/ + uint8_t rlr:1; /*Rear Left and Right channels*/ + uint8_t rc:1; /*Rear Center channel*/ + uint8_t flrc:1; /*Front left and Right of Center + *transmission channels + */ + uint8_t rlrc:1; /*Rear left and Right of Center + *transmission channels + */ + uint8_t reserved3:1; /* Reserved */ + }; + }; + + /* Byte[8 - 15] - 8 Byte port identification value */ + uint8_t port_id_value[8]; + + /* Byte[16 - 17] - 2 Byte Manufacturer ID */ + uint8_t manufacturer_id[2]; + + /* Byte[18 - 19] - 2 Byte Product ID */ + uint8_t product_id[2]; + + /* Byte [20-83] - 64 Bytes of BaseLine Data */ + uint8_t mn_sand_sads[64]; /* This will include + * - ASCII string of Monitor name + * - List of 3 byte SADs + * - Zero padding + */ + + /* Vendor ELD Block should continue here! + * No Vendor ELD block defined as of now. + */ + }; + #pragma pack() +} hdmi_eeld_t; + +typedef struct _cea_861b_adb { +#pragma pack(1) + union { + uint8_t byte1; + struct { + uint8_t max_channels:3; /* Bits[0-2] */ + uint8_t audio_format_code:4; /* Bits[3-6], + see AUDIO_FORMAT_CODES*/ + uint8_t b1reserved:1; /* Bit[7] - reserved */ + }; + }; + union { + uint8_t byte2; + struct { + uint8_t sp_rate_32kHz:1; /*Bit[0] sample rate=32kHz*/ + uint8_t sp_rate_44kHz:1; /*Bit[1] sample rate=44kHz*/ + uint8_t sp_rate_48kHz:1; /*Bit[2] sample rate=48kHz*/ + uint8_t sp_rate_88kHz:1; /*Bit[3] sample rate=88kHz*/ + uint8_t sp_rate_96kHz:1; /*Bit[4] sample rate=96kHz*/ + uint8_t sp_rate_176kHz:1; /*Bit[5] sample rate=176kHz*/ + uint8_t sp_rate_192kHz:1; /*Bit[6] sample rate=192kHz*/ + uint8_t sp_rate_b2reserved:1; /* Bit[7] - reserved*/ + }; + }; + union { + uint8_t byte3; /* maximum bit rate divided by 8kHz */ + /* following is the format of 3rd byte for + * uncompressed(LPCM) audio + */ + struct { + uint8_t bit_rate_16bit:1; /* Bit[0] */ + uint8_t bit_rate_20bit:1; /* Bit[1] */ + uint8_t bit_rate_24bit:1; /* Bit[2] */ + uint8_t bit_rate_b3reserved:5; /* Bits[3-7] */ + }; + }; +#pragma pack() + +} cea_861b_adb_t; + +struct android_hdmi_priv { + /* common */ + struct drm_device *dev; + + /* oaktrail specific */ + /* PCI related parameters are not needed to be exposed. + * Need to remove. + */ + void *regs; + int dpms_mode; + struct hdmi_i2c_dev *i2c_dev; + + + /*medfield specific */ + u32 hdmib_reg; + u32 save_HDMIB; + bool has_hdmi_sink; + /* Should set this when detect hotplug */ + bool hdmi_device_connected; + struct mdfld_hdmi_i2c *i2c_bus; + /* EELD packet holder*/ + hdmi_eeld_t eeld; + u32 hdmi_eeld_size; + cea_861b_adb_t lpcm_sad; + bool is_hdcp_supported; + struct i2c_adapter *hdmi_i2c_adapter; /* for control functions */ + /*TODO: remove this and use from context when set_property is + * implemented in OTM. + */ + int monitor_type; + void *context; +}; + +/* Global devices for switch class used for hotplug notification */ +extern struct switch_dev g_switch_hdmi_dev; +extern struct switch_dev g_switch_dvi_dev; + +/* TODO: remove this once all code moved into OTM */ +extern const struct drm_encoder_funcs psb_intel_lvds_enc_funcs; +extern const struct drm_encoder_helper_funcs mdfld_hdmi_helper_funcs; +extern const struct drm_connector_funcs mdfld_hdmi_connector_funcs; +extern const struct drm_connector_helper_funcs + mdfld_hdmi_connector_helper_funcs; + +extern void android_hdmi_driver_init(struct drm_device *dev, + void *mode_dev); + +extern void android_hdmi_enable_hotplug(struct drm_device *dev); + +extern void android_hdmi_driver_setup(struct drm_device *dev); + +extern void android_hdmi_context_init(void *context); + +extern int android_hdmi_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode); + +extern int android_hdmi_get_modes(struct drm_connector *connector); + +/* + * Description: crtc mode set for hdmi pipe. + * + * @crtc: crtc + * @mode: mode requested + * @adjusted_mode: adjusted mode + * @x, y, old_fb: old frame buffer values used for flushing old plane. + * + * Returns: 0 on success + * -EINVAL on NULL input arguments + */ +extern int android_hdmi_crtc_mode_set(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode, + int x, int y, + struct drm_framebuffer *old_fb); + +/* + * Description: encoder mode set for hdmi pipe. + * + * @encoder: hdmi encoder + * @mode: mode requested + * @adjusted_mode: adjusted mode + * + * Returns: none. + */ +extern void android_hdmi_enc_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode); + +/* TODO: do this down the layers. */ +extern int psb_intel_panel_fitter_pipe(struct drm_device *dev); + +/* TODO: medfiled specific */ +extern void mdfld_hdmi_audio_init(struct android_hdmi_priv *p_hdmi_priv); +extern void mdfld_msic_init(struct android_hdmi_priv *p_hdmi_priv); + +/* + * Allocates the hdmi buffers of specified dimensions. + * Initializes Scaling related paramters. + * input parameters: + * psDrmDev: Drm Device. + * ui32HdmiWidth, ui32HdmiHeight: HDMI mode + * ui32BufferCount,: number of HDMI buffers to allocate. + * bpp: bits per pixel to consider for allocating the buffer. + * ui32LvdsWidth, ui32LvdsHeight: Native display (LVDS) Mode. + * returns '0' on success and other values on failure. + */ +extern int android_hdmi_setup_hdmibuffers(struct drm_device *psDrmDev, + u32 ui32HdmiWidth, u32 ui32HdmiHeight, + u32 ui32BufferCount, int bpp, u32 ui32LvdsWidth, + u32 ui32LvdsHeight); + +/* + * Store the HDMI registers and enable the display + * Input parameters: + * psDrmDev: Drm Device. + * Returns: none + */ +extern void android_hdmi_restore_and_enable_display(struct drm_device *dev); + +/* + * Save the HDMI display registers + * Input parameters: + * psDrmDev: Drm Device. + * Returns: none + */ +extern void android_hdmi_save_display_registers(struct drm_device *dev); + +/* + * disable HDMI display + * Input parameters: + * psDrmDev: Drm Device. + * Returns: none + */ +extern void android_disable_hdmi(struct drm_device *dev); + + +/* + * Description: hdmi helper function to detect whether hdmi/dvi + * is connected or not. + * + * @connector: hdmi connector + * + * Returns: connector_status_connected if hdmi/dvi is connected. + * connector_status_disconnected if hdmi/dvi is not connected. + */ +extern enum drm_connector_status android_hdmi_detect(struct drm_connector + *connector); + +/* + * Description: hdmi helper function to manage power to the display (dpms) + * + * @encoder: hdmi encoder + * @mode: dpms on or off + * + * Returns: none + */ +extern void android_hdmi_dpms(struct drm_encoder *encoder, + int mode); + +#endif /* __ANDROID_HDMI_H */ diff --git a/drivers/staging/mrst/drv/otm_hdmi/pil/common/edid.c b/drivers/staging/mrst/drv/otm_hdmi/pil/common/edid.c new file mode 100644 index 0000000..3abc4e5 --- /dev/null +++ b/drivers/staging/mrst/drv/otm_hdmi/pil/common/edid.c @@ -0,0 +1,1365 @@ +/* + + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2011 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + + Intel Corporation + 2200 Mission College Blvd. + Santa Clara, CA 95054 + + BSD LICENSE + + Copyright(c) 2011 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include +#include + +#include "otm_hdmi_types.h" +#include "edid_internal.h" +#include "hdmi_timings.h" + + +/* + * Macro for error checking + */ +#define VERIFY(exp, rc, error, label) \ + if (!(exp)) { \ + rc = error; \ + goto label; \ + } + +#define VERIFY_QUICK(exp, label) \ + if (!(exp)) { \ + goto label; \ + } + +/* + * Various constants + */ +#define EDID_SIGNATURE 0x00FFFFFFFFFFFF00ull + +/* + * Debug printing setup + */ +/* TODO: All printing should use one method,either PD_LOG_PRINT, + * EDID_PRINT, DRM printing, pr_debug. The solution should be run-time + * instead of compile-time switches. Will need some work to get + * that done. Deferring for the time-being. Keep EDID prints + * disabled as they are invoked on every DRM get_mode query + * and prove costly and add problems like slow, jittery playback */ +#ifndef OTM_HDMI_FIXME +int EDID_PRINT(const char *fmt, ...) +{ + return 0; +} +#else +int EDID_PRINT(const char *fmt, ...) +{ + va_list arg_list; + + va_start(arg_list, fmt); + vprintk(fmt, arg_list); + va_end(arg_list); + return 0; +} +#endif + +/* + * Structure to keep state of read operation + */ +typedef struct { + unsigned char *buffer; + int position; +} read_context_t; + +/* + * fetch_next_field() + */ +void fetch_next_field(void *dst, read_context_t *read_context, + unsigned int size) +{ + unsigned char *b = read_context->buffer + read_context->position; + + switch (size) { +#ifdef __ORDER_MSB__ + case 1: + *(unsigned char *)dst = *b; + break; + + case 2: + *(unsigned short *)dst |= (unsigned short)*(b + 1) << 0; + *(unsigned short *)dst |= (unsigned short)*(b + 0) << 8; + break; + + case 4: + *(unsigned int *)dst |= (unsigned int)*(b + 3) << 0; + *(unsigned int *)dst |= (unsigned int)*(b + 2) << 8; + *(unsigned int *)dst |= (unsigned int)*(b + 1) << 16; + *(unsigned int *)dst |= (unsigned int)*(b + 0) << 24; + break; + + case 8: + *(unsigned long long *)dst |= (unsigned long long)*(b + 7) << 0; + *(unsigned long long *)dst |= (unsigned long long)*(b + 6) << 8; + *(unsigned long long *)dst |= + (unsigned long long)*(b + 5) << 16; + *(unsigned long long *)dst |= + (unsigned long long)*(b + 4) << 24; + *(unsigned long long *)dst |= + (unsigned long long)*(b + 3) << 32; + *(unsigned long long *)dst |= + (unsigned long long)*(b + 2) << 40; + *(unsigned long long *)dst |= + (unsigned long long)*(b + 1) << 48; + *(unsigned long long *)dst |= + (unsigned long long)*(b + 0) << 56; + break; +#endif + + default: + /* + * This is only for byte sequences with LSB order, or where + * where order does not matter + */ + memcpy(dst, b, size); + break; + } + + read_context->position += size; +} + +/* + * fetch_generic_descriptor() + */ +void fetch_generic_descriptor(generic_descriptor_t *gd, read_context_t *rctx) +{ + fetch_next_field(&gd->flag_required, rctx, 2); + fetch_next_field(&gd->flag_reserved, rctx, 1); + fetch_next_field(&gd->data_type_tag, rctx, 1); + fetch_next_field(&gd->flag, rctx, 1); + fetch_next_field(&gd->payload, rctx, 13); +} + +/* + * fetch_timing_descriptor() + */ +void fetch_timing_descriptor(timing_descriptor_t *td, read_context_t *rctx) +{ + fetch_next_field(&td->pixel_clock, rctx, 2); + fetch_next_field(&td->h_active, rctx, 1); + fetch_next_field(&td->h_blanking, rctx, 1); + fetch_next_field(&td->h_active_blanking_hb, rctx, 1); + fetch_next_field(&td->v_active, rctx, 1); + fetch_next_field(&td->v_blanking, rctx, 1); + fetch_next_field(&td->v_active_blanking_hb, rctx, 1); + fetch_next_field(&td->h_sync_offset, rctx, 1); + fetch_next_field(&td->h_sync_pulse_width, rctx, 1); + fetch_next_field(&td->vs_offset_pulse_width, rctx, 1); + fetch_next_field(&td->offset_pulse_width_hb, rctx, 1); + fetch_next_field(&td->h_image_size, rctx, 1); + fetch_next_field(&td->v_image_size, rctx, 1); + fetch_next_field(&td->hv_image_size, rctx, 1); + fetch_next_field(&td->h_border, rctx, 1); + fetch_next_field(&td->v_border, rctx, 1); + fetch_next_field(&td->flags, rctx, 1); +} + +/* + * fetch_block_zero() + * - ebz : structure representing edid block zero to be filled in + * - data: buffer of 128 bytes containing raw edid data supplied by TV + */ +otm_hdmi_ret_t fetch_block_zero(edid_block_zero_t *ebz, unsigned char *data) +{ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + read_context_t read_context = {data, 0}; + read_context_t *rctx = &read_context; + int i; + + VERIFY(ebz != NULL, rc, OTM_HDMI_ERR_NULL_ARG, exit); + VERIFY(data != NULL, rc, OTM_HDMI_ERR_NULL_ARG, exit); + + /* EDID signature */ + fetch_next_field(&ebz->signature, rctx, 8); + + /* Manufacturer name id */ + fetch_next_field(&ebz->manufacturer_id, rctx, 2); + + /* Product code */ + fetch_next_field(&ebz->product_code, rctx, 2); + + /* Serial number */ + fetch_next_field(&ebz->serial_number, rctx, 4); + + /* Manufacture week */ + fetch_next_field(&ebz->manufacture_week, rctx, 1); + + /* Manufacture year */ + fetch_next_field(&ebz->manufacture_year, rctx, 1); + + /* EDID version */ + fetch_next_field(&ebz->version, rctx, 1); + + /* EDID revision */ + fetch_next_field(&ebz->revision, rctx, 1); + + /* Video input definition */ + fetch_next_field(&ebz->video_input_definition, rctx, 1); + + /* Max horizontal image size */ + fetch_next_field(&ebz->max_horz_image_size, rctx, 1); + + /* Max vertical image size*/ + fetch_next_field(&ebz->max_vert_image_size, rctx, 1); + + /* Gamma */ + fetch_next_field(&ebz->gamma, rctx, 1); + + /* Feature support */ + fetch_next_field(&ebz->feature_support, rctx, 1); + + /* Color characteristics */ + fetch_next_field(&ebz->rg_lowbits, rctx, 1); + fetch_next_field(&ebz->bw_lowbits, rctx, 1); + fetch_next_field(&ebz->red_x, rctx, 1); + fetch_next_field(&ebz->red_y, rctx, 1); + fetch_next_field(&ebz->green_x, rctx, 1); + fetch_next_field(&ebz->green_y, rctx, 1); + fetch_next_field(&ebz->blue_x, rctx, 1); + fetch_next_field(&ebz->blue_y, rctx, 1); + fetch_next_field(&ebz->white_x, rctx, 1); + fetch_next_field(&ebz->white_x, rctx, 1); + + /* Established timings */ + fetch_next_field(&ebz->est_timing_1, rctx, 1); + fetch_next_field(&ebz->est_timing_2, rctx, 1); + fetch_next_field(&ebz->est_timing_3, rctx, 1); + + /* Standard timings */ + for (i = 0; i < EDID_STD_TIMINGS_NUM; i++) + fetch_next_field(&ebz->std_timings[i], rctx, 2); + + /* Detailed timing descriptors 1 and 2 */ + fetch_generic_descriptor((generic_descriptor_t *) &ebz->td_1, rctx); + fetch_generic_descriptor((generic_descriptor_t *) &ebz->td_2, rctx); + + /* Monitor Descriptors 1 and 2 */ + fetch_generic_descriptor((generic_descriptor_t *) &ebz->md_1, rctx); + fetch_generic_descriptor((generic_descriptor_t *) &ebz->md_2, rctx); + + /* Number of 128 byte blocks to follow */ + fetch_next_field(&ebz->num_extentions, rctx, 1); + +exit: + return rc; +} + +/* + * fetch_extension_block_cea() + */ +otm_hdmi_ret_t fetch_extension_block_cea(extention_block_cea_t *eb, + unsigned char *data) +{ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + read_context_t read_context = {data, 0}; + read_context_t *rctx = &read_context; + + VERIFY(eb != NULL, rc, OTM_HDMI_ERR_NULL_ARG, exit); + VERIFY(data != NULL, rc, OTM_HDMI_ERR_NULL_ARG, exit); + + fetch_next_field(&eb->tag, rctx, 1); + fetch_next_field(&eb->revision, rctx, 1); + fetch_next_field(&eb->content_offset, rctx, 1); + fetch_next_field(&eb->flags, rctx, 1); + fetch_next_field(&eb->data, rctx, 124); + +exit: + return rc; +} + +/* + * encode_refresh() + * Convert an integer refresh rate to the equivalent enumeration + */ +static otm_hdmi_refresh_t encode_refresh(unsigned refresh) +{ + /* Both 1/1001 and 1/1000 refresh rates are included in case + * EDID contains 1/1001 pixel clock values in the entry + */ + switch (refresh) { + case 23: + return OTM_HDMI_REFRESH_24; + case 24: + return OTM_HDMI_REFRESH_24; + case 25: + return OTM_HDMI_REFRESH_25; + case 29: + return OTM_HDMI_REFRESH_30; + case 30: + return OTM_HDMI_REFRESH_30; + case 50: + return OTM_HDMI_REFRESH_50; + case 59: + return OTM_HDMI_REFRESH_60; + case 60: + return OTM_HDMI_REFRESH_60; + } + return OTM_HDMI_REFRESH_USER_DEFINED; +} + +/* + * Returns index of timing with given VIC in given table; -1 otherwise + */ +int find_timing_by_vic_tp(const otm_hdmi_timing_t **set, int size, + unsigned int vic) +{ + int i, rc = -1; + + VERIFY(set, rc, -1, exit); + + for (i = 0; i < size; i++) { + if (set[i]->metadata == vic) { + rc = i; + break; + } + } + +exit: + return rc; +} + +/* + * Timings comparison + */ +static bool __timing_equal(const otm_hdmi_timing_t *t1, + const otm_hdmi_timing_t *t2) +{ + unsigned int t1_flags = t1->mode_info_flags & PD_SCAN_INTERLACE; + unsigned int t2_flags = t2->mode_info_flags & PD_SCAN_INTERLACE; + + return ((t1->width == t2->width) && + (t1->height == t2->height) && + (t1->refresh == t2->refresh) && + (t1_flags == t2_flags) && (t1->stereo_type == t2->stereo_type)); +} + +/* + * Returns index of given timings in given table of timings; -1 otherwise + */ +int find_timing(const otm_hdmi_timing_t *set, int size, + const otm_hdmi_timing_t *e) +{ + int i, rc = -1; + VERIFY(set && e, rc, -1, exit); + for (i = 0; i < size && !__timing_equal(&set[i], e); i++); + + rc = (i < size) ? i : -1; +exit: + return rc; +} + +/* + * Returns index of given timings in given table of timing pointers; + * -1 otherwise + */ +int find_timing_tp(const otm_hdmi_timing_t **set, int size, + const otm_hdmi_timing_t *e) +{ + int i, rc = -1; + VERIFY(set && e, rc, -1, exit); + for (i = 0; i < size && !__timing_equal(set[i], e); i++); + + rc = (i < size) ? i : -1; +exit: + return rc; +} + +/* + * add_timings() + */ +otm_hdmi_ret_t add_timings(edid_info_t *edid, const otm_hdmi_timing_t *pdt, + unsigned int order) +{ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + int i, j; + + /* Safety checks */ + VERIFY((edid != NULL) && (pdt != NULL), rc, + OTM_HDMI_ERR_NULL_ARG, exit); + + /* Is there room for more timings at all? */ + VERIFY(edid->num_timings < MAX_TIMINGS, rc, + OTM_HDMI_ERR_INVAL, exit); + + /* Print info about it */ + print_pd_timing(pdt, order, EDID_PRINT); + + /* Do not add modes that we dont support */ + i = find_timing_tp(edid->ref_timings, edid->num_ref_timings, pdt); + VERIFY(i > -1, rc, OTM_HDMI_ERR_INVAL, exit); + + /* Do not add duplicates; Update discovery order though for cases when + * a mode was decoded from DTD first + */ + if ((j = find_timing(edid->timings, edid->num_timings, pdt)) != -1) { + edid->order[j] = !edid->order[j] ? order : edid->order[j]; + goto exit; + } + /* Save discovery order */ + edid->order[edid->num_timings] = order; + + /* Add timing */ + edid->timings[edid->num_timings++] = *edid->ref_timings[i]; + + /* Update supported family of refresh rates */ + edid->supports_60Hz = edid->supports_60Hz + || pdt->refresh == OTM_HDMI_REFRESH_60; + edid->supports_50Hz = edid->supports_50Hz + || pdt->refresh == OTM_HDMI_REFRESH_50; + +exit: + return rc; +} + +/* + * checksum_valid() + */ +bool checksum_valid(unsigned char *buffer, int size) +{ + unsigned char sum_computed = 0; + + while (size-- > 0) + sum_computed += *(buffer++); + + return (sum_computed == 0) ? true : false; +} + +/* + * decode_speaker_allocation_data_block() + */ +void decode_speaker_allocation_data_block(unsigned char *e, int n, + edid_info_t *edid) +{ + int ne = n / 3; + + EDID_PRINT("[speaker block]\n"); + + while (ne-- > 0) { + edid->speaker_map = + (unsigned)*e | (unsigned)(*(e + 1) & 0x7) << 8; + print_speaker_layout(edid->speaker_map, EDID_PRINT); + e++; + e++; /* skip the rest of the block */ + } +} + +/* + * decode_video_data_block() + */ +void decode_video_data_block(unsigned char *e, int n, edid_info_t *edid) +{ + int vic, j, i = 0; + + EDID_PRINT("[video data block]\n"); + + while (n-- > 0) { + vic = *e & 0x7F; + EDID_PRINT("- mode #%d %s\n", vic, (*e & 0x80) ? "native" : ""); + + if ((j = + find_timing_by_vic_tp(edid->ref_timings, + edid->num_ref_timings, vic)) != -1) { + add_timings(edid, edid->ref_timings[j], ++i); + + /* Handle native mode */ + if (*e & 0x80) { + edid->native_idx = + find_timing(edid->timings, + edid->num_timings, + edid->ref_timings[j]); + } + } + e++; + } +} + +/* + * decode_audio_data_block() + */ +void decode_audio_data_block(unsigned char *e, int n, edid_info_t *edid) +{ + int ne = n / 3; + otm_hdmi_audio_cap_t *adb = (otm_hdmi_audio_cap_t *) &edid->audio_caps; + + EDID_PRINT("[audio data block... %d entries]\n", ne); + + while (ne-- > 0) { + /* Do we have room for another capability? */ + if (edid->num_caps < MAX_CAPS) { + adb[edid->num_caps].format = (*e & 0x78) >> 3; + adb[edid->num_caps].max_channels = (*e & 0x07) + 1; + adb[edid->num_caps].fs = *(e + 1) & 0x7F; + adb[edid->num_caps].ss_bitrate = *(e + 2); + print_audio_capability(&adb[edid->num_caps], + EDID_PRINT); + edid->num_caps++; + } + /* Go to the next entry of the block */ + e += 3; + } +} + +/* + * + */ +void declare_mandatory_3d(edid_info_t *edid) +{ + if (true) { + add_timings(edid, &MODE_1920x1080p24__FP2, 0); + add_timings(edid, &MODE_1920x1080p24__FP, 0); + add_timings(edid, &MODE_1920x1080p24__TBH2, 0); + } + + if (edid->supports_60Hz) { + add_timings(edid, &MODE_1280x720p5994_60__FP2, 0); + add_timings(edid, &MODE_1280x720p5994_60__FP, 0); + add_timings(edid, &MODE_1920x1080i5994_60__SBSH2, 0); + add_timings(edid, &MODE_1280x720p5994_60__TBH2, 0); + } + + if (edid->supports_50Hz) { + add_timings(edid, &MODE_1280x720p50__FP2, 0); + add_timings(edid, &MODE_1280x720p50__FP, 0); + add_timings(edid, &MODE_1920x1080i50__SBSH2, 0); + add_timings(edid, &MODE_1280x720p50__TBH2, 0); + } +}; + +/* + * Addition of 3D timing via 2D mode + */ +void add_3d_mode_via_2d(unsigned int vic, unsigned int struc_3d, + edid_info_t *edid) +{ + unsigned int j, k, num_timings = edid->num_timings; + otm_hdmi_timing_t t; + + struct { + unsigned int struc; + unsigned int type; + } details_3d[] = { + { + 0x00, OTM_HDMI_STEREO_FRAME_PACKING_2}, { + 0x00, OTM_HDMI_STEREO_FRAME_PACKING}, { + 0x06, OTM_HDMI_STEREO_TOP_BOTTOM_HALF_2}, { + 0x08, OTM_HDMI_STEREO_SIDE_BY_SIDE_HALF_2},}; + + /* Look for an entry with given order among all decoded 2D timings */ + for (j = 0; j < num_timings; j++) { + if (edid->order[j] == vic) { + /* + * Create all required 3D variations for given + * 2D mode + */ + for (k = 0; + k < sizeof(details_3d) / sizeof(*details_3d); + k++) { + if (details_3d[k].struc == struc_3d) { + t = edid->timings[j]; + t.stereo_type = details_3d[k].type; + add_timings(edid, &t, 0); + } + } + + /* Entry of given order was found so start looking for + * new one + */ + break; + } + } +} + +/* + * Processing of 3D modes declared via 3D_Struture_ALL and 3D_MASK + */ +void declare_short_3d(unsigned int struc_3d, unsigned int mask, + edid_info_t *edid) +{ + unsigned int i, j, modes; + + /* Go through each 2D_VIC specified via 3D_MASK */ + for (i = 0; i < 16; i++, mask = mask >> 1) { + /* + * Go through stereo variations specified via + * 3D_Structure_ALL + */ + for (j = 0, modes = struc_3d; j < 16; j++, modes = modes >> 1) { + if (modes & 0x01 && mask & 0x01) + add_3d_mode_via_2d(i + 1, j, edid); + } + } +} + +/* + * Processing of 3D modes declared via explicit list of 2D vics + */ +void declare_explicit_3d(unsigned char *e, unsigned int n, edid_info_t *edid) +{ + unsigned int i; + + /* Go through the list of 2D_VIC_ORDER_X entries + * 0x08 typed entries are 2 bytes, others are 1 byte + */ + for (i = 0; i < n; i += (e[i] & 0x0F) == 0x08 ? 2 : 1) + add_3d_mode_via_2d(((e[i] & 0xF0) >> 4) + 1, e[i] & 0x0F, edid); +} + +/* + * decode_misc_modes() + */ +void decode_misc_modes(unsigned char *e, int n, edid_info_t *edid) +{ + +} + +#ifdef OTM_HDMI_FIXME +/* TODO: Should be Revisted + * 3D parsing hangs system with edid09 of analyzer Bug206379 */ +/* + * decode_3D_modes() + */ +void decode_3D_modes(unsigned char *e, int n, int layout, edid_info_t *edid) +{ + unsigned int offset; + + EDID_PRINT("- 3D modes supported:\n"); + + /* Declare mandatory modes */ + declare_mandatory_3d(edid); + + /* There are several ways of declaring 3D modes support */ + switch (layout) { + case 0: /* Mandatory modes only */ + offset = 0; + break; + + case 1: /* Mandatory modes + variations described in + * 3D_Structure_ALL */ + /* supported by each of first 16 VICs */ + offset = 2; + declare_short_3d(e[1] | (e[0] << 8), 0xFFFF, edid); + break; + + case 2: /* Mandatory modes + variations described in + * 3D_Structure_ALL */ + /* supported only by some of 16 first VICs + * [as told by 3D_MASK] */ + offset = 4; + declare_short_3d(e[1] | (e[0] << 8), e[3] | (e[2] << 8), edid); + break; + + default: /* Reserved for future use */ + offset = 0; + break; + } + + /* Declare 3D modes based on present 2D VIC entries */ + declare_explicit_3d(e + offset, (n >= offset) ? n - offset : 0, edid); +} +#endif + +/* + * decode_vendor_data_block() + */ +void decode_vendor_data_block(unsigned char *e, int n, edid_info_t * edid) +{ + unsigned int pos; +#ifdef OTM_HDMI_FIXME + unsigned int len_3d, len_hdmi; +#endif + + EDID_PRINT("[vendor specific data block.. length %d]\n", n); + + /* Look for HDMI signature [0x030C00] */ + if (n >= 3) { + if ((e[0] == 0x03) && (e[1] == 0x0C) && (e[2] == 0x00)) { + edid->hdmi = true; + EDID_PRINT("- HDMI signature found\n"); + } + } + /* Parse Source Physical Address */ + if (n >= 5) + edid->spa = (e[3] << 8) | e[4]; + /* Look for more optional stuff */ + if (n >= 6) { + /* Deep Color support */ + edid->dc_48 = (e[5] & 0x40) != 0; + edid->dc_36 = (e[5] & 0x20) != 0; + edid->dc_30 = (e[5] & 0x10) != 0; + edid->dc_y444 = (e[5] & 0x08) != 0; + + /* AI support */ + edid->supports_ai = (e[5] & 0x80) != 0; + } + /* MAX TMDS clock */ + if (n >= 7) + edid->max_tmds_clock = e[6] * 5; + /* Check for optional latency and 3D fields */ + if ((n >= 8)) { + edid->latency_present = (e[7] & 0x80) != 0; + edid->latency_int_present = (e[7] & 0x40) != 0; + edid->hdmi_video_present = (e[7] & 0x20) != 0; + } + /* From now on keep explicit track of position we are reading */ + pos = 8; + + /* Get video latency [in ms] */ + if (edid->latency_present) { + edid->latency_video = e[pos++]; + edid->latency_audio = e[pos++]; + + /* Get interlaced video latency [in ms] */ + if (edid->latency_int_present) { + edid->latency_video_interlaced = e[pos++]; + edid->latency_audio_interlaced = e[pos++]; + } + } + +#ifdef OTM_HDMI_FIXME + /* TODO: Should be Revisted + * 3D parsing hangs system with edid09 of analyzer Bug206379 */ + + /* 3D and misc modes information from HDMI 1.4 specification */ + if (edid->hdmi_video_present) { + edid->enabled_3d = (e[pos++] & 0x80) != 0; + + len_3d = (e[pos] & 0x1F); + len_hdmi = (e[pos++] & 0xE0) >> 5; + + /* Assumption is that both misc and 3D modes can be + * present so deal with + * misc modes first + */ + decode_misc_modes(e + pos, len_hdmi, edid); + + /* Now deal with 3D stuff */ + if (len_3d || edid->enabled_3d) { + decode_3D_modes(e + pos + len_hdmi, len_3d, + (e[pos - 2] & 0x60) >> 5, edid); + } + + } +#endif + +} + +/* + * decode_extended_data_block() + */ +void decode_extended_data_block(unsigned char *e, int n, edid_info_t * edid) +{ + EDID_PRINT("[extended data block.. length %d]\n", n); + + switch (*(e + 0)) { + case 0x00: /* Video Capability Block */ + EDID_PRINT("Video Capability Block\n"); + edid->rgb_quant_selectable = *(e + 1) & 0x40; + edid->ycc_quant_selectable = *(e + 1) & 0x80; + break; + case 0x01: /* Vendor Specific Video Data Block */ + EDID_PRINT("Vendor Specific Video Data Block\n"); + break; + case 0x05: /* Colorimetry Block */ + EDID_PRINT("Colorimetry Block\n"); + if (n == 3) { + edid->xvycc601 = (*(e + 1) & 0x01) != 0; + edid->xvycc709 = (*(e + 1) & 0x02) != 0; + } + break; + case 0x11: /* CEA Misc Audio Block */ + EDID_PRINT("CEA Misc Audio Block\n"); + break; + case 0x12: /* Vendor specific audio data block */ + EDID_PRINT("Vendor specific audio data Block\n"); + break; + default: /* reserved blocks */ + EDID_PRINT("Reserved Block\n"); + break; + } + +} + +/* + * This is what short descriptor handler signature should look like + * NOTE: e is where payload starts, i.e. header byte is not included!!! + */ +typedef void (*short_block_decoder_t)(unsigned char *e, int n, + edid_info_t *edid); + +short_block_decoder_t short_block_decoders[] = { + /* Reserved */ + NULL, + /* Audio data block decoder */ + decode_audio_data_block, + /* Video data block decoder */ + decode_video_data_block, + /* Vendor specific block decoder */ + decode_vendor_data_block, + /* Speaker allocation block decoder */ + decode_speaker_allocation_data_block, + /* VESA DTC data block decoder */ + NULL, + /* Reserved */ + NULL, + /* Extended tag handler */ + decode_extended_data_block +}; + +/* + * decode_block_collection() + * See section 7.5 of CEA-861-C for details + */ +void decode_block_collection(extention_block_cea_t *eb, edid_info_t *edid) +{ + unsigned char *c = eb->data; + int block_type, payload_size; + + /* All area before detailed descriptors should be filled + * TODO: Shall we change this to safer check? + */ + while (c < ((unsigned char *)eb + eb->content_offset)) { + block_type = (*c & 0xE0) >> 5; + payload_size = *c & 0x1F; + + /* Simple block types */ + if ((block_type < 8) && (block_type >= 0)) { + if (short_block_decoders[block_type]) { + short_block_decoders[block_type] ((unsigned char + *)c + 1, + payload_size, + edid); + } else { + EDID_PRINT("[block 0x%x.. TBA]\n", block_type); + } + } + /* Unknown */ + else + EDID_PRINT("[unknown block 0x%x]\n", (int)*c); + + EDID_PRINT("\n"); + c += (*c & 0x1F) + 1; + } +} + +/* + * decode_standard_timings() + * Section 3.9.1 of EDID STD + */ +void decode_standard_timings(unsigned short st, edid_info_t *edid) +{ + struct { + int h; + int v; + } ar[] = { { + 16, 10}, { + 4, 3}, { + 5, 4}, { + 16, 9} }; + otm_hdmi_timing_t pdt; + int r; + + if (st != 0x0101) { + pdt.width = ((st & 0x00FF) + 31) * 8; + pdt.refresh = encode_refresh(((st & 0x3F00) >> 8) + 60); + + r = ((st & 0xC000) >> 14); + + /* Init flags with respect to aspect ratio */ + pdt.mode_info_flags = (r == 3) ? PD_AR_16_BY_9 : 0; + + /* TODO: Add proper logic for EDID earlier than 1.3 + * This weird line below makes sure division by zero is avoided + */ + pdt.height = + pdt.width * ar[r].v / (ar[r].h ? ar[r].h : ar[r].v); + + /* Indicate no stereo support */ + pdt.stereo_type = OTM_HDMI_STEREO_NONE; + + EDID_PRINT("[Standart timing]\n"); + add_timings(edid, &pdt, 0); + } +} + +/* + * decode_detailed_timings() + * Table 3.16 of EDID STD + */ +bool decode_detailed_timings(timing_descriptor_t *td, + otm_hdmi_timing_t *pdt) +{ + bool rc = true; + + int pixel_clock = td->pixel_clock * 10; + int h_active = ((td->h_active_blanking_hb & 0xF0) << 4) | td->h_active; + int h_blanking = + ((td->h_active_blanking_hb & 0x0F) << 8) | td->h_blanking; + int v_active = ((td->v_active_blanking_hb & 0xF0) << 4) | td->v_active; + int v_blanking = + ((td->v_active_blanking_hb & 0x0F) << 8) | td->v_blanking; + int h_sync_off = + ((td->offset_pulse_width_hb & 0xC0) << 2) | td->h_sync_offset; + int h_sync_pw = + ((td->offset_pulse_width_hb & 0x30) << 4) | td->h_sync_pulse_width; + + int v_sync_off = ((td->vs_offset_pulse_width & 0xF0) >> 4) + | (td->offset_pulse_width_hb & 0x0C); + + int v_sync_pw = ((td->offset_pulse_width_hb & 0x03) << 4) + | (td->vs_offset_pulse_width & 0x0F); + + int h_img_size = ((td->hv_image_size & 0xF0) << 4) | td->h_image_size; + int v_img_size = ((td->hv_image_size & 0x0F) << 8) | td->v_image_size; + + EDID_PRINT("[detailed timing descriptor]\n"); + +#ifndef PRINT_DETAILED_TIMINGS + EDID_PRINT(" - pixel_clock : %d KHz\n", pixel_clock); + EDID_PRINT(" - horz_active : %d pixels\n", h_active); + EDID_PRINT(" - horz_blanking : %d pixels\n", h_blanking); + EDID_PRINT(" - vert_active : %d lines\n", v_active); + EDID_PRINT(" - vert_blanking : %d lines\n", v_blanking); + EDID_PRINT(" - horz_sync_off : %d pixels\n", h_sync_off); + EDID_PRINT(" - horz_sync_pw : %d pixels\n", h_sync_pw); + EDID_PRINT(" - vert_sync_off : %d lines\n", v_sync_off); + EDID_PRINT(" - vert_sync_pw : %d lines\n", v_sync_pw); + EDID_PRINT(" - image ratio : %d : %d\n", h_img_size, v_img_size); +#endif + + pdt->width = h_active; + pdt->htotal = h_active + h_blanking; + pdt->hblank_start = h_active; + pdt->hblank_end = h_active + h_blanking; + pdt->hsync_start = h_active + h_sync_off; + pdt->hsync_end = h_active + h_sync_off + h_sync_pw; + + pdt->height = v_active; + pdt->vtotal = v_active + v_blanking; + pdt->vblank_start = v_active; + pdt->vblank_end = v_active + v_blanking; + pdt->vsync_start = v_active + v_sync_off; + pdt->vsync_end = v_active + v_sync_off + v_sync_pw; + + pdt->dclk = pixel_clock; + + /* Make sure we are seeing valid mode */ + VERIFY(pdt->htotal && pdt->vtotal && pdt->dclk, rc, false, exit); + + pdt->refresh = (pdt->dclk * 1000) / (pdt->htotal * pdt->vtotal); + + /* Convert refresh velue to enumeration entry */ + pdt->refresh = encode_refresh(pdt->refresh); + + /* Check if mode is interlaced */ + pdt->mode_info_flags |= (td->flags & 0x80) ? PD_SCAN_INTERLACE : 0; + + /* Determine picture aspect ratio */ + pdt->mode_info_flags |= + (h_img_size / 4 == v_img_size / 3) ? 0 : PD_AR_16_BY_9; + + /* Check for sync signal polarity */ + if (td->flags & 0x18) { + pdt->mode_info_flags |= (td->flags & 0x02) ? PD_HSYNC_HIGH : 0; + pdt->mode_info_flags |= (td->flags & 0x04) ? PD_VSYNC_HIGH : 0; + } + /* Indicate no stereo support */ + pdt->stereo_type = OTM_HDMI_STEREO_NONE; + +exit: + return rc; +} + +/* + * decode_generic_descriptor() + * Table 3.19. Table 3.20 of EDID STD + */ +void decode_generic_descriptor(generic_descriptor_t *gd, edid_info_t *edid) +{ + int i; + + /* Not a timing descriptor */ + if ((gd->flag_required == 0) && (gd->flag_reserved == 0) + && (gd->flag == 0)) { + switch (gd->data_type_tag) { + case 0xFF: + EDID_PRINT("[Monitor Serial Number ]\n"); + EDID_PRINT(" - %s\n", gd->payload); + break; + case 0xFE: + EDID_PRINT("[ASCII String ]\n"); + EDID_PRINT(" - %s\n", gd->payload); + break; + case 0xFD: + EDID_PRINT("[Monitor Range Limits ]\n"); + EDID_PRINT(" - ...\n"); + break; + case 0xFC: + EDID_PRINT("[Monitor Name ]\n"); + EDID_PRINT(" - %s\n", gd->payload); + for (i = 0; i < 13; i++) { + if (gd->payload[i] == '\n') + break; + else + edid->product_name[i] = gd->payload[i]; + } + break; + case 0xFB: + EDID_PRINT("[Color Data ]\n"); + break; + case 0xFA: + EDID_PRINT("[More Standard Timings ]\n"); + for (i = 0; i < 12; i += 2) { + /* TODO: Need more info on proper byte order */ + decode_standard_timings + ((gd->payload[i] << 8) | gd->payload[i + 1], + edid); + } + break; + case 0x10: + EDID_PRINT("[Dummy ]\n"); + break; + default: + EDID_PRINT("[Manufacturer/Undefined]\n"); + break; + } + } + /* Timing descriptor */ + else { + otm_hdmi_timing_t pdt; + memset(&pdt, 0, sizeof(otm_hdmi_timing_t)); + if (decode_detailed_timings((timing_descriptor_t *) gd, &pdt)) + add_timings(edid, &pdt, 0); + } +} + +#define __BASIC_AUDIO_FS (OTM_HDMI_AUDIO_FS_32_KHZ | \ + OTM_HDMI_AUDIO_FS_44_1_KHZ | \ + OTM_HDMI_AUDIO_FS_48_KHZ) + +/* + * __find_and_declare_basic_audio_support() + */ +static otm_hdmi_ret_t __find_and_declare_basic_audio_support(edid_info_t *edid) +{ + otm_hdmi_audio_cap_t *caps = edid->audio_caps; + unsigned int i = 0; + + otm_hdmi_audio_cap_t cap = { + .format = OTM_HDMI_AUDIO_FORMAT_PCM, + .max_channels = 2, + .fs = __BASIC_AUDIO_FS, + .ss_bitrate = OTM_HDMI_AUDIO_SS_16, + }; + + /* Try to find basic audio functionality among declared capabilities */ + for (i = 0; i < edid->num_caps; i++) { + if ((caps[i].format == cap.format) + && (caps[i].max_channels >= cap.max_channels) + && (caps[i].ss_bitrate & cap.ss_bitrate) + && ((caps[i].fs & cap.fs) == cap.fs)) { + goto exit; + } + } + + /* Add RLRF pair to the speaker allocation map */ + edid->speaker_map |= 0x01; + + /* Add basic audio capability to the list of capabilities */ + memcpy(&caps[edid->num_caps++], &cap, sizeof(cap)); + +exit: + return OTM_HDMI_SUCCESS; +} + +/* + * decode_extention_block_cea() + * Refer to section A.2.13 of CEA-861-C document for additional details + */ +void decode_extention_block_cea(extention_block_cea_t *eb, edid_info_t *edid) +{ + int i; + generic_descriptor_t gd; + + /* Check YCbCr444 and YCbCr422 support */ + if (eb->revision >= 2) { + edid->ycbcr444 = (eb->flags & 0x20) ? true : false; + edid->ycbcr422 = (eb->flags & 0x10) ? true : false; + } + /* + * Short descriptors section exists when: + * - offset is not 4 + * - CEA extension version is 3 + */ + if ((eb->content_offset != 4) && (eb->revision >= 3)) + decode_block_collection(eb, edid); + /* + * Detailed timing descriptors: + * - do not exist when offset is zero + * - may still not exist even when offset is non-zero; in this case + * location where they would exist is padded so make sure + * appropriate decoding routine can handle that padding correctly + */ +#define __DSCR_SIZE 18 + if (eb->content_offset != 0) { + for (i = 0; i < (128 - eb->content_offset) / __DSCR_SIZE; i++) { + /* + * Instead of using a casted pointer to descriptor, + * we explicitely copy memory content temporary + * placeholder. This way we are avoiding possible + * integer addressing problems + */ + memcpy(&gd, + (char *)eb + eb->content_offset + + __DSCR_SIZE * i, __DSCR_SIZE); + decode_generic_descriptor(&gd, edid); + } + } +#undef __DSCR_SIZE + + /* Check for basic audio support and add it to caps list if necessary */ + if ((eb->revision >= 2) && (eb->flags & 0x40)) + __find_and_declare_basic_audio_support(edid); +} + +/* + * fetch_block_map() + */ +otm_hdmi_ret_t fetch_block_map(edid_block_map_t *ebm, unsigned char *data) +{ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + read_context_t read_context = { data, 0 }; + read_context_t *rctx = &read_context; + + VERIFY(ebm != NULL, rc, OTM_HDMI_ERR_INTERNAL, exit); + VERIFY(data != NULL, rc, OTM_HDMI_ERR_INTERNAL, exit); + + /* Fill tag, map and checksum fields */ + fetch_next_field(&ebm->tag, rctx, 1); + fetch_next_field(&ebm->map, rctx, BLOCK_MAP_SIZE); + fetch_next_field(&ebm->checksum, rctx, 2); + +exit: + return rc; +} + +/* + * block_decode() + */ +otm_hdmi_ret_t block_decode(edid_info_t *edid_info, unsigned int type, + unsigned char *buffer) +{ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + extention_block_cea_t eb; + + EDID_PRINT("Decoding extension 0x%x\n", type); + + switch (type) { + case 0x02: + VERIFY(buffer[0] == 0x02, rc, OTM_HDMI_ERR_FAILED, exit); + memset(&eb, 0, sizeof(extention_block_cea_t)); + fetch_extension_block_cea(&eb, buffer); + decode_extention_block_cea(&eb, edid_info); + break; + + default: + EDID_PRINT("Extension 0x%x is not supported; Bypassing\n", + type); + break; + } + +exit: + return rc; +} + +int edid_parse_pd_timing_from_cea_block(edid_info_t *edid_info, + unsigned char *buffer, + otm_hdmi_timing_t *pdts) +{ + extention_block_cea_t eb; + int i = 0; + + if (buffer[0x0] == 0x2) { + memset(&eb, 0, sizeof(extention_block_cea_t)); + edid_info->num_timings = 0; + fetch_extension_block_cea(&eb, buffer); + decode_extention_block_cea(&eb, edid_info); + + for (i = 0; i < edid_info->num_timings; i++) { + memcpy((unsigned char *)&pdts[i], + (unsigned char *)&edid_info->timings[i], + sizeof(otm_hdmi_timing_t)); + } + return edid_info->num_timings; + } + return 0; +} + + +/* + * edid_parse() + */ +otm_hdmi_ret_t edid_parse(edid_info_t *edid_info, + i2c_read_t data_read, void *cd, + bool hex_dump) +{ + unsigned char buffer[SEGMENT_SIZE]; + edid_block_zero_t ebz; + edid_block_map_t ebm; + extention_block_cea_t eb; + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + int i, sp, offset; + + /* Read block zero */ + rc = data_read(cd, 0, 0, buffer, SEGMENT_SIZE); + VERIFY_QUICK(rc == OTM_HDMI_SUCCESS, exit); + print_raw_block(buffer, SEGMENT_SIZE, (bool) hex_dump); + VERIFY(checksum_valid(buffer, SEGMENT_SIZE), rc, + OTM_HDMI_ERR_FAILED, exit); + + /* Process block zero */ + memset(&ebz, 0, sizeof(edid_block_zero_t)); + fetch_block_zero(&ebz, buffer); + + VERIFY(ebz.signature == EDID_SIGNATURE, rc, OTM_HDMI_ERR_FAILED, exit); + + /* Decode general stuff */ + edid_info->manufacturer_id = ebz.manufacturer_id; + edid_info->product_code = ebz.product_code; + edid_info->product_sn = ebz.serial_number; + edid_info->product_year = ebz.manufacture_year + 1990; + edid_info->product_week = ebz.manufacture_week; + edid_info->max_horz_image_size = ebz.max_horz_image_size; + edid_info->max_vert_image_size = ebz.max_vert_image_size; + edid_info->native_idx = -1; + + /* Decode timings */ + decode_generic_descriptor((generic_descriptor_t *) &ebz.td_1, + edid_info); + decode_generic_descriptor((generic_descriptor_t *) &ebz.td_2, + edid_info); + decode_generic_descriptor((generic_descriptor_t *) &ebz.md_1, + edid_info); + decode_generic_descriptor((generic_descriptor_t *) &ebz.md_2, + edid_info); + + for (i = 0; i < EDID_STD_TIMINGS_NUM; i++) + decode_standard_timings(ebz.std_timings[i], edid_info); + + /* If there are no extentions - we are done */ + VERIFY(ebz.num_extentions != 0, rc, OTM_HDMI_SUCCESS, exit); + + /* Read next block */ + rc = data_read(cd, 0, SEGMENT_SIZE, buffer, SEGMENT_SIZE); + VERIFY_QUICK(rc == OTM_HDMI_SUCCESS, exit); + print_raw_block(buffer, SEGMENT_SIZE, (bool) hex_dump); + VERIFY(checksum_valid(buffer, SEGMENT_SIZE), rc, + OTM_HDMI_ERR_FAILED, exit); + + /* There is only 1 extention; Assume its CEA Extension [tag = 0x02] */ + if (ebz.num_extentions == 1) { + /* Process extention block */ + memset(&eb, 0, sizeof(extention_block_cea_t)); + fetch_extension_block_cea(&eb, buffer); + VERIFY(eb.tag == 0x02, rc, OTM_HDMI_SUCCESS, exit); + decode_extention_block_cea(&eb, edid_info); + } + /* There is a block map and more extentions */ + else { + /* Process block map */ + memset(&ebm, 0, sizeof(edid_block_map_t)); + fetch_block_map(&ebm, buffer); + + /* Verify we are indeed dealing with map block */ + VERIFY(ebm.tag == 0xF0, rc, OTM_HDMI_ERR_FAILED, exit); + + /* Deal with each block in the map */ + for (i = 0; (i < BLOCK_MAP_SIZE) && ebm.map[i]; i++) { + /* Compute extension block location */ + sp = (i + 2) / 2; + offset = (i % 2) ? SEGMENT_SIZE : 0; + + /* Read extension block */ + rc = data_read(cd, sp, offset, buffer, SEGMENT_SIZE); + VERIFY_QUICK(rc == OTM_HDMI_SUCCESS, exit); + print_raw_block(buffer, SEGMENT_SIZE, (bool) hex_dump); + VERIFY(checksum_valid(buffer, SEGMENT_SIZE), rc, + OTM_HDMI_ERR_FAILED, exit); + + /* Decode extension block */ + rc = block_decode(edid_info, ebm.map[i], buffer); + VERIFY_QUICK(rc == OTM_HDMI_SUCCESS, exit); + } + + goto exit; + } + +exit: + return rc; +} + +/* + * TODO LIST (in addition to small todos in the code) + * + * 1. Currently we parse ALL timings, but return only those supported by CE 3100 + * Shall we change it so it behaves like true parser and returns ALL timings? + */ diff --git a/drivers/staging/mrst/drv/otm_hdmi/pil/common/edid.h b/drivers/staging/mrst/drv/otm_hdmi/pil/common/edid.h new file mode 100644 index 0000000..45e671a --- /dev/null +++ b/drivers/staging/mrst/drv/otm_hdmi/pil/common/edid.h @@ -0,0 +1,151 @@ +/* + + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2011 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + + Intel Corporation + 2200 Mission College Blvd. + Santa Clara, CA 95054 + + BSD LICENSE + + Copyright(c) 2011 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef _EDID_H +#define _EDID_H + + +#include + +#include "otm_hdmi.h" + +#define MAX_TIMINGS 100 +#define MAX_CAPS 30 +#define SEGMENT_SIZE 128 +#define MAX_EDID_BLOCKS 5 + +/** + * Different types representing pointers to a function + */ +typedef otm_hdmi_ret_t (*i2c_read_t)(void *client_data, unsigned int sp, + unsigned int offset, void *buffer, + unsigned int size); + +typedef int (*printf_t) (const char *fmt, ...); + +/** + * Structure with parsed EDID information returned to end user + */ +typedef struct { + bool hdmi; /* HDMI or DVI device */ + unsigned int num_timings; /* Number of supported timings */ + otm_hdmi_timing_t timings[MAX_TIMINGS]; /* Supported timings */ + unsigned int order[MAX_TIMINGS]; /* VIC order of descovery */ + unsigned int num_caps; /* Number of supported audiocaps */ + otm_hdmi_audio_cap_t audio_caps[MAX_CAPS]; /* Supported audio caps + */ + unsigned int speaker_map; /* Speaker layout */ + unsigned short manufacturer_id; /* Manufacturer ID */ + unsigned short product_code; /* Product code */ + unsigned int product_sn; /* Serial number */ + unsigned int product_year; /* Year of product manufacture */ + unsigned int product_week; /* Week of product manufacture */ + unsigned char product_name[14]; /* Product name */ + bool ycbcr444; /* YCbCr444 support */ + bool ycbcr422; /* YCbCr422 support */ + unsigned int spa; /* CEC source physical address */ + bool dc_30; /* 30 bit Deep Color support */ + bool dc_36; /* 36 bit Deep Color support */ + bool dc_48; /* 48 bit Deep Color support */ + bool dc_y444; /* YCbCr444 support with DC */ + bool xvycc601; /* xvYCC BT601 Colorimetry */ + bool xvycc709; /* xvYCC BT709 Colorimetry */ + bool supports_ai; /* Aux audio info support */ + unsigned int max_tmds_clock; + bool latency_present; + bool latency_int_present; + bool hdmi_video_present; + int latency_video; + int latency_audio; + int latency_video_interlaced; + int latency_audio_interlaced; + bool enabled_3d; + bool supports_60Hz; + bool supports_50Hz; + unsigned char max_horz_image_size; + unsigned char max_vert_image_size; + int native_idx; + bool rgb_quant_selectable; /*rgb quant mode selectable */ + bool ycc_quant_selectable; /*ycc quant mode selectable */ + + const otm_hdmi_timing_t **ref_timings; /* INPUT: reference timings + table */ + unsigned int num_ref_timings; /* INPUT: size of ref timings table */ +} edid_info_t; + +otm_hdmi_ret_t edid_parse(edid_info_t *edid_info, i2c_read_t data_read, + void *cd, bool hex_dump); + +void print_pd_timing(const otm_hdmi_timing_t *pdt, unsigned int order, + printf_t print); +void print_audio_capability(otm_hdmi_audio_cap_t *adb, printf_t print); +void print_speaker_layout(unsigned int layout, printf_t print); +void print_raw_block(unsigned char *buffer, int size, bool print); + +int find_timing(const otm_hdmi_timing_t *set, int size, + const otm_hdmi_timing_t *e); + +int edid_parse_pd_timing_from_cea_block(edid_info_t *edid_info, + unsigned char *buffer, + otm_hdmi_timing_t *pdts); +#endif /* _EDID_H */ diff --git a/drivers/staging/mrst/drv/otm_hdmi/pil/common/edid_internal.h b/drivers/staging/mrst/drv/otm_hdmi/pil/common/edid_internal.h new file mode 100644 index 0000000..ac30733 --- /dev/null +++ b/drivers/staging/mrst/drv/otm_hdmi/pil/common/edid_internal.h @@ -0,0 +1,180 @@ +/* + + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2011 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + + Intel Corporation + 2200 Mission College Blvd. + Santa Clara, CA 95054 + + BSD LICENSE + + Copyright(c) 2011 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef _EDID_INTERNAL_H +#define _EDID_INTERNAL_H + +#include "edid.h" + +#define EDID_STD_TIMINGS_NUM 8 +#define BLOCK_MAP_SIZE 126 + +/* + * Structure representing timing descriptor in EDID native format + * See Table 3.16 of EDID STD and Table 50 of CEA-861-C documents for details + * Order of fields MUST match documentation + */ +typedef struct { + unsigned short pixel_clock; + unsigned char h_active; + unsigned char h_blanking; + unsigned char h_active_blanking_hb; + unsigned char v_active; + unsigned char v_blanking; + unsigned char v_active_blanking_hb; + unsigned char h_sync_offset; + unsigned char h_sync_pulse_width; + unsigned char vs_offset_pulse_width; + unsigned char offset_pulse_width_hb; + unsigned char h_image_size; + unsigned char v_image_size; + unsigned char hv_image_size; + unsigned char h_border; + unsigned char v_border; + unsigned char flags; +} timing_descriptor_t; + +/* + * Structure representing any 18 bytes descriptor + * See Table 3.19 and 3.20 of EDID STD for details + * Order of fields MUST match documentation + */ +typedef struct { + unsigned short flag_required; + unsigned char flag_reserved; + unsigned char data_type_tag; + unsigned char flag; + unsigned char payload[13]; +} generic_descriptor_t; + +/* + * Structure representing EDID CEA extention block + * See Table 56, Table 26 and section A.2.13 of CEA-861-C for details + */ +typedef struct { + unsigned char tag; + unsigned char revision; + unsigned char content_offset; + unsigned char flags; + unsigned char data[124]; +} extention_block_cea_t; + +/* + * EDID Block 0 + */ +typedef struct { + unsigned long long signature; + unsigned short manufacturer_id; + unsigned short product_code; + unsigned int serial_number; + unsigned char manufacture_week; + unsigned char manufacture_year; + unsigned char version; + unsigned char revision; + unsigned char video_input_definition; + unsigned char max_horz_image_size; + unsigned char max_vert_image_size; + unsigned char gamma; + unsigned char feature_support; + unsigned char rg_lowbits; + unsigned char bw_lowbits; + unsigned char red_x; + unsigned char red_y; + unsigned char green_x; + unsigned char green_y; + unsigned char blue_x; + unsigned char blue_y; + unsigned char white_x; + unsigned char white_y; + unsigned char est_timing_1; + unsigned char est_timing_2; + unsigned char est_timing_3; + unsigned short std_timings[EDID_STD_TIMINGS_NUM]; + unsigned char td_1[sizeof(generic_descriptor_t)]; + unsigned char td_2[sizeof(generic_descriptor_t)]; + unsigned char md_1[sizeof(generic_descriptor_t)]; + unsigned char md_2[sizeof(generic_descriptor_t)]; + unsigned char num_extentions; +} edid_block_zero_t; + +/* + * EDID block map + */ +typedef struct { + unsigned char tag; + unsigned char map[BLOCK_MAP_SIZE]; + unsigned char checksum; +} edid_block_map_t; + +/* + * Detailed printing routines prototypes + */ +void print_monitor_descriptor_undecoded(generic_descriptor_t *md, + printf_t print); + +void print_timing_descriptor_undecoded(timing_descriptor_t *td, + printf_t print); + +void print_block_zero_undecoded(edid_block_zero_t *ebz, printf_t print); + +#endif /* _EDID_INTERNAL_H */ diff --git a/drivers/staging/mrst/drv/otm_hdmi/pil/common/edid_print.c b/drivers/staging/mrst/drv/otm_hdmi/pil/common/edid_print.c new file mode 100644 index 0000000..523cf1f --- /dev/null +++ b/drivers/staging/mrst/drv/otm_hdmi/pil/common/edid_print.c @@ -0,0 +1,358 @@ +/* + + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2011 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + + Intel Corporation + 2200 Mission College Blvd. + Santa Clara, CA 95054 + + BSD LICENSE + + Copyright(c) 2011 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include +#include "edid_internal.h" + +/* __fake_printf */ +static int __fake_printf(const char *fmt, ...) +{ + return 0; +} + +/* Convert the refresh rate enum to a string for printing */ +static char *_refresh_string(otm_hdmi_refresh_t r) +{ + char *ret; + + switch (r) { + case OTM_HDMI_REFRESH_23_98: + ret = "23.98"; + break; + case OTM_HDMI_REFRESH_24: + ret = "24"; + break; + case OTM_HDMI_REFRESH_25: + ret = "25"; + break; + case OTM_HDMI_REFRESH_29_97: + ret = "29.97"; + break; + case OTM_HDMI_REFRESH_30: + ret = "30"; + break; + case OTM_HDMI_REFRESH_50: + ret = "50"; + break; + case OTM_HDMI_REFRESH_47_96: + ret = "47.96"; + break; + case OTM_HDMI_REFRESH_48: + ret = "48"; + break; + case OTM_HDMI_REFRESH_59_94: + ret = "59.94"; + break; + case OTM_HDMI_REFRESH_60: + ret = "60"; + break; + case OTM_HDMI_REFRESH_NONE: + ret = "0"; + break; + default: + ret = ""; + break; + }; + + return ret; +} + +/* Convert stereo enum to a string for printing */ +static char *_stereo_string(otm_hdmi_stereo_t stereo_type) +{ + char *ret; + + switch (stereo_type) { + case OTM_HDMI_STEREO_NONE: + ret = "Stereo None"; + break; + case OTM_HDMI_STEREO_FRAME_PACKING_2: + ret = "Stereo Frame Packing 2"; + break; + case OTM_HDMI_STEREO_FRAME_PACKING: + ret = "Stereo Frame Packing"; + break; + case OTM_HDMI_STEREO_SIDE_BY_SIDE_HALF_2: + ret = "Stereo Side by Side Half 2"; + break; + case OTM_HDMI_STEREO_TOP_BOTTOM_HALF_2: + ret = "Stereo Top Bottom Half 2"; + break; + case OTM_HDMI_STEREO_FRAME_SEQUENTIAL: + ret = "Stereo Frame Sequential"; + break; + default: + ret = ""; + break; + }; + + return ret; +} + +/* print_pd_timing */ +void print_pd_timing(const otm_hdmi_timing_t *t, + unsigned int order, printf_t print) +{ + printf_t p = print ? print : __fake_printf; + + p(" - %dx%d @ %s", t->width, t->height, _refresh_string(t->refresh)); + p("%s", (t->mode_info_flags & PD_SCAN_INTERLACE) ? "i" : "p"); + p(" [%s]", (t->mode_info_flags & PD_AR_16_BY_9) ? "16:9" : "4:3"); + p(" [%d]", order); + p(" [%s]\n", _stereo_string(t->stereo_type)); + +#ifdef PRINT_DETAILED_TIMINGS + p(" - htotal : %d\n", t->htotal); + p(" - hblank_start: %d\n", t->hblank_start); + p(" - hblank_end : %d\n", t->hblank_end); + p(" - hsync_start : %d\n", t->hsync_start); + p(" - hsync_end : %d\n", t->hsync_end); + p(" - vtotal : %d\n", t->vtotal); + p(" - vblank_start: %d\n", t->vblank_start); + p(" - vblank_end : %d\n", t->vblank_end); + p(" - vsync_start : %d\n", t->vsync_start); + p(" - vsync_end : %d\n", t->vsync_end); + p(" - clock : %dMhz\n", (int)(t->dclk / 1000)); +#endif +} + +/* Convert audio format enum to a string for printing */ +static char *_audio_format(otm_hdmi_audio_fmt_t fmt) +{ + char *s; + + switch (fmt) { + case OTM_HDMI_AUDIO_FORMAT_PCM: + s = "PCM"; + break; + case OTM_HDMI_AUDIO_FORMAT_AC3: + s = "AC3"; + break; + case OTM_HDMI_AUDIO_FORMAT_MPEG1: + s = "MPEG1"; + break; + case OTM_HDMI_AUDIO_FORMAT_MP3: + s = "MP3"; + break; + case OTM_HDMI_AUDIO_FORMAT_MPEG2: + s = "MPEG2"; + break; + case OTM_HDMI_AUDIO_FORMAT_AAC: + s = "AAC"; + break; + case OTM_HDMI_AUDIO_FORMAT_DTS: + s = "DTS"; + break; + case OTM_HDMI_AUDIO_FORMAT_ATRAC: + s = "ATRAC"; + break; + case OTM_HDMI_AUDIO_FORMAT_OBA: + s = "One Bit Audio"; + break; + case OTM_HDMI_AUDIO_FORMAT_DDP: + s = "Dolby Digital +"; + break; + case OTM_HDMI_AUDIO_FORMAT_DTSHD: + s = "DTSHD"; + break; + case OTM_HDMI_AUDIO_FORMAT_MLP: + s = "MLP"; + break; + case OTM_HDMI_AUDIO_FORMAT_DST: + s = "DST"; + break; + case OTM_HDMI_AUDIO_FORMAT_WMA_PRO: + s = "WMA Pro"; + break; + default: + s = "< unknown format >"; + break; + }; + + return s; +} + +/* Convert sampling rate enum to a string for printing */ +static char *_sampling_rate(otm_hdmi_audio_fs_t fs) +{ + char *s; + + switch (fs) { + case OTM_HDMI_AUDIO_FS_32_KHZ: + s = "32"; + break; + case OTM_HDMI_AUDIO_FS_44_1_KHZ: + s = "44.1"; + break; + case OTM_HDMI_AUDIO_FS_48_KHZ: + s = "48"; + break; + case OTM_HDMI_AUDIO_FS_88_2_KHZ: + s = "88.2"; + break; + case OTM_HDMI_AUDIO_FS_96_KHZ: + s = "96"; + break; + case OTM_HDMI_AUDIO_FS_176_4_KHZ: + s = "176.4"; + break; + case OTM_HDMI_AUDIO_FS_192_KHZ: + s = "192"; + break; + + default: + s = "< unknown sampling rate >"; + break; + } + + return s; +} + +/* print_audio_capability() */ +void print_audio_capability(otm_hdmi_audio_cap_t *cap, printf_t print) +{ + printf_t p = print ? print : __fake_printf; + int i; + + p(" - Format: %s; Max channels: %d; Sampling rates, KHz:", + _audio_format(cap->format), cap->max_channels); + + for (i = 0; i < 7; i++) + p(" %s", (cap->fs & (1 << i)) ? _sampling_rate(1 << i) : ""); + p("\n"); +} + +/* Convert a speaker map enum to a string for printing */ +static char *_speaker_map(otm_hdmi_audio_speaker_map_t map) +{ + char *s; + + switch (map) { + case OTM_HDMI_AUDIO_SPEAKER_MAP_FLFR: + s = "FL/FR"; + break; + case OTM_HDMI_AUDIO_SPEAKER_MAP_LFE: + s = "LFE"; + break; + case OTM_HDMI_AUDIO_SPEAKER_MAP_FC: + s = "FC"; + break; + case OTM_HDMI_AUDIO_SPEAKER_MAP_RLRR: + s = "RL/RR"; + break; + case OTM_HDMI_AUDIO_SPEAKER_MAP_RC: + s = "RC"; + break; + case OTM_HDMI_AUDIO_SPEAKER_MAP_FLCFRC: + s = "FLC/FRC"; + break; + case OTM_HDMI_AUDIO_SPEAKER_MAP_RLCRRC: + s = "RLC/RRC"; + break; + case OTM_HDMI_AUDIO_SPEAKER_MAP_FLWFRW: + s = "FLW/FRW"; + break; + case OTM_HDMI_AUDIO_SPEAKER_MAP_FLHFRH: + s = "FLH/FRH"; + break; + case OTM_HDMI_AUDIO_SPEAKER_MAP_TC: + s = "TC"; + break; + case OTM_HDMI_AUDIO_SPEAKER_MAP_FCH: + s = "FCH"; + break; + + default: + s = "< unknown allocation >\n"; + break; + } + + return s; +} + +/* print_speaker_layout() */ +void print_speaker_layout(unsigned int layout, printf_t print) +{ + printf_t p = print ? print : __fake_printf; + int i; + + p(" - Speaker layout map:"); + for (i = 0; i < 11; i++) + p(" %s", (layout & (1 << i)) ? _speaker_map(1 << i) : ""); + p("\n"); +} + +/* print_raw_block() */ +void print_raw_block(unsigned char *buffer, int size, bool print) +{ + int i; + + if (!print) + return; + + for (i = 0; i < size; i++) { + pr_debug("%s", (i % 0x10) ? "" : "\n"); + pr_debug("%02X ", buffer[i]); + } + pr_debug("\n"); +} diff --git a/drivers/staging/mrst/drv/otm_hdmi/pil/common/hdcp.c b/drivers/staging/mrst/drv/otm_hdmi/pil/common/hdcp.c new file mode 100644 index 0000000..eae4761 --- /dev/null +++ b/drivers/staging/mrst/drv/otm_hdmi/pil/common/hdcp.c @@ -0,0 +1,859 @@ +/* + + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2011 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + + Intel Corporation + 2200 Mission College Blvd. + Santa Clara, CA 95054 + + BSD LICENSE + + Copyright(c) 2011 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + + +#include +#include +#include +#include +#include +#include "hdcp_rx_defs.h" +#include "otm_hdmi.h" +#include "otm_hdmi_types.h" +#include "ipil_hdcp_api.h" + +#define OTM_HDCP_DEBUG_MODULE + +#ifdef OTM_HDCP_DEBUG_MODULE +bool module_disable_hdcp = false; +EXPORT_SYMBOL_GPL(module_disable_hdcp); +bool module_force_ri_mismatch = false; +EXPORT_SYMBOL_GPL(module_force_ri_mismatch); +#endif + +enum { + HDCP_ENABLE = 1, + HDCP_RESET, + HDCP_RI_CHECK, + HDCP_REPEATER_CHECK, + HDCP_REPEATER_WDT_EXPIRED, + HDCP_SET_POWER_SAVE_STATUS, + HDCP_SET_HPD_STATUS, + HDCP_SET_DPMS_STATUS +} hdcp_task_msg_en; + +struct hdcp_wq_struct_t { + struct delayed_work dwork;/* TODO: Needs Cosai Struct */ + int msg; + void *msg_data; +}; + +/* = = = = = = = = = = = = = = = = == = = = = = = = = = = = = = = = = = = = = */ +/*! \brief Our local context. + */ +struct hdcp_context_t { + int can_authenticate; + /*!< indicates HDCP Authentication currently allowed + */ + bool is_required; + bool is_enabled; + bool suspend; + bool hpd; + bool display_power_on; + bool auto_retry; + bool wdt_expired; + + unsigned int current_srm_ver; + /*!< currently used SRM version (if vrl is not null) + */ + uint64_t *vrl; + /*!< pointer to our VRL, formatted as array of KSVs + * as hdcp__u64_t's + */ + unsigned int vrl_count; + /*!< total number of KSVs in our VRL */ + int (*ddc_read_write)(bool, uint8_t, uint8_t, uint8_t *, int); + /*!< Pointer to callback function for DDC Read Write */ + struct workqueue_struct *hdcp_wq; +}; + +/* Global instance of local context */ +static struct hdcp_context_t *hdcp_context; + +/* HDCP Main Event Handler */ +static void hdcp_task_event_handler(struct work_struct *work); + +static bool wq_send_message_delayed(int msg, + void *msg_data, + unsigned long delay) +{ + struct hdcp_wq_struct_t *hwq = NULL; + hwq = kmalloc(sizeof(struct hdcp_wq_struct_t), GFP_KERNEL); + if (hwq == NULL) + return false; + hwq->msg = msg; + hwq->msg_data = msg_data; + /* TODO: Needs Cosai Calls */ + INIT_DELAYED_WORK(&hwq->dwork, hdcp_task_event_handler); + /* TODO: Needs Cosai Calls */ + if (queue_delayed_work(hdcp_context->hdcp_wq, &hwq->dwork, + (unsigned long)(msecs_to_jiffies(delay))) != 0) + return true; + else + pr_debug("hdcp: failed to add messge to delayed wq\n"); + return false; +} + +static bool wq_send_message(int msg, void *msg_data) +{ + return wq_send_message_delayed(msg, msg_data, 0); +} + +static bool hdcp_enable_condition_ready(void) +{ + if (hdcp_context != NULL && + hdcp_context->can_authenticate == true && + hdcp_context->is_required == true && + hdcp_context->suspend == false && + hdcp_context->hpd == true && + hdcp_context->display_power_on == true) + return true; + + return false; +} + +static int hdcp_ddc_read(uint8_t offset, uint8_t *buffer, int size) +{ + if (hdcp_enable_condition_ready() == true) + return hdcp_context->ddc_read_write(true, + HDCP_PRIMARY_I2C_ADDR, offset, buffer, size); + return false; +} + +static int hdcp_ddc_write(uint8_t offset, uint8_t *buffer, int size) +{ + if (hdcp_enable_condition_ready() == true) + return hdcp_context->ddc_read_write(false, + HDCP_PRIMARY_I2C_ADDR, offset, buffer, size); + return false; +} + +static uint64_t hdcp_ksv_64val_conv(uint8_t *ksv, uint32_t size) +{ + int i = 0; + uint64_t ksv64 = 0; + if (ksv != NULL && size == HDCP_KSV_SIZE) { + for (i = 0; i < 5; i++) + ksv64 |= (ksv[i] << (i*8)); + } + return ksv64; +} + +static bool hdcp_validate_ksv(uint8_t *ksv, uint32_t size) +{ + int i = 0, count = 0; + uint8_t temp = 0; + uint64_t ksv64 = hdcp_ksv_64val_conv(ksv, size); + bool ret = false; + if (ksv != NULL && size == HDCP_KSV_SIZE) { + count = 0; + for (i = 0; i < 5; i++) { + temp = ksv[i]; + while (temp) { + temp &= (temp-1); + count++; + } + } + if (count == HDCP_KSV_HAMMING_WT) + ret = true; + } + if (ret) { + /* SRM Check ? */ + if (hdcp_context->vrl != NULL) { + const uint64_t *vrl = hdcp_context->vrl; + for (i = 0; i < hdcp_context->vrl_count; i++, vrl++) { + if (ksv64 == *vrl) + return true; + } + } + } + return ret; +} + +static bool hdcp_get_aksv(uint8_t *aksv, uint32_t size) +{ + bool ret = false; + if (ipil_hdcp_get_aksv(aksv, HDCP_KSV_SIZE) == true) { + if (hdcp_validate_ksv(aksv, size) == true) + ret = true; + } + return ret; +} + +static bool hdcp_read_bksv(uint8_t *bksv, uint32_t size) +{ + bool ret = false; + if (bksv != NULL && size == HDCP_KSV_SIZE) { + if (hdcp_ddc_read(HDCP_RX_BKSV_ADDR, + bksv, HDCP_KSV_SIZE) == true) { + if (hdcp_validate_ksv(bksv, size) == true) + ret = true; + } + } + return ret; +} + +static bool hdcp_read_bcaps(uint8_t *bcaps) +{ + bool ret = false; + if (bcaps != NULL) { + if (hdcp_ddc_read(HDCP_RX_BCAPS_ADDR, + bcaps, HDCP_RX_BCAPS_SIZE) == true) + ret = true; + } + return ret; +} + +static bool hdcp_read_bstatus(uint16_t *bstatus) +{ + bool ret = false; + if (bstatus != NULL) { + if (hdcp_ddc_read(HDCP_RX_BSTATUS_ADDR, + (uint8_t *)bstatus, HDCP_RX_BSTATUS_SIZE) == true) + ret = true; + } + return ret; +} + +static bool hdcp_read_rx_ri(uint16_t *rx_ri) +{ + bool ret = false; + if (rx_ri != NULL) { + if (hdcp_ddc_read(HDCP_RX_RI_ADDR, + (uint8_t *)rx_ri, HDCP_RI_SIZE) == true) + ret = true; + } + return ret; +} + +static bool hdcp_read_rx_r0(uint16_t *rx_r0) +{ + return hdcp_read_rx_ri(rx_r0); +} + +static bool hdcp_stage3_ri_check(void) +{ + uint16_t rx_ri = 0; + + if (hdcp_enable_condition_ready() == false || + hdcp_context->is_enabled == false) + return false; + +#ifdef OTM_HDCP_DEBUG_MODULE + if (module_force_ri_mismatch) { + pr_debug("hdcp: force Ri mismatch\n"); + module_force_ri_mismatch = false; + return false; + } +#endif + + if (hdcp_read_rx_ri(&rx_ri) == true) + if (ipil_hdcp_does_ri_match(rx_ri) == true) + /* pr_debug("hdcp: Ri Matches %04x\n", rx_ri);*/ + return true; + + pr_debug("hdcp: error!!! Ri check failed %x\n", rx_ri); + return false; +} + +static bool hdcp_send_an_aksv(uint8_t *an, uint8_t an_size, + uint8_t *aksv, uint8_t aksv_size) +{ + bool ret = false; + if (an != NULL && an_size == HDCP_AN_SIZE && + aksv != NULL && aksv_size == HDCP_KSV_SIZE) { + if (hdcp_ddc_write(HDCP_RX_AN_ADDR, an, HDCP_AN_SIZE) == + true) { + if (hdcp_ddc_write(HDCP_RX_AKSV_ADDR, aksv, + HDCP_KSV_SIZE) == true) + ret = true; + } + } + return ret; +} + +static void hdcp_reset(void) +{ + pr_debug("hdcp: reset\n"); + + /* TODO */ + /* Stop Video if HDCP is still required */ + /* if (hdcp_context->is_required) */ + + /* Stop HDCP */ + ipil_hdcp_disable(); + + hdcp_context->is_enabled = false; +} + +static bool hdcp_rep_check(void) +{ + int msg = HDCP_REPEATER_CHECK; + return wq_send_message(msg, NULL); +} + +static bool hdcp_rep_watch_dog(void) +{ + int msg = HDCP_REPEATER_WDT_EXPIRED; + return wq_send_message_delayed(msg, NULL, 5000); +} + +static bool hdcp_initiate_rep_auth(void) +{ + pr_debug("hdcp: initiating repeater check\n"); + hdcp_context->wdt_expired = false; + if (hdcp_rep_check() == true) { + if (hdcp_rep_watch_dog() == true) + return true; + else + pr_debug("hdcp: failed to start repeater wdt\n"); + } else + pr_debug("hdcp: failed to start repeater check\n"); + return false; +} + +static bool hdcp_stage3_schedule_ri_check(void) +{ + int msg = HDCP_RI_CHECK; + return wq_send_message_delayed(msg, NULL, 2500); +} + +static int hdcp_stage1_authentication(bool *is_repeater) +{ + uint8_t bksv[HDCP_KSV_SIZE], aksv[HDCP_KSV_SIZE], an[HDCP_AN_SIZE]; + struct hdcp_rx_bstatus_t bstatus; + struct hdcp_rx_bcaps_t bcaps; + uint8_t retry = 0; + uint16_t rx_r0 = 0; + + /* Read BKSV */ + if (hdcp_read_bksv(bksv, HDCP_KSV_SIZE) == false) + return false; + pr_debug("hdcp: bksv: %02x%02x%02x%02x%02x\n", + bksv[0], bksv[1], bksv[2], bksv[3], bksv[4]); + + /* Read An AKSV */ + if (ipil_hdcp_get_an(an, HDCP_AN_SIZE) == false) + return false; + pr_debug("hdcp: an: %02x%02x%02x%02x%02x%02x%02x%02x\n", + an[0], an[1], an[2], an[3], an[4], an[5], an[6], an[7]); + + if (hdcp_get_aksv(aksv, HDCP_KSV_SIZE) == false) + return false; + pr_debug("hdcp: aksv: %02x%02x%02x%02x%02x\n", + aksv[0], aksv[1], aksv[2], aksv[3], aksv[4]); + + /* Write An AKSV to Downstream Rx */ + if (hdcp_send_an_aksv(an, HDCP_AN_SIZE, aksv, HDCP_KSV_SIZE) + == false) + return false; + pr_debug("hdcp: sent an aksv\n"); + + /* Read BCAPS & BKSV */ + if (hdcp_read_bksv(bksv, HDCP_KSV_SIZE) == false) + return false; + pr_debug("hdcp: bksv: %02x%02x%02x%02x%02x\n", + bksv[0], bksv[1], bksv[2], bksv[3], bksv[4]); + + if (hdcp_read_bcaps(&bcaps.value) == false) + return false; + pr_debug("hdcp: bcaps: %x\n", bcaps.value); + + /* Read BSTATUS */ + if (hdcp_read_bstatus(&bstatus.value) == false) + return false; + pr_debug("hdcp: bstatus: %04x\n", bstatus.value); + + /* Update repeater present status */ + *is_repeater = bcaps.is_repeater; + + /* Set Repeater Bit */ + if (ipil_hdcp_set_repeater(bcaps.is_repeater) == false) + return false; + + /* Write BKSV to Self */ + if (ipil_hdcp_set_bksv(bksv) == false) + return false; + + pr_debug("hdcp: set repeater & bksv\n"); + + /* Start First Stage of Authenticatioin */ + if (ipil_hdcp_start_authentication() == false) + return false; + + pr_debug("hdcp: auth started\n"); + + /* Wait for 100ms */ + msleep_interruptible(100); + + /* Check if R0 Ready */ + retry = 20; + do { + if (ipil_hdcp_is_r0_ready() == true) + break; + msleep_interruptible(5); + retry--; + } while (retry); + + if (retry == 0 && ipil_hdcp_is_r0_ready() == false) + return false; + + pr_debug("hdcp: R0 ready\n"); + + /* Read Ro' from Receiver */ + if (hdcp_read_rx_r0(&rx_r0) == false) + return false; + pr_debug("hdcp: rx_r0 = %04x\n", rx_r0); + + /* Check if R0 Matches */ + if (ipil_hdcp_does_ri_match(rx_r0) == false) + return false; + pr_debug("hdcp: R0 matched\n"); + + /* Enable Encryption & Check status */ + if (ipil_hdcp_enable_encryption() == false) + return false; + pr_debug("hdcp: encryption enabled\n"); + + hdcp_context->is_enabled = true; + + return true; +} + +static int hdcp_stage2_repeater_authentication(void) +{ + /* TODO: Repeater Authentication */ + if (hdcp_enable_condition_ready() == false || + hdcp_context->is_enabled == false || + hdcp_context->wdt_expired == false) + return false; + + /* check validity of repeater depth & device count */ + /* check if fifo ready */ + /* read ksv list */ + /* verify SHA1 */ + /* validate KSV's */ + return true; +} + +static bool hdcp_start(void) +{ + bool is_repeater = false; + + pr_debug("hdcp: start\n"); + + /* Check HDCP Status */ + if (ipil_hdcp_is_ready() == false) + return false; + + if (hdcp_stage1_authentication(&is_repeater) == false) + return false; + + pr_debug("hdcp: initial authentication completed, repeater:%d\n", + is_repeater); + + /* Branch Repeater Mode Authentication */ + if (is_repeater == true) + if (hdcp_initiate_rep_auth() == false) + return false; + + /* Branch Periodic Ri Check */ + pr_debug("hdcp: starting periodic Ri check\n"); + if (hdcp_stage3_schedule_ri_check() == false) + return false; + + return true; +} + +static void hdcp_retry_enable(void) +{ + int msg = HDCP_ENABLE; + if (hdcp_enable_condition_ready() == true && + hdcp_context->is_enabled == false && + hdcp_context->auto_retry == true) { + wq_send_message_delayed(msg, NULL, 30); + pr_debug("hdcp: retry enable\n"); + } +} + +static void hdcp_task_event_handler(struct work_struct *work) +{ + struct delayed_work *delayed_work = to_delayed_work(work); + struct hdcp_wq_struct_t *hwq = container_of(delayed_work, + struct hdcp_wq_struct_t, + dwork); + int msg = 0; + void *msg_data = NULL; + bool reset_hdcp = false; + + if (hwq != NULL) { + msg = hwq->msg; + msg_data = hwq->msg_data; + } + + if (hdcp_context == NULL || hwq == NULL) + goto EXIT_HDCP_HANDLER; + + switch (msg) { + case HDCP_ENABLE: + if (hdcp_enable_condition_ready() == true && + hdcp_context->is_enabled == false && + hdcp_start() == false) { + reset_hdcp = true; + pr_debug("hdcp: failed to start hdcp\n"); + } + break; + + case HDCP_RI_CHECK: + /*pr_debug("hdcp: RI CHECK\n");*/ + if (hdcp_stage3_ri_check() == false || + hdcp_stage3_schedule_ri_check() == false) + reset_hdcp = true; + break; + + case HDCP_REPEATER_CHECK: + pr_debug("hdcp: repeater check\n"); + if (hdcp_stage2_repeater_authentication() == false) + reset_hdcp = true; + break; + + case HDCP_REPEATER_WDT_EXPIRED: + /* TODO */ + hdcp_context->wdt_expired = true; + pr_debug("hdcp: repeater wdt expired\n"); + break; + + case HDCP_RESET: + hdcp_reset(); + break; + + case HDCP_SET_POWER_SAVE_STATUS:/* handle suspend resume */ + if (msg_data != NULL) { + hdcp_context->suspend = *((bool *)msg_data); + pr_debug("hdcp: suspend = %d\n", + hdcp_context->suspend); + if (hdcp_context->suspend == true) { + if (hdcp_context->is_enabled == true) + reset_hdcp = true; + } + } + break; + + case HDCP_SET_HPD_STATUS:/* handle hpd status */ + if (msg_data != NULL) { + hdcp_context->hpd = *((bool *)msg_data); + pr_debug("hdcp: hpd = %d\n", + hdcp_context->hpd); + if (hdcp_context->hpd == false) + reset_hdcp = true; + } + break; + + case HDCP_SET_DPMS_STATUS:/* handle display_power_on status */ + if (msg_data != NULL) { + hdcp_context->display_power_on = + *((bool *)msg_data); + pr_debug("hdcp: display_power_on = %d\n", + hdcp_context->display_power_on); + if (hdcp_context->display_power_on == false) + reset_hdcp = true; + } + break; + + default: + break; + } + + if (reset_hdcp == true) { + msg = HDCP_RESET; + wq_send_message(msg, NULL); + } else + /* if disabled retry HDCP authentication */ + hdcp_retry_enable(); +EXIT_HDCP_HANDLER: + if (msg_data != NULL) + kfree(msg_data); + if (hwq != NULL) + kfree(hwq); + + return; +} + +/* + * Description: function to update HPD status + * + * @hpdi HPD high/low status + * + * Returns: true on success + * false on failure + */ +bool otm_hdmi_hdcp_set_hpd_state(hdmi_context_t *hdmi_context, + bool hpd) +{ + int msg = HDCP_SET_HPD_STATUS; + bool *p_hpd = NULL; + hpd = !!(hpd); + + if (hdmi_context == NULL || hdcp_context == NULL) + return false; + + if (hdcp_context->hpd != hpd) { + p_hpd = kmalloc(sizeof(bool), GFP_KERNEL); + if (p_hpd != NULL) { + *p_hpd = hpd; + return wq_send_message(msg, (void *)p_hpd); + } else + pr_debug("hdcp: %s failed to alloc mem\n", __func__); + } + + return false; +} + +/* + * Description: function to update power save (suspend/resume) status + * + * @suspend suspend/resume status + * + * Returns: true on success + * false on failure + */ +bool otm_hdmi_hdcp_set_power_save(hdmi_context_t *hdmi_context, + bool suspend) +{ + int msg = HDCP_SET_POWER_SAVE_STATUS; + bool *p_suspend = NULL; + suspend = !!(suspend); + + if (hdmi_context == NULL || hdcp_context == NULL) + return false; + + if (hdcp_context->suspend != suspend) { + p_suspend = kmalloc(sizeof(bool), GFP_KERNEL); + if (p_suspend != NULL) { + *p_suspend = suspend; + return wq_send_message(msg, (void *)p_suspend); + } else + pr_debug("hdcp: %s failed to alloc mem\n", __func__); + if (suspend == true) + /* Cleanup WorkQueue */ + /* TODO: Needs Cosai Calls */ + flush_workqueue(hdcp_context->hdcp_wq); + } + + return false; +} + +/* + * Description: function to update display_power_on status + * + * @display_power_on display power on/off status + * + * Returns: true on success + * false on failure + */ +bool otm_hdmi_hdcp_set_dpms(hdmi_context_t *hdmi_context, + bool display_power_on) +{ + int msg = HDCP_SET_DPMS_STATUS; + bool *p_display_power_on = NULL; + display_power_on = !!(display_power_on); + + if (hdmi_context == NULL || hdcp_context == NULL) + return false; + + if (hdcp_context->display_power_on != display_power_on) { + p_display_power_on = kmalloc(sizeof(bool), GFP_KERNEL); + if (p_display_power_on != NULL) { + *p_display_power_on = display_power_on; + return wq_send_message(msg, (void *)p_display_power_on); + } else + pr_debug("hdcp: %s failed to alloc mem\n", __func__); + if (display_power_on == false) + /* Cleanup WorkQueue */ + /* TODO: Needs Cosai Calls */ + flush_workqueue(hdcp_context->hdcp_wq); + } + return false; +} + +/* + * Description: function to enable HDCP + * + * Returns: true on success + * false on failure + */ +bool otm_hdmi_hdcp_enable(hdmi_context_t *hdmi_context) +{ + int msg = HDCP_ENABLE; + + if (hdmi_context == NULL || hdcp_context == NULL) + return false; + + if (hdcp_context->is_required == true) { + pr_debug("hdcp: already enabled\n"); + return true; + } +#ifdef OTM_HDCP_DEBUG_MODULE + if (module_disable_hdcp) { + pr_debug("hdcp: disabled by module\n"); + return false; + } +#endif + hdcp_context->is_required = true; + + pr_debug("hdcp: enable\n"); + + return wq_send_message(msg, NULL); +} + +/* + * Description: function to disable HDCP + * + * Returns: true on success + * false on failure + */ +bool otm_hdmi_hdcp_disable(hdmi_context_t *hdmi_context) +{ + int msg = HDCP_RESET; + + if (hdmi_context == NULL || hdcp_context == NULL) + return false; + + if (hdcp_context->is_required == false) { + pr_debug("hdcp: already disabled\n"); + return true; + } + + wq_send_message(msg, NULL); + + /* Cleanup WorkQueue */ + /* TODO: Needs Cosai Calls */ + flush_workqueue(hdcp_context->hdcp_wq); + + hdcp_context->is_required = false; + + pr_debug("hdcp: disable\n"); + + return true; +} + +/* + * Description: hdcp init function + * + * @ddc_rd_wr: pointer to ddc read write function + * + * Returns: true on success + * false on failure + */ +bool otm_hdmi_hdcp_init(hdmi_context_t *hdmi_context, + int (*ddc_rd_wr)(bool, uint8_t, uint8_t, uint8_t *, int)) +{ + if (hdmi_context == NULL || + ddc_rd_wr == NULL || + ipil_hdcp_device_can_authenticate() == false || + hdcp_context != NULL) { + pr_debug("hdcp: init error!!! parameters\n"); + return false; + } + + hdcp_context = kmalloc(sizeof(struct hdcp_context_t), GFP_KERNEL); + hdcp_context->hdcp_wq = NULL; + + if (hdcp_context != NULL) + hdcp_context->hdcp_wq = create_workqueue("HDCP_WQ"); + + if (hdcp_context == NULL || hdcp_context->hdcp_wq == NULL) { + pr_debug("hdcp: init error!!! allocation\n"); + goto EXIT_INIT; + } + + hdcp_context->is_required = false; + hdcp_context->is_enabled = false; + hdcp_context->suspend = false; + hdcp_context->hpd = false; + hdcp_context->display_power_on = false; + hdcp_context->auto_retry = true; + hdcp_context->wdt_expired = false; + hdcp_context->can_authenticate = true; + hdcp_context->current_srm_ver = 0u; + hdcp_context->vrl = NULL; + hdcp_context->vrl_count = 0u; + + hdcp_context->ddc_read_write = ddc_rd_wr; + + if (ipil_hdcp_init() == true) { + pr_debug("hdcp: initialized\n"); + return true; + } +EXIT_INIT: + /* Cleanup and exit */ + if (hdcp_context != NULL) { + if (hdcp_context->hdcp_wq != NULL) + destroy_workqueue(hdcp_context->hdcp_wq); + kfree(hdcp_context); + hdcp_context = NULL; + } + + return false; +} + diff --git a/drivers/staging/mrst/drv/otm_hdmi/pil/common/hdmi_internal.h b/drivers/staging/mrst/drv/otm_hdmi/pil/common/hdmi_internal.h new file mode 100644 index 0000000..ecd7a7e --- /dev/null +++ b/drivers/staging/mrst/drv/otm_hdmi/pil/common/hdmi_internal.h @@ -0,0 +1,306 @@ +/* + + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2011 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + + Intel Corporation + 2200 Mission College Blvd. + Santa Clara, CA 95054 + + BSD LICENSE + + Copyright(c) 2011 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef _OTM_HDMI_INTERNAL_H +#define _OTM_HDMI_INTERNAL_H + + +#include +#include +#include + +#include "otm_hdmi_types.h" +#include "otm_hdmi_defs.h" + +#include "edid.h" +#include "hdmi_hal.h" + +/** + * Defines, shortcuts and globals + */ + +extern otm_hdmi_attribute_t + otm_hdmi_attributes_table[OTM_HDMI_MAX_SUPPORTED_ATTRIBUTES]; + +#define ATTRS otm_hdmi_attributes_table + +/* Note: this macro should **only** be used when time difference is less than + * 4s */ +#define TIME_DIFF(tv2, tv1) ((((tv2).tv_sec - (tv1).tv_sec) * 1000000) + \ + ((tv2).tv_usec - (tv1).tv_usec)) + +#define GPIO_MIN 0 +#define GPIO_MAX 28 + +#define I2C_HW_TIMEOUT TIME_MS(200) +#define I2C_SW_TIMEOUT 500 + +#define CURRENT_DMA_READ_DESCRIPTOR(ai) \ +(((hdmi_dma_descriptor_t *) (ai)->dscr_buf_addr_v)[(ai)->dscr_current_r]) + +#define NUM_ENTRIES_IN(set) (sizeof(set) / sizeof(*set)) + +#define ALL_SF (OTM_HDMI_AUDIO_FS_192_KHZ | \ + OTM_HDMI_AUDIO_FS_176_4_KHZ | \ + OTM_HDMI_AUDIO_FS_96_KHZ | \ + OTM_HDMI_AUDIO_FS_88_2_KHZ | \ + OTM_HDMI_AUDIO_FS_48_KHZ | \ + OTM_HDMI_AUDIO_FS_44_1_KHZ | \ + OTM_HDMI_AUDIO_FS_32_KHZ) + +#define ALL_SS (OTM_HDMI_AUDIO_SS_16 | \ + OTM_HDMI_AUDIO_SS_20 | \ + OTM_HDMI_AUDIO_SS_24) + +#define DECLARE_AUDIO_CAP(_fmt, _nch, _fs, _ss) \ + { .format = _fmt, .max_channels = _nch, .fs = _fs, .ss_bitrate = _ss } + +/** + * Interrupts grouped by use + */ +#define HDMI_INTERRUPTS (HDMI_INTERRUPT_I2C_BUS_ERROR | \ + HDMI_INTERRUPT_I2C_BUFFER_FULL | \ + HDMI_INTERRUPT_I2C_TRANSACTION_DONE | \ + HDMI_INTERRUPT_HDCP_KEYS_READY | \ + HDMI_INTERRUPT_HDCP_RI | \ + HDMI_INTERRUPT_HDCP_PI | \ + HDMI_INTERRUPT_HDCP_FRAME | \ + HDMI_INTERRUPT_HDCP_M0 | \ + HDMI_INTERRUPT_HDCP_R0 | \ + HDMI_INTERRUPT_AUDIO_FIFO_UNDERFLOW | \ + HDMI_INTERRUPT_DMA_SRC_COMPLETE | \ + HDMI_INTERRUPT_HOTPLUG_DETECT) /* Enable HPD */ + +/** + * Infoframe slot aliases + */ +enum { + PACKET_SLOT_AVI = 0, + PACKET_SLOT_AUDIO = 1, + PACKET_SLOT_GENERIC_0 = 2, + PACKET_SLOT_GENERIC_1 = 3, +}; + +/** + * Infoframe Transmission Frequency + */ +enum { + HDMI_DIP_SEND_ONCE = 0, + HDMI_DIP_SEND_EVERY_VSYNC = 1, + HDMI_DIP_SEND_ATLEAST_EVERY_OTHER_VSYNC = 2, +}; + +/** + * Supported packets + */ +typedef enum { + HDMI_PACKET_NULL = 0x00, + HDMI_PACKET_ACP = 0x04, + HDMI_PACKET_ISRC1 = 0x05, + HDMI_PACKET_ISRC2 = 0x06, + HDMI_PACKET_GAMUT = 0x0A, + HDMI_PACKET_VS = 0x81, + HDMI_PACKET_AVI = 0x82, + HDMI_PACKET_SPD = 0x83, +} hdmi_packet_type_t; + +/** + * Packet management info + */ +typedef struct { + otm_hdmi_packet_t packet; + bool int_use; +} packet_info_t; + +/** + * HDMI AV mute source + */ +typedef enum { + MUTE_SOURCE_HDCP = 0x01, + MUTE_SOURCE_APP = 0x02, +} mute_source_t; + +/** + * This structure represents typical "enumerator - value" pair + */ +typedef struct { + int e; + int v; +} ev_t; + +/** + * Audio setup information + */ +typedef struct { + unsigned int dscr_buf_addr; /* DMA descriptors buffer physical + address */ + void *dscr_buf_addr_v; /* DMA descriptors buffer virtual + address */ + unsigned int dscr_buf_size; /* DMA descriptors buffer size */ + unsigned int dscr_current_w; /* index of current write descriptor */ + unsigned int dscr_current_r; /* index of current read descriptor */ + bool playback; /* playback status */ + bool prebuffer; /* prebuffering status */ + + otm_hdmi_audio_fmt_t fmt; /* format */ + otm_hdmi_audio_fs_t fs; /* sampling frequency */ + unsigned int nch; /* number of channels */ + otm_hdmi_audio_ss_t ss; /* sample size */ + unsigned int map; /* speaker allocation map */ + unsigned int chst[2]; /* channel status info */ + bool hbr; /* HBR vs non-HBR transmission mode */ + otm_hdmi_audio_fs_t fs_adj; /* audio frame rate */ +} audio_info_t; + +/** + * HDMI context definition + */ +typedef struct { + hdmi_device_t dev; /* hdmi hal handle */ + void *io_address; /* address of mapped io region */ + unsigned int io_length; /* size of io region */ + + edid_info_t edid_ext; /* external EDID structure */ + edid_info_t edid_int; /* internal EDID structure */ + char edid_raw[MAX_EDID_BLOCKS*SEGMENT_SIZE]; /* raw EDID data */ + + otm_hdmi_timing_t mode; /* current mode */ + bool mode_set; /* mode switch completion indicator */ + bool hdmi; /* active transmission type */ + + void *hdcp; /* HDCP library handle */ + bool hdcp_1p1; /* HDCP 1.1 support */ + + unsigned int irq_number; /* IRQ number */ + void *thread_hpd; /* hot plug thread handler */ + struct mutex modes_sema; /* protecting modes table sharing */ + struct mutex exec_sema; /* to sync pd entries execution */ + struct mutex i2c_sema; /* i2c access synchronization semaphore */ + struct mutex hpd_sema; /* semaphore to sync hot plug sensetive data */ + struct mutex srv_sema; /* semaphore to sync service and main threads */ + struct mutex mute_sema; /* to sync av mute operations */ + + bool phy_status;/* current HW PHY status */ + bool ph2_active;/* indicates whether hdcp ph2 is in progress */ + bool ph1_cancel;/* indicates need to cancel current phase 1 */ + bool dtv; /* TX vs DTV indicator */ + bool dc; /* Deep Color enable indicator */ + bool hw_i2c; /* I2C HW acceleration indicator */ + + struct timeval ph2_start; /* start time of hdcp auth phase #2 */ + struct timeval phy_time; /* PHY enabling countdown reference */ + struct timeval hpe_time; /* last time of any hot plug event */ + struct timeval hal_timer; /* HAL polling timer */ + + packet_info_t pi_0; /* data to be sent via 1st available slot */ + packet_info_t pi_1; /* data to be sent via 2nd available slot */ + packet_info_t pi_avi; /* data to be sent via AVI slot */ + + unsigned int gpio; /* GPIO ID for I2C workaround */ + unsigned char ksvs[635]; /* list of downstream ksvs */ + bool ef_int_pend; /* encrypted frame interrupt indicator + */ + bool usr_avi; /* indicator for user-defn AVI */ + int n_modes_tx; /* number of static modes */ + int n_modes_ref; /* number of reference modes */ + + int mode_width; /* selected mode width */ + int mode_height; /* selected mode height */ + + audio_info_t audio_info; /* hdmi audio unit information */ + mute_source_t mute_source; /* current mute sources list */ + + otm_hdmi_phy_info_t phy_info; /* Current PHY electrical properties */ + otm_hdmi_hdcp_info_t hdcp_info; /* HDCP debug information */ +} hdmi_context_t; + +/* mapping structures between pil and ipil */ +typedef otm_hdmi_timing_t ipil_timings_t; + +/* scaling types */ +#define IPIL_TIMING_SCALE_NONE 0 /* Unmodified timing (display or + software can still scale) */ +#define IPIL_TIMING_SCALE_FULLSCREEN 1 /* Full screen, ignore aspect */ +#define IPIL_TIMING_SCALE_CENTER 2 /* Centered, no scaling */ +#define IPIL_TIMING_SCALE_ASPECT 3 /* Full screen, preserve aspect */ + +/* HDMI attributes setup routine */ +typedef otm_hdmi_ret_t(*pd_attr_declare_t)(otm_hdmi_attribute_t *table, + otm_hdmi_attribute_id_t id, + otm_hdmi_attribute_type_t type, + otm_hdmi_attribute_flag_t flags, + char *name, + void *value, + unsigned int min, + unsigned int max); + +otm_hdmi_ret_t otm_hdmi_declare_attributes(pd_attr_declare_t declare, + pd_attr_get_name_t get_name); + +otm_hdmi_ret_t hdmi_timing_add_twin_entries(edid_info_t *edid, + otm_hdmi_refresh_t src, + otm_hdmi_refresh_t dst); + +void hdmi_timing_edid_to_vdc(otm_hdmi_timing_t *t); + +#endif /* _OTM_HDMI_INTERNAL_H */ diff --git a/drivers/staging/mrst/drv/otm_hdmi/pil/common/hdmi_timings.h b/drivers/staging/mrst/drv/otm_hdmi/pil/common/hdmi_timings.h new file mode 100644 index 0000000..97b8d6e --- /dev/null +++ b/drivers/staging/mrst/drv/otm_hdmi/pil/common/hdmi_timings.h @@ -0,0 +1,121 @@ +/* + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2006-2011 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + Intel Corporation + 2200 Mission College Blvd. + Santa Clara, CA 97052 + + BSD LICENSE + + Copyright(c) 2006-2011 Intel Corporation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + - Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + + +#ifndef __HDMI_TIMINGS_H__ +#define __HDMI_TIMINGS_H__ + +#include "otm_hdmi.h" + +extern const otm_hdmi_timing_t MODE_640x480p5994_60; +extern const otm_hdmi_timing_t MODE_720x480p5994_60; +extern const otm_hdmi_timing_t MODE_720x480p5994_60__16by9; +extern const otm_hdmi_timing_t MODE_1280x720p5994_60; +extern const otm_hdmi_timing_t MODE_1920x1080i5994_60; +extern const otm_hdmi_timing_t MODE_1920x1080i5994_60__FP; +extern const otm_hdmi_timing_t MODE_720_1440x480i5994_60; +extern const otm_hdmi_timing_t MODE_720_1440x480i5994_60__16by9; +extern const otm_hdmi_timing_t MODE_1920x1080p5994_60; +extern const otm_hdmi_timing_t MODE_720x576p50; +extern const otm_hdmi_timing_t MODE_720x576p50__16by9; +extern const otm_hdmi_timing_t MODE_1280x720p50; +extern const otm_hdmi_timing_t MODE_1920x1080i50; +extern const otm_hdmi_timing_t MODE_1920x1080i50__FP; +extern const otm_hdmi_timing_t MODE_720_1440x576i50; +extern const otm_hdmi_timing_t MODE_720_1440x576i50__16by9; +extern const otm_hdmi_timing_t MODE_1920x1080p50; +extern const otm_hdmi_timing_t MODE_1920x1080p24; +extern const otm_hdmi_timing_t MODE_1920x1080p25; +extern const otm_hdmi_timing_t MODE_1920x1080p30; +extern const otm_hdmi_timing_t MODE_1920x1080p30__FP2; +extern const otm_hdmi_timing_t MODE_1920x1080p30__FP; +extern const otm_hdmi_timing_t MODE_1920x1080p30__TBH2; +extern const otm_hdmi_timing_t MODE_1920x1080p48; +extern const otm_hdmi_timing_t MODE_1920x1080p24__FP2; +extern const otm_hdmi_timing_t MODE_1920x1080p24__FP; +extern const otm_hdmi_timing_t MODE_1280x720p5994_60__FP2; +extern const otm_hdmi_timing_t MODE_1280x720p5994_60__FP; +extern const otm_hdmi_timing_t MODE_1280x720p50__FP2; +extern const otm_hdmi_timing_t MODE_1280x720p50__FP; +extern const otm_hdmi_timing_t MODE_1280x720p5994_60__SBSH2; +extern const otm_hdmi_timing_t MODE_1280x720p50__SBSH2; +extern const otm_hdmi_timing_t MODE_1920x1080i5994_60__SBSH2; +extern const otm_hdmi_timing_t MODE_1920x1080i50__SBSH2; +extern const otm_hdmi_timing_t MODE_1920x1080p5994_60__SBSH2; +extern const otm_hdmi_timing_t MODE_1920x1080p50__SBSH2; +extern const otm_hdmi_timing_t MODE_1920x1080p24__SBSH2; +extern const otm_hdmi_timing_t MODE_1280x720p5994_60__TBH2; +extern const otm_hdmi_timing_t MODE_1280x720p50__TBH2; +extern const otm_hdmi_timing_t MODE_1920x1080p5994_60__TBH2; +extern const otm_hdmi_timing_t MODE_1920x1080p50__TBH2; +extern const otm_hdmi_timing_t MODE_1920x1080p24__TBH2; +extern const otm_hdmi_timing_t MODE_1280x720p60__PANEL_FS; +extern const otm_hdmi_timing_t MODE_1280x720p50__PANEL_FS; +extern const otm_hdmi_timing_t MODE_1920x540p60__PANEL_FS; +extern const otm_hdmi_timing_t MODE_1920x540p50__PANEL_FS; +extern const otm_hdmi_timing_t MODE_920x1080p60__PANEL_FS; +extern const otm_hdmi_timing_t MODE_920x1080p50__PANEL_FS; +extern const otm_hdmi_timing_t MODE_1920x1080p30__PANEL_FS; +extern const otm_hdmi_timing_t MODE_1920x1080p25__PANEL_FS; +extern const otm_hdmi_timing_t MODE_1920x1080p24__PANEL_FS; +extern const otm_hdmi_timing_t MODE_1920x1080p60__PANEL; +extern const otm_hdmi_timing_t MODE_1920x1080p50__PANEL; +extern const otm_hdmi_timing_t MODE_1920x1080p48__PANEL; +#endif /* __HDMI_TIMINGS_H_ */ diff --git a/drivers/staging/mrst/drv/otm_hdmi/pil/common/infoframes.c b/drivers/staging/mrst/drv/otm_hdmi/pil/common/infoframes.c new file mode 100644 index 0000000..a6b9413 --- /dev/null +++ b/drivers/staging/mrst/drv/otm_hdmi/pil/common/infoframes.c @@ -0,0 +1,275 @@ +/* + + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2011 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + + Intel Corporation + 2200 Mission College Blvd. + Santa Clara, CA 95054 + + BSD LICENSE + + Copyright(c) 2011 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + + +#include +#include +#include "otm_hdmi.h" +#include "ipil_hdmi.h" + +#include "hdmi_internal.h" +#include "hdmi_timings.h" + + +/** + * This enumeration represents possible color space settings found in GBD + * Current driver logic assumes we only support colorimetries that can be + * advertised in EDID: xvYCC601 and xvYCC709 + */ +enum { + GBD_CS_ITU_BT709 = 0, + GBD_CS_XVYCC601 = 1, + GBD_CS_XVYCC709 = 2, + GBD_CS_XYZ = 3, + GBD_CS_RESERVED = 4, +}; + +static int __compute_check_sum(otm_hdmi_packet_t *packet) +{ + uint8_t i = 0; + uint8_t sum = 0; + + for (i = 0; i < 3; i++) + sum += packet->header[i]; + for (i = 1; i < 28; i++) + sum += packet->data[i]; + + packet->data[0] = (uint8_t)(0xFF - sum + 1); + + return (int)packet->data[0]; +} + +/** + * Note: higher level ensures that input value is valid + */ +static int __pfconvert(otm_hdmi_output_pixel_format_t pf) +{ + int rc = 0; /* init to RGB444 */ + + switch (pf) { + case OTM_HDMI_OPF_RGB444: + rc = 0; + break; + case OTM_HDMI_OPF_YUV422: + rc = 1; + break; + case OTM_HDMI_OPF_YUV444: + rc = 2; + break; + default: + rc = 0; + break; + } + + return rc; +} + +otm_hdmi_ret_t hdmi_packet_check_type(otm_hdmi_packet_t *p, + hdmi_packet_type_t type) +{ + return ((p && p->header[0] == type) ? + OTM_HDMI_SUCCESS : OTM_HDMI_ERR_FAILED); +} + +/* + * Description: set avi infoframe based on mode + * + * @context: hdmi_context + * @mode: mode requested + * + * Returns: OTM_HDMI_SUCCESS on success + * OTM_HDMI_ERR_INVAL on NULL input arguments + */ +otm_hdmi_ret_t otm_hdmi_infoframes_set_avi(void *context, + otm_hdmi_timing_t *mode) +{ + hdmi_context_t *ctx = (hdmi_context_t *)context; + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + unsigned int type = HDMI_PACKET_AVI; + unsigned int freq = HDMI_DIP_SEND_EVERY_VSYNC; + int cs = GBD_CS_XVYCC601; + otm_hdmi_packet_t avi_pkt; + unsigned int pf, vic; + bool p, ext; + otm_hdmi_par_t par = PD_ATTR_UINT(ATTRS[OTM_HDMI_ATTR_ID_PAR]); + + if (!context || !mode) { + pr_debug("\ninvalid arguments\n"); + return OTM_HDMI_ERR_NULL_ARG; + } + + /* Set header to AVI */ + avi_pkt.header[0] = 0x82; + avi_pkt.header[1] = 0x02; + avi_pkt.header[2] = 0x0D; + /* Clear payload section */ + memset(avi_pkt.data, 0, sizeof(avi_pkt.data)); + + /* RGB, Active Format Info valid, no bars */ + /* use underscan as HDMI video is composed with all + * active pixels and lines with or without border + */ + avi_pkt.data[1] = 0x12; + /* Set color component sample format */ + pf = __pfconvert(PD_ATTR_UINT + (ATTRS[OTM_HDMI_ATTR_ID_PIXEL_FORMAT_OUTPUT])); + avi_pkt.data[1] |= pf << 5; + /* Colorimetry */ + ext = PD_ATTR_BOOL(ATTRS[OTM_HDMI_ATTR_ID_COLOR_SPACE_EXT]); + avi_pkt.data[2] = + (ext ? 3 : (!pf ? 0 : ((mode->width <= 720) ? 0x01 : 0x02))) << 6; + /* Fill PAR for all supported modes + * This is required for passing compliance tests + */ + switch (mode->metadata) { + case 1: /* 640x480p60 */ + case 2: /* 720x480p60 */ + case 17:/* 720x576p50 */ + /* Fall Through */ + par = OTM_HDMI_PAR_4_3; break; + case 3: /* 720x480p60 */ + case 4: /* 1280x720p60 */ + case 16:/* 1920x1080p60 */ + case 18:/* 720x576p50 */ + case 19:/* 1280x720p50 */ + case 32:/* 1920x1080p24 */ + case 33:/* 1920x1080p25 */ + case 34:/* 1920x1080p30 */ + /* Fall Through */ + par = OTM_HDMI_PAR_16_9; break; + default: + break; + } + avi_pkt.data[2] |= par << 4; + /* Fill FAR */ + avi_pkt.data[2] |= PD_ATTR_UINT(ATTRS[OTM_HDMI_ATTR_ID_FAR]); + + /* Get extended colorimetry from slot 1 */ + if (hdmi_packet_check_type(&ctx->pi_1.packet, HDMI_PACKET_GAMUT) == + OTM_HDMI_SUCCESS) + cs = ctx->pi_1.packet.data[0] & 0x07; + /* Get extended colorimetry from slot 0 */ + else if (hdmi_packet_check_type(&ctx->pi_0.packet, HDMI_PACKET_GAMUT) == + OTM_HDMI_SUCCESS) + cs = ctx->pi_0.packet.data[0] & 0x07; + + /* Fill extended colorimetry */ + avi_pkt.data[3] = ((cs == GBD_CS_XVYCC601) ? 0 : 1) << 4; + + /* Fill quantization range */ + if (ctx->edid_int.rgb_quant_selectable + && PD_ATTR_UINT(ATTRS[OTM_HDMI_ATTR_ID_PIXEL_FORMAT_OUTPUT]) == + OTM_HDMI_OPF_RGB444) + avi_pkt.data[3] |= + PD_ATTR_BOOL(ATTRS[OTM_HDMI_ATTR_ID_OUTPUT_CLAMP]) ? + (0x01 << 2) : (0x02 << 2); + + /* Fill Video Identification Code [adjust VIC according to PAR] */ + vic = mode->metadata; +#ifdef OTM_HDMI_FIXME + /* TODO: use this when PAR value gets updated in get attributes */ + /* and reverify the VIC & PAR settings */ + avi_pkt.data[4] = vic + + ((mode->width == 720 && par == OTM_HDMI_PAR_16_9) ? 1 : 0); +#else + avi_pkt.data[4] = vic; +#endif + + /* Fill pixel repetition value: 2x for 480i and 546i */ + p = ((mode->mode_info_flags & PD_SCAN_INTERLACE) == 0); + avi_pkt.data[5] = ((mode->width == 720) && !p) ? 0x01 : 0x00; + /* Fill quantization range */ + if (ctx->edid_int.ycc_quant_selectable + && (PD_ATTR_UINT(ATTRS[OTM_HDMI_ATTR_ID_PIXEL_FORMAT_OUTPUT]) == + OTM_HDMI_OPF_YUV444 || + PD_ATTR_UINT(ATTRS[OTM_HDMI_ATTR_ID_PIXEL_FORMAT_OUTPUT]) == + OTM_HDMI_OPF_YUV422)) + avi_pkt.data[5] |= + PD_ATTR_BOOL(ATTRS[OTM_HDMI_ATTR_ID_OUTPUT_CLAMP]) ? + (0x00 << 6) : (0x01 << 6); + + /* Compute and fill checksum */ + avi_pkt.data[0] = __compute_check_sum(&avi_pkt); + + /* Enable AVI infoframe */ + rc = ipil_hdmi_enable_infoframe(&ctx->dev, type, &avi_pkt, freq); + + return rc; +} + +/* + * Description: disable all infoframes + * + * @context: hdmi_context + * + * Returns: OTM_HDMI_ERR_NULL_ARG on NULL parameters + * OTM_HDMI_SUCCESS on success +*/ +otm_hdmi_ret_t otm_hdmi_disable_all_infoframes(void *context) +{ + hdmi_context_t *ctx = (hdmi_context_t *)context; + if (!ctx) + return OTM_HDMI_ERR_NULL_ARG; + + return ipil_hdmi_disable_all_infoframes(&ctx->dev); +} diff --git a/drivers/staging/mrst/drv/otm_hdmi/pil/common/infoframes_api.h b/drivers/staging/mrst/drv/otm_hdmi/pil/common/infoframes_api.h new file mode 100644 index 0000000..8dd1a39 --- /dev/null +++ b/drivers/staging/mrst/drv/otm_hdmi/pil/common/infoframes_api.h @@ -0,0 +1,89 @@ +/* + + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2011 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + + Intel Corporation + 2200 Mission College Blvd. + Santa Clara, CA 95054 + + BSD LICENSE + + Copyright(c) 2011 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef _INFOFRAMES_API_H +#define _INFOFRAMES_API_H + +/* + * Description: set avi infoframe based on mode + * + * @context: hdmi_context + * @mode: mode requested + * + * Returns: OTM_HDMI_SUCCESS on success + * OTM_HDMI_ERR_INVAL on NULL input arguments + */ +extern otm_hdmi_ret_t otm_hdmi_infoframes_set_avi(void *context, + otm_hdmi_timing_t *mode); + +/* + * Description: disable all infoframes + * + * @context: hdmi_context + * + * Returns: OTM_HDMI_ERR_NULL_ARG on NULL parameters + * OTM_HDMI_SUCCESS on success + */ +extern otm_hdmi_ret_t otm_hdmi_disable_all_infoframes(void *context); + +#endif /* _INFOFRAMES_API_H */ diff --git a/drivers/staging/mrst/drv/otm_hdmi/pil/common/mode_info.c b/drivers/staging/mrst/drv/otm_hdmi/pil/common/mode_info.c new file mode 100644 index 0000000..fce6721 --- /dev/null +++ b/drivers/staging/mrst/drv/otm_hdmi/pil/common/mode_info.c @@ -0,0 +1,1151 @@ +/* + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2006-2011 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + Intel Corporation + 2200 Mission College Blvd. + Santa Clara, CA 97052 + + BSD LICENSE + + Copyright(c) 2006-2011 Intel Corporation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + - Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "hdmi_internal.h" +#include "otm_hdmi_defs.h" + +/*----------------------------------------------------------------------------- + 480P TIMINGS +-----------------------------------------------------------------------------*/ +#define TIMING_640x480p5994_60 \ + 640, /* width */ \ + 480, /* height */ \ + OTM_HDMI_REFRESH_60, /* refresh rate */ \ + 25200, /* clock */ \ + 800, /* htotal */ \ + 640, /* hblank start */ \ + 800, /* hblank end */ \ + 656, /* hsync start */ \ + 752, /* hsync end */ \ + 525, /* vtotal */ \ + 480, /* vblank start */ \ + 525, /* vblank end */ \ + 490, /* vsync start */ \ + 492 /* vsync end */ + + +#define TIMING_720x480p5994_60 \ + 720, /* width */ \ + 480, /* height */ \ + OTM_HDMI_REFRESH_60, /* refresh rate */ \ + 27027, /* clock */ \ + 858, /* htotal */ \ + 720, /* hblank start */ \ + 858, /* hblank end */ \ + 736, /* hsync start */ \ + 798, /* hsync end */ \ + 525, /* vtotal */ \ + 480, /* vblank start */ \ + 525, /* vblank end */ \ + 489, /* vsync start */ \ + 495 /* vsync end */ + +/*----------------------------------------------------------------------------- + 576P TIMINGS +-----------------------------------------------------------------------------*/ +#define TIMING_720x576p50 \ + 720, /* width */ \ + 576, /* height */ \ + OTM_HDMI_REFRESH_50, /* refresh rate */ \ + 27000, /* clock */ \ + 864, /* htotal */ \ + 720, /* hblank start */ \ + 864, /* hblank end */ \ + 732, /* hsync start */ \ + 796, /* hsync end */ \ + 625, /* vtotal */ \ + 576, /* vblank start */ \ + 625, /* vblank end */ \ + 581, /* vsync start */ \ + 586 /* vsync end */ + +/*----------------------------------------------------------------------------- + 720I TIMINGS +-----------------------------------------------------------------------------*/ +#define TIMING_720_1440x480i5994_60 \ + 1440, /* width */ \ + 240, /* height */ \ + OTM_HDMI_REFRESH_60, /* refresh rate */ \ + 27027, /* clock */ \ + 1716, /* htotal */ \ + 1440, /* hblank start */ \ + 1716, /* hblank end */ \ + 1478, /* hsync start */ \ + 1602, /* hsync end */ \ + 262, /* vtotal */ \ + 240, /* vblank start */ \ + 262, /* vblank end */ \ + 244, /* vsync start */ \ + 247 /* vsync end */ + +#define TIMING_720_1440x576i50 \ + 1440, /* width */ \ + 288, /* height */ \ + OTM_HDMI_REFRESH_50, /* refresh rate */ \ + 27000, /* clock */ \ + 1728, /* htotal */ \ + 1440, /* hblank start */ \ + 1728, /* hblank end */ \ + 1464, /* hsync start */ \ + 1590, /* hsync end */ \ + 312, /* vtotal */ \ + 288, /* vblank start */ \ + 312, /* vblank end */ \ + 290, /* vsync start */ \ + 293 /* vsync end */ + +/*----------------------------------------------------------------------------- + 720P TIMINGS +-----------------------------------------------------------------------------*/ +#define TIMING_1280x720p50 \ + 1280, /* width */ \ + 720, /* height */ \ + OTM_HDMI_REFRESH_50, /* refresh rate */ \ + 74250, /* clock */ \ + 1980, /* htotal */ \ + 1280, /* hblank start */ \ + 1980, /* hblank end */ \ + 1720, /* hsync start */ \ + 1760, /* hsync end */ \ + 750, /* vtotal */ \ + 720, /* vblank start */ \ + 750, /* vblank end */ \ + 725, /* vsync start */ \ + 730 /* vsync end */ + +#define TIMING_1280x720p50_FP \ + 1280, /* width */ \ + 720, /* height */ \ + OTM_HDMI_REFRESH_50, /* refresh rate */ \ + 148500, /* clock */ \ + 1980, /* htotal */ \ + 1280, /* hblank start */ \ + 1980, /* hblank end */ \ + 1720, /* hsync start */ \ + 1760, /* hsync end */ \ + 750, /* vtotal */ \ + 720, /* vblank start */ \ + 750, /* vblank end */ \ + 725, /* vsync start */ \ + 730 /* vsync end */ + +#define TIMING_1280x720p50_FP2 \ + 1280, /* width */ \ + 720, /* height */ \ + OTM_HDMI_REFRESH_50, /* refresh rate */ \ + 148500, /* clock */ \ + 1980, /* htotal */ \ + 1280, /* hblank start */ \ + 1980, /* hblank end */ \ + 1720, /* hsync start */ \ + 1760, /* hsync end */ \ + 1500, /* vtotal */ \ + 1470, /* vblank start */ \ + 1500, /* vblank end */ \ + 1475, /* vsync start */ \ + 1480 /* vsync end */ + +#define TIMING_1280x720p50_FSEQ \ + 1280, /* width */ \ + 720, /* height */ \ + OTM_HDMI_REFRESH_50, /* refresh rate */ \ + 148500, /* clock */ \ + 1980, /* htotal */ \ + 1280, /* hblank start */ \ + 1980, /* hblank end */ \ + 1720, /* hsync start */ \ + 1760, /* hsync end */ \ + 750, /* vtotal */ \ + 720, /* vblank start */ \ + 750, /* vblank end */ \ + 725, /* vsync start */ \ + 730 /* vsync end */ + +#define TIMING_1280x720p5994_60 \ + 1280, /* width */ \ + 720, /* height */ \ + OTM_HDMI_REFRESH_60, /* refresh rate */ \ + 74250, /* clock */ \ + 1650, /* htotal */ \ + 1280, /* hblank start */ \ + 1650, /* hblank end */ \ + 1390, /* hsync start */ \ + 1430, /* hsync end */ \ + 750, /* vtotal */ \ + 720, /* vblank start */ \ + 750, /* vblank end */ \ + 725, /* vsync start */ \ + 730 /* vsync end */ + +#define TIMING_1280x720p5994_60_FP \ + 1280, /* width */ \ + 720, /* height */ \ + OTM_HDMI_REFRESH_60, /* refresh rate */ \ + 148500, /* clock */ \ + 1650, /* htotal */ \ + 1280, /* hblank start */ \ + 1650, /* hblank end */ \ + 1390, /* hsync start */ \ + 1430, /* hsync end */ \ + 750, /* vtotal */ \ + 720, /* vblank start */ \ + 750, /* vblank end */ \ + 725, /* vsync start */ \ + 730 /* vsync end */ + +#define TIMING_1280x720p5994_60_FP2 \ + 1280, /* width */ \ + 720, /* height */ \ + OTM_HDMI_REFRESH_60, /* refresh rate */ \ + 148500, /* clock */ \ + 1650, /* htotal */ \ + 1280, /* hblank start */ \ + 1650, /* hblank end */ \ + 1390, /* hsync start */ \ + 1430, /* hsync end */ \ + 1500, /* vtotal */ \ + 1470, /* vblank start */ \ + 1500, /* vblank end */ \ + 1475, /* vsync start */ \ + 1480 /* vsync end */ + +#define TIMING_1280x720p5994_60_FSEQ \ + 1280, /* width */ \ + 720, /* height */ \ + OTM_HDMI_REFRESH_60, /* refresh rate */ \ + 148500, /* clock */ \ + 1650, /* htotal */ \ + 1280, /* hblank start */ \ + 1650, /* hblank end */ \ + 1390, /* hsync start */ \ + 1430, /* hsync end */ \ + 750, /* vtotal */ \ + 720, /* vblank start */ \ + 750, /* vblank end */ \ + 725, /* vsync start */ \ + 730 /* vsync end */ + +/*----------------------------------------------------------------------------- + 1080I TIMINGS +-----------------------------------------------------------------------------*/ +#define TIMING_1920x1080i50 \ + 1920, /* width */ \ + 540, /* height */ \ + OTM_HDMI_REFRESH_50, /* refresh rate */ \ + 74250, /* clock */ \ + 2640, /* htotal */ \ + 1920, /* hblank start */ \ + 2640, /* hblank end */ \ + 2448, /* hsync start */ \ + 2492, /* hsync end */ \ + 562, /* vtotal */ \ + 540, /* vblank start */ \ + 562, /* vblank end */ \ + 542, /* vsync start */ \ + 547 /* vsync end */ + +#define TIMING_1920x1080i50_FP \ + 1920, /* width */ \ + 540, /* height */ \ + OTM_HDMI_REFRESH_50, /* refresh rate */ \ + 148500, /* clock */ \ + 2640, /* htotal */ \ + 1920, /* hblank start */ \ + 2640, /* hblank end */ \ + 2448, /* hsync start */ \ + 2492, /* hsync end */ \ + 562, /* vtotal */ \ + 540, /* vblank start */ \ + 562, /* vblank end */ \ + 542, /* vsync start */ \ + 547 /* vsync end */ + +#define TIMING_1920x1080i5994_60 \ + 1920, /* width */ \ + 540, /* height */ \ + OTM_HDMI_REFRESH_60, /* refresh rate */ \ + 74250, /* clock */ \ + 2200, /* htotal */ \ + 1920, /* hblank start */ \ + 2200, /* hblank end */ \ + 2008, /* hsync start */ \ + 2052, /* hsync end */ \ + 562, /* vtotal */ \ + 540, /* vblank start */ \ + 562, /* vblank end */ \ + 542, /* vsync start */ \ + 547 /* vsync end */ + +#define TIMING_1920x1080i5994_60_FP \ + 1920, /* width */ \ + 540, /* height */ \ + OTM_HDMI_REFRESH_60, /* refresh rate */ \ + 148500, /* clock */ \ + 2200, /* htotal */ \ + 1920, /* hblank start */ \ + 2200, /* hblank end */ \ + 2008, /* hsync start */ \ + 2052, /* hsync end */ \ + 562, /* vtotal */ \ + 540, /* vblank start */ \ + 562, /* vblank end */ \ + 542, /* vsync start */ \ + 547 /* vsync end */ + +/*----------------------------------------------------------------------------- + 1080P TIMINGS +-----------------------------------------------------------------------------*/ +#define TIMING_1920x1080p24 \ + 1920, /* width */ \ + 1080, /* height */ \ + OTM_HDMI_REFRESH_24, /* refresh */ \ + 74250, /* clock */ \ + 2750, /* htotal */ \ + 1920, /* hblank start */ \ + 2750, /* hblank end */ \ + 2558, /* hsync start */ \ + 2602, /* hsync end */ \ + 1125, /* vtotal */ \ + 1080, /* vblank start */ \ + 1125, /* vblank end */ \ + 1084, /* vsync start */ \ + 1089 /* vsync end */ + +#define TIMING_1920x1080p24_FP \ + 1920, /* width */ \ + 1080, /* height */ \ + OTM_HDMI_REFRESH_24, /* refresh */ \ + 148500, /* clock */ \ + 2750, /* htotal */ \ + 1920, /* hblank start */ \ + 2750, /* hblank end */ \ + 2558, /* hsync start */ \ + 2602, /* hsync end */ \ + 1125, /* vtotal */ \ + 1080, /* vblank start */ \ + 1125, /* vblank end */ \ + 1084, /* vsync start */ \ + 1089 /* vsync end */ + +#define TIMING_1920x1080p24_FP2 \ + 1920, /* width */ \ + 1080, /* height */ \ + OTM_HDMI_REFRESH_24, /* refresh */ \ + 148500, /* clock */ \ + 2750, /* htotal */ \ + 1920, /* hblank start */ \ + 2750, /* hblank end */ \ + 2558, /* hsync start */ \ + 2602, /* hsync end */ \ + 2250, /* vtotal */ \ + 2205, /* vblank start */ \ + 2250, /* vblank end */ \ + 2209, /* vsync start */ \ + 2214 /* vsync end */ + +#define TIMING_1920x1080p24_FSEQ \ + 1920, /* width */ \ + 1080, /* height */ \ + OTM_HDMI_REFRESH_24, /* refresh */ \ + 148500, /* clock */ \ + 2750, /* htotal */ \ + 1920, /* hblank start */ \ + 2750, /* hblank end */ \ + 2558, /* hsync start */ \ + 2602, /* hsync end */ \ + 1125, /* vtotal */ \ + 1080, /* vblank start */ \ + 1125, /* vblank end */ \ + 1084, /* vsync start */ \ + 1089 /* vsync end */ + +#define TIMING_1920x1080p25 \ + 1920, /* width */ \ + 1080, /* height */ \ + OTM_HDMI_REFRESH_25, /* refresh */ \ + 74250, /* clock */ \ + 2640, /* htotal */ \ + 1920, /* hblank start */ \ + 2640, /* hblank end */ \ + 2448, /* hsync start */ \ + 2492, /* hsync end */ \ + 1125, /* vtotal */ \ + 1080, /* vblank start */ \ + 1125, /* vblank end */ \ + 1084, /* vsync start */ \ + 1089 /* vsync end */ + +#define TIMING_1920x1080p30 \ + 1920, /* width */ \ + 1080, /* height */ \ + OTM_HDMI_REFRESH_30, /* refresh */ \ + 74250, /* clock */ \ + 2200, /* htotal */ \ + 1920, /* hblank start */ \ + 2200, /* hblank end */ \ + 2008, /* hsync start */ \ + 2052, /* hsync end */ \ + 1125, /* vtotal */ \ + 1080, /* vblank start */ \ + 1125, /* vblank end */ \ + 1084, /* vsync start */ \ + 1089 /* vsync end */ + +#define TIMING_1920x1080p30_FP \ + 1920, /* width */ \ + 1080, /* height */ \ + OTM_HDMI_REFRESH_30, /* refresh */ \ + 148500, /* clock */ \ + 2200, /* htotal */ \ + 1920, /* hblank start */ \ + 2200, /* hblank end */ \ + 2008, /* hsync start */ \ + 2052, /* hsync end */ \ + 1125, /* vtotal */ \ + 1080, /* vblank start */ \ + 1125, /* vblank end */ \ + 1084, /* vsync start */ \ + 1089 /* vsync end */ + +#define TIMING_1920x1080p30_FP2 \ + 1920, /* width */ \ + 1080, /* height */ \ + OTM_HDMI_REFRESH_30, /* refresh */ \ + 148500, /* clock */ \ + 2200, /* htotal */ \ + 1920, /* hblank start */ \ + 2200, /* hblank end */ \ + 2008, /* hsync start */ \ + 2052, /* hsync end */ \ + 2250, /* vtotal */ \ + 2205, /* vblank start */ \ + 2250, /* vblank end */ \ + 2209, /* vsync start */ \ + 2214 /* vsync end */ + +#define TIMING_1920x1080p48 \ + 1920, /* width */ \ + 1080, /* height */ \ + OTM_HDMI_REFRESH_48, /* refresh */ \ + 148500, /* clock */ \ + 2750, /* htotal */ \ + 1920, /* hblank start */ \ + 2750, /* hblank end */ \ + 2558, /* hsync start */ \ + 2602, /* hsync end */ \ + 1125, /* vtotal */ \ + 1080, /* vblank start */ \ + 1125, /* vblank end */ \ + 1084, /* vsync start */ \ + 1089 /* vsync end */ + +#define TIMING_1920x1080p50 \ + 1920, /* width */ \ + 1080, /* height */ \ + OTM_HDMI_REFRESH_50, /* refresh */ \ + 148500, /* clock */ \ + 2640, /* htotal */ \ + 1920, /* hblank start */ \ + 2640, /* hblank end */ \ + 2448, /* hsync start */ \ + 2492, /* hsync end */ \ + 1125, /* vtotal */ \ + 1080, /* vblank start */ \ + 1125, /* blank end */ \ + 1084, /* vsync start */ \ + 1089 /* vsync end */ + +#define TIMING_1920x1080p5994_60 \ + 1920, /* width */ \ + 1080, /* height */ \ + OTM_HDMI_REFRESH_60, /* refresh */ \ + 148500, /* clock */ \ + 2200, /* htotal */ \ + 1920, /* hblank start */ \ + 2200, /* hblank end */ \ + 2008, /* hsync start */ \ + 2052, /* hsync end */ \ + 1125, /* vtotal */ \ + 1080, /* vblank start */ \ + 1125, /* blank end */ \ + 1084, /* vsync start */ \ + 1089 /* vsync end */ + +/*----------------------------------------------------------------------------- + Panel TIMINGS +-----------------------------------------------------------------------------*/ + +#define TIMING_1920x1080p60_PANEL \ + 1920, /* width */ \ + 1080, /* height */ \ + OTM_HDMI_REFRESH_60, /* refresh */ \ + 148500, /* clock */ \ + 2184, /* htotal */ \ + 1920, /* hblank start*/ \ + 2184, /* hblank end */ \ + 1920 + 32, /* hsync start */ \ + 1920 + 32 + 32, /* hsync end */ \ + 1134, /* vtotal */ \ + 1080, /* vblank start*/ \ + 1134, /* vblank end */ \ + 1080 + 34, /* vsync start */ \ + 1080 + 34 + 4 /* vsync end */ + +#define TIMING_1920x1080p50_PANEL \ + 1920, /* width */ \ + 1080, /* height */ \ + OTM_HDMI_REFRESH_50, /* refresh */ \ + 148500, /* clock */ \ + 2184, /* htotal */ \ + 1920, /* hblank start*/ \ + 2184, /* hblank end */ \ + 1920 + 32, /* hsync start */ \ + 1920 + 32 + 32, /* hsync end */ \ + 1360, /* vtotal */ \ + 1080, /* vblank start*/ \ + 1360, /* vblank end */ \ + 1080 + 260, /* vsync start*/ \ + 1080 + 260 + 4 /* vsync end */ + +#define TIMING_1920x1080p48_PANEL \ + 1920, /* width */ \ + 1080, /* height */ \ + OTM_HDMI_REFRESH_48, /* refresh */ \ + 148500, /* clock */ \ + 2184, /* htotal */ \ + 1920, /* hblank start*/ \ + 2184, /* hblank end */ \ + 1920 + 32, /* hsync start */ \ + 1920 + 32 + 32, /* hsync end */ \ + 1417, /* vtotal */ \ + 1080, /* vblank start*/ \ + 1417, /* vblank end */ \ + 1080 + 317, /* vsync start */ \ + 1080 + 317 + 4 /* vsync end */ + +#define TIMING_1920x1080p30_PANEL_FS \ + 1920, /* width */ \ + 1080, /* height */ \ + OTM_HDMI_REFRESH_30, /* refresh */ \ + 148500, /* clock */ \ + 2184, /* htotal */ \ + 1920, /* hblank start*/ \ + 2184, /* hblank end */ \ + 1920 + 32, /* hsync start */ \ + 1920 + 32 + 32, /* hsync end */ \ + 1134, /* vtotal */ \ + 1080, /* vblank start*/ \ + 1134, /* vblank end */ \ + 1080 + 34, /* vsync start */ \ + 1080 + 34 + 4 /* vsync end */ + +#define TIMING_1920x1080p25_PANEL_FS \ + 1920, /* width */ \ + 1080, /* height */ \ + OTM_HDMI_REFRESH_25, /* refresh */ \ + 148500, /* clock */ \ + 2184, /* htotal */ \ + 1920, /* hblank start*/ \ + 2184, /* hblank end */ \ + 1920 + 32, /* hsync start */ \ + 1920 + 32 + 32, /* hsync end */ \ + 1360, /* vtotal */ \ + 1080, /* vblank start*/ \ + 1360, /* vblank end */ \ + 1080 + 260, /* vsync start*/ \ + 1080 + 260 + 4 /* vsync end */ + +#define TIMING_1920x1080p24_PANEL_FS \ + 1920, /* width */ \ + 1080, /* height */ \ + OTM_HDMI_REFRESH_24, /* refresh */ \ + 148500, /* clock */ \ + 2184, /* htotal */ \ + 1920, /* hblank start*/ \ + 2184, /* hblank end */ \ + 1920 + 32, /* hsync start */ \ + 1920 + 32 + 32, /* hsync end */ \ + 1417, /* vtotal */ \ + 1080, /* vblank start*/ \ + 1417, /* vblank end */ \ + 1080 + 317, /* vsync start */ \ + 1080 + 317 + 4 /* vsync end */ + +#define TIMING_960x1080p60_PANEL_FS \ + 960, /* width */ \ + 1080, /* height */ \ + OTM_HDMI_REFRESH_60, /* refresh */ \ + 148500, /* clock */ \ + 1092, /* htotal */ \ + 960, /* hblank start*/ \ + 1092, /* hblank end */ \ + 960 + 24, /* hsync start */ \ + 960 + 24 + 32, /* hsync end */ \ + 1134, /* vtotal */ \ + 1080, /* vblank start*/ \ + 1134, /* vblank end */ \ + 1080 + 34, /* vsync start */ \ + 1080 + 34 + 4 /* vsync end */ + +#define TIMING_960x1080p50_PANEL_FS \ + 960, /* width */ \ + 1080, /* height */ \ + OTM_HDMI_REFRESH_50, /* refresh */ \ + 148500, /* clock */ \ + 1092, /* htotal */ \ + 960, /* hblank start*/ \ + 1092, /* hblank end */ \ + 960 + 24, /* hsync start */ \ + 960 + 24 + 32, /* hsync end */ \ + 1360, /* vtotal */ \ + 1080, /* vblank start*/ \ + 1360, /* vblank end */ \ + 1080 + 260, /* vsync start */ \ + 1080 + 260 + 4 /* vsync end */ + +#define TIMING_1920x540p60_PANEL_FS \ + 1920, /* width */ \ + 540, /* height */ \ + OTM_HDMI_REFRESH_60, /* refresh */ \ + 148500, /* clock */ \ + 2184, /* htotal */ \ + 1920, /* hblank start*/ \ + 2184, /* hblank end */ \ + 1920 + 32, /* hsync start */ \ + 1920 + 32 + 32, /* hsync end */ \ + 567, /* vtotal */ \ + 540, /* vblank start*/ \ + 567, /* vblank end */ \ + 540 + 17, /* vsync start */ \ + 540 + 17 + 4 /* vsync end */ + +#define TIMING_1920x540p50_PANEL_FS \ + 1920, /* width */ \ + 540, /* height */ \ + OTM_HDMI_REFRESH_50, /* refresh */ \ + 148500, /* clock */ \ + 2184, /* htotal */ \ + 1920, /* hblank start*/ \ + 2184, /* hblank end */ \ + 1920 + 32, /* hsync start */ \ + 1920 + 32 + 32, /* hsync end */ \ + 680, /* vtotal */ \ + 540, /* vblank start*/ \ + 680, /* vblank end */ \ + 540 + 130, /* vsync start */ \ + 540 + 130 + 4 /* vsync end */ + +#define TIMING_1280x720p60_PANEL_FS \ + 1280, /* width */ \ + 720, /* height */ \ + OTM_HDMI_REFRESH_60, /* refresh */ \ + 148500, /* clock */ \ + 1650, /* htotal */ \ + 1280, /* hblank start*/ \ + 1650, /* hblank end */ \ + 1390, /* hsync start */ \ + 1422, /* hsync end */ \ + 750, /* vtotal */ \ + 720, /* vblank start*/ \ + 750, /* vblank end */ \ + 735, /* vsync start */ \ + 739 /* vsync end */ + +#define TIMING_1280x720p50_PANEL_FS \ + 1280, /* width */ \ + 720, /* height */ \ + OTM_HDMI_REFRESH_50, /* refresh */ \ + 148500, /* clock */ \ + 1650, /* htotal */ \ + 1280, /* hblank start*/ \ + 1650, /* hblank end */ \ + 1280 + 110, /* hsync start */ \ + 1280 + 110 + 32,/* hsync end */ \ + 900, /* vtotal */ \ + 720, /* vblank start*/ \ + 900, /* vblank end */ \ + 720 + 165, /* vsync start */ \ + 720 + 165 + 4 /* vsync end */ + + +const otm_hdmi_timing_t MODE_640x480p5994_60 = { + TIMING_640x480p5994_60, + 0, /* flags */ + OTM_HDMI_STEREO_NONE, /* stereo_type */ + 1 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_720x480p5994_60 = { + TIMING_720x480p5994_60, + 0, /* flags */ + OTM_HDMI_STEREO_NONE, /* stereo_type */ + 2 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_720x480p5994_60__16by9 = { + TIMING_720x480p5994_60, + PD_AR_16_BY_9, /* flags */ + OTM_HDMI_STEREO_NONE, /* stereo_type */ + 3 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1280x720p5994_60 = { + TIMING_1280x720p5994_60, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH, + /* flags */ + OTM_HDMI_STEREO_NONE, /* stereo_type */ + 4 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1920x1080i5994_60 = { + TIMING_1920x1080i5994_60, + PD_SCAN_INTERLACE | PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH, + /* flags */ + OTM_HDMI_STEREO_NONE, /* stereo_type */ + 5 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1920x1080i5994_60__FP = { + TIMING_1920x1080i5994_60_FP, + PD_SCAN_INTERLACE | PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH, + /* flags */ + OTM_HDMI_STEREO_FRAME_PACKING, /* stereo_type */ + 5 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_720_1440x480i5994_60 = { + TIMING_720_1440x480i5994_60, + PD_SCAN_INTERLACE, /* flags */ + OTM_HDMI_STEREO_NONE, /* stereo_type */ + 6 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_720_1440x480i5994_60__16by9 = { + TIMING_720_1440x480i5994_60, + PD_SCAN_INTERLACE | PD_AR_16_BY_9, + /* flags */ + OTM_HDMI_STEREO_NONE, /* stereo_type */ + 7 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1920x1080p5994_60 = { + TIMING_1920x1080p5994_60, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH, + /* flags */ + OTM_HDMI_STEREO_NONE, /* stereo_type */ + 16 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_720x576p50 = { + TIMING_720x576p50, + 0, /* flags */ + OTM_HDMI_STEREO_NONE, /* stereo_type */ + 17 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_720x576p50__16by9 = { + TIMING_720x576p50, + PD_AR_16_BY_9, /* flags */ + OTM_HDMI_STEREO_NONE, /* stereo_type */ + 18 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1280x720p50 = { + TIMING_1280x720p50, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH, + /* flags */ + OTM_HDMI_STEREO_NONE, /* stereo_type */ + 19 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1920x1080i50 = { + TIMING_1920x1080i50, + PD_SCAN_INTERLACE | PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH, + /* flags */ + OTM_HDMI_STEREO_NONE, /* stereo_type */ + 20 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1920x1080i50__FP = { + TIMING_1920x1080i50_FP, + PD_SCAN_INTERLACE | PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH, + /* flags */ + OTM_HDMI_STEREO_FRAME_PACKING, /* stereo_type */ + 20 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_720_1440x576i50 = { + TIMING_720_1440x576i50, + PD_SCAN_INTERLACE, /* flags */ + OTM_HDMI_STEREO_NONE, /* stereo_type */ + 21 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_720_1440x576i50__16by9 = { + TIMING_720_1440x576i50, + PD_SCAN_INTERLACE | PD_AR_16_BY_9, + /* flags */ + OTM_HDMI_STEREO_NONE, /* stereo_type */ + 22 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1920x1080p50 = { + TIMING_1920x1080p50, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH, + /* flags */ + OTM_HDMI_STEREO_NONE, /* stereo_type */ + 31 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1920x1080p24 = { + TIMING_1920x1080p24, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH, + /* flags */ + OTM_HDMI_STEREO_NONE, /* stereo_type */ + 32 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1920x1080p25 = { + TIMING_1920x1080p25, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH, + /* flags */ + OTM_HDMI_STEREO_NONE, /* stereo_type */ + 33 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1920x1080p30 = { + TIMING_1920x1080p30, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH, + /* flags */ + OTM_HDMI_STEREO_NONE, /* stereo_type */ + 34 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1920x1080p30__FP2 = { + TIMING_1920x1080p30_FP2, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH, + /* flags */ + OTM_HDMI_STEREO_FRAME_PACKING_2,/* stereo_type */ + 34 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1920x1080p30__FP = { + TIMING_1920x1080p30_FP, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH, + /* flags */ + OTM_HDMI_STEREO_FRAME_PACKING, /* stereo_type */ + 34 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1920x1080p30__TBH2 = { + TIMING_1920x1080p30, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH, + /* flags */ + OTM_HDMI_STEREO_TOP_BOTTOM_HALF_2, /* stereo_type */ + 34 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1920x1080p48 = { + TIMING_1920x1080p48, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH, + /* flags */ + OTM_HDMI_STEREO_NONE, /* stereo_type */ + 32 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1920x1080p24__FP2 = { + TIMING_1920x1080p24_FP2, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH, + /* flags */ + OTM_HDMI_STEREO_FRAME_PACKING_2,/* stereo_type */ + 32 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1920x1080p24__FP = { + TIMING_1920x1080p24_FP, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH, + /* flags */ + OTM_HDMI_STEREO_FRAME_PACKING, /* stereo_type */ + 32 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1280x720p5994_60__FP2 = { + TIMING_1280x720p5994_60_FP2, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH, + /* flags */ + OTM_HDMI_STEREO_FRAME_PACKING_2,/* stereo_type */ + 4 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1280x720p5994_60__FP = { + TIMING_1280x720p5994_60_FP, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH, + /* flags */ + OTM_HDMI_STEREO_FRAME_PACKING, /* stereo_type */ + 4 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1280x720p50__FP2 = { + TIMING_1280x720p50_FP2, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH, + /* flags */ + OTM_HDMI_STEREO_FRAME_PACKING_2,/* stereo_type */ + 19 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1280x720p50__FP = { + TIMING_1280x720p50_FP, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH, + /* flags */ + OTM_HDMI_STEREO_FRAME_PACKING, /* stereo_type */ + 19 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1280x720p5994_60__SBSH2 = { + TIMING_1280x720p5994_60, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH, + /* flags */ + OTM_HDMI_STEREO_SIDE_BY_SIDE_HALF_2, /* stereo_type */ + 4 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1280x720p50__SBSH2 = { + TIMING_1280x720p50, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH, + /* flags */ + OTM_HDMI_STEREO_SIDE_BY_SIDE_HALF_2, /* stereo_type */ + 19 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1920x1080i5994_60__SBSH2 = { + TIMING_1920x1080i5994_60, + PD_SCAN_INTERLACE | PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH, + /* flags */ + OTM_HDMI_STEREO_SIDE_BY_SIDE_HALF_2, /* stereo_type */ + 5 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1920x1080i50__SBSH2 = { + TIMING_1920x1080i50, + PD_SCAN_INTERLACE | PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH, + /* flags */ + OTM_HDMI_STEREO_SIDE_BY_SIDE_HALF_2, /* stereo_type */ + 20 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1920x1080p5994_60__SBSH2 = { + TIMING_1920x1080p5994_60, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH, + /* flags */ + OTM_HDMI_STEREO_SIDE_BY_SIDE_HALF_2, /* stereo_type */ + 16 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1920x1080p50__SBSH2 = { + TIMING_1920x1080p50, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH, + /* flags */ + OTM_HDMI_STEREO_SIDE_BY_SIDE_HALF_2, /* stereo_type */ + 31 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1920x1080p24__SBSH2 = { + TIMING_1920x1080p24, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH, + /* flags */ + OTM_HDMI_STEREO_SIDE_BY_SIDE_HALF_2, /* stereo_type */ + 32 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1280x720p5994_60__TBH2 = { + TIMING_1280x720p5994_60, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH, + /* flags */ + OTM_HDMI_STEREO_TOP_BOTTOM_HALF_2, /* stereo_type */ + 4 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1280x720p50__TBH2 = { + TIMING_1280x720p50, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH, + /* flags */ + OTM_HDMI_STEREO_TOP_BOTTOM_HALF_2, /* stereo_type */ + 19 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1920x1080p5994_60__TBH2 = { + TIMING_1920x1080p5994_60, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH, + /* flags */ + OTM_HDMI_STEREO_TOP_BOTTOM_HALF_2, /* stereo_type */ + 16 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1920x1080p50__TBH2 = { + TIMING_1920x1080p50, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH, + /* flags */ + OTM_HDMI_STEREO_TOP_BOTTOM_HALF_2, /* stereo_type */ + 31 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1920x1080p24__TBH2 = { + TIMING_1920x1080p24, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH, + /* flags */ + OTM_HDMI_STEREO_TOP_BOTTOM_HALF_2, /* stereo_type */ + 32 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1280x720p60__PANEL_FS = { + TIMING_1280x720p60_PANEL_FS, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH | PD_DTV_MODE, + /* flags */ + OTM_HDMI_STEREO_FRAME_SEQUENTIAL, /* stereo_type */ + 0 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1280x720p50__PANEL_FS = { + TIMING_1280x720p50_PANEL_FS, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH | PD_DTV_MODE, + /* flags */ + OTM_HDMI_STEREO_FRAME_SEQUENTIAL, /* stereo_type */ + 0 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1920x540p60__PANEL_FS = { + TIMING_1920x540p60_PANEL_FS, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH | PD_DTV_MODE, + /* flags */ + OTM_HDMI_STEREO_FRAME_SEQUENTIAL, /* stereo_type */ + 0 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1920x540p50__PANEL_FS = { + TIMING_1920x540p50_PANEL_FS, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH | PD_DTV_MODE, + /* flags */ + OTM_HDMI_STEREO_FRAME_SEQUENTIAL, /* stereo_type */ + 0 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_920x1080p60__PANEL_FS = { + TIMING_960x1080p60_PANEL_FS, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH | PD_DTV_MODE, + /* flags */ + OTM_HDMI_STEREO_FRAME_SEQUENTIAL, /* stereo_type */ + 0 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_920x1080p50__PANEL_FS = { + TIMING_960x1080p50_PANEL_FS, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH | PD_DTV_MODE, + /* flags */ + OTM_HDMI_STEREO_FRAME_SEQUENTIAL, /* stereo_type */ + 0 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1920x1080p30__PANEL_FS = { + TIMING_1920x1080p30_PANEL_FS, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH | PD_DTV_MODE, + /* flags */ + OTM_HDMI_STEREO_FRAME_SEQUENTIAL, /* stereo_type */ + 0 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1920x1080p25__PANEL_FS = { + TIMING_1920x1080p25_PANEL_FS, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH | PD_DTV_MODE, + /* flags */ + OTM_HDMI_STEREO_FRAME_SEQUENTIAL, /* stereo_type */ + 0 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1920x1080p24__PANEL_FS = { + TIMING_1920x1080p24_PANEL_FS, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH | PD_DTV_MODE, + /* flags */ + OTM_HDMI_STEREO_FRAME_SEQUENTIAL, /* stereo_type */ + 0 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1920x1080p60__PANEL = { + TIMING_1920x1080p60_PANEL, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH | PD_DTV_MODE, + /* flags */ + OTM_HDMI_STEREO_NONE, /* stereo_type */ + 0 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1920x1080p50__PANEL = { + TIMING_1920x1080p50_PANEL, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH | PD_DTV_MODE, + /* flags */ + OTM_HDMI_STEREO_NONE, /* stereo_type */ + 0 /* Metadata VIC */ +}; + +const otm_hdmi_timing_t MODE_1920x1080p48__PANEL = { + TIMING_1920x1080p48_PANEL, + PD_AR_16_BY_9 | PD_HSYNC_HIGH | PD_VSYNC_HIGH | PD_DTV_MODE, + /* flags */ + OTM_HDMI_STEREO_NONE, /* stereo_type */ + 0 /* Metadata VIC */ +}; diff --git a/drivers/staging/mrst/drv/otm_hdmi/pil/common/otm_hdmi.c b/drivers/staging/mrst/drv/otm_hdmi/pil/common/otm_hdmi.c new file mode 100644 index 0000000..90dc331 --- /dev/null +++ b/drivers/staging/mrst/drv/otm_hdmi/pil/common/otm_hdmi.c @@ -0,0 +1,2235 @@ +/* + + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2011 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + + Intel Corporation + 2200 Mission College Blvd. + Santa Clara, CA 95054 + + BSD LICENSE + + Copyright(c) 2011 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include "otm_hdmi.h" +#include "ipil_hdmi.h" + +#include "hdmi_internal.h" +#include "hdmi_timings.h" +#ifdef OTM_HDMI_HDCP_ENABLE +#include "hdcp_api.h" +#endif +#include "edid.h" +#include "ps_hdmi.h" +#include "ips_hdmi.h" +#include "infoframes_api.h" + +/* TODO: Leave it here or move to some .h? */ +#define OTM_HDMI_NAME "OTM HDMI" + +/** + * Table of attributes + */ +otm_hdmi_attribute_t otm_hdmi_attributes_table + [OTM_HDMI_MAX_SUPPORTED_ATTRIBUTES]; + +/* Placeholder for all TX supported modes */ +static const otm_hdmi_timing_t *g_video_modes[MAX_TIMINGS]; +/* Placeholder for all TX supported modes per CEA 861E spec used by EDID parser + */ +static const otm_hdmi_timing_t *g_video_modes_ref[MAX_TIMINGS]; +static otm_hdmi_ret_t otm_hdmi_attr_set_validate(otm_hdmi_attribute_id_t id, + void *value); +static otm_hdmi_ret_t otm_hdmi_attr_get_validate(otm_hdmi_attribute_id_t id); + +static otm_hdmi_ret_t __pd_attr_declare(otm_hdmi_attribute_t *table, + otm_hdmi_attribute_id_t id, + otm_hdmi_attribute_type_t type, + otm_hdmi_attribute_flag_t flags, + char *name, + void *value, + unsigned int min, + unsigned int max); + +static unsigned int g_gpio = GPIO_MIN; +static unsigned int g_dtv; +static unsigned int g_dc = 1; + +#define EDID_SIGNATURE 0x00FFFFFFFFFFFF00ull + +static hdmi_context_t *g_context; + +/* This table preserves the special timings for DTV models */ +static const otm_hdmi_timing_t *static_dtv_modes[] = { + &MODE_1920x1080p60__PANEL, + &MODE_1920x1080p50__PANEL, + &MODE_1920x1080p48__PANEL, + &MODE_1280x720p60__PANEL_FS, + &MODE_1280x720p50__PANEL_FS, + &MODE_1920x540p60__PANEL_FS, + &MODE_1920x540p50__PANEL_FS, + &MODE_920x1080p60__PANEL_FS, + &MODE_920x1080p50__PANEL_FS, + &MODE_1920x1080p30__PANEL_FS, + &MODE_1920x1080p25__PANEL_FS, + &MODE_1920x1080p24__PANEL_FS, +}; + +/* This table contains list of audio timings supported by Intel CE Media + * Processors and used in the situations when EDID is not available + * + * Note: Do *NOT* add declaration WMA in here as we dont have approval for that + */ +static otm_hdmi_audio_cap_t static_audio_modes[] = { + DECLARE_AUDIO_CAP(OTM_HDMI_AUDIO_FORMAT_PCM, 8, ALL_SF, ALL_SS), + DECLARE_AUDIO_CAP(OTM_HDMI_AUDIO_FORMAT_AC3, 8, ALL_SF, 640 / 8), + DECLARE_AUDIO_CAP(OTM_HDMI_AUDIO_FORMAT_DTS, 8, ALL_SF, 1536 / 8), + DECLARE_AUDIO_CAP(OTM_HDMI_AUDIO_FORMAT_DDP, 8, ALL_SF, 0), + DECLARE_AUDIO_CAP(OTM_HDMI_AUDIO_FORMAT_DTSHD, 8, ALL_SF, 0), + DECLARE_AUDIO_CAP(OTM_HDMI_AUDIO_FORMAT_MLP, 8, ALL_SF, 0), +}; + +static otm_hdmi_ret_t __program_clocks(hdmi_context_t *ctx, unsigned int dclk) +{ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + return rc; +} + +/* + * Wrapper over printing to both console and SVEN. Note that Both underlying + * routines accept frame stack pointer + */ +static int __vprintf(const char *fmt, ...) +{ + int rc = 0; + va_list argp; + + /* Log on console only if debug is on */ + if (PD_ATTR_UINT(ATTRS[OTM_HDMI_ATTR_ID_DEBUG]) >= PD_LOG_LEVEL_ERROR) { + va_start(argp, fmt); + rc = vprintk(fmt, argp); + va_end(argp); + } + return rc; +} + +static void __hdmi_report_edid(hdmi_context_t *ctx, edid_info_t *edid) +{ + int i = 0; + + PD_LOG_PRINT(PD_LOG_LEVEL_HIGH, "----------------------\n"); + PD_LOG_PRINT(PD_LOG_LEVEL_HIGH, "Name : %s\n", edid->product_name); + PD_LOG_PRINT(PD_LOG_LEVEL_HIGH, "Year : %d\n", edid->product_year); + PD_LOG_PRINT(PD_LOG_LEVEL_HIGH, "SN : %d\n", edid->product_sn); + PD_LOG_PRINT(PD_LOG_LEVEL_HIGH, "Type : %s\n", + edid->hdmi ? "HDMI" : "DVI"); + PD_LOG_PRINT(PD_LOG_LEVEL_HIGH, "YCbCr444 : %s\n", + edid->ycbcr444 ? "Y" : "N"); + PD_LOG_PRINT(PD_LOG_LEVEL_HIGH, "YCbCr422 : %s\n", + edid->ycbcr422 ? "Y" : "N"); + PD_LOG_PRINT(PD_LOG_LEVEL_HIGH, "30 bpp : %s\n", + edid->dc_30 ? "Y" : "N"); + PD_LOG_PRINT(PD_LOG_LEVEL_HIGH, "36 bpp : %s\n", + edid->dc_36 ? "Y" : "N"); + PD_LOG_PRINT(PD_LOG_LEVEL_HIGH, "48 bpp : %s\n", + edid->dc_48 ? "Y" : "N"); + PD_LOG_PRINT(PD_LOG_LEVEL_HIGH, "DC_YUV : %s\n", + edid->dc_y444 ? "Y" : "N"); + PD_LOG_PRINT(PD_LOG_LEVEL_HIGH, "Max CLK : %d\n", + edid->max_tmds_clock); + PD_LOG_PRINT(PD_LOG_LEVEL_HIGH, "Lip sync : %s\n", + edid->latency_present ? "Y" : "N"); + PD_LOG_PRINT(PD_LOG_LEVEL_HIGH, "ILip sync: %s\n", + edid->latency_int_present ? "Y" : "N"); + PD_LOG_PRINT(PD_LOG_LEVEL_HIGH, "Vid lat : %d\n", + edid->latency_video); + PD_LOG_PRINT(PD_LOG_LEVEL_HIGH, "Aud lat : %d\n", + edid->latency_audio); + PD_LOG_PRINT(PD_LOG_LEVEL_HIGH, "IVid lat : %d\n", + edid->latency_video_interlaced); + PD_LOG_PRINT(PD_LOG_LEVEL_HIGH, "IAud lat : %d\n", + edid->latency_audio_interlaced); + PD_LOG_PRINT(PD_LOG_LEVEL_HIGH, "HDMI VID : %s\n", + edid->hdmi_video_present ? "Y" : "N"); + PD_LOG_PRINT(PD_LOG_LEVEL_HIGH, "HDMI 3D : %s\n", + edid->enabled_3d ? "Y" : "N"); + + PD_LOG_PRINT(PD_LOG_LEVEL_HIGH, "SPA : %d.%d.%d.%d\n", + (edid->spa & 0xF000) >> 12, + (edid->spa & 0x0F00) >> 8, + (edid->spa & 0x00F0) >> 4, (edid->spa & 0x000F) >> 0); + + PD_LOG_PRINT(PD_LOG_LEVEL_HIGH, "Supported timings [%d]:\n", + edid->num_timings); + + for (i = 0; i < edid->num_timings; i++) + print_pd_timing(&edid->timings[i], edid->order[i], __vprintf); + + PD_LOG_PRINT(PD_LOG_LEVEL_HIGH, "Audio capabilities:\n"); + for (i = 0; i < edid->num_caps; i++) + print_audio_capability(&edid->audio_caps[i], __vprintf); + + print_speaker_layout(edid->speaker_map, __vprintf); + PD_LOG_PRINT(PD_LOG_LEVEL_HIGH, "----------------------\n"); +} + +static otm_hdmi_ret_t __hdmi_edid_override(hdmi_context_t *ctx, + edid_info_t *edid, + bool safe) +{ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + unsigned int i, n = 0; + bool hdmi; + bool dc_30, dc_36; + const otm_hdmi_timing_t **modes = NULL; + bool hdcp = PD_ATTR_BOOL(ATTRS[OTM_HDMI_ATTR_ID_HDCP]); + unsigned int n_modes_dtv = NUM_ENTRIES_IN(static_dtv_modes); + + /* Verify pointers */ + if (!(edid)) { + rc = OTM_HDMI_ERR_INTERNAL; + goto exit; + } + /* Save device type and DC caps */ + hdmi = !ctx->dtv && (safe ? edid->hdmi : true); + dc_30 = hdmi && edid->dc_30; + dc_36 = hdmi && edid->dc_36; + + /* Clear EDID */ + memset(edid, 0, sizeof(edid_info_t)); + + /* Set device type */ + edid->hdmi = hdmi; + + /* Pick caps table based on whether we are HDMI TX or DTV */ + modes = ctx->dtv ? static_dtv_modes : g_video_modes; + n = ctx->dtv ? n_modes_dtv : ctx->n_modes_tx; + + /* Add all supported video modes */ + for (i = edid->num_timings = 0; i < n; i++) { + edid->timings[edid->num_timings++] = *modes[i]; + + /* Do NOT advertise 3D modes in DVI mode unless we are in DTV + * mode which means always use DTV static table + */ + if (!ctx->dtv && !hdmi && + modes[i]->stereo_type != OTM_HDMI_STEREO_NONE) { + edid->num_timings--; + } + } + + /* Set HDCP based on DTV indicator */ + PD_ATTR_BOOL(ATTRS[OTM_HDMI_ATTR_ID_HDCP]) = + ctx->dtv ? false : hdcp; + + /* Dont bother with HDMI caps if we are in DVI mode */ + if (!(hdmi)) + goto exit; + + /* Add all supported audio modes */ + edid->num_caps = NUM_ENTRIES_IN(static_audio_modes); + for (i = 0; i < edid->num_caps; i++) + edid->audio_caps[i] = static_audio_modes[i]; + + /* Enable all possible speaker allocation maps */ + edid->speaker_map |= 0x3ff; + + /* Indicate support of deep color and YCbCr output */ + edid->ycbcr444 = true; + edid->ycbcr422 = true; + edid->dc_30 = safe ? dc_30 : true; + edid->dc_36 = safe ? dc_36 : true; + +exit: + return rc; +} + +/** + * otm_hdmi_edid_parse() - fill capability table + * @ctx: hdmi context + * @use_edid: True or False + * + * This routine files capability table. + * + * Returns - check otm_hdmi_ret_t + */ +otm_hdmi_ret_t otm_hdmi_edid_parse(void *context, otm_hdmi_use_edid_t use_edid) +{ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + i2c_read_t edid_foo = ps_hdmi_i2c_edid_read; + bool cable = PD_ATTR_BOOL(ATTRS[OTM_HDMI_ATTR_ID_CABLE_STATUS]); + edid_info_t *edid; + unsigned int i; + hdmi_context_t *ctx = (hdmi_context_t *)context; + + /* Verify pointers */ + if (!ctx) { + rc = OTM_HDMI_ERR_INTERNAL; + goto exit; + } + /* Init locals */ + edid = &ctx->edid_int; + + /* Begin EDID update protection */ + mutex_lock(&ctx->modes_sema); + + /* Clear EDID */ + memset(edid, 0, sizeof(edid_info_t)); + + /* Setup reference table for parsing */ + edid->num_ref_timings = ctx->n_modes_ref; + edid->ref_timings = g_video_modes_ref; + + /* DTV mode will use static DTV timings directly */ + if (ctx->dtv) + goto edid_override; + + switch (use_edid) { + case OTM_HDMI_USE_EDID_REAL: + /* Try reading EDID. If reading failed pick overriding strategy + * based on cable status + */ + rc = edid_parse(edid, edid_foo, ctx, false); + if (rc != OTM_HDMI_SUCCESS) { + pr_debug("Failed to read EDID info\n"); + use_edid = cable ? OTM_HDMI_USE_EDID_SAFE : + OTM_HDMI_USE_EDID_NONE; + } + break; + case OTM_HDMI_USE_EDID_SAFE: + /* In safe mode we still need real EDID */ + edid_parse(edid, edid_foo, ctx, false); + break; + case OTM_HDMI_USE_EDID_NONE: + /* In full override mode we dont care of real EDID + * so do nothing + */ + break; + default: + rc = OTM_HDMI_ERR_FAILED; + goto exit; + } + + /* Dont bother with static timings if we are using real EDID */ + if (use_edid == OTM_HDMI_USE_EDID_REAL) + goto twin_caps; + +edid_override: + /* Use static timings */ + __hdmi_edid_override(ctx, edid, use_edid == OTM_HDMI_USE_EDID_SAFE); + + /* Insertion of twin entries below is done right in the parsed table of + * modes without knowledge of its maximum size. Be extra careful about + * it and check that MAX_TIMINGS is big enough; This needs to be fixed + * in long run + */ +twin_caps: + /* Insert 59.94 entries */ + hdmi_timing_add_twin_entries(edid, OTM_HDMI_REFRESH_60, + OTM_HDMI_REFRESH_59_94); + + /* Insert 29.97 entries */ + hdmi_timing_add_twin_entries(edid, OTM_HDMI_REFRESH_30, + OTM_HDMI_REFRESH_29_97); + + /* Insert 23.98 entries */ + hdmi_timing_add_twin_entries(edid, OTM_HDMI_REFRESH_24, + OTM_HDMI_REFRESH_23_98); + + /* Insert 47.96 entries */ + hdmi_timing_add_twin_entries(edid, OTM_HDMI_REFRESH_48, + OTM_HDMI_REFRESH_47_96); + + /* Adjust received timings */ + for (i = 0; i < edid->num_timings; i++) + hdmi_timing_edid_to_vdc(&edid->timings[i]); + + /* Print warning message in case there are no timings */ + if (ctx->edid_int.num_timings == 0) { + PD_LOG_ERROR + ("----------------- WARNING -----------------------\n"); + PD_LOG_ERROR + ("-- TV timings are not available --\n"); + PD_LOG_ERROR + ("-- To resolve this switch to static TV timings --\n"); + } + /* Update EDID availability indicator */ + PD_ATTR_UINT(ATTRS[OTM_HDMI_ATTR_ID_USE_EDID]) = use_edid; + + /* End EDID update protection */ + mutex_unlock(&ctx->modes_sema); + +exit: + return rc; +} + +/** + * otm_hdmi_timing_from_cea_modes() - get timings for cea modes + * @buffer: the extension block buffer + * @timings: the result CEA timings extacted from the buffer + * + * Returns - the number of modes in the timings + */ +int otm_hdmi_timing_from_cea_modes(unsigned char *buffer, + otm_hdmi_timing_t *timings) +{ + edid_info_t *edid = NULL; + + if (buffer == NULL) + return 0; + + if (timings == NULL) + return 0; + + if (g_context == NULL) + return 0; + + edid = &g_context->edid_int; + if (edid == NULL) + return 0; + + edid->num_ref_timings = g_context->n_modes_ref; + edid->ref_timings = g_video_modes_ref; + + return edid_parse_pd_timing_from_cea_block(edid, buffer, timings); +} + +/* + * otm_hdmi_get_mode_timings() - get timings of a mode, given: + * @ctx : HDMI context + * @hdisplay: mode width + * @vdisplay: mode height + * @vrefresh: mode refresh rate + * + * Returns matching mode, NULL otherwise. + */ +otm_hdmi_timing_t *otm_hdmi_get_mode_timings(void *context, + int hdisplay, + int vdisplay, + int vrefresh) +{ + otm_hdmi_timing_t *mode = NULL; + int i, refresh_rate; + + if (hdisplay < 0 || vdisplay < 0 || vrefresh < 0) + goto exit; + + for (i = 0; i < MAX_TIMINGS; i++) { + mode = g_video_modes[i]; + refresh_rate = ((mode->dclk * 1000) / + (mode->htotal * mode->vtotal)); + if (hdisplay == mode->width && + vdisplay == mode->height && + vrefresh == refresh_rate) + return mode; + } +exit: + return NULL; +} + +/* This routine fills given table with timings according to current unit version + * and subsequent use of table + */ +static int __init_tx_modes(hdmi_unit_revision_id_t unit_id, + const otm_hdmi_timing_t **table, + unsigned int max_size, bool reference) +{ + int i = 0; + +#define __ADD_MODE(mode) \ + do { \ + if (i < max_size) \ + table[i++] = mode; \ + else { \ + i = -1; \ + goto exit; \ + } \ + } while (0); + + /* The following 2D modes are supported on all unit revisions */ + __ADD_MODE(&MODE_640x480p5994_60); + __ADD_MODE(&MODE_720_1440x576i50); + __ADD_MODE(&MODE_720_1440x480i5994_60); + __ADD_MODE(&MODE_720x576p50); + __ADD_MODE(&MODE_720x480p5994_60); + __ADD_MODE(&MODE_1280x720p50); + __ADD_MODE(&MODE_1280x720p5994_60); + __ADD_MODE(&MODE_1920x1080i50); + __ADD_MODE(&MODE_1920x1080i5994_60); + __ADD_MODE(&MODE_1920x1080p24); + __ADD_MODE(&MODE_1920x1080p25); + __ADD_MODE(&MODE_1920x1080p30); + __ADD_MODE(&MODE_1920x1080p50); + __ADD_MODE(&MODE_1920x1080p5994_60); + + /* The following 3D modes are supported on all unit revisions */ + __ADD_MODE(&MODE_1280x720p50__SBSH2); + __ADD_MODE(&MODE_1280x720p5994_60__SBSH2); + __ADD_MODE(&MODE_1920x1080i50__SBSH2); + __ADD_MODE(&MODE_1920x1080i5994_60__SBSH2); + __ADD_MODE(&MODE_1920x1080p24__SBSH2); + __ADD_MODE(&MODE_1920x1080p50__SBSH2); + __ADD_MODE(&MODE_1920x1080p5994_60__SBSH2); + __ADD_MODE(&MODE_1280x720p50__TBH2); + __ADD_MODE(&MODE_1280x720p5994_60__TBH2); + __ADD_MODE(&MODE_1920x1080p24__TBH2); + __ADD_MODE(&MODE_1920x1080p30__TBH2); + __ADD_MODE(&MODE_1920x1080p50__TBH2); + __ADD_MODE(&MODE_1920x1080p5994_60__TBH2); + __ADD_MODE(&MODE_1280x720p50__FP2); + __ADD_MODE(&MODE_1920x1080p30__FP2); + + /* The following modes are only included if the table is used as a + * reference set for EDID parsing + */ + if (reference) { + __ADD_MODE(&MODE_720_1440x576i50__16by9); + __ADD_MODE(&MODE_720_1440x480i5994_60__16by9); + __ADD_MODE(&MODE_720x576p50__16by9); + __ADD_MODE(&MODE_720x480p5994_60__16by9); + } + /* The following mode are supported only on CE4200 B0 and further */ + if (unit_id >= HDMI_PCI_REV_CE4200_B0) { + __ADD_MODE(&MODE_1280x720p50__FP); + __ADD_MODE(&MODE_1280x720p5994_60__FP); + __ADD_MODE(&MODE_1920x1080i50__FP); + __ADD_MODE(&MODE_1920x1080i5994_60__FP); + __ADD_MODE(&MODE_1920x1080p24__FP); + __ADD_MODE(&MODE_1920x1080p30__FP); + } +#undef __ADD_MODE + +exit: + return i; +} + +/** + * otm_hdmi_phy_enable() - PHY power programming wrapper + * @ctx: hdmi context + * @status: status + * + * This routine is PHY power programming wrapper + * + * Returns - check otm_hdmi_ret_t + */ +otm_hdmi_ret_t __hdmi_phy_enable(void *context, bool status) +{ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + hdmi_context_t *ctx = (hdmi_context_t *)context; + + bool cable = PD_ATTR_BOOL(ATTRS + [OTM_HDMI_ATTR_ID_CABLE_STATUS]); +#ifdef SOC_HDCP_ENABLE + bool mute = PD_ATTR_BOOL(ATTRS + [OTM_HDMI_ATTR_ID_HDCP_AUTO_MUTE]); +#endif + /* Safety checks */ + if (ctx == NULL) { + rc = OTM_HDMI_ERR_INTERNAL; + goto exit; + } + + /* Override given setting based on current mode, cable status and + * hot plug processing state + * TODO - Fix timerisset + */ + status = status && ctx->mode_set + && cable /* && !timerisset(&ctx->phy_time) */ ; + + /* It's gonna take a while for HDCP to re-authenticate after phy + * enabling hence mute output to prevent premium content going out + * unencrypted + */ +#ifdef SOC_HDCP_ENABLE + if (PD_ATTR_BOOL(ATTRS[OTM_HDMI_ATTR_ID_HDCP]) && status && mute) + hdmi_mute(ctx, OTM_HDMI_MUTE_VIDEO, MUTE_SOURCE_HDCP); +#endif + + pr_debug("About to call hdmi_phy_enable\n"); + /* Program HW and update status indicator */ + + rc = hdmi_phy_enable(&ctx->dev, status); + if (rc != OTM_HDMI_SUCCESS) + goto exit; + ctx->phy_status = status; + + /* Debug print */ + PD_LOG_PRINT(PD_LOG_LEVEL_HIGH, "PHY -> %s\n", status ? "on" : "off"); + +exit: + return rc; +} + +/* Enable hdmi HW device */ +static otm_hdmi_ret_t __hdmi_enable(hdmi_context_t *ctx) +{ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + + /* Check context */ + if (ctx == NULL) { + rc = OTM_HDMI_ERR_INTERNAL; + goto exit; + } + + /* Disable PHY */ + rc = __hdmi_phy_enable(ctx, false); + pr_debug("phy_enable returned with %d\n", rc); + +#ifdef OTM_HDMI_FIXME + /* Setup and enable I2C subunit */ + rc = hdmi_i2c_reset_init_enable(ctx); + if (rc != OTM_HDMI_SUCCESS) + goto exit; + + /* Activate interrupts of interest */ + hdmi_interrupts_set_mask(&ctx->dev, HDMI_INTERRUPTS); + + /* Bring device to a known state */ + hdmi_general_pixel_clock_enable(&ctx->dev); + hdmi_general_tdms_clock_enable(&ctx->dev); + hdmi_general_audio_clock_enable(&ctx->dev); + hdmi_general_hdcp_clock_enable(&ctx->dev); + hdmi_general_5V_enable(&ctx->dev); +#endif + +#ifdef SOC_HDCP_ENABLE + hdmi_hdcp_disable(ctx); +#endif + +exit: + return rc; +} + +static void log_entry(void *uhandle, char *foo) +{ +#ifdef __HDMI_HAL_TRACE__ + PD_PRINT("%s: Entering %s\n", PD_NAME, foo); +#endif +} + +static void log_exit(void *uhandle, char *foo, int rc) +{ +#ifdef __HDMI_HAL_TRACE__ + PD_PRINT("%s: Exiting %s with %d\n", PD_NAME, foo, rc); +#endif +} + +/* Microseconds domain timer initialization */ +static void __poll_start(void *poll_timer) +{ + do_gettimeofday(poll_timer); +} + +/* Microseconds domain timeout verification */ +static bool __poll_timeout(void *poll_timer) +{ + struct timeval tv_stop; + do_gettimeofday(&tv_stop); + return TIME_DIFF(tv_stop, *((struct timeval *) poll_timer)) > + I2C_SW_TIMEOUT; +} + +static otm_hdmi_ret_t __hdmi_context_init(void *context, struct pci_dev *pdev) +{ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + hdmi_context_t *ctx = NULL; + unsigned int isr_address; + + PD_LOG_ENTRY(PD_LOG_LEVEL_HIGH); + + /* Verify pointers */ + if (context == NULL) { + rc = OTM_HDMI_ERR_INTERNAL; + goto exit; + } + ctx = (hdmi_context_t *)context; + + rc = ps_hdmi_pci_dev_init(ctx, pdev); + if (rc != OTM_HDMI_SUCCESS) + goto exit; + +#ifndef OTM_HDMI_FIXME +/* FIXME: this should come from IPIL */ +#define HDMI_INTERRUPT_STATUS 0x100C +#endif + /* Register for interrupt routine invocation at given interrupt */ + isr_address = (unsigned int)ctx->io_address + HDMI_INTERRUPT_STATUS; + + pr_debug("About to call initialize HAL members and io_address " + "is 0x%x\n", + (unsigned int)ctx->io_address); + + /* Initialize HAL; It's important that ALL entries are initialized!!! */ + ctx->dev.usleep = 0; + ctx->dev.log_entry = log_entry; + ctx->dev.log_exit = log_exit; + ctx->dev.poll_timer = &ctx->hal_timer; + ctx->dev.poll_start = __poll_start; + ctx->dev.poll_timeout = __poll_timeout; + ctx->dev.io_address = (unsigned int)ctx->io_address; + ctx->dev.io_address = (unsigned int)ctx->io_address; +#ifdef OTM_HDMI_FIXME + ctx->dev.io_read = ior; + ctx->dev.io_write = iow; +#endif + + ctx->dev.uhandle = ctx->io_address; + /* Create modes table sharing protection semaphore */ + mutex_init (&ctx->modes_sema); + + /* Create execution protection semaphore */ + mutex_init (&ctx->exec_sema); + + /* Create HPD protection semaphore */ + mutex_init (&ctx->hpd_sema); + + /* Create server thread synchronization semaphore */ + mutex_init (&ctx->srv_sema); + + /* Create server thread synchronization semaphore */ + mutex_init (&ctx->i2c_sema); + + /* Create AV mute synchronization semaphore */ + mutex_init (&ctx->mute_sema); + +exit: + PD_LOG_EXIT(PD_LOG_LEVEL_HIGH, rc); + return rc; +} + +void otm_hdmi_deinit(void *context) +{ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + hdmi_context_t *ctx = NULL; + + PD_LOG_ENTRY(PD_LOG_LEVEL_HIGH); + + /* Verify pointers */ + if (context == NULL) { + rc = OTM_HDMI_ERR_INTERNAL; + goto exit; + } + ctx = context; + +#ifdef OTM_HDMI_FIXME + /* Disable interrupts and unregister interrupts handling routine */ + hdmi_interrupts_set_mask(&ctx->dev, 0); + free_irq(ctx->irq_number, ctx); +#endif + /* Destroy semaphores */ + mutex_destroy(&ctx->modes_sema); + mutex_destroy(&ctx->exec_sema); + mutex_destroy(&ctx->hpd_sema); + mutex_destroy(&ctx->srv_sema); + mutex_destroy(&ctx->i2c_sema); + mutex_destroy(&ctx->mute_sema); + + /* Bring device to a known state */ +#ifdef OTM_HDMI_FIXME +#ifdef SOC_HDMI_VIDEO_ENABLE + hdmi_video_set_pixel_source(&ctx->dev, false); +#endif +#ifdef SOC_HDMI_INFOFRAMES_ENABLE + hdmi_infoframe_disable_all(&ctx->dev); +#endif +#endif + ipil_hdmi_general_unit_disable(&ctx->dev); +#ifdef OTM_HDMI_FIXME + /* Disable PHY */ + rc = __hdmi_phy_enable(ctx, false); + pr_debug("__hdmi_phy_enable returned with %d\n", rc); +#endif + ipil_hdmi_general_hdcp_clock_disable(&ctx->dev); + ipil_hdmi_general_5V_disable(&ctx->dev); + ipil_hdmi_general_audio_clock_disable(&ctx->dev); + ipil_hdmi_general_pixel_clock_disable(&ctx->dev); + ipil_hdmi_general_tdms_clock_disable(&ctx->dev); + ipil_hdmi_i2c_disable(&ctx->dev); + + /* Clearing audio information */ + ipil_hdmi_audio_deinit(ctx); + + /* Unmap IO region, Disable the PCI devices + */ + rc = ps_hdmi_pci_dev_deinit(ctx); + + /* Free context */ + kfree(ctx); + + pr_debug("Exiting deinit with error code %d\n", rc); +exit: + PD_LOG_EXIT(PD_LOG_LEVEL_HIGH, rc); + return; +} + +#ifndef OTM_HDMI_FIXME +otm_hdmi_ret_t hdmi_phy_enable(hdmi_device_t *dev, bool status) +{ + return OTM_HDMI_SUCCESS; +} + +otm_hdmi_ret_t hdmi_timing_add_twin_entries(edid_info_t *edid, + otm_hdmi_refresh_t src, + otm_hdmi_refresh_t dst) +{ + return OTM_HDMI_SUCCESS; +} + +void hdmi_timing_edid_to_vdc(otm_hdmi_timing_t *t) +{ + return; +} +#endif + +/* turn HDMI power rails on */ +bool otm_hdmi_power_rails_on() +{ + return ipil_hdmi_power_rails_on(); +} + +/* get pixel clock range */ +otm_hdmi_ret_t otm_hdmi_get_pixel_clock_range(unsigned int *pc_min, + unsigned int *pc_max) +{ + if (!pc_min || !pc_max) + return OTM_HDMI_ERR_FAILED; + + *pc_min = IPIL_MIN_PIXEL_CLOCK; + *pc_max = IPIL_MAX_PIXEL_CLOCK; + return OTM_HDMI_SUCCESS; +} + +/* + * Description: hdmi interrupt handler (upper half). + * handles the interrupts by reading hdmi status register + * and waking up bottom half if needed. + * + * @irq: irq number + * @data: data for the interrupt handler + * + * Returns: IRQ_HANDLED on NULL input arguments, and if the + * interrupt is not HDMI HPD interrupts. + * IRQ_WAKE_THREAD if this is a HDMI HPD interrupt. + */ +static irqreturn_t __hdmi_irq_handler(int irq, void *data) +{ + if (g_context != NULL) + return ipil_hdmi_irq_handler(&g_context->dev); + + return IRQ_HANDLED; +} + +/** + * otm_hdmi_setup_irq - install HPD IRQ call back + * @context: hdmi device context + * @pdev: pci device + * @phdmi_irq_cb: function pointer for hotplug/unplug IRQ callbacks. + * data: data for irq callback + * + * Perform HPD IRQ call back initialization + * + * Returns - check otm_hdmi_ret_t + */ +otm_hdmi_ret_t otm_hdmi_setup_irq(void *context, struct pci_dev *pdev, + irqreturn_t (*phdmi_irq_cb) (int, void*), + void *data) +{ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + hdmi_context_t *ctx = NULL; + int ret; + + /* Verify pointers */ + if (context == NULL) { + rc = OTM_HDMI_ERR_INTERNAL; + goto exit; + } + ctx = (hdmi_context_t *)context; + + /* Setup interrupt handler */ + if (phdmi_irq_cb != NULL && data != NULL) { + ret = request_threaded_irq(ctx->irq_number, + __hdmi_irq_handler, phdmi_irq_cb, + IRQF_SHARED,OTM_HDMI_NAME, (void *)data); + if (ret) { + pr_debug("\nregister irq interrupt failed\n"); + rc = OTM_HDMI_ERR_INTERNAL; + /* + * TODO: ignore failure as PCI is not working on DV1. + */ + goto exit; + } + } +exit: + return rc; + +} + +/** + * otm_hdmi_device_init - init hdmi device driver + * @context: hdmi device context + * @pdev: pci device + * + * Perform HDMI device initialization which includes 3 steps: + * 1) otm context create, + * 2) os specific context init, + * 3) device enable + * + * Returns - check otm_hdmi_ret_t + */ +otm_hdmi_ret_t otm_hdmi_device_init(void **context, struct pci_dev *pdev) +{ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + hdmi_context_t *ctx = NULL; + int n; + int ret; + + PD_LOG_ENTRY(PD_LOG_LEVEL_HIGH); + + /* Verify pointers */ + if (context == NULL) { + rc = OTM_HDMI_ERR_INTERNAL; + goto exit; + } + + /* Create and clear context */ + g_context = ctx = + (hdmi_context_t *) kmalloc(sizeof(hdmi_context_t), GFP_KERNEL); + if (ctx == NULL) { + rc = OTM_HDMI_ERR_NO_MEMORY; + goto exit; + } + memset(ctx, 0, sizeof(hdmi_context_t)); + + pr_debug("HDMI Context created = 0x%08x\n", (unsigned int)ctx); + + /* Init HDMI context */ + rc = __hdmi_context_init(ctx, pdev); + if (rc != OTM_HDMI_SUCCESS) { + pr_debug("\nHDMI Context init failed\n"); + goto exit; + } + + rc = otm_hdmi_declare_attributes(__pd_attr_declare, __pd_attr_get_name); + if (rc != OTM_HDMI_SUCCESS) { + pr_debug("\nHDMI declare attributes table failed\n"); + goto exit; + } + + ipil_hdmi_set_hdmi_dev(&ctx->dev); + + /* Decide on I2C HW acceleration */ + ipil_hdmi_decide_I2C_HW(ctx); + + /* Save the output mode as DTV or HDMT tx */ + ctx->dtv = g_dtv; + + /* Save the deep color enable flag */ + ctx->dc = g_dc; + + /* Explicitly disable 5V before enabling it later as transition from + * off to on seems to be responsible to hot plug generation during + * starup */ + ipil_hdmi_general_5V_disable(&ctx->dev); + + /* Save active GPIO number */ + ctx->gpio = g_gpio; + + /* Save context */ + *context = ctx; + + /* Setup all external clocks */ + rc = ipil_hdmi_set_program_clocks(ctx, 27000); + if (rc != OTM_HDMI_SUCCESS) + goto exit; + + /* Fill in static timing table */ + n = __init_tx_modes(ctx->dev.id, g_video_modes, MAX_TIMINGS, + false); + if (n < 0) { + rc = OTM_HDMI_ERR_NO_MEMORY; + goto exit; + } + ctx->n_modes_tx = n; + + /* Fill EDID parser reference timing table */ + n = __init_tx_modes(ctx->dev.id, g_video_modes_ref, MAX_TIMINGS, + true); + if (n < 0) { + rc = OTM_HDMI_ERR_NO_MEMORY; + goto exit; + } + ctx->n_modes_ref = n; + + /* Fill in advertised timings table */ + otm_hdmi_edid_parse(ctx, OTM_HDMI_USE_EDID_NONE); + +#ifdef OTM_HDMI_FIXME + /* Enable HDMI unit */ + rc = __hdmi_enable(ctx); + if (rc != OTM_HDMI_SUCCESS) + goto exit; +#endif + rc = ipil_hdmi_audio_init(ctx); + if (rc != OTM_HDMI_SUCCESS) + goto exit; + +exit: + /* Clean up if appropriate */ + if ((rc != OTM_HDMI_SUCCESS) && (ctx != NULL)) + otm_hdmi_deinit((void *)ctx); + + PD_LOG_EXIT(PD_LOG_LEVEL_HIGH, rc); + return rc; +} + +bool otm_hdmi_is_preferred_mode(int hdisplay, int vdisplay, int refresh) +{ + if (hdisplay == IPIL_PREFERRED_HDISPLAY && + vdisplay == IPIL_PREFERRED_VDISPLAY && + refresh == IPIL_PREFERRED_REFRESH_RATE) + return true; + else + return false; +} + +otm_hdmi_ret_t otm_hdmi_set_raw_edid(void *context, char *raw_edid) +{ + hdmi_context_t *ctx = (hdmi_context_t *)context; + + if (ctx == NULL) + return OTM_HDMI_ERR_FAILED; + + /* TODO: need more flexiable way which should be edid size-aware copy */ + memcpy(ctx->edid_raw, raw_edid, MAX_EDID_BLOCKS * SEGMENT_SIZE); + + return OTM_HDMI_SUCCESS; +} + +otm_hdmi_ret_t otm_hdmi_get_raw_edid(void *context, char **raw_edid) +{ + hdmi_context_t *ctx = (hdmi_context_t *)context; + + if (ctx == NULL || raw_edid == NULL) + return OTM_HDMI_ERR_FAILED; + + *raw_edid = (char *)ctx->edid_raw; + + return OTM_HDMI_SUCCESS; +} + +bool otm_hdmi_is_monitor_hdmi(void *context) +{ + hdmi_context_t *ctx = (hdmi_context_t *)context; + + if (ctx == NULL) + return true; /* default to HDMI */ + + return ctx->edid_int.hdmi; +} + +/* + * HDMI video mute handling + */ +void hdmi_mute(hdmi_context_t *ctx, otm_hdmi_mute_t type, mute_source_t source) +{ +#ifdef OTM_HDMI_FIXME + unsigned int color = PD_ATTR_UINT(ATTRS[OTM_HDMI_ATTR_ID_BG_COLOR]); + hdmi_video_set_pixel_color(&ctx->dev, color); +#endif + mutex_lock(&ctx->mute_sema); + if (type & OTM_HDMI_MUTE_VIDEO) { + /* + * Update mute list and mute video + */ + ctx->mute_source |= source; +#ifdef OTM_HDMI_FIXME + hdmi_video_set_pixel_source(&ctx->dev, false); +#endif + } else { + /* + * Update mute list and unmute video [if possible] + */ + ctx->mute_source &= ~source; +#ifdef OTM_HDMI_FIXME + hdmi_video_set_pixel_source(&ctx->dev, ctx->mute_source == 0); +#endif + } + mutex_unlock(&ctx->mute_sema); +} + +/* + * __check_opd_support() + */ +static otm_hdmi_ret_t __check_opd_support(otm_hdmi_output_pixel_depth_t depth, + bool depth_30, + bool depth_36) +{ + otm_hdmi_ret_t rc = OTM_HDMI_ERR_INTERNAL; + + switch (depth) { + case OTM_HDMI_OPD_24BIT: + rc = OTM_HDMI_SUCCESS; + break; + case OTM_HDMI_OPD_30BIT: + rc = depth_30 ? OTM_HDMI_SUCCESS : rc; + break; + case OTM_HDMI_OPD_36BIT: + rc = depth_36 ? OTM_HDMI_SUCCESS : rc; + break; + default: + rc = OTM_HDMI_ERR_INTERNAL; + break; + } + + return rc; +} + +/* + * __check_pixel_depth_cfg() + */ +static otm_hdmi_ret_t __check_pixel_depth_cfg( + otm_hdmi_output_pixel_format_t opf, + otm_hdmi_output_pixel_depth_t opd) +{ + bool rc = (opf != OTM_HDMI_OPF_YUV422) + || (opd == OTM_HDMI_OPD_24BIT); + return rc ? OTM_HDMI_SUCCESS : OTM_HDMI_ERR_INTERNAL; +} + +/* + * __check_opf_support() + */ +static otm_hdmi_ret_t __check_opf_support(otm_hdmi_output_pixel_format_t format, + bool yuv444, + bool yuv422) +{ + otm_hdmi_ret_t rc = OTM_HDMI_ERR_INTERNAL; + bool ext_color = + PD_ATTR_BOOL(ATTRS[OTM_HDMI_ATTR_ID_COLOR_SPACE_EXT]); + + switch (format) { + case OTM_HDMI_OPF_YUV444: + rc = yuv444 ? OTM_HDMI_SUCCESS : rc; + break; + case OTM_HDMI_OPF_YUV422: + rc = yuv422 ? OTM_HDMI_SUCCESS : rc; + break; + case OTM_HDMI_OPF_RGB444: + rc = (!ext_color) ? OTM_HDMI_SUCCESS : rc; + break; + default: + rc = OTM_HDMI_ERR_INTERNAL; + break; + } + + return rc; +} + +/* + * __set_attr_csc() + */ +static otm_hdmi_ret_t __set_attr_csc(hdmi_context_t *ctx) +{ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + int in, out; + + if (NULL == ctx) { + PD_LOG_ERROR("Invalid argument passed (ctx)\n"); + rc = OTM_HDMI_ERR_FAILED; + goto exit; + } + /* + * Set CSC appropriately + */ + out = PD_ATTR_UINT(ATTRS[OTM_HDMI_ATTR_ID_PIXEL_FORMAT_OUTPUT]); + in = PD_ATTR_UINT(ATTRS[OTM_HDMI_ATTR_ID_COLOR_SPACE_INPUT]); +#ifdef OTM_HDMI_FIXME + rc = hdmi_configure_csc(&ctx->dev, in, out, &ctx->mode); +#endif + +exit: + return rc; +} + +/** + * otm_hdmi_attr_set_validate - validates the attribute to + * be written or not. + * + * Write's the attributes value. + * + * Returns - + * OTM_HDMI_SUCCESS - if the attribute value is writable. + * OTM_HDMI_ERR_INTERNAL - if the attribute value is non-writable. + * OTM_HDMI_ERR_FAILED - if the attribute is not in range. + */ +static otm_hdmi_ret_t otm_hdmi_attr_set_validate(otm_hdmi_attribute_id_t id, + void *value) +{ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + bool _bool; + unsigned int _uint; + char *_string = NULL; + int str_len = 0; + + if (id < 0 || id > OTM_HDMI_MAX_SUPPORTED_ATTRIBUTES) { + PD_LOG_ERROR("Invalid argument passed (id): %d\n", id); + rc = OTM_HDMI_ERR_FAILED; + goto exit; + } + if (NULL == value) { + PD_LOG_ERROR("Invalid argument passed (value): %d\n", id); + rc = OTM_HDMI_ERR_FAILED; + goto exit; + } + + if (OTM_HDMI_ATTR_FLAG_WRITE != ATTRS[id].flags) { + PD_LOG_ERROR("Attribute id: %d is read-only\n", id); + rc = OTM_HDMI_ERR_FAILED; + goto exit; + } + + /* + * Based on attribute type perform appropriate check + */ + switch (ATTRS[id].type) { + case OTM_HDMI_ATTR_TYPE_BOOLEAN: + _bool = *(bool *) value; + if ((_bool != true) && (_bool != false)) + rc = OTM_HDMI_ERR_FAILED; + break; + + case OTM_HDMI_ATTR_TYPE_UINT: + _uint = *(unsigned int *)value; + if ((_uint < ATTRS[id].content._uint.value_min) + || (_uint > ATTRS[id].content._uint.value_max)) { + rc = OTM_HDMI_ERR_FAILED; + } + break; + + case OTM_HDMI_ATTR_TYPE_STRING: + _string = (char *) value; + str_len = strlen(_string); + if (str_len < 1 || str_len > OTM_HDMI_MAX_STRING_LENGTH) { + rc = OTM_HDMI_ERR_FAILED; + goto exit; + } + break; + default: + PD_LOG_ERROR("Invalid attribute id (%d)\n", id); + rc = OTM_HDMI_ERR_FAILED; + break; + } + +exit: + PD_LOG_EXIT(PD_LOG_LEVEL_HIGH, rc); + return rc; +} + +/* + * Setting given attribute + * @param [in] context : port driver specific information + * @param [in] id : attribute id + * @param [in] data : user provided buffer with attribute value + * @param [in] internal : internal [driver] or external [app] call + + * Note: Some attributes settings can not be applied until mode change was done. + * Hence such attributes are set logically and the actual HW will be set during + * mode change. + */ +otm_hdmi_ret_t otm_hdmi_set_attribute(void *context, + otm_hdmi_attribute_id_t id, + void *data, + bool internal) +{ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + hdmi_context_t *ctx = (hdmi_context_t *) context; +#ifdef OTM_HDMI_FIXME + gdl_display_id_t pipe = + PD_ATTR_UINT(ATTRS[OTM_HDMI_ATTR_ID_DISPLAY_PIPE]); + otm_hdmi_ret_t rc1, rc2; + bool hdcp_ctrl = PD_ATTR_BOOL(ATTRS[OTM_HDMI_ATTR_ID_HDCP]); + otm_hdmi_hdcp_status_t hdcp_status = + PD_ATTR_UINT(ATTRS[OTM_HDMI_ATTR_ID_HDCP_STATUS]); +#endif + bool pwr = PD_ATTR_BOOL(ATTRS[OTM_HDMI_ATTR_ID_POWER]); + edid_info_t *edid; + bool abool; + unsigned int auint, out, depth; + otm_hdmi_attribute_flag_t flags; + PD_LOG_ENTRY(PD_LOG_LEVEL_HIGH); + + if (NULL == ctx) { + PD_LOG_ERROR("Invalid argument passed (context): %d\n", id); + rc = OTM_HDMI_ERR_FAILED; + goto exit; + } + flags = + OTM_HDMI_ATTR_FLAG_WRITE | + (internal ? OTM_HDMI_ATTR_FLAG_INTERNAL : 0); + + rc = otm_hdmi_attr_set_validate(id, data); + if (OTM_HDMI_SUCCESS != rc) + goto exit; + abool = *(bool *) (data); + auint = *(unsigned int *) (data); + PD_LOG_PRINT(PD_LOG_LEVEL_HIGH, "ATTR[%d] -> %d\n", id, auint); + +#ifdef OTM_HDMI_FIXME + /* + * If not on pipe 0 all requests + * [except new pipe setting] must be rejected + */ + if (pipe == GDL_DISPLAY_ID_UNDEFINED + && id != OTM_HDMI_ATTR_ID_DISPLAY_PIPE) { + rc = OTM_HDMI_ERR_FAILED; + goto exit; + } + + rc = __update_edid(ctx); + if (rc != OTM_HDMI_SUCCESS) { + PD_LOG_ERROR("ERR: %s at %d code = %d\n", + __func__, __LINE__, rc); + goto exit; + } +#endif + edid = &ctx->edid_ext; + + switch (id) { + case OTM_HDMI_ATTR_ID_PIXEL_FORMAT_OUTPUT: + out = auint; + depth = + ctx->dc ? PD_ATTR_UINT(ATTRS + [OTM_HDMI_ATTR_ID_PIXEL_DEPTH]) : + OTM_HDMI_OPD_24BIT; + rc = __check_opf_support(out, edid->ycbcr444, edid->ycbcr422); + if (OTM_HDMI_SUCCESS != rc) + goto exit; + rc = __check_pixel_depth_cfg(out, depth); + if (OTM_HDMI_SUCCESS != rc) + goto exit; +#ifdef OTM_HDMI_FIXME + rc = ctx->support->pd_setmode_required(pipe); + if (rc != OTM_HDMI_SUCCESS) { + PD_LOG_ERROR("ERR: %s at %d code = %d\n", + __func__, __LINE__, rc); + goto exit; + } +#endif + break; + + case OTM_HDMI_ATTR_ID_PIXEL_DEPTH: + if (false == ctx->dc) { + rc = OTM_HDMI_ERR_FAILED; + goto exit; + } + depth = auint; + out = PD_ATTR_UINT(ATTRS + [OTM_HDMI_ATTR_ID_PIXEL_FORMAT_OUTPUT]); + + rc = __check_opd_support(depth, edid->dc_30, edid->dc_36); + if (OTM_HDMI_SUCCESS != rc) + goto exit; + + rc = __check_pixel_depth_cfg(out, depth); + if (OTM_HDMI_SUCCESS != rc) + goto exit; + +#ifdef OTM_HDMI_FIXME + rc = ctx->support->pd_setmode_required(pipe); + if (rc != OTM_HDMI_SUCCESS) { + PD_LOG_ERROR("ERR: %s at %d code = %d\n", + __func__, __LINE__, rc); + goto exit; + } +#endif + break; + + case OTM_HDMI_ATTR_ID_HDCP: + if (true == ctx->dtv) { + rc = OTM_HDMI_ERR_FAILED; + goto exit; + } +#ifdef OTM_HDMI_FIXME + rc = (abool != hdcp_ctrl) ? service_hdcp_set(ctx, abool, + !abool) : + OTM_HDMI_SUCCESS; +#endif + if (OTM_HDMI_SUCCESS != rc) + goto exit; + break; +#ifdef OTM_HDMI_FIXME + case OTM_HDMI_ATTR_ID_BG_COLOR: + rc = hdmi_video_set_pixel_color(&ctx->dev, auint); + if (rc != OTM_HDMI_SUCCESS) { + PD_LOG_ERROR("ERR: %s at %d code = %d\n", + __func__, __LINE__, rc); + goto exit; + } + break; +#endif + case OTM_HDMI_ATTR_ID_USE_EDID: + if (true == ctx->dtv) { + rc = OTM_HDMI_ERR_FAILED; + goto exit; + } + + rc = otm_hdmi_edid_parse(ctx, auint); + if (OTM_HDMI_SUCCESS != rc) + goto exit; +#ifdef OTM_HDMI_FIXME + rc = ctx->support->pd_setmode_required(pipe); + if (rc != OTM_HDMI_SUCCESS) { + PD_LOG_ERROR("ERR: %s at %d code = %d\n", + __func__, __LINE__, rc); + goto exit; + } +#endif + break; + + case OTM_HDMI_ATTR_ID_POWER: + if (abool != pwr) { + /* + * When shutting down the PHY also disable HDCP + * Some sinks are picky to PHY going off + * when input is encrypted PHY enabling expects + * HDCP to be off for unmute to happen + */ + if (!abool) { +#ifdef OTM_HDMI_FIXME + rc = service_hdcp_set(ctx, false, + true); + if (rc != OTM_HDMI_SUCCESS) { + PD_LOG_ERROR("ERR: %s at %d code :%d\n", + __func__, __LINE__, rc); + goto exit; + } +#endif + } + rc = hdmi_phy_enable(&(ctx->dev), abool); + if (OTM_HDMI_SUCCESS != rc) + goto exit; +#ifdef OTM_HDMI_FIXME + ctx->support->pd_submit_event + (GDL_APP_EVENT_PHY_STATUS_CHANGE); +#endif + } + break; + + case OTM_HDMI_ATTR_ID_SLOW_DDC: +#ifdef OTM_HDMI_FIXME + rc = hdmi_i2c_set_ddc_speed(&ctx->dev, abool); + if (rc != OTM_HDMI_SUCCESS) { + PD_LOG_ERROR("ERR: %s at %d code = %d\n", + __func__, __LINE__, rc); + goto exit; + } +#endif + break; + + case OTM_HDMI_ATTR_ID_COLOR_SPACE_EXT: + if (abool) { + /* + * xvYCC colorimetry can only be set + * if we are outputing YCbCr + */ + out = PD_ATTR_UINT(ATTRS + [OTM_HDMI_ATTR_ID_PIXEL_FORMAT_OUTPUT]); + if (OTM_HDMI_OPF_RGB444 == out) { + rc = OTM_HDMI_ERR_FAILED; + goto exit; + } +#ifdef OTM_HDMI_FIXME + /* + * xvYCC colorimetry can only be set + * if we are sending gamut packets + */ + rc1 = + hdmi_packet_check_type(&ctx->pi_0.packet, + HDMI_PACKET_GAMUT); + rc2 = + hdmi_packet_check_type(&ctx->pi_1.packet, + HDMI_PACKET_GAMUT); +#endif + } + if (false == ctx->usr_avi) { + rc = OTM_HDMI_ERR_FAILED; + goto exit; + } + break; + + case OTM_HDMI_ATTR_ID_DISPLAY_PIPE: +#ifdef OTM_HDMI_FIXME + if (GDL_DISPLAY_ID_1 == auint) { + rc = OTM_HDMI_ERR_FAILED; + goto exit; + } + if (pipe == pipe) + goto exit; + rc = __switch_pipe(ctx); + if (rc != OTM_HDMI_SUCCESS) { + PD_LOG_ERROR("ERR: %s at %d code = %d\n", + __func__, __LINE__, rc); + goto exit; + } +#endif + break; + + case OTM_HDMI_ATTR_ID_MUTE: + /* + * Audio mute is handled indirectly + * during writes based on attribute value + * Video mute needs to be handled directly + */ + hdmi_mute(ctx, auint, MUTE_SOURCE_APP); + break; + + case OTM_HDMI_ATTR_ID_PURE_VIDEO: +#ifdef OTM_HDMI_FIXME + rc = hdmi_video_set_video_indicator(&ctx->dev, abool); + if (rc != OTM_HDMI_SUCCESS) { + PD_LOG_ERROR("ERR: %s at %d code = %d\n", + __func__, __LINE__, rc); + goto exit; + } +#endif + break; + + case OTM_HDMI_ATTR_ID_OUTPUT_DITHER: +#ifdef OTM_HDMI_FIXME + rc = ctx->support->pd_setmode_required(pipe); + if (rc != OTM_HDMI_SUCCESS) { + PD_LOG_ERROR("ERR: %s at %d code = %d\n", + __func__, __LINE__, rc); + goto exit; + } +#endif + break; + + case OTM_HDMI_ATTR_ID_HDCP_ENCRYPT: +#ifdef OTM_HDMI_FIXME + rc = hdmi_hdcp_set_enc(ctx, abool && HDCP_OFF != hdcp_status); + if (rc != OTM_HDMI_SUCCESS) { + PD_LOG_ERROR("ERR: %s at %d code = %d\n", + __func__, __LINE__, rc); + goto exit; + } +#endif + break; + + case OTM_HDMI_ATTR_ID_DVI: +#ifdef OTM_HDMI_FIXME + rc = ctx->support->pd_setmode_required(pipe); + if (rc != OTM_HDMI_SUCCESS) { + PD_LOG_ERROR("ERR: %s at %d code = %d\n", + __func__, __LINE__, rc); + goto exit; + } +#endif + break; + + case OTM_HDMI_ATTR_ID_PAR: + case OTM_HDMI_ATTR_ID_FAR: + if (false == ctx->usr_avi) { + rc = OTM_HDMI_ERR_FAILED; + goto exit; + } + break; + + default: + break; + } + +#ifdef OTM_HDMI_FIXME + rc = ctx->support->pd_attr_set(ATTRS, id, data, flags); + if (rc != OTM_HDMI_SUCCESS) { + PD_LOG_ERROR("ERR: %s at %d code = %d\n", + __func__, __LINE__, rc); + goto exit; + } +#endif + /* + * Post processing [here we call routines + * that rely on the value in the ATTR + * table which are not yet available + * during the switch statement above + */ + switch (id) { + case OTM_HDMI_ATTR_ID_COLOR_SPACE_INPUT: + rc = (ctx->mode_set) ? __set_attr_csc(ctx) : rc; + break; + + case OTM_HDMI_ATTR_ID_OUTPUT_CLAMP: + rc = (ctx->mode_set) ? __set_attr_csc(ctx) : rc; + if (false == ctx->usr_avi) + goto exit; + + case OTM_HDMI_ATTR_ID_PAR: + case OTM_HDMI_ATTR_ID_FAR: + case OTM_HDMI_ATTR_ID_COLOR_SPACE_EXT: + rc = (ctx->mode_set) ? + otm_hdmi_infoframes_set_avi(ctx, + &ctx->mode) : rc; + break; + + default: + break; + } + +exit: + PD_LOG_EXIT(PD_LOG_LEVEL_HIGH, rc); + return rc; +} +EXPORT_SYMBOL(otm_hdmi_set_attribute); + +/** + * otm_hdmi_attr_get_validate - validates the attribute + * to be read or not. + * + * Read's the attributes flag value. + * + * Returns - + * OTM_HDMI_SUCCESS - if the attribute is readable. + * OTM_HDMI_ERR_INTERNAL - if the attribute is non-readable. + * OTM_HDMI_ERR_FAILED - if the attribute is not in range. + */ +static otm_hdmi_ret_t otm_hdmi_attr_get_validate(otm_hdmi_attribute_id_t id) +{ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + if (id < 0 || id > OTM_HDMI_MAX_SUPPORTED_ATTRIBUTES) { + PD_LOG_ERROR("Invalid argument passed (id): %d\n", id); + rc = OTM_HDMI_ERR_FAILED; + goto exit; + } + /* + * Based on attribute type perform appropriate check + */ + switch (ATTRS[id].flags) { + case OTM_HDMI_ATTR_FLAG_WRITE: + break; + + case OTM_HDMI_ATTR_FLAG_SUPPORTED: + /* + * Needs a Fix. + */ + rc = OTM_HDMI_SUCCESS; + break; + + case OTM_HDMI_ATTR_FLAG_INTERNAL: + rc = OTM_HDMI_ERR_INTERNAL; + break; + default: + PD_LOG_ERROR("Invalid attribute accessed: (%d)\n", id); + rc = OTM_HDMI_ERR_FAILED; + break; + } +exit: + PD_LOG_EXIT(PD_LOG_LEVEL_HIGH, rc); + return rc; +} + +/* + * Getting given attribute + * @param [in ] id : attribute id + * @param [out] data : user provided buffer for attribute details + * @param [in ] log : a hint wether port driver should log the call + */ +otm_hdmi_ret_t otm_hdmi_get_attribute(void *context, + otm_hdmi_attribute_id_t id, + otm_hdmi_attribute_t *attribute, + bool log) +{ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + PD_LOG_ENTRY((log) ? PD_LOG_LEVEL_HIGH : PD_LOG_LEVEL_VBLANK); + + rc = otm_hdmi_attr_get_validate(id); + if (OTM_HDMI_SUCCESS != rc) + goto exit; + if (NULL == attribute || NULL == context) { + PD_LOG_ERROR("Invalid argument passed (attribute): %d\n", id); + rc = OTM_HDMI_ERR_FAILED; + goto exit; + } + + *attribute = ATTRS[id]; +exit: + PD_LOG_EXIT((log) ? PD_LOG_LEVEL_HIGH : PD_LOG_LEVEL_VBLANK, rc); + return rc; +} +EXPORT_SYMBOL(otm_hdmi_get_attribute); + +/** + * Attribute name getting routine + */ +char *__pd_attr_get_name(otm_hdmi_attribute_id_t id) +{ + otm_hdmi_attribute_t *table = otm_hdmi_attributes_table; + + if ((0 <= id) && (id < OTM_HDMI_MAX_SUPPORTED_ATTRIBUTES)) + return table[id].name; + else + return NULL; +} +EXPORT_SYMBOL(__pd_attr_get_name); + +/** + * Generic attribute declaration routine + */ +static otm_hdmi_ret_t __pd_attr_declare(otm_hdmi_attribute_t *table, + otm_hdmi_attribute_id_t id, + otm_hdmi_attribute_type_t type, + otm_hdmi_attribute_flag_t flags, + char *name, + void *value, + unsigned int min, + unsigned int max) +{ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + + if ((id < 0) || (id > OTM_HDMI_MAX_SUPPORTED_ATTRIBUTES)) + return OTM_HDMI_ERR_FAILED; + + if ((name != NULL) && (strlen(name) < OTM_HDMI_MAX_STRING_LENGTH)) + strncpy(table[id].name, name, strlen(name)); + else if (strlen(table[id].name) == 0) + PD_LOG_ERROR("set default name\n"); + /* TODO: set default name */ + + table[id].flags = flags; + + switch (type) { + case OTM_HDMI_ATTR_TYPE_UINT: + table[id].content._uint.value_default = + (unsigned int) value; + table[id].content._uint.value_min = min; + table[id].content._uint.value_max = max; + break; + case OTM_HDMI_ATTR_TYPE_BOOLEAN: + table[id].content._bool.value_default = + (bool) value; + break; + case OTM_HDMI_ATTR_TYPE_STRING: + if ((value != NULL) && + strlen(value) < OTM_HDMI_MAX_STRING_LENGTH) + strncpy(table[id].content.string.value, + (char *) value, + strlen(value)); + else + rc = OTM_HDMI_ERR_FAILED; + break; + default: + break; + } + return rc; +} + +/** + * otm_hdmi_declare_attributes - init hdmi global attributes table + * + * Returns - check otm_hdmi_ret_t + */ +otm_hdmi_ret_t otm_hdmi_declare_attributes(pd_attr_declare_t declare, + pd_attr_get_name_t get_name) +{ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + + otm_hdmi_attribute_t *table = otm_hdmi_attributes_table; + + PD_LOG_ENTRY(PD_LOG_LEVEL_HIGH); + + /* + * declare(table, OTM_HDMI_ATTR_ID_NAME, + * OTM_HDMI_ATTR_TYPE_STRING, PD_ATTR_FLAGS_RS, + * get_name(OTM_HDMI_ATTR_ID_NAME), + * (void *) PD_NAME, 0, 0); + */ + + PD_DECLARE_ATTRIBUTE_STRING(declare, table, + OTM_HDMI_ATTR_ID_NAME, + PD_ATTR_FLAGS_RS, get_name, PD_NAME); + + PD_DECLARE_ATTRIBUTE_BOOL(declare, table, + OTM_HDMI_ATTR_ID_CABLE_STATUS, + PD_ATTR_FLAGS_RS, get_name, false); + + PD_DECLARE_ATTRIBUTE_BOOL(declare, table, + OTM_HDMI_ATTR_ID_POWER, + PD_ATTR_FLAGS_RWS, get_name, true); + + PD_DECLARE_ATTRIBUTE_BOOL(declare, table, + OTM_HDMI_ATTR_ID_HDCP, + PD_ATTR_FLAGS_RWS, get_name, true); + + PD_DECLARE_ATTRIBUTE_BOOL(declare, table, + OTM_HDMI_ATTR_ID_HDCP_AUTO_MUTE, + PD_ATTR_FLAGS_RWS, get_name, true); + + PD_DECLARE_ATTRIBUTE_UINT(declare, table, + OTM_HDMI_ATTR_ID_HDCP_STATUS, + PD_ATTR_FLAGS_RS, get_name, + OTM_HDMI_HDCP_STATUS_OFF, + OTM_HDMI_HDCP_STATUS_OFF, + OTM_HDMI_HDCP_STATUS_ON); + + PD_DECLARE_ATTRIBUTE_BOOL(declare, table, + OTM_HDMI_ATTR_ID_HDCP_ENCRYPT, + PD_ATTR_FLAGS_RWS, get_name, true); + + PD_DECLARE_ATTRIBUTE_UINT(declare, table, + OTM_HDMI_ATTR_ID_COLOR_SPACE_INPUT, + PD_ATTR_FLAGS_RWSI, + get_name, + OTM_HDMI_COLOR_SPACE_RGB, + 0, OTM_HDMI_COLOR_SPACE_COUNT - 1); + + PD_DECLARE_ATTRIBUTE_UINT(declare, table, + OTM_HDMI_ATTR_ID_PIXEL_FORMAT_OUTPUT, + PD_ATTR_FLAGS_RWS, get_name, + OTM_HDMI_OPF_RGB444, 0, OTM_HDMI_OPF_COUNT - 1); + + PD_DECLARE_ATTRIBUTE_UINT(declare, table, + OTM_HDMI_ATTR_ID_PIXEL_DEPTH, + PD_ATTR_FLAGS_RWS, + get_name, + OTM_HDMI_OPD_24BIT, + 0, OTM_HDMI_PIXEL_DEPTH_COUNT - 1); + + PD_DECLARE_ATTRIBUTE_UINT(declare, table, + OTM_HDMI_ATTR_ID_BG_COLOR, + PD_ATTR_FLAGS_RWS, + get_name, 0xFF0000, 0x000000, 0xFFFFFF); + + PD_DECLARE_ATTRIBUTE_UINT(declare, table, + OTM_HDMI_ATTR_ID_USE_EDID, + PD_ATTR_FLAGS_RWS, + get_name, + OTM_HDMI_USE_EDID_REAL, + OTM_HDMI_USE_EDID_NONE, + OTM_HDMI_USE_EDID_SAFE); + + PD_DECLARE_ATTRIBUTE_UINT(declare, table, + OTM_HDMI_ATTR_ID_DEBUG, + PD_ATTR_FLAGS_RWS, + get_name, + PD_LOG_LEVEL_ERROR, + __PD_LOG_LEVEL_MIN, __PD_LOG_LEVEL_MAX); + + PD_DECLARE_ATTRIBUTE_UINT(declare, table, + OTM_HDMI_ATTR_ID_VERSION_MAJOR, + PD_ATTR_FLAGS_RS, get_name, 0, 0, 100); + + PD_DECLARE_ATTRIBUTE_UINT(declare, table, + OTM_HDMI_ATTR_ID_VERSION_MINOR, + PD_ATTR_FLAGS_RS, get_name, 4, 0, 9); + + PD_DECLARE_ATTRIBUTE_STRING(declare, table, + OTM_HDMI_ATTR_ID_BUILD_DATE, + PD_ATTR_FLAGS_RS, get_name, __DATE__); + + PD_DECLARE_ATTRIBUTE_STRING(declare, table, + OTM_HDMI_ATTR_ID_BUILD_TIME, + PD_ATTR_FLAGS_RS, get_name, __TIME__); + + PD_DECLARE_ATTRIBUTE_UINT(declare, table, + OTM_HDMI_ATTR_ID_DISPLAY_PIPE, + PD_ATTR_FLAGS_RWS, + get_name, + OTM_HDMI_DISPLAY_ID_0, + OTM_HDMI_DISPLAY_ID_0, + OTM_HDMI_DISPLAY_ID_UNDEFINED); + + PD_DECLARE_ATTRIBUTE_UINT(declare, table, + OTM_HDMI_ATTR_ID_PAR, + PD_ATTR_FLAGS_RWS, + get_name, + OTM_HDMI_PAR_NO_DATA, + OTM_HDMI_PAR_NO_DATA, + OTM_HDMI_PAR_16_9); + + PD_DECLARE_ATTRIBUTE_UINT(declare, table, + OTM_HDMI_ATTR_ID_FAR, + PD_ATTR_FLAGS_RWS, + get_name, + OTM_HDMI_FAR_SAME_AS_PAR, + OTM_HDMI_FAR_16_9_TOP, + OTM_HDMI_FAR_16_9_SP_4_3); + + PD_DECLARE_ATTRIBUTE_BOOL(declare, table, + OTM_HDMI_ATTR_ID_SLOW_DDC, + PD_ATTR_FLAGS_RWS, get_name, true); + + PD_DECLARE_ATTRIBUTE_UINT(declare, table, + OTM_HDMI_ATTR_ID_AUDIO_CLOCK, + PD_ATTR_FLAGS_RWS, + get_name, + OTM_HDMI_AUDIO_CLOCK_36, + OTM_HDMI_AUDIO_CLOCK_24, + OTM_HDMI_AUDIO_CLOCK_16); + + PD_DECLARE_ATTRIBUTE_BOOL(declare, table, + OTM_HDMI_ATTR_ID_AUDIO_STATUS, + PD_ATTR_FLAGS_RS, get_name, false); + + PD_DECLARE_ATTRIBUTE_UINT(declare, table, + OTM_HDMI_ATTR_ID_TMDS_DELAY, + PD_ATTR_FLAGS_RWS, get_name, 400, 100, 500); + + PD_DECLARE_ATTRIBUTE_BOOL(declare, table, + OTM_HDMI_ATTR_ID_COLOR_SPACE_EXT, + PD_ATTR_FLAGS_RWS, get_name, false); + + PD_DECLARE_ATTRIBUTE_BOOL(declare, table, + OTM_HDMI_ATTR_ID_OUTPUT_CLAMP, + PD_ATTR_FLAGS_RWS, get_name, true); + + PD_DECLARE_ATTRIBUTE_BOOL(declare, table, + OTM_HDMI_ATTR_ID_OUTPUT_DITHER, + PD_ATTR_FLAGS_RWS, get_name, false); + + PD_DECLARE_ATTRIBUTE_BOOL(declare, table, + OTM_HDMI_ATTR_ID_HDCP_1P1, + PD_ATTR_FLAGS_RWS, get_name, true); + + PD_DECLARE_ATTRIBUTE_UINT(declare, table, + OTM_HDMI_ATTR_ID_MUTE, + PD_ATTR_FLAGS_RWS, + get_name, + OTM_HDMI_MUTE_OFF, + OTM_HDMI_MUTE_OFF, OTM_HDMI_MUTE_BOTH); + + PD_DECLARE_ATTRIBUTE_BOOL(declare, table, + OTM_HDMI_ATTR_ID_PURE_VIDEO, + PD_ATTR_FLAGS_RWS, get_name, false); + + PD_DECLARE_ATTRIBUTE_BOOL(declare, table, + OTM_HDMI_ATTR_ID_HDCP_AUTO_PHY, + PD_ATTR_FLAGS_RWS, get_name, true); + + PD_DECLARE_ATTRIBUTE_BOOL(declare, table, + OTM_HDMI_ATTR_ID_HDCP_AUTO_RETRY, + PD_ATTR_FLAGS_RWS, get_name, true); + + PD_DECLARE_ATTRIBUTE_BOOL(declare, table, + OTM_HDMI_ATTR_ID_DVI, + PD_ATTR_FLAGS_RWS, get_name, false); + + PD_DECLARE_ATTRIBUTE_UINT(declare, table, + OTM_HDMI_ATTR_ID_HDCP_RI_RETRY, + PD_ATTR_FLAGS_RWS, get_name, 40, 0, 50); + + PD_LOG_EXIT(PD_LOG_LEVEL_HIGH, rc); + return rc; +} +EXPORT_SYMBOL(otm_hdmi_declare_attributes); + +/* + * Description: crtc mode set function for hdmi. + * + * @context: hdmi_context + * @mode: mode requested + * @adjusted_mode: adjusted mode + * @fb_width, fb_height:allocated frame buffer dimensions + * @pclk_khz: tmds clk value for the best pll and is needed for audio. + * This field has to be moved into OTM audio + * interfaces when implemented + * + * Returns: OTM_HDMI_SUCCESS on success + * OTM_HDMI_ERR_INVAL on NULL input arguments + */ +/* + * TODO: Revisit scaling type enums: + * 0 - scale_none + * 1 - full screen + * 2 - center + * 3 - scale aspect + */ +otm_hdmi_ret_t otm_hdmi_crtc_mode_set(void *context, otm_hdmi_timing_t *mode, + otm_hdmi_timing_t *adjusted_mode, int fb_width, + int fb_height, uint32_t *pclk_khz) +{ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + hdmi_context_t *ctx = (hdmi_context_t *)context; + int scalingtype = IPIL_TIMING_SCALE_NONE; + + /* NULL checks */ + if (context == NULL || mode == NULL || adjusted_mode == NULL + || pclk_khz == NULL) { + pr_debug("\ninvalid arguments\n"); + return OTM_HDMI_ERR_INVAL; + } + + /* prepare for crtc mode set. This includes any hdmi unit reset etc. */ + rc = ipil_hdmi_crtc_mode_set_prepare(&ctx->dev); + if (rc != OTM_HDMI_SUCCESS) { + pr_debug("\nfailed in preparing for mode set\n"); + return rc; + } + + /* get the preferred scaling type for the platform */ + rc = ps_hdmi_get_pref_scalingtype(ctx, &scalingtype); + if (rc != OTM_HDMI_SUCCESS) { + pr_debug("\nfailed to get preferred scaling type\n"); + return rc; + } + /* TODO: For phone, these registers are taken care in + * pipe_set_base call. Need to combine both the solutions + * into a common function. + */ +#ifndef MFLD_HDMI_PR3 + /* program display related registers: dpssize and pipesrc, pfit */ + rc = ipil_hdmi_crtc_mode_set_program_dspregs(&ctx->dev, scalingtype, + mode, adjusted_mode, + fb_width, fb_height); + if (rc != OTM_HDMI_SUCCESS) { + pr_debug("\nfailed to set display registers\n"); + return rc; + } +#endif + + /* program hdmi mode timing registers */ + rc = ipil_hdmi_crtc_mode_set_program_timings(&ctx->dev, + scalingtype, mode, + adjusted_mode); + if (rc != OTM_HDMI_SUCCESS) { + pr_debug("\nfailed to set timing registers\n"); + return rc; + } + + /* program hdmi mode timing registers */ + rc = ipil_hdmi_crtc_mode_set_program_dpll(&ctx->dev, + adjusted_mode->dclk); + if (rc != OTM_HDMI_SUCCESS) { + pr_debug("\nfailed to program dpll\n"); + return rc; + } + *pclk_khz = ctx->dev.clock_khz; + + /* program hdmi mode timing registers */ + rc = ipil_hdmi_crtc_mode_set_program_pipeconf(&ctx->dev); + if (rc != OTM_HDMI_SUCCESS) + pr_debug("\nfailed to program pipeconf\n"); + + return rc; +} + +/* + * Description: encoder mode set function for hdmi. enables phy. + * set correct polarity for the current mode. + * + * @context: hdmi_context + * @mode: mode requested + * @adjusted_mode: adjusted mode + * + * Returns: OTM_HDMI_SUCCESS on success + * OTM_HDMI_ERR_INVAL on NULL input arguments + */ +otm_hdmi_ret_t otm_hdmi_enc_mode_set(void *context, otm_hdmi_timing_t *mode, + otm_hdmi_timing_t *adjusted_mode) +{ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + hdmi_context_t *ctx = (hdmi_context_t *)context; + bool is_monitor_hdmi; + + /* NULL checks */ + if (context == NULL || mode == NULL || adjusted_mode == NULL) { + pr_debug("\ninvalid arguments\n"); + return OTM_HDMI_ERR_INVAL; + } + + is_monitor_hdmi = otm_hdmi_is_monitor_hdmi(ctx); + pr_debug("\nMonitor Mode: %s\n", is_monitor_hdmi ? "HDMI" : "DVI"); + + /* handle encoder mode set */ + rc = ipil_hdmi_enc_mode_set(&ctx->dev, mode, adjusted_mode, + is_monitor_hdmi); + if (rc != OTM_HDMI_SUCCESS) { + pr_debug("\nfailed in programing enc mode set\n"); + return rc; + } + + /* Enable AVI infoframes for HDMI mode */ + if (is_monitor_hdmi) { + rc = otm_hdmi_infoframes_set_avi(context, mode); + if (rc != OTM_HDMI_SUCCESS) + pr_debug("\nfailed to program avi infoframe\n"); + } else {/* Disable all inofoframes for DVI mode */ + rc = otm_hdmi_disable_all_infoframes(context); + if (rc != OTM_HDMI_SUCCESS) + pr_debug("\nfailed to disable all infoframes\n"); + } + + return rc; +} + +/* + * Description: restore HDMI registers and enable the display + * + * @context: hdmi_context + * + * Returns: none + */ +void otm_hdmi_restore_and_enable_display(void *context, bool connected) +{ + if (NULL != context) { + if (connected) { + ipil_hdmi_restore_and_enable_display( + &((hdmi_context_t *)context)->dev); + /* restore data island packets */ + if (otm_hdmi_is_monitor_hdmi(context)) { + ipil_hdmi_restore_data_island( + &((hdmi_context_t *)context)->dev); + } + } else { + ipil_hdmi_destroy_saved_data( + &((hdmi_context_t *)context)->dev); + } +#ifdef OTM_HDMI_HDCP_ENABLE + /* inform HDCP about resume */ + if (otm_hdmi_hdcp_set_power_save(context, false) + == false) + pr_debug("failed to resume hdcp\n"); +#endif + } +} + +/* + * Description: save HDMI display registers + * + * @context: hdmi_context + * + * Returns: none + */ +void otm_hdmi_save_display_registers(void *context, bool connected) +{ + if (NULL != context) { + if (connected) { + ipil_hdmi_save_display_registers( + &((hdmi_context_t *)context)->dev); + /* save data island packets */ + if (otm_hdmi_is_monitor_hdmi(context)) { + ipil_hdmi_save_data_island( + &((hdmi_context_t *)context)->dev); + } + } else { + ipil_hdmi_destroy_saved_data( + &((hdmi_context_t *)context)->dev); + } + } +} + +/* + * Description: disable HDMI display + * + * @context: hdmi_context + * + * Returns: none + */ +void otm_disable_hdmi(void *context) +{ + if (NULL != context) { +#ifdef OTM_HDMI_HDCP_ENABLE + /* inform HDCP about suspend */ + if (otm_hdmi_hdcp_set_power_save(context, true) + == false) + pr_debug("failed to suspend hdcp\n"); +#endif + /* disable HDMI */ + ipil_disable_hdmi(&((hdmi_context_t *)context)->dev); + } +} + +/** + * + * Internal scripts wrapper functions. + * + */ + +/* Starting this off, but all scripts/unit test helpers should move + * to another file. + */ + +#ifdef OTM_HDMI_UNIT_TEST + +/** + * test_otm_hdmi_report_edid() - Report current EDID information + * + * This routine simply dumps the EDID information + * + * Returns - nothing + */ +void test_otm_hdmi_report_edid() +{ + edid_info_t *edid = NULL; + if (NULL == g_context) { + PD_LOG_PRINT(PD_LOG_LEVEL_HIGH, + "Cant print EDID, Initialize otm_hdmi first!\n"); + return; + } + edid = &g_context->edid_int; + if (NULL == edid) { + PD_LOG_PRINT(PD_LOG_LEVEL_HIGH, + "EDID not initialized in driver.\n"); + return; + } + __hdmi_report_edid(g_context, edid); +} +EXPORT_SYMBOL_GPL(test_otm_hdmi_report_edid); +#endif diff --git a/drivers/staging/mrst/drv/otm_hdmi/pil/include/hdcp_api.h b/drivers/staging/mrst/drv/otm_hdmi/pil/include/hdcp_api.h new file mode 100644 index 0000000..b0738cc --- /dev/null +++ b/drivers/staging/mrst/drv/otm_hdmi/pil/include/hdcp_api.h @@ -0,0 +1,81 @@ +/* + + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2011 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + + Intel Corporation + 2200 Mission College Blvd. + Santa Clara, CA 95054 + + BSD LICENSE + + Copyright(c) 2011 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef HDCP_API_H +#define HDCP_API_H + +#include +#include "hdmi_internal.h" + +extern bool otm_hdmi_hdcp_set_hpd_state(hdmi_context_t *hdmi_context, + bool hpd); +extern bool otm_hdmi_hdcp_set_power_save(hdmi_context_t *hdmi_context, + bool suspend); +extern bool otm_hdmi_hdcp_set_dpms(hdmi_context_t *hdmi_context, + bool display_power_on); +extern bool otm_hdmi_hdcp_enable(hdmi_context_t *hdmi_context); +extern bool otm_hdmi_hdcp_disable(hdmi_context_t *hdmi_context); +extern bool otm_hdmi_hdcp_init(hdmi_context_t *hdmi_context, + int (*ddc_rd_wr)(bool, uint8_t, uint8_t, uint8_t *, int)); + +#endif /* HDCP_API_H */ diff --git a/drivers/staging/mrst/drv/otm_hdmi/pil/include/otm_hdmi.h b/drivers/staging/mrst/drv/otm_hdmi/pil/include/otm_hdmi.h new file mode 100644 index 0000000..5e74660 --- /dev/null +++ b/drivers/staging/mrst/drv/otm_hdmi/pil/include/otm_hdmi.h @@ -0,0 +1,358 @@ +/* + + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2011 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + + Intel Corporation + 2200 Mission College Blvd. + Santa Clara, CA 95054 + + BSD LICENSE + + Copyright(c) 2011 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef _OTM_HDMI_H +#define _OTM_HDMI_H + + +#include +#include +#include +#include + +#include "otm_hdmi_types.h" +#include "otm_hdmi_defs.h" + +/** + * Attribute name getting routine + */ +char *__pd_attr_get_name(otm_hdmi_attribute_id_t id); + +/** + * Type definition based on the function signature above + */ +typedef otm_hdmi_ret_t(*pd_attr_set_t)(otm_hdmi_attribute_t *table, + otm_hdmi_attribute_id_t id, + void *value, + otm_hdmi_attribute_flag_t flags); + +/** + * Attribute name getting routine + */ +char *__pd_attr_get_name(otm_hdmi_attribute_id_t id); + +/** + * Type definition based on the function signature above + */ +typedef char *(*pd_attr_get_name_t)(otm_hdmi_attribute_id_t id); + +/** + * Attribute declaration / setting macros + */ +#define PD_DECLARE_ATTRIBUTE_BOOL(f_d, t, id, flags, \ + f_n, value) \ + f_d(t, id, OTM_HDMI_ATTR_TYPE_BOOLEAN, flags, \ + f_n(id), (void *) value, 0, 0) + +#define PD_DECLARE_ATTRIBUTE_BOOL_CUSTOM(f_d, t, id, flags, \ + name, value) \ + f_d(t, id, OTM_HDMI_ATTR_TYPE_BOOLEAN, flags, \ + name, (void *) value, 0, 0) + +#define PD_DECLARE_ATTRIBUTE_UINT(f_d, t, id, flags, \ + f_n, value, min, max) \ + f_d(t, id, OTM_HDMI_ATTR_TYPE_UINT, flags, \ + f_n(id), (void *) value, min, max) + +#define PD_DECLARE_ATTRIBUTE_UINT_CUSTOM(f_d, t, id, flags, \ + name, value, min, max) \ + f_d(t, id, OTM_HDMI_ATTR_TYPE_UINT, flags, \ + name, (void *) value, min, max) + +#define PD_DECLARE_ATTRIBUTE_STRING(f_d, t, id, \ + flags, f_n, value) \ + f_d(t, id, OTM_HDMI_ATTR_TYPE_STRING, flags, \ + f_n(id), (void *) value, 0, 0) + +#define PD_DECLARE_ATTRIBUTE_STRING_CUSTOM(f_d, t, id, \ + flags, name, value) \ + f_d(t, id, OTM_HDMI_ATTR_TYPE_STRING, flags, \ + name, (void *) value, 0, 0) + +/** + * Attribute values accessor macros + */ +#define PD_ATTR_BOOL(attr) ((attr).content._bool.value) +#define PD_ATTR_UINT(attr) ((attr).content._uint.value) + +/** + * Shortcuts for common flags combinations + */ +#define PD_ATTR_FLAGS_RWSI (OTM_HDMI_ATTR_FLAG_WRITE | \ + OTM_HDMI_ATTR_FLAG_SUPPORTED | \ + OTM_HDMI_ATTR_FLAG_INTERNAL) + +#define PD_ATTR_FLAGS_RWS (OTM_HDMI_ATTR_FLAG_WRITE | \ + OTM_HDMI_ATTR_FLAG_SUPPORTED) + +#define PD_ATTR_FLAGS_RS (OTM_HDMI_ATTR_FLAG_SUPPORTED) + +/** + * Display timing information + */ +typedef struct { + unsigned short width; /* width */ + unsigned short height; /* height */ + otm_hdmi_refresh_t refresh; /* refresh rate */ + unsigned long dclk; /* refresh rate dot clock in kHz */ + unsigned short htotal; /* horizontal total */ + unsigned short hblank_start; /* horizontal blank start */ + unsigned short hblank_end; /* horizontal blank end */ + unsigned short hsync_start; /* horizontal sync start */ + unsigned short hsync_end; /* horizontal sync end */ + unsigned short vtotal; /* vertical total */ + unsigned short vblank_start; /* vertical blank start */ + unsigned short vblank_end; /* vertical blank end */ + unsigned short vsync_start; /* vertical sync start */ + unsigned short vsync_end; /* vertical sync end */ + unsigned long mode_info_flags; /* flags */ + otm_hdmi_stereo_t stereo_type; /* stereo mode type */ + unsigned long metadata; /* port driver specific information */ +} otm_hdmi_timing_t; + +/* set timing from cea modes */ +int otm_hdmi_timing_from_cea_modes(unsigned char *buffer, + otm_hdmi_timing_t *pdts); + +/* get timings of a mode */ +otm_hdmi_timing_t *otm_hdmi_get_mode_timings(void *context, + int hdisplay, + int vdisplay, + int vrefresh); + +/* parse the raw edid and fill the capability table */ +otm_hdmi_ret_t otm_hdmi_edid_parse(void *ctx, otm_hdmi_use_edid_t use_edid); + +/* install HPD IRQ */ +otm_hdmi_ret_t otm_hdmi_setup_irq(void *context, struct pci_dev *pdev, + irqreturn_t (*phdmi_irq_cb) (int, void*), + void *data); + +/* init hdmi device driver */ +otm_hdmi_ret_t otm_hdmi_device_init(void **context, struct pci_dev *pdev); + +/* read edid information */ +unsigned char *otm_hdmi_read_edid(void); + +/* turn HDMI power rails on */ +bool otm_hdmi_power_rails_on(); + +/* get pixel clock range */ +otm_hdmi_ret_t otm_hdmi_get_pixel_clock_range(unsigned int *pc_min, + unsigned int *pc_max); + +/* + * Getting given attribute + * @param [in ] id : attribute id + * @param [out] data : user provided buffer for attribute details + * @param [in ] log : a hint wether port driver should log the call + */ +otm_hdmi_ret_t otm_hdmi_get_attribute(void *context, + otm_hdmi_attribute_id_t id, + otm_hdmi_attribute_t *attribute, + bool log); + +/* + * Setting given attribute + * @param [in] context : port driver specific information + * @param [in] id : attribute id + * @param [in] data : user provided buffer with attribute value + * @param [in] internal : internal [driver] or external [app] call + */ +otm_hdmi_ret_t otm_hdmi_set_attribute(void *context, + otm_hdmi_attribute_id_t id, + void *data, + bool internal); + +/* check the mode is preferred or not */ +bool otm_hdmi_is_preferred_mode(int hdisplay, + int vdisplay, int refresh); + +/* set the raw edid into HDMI context */ +otm_hdmi_ret_t otm_hdmi_set_raw_edid(void *context, char *raw_edid); + +/* get the raw edid from HDMI context */ +otm_hdmi_ret_t otm_hdmi_get_raw_edid(void *context, char **raw_edid); + +/* check the connection is hdmi or dvi */ +bool otm_hdmi_is_monitor_hdmi(void *context); + +/* + * Description: crtc mode set function for hdmi. + * + * @context: hdmi_context + * @mode: mode requested + * @adjusted_mode: adjusted mode + * @fb_width, fb_height:allocated frame buffer dimensions + * @pclk_khz: tmds clk value for the best pll and is needed for audio. + * This field has to be moved into OTM audio + * interfaces when implemented + * + * Returns: OTM_HDMI_SUCCESS on success + * OTM_HDMI_ERR_INVAL on NULL input arguments + */ +otm_hdmi_ret_t otm_hdmi_crtc_mode_set(void *context, otm_hdmi_timing_t *mode, + otm_hdmi_timing_t *adjusted_mode, int fb_width, + int fb_height, uint32_t *pclock_khz); + +/* + * Description: encoder mode set function for hdmi. enables phy. + * set correct polarity for the current mode. + * + * @context: hdmi_context + * @mode: mode requested + * @adjusted_mode: adjusted mode + * + * Returns: OTM_HDMI_SUCCESS on success + * OTM_HDMI_ERR_INVAL on NULL input arguments + */ +otm_hdmi_ret_t otm_hdmi_enc_mode_set(void *context, otm_hdmi_timing_t *mode, + otm_hdmi_timing_t *adjusted_mode); + +/* + * Description: save hdmi display registers + * + * @context: hdmi_context + * + * Returns: none + */ +void otm_hdmi_save_display_registers(void *context, bool connected); + +/* + * Description: disable HDMI display + * + * @context: hdmi_context + * + * Returns: none + */ +void otm_disable_hdmi(void *context); + +/* + * Description: restore hdmi display registers and enable the display + * + * @context: hdmi_context + * + * Returns: none + */ +void otm_hdmi_restore_and_enable_display(void *context, bool connected); + +/* TODO: Need refactor the logging and attr table */ + +/* + * Logging macros + */ +#define ATTRIBUTES otm_hdmi_attributes_table + +typedef enum { + PD_LOG_LEVEL_ERROR = 0, /* Error messages; Will always be printed */ + __PD_LOG_LEVEL_MIN = PD_LOG_LEVEL_ERROR, + /* Add log levels below this line */ + PD_LOG_LEVEL_HIGH = 1, /* Printed if 'debug' is set to 1 or higher */ + PD_LOG_LEVEL_LOW, /* Printed if 'debug' is set to 2 or higher */ + PD_LOG_LEVEL_VBLANK, /* Printed if 'debug' at highest level */ + /* Add log levels above this line */ + __PD_LOG_LEVEL_TEMP_UPPER__, /* DO NOT USE */ + __PD_LOG_LEVEL_MAX = __PD_LOG_LEVEL_TEMP_UPPER__ - 1, +} pd_log_level_t; + +/* Used to log entry in to a function */ +#define PD_LOG_ENTRY(log_level) \ + if ((log_level) <= (int) PD_ATTR_UINT( \ + ATTRIBUTES[OTM_HDMI_ATTR_ID_DEBUG])) \ + printk("OTM_HDMI: Entering %s\n", __func__) + +/* Used to log exit from a function */ +#define PD_LOG_EXIT(log_level, rc) \ + if ((log_level) <= (int) PD_ATTR_UINT( \ + ATTRIBUTES[OTM_HDMI_ATTR_ID_DEBUG])) \ + printk("OTM_HDMI: Exiting %s with %d\n", __func__, rc) + +#ifdef OTM_HDMI_FIXME +#define PD_LOG_PRINT(log_level, args...) \ + if ((log_level) <= (int) PD_ATTR_UINT( \ + ATTRIBUTES[OTM_HDMI_ATTR_ID_DEBUG])) \ + printk(args) +#else +#define PD_LOG_PRINT(log_level, args...) printk("OTM_HDMI: " args) +#endif + +#define PD_LOG_ERROR(msg, args...) PD_LOG_PRINT(PD_LOG_LEVEL_ERROR, msg, ##args) + +/* + * Bits in 'mode_info_flags' field + */ +#define PD_SCAN_INTERLACE 0x80000000 /* Interlaced pipe configuration */ +#define PD_PIXEL_REPLICATION 0x40000000 /* Mode uses pixel replication */ +#define PD_HSYNC_HIGH 0x20000000 /* HSYNC is active high */ +#define PD_VSYNC_HIGH 0x10000000 /* VSYNC is active high */ +#define PD_CLOCK_OVERSAMPLE 0x00020000 /* Indicates dot clock is a multiple */ + /* of the MDVO clock; See VDC_SetMode*/ +#define PD_EVO_DITHER 0x00008000 /* Enable EVO dithering */ +#define PD_EVO_FORMAT_8 0x00004000 /* Set EVO 8 bit mode */ +#define PD_EVO_CLK_INV 0x00002000 /* Invert EVO pixel clock */ +#define PD_WSS_WORKAROUND 0x00000800 /* PAL Wide Screen Signal workaround */ +#define PD_DTV_MODE 0x00000400 /* Digital Panel mode */ +#define PD_SVBI 0x00000010 /* Software VBI supported timings */ +#define PD_AR_16_BY_9 0x00000001 /* 16:9 aspect ratio */ + +#endif /* _OTM_HDMI_H */ diff --git a/drivers/staging/mrst/drv/otm_hdmi/pil/include/otm_hdmi_defs.h b/drivers/staging/mrst/drv/otm_hdmi/pil/include/otm_hdmi_defs.h new file mode 100644 index 0000000..030f662 --- /dev/null +++ b/drivers/staging/mrst/drv/otm_hdmi/pil/include/otm_hdmi_defs.h @@ -0,0 +1,1167 @@ +/* + + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2011 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + + Intel Corporation + 2200 Mission College Blvd. + Santa Clara, CA 95054 + + BSD LICENSE + + Copyright(c) 2011 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ +#ifndef _OTM_HDMI_DEFS_H +#define _OTM_HDMI_DEFS_H + + +#include + +#include "otm_hdmi_types.h" + +/** + Existing port driver IDs with room for user specified port drivers. + When communicating with a specific port driver the port id must be passed. +*/ +typedef enum { + OTM_HDMI_MIN_SUPPORTED_DRIVERS = 0, /* Port Driver IDs start at this + value */ + + OTM_HDMI_ID_INTTVENC = OTM_HDMI_MIN_SUPPORTED_DRIVERS, /* CVBS TV + encoder */ + OTM_HDMI_ID_INTTVENC_COMPONENT, /* Component TV encoder */ + OTM_HDMI_ID_HDMI, /* HDMI */ + OTM_HDMI_ID_USER_MIN, /* Begin user defined drivers */ + OTM_HDMI_ID_USER_MAX = 8, /* End user defined drivers */ + + OTM_HDMI_MAX_SUPPORTED_DRIVERS /* Maximum number of port drivers. */ +} otm_hdmi_id_t; + +/** +Defined port driver attributes. Which ones are supported (and exactly how) +can vary from one port driver to another. See the Intel� CE Media Processors +GDL 3.0 Programming Guide for details on the attributes supported by +each port driver. + +The following Attributes require "elevated" privileges: +OTM_HDMI_ATTR_ID_HDCP +OTM_HDMI_ATTR_ID_HDCP_AUTO_MUTE +OTM_HDMI_ATTR_ID_POWER +OTM_HDMI_ATTR_ID_MUTE +OTM_HDMI_ATTR_ID_HDCP_AUTO_PHY +OTM_HDMI_ATTR_ID_HDCP_AUTO_RETRY +OTM_HDMI_ATTR_ID_HDCP_RI_RETRY +OTM_HDMI_ATTR_ID_HDCP_1P1 +OTM_HDMI_ATTR_ID_HDCP_ENCRYPT +*/ + +/* *NOTE* Extend pd_lib.c::__pd_attr_get_name() when adding new entries */ +typedef enum { + OTM_HDMI_MIN_SUPPORTED_ATTRIBUTES = 0, /* Attribute ID enum's start + at this value */ + + OTM_HDMI_ATTR_ID_HDCP = OTM_HDMI_MIN_SUPPORTED_ATTRIBUTES, /* HDCP + control */ + OTM_HDMI_ATTR_ID_HDCP_AUTO_MUTE, /* HDCP auto mute */ + OTM_HDMI_ATTR_ID_HDCP_STATUS, /*HDCP status */ + OTM_HDMI_ATTR_ID_HDCP_1P1, /* HDCP 1.1 Pj check control */ + OTM_HDMI_ATTR_ID_COLOR_SPACE_INPUT, /*Input colorspace */ + OTM_HDMI_ATTR_ID_PIXEL_FORMAT_OUTPUT, /* Output colorspace */ + OTM_HDMI_ATTR_ID_PIXEL_DEPTH, /* Depth of outgoing pixels */ + OTM_HDMI_ATTR_ID_BG_COLOR, /* Color for HDCP failure & video mute */ + OTM_HDMI_ATTR_ID_CABLE_STATUS, /* Cable status */ + OTM_HDMI_ATTR_ID_PAR, /* Picture aspect ratio */ + OTM_HDMI_ATTR_ID_FAR, /* Format aspect ratio */ + OTM_HDMI_ATTR_ID_USE_EDID, /* TV timings source */ + OTM_HDMI_ATTR_ID_SLOW_DDC, /* DDC bus speed */ + OTM_HDMI_ATTR_ID_AUDIO_CLOCK, /* Audio clock */ + OTM_HDMI_ATTR_ID_COLOR_SPACE_EXT, /* Extended colorimetry */ + OTM_HDMI_ATTR_ID_OUTPUT_CLAMP, /* Clamp output in [16,235] when it is */ + /* RGB color space. In YCbCr output */ + /* this attribute is ignored. */ + OTM_HDMI_ATTR_ID_BRIGHTNESS, /* Brightness Level */ + OTM_HDMI_ATTR_ID_CONTRAST, /* Contrast Level */ + OTM_HDMI_ATTR_ID_HUE, /* Hue Angle */ + OTM_HDMI_ATTR_ID_SATURATION, /* Saturation Level */ + OTM_HDMI_ATTR_ID_ACP, /* Analog Content Protection */ + OTM_HDMI_ATTR_ID_CC, /* Closed Captioning */ + OTM_HDMI_ATTR_ID_OUTPUT_DITHER, /* Dither 12-bit->10/8bit conversion */ + OTM_HDMI_ATTR_ID_SHARPNESS_HLUMA, /* Horizontal Luma filter */ + OTM_HDMI_ATTR_ID_SHARPNESS_HCHROMA, /* Horizontal Chroma Filter */ + OTM_HDMI_ATTR_ID_BLANK_LEVEL, /* Sync pulse level */ + OTM_HDMI_ATTR_ID_BLACK_LEVEL, /* Black Level */ + OTM_HDMI_ATTR_ID_BURST_LEVEL, /* Burst Level */ + OTM_HDMI_ATTR_ID_HDCP_RI_RETRY, /* RI retry delay */ + OTM_HDMI_ATTR_ID_DVI, /* DVI enforcement */ + OTM_HDMI_ATTR_ID_TVOUT_TYPE, /* Current DAC configuration */ + OTM_HDMI_ATTR_ID_HDCP_ENCRYPT, /* HDCP encryption control */ + OTM_HDMI_ATTR_ID_3CH_SYNC, /* 3 Channel sync */ + OTM_HDMI_ATTR_ID_SD_OPTION, /* Alternate SD mode (e.g.: PAL-M, */ + /* PAL-N, etc.) */ + OTM_HDMI_ATTR_ID_RGB, /* RGB / YPbPr output selection */ + OTM_HDMI_ATTR_ID_CGMS_MODE, /* Current Copy Generation mode */ + OTM_HDMI_ATTR_ID_NO_SYNC, /* Sync removal from green (y) signal */ + OTM_HDMI_ATTR_ID_YC_DELAY, /* Luma vs Chroma delay */ + OTM_HDMI_ATTR_ID_POWER, /* Disable DAC output */ + OTM_HDMI_ATTR_ID_NAME, /* Driver name */ + OTM_HDMI_ATTR_ID_VERSION_MAJOR, /* Driver major version */ + OTM_HDMI_ATTR_ID_VERSION_MINOR, /* Driver minor version */ + OTM_HDMI_ATTR_ID_DEBUG, /* Debug log */ + OTM_HDMI_ATTR_ID_BUILD_DATE, /* Driver Build date */ + OTM_HDMI_ATTR_ID_BUILD_TIME, /* Driver Build time */ + OTM_HDMI_ATTR_ID_DISPLAY_PIPE, /* Display Pipeline assigned */ + OTM_HDMI_ATTR_ID_SVIDEO, /* Assignment of component Pb & Pr */ + /* DACs for S-Video output */ + OTM_HDMI_ATTR_ID_AUDIO_STATUS, /* Status of audio playback */ + OTM_HDMI_ATTR_ID_TMDS_DELAY, /* HPD to TMDS assert delay */ + OTM_HDMI_ATTR_ID_MUTE, /* Mute */ + OTM_HDMI_ATTR_ID_PURE_VIDEO, /* Pure video indication control */ + OTM_HDMI_ATTR_ID_HDCP_AUTO_PHY, /* PHY blinking on HDCP Ri/Pj failure */ + OTM_HDMI_ATTR_ID_CALIBRATION, /* Calibration value */ + OTM_HDMI_ATTR_ID_HDCP_AUTO_RETRY, /* Automatic HDCP retry control */ + OTM_HDMI_ATTR_ID_INTERNAL_TEST, /* CVBS/Component internal test */ + + /* EXTENDED */ + OTM_HDMI_ATTR_ID_USER_MIN, /* Start of user defined attributes */ + OTM_HDMI_ATTR_ID_USER_MAX = 100, /* Max user defined attribute */ + OTM_HDMI_MAX_SUPPORTED_ATTRIBUTES /* End of attribute IDs; + must be last */ +} otm_hdmi_attribute_id_t; + + +/* + * the following def should be moved to otm_htmi_internel.h later + */ +#define PD_NAME "pd_hdmi" + +/** @ingroup disp_mode + * Defines supported color spaces + * + */ +typedef enum { + /* Normally used for Standard Definition YCbCr content */ + OTM_HDMI_COLOR_SPACE_BT601 = 0, + /* Normally used for High Definition YCbCr content */ + OTM_HDMI_COLOR_SPACE_BT709, + /* Used for all RGB pixel formats */ + OTM_HDMI_COLOR_SPACE_RGB, + /* Number of entries in this enumeration */ + OTM_HDMI_COLOR_SPACE_COUNT +} otm_hdmi_color_space_t; + +/** @ingroup disp_mode + * Display (pipe) ids. The Intel CE Media Processors have two displays. + */ +typedef enum { + /* [Pipe A] Main display/HDMI */ + OTM_HDMI_DISPLAY_ID_0 = 0, + /* [Pipe B] Secondary display/Composite */ + OTM_HDMI_DISPLAY_ID_1, + /* Undefined Pipe */ + OTM_HDMI_DISPLAY_ID_UNDEFINED +} otm_hdmi_display_id_t; + +/* + * + * Attribute usage flags. + */ +/* TODO: Move OTM_HDMI_ATTR_FLAG_SUPPORTED since it's internal to PD */ +typedef enum { + OTM_HDMI_ATTR_FLAG_WRITE = 0x1, /* Attribute can be written */ + OTM_HDMI_ATTR_FLAG_SUPPORTED = 0x2, + /* Attribute is supported on this port + driver. FOR INTERNAL USE ONLY. */ + OTM_HDMI_ATTR_FLAG_INTERNAL = 0x4, + /* Attribute is invisible to outside + world. FOR INTERNAL USE ONLY */ +} otm_hdmi_attribute_flag_t; + +/* + * Attribute flags used internally to override / extend certain behavior + * NOTE: Make sure values don't collide with otm_hdmi_attribute_flag_t + */ +#define OTM_HDMI_ATTR_FLAG_FORCED 0x8000 /* Read only is ignored */ + +/** + Attribute types +*/ +typedef enum { + OTM_HDMI_ATTR_TYPE_UINT, /* Attribute is of type #unsigned int. */ + OTM_HDMI_ATTR_TYPE_BOOLEAN, /* Attribute is of type #bool. */ + OTM_HDMI_ATTR_TYPE_STRING /* Attribute is a read-only 0-terminated + ASCII string. */ +} otm_hdmi_attribute_type_t; + +/** + Maximum size of PD string attributes +*/ +#define OTM_HDMI_MAX_STRING_LENGTH 16 + +/** + This structure represents port driver attribute +*/ +typedef struct { + otm_hdmi_attribute_id_t id; /* Global attribute ID. */ + otm_hdmi_attribute_type_t type; /* Data type of attribute. */ + otm_hdmi_attribute_flag_t flags;/* Access permissions and + internal use*/ + + char name[OTM_HDMI_MAX_STRING_LENGTH + 1]; + + union /* Attribute data dependent on attribute type */ + { + struct { + unsigned int value_default; /* default value */ + unsigned int value_min; /* minimum value */ + unsigned int value_max; /* maximum value */ + unsigned int value; /* current value */ + } _uint; + + struct { + bool value_default; /* default value */ + bool value; /* current value */ + } _bool; + + struct { + /* current value */ + char value[OTM_HDMI_MAX_STRING_LENGTH + 1]; + } string; + + } content; +} otm_hdmi_attribute_t; + +/** + The Internal TV Encoders can support several different TV standards when + they are used in Standard Definition (SD) resolutions. The entries in + this enumeration are values that can be used to set the + OTM_HDMI_ATR_ID_SD_OPTION attribute to specify the standard to be used + for SD. +*/ +typedef enum { + TV_STD_UNDEFINED = 0, /* Use Default per resolution */ + TV_STD_NTSC = 0, /* Use NTSC for 720x480i mode. */ + TV_STD_PAL = 0, /* Use PAL for 720x576i mode. */ + TV_STD_NTSC_J = 1, /* Use NTSC-J (Japan) for 720x480i mode. */ + TV_STD_PAL_M = 2, /* Use PAL-M (Brazil) for 720x480i mode. */ + TV_STD_PAL_N = 3, /* Use PAL-N (Argentina) for 720x576i mode. */ + TV_STD_MAX /* The number of IDs in this enumeration. */ +} otm_hdmi_sd_option_t; + +/* + * Unique IDs for [end user -> port driver] communication + */ +/* + * Command codes for the otm_hdmi_port_send() function. + */ +typedef enum { + OTM_HDMI_SEND_CC = 0, + /* Closed Captioning data; see #otm_hdmi_cc_data_t */ + OTM_HDMI_SEND_PAL_WSS, + /* Pal Wide Screen signaling; See #otm_hdmi_wss_data_t */ + OTM_HDMI_SEND_CGMS_A, + /* CGMS-A for NTSC and ATSC formats; See #otm_hdmi_cgms_data_t */ + OTM_HDMI_SEND_CGMS_A_TYPE_B, + /* CGMS-A for CEA 770.2 and 770.3; see #otm_hdmi_cgms_type_b_data_t */ + OTM_HDMI_SEND_HDMI_AUDIO_CTRL, + /* HDMI audio data; See #otm_hdmi_audio_ctrl_t */ + OTM_HDMI_SEND_HDMI_HDCP_SRM, + /* HDCP System Renewability Message */ + OTM_HDMI_SEND_HDMI_PACKET, + /* Generic HDMI packet; See #otm_hdmi_packet_info_t */ + OTM_HDMI_SEND_HDMI_PHY, + /* Set HDMI PHY electrical properties */ + OTM_HDMI_SEND_TELETEXT, + /* Teletext data to be re inserted into the vbi */ + OTM_HDMI_SEND_USER_MIN, + /* External (non-Intel) port drivers may define command codes + starting with this value. + */ + OTM_HDMI_SEND_USER_MAX = 30 + /* External (non-Intel) port drivers may define command codes up to + this value. + */ +} otm_hdmi_otm_hdmi_send_t; + +/* Unique IDs for [port driver -> end user] communication */ +/** + Command codes for retrieving port driver extended information + via otm_hdmi_port_recv(). +*/ +typedef enum { + OTM_HDMI_RECV_HDMI_AUDIO_CTRL = 0, /* Audio control information + see #otm_hdmi_audio_ctrl_t */ + OTM_HDMI_RECV_HDMI_SINK_INFO, /* HDMI sink information + see #otm_hdmi_sink_info_t */ + OTM_HDMI_RECV_HDMI_EDID_BLOCK, /* 128 bytes of raw EDID + see #otm_hdmi_edid_block_t */ + OTM_HDMI_RECV_HDMI_HDCP_INFO, /* HDCP information */ + OTM_HDMI_RECV_HDMI_HDCP_KSVS, /* HDCP keys selection vectors */ + OTM_HDMI_RECV_HDMI_PHY, /* PHY settings */ + OTM_HDMI_RECV_HDMI_NATIVE_MODE,/* Native modes query */ + OTM_HDMI_RECV_USER_MIN, /* Begin user defined command codes */ + OTM_HDMI_RECV_USER_MAX = 30 /* End user defined command codes */ +} otm_hdmi_otm_hdmi_receive_t; + +/* Output pixel format */ +/** + Attribute values for the HDMI output pixel format. + See #OTM_HDMI_ATTR_ID_PIXEL_FORMAT_OUTPUT. +*/ +typedef enum { + OTM_HDMI_OPF_RGB444 = 0, /* RGB 4:4:4 Output */ + OTM_HDMI_OPF_YUV422, /* YUV 4:2:2 Output */ + OTM_HDMI_OPF_YUV444, /* YUV 4:4:4 Output */ + OTM_HDMI_OPF_COUNT /* Number of output pixel formats + 1 */ +} otm_hdmi_output_pixel_format_t; + +/* Output pixel depth */ +/** + Attribute values for the HDMI output pixel depth. + See #OTM_HDMI_ATTR_ID_PIXEL_DEPTH. +*/ +typedef enum { + OTM_HDMI_OPD_24BIT = 0, /* 24 bits per pixel */ + OTM_HDMI_OPD_30BIT, /* 30 bits per pixel */ + OTM_HDMI_OPD_36BIT, /* 36 bits per pixel */ + OTM_HDMI_PIXEL_DEPTH_COUNT /* Number of supported pixel depths + 1 */ +} otm_hdmi_output_pixel_depth_t; + +/* Picture Aspect Ratio infoframe code */ +/** + Attribute values for the HDMI Picture Aspect Ratio information sent via + AVI infoframes. See #OTM_HDMI_ATTR_ID_PAR . +*/ +typedef enum { + OTM_HDMI_PAR_NO_DATA = 0x00, /* No aspect ratio specified */ + OTM_HDMI_PAR_4_3 = 0x01, /* 4:3 aspect ratio */ + OTM_HDMI_PAR_16_9 = 0x02, /* 16:9 aspect ratio */ +} otm_hdmi_par_t; + +/* Format Aspect Ratio infoframe code */ +/** + Attribute values for the HDMI Format Aspect Ratio information sent via + AVI infoframes. See #OTM_HDMI_ATTR_ID_FAR. +*/ +typedef enum { + OTM_HDMI_FAR_16_9_TOP = 0x02, /* box 16:9 (top) */ + OTM_HDMI_FAR_14_9_TOP = 0x03, /* box 14:9 (top) */ + OTM_HDMI_FAR_G_14_9_CENTER = 0x04, /* box > 16:9 (center) */ + OTM_HDMI_FAR_SAME_AS_PAR = 0x08, /* As encoded frame */ + OTM_HDMI_FAR_4_3_CENTER = 0x09, /* 4:3 center */ + OTM_HDMI_FAR_16_9_CENTER = 0x0A, /* 16:9 center */ + OTM_HDMI_FAR_14_9_CENTER = 0x0B, /* 14:9 center */ + OTM_HDMI_FAR_4_3_SP_14_9 = 0x0D, /* 4:3 with s&p 14:9 center */ + OTM_HDMI_FAR_16_9_SP_14_9 = 0x0E, /* 16:9 with s&p 14:9 center */ + OTM_HDMI_FAR_16_9_SP_4_3 = 0x0F, /* 4:3 with s&p 4:3 center */ +} otm_hdmi_far_t; + +/* V B I S E R V I C E S */ +/** + When inserting VBI information into the analog TV signal, this enumeration + is used to indicate the field into which the information should be inserted. +*/ +typedef enum { + VBI_FIELD_ID_ODD = 1, /* Odd field (field 1). */ + VBI_FIELD_ID_EVEN = 2, /* Even field (field 2). */ + VBI_FIELD_ID_UNDEFINED = 3 + /* This value should be passed when the + display is in a progressive (frame) mode. + */ +} otm_hdmi_vbi_fieldid_t; + +/** + + This enumeration is used to specify values for the #OTM_HDMI_ATTR_ID_ACP + attribute (the Analog Copy Protection mode). +*/ +typedef enum { + ACP_MODE_OFF, /* ACP Off */ + ACP_MODE_PSP, /* Pseudo Sync Pulse+No Color Stripes */ + ACP_MODE_PSP_CS_2_LINES, /* Pseudo Sync Pulse+Color Stripes (2 lines)*/ + ACP_MODE_PSP_CS_4_LINES, /* Pseudo Sync Pulse+Color Stripes (4 lines)*/ + ACP_MODE_PSP_ALT, /* Pseudo Sync Pulse + No Color Stripes */ + /* Type 1 Supplement 1 BPP configuration */ + ACP_MODE_PSP_CS_2_LINES_ALT, /* Pseudo Sync Pulse + + Color Stripes (2 lines) */ + /* Type 2 Supplement 1 BPP configuration */ + ACP_MODE_PSP_CS_4_LINES_ALT /* Pseudo Sync Pulse + + Color Stripes (4 lines) */ + /* Type 3 Supplement 1 BPP configuration */ +} otm_hdmi_acp_mode_t; + +/** + This enumeration specifies values for CGMS-A copy permission states to be + inserted into the analog TV signal. See the #otm_hdmi_cgms_data_t + data structure. +*/ +typedef enum { + CGMS_A_COPY_FREELY = 1, /* Unlimited Copies can be made */ + CGMS_A_COPY_NOMORE = 2, /* Copy has already been made (was reserved) */ + CGMS_A_COPY_ONCE = 3, /* One copy can be made */ + CGMS_A_COPY_NEVER = 4, /* No copies can be made */ + CGMS_A_NO_DATA = 5 /* No data. Word 1 will be 1111 */ +} otm_hdmi_cgms_copy_t; + +/** + + This enumeration specifies values for CGMS-A aspect ratios to be inserted + into the analog TV signal. See the #otm_hdmi_cgms_data_t data structure. +*/ +typedef enum { + CGMS_A_4_3 = 1, /* Normal 4:3 aspect ratio */ + CGMS_A_4_3_LB = 2, /* 4:3 aspect ratio letterboxed */ + CGMS_A_16_9 = 3 /* 16:9 aspect ratio (Not available at 480i/576i) */ +} otm_hdmi_cgms_aspect_t; + +/** + + This enumeration specifies values for CGMS-A aspect ratios to be inserted + into the analog TV signal. See the #otm_hdmi_cgms_data_t data structure. +*/ +typedef enum { + CGMS_A_SCAN_NODATA = 0, /* No Data */ + CGMS_A_SCAN_OVER = 1, /* Overscanned */ + CGMS_A_SCAN_UNDER = 2, /* Underscanned */ + CGMS_A_SCAN_RESERVED = 3 +} otm_hdmi_cgms_scan_t; + +/** + + This enumeration specifies values for CGMS-A aspect ratios to be inserted + into the analog TV signal. See the #otm_hdmi_cgms_data_t data structure. +*/ +typedef enum { + CGMS_A_CSC_NO_DATA = 0, /* No Data */ + CGMS_A_CSC_BT601 = 1, /* BT601 */ + CGMS_A_CSC_BT709 = 2, /* BT709 */ + CGMS_A_CSC_RESERVED = 3 /* Reserved */ +} otm_hdmi_cgms_colorimetery; + +/** + This enumeration specifies values for Wide Screen Signalling aspect ration + information to be inserted into the analog TV signal. See the + +*/ +typedef enum { + /* PAL specific Modes */ + WSS_4_3_FF = 0, /* 4:3 Full Format */ + WSS_14_9_LB_C = 1, /* 14:9 Letterbox, Centered */ + WSS_14_9_LB_T = 2, /* 14:9 Letterbox, Top */ + WSS_16_9_LB_C = 3, /* 16:9 Letterbox, Centered */ + WSS_16_9_LB_T = 4, /* 16:9 Letterbox, Top */ + WSS_G_16_9_LB_C = 5, /* 16:9 Letterbox, Centered */ + WSS_14_9_FF = 6, /* 14:9 Full Format */ + WSS_16_9_ANAMORPHIC = 7, /*16:9 Anamorphic */ +} otm_hdmi_wss_aspect_t; + +/** + This enumeration specifies values for Wide Screen Signalling camera mode + information to be inserted into the analog TV signal. See the + +*/ +typedef enum { + WSS_CAMERA_MODE = 0, /* Camera Mode */ + WSS_FILM_MODE = 1, /* Film Mode */ +} otm_hdmi_wss_camera_t; + +/** + This enumeration specifies values for Wide Screen Signalling color encoding + information to be inserted into the analog TV signal. See the + +*/ +typedef enum { + WSS_CE_NORMAL_PAL = 10, /* Normal PAL Colors */ + WSS_CE_COLOR_PLUS = 11, /* Motion Adaptive Color Plus */ +} otm_hdmi_wss_ce_t; + +/** + This enumeration specifies values to indicate Wide Screen Signalling + helpers state, to be inserted into the analog TV signal. See the + +*/ +typedef enum { + WSS_HELPERS_NOT_PRESENT = 1, /* No Helper */ + WSS_HELPERS_PRESENT = 2, /* Modulated helper */ + +} otm_hdmi_wss_helpers_t; + +/** + This enumeration specifies values for Wide Screen Signalling open subtitles + state, to be inserted into the analog TV signal. + See the #otm_hdmi_wss_data_t data structure. +*/ +typedef enum { + WSS_OPEN_SUBTITLES_NO = 1, /* No open subtitles */ + WSS_OPEN_SUBTITLES_INSIDE = 2, /* Subtitles in active image area*/ + WSS_OPEN_SUBTITLES_OUTSIDE = 3, /* Subtitles out of active image area*/ +} otm_hdmi_wss_opensub_t; + +/** + This enumeration specifies values for Wide Screen Signalling surround sound + state, to be inserted into the analog TV signal. + See the #otm_hdmi_wss_data_t data structure. +*/ +typedef enum { + WSS_SURROUND_NO = 1, /* No surround sound information */ + WSS_SURROUND_YES = 2, /* Surround sound present */ +} otm_hdmi_wss_surround_t; + +/** + This enumeration contains the data type identifier for the WSS information + to pass to the TV encoder to be inserted into the analog TV signal. +*/ +typedef enum { + WSS_NO_COPYRIGHT = 1, /* No Copyright asserted or status unknown */ + WSS_COPYRIGHT = 2, /* Copyright Asserted */ +} otm_hdmi_wss_copyright_t; + +/** + This enumeration specifies values for Wide Screen Signalling copy + restriction state, to be inserted into the analog TV signal. See the + +*/ +typedef enum { + WSS_COPY_NO_REST = 1, /* Copying not restricted */ + WSS_COPY_RESTRICTED = 2 /* Copying Restricted */ +} otm_hdmi_wss_copy_t; + +/** + + This data structure is used to pass closed captioning information to the + display driver. The driver will pass this information to the TV encoder to + be inserted into the analog TV signal. +*/ +typedef struct { + otm_hdmi_vbi_fieldid_t pd_vbi_field_id; /* Field ID identifier */ + unsigned char data_length; + /* Number of valid closed caption data bytes + passed; must be an even number, with a + maximum value of 8. + */ + unsigned char ccdata[8]; + /* Array containing the closed caption data + to be inserted. + */ +} otm_hdmi_cc_data_t; + +/** + This data structure is used to pass PAL Wide Screen signaling from an + application to the display driver. The driver will pass this + information to the TV encoder to be inserted into the PAL analog TV signal. + + Teletext is not supported in silicon. Teletext in subtitle always is 0. + + Standard in use: + ETSI EN 300 294 V1.4.1 2003-2004 +*/ +typedef struct { + bool enabled; /* OTM_HDMI_TRUE => Enabled */ + otm_hdmi_wss_aspect_t aspect; /* Aspect Ratio */ + otm_hdmi_wss_camera_t cam_mode; /* Camera Mode */ + otm_hdmi_wss_ce_t color_enc; /* Color Encoding */ + otm_hdmi_wss_helpers_t helpers; /* Helpers Present */ + otm_hdmi_wss_opensub_t open_sub; /* Open Subtitles */ + otm_hdmi_wss_surround_t surround; /* Surround sound */ + otm_hdmi_wss_copyright_t copyright; /* Copyright assertion */ + otm_hdmi_wss_copy_t copy_rest; /* Copy Restriction */ +} otm_hdmi_wss_data_t; + +/** + This data structure is used to pass Copy Generation Management System + (Analog) information from the application to the display driver. The driver + will pass this information to the TV encoder to be inserted into the analog + TV signal. + + XDS CEA-608 based CGMS-A should be passed using the Closed Captioning API. + See #otm_hdmi_cc_data_t + + Standard is use: IEC 61880 480i Line20, EIA/CEA-805 480p Line 41, + 720p Line 24 , and 1080i Line 19 +*/ +typedef struct { + bool enabled; /* OTM_HDMI_TRUE => Enabled */ + otm_hdmi_cgms_copy_t copyGen; /* CGMS-A data see #otm_hdmi_cgms_copy_t*/ + otm_hdmi_cgms_aspect_t aspect; /* Wide Screen signaling. */ + otm_hdmi_acp_mode_t mv; /* APS */ + bool analog_src; /* Analog Source Bit */ +} otm_hdmi_cgms_data_t; + +/** + This enumeration is used to specify values for the #OTM_HDMI_ATTR_ID_SVIDEO + attribute +*/ +typedef enum { + OTM_HDMI_TVOUT_TYPE_COMPOSITE, /* Composite only */ + OTM_HDMI_TVOUT_TYPE_SVIDEO, /* S-Video only */ + OTM_HDMI_TVOUT_TYPE_COMPONENT, /* Reserved for internal use */ + OTM_HDMI_TVOUT_TYPE_CVBSSV, /* Composite and S-video */ +} otm_hdmi_tvout_type_t; + +/** + +* This data structure is used to pass Copy Generation +* Management System (Analog) Type B information from the +* application to the display driver. The driver will pass +* this information to the TV encoder to be inserted into the +* analog TV signal. + + XDS CEA-608 based CGMS-A should be passed using the Closed Captioning API. + See #otm_hdmi_cc_data_t + + Standard is use: EIA/CEA-805 480p Line 40, + 720p Line 23 , and 1080i Line 18, 581 +*/ +typedef struct { + bool enabled; /* OTM_HDMI_TRUE => Enabled */ + otm_hdmi_cgms_aspect_t aspect; /* Wide Screen signaling IEC 61880. */ + bool analog_src; /* Analog Source Bit */ + bool activeFormatValid; + bool barDataValid; + otm_hdmi_cgms_scan_t scanData; + otm_hdmi_cgms_colorimetery colorimetery; + unsigned char activeFormat; + bool RCI; + otm_hdmi_acp_mode_t mv; /* APS */ + otm_hdmi_cgms_copy_t copyGen; /* CGMS-A data + see #otm_hdmi_cgms_copy_t */ + unsigned short lineEndTop; + unsigned short lineStartBottom; + unsigned short pixelEndLeft; + unsigned short pixelStartRight; +} otm_hdmi_cgms_type_b_data_t; + +/* Defines the size of the Teletext data packet. */ +#define TELETEXT_NUM_LINES 32 +#define TELETEXT_LINE_LENGTH 46 + +/** + +* This data structure is used as part of otm_hdmi_teletext_data_t +* structure to more easily fill out the PES header. +* +* The packet structure is for a single Teletext line. This is +* a convenience structure that describes the PES data header +* defined in section 4.3 ETSI EN 300-472. +* +* Only data_unit_id's of Teletext Data (0x02) and Teletext +* subtitles (0x03) will be processed by the driver. Stuffing +* (0xFF) will be ignored. A value of 0x00 will generate a +* warning. +* +* Line numbers with a field id of 0 will have 313 added. +* Line numbers outside the VBI will generate a warning. +*/ +typedef struct { + unsigned char type:8; /* Data unit ID */ + unsigned char length:8; /* Length is required to be 44. */ + unsigned char line:5; /* VBI line */ + unsigned char field:1; /* VBI Field, 1 is bottom field */ + unsigned char:2; /* padding */ + unsigned char framing_code:8; /* Framing Code is required + to be 0xE4. */ + unsigned char data[42]; /* Teletext data */ +} teletext_packet_t; + +/** + +* This data structure is used to pass Teletext and Subtitle +* information to be reinserted into the VBI of the PAL signal +* +* The packet structure contains up to two field's teletext +* lines with a 4-byte PES data header as defined in section +* 4.3 ETSI EN 300-472. +* +* Only data_unit_id's of Teletext Data (0x02) and Teletext +* subtitles (0x03) will be processed by the driver. Stuffing +* (0xFF) will be ignored. A value of 0x00 will generate a +* warning. +* +* Line numbers with a field id of 0 will have 313 added. +* Line numbers outside the VBI will generate a warning. +*/ +typedef struct { + bool enabled; /* OTM_HDMI_TRUE => Enabled */ + union { + teletext_packet_t packet[TELETEXT_NUM_LINES]; + unsigned char + raw_data[TELETEXT_NUM_LINES][TELETEXT_LINE_LENGTH]; + }; +} otm_hdmi_teletext_data_t; + +/* H D M I S P E C I F I C D A T A T Y P E S */ + +/** + This structure defines the HDMI audio data blocks. +*/ +typedef struct { + unsigned int format; + unsigned int max_channels; + unsigned int fs; + unsigned int ss_bitrate; +} otm_hdmi_audio_cap_t; + +/** + A CEC Source Physical Address. +*/ +typedef struct { + unsigned char a; + unsigned char b; + unsigned char c; + unsigned char d; +} otm_hdmi_src_phys_addr_t; + +/** + This data structure represents additional sink details not-available through + port attributes +*/ +typedef struct { + unsigned short manufac_id; /* Sink manufacturer ID */ + unsigned short product_code; /* Sink product code */ + bool hdmi; /* Sink is HDMI */ + bool ycbcr444; /* Sink supports YCbCr444 */ + bool ycbcr422; /* Sink supports YCbCr422 */ + otm_hdmi_src_phys_addr_t spa; /* CEC source physical address a.b.c.d*/ + unsigned int speaker_map; /* Speaker allocation map */ + bool dc_30; /* Sink supports 30-bit color */ + bool dc_36; /* Sink supports 36-bit color */ + bool dc_y444; /* Sink supports YCbCr444 in supported DC modes*/ + bool xvycc601; /* Sink supports xvYCC BT601 Colorimetry */ + bool xvycc709; /* Sink supports xvYCC BT709 Colorimetry */ + bool supports_ai; /* Sink supports aux audio information */ + unsigned int max_tmds_clock; /* Sink MAX TMDS clock in MHz. */ + bool latency_present; /* Sink lipsync data valid */ + bool latency_int_present; /* Sink Interlaced lipsync + data valid */ + bool hdmi_video_present; /* Sink Supports HDMI spec. + video modes */ + int latency_video; /* progressive modes video latency */ + int latency_audio; /* progressive modes audio latency */ + int latency_video_interlaced; /* interlaced modes video latency */ + int latency_audio_interlaced; /* interlaced modes audio latency */ + bool enabled_3d; /* Sink supports 3D video modes */ + bool num_modes_3d; /* DEPRECATED; */ + unsigned char max_horz_image_size; /* Sink's screen size in cm */ + unsigned char max_vert_image_size; /* Sink's screen size in cm */ + unsigned char name[14]; /* Sink's name */ + bool rgb_quant_full; /* RGB quantization mode selectable */ + bool ycc_quant_full; /* YCC quantization mode selectable */ +} otm_hdmi_sink_info_t; + +/** + This data structure represents 128 byte EDID block +*/ +typedef struct { + unsigned char index; /* Block number to read */ + unsigned char data[128]; /* Block contents */ +} otm_hdmi_edid_block_t; + +/** + This data structure represents HDCP topology information +*/ +typedef struct { + bool hdcp_1p1; /* Sink supports HDCP 1.1 */ + bool repeater; /* Sink is a repeater */ + bool max_cascade_exceeded; /* Maximum allowed depth exceeded */ + unsigned int depth; /* Topology depth */ + bool max_devs_exceeded; /* Maximum allowed device + number exceeded */ + unsigned int device_count; /* Number of devices connected + to the repeater */ + unsigned char aksv[5]; /* AKSV */ + unsigned char bksv[5]; /* BKSV read from connected sink */ + unsigned long long an; /* An */ + unsigned short ri; /* Ri */ + unsigned short ri_prime; /* Ri' from Sink */ + unsigned short pj; /* Pj */ + unsigned short pj_prime; /* Pj' from Sink */ +} otm_hdmi_hdcp_info_t; + +/** + This enumeration defines the command IDs for the HDMI audio commands. + See #otm_hdmi_audio_ctrl_t. +*/ +typedef enum { + OTM_HDMI_AUDIO_START, /* Start audio playback */ + OTM_HDMI_AUDIO_STOP, /* Stop audio playback */ + OTM_HDMI_AUDIO_SET_FORMAT, /* Set audio format */ + OTM_HDMI_AUDIO_GET_CAPS, /* Retrieve descriptor of audio blocks */ + OTM_HDMI_AUDIO_WRITE, /* For driver internal use only */ + OTM_HDMI_AUDIO_SET_CHANNEL_STATUS, /* Set channel status info */ + OTM_HDMI_AUDIO_GET_CHANNEL_STATUS, /* Get channel status info */ +} otm_hdmi_audio_cmd_id_t; + +/** + This enumeration defines IDs for different HDMI audio formats. +*/ +/* IMPORTANT: DO NOT change order!!! */ +typedef enum { + OTM_HDMI_AUDIO_FORMAT_UNDEFINED = 0x00, + OTM_HDMI_AUDIO_FORMAT_PCM, + OTM_HDMI_AUDIO_FORMAT_AC3, + OTM_HDMI_AUDIO_FORMAT_MPEG1, + OTM_HDMI_AUDIO_FORMAT_MP3, + OTM_HDMI_AUDIO_FORMAT_MPEG2, + OTM_HDMI_AUDIO_FORMAT_AAC, + OTM_HDMI_AUDIO_FORMAT_DTS, + OTM_HDMI_AUDIO_FORMAT_ATRAC, + OTM_HDMI_AUDIO_FORMAT_OBA, + OTM_HDMI_AUDIO_FORMAT_DDP, + OTM_HDMI_AUDIO_FORMAT_DTSHD, + OTM_HDMI_AUDIO_FORMAT_MLP, + OTM_HDMI_AUDIO_FORMAT_DST, + OTM_HDMI_AUDIO_FORMAT_WMA_PRO, +} otm_hdmi_audio_fmt_t; + +/** + This enumeration defines IDs for different HDMI audio sampling frequencies. +*/ +typedef enum { + OTM_HDMI_AUDIO_FS_32_KHZ = 0x01, + OTM_HDMI_AUDIO_FS_44_1_KHZ = 0x02, + OTM_HDMI_AUDIO_FS_48_KHZ = 0x04, + OTM_HDMI_AUDIO_FS_88_2_KHZ = 0x08, + OTM_HDMI_AUDIO_FS_96_KHZ = 0x10, + OTM_HDMI_AUDIO_FS_176_4_KHZ = 0x20, + OTM_HDMI_AUDIO_FS_192_KHZ = 0x40, +} otm_hdmi_audio_fs_t; + +/** + This enumeration defines IDs for different HDMI audio sample sizes. +*/ +typedef enum { + OTM_HDMI_AUDIO_SS_UNDEFINED = 0x00, /* Undefined value */ + OTM_HDMI_AUDIO_SS_16 = 0x01, /* 16 bits */ + OTM_HDMI_AUDIO_SS_20 = 0x02, /* 20 bits */ + OTM_HDMI_AUDIO_SS_24 = 0x04, /* 24 bits */ +} otm_hdmi_audio_ss_t; + +/** + Enumeration of the different audio speaker allocation options defined in the + CEA-861D specification. +*/ +typedef enum { + OTM_HDMI_AUDIO_SPEAKER_MAP_FLFR = 0x0001, + OTM_HDMI_AUDIO_SPEAKER_MAP_LFE = 0x0002, + OTM_HDMI_AUDIO_SPEAKER_MAP_FC = 0x0004, + OTM_HDMI_AUDIO_SPEAKER_MAP_RLRR = 0x0008, + OTM_HDMI_AUDIO_SPEAKER_MAP_RC = 0x0010, + OTM_HDMI_AUDIO_SPEAKER_MAP_FLCFRC = 0x0020, + OTM_HDMI_AUDIO_SPEAKER_MAP_RLCRRC = 0x0040, + OTM_HDMI_AUDIO_SPEAKER_MAP_FLWFRW = 0x0080, + OTM_HDMI_AUDIO_SPEAKER_MAP_FLHFRH = 0x0100, + OTM_HDMI_AUDIO_SPEAKER_MAP_TC = 0x0200, + OTM_HDMI_AUDIO_SPEAKER_MAP_FCH = 0x0400, +} otm_hdmi_audio_speaker_map_t; + +/** + This structure represents different audio commands +*/ +typedef struct { + otm_hdmi_audio_cmd_id_t cmd_id; /* Audio command type */ + + union /* Audio command details */ + { + struct /* Arguments for #OTM_HDMI_AUDIO_SET_FORMAT command. */ + { + otm_hdmi_audio_fmt_t fmt; /* Audio format */ + otm_hdmi_audio_fs_t fs; /* Sampling frequency */ + unsigned int ch; /* Number of channels */ + otm_hdmi_audio_ss_t ss; /* Sample size [in bits] */ + otm_hdmi_audio_speaker_map_t map; /* Speaker allocation + map */ + } _set_config; + + struct /* Arguments for #OTM_HDMI_AUDIO_GET_CAPS command. */ + { + unsigned int index; /* Capability number */ + otm_hdmi_audio_cap_t cap; /* Capability content */ + } _get_caps; + + struct /* Arguments for #OTM_HDMI_AUDIO_WRITE command */ + { + unsigned int samples; /* Audio samples buffer address*/ + unsigned int silence; /* Audio silence buffer address*/ + unsigned int size; /* Audio data buffer size */ + unsigned int id; /* Audio buffer ID */ + bool sync; /* Type of write operation */ + } _write; + + struct /* Arguments for #OTM_HDMI_AUDIO_STOP command */ + { + bool sync; /* Type of stop request */ + } _stop; + + struct /* Arguments for + #OTM_HDMI_AUDIO_SET_CHANNEL_STATUS command */ + { + unsigned int lsw; /* Least significant word of + ch status */ + unsigned int msw; /* Most significant word of + ch status */ + } _channel_status; + + } data; + +} otm_hdmi_audio_ctrl_t; + +#define HDMI_DIP_PACKET_HEADER_LEN 3 +#define HDMI_DIP_PACKET_DATA_LEN 28 + +/** + This structure represents generic HDMI packet +*/ +typedef struct { + uint8_t header[HDMI_DIP_PACKET_HEADER_LEN]; + union { + uint8_t data[HDMI_DIP_PACKET_DATA_LEN]; + uint32_t data32[HDMI_DIP_PACKET_DATA_LEN/4]; + }; +} otm_hdmi_packet_t; + +/** + This structure represents HDMI packet slot number +*/ +typedef enum { + OTM_HDMI_PACKET_SLOT_0, + OTM_HDMI_PACKET_SLOT_1, + OTM_HDMI_PACKET_SLOT_AVI, +} otm_hdmi_packet_slot_t; + +/** + This structure is used to submit data via #OTM_HDMI_SEND_HDMI_PACKET service + provided by #otm_hdmi_port_send +*/ +typedef struct { + otm_hdmi_packet_t packet; + otm_hdmi_packet_slot_t slot; +} otm_hdmi_packet_info_t; + +/** + This enumeration is used to specify values for the + #OTM_HDMI_ATTR_ID_USE_EDID attribute +*/ +typedef enum { + OTM_HDMI_USE_EDID_NONE = 0, + OTM_HDMI_USE_EDID_REAL = 1, + OTM_HDMI_USE_EDID_SAFE = 2, +} otm_hdmi_use_edid_t; + +/** +* This enumeration represents YC Delay amounts +*/ +typedef enum { + OTM_HDMI_YC_DELAY_NONE, /* No YC delay */ + OTM_HDMI_YC_DELAY_ADVANCE, /* Y 0.5 Pixel Advance delay */ + OTM_HDMI_YC_DELAY_MINUS /* Y 1.0 Pixel delay */ +} otm_hdmi_yc_delay_t; + +/** +* This enumeration represents vswing equalization values +*/ +typedef enum { + OTM_HDMI_EQUALIZE_NONE, /* Equalization disabled */ + OTM_HDMI_EQUALIZE_10, /* Equalization 10%, not supported on CE3100 */ + OTM_HDMI_EQUALIZE_20, /* Equalization 20% */ + OTM_HDMI_EQUALIZE_30, /* Equalization 30%, not supported on CE3100 */ + OTM_HDMI_EQUALIZE_40, /* Equalization 40% */ + OTM_HDMI_EQUALIZE_50, /* Equalization 50%, not supported on CE3100 */ + OTM_HDMI_EQUALIZE_60, /* Equalization 60% */ + OTM_HDMI_EQUALIZE_70, /* Equalization 70%, not supported on CE3100 */ + OTM_HDMI_EQUALIZE_80, /* Equalization 80% */ +} otm_hdmi_equalize_t; + +/** +* This enumeration represents transmit level amplitude values +*/ +typedef enum { + OTM_HDMI_TRANSMIT_LEVEL_300, /* 300 mV, not supported on CE3100 */ + OTM_HDMI_TRANSMIT_LEVEL_325, /* 325 mV, not supported on CE3100 */ + OTM_HDMI_TRANSMIT_LEVEL_350, /* 350 mV, not supported on CE3100 */ + OTM_HDMI_TRANSMIT_LEVEL_375, /* 375 mV, not supported on CE3100 */ + OTM_HDMI_TRANSMIT_LEVEL_400, /* 400 mV, not supported on CE3100 */ + OTM_HDMI_TRANSMIT_LEVEL_425, /* 425 mV, not supported on CE3100 */ + OTM_HDMI_TRANSMIT_LEVEL_450, /* 450 mV */ + OTM_HDMI_TRANSMIT_LEVEL_475, /* 475 mV, not supported on CE3100 */ + OTM_HDMI_TRANSMIT_LEVEL_500, /* 500 mV */ + OTM_HDMI_TRANSMIT_LEVEL_525, /* 525 mV, not supported on CE3100 */ + OTM_HDMI_TRANSMIT_LEVEL_550, /* 550 mV */ + OTM_HDMI_TRANSMIT_LEVEL_575, /* 575 mV, not supported on CE3100 */ + OTM_HDMI_TRANSMIT_LEVEL_600, /* 600 mV */ + OTM_HDMI_TRANSMIT_LEVEL_625, /* 625 mV, not supported on CE3100 */ + OTM_HDMI_TRANSMIT_LEVEL_650, /* 650 mV, not supported on CE3100 */ + OTM_HDMI_TRANSMIT_LEVEL_675, /* 675 mV, not supported on CE3100 */ +} otm_hdmi_transmit_level_t; + +/** +* This enumeration represents termination impedance values +*/ +typedef enum { + OTM_HDMI_TERMINATION_OPEN, /* Open */ + OTM_HDMI_TERMINATION_677, /* 677 Ohm, not supported on CE3100 */ + OTM_HDMI_TERMINATION_398, /* 398 Ohm, not supported on CE3100 */ + OTM_HDMI_TERMINATION_250, /* 250 Ohm, not supported on CE3100 */ + OTM_HDMI_TERMINATION_200, /* 200 Ohm */ + OTM_HDMI_TERMINATION_100, /* 100 Ohm */ + OTM_HDMI_TERMINATION_88, /* 88 Ohm, not supported on CE3100 */ + OTM_HDMI_TERMINATION_78, /* 78 Ohm, not supported on CE3100 */ + OTM_HDMI_TERMINATION_72, /* 72 Ohm, not supported on CE3100 */ + OTM_HDMI_TERMINATION_67, /* 67 Ohm */ + OTM_HDMI_TERMINATION_65, /* 65 Ohm, not supported on CE3100 */ + OTM_HDMI_TERMINATION_50, /* 50 Ohm */ +} otm_hdmi_termination_t; + +/** +* This enumeration represents current adjustment values +*/ +typedef enum { + OTM_HDMI_CURRENT_0MA, /* 0 mA */ + OTM_HDMI_CURRENT_40MA, /* 40 mA */ + OTM_HDMI_CURRENT_60MA, /* 60 mA */ + OTM_HDMI_CURRENT_10MA, /* 10 mA */ + OTM_HDMI_CURRENT_250MA, /* 250 mA */ + OTM_HDMI_CURRENT_290MA, /* 290 mA */ + OTM_HDMI_CURRENT_310MA, /* 310 mA */ + OTM_HDMI_CURRENT_350MA, /* 350 mA */ +} otm_hdmi_current_t; + +/** +* This enumeration represents band gap resistor values +*/ +typedef enum { + OTM_HDMI_BGLVL_788, /* 0.788v not supported on CE4100 */ + OTM_HDMI_BGLVL_818, /* 0.818v not supported on CE4100 */ + OTM_HDMI_BGLVL_854, /* 0.854v not supported on CE4100 + [CE3100 default] */ + OTM_HDMI_BGLVL_891, /* 0.891v not supported on CE4100 */ + OTM_HDMI_BGLVL_820, /* 0.82v not supported on CE3100 + [CE4100 default] */ + OTM_HDMI_BGLVL_800, /* 0.80v not supported on CE3100 */ + OTM_HDMI_BGLVL_780, /* 0.78v not supported on CE3100 */ + OTM_HDMI_BGLVL_760, /* 0.76v not supported on CE3100 */ + OTM_HDMI_BGLVL_750, /* 0.75v not supported on CE3100 */ + OTM_HDMI_BGLVL_720, /* 0.72v not supported on CE3100 */ + OTM_HDMI_BGLVL_660, /* 0.66v not supported on CE3100 */ + OTM_HDMI_BGLVL_600, /* 0.60v not supported on CE3100 */ +} otm_hdmi_bglvl_t; + +/** + This structure is used to submit data via #OTM_HDMI_SEND_HDMI_PACKET service + provided by #otm_hdmi_port_send and is intended for adjustments of PHY clock + and data lines. +*/ +typedef struct { + otm_hdmi_equalize_t clock_equalization; + /**< Clock equalization percentage. On CE3100, + * same value is used for both clock and data. + */ + otm_hdmi_equalize_t data_equalization; + /**< Data equalization percentage. + * IGNORED ON CE3100 + */ + otm_hdmi_transmit_level_t clock_transmit_level; + /**< Clock transmit level in mV. On CE3100, + * same value is used for both clock and data. + */ + otm_hdmi_transmit_level_t data_transmit_level; + /**< Data transmit level in mV. + * IGNORED ON CE3100. + */ + otm_hdmi_termination_t clock_termination; + /**< Clock termination in ohms. On CE3100, same + * value is used for both clock and data. + */ + otm_hdmi_termination_t data_termination; + /**< Data termination in ohms. + * IGNORED ON CE3100. + */ + otm_hdmi_current_t clock_current; + /**< Clock current in mA. On CE3100, same value + * is used for both clock and data. + */ + otm_hdmi_current_t data_current; + /**< Data current in mA. IGNORED ON CE3100 */ + otm_hdmi_bglvl_t bandgap_level; + /**< Same value used for both clock and data */ +} otm_hdmi_phy_info_t; + +/** +* This enumeration represents different HDCP states +*/ +typedef enum { + OTM_HDMI_HDCP_STATUS_OFF, /* HDCP is disabled */ + OTM_HDMI_HDCP_STATUS_IN_PROGRESS, /* HDCP is enabled but not + authenticated yet */ + OTM_HDMI_HDCP_STATUS_ON, /* HDCP is enabled and is authenticated */ +} otm_hdmi_hdcp_status_t; + +/** +* This enumeration represents audio clock values with respect to which +* internal audio divisor value is chosen +*/ +typedef enum { + OTM_HDMI_AUDIO_CLOCK_24, /* Audio clock is running at 24MHz */ + OTM_HDMI_AUDIO_CLOCK_36, /* Audio clock is running at 36Mhz */ + OTM_HDMI_AUDIO_CLOCK_16, /* Audio clock is running at 16Mhz */ +} otm_hdmi_audio_clock_t; + +/** +* This enumeration is used to specify values for the #OTM_HDMI_ATTR_ID_MUTE +* attribute +*/ +typedef enum { + OTM_HDMI_MUTE_OFF = 0x0, /* Unmute */ + OTM_HDMI_MUTE_VIDEO = 0x1, /* Mute video only */ + OTM_HDMI_MUTE_AUDIO = 0x2, /* Mute audio only */ + OTM_HDMI_MUTE_BOTH = 0x3, /* Mute both audio and video */ +} otm_hdmi_mute_t; + +#endif /* _OTM_HDMI_DEFS_H */ diff --git a/drivers/staging/mrst/drv/otm_hdmi/pil/include/otm_hdmi_types.h b/drivers/staging/mrst/drv/otm_hdmi/pil/include/otm_hdmi_types.h new file mode 100644 index 0000000..e1172b4 --- /dev/null +++ b/drivers/staging/mrst/drv/otm_hdmi/pil/include/otm_hdmi_types.h @@ -0,0 +1,463 @@ +/* + + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2011 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + + Intel Corporation + 2200 Mission College Blvd. + Santa Clara, CA 95054 + + BSD LICENSE + + Copyright(c) 2011 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ +#ifndef _OTM_HDMI_TYPES_H +#define _OTM_HDMI_TYPES_H + +/** + * typedef enum otm_hdmi_ret_t - OTM HDMI module return code definition + * OTM_HDMI_SUCCESS: Function executed without errors. + * OTM_HDMI_ERR_NO_MEMORY: Could not allocate memory. + * OTM_HDMI_ERR_FAILED: This is a generic error code means that a + * system call or call to some other software + * external to the driver. + * OTM_HDMI_ERR_INTERNAL: A condition that "should not be possible" was + * detected within the driver. This generally + * means there is nothing the application can do + * to correct the problem. + */ +typedef enum { + OTM_HDMI_SUCCESS = 0, + /**< + Function executed without errors + */ + OTM_HDMI_ERR_INVAL = 0x01, + /**< + An invalid argument was passed. + */ + OTM_HDMI_ERR_BUSY = 0x02, + /**< + An operation could not be completed because a needed resource is in use. + */ + OTM_HDMI_ERR_DISPLAY = 0x03, + /**< + An invalid display ID was passed. + */ + OTM_HDMI_ERR_SURFACE = 0x04, + /**< + An invalid surface ID, or the ID of a surface that is not + appropriate for the requested operation, was passed. + */ + OTM_HDMI_ERR_COMMAND = 0x05, + /**< + An internal command processing error occurred + */ + OTM_HDMI_ERR_NULL_ARG = 0x06, + /**< + A required argument was missing. Either a NULL pointer or a count + of 0 was passed for a required argument. + */ + OTM_HDMI_ERR_NO_MEMORY = 0x07, + /**< + Could not allocate memory. + */ + OTM_HDMI_ERR_FAILED = 0x08, + /**< + This is a generic error code that generally means that a system + call or call to some other software external to the driver + returned a failure code. + */ + OTM_HDMI_ERR_INTERNAL = 0x09, + /**< + A condition that "should not be possible" was detected within the + driver. This generally means there is nothing the application can + do to correct the problem. + */ + OTM_HDMI_ERR_NOT_IMPL = 0x0a, + /**< + The function is not currently implemented for the target chip. + */ + OTM_HDMI_ERR_MAPPED = 0x0b, + /**< + Operation not permitted on the mapped surface. + */ + OTM_HDMI_ERR_NO_INIT = 0x0c, + /**< + A GDL function was called without a preceding call to gdl_init(). + */ + OTM_HDMI_ERR_NO_HW_SUPPORT = 0x0d, + /**< + The target chip does not support the requested function. Examples: + - A graphics rendering option is not supported by the graphics core + in the target chip. + - A plane or port driver does not support a requested attribute. + - An attempt was made to request the attribute list from a port + driver that does not support any attributes. + */ + OTM_HDMI_ERR_INVAL_PF = 0x0e, + /**< + An unknown pixel format, or a pixel format not supported by the + attempted operation, was passed. + */ + OTM_HDMI_ERR_INVAL_RECT = 0x0f, + /**< + An invalid argument of type #gdl_rectangle_t was passed to the function. + */ + OTM_HDMI_ERR_ATTR_ID = 0x10, + /**< + An undefined ID was specified for a plane attribute or a port + driver attribute. + */ + OTM_HDMI_ERR_ATTR_NO_SUPPORT = 0x11, + /**< + An unsupported ID was specified for a plane attribute or a port + driver attribute. + */ + OTM_HDMI_ERR_ATTR_READONLY = 0x12, + /**< + An attempt was made to set the value of a read-only plane attribute + or port driver attribute. + */ + OTM_HDMI_ERR_ATTR_VALUE = 0x13, + /**< + An invalid value was specified for a plane attribute or a port + driver attribute. + */ + OTM_HDMI_ERR_PLANE_CONFLICT = 0x14, + /**< + An attempt was made to change the display mode to a resolution too + small to accommodate all of the currently enabled planes at their + current positions on the display. Move/shrink the affected planes first. + */ + OTM_HDMI_ERR_DISPLAY_CONFLICT = 0x15, + /**< + An attempt was made to change either display resolution or plane + size/origin, such that part/all of the plane will no longer be on the + display. + - If the display resolution is being reduced, change plane size/origin + first. + - If plane size is being increased, increase the display resolution + first, or reposition the plane. + - If plane origin is being changed, make sure you have picked an + appropriate origin given the current plane size and display + resolution. + */ + OTM_HDMI_ERR_TIMEOUT = 0x16, + /**< + The requested timeout period occurred before the requested + operation trigger occurred. + */ + OTM_HDMI_ERR_MISSING_BEGIN = 0x17, + /**< + An attempt was made to set a plane attribute without first calling + gdl_config_begin(). + */ + OTM_HDMI_ERR_PLANE_ID = 0x18, + /**< + An invalid plane ID was passed. The ID is undefined, the plane is not + supported by the target chip, or the plane is not supported by the + called function. + */ + OTM_HDMI_ERR_INVAL_PTR = 0x19, + /**< + On Linux, a copy between user and kernel space failed. This + probably indicates an invalid user space (argument) pointer. + */ + + OTM_HDMI_ERR_INVAL_HEAP = 0x1a, + /**< + An invalid heap was passed for addition or removal. Attempt + to add overlaping heaps will cause this error too. + */ + + OTM_HDMI_ERR_HEAP_IN_USE = 0x1b, + /**< + Heap removal was attempted while at least one surface was allocated + from that heap. + */ + + OTM_HDMI_ERR_INVAL_CALLBACK = 0x1c, + /**< + Invalid callback (null) was passed to gdl_event_register() function + */ + + OTM_HDMI_ERR_SCALING_POLICY = 0x1d, + /**< + A single scaling policy is required and was not specified for the + unsupported for the specified display ID. + */ + + OTM_HDMI_ERR_INVAL_EVENT = 0x1e, + /**< + Invalid event was passed to functions expecting #gdl_app_event_t. + */ + + OTM_HDMI_ERR_INVAL_IOCTL = 0x1f, + /**< + Invalid IOCTL request was sent to kernel module + */ + OTM_HDMI_ERR_SCHED_IN_ATOMIC = 0x20, + /**< + Scheduling was attempted while being in atomic context. + */ + OTM_HDMI_ERR_MMAP = 0x21, + /**< + Memory mapping failed + */ + OTM_HDMI_ERR_HDCP = 0x22, + /**< + HDCP failure + */ + OTM_HDMI_ERR_CONFIG = 0x23, + /**< + Platform config file error: either a required entry in the + platform configuration file is missing, or its entry is invalid. + */ + OTM_HDMI_ERR_HDMI_AUDIO_PLAYBACK = 0x24, + /**< + HDMI Audio start / stop / set buffer / set format command was + initiated at the wrong time. + */ + OTM_HDMI_ERR_HDMI_AUDIO_BUFFER_FULL = 0x25, + /**< + Given data does not fit in the internal buffer + */ + OTM_HDMI_ERR_PLANE_ORIGIN_ODD = 0x26, + /**< + In interlaced display modes, active planes must be configured with + their origins on even display lines. This error is returned when: + - in a progressive display mode: an attempt is made to change to an + interlaced display mode while there is an active plane does not + meet this requirement. + - in an interlaced display mode: + - an attempt is made to reconfigure an active plane's origin + to an odd line number, OR + - an attempt is made to activate (by flipping a surface to) a + plane that doesn't meet this requirement. + */ + OTM_HDMI_ERR_PLANE_HEIGHT_ODD = 0x27, + /**< + In interlaced display modes, active planes must be configured with + their even heights. This error is returned when: + - in a progressive display mode: an attempt is made to change to an + interlaced display mode while there is an active plane does not + meet this requirement. + - in an interlaced display mode: + - an attempt is made to reconfigure an active plane's height + to an odd value, OR + - an attempt is made to activate (by flipping a surface to) a + plane that doesn't meet this requirement. + */ + OTM_HDMI_ERR_HANDLE = 0x28, + /**< + Handle is not valid. + */ + OTM_HDMI_ERR_TVMODE_UNDEFINED = 0x29, + /**< + Display has undefined tv mode set on it. + */ + OTM_HDMI_ERR_PREMULT_CONFLICT = 0x2a, + /**< + An attempt was made to enable the #OTM_HDMI_PLANE_ALPHA_PREMULT + attribute and one of the following incompatible features at the same + time: + - Chroma keying on the same plane + (#OTM_HDMI_PLANE_CHROMA_KEY_SRC_ENABLE set to #OTM_HDMI_TRUE). + - Gamma removal on the same plane (#OTM_HDMI_PLANE_REVERSE_GAMMA_TYPE + set to a value other than #OTM_HDMI_GAMMA_LINEAR. + - color space conversion (the value of the plane's + + space of the display to which it is connected). + - a non-RGB pixel format. + */ + + OTM_HDMI_ERR_SUSPENDED = 0x2b, + /**< + An attempt was made to execute a command while the driver was in a + suspended mode. During the suspended mode driver is in a low-power + state and no access to hardware is allowed. + */ + + OTM_HDMI_ERR_STEREO_PLANE = 0x2c, + /**< + An attempt was made to stereo-flip to a plane unlinked to a right view + while a two-plane stereo display mode is in effect. + */ + + OTM_HDMI_ERR_CE4100_3D_ORIGIN = 0x2d, + /**< + On the CE4100, the origin of a plane's destination rectangle cannot + exceed 922 when OTM_HDMI_STEREO_FRAME_PACKING_2 stereo frame format is + in use. + */ + + OTM_HDMI_ERR_HDCP_KSV_INVALID = 0x2e, + /**< + HDCP invalid KSV + */ + OTM_HDMI_ERR_HDCP_KSV_REVOKED = 0x2f, + /**< + HDCP revoked KSV + */ + OTM_HDMI_ERR_HDCP_NO_ACK = 0x30, + /**< + HDCP I2C timeout when receiving R' + */ + OTM_HDMI_ERR_HDCP_LINK_INTEGRITY = 0x31, + /**< + HDCP R != R' + */ + + OTM_HDMI_ERR_PERM = 0x32, + /**< + Callers permissions are insufficient to perform a requested action. + */ + + /********************************************************************** + ATTENTION!!: WHEN ADDING AN ERROR CODE MAKE SURE TO: + - Search for a value marked "Currently unused" in the list above + before adding a new value at the end. + - Include inline (doxygen) documentation for the new error. + - Add the new error to _error_string() in debug.c + **********************************************************************/ +} otm_hdmi_ret_t; + +/* ---------------------------------------------------------------------- + * D I S P L A Y M O D E + * ---------------------------------------------------------------------- + */ + +/** + * Refresh rates for TV mode definitions. + * + * Refresh rate is the number of times the display is updated per second. + * This is the number of frames per second for progressive display modes; + * the number of fields (half the number of frames) per second for interlaced + * display modes. + * +*/ +typedef enum { + OTM_HDMI_REFRESH_23_98, /* 23.98... (24/1.001) */ + OTM_HDMI_REFRESH_24, /* 24 */ + OTM_HDMI_REFRESH_25, /* 25 */ + OTM_HDMI_REFRESH_29_97, /* 29.97... (30/1.001) */ + OTM_HDMI_REFRESH_30, /* 30 - DEPRECATED: This value is normally only + used on computer systems and should be used + with care, if at all. The corresponding TV + rate is 30/(1.001) (see + #OTM_HDMI_REFRESH_29_97). */ + OTM_HDMI_REFRESH_50, /* 50 */ + OTM_HDMI_REFRESH_59_94, /* 59.94... (60/1.001) */ + OTM_HDMI_REFRESH_60, /* 60 - DEPRECATED: This value is normally only + used on computer systems and should be used + with care, if at all. The corresponding TV + rate is 60/(1.001) (see + #OTM_HDMI_REFRESH_59_94). */ + OTM_HDMI_REFRESH_48, /* 48 - DEPRECATED: This value is normally only + used on HDMI output with special sink device + and should be used with care, if at all. */ + OTM_HDMI_REFRESH_47_96, /* 47.96... (48/1.001) */ + OTM_HDMI_REFRESH_NONE, /* Indicates that mode is not set */ + OTM_HDMI_REFRESH_USER_DEFINED + /* External (non-Intel) port drivers may define + additional refresh rates that the support. + Their IDs must be numbered starting at this + value. */ +} otm_hdmi_refresh_t; + +/** + * This enumeration is used to specify a stereo (3D) video format. The SOCs + * on which each format is supported are specified within square brackets. + * + * Format names ending in "_2" indicate that the format requires the use of + * two UPPs, one for the left view and one for the right. The + * + * to reference the left view plane in order to link them together. + * + * OTM_HDMI_STEREO_NONE + * Indicates a mono display mode (no stereo format is in use). + * + * OTM_HDMI_STEREO_FRAME_PACKING_2 + * Frame packing format implemented with 2 planes per stream. + * + * OTM_HDMI_STEREO_FRAME_PACKING [CE4200-B and above] + * Single-plane frame packing format. + * + * OTM_HDMI_STEREO_SIDE_BY_SIDE_HALF_2 + * Side-by-side format with the horizontal axis subsampled by half, + * implemented with 2 planes per stream. + * NOTE: Planes should be configured and buffers for graphics + * allocated at half horizontal resolution. The TV set is responsible for + * scaling the blended image horizontally by 2. + * + * OTM_HDMI_STEREO_TOP_BOTTOM_HALF_2 + * Top-and-bottom format with the vertical axis subsampled by half, + * implemented with 2 planes per stream. + * NOTE: Planes should be configured and buffers for graphics + * allocated at half vertical resolution. The TV set is responsible for + * scaling the blended image vertically by 2. + * + * OTM_HDMI_STEREO_FRAME_SEQUENTIAL + * Frame sequential format, a format used internally in some Digital TV + * sets for direct output to the panel. NOTE: in order to use Frame + * Sequential format, the HDMI port driver must be loaded with the dtv=1 + * command line argument. +*/ +typedef enum { + OTM_HDMI_STEREO_NONE = 0xabcdef01, + OTM_HDMI_STEREO_FRAME_PACKING_2, + OTM_HDMI_STEREO_FRAME_PACKING, + OTM_HDMI_STEREO_SIDE_BY_SIDE_HALF_2, + OTM_HDMI_STEREO_TOP_BOTTOM_HALF_2, + OTM_HDMI_STEREO_FRAME_SEQUENTIAL, +} otm_hdmi_stereo_t; +#endif /* _OTM_HDMI_TYPES_H */ diff --git a/drivers/staging/mrst/drv/otm_hdmi/pil/specific/include/ps_hdmi.h b/drivers/staging/mrst/drv/otm_hdmi/pil/specific/include/ps_hdmi.h new file mode 100644 index 0000000..1a5a8c8 --- /dev/null +++ b/drivers/staging/mrst/drv/otm_hdmi/pil/specific/include/ps_hdmi.h @@ -0,0 +1,91 @@ +/* + + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2011 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + + Intel Corporation + 2200 Mission College Blvd. + Santa Clara, CA 95054 + + BSD LICENSE + + Copyright(c) 2011 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef _PLATFORM_SPEC_H +#define _PLATFORM_SPEC_H + +#include +#include "otm_hdmi_types.h" +#include "otm_hdmi_defs.h" +#include "edid.h" + +otm_hdmi_ret_t ps_hdmi_i2c_edid_read(void *ctx, unsigned int sp, + unsigned int offset, void *buffer, + unsigned int size); + +otm_hdmi_ret_t ps_hdmi_pci_dev_init(void *context, struct pci_dev *pdev); + +otm_hdmi_ret_t ps_hdmi_pci_dev_deinit(void *context); + +/* + * Description: fetches the preferred scaling type for a aprticular platfrom. + * + * @context: hdmi context pointer + * @pscaling_type: pointer to be updated with scaling type info. + * + * Returns: OTM_HDMI_SUCCESS on success + * OTM_HDMI_ERR_INVAL on NULL input arguments + */ +otm_hdmi_ret_t ps_hdmi_get_pref_scalingtype(void *context, + int *pscaling_type); +#endif /* _PLATFORM_SPEC_H */ diff --git a/drivers/staging/mrst/drv/otm_hdmi/pil/specific/mfld/ps_hdmi.c b/drivers/staging/mrst/drv/otm_hdmi/pil/specific/mfld/ps_hdmi.c new file mode 100644 index 0000000..f994033 --- /dev/null +++ b/drivers/staging/mrst/drv/otm_hdmi/pil/specific/mfld/ps_hdmi.c @@ -0,0 +1,186 @@ +/* + + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2011 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + + Intel Corporation + 2200 Mission College Blvd. + Santa Clara, CA 95054 + + BSD LICENSE + + Copyright(c) 2011 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ +#include "otm_hdmi_types.h" + +#include +#include +#include +#include +#include "otm_hdmi.h" +#include "ipil_hdmi.h" + +#define PS_HDMI_MMIO_RESOURCE 0 +#define PS_VDC_OFFSET 0x00000000 +#define PS_VDC_SIZE 0x000080000 +#define PS_MSIC_PCI_DEVICE_ID 0x0831 +#define PS_MSIC_VRINT_ADDR 0xFFFF7FCB +#define PS_MSIC_VRINT_IOADDR_LEN 0x02 + +otm_hdmi_ret_t ps_hdmi_pci_dev_init(void *context, struct pci_dev *pdev) +{ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + int result = 0; + struct pci_dev *msic_pdev = NULL; + unsigned int vdc_start; + uint32_t pci_address = 0; + uint8_t pci_dev_revision = 0; + hdmi_context_t *ctx = NULL; + + if (pdev == NULL || context == NULL) { + rc = OTM_HDMI_ERR_INTERNAL; + goto exit; + } + ctx = (hdmi_context_t *)context; + + pr_debug("\nget resource start\n"); + result = pci_read_config_dword(pdev, 16, &vdc_start); + if (result != 0) { + rc = OTM_HDMI_ERR_FAILED; + goto exit; + } + pci_address = vdc_start + PS_VDC_OFFSET; + + pr_debug("\nmap IO region\n"); + /* Map IO region and save its length */ + ctx->io_length = PS_VDC_SIZE; + ctx->io_address = ioremap_cache(pci_address, ctx->io_length); + if (!ctx->io_address) { + rc = OTM_HDMI_ERR_FAILED; + goto exit; + } + + /* Map IO region for IRQ registers */ + ctx->dev.irq_io_address = ioremap_nocache(PS_MSIC_VRINT_ADDR, + PS_MSIC_VRINT_IOADDR_LEN); + if (!ctx->dev.irq_io_address) { + rc = OTM_HDMI_ERR_FAILED; + goto exit; + } + + pr_debug("\nget PCI dev revision\n"); + result = pci_read_config_byte(pdev, 8, &pci_dev_revision); + if (result != 0) { + rc = OTM_HDMI_ERR_FAILED; + goto exit; + } + ctx->dev.id = pci_dev_revision; + + pr_debug("pci_get_device for 0x%x\n", PS_MSIC_PCI_DEVICE_ID); + msic_pdev = pci_get_device(PCI_VENDOR_INTEL, + PS_MSIC_PCI_DEVICE_ID, msic_pdev); + if (msic_pdev == NULL) { + rc = OTM_HDMI_ERR_FAILED; + goto exit; + } + pr_debug("pci_enable_device for 0x%x\n", + PS_MSIC_PCI_DEVICE_ID); + result = pci_enable_device(msic_pdev); + if (result) { + rc = OTM_HDMI_ERR_FAILED; + goto exit; + } + pr_debug("IRQ number assigned = %d\n", msic_pdev->irq); + ctx->irq_number = msic_pdev->irq; + +exit: + return rc; +} + +otm_hdmi_ret_t ps_hdmi_pci_dev_deinit(void *context) +{ + otm_hdmi_ret_t rc = OTM_HDMI_SUCCESS; + struct pci_dev *msic_pdev = NULL; + hdmi_context_t *ctx = NULL; + + if (context == NULL) { + rc = OTM_HDMI_ERR_INTERNAL; + goto exit; + } + ctx = (hdmi_context_t *)context; + + /* unmap IO region */ + iounmap(ctx->io_address) ; + + /* TODO: Enable this on DV1 once PCI issue is resolved */ + msic_pdev = pci_get_device(PCI_VENDOR_INTEL, + PS_MSIC_PCI_DEVICE_ID, msic_pdev); + if (msic_pdev == NULL) { + rc = OTM_HDMI_ERR_FAILED; + goto exit; + } + pci_disable_device(msic_pdev); +exit: + return rc; +} + +otm_hdmi_ret_t ps_hdmi_i2c_edid_read(void *ctx, unsigned int sp, + unsigned int offset, void *buffer, + unsigned int size) +{ + hdmi_context_t *context = (hdmi_context_t *)ctx; + + char *src = context->edid_raw + sp * SEGMENT_SIZE + offset; + memcpy(buffer, src, size); + + return OTM_HDMI_SUCCESS; +} diff --git a/drivers/staging/mrst/drv/otm_hdmi/pil/specific/mfld/ps_hdmi_tablet.c b/drivers/staging/mrst/drv/otm_hdmi/pil/specific/mfld/ps_hdmi_tablet.c new file mode 100644 index 0000000..36e47be --- /dev/null +++ b/drivers/staging/mrst/drv/otm_hdmi/pil/specific/mfld/ps_hdmi_tablet.c @@ -0,0 +1,89 @@ +/* + + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2011 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + + Intel Corporation + 2200 Mission College Blvd. + Santa Clara, CA 95054 + + BSD LICENSE + + Copyright(c) 2011 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ +#include "otm_hdmi_types.h" +#include "hdmi_internal.h" + +#define PS_PREF_SCALINGTYPE IPIL_TIMING_SCALE_FULLSCREEN + +/* + * Description: fetches the preferred scaling type for a aprticular platfrom. + * + * @context: hdmi context pointer + * @pscaling_type: pointer to be updated with scaling type info. + * + * Returns: OTM_HDMI_SUCCESS on success + * OTM_HDMI_ERR_INVAL on NULL input arguments + */ +otm_hdmi_ret_t ps_hdmi_get_pref_scalingtype(void *context, + int *pscaling_type) +{ + hdmi_context_t *ctx = (hdmi_context_t *)context; + + if (NULL == ctx || NULL == pscaling_type) + return OTM_HDMI_ERR_INVAL; + + *pscaling_type = PS_PREF_SCALINGTYPE; + + return OTM_HDMI_SUCCESS; +} + -- 2.7.4