diff --git a/MAINTAINERS b/MAINTAINERS index d25049a12385..c5fe56c7de02 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14151,3 +14151,7 @@ F: arch/arm64/boot/dts/amlogic/gxl_p241_v2-1g.dts AMLOGIC lcd driver M: Evoke Zhang F: drivers/amlogic/media/vout/lcd/lcd_extern/mipi_TV070WSM.c + +AMLOGIC remote +M: Zan Peng +F: {include/uapi/linux => drivers/amlogic/input/remote}/rc_common.h diff --git a/include/uapi/linux/rc_common.h b/drivers/amlogic/input/remote/rc_common.h similarity index 67% rename from include/uapi/linux/rc_common.h rename to drivers/amlogic/input/remote/rc_common.h index 912d1dab1c00..762a972c94ea 100644 --- a/include/uapi/linux/rc_common.h +++ b/drivers/amlogic/input/remote/rc_common.h @@ -14,7 +14,7 @@ #define CUSTOM_NAME_LEN 64 /*to ensure kernel and user spase use the same header file*/ -#define SHARE_DATA_VERSION "v1.0.0" +#define SHARE_DATA_VERSION "v1.1.0" union _codemap { struct ir_key_map { @@ -23,10 +23,31 @@ union _codemap { } map; __u32 code; }; + +/* + *struct cursor_codemap - codemap for mouse mode + * + *@fn_key_scancode: scancode of fn key which used to swith mode + *@cursor_left_scancode: scancode of left key + *@cursor_right_scancode: scancode of right key + *@cursor_up_scancode: scancode of up key + *@cursor_down_scancode: scancode of down key + *@cursor_ok_scancode: scancode of ok key + */ +struct cursor_codemap { + __u16 fn_key_scancode; + __u16 cursor_left_scancode; + __u16 cursor_right_scancode; + __u16 cursor_up_scancode; + __u16 cursor_down_scancode; + __u16 cursor_ok_scancode; +}; + /** *struct ir_map_table - the IR key map table for different remote-control * *@custom_name: table name + *@cursor_code: mouse mode need *@map_size: number of IR key *@custom_code: custom code, identify different key mapping table *@release_delay: release delay time @@ -34,6 +55,7 @@ union _codemap { */ struct ir_map_tab { char custom_name[CUSTOM_NAME_LEN]; + struct cursor_codemap cursor_code; __u16 map_size; __u32 custom_code; __u32 release_delay; diff --git a/drivers/amlogic/input/remote/remote_core.c b/drivers/amlogic/input/remote/remote_core.c index 0d4754dc22e7..1bb70b727182 100644 --- a/drivers/amlogic/input/remote/remote_core.c +++ b/drivers/amlogic/input/remote/remote_core.c @@ -125,6 +125,20 @@ void remote_keydown(struct remote_dev *dev, int scancode, int status) dev->cur_hardcode); } spin_lock_irqsave(&dev->keylock, flags); + /** + *only a few keys which be set in key map table support + *report relative axes event in mouse mode, other keys + *will continue to report key event. + */ + if (status == REMOTE_NORMAL || + status == REMOTE_REPEAT) { + /*to report relative axes event*/ + if (dev->ir_report_rel(dev, scancode, status) == 0) { + spin_unlock_irqrestore(&dev->keylock, flags); + return; + } + } + if (status == REMOTE_NORMAL) { keycode = dev->getkeycode(dev, scancode); if (keycode == KEY_POWER) @@ -190,6 +204,16 @@ int remote_register_device(struct remote_dev *dev) for (i = KEY_OK; i < BTN_TRIGGER_HAPPY; i++) __set_bit(i, dev->input_device->keybit); + __set_bit(BTN_MOUSE, dev->input_device->keybit); + __set_bit(BTN_LEFT, dev->input_device->keybit); + __set_bit(BTN_RIGHT, dev->input_device->keybit); + __set_bit(BTN_MIDDLE, dev->input_device->keybit); + + __set_bit(EV_REL, dev->input_device->evbit); + __set_bit(REL_X, dev->input_device->relbit); + __set_bit(REL_Y, dev->input_device->relbit); + __set_bit(REL_WHEEL, dev->input_device->relbit); + dev->input_device->keycodesize = sizeof(unsigned short); dev->input_device->keycodemax = 0x1ff; @@ -221,4 +245,3 @@ EXPORT_SYMBOL(remote_unregister_device); MODULE_AUTHOR("AMLOGIC"); MODULE_DESCRIPTION("Remote Driver"); MODULE_LICENSE("GPL"); - diff --git a/drivers/amlogic/input/remote/remote_core.h b/drivers/amlogic/input/remote/remote_core.h index ede09b968bec..ec8da62c8402 100644 --- a/drivers/amlogic/input/remote/remote_core.h +++ b/drivers/amlogic/input/remote/remote_core.h @@ -88,10 +88,11 @@ struct remote_dev { int debug_buffer_size; int debug_current; - u32 (*getkeycode)(struct remote_dev *dev, u32 scancode); - bool (*set_custom_code)(struct remote_dev *dev, u32 code); - bool (*is_valid_custom)(struct remote_dev *dev); - bool (*is_next_repeat)(struct remote_dev *dev); + u32 (*getkeycode)(struct remote_dev *, u32); + int (*ir_report_rel)(struct remote_dev *, u32, int); + bool (*set_custom_code)(struct remote_dev *, u32); + bool (*is_valid_custom)(struct remote_dev *); + bool (*is_next_repeat)(struct remote_dev *); }; struct remote_raw_handle { @@ -205,5 +206,3 @@ bool remote_debug_get_enable(void); int debug_log_printk(struct remote_dev *dev, const char *fmt); #endif - - diff --git a/drivers/amlogic/input/remote/remote_meson.c b/drivers/amlogic/input/remote/remote_meson.c index 6ffbd73cea56..fcbf5fa0afc8 100644 --- a/drivers/amlogic/input/remote/remote_meson.c +++ b/drivers/amlogic/input/remote/remote_meson.c @@ -136,6 +136,60 @@ static int ir_lookup_by_scancode(struct ir_map_tab *ir_map, return -1; } +static int ir_report_rel(struct remote_dev *dev, u32 scancode, int status) +{ + struct remote_chip *chip = (struct remote_chip *)dev->platform_data; + struct ir_map_tab_list *ct = chip->cur_tab; + static u32 repeat_count; + s32 cursor_value = 0; + u32 valid_scancode; + u16 mouse_code; + s32 move_accelerate[] = CURSOR_MOVE_ACCELERATE; + + /*nothing need to do in normal mode*/ + if (!ct || (ct->ir_dev_mode != MOUSE_MODE)) + return -EINVAL; + + if (status == REMOTE_REPEAT) { + valid_scancode = dev->last_scancode; + repeat_count++; + if (repeat_count > ARRAY_SIZE(move_accelerate) - 1) + repeat_count = ARRAY_SIZE(move_accelerate) - 1; + } else { + valid_scancode = scancode; + dev->last_scancode = scancode; + repeat_count = 0; + } + if (valid_scancode == ct->tab.cursor_code.cursor_left_scancode) { + cursor_value = -(1 + move_accelerate[repeat_count]); + mouse_code = REL_X; + } else if (valid_scancode == + ct->tab.cursor_code.cursor_right_scancode) { + cursor_value = 1 + move_accelerate[repeat_count]; + mouse_code = REL_X; + } else if (valid_scancode == + ct->tab.cursor_code.cursor_up_scancode) { + cursor_value = -(1 + move_accelerate[repeat_count]); + mouse_code = REL_Y; + } else if (valid_scancode == + ct->tab.cursor_code.cursor_down_scancode) { + cursor_value = 1 + move_accelerate[repeat_count]; + mouse_code = REL_Y; + } else { + return -EINVAL; + } + input_event(chip->r_dev->input_device, EV_REL, + mouse_code, cursor_value); + input_sync(chip->r_dev->input_device); + + remote_dbg(chip->dev, "mouse cursor be %s moved %d.\n", + mouse_code == REL_X ? "horizontal" : + "vertical", + cursor_value); + + return 0; +} + static u32 getkeycode(struct remote_dev *dev, u32 scancode) { struct remote_chip *chip = (struct remote_chip *)dev->platform_data; @@ -146,13 +200,36 @@ static u32 getkeycode(struct remote_dev *dev, u32 scancode) dev_err(chip->dev, "cur_custom is nulll\n"); return KEY_RESERVED; } + /*return BTN_LEFT in mouse mode*/ + if (ct->ir_dev_mode == MOUSE_MODE && + scancode == ct->tab.cursor_code.cursor_ok_scancode) { + remote_dbg(chip->dev, "mouse left button scancode: 0x%x", + BTN_LEFT); + return BTN_LEFT; + } + index = ir_lookup_by_scancode(&ct->tab, scancode); if (index < 0) { dev_err(chip->dev, "scancode %d undefined\n", scancode); return KEY_RESERVED; } + + /*save remote-control work mode*/ + if (dev->keypressed == false && + scancode == ct->tab.cursor_code.fn_key_scancode) { + if (ct->ir_dev_mode == NORMAL_MODE) + ct->ir_dev_mode = MOUSE_MODE; + else + ct->ir_dev_mode = NORMAL_MODE; + dev_info(chip->dev, "remote control[ID: 0x%x] switch to %s\n", + ct->tab.custom_code, + ct->ir_dev_mode ? + "mouse mode":"normal mode"); + } + return ct->tab.codemap[index].map.keycode; } + static bool is_valid_custom(struct remote_dev *dev) { struct remote_chip *chip = (struct remote_chip *)dev->platform_data; @@ -371,6 +448,8 @@ static int get_custom_tables(struct device_node *node, goto err; } + memset(&ptable->tab.cursor_code, 0xff, + sizeof(struct cursor_codemap)); ir_scancode_sort(&ptable->tab); /*insert list*/ spin_lock_irqsave(&chip->slock, flags); @@ -540,6 +619,7 @@ static int remote_probe(struct platform_device *pdev) chip->r_dev->dev = &pdev->dev; chip->r_dev->platform_data = (void *)chip; chip->r_dev->getkeycode = getkeycode; + chip->r_dev->ir_report_rel = ir_report_rel; chip->r_dev->set_custom_code = set_custom_code; chip->r_dev->is_valid_custom = is_valid_custom; chip->r_dev->is_next_repeat = is_next_repeat; @@ -689,4 +769,3 @@ module_exit(remote_exit); MODULE_AUTHOR("AMLOGIC"); MODULE_DESCRIPTION("AMLOGIC REMOTE PROTOCOL"); MODULE_LICENSE("GPL"); - diff --git a/drivers/amlogic/input/remote/remote_meson.h b/drivers/amlogic/input/remote/remote_meson.h index 6ccbc8811ed1..02534007ae6e 100644 --- a/drivers/amlogic/input/remote/remote_meson.h +++ b/drivers/amlogic/input/remote/remote_meson.h @@ -18,7 +18,7 @@ #ifndef _REMOTE_MESON_H #define _REMOTE_MESON_H #include -#include +#include "rc_common.h" #include "remote_core.h" #define DRIVER_NAME "meson-remote" @@ -26,12 +26,19 @@ #define IR_DATA_IS_VALID(data) (data & 0x8) #define IR_CONTROLLER_BUSY(x) ((x >> 7) & 0x1) +#define CURSOR_MOVE_ACCELERATE {0, 2, 2, 4, 4, 6, 8, 10, 12, 14, 16, 18} + enum IR_CONTR_NUMBER { MULTI_IR_ID = 0, LEGACY_IR_ID, IR_ID_MAX }; +enum IR_WORK_MODE { + NORMAL_MODE = 0, + MOUSE_MODE = 1 +}; + struct remote_range { struct range active; struct range idle; @@ -47,7 +54,15 @@ struct remote_reg_map { unsigned int val; }; +/* + *struct ir_map_tab_list + * + *@ir_dev_mode: 0: normal mode; 1: mouse mode + *@list: + *@tab: + */ struct ir_map_tab_list { + bool ir_dev_mode; struct list_head list; struct ir_map_tab tab; }; @@ -185,6 +200,3 @@ struct ir_map_tab_list *seek_map_tab(struct remote_chip *chip, int custom_code); void ir_tab_free(struct ir_map_tab_list *ir_map_list); #endif - - - diff --git a/drivers/amlogic/input/remote/sysfs.c b/drivers/amlogic/input/remote/sysfs.c index 86cf48b7831b..9fbbdb66e0a5 100644 --- a/drivers/amlogic/input/remote/sysfs.c +++ b/drivers/amlogic/input/remote/sysfs.c @@ -106,6 +106,18 @@ static ssize_t keymap_show(struct device *dev, len += sprintf(buf+len, "release_delay=%d\n", map_tab->tab.release_delay); len += sprintf(buf+len, "map_size=%d\n", map_tab->tab.map_size); + len += sprintf(buf+len, "fn_key_scancode = 0x%x\n", + map_tab->tab.cursor_code.fn_key_scancode); + len += sprintf(buf+len, "cursor_left_scancode = 0x%x\n", + map_tab->tab.cursor_code.cursor_left_scancode); + len += sprintf(buf+len, "cursor_right_scancode = 0x%x\n", + map_tab->tab.cursor_code.cursor_right_scancode); + len += sprintf(buf+len, "cursor_up_scancode = 0x%x\n", + map_tab->tab.cursor_code.cursor_up_scancode); + len += sprintf(buf+len, "cursor_down_scancode = 0x%x\n", + map_tab->tab.cursor_code.cursor_down_scancode); + len += sprintf(buf+len, "cursor_ok_scancode = 0x%x\n", + map_tab->tab.cursor_code.cursor_ok_scancode); len += sprintf(buf+len, "keycode scancode\n"); for (i = 0; i < map_tab->tab.map_size; i++) { len += sprintf(buf+len, "%4d %4d\n", @@ -283,6 +295,3 @@ void ir_sys_device_attribute_sys(struct remote_chip *chip) device_destroy(&remote_class, chip->chr_devno); } EXPORT_SYMBOL_GPL(ir_sys_device_attribute_sys); - - -