Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

input: Monitor both onkey up and down event

Remove original 3-second ONKEY event. Detect ONKEY changing event directly.
So both UP and DOWN event of ONKEY in max8925 are monitered.

Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>

authored by

Haojian Zhuang and committed by
Samuel Ortiz
2d95ae3b f5d59fc5

+61 -20
+53 -17
drivers/input/misc/max8925_onkey.c
··· 27 27 #include <linux/mfd/max8925.h> 28 28 #include <linux/slab.h> 29 29 30 + #define SW_INPUT (1 << 7) /* 0/1 -- up/down */ 30 31 #define HARDRESET_EN (1 << 7) 31 32 #define PWREN_EN (1 << 7) 32 33 33 34 struct max8925_onkey_info { 34 35 struct input_dev *idev; 35 36 struct i2c_client *i2c; 36 - int irq; 37 + struct device *dev; 38 + int irq[2]; 37 39 }; 38 40 39 41 /* 40 - * MAX8925 gives us an interrupt when ONKEY is held for 3 seconds. 42 + * MAX8925 gives us an interrupt when ONKEY is pressed or released. 41 43 * max8925_set_bits() operates I2C bus and may sleep. So implement 42 44 * it in thread IRQ handler. 43 45 */ 44 46 static irqreturn_t max8925_onkey_handler(int irq, void *data) 45 47 { 46 48 struct max8925_onkey_info *info = data; 49 + int ret, event; 47 50 48 - input_report_key(info->idev, KEY_POWER, 1); 51 + ret = max8925_reg_read(info->i2c, MAX8925_ON_OFF_STATUS); 52 + if (ret & SW_INPUT) 53 + event = 1; 54 + else 55 + event = 0; 56 + input_report_key(info->idev, KEY_POWER, event); 49 57 input_sync(info->idev); 58 + 59 + dev_dbg(info->dev, "onkey event:%d\n", event); 50 60 51 61 /* Enable hardreset to halt if system isn't shutdown on time */ 52 62 max8925_set_bits(info->i2c, MAX8925_SYSENSEL, ··· 69 59 { 70 60 struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); 71 61 struct max8925_onkey_info *info; 72 - int error; 62 + int irq[2], error; 63 + 64 + irq[0] = platform_get_irq(pdev, 0); 65 + if (irq[0] < 0) { 66 + dev_err(&pdev->dev, "No IRQ resource!\n"); 67 + return -EINVAL; 68 + } 69 + irq[1] = platform_get_irq(pdev, 1); 70 + if (irq[1] < 0) { 71 + dev_err(&pdev->dev, "No IRQ resource!\n"); 72 + return -EINVAL; 73 + } 73 74 74 75 info = kzalloc(sizeof(struct max8925_onkey_info), GFP_KERNEL); 75 76 if (!info) 76 77 return -ENOMEM; 77 78 78 79 info->i2c = chip->i2c; 79 - info->irq = chip->irq_base + MAX8925_IRQ_GPM_SW_3SEC; 80 + info->dev = &pdev->dev; 81 + irq[0] += chip->irq_base; 82 + irq[1] += chip->irq_base; 83 + 84 + error = request_threaded_irq(irq[0], NULL, max8925_onkey_handler, 85 + IRQF_ONESHOT, "onkey-down", info); 86 + if (error < 0) { 87 + dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n", 88 + irq[0], error); 89 + goto out; 90 + } 91 + error = request_threaded_irq(irq[1], NULL, max8925_onkey_handler, 92 + IRQF_ONESHOT, "onkey-up", info); 93 + if (error < 0) { 94 + dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n", 95 + irq[1], error); 96 + goto out_irq; 97 + } 80 98 81 99 info->idev = input_allocate_device(); 82 100 if (!info->idev) { ··· 117 79 info->idev->phys = "max8925_on/input0"; 118 80 info->idev->id.bustype = BUS_I2C; 119 81 info->idev->dev.parent = &pdev->dev; 82 + info->irq[0] = irq[0]; 83 + info->irq[1] = irq[1]; 120 84 info->idev->evbit[0] = BIT_MASK(EV_KEY); 121 85 info->idev->keybit[BIT_WORD(KEY_POWER)] = BIT_MASK(KEY_POWER); 122 86 123 - error = request_threaded_irq(info->irq, NULL, max8925_onkey_handler, 124 - IRQF_ONESHOT, "onkey", info); 125 - if (error < 0) { 126 - dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n", 127 - info->irq, error); 128 - goto out_irq; 129 - } 130 87 131 88 error = input_register_device(info->idev); 132 89 if (error) { 133 90 dev_err(chip->dev, "Can't register input device: %d\n", error); 134 - goto out; 91 + goto out_reg; 135 92 } 136 93 137 94 platform_set_drvdata(pdev, info); 138 95 139 96 return 0; 140 97 141 - out: 142 - free_irq(info->irq, info); 143 - out_irq: 98 + out_reg: 144 99 input_free_device(info->idev); 145 100 out_input: 101 + free_irq(info->irq[1], info); 102 + out_irq: 103 + free_irq(info->irq[0], info); 104 + out: 146 105 kfree(info); 147 106 return error; 148 107 } ··· 148 113 { 149 114 struct max8925_onkey_info *info = platform_get_drvdata(pdev); 150 115 151 - free_irq(info->irq, info); 116 + free_irq(info->irq[0], info); 117 + free_irq(info->irq[1], info); 152 118 input_unregister_device(info->idev); 153 119 kfree(info); 154 120
+8 -3
drivers/mfd/max8925-core.c
··· 93 93 static struct resource onkey_resources[] = { 94 94 { 95 95 .name = "max8925-onkey", 96 - .start = MAX8925_IRQ_GPM_SW_3SEC, 97 - .end = MAX8925_IRQ_GPM_SW_3SEC, 96 + .start = MAX8925_IRQ_GPM_SW_R, 97 + .end = MAX8925_IRQ_GPM_SW_R, 98 + .flags = IORESOURCE_IRQ, 99 + }, { 100 + .name = "max8925-onkey", 101 + .start = MAX8925_IRQ_GPM_SW_F, 102 + .end = MAX8925_IRQ_GPM_SW_F, 98 103 .flags = IORESOURCE_IRQ, 99 104 }, 100 105 }; ··· 107 102 static struct mfd_cell onkey_devs[] = { 108 103 { 109 104 .name = "max8925-onkey", 110 - .num_resources = 1, 105 + .num_resources = 2, 111 106 .resources = &onkey_resources[0], 112 107 .id = -1, 113 108 },