libcec: repaired detection of logical address; prevent that amlogic adapter hangs on close

This commit is contained in:
Gerald Dachs 2016-03-22 19:34:58 +01:00 committed by kszaq
parent 14b0ed1abe
commit 4344e2a16b
3 changed files with 410 additions and 228 deletions

View File

@ -1,36 +1,7 @@
diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/include/cectypes.h libcec-3.0.1-with-amlogic-adapter/include/cectypes.h
--- libcec-3.0.1/include/cectypes.h 2016-02-21 01:11:20.791177759 +0100
+++ libcec-3.0.1-with-amlogic-adapter/include/cectypes.h 2016-02-10 13:45:19.057046951 +0100
@@ -320,6 +320,16 @@
/*!
+ * the path to use for the Amlogic HDMI CEC device
+ */
+#define CEC_AMLOGIC_PATH "/dev/AmlogicCEC"
+
+/*!
+ * the name of the virtual COM port to use for the AMLOGIC' CEC wire
+ */
+#define CEC_AMLOGIC_VIRTUAL_COM "Amlogic"
+
+/*!
* Mimimum client version
*/
#define CEC_MIN_LIB_VERSION 3
@@ -888,7 +898,8 @@
ADAPTERTYPE_RPI = 0x100,
ADAPTERTYPE_TDA995x = 0x200,
ADAPTERTYPE_EXYNOS = 0x300,
- ADAPTERTYPE_IMX = 0x400
+ ADAPTERTYPE_IMX = 0x400,
+ ADAPTERTYPE_AMLOGIC = 0x500
} cec_adapter_type;
/** force exporting through swig */
diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/README.md libcec-3.0.1-with-amlogic-adapter/README.md
--- libcec-3.0.1/README.md 2015-07-03 19:20:49.000000000 +0200
+++ libcec-3.0.1-with-amlogic-adapter/README.md 2016-02-10 12:03:54.517523977 +0100
diff --git a/README.md b/README.md
index dfaf4d6..0dffdcf 100644
--- a/README.md
+++ b/README.md
@@ -58,6 +58,12 @@
cmake -DHAVE_EXYNOS_API=1 ..
```
@ -44,9 +15,54 @@ diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/README.md libcec-3.
## TDA995x ##
To compile in support for TDA995x devices, you have to pass the argument -DHAVE_TDA995X_API=1 to cmake:
```
diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/adapter/AdapterFactory.cpp libcec-3.0.1-with-amlogic-adapter/src/libcec/adapter/AdapterFactory.cpp
--- libcec-3.0.1/src/libcec/adapter/AdapterFactory.cpp 2016-02-21 01:11:12.579266950 +0100
+++ libcec-3.0.1-with-amlogic-adapter/src/libcec/adapter/AdapterFactory.cpp 2016-02-10 12:41:44.252060917 +0100
diff --git a/include/cectypes.h b/include/cectypes.h
index e28c8df..c0b9476 100644
--- a/include/cectypes.h
+++ b/include/cectypes.h
@@ -318,6 +318,15 @@ namespace CEC {
*/
#define CEC_IMX_VIRTUAL_COM "i.MX"
+/*!
+ * the path to use for the Amlogic HDMI CEC device
+ */
+#define CEC_AMLOGIC_PATH "/dev/AmlogicCEC"
+
+/*!
+ * the name of the virtual COM port to use for the AMLOGIC' CEC wire
+ */
+#define CEC_AMLOGIC_VIRTUAL_COM "Amlogic"
/*!
* Mimimum client version
@@ -889,7 +898,8 @@ typedef enum cec_adapter_type
ADAPTERTYPE_RPI = 0x100,
ADAPTERTYPE_TDA995x = 0x200,
ADAPTERTYPE_EXYNOS = 0x300,
- ADAPTERTYPE_IMX = 0x400
+ ADAPTERTYPE_IMX = 0x400,
+ ADAPTERTYPE_AMLOGIC = 0x500
} cec_adapter_type;
/** force exporting through swig */
diff --git a/src/libcec/CMakeLists.txt b/src/libcec/CMakeLists.txt
index a494533..e94b094 100644
--- a/src/libcec/CMakeLists.txt
+++ b/src/libcec/CMakeLists.txt
@@ -87,6 +87,9 @@ set(CEC_HEADERS devices/CECRecordingDevice.h
adapter/Exynos/ExynosCEC.h
adapter/Exynos/ExynosCECAdapterDetection.h
adapter/Exynos/ExynosCECAdapterCommunication.h
+ adapter/Amlogic/AmlogicCEC.h
+ adapter/Amlogic/AmlogicCECAdapterDetection.h
+ adapter/Amlogic/AmlogicCECAdapterCommunication.h
adapter/Pulse-Eight/USBCECAdapterMessageQueue.h
adapter/Pulse-Eight/USBCECAdapterCommunication.h
adapter/Pulse-Eight/USBCECAdapterCommands.h
diff --git a/src/libcec/adapter/AdapterFactory.cpp b/src/libcec/adapter/AdapterFactory.cpp
index 92e378b..55703b9 100644
--- a/src/libcec/adapter/AdapterFactory.cpp
+++ b/src/libcec/adapter/AdapterFactory.cpp
@@ -63,6 +63,11 @@
#include "IMX/IMXCECAdapterCommunication.h"
#endif
@ -59,7 +75,16 @@ diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/adapter/
using namespace CEC;
int8_t CAdapterFactory::FindAdapters(cec_adapter *deviceList, uint8_t iBufSize, const char *strDevicePath /* = NULL */)
@@ -131,6 +136,18 @@
@@ -131,8 +136,6 @@ int8_t CAdapterFactory::DetectAdapters(cec_adapter_descriptor *deviceList, uint8
}
#endif
-
-
#if defined(HAVE_IMX_API)
if (iAdaptersFound < iBufSize && CIMXCECAdapterDetection::FindAdapter() &&
(!strDevicePath || !strcmp(strDevicePath, CEC_IMX_VIRTUAL_COM)))
@@ -146,8 +149,20 @@ int8_t CAdapterFactory::DetectAdapters(cec_adapter_descriptor *deviceList, uint8
}
#endif
@ -74,12 +99,15 @@ diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/adapter/
+ iAdaptersFound++;
+ }
+#endif
-#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) && !defined(HAVE_IMX_API)
+
+#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) && !defined(HAVE_IMX_API) && !defined(HAVE_AMLOGIC_API)
#error "libCEC doesn't have support for any type of adapter. please check your build system or configuration"
#endif
#if defined(HAVE_IMX_API)
@@ -166,6 +183,11 @@
return new CExynosCECAdapterCommunication(m_lib->m_cec);
@@ -176,11 +191,16 @@ IAdapterCommunication *CAdapterFactory::GetInstance(const char *strPort, uint16_
return new CIMXCECAdapterCommunication(m_lib->m_cec);
#endif
+#if defined(HAVE_AMLOGIC_API)
@ -87,22 +115,68 @@ diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/adapter/
+ return new CAmlogicCECAdapterCommunication(m_lib->m_cec);
+#endif
+
#if defined(HAVE_RPI_API)
if (!strcmp(strPort, CEC_RPI_VIRTUAL_COM))
return new CRPiCECAdapterCommunication(m_lib->m_cec);
@@ -180,7 +202,7 @@
#if defined(HAVE_P8_USB)
return new CUSBCECAdapterCommunication(m_lib->m_cec, strPort, iBaudRate);
#endif
-#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) && !defined(HAVE_EXYNOS_API) && !defined(HAVE_IMX_API)
+#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) && !defined(HAVE_EXYNOS_API) && !defined(HAVE_IMX_API) && !defined(HAVE_AMLOGIC_API)
+#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) && !defined(HAVE_EXYNOS_API) && !defined(HAVE_IMX_API) && !defined(HAVE_AMLOGIC_API)
return NULL;
#endif
}
diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/adapter/Amlogic/AmlogicCECAdapterCommunication.cpp libcec-3.0.1-with-amlogic-adapter/src/libcec/adapter/Amlogic/AmlogicCECAdapterCommunication.cpp
--- libcec-3.0.1/src/libcec/adapter/Amlogic/AmlogicCECAdapterCommunication.cpp 1970-01-01 01:00:00.000000000 +0100
+++ libcec-3.0.1-with-amlogic-adapter/src/libcec/adapter/Amlogic/AmlogicCECAdapterCommunication.cpp 2016-02-28 12:31:26.771045268 +0100
@@ -0,0 +1,298 @@
diff --git a/src/libcec/adapter/Amlogic/AmlogicCEC.h b/src/libcec/adapter/Amlogic/AmlogicCEC.h
new file mode 100644
index 0000000..7b86982
--- /dev/null
+++ b/src/libcec/adapter/Amlogic/AmlogicCEC.h
@@ -0,0 +1,41 @@
+#pragma once
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC Amlogic Code Copyright (C) 2016 Gerald Dachs
+ * based heavily on:
+ * libCEC Exynos Code Copyright (C) 2014 Valentin Manea
+ * libCEC(R) is Copyright (C) 2011-2015 Pulse-Eight Limited. All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing <license@pulse-eight.com>
+ * http://www.pulse-eight.com/
+ * http://www.pulse-eight.net/
+ */
+
+
+#define CEC_DEFAULT_PADDR 0x1000
+#define CEC_IOC_SETLADDR _IOW('c', 0, unsigned int)
+#define CEC_IOC_GETPADDR _IO('c', 1)
+#define CEC_MAX_FRAME_SIZE 16
diff --git a/src/libcec/adapter/Amlogic/AmlogicCECAdapterCommunication.cpp b/src/libcec/adapter/Amlogic/AmlogicCECAdapterCommunication.cpp
new file mode 100644
index 0000000..5aeddda
--- /dev/null
+++ b/src/libcec/adapter/Amlogic/AmlogicCECAdapterCommunication.cpp
@@ -0,0 +1,305 @@
+/*
+ * This file is part of the libCEC(R) library.
+ *
@ -346,6 +420,7 @@ diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/adapter/
+ uint32_t size;
+ fd_set rfds;
+ cec_logical_address initiator, destination;
+ struct timeval tv;
+
+ if (!IsOpen())
+ return 0;
@ -362,8 +437,15 @@ diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/adapter/
+ FD_ZERO(&rfds);
+ FD_SET(fd, &rfds);
+
+ if (select(fd + 1, &rfds, NULL, NULL, NULL) >= 0 )
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+
+ if (select(fd + 1, &rfds, NULL, NULL, &tv) >= 0 )
+ {
+
+ if (!FD_ISSET(fd, &rfds))
+ continue;
+
+ size = read(fd, buffer, CEC_MAX_FRAME_SIZE);
+
+ if (size > 0)
@ -394,16 +476,17 @@ diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/adapter/
+ m_callback->OnCommandReceived(cmd);
+ }
+ }
+
+ }
+
+ return 0;
+}
+
+#endif // HAVE_AMLOGIC_API
diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/adapter/Amlogic/AmlogicCECAdapterCommunication.h libcec-3.0.1-with-amlogic-adapter/src/libcec/adapter/Amlogic/AmlogicCECAdapterCommunication.h
--- libcec-3.0.1/src/libcec/adapter/Amlogic/AmlogicCECAdapterCommunication.h 1970-01-01 01:00:00.000000000 +0100
+++ libcec-3.0.1-with-amlogic-adapter/src/libcec/adapter/Amlogic/AmlogicCECAdapterCommunication.h 2016-02-28 12:16:30.985474428 +0100
diff --git a/src/libcec/adapter/Amlogic/AmlogicCECAdapterCommunication.h b/src/libcec/adapter/Amlogic/AmlogicCECAdapterCommunication.h
new file mode 100644
index 0000000..0e99cf8
--- /dev/null
+++ b/src/libcec/adapter/Amlogic/AmlogicCECAdapterCommunication.h
@@ -0,0 +1,105 @@
+#pragma once
+/*
@ -510,9 +593,11 @@ diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/adapter/
+ };
+};
+#endif
diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/adapter/Amlogic/AmlogicCECAdapterDetection.cpp libcec-3.0.1-with-amlogic-adapter/src/libcec/adapter/Amlogic/AmlogicCECAdapterDetection.cpp
--- libcec-3.0.1/src/libcec/adapter/Amlogic/AmlogicCECAdapterDetection.cpp 1970-01-01 01:00:00.000000000 +0100
+++ libcec-3.0.1-with-amlogic-adapter/src/libcec/adapter/Amlogic/AmlogicCECAdapterDetection.cpp 2016-02-10 11:57:58.445532459 +0100
diff --git a/src/libcec/adapter/Amlogic/AmlogicCECAdapterDetection.cpp b/src/libcec/adapter/Amlogic/AmlogicCECAdapterDetection.cpp
new file mode 100644
index 0000000..2247346
--- /dev/null
+++ b/src/libcec/adapter/Amlogic/AmlogicCECAdapterDetection.cpp
@@ -0,0 +1,50 @@
+/*
+ * This file is part of the libCEC(R) library.
@ -564,9 +649,11 @@ diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/adapter/
+}
+
+#endif
diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/adapter/Amlogic/AmlogicCECAdapterDetection.h libcec-3.0.1-with-amlogic-adapter/src/libcec/adapter/Amlogic/AmlogicCECAdapterDetection.h
--- libcec-3.0.1/src/libcec/adapter/Amlogic/AmlogicCECAdapterDetection.h 1970-01-01 01:00:00.000000000 +0100
+++ libcec-3.0.1-with-amlogic-adapter/src/libcec/adapter/Amlogic/AmlogicCECAdapterDetection.h 2016-02-10 11:57:58.445532459 +0100
diff --git a/src/libcec/adapter/Amlogic/AmlogicCECAdapterDetection.h b/src/libcec/adapter/Amlogic/AmlogicCECAdapterDetection.h
new file mode 100644
index 0000000..8a7418d
--- /dev/null
+++ b/src/libcec/adapter/Amlogic/AmlogicCECAdapterDetection.h
@@ -0,0 +1,46 @@
+#pragma once
+/*
@ -614,54 +701,10 @@ diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/adapter/
+ static bool FindAdapter(void);
+ };
+}
diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/adapter/Amlogic/AmlogicCEC.h libcec-3.0.1-with-amlogic-adapter/src/libcec/adapter/Amlogic/AmlogicCEC.h
--- libcec-3.0.1/src/libcec/adapter/Amlogic/AmlogicCEC.h 1970-01-01 01:00:00.000000000 +0100
+++ libcec-3.0.1-with-amlogic-adapter/src/libcec/adapter/Amlogic/AmlogicCEC.h 2016-02-10 11:57:58.445532459 +0100
@@ -0,0 +1,41 @@
+#pragma once
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC Amlogic Code Copyright (C) 2016 Gerald Dachs
+ * based heavily on:
+ * libCEC Exynos Code Copyright (C) 2014 Valentin Manea
+ * libCEC(R) is Copyright (C) 2011-2015 Pulse-Eight Limited. All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing <license@pulse-eight.com>
+ * http://www.pulse-eight.com/
+ * http://www.pulse-eight.net/
+ */
+
+
+#define CEC_DEFAULT_PADDR 0x1000
+#define CEC_IOC_SETLADDR _IOW('c', 0, unsigned int)
+#define CEC_IOC_GETPADDR _IO('c', 1)
+#define CEC_MAX_FRAME_SIZE 16
diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/cmake/CheckPlatformSupport.cmake libcec-3.0.1-with-amlogic-adapter/src/libcec/cmake/CheckPlatformSupport.cmake
--- libcec-3.0.1/src/libcec/cmake/CheckPlatformSupport.cmake 2016-02-21 01:11:12.579266950 +0100
+++ libcec-3.0.1-with-amlogic-adapter/src/libcec/cmake/CheckPlatformSupport.cmake 2016-02-10 13:18:20.847385373 +0100
diff --git a/src/libcec/cmake/CheckPlatformSupport.cmake b/src/libcec/cmake/CheckPlatformSupport.cmake
index dc5bc25..64003d9 100644
--- a/src/libcec/cmake/CheckPlatformSupport.cmake
+++ b/src/libcec/cmake/CheckPlatformSupport.cmake
@@ -11,6 +11,7 @@
# HAVE_IMX_API 1 if i.MX is supported
# HAVE_TDA995X_API 1 if TDA995X is supported
@ -670,7 +713,7 @@ diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/cmake/Ch
# HAVE_P8_USB_DETECT 1 if Pulse-Eight devices can be auto-detected
#
@@ -129,6 +130,18 @@
@@ -142,6 +143,18 @@ else()
else()
set(HAVE_EXYNOS_API 0)
endif()
@ -689,11 +732,12 @@ diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/cmake/Ch
endif()
# rt
diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/cmake/DisplayPlatformSupport.cmake libcec-3.0.1-with-amlogic-adapter/src/libcec/cmake/DisplayPlatformSupport.cmake
--- libcec-3.0.1/src/libcec/cmake/DisplayPlatformSupport.cmake 2016-02-21 01:11:12.579266950 +0100
+++ libcec-3.0.1-with-amlogic-adapter/src/libcec/cmake/DisplayPlatformSupport.cmake 2016-02-10 12:47:10.380408360 +0100
@@ -50,6 +50,12 @@
message(STATUS "Exynos support: no")
diff --git a/src/libcec/cmake/DisplayPlatformSupport.cmake b/src/libcec/cmake/DisplayPlatformSupport.cmake
index 4e24def..1890cac 100644
--- a/src/libcec/cmake/DisplayPlatformSupport.cmake
+++ b/src/libcec/cmake/DisplayPlatformSupport.cmake
@@ -50,6 +50,12 @@ else()
message(STATUS "DRM support: no")
endif()
+if (HAVE_AMLOGIC_API)
@ -705,23 +749,11 @@ diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/cmake/Di
if (HAVE_PYTHON)
message(STATUS "Python support: version ${PYTHONLIBS_VERSION_STRING} (${PYTHON_VERSION})")
else()
diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/CMakeLists.txt libcec-3.0.1-with-amlogic-adapter/src/libcec/CMakeLists.txt
--- libcec-3.0.1/src/libcec/CMakeLists.txt 2015-07-03 19:20:49.000000000 +0200
+++ libcec-3.0.1-with-amlogic-adapter/src/libcec/CMakeLists.txt 2016-02-10 11:57:58.445532459 +0100
@@ -83,6 +83,9 @@
adapter/Exynos/ExynosCEC.h
adapter/Exynos/ExynosCECAdapterDetection.h
adapter/Exynos/ExynosCECAdapterCommunication.h
+ adapter/Amlogic/AmlogicCEC.h
+ adapter/Amlogic/AmlogicCECAdapterDetection.h
+ adapter/Amlogic/AmlogicCECAdapterCommunication.h
adapter/Pulse-Eight/USBCECAdapterMessageQueue.h
adapter/Pulse-Eight/USBCECAdapterCommunication.h
adapter/Pulse-Eight/USBCECAdapterCommands.h
diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/env.h.in libcec-3.0.1-with-amlogic-adapter/src/libcec/env.h.in
--- libcec-3.0.1/src/libcec/env.h.in 2016-02-21 01:11:12.579266950 +0100
+++ libcec-3.0.1-with-amlogic-adapter/src/libcec/env.h.in 2016-02-10 11:57:58.449532413 +0100
@@ -69,6 +69,9 @@
diff --git a/src/libcec/env.h.in b/src/libcec/env.h.in
index 384f1c7..c3f00bc 100644
--- a/src/libcec/env.h.in
+++ b/src/libcec/env.h.in
@@ -75,6 +75,9 @@
/* Define to 1 for Exynos support */
#cmakedefine HAVE_EXYNOS_API @HAVE_EXYNOS_API@

View File

@ -55,10 +55,10 @@ index 7a944cd..f74ec1f 100755
#EXTRA_CFLAGS += -O2
diff --git a/drivers/amlogic/hdmi/hdmi_tx/amlogic_cec.c b/drivers/amlogic/hdmi/hdmi_tx/amlogic_cec.c
new file mode 100644
index 0000000..bd31aaa
index 0000000..a3556b3
--- /dev/null
+++ b/drivers/amlogic/hdmi/hdmi_tx/amlogic_cec.c
@@ -0,0 +1,596 @@
@@ -0,0 +1,671 @@
+/* linux/drivers/amlogic/hdmi/hdmi_tx/amlogic_cec.c
+ *
+ * Copyright (c) 2016 Gerald Dachs
@ -84,6 +84,7 @@ index 0000000..bd31aaa
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/atomic.h>
+#include <linux/semaphore.h>
+
+#include <asm/uaccess.h>
+#include <asm/delay.h>
@ -127,6 +128,8 @@ index 0000000..bd31aaa
+/* CEC Tx buffer size */
+#define CEC_TX_BUFF_SIZE 16
+
+static DEFINE_SEMAPHORE(init_mutex);
+
+struct cec_rx_list {
+ u8 buffer[CEC_RX_BUFF_SIZE];
+ unsigned char size;
@ -226,7 +229,7 @@ index 0000000..bd31aaa
+ rx_msg_status = amlogic_cec_read_reg(CEC_RX_MSG_STATUS);
+ rx_num_msg = amlogic_cec_read_reg(CEC_RX_NUM_MSG);
+
+ amlogic_cec_log_dbg("amlogic_cec_read_hw: enter: CEC_RX_MSG_STATUS %d, CEC_RX_NUM_MSG %d\n", rx_msg_status, rx_num_msg);
+ amlogic_cec_log_dbg("rx_msg_status: %d, rx_num_msg: %d\n", rx_msg_status, rx_num_msg);
+
+ valid_msg = (RX_DONE == rx_msg_status) && (1 == rx_num_msg);
+
@ -248,7 +251,7 @@ index 0000000..bd31aaa
+#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8
+ aml_write_reg32(P_AO_CEC_INTR_CLR, aml_read_reg32(P_AO_CEC_INTR_CLR) | (1 << 2));
+#endif
+ amlogic_cec_write_reg(CEC_RX_MSG_CMD, RX_ACK_NEXT);
+ amlogic_cec_write_reg(CEC_RX_MSG_CMD, valid_msg ? RX_ACK_NEXT : RX_ACK_CURRENT);
+ amlogic_cec_write_reg(CEC_RX_MSG_CMD, RX_NO_OP);
+
+ return ret;
@ -290,45 +293,89 @@ index 0000000..bd31aaa
+ if (hdmitx_device->hdmi_info.vsdb_phy_addr.valid == 0)
+ {
+ amlogic_cec_log_dbg("no valid cec physical address\n");
+ if (aml_read_reg32(P_AO_DEBUG_REG1))
+ if (aml_read_reg32(P_AO_DEBUG_REG1) & 0xffff)
+ {
+ amlogic_cec_log_dbg("use last physical address\n");
+ }
+ else
+ {
+ aml_write_reg32(P_AO_DEBUG_REG1, 0x1000);
+ aml_write_reg32(P_AO_DEBUG_REG1, (aml_read_reg32(P_AO_DEBUG_REG1) & (0xf << 16)) | 0x1000);
+ amlogic_cec_log_dbg("use default physical address\n");
+ }
+ }
+ else
+ {
+ aml_write_reg32(P_AO_DEBUG_REG1, cec_phy_addr);
+ amlogic_cec_log_dbg("physical address:0x%x\n", aml_read_reg32(P_AO_DEBUG_REG1));
+
+ if ((hdmitx_device->cec_init_ready != 0) && (hdmitx_device->hpd_state != 0))
+ {
+ if ((entry = kmalloc(sizeof(struct cec_rx_list), GFP_ATOMIC)) == NULL)
+ if (cec_global_info.my_node_index)
+ {
+ // prevent write operations
+ if (down_interruptible(&init_mutex))
+ {
+ amlogic_cec_log_dbg("can't alloc cec_rx_list\n");
+ printk(KERN_ERR "[amlogic] ##### cec node init interrupted! #####\n");
+ return;
+ }
+ else
+ hdmitx_device->cec_init_ready = 0;
+ spin_lock_irqsave(&cec_rx_struct.lock, spin_flags);
+
+ amlogic_cec_log_dbg("start reset\n");
+#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6
+ aml_write_reg32(P_HDMI_CTRL_PORT, aml_read_reg32(P_HDMI_CTRL_PORT)|(1<<16));
+ hdmi_wr_reg(OTHER_BASE_ADDR+HDMI_OTHER_CTRL0, 0xc); //[3]cec_creg_sw_rst [2]cec_sys_sw_rst
+
+#if 0
+ hdmi_wr_reg(CEC0_BASE_ADDR+CEC_TX_CLEAR_BUF, 0x1);
+ hdmi_wr_reg(CEC0_BASE_ADDR+CEC_RX_CLEAR_BUF, 0x1);
+
+ hdmi_wr_reg(CEC0_BASE_ADDR+CEC_TX_CLEAR_BUF, 0x0);
+ hdmi_wr_reg(CEC0_BASE_ADDR+CEC_RX_CLEAR_BUF, 0x0);
+#endif
+
+ hdmi_wr_reg(OTHER_BASE_ADDR+HDMI_OTHER_CTRL0, 0x0);
+ aml_write_reg32(P_HDMI_CTRL_PORT, aml_read_reg32(P_HDMI_CTRL_PORT)&(~(1<<16)));
+ hdmi_wr_reg(CEC0_BASE_ADDR+CEC_CLOCK_DIV_H, 0x00 );
+ hdmi_wr_reg(CEC0_BASE_ADDR+CEC_CLOCK_DIV_L, 0xf0 );
+
+#endif
+#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8
+ // regain rx interrupts
+ cec_enable_irq();
+#endif
+ spin_unlock_irqrestore(&cec_rx_struct.lock, spin_flags);
+
+ hdmitx_device->cec_init_ready = 1;
+
+ up(&init_mutex);
+ amlogic_cec_log_dbg("stop reset\n");
+ }
+
+ if ((aml_read_reg32(P_AO_DEBUG_REG1) & 0xffff) != cec_phy_addr)
+ {
+ aml_write_reg32(P_AO_DEBUG_REG1, (aml_read_reg32(P_AO_DEBUG_REG1) & (0xf << 16)) | cec_phy_addr);
+ amlogic_cec_log_dbg("physical address:0x%x\n", aml_read_reg32(P_AO_DEBUG_REG1) & 0xffff);
+
+ if ((hdmitx_device->cec_init_ready != 0) && (hdmitx_device->hpd_state != 0))
+ {
+ // let the libCEC ask for new physical Address
+ entry->buffer[0] = 0xff;
+ entry->size = 1;
+ INIT_LIST_HEAD(&entry->list);
+ if ((entry = kmalloc(sizeof(struct cec_rx_list), GFP_ATOMIC)) == NULL)
+ {
+ amlogic_cec_log_dbg("can't alloc cec_rx_list\n");
+ }
+ else
+ {
+ // let the libCEC ask for new physical Address
+ entry->buffer[0] = 0xff;
+ entry->size = 1;
+ INIT_LIST_HEAD(&entry->list);
+
+ spin_lock_irqsave(&cec_rx_struct.lock, spin_flags);
+ list_add_tail(&entry->list, &cec_rx_struct.list);
+ amlogic_cec_set_rx_state(STATE_DONE);
+ spin_unlock_irqrestore(&cec_rx_struct.lock, spin_flags);
+ spin_lock_irqsave(&cec_rx_struct.lock, spin_flags);
+ list_add_tail(&entry->list, &cec_rx_struct.list);
+ amlogic_cec_set_rx_state(STATE_DONE);
+ spin_unlock_irqrestore(&cec_rx_struct.lock, spin_flags);
+
+ amlogic_cec_log_dbg("trigger libCEC\n");
+ wake_up_interruptible(&cec_rx_struct.waitq);
+ amlogic_cec_log_dbg("trigger libCEC\n");
+ wake_up_interruptible(&cec_rx_struct.waitq);
+ }
+ }
+ }
+ }
+ }
+ amlogic_cec_log_dbg("cec node init: cec features ok !\n");
+}
+
+static irqreturn_t amlogic_cec_irq_handler(int irq, void *dummy)
@ -338,7 +385,9 @@ index 0000000..bd31aaa
+ unsigned int tx_msg_state;
+ unsigned int rx_msg_state;
+
+#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6
+ udelay(100); //Delay execution a little. This fixes an issue when HDMI CEC stops working after a while.
+#endif
+
+ tx_msg_state = amlogic_cec_read_reg(CEC_TX_MSG_STATUS);
+ rx_msg_state = amlogic_cec_read_reg(CEC_RX_MSG_STATUS);
@ -356,9 +405,6 @@ index 0000000..bd31aaa
+ case TX_DONE :
+ amlogic_cec_set_tx_state(STATE_DONE);
+ break;
+ default :
+ amlogic_cec_log_dbg("unexpected ts message state: 0x%x", tx_msg_state);
+ break;
+ }
+ wake_up_interruptible(&cec_tx_struct.waitq);
+ }
@ -372,16 +418,18 @@ index 0000000..bd31aaa
+ return IRQ_HANDLED;
+ }
+
+ INIT_LIST_HEAD(&entry->list);
+
+ spin_lock_irqsave(&cec_rx_struct.lock, spin_flags);
+
+ if ((-1) == amlogic_cec_read_hw(entry->buffer, &entry->size))
+ {
+ kfree(entry);
+ amlogic_cec_log_dbg("amlogic_cec_irq_handler: nothing to read\n");
+ spin_unlock_irqrestore(&cec_rx_struct.lock, spin_flags);
+ return IRQ_HANDLED;
+ }
+
+ INIT_LIST_HEAD(&entry->list);
+
+ spin_lock_irqsave(&cec_rx_struct.lock, spin_flags);
+ list_add_tail(&entry->list, &cec_rx_struct.list);
+ amlogic_cec_set_rx_state(STATE_DONE);
+ spin_unlock_irqrestore(&cec_rx_struct.lock, spin_flags);
@ -432,21 +480,17 @@ index 0000000..bd31aaa
+ aml_write_reg32(P_SYS_CPU_0_IRQ_IN1_INTR_MASK, aml_read_reg32(P_SYS_CPU_0_IRQ_IN1_INTR_MASK) | (1 << 23)); // Enable the hdmi cec interrupt
+#endif
+#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8
+#if 1 // Please match with H/W cec config
+// GPIOAO_12
+ aml_set_reg32_bits(P_AO_RTI_PIN_MUX_REG, 0, 14, 1); // bit[14]: AO_PWM_C pinmux //0xc8100014
+ aml_set_reg32_bits(P_AO_RTI_PULL_UP_REG, 1, 12, 1); // bit[12]: enable AO_12 internal pull-up //0xc810002c
+ aml_set_reg32_bits(P_AO_RTI_PIN_MUX_REG, 1, 17, 1); // bit[17]: AO_CEC pinmux //0xc8100014
+ ao_cec_init();
+#else
+// GPIOH_3
+ aml_set_reg32_bits(P_PAD_PULL_UP_EN_REG1, 0, 19, 1); // disable gpioh_3 internal pull-up
+ aml_set_reg32_bits(P_PERIPHS_PIN_MUX_1, 1, 23, 1); // gpioh_3 cec pinmux
+#endif
+ cec_arbit_bit_time_set(3, 0x118, 0);
+ cec_arbit_bit_time_set(5, 0x000, 0);
+ cec_arbit_bit_time_set(7, 0x2aa, 0);
+#endif
+ amlogic_cec_write_reg(CEC_LOGICAL_ADDR0, (0x1 << 4) | 0xf);
+
+ hdmitx_device->cec_init_ready = 1;
+
+ }
@ -463,6 +507,8 @@ index 0000000..bd31aaa
+ free_irq(INT_AO_CEC, (void *)hdmitx_device);
+#endif
+
+ amlogic_cec_write_reg(CEC_LOGICAL_ADDR0, (0x1 << 4) | 0xf);
+
+ atomic_dec(&hdmi_on);
+
+ return 0;
@ -520,6 +566,7 @@ index 0000000..bd31aaa
+static ssize_t amlogic_cec_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ int retval = count;
+ char data[CEC_TX_BUFF_SIZE];
+
+ /* check data size */
@ -534,9 +581,8 @@ index 0000000..bd31aaa
+
+ amlogic_cec_set_tx_state(STATE_TX);
+
+ // just for the case that the first write starts
+ // before the end of amlogic_cec_delayed_init()
+ if (wait_event_interruptible(cec_tx_struct.waitq, hdmitx_device->cec_init_ready == 1))
+ // don't write if cec_node_init() is in progress
+ if (down_interruptible(&init_mutex))
+ {
+ amlogic_cec_log_dbg("error during wait on state change\n");
+ printk(KERN_ERR "[amlogic] ##### cec write error! #####\n");
@ -552,22 +598,27 @@ index 0000000..bd31aaa
+ printk(KERN_ERR "[amlogic] ##### cec write error! #####\n");
+ amlogic_cec_write_reg(CEC_TX_MSG_CMD, TX_ABORT); // stop cec tx for hw retry.
+ amlogic_cec_write_reg(CEC_TX_MSG_CMD, TX_NO_OP);
+ return -ERESTARTSYS;
+ retval = -ERESTARTSYS;
+ goto error_exit;
+ }
+
+ if (atomic_read(&cec_tx_struct.state) != STATE_DONE)
+ {
+ printk(KERN_ERR "[amlogic] ##### cec write error! #####\n");
+ return -1;
+ retval = -1;
+ }
+
+ return count;
+error_exit:
+ up(&init_mutex);
+
+ return retval;
+}
+
+static long amlogic_cec_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ unsigned char logical_addr;
+ unsigned int reg;
+
+ switch(cmd) {
+ case CEC_IOC_SETLADDR:
@ -578,12 +629,21 @@ index 0000000..bd31aaa
+ }
+
+ amlogic_cec_write_reg(CEC_LOGICAL_ADDR0, (0x1 << 4) | logical_addr);
+ cec_global_info.my_node_index = logical_addr;
+ /*
+ * use DEBUG_REG1 bit 16 ~ 31 to save logic address.
+ * So uboot can use this logic address directly
+ */
+ reg = (aml_read_reg32(P_AO_DEBUG_REG1) & 0xffff);
+ reg |= ((unsigned int)logical_addr) << 16;
+ aml_write_reg32(P_AO_DEBUG_REG1, reg);
+
+ amlogic_cec_log_dbg("amlogic_cec_ioctl: Set logical address: %d\n", logical_addr);
+ return 0;
+
+ case CEC_IOC_GETPADDR:
+ amlogic_cec_log_dbg("amlogic_cec_ioctl: return physical address 0x%x\n", aml_read_reg32(P_AO_DEBUG_REG1));
+ return aml_read_reg32(P_AO_DEBUG_REG1);
+ amlogic_cec_log_dbg("amlogic_cec_ioctl: return physical address 0x%x\n", aml_read_reg32(P_AO_DEBUG_REG1) & 0xffff);
+ return aml_read_reg32(P_AO_DEBUG_REG1) & 0xffff;
+ }
+
+ return -EINVAL;
@ -618,13 +678,23 @@ index 0000000..bd31aaa
+
+static int amlogic_cec_init(void)
+{
+ int retval = 0;
+ extern hdmitx_dev_t * get_hdmitx_device(void);
+
+ if (down_interruptible(&init_mutex))
+ {
+ return -ERESTARTSYS;
+ }
+
+ INIT_LIST_HEAD(&cec_rx_struct.list);
+
+ printk("%s, Version: %s\n", banner, VERSION);
+
+ hdmitx_device = get_hdmitx_device();
+ amlogic_cec_log_dbg("CEC init\n");
+
+ amlogic_cec_write_reg(CEC_LOGICAL_ADDR0, (0x1 << 4) | 0xf);
+
+#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6
+ hdmi_wr_reg(CEC0_BASE_ADDR+CEC_CLOCK_DIV_H, 0x00 );
+ hdmi_wr_reg(CEC0_BASE_ADDR+CEC_CLOCK_DIV_L, 0xf0 );
@ -641,10 +711,15 @@ index 0000000..bd31aaa
+ if (misc_register(&cec_misc_device))
+ {
+ printk(KERN_WARNING " Couldn't register device 10, %d.\n", CEC_MINOR);
+ return -EBUSY;
+ retval = -EBUSY;
+ }
+
+ return 0;
+ // release initial lock on init_mutex
+ up(&init_mutex);
+
+ amlogic_cec_log_dbg("CEC init finished: %d\n", retval);
+
+ return retval;
+}
+
+static void amlogic_cec_exit(void)

View File

@ -55,10 +55,10 @@ index 7a944cd..f74ec1f 100755
#EXTRA_CFLAGS += -O2
diff --git a/drivers/amlogic/hdmi/hdmi_tx/amlogic_cec.c b/drivers/amlogic/hdmi/hdmi_tx/amlogic_cec.c
new file mode 100644
index 0000000..bd31aaa
index 0000000..a3556b3
--- /dev/null
+++ b/drivers/amlogic/hdmi/hdmi_tx/amlogic_cec.c
@@ -0,0 +1,596 @@
@@ -0,0 +1,671 @@
+/* linux/drivers/amlogic/hdmi/hdmi_tx/amlogic_cec.c
+ *
+ * Copyright (c) 2016 Gerald Dachs
@ -84,6 +84,7 @@ index 0000000..bd31aaa
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/atomic.h>
+#include <linux/semaphore.h>
+
+#include <asm/uaccess.h>
+#include <asm/delay.h>
@ -127,6 +128,8 @@ index 0000000..bd31aaa
+/* CEC Tx buffer size */
+#define CEC_TX_BUFF_SIZE 16
+
+static DEFINE_SEMAPHORE(init_mutex);
+
+struct cec_rx_list {
+ u8 buffer[CEC_RX_BUFF_SIZE];
+ unsigned char size;
@ -226,7 +229,7 @@ index 0000000..bd31aaa
+ rx_msg_status = amlogic_cec_read_reg(CEC_RX_MSG_STATUS);
+ rx_num_msg = amlogic_cec_read_reg(CEC_RX_NUM_MSG);
+
+ amlogic_cec_log_dbg("amlogic_cec_read_hw: enter: CEC_RX_MSG_STATUS %d, CEC_RX_NUM_MSG %d\n", rx_msg_status, rx_num_msg);
+ amlogic_cec_log_dbg("rx_msg_status: %d, rx_num_msg: %d\n", rx_msg_status, rx_num_msg);
+
+ valid_msg = (RX_DONE == rx_msg_status) && (1 == rx_num_msg);
+
@ -248,7 +251,7 @@ index 0000000..bd31aaa
+#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8
+ aml_write_reg32(P_AO_CEC_INTR_CLR, aml_read_reg32(P_AO_CEC_INTR_CLR) | (1 << 2));
+#endif
+ amlogic_cec_write_reg(CEC_RX_MSG_CMD, RX_ACK_NEXT);
+ amlogic_cec_write_reg(CEC_RX_MSG_CMD, valid_msg ? RX_ACK_NEXT : RX_ACK_CURRENT);
+ amlogic_cec_write_reg(CEC_RX_MSG_CMD, RX_NO_OP);
+
+ return ret;
@ -290,45 +293,89 @@ index 0000000..bd31aaa
+ if (hdmitx_device->hdmi_info.vsdb_phy_addr.valid == 0)
+ {
+ amlogic_cec_log_dbg("no valid cec physical address\n");
+ if (aml_read_reg32(P_AO_DEBUG_REG1))
+ if (aml_read_reg32(P_AO_DEBUG_REG1) & 0xffff)
+ {
+ amlogic_cec_log_dbg("use last physical address\n");
+ }
+ else
+ {
+ aml_write_reg32(P_AO_DEBUG_REG1, 0x1000);
+ aml_write_reg32(P_AO_DEBUG_REG1, (aml_read_reg32(P_AO_DEBUG_REG1) & (0xf << 16)) | 0x1000);
+ amlogic_cec_log_dbg("use default physical address\n");
+ }
+ }
+ else
+ {
+ aml_write_reg32(P_AO_DEBUG_REG1, cec_phy_addr);
+ amlogic_cec_log_dbg("physical address:0x%x\n", aml_read_reg32(P_AO_DEBUG_REG1));
+
+ if ((hdmitx_device->cec_init_ready != 0) && (hdmitx_device->hpd_state != 0))
+ {
+ if ((entry = kmalloc(sizeof(struct cec_rx_list), GFP_ATOMIC)) == NULL)
+ if (cec_global_info.my_node_index)
+ {
+ // prevent write operations
+ if (down_interruptible(&init_mutex))
+ {
+ amlogic_cec_log_dbg("can't alloc cec_rx_list\n");
+ printk(KERN_ERR "[amlogic] ##### cec node init interrupted! #####\n");
+ return;
+ }
+ else
+ hdmitx_device->cec_init_ready = 0;
+ spin_lock_irqsave(&cec_rx_struct.lock, spin_flags);
+
+ amlogic_cec_log_dbg("start reset\n");
+#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6
+ aml_write_reg32(P_HDMI_CTRL_PORT, aml_read_reg32(P_HDMI_CTRL_PORT)|(1<<16));
+ hdmi_wr_reg(OTHER_BASE_ADDR+HDMI_OTHER_CTRL0, 0xc); //[3]cec_creg_sw_rst [2]cec_sys_sw_rst
+
+#if 0
+ hdmi_wr_reg(CEC0_BASE_ADDR+CEC_TX_CLEAR_BUF, 0x1);
+ hdmi_wr_reg(CEC0_BASE_ADDR+CEC_RX_CLEAR_BUF, 0x1);
+
+ hdmi_wr_reg(CEC0_BASE_ADDR+CEC_TX_CLEAR_BUF, 0x0);
+ hdmi_wr_reg(CEC0_BASE_ADDR+CEC_RX_CLEAR_BUF, 0x0);
+#endif
+
+ hdmi_wr_reg(OTHER_BASE_ADDR+HDMI_OTHER_CTRL0, 0x0);
+ aml_write_reg32(P_HDMI_CTRL_PORT, aml_read_reg32(P_HDMI_CTRL_PORT)&(~(1<<16)));
+ hdmi_wr_reg(CEC0_BASE_ADDR+CEC_CLOCK_DIV_H, 0x00 );
+ hdmi_wr_reg(CEC0_BASE_ADDR+CEC_CLOCK_DIV_L, 0xf0 );
+
+#endif
+#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8
+ // regain rx interrupts
+ cec_enable_irq();
+#endif
+ spin_unlock_irqrestore(&cec_rx_struct.lock, spin_flags);
+
+ hdmitx_device->cec_init_ready = 1;
+
+ up(&init_mutex);
+ amlogic_cec_log_dbg("stop reset\n");
+ }
+
+ if ((aml_read_reg32(P_AO_DEBUG_REG1) & 0xffff) != cec_phy_addr)
+ {
+ aml_write_reg32(P_AO_DEBUG_REG1, (aml_read_reg32(P_AO_DEBUG_REG1) & (0xf << 16)) | cec_phy_addr);
+ amlogic_cec_log_dbg("physical address:0x%x\n", aml_read_reg32(P_AO_DEBUG_REG1) & 0xffff);
+
+ if ((hdmitx_device->cec_init_ready != 0) && (hdmitx_device->hpd_state != 0))
+ {
+ // let the libCEC ask for new physical Address
+ entry->buffer[0] = 0xff;
+ entry->size = 1;
+ INIT_LIST_HEAD(&entry->list);
+ if ((entry = kmalloc(sizeof(struct cec_rx_list), GFP_ATOMIC)) == NULL)
+ {
+ amlogic_cec_log_dbg("can't alloc cec_rx_list\n");
+ }
+ else
+ {
+ // let the libCEC ask for new physical Address
+ entry->buffer[0] = 0xff;
+ entry->size = 1;
+ INIT_LIST_HEAD(&entry->list);
+
+ spin_lock_irqsave(&cec_rx_struct.lock, spin_flags);
+ list_add_tail(&entry->list, &cec_rx_struct.list);
+ amlogic_cec_set_rx_state(STATE_DONE);
+ spin_unlock_irqrestore(&cec_rx_struct.lock, spin_flags);
+ spin_lock_irqsave(&cec_rx_struct.lock, spin_flags);
+ list_add_tail(&entry->list, &cec_rx_struct.list);
+ amlogic_cec_set_rx_state(STATE_DONE);
+ spin_unlock_irqrestore(&cec_rx_struct.lock, spin_flags);
+
+ amlogic_cec_log_dbg("trigger libCEC\n");
+ wake_up_interruptible(&cec_rx_struct.waitq);
+ amlogic_cec_log_dbg("trigger libCEC\n");
+ wake_up_interruptible(&cec_rx_struct.waitq);
+ }
+ }
+ }
+ }
+ }
+ amlogic_cec_log_dbg("cec node init: cec features ok !\n");
+}
+
+static irqreturn_t amlogic_cec_irq_handler(int irq, void *dummy)
@ -338,7 +385,9 @@ index 0000000..bd31aaa
+ unsigned int tx_msg_state;
+ unsigned int rx_msg_state;
+
+#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6
+ udelay(100); //Delay execution a little. This fixes an issue when HDMI CEC stops working after a while.
+#endif
+
+ tx_msg_state = amlogic_cec_read_reg(CEC_TX_MSG_STATUS);
+ rx_msg_state = amlogic_cec_read_reg(CEC_RX_MSG_STATUS);
@ -356,9 +405,6 @@ index 0000000..bd31aaa
+ case TX_DONE :
+ amlogic_cec_set_tx_state(STATE_DONE);
+ break;
+ default :
+ amlogic_cec_log_dbg("unexpected ts message state: 0x%x", tx_msg_state);
+ break;
+ }
+ wake_up_interruptible(&cec_tx_struct.waitq);
+ }
@ -372,16 +418,18 @@ index 0000000..bd31aaa
+ return IRQ_HANDLED;
+ }
+
+ INIT_LIST_HEAD(&entry->list);
+
+ spin_lock_irqsave(&cec_rx_struct.lock, spin_flags);
+
+ if ((-1) == amlogic_cec_read_hw(entry->buffer, &entry->size))
+ {
+ kfree(entry);
+ amlogic_cec_log_dbg("amlogic_cec_irq_handler: nothing to read\n");
+ spin_unlock_irqrestore(&cec_rx_struct.lock, spin_flags);
+ return IRQ_HANDLED;
+ }
+
+ INIT_LIST_HEAD(&entry->list);
+
+ spin_lock_irqsave(&cec_rx_struct.lock, spin_flags);
+ list_add_tail(&entry->list, &cec_rx_struct.list);
+ amlogic_cec_set_rx_state(STATE_DONE);
+ spin_unlock_irqrestore(&cec_rx_struct.lock, spin_flags);
@ -432,21 +480,17 @@ index 0000000..bd31aaa
+ aml_write_reg32(P_SYS_CPU_0_IRQ_IN1_INTR_MASK, aml_read_reg32(P_SYS_CPU_0_IRQ_IN1_INTR_MASK) | (1 << 23)); // Enable the hdmi cec interrupt
+#endif
+#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8
+#if 1 // Please match with H/W cec config
+// GPIOAO_12
+ aml_set_reg32_bits(P_AO_RTI_PIN_MUX_REG, 0, 14, 1); // bit[14]: AO_PWM_C pinmux //0xc8100014
+ aml_set_reg32_bits(P_AO_RTI_PULL_UP_REG, 1, 12, 1); // bit[12]: enable AO_12 internal pull-up //0xc810002c
+ aml_set_reg32_bits(P_AO_RTI_PIN_MUX_REG, 1, 17, 1); // bit[17]: AO_CEC pinmux //0xc8100014
+ ao_cec_init();
+#else
+// GPIOH_3
+ aml_set_reg32_bits(P_PAD_PULL_UP_EN_REG1, 0, 19, 1); // disable gpioh_3 internal pull-up
+ aml_set_reg32_bits(P_PERIPHS_PIN_MUX_1, 1, 23, 1); // gpioh_3 cec pinmux
+#endif
+ cec_arbit_bit_time_set(3, 0x118, 0);
+ cec_arbit_bit_time_set(5, 0x000, 0);
+ cec_arbit_bit_time_set(7, 0x2aa, 0);
+#endif
+ amlogic_cec_write_reg(CEC_LOGICAL_ADDR0, (0x1 << 4) | 0xf);
+
+ hdmitx_device->cec_init_ready = 1;
+
+ }
@ -463,6 +507,8 @@ index 0000000..bd31aaa
+ free_irq(INT_AO_CEC, (void *)hdmitx_device);
+#endif
+
+ amlogic_cec_write_reg(CEC_LOGICAL_ADDR0, (0x1 << 4) | 0xf);
+
+ atomic_dec(&hdmi_on);
+
+ return 0;
@ -520,6 +566,7 @@ index 0000000..bd31aaa
+static ssize_t amlogic_cec_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ int retval = count;
+ char data[CEC_TX_BUFF_SIZE];
+
+ /* check data size */
@ -534,9 +581,8 @@ index 0000000..bd31aaa
+
+ amlogic_cec_set_tx_state(STATE_TX);
+
+ // just for the case that the first write starts
+ // before the end of amlogic_cec_delayed_init()
+ if (wait_event_interruptible(cec_tx_struct.waitq, hdmitx_device->cec_init_ready == 1))
+ // don't write if cec_node_init() is in progress
+ if (down_interruptible(&init_mutex))
+ {
+ amlogic_cec_log_dbg("error during wait on state change\n");
+ printk(KERN_ERR "[amlogic] ##### cec write error! #####\n");
@ -552,22 +598,27 @@ index 0000000..bd31aaa
+ printk(KERN_ERR "[amlogic] ##### cec write error! #####\n");
+ amlogic_cec_write_reg(CEC_TX_MSG_CMD, TX_ABORT); // stop cec tx for hw retry.
+ amlogic_cec_write_reg(CEC_TX_MSG_CMD, TX_NO_OP);
+ return -ERESTARTSYS;
+ retval = -ERESTARTSYS;
+ goto error_exit;
+ }
+
+ if (atomic_read(&cec_tx_struct.state) != STATE_DONE)
+ {
+ printk(KERN_ERR "[amlogic] ##### cec write error! #####\n");
+ return -1;
+ retval = -1;
+ }
+
+ return count;
+error_exit:
+ up(&init_mutex);
+
+ return retval;
+}
+
+static long amlogic_cec_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ unsigned char logical_addr;
+ unsigned int reg;
+
+ switch(cmd) {
+ case CEC_IOC_SETLADDR:
@ -578,12 +629,21 @@ index 0000000..bd31aaa
+ }
+
+ amlogic_cec_write_reg(CEC_LOGICAL_ADDR0, (0x1 << 4) | logical_addr);
+ cec_global_info.my_node_index = logical_addr;
+ /*
+ * use DEBUG_REG1 bit 16 ~ 31 to save logic address.
+ * So uboot can use this logic address directly
+ */
+ reg = (aml_read_reg32(P_AO_DEBUG_REG1) & 0xffff);
+ reg |= ((unsigned int)logical_addr) << 16;
+ aml_write_reg32(P_AO_DEBUG_REG1, reg);
+
+ amlogic_cec_log_dbg("amlogic_cec_ioctl: Set logical address: %d\n", logical_addr);
+ return 0;
+
+ case CEC_IOC_GETPADDR:
+ amlogic_cec_log_dbg("amlogic_cec_ioctl: return physical address 0x%x\n", aml_read_reg32(P_AO_DEBUG_REG1));
+ return aml_read_reg32(P_AO_DEBUG_REG1);
+ amlogic_cec_log_dbg("amlogic_cec_ioctl: return physical address 0x%x\n", aml_read_reg32(P_AO_DEBUG_REG1) & 0xffff);
+ return aml_read_reg32(P_AO_DEBUG_REG1) & 0xffff;
+ }
+
+ return -EINVAL;
@ -618,13 +678,23 @@ index 0000000..bd31aaa
+
+static int amlogic_cec_init(void)
+{
+ int retval = 0;
+ extern hdmitx_dev_t * get_hdmitx_device(void);
+
+ if (down_interruptible(&init_mutex))
+ {
+ return -ERESTARTSYS;
+ }
+
+ INIT_LIST_HEAD(&cec_rx_struct.list);
+
+ printk("%s, Version: %s\n", banner, VERSION);
+
+ hdmitx_device = get_hdmitx_device();
+ amlogic_cec_log_dbg("CEC init\n");
+
+ amlogic_cec_write_reg(CEC_LOGICAL_ADDR0, (0x1 << 4) | 0xf);
+
+#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6
+ hdmi_wr_reg(CEC0_BASE_ADDR+CEC_CLOCK_DIV_H, 0x00 );
+ hdmi_wr_reg(CEC0_BASE_ADDR+CEC_CLOCK_DIV_L, 0xf0 );
@ -641,10 +711,15 @@ index 0000000..bd31aaa
+ if (misc_register(&cec_misc_device))
+ {
+ printk(KERN_WARNING " Couldn't register device 10, %d.\n", CEC_MINOR);
+ return -EBUSY;
+ retval = -EBUSY;
+ }
+
+ return 0;
+ // release initial lock on init_mutex
+ up(&init_mutex);
+
+ amlogic_cec_log_dbg("CEC init finished: %d\n", retval);
+
+ return retval;
+}
+
+static void amlogic_cec_exit(void)