From 487d82090b277c45f9c4dac64f7443b43d5b995d Mon Sep 17 00:00:00 2001 From: wangzijiao Date: Fri, 11 Jan 2019 17:34:05 +0800 Subject: [PATCH] add c1 evb key driver --- .../linux-4.9/drivers/input/keyboard/Kconfig | 5 +- .../linux-4.9/drivers/input/keyboard/Makefile | 1 + .../input/keyboard/R311-keyboard-c1evb.c | 423 ++++++++++++++++++ target/allwinner/mandolin-c1evb/config-4.9 | 8 +- 4 files changed, 434 insertions(+), 3 deletions(-) create mode 100755 lichee/linux-4.9/drivers/input/keyboard/R311-keyboard-c1evb.c diff --git a/lichee/linux-4.9/drivers/input/keyboard/Kconfig b/lichee/linux-4.9/drivers/input/keyboard/Kconfig index a9204fbba..c54b0224f 100755 --- a/lichee/linux-4.9/drivers/input/keyboard/Kconfig +++ b/lichee/linux-4.9/drivers/input/keyboard/Kconfig @@ -749,13 +749,16 @@ config IR_TX_SUNXI choice prompt "Selected Keyboard for netease ihw product" - default XUNFEI_TTS_SDK + default KEYBOARD_NETEASE_C1EVB config KEYBOARD_NETEASE_PV1 tristate "KEYBOARD_NETEASE_PV1" config KEYBOARD_NETEASE_PV1_CES tristate "KEYBOARD_NETEASE_PV1_CES" + + config KEYBOARD_NETEASE_C1EVB + tristate "KEYBOARD_NETEASE_C1EVB" endchoice diff --git a/lichee/linux-4.9/drivers/input/keyboard/Makefile b/lichee/linux-4.9/drivers/input/keyboard/Makefile index bac996dd3..c20c2b5b2 100755 --- a/lichee/linux-4.9/drivers/input/keyboard/Makefile +++ b/lichee/linux-4.9/drivers/input/keyboard/Makefile @@ -68,3 +68,4 @@ obj-$(CONFIG_KEYBOARD_SUNXI) += sunxi-keyboard.o obj-$(CONFIG_IR_TX_SUNXI) += sunxi-ir-tx.o obj-$(CONFIG_KEYBOARD_NETEASE_PV1) += R16-keyboard-pv1.o obj-$(CONFIG_KEYBOARD_NETEASE_PV1_CES) += R16-keyboard-pv1-ces.o +obj-$(CONFIG_KEYBOARD_NETEASE_C1EVB) += R311-keyboard-c1evb.o diff --git a/lichee/linux-4.9/drivers/input/keyboard/R311-keyboard-c1evb.c b/lichee/linux-4.9/drivers/input/keyboard/R311-keyboard-c1evb.c new file mode 100755 index 000000000..abceb2cc8 --- /dev/null +++ b/lichee/linux-4.9/drivers/input/keyboard/R311-keyboard-c1evb.c @@ -0,0 +1,423 @@ +/********************************************************************************* + * Copyright: (C) 2017 NetEase(Hangzhou) Network Co., Ltd. + * All rights reserved. + * + * Filename: R16-keyboard.c + * Description: This is the common button driver runs on S3C2440 + * + * Version: 1.0.0(8/3/2017) + * Author: Netease IHW + * ChangeLog: 1, Release initial version + * + ********************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define USED_SYSCONF 0 +#define DRV_NAME ("r16kbd") + +#if USED_SYSCONF +struct encoder_gkey_config { + u32 encoder1_gkey; + u32 encoder2_gkey; +}; +#else +#define GPIO_ENCODER1 GPIOB(3) +#define GPIO_ENCODER2 GPIOB(2) +#define GPIO_MUTE_KEY GPIOB(1) +#define GPIO_HOME_KEY GPIOB(0) +//#define GPIO_RESERVE GPIOL(11) + +struct Volkey_status { + u8 nVolup; + u8 nVoldown; +}; + +#endif + +enum { + DEBUG_INIT = 1U << 0, + DEBUG_INT = 1U << 1, + DEBUG_DATA_INFO = 1U << 2, + DEBUG_SUSPEND = 1U << 3, +}; +static u32 debug_mask = 1; +#define dprintk(level_mask, fmt, arg...) \ + if (unlikely(debug_mask & level_mask)) \ + printk(fmt, ##arg) + +struct gpio_keys_button_data { + int last_state; + int count; + int threshold; + int can_sleep; +}; + +struct gpio_keys_polled_dev { + struct input_polled_dev *poll_dev; + struct device *dev; + struct gpio_keys_platform_data *pdata; + struct gpio_keys_button_data data[0]; +}; + +#if USED_SYSCONF +static struct encoder_gkey_config *r16_gkey; +#endif +static struct Volkey_status *sVolkey_status; +static struct input_dev *tymr16kbd_dev; +static struct input_polled_dev *poll_dev; +#define VOL_CONFIRM 5 +#define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake, debounce) \ + { \ + .gpio = gpio_num, .type = EV_KEY, .code = ev_code, \ + .active_low = act_low, .desc = "btn " descr, .wakeup = wake, \ + .debounce_interval = debounce, \ + } + +static struct gpio_keys_button tym_r16_buttons[] = { + GPIO_BUTTON(GPIO_HOME_KEY, KEY_HOME, 1, "user-key-home", 0, 1), + GPIO_BUTTON(GPIO_MUTE_KEY, KEY_MUTE, 1, "user-key-mute", 0, 1), + GPIO_BUTTON(GPIO_ENCODER1, KEY_VOLUMEUP, 1, "user-key-volup", 0, 1), + GPIO_BUTTON(GPIO_ENCODER2, KEY_VOLUMEDOWN, 1, "user-key-voldown", 0, 1), +}; + +struct rotary_encoder_data { + u8 encoder_state; +}; + +static struct gpio_keys_platform_data tym_r16_button_data = { + .buttons = tym_r16_buttons, + .nbuttons = ARRAY_SIZE(tym_r16_buttons), + .poll_interval = 50, + .name = "tymkey", +}; + +static void init_nVol(void) { + sVolkey_status->nVolup = 0; + sVolkey_status->nVoldown = 0; +} + +static irqreturn_t rotary_encoder_check_state_irq(int irq, void *dummy) { + int state_a, state_b; +#if USED_SYSCONF + state_a = !!gpio_get_value(r16_gkey->encoder1_gkey); + state_b = !!gpio_get_value(r16_gkey->encoder2_gkey); +#else + state_a = !!gpio_get_value(GPIO_ENCODER1); + state_b = !!gpio_get_value(GPIO_ENCODER2); +#endif + if (state_b != state_a) { + sVolkey_status->nVoldown++; + /*dprintk(DEBUG_INIT,"encoder check state v+ \n"); + input_event(tymr16kbd_dev, EV_KEY, KEY_VOLUMEDOWN, 2); + input_sync(tymr16kbd_dev);*/ + } else { + sVolkey_status->nVolup++; + /*dprintk(DEBUG_INIT,"encoder check state v- \n"); + input_event(tymr16kbd_dev, EV_KEY, KEY_VOLUMEUP, 2); + input_sync(tymr16kbd_dev);*/ + } + if (sVolkey_status->nVoldown > VOL_CONFIRM) { + init_nVol(); + dprintk(DEBUG_INIT, "encoder check state v+ \n"); + input_event(tymr16kbd_dev, EV_KEY, KEY_VOLUMEDOWN, 2); + input_sync(tymr16kbd_dev); + } + if (sVolkey_status->nVolup > VOL_CONFIRM) { + init_nVol(); + dprintk(DEBUG_INIT, "encoder check state v- \n"); + input_event(tymr16kbd_dev, EV_KEY, KEY_VOLUMEUP, 2); + input_sync(tymr16kbd_dev); + } + return IRQ_HANDLED; +} +static void gpio_keys_polled_check_state(struct input_dev *input, + struct gpio_keys_button *button, + struct gpio_keys_button_data *bdata) { + int state; + // dprintk(DEBUG_INIT,"gpio_keys_polled_check_state\n"); + if (bdata->can_sleep) + state = !!gpio_get_value_cansleep(button->gpio); + else + state = !!gpio_get_value(button->gpio); + if (state != bdata->last_state) { + unsigned int type = button->type ?: EV_KEY; + dprintk(DEBUG_INIT, "button->gpio, %d , state, %d \n", button->gpio, + state); + + input_event(input, type, button->code, !!(state ^ button->active_low)); + input_sync(input); + bdata->count = 0; + bdata->last_state = state; + } +} + +static void gpio_keys_polled_poll(struct input_polled_dev *dev) { + struct gpio_keys_polled_dev *bdev = dev->private; + struct gpio_keys_platform_data *pdata = bdev->pdata; + struct input_dev *input = dev->input; + int i; + // dprintk(DEBUG_INIT,"gpio_keys_polled_poll"); + for (i = 0; i < bdev->pdata->nbuttons; i++) { + struct gpio_keys_button_data *bdata = &bdev->data[i]; + gpio_keys_polled_check_state(input, &pdata->buttons[i], bdata); + } +} + +static void gpio_keys_polled_open(struct input_polled_dev *dev) { + struct gpio_keys_polled_dev *bdev = dev->private; + struct gpio_keys_platform_data *pdata = bdev->pdata; + + if (pdata->enable) + pdata->enable(bdev->dev); +} + +static void gpio_keys_polled_close(struct input_polled_dev *dev) { + struct gpio_keys_polled_dev *bdev = dev->private; + struct gpio_keys_platform_data *pdata = bdev->pdata; + + if (pdata->disable) + pdata->disable(bdev->dev); +} + +#if USED_SYSCONF +static int GPIO_fetch_sysconfig_para(void) { + int ret = -1; + int gpio_used = -1; + script_item_u val; + script_item_value_type_e type; + dprintk(DEBUG_INIT, "gpio fetch sysconfig para!\n"); + + r16_gkey = input_allocate_device(); + if (!r16_gkey) { + pr_err("tymkbd: not enough memory for input device\n"); + ret = -ENOMEM; + goto script_get_item_err; + } + + type = script_get_item("gkey_para", "gkey_used", &val); + if (SCIRPT_ITEM_VALUE_TYPE_INT != type) { + pr_err("%s: gkey_used script_get_item err. \n", __func__); + goto script_get_item_err; + } + gpio_used = val.val; + + if (1 == gpio_used) { + type = script_get_item("gkey_para", "gkey_encoder1", &val); + if (SCIRPT_ITEM_VALUE_TYPE_PIO != type) { + goto script_get_item_err; + } + r16_gkey->encoder1_gkey = val.gpio.gpio; + type = script_get_item("gkey_para", "gkey_encoder2", &val); + if (SCIRPT_ITEM_VALUE_TYPE_PIO != type) { + goto script_get_item_err; + } + r16_gkey->encoder2_gkey = val.gpio.gpio; + ret = 0; + } else { + pr_err("%s: gkey_unused. \n", __func__); + ret = -1; + } + +script_get_item_err: + printk("get gpio fetch sysconfig para error!\n"); + + return ret; +} +#endif + +static int __init r16_button_init(void) { +#if 1 + struct gpio_keys_polled_dev *bdev; + int i; + int error; + int virq; + dprintk(DEBUG_INIT, "wzj: r311_c1evb_button_init\n"); +#if USED_SYSCONF + GPIO_fetch_sysconfig_para(); +#endif + sVolkey_status = kzalloc(sizeof(struct Volkey_status), GFP_KERNEL); + init_nVol(); + bdev = kzalloc(sizeof(struct gpio_keys_polled_dev) + + tym_r16_button_data.nbuttons * + sizeof(struct gpio_keys_button_data), + GFP_KERNEL); + if (!bdev) { + pr_err("no memory for private data\n"); + return -ENOMEM; + } + bdev->pdata = &tym_r16_button_data; + poll_dev = input_allocate_polled_device(); + if (!poll_dev) { + pr_err("no memory for polled device\n"); + goto err_free_bdev; + } + poll_dev->private = bdev; + poll_dev->poll = gpio_keys_polled_poll; + poll_dev->poll_interval = 50; + // poll_dev->open = gpio_keys_polled_open; + // poll_dev->close = gpio_keys_polled_close; + + tymr16kbd_dev = input_allocate_device(); + if (!tymr16kbd_dev) { + pr_err("tymkbd: not enough memory for input device\n"); + error = -ENOMEM; + goto fail1; + } + tymr16kbd_dev->name = DRV_NAME; + tymr16kbd_dev->phys = "r16kbd/input0"; + tymr16kbd_dev->id.bustype = BUS_HOST; + tymr16kbd_dev->id.vendor = 0x0001; + tymr16kbd_dev->id.product = 0x0001; + tymr16kbd_dev->id.version = 0x0100; + tymr16kbd_dev->evbit[0] = BIT_MASK(EV_KEY); + poll_dev->input = tymr16kbd_dev; + for (i = 0; i < tym_r16_button_data.nbuttons; i++) { + struct gpio_keys_button *button = &tym_r16_buttons[i]; + // struct gpio_keys_button_data *bdata = &bdev->data[i]; + unsigned int gpio = tym_r16_buttons[i].gpio; + unsigned int type = tym_r16_buttons[i].type ?: EV_KEY; + unsigned int desc = tym_r16_buttons[i].desc ?: DRV_NAME; + error = gpio_request(gpio, desc); + if (error) { + pr_err("unable to claim gpio %u, err=%d\n", gpio, error); + goto err_free_gpio; + } + + error = gpio_direction_input(gpio); + if (error) { + pr_err("unable to set direction on gpio %u, err=%d\n", gpio, error); + goto err_free_gpio; + } + + // bdata->can_sleep = gpio_cansleep(gpio); + // bdata->last_state = -1; + // bdata->threshold = + //DIV_ROUND_UP(button->debounce_interval, poll_dev->poll_interval); + + input_set_capability(tymr16kbd_dev, type, button->code); + } + + input_set_capability(tymr16kbd_dev, EV_KEY, KEY_VOLUMEUP); + input_set_capability(tymr16kbd_dev, EV_KEY, KEY_VOLUMEDOWN); + + error = input_register_polled_device(poll_dev); + if (error) { + pr_err("unable to register polled device, err=%d\n", error); + goto err_free_gpio; + } +/* + for (i = 0; i < tym_r16_button_data.nbuttons; i++) + gpio_keys_polled_check_state(tymr16kbd_dev, &tym_r16_buttons[i], + &bdev->data[i]); +*/ +#if USED_SYSCONF + gpio_request(r16_gkey->encoder2_gkey, "gpio_encoder2"); + gpio_direction_input(r16_gkey->encoder2_gkey); + + virq = gpio_to_irq(r16_gkey->encoder1_gkey); + if (request_irq(virq, rotary_encoder_check_state_irq, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "r16kbd", + NULL)) { + // err = -EBUSY; + pr_err("request irq failure. \n"); + goto fail2; + } + if (request_irq(virq, rotary_encoder_check_rising_state_irq, + IRQF_TRIGGER_RISING, "r16kbd", NULL)) { + // err = -EBUSY; + pr_err("request irq failure. \n"); + goto fail2; + } + + if (request_irq(virq, rotary_encoder_check_falling_state_irq, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "r16kbd", + NULL)) { + // err = -EBUSY; + pr_err("request irq failure. \n"); + goto fail2; + } +#else + // gpio_request(GPIO_ENCODER2, "gpio_encoder2"); + // gpio_direction_input(GPIO_ENCODER2); + + // virq = gpio_to_irq(GPIO_ENCODER1); + // if (request_irq(virq, rotary_encoder_check_state_irq, + // IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "r16kbd", + // NULL)) { + // // err = -EBUSY; + // pr_err("request irq failure. \n"); + // goto fail2; + // } +#endif + + dprintk(DEBUG_INIT, "Regist R16 %s device successfully.\n", DRV_NAME); + + return 0; + +err_free_gpio: + while (--i >= 0) + gpio_free(tym_r16_buttons[i].gpio); + + input_free_polled_device(poll_dev); + +err_free_bdev: + kfree(bdev); +fail1: + pr_err("sunxikbd_init failed. \n"); + +fail2: + kfree(sVolkey_status); + free_irq(virq, NULL); +#if USED_SYSCONF + gpio_free(r16_gkey->encoder2_gkey); +#else + gpio_free(GPIO_ENCODER2); +#endif + return error; +#endif +} + +static void r16_button_exit(void) { + int i; + int virq; + + input_unregister_polled_device(poll_dev); + + for (i = 0; i < tym_r16_button_data.nbuttons; i++) + gpio_free(tym_r16_button_data.buttons[i].gpio); + + input_free_polled_device(poll_dev); +#if USED_SYSCONF + gpio_free(r16_gkey->encoder2_gkey); + virq = gpio_to_irq(r16_gkey->encoder1_gkey); +#else + gpio_free(GPIO_ENCODER2); + virq = gpio_to_irq(GPIO_ENCODER1); +#endif + free_irq(virq, NULL); + kfree(sVolkey_status); + kfree(tymr16kbd_dev); + dprintk(DEBUG_INIT, "R16 %s platform device removed.\n", DRV_NAME); + return 0; +} + +module_init(r16_button_init); +module_exit(r16_button_exit); + +MODULE_AUTHOR("Netease IHW"); +MODULE_DESCRIPTION("Netease r16 button driver"); +MODULE_LICENSE("GPL"); diff --git a/target/allwinner/mandolin-c1evb/config-4.9 b/target/allwinner/mandolin-c1evb/config-4.9 index c9a1869e3..e29258f75 100644 --- a/target/allwinner/mandolin-c1evb/config-4.9 +++ b/target/allwinner/mandolin-c1evb/config-4.9 @@ -317,8 +317,11 @@ CONFIG_EXT4_FS=y # CONFIG_FAT_DEFAULT_UTF8 is not set CONFIG_FAT_FS=y CONFIG_FB=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_IMAGEBLIT=y CONFIG_FB_CMDLINE=y -# CONFIG_FB_CONSOLE_SUNXI is not set +CONFIG_FB_CONSOLE_SUNXI=y CONFIG_FB_NOTIFY=y CONFIG_FHANDLE=y # CONFIG_FIQ_DEBUGGER is not set @@ -533,8 +536,9 @@ CONFIG_KERNEL_GZIP=y CONFIG_KEYBOARD_ATKBD=y CONFIG_KEYBOARD_GPIO=y CONFIG_KEYBOARD_GPIO_POLLED=y +CONFIG_KEYBOARD_NETEASE_C1EVB=y # CONFIG_KEYBOARD_NETEASE_PV1 is not set -CONFIG_KEYBOARD_NETEASE_PV1_CES=y +# CONFIG_KEYBOARD_NETEASE_PV1_CES is not set # CONFIG_KEYBOARD_SUN4I_LRADC is not set CONFIG_KEYBOARD_SUNXI=y # CONFIG_KS7010 is not set