示例#1
0
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;
}
示例#2
0
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;
}
示例#3
0
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,
};
示例#8
0
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,