input: fingerprint: Drop unnecesary goodix fingerprint driver copies
Change-Id: Ifcea0dc445c6af46dc7ea1db14f029f6023fb3e9
This commit is contained in:
parent
605bca6d8b
commit
1d7c5b07d7
@ -18,7 +18,5 @@ menuconfig INPUT_FINGERPRINT
|
|||||||
if INPUT_FINGERPRINT
|
if INPUT_FINGERPRINT
|
||||||
|
|
||||||
source "drivers/input/fingerprint/fpc_1540/Kconfig"
|
source "drivers/input/fingerprint/fpc_1540/Kconfig"
|
||||||
source "drivers/input/fingerprint/goodix_3626/Kconfig"
|
|
||||||
source "drivers/input/fingerprint/goodix_fod/Kconfig"
|
|
||||||
source "drivers/input/fingerprint/goodix_tee/Kconfig"
|
source "drivers/input/fingerprint/goodix_tee/Kconfig"
|
||||||
endif
|
endif
|
||||||
|
@ -5,6 +5,4 @@
|
|||||||
# Each configuration option enables a list of files.
|
# Each configuration option enables a list of files.
|
||||||
|
|
||||||
obj-$(CONFIG_FINGERPRINT_FPC_1540) += fpc_1540/
|
obj-$(CONFIG_FINGERPRINT_FPC_1540) += fpc_1540/
|
||||||
obj-$(CONFIG_FINGERPRINT_GOODIX_3626) += goodix_3626/
|
|
||||||
obj-$(CONFIG_FINGERPRINT_GOODIX_FOD) += goodix_fod/
|
|
||||||
obj-$(CONFIG_FINGERPRINT_GOODIX_TEE) += goodix_tee/
|
obj-$(CONFIG_FINGERPRINT_GOODIX_TEE) += goodix_tee/
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
config FINGERPRINT_GOODIX_3626
|
|
||||||
tristate "Finger print card goodix"
|
|
||||||
depends on INPUT_FINGERPRINT
|
|
||||||
help
|
|
||||||
Say Y here to enable support for retrieving self-test reports.
|
|
||||||
|
|
||||||
If unsure, say N.
|
|
||||||
|
|
||||||
To compile this driver as a module, choose M here.
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
|||||||
ifneq ($(KERNELRELEASE),)
|
|
||||||
goodix_3626-objs := gf_spi.o platform.o netlink.o
|
|
||||||
obj-$(CONFIG_FINGERPRINT_GOODIX_3626) += goodix_3626.o
|
|
||||||
else
|
|
||||||
KDIR = $(OUT)/obj/KERNEL_OBJ
|
|
||||||
CROSS_COMPILE = $(ANDROID_TOOLCHAIN)/aarch64-linux-android-
|
|
||||||
CLANG = $(ANDROID_BUILD_TOP)/prebuilts/clang/host/linux-x86/clang-r370808
|
|
||||||
REAL_CC = $(CLANG)/bin/clang
|
|
||||||
AR = $(CLANG)/bin/llvm-ar
|
|
||||||
LLVM_NM = $(CLANG)/bin/llvm-nm
|
|
||||||
LD = $(CLANG)/bin/ld.lld
|
|
||||||
|
|
||||||
.PHONY: clean
|
|
||||||
|
|
||||||
default:
|
|
||||||
$(MAKE) ARCH=arm64 CROSS_COMPILE=$(CROSS_COMPILE) REAL_CC=$(REAL_CC) CLANG_TRIPLE=aarch64-linux-gnu- AR=$(AR) LLVM_NM=$(LLVM_NM) LD=$(LD) -C $(KDIR) M=$(PWD) modules
|
|
||||||
clean:
|
|
||||||
@rm -rf *.o* *.order *.symvers *.mod* .*.o.cmd .*.mod.o.cmd .*.ko.cmd .tmp_versions *.ko
|
|
||||||
|
|
||||||
endif
|
|
File diff suppressed because it is too large
Load Diff
@ -1,174 +0,0 @@
|
|||||||
/*
|
|
||||||
* driver definition for sensor driver
|
|
||||||
*
|
|
||||||
* Coypright (c) 2017 Goodix
|
|
||||||
*/
|
|
||||||
#ifndef __GF_SPI_H
|
|
||||||
#define __GF_SPI_H
|
|
||||||
|
|
||||||
#include <linux/types.h>
|
|
||||||
#include <linux/notifier.h>
|
|
||||||
/**********************************************************/
|
|
||||||
enum FP_MODE {
|
|
||||||
GF_IMAGE_MODE = 0,
|
|
||||||
GF_KEY_MODE,
|
|
||||||
GF_SLEEP_MODE,
|
|
||||||
GF_FF_MODE,
|
|
||||||
GF_DEBUG_MODE = 0x56
|
|
||||||
};
|
|
||||||
|
|
||||||
#define SUPPORT_NAV_EVENT
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
#if defined(SUPPORT_NAV_EVENT)
|
|
||||||
#define GF_NAV_INPUT_UP KEY_UP
|
|
||||||
#define GF_NAV_INPUT_DOWN KEY_DOWN
|
|
||||||
#define GF_NAV_INPUT_LEFT KEY_LEFT
|
|
||||||
#define GF_NAV_INPUT_RIGHT KEY_RIGHT
|
|
||||||
#define GF_NAV_INPUT_CLICK KEY_VOLUMEDOWN
|
|
||||||
#define GF_NAV_INPUT_DOUBLE_CLICK KEY_VOLUMEUP
|
|
||||||
#define GF_NAV_INPUT_LONG_PRESS KEY_SEARCH
|
|
||||||
#define GF_NAV_INPUT_HEAVY KEY_CHAT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define GF_KEY_INPUT_HOME KEY_SELECT
|
|
||||||
#define GF_KEY_DOUBLE_CLICK BTN_C
|
|
||||||
#define GF_KEY_INPUT_MENU KEY_MENU
|
|
||||||
#define GF_KEY_INPUT_BACK KEY_BACK
|
|
||||||
#define GF_KEY_INPUT_POWER KEY_POWER
|
|
||||||
#define GF_KEY_INPUT_CAMERA KEY_CAMERA
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
#if defined(SUPPORT_NAV_EVENT)
|
|
||||||
typedef enum gf_nav_event {
|
|
||||||
GF_NAV_NONE = 0,
|
|
||||||
GF_NAV_FINGER_UP,
|
|
||||||
GF_NAV_FINGER_DOWN,
|
|
||||||
GF_NAV_UP,
|
|
||||||
GF_NAV_DOWN,
|
|
||||||
GF_NAV_LEFT,
|
|
||||||
GF_NAV_RIGHT,
|
|
||||||
GF_NAV_CLICK,
|
|
||||||
GF_NAV_HEAVY,
|
|
||||||
GF_NAV_LONG_PRESS,
|
|
||||||
GF_NAV_DOUBLE_CLICK,
|
|
||||||
} gf_nav_event_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef enum gf_key_event {
|
|
||||||
GF_KEY_NONE = 0,
|
|
||||||
GF_KEY_HOME,
|
|
||||||
GF_KEY_POWER,
|
|
||||||
GF_KEY_MENU,
|
|
||||||
GF_KEY_BACK,
|
|
||||||
GF_KEY_CAMERA,
|
|
||||||
GF_KEY_HOME_DOUBLE_CLICK,
|
|
||||||
} gf_key_event_t;
|
|
||||||
|
|
||||||
struct gf_key {
|
|
||||||
enum gf_key_event key;
|
|
||||||
uint32_t value; /* key down = 1, key up = 0 */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct gf_key_map {
|
|
||||||
unsigned int type;
|
|
||||||
unsigned int code;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct gf_ioc_chip_info {
|
|
||||||
unsigned char vendor_id;
|
|
||||||
unsigned char mode;
|
|
||||||
unsigned char operation;
|
|
||||||
unsigned char reserved[5];
|
|
||||||
};
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
#define GF_IOC_MAGIC 'g' /* define magic number */
|
|
||||||
#define GF_IOC_INIT _IOR(GF_IOC_MAGIC, 0, uint8_t)
|
|
||||||
#define GF_IOC_EXIT _IO(GF_IOC_MAGIC, 1)
|
|
||||||
#define GF_IOC_RESET _IO(GF_IOC_MAGIC, 2)
|
|
||||||
#define GF_IOC_ENABLE_IRQ _IO(GF_IOC_MAGIC, 3)
|
|
||||||
#define GF_IOC_DISABLE_IRQ _IO(GF_IOC_MAGIC, 4)
|
|
||||||
#define GF_IOC_ENABLE_SPI_CLK _IOW(GF_IOC_MAGIC, 5, uint32_t)
|
|
||||||
#define GF_IOC_DISABLE_SPI_CLK _IO(GF_IOC_MAGIC, 6)
|
|
||||||
#define GF_IOC_ENABLE_POWER _IO(GF_IOC_MAGIC, 7)
|
|
||||||
#define GF_IOC_DISABLE_POWER _IO(GF_IOC_MAGIC, 8)
|
|
||||||
#define GF_IOC_INPUT_KEY_EVENT _IOW(GF_IOC_MAGIC, 9, struct gf_key)
|
|
||||||
#define GF_IOC_ENTER_SLEEP_MODE _IO(GF_IOC_MAGIC, 10)
|
|
||||||
#define GF_IOC_GET_FW_INFO _IOR(GF_IOC_MAGIC, 11, uint8_t)
|
|
||||||
#define GF_IOC_REMOVE _IO(GF_IOC_MAGIC, 12)
|
|
||||||
#define GF_IOC_CHIP_INFO _IOW(GF_IOC_MAGIC, 13, struct gf_ioc_chip_info)
|
|
||||||
|
|
||||||
#if defined(SUPPORT_NAV_EVENT)
|
|
||||||
#define GF_IOC_NAV_EVENT _IOW(GF_IOC_MAGIC, 14, gf_nav_event_t)
|
|
||||||
#define GF_IOC_MAXNR 15 /* THIS MACRO IS NOT USED NOW... */
|
|
||||||
#else
|
|
||||||
#define GF_IOC_MAXNR 14 /* THIS MACRO IS NOT USED NOW... */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*#define AP_CONTROL_CLK 1*/
|
|
||||||
#define USE_PLATFORM_BUS 1
|
|
||||||
//#define USE_SPI_BUS 1
|
|
||||||
//#define GF_FASYNC 1 /* If support fasync mechanism */
|
|
||||||
//#define CONFIG_FINGERPRINT_FP_VREG_CONTROL
|
|
||||||
//#ifndef CONFIG_FINGERPRINT_FP_VREG_CONTROL
|
|
||||||
//#define GF_PW_CTL 1
|
|
||||||
//#endif
|
|
||||||
#undef GF_PW_CTL
|
|
||||||
|
|
||||||
#define GF_NETLINK_ENABLE 1
|
|
||||||
#define GF_NET_EVENT_IRQ 1
|
|
||||||
#define GF_NET_EVENT_FB_BLACK 2
|
|
||||||
#define GF_NET_EVENT_FB_UNBLACK 3
|
|
||||||
#define NETLINK_TEST 25
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
struct gf_dev {
|
|
||||||
dev_t devt;
|
|
||||||
struct list_head device_entry;
|
|
||||||
#if defined(USE_SPI_BUS)
|
|
||||||
struct spi_device *spi;
|
|
||||||
#elif defined(USE_PLATFORM_BUS)
|
|
||||||
struct platform_device *spi;
|
|
||||||
#endif
|
|
||||||
struct clk *core_clk;
|
|
||||||
struct clk *iface_clk;
|
|
||||||
|
|
||||||
struct input_dev *input;
|
|
||||||
/* buffer is NULL unless this device is open (users > 0) */
|
|
||||||
unsigned users;
|
|
||||||
signed irq_gpio;
|
|
||||||
signed reset_gpio;
|
|
||||||
signed pwr_gpio;
|
|
||||||
int irq;
|
|
||||||
int irq_enabled;
|
|
||||||
int clk_enabled;
|
|
||||||
#ifdef GF_FASYNC
|
|
||||||
struct fasync_struct *async;
|
|
||||||
#endif
|
|
||||||
//struct notifier_block notifier;
|
|
||||||
struct workqueue_struct *screen_state_wq;
|
|
||||||
struct delayed_work screen_state_dw;
|
|
||||||
char device_available;
|
|
||||||
char fb_black;
|
|
||||||
char wait_finger_down;
|
|
||||||
struct work_struct work;
|
|
||||||
uint32_t key_flag; /*if not up, flag = 1*/
|
|
||||||
#ifdef CONFIG_FINGERPRINT_FP_VREG_CONTROL
|
|
||||||
struct regulator *vreg;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
int gf_parse_dts(struct gf_dev *gf_dev);
|
|
||||||
void gf_cleanup(struct gf_dev *gf_dev);
|
|
||||||
|
|
||||||
int gf_power_on(struct gf_dev *gf_dev);
|
|
||||||
int gf_power_off(struct gf_dev *gf_dev);
|
|
||||||
|
|
||||||
int gf_hw_reset(struct gf_dev *gf_dev, unsigned int delay_ms);
|
|
||||||
int gf_irq_num(struct gf_dev *gf_dev);
|
|
||||||
|
|
||||||
void sendnlmsg(char *message);
|
|
||||||
int netlink_init(void);
|
|
||||||
void netlink_exit(void);
|
|
||||||
#endif /*__GF_SPI_H*/
|
|
@ -1,96 +0,0 @@
|
|||||||
/*
|
|
||||||
* netlink interface
|
|
||||||
*
|
|
||||||
* Copyright (c) 2017 Goodix
|
|
||||||
*/
|
|
||||||
#include <linux/init.h>
|
|
||||||
#include <linux/module.h>
|
|
||||||
#include <linux/timer.h>
|
|
||||||
#include <linux/time.h>
|
|
||||||
#include <linux/types.h>
|
|
||||||
#include <net/sock.h>
|
|
||||||
#include <net/netlink.h>
|
|
||||||
|
|
||||||
#define NETLINK_TEST 25
|
|
||||||
#define MAX_MSGSIZE 32
|
|
||||||
int stringlength(char *s);
|
|
||||||
void sendnlmsg(char *message);
|
|
||||||
static int pid = -1;
|
|
||||||
struct sock *nl_sk;
|
|
||||||
|
|
||||||
void sendnlmsg(char *message)
|
|
||||||
{
|
|
||||||
struct sk_buff *skb_1;
|
|
||||||
struct nlmsghdr *nlh;
|
|
||||||
int len = NLMSG_SPACE(MAX_MSGSIZE);
|
|
||||||
int slen = 0;
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if (!message || !nl_sk || !pid) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
skb_1 = alloc_skb(len, GFP_KERNEL);
|
|
||||||
|
|
||||||
if (!skb_1) {
|
|
||||||
pr_err("alloc_skb error\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
slen = strlen(message);
|
|
||||||
nlh = nlmsg_put(skb_1, 0, 0, 0, MAX_MSGSIZE, 0);
|
|
||||||
NETLINK_CB(skb_1).portid = 0;
|
|
||||||
NETLINK_CB(skb_1).dst_group = 0;
|
|
||||||
message[slen] = '\0';
|
|
||||||
memcpy(NLMSG_DATA(nlh), message, slen + 1);
|
|
||||||
ret = netlink_unicast(nl_sk, skb_1, pid, MSG_DONTWAIT);
|
|
||||||
|
|
||||||
if (!ret) {
|
|
||||||
/*kfree_skb(skb_1);*/
|
|
||||||
pr_err("send msg from kernel to usespace failed ret 0x%x\n",
|
|
||||||
ret);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void nl_data_ready(struct sk_buff *__skb)
|
|
||||||
{
|
|
||||||
struct sk_buff *skb;
|
|
||||||
struct nlmsghdr *nlh;
|
|
||||||
char str[100];
|
|
||||||
skb = skb_get(__skb);
|
|
||||||
|
|
||||||
if (skb->len >= NLMSG_SPACE(0)) {
|
|
||||||
nlh = nlmsg_hdr(skb);
|
|
||||||
memcpy(str, NLMSG_DATA(nlh), sizeof(str));
|
|
||||||
pid = nlh->nlmsg_pid;
|
|
||||||
kfree_skb(skb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int netlink_init(void)
|
|
||||||
{
|
|
||||||
struct netlink_kernel_cfg netlink_cfg;
|
|
||||||
memset(&netlink_cfg, 0, sizeof(struct netlink_kernel_cfg));
|
|
||||||
netlink_cfg.groups = 0;
|
|
||||||
netlink_cfg.flags = 0;
|
|
||||||
netlink_cfg.input = nl_data_ready;
|
|
||||||
netlink_cfg.cb_mutex = NULL;
|
|
||||||
nl_sk = netlink_kernel_create(&init_net, NETLINK_TEST, &netlink_cfg);
|
|
||||||
|
|
||||||
if (!nl_sk) {
|
|
||||||
pr_err("create netlink socket error\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void netlink_exit(void)
|
|
||||||
{
|
|
||||||
if (nl_sk != NULL) {
|
|
||||||
netlink_kernel_release(nl_sk);
|
|
||||||
nl_sk = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
pr_info("self module exited\n");
|
|
||||||
}
|
|
@ -1,141 +0,0 @@
|
|||||||
/*
|
|
||||||
* platform indepent driver interface
|
|
||||||
*
|
|
||||||
* Coypritht (c) 2017 Goodix
|
|
||||||
*/
|
|
||||||
#define DEBUG
|
|
||||||
#define pr_fmt(fmt) "gf_platform: " fmt
|
|
||||||
|
|
||||||
#include <linux/delay.h>
|
|
||||||
#include <linux/workqueue.h>
|
|
||||||
#include <linux/of_gpio.h>
|
|
||||||
#include <linux/gpio.h>
|
|
||||||
#include <linux/regulator/consumer.h>
|
|
||||||
#include <linux/timer.h>
|
|
||||||
#include <linux/err.h>
|
|
||||||
|
|
||||||
#include "gf_spi.h"
|
|
||||||
|
|
||||||
#if defined(USE_SPI_BUS)
|
|
||||||
#include <linux/spi/spi.h>
|
|
||||||
#include <linux/spi/spidev.h>
|
|
||||||
#elif defined(USE_PLATFORM_BUS)
|
|
||||||
#include <linux/platform_device.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int gf_parse_dts(struct gf_dev *gf_dev)
|
|
||||||
{
|
|
||||||
#ifdef GF_PW_CTL
|
|
||||||
/*get pwr resource*/
|
|
||||||
gf_dev->pwr_gpio =
|
|
||||||
of_get_named_gpio(gf_dev->spi->dev.of_node, "fp-gpio-pwr", 0);
|
|
||||||
|
|
||||||
if (!gpio_is_valid(gf_dev->pwr_gpio)) {
|
|
||||||
pr_info("PWR GPIO is invalid.\n");
|
|
||||||
return -EPERM;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
/*get reset resource*/
|
|
||||||
gf_dev->reset_gpio = of_get_named_gpio(gf_dev->spi->dev.of_node,
|
|
||||||
"goodix,gpio-reset", 0);
|
|
||||||
|
|
||||||
if (!gpio_is_valid(gf_dev->reset_gpio)) {
|
|
||||||
pr_info("RESET GPIO is invalid.\n");
|
|
||||||
return -EPERM;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*get irq resourece*/
|
|
||||||
gf_dev->irq_gpio = of_get_named_gpio(gf_dev->spi->dev.of_node,
|
|
||||||
"goodix,gpio-irq", 0);
|
|
||||||
pr_info("gf::irq_gpio:%d\n", gf_dev->irq_gpio);
|
|
||||||
|
|
||||||
if (!gpio_is_valid(gf_dev->irq_gpio)) {
|
|
||||||
pr_info("IRQ GPIO is invalid.\n");
|
|
||||||
return -EPERM;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void gf_cleanup(struct gf_dev *gf_dev)
|
|
||||||
{
|
|
||||||
pr_info("[info] %s\n", __func__);
|
|
||||||
|
|
||||||
if (gpio_is_valid(gf_dev->irq_gpio)) {
|
|
||||||
gpio_free(gf_dev->irq_gpio);
|
|
||||||
pr_info("remove irq_gpio success\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gpio_is_valid(gf_dev->reset_gpio)) {
|
|
||||||
gpio_free(gf_dev->reset_gpio);
|
|
||||||
pr_info("remove reset_gpio success\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef GF_PW_CTL
|
|
||||||
|
|
||||||
if (gpio_is_valid(gf_dev->pwr_gpio)) {
|
|
||||||
gpio_free(gf_dev->pwr_gpio);
|
|
||||||
pr_info("remove pwr_gpio success\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int gf_power_on(struct gf_dev *gf_dev)
|
|
||||||
{
|
|
||||||
int rc = 0;
|
|
||||||
#ifdef GF_PW_CTL
|
|
||||||
|
|
||||||
if (gpio_is_valid(gf_dev->pwr_gpio)) {
|
|
||||||
rc = gpio_direction_output(gf_dev->pwr_gpio, 1);
|
|
||||||
pr_info("---- power on result: %d----\n", rc);
|
|
||||||
} else {
|
|
||||||
pr_info("%s: gpio_is_invalid\n", __func__);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
msleep(10);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
int gf_power_off(struct gf_dev *gf_dev)
|
|
||||||
{
|
|
||||||
int rc = 0;
|
|
||||||
#ifdef GF_PW_CTL
|
|
||||||
|
|
||||||
if (gpio_is_valid(gf_dev->pwr_gpio)) {
|
|
||||||
rc = gpio_direction_output(gf_dev->pwr_gpio, 0);
|
|
||||||
pr_info("---- power off result: %d----\n", rc);
|
|
||||||
} else {
|
|
||||||
pr_info("%s: gpio_is_invalid\n", __func__);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
int gf_hw_reset(struct gf_dev *gf_dev, unsigned int delay_ms)
|
|
||||||
{
|
|
||||||
if (gf_dev == NULL) {
|
|
||||||
pr_info("Input buff is NULL.\n");
|
|
||||||
return -EPERM;
|
|
||||||
}
|
|
||||||
|
|
||||||
gpio_direction_output(gf_dev->reset_gpio, 0);
|
|
||||||
mdelay(3);
|
|
||||||
gpio_set_value(gf_dev->reset_gpio, 1);
|
|
||||||
mdelay(delay_ms);
|
|
||||||
pr_info("%s\n", __func__);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int gf_irq_num(struct gf_dev *gf_dev)
|
|
||||||
{
|
|
||||||
if (gf_dev == NULL) {
|
|
||||||
pr_info("Input buff is NULL.\n");
|
|
||||||
return -EPERM;
|
|
||||||
} else {
|
|
||||||
return gpio_to_irq(gf_dev->irq_gpio);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
config FINGERPRINT_GOODIX_FOD
|
|
||||||
tristate "Finger print card goodix"
|
|
||||||
depends on INPUT_FINGERPRINT
|
|
||||||
help
|
|
||||||
Say Y here to enable support for retrieving self-test reports.
|
|
||||||
|
|
||||||
If unsure, say N.
|
|
||||||
|
|
||||||
To compile this driver as a module, choose M here.
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
|||||||
ifneq ($(KERNELRELEASE),)
|
|
||||||
goodix_fod-objs := gf_spi.o platform.o netlink.o
|
|
||||||
obj-$(CONFIG_FINGERPRINT_GOODIX_FOD) += goodix_fod.o
|
|
||||||
else
|
|
||||||
KDIR = $(OUT)/obj/KERNEL_OBJ
|
|
||||||
CROSS_COMPILE = $(ANDROID_TOOLCHAIN)/aarch64-linux-android-
|
|
||||||
CLANG = $(ANDROID_BUILD_TOP)/prebuilts/clang/host/linux-x86/clang-r370808
|
|
||||||
REAL_CC = $(CLANG)/bin/clang
|
|
||||||
AR = $(CLANG)/bin/llvm-ar
|
|
||||||
LLVM_NM = $(CLANG)/bin/llvm-nm
|
|
||||||
LD = $(CLANG)/bin/ld.lld
|
|
||||||
|
|
||||||
.PHONY: clean
|
|
||||||
|
|
||||||
default:
|
|
||||||
$(MAKE) ARCH=arm64 CROSS_COMPILE=$(CROSS_COMPILE) REAL_CC=$(REAL_CC) CLANG_TRIPLE=aarch64-linux-gnu- AR=$(AR) LLVM_NM=$(LLVM_NM) LD=$(LD) -C $(KDIR) M=$(PWD) modules
|
|
||||||
clean:
|
|
||||||
@rm -rf *.o* *.order *.symvers *.mod* .*.o.cmd .*.mod.o.cmd .*.ko.cmd .tmp_versions *.ko
|
|
||||||
|
|
||||||
endif
|
|
File diff suppressed because it is too large
Load Diff
@ -1,168 +0,0 @@
|
|||||||
/*
|
|
||||||
* driver definition for sensor driver
|
|
||||||
*
|
|
||||||
* Coypright (c) 2017 Goodix
|
|
||||||
*/
|
|
||||||
#ifndef __GF_SPI_H
|
|
||||||
#define __GF_SPI_H
|
|
||||||
|
|
||||||
#include <linux/types.h>
|
|
||||||
#include <linux/notifier.h>
|
|
||||||
/**********************************************************/
|
|
||||||
enum FP_MODE {
|
|
||||||
GF_IMAGE_MODE = 0,
|
|
||||||
GF_KEY_MODE,
|
|
||||||
GF_SLEEP_MODE,
|
|
||||||
GF_FF_MODE,
|
|
||||||
GF_DEBUG_MODE = 0x56
|
|
||||||
};
|
|
||||||
|
|
||||||
#define SUPPORT_NAV_EVENT
|
|
||||||
|
|
||||||
#if defined(SUPPORT_NAV_EVENT)
|
|
||||||
#define GF_NAV_INPUT_UP KEY_UP
|
|
||||||
#define GF_NAV_INPUT_DOWN KEY_DOWN
|
|
||||||
#define GF_NAV_INPUT_LEFT KEY_LEFT
|
|
||||||
#define GF_NAV_INPUT_RIGHT KEY_RIGHT
|
|
||||||
#define GF_NAV_INPUT_CLICK KEY_VOLUMEDOWN
|
|
||||||
#define GF_NAV_INPUT_DOUBLE_CLICK KEY_VOLUMEUP
|
|
||||||
#define GF_NAV_INPUT_LONG_PRESS KEY_SEARCH
|
|
||||||
#define GF_NAV_INPUT_HEAVY KEY_CHAT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define GF_KEY_INPUT_HOME KEY_HOME
|
|
||||||
#define GF_KEY_INPUT_MENU KEY_MENU
|
|
||||||
#define GF_KEY_INPUT_BACK KEY_BACK
|
|
||||||
#define GF_KEY_INPUT_POWER KEY_POWER
|
|
||||||
#define GF_KEY_INPUT_CAMERA KEY_CAMERA
|
|
||||||
|
|
||||||
#if defined(SUPPORT_NAV_EVENT)
|
|
||||||
typedef enum gf_nav_event {
|
|
||||||
GF_NAV_NONE = 0,
|
|
||||||
GF_NAV_FINGER_UP,
|
|
||||||
GF_NAV_FINGER_DOWN,
|
|
||||||
GF_NAV_UP,
|
|
||||||
GF_NAV_DOWN,
|
|
||||||
GF_NAV_LEFT,
|
|
||||||
GF_NAV_RIGHT,
|
|
||||||
GF_NAV_CLICK,
|
|
||||||
GF_NAV_HEAVY,
|
|
||||||
GF_NAV_LONG_PRESS,
|
|
||||||
GF_NAV_DOUBLE_CLICK,
|
|
||||||
} gf_nav_event_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef enum gf_key_event {
|
|
||||||
GF_KEY_NONE = 0,
|
|
||||||
GF_KEY_HOME,
|
|
||||||
GF_KEY_POWER,
|
|
||||||
GF_KEY_MENU,
|
|
||||||
GF_KEY_BACK,
|
|
||||||
GF_KEY_CAMERA,
|
|
||||||
} gf_key_event_t;
|
|
||||||
|
|
||||||
struct gf_key {
|
|
||||||
enum gf_key_event key;
|
|
||||||
uint32_t value; /* key down = 1, key up = 0 */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct gf_key_map {
|
|
||||||
unsigned int type;
|
|
||||||
unsigned int code;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct gf_ioc_chip_info {
|
|
||||||
unsigned char vendor_id;
|
|
||||||
unsigned char mode;
|
|
||||||
unsigned char operation;
|
|
||||||
unsigned char reserved[5];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct gf_supplies {
|
|
||||||
struct regulator *l1c;
|
|
||||||
struct regulator *l3c;
|
|
||||||
struct regulator *l9c;
|
|
||||||
struct regulator *l11c;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define GF_IOC_MAGIC 'g' /*define magic number */
|
|
||||||
#define GF_IOC_INIT _IOR(GF_IOC_MAGIC, 0, uint8_t)
|
|
||||||
#define GF_IOC_EXIT _IO(GF_IOC_MAGIC, 1)
|
|
||||||
#define GF_IOC_RESET _IO(GF_IOC_MAGIC, 2)
|
|
||||||
#define GF_IOC_ENABLE_IRQ _IO(GF_IOC_MAGIC, 3)
|
|
||||||
#define GF_IOC_DISABLE_IRQ _IO(GF_IOC_MAGIC, 4)
|
|
||||||
#define GF_IOC_ENABLE_SPI_CLK _IOW(GF_IOC_MAGIC, 5, uint32_t)
|
|
||||||
#define GF_IOC_DISABLE_SPI_CLK _IO(GF_IOC_MAGIC, 6)
|
|
||||||
#define GF_IOC_ENABLE_POWER _IO(GF_IOC_MAGIC, 7)
|
|
||||||
#define GF_IOC_DISABLE_POWER _IO(GF_IOC_MAGIC, 8)
|
|
||||||
#define GF_IOC_INPUT_KEY_EVENT _IOW(GF_IOC_MAGIC, 9, struct gf_key)
|
|
||||||
#define GF_IOC_ENTER_SLEEP_MODE _IO(GF_IOC_MAGIC, 10)
|
|
||||||
#define GF_IOC_GET_FW_INFO _IOR(GF_IOC_MAGIC, 11, uint8_t)
|
|
||||||
#define GF_IOC_REMOVE _IO(GF_IOC_MAGIC, 12)
|
|
||||||
#define GF_IOC_CHIP_INFO _IOW(GF_IOC_MAGIC, 13, struct gf_ioc_chip_info)
|
|
||||||
|
|
||||||
#if defined(SUPPORT_NAV_EVENT)
|
|
||||||
#define GF_IOC_NAV_EVENT _IOW(GF_IOC_MAGIC, 14, gf_nav_event_t)
|
|
||||||
#define GF_IOC_MAXNR 15 /* THIS MACRO IS NOT USED NOW... */
|
|
||||||
#else
|
|
||||||
#define GF_IOC_MAXNR 14 /* THIS MACRO IS NOT USED NOW... */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*#define AP_CONTROL_CLK 1*/
|
|
||||||
#define USE_PLATFORM_BUS 1
|
|
||||||
/*#define USE_SPI_BUS 1*/
|
|
||||||
/*#define GF_FASYNC 1*/
|
|
||||||
/*If support fasync mechanism. */
|
|
||||||
/*#define GF_PW_CTL 1*/
|
|
||||||
#undef GF_PW_CTL
|
|
||||||
#define GF_NETLINK_ENABLE 1
|
|
||||||
#define GF_NET_EVENT_IRQ 1
|
|
||||||
#define GF_NET_EVENT_FB_BLACK 2
|
|
||||||
#define GF_NET_EVENT_FB_UNBLACK 3
|
|
||||||
#define NETLINK_TEST 25
|
|
||||||
|
|
||||||
struct gf_dev {
|
|
||||||
dev_t devt;
|
|
||||||
struct list_head device_entry;
|
|
||||||
#if defined(USE_SPI_BUS)
|
|
||||||
struct spi_device *spi;
|
|
||||||
#elif defined(USE_PLATFORM_BUS)
|
|
||||||
struct platform_device *spi;
|
|
||||||
#endif
|
|
||||||
struct clk *core_clk;
|
|
||||||
struct clk *iface_clk;
|
|
||||||
|
|
||||||
struct input_dev *input;
|
|
||||||
/* buffer is NULL unless this device is open (users > 0) */
|
|
||||||
unsigned users;
|
|
||||||
signed irq_gpio;
|
|
||||||
signed reset_gpio;
|
|
||||||
signed pwr_gpio;
|
|
||||||
int irq;
|
|
||||||
int irq_enabled;
|
|
||||||
int clk_enabled;
|
|
||||||
#ifdef GF_FASYNC
|
|
||||||
struct fasync_struct *async;
|
|
||||||
#endif
|
|
||||||
struct notifier_block notifier;
|
|
||||||
char device_available;
|
|
||||||
char fb_black;
|
|
||||||
char wait_finger_down;
|
|
||||||
struct work_struct work;
|
|
||||||
struct pinctrl *pinctrl;
|
|
||||||
struct pinctrl_state *gf_default_state;
|
|
||||||
};
|
|
||||||
|
|
||||||
int gf_parse_dts(struct gf_dev *gf_dev);
|
|
||||||
void gf_cleanup(struct gf_dev *gf_dev);
|
|
||||||
|
|
||||||
int gf_power_on(struct gf_dev *gf_dev);
|
|
||||||
int gf_power_off(struct gf_dev *gf_dev);
|
|
||||||
|
|
||||||
int gf_hw_reset(struct gf_dev *gf_dev, unsigned int delay_ms);
|
|
||||||
int gf_irq_num(struct gf_dev *gf_dev);
|
|
||||||
|
|
||||||
void sendnlmsg(char *message);
|
|
||||||
int netlink_init(void);
|
|
||||||
void netlink_exit(void);
|
|
||||||
#endif /*__GF_SPI_H*/
|
|
@ -1,96 +0,0 @@
|
|||||||
/*
|
|
||||||
* netlink interface
|
|
||||||
*
|
|
||||||
* Copyright (c) 2017 Goodix
|
|
||||||
*/
|
|
||||||
#include <linux/init.h>
|
|
||||||
#include <linux/module.h>
|
|
||||||
#include <linux/timer.h>
|
|
||||||
#include <linux/time.h>
|
|
||||||
#include <linux/types.h>
|
|
||||||
#include <net/sock.h>
|
|
||||||
#include <net/netlink.h>
|
|
||||||
|
|
||||||
#define NETLINK_TEST 25
|
|
||||||
#define MAX_MSGSIZE 32
|
|
||||||
int stringlength(char *s);
|
|
||||||
void sendnlmsg(char *message);
|
|
||||||
static int pid = -1;
|
|
||||||
struct sock *nl_sk;
|
|
||||||
|
|
||||||
void sendnlmsg(char *message)
|
|
||||||
{
|
|
||||||
struct sk_buff *skb_1;
|
|
||||||
struct nlmsghdr *nlh;
|
|
||||||
int len = NLMSG_SPACE(MAX_MSGSIZE);
|
|
||||||
int slen = 0;
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if (!message || !nl_sk || !pid) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
skb_1 = alloc_skb(len, GFP_KERNEL);
|
|
||||||
|
|
||||||
if (!skb_1) {
|
|
||||||
pr_err("alloc_skb error\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
slen = strlen(message);
|
|
||||||
nlh = nlmsg_put(skb_1, 0, 0, 0, MAX_MSGSIZE, 0);
|
|
||||||
NETLINK_CB(skb_1).portid = 0;
|
|
||||||
NETLINK_CB(skb_1).dst_group = 0;
|
|
||||||
message[slen] = '\0';
|
|
||||||
memcpy(NLMSG_DATA(nlh), message, slen + 1);
|
|
||||||
ret = netlink_unicast(nl_sk, skb_1, pid, MSG_DONTWAIT);
|
|
||||||
|
|
||||||
if (!ret) {
|
|
||||||
/*kfree_skb(skb_1); */
|
|
||||||
pr_err("send msg from kernel to usespace failed ret 0x%x\n",
|
|
||||||
ret);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void nl_data_ready(struct sk_buff *__skb)
|
|
||||||
{
|
|
||||||
struct sk_buff *skb;
|
|
||||||
struct nlmsghdr *nlh;
|
|
||||||
char str[100];
|
|
||||||
skb = skb_get(__skb);
|
|
||||||
|
|
||||||
if (skb->len >= NLMSG_SPACE(0)) {
|
|
||||||
nlh = nlmsg_hdr(skb);
|
|
||||||
memcpy(str, NLMSG_DATA(nlh), sizeof(str));
|
|
||||||
pid = nlh->nlmsg_pid;
|
|
||||||
kfree_skb(skb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int netlink_init(void)
|
|
||||||
{
|
|
||||||
struct netlink_kernel_cfg netlink_cfg;
|
|
||||||
memset(&netlink_cfg, 0, sizeof(struct netlink_kernel_cfg));
|
|
||||||
netlink_cfg.groups = 0;
|
|
||||||
netlink_cfg.flags = 0;
|
|
||||||
netlink_cfg.input = nl_data_ready;
|
|
||||||
netlink_cfg.cb_mutex = NULL;
|
|
||||||
nl_sk = netlink_kernel_create(&init_net, NETLINK_TEST, &netlink_cfg);
|
|
||||||
|
|
||||||
if (!nl_sk) {
|
|
||||||
pr_err("create netlink socket error\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void netlink_exit(void)
|
|
||||||
{
|
|
||||||
if (nl_sk != NULL) {
|
|
||||||
netlink_kernel_release(nl_sk);
|
|
||||||
nl_sk = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
pr_info("self module exited\n");
|
|
||||||
}
|
|
@ -1,174 +0,0 @@
|
|||||||
/*
|
|
||||||
* platform indepent driver interface
|
|
||||||
*
|
|
||||||
* Coypritht (c) 2017 Goodix
|
|
||||||
*/
|
|
||||||
#define DEBUG
|
|
||||||
#define pr_fmt(fmt) "gf_platform: " fmt
|
|
||||||
|
|
||||||
#include <linux/delay.h>
|
|
||||||
#include <linux/workqueue.h>
|
|
||||||
#include <linux/of_gpio.h>
|
|
||||||
#include <linux/gpio.h>
|
|
||||||
#include <linux/regulator/consumer.h>
|
|
||||||
#include <linux/timer.h>
|
|
||||||
#include <linux/err.h>
|
|
||||||
|
|
||||||
#include "gf_spi.h"
|
|
||||||
|
|
||||||
#if defined(USE_SPI_BUS)
|
|
||||||
#include <linux/spi/spi.h>
|
|
||||||
#include <linux/spi/spidev.h>
|
|
||||||
#elif defined(USE_PLATFORM_BUS)
|
|
||||||
#include <linux/platform_device.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define GOODIX_FINGERPRINT_PINCTRL_DEFAULT_STATE "fingerprint_goodix_default"
|
|
||||||
|
|
||||||
static int gf_pinctrl_init(struct gf_dev *gf_dev)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
gf_dev->pinctrl = devm_pinctrl_get(&gf_dev->spi->dev);
|
|
||||||
if (IS_ERR_OR_NULL(gf_dev->pinctrl)) {
|
|
||||||
pr_info("Failed to get pinctrl, please check dts\n");
|
|
||||||
ret = PTR_ERR(gf_dev->pinctrl);
|
|
||||||
goto err_pinctrl_get;
|
|
||||||
}
|
|
||||||
|
|
||||||
gf_dev->gf_default_state = pinctrl_lookup_state(
|
|
||||||
gf_dev->pinctrl, GOODIX_FINGERPRINT_PINCTRL_DEFAULT_STATE);
|
|
||||||
if (IS_ERR_OR_NULL(gf_dev->gf_default_state)) {
|
|
||||||
pr_info("Pin state[default] not found\n");
|
|
||||||
ret = PTR_ERR(gf_dev->gf_default_state);
|
|
||||||
goto err_pinctrl_lookup;
|
|
||||||
}
|
|
||||||
|
|
||||||
pr_info("gf_pinctrl_init done\n");
|
|
||||||
return 0;
|
|
||||||
err_pinctrl_lookup:
|
|
||||||
if (gf_dev->pinctrl) {
|
|
||||||
devm_pinctrl_put(gf_dev->pinctrl);
|
|
||||||
}
|
|
||||||
err_pinctrl_get:
|
|
||||||
gf_dev->pinctrl = NULL;
|
|
||||||
gf_dev->gf_default_state = NULL;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int gf_parse_dts(struct gf_dev *gf_dev)
|
|
||||||
{
|
|
||||||
#ifdef GF_PW_CTL
|
|
||||||
/*get pwr resource */
|
|
||||||
gf_dev->pwr_gpio =
|
|
||||||
of_get_named_gpio(gf_dev->spi->dev.of_node, "fp-gpio-pwr", 0);
|
|
||||||
|
|
||||||
if (!gpio_is_valid(gf_dev->pwr_gpio)) {
|
|
||||||
pr_info("PWR GPIO is invalid.\n");
|
|
||||||
return -EPERM;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
/*get reset resource */
|
|
||||||
gf_dev->reset_gpio = of_get_named_gpio(gf_dev->spi->dev.of_node,
|
|
||||||
"goodix,gpio-reset", 0);
|
|
||||||
|
|
||||||
if (!gpio_is_valid(gf_dev->reset_gpio)) {
|
|
||||||
pr_info("RESET GPIO is invalid.\n");
|
|
||||||
return -EPERM;
|
|
||||||
}
|
|
||||||
pr_info("gf::gpio-reset:%d\n", gf_dev->reset_gpio);
|
|
||||||
|
|
||||||
/*get irq resourece */
|
|
||||||
gf_dev->irq_gpio = of_get_named_gpio(gf_dev->spi->dev.of_node,
|
|
||||||
"goodix,gpio-irq", 0);
|
|
||||||
pr_info("gf::irq_gpio:%d\n", gf_dev->irq_gpio);
|
|
||||||
|
|
||||||
if (!gpio_is_valid(gf_dev->irq_gpio)) {
|
|
||||||
pr_info("IRQ GPIO is invalid.\n");
|
|
||||||
return -EPERM;
|
|
||||||
}
|
|
||||||
|
|
||||||
gf_pinctrl_init(gf_dev);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void gf_cleanup(struct gf_dev *gf_dev)
|
|
||||||
{
|
|
||||||
pr_info("[info] %s\n", __func__);
|
|
||||||
|
|
||||||
if (gpio_is_valid(gf_dev->irq_gpio)) {
|
|
||||||
gpio_free(gf_dev->irq_gpio);
|
|
||||||
pr_info("remove irq_gpio success\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gpio_is_valid(gf_dev->reset_gpio)) {
|
|
||||||
gpio_free(gf_dev->reset_gpio);
|
|
||||||
pr_info("remove reset_gpio success\n");
|
|
||||||
}
|
|
||||||
#ifdef GF_PW_CTL
|
|
||||||
|
|
||||||
if (gpio_is_valid(gf_dev->pwr_gpio)) {
|
|
||||||
gpio_free(gf_dev->pwr_gpio);
|
|
||||||
pr_info("remove pwr_gpio success\n");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int gf_power_on(struct gf_dev *gf_dev)
|
|
||||||
{
|
|
||||||
int rc = 0;
|
|
||||||
#ifdef GF_PW_CTL
|
|
||||||
|
|
||||||
if (gpio_is_valid(gf_dev->pwr_gpio)) {
|
|
||||||
rc = gpio_direction_output(gf_dev->pwr_gpio, 1);
|
|
||||||
pr_info("---- power on result: %d----\n", rc);
|
|
||||||
} else {
|
|
||||||
pr_info("%s: gpio_is_invalid\n", __func__);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
msleep(10);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
int gf_power_off(struct gf_dev *gf_dev)
|
|
||||||
{
|
|
||||||
int rc = 0;
|
|
||||||
#ifdef GF_PW_CTL
|
|
||||||
|
|
||||||
if (gpio_is_valid(gf_dev->pwr_gpio)) {
|
|
||||||
rc = gpio_direction_output(gf_dev->pwr_gpio, 0);
|
|
||||||
pr_info("---- power off result: %d----\n", rc);
|
|
||||||
} else {
|
|
||||||
pr_info("%s: gpio_is_invalid\n", __func__);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
int gf_hw_reset(struct gf_dev *gf_dev, unsigned int delay_ms)
|
|
||||||
{
|
|
||||||
if (gf_dev == NULL) {
|
|
||||||
pr_info("Input buff is NULL.\n");
|
|
||||||
return -EPERM;
|
|
||||||
}
|
|
||||||
|
|
||||||
gpio_direction_output(gf_dev->reset_gpio, 0);
|
|
||||||
mdelay(3);
|
|
||||||
gpio_set_value(gf_dev->reset_gpio, 1);
|
|
||||||
mdelay(delay_ms);
|
|
||||||
pr_info("%s\n", __func__);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int gf_irq_num(struct gf_dev *gf_dev)
|
|
||||||
{
|
|
||||||
if (gf_dev == NULL) {
|
|
||||||
pr_info("Input buff is NULL.\n");
|
|
||||||
return -EPERM;
|
|
||||||
} else {
|
|
||||||
return gpio_to_irq(gf_dev->irq_gpio);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user