Ejemplo n.º 1
0
static irqreturn_t button_irq_handler(int irq, void *dev_id)
{
    struct hsd_info *hi = (struct hsd_info *) dev_id;

    int value;

    wake_lock_timeout(&ear_hook_wake_lock, 2 * HZ);

    HSD_DBG("button_irq_handler");

    // low:pressed, high:released
    if( gpio_cansleep(hi->gpio_swd) )
        value = gpio_get_value_cansleep(hi->gpio_swd);
    else
        value = gpio_get_value(hi->gpio_swd);

    HSD_DBG("======= hi->gpio_swd : %d =======", value);

    if (value)
        queue_delayed_work(local_max1462x_workqueue, &(hi->work_for_key_released), hi->latency_for_key );
    else
        queue_delayed_work(local_max1462x_workqueue, &(hi->work_for_key_pressed), hi->latency_for_key );

    return IRQ_HANDLED;
}
Ejemplo n.º 2
0
static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
	struct uart_omap_port *up = to_uart_omap_port(port);
	unsigned char mcr = 0;

	dev_dbg(up->port.dev, "serial_omap_set_mctrl+%d\n", up->port.line);
	if (mctrl & TIOCM_RTS)
		mcr |= UART_MCR_RTS;
	if (mctrl & TIOCM_DTR)
		mcr |= UART_MCR_DTR;
	if (mctrl & TIOCM_OUT1)
		mcr |= UART_MCR_OUT1;
	if (mctrl & TIOCM_OUT2)
		mcr |= UART_MCR_OUT2;
	if (mctrl & TIOCM_LOOP)
		mcr |= UART_MCR_LOOP;

	pm_runtime_get_sync(up->dev);
	up->mcr = serial_in(up, UART_MCR);
	up->mcr |= mcr;
	serial_out(up, UART_MCR, up->mcr);
	pm_runtime_mark_last_busy(up->dev);
	pm_runtime_put_autosuspend(up->dev);

	if (gpio_is_valid(up->DTR_gpio) &&
	    !!(mctrl & TIOCM_DTR) != up->DTR_active) {
		up->DTR_active = !up->DTR_active;
		if (gpio_cansleep(up->DTR_gpio))
			schedule_work(&up->qos_work);
		else
			gpio_set_value(up->DTR_gpio,
				       up->DTR_active != up->DTR_inverted);
	}
}
Ejemplo n.º 3
0
static int gpio_keys_getval(int gpio)
{
	int ret;

	if (gpio_cansleep(gpio))
		ret = gpio_get_value_cansleep(gpio);
	else
		ret = gpio_get_value(gpio);
	return ret;
}
Ejemplo n.º 4
0
static int gpio_keys_request_irq(int gpio, irq_handler_t isr,
		unsigned long flags, const char *name, void *data)
{
	int ret;

	if (gpio_cansleep(gpio))
		ret = request_threaded_irq(gpio_to_irq(gpio), NULL, isr,
				flags | IRQF_ONESHOT, name, data);
	else
		ret = request_irq(gpio_to_irq(gpio), isr, flags, name, data);
	return ret;
}
Ejemplo n.º 5
0
bool is_4pole_earjack (void) 
{
	bool retVal;
	int err;
	if (gpio_cansleep(REMOTEKEY_DET)){
		err=gpio_get_value_cansleep(REMOTEKEY_DET);
		dbg("gpio_get_value_cansleep(REMOTEKEY_DET) start\n");                    
	}else{
		err=gpio_get_value(REMOTEKEY_DET);
		dbg("gpio_get_value(REMOTEKEY_DET) start\n");
	}
	retVal = (err>0) ? 1:0;
	return retVal;
}
Ejemplo n.º 6
0
static void remove_headset(struct hsd_info *hi)
{
    int has_mic = switch_get_state(&hi->sdev);

    HSD_DBG("remove_headset");

    atomic_set(&hi->is_3_pole_or_not, HEADSET_POLE_INIT);
    mutex_lock(&hi->mutex_lock);
    switch_set_state(&hi->sdev, HEADSET_NO_DEVICE);
    mutex_unlock(&hi->mutex_lock);

    if (atomic_read(&hi->irq_key_enabled)) {
        unsigned long irq_flags;

        local_irq_save(irq_flags);
        disable_irq(hi->irq_key);
        local_irq_restore(irq_flags);
        atomic_set(&hi->irq_key_enabled, FALSE);
    }

    if( atomic_read(&hi->btn_state) == HEADSET_BTN_PRESSED )
#ifdef	CONFIG_MAX1462X_USE_LOCAL_WORK_QUEUE
        queue_delayed_work(local_max1462x_workqueue, &(hi->work_for_key_released), hi->latency_for_key );
#else
        schedule_delayed_work(&(hi->work_for_key_released), hi->latency_for_key );
#endif

    input_report_switch(hi->input, SW_HEADPHONE_INSERT, 0);

    if (has_mic == HEADSET_WITH_MIC) {
        irq_set_irq_wake(hi->irq_key, 0);
        input_report_switch(hi->input, SW_MICROPHONE_INSERT, 0);

//LGE_CHANGE_S 20130710 ilda.jung[Audio] Disable not using GPIO
#if !defined(CONFIG_MACH_APQ8064_AWIFI)
        // set low to an external LDO for mic bias
        if (hi->set_headset_mic_bias) {
            hi->set_headset_mic_bias(FALSE);
        } else if( hi->external_ldo_mic_bias > 0 ) {
            gpio_cansleep(hi->external_ldo_mic_bias) ?
            gpio_set_value_cansleep(hi->external_ldo_mic_bias, 0) : gpio_set_value(hi->external_ldo_mic_bias, 0);
        }
#endif
//LGE_CHANGE_E 20130710 ilda.jung[Audio] Disable not using GPIO
    }

    input_sync(hi->input);
}
Ejemplo n.º 7
0
static void button_released(struct work_struct *work)
{
    struct delayed_work *dwork = container_of(work, struct delayed_work, work);
    struct hsd_info *hi = container_of(dwork, struct hsd_info, work_for_key_released);
    struct ear_3button_info_table *table;
    int table_size = ARRAY_SIZE(max1462x_ear_3button_type_data);
    int i;

    if( gpio_cansleep(hi->gpio_det) ) {
        if( gpio_get_value_cansleep(hi->gpio_det) ) {
            //if( gpio_get_value_cansleep(hi->gpio_det) && !(atomic_read(&hi->btn_state) == HEADSET_BTN_PRESSED) ) {
            HSD_ERR("button_released but ear jack is plugged out already! just ignore the event.\n");
            return;
        }
    } else {
        if( gpio_get_value(hi->gpio_det) ) {
            //if( gpio_get_value(hi->gpio_det) && !(atomic_read(&hi->btn_state) == HEADSET_BTN_PRESSED) ) {
            HSD_ERR("button_released but ear jack is plugged out already! just ignore the event.\n");
            return;
        }
    }

    HSD_DBG("======= button_released =======");

    for (i = 0; i < table_size; i++) {
        table = &max1462x_ear_3button_type_data[i];
        if (table->PRESS_OR_NOT) {
            atomic_set(&hi->btn_state, HEADSET_BTN_RELEASED);
            switch(table->ADC_HEADSET_BUTTON) {
            case  KEY_MEDIA :
                input_report_key(hi->input, KEY_MEDIA, 0);
                break;
            case KEY_VOLUMEUP :
                input_report_key(hi->input, KEY_VOLUMEUP, 0);
                break;
            case KEY_VOLUMEDOWN :
                input_report_key(hi->input, KEY_VOLUMEDOWN, 0);
                break;
            }

            table->PRESS_OR_NOT = 0;
            input_sync(hi->input);
            break;
        }
    }
}
Ejemplo n.º 8
0
static int dht22_probe(struct platform_device *pdev) { 
  struct device* dev;
  struct dht22_platform_data* pdata;
  struct dht22_priv* priv;
  
  dev = &pdev->dev;
  
  priv = devm_kzalloc(dev,sizeof(struct dht22_priv),GFP_KERNEL);
  if (!priv)
    return -ENOMEM;

  pdata = dev->platform_data;
  if (pdata)
    priv->gpio = pdata->gpio;
  else
    priv->gpio = of_get_gpio(dev->of_node, 0);
  dev_info(dev, "Creating dht22 for gpio %d\n", priv->gpio);
  
  if(!gpio_is_valid(priv->gpio)) {
    dev_err(dev, "Invalid GPIO number : %u",priv->gpio);
    return -EINVAL;
  }
  if(gpio_cansleep(priv->gpio)) {
    dev_err(dev, "Calls for GPIO number %u can sleep, driver can't use it",priv->gpio);
    return -EFAULT;
  }
  if (gpio_request_one(priv->gpio, GPIOF_IN, dev_name(dev))) {
    dev_err(dev, "Can't request GPIO number %u",priv->gpio);
    return -EFAULT;
  }
  
  request_irq(gpio_to_irq(priv->gpio), dht22_handler, IRQF_TRIGGER_FALLING | IRQF_NO_THREAD, dev_name(dev), dev);
  
  sysfs_create_group(&dev->kobj, &dht22_attr_group);
  
  platform_set_drvdata(pdev,priv);
  
  return 0;
}
Ejemplo n.º 9
0
static void detect_work(struct work_struct *work)
{
    int state = 0;
    struct delayed_work *dwork = container_of(work, struct delayed_work, work);
    struct hsd_info *hi = container_of(dwork, struct hsd_info, work);

    HSD_DBG("detect_work");

    if( gpio_cansleep(hi->gpio_det) )
        state = gpio_get_value_cansleep(hi->gpio_det);
    else
        state = gpio_get_value(hi->gpio_det);

    if( state == 1 ) {  // gpio_det high - jack out
        if( switch_get_state(&hi->sdev) != HEADSET_NO_DEVICE ) {
            HSD_DBG("======= LGE headset removing =======");
            remove_headset(hi);
#ifdef CONFIG_LGE_BROADCAST_ONESEG
            isdbt_hw_antenna_switch(0);
            ear_state = 0;
#endif
        } else {
            HSD_DBG("err_invalid_state state = %d\n", state);
        }
    } else {    // gpio_det low - jack in
        if( switch_get_state(&hi->sdev) == HEADSET_NO_DEVICE ) {
            HSD_DBG("********** LGE headset inserting **********");
            insert_headset(hi);

#ifdef CONFIG_LGE_BROADCAST_ONESEG
            isdbt_hw_antenna_switch(1);
            ear_state = 1;
#endif
        } else {
            HSD_DBG("err_invalid_state state = %d\n", state);
        }
    }
}
Ejemplo n.º 10
0
static enum hrtimer_restart
gpio_pwm_timeout(struct hrtimer *t)
{
    struct gpio_pwm *gp = container_of(t, struct gpio_pwm, timer);
    ktime_t tnew;

    if (unlikely(gp->pwm.channels[0].duty_ticks == 0))
        gp->active = 0;
    else if (unlikely(gp->pwm.channels[0].duty_ticks
    == gp->pwm.channels[0].period_ticks))
        gp->active = 1;
    else
        gp->active ^= 1;

    if (gpio_cansleep(gp->gpio))
        schedule_work(&gp->work);
    else
        gpio_pwm_work(&gp->work);

    if (!gp->active && gp->pwm.channels[0].callback)
        gp->pwm.channels[0].callback(&gp->pwm.channels[0]);

    if (unlikely(!gp->active &&
    (gp->pwm.channels[0].flags & BIT(FLAG_STOP)))) {
        clear_bit(FLAG_STOP, &gp->pwm.channels[0].flags);
        complete_all(&gp->pwm.channels[0].complete);
        return HRTIMER_NORESTART;
    }

    if (gp->active)
        tnew = ktime_set(0, gp->pwm.channels[0].duty_ticks);
    else
        tnew = ktime_set(0, gp->pwm.channels[0].period_ticks
        - gp->pwm.channels[0].duty_ticks);
    hrtimer_start(&gp->timer, tnew, HRTIMER_MODE_REL);

    return HRTIMER_NORESTART;
}
Ejemplo n.º 11
0
static void insert_headset(struct hsd_info *hi)
{
    int earjack_type;

    HSD_DBG("insert_headset");

    // set irq to wake up in sleep mode
    irq_set_irq_wake(hi->irq_key, 1);

//LGE_CHANGE_S 20130710 ilda.jung[Audio] Disable not using GPIO
#if !defined(CONFIG_MACH_APQ8064_AWIFI)
    // set high to an external LDO for mic bias
    if (hi->set_headset_mic_bias) {
        hi->set_headset_mic_bias(TRUE);
    } else if( hi->external_ldo_mic_bias > 0 ) {
        gpio_cansleep(hi->external_ldo_mic_bias) ?
        gpio_set_value_cansleep(hi->external_ldo_mic_bias, 1) : gpio_set_value(hi->external_ldo_mic_bias, 1);
    }
#endif
//LGE_CHANGE_E20130710 ilda.jung[Audio] Disable not using GPIO

    // set mode pin high
    gpio_direction_output(hi->gpio_mode, 1);
    msleep(25);

    /* check if 3-pole or 4-pole
    * 1. read gpio_swd
    * 2. check if 3-pole or 4-pole
    * 3-1. NOT regiter irq with gpio_swd if 3-pole. complete.
    * 3-2. regiter irq with gpio_swd if 4-pole
    * 4. read MPP1 and decide a pressed key when interrupt occurs
    */

    /* 1. read gpio_swd */
    if( gpio_cansleep(hi->gpio_swd) )
        earjack_type = gpio_get_value_cansleep(hi->gpio_swd);
    else
        earjack_type = gpio_get_value(hi->gpio_swd);

    /* 2. check if 3-pole or 4-pole */
    if ( earjack_type == HEADSET_POLE_4 ) {// high
        HSD_DBG("======= 4 polarity earjack =======");

        atomic_set(&hi->is_3_pole_or_not, HEADSET_POLE_4);

        mutex_lock(&hi->mutex_lock);
        switch_set_state(&hi->sdev, HEADSET_WITH_MIC);
        mutex_unlock(&hi->mutex_lock);

        if (!atomic_read(&hi->irq_key_enabled)) {
            unsigned long irq_flags;
            HSD_DBG("irq_key_enabled = enable");

            local_irq_save(irq_flags);
            enable_irq(hi->irq_key);
            local_irq_restore(irq_flags);

            atomic_set(&hi->irq_key_enabled, TRUE);
        }

        // set mode pin high
#if 1
        //gpio_direction_output(hi->gpio_mode, 1);
#else
        gpio_tlmm_config(           // GPIOMUX_FUNC_GPIO
            GPIO_CFG(hi->gpio_mode, 0, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP, 0xf),
            GPIO_CFG_ENABLE);
#endif

        input_report_switch(hi->input, SW_HEADPHONE_INSERT, 1);
        input_report_switch(hi->input, SW_MICROPHONE_INSERT, 1);
        input_sync(hi->input);
    } else {// low
        HSD_DBG("********** 3 polarity earjack **********");

        atomic_set(&hi->is_3_pole_or_not, HEADSET_POLE_3);

        mutex_lock(&hi->mutex_lock);
        switch_set_state(&hi->sdev, HEADSET_NO_MIC);
        mutex_unlock(&hi->mutex_lock);

        irq_set_irq_wake(hi->irq_key, 0);

//LGE_CHANGE_S 20130710 ilda.jung[Audio] Disable not using GPIO
#if !defined(CONFIG_MACH_APQ8064_AWIFI)
        // set low to an external LDO for mic bias
        if (hi->set_headset_mic_bias) {
            hi->set_headset_mic_bias(FALSE);
        } else if( hi->external_ldo_mic_bias > 0 ) {
            gpio_cansleep(hi->external_ldo_mic_bias) ?
            gpio_set_value_cansleep(hi->external_ldo_mic_bias, 0) : gpio_set_value(hi->external_ldo_mic_bias, 0);
        }
#endif
//LGE_CHANGE_E 20130710 ilda.jung[Audio] Disable not using GPIO

        // set mode pin high-z
#if 1
        gpio_direction_input(hi->gpio_mode);
#else
        gpio_tlmm_config(           // GPIOMUX_FUNC_GPIO
            GPIO_CFG(hi->gpio_mode, 0, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
            GPIO_CFG_ENABLE);
#endif

        input_report_switch(hi->input, SW_HEADPHONE_INSERT, 1);
        input_sync(hi->input);
    }
}
Ejemplo n.º 12
0
int gpio_event_matrix_func(struct gpio_event_input_devs *input_devs,
	struct gpio_event_info *info, void **data, int func)
{
	int i;
	int err;
	int key_count;
	struct gpio_kp *kp;
	struct gpio_event_matrix_info *mi;

	mi = container_of(info, struct gpio_event_matrix_info, info);
	if (func == GPIO_EVENT_FUNC_SUSPEND || func == GPIO_EVENT_FUNC_RESUME) {
		/* TODO: disable scanning */
		return 0;
	}

	if (func == GPIO_EVENT_FUNC_INIT) {
		if (mi->keymap == NULL ||
		   mi->input_gpios == NULL ||
		   mi->output_gpios == NULL) {
			err = -ENODEV;
			pr_err("gpiomatrix: Incomplete pdata\n");
			goto err_invalid_platform_data;
		}
		key_count = mi->ninputs * mi->noutputs;

		*data = kp = kzalloc(sizeof(*kp) + sizeof(kp->keys_pressed[0]) *
				     BITS_TO_LONGS(key_count), GFP_KERNEL);
		if (kp == NULL) {
			err = -ENOMEM;
			pr_err("gpiomatrix: Failed to allocate private data\n");
			goto err_kp_alloc_failed;
		}
		kp->input_devs = input_devs;
		kp->keypad_info = mi;
		for (i = 0; i < key_count; i++) {
			unsigned short keyentry = mi->keymap[i];
			unsigned short keycode = keyentry & MATRIX_KEY_MASK;
			unsigned short dev = keyentry >> MATRIX_CODE_BITS;
			if (dev >= input_devs->count) {
				pr_err("gpiomatrix: bad device index %d >= "
					"%d for key code %d\n",
					dev, input_devs->count, keycode);
				err = -EINVAL;
				goto err_bad_keymap;
			}
			if (keycode && keycode <= KEY_MAX)
				input_set_capability(input_devs->dev[dev],
							EV_KEY, keycode);
		}
              set_bit(KEY_BACK & KEY_MAX, input_devs->dev[0]->keybit);
              set_bit(KEY_HOME & KEY_MAX, input_devs->dev[0]->keybit);
		for (i = 0; i < mi->noutputs; i++) {
			if (gpio_cansleep(mi->output_gpios[i])) {
				pr_err("gpiomatrix: unsupported output gpio %d,"
					" can sleep\n", mi->output_gpios[i]);
				err = -EINVAL;
				goto err_request_output_gpio_failed;
			}
			err = gpio_request(mi->output_gpios[i], "gpio_kp_out");
			if (err) {
				pr_err("gpiomatrix: gpio_request failed for "
					"output %d\n", mi->output_gpios[i]);
				goto err_request_output_gpio_failed;
			}
			if (mi->flags & GPIOKPF_DRIVE_INACTIVE)
				err = gpio_direction_output(mi->output_gpios[i],
					!(mi->flags & GPIOKPF_ACTIVE_HIGH));
			else
			{
				unsigned gpio_config = GPIO_CFG(mi->output_gpios[i], 0, GPIO_INPUT, GPIO_PULL_UP, GPIO_2MA);
				gpio_tlmm_config(gpio_config, GPIO_ENABLE);
				err = gpio_direction_input(mi->output_gpios[i]);
			}
			if (err) {
				pr_err("gpiomatrix: gpio_configure failed for "
					"output %d\n", mi->output_gpios[i]);
				goto err_output_gpio_configure_failed;
			}
		}
		for (i = 0; i < mi->ninputs; i++) {
			err = gpio_request(mi->input_gpios[i], "gpio_kp_in");
			if (err) {
				pr_err("gpiomatrix: gpio_request failed for "
					"input %d\n", mi->input_gpios[i]);
				goto err_request_input_gpio_failed;
			}
			err = gpio_direction_input(mi->input_gpios[i]);
			if (err) {
				pr_err("gpiomatrix: gpio_direction_input failed"
					" for input %d\n", mi->input_gpios[i]);
				goto err_gpio_direction_input_failed;
			}
		}
		kp->current_output = mi->noutputs;
		kp->key_state_changed = 1;

		hrtimer_init(&kp->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
        #ifdef CONFIG_HUAWEI_BACK_KEY_MULTI
        kp->back_pressed = FALSE;
        #endif
		kp->timer.function = gpio_keypad_timer_func;
              hrtimer_init(&kp->back_key_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
              kp->back_key_timer.function = back_key_timer_func;
		wake_lock_init(&kp->wake_lock, WAKE_LOCK_SUSPEND, "gpio_kp");
		err = gpio_keypad_request_irqs(kp);
		kp->use_irq = err == 0;

		pr_info("GPIO Matrix Keypad Driver: Start keypad matrix for "
			"%s%s in %s mode\n", input_devs->dev[0]->name,
			(input_devs->count > 1) ? "..." : "",
			kp->use_irq ? "interrupt" : "polling");

		if (kp->use_irq)
			wake_lock(&kp->wake_lock);
		hrtimer_start(&kp->timer, ktime_set(0, 0), HRTIMER_MODE_REL);

		return 0;
	}

	err = 0;
	kp = *data;

	if (kp->use_irq)
		for (i = mi->noutputs - 1; i >= 0; i--)
			free_irq(gpio_to_irq(mi->input_gpios[i]), kp);

	hrtimer_cancel(&kp->timer);
	wake_lock_destroy(&kp->wake_lock);
	for (i = mi->noutputs - 1; i >= 0; i--) {
err_gpio_direction_input_failed:
		gpio_free(mi->input_gpios[i]);
err_request_input_gpio_failed:
		;
	}
	for (i = mi->noutputs - 1; i >= 0; i--) {
err_output_gpio_configure_failed:
		gpio_free(mi->output_gpios[i]);
err_request_output_gpio_failed:
		;
	}
err_bad_keymap:
	kfree(kp);
err_kp_alloc_failed:
err_invalid_platform_data:
	return err;
}
Ejemplo n.º 13
0
int gpio_event_matrix_func(struct gpio_event_input_devs *input_devs,
	struct gpio_event_info *info, void **data, int func)
{
	int i;
	int err;
	int key_count;
	struct gpio_kp *kp;
	struct gpio_event_matrix_info *mi;

#if defined(CONFIG_MACH_RANT3) || defined(CONFIG_MACH_REALITY2) || defined(CONFIG_MACH_VINO) || defined(CONFIG_MACH_ROOKIE) || defined(CONFIG_MACH_ESCAPE) || defined(CONFIG_MACH_GIO) || defined(CONFIG_MACH_GIOS)
	/* Implementation for sysfs entries , creating Keypad-backlight class */
	bl_class = class_create(THIS_MODULE, "keypad-backlight");
	if ( bl_class) {
		printk(KERN_WARNING "Unable to create Keypad Backlight class \n");
	}

	/* Creating the device backlight under keypad-backlight class */
   	kpd_dev = device_create( bl_class, NULL, 0, NULL, "backlight");
   	if (!kpd_dev){
		class_destroy(bl_class);
     		printk("Failed to create device(keypad backlight) \n");
	}

       if (device_create_file(kpd_dev, &dev_attr_key_pressed) < 0)
		printk("Failed to create device file(%s)!\n", dev_attr_key_pressed.attr.name);

       if (device_create_file(kpd_dev, &dev_attr_backlight_ctrl) < 0)
		printk("Failed to create device file(%s)!\n", dev_attr_backlight_ctrl.attr.name);

       if (device_create_file(kpd_dev, &dev_attr_backlight_lpm_ctrl) < 0)
		printk("Failed to create device file(%s)!\n", dev_attr_backlight_lpm_ctrl.attr.name);

#if defined(CONFIG_MACH_VINO) || defined(CONFIG_MACH_GIOS)
       if (device_create_file(kpd_dev, &dev_attr_volumnkey_ctrl) < 0)
  		printk("Failed to create device file(%s)!\n", dev_attr_volumnkey_ctrl.attr.name);

#endif
	/* Creating device attributes for setting keypad backlight time */
  	if (device_create_file(kpd_dev, &bl_keypad_attributes[0]) < 0){
   		printk("Failed to create device attributes for Keypad Backlight \n");
		device_destroy(bl_class,0);
		class_destroy(bl_class);
	}

      /* Initializing delayed work for Back light off */
      INIT_DELAYED_WORK(&backlightoff, keypad_backlightoff_work);	
#endif      
	mi = container_of(info, struct gpio_event_matrix_info, info);
	if (func == GPIO_EVENT_FUNC_SUSPEND || func == GPIO_EVENT_FUNC_RESUME) {
#if defined(CONFIG_MACH_RANT3) || defined(CONFIG_MACH_REALITY2) || defined(CONFIG_MACH_VINO) || defined(CONFIG_MACH_ROOKIE) || defined(CONFIG_MACH_ESCAPE) || defined(CONFIG_MACH_GIO) || defined(CONFIG_MACH_GIOS)
  if(func == GPIO_EVENT_FUNC_SUSPEND) 
    keypad_backlight_power(OFF);
  else
    keypad_backlight_power(ON);
#endif
		/* TODO: disable scanning */
		return 0;
	}

	if (func == GPIO_EVENT_FUNC_INIT) {
		if (mi->keymap == NULL ||
		   mi->input_gpios == NULL ||
		   mi->output_gpios == NULL) {
			err = -ENODEV;
			pr_err("gpiomatrix: Incomplete pdata\n");
			goto err_invalid_platform_data;
		}
		key_count = mi->ninputs * mi->noutputs;

		pgpio_key=*data = kp = kzalloc(sizeof(*kp) + sizeof(kp->keys_pressed[0]) *
				     BITS_TO_LONGS(key_count), GFP_KERNEL);
		if (kp == NULL) {
			err = -ENOMEM;
			pr_err("gpiomatrix: Failed to allocate private data\n");
			goto err_kp_alloc_failed;
		}
		kp->input_devs = input_devs;
		kp->keypad_info = mi;
		for (i = 0; i < key_count; i++) {
			unsigned short keyentry = mi->keymap[i];
			unsigned short keycode = keyentry & MATRIX_KEY_MASK;
			unsigned short dev = keyentry >> MATRIX_CODE_BITS;
			if (dev >= input_devs->count) {
				pr_err("gpiomatrix: bad device index %d >= "
					"%d for key code %d\n",
					dev, input_devs->count, keycode);
				err = -EINVAL;
				goto err_bad_keymap;
			}
			if (keycode && keycode <= KEY_MAX)
				input_set_capability(input_devs->dev[dev],
							EV_KEY, keycode);
		}

#if defined(CONFIG_MACH_ESCAPE)
		input_set_capability(kp->input_devs->dev[0], EV_SW, SW_LID);

		if(gpio_get_value(HALL_GPIO))
			kp->input_devs->dev[0]->sw[SW_LID] = 0;
		else
			kp->input_devs->dev[0]->sw[SW_LID] = 1;
#endif

		for (i = 0; i < mi->noutputs; i++) {
			err = gpio_request(mi->output_gpios[i], "gpio_kp_out");
			if (err) {
				pr_err("gpiomatrix: gpio_request failed for "
					"output %d\n", mi->output_gpios[i]);
				goto err_request_output_gpio_failed;
			}
			if (gpio_cansleep(mi->output_gpios[i])) {
				pr_err("gpiomatrix: unsupported output gpio %d,"
					" can sleep\n", mi->output_gpios[i]);
				err = -EINVAL;
				goto err_output_gpio_configure_failed;
			}
			if (mi->flags & GPIOKPF_DRIVE_INACTIVE){
#if defined(CONFIG_MACH_RANT3) || defined(CONFIG_MACH_ESCAPE)
	#if defined(CONFIG_MACH_RANT3)
				if(hw_version < 6)
	#endif
    				{
        				err = gpio_tlmm_config(GPIO_CFG(mi->output_gpios[i] , 0, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP,GPIO_CFG_2MA), GPIO_CFG_ENABLE);
        				printk("Gpio config %d return %d \r\n",mi->output_gpios[i] ,err);
        				if (err) {
        				pr_err("gpiomatrix: gpio_tlmm_config failed for "
        					"output %d\n", mi->output_gpios[i]);
        				goto err_request_output_gpio_failed;
        				}
    				}
#endif

				err = gpio_direction_output(mi->output_gpios[i],
					!(mi->flags & GPIOKPF_ACTIVE_HIGH));
			}
			else
				err = gpio_direction_input(mi->output_gpios[i]);
			if (err) {
				pr_err("gpiomatrix: gpio_configure failed for "
					"output %d\n", mi->output_gpios[i]);
				goto err_output_gpio_configure_failed;
			}
		}
		for (i = 0; i < mi->ninputs; i++) {
			err = gpio_request(mi->input_gpios[i], "gpio_kp_in");
			if (err) {
				pr_err("gpiomatrix: gpio_request failed for "
					"input %d\n", mi->input_gpios[i]);
				goto err_request_input_gpio_failed;
			}
#if defined (CONFIG_MACH_ROOKIE) || defined(CONFIG_MACH_ESCAPE)// || defined(CONFIG_MACH_GIO)
			if ( i >= mi->ninputs-2) // ( (i == 2) || (i == 3))
				err = gpio_tlmm_config(GPIO_CFG(mi->input_gpios[i] , 0, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL,GPIO_CFG_2MA), GPIO_CFG_ENABLE);
			else
#endif
#if defined(CONFIG_MACH_RANT3)
			if(hw_version < 6)
    			{
        			err = gpio_tlmm_config(GPIO_CFG(mi->input_gpios[i] , 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN,GPIO_CFG_2MA), GPIO_CFG_ENABLE);
        			pr_err("Gpio config %d return %d\r\n",mi->input_gpios[i] ,err);
        			if (err) {
        				printk("gpiomatrix: gpio_tlmm_config failed for "
        					"input %d\n", mi->input_gpios[i]);
        				goto err_request_input_gpio_failed;
        			}
    			}
#elif defined(CONFIG_MACH_GIO) || defined(CONFIG_MACH_VINO) || defined(CONFIG_MACH_GIOS)

#else
			err = gpio_tlmm_config(GPIO_CFG(mi->input_gpios[i] , 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN,GPIO_CFG_2MA), GPIO_CFG_ENABLE);
        			pr_err("Gpio config %d return %d\r\n",mi->input_gpios[i] ,err);
			if (err) {
        				printk("gpiomatrix: gpio_tlmm_config failed for "
					"input %d\n", mi->input_gpios[i]);
				goto err_request_input_gpio_failed;
			}
#endif
			err = gpio_direction_input(mi->input_gpios[i]);
			if (err) {
				pr_err("gpiomatrix: gpio_direction_input failed"
					" for input %d\n", mi->input_gpios[i]);
				goto err_gpio_direction_input_failed;
			}
		}
		for (i = 0; i < mi->ninputs; i++) {
			printk("Reading Input GPIO %d at init is %d \r\n",mi->input_gpios[i],gpio_get_value(mi->input_gpios[i]));

		}
		
		kp->current_output = mi->noutputs;
		kp->key_state_changed = 1;

		hrtimer_init(&kp->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
		kp->timer.function = gpio_keypad_timer_func;
		wake_lock_init(&kp->wake_lock, WAKE_LOCK_SUSPEND, "gpio_kp");
		err = gpio_keypad_request_irqs(kp);
		kp->use_irq = err == 0;

		pr_debug("GPIO Matrix Keypad Driver: Start keypad matrix for "
			"%s%s in %s mode\n", input_devs->dev[0]->name,
			(input_devs->count > 1) ? "..." : "",
			kp->use_irq ? "interrupt" : "polling");

		if (kp->use_irq)
			wake_lock(&kp->wake_lock);
    
		hrtimer_start(&kp->timer, ktime_set(0, 10000), HRTIMER_MODE_REL);
    
#if defined(CONFIG_MACH_RANT3) || defined(CONFIG_MACH_VINO) || defined(CONFIG_MACH_REALITY2) || defined(CONFIG_MACH_ROOKIE) || defined(CONFIG_MACH_ESCAPE) || defined(CONFIG_MACH_GIO) || defined(CONFIG_MACH_GIOS)
		early_suspend.suspend = keypad_early_suspend;
		early_suspend.resume = keypad_late_resume;
		register_early_suspend(&early_suspend);	
		backlight_flag = 1;
		keypad_backlight_power(OFF);
		spin_lock_init(&keypad_led_lock);
#endif

		return 0;
	}

	err = 0;
	kp = *data;

	if (kp->use_irq)
		for (i = mi->noutputs - 1; i >= 0; i--)
			free_irq(gpio_to_irq(mi->input_gpios[i]), kp);

	hrtimer_cancel(&kp->timer);
	wake_lock_destroy(&kp->wake_lock);
	for (i = mi->noutputs - 1; i >= 0; i--) {
err_gpio_direction_input_failed:
		gpio_free(mi->input_gpios[i]);
err_request_input_gpio_failed:
		;
	}
	for (i = mi->noutputs - 1; i >= 0; i--) {
err_output_gpio_configure_failed:
		gpio_free(mi->output_gpios[i]);
err_request_output_gpio_failed:
		;
	}
err_bad_keymap:
	kfree(kp);
err_kp_alloc_failed:
err_invalid_platform_data:
	return err;
}
int gpio_event_matrix_func(struct gpio_event_input_devs *input_devs,
	struct gpio_event_info *info, void **data, int func)
{
	int i;
	int err;
	int key_count;
	struct gpio_kp *kp;
	struct gpio_event_matrix_info *mi;

	mi = container_of(info, struct gpio_event_matrix_info, info);
	if (func == GPIO_EVENT_FUNC_SUSPEND || func == GPIO_EVENT_FUNC_RESUME) {
		/* TODO: disable scanning */
		return 0;
	}

	if (func == GPIO_EVENT_FUNC_INIT) {
		if (mi->keymap == NULL ||
		   mi->input_gpios == NULL ||
		   mi->output_gpios == NULL) {
			err = -ENODEV;
			pr_err("gpiomatrix: Incomplete pdata\n");
			goto err_invalid_platform_data;
		}
		printk("[%s:%d] hw rev = %d\n", __func__, __LINE__, board_hw_revision);

#if defined(CONFIG_MACH_EUROPA)
		if(board_hw_revision >= 3)
		{
			mi->keymap[(0)*mi->ninputs + (1)] = KEY_RESERVED;
			mi->keymap[(3)*mi->ninputs + (1)] = KEY_VOLUMEDOWN;
			mi->keymap[(3)*mi->ninputs + (4)] = KEY_VOLUMEUP;

			if(board_hw_revision >= 4)
			{
				mi->input_gpios[4] = 76;
			}
		}
#endif
#if defined(CONFIG_MACH_CALLISTO)
		// hsil
		input_set_capability(input_devs->dev[0], EV_SW, SW_LID);
#endif
		key_count = mi->ninputs * mi->noutputs;

		*data = kp = kzalloc(sizeof(*kp) + sizeof(kp->keys_pressed[0]) *
				     BITS_TO_LONGS(key_count), GFP_KERNEL);
		if (kp == NULL) {
			err = -ENOMEM;
			pr_err("gpiomatrix: Failed to allocate private data\n");
			goto err_kp_alloc_failed;
		}
		kp->input_devs = input_devs;
		kp->keypad_info = mi;
		for (i = 0; i < key_count; i++) {
			unsigned short keyentry = mi->keymap[i];
			unsigned short keycode = keyentry & MATRIX_KEY_MASK;
			unsigned short dev = keyentry >> MATRIX_CODE_BITS;
			if (dev >= input_devs->count) {
				pr_err("gpiomatrix: bad device index %d >= "
					"%d for key code %d\n",
					dev, input_devs->count, keycode);
				err = -EINVAL;
				goto err_bad_keymap;
			}
			if (keycode && keycode <= KEY_MAX)
				input_set_capability(input_devs->dev[dev],
							EV_KEY, keycode);
		}
		input_set_capability(input_devs->dev[0],EV_KEY, KEY_END); // for COOPER

#if defined(CONFIG_MACH_COOPER) || defined(CONFIG_MACH_BENI) || defined(CONFIG_MACH_TASS) || defined(CONFIG_MACH_LUCAS)
#if defined(CONFIG_KERNEL_SEC_MMICHECK)
		for(i = 0 ; i < ARRAY_SIZE(mmi_keycode) ; i++)
			input_set_capability(input_devs->dev[0],EV_KEY, mmi_keycode[i]); // for COOPER			
#endif
#endif
		for (i = 0; i < mi->noutputs; i++) {
			if (gpio_cansleep(mi->output_gpios[i])) {
				pr_err("gpiomatrix: unsupported output gpio %d,"
					" can sleep\n", mi->output_gpios[i]);
				err = -EINVAL;
				goto err_request_output_gpio_failed;
			}
			err = gpio_request(mi->output_gpios[i], "gpio_kp_out");
			if (err) {
				pr_err("gpiomatrix: gpio_request failed for "
					"output %d\n", mi->output_gpios[i]);
				goto err_request_output_gpio_failed;
			}
			if (mi->flags & GPIOKPF_DRIVE_INACTIVE)
				err = gpio_direction_output(mi->output_gpios[i],
					!(mi->flags & GPIOKPF_ACTIVE_HIGH));
			else
				err = gpio_direction_input(mi->output_gpios[i]);
			if (err) {
				pr_err("gpiomatrix: gpio_configure failed for "
					"output %d\n", mi->output_gpios[i]);
				goto err_output_gpio_configure_failed;
			}
		}
		for (i = 0; i < mi->ninputs; i++) {
			err = gpio_request(mi->input_gpios[i], "gpio_kp_in");
			if (err) {
				pr_err("gpiomatrix: gpio_request failed for "
					"input %d\n", mi->input_gpios[i]);
				goto err_request_input_gpio_failed;
			}
			err = gpio_direction_input(mi->input_gpios[i]);
			if (err) {
				pr_err("gpiomatrix: gpio_direction_input failed"
					" for input %d\n", mi->input_gpios[i]);
				goto err_gpio_direction_input_failed;
			}
		}
		
		// for COOPER
		err = gpio_request(GPIO_POWERKEY, "gpio_powerkey");
		if (err) {
			pr_err("gpiomatrix: gpio_request failed for "
				"input GPIO_POWERKEY %d\n", GPIO_POWERKEY);
			goto err_request_input_gpio_failed;
		}
		err = gpio_direction_input(GPIO_POWERKEY);
		if (err) {
			pr_err("gpiomatrix: gpio_direction_input failed"
				" for input GPIO_POWERKEY %d\n", GPIO_POWERKEY);
			goto err_gpio_direction_input_failed;
		}

		kp->current_output = mi->noutputs;
		kp->key_state_changed = 1;

		hrtimer_init(&kp->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
		kp->timer.function = gpio_keypad_timer_func;
		wake_lock_init(&kp->wake_lock, WAKE_LOCK_SUSPEND, "gpio_kp");
		err = gpio_keypad_request_irqs(kp);
		kp->use_irq = err == 0;

		pr_info("GPIO Matrix Keypad Driver: Start keypad matrix for "
			"%s%s in %s mode\n", input_devs->dev[0]->name,
			(input_devs->count > 1) ? "..." : "",
			kp->use_irq ? "interrupt" : "polling");

		if (kp->use_irq)
			wake_lock(&kp->wake_lock);
		hrtimer_start(&kp->timer, ktime_set(0, 0), HRTIMER_MODE_REL);

		return 0;
	}

	err = 0;
	kp = *data;

	if (kp->use_irq)
		for (i = mi->noutputs - 1; i >= 0; i--)
			free_irq(gpio_to_irq(mi->input_gpios[i]), kp);

	hrtimer_cancel(&kp->timer);
	wake_lock_destroy(&kp->wake_lock);
	for (i = mi->noutputs - 1; i >= 0; i--) {
err_gpio_direction_input_failed:
		gpio_free(mi->input_gpios[i]);
err_request_input_gpio_failed:
		;
	}
	for (i = mi->noutputs - 1; i >= 0; i--) {
err_output_gpio_configure_failed:
		gpio_free(mi->output_gpios[i]);
err_request_output_gpio_failed:
		;
	}
err_bad_keymap:
	kfree(kp);
err_kp_alloc_failed:
err_invalid_platform_data:
	return err;
}
int gpio_event_matrix_func(struct gpio_event_input_devs *input_devs,
	struct gpio_event_info *info, void **data, int func)
{
	int i;
	int err;
	int key_count;
#ifdef CONFIG_KEYBOARD_WAKEUP	
	int wakeup_keys_status;
	int irq;
	static int irq_status = 1;
#endif
	struct gpio_kp *kp;
	struct gpio_event_matrix_info *mi;

//	pr_info("[KEY TEST] %s, %d \n", __func__, __LINE__);
	mi = container_of(info, struct gpio_event_matrix_info, info);
	if (func == GPIO_EVENT_FUNC_SUSPEND || func == GPIO_EVENT_FUNC_RESUME) {
		/* TODO: disable scanning */
#ifdef CONFIG_KEYBOARD_WAKEUP	
		wakeup_keys_status = gpio_event_get_wakeup_keys_status() & 0x01;

		if (irq_status != wakeup_keys_status)
			irq_status = wakeup_keys_status;
		else
			return 0;


		for (i = 0; i < mi->ninputs; i++) {
			irq = gpio_to_irq(mi->input_gpios[i]);

			if (irq_status == 1)
				err = enable_irq_wake(irq);
			else
				err = disable_irq_wake(irq);
		}
		/* HOME Key is wakeup source */
		for (i = 0; i < mi->nwakeups; i++) {
			irq = gpio_to_irq(mi->wakeup_gpios[i]);
			err = enable_irq_wake(irq);
		}
#endif
		return 0;
	}

	if (func == GPIO_EVENT_FUNC_INIT) {
		if (mi->keymap == NULL ||
		   mi->input_gpios == NULL ||
		   mi->output_gpios == NULL) {
			err = -ENODEV;
			pr_err("gpiomatrix: Incomplete pdata\n");
			goto err_invalid_platform_data;
		}
		key_count = mi->ninputs * mi->noutputs;

		pgpio_key = *data = kp = kzalloc(sizeof(*kp) + sizeof(kp->keys_pressed[0]) *
				     BITS_TO_LONGS(key_count), GFP_KERNEL);
		if (kp == NULL) {
			err = -ENOMEM;
			pr_err("gpiomatrix: Failed to allocate private data\n");
			goto err_kp_alloc_failed;
		}
		kp->input_devs = input_devs;
		kp->keypad_info = mi;
		for (i = 0; i < key_count; i++) {
			unsigned short keyentry = mi->keymap[i];
			unsigned short keycode = keyentry & MATRIX_KEY_MASK;
			unsigned short dev = keyentry >> MATRIX_CODE_BITS;
			if (dev >= input_devs->count) {
				pr_err("gpiomatrix: bad device index %d >= "
					"%d for key code %d\n",
					dev, input_devs->count, keycode);
				err = -EINVAL;
				goto err_bad_keymap;
			}
			if (keycode && keycode <= KEY_MAX)
				input_set_capability(input_devs->dev[dev],
							EV_KEY, keycode);
		}

		for (i = 0; i < mi->noutputs; i++) {
			err = gpio_request(mi->output_gpios[i], "gpio_kp_out");
			if (err) {
				pr_err("gpiomatrix: gpio_request failed for "
					"output %d\n", mi->output_gpios[i]);
				goto err_request_output_gpio_failed;
			}
			if (gpio_cansleep(mi->output_gpios[i])) {
				pr_err("gpiomatrix: unsupported output gpio %d,"
					" can sleep\n", mi->output_gpios[i]);
				err = -EINVAL;
				goto err_output_gpio_configure_failed;
			}
			if (mi->flags & GPIOKPF_DRIVE_INACTIVE)
				err = gpio_direction_output(mi->output_gpios[i],
					!(mi->flags & GPIOKPF_ACTIVE_HIGH));
			else
				err = gpio_direction_input(mi->output_gpios[i]);
			if (err) {
				pr_err("gpiomatrix: gpio_configure failed for "
					"output %d\n", mi->output_gpios[i]);
				goto err_output_gpio_configure_failed;
			}
		}
		for (i = 0; i < mi->ninputs; i++) {
			err = gpio_request(mi->input_gpios[i], "gpio_kp_in");
			if (err) {
				pr_err("gpiomatrix: gpio_request failed for "
					"input %d\n", mi->input_gpios[i]);
				goto err_request_input_gpio_failed;
			}
			err = gpio_direction_input(mi->input_gpios[i]);
			if (err) {
				pr_err("gpiomatrix: gpio_direction_input failed"
					" for input %d\n", mi->input_gpios[i]);
				goto err_gpio_direction_input_failed;
			}
		}
		kp->current_output = mi->noutputs;
		kp->key_state_changed = 1;

		hrtimer_init(&kp->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
		kp->timer.function = gpio_keypad_timer_func;
		wake_lock_init(&kp->wake_lock, WAKE_LOCK_SUSPEND, "gpio_kp");
		err = gpio_keypad_request_irqs(kp);
		kp->use_irq = err == 0;

#ifdef CONFIG_KEYBOARD_WAKEUP	
		kpd_dev = device_create(sec_class, NULL, 0, NULL, "sec_key");
		if (!kpd_dev)
			printk(KERN_WARNING "Failed to create device(sec_key)!\n");
		if (device_create_file(kpd_dev, &dev_attr_sec_key_pressed) < 0)
			printk(KERN_WARNING "Failed to create file(%s)!\n"
				, dev_attr_sec_key_pressed.attr.name);
#endif
		pr_info("GPIO Matrix Keypad Driver: Start keypad matrix for "
			"%s%s in %s mode\n", input_devs->dev[0]->name,
			(input_devs->count > 1) ? "..." : "",
			kp->use_irq ? "interrupt" : "polling");

		if (kp->use_irq)
			wake_lock(&kp->wake_lock);
		hrtimer_start(&kp->timer, ktime_set(0, 0), HRTIMER_MODE_REL);

		return 0;
	}

	err = 0;
	kp = *data;

	if (kp->use_irq)
		for (i = mi->noutputs - 1; i >= 0; i--)
			free_irq(gpio_to_irq(mi->input_gpios[i]), kp);

	hrtimer_cancel(&kp->timer);
	wake_lock_destroy(&kp->wake_lock);
	for (i = mi->noutputs - 1; i >= 0; i--) {
err_gpio_direction_input_failed:
		gpio_free(mi->input_gpios[i]);
err_request_input_gpio_failed:
		;
	}
	for (i = mi->noutputs - 1; i >= 0; i--) {
err_output_gpio_configure_failed:
		gpio_free(mi->output_gpios[i]);
err_request_output_gpio_failed:
		;
	}
err_bad_keymap:
	kfree(kp);
err_kp_alloc_failed:
err_invalid_platform_data:
	return err;
}
Ejemplo n.º 16
0
static int lge_hsd_probe(struct platform_device *pdev)
{
    int ret = 0;
    struct max1462x_platform_data *pdata = pdev->dev.platform_data;

    struct hsd_info *hi;

    HSD_DBG("lge_hsd_probe");

    hi = kzalloc(sizeof(struct hsd_info), GFP_KERNEL);

    if (NULL == hi) {
        HSD_ERR("Failed to allloate headset per device info\n");
        return -ENOMEM;
    }

    platform_set_drvdata(pdev, hi);

    // initialize internal variables
    atomic_set(&hi->btn_state, HEADSET_BTN_INIT);
    atomic_set(&hi->is_3_pole_or_not, HEADSET_POLE_INIT);

    // set key code
    hi->key_code = pdata->key_code; // KEY_RESERVED(0), KEY_MEDIA(226), KEY_VOLUMEUP(115) or KEY_VOLUMEDOWN(114)

    // set GPIO number for each pin
    hi->gpio_mode = pdata->gpio_mode;
    hi->gpio_det = pdata->gpio_det;
    hi->gpio_swd = pdata->gpio_swd;

    // set delayed time for latency
    hi->latency_for_detection = msecs_to_jiffies(pdata->latency_for_detection);
    HSD_DBG("jiffies of hi->latency_for_detection : %u \n", hi->latency_for_detection);

    hi->latency_for_key = msecs_to_jiffies(pdata->latency_for_key);
    HSD_DBG("jiffies of hi->latency_for_key : %u \n", hi->latency_for_key);

    hi->adc_mpp_num = pdata->adc_mpp_num;
    HSD_DBG("hi->adc_mpp_num : %u \n", hi->adc_mpp_num);

    hi->adc_channel = pdata->adc_channel;
    HSD_DBG("hi->adc_channel : %u \n", hi->adc_channel);

//LGE_CHANGE_S 20130710 ilda.jung[Audio] Disable not using GPIO
#if !defined(CONFIG_MACH_APQ8064_AWIFI)
    // set gpio for an external LDO control
    if( pdata->external_ldo_mic_bias > 0 ) {
        hi->external_ldo_mic_bias = pdata->external_ldo_mic_bias;
        HSD_DBG("control an external LDO(GPIO# %u) for MIC BIAS", hi->external_ldo_mic_bias);
    } else {
        hi->external_ldo_mic_bias = 0;
        HSD_DBG("don't control an external LDO for MIC");
    }

    // set callback function for an external LDO control
    if( pdata->set_headset_mic_bias!= NULL ) {
        hi->set_headset_mic_bias = pdata->set_headset_mic_bias;
        HSD_DBG("set a func pointer of an external LDO for MIC");
    } else {
        pdata->set_headset_mic_bias = NULL;
        HSD_DBG("don't set a func pointer of an external LDO for MIC");
    }
#endif
//LGE_CHANGE_E 20130710 ilda.jung[Audio] Disable not using GPIO

    mutex_init(&hi->mutex_lock);

    INIT_DELAYED_WORK(&hi->work, detect_work);
    INIT_DELAYED_WORK(&hi->work_for_key_pressed, button_pressed);
    INIT_DELAYED_WORK(&hi->work_for_key_released, button_released);


    // initialize gpio_mode
    // set gpio_mode high as a default, and set mode among high,low,high-Z after deciding 3 or 4 polarity
    ret = gpio_request(hi->gpio_mode, "gpio_mode");
    if (ret < 0) {
        HSD_ERR("Failed to configure gpio%u (gpio_mode) gpio_request\n", hi->gpio_mode);
        goto error_01;
    }

    ret = gpio_direction_output(hi->gpio_mode, 1);
    if (ret < 0) {
        HSD_ERR("Failed to configure gpio%d (gpio_mode) gpio_direction_input\n", hi->gpio_mode);
        goto error_01;
    }

    // initialize gpio_det
    ret = gpio_request(hi->gpio_det, "gpio_det");
    if (ret < 0) {
        HSD_ERR("Failed to configure gpio%u (gpio_det) gpio_request\n", hi->gpio_det);
        goto error_02;
    }

    ret = gpio_direction_input(hi->gpio_det);
    if (ret < 0) {
        HSD_ERR("Failed to configure gpio%u (gpio_det) gpio_direction_input\n", hi->gpio_det);
        goto error_02;
    }

    // initialize gpio_swd
    ret = gpio_request(hi->gpio_swd, "gpio_swd");
    if (ret < 0) {
        HSD_ERR("Failed to configure gpio%u (gpio_swd) gpio_request\n", hi->gpio_swd);
        goto error_03;
    }

    ret = gpio_direction_input(hi->gpio_swd);
    if (ret < 0) {
        HSD_ERR("Failed to configure gpio%u (gpio_swd) gpio_direction_input\n", hi->gpio_swd);
        goto error_03;
    }

//LGE_CHANGE_S 20130710 ilda.jung[Audio] Disable not using GPIO
#if !defined(CONFIG_MACH_APQ8064_AWIFI)
    // initialize external_ldo_mic_bias
    if( hi->external_ldo_mic_bias > 0 ) {
        ret = gpio_request(hi->external_ldo_mic_bias, "external_ldo_mic_bias");
        if (ret < 0) {
            HSD_ERR("Failed to configure gpio%u (external_ldo_mic_bias) gpio_request\n", hi->external_ldo_mic_bias);
            goto error_04;
        }

        ret = gpio_direction_output(hi->external_ldo_mic_bias, 0);
        if (ret < 0) {
            HSD_ERR("Failed to configure gpio%u (external_ldo_mic_bias) gpio_direction_input\n", hi->external_ldo_mic_bias);
            goto error_04;
        }

        HSD_DBG("hi->external_ldo_mic_bias value = %d \n",
                gpio_cansleep(hi->external_ldo_mic_bias) ?
                gpio_get_value_cansleep(hi->external_ldo_mic_bias) : gpio_get_value(hi->external_ldo_mic_bias));
    }
#endif
//LGE_CHANGE_E 20130710 ilda.jung[Audio] Disable not using GPIO

    /* initialize irq of detection */
    hi->irq_detect = gpio_to_irq(hi->gpio_det);

    HSD_DBG("hi->irq_detect = %d\n", hi->irq_detect);

    if (hi->irq_detect < 0) {
        HSD_ERR("Failed to get interrupt number\n");
        ret = hi->irq_detect;
        goto error_05;
    }

    ret = request_threaded_irq(hi->irq_detect, NULL, earjack_det_irq_handler,
                               IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING, pdev->name, hi);

    if (ret) {
        HSD_ERR("failed to request button irq");
        goto error_05;
    }

    ret = irq_set_irq_wake(hi->irq_detect, 1);
    if (ret < 0) {
        HSD_ERR("Failed to set irq_detect interrupt wake\n");
        goto error_05;
    }

    /* initialize irq of gpio_key */
    hi->irq_key = gpio_to_irq(hi->gpio_swd);

    HSD_DBG("hi->irq_key = %d\n", hi->irq_key);

    if (hi->irq_key < 0) {
        HSD_ERR("Failed to get interrupt number\n");
        ret = hi->irq_key;
        goto error_06;
    }

    ret = request_threaded_irq(hi->irq_key, NULL, button_irq_handler,
                               IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING, pdev->name, hi);

    if (ret) {
        HSD_ERR("failed to request button irq");
        goto error_06;
    }

    disable_irq(hi->irq_key);

#if 0
    ret = irq_set_irq_wake(hi->irq_key, 1);
    if (ret < 0) {
        HSD_ERR("Failed to set irq_key interrupt wake\n");
        goto error_06;
    }
#endif

    /* initialize switch device */
    hi->sdev.name = pdata->switch_name;
    hi->sdev.print_state = lge_hsd_print_state;
    hi->sdev.print_name = lge_hsd_print_name;

    ret = switch_dev_register(&hi->sdev);
    if (ret < 0) {
        HSD_ERR("Failed to register switch device\n");
        goto error_06;
    }

    /* initialize input device */
    hi->input = input_allocate_device();
    if (!hi->input) {
        HSD_ERR("Failed to allocate input device\n");
        ret = -ENOMEM;
        goto error_07;
    }

    hi->input->name = pdata->keypad_name;

    hi->input->id.vendor    = 0x0001;
    hi->input->id.product   = 1;
    hi->input->id.version   = 1;

    // [START] // headset tx noise
    {
        struct pm8xxx_adc_chan_result result;
        int acc_read_value = 0;
        int i, rc;
        int count = 3;

        for (i = 0; i < count; i++)
        {
            rc = pm8xxx_adc_mpp_config_read(hi->adc_mpp_num, hi->adc_channel, &result);

            if (rc < 0)
            {
                if (rc == -ETIMEDOUT) {
                    HSD_ERR("[DEBUG]adc read timeout \n");
                } else {
                    HSD_ERR("[DEBUG]adc read error - %d\n", rc);
                }
            }
            else
            {
                acc_read_value = (int)result.physical;
                HSD_DBG("%s: acc_read_value - %d\n", __func__, (int)result.physical);
                break;
            }
        }
    }
    // [END]

    /*input_set_capability(hi->input, EV_SW, SW_HEADPHONE_INSERT);*/
    set_bit(EV_SYN, hi->input->evbit);
    set_bit(EV_KEY, hi->input->evbit);
    set_bit(EV_SW, hi->input->evbit);
    set_bit(hi->key_code, hi->input->keybit);
    set_bit(SW_HEADPHONE_INSERT, hi->input->swbit);
    set_bit(SW_MICROPHONE_INSERT, hi->input->swbit);
    input_set_capability(hi->input, EV_KEY, KEY_MEDIA);
    input_set_capability(hi->input, EV_KEY, KEY_VOLUMEUP);
    input_set_capability(hi->input, EV_KEY, KEY_VOLUMEDOWN);

    ret = input_register_device(hi->input);
    if (ret) {
        HSD_ERR("Failed to register input device\n");
        goto error_08;
    }

    // to detect in initialization with eacjack insertion
    if( gpio_cansleep(hi->gpio_det) ) {
        if( !gpio_get_value_cansleep(hi->gpio_det) ) {
#ifdef CONFIG_MAX1462X_USE_LOCAL_WORK_QUEUE
            queue_delayed_work(local_max1462x_workqueue, &(hi->work), 0);
#else
            schedule_delayed_work(&(hi->work), 0);
#endif
        }
    } else {
        if( !gpio_get_value_cansleep(hi->gpio_det) ) {
#ifdef CONFIG_MAX1462X_USE_LOCAL_WORK_QUEUE
            queue_delayed_work(local_max1462x_workqueue, &(hi->work), 0);
#else
            schedule_delayed_work(&(hi->work), 0);
#endif
        }
    }

    return ret;

error_08:
    input_free_device(hi->input);
error_07:
    switch_dev_unregister(&hi->sdev);
error_06:
    free_irq(hi->irq_key, 0);
error_05:
    free_irq(hi->irq_detect, 0);
//LGE_CHANGE_S 20130710 ilda.jung[Audio] Disable not using GPIO
#if !defined(CONFIG_MACH_APQ8064_AWIFI)
error_04:
    if( hi->external_ldo_mic_bias > 0 )
        gpio_free(hi->external_ldo_mic_bias);
#endif
//LGE_CHANGE_E 20130710 ilda.jung[Audio] Disable not using GPIO
error_03:
    gpio_free(hi->gpio_swd);
error_02:
    gpio_free(hi->gpio_det);
error_01:
    mutex_destroy(&hi->mutex_lock);
    kfree(hi);
    return ret;
}
Ejemplo n.º 17
0
static int __devinit gpio_ir_recv_probe(struct platform_device *pdev)
{
	struct gpio_rc_dev *gpio_dev;
	struct rc_dev *rcdev;
	const struct gpio_ir_recv_platform_data *pdata =
					pdev->dev.platform_data;
	int rc;

	if (!pdata)
		return -EINVAL;

	if (pdata->gpio_nr < 0)
		return -EINVAL;

	gpio_dev = kzalloc(sizeof(struct gpio_rc_dev), GFP_KERNEL);
	if (!gpio_dev)
		return -ENOMEM;

	rcdev = rc_allocate_device();
	if (!rcdev) {
		rc = -ENOMEM;
		goto err_allocate_device;
	}

	rcdev->driver_type = RC_DRIVER_IR_RAW;
	rcdev->allowed_protos = RC_TYPE_ALL;
	rcdev->input_name = GPIO_IR_DEVICE_NAME;
	rcdev->input_id.bustype = BUS_HOST;
	rcdev->driver_name = GPIO_IR_DRIVER_NAME;
	rcdev->map_name = RC_MAP_SAMSUNG_NECX;

	gpio_dev->rcdev = rcdev;
	gpio_dev->gpio_nr = pdata->gpio_nr;
	gpio_dev->active_low = pdata->active_low;
	gpio_dev->can_wakeup = pdata->can_wakeup;
	gpio_dev->gpio_irq_latency = pdata->swfi_latency + 1;
	gpio_dev->pm_qos_vote = 0;

	rc = gpio_request(pdata->gpio_nr, "gpio-ir-recv");
	if (rc < 0)
		goto err_gpio_request;

	gpio_dev->can_sleep = gpio_cansleep(pdata->gpio_nr);

	rc  = gpio_direction_input(pdata->gpio_nr);
	if (rc < 0)
		goto err_gpio_direction_input;

	rc = rc_register_device(rcdev);
	if (rc < 0) {
		dev_err(&pdev->dev, "failed to register rc device\n");
		goto err_register_rc_device;
	}

	platform_set_drvdata(pdev, gpio_dev);

	rc = request_any_context_irq(gpio_to_irq(pdata->gpio_nr),
				gpio_ir_recv_irq,
			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
					"gpio-ir-recv-irq", gpio_dev);
	if (rc < 0)
		goto err_request_irq;

	if (gpio_dev->can_wakeup) {
		pm_qos_add_request(&gpio_dev->pm_qos_req,
					PM_QOS_CPU_DMA_LATENCY,
					PM_QOS_DEFAULT_VALUE);
		device_init_wakeup(&pdev->dev, pdata->can_wakeup);
		setup_timer(&gpio_dev->gpio_ir_timer, gpio_ir_timer,
						(unsigned long)gpio_dev);
	}

	return 0;

err_request_irq:
	platform_set_drvdata(pdev, NULL);
	rc_unregister_device(rcdev);
err_register_rc_device:
err_gpio_direction_input:
	gpio_free(pdata->gpio_nr);
err_gpio_request:
	rc_free_device(rcdev);
	rcdev = NULL;
err_allocate_device:
	kfree(gpio_dev);
	return rc;
}
Ejemplo n.º 18
0
int gpio_event_matrix_func(struct input_dev *input_dev,
	struct gpio_event_info *info, void **data, int func)
{
	int i;
	int err;
	int key_count;
	struct gpio_kp *kp;
	struct gpio_event_matrix_info *mi;

	mi = container_of(info, struct gpio_event_matrix_info, info);
	if (func == GPIO_EVENT_FUNC_SUSPEND || func == GPIO_EVENT_FUNC_RESUME) {
		/* TODO: disable scanning */
		return 0;
	}

	if (func == GPIO_EVENT_FUNC_INIT) {
		if (mi->keymap == NULL ||
		   mi->input_gpios == NULL ||
		   mi->output_gpios == NULL) {
			err = -ENODEV;
			pr_err("gpiomatrix: Incomplete pdata\n");
			goto err_invalid_platform_data;
		}
		key_count = mi->ninputs * mi->noutputs;

		*data = kp = kzalloc(sizeof(*kp) + sizeof(kp->keys_pressed[0]) *
				     BITS_TO_LONGS(key_count), GFP_KERNEL);
		if (kp == NULL) {
			err = -ENOMEM;
			pr_err("gpiomatrix: Failed to allocate private data\n");
			goto err_kp_alloc_failed;
		}
		kp->input_dev = input_dev;
		kp->keypad_info = mi;
		set_bit(EV_KEY, input_dev->evbit);
		for (i = 0; i < key_count; i++) {
			if (mi->keymap[i])
				set_bit(mi->keymap[i] & KEY_MAX,
					input_dev->keybit);
		}

		for (i = 0; i < mi->noutputs; i++) {
			if (gpio_cansleep(mi->output_gpios[i])) {
				pr_err("gpiomatrix: unsupported output gpio %d,"
					" can sleep\n", mi->output_gpios[i]);
				err = -EINVAL;
				goto err_request_output_gpio_failed;
			}
			err = gpio_request(mi->output_gpios[i], "gpio_kp_out");
			if (err) {
				pr_err("gpiomatrix: gpio_request failed for "
					"output %d\n", mi->output_gpios[i]);
				goto err_request_output_gpio_failed;
			}
			if (mi->flags & GPIOKPF_DRIVE_INACTIVE)
				err = gpio_direction_output(mi->output_gpios[i],
					!(mi->flags & GPIOKPF_ACTIVE_HIGH));
			else
				err = gpio_direction_input(mi->output_gpios[i]);
			if (err) {
				pr_err("gpiomatrix: gpio_configure failed for "
					"output %d\n", mi->output_gpios[i]);
				goto err_output_gpio_configure_failed;
			}
		}
		for (i = 0; i < mi->ninputs; i++) {
			err = gpio_request(mi->input_gpios[i], "gpio_kp_in");
			if (err) {
				pr_err("gpiomatrix: gpio_request failed for "
					"input %d\n", mi->input_gpios[i]);
				goto err_request_input_gpio_failed;
			}
			err = gpio_direction_input(mi->input_gpios[i]);
			if (err) {
				pr_err("gpiomatrix: gpio_direction_input failed"
					" for input %d\n", mi->input_gpios[i]);
				goto err_gpio_direction_input_failed;
			}
		}
		kp->current_output = mi->noutputs;
		kp->key_state_changed = 1;

		hrtimer_init(&kp->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
		kp->timer.function = gpio_keypad_timer_func;
		wake_lock_init(&kp->wake_lock, WAKE_LOCK_SUSPEND, "gpio_kp");
		err = gpio_keypad_request_irqs(kp);
		kp->use_irq = err == 0;

		pr_info("GPIO Matrix Keypad Driver: Start keypad matrix for %s "
			"in %s mode\n", input_dev->name,
			kp->use_irq ? "interrupt" : "polling");

		if (kp->use_irq)
			wake_lock(&kp->wake_lock);
		hrtimer_start(&kp->timer, ktime_set(0, 0), HRTIMER_MODE_REL);

		return 0;
	}

	err = 0;
	kp = *data;

	if (kp->use_irq)
		for (i = mi->noutputs - 1; i >= 0; i--)
			free_irq(gpio_to_irq(mi->input_gpios[i]), kp);

	hrtimer_cancel(&kp->timer);
	wake_lock_destroy(&kp->wake_lock);
	for (i = mi->noutputs - 1; i >= 0; i--) {
err_gpio_direction_input_failed:
		gpio_free(mi->input_gpios[i]);
err_request_input_gpio_failed:
		;
	}
	for (i = mi->noutputs - 1; i >= 0; i--) {
err_output_gpio_configure_failed:
		gpio_free(mi->output_gpios[i]);
err_request_output_gpio_failed:
		;
	}
	kfree(kp);
err_kp_alloc_failed:
err_invalid_platform_data:
	return err;
}
Ejemplo n.º 19
0
static void button_pressed(struct work_struct *work)
{
    struct delayed_work *dwork = container_of(work, struct delayed_work, work);
    struct hsd_info *hi = container_of(dwork, struct hsd_info, work_for_key_pressed);
    struct pm8xxx_adc_chan_result result;
    struct ear_3button_info_table *table;

    int acc_read_value=0, i=0, rc=0, table_size=ARRAY_SIZE(max1462x_ear_3button_type_data);

    HSD_DBG("button_pressed begin \n");

    if( gpio_cansleep(hi->gpio_det) ) {
        if( gpio_get_value_cansleep(hi->gpio_det) ) {
            HSD_ERR("button_pressed but ear jack is plugged out already! just ignore the event.\n");
            return;
        }
    } else {
        if( gpio_get_value(hi->gpio_det) ) {
            HSD_ERR("button_pressed but ear jack is plugged out already! just ignore the event.\n");
            return;
        }
    }

    for (i = 0; i < table_size; i++) {
        rc = pm8xxx_adc_mpp_config_read(hi->adc_mpp_num, hi->adc_channel, &result);

        if (rc < 0) {
            if (rc == -ETIMEDOUT) {
                HSD_ERR("button_pressed : adc read timeout[try count:%d]\n", i+1);
            } else {
                HSD_ERR("button_pressed : adc read error - rc:%d[try count:%d]\n", rc, i+1);
            }
        } else {
            acc_read_value = (int)result.physical;
            HSD_DBG("======= acc_read_value - %d [try count:%d] =======\n", (int)result.physical, i+1);

            if( acc_read_value > VDOWN_MAX ) {
                HSD_DBG("********** read again acc_read_value [try count:%d] **********\n", i+1);
                continue;
            }

            // if success, exit from loop
            break;
        }
    }

    for (i = 0; i < table_size; i++) {
        table = &max1462x_ear_3button_type_data[i];
        // [AUDIO_BSP] 20130110, junday.lee, include min value '=' for 1 button earjack (ADC value= 0)
        if ((acc_read_value <= table->PERMISS_REANGE_MAX)&&(acc_read_value >= table->PERMISS_REANGE_MIN)) {

            atomic_set(&hi->btn_state, HEADSET_BTN_PRESSED);

            switch(table->ADC_HEADSET_BUTTON) {
            case KEY_MEDIA:
                input_report_key(hi->input, KEY_MEDIA, 1);
                HSD_DBG("********** KEY_MEDIA **********\n");
                break;

            case KEY_VOLUMEUP:
                input_report_key(hi->input, KEY_VOLUMEUP, 1);
                HSD_DBG("********** KEY_VOLUMEUP **********\n");
                break;

            case KEY_VOLUMEDOWN:
                input_report_key(hi->input, KEY_VOLUMEDOWN, 1);
                HSD_DBG("********** KEY_VOLUMEDOWN **********\n");
                break;
            }

            table->PRESS_OR_NOT = 1;
            input_sync(hi->input);
            break;
        }
    }

    HSD_DBG("button_pressed end \n");
}
static int archer_led_probe(struct platform_device *pdev)
{	

	struct led_platform_data *pdata = pdev->dev.platform_data;
	struct led_info *cur_led;
	struct archer_led_data *leds_data, *led_dat;
	
	int i, ret = 0;

	printk("[LED] %s +\n", __func__);

	if (!pdata)
		return -EBUSY;

	leds_data = kzalloc(sizeof(struct archer_led_data) * pdata->num_leds,
				GFP_KERNEL);
	if (!leds_data)
		return -ENOMEM;

	for (i = 0; i < pdata->num_leds; i++) {
		cur_led = &pdata->leds[i];
		led_dat = &leds_data[i];
		printk("[LED] %s hw_revision=%d \n", __func__, hw_revision);
		if(hw_revision < 3 ) 
		{
			vmmc2 = regulator_get( &pdev->dev, "vmmc2" );
			if( IS_ERR( vmmc2 ) )
			{
				printk("PSENSOR: %s: regulator_get failed to get vmmc2!\n", __func__);
				goto err;
			}
		}
		else 
		{
			ret = gpio_request(OMAP_GPIO_LED_EN, cur_led->name);
			if (ret < 0)
				goto err;
			led_dat->gpio = OMAP_GPIO_LED_EN;
			led_dat->can_sleep = gpio_cansleep(OMAP_GPIO_LED_EN);
			gpio_direction_output(OMAP_GPIO_LED_EN, 1);

			ret = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x00, TWL4030_VMMC2_DEV_GRP);
			if (ret)
				printk(" leds-archer.c fail to set reousrce off TWL4030_VMMC2_DEV_GRP\n");
		}


		led_dat->cdev.name = cur_led->name;
		led_dat->cdev.default_trigger = cur_led->default_trigger;
		led_dat->cdev.brightness_set = archer_led_set;
		led_dat->cdev.brightness = LED_OFF;
		led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;

//		gpio_direction_output(led_dat->gpio, led_dat->active_low);

//		INIT_WORK(&led_dat->work, gpio_led_work);

		ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
		if (ret < 0) {
//			gpio_free(led_dat->gpio);
			regulator_put( vmmc2 );
			goto err;
		}
	}

	platform_set_drvdata(pdev, leds_data);

	return 0;

err:
	if (i > 0) {
		for (i = i - 1; i >= 0; i--) {
			led_classdev_unregister(&leds_data[i].cdev);
//			cancel_work_sync(&leds_data[i].work);
//			gpio_free(leds_data[i].gpio);
		}
	}

	kfree(leds_data);

	return ret;
}
Ejemplo n.º 21
0
int gpio_event_matrix_func(struct gpio_event_input_devs *input_devs,
	struct gpio_event_info *info, void **data, int func)
{
	int i;
	int err;
	int key_count;
	int phone_call_status;
	int fm_radio_status;
	int irq;
	static int irq_status = 1;
	struct gpio_kp *kp;
	struct gpio_event_matrix_info *mi;

	mi = container_of(info, struct gpio_event_matrix_info, info);
	if (func == GPIO_EVENT_FUNC_SUSPEND || func == GPIO_EVENT_FUNC_RESUME) {
		/* TODO: disable scanning */
		if (mi->detect_phone_status == 0) {
			if (func == GPIO_EVENT_FUNC_SUSPEND)
				irq_status = 0;
			else
				irq_status = 1;
		} else {
			phone_call_status = gpio_event_get_phone_call_status() & 0x01;
			fm_radio_status = gpio_event_get_fm_radio_status() & 0x01;
			KEY_LOGI("%s: mi->ninputs: %d, func&0x01 = %d, phone_call_status=%d, fm_radio_status=%d\n", __func__, mi->ninputs, func & 0x01, phone_call_status, fm_radio_status);

			if (irq_status != ((func & 0x01) | phone_call_status | fm_radio_status)) {
				irq_status = ((func & 0x01) | phone_call_status | fm_radio_status);
				KEY_LOGI("%s: irq_status %d \n", __func__, irq_status);
			} else {
				KEY_LOGI("%s: irq_status %d, did not change\n", __func__, irq_status);
				return 0;
			}
		}

		for (i = 0; i < mi->ninputs; i++) {
			irq = gpio_to_irq(mi->input_gpios[i]);
			err = irq_set_irq_wake(irq, irq_status);
			if (err)
				KEY_LOGE("gpiomatrix: set_irq_wake failed ,irq_status %d ,for input irq %d,%d\n",  irq_status, i, irq);
			else
				KEY_LOGD("%s: set ok,irq_status %d, irq %d = %d\n", __func__, irq_status, i, irq);
		}
		return 0;
	}

	if (func == GPIO_EVENT_FUNC_INIT) {
		if (mi->keymap == NULL ||
		   mi->input_gpios == NULL ||
		   mi->output_gpios == NULL) {
			err = -ENODEV;
			KEY_LOGE("gpiomatrix: Incomplete pdata\n");
			goto err_invalid_platform_data;
		}
		key_count = mi->ninputs * mi->noutputs;

		*data = kp = kzalloc(sizeof(*kp) + sizeof(kp->keys_pressed[0]) *
				     BITS_TO_LONGS(key_count), GFP_KERNEL);
		if (kp == NULL) {
			err = -ENOMEM;
			KEY_LOGE("gpiomatrix: Failed to allocate private data\n");
			goto err_kp_alloc_failed;
		}
		kp->input_devs = input_devs;
		kp->keypad_info = mi;
		for (i = 0; i < key_count; i++) {
			unsigned short keyentry = mi->keymap[i];
			unsigned short keycode = keyentry & MATRIX_KEY_MASK;
			unsigned short dev = keyentry >> MATRIX_CODE_BITS;
			if (dev >= input_devs->count) {
				KEY_LOGE("gpiomatrix: bad device index %d >= "
					"%d for key code %d\n",
					dev, input_devs->count, keycode);
				err = -EINVAL;
				goto err_bad_keymap;
			}
			if (keycode && keycode <= KEY_MAX)
				input_set_capability(input_devs->dev[dev],
							EV_KEY, keycode);
		}

#ifndef CONFIG_ARCH_MSM8X60
		if (mi->setup_ninputs_gpio)
			mi->setup_ninputs_gpio();
#else
		if (mi->setup_matrix_gpio)
			mi->setup_matrix_gpio();
#endif

		for (i = 0; i < mi->noutputs; i++) {
			err = gpio_request(mi->output_gpios[i], "gpio_kp_out");
			if (err) {
				KEY_LOGE("gpiomatrix: gpio_request failed for "
					"output %d\n", mi->output_gpios[i]);
				goto err_request_output_gpio_failed;
			}
			if (gpio_cansleep(mi->output_gpios[i])) {
				KEY_LOGE("gpiomatrix: unsupported output gpio %d,"
					" can sleep\n", mi->output_gpios[i]);
				err = -EINVAL;
				goto err_output_gpio_configure_failed;
			}
			if (mi->flags & GPIOKPF_DRIVE_INACTIVE)
				err = gpio_direction_output(mi->output_gpios[i],
					!(mi->flags & GPIOKPF_ACTIVE_HIGH));
			else
				err = gpio_direction_input(mi->output_gpios[i]);
			if (err) {
				KEY_LOGE("gpiomatrix: gpio_configure failed for "
					"output %d\n", mi->output_gpios[i]);
				goto err_output_gpio_configure_failed;
			}
		}
		for (i = 0; i < mi->ninputs; i++) {
			err = gpio_request(mi->input_gpios[i], "gpio_kp_in");
			if (err) {
				KEY_LOGE("gpiomatrix: gpio_request failed for "
					"input %d\n", mi->input_gpios[i]);
				goto err_request_input_gpio_failed;
			}
			err = gpio_direction_input(mi->input_gpios[i]);
			if (err) {
				KEY_LOGE("gpiomatrix: gpio_direction_input failed"
					" for input %d\n", mi->input_gpios[i]);
				goto err_gpio_direction_input_failed;
			}
		}
		kp->current_output = mi->noutputs;
		kp->key_state_changed = 1;

#ifndef CONFIG_ARCH_MSM8X60
		hrtimer_init(&kp->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
		kp->timer.function = gpio_keypad_timer_func;
#else
		km_queue = create_singlethread_workqueue("km_queue");
		INIT_WORK(&kp->work, gpio_keypad_timer_func);
#endif
		wake_lock_init(&kp->wake_lock, WAKE_LOCK_SUSPEND, "gpio_kp");
		err = gpio_keypad_request_irqs(kp);
		kp->use_irq = err == 0;
#ifndef CONFIG_ARCH_MSM8X60
		kp_use_irq = kp->use_irq;
#endif

		KEY_LOGI("GPIO Matrix Keypad Driver: Start keypad matrix for "
			"%s%s in %s mode\n", input_devs->dev[0]->name,
			(input_devs->count > 1) ? "..." : "",
			kp->use_irq ? "interrupt" : "polling");

		if (kp->use_irq)
			wake_lock(&kp->wake_lock);
#ifndef CONFIG_ARCH_MSM8X60
		hrtimer_start(&kp->timer, ktime_set(0, 0), HRTIMER_MODE_REL);
#else
		queue_work(km_queue, &kp->work);
#endif
		return 0;
	}

	err = 0;
	kp = *data;

	if (kp->use_irq)
		for (i = mi->noutputs - 1; i >= 0; i--)
			free_irq(gpio_to_irq(mi->input_gpios[i]), kp);

#ifndef CONFIG_ARCH_MSM8X60
	hrtimer_cancel(&kp->timer);
#else
	cancel_work_sync(&kp->work);
#endif
	wake_lock_destroy(&kp->wake_lock);
	for (i = mi->noutputs - 1; i >= 0; i--) {
err_gpio_direction_input_failed:
		gpio_free(mi->input_gpios[i]);
err_request_input_gpio_failed:
		;
	}
	for (i = mi->noutputs - 1; i >= 0; i--) {
err_output_gpio_configure_failed:
		gpio_free(mi->output_gpios[i]);
err_request_output_gpio_failed:
		;
	}
err_bad_keymap:
	kfree(kp);
err_kp_alloc_failed:
err_invalid_platform_data:
	return err;
}