static irqreturn_t fbx_kybd_irqhandler(int irq, void *dev_id) { struct fbx_kybd_record *kbdrec = (struct fbx_kybd_record *) dev_id; if (kbdrec->kybd_connected) { if (PM8058_GPIO_IRQ(PMIC8058_IRQ_BASE, kbdrec->pmic_gpio_vol_up) == irq) schedule_work(&kbdrec->qkybd_volup); else if (PM8058_GPIO_IRQ(PMIC8058_IRQ_BASE, kbdrec->pmic_gpio_vol_dn) == irq) schedule_work(&kbdrec->qkybd_voldn); /* Div1-FW3-BSP-AUDIO */ else if (MSM_GPIO_TO_INT(kbdrec->hook_sw_pin) == irq){ queue_work(headset_hook_wq, &kbdrec->hook_switchkey); set_irq_type(MSM_GPIO_TO_INT(rd->hook_sw_pin), gpio_get_value_cansleep(rd->hook_sw_pin) ? IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH); } else if (rd->product_phase == Product_PR1 || rd->product_phase == Product_EVB) { if (PM8058_GPIO_IRQ(PMIC8058_IRQ_BASE, kbdrec->pmic_gpio_cam_f) == irq) schedule_work(&kbdrec->qkybd_camf); else if (PM8058_GPIO_IRQ(PMIC8058_IRQ_BASE, kbdrec->pmic_gpio_cam_t) == irq) schedule_work(&kbdrec->qkybd_camt); } } return IRQ_HANDLED; }
static int fbx_kybd_irqsetup(void) { int rc; rc = request_irq(PM8058_GPIO_IRQ(PMIC8058_IRQ_BASE, rd->pmic_gpio_vol_up), &fbx_kybd_irqhandler, (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING), fbx_kybd_name, rd); if (rc < 0) { dev_err(rd->fbx_kybd_pdev, "Could not register for %s interrupt %d" "(rc = %d)\n", fbx_kybd_name, rd->pmic_gpio_vol_up, rc); rc = -EIO; } rc = request_irq(PM8058_GPIO_IRQ(PMIC8058_IRQ_BASE, rd->pmic_gpio_vol_dn), &fbx_kybd_irqhandler, (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING), fbx_kybd_name, rd); if (rc < 0) { dev_err(rd->fbx_kybd_pdev, "Could not register for %s interrupt %d" "(rc = %d)\n", fbx_kybd_name, rd->pmic_gpio_vol_dn, rc); rc = -EIO; } if (rd->product_phase == Product_PR1 || rd->product_phase == Product_EVB) { rc = request_irq(PM8058_GPIO_IRQ(PMIC8058_IRQ_BASE, rd->pmic_gpio_cam_f), &fbx_kybd_irqhandler, (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING), fbx_kybd_name, rd); if (rc < 0) { dev_err(rd->fbx_kybd_pdev, "Could not register for %s interrupt %d" "(rc = %d)\n", fbx_kybd_name, rd->pmic_gpio_cam_f, rc); rc = -EIO; } rc = request_irq(PM8058_GPIO_IRQ(PMIC8058_IRQ_BASE, rd->pmic_gpio_cam_t), &fbx_kybd_irqhandler, (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING), fbx_kybd_name, rd); if (rc < 0) { dev_err(rd->fbx_kybd_pdev, "Could not register for %s interrupt %d" "(rc = %d)\n", fbx_kybd_name, rd->pmic_gpio_cam_t, rc); rc = -EIO; } } return rc; }
static int akm8975_setup_irq(struct akm8975_data *akm) { int rc = -EIO; struct akm8975_platform_data *pdata = akm->pdata; int irq; #if 0 rc = gpio_request(pdata->gpio_data_ready_int, "gpio_akm_int"); if (rc < 0) { pr_err("%s: gpio %d request failed (%d)\n", __func__, pdata->gpio_data_ready_int, rc); return rc; } rc = gpio_direction_input(pdata->gpio_data_ready_int); if (rc < 0) { pr_err("%s: failed to set gpio %d as input (%d)\n", __func__, pdata->gpio_data_ready_int, rc); goto err_gpio_direction_input; } irq = gpio_to_irq(pdata->gpio_data_ready_int); #else irq = PM8058_GPIO_IRQ(PMIC8058_IRQ_BASE, pdata->gpio_data_ready_int); #endif /* trigger high so we don't miss initial interrupt if it * is already pending */ rc = request_threaded_irq(irq, NULL, akm8975_irq_handler, IRQF_TRIGGER_RISING, "akm_int", akm); if (rc < 0) { pr_err("%s: request_irq(%d) failed for gpio %d (%d)\n", __func__, irq, pdata->gpio_data_ready_int, rc); goto err_request_irq; } /* start with interrupt disabled until the driver is enabled */ akm->irq = irq; akm8975_disable_irq(akm); goto done; err_request_irq: //err_gpio_direction_input: // gpio_free(pdata->gpio_data_ready_int); done: return rc; }
static irqreturn_t pmic8058_silent_key_handler(int irq, void *data) { struct pmic8058_kp *kp = data; bool gpio_val; printk(KERN_INFO "[KEYPAD] Silent Key Up IRQ ~"); if(PM8058_GPIO_IRQ(PMIC8058_IRQ_BASE, SILENT_KEY_UP_GPIO) == irq) { gpio_val = (bool)gpio_get_value(PM8058_GPIO_PM_TO_SYS(SILENT_KEY_UP_GPIO)); set_irq_type(irq, gpio_val ? IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH); if(gpio_val) { if(!silent_key_down) { //printk(KERN_INFO "[KEYPAD] SilentKeyUp GPIO HIGH\n"); printk(KERN_INFO "[KEYPAD] Silent Key Down \n"); input_report_key(kp->input, KEY_SILENT, 1); silent_key_down = true; silent_on =1; } } else { if(silent_key_down) { //printk(KERN_INFO "[KEYPAD] SilentKeyUp GPIO LOW\n"); printk(KERN_INFO "[KEYPAD] Silent Key Up \n"); input_report_key(kp->input, KEY_SILENT, 0); silent_key_down = false; silent_on =0; } } } input_sync(kp->input); return IRQ_HANDLED; }
#ifdef CONFIG_FUJI_PMIC_KEYPAD #define GPIO_KEYPAD_VOLUME_UP_KEY 26 static struct pm8058_gpio pm_gpio_config = { .direction = PM_GPIO_DIR_IN, .pull = PM_GPIO_PULL_NO, .vin_sel = PM_GPIO_VIN_S3, .out_strength = PM_GPIO_STRENGTH_NO, .function = PM_GPIO_FUNC_NORMAL, .inv_int_pol = 1, }; static struct keypad_pmic_fuji_key keymap_pmic[] = { { .code = KEY_VOLUMEUP, .irq = PM8058_GPIO_IRQ(PM8058_IRQ_BASE, GPIO_KEYPAD_VOLUME_UP_KEY - 1), .gpio = GPIO_KEYPAD_VOLUME_UP_KEY, .wake = 1, .debounce_time.tv.nsec = 10 * NSEC_PER_MSEC, }, }; struct keypad_pmic_fuji_platform_data keypad_pmic_platform_data = { .keymap = keymap_pmic, .keymap_size = ARRAY_SIZE(keymap_pmic), .input_name = "keypad-pmic-fuji", .pm_gpio_config = &pm_gpio_config, }; #endif /* CONFIG_FUJI_PMIC_KEYPAD */ #ifdef CONFIG_FUJI_GPIO_KEYPAD
static int pm8058_kp_config_drv(int gpio_start, int num_gpios) { int rc; struct pm8058_gpio kypd_drv = { .direction = PM_GPIO_DIR_OUT, .output_buffer = PM_GPIO_OUT_BUF_OPEN_DRAIN, .output_value = 0, .pull = PM_GPIO_PULL_NO, .vin_sel = 2, .out_strength = PM_GPIO_STRENGTH_LOW, .function = PM_GPIO_FUNC_1, .inv_int_pol = 1, }; if (gpio_start < 0 || num_gpios < 0 || num_gpios > PM8058_GPIOS) return -EINVAL; while (num_gpios--) { rc = pm8058_gpio_config(gpio_start++, &kypd_drv); if (rc) { pr_err("%s: FAIL pm8058_gpio_config(): rc=%d.\n", __func__, rc); return rc; } } return 0; } static int pm8058_kp_config_sns(int gpio_start, int num_gpios) { int rc; struct pm8058_gpio kypd_sns = { .direction = PM_GPIO_DIR_IN, .pull = PM_GPIO_PULL_UP_31P5, .vin_sel = 2, .out_strength = PM_GPIO_STRENGTH_NO, .function = PM_GPIO_FUNC_NORMAL, .inv_int_pol = 1, }; if (gpio_start < 0 || num_gpios < 0 || num_gpios > PM8058_GPIOS) return -EINVAL; while (num_gpios--) { rc = pm8058_gpio_config(gpio_start++, &kypd_sns); if (rc) { pr_err("%s: FAIL pm8058_gpio_config(): rc=%d.\n", __func__, rc); return rc; } } return 0; } /* * keypad controller should be initialized in the following sequence * only, otherwise it might get into FSM stuck state. * * - Initialize keypad control parameters, like no. of rows, columns, * timing values etc., * - configure rows and column gpios pull up/down. * - set irq edge type. * - enable the keypad controller. */ static int __devinit pmic8058_kp_probe(struct platform_device *pdev) { struct pmic8058_keypad_data *pdata = pdev->dev.platform_data; const struct matrix_keymap_data *keymap_data; struct pmic8058_kp *kp; int rc; unsigned short *keycodes; u8 ctrl_val; struct pm8058_chip *pm_chip; #ifdef CONFIG_FIH_PROJECT_SF4V5 bool gpio_val; #endif pm_chip = platform_get_drvdata(pdev); if (pm_chip == NULL) { dev_err(&pdev->dev, "no parent data passed in\n"); return -EFAULT; } if (!pdata || !pdata->num_cols || !pdata->num_rows || pdata->num_cols > PM8058_MAX_COLS || pdata->num_rows > PM8058_MAX_ROWS || pdata->num_cols < PM8058_MIN_COLS || pdata->num_rows < PM8058_MIN_ROWS) { dev_err(&pdev->dev, "invalid platform data\n"); return -EINVAL; } if (pdata->rows_gpio_start < 0 || pdata->cols_gpio_start < 0) { dev_err(&pdev->dev, "invalid gpio_start platform data\n"); return -EINVAL; } if (!pdata->scan_delay_ms || pdata->scan_delay_ms > MAX_SCAN_DELAY || pdata->scan_delay_ms < MIN_SCAN_DELAY || !is_power_of_2(pdata->scan_delay_ms)) { dev_err(&pdev->dev, "invalid keypad scan time supplied\n"); return -EINVAL; } if (!pdata->row_hold_ns || pdata->row_hold_ns > MAX_ROW_HOLD_DELAY || pdata->row_hold_ns < MIN_ROW_HOLD_DELAY || ((pdata->row_hold_ns % MIN_ROW_HOLD_DELAY) != 0)) { dev_err(&pdev->dev, "invalid keypad row hold time supplied\n"); return -EINVAL; } if (pm8058_rev(pm_chip) == PM_8058_REV_1p0) { if (!pdata->debounce_ms || !is_power_of_2(pdata->debounce_ms[0]) || pdata->debounce_ms[0] > MAX_DEBOUNCE_A0_TIME || pdata->debounce_ms[0] < MIN_DEBOUNCE_A0_TIME) { dev_err(&pdev->dev, "invalid debounce time supplied\n"); return -EINVAL; } } else { if (!pdata->debounce_ms || ((pdata->debounce_ms[1] % 5) != 0) || pdata->debounce_ms[1] > MAX_DEBOUNCE_B0_TIME || pdata->debounce_ms[1] < MIN_DEBOUNCE_B0_TIME) { dev_err(&pdev->dev, "invalid debounce time supplied\n"); return -EINVAL; } } keymap_data = pdata->keymap_data; if (!keymap_data) { dev_err(&pdev->dev, "no keymap data supplied\n"); return -EINVAL; } kp = kzalloc(sizeof(*kp), GFP_KERNEL); if (!kp) return -ENOMEM; keycodes = kzalloc(PM8058_MATRIX_MAX_SIZE * sizeof(*keycodes), GFP_KERNEL); if (!keycodes) { rc = -ENOMEM; goto err_alloc_mem; } platform_set_drvdata(pdev, kp); mutex_init(&kp->mutex); kp->pdata = pdata; kp->dev = &pdev->dev; kp->keycodes = keycodes; kp->pm_chip = pm_chip; if (pm8058_rev(pm_chip) == PM_8058_REV_1p0) kp->flags |= KEYF_FIX_LAST_ROW; kp->input = input_allocate_device(); if (!kp->input) { dev_err(&pdev->dev, "unable to allocate input device\n"); rc = -ENOMEM; goto err_alloc_device; } /* Enable runtime PM ops, start in ACTIVE mode */ rc = pm_runtime_set_active(&pdev->dev); if (rc < 0) dev_dbg(&pdev->dev, "unable to set runtime pm state\n"); pm_runtime_enable(&pdev->dev); kp->key_sense_irq = platform_get_irq(pdev, 0); if (kp->key_sense_irq < 0) { dev_err(&pdev->dev, "unable to get keypad sense irq\n"); rc = -ENXIO; goto err_get_irq; } kp->key_stuck_irq = platform_get_irq(pdev, 1); if (kp->key_stuck_irq < 0) { dev_err(&pdev->dev, "unable to get keypad stuck irq\n"); rc = -ENXIO; goto err_get_irq; } if (pdata->input_name) kp->input->name = pdata->input_name; else kp->input->name = "PMIC8058 keypad"; if (pdata->input_phys_device) kp->input->phys = pdata->input_phys_device; else kp->input->phys = "pmic8058_keypad/input0"; kp->input->dev.parent = &pdev->dev; kp->input->id.bustype = BUS_HOST; kp->input->id.version = 0x0001; kp->input->id.product = 0x0001; kp->input->id.vendor = 0x0001; kp->input->evbit[0] = BIT_MASK(EV_KEY); if (pdata->rep) __set_bit(EV_REP, kp->input->evbit); kp->input->keycode = keycodes; kp->input->keycodemax = PM8058_MATRIX_MAX_SIZE; kp->input->keycodesize = sizeof(*keycodes); matrix_keypad_build_keymap(keymap_data, PM8058_ROW_SHIFT, kp->input->keycode, kp->input->keybit); input_set_capability(kp->input, EV_MSC, MSC_SCAN); input_set_drvdata(kp->input, kp); rc = input_register_device(kp->input); if (rc < 0) { dev_err(&pdev->dev, "unable to register keypad input device\n"); goto err_get_irq; } /* initialize keypad state */ memset(kp->keystate, 0xff, sizeof(kp->keystate)); memset(kp->stuckstate, 0xff, sizeof(kp->stuckstate)); rc = pmic8058_kpd_init(kp); if (rc < 0) { dev_err(&pdev->dev, "unable to initialize keypad controller\n"); goto err_kpd_init; } rc = pm8058_kp_config_sns(pdata->cols_gpio_start, pdata->num_cols); if (rc < 0) { dev_err(&pdev->dev, "unable to configure keypad sense lines\n"); goto err_gpio_config; } rc = pm8058_kp_config_drv(pdata->rows_gpio_start, pdata->num_rows); if (rc < 0) { dev_err(&pdev->dev, "unable to configure keypad drive lines\n"); goto err_gpio_config; } #ifdef CONFIG_FIH_PROJECT_SF4V5 rc = request_threaded_irq(kp->key_sense_irq, NULL, pmic8058_kp_irq, IRQF_TRIGGER_RISING, SF4V5_PMICKPD_NAME, kp); #else rc = request_threaded_irq(kp->key_sense_irq, NULL, pmic8058_kp_irq, IRQF_TRIGGER_RISING, "pmic-keypad", kp); #endif if (rc < 0) { dev_err(&pdev->dev, "failed to request keypad sense irq\n"); goto err_req_sense_irq; } #ifdef CONFIG_FIH_PROJECT_SF4V5 rc = request_threaded_irq(kp->key_stuck_irq, NULL, pmic8058_kp_stuck_irq, IRQF_TRIGGER_RISING, SF4V5_PMICKPD_NAME, kp); #else rc = request_threaded_irq(kp->key_stuck_irq, NULL, pmic8058_kp_stuck_irq, IRQF_TRIGGER_RISING, "pmic-keypad-stuck", kp); #endif if (rc < 0) { dev_err(&pdev->dev, "failed to request keypad stuck irq\n"); goto err_req_stuck_irq; } //Div2D5-OwenHung-keypad driver porting+ #ifdef CONFIG_FIH_PROJECT_SF4V5 gpio_keypad_config(kp); gpio_val = (bool)gpio_get_value(PM8058_GPIO_PM_TO_SYS(SILENT_KEY_UP_GPIO)); if(gpio_val) { input_report_key(kp->input, KEY_SILENT, 1); printk(KERN_INFO "[KEYPAD] Initial is Silent Key Down so add to report key.\n"); silent_key_down = true; silent_on =1; } else { input_report_key(kp->input, KEY_SILENT, 0); printk(KERN_INFO "[KEYPAD] Initial is Silent Key Up so add to report key.\n"); silent_key_down = false; silent_on =0; } input_sync(kp->input); rc = request_irq(PM8058_GPIO_IRQ(PMIC8058_IRQ_BASE, SILENT_KEY_UP_GPIO), &pmic8058_silent_key_handler, gpio_val ? IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH, SF4V5_PMICKPD_NAME, kp); if (rc < 0) { dev_err(&pdev->dev, "failed to request Silent Key UP irq\n"); goto err_req_gpio_irq; } #endif //Div2D5-OwenHung-keypad driver porting- rc = pmic8058_kp_read_u8(kp, &ctrl_val, KEYP_CTRL); ctrl_val |= KEYP_CTRL_KEYP_EN; rc = pmic8058_kp_write_u8(kp, ctrl_val, KEYP_CTRL); kp->ctrl_reg = ctrl_val; __dump_kp_regs(kp, "probe"); rc = device_create_file(&pdev->dev, &dev_attr_disable_kp); if (rc < 0) goto err_create_file; //Div2D5-AH-Get phone state for check keypad into suspend+{ #ifdef CONFIG_FIH_PROJECT_SF4V5 rc = device_create_file(&pdev->dev, &dev_attr_phone_state); if (rc < 0) goto err_create_file; #endif //Div2D5-AH-Get phone state for check keypad into suspend+} device_init_wakeup(&pdev->dev, pdata->wakeup); dev_info(&pdev->dev, "%s Complete \n", __func__ ); return 0; err_create_file: free_irq(kp->key_stuck_irq, NULL); err_req_stuck_irq: free_irq(kp->key_sense_irq, NULL); err_req_sense_irq: #ifdef CONFIG_FIH_PROJECT_SF4V5 err_req_gpio_irq: #endif err_gpio_config: err_kpd_init: input_unregister_device(kp->input); kp->input = NULL; err_get_irq: pm_runtime_set_suspended(&pdev->dev); pm_runtime_disable(&pdev->dev); input_free_device(kp->input); err_alloc_device: kfree(keycodes); err_alloc_mem: kfree(kp); return rc; } static int __devexit pmic8058_kp_remove(struct platform_device *pdev) { struct pmic8058_kp *kp = platform_get_drvdata(pdev); pm_runtime_set_suspended(&pdev->dev); pm_runtime_disable(&pdev->dev); device_remove_file(&pdev->dev, &dev_attr_disable_kp); device_init_wakeup(&pdev->dev, 0); free_irq(kp->key_stuck_irq, NULL); free_irq(kp->key_sense_irq, NULL); input_unregister_device(kp->input); platform_set_drvdata(pdev, NULL); kfree(kp->input->keycode); kfree(kp); return 0; } #ifdef CONFIG_PM static int pmic8058_kp_suspend(struct device *dev) { struct pmic8058_kp *kp = dev_get_drvdata(dev); //Div2D5-AH-Get phone state for check keypad into suspend+{ #ifdef CONFIG_FIH_PROJECT_SF4V5 printk(KERN_INFO "[KEYPAD] %s , phone state: %d", __func__, phone_state); if (device_may_wakeup(dev) && !pmic8058_kp_disabled(kp) && phone_state) { enable_irq_wake(kp->key_sense_irq); printk(KERN_INFO "[KEYPAD] pmic8058_kp_suspend enable_irq_wake.\n"); } else { mutex_lock(&kp->mutex); pmic8058_kp_disable(kp); mutex_unlock(&kp->mutex); printk(KERN_INFO "[KEYPAD] pmic8058_kp_suspend pmic8058_kp_disable.\n"); } #else if (device_may_wakeup(dev) && !pmic8058_kp_disabled(kp)) { enable_irq_wake(kp->key_sense_irq); } else { mutex_lock(&kp->mutex); pmic8058_kp_disable(kp); mutex_unlock(&kp->mutex); } #endif //Div2D5-AH-Get phone state for check keypad into suspend+} return 0; } static int pmic8058_kp_resume(struct device *dev) { struct pmic8058_kp *kp = dev_get_drvdata(dev); //Div2D5-AH-Get phone state for check keypad into suspend+{ #ifdef CONFIG_FIH_PROJECT_SF4V5 printk(KERN_INFO "[KEYPAD] %s , phone state: %d", __func__, phone_state); if (device_may_wakeup(dev) && !pmic8058_kp_disabled(kp) && phone_state) { disable_irq_wake(kp->key_sense_irq); printk(KERN_INFO "[KEYPAD] pmic8058_kp_resume disable_irq_wake.\n"); } else { mutex_lock(&kp->mutex); pmic8058_kp_enable(kp); mutex_unlock(&kp->mutex); printk(KERN_INFO "[KEYPAD] pmic8058_kp_resume pmic8058_kp_enable.\n"); } #else if (device_may_wakeup(dev) && !pmic8058_kp_disabled(kp)) { disable_irq_wake(kp->key_sense_irq); } else { mutex_lock(&kp->mutex); pmic8058_kp_enable(kp); mutex_unlock(&kp->mutex); } #endif //Div2D5-AH-Get phone state for check keypad into suspend+} return 0; } static struct dev_pm_ops pm8058_kp_pm_ops = { .suspend = pmic8058_kp_suspend, .resume = pmic8058_kp_resume, }; #endif static struct platform_driver pmic8058_kp_driver = { .probe = pmic8058_kp_probe, .remove = __devexit_p(pmic8058_kp_remove), .driver = { #ifdef CONFIG_FIH_PROJECT_SF4V5 .name = SF4V5_PMICKPD_NAME, #else .name = "pm8058-keypad", #endif .owner = THIS_MODULE, #ifdef CONFIG_PM .pm = &pm8058_kp_pm_ops, #endif }, }; static int __init pmic8058_kp_init(void) { return platform_driver_register(&pmic8058_kp_driver); } module_init(pmic8058_kp_init); static void __exit pmic8058_kp_exit(void) { platform_driver_unregister(&pmic8058_kp_driver); }
* 02110-1301, USA. * */ #include <linux/mfd/pmic8058.h> #include <linux/input.h> #include "keypad-pmic-mogami.h" static struct pm8058_gpio pm_gpio_config = { .direction = PM_GPIO_DIR_IN, .pull = PM_GPIO_PULL_UP_31P5, .vin_sel = PM_GPIO_VIN_S3, .function = PM_GPIO_FUNC_NORMAL, .inv_int_pol = 0, }; static struct keypad_pmic_mogami_key keymap_pmic[] = { { .code = KEY_VENDOR, .irq = PM8058_GPIO_IRQ(PMIC8058_IRQ_BASE, 26 - 1), .gpio = 26, .wake = 1, }, }; struct keypad_pmic_mogami_platform_data keypad_pmic_platform_data = { .keymap = keymap_pmic, .keymap_size = ARRAY_SIZE(keymap_pmic), .input_name = "keypad-pmic-azusa", .pm_gpio_config = &pm_gpio_config, };
static int fbx_kybd_config_gpio(void) { struct pm8058_gpio button_configuration = { .direction = PM_GPIO_DIR_IN, .pull = PM_GPIO_PULL_DN, .vin_sel = 2, .out_strength = PM_GPIO_STRENGTH_NO, .function = PM_GPIO_FUNC_NORMAL, .inv_int_pol = 0, }; int rc = 0; printk(KERN_INFO "%s\n", __func__); rc = pm8058_gpio_config(rd->pmic_gpio_vol_up, &button_configuration); if (rc < 0) { dev_err(rd->fbx_kybd_pdev, "%s: gpio %d configured failed\n", __func__, rd->pmic_gpio_vol_up); return rc; } else { rc = gpio_request(rd->sys_gpio_vol_up, "vol_up_key"); if (rc < 0) { dev_err(rd->fbx_kybd_pdev, "%s: gpio %d requested failed\n", __func__, rd->sys_gpio_vol_up); return rc; } else { rc = gpio_direction_input(rd->sys_gpio_vol_up); if (rc < 0) { dev_err(rd->fbx_kybd_pdev, "%s: set gpio %d direction failed\n", __func__, rd->sys_gpio_vol_up); return rc; } } } rc = pm8058_gpio_config(rd->pmic_gpio_vol_dn, &button_configuration); if (rc < 0) { dev_err(rd->fbx_kybd_pdev, "%s: gpio %d configured failed\n", __func__, rd->pmic_gpio_vol_dn); return rc; } else { rc = gpio_request(rd->sys_gpio_vol_dn, "vol_down_key"); if (rc < 0) { dev_err(rd->fbx_kybd_pdev, "%s: gpio %d requested failed\n", __func__, rd->sys_gpio_vol_dn); return rc; } else { rc = gpio_direction_input(rd->sys_gpio_vol_dn); if (rc < 0) { dev_err(rd->fbx_kybd_pdev, "%s: set gpio %d direction failed\n", __func__, rd->sys_gpio_vol_dn); return rc; } } } if (rd->product_phase == Product_PR1 || rd->product_phase == Product_EVB) { rc = pm8058_gpio_config(rd->pmic_gpio_cam_t, &button_configuration); if (rc < 0) { dev_err(rd->fbx_kybd_pdev, "%s: gpio %d configured failed\n", __func__, rd->pmic_gpio_cam_t); return rc; } else { rc = gpio_request(rd->sys_gpio_cam_t, "camera_key"); if (rc < 0) { dev_err(rd->fbx_kybd_pdev, "%s: gpio %d requested failed\n", __func__, rd->sys_gpio_cam_t); return rc; } else { rc = gpio_direction_input(rd->sys_gpio_cam_t); if (rc < 0) { dev_err(rd->fbx_kybd_pdev, "%s: set gpio %d direction failed\n", __func__, rd->sys_gpio_cam_t); return rc; } } } rc = pm8058_gpio_config(rd->pmic_gpio_cam_f, &button_configuration); if (rc < 0) { dev_err(rd->fbx_kybd_pdev, "%s: gpio %d configured failed\n", __func__, rd->pmic_gpio_cam_f); return rc; } else { rc = gpio_request(rd->sys_gpio_cam_f, "camera_focus_key"); if (rc < 0) { dev_err(rd->fbx_kybd_pdev, "%s: gpio %d requested failed\n", __func__, rd->sys_gpio_cam_f); return rc; } else { rc = gpio_direction_input(rd->sys_gpio_cam_f); if (rc < 0) { dev_err(rd->fbx_kybd_pdev, "%s: set gpio %d direction failed\n", __func__, rd->sys_gpio_cam_f); return rc; } } } } /* Div1-FW3-BSP-AUDIO */ rc = gpio_request(rd->hook_sw_pin, "gpio_hook_sw"); if (rc) { printk("gpio_request failed on pin(rc=%d)\n", rc); return rc; } rc = gpio_direction_input(rd->hook_sw_pin); if (rc) { printk("gpio_direction_input failed on pin rc=%d\n", rc); return rc; } return rc; } static void fbx_kybd_volup(struct work_struct *work) { struct fbx_kybd_record *kbdrec = container_of(work, struct fbx_kybd_record, qkybd_volup); struct input_dev *idev = kbdrec->fbx_kybd_idev; bool gpio_val = (bool)gpio_get_value_cansleep(kbdrec->sys_gpio_vol_up); dev_dbg(kbdrec->fbx_kybd_pdev, "%s: Key VOLUMEUP (%d) %s\n", __func__, KEY_VOLUMEUP, !gpio_val ? "was RELEASED" : "is PRESSING"); if (!gpio_val) { input_report_key(idev, KEY_VOLUMEUP, KEYRELEASE); } else { input_report_key(idev, KEY_VOLUMEUP, KEYPRESS); } input_sync(idev); } static void fbx_kybd_voldn(struct work_struct *work) { struct fbx_kybd_record *kbdrec = container_of(work, struct fbx_kybd_record, qkybd_voldn); struct input_dev *idev = kbdrec->fbx_kybd_idev; bool gpio_val = (bool)gpio_get_value_cansleep(kbdrec->sys_gpio_vol_dn); dev_dbg(kbdrec->fbx_kybd_pdev, "%s: Key VOLUMEDOWN (%d) %s\n", __func__, KEY_VOLUMEDOWN, !gpio_val ? "was RELEASED" : "is PRESSING"); if (!gpio_val) { input_report_key(idev, KEY_VOLUMEDOWN, KEYRELEASE); } else { input_report_key(idev, KEY_VOLUMEDOWN, KEYPRESS); } input_sync(idev); } static void fbx_kybd_camf(struct work_struct *work) { struct fbx_kybd_record *kbdrec = container_of(work, struct fbx_kybd_record, qkybd_camf); struct input_dev *idev = kbdrec->fbx_kybd_idev; bool gpio_val = (bool)gpio_get_value_cansleep(kbdrec->sys_gpio_cam_f); dev_dbg(kbdrec->fbx_kybd_pdev, "%s: Key FOCUS (%d) %s\n", __func__, KEY_FOCUS, !gpio_val ? "was RELEASED" : "is PRESSING"); if (!gpio_val) { input_report_key(idev, KEY_FOCUS, KEYRELEASE); } else { input_report_key(idev, KEY_FOCUS, KEYPRESS); } input_sync(idev); } static void fbx_kybd_camt(struct work_struct *work) { struct fbx_kybd_record *kbdrec = container_of(work, struct fbx_kybd_record, qkybd_camt); struct input_dev *idev = kbdrec->fbx_kybd_idev; bool gpio_val = (bool)gpio_get_value_cansleep(kbdrec->sys_gpio_cam_t); dev_dbg(kbdrec->fbx_kybd_pdev, "%s: Key CAMERA (%d) %s\n", __func__, KEY_CAMERA, !gpio_val ? "was RELEASED" : "is PRESSING"); if (!gpio_val) { input_report_key(idev, KEY_CAMERA, KEYRELEASE); } else { input_report_key(idev, KEY_CAMERA, KEYPRESS); } input_sync(idev); } /* Div1-FW3-BSP-AUDIO */ static void fbx_kybd_hooksw(struct work_struct *work) { //MM-SL-DisableHookInFTM-oo*{ #ifndef CONFIG_FIH_FTM struct fbx_kybd_record *kbdrec= container_of(work, struct fbx_kybd_record, hook_switchkey); struct input_dev *idev = kbdrec->fbx_kybd_idev; bool hook_sw_val = (bool)gpio_get_value_cansleep(kbdrec->hook_sw_pin); bool headset_status = (bool)gpio_get_value_cansleep(26); if((rd->hooksw_irq_enable == true) && (headset_status == 1)){ disable_irq(MSM_GPIO_TO_INT(kbdrec->hook_sw_pin)); if(idev) { if (hook_sw_val) { report_hs_key(HS_HEADSET_SWITCH_K, HS_REL_K); printk("FIH: keyrelease KEY_HEADSETHOOK\n"); } else { report_hs_key(HS_HEADSET_SWITCH_K, HS_NONE_K); printk("FIH: keypress KEY_HEADSETHOOK\n"); } input_sync(idev); } enable_irq(MSM_GPIO_TO_INT(kbdrec->hook_sw_pin)); enable_irq_wake(MSM_GPIO_TO_INT(kbdrec->hook_sw_pin)); } #endif //MM-SL-DisableHookInFTM-oo*} } static void fbx_kybd_free_irq(void) { free_irq(PM8058_GPIO_IRQ(PMIC8058_IRQ_BASE, rd->pmic_gpio_vol_up), rd); free_irq(PM8058_GPIO_IRQ(PMIC8058_IRQ_BASE, rd->pmic_gpio_vol_dn), rd); if (rd->product_phase == Product_PR1 || rd->product_phase == Product_EVB) { free_irq(PM8058_GPIO_IRQ(PMIC8058_IRQ_BASE, rd->pmic_gpio_cam_f), rd); free_irq(PM8058_GPIO_IRQ(PMIC8058_IRQ_BASE, rd->pmic_gpio_cam_t), rd); } /* Div1-FW3-BSP-AUDIO */ free_irq(MSM_GPIO_TO_INT(rd->hook_sw_pin), rd); }
/*8X60 PROJECT need to use Marco PM8058_GPIO_IRQ to decode the IRQ number(id) for PMIC GPIO*/ int mmc_wimax_get_hostwakeup_IRQ_ID(void) { return PM8058_GPIO_IRQ(PM8058_IRQ_BASE,RIDER_WIMAX_HOST_WAKEUP); }
#include <linux/input.h> #include "keypad-pmic-mogami.h" static struct pm8058_gpio pm_gpio_config = { .direction = PM_GPIO_DIR_IN, .pull = PM_GPIO_PULL_UP_31P5, .vin_sel = 2, .out_strength = PM_GPIO_STRENGTH_LOW, .function = PM_GPIO_FUNC_NORMAL, .inv_int_pol = 0, }; static struct keypad_pmic_mogami_key keymap_pmic[] = { { .code = KEY_BACK, .irq = PM8058_GPIO_IRQ(PMIC8058_IRQ_BASE, 17 - 1), .gpio = 17, }, { .code = KEY_MENU, .irq = PM8058_GPIO_IRQ(PMIC8058_IRQ_BASE, 18 - 1), .gpio = 18, }, { .code = KEY_HOME, .irq = PM8058_GPIO_IRQ(PMIC8058_IRQ_BASE, 19 - 1), .gpio = 19, .wake = 1, }, { .code = KEY_SEARCH,