static irqreturn_t mxskbd_irq_handler(int irq, void *dev_id) { struct platform_device *pdev = dev_id; struct mxskbd_data *devdata = platform_get_drvdata(pdev); u16 raw_button, normalized_button, vddio; unsigned btn; if (devdata->btn_irq == irq) { __raw_writel(devdata->btn_irq_stat, devdata->base + HW_LRADC_CTRL1_CLR); __raw_writel(BM_LRADC_CTRL1_LRADC0_IRQ << devdata->chan, devdata->base + HW_LRADC_CTRL1_CLR); __raw_writel(BM_LRADC_CTRL1_LRADC0_IRQ_EN << devdata->chan, devdata->base + HW_LRADC_CTRL1_SET); return IRQ_HANDLED; } raw_button = __raw_readl(devdata->base + HW_LRADC_CHn(devdata->chan)) & BM_LRADC_CHn_VALUE; vddio = hw_lradc_vddio(); BUG_ON(vddio == 0); normalized_button = (raw_button * TARGET_VDDIO_LRADC_VALUE) / vddio; if (normalized_button < BUTTON_PRESS_THRESHOLD && devdata->last_button < 0) { btn = mxskbd_decode_button(devdata->keycodes, normalized_button); if (btn < KEY_MAX) { devdata->last_button = btn; input_report_key(GET_INPUT_DEV(devdata), devdata->last_button, !0); } else dev_err(&pdev->dev, "Invalid button: raw = %d, " "normalized = %d, vddio = %d\n", raw_button, normalized_button, vddio); } else if (devdata->last_button > 0 && normalized_button >= BUTTON_PRESS_THRESHOLD) { input_report_key(GET_INPUT_DEV(devdata), devdata->last_button, 0); devdata->last_button = -1; if (devdata->btn_irq > 0) __raw_writel(BM_LRADC_CTRL1_LRADC0_IRQ_EN << devdata->chan, devdata->base + HW_LRADC_CTRL1_CLR); } __raw_writel(BM_LRADC_CTRL1_LRADC0_IRQ << devdata->chan, devdata->base + HW_LRADC_CTRL1_CLR); return IRQ_HANDLED; }
static int __devexit mxskbd_remove(struct platform_device *pdev) { int i; struct mxskbd_data *d = platform_get_drvdata(pdev); #ifdef CONFIG_HAS_WAKELOCK wake_lock_destroy(&key_wake_lock); #endif for (i = 0; i < MAX_CH; i++) hw_lradc_unuse_channel(d->chan[i]); input_unregister_device(GET_INPUT_DEV(d)); if (d->btn_irq1 > 0) free_irq(d->btn_irq1, pdev); mxskbd_data_free(d); platform_set_drvdata(pdev, NULL); #ifdef ENABLE_BACKLIGHT_GPIO_CONTROL _keypad_set_backlight(0); #endif return 0; }
static void jack_process(struct mxskbd_data *d) { int pin; int in; int jack; static int amp_on_cnt; static int amp; pin = !!mxs_audio_jack_gpio_get(); if (pin) amp_on_cnt = 10; else if (amp_on_cnt > 0) amp_on_cnt--; if (amp_on_cnt > 0) { if (!amp) { mxs_audio_headset_mic_detect_amp_gpio_set(1); amp = 1; } } else { if (amp) { mxs_audio_headset_mic_detect_amp_gpio_set(0); amp = 0; } } if (!!d->jack_last == pin) { d->jack_cnt = 0; return; } if (++d->jack_cnt <= 6) return; if (pin == 0) { /* eject */ in = 0; jack = d->jack_last; d->jack_last = 0; } else { /* insert */ int i = __raw_readl(d->base + HW_LRADC_CHn(d->chan[MAX_CH-1])) & BM_LRADC_CHn_VALUE; d->jack_last = (i > MIC_DET_THRESHOLD) ? SW_MICROPHONE_INSERT : SW_HEADPHONE_INSERT; in = 1; jack = d->jack_last; } input_report_switch(GET_INPUT_DEV(d), jack, in); }
static int __devexit mxskbd_remove(struct platform_device *pdev) { struct mxskbd_data *d = platform_get_drvdata(pdev); hw_lradc_unuse_channel(d->chan); input_unregister_device(GET_INPUT_DEV(d)); free_irq(d->irq, pdev); if (d->btn_irq > 0) free_irq(d->btn_irq, pdev); mxskbd_data_free(d); platform_set_drvdata(pdev, NULL); return 0; }
static int __devinit mxskbd_probe(struct platform_device *pdev) { int err = 0; struct resource *res; struct mxskbd_data *d; struct mxs_kbd_plat_data *plat_data; plat_data = (struct mxs_kbd_plat_data *)pdev->dev.platform_data; if (plat_data == NULL) return -ENODEV; /* Create and register the input driver. */ d = mxskbd_data_alloc(pdev, plat_data->keypair); if (!d) { dev_err(&pdev->dev, "Cannot allocate driver structures\n"); err = -ENOMEM; goto err_out; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { err = -ENODEV; goto err_out; } d->base = (unsigned int)IO_ADDRESS(res->start); d->chan = plat_data->channel; d->irq = platform_get_irq(pdev, 0); d->btn_irq = platform_get_irq(pdev, 1); d->btn_enable = plat_data->btn_enable; d->btn_irq_stat = plat_data->btn_irq_stat; d->btn_irq_ctrl = plat_data->btn_irq_ctrl; platform_set_drvdata(pdev, d); err = request_irq(d->irq, mxskbd_irq_handler, IRQF_DISABLED, pdev->name, pdev); if (err) { dev_err(&pdev->dev, "Cannot request keypad IRQ\n"); goto err_free_dev; } if (d->btn_irq > 0) { err = request_irq(d->btn_irq, mxskbd_irq_handler, IRQF_DISABLED, pdev->name, pdev); if (err) { dev_err(&pdev->dev, "Cannot request keybad detect IRQ\n"); goto err_free_irq; } } /* Register the input device */ err = input_register_device(GET_INPUT_DEV(d)); if (err) goto err_free_irq2; /* these two have to be set after registering the input device */ d->input->rep[REP_DELAY] = delay1; d->input->rep[REP_PERIOD] = delay2; hw_lradc_use_channel(d->chan); mxskbd_hwinit(pdev); return 0; err_free_irq2: platform_set_drvdata(pdev, NULL); if (d->btn_irq > 0) free_irq(d->btn_irq, pdev); err_free_irq: free_irq(d->irq, pdev); err_free_dev: mxskbd_data_free(d); err_out: return err; }
static int __devinit mxskbd_probe(struct platform_device *pdev) { int i; int err = 0; struct resource *res; struct mxskbd_data *d; struct mxs_kbd_plat_data *plat_data; plat_data = (struct mxs_kbd_plat_data *)pdev->dev.platform_data; if (plat_data == NULL) return -ENODEV; #ifdef CONFIG_HAS_WAKELOCK wake_lock_init(&key_wake_lock, WAKE_LOCK_SUSPEND, "mxs-keypad"); #endif /* Create and register the input driver. */ d = mxskbd_data_alloc(pdev, plat_data->keypair, plat_data->keypair_offset); if (!d) { dev_err(&pdev->dev, "Cannot allocate driver structures\n"); err = -ENOMEM; goto err_out; } _devdata = d; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { err = -ENODEV; goto err_out; } d->base = (unsigned int)IO_ADDRESS(res->start); for (i = 0; i < MAX_CH; i++) d->chan[i] = plat_data->channel[i]; d->btn_irq1 = platform_get_irq(pdev, 0); platform_set_drvdata(pdev, d); if (d->btn_irq1 > 0) { err = request_irq(d->btn_irq1, mxskbd_irq_handler, IRQF_DISABLED, pdev->name, pdev); if (err) { dev_err(&pdev->dev, "Cannot request keypad IRQ\n"); goto err_free_dev; } } /* Register the input device */ err = input_register_device(GET_INPUT_DEV(d)); if (err) goto err_free_dev; /* these two have to be set after registering the input device */ d->input->rep[REP_DELAY] = delay1; d->input->rep[REP_PERIOD] = delay2; for (i = 0; i < MAX_CH; i++) hw_lradc_use_channel(d->chan[i]); mxskbd_hwinit(pdev); #ifdef ENABLE_BACKLIGHT_GPIO_CONTROL init_timer(&_bl_timer); _bl_timer.function = _keypad_bl_timer_handler; #endif return 0; err_free_dev: if (d->btn_irq1 > 0) free_irq(d->btn_irq1, pdev); mxskbd_data_free(d); err_out: #ifdef CONFIG_HAS_WAKELOCK wake_lock_destroy(&key_wake_lock); #endif return err; }
static irqreturn_t mxskbd_irq_handler(int irq, void *dev_id) { struct platform_device *pdev = dev_id; struct mxskbd_data *d = platform_get_drvdata(pdev); int i, key, f_key = -1; u32 vddio; jack_process(d); /* end key process */ i = (__raw_readl(REGS_POWER_BASE + HW_POWER_STS) & BF_POWER_STS_PSWITCH(0x1)) ? KEY_END : -1; if (i == KEY_END) { if (i == d->last_button) goto _end; f_key = i; } if (f_key < 0 && d->jack_cnt == 0 && d->jack_last == SW_MICROPHONE_INSERT) { i = __raw_readl(d->base + HW_LRADC_CHn(d->chan[MAX_CH-1])) & BM_LRADC_CHn_VALUE; if (i <= MIC_DET_THRESHOLD) { if (d->last_button == KEY_KPENTER) { d->jack_push_cnt = 0; goto _end; } if (++d->jack_push_cnt > 4) f_key = KEY_KPENTER; } else d->jack_push_cnt = 0; } else d->jack_push_cnt = 0; /* adc key process */ vddio = __raw_readl(d->base + HW_LRADC_CHn(VDDIO_VOLTAGE_CH)) & BM_LRADC_CHn_VALUE; BUG_ON(vddio == 0); #ifdef DUMP_KEY_ADC static int val[MAX_CH]; printk("KEY=0x%03x(%4d), 0x%03x(%4d), 0x%03x(%4d), 0x%03x(%4d)\n", val[0], val[0], val[1], val[1], val[2], val[2], val[3], val[3]); #endif for (i = 0; i < MAX_CH-1; i++) { int raw, norm; raw = __raw_readl(d->base + HW_LRADC_CHn(d->chan[i])) & BM_LRADC_CHn_VALUE; norm = (raw * TARGET_VDDIO_LRADC_VALUE) / vddio; key = mxskbd_decode_button(d->keycodes + d->keycodes_offset*i, norm); key = unjitter_key(i, key); #ifdef DUMP_KEY_ADC val[i] = raw; #endif if (key >= 0) { if (key == d->last_button) goto _end; if (f_key < 0) f_key = key; } } key = volume_key_process(d); if (key > 0) { if (key == d->last_button) goto _end; if (f_key < 0) f_key = key; } if (d->last_button >= 0) { input_report_key(GET_INPUT_DEV(d), d->last_button, 0); d->last_button = -1; } if (f_key >= 0 && f_key != d->last_button) { input_report_key(GET_INPUT_DEV(d), f_key, !0); #ifdef ENABLE_BACKLIGHT_GPIO_CONTROL _keypad_set_backlight(1); #endif #ifdef CONFIG_HAS_WAKELOCK wake_lock_timeout(&key_wake_lock, 5*HZ); #endif d->last_button = f_key; } _end: __raw_writel((BM_LRADC_CTRL1_LRADC0_IRQ << d->chan[0]) + (BM_LRADC_CTRL1_LRADC0_IRQ << d->chan[1]) + (BM_LRADC_CTRL1_LRADC0_IRQ << d->chan[2]) + (BM_LRADC_CTRL1_LRADC0_IRQ << d->chan[3]) + (BM_LRADC_CTRL1_LRADC0_IRQ << VDDIO_VOLTAGE_CH), d->base + HW_LRADC_CTRL1_CLR); return IRQ_HANDLED; }