https://github.com/WOA-Project/Lumia950XLPkg/tree/master/Driver/SynapticsTouchDxe
--- /dev/null
+#include <Uefi.h>
+
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+
+#include <Protocol/AbsolutePointer.h>
+#include <Protocol/QcomTlmm.h>
+#include <Protocol/QcomI2c.h>
+
+#include "SynapticsRmi4.h"
+
+//
+// EFI Component Name Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL
+ gRmi4DriverComponentName = {Rmi4DriverComponentNameGetDriverName,
+ Rmi4DriverComponentNameGetControllerName,
+ "eng"};
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL
+ gRmi4DriverComponentName2 = {(EFI_COMPONENT_NAME2_GET_DRIVER_NAME)
+ Rmi4DriverComponentNameGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)
+ Rmi4DriverComponentNameGetControllerName,
+ "en"};
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mRmi4DriverNameTable[] =
+ {{"eng;en", L"Synaptics RMI4 Absolute Pointer Driver"}, {NULL, NULL}};
+
+EFI_STATUS
+EFIAPI
+Rmi4DriverComponentNameGetDriverName(
+ IN EFI_COMPONENT_NAME_PROTOCOL *This, IN CHAR8 *Language,
+ OUT CHAR16 **DriverName)
+{
+ return LookupUnicodeString2(
+ Language, This->SupportedLanguages, mRmi4DriverNameTable, DriverName,
+ (BOOLEAN)(This == &gRmi4DriverComponentName));
+}
+
+EFI_STATUS
+EFIAPI
+Rmi4DriverComponentNameGetControllerName(
+ IN EFI_COMPONENT_NAME_PROTOCOL *This, IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL, IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName)
+{
+ EFI_STATUS Status;
+ RMI4_INTERNAL_DATA * Instance;
+ EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointerProtocol;
+
+ //
+ // This is a device driver, so ChildHandle must be NULL.
+ //
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Get the device context
+ //
+ Status = gBS->OpenProtocol(
+ ControllerHandle, &gEfiAbsolutePointerProtocolGuid,
+ (VOID **)&AbsolutePointerProtocol, gRmi4DriverBinding.DriverBindingHandle,
+ ControllerHandle, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ Instance = RMI4_TCH_INSTANCE_FROM_ABSTCH_THIS(AbsolutePointerProtocol);
+
+ return LookupUnicodeString2(
+ Language, This->SupportedLanguages, Instance->ControllerNameTable,
+ ControllerName, (BOOLEAN)(This == &gRmi4DriverComponentName));
+}
--- /dev/null
+#include <Uefi.h>
+
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+
+#include <Protocol/AbsolutePointer.h>
+#include <Protocol/QcomTlmm.h>
+#include <Protocol/QcomI2c.h>
+
+#include "SynapticsRmi4.h"
+
+EFI_STATUS
+EFIAPI
+SynaI2cRead(
+ RMI4_INTERNAL_DATA *Instance, IN UINT8 Address, IN UINT8 *Data,
+ IN UINT16 ReadBytes)
+{
+ UINT32 Reads = 0;
+ I2C_STATUS I2CStatus = I2C_SUCCESS;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ if (Instance == NULL || Instance->Rmi4Device == NULL ||
+ Instance->I2cController == NULL ||
+ Instance->Rmi4Device->I2cQupProtocol == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ if (Data == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ I2CStatus = Instance->Rmi4Device->I2cQupProtocol->Read(
+ Instance->I2cController,
+ &Instance->Rmi4Device->SlaveCfg,
+ Address,
+ sizeof(Address),
+ Data,
+ ReadBytes,
+ &Reads,
+ 0
+ );
+
+ if (I2C_ERROR (I2CStatus)) {
+ DEBUG((EFI_D_ERROR, "SynapticsTouchDxe: I2C Read Failed: %d\n", I2CStatus));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+exit:
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+SynaI2cWrite(
+ RMI4_INTERNAL_DATA *Instance, IN UINT8 Address, IN UINT8 *Data,
+ IN UINT16 WriteBytes)
+{
+ UINT32 Writes = 0;
+ I2C_STATUS I2CStatus = I2C_SUCCESS;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ if (Instance == NULL || Instance->Rmi4Device == NULL ||
+ Instance->I2cController == NULL ||
+ Instance->Rmi4Device->I2cQupProtocol == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ if (Data == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ I2CStatus = Instance->Rmi4Device->I2cQupProtocol->Write(
+ Instance->I2cController,
+ &Instance->Rmi4Device->SlaveCfg,
+ Address,
+ sizeof(Address),
+ Data,
+ WriteBytes,
+ &Writes,
+ 0
+ );
+
+ if (I2C_ERROR (I2CStatus)) {
+ DEBUG((EFI_D_ERROR, "SynapticsTouchDxe: I2C Read Failed: %d\n", I2CStatus));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+exit:
+ return Status;
+}
--- /dev/null
+#ifndef _SYNAPTICS_RMI4_H_\r
+#define _SYNAPTICS_RMI4_H_\r
+\r
+#define TOUCH_RMI_PAGE_INFO_BYTES 6\r
+#define TOUCH_RMI_PAGE_INFO_ADDRESS 0xE9\r
+#define TOUCH_RMI_MAX_FUNCTIONS 10\r
+#define TOUCH_RMI_F12_FUNCTION 0x12\r
+\r
+#define TOUCH_DELAY_TO_COMMUNICATE 200000\r
+#define TOUCH_POWER_RAIL_STABLE_TIME 2000\r
+\r
+#define RMI_CHANGE_PAGE_ADDRESS 0xFF\r
+\r
+#define TIMER_INTERVAL_TOUCH_POLL 100000\r
+#define TOUCH_BUFFER_SIZE 25\r
+#define TOUCH_DATA_BYTES 8\r
+\r
+#define FAILURE_THRESHOLD 25\r
+\r
+typedef struct _TOUCH_DATA {\r
+ UINT16 TouchX;\r
+ UINT16 TouchY;\r
+ UINT8 TouchStatus;\r
+} TOUCH_DATA, *PTOUCH_DATA;\r
+\r
+// RMI4 device\r
+\r
+extern EFI_GUID gSynapticsTouchDeviceProtocolGuid;\r
+\r
+typedef struct _SYNAPTICS_I2C_DEVICE {\r
+ UINT32 Signature;\r
+ UINT32 XMax;\r
+ UINT32 YMax;\r
+ UINT32 XMin;\r
+ UINT32 YMin;\r
+ BOOLEAN XInverted;\r
+ BOOLEAN YInverted;\r
+ UINT32 ControllerResetPin;\r
+ UINT32 ControllerInterruptPin;\r
+ UINT32 ControllerI2cDevice;\r
+ EFI_QCOM_TLMM_PROTOCOL *GpioTlmmProtocol;\r
+ EFI_QCOM_I2C_PROTOCOL *I2cQupProtocol;\r
+ I2C_SLAVE_CONFIG SlaveCfg;\r
+} SYNAPTICS_I2C_DEVICE;\r
+\r
+#define RMI4_DEV_INSTANCE_SIGNATURE SIGNATURE_32('r', 'm', '4', 'd')\r
+\r
+// RMI4 driver internals\r
+\r
+typedef struct _RMI4_INTERNAL_DATA {\r
+ UINT32 Signature;\r
+ UINT16 LastX;\r
+ UINT16 LastY;\r
+ EFI_ABSOLUTE_POINTER_PROTOCOL AbsPointerProtocol;\r
+ EFI_ABSOLUTE_POINTER_MODE AbsPointerMode;\r
+ EFI_EVENT PollingTimerEvent;\r
+ BOOLEAN Initialized;\r
+ UINT8 PageF12;\r
+ UINT32 TouchDataAddress;\r
+ UINT32 FailureCount;\r
+ VOID *I2cController;\r
+ BOOLEAN StateChanged;\r
+ SYNAPTICS_I2C_DEVICE *Rmi4Device;\r
+ EFI_UNICODE_STRING_TABLE *ControllerNameTable;\r
+} RMI4_INTERNAL_DATA;\r
+\r
+#define RMI4_TCH_INSTANCE_SIGNATURE SIGNATURE_32('r', 'm', 'i', '4')\r
+#define RMI4_TCH_INSTANCE_FROM_ABSTCH_THIS(a) \\r
+ CR(a, RMI4_INTERNAL_DATA, AbsPointerProtocol, RMI4_TCH_INSTANCE_SIGNATURE)\r
+\r
+// Below is the driver binding section\r
+\r
+extern EFI_DRIVER_BINDING_PROTOCOL gRmi4DriverBinding;\r
+extern EFI_COMPONENT_NAME_PROTOCOL gRmi4DriverComponentName;\r
+extern EFI_COMPONENT_NAME2_PROTOCOL gRmi4DriverComponentName2;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+Rmi4AbsolutePointerDriverBindingSupported(\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+Rmi4AbsolutePointerDriverBindingStart(\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+Rmi4AbsolutePointerDriverBindingStop(\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller,\r
+ IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+Rmi4DriverComponentNameGetDriverName(\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This, IN CHAR8 *Language,\r
+ OUT CHAR16 **DriverName);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+Rmi4DriverComponentNameGetControllerName(\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This, IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_HANDLE ChildHandle OPTIONAL, IN CHAR8 *Language,\r
+ OUT CHAR16 **ControllerName);\r
+\r
+// Below is RMI4 driver code\r
+EFI_STATUS\r
+EFIAPI\r
+SynaI2cRead(\r
+ RMI4_INTERNAL_DATA *Instance, IN UINT8 Address, IN UINT8 *Data,\r
+ IN UINT16 ReadBytes);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+SynaI2cWrite(\r
+ RMI4_INTERNAL_DATA *Instance, IN UINT8 Address, IN UINT8 *Data,\r
+ IN UINT16 WriteBytes);\r
+\r
+EFI_STATUS AbsPReset(\r
+ IN EFI_ABSOLUTE_POINTER_PROTOCOL *This, IN BOOLEAN ExtendedVerification);\r
+\r
+EFI_STATUS AbsPGetState(\r
+ IN EFI_ABSOLUTE_POINTER_PROTOCOL *This,\r
+ IN OUT EFI_ABSOLUTE_POINTER_STATE *State);\r
+\r
+EFI_STATUS AbsStartPolling(IN RMI4_INTERNAL_DATA *Instance);\r
+\r
+VOID EFIAPI AbsPWaitForInput(IN EFI_EVENT Event, IN VOID *Context);\r
+\r
+VOID EFIAPI SyncPollCallback(IN EFI_EVENT Event, IN VOID *Context);\r
+\r
+EFI_STATUS EFIAPI SynaPowerUpController(RMI4_INTERNAL_DATA *Instance);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+SyncGetTouchData(RMI4_INTERNAL_DATA *Instance, IN PTOUCH_DATA DataBuffer);\r
+\r
+VOID EFIAPI SyncPollCallback(IN EFI_EVENT Event, IN VOID *Context);\r
+\r
+#endif
\ No newline at end of file
--- /dev/null
+#include <Uefi.h>
+
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+
+#include <Protocol/AbsolutePointer.h>
+#include <Protocol/QcomTlmm.h>
+#include <Protocol/QcomI2c.h>
+
+#include "SynapticsRmi4.h"
+#include <Device/TouchDevicePath.h>
+
+SYNAPTICS_I2C_DEVICE mTemplate = {
+ .Signature = RMI4_DEV_INSTANCE_SIGNATURE,
+ .XMax = 0,
+ .YMax = 0,
+ .XMin = 0,
+ .YMin = 0,
+ .XInverted = FALSE,
+ .YInverted = FALSE,
+ .ControllerResetPin = 0,
+ .ControllerInterruptPin = 0,
+ .ControllerI2cDevice = 0,
+ .GpioTlmmProtocol = 0,
+ .GpioTlmmProtocol = NULL,
+ .I2cQupProtocol = NULL,
+ .SlaveCfg = {
+ .BusFrequency = I2C_FAST_MODE_FREQ_KHZ,
+ .SlaveAddress = 0,
+ .Mode = I2C,
+ .SlaveMaxClockStretch = 500,
+ .CoreConfiguration1 = 0,
+ .CoreConfiguration2 = 0,
+ },
+};
+
+EFI_STATUS EFIAPI SynaDeviceInitialize(
+ IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
+{
+ SYNAPTICS_I2C_DEVICE *Instance;
+ EFI_STATUS Status;
+
+ // Device instance
+ Instance = AllocateCopyPool(sizeof(SYNAPTICS_I2C_DEVICE), &mTemplate);
+ if (Instance == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto exit;
+ }
+
+ // Config
+ Instance->SlaveCfg.SlaveAddress = PcdGet16(PcdTouchCtlrAddress);
+ Instance->ControllerI2cDevice = PcdGet32(PcdTouchCtlrI2cDevice);
+ Instance->ControllerResetPin = PcdGet32(PcdTouchCtlrResetPin);
+ Instance->ControllerInterruptPin = PcdGet32(PcdTouchCtlrIntPin);
+ Instance->XMax = PcdGet32(PcdTouchMaxX);
+ Instance->XMin = PcdGet32(PcdTouchMinX);
+ Instance->XInverted = PcdGetBool(PcdTouchInvertedX);
+ Instance->YMax = PcdGet32(PcdTouchMaxY);
+ Instance->YMin = PcdGet32(PcdTouchMinY);
+ Instance->YInverted = PcdGetBool(PcdTouchInvertedY);
+ DEBUG((EFI_D_INFO,
+ "SynapticsTouchDevice: "
+ "Address: 0x%X Device: %d "
+ "ResetPin: %d IntPin: %d "
+ "X: %d - %d (Inverted: %d) "
+ "Y: %d - %d (Inverted: %d)\n",
+ Instance->SlaveCfg.SlaveAddress, Instance->ControllerI2cDevice,
+ Instance->ControllerResetPin, Instance->ControllerInterruptPin,
+ Instance->XMin, Instance->XMax, Instance->XInverted,
+ Instance->YMax, Instance->YMax, Instance->YInverted
+ ));
+
+ // I2C Protocol
+ Status = gBS->LocateProtocol(
+ &gQcomI2cProtocolGuid, NULL, (VOID *)&Instance->I2cQupProtocol);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "SynapticsTouchDevice: Unable to locate I2C protocol: %r\n", Status));
+ goto exit;
+ }
+
+ // GPIO Processing
+ Status = gBS->LocateProtocol(
+ &gQcomTlmmProtocolGuid, NULL, (VOID *)&Instance->GpioTlmmProtocol);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "SynapticsTouchDevice: Unable to locate GPIO protocol: %r\n", Status));
+ goto exit;
+ }
+
+ // Looks good and publish the protocol
+ Status = gBS->InstallMultipleProtocolInterfaces(
+ &ImageHandle, &gSynapticsTouchDeviceProtocolGuid, Instance,
+ &gEfiDevicePathProtocolGuid, &TouchDxeDevicePath, NULL);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "SynapticsTouchDevice: Unable to install protocol: %r\n", Status));
+ }
+
+exit:
+ return Status;
+}
--- /dev/null
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SynapticsTouchDeviceDxe
+ FILE_GUID = f0d87c5e-4d5d-4fb5-939f-a6768ae8a310
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = SynaDeviceInitialize
+
+[Sources.common]
+ SynapticsTouchDevice.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ArmPkg/ArmPkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ sdm845Pkg/sdm845Pkg.dec
+
+[BuildOptions.AARCH64]
+ GCC:*_*_*_CC_FLAGS = -Werror -Wno-error=unused-variable
+
+[LibraryClasses]
+ ArmLib
+ UefiDriverEntryPoint
+ IoLib
+ TimerLib
+ BaseLib
+ DebugLib
+ PrintLib
+ CompilerIntrinsicsLib
+ CacheMaintenanceLib
+ UefiLib
+
+[Pcd]
+ gsdm845PkgTokenSpaceGuid.PcdMipiFrameBufferWidth
+ gsdm845PkgTokenSpaceGuid.PcdMipiFrameBufferHeight
+ gsdm845PkgTokenSpaceGuid.PcdTouchCtlrAddress
+ gsdm845PkgTokenSpaceGuid.PcdTouchCtlrResetPin
+ gsdm845PkgTokenSpaceGuid.PcdTouchCtlrIntPin
+ gsdm845PkgTokenSpaceGuid.PcdTouchCtlrI2cDevice
+ gsdm845PkgTokenSpaceGuid.PcdTouchMinX
+ gsdm845PkgTokenSpaceGuid.PcdTouchMaxX
+ gsdm845PkgTokenSpaceGuid.PcdTouchInvertedX
+ gsdm845PkgTokenSpaceGuid.PcdTouchMinY
+ gsdm845PkgTokenSpaceGuid.PcdTouchMaxY
+ gsdm845PkgTokenSpaceGuid.PcdTouchInvertedY
+
+[Protocols]
+ gQcomI2cProtocolGuid
+ gQcomTlmmProtocolGuid
+ gHardwareInterruptProtocolGuid
+ gSynapticsTouchDeviceProtocolGuid
+ gEfiDevicePathProtocolGuid
+
+[Depex]
+ gQcomI2cProtocolGuid AND gQcomTlmmProtocolGuid
+
--- /dev/null
+#include <Uefi.h>\r
+\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/DebugLib.h>\r
+\r
+#include <Protocol/AbsolutePointer.h>\r
+#include <Protocol/QcomTlmm.h>\r
+#include <Protocol/QcomI2c.h>\r
+\r
+#include "SynapticsRmi4.h"\r
+\r
+// Instance Template\r
+RMI4_INTERNAL_DATA mInstanceTemplate = {\r
+ RMI4_TCH_INSTANCE_SIGNATURE,\r
+ 0,\r
+ 0,\r
+ {\r
+ AbsPReset,\r
+ AbsPGetState,\r
+ NULL,\r
+ NULL,\r
+ },\r
+ {\r
+ 0,\r
+ 0,\r
+ 0,\r
+ 0,\r
+ 0,\r
+ 0,\r
+ 0,\r
+ },\r
+ NULL,\r
+ FALSE,\r
+ 0,\r
+ 0,\r
+ 0,\r
+ NULL,\r
+ FALSE,\r
+ NULL,\r
+ NULL,\r
+};\r
+\r
+// Binding\r
+EFI_DRIVER_BINDING_PROTOCOL gRmi4DriverBinding = {\r
+ Rmi4AbsolutePointerDriverBindingSupported,\r
+ Rmi4AbsolutePointerDriverBindingStart,\r
+ Rmi4AbsolutePointerDriverBindingStop,\r
+ 0x1,\r
+ NULL,\r
+ NULL,\r
+};\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+Rmi4AbsolutePointerDriverBindingSupported(\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath)\r
+{\r
+ EFI_STATUS Status;\r
+ SYNAPTICS_I2C_DEVICE *Rmi4I2cDeviceIo;\r
+\r
+ Status = gBS->OpenProtocol(\r
+ Controller, &gSynapticsTouchDeviceProtocolGuid, (VOID **)&Rmi4I2cDeviceIo,\r
+ This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER);\r
+\r
+ if (EFI_ERROR(Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ gBS->CloseProtocol(\r
+ Controller, &gSynapticsTouchDeviceProtocolGuid, This->DriverBindingHandle,\r
+ Controller);\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+Rmi4AbsolutePointerDriverBindingStart(\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath)\r
+{\r
+ EFI_TPL OldTpl;\r
+ EFI_STATUS Status;\r
+ I2C_STATUS I2CStatus;\r
+ SYNAPTICS_I2C_DEVICE *Rmi4I2cDeviceIo;\r
+ RMI4_INTERNAL_DATA * Instance;\r
+\r
+ UINT8 InfoData[TOUCH_RMI_PAGE_INFO_BYTES] = {0};\r
+ UINT8 Address = TOUCH_RMI_PAGE_INFO_ADDRESS;\r
+\r
+ UINT8 Page = 0;\r
+ UINT8 Function = 0;\r
+\r
+ OldTpl = gBS->RaiseTPL(TPL_CALLBACK);\r
+ Status = gBS->OpenProtocol(\r
+ Controller, &gSynapticsTouchDeviceProtocolGuid, (VOID **)&Rmi4I2cDeviceIo,\r
+ This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER);\r
+ if (EFI_ERROR(Status)) {\r
+ goto exit;\r
+ }\r
+\r
+ Instance = AllocateCopyPool(sizeof(RMI4_INTERNAL_DATA), &mInstanceTemplate);\r
+ ASSERT(Instance != NULL);\r
+ ASSERT(Rmi4I2cDeviceIo != NULL);\r
+\r
+ Instance->Rmi4Device = Rmi4I2cDeviceIo;\r
+ Instance->AbsPointerMode.AbsoluteMaxX = Rmi4I2cDeviceIo->XMax - Rmi4I2cDeviceIo->XMin;\r
+ Instance->AbsPointerMode.AbsoluteMaxY = Rmi4I2cDeviceIo->YMax - Rmi4I2cDeviceIo->YMin;\r
+ Instance->AbsPointerProtocol.Mode = &Instance->AbsPointerMode;\r
+ I2CStatus = Rmi4I2cDeviceIo->I2cQupProtocol->Open(\r
+ Instance->Rmi4Device->ControllerI2cDevice,\r
+ &Instance->I2cController);\r
+\r
+ if (I2C_ERROR(I2CStatus)) {\r
+ DEBUG((EFI_D_ERROR,\r
+ "SynapticsTouchDxe: Failed to open I2C%d: %d \n",\r
+ Instance->Rmi4Device->ControllerI2cDevice,\r
+ I2CStatus));\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto exit;\r
+ }\r
+\r
+ Status = SynaPowerUpController(Instance);\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG((EFI_D_ERROR, "SynapticsTouchDxe: Failed to power on controller: %r\n", Status));\r
+ goto exit;\r
+ }\r
+\r
+ DEBUG((EFI_D_INFO, "SynapticsTouchDxe: Probe Synaptics RMI4 F12 Function \n"));\r
+\r
+ // Probe device to locate F12 function\r
+ do {\r
+ Status =\r
+ SynaI2cRead(Instance, Address, &InfoData[0], TOUCH_RMI_PAGE_INFO_BYTES);\r
+\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG((EFI_D_ERROR, "SynapticsTouchDxe: I2C Read failed: %r\n", Status));\r
+ goto exit;\r
+ }\r
+\r
+ if (InfoData[5] == TOUCH_RMI_F12_FUNCTION) {\r
+ DEBUG((EFI_D_INFO, "SynapticsTouchDxe: RMI4 F12 Function Found. \n"));\r
+ Instance->PageF12 = Page;\r
+ Instance->TouchDataAddress = InfoData[3];\r
+ break;\r
+ }\r
+\r
+ // Last page. Go out\r
+ if (InfoData[5] == 0 && Address == TOUCH_RMI_PAGE_INFO_ADDRESS) {\r
+ break;\r
+ }\r
+ // Switch page\r
+ else if (InfoData[5] == 0 && Address != TOUCH_RMI_PAGE_INFO_ADDRESS) {\r
+ DEBUG((EFI_D_INFO, "SynapticsTouchDxe: Switching to next Synaptics RMI4 Page........"));\r
+\r
+ Page++;\r
+ Address = TOUCH_RMI_PAGE_INFO_ADDRESS;\r
+\r
+ Status = SynaI2cWrite(Instance, RMI_CHANGE_PAGE_ADDRESS, &Page, 1);\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG((EFI_D_ERROR, "SynapticsTouchDxe: Unable to switch RMI4 page: %r\n", Status));\r
+ goto exit;\r
+ }\r
+ }\r
+ else {\r
+ Function++;\r
+ Address = Address - TOUCH_RMI_PAGE_INFO_BYTES;\r
+ }\r
+ } while ((Address > 0) && (Function < TOUCH_RMI_MAX_FUNCTIONS));\r
+\r
+ // Determine final result\r
+ if (Function >= TOUCH_RMI_MAX_FUNCTIONS) {\r
+ DEBUG((EFI_D_ERROR, "SynapticsTouchDxe: Invalid RMI4 function index \n"));\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto exit;\r
+ }\r
+\r
+ if (Address <= 0) {\r
+ DEBUG((EFI_D_ERROR, "SynapticsTouchDxe: Invalid RMI4 address \n"));\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto exit;\r
+ }\r
+\r
+ // Flag device as initialized\r
+ Instance->Initialized = TRUE;\r
+\r
+ // Set touch event\r
+ Status = gBS->CreateEvent(\r
+ EVT_NOTIFY_WAIT, TPL_NOTIFY, AbsPWaitForInput, Instance,\r
+ &Instance->AbsPointerProtocol.WaitForInput);\r
+ ASSERT_EFI_ERROR(Status);\r
+\r
+ // Start polling\r
+ Status = AbsStartPolling(Instance);\r
+ ASSERT_EFI_ERROR(Status);\r
+\r
+ // Install protocols\r
+ Status = gBS->InstallProtocolInterface(\r
+ &Controller, &gEfiAbsolutePointerProtocolGuid, EFI_NATIVE_INTERFACE,\r
+ &Instance->AbsPointerProtocol);\r
+\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG((EFI_D_ERROR, "SynapticsTouchDxe: Failed to install protocol interface: %r\n", Status));\r
+ }\r
+\r
+ // Name table\r
+ Instance->ControllerNameTable = NULL;\r
+ AddUnicodeString2(\r
+ "eng", gRmi4DriverComponentName.SupportedLanguages,\r
+ &Instance->ControllerNameTable, L"Synaptics RMI4 Absolute Pointer", TRUE);\r
+ AddUnicodeString2(\r
+ "en", gRmi4DriverComponentName.SupportedLanguages,\r
+ &Instance->ControllerNameTable, L"Synaptics RMI4 Absolute Pointer",\r
+ FALSE);\r
+\r
+exit:\r
+ gBS->RestoreTPL(OldTpl);\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+Rmi4AbsolutePointerDriverBindingStop(\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller,\r
+ IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer)\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointerProtocol;\r
+ RMI4_INTERNAL_DATA * Instance;\r
+\r
+ Status = gBS->OpenProtocol(\r
+ Controller, &gEfiAbsolutePointerProtocolGuid,\r
+ (VOID **)&AbsolutePointerProtocol, This->DriverBindingHandle, Controller,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);\r
+\r
+ if (EFI_ERROR(Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Instance = RMI4_TCH_INSTANCE_FROM_ABSTCH_THIS(AbsolutePointerProtocol);\r
+\r
+ Status = gBS->UninstallProtocolInterface(\r
+ Controller, &gEfiAbsolutePointerProtocolGuid,\r
+ &Instance->AbsPointerProtocol);\r
+ if (EFI_ERROR(Status)) {\r
+ return Status;\r
+ }\r
+\r
+ gBS->CloseEvent(Instance->PollingTimerEvent);\r
+ gBS->CloseEvent(Instance->AbsPointerProtocol.WaitForInput);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS AbsPReset(\r
+ IN EFI_ABSOLUTE_POINTER_PROTOCOL *This, IN BOOLEAN ExtendedVerification)\r
+{\r
+ RMI4_INTERNAL_DATA *Instance;\r
+\r
+ Instance = RMI4_TCH_INSTANCE_FROM_ABSTCH_THIS(This);\r
+ Instance->LastX = 0;\r
+ Instance->LastY = 0;\r
+ Instance->StateChanged = FALSE;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS AbsStartPolling(IN RMI4_INTERNAL_DATA *Instance)\r
+{\r
+ EFI_STATUS Status = EFI_SUCCESS;\r
+\r
+ // Set event routines\r
+ Status = gBS->CreateEvent(\r
+ EVT_NOTIFY_SIGNAL | EVT_TIMER, TPL_CALLBACK, SyncPollCallback, Instance,\r
+ &Instance->PollingTimerEvent);\r
+ ASSERT_EFI_ERROR(Status);\r
+\r
+ Status = gBS->SetTimer(Instance->PollingTimerEvent, TimerPeriodic, 200000);\r
+ ASSERT_EFI_ERROR(Status);\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS AbsPGetState(\r
+ IN EFI_ABSOLUTE_POINTER_PROTOCOL *This,\r
+ IN OUT EFI_ABSOLUTE_POINTER_STATE *State)\r
+{\r
+ EFI_STATUS Status = EFI_SUCCESS;\r
+ RMI4_INTERNAL_DATA *Instance;\r
+\r
+ if (This == NULL || State == NULL) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto exit;\r
+ }\r
+\r
+ Instance = RMI4_TCH_INSTANCE_FROM_ABSTCH_THIS(This);\r
+ if (!Instance->StateChanged) {\r
+ Status = EFI_NOT_READY;\r
+ goto exit;\r
+ }\r
+\r
+ State->CurrentX = Instance->LastX;\r
+ State->CurrentY = Instance->LastY;\r
+ State->CurrentZ = 0;\r
+ State->ActiveButtons = 1;\r
+ Instance->StateChanged = FALSE;\r
+\r
+exit:\r
+ return Status;\r
+}\r
+\r
+VOID EFIAPI AbsPWaitForInput(IN EFI_EVENT Event, IN VOID *Context)\r
+{\r
+ RMI4_INTERNAL_DATA *Instance = (RMI4_INTERNAL_DATA *)Context;\r
+ EFI_TPL OldTpl;\r
+\r
+ //\r
+ // Enter critical section\r
+ //\r
+ OldTpl = gBS->RaiseTPL(TPL_NOTIFY);\r
+\r
+ SyncPollCallback(NULL, Instance);\r
+\r
+ if (Instance->StateChanged) {\r
+ gBS->SignalEvent(Event);\r
+ }\r
+\r
+ //\r
+ // Leave critical section and return\r
+ //\r
+ gBS->RestoreTPL(OldTpl);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+SynaPowerUpController(RMI4_INTERNAL_DATA *Instance)\r
+{\r
+ UINT32 Config;\r
+ UINT32 ResetLine;\r
+ EFI_STATUS Status;\r
+\r
+ if (Instance == NULL || Instance->Rmi4Device == NULL ||\r
+ Instance->Rmi4Device->GpioTlmmProtocol == NULL) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto exit;\r
+ }\r
+\r
+ // Pin Sanity check\r
+ ResetLine = Instance->Rmi4Device->ControllerResetPin;\r
+ if (ResetLine <= 0) {\r
+ DEBUG((EFI_D_ERROR, "SynapticsTouchDxe: Invalid GPIO configuration \n"));\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto exit;\r
+ }\r
+\r
+ // Power Seq\r
+ Config = EFI_GPIO_CFG( ResetLine, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA );\r
+ Status = Instance->Rmi4Device->GpioTlmmProtocol->ConfigGpio(Config, TLMM_GPIO_ENABLE);\r
+\r
+ // Configure MSM GPIO RESET line to Low\r
+ Instance->Rmi4Device->GpioTlmmProtocol->GpioOut(Config, GPIO_LOW_VALUE);\r
+ gBS->Stall(TOUCH_POWER_RAIL_STABLE_TIME);\r
+\r
+ // configure MSM GPIO RESET line to High\r
+ Instance->Rmi4Device->GpioTlmmProtocol->GpioOut(Config, GPIO_HIGH_VALUE);\r
+ gBS->Stall(TOUCH_DELAY_TO_COMMUNICATE);\r
+\r
+ DEBUG((EFI_D_INFO, "SynapticsTouchDxe: Touch controller powered on \n"));\r
+ Status = EFI_SUCCESS;\r
+\r
+exit:\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+SyncGetTouchData(RMI4_INTERNAL_DATA *Instance, IN PTOUCH_DATA DataBuffer)\r
+{\r
+ EFI_STATUS Status = EFI_SUCCESS;\r
+ UINT8 TouchCoordinates[TOUCH_DATA_BYTES] = {0};\r
+\r
+ if (Instance == NULL || DataBuffer == NULL) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto exit;\r
+ }\r
+\r
+ if (!Instance->Initialized) {\r
+ Status = EFI_NOT_READY;\r
+ goto exit;\r
+ }\r
+\r
+ // Change RMI page to F12\r
+ Status =\r
+ SynaI2cWrite(Instance, RMI_CHANGE_PAGE_ADDRESS, &Instance->PageF12, 1);\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG((EFI_D_ERROR, "SynapticsTouchDxe: Failed to change RMI4 page address: %r\n", Status));\r
+ goto exit;\r
+ }\r
+\r
+ // Read a fingerprint\r
+ Status = SynaI2cRead(\r
+ Instance, Instance->TouchDataAddress, &TouchCoordinates[0],\r
+ TOUCH_DATA_BYTES);\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG((EFI_D_ERROR, "SynapticsTouchDxe: Failed to read RMI4 F12 page data: %r\n", Status));\r
+ goto exit;\r
+ }\r
+\r
+ DataBuffer->TouchStatus = TouchCoordinates[0];\r
+ DataBuffer->TouchX =\r
+ ((TouchCoordinates[1] & 0xFF) | ((TouchCoordinates[2] & 0xFF) << 8));\r
+ DataBuffer->TouchY =\r
+ ((TouchCoordinates[3] & 0xFF) | ((TouchCoordinates[4] & 0xFF) << 8));\r
+\r
+exit:\r
+ return Status;\r
+}\r
+\r
+VOID EFIAPI SyncPollCallback(IN EFI_EVENT Event, IN VOID *Context)\r
+{\r
+ EFI_STATUS Status;\r
+ RMI4_INTERNAL_DATA *Instance = (RMI4_INTERNAL_DATA *)Context;\r
+ TOUCH_DATA TouchPointerData;\r
+ //EFI_TPL OldTpl;\r
+\r
+ //\r
+ // Enter critical section\r
+ //\r
+ //OldTpl = gBS->RaiseTPL(TPL_NOTIFY);\r
+\r
+ Status = SyncGetTouchData(Instance, &TouchPointerData);\r
+\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG((EFI_D_ERROR, "SynapticsTouchDxe: Failed to get Synaptics RMI4 F12 Data: %r\n", Status));\r
+ }\r
+ else {\r
+ if (TouchPointerData.TouchStatus > 0) {\r
+ Instance->LastX = TouchPointerData.TouchX + Instance->Rmi4Device->XMin;\r
+ Instance->LastY = TouchPointerData.TouchY + Instance->Rmi4Device->YMin;\r
+ Instance->StateChanged = TRUE;\r
+ if (Instance->Rmi4Device->XInverted) {\r
+ Instance->LastX = Instance->AbsPointerMode.AbsoluteMaxX - Instance->LastX;\r
+ }\r
+ if (Instance->Rmi4Device->YInverted) {\r
+ Instance->LastY = Instance->AbsPointerMode.AbsoluteMaxY - Instance->LastY;\r
+ }\r
+\r
+ DEBUG(\r
+ (EFI_D_INFO, "SynapticsTouchDxe: Touch: X: %d, Y: %d \n", Instance->LastX,\r
+ Instance->LastY));\r
+ }\r
+ }\r
+\r
+ //\r
+ // Leave critical section and return\r
+ //\r
+ //gBS->RestoreTPL(OldTpl);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+SynaInitialize(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = EfiLibInstallDriverBindingComponentName2(\r
+ ImageHandle, SystemTable, &gRmi4DriverBinding, ImageHandle,\r
+ &gRmi4DriverComponentName, &gRmi4DriverComponentName2);\r
+ ASSERT_EFI_ERROR(Status);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = SynapticsTouchDxe\r
+ FILE_GUID = f0d87c5e-4d5d-4fb5-939f-a6768ae8a309\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+ ENTRY_POINT = SynaInitialize\r
+\r
+[Sources.common]\r
+ SynapticsTouchDxe.c\r
+ I2cOps.c\r
+ ComponentName.c\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ ArmPkg/ArmPkg.dec\r
+ EmbeddedPkg/EmbeddedPkg.dec\r
+ sdm845Pkg/sdm845Pkg.dec\r
+\r
+[BuildOptions.AARCH64]\r
+ GCC:*_*_*_CC_FLAGS = -Werror -Wno-error=unused-variable\r
+\r
+[LibraryClasses]\r
+ ArmLib\r
+ UefiDriverEntryPoint\r
+ IoLib\r
+ TimerLib\r
+ BaseLib\r
+ DebugLib\r
+ PrintLib\r
+ CompilerIntrinsicsLib\r
+ CacheMaintenanceLib\r
+ UefiLib\r
+\r
+[Protocols]\r
+ gQcomI2cProtocolGuid\r
+ gQcomTlmmProtocolGuid\r
+ gHardwareInterruptProtocolGuid\r
+ gEfiAbsolutePointerProtocolGuid\r
+ gSynapticsTouchDeviceProtocolGuid\r
+ gEfiDevicePathProtocolGuid\r
+\r
+[Depex]\r
+ gSynapticsTouchDeviceProtocolGuid\r
--- /dev/null
+#ifndef _TOUCH_DEVICE_PATH_H_\r
+#define _TOUCH_DEVICE_PATH_H_\r
+\r
+typedef struct {\r
+ VENDOR_DEVICE_PATH VendorDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL End;\r
+} EFI_TOUCH_DEVICE_PATH;\r
+\r
+#define TOUCH_DEVICE_GUID \\r
+ { \\r
+ 0x0A861D79, 0x6D25, 0x4170, \\r
+ { \\r
+ 0xB6, 0xC4, 0x48, 0x7A, 0xA3, 0x57, 0xCC, 0x79 \\r
+ } \\r
+ }\r
+\r
+EFI_TOUCH_DEVICE_PATH TouchDxeDevicePath = {\r
+ {\r
+ {\r
+ HARDWARE_DEVICE_PATH,\r
+ HW_VENDOR_DP,\r
+ {\r
+ sizeof(VENDOR_DEVICE_PATH),\r
+ 0,\r
+ },\r
+ },\r
+ TOUCH_DEVICE_GUID,\r
+ },\r
+ {\r
+ END_DEVICE_PATH_TYPE,\r
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
+ {\r
+ sizeof(EFI_DEVICE_PATH_PROTOCOL),\r
+ 0,\r
+ },\r
+ },\r
+};\r
+\r
+#endif\r
[Protocols]
gEFIDroidKeypadDeviceProtocolGuid = { 0xb27625b5, 0x0b6c, 0x4614, { 0xaa, 0x3c, 0x33, 0x13, 0xb5, 0x1d, 0x36, 0x46 } }
gEfiMemCardInfoProtocolGuid = { 0x85c1f7d2, 0xbce6, 0x4f31, { 0x8f, 0x4d, 0xd3, 0x7e, 0x03, 0xd0, 0x5e, 0xaa } }
+ gSynapticsTouchDeviceProtocolGuid = { 0xf6ba192f, 0x9ee4, 0x4e3b, { 0xb1, 0x7a, 0xda, 0x75, 0x40, 0x3f, 0xa5, 0xa7 } }
gQcomI2cProtocolGuid = { 0xb27ae8b1, 0x3e10, 0x4d07, { 0xab, 0x5c, 0xeb, 0x9a, 0x6d, 0xc6, 0xfa, 0x8f } }
gQcomTlmmProtocolGuid = { 0xad9aec18, 0x7bf0, 0x4809, { 0x9e, 0x96, 0x30, 0x12, 0x30, 0x9f, 0x3d, 0xf7 } }
gQcomTlmmRTProtocolGuid = { 0xcc3f4da6, 0xa51e, 0x4fb7, { 0x98, 0xd1, 0xa0, 0x6e, 0xb8, 0x5d, 0x8e, 0x1e } }
gsdm845PkgTokenSpaceGuid.PcdDeviceVendor|"Qualcomm"|VOID*|0x0000a301
gsdm845PkgTokenSpaceGuid.PcdDeviceProduct|"Snapdragon 845 Device"|VOID*|0x0000a302
gsdm845PkgTokenSpaceGuid.PcdDeviceCodeName|"sdm845"|VOID*|0x0000a303
+ # Touch Screen
+ gsdm845PkgTokenSpaceGuid.PcdTouchCtlrAddress|0|UINT16|0x0000a501
+ gsdm845PkgTokenSpaceGuid.PcdTouchCtlrResetPin|0|UINT32|0x0000a502
+ gsdm845PkgTokenSpaceGuid.PcdTouchCtlrIntPin|0|UINT32|0x0000a503
+ gsdm845PkgTokenSpaceGuid.PcdTouchCtlrI2cDevice|0|UINT32|0x0000a504
+ gsdm845PkgTokenSpaceGuid.PcdTouchMinX|0|UINT32|0x0000a505
+ gsdm845PkgTokenSpaceGuid.PcdTouchMaxX|0|UINT32|0x0000a506
+ gsdm845PkgTokenSpaceGuid.PcdTouchInvertedX|FALSE|BOOLEAN|0x0000a507
+ gsdm845PkgTokenSpaceGuid.PcdTouchMinY|0|UINT32|0x0000a508
+ gsdm845PkgTokenSpaceGuid.PcdTouchMaxY|0|UINT32|0x0000a509
+ gsdm845PkgTokenSpaceGuid.PcdTouchInvertedY|FALSE|BOOLEAN|0x0000a50a
sdm845Pkg/Binary/845/LinuxSimpleMassStorage/LinuxSimpleMassStorage.inf
+ sdm845Pkg/Drivers/SynapticsTouchDxe/SynapticsTouchDevice.inf
+ sdm845Pkg/Drivers/SynapticsTouchDxe/SynapticsTouchDxe.inf
+
[BuildOptions.common]
GCC:*_*_AARCH64_CC_FLAGS = -Wno-unused-variable