Пример #1
0
static void pwm_lut_delayed_fade_out(struct work_struct *work)
{
	struct pm8058_led_data *ldata;
	int id, mode;
	ldata = container_of(work, struct pm8058_led_data,
			     led_delayed_work.work);
	id = bank_to_id(ldata->bank);
	mode = (id == PM_PWM_LED_KPD) ? PM_PWM_CONF_PWM1 :
					PM_PWM_CONF_PWM1 + (ldata->bank - 4);
	LED_INFO_LOG("%s \n", __func__);
	pm8058_pwm_lut_enable(ldata->pwm_led, 0);
	pm8058_pwm_config_led(ldata->pwm_led, id, mode, 0);
}
Пример #2
0
void button_backlight_flash(int brightness_key)
{
	int milliamps;
	int id, mode;

	LED_INFO_LOG("%s brightness_key: %d\n", __func__,brightness_key);
	pwm_disable(for_key_led_data->pwm_led);
	id = bank_to_id(for_key_led_data->bank);
	mode = (id == PM_PWM_LED_KPD) ? PM_PWM_CONF_PWM1 :
					PM_PWM_CONF_PWM1 + (for_key_led_data->bank - 4);

	if (brightness_key) {
		flag_hold_virtual_key = 1;
		milliamps = (for_key_led_data->flags & PM8058_LED_DYNAMIC_BRIGHTNESS_EN) ?
	    for_key_led_data->out_current * brightness_key / LED_FULL :
	    for_key_led_data->out_current;
		pm8058_pwm_config_led(for_key_led_data->pwm_led, id, mode, milliamps);
		pwm_config(for_key_led_data->pwm_led, 320000, 640000);
		pwm_enable(for_key_led_data->pwm_led);
		LED_INFO_LOG("%s Button_backlight flash on\n", __func__);
	} else {
		pwm_disable(for_key_led_data->pwm_led);
		pwm_disable(for_key_led_data->pwm_led);
		pm8058_pwm_config_led(for_key_led_data->pwm_led, id, mode, 0);
		LED_INFO_LOG("%s Button_backlight flash off\n", __func__);
		if (virtual_key_state != 0){
			milliamps = (for_key_led_data->flags & PM8058_LED_DYNAMIC_BRIGHTNESS_EN) ?
			for_key_led_data->out_current * brightness_key / LED_FULL :
			for_key_led_data->out_current;
			pm8058_pwm_config_led(for_key_led_data->pwm_led, id, mode, milliamps);
			pwm_config(for_key_led_data->pwm_led, 64000, 64000);
			pwm_enable(for_key_led_data->pwm_led);
			LED_INFO_LOG("%s Button_backlight state resume\n", __func__);
		}
		flag_hold_virtual_key = 0;
	}
}
Пример #3
0
static ssize_t pm8058_led_blink_store(struct device *dev,
				       struct device_attribute *attr,
				       const char *buf, size_t count)
{
	struct led_classdev *led_cdev;
	struct pm8058_led_data *ldata;
	int id, mode;
	int val;
	int enable = 0;
#ifdef CONFIG_HTC_HEADSET_MISC
	int *pduties;
#endif

/*struct timespec ts1, ts2;*/

	val = -1;
	sscanf(buf, "%u", &val);
	if (val < 0 || val > 255)
		return -EINVAL;

	led_cdev = (struct led_classdev *) dev_get_drvdata(dev);
	ldata = container_of(led_cdev, struct pm8058_led_data, ldev);

	id = bank_to_id(ldata->bank);
	mode = (id == PM_PWM_LED_KPD) ? PM_PWM_CONF_PWM1 :
					PM_PWM_CONF_PWM1 + (ldata->bank - 4);

	if (ldata->flags & PM8058_LED_BLINK_EN)
		pm8058_pwm_config_led(ldata->pwm_led, id, mode,
				      ldata->out_current);

	LED_INFO_LOG("%s: bank %d blink %d\n", __func__, ldata->bank, val);

	enable = (val > 0) ? 1 : 0;
	if (strcmp(ldata->ldev.name, "charming-led") == 0)
		charming_led_enable(enable);

	switch (val) {
	case -1: /* stop flashing */
		pwm_disable(ldata->pwm_led);
		if (ldata->flags & PM8058_LED_BLINK_EN)
			pm8058_pwm_config_led(ldata->pwm_led, id, mode, 0);
		break;
	case 0:
		pwm_disable(ldata->pwm_led);
		if (led_cdev->brightness) {
			pwm_config(ldata->pwm_led, 6400 * pwm_coefficient / 100, 6400);
			pwm_enable(ldata->pwm_led);
		} else {
			if (ldata->flags & PM8058_LED_BLINK_EN)
				pm8058_pwm_config_led(ldata->pwm_led, id,
						      mode, 0);
		}
		break;
	case 1:
		pwm_disable(ldata->pwm_led);
		pwm_config(ldata->pwm_led, 64000, 2000000);
		pwm_enable(ldata->pwm_led);
		break;
	case 2:
		cancel_delayed_work_sync(&ldata->led_delayed_work);
		pwm_disable(ldata->pwm_led);
		ldata->duty_time_ms = 64;
		ldata->period_us = 2000000;
		queue_delayed_work(g_led_work_queue, &ldata->led_delayed_work,
				   msecs_to_jiffies(310));
		break;
	case 3:
		cancel_delayed_work_sync(&ldata->led_delayed_work);
		pwm_disable(ldata->pwm_led);
		ldata->duty_time_ms = 64;
		ldata->period_us = 2000000;
		queue_delayed_work(g_led_work_queue, &ldata->led_delayed_work,
				   msecs_to_jiffies(1000));
		break;
	case 4:
		pwm_disable(ldata->pwm_led);
		pwm_config(ldata->pwm_led, 1000000, 2000000);
#if 0
		pwm_conf.pwm_size = 9;
		pwm_conf.clk = PM_PWM_CLK_1KHZ;
		pwm_conf.pre_div = PM_PWM_PREDIVIDE_2;
		pwm_conf.pre_div_exp = 1;
		pwm_conf.pwm_value = 512/2;
		pwm_conf.bypass_lut = 1;
		pwm_configure(ldata->pwm_led, &pwm_conf);
#endif
		pwm_enable(ldata->pwm_led);
		break;
	case 5:
		pwm_disable(ldata->pwm_led);
		pwm_config(ldata->pwm_led, 100000, 200000);
		pwm_enable(ldata->pwm_led);
		break;
#ifdef CONFIG_HTC_HEADSET_MISC
	case 6:
		pm8058_pwm_config_led(ldata->pwm_led, id, mode,
				      ldata->out_current);
		pduties = &duties[ldata->start_index];
		pm8058_pwm_lut_config(ldata->pwm_led, ldata->period_us,
				      pduties, ldata->duty_time_ms,
				      ldata->start_index, ldata->duites_size,
				      0, 0, ldata->lut_flag);
		pm8058_pwm_lut_enable(ldata->pwm_led, 0);
		pm8058_pwm_lut_enable(ldata->pwm_led, 1);
		break;
	case 7:
		pwm_disable(ldata->pwm_led);
		pwm_config(ldata->pwm_led, 64000, 4000000);
		pwm_enable(ldata->pwm_led);
		break;
#endif
	default:
		LED_ERR_LOG(KERN_INFO "%s: bank %d not support blink %d\n", __func__, ldata->bank, val);
		return -EINVAL;
	}
	return count;
}
Пример #4
0
extern void pm8058_drvx_led_brightness_set(struct led_classdev *led_cdev,
					   enum led_brightness brightness)
{
	struct pm8058_led_data *ldata;
	int *pduties;
	int id, mode;
	int lut_flag;
	int milliamps;
	int enable = 0;

	ldata = container_of(led_cdev, struct pm8058_led_data, ldev);

	pwm_disable(ldata->pwm_led);
	cancel_delayed_work_sync(&ldata->led_delayed_work);

	id = bank_to_id(ldata->bank);
	mode = (id == PM_PWM_LED_KPD) ? PM_PWM_CONF_PWM1 :
					PM_PWM_CONF_PWM1 + (ldata->bank - 4);

	brightness = (brightness > LED_FULL) ? LED_FULL : brightness;
	brightness = (brightness < LED_OFF) ? LED_OFF : brightness;
	LED_INFO_LOG("%s: bank %d brightness %d +\n", __func__,
	       ldata->bank, brightness);

	enable = (brightness) ? 1 : 0;
	if (strcmp(ldata->ldev.name, "charming-led") == 0)
		charming_led_enable(enable);

	lut_flag = ldata->lut_flag & ~(PM_PWM_LUT_LOOP | PM_PWM_LUT_REVERSE);
	virtual_key_state = enable;
	if (flag_hold_virtual_key == 1) {
		LED_INFO_LOG("%s, Return control by button_backlight flash \n", __func__);
		return;
	}

	if (brightness) {
		milliamps = (ldata->flags & PM8058_LED_DYNAMIC_BRIGHTNESS_EN) ?
			    ldata->out_current * brightness / LED_FULL :
			    ldata->out_current;
		pm8058_pwm_config_led(ldata->pwm_led, id, mode, milliamps);
		if (ldata->flags & PM8058_LED_LTU_EN) {
			pduties = &duty_array[ldata->start_index];
			pm8058_pwm_lut_config(ldata->pwm_led,
					      ldata->period_us,
					      pduties,
					      ldata->duty_time_ms,
					      ldata->start_index,
					      ldata->duites_size,
					      0, 0,
					      lut_flag);
			pm8058_pwm_lut_enable(ldata->pwm_led, 0);
			pm8058_pwm_lut_enable(ldata->pwm_led, 1);
		} else {
			pwm_config(ldata->pwm_led, 64000, 64000);
			pwm_enable(ldata->pwm_led);
		}
	} else {
		if (ldata->flags & PM8058_LED_LTU_EN) {
			wake_lock_timeout(&pmic_led_wake_lock,HZ*2);
			pduties = &duty_array[ldata->start_index +
					  ldata->duites_size];
			pm8058_pwm_lut_config(ldata->pwm_led,
					      ldata->period_us,
					      pduties,
					      ldata->duty_time_ms,
					      ldata->start_index +
					      ldata->duites_size,
					      ldata->duites_size,
					      0, 0,
					      lut_flag);
			pm8058_pwm_lut_enable(ldata->pwm_led, 1);
			queue_delayed_work(g_led_work_queue,
					   &ldata->led_delayed_work,
					   msecs_to_jiffies(ldata->duty_time_ms * ldata->duites_size));

			LED_INFO_LOG("%s: bank %d fade out brightness %d -\n", __func__,
			ldata->bank, brightness);
			return;
		} else
			pwm_disable(ldata->pwm_led);
		pm8058_pwm_config_led(ldata->pwm_led, id, mode, 0);
	}
	LED_INFO_LOG("%s: bank %d brightness %d -\n", __func__, ldata->bank, brightness);
}
Пример #5
0
static int pm8058_led_probe(struct platform_device *pdev)
{
	struct pm8058_led_platform_data *pdata;
	struct pm8058_led_data *ldata;
	int i, ret;

	ret = -ENOMEM;

	pdata = pdev->dev.platform_data;

	if (pdata == NULL) {
		pr_err("%s: platform data is NULL\n", __func__);
		return -ENODEV;
	}

	if (!pdata->num_leds) {
		pr_err("%s: LED num is 0\n", __func__);
		return 0;
	}

	ldata = kzalloc(sizeof(struct pm8058_led_data)
			* pdata->num_leds, GFP_KERNEL);
	if (ldata == NULL) {
		ret = -ENOMEM;
		pr_err("%s: failed on allocate ldata\n", __func__);
		goto err_exit;
	}

	dev_set_drvdata(&pdev->dev, ldata);

	wake_lock_init(&pmic_led_wake_lock, WAKE_LOCK_SUSPEND, "pmic_led");

	g_led_work_queue = create_workqueue("led");
	if (!g_led_work_queue)
		goto err_create_work_queue;

	for (i = 0; i < 64; i++)
		duties[i] = pdata->duties[i];

	for (i = 0; i < pdata->num_leds; i++) {
		ldata[i].led_config = pdata->led_config + i;
		ldata[i].ldev.name = pdata->led_config[i].name;
		ldata[i].bank = pdata->led_config[i].bank;
		ldata[i].flags =  pdata->led_config[i].flags;
		ldata[i].pwm_size =  pdata->led_config[i].pwm_size;
		ldata[i].clk =  pdata->led_config[i].clk;
		ldata[i].pre_div =  pdata->led_config[i].pre_div;
		ldata[i].pre_div_exp =  pdata->led_config[i].pre_div_exp;
		ldata[i].pwm_value =  pdata->led_config[i].pwm_value;
		ldata[i].period_us =  pdata->led_config[i].period_us;
		ldata[i].start_index =  pdata->led_config[i].start_index;
		ldata[i].duites_size =  pdata->led_config[i].duites_size;
		ldata[i].duty_time_ms =  pdata->led_config[i].duty_time_ms;
		ldata[i].lut_flag =  pdata->led_config[i].lut_flag;
		ldata[i].out_current =  pdata->led_config[i].out_current;
		switch (pdata->led_config[i].type) {
		case PM8058_LED_CURRENT:
			if (ldata[i].flags & PM8058_LED_BLINK_EN)
				INIT_DELAYED_WORK(&ldata[i].led_delayed_work,
						  led_blink_do_work);
			else
				INIT_DELAYED_WORK(&ldata[i].led_delayed_work,
						  pwm_lut_delayed_fade_out);
			ldata[i].pwm_led = pwm_request(ldata[i].bank,
						ldata[i].ldev.name);
			ldata[i].ldev.brightness_set =
					pm8058_drvx_led_brightness_set;
			break;
		case PM8058_LED_RGB:
			INIT_DELAYED_WORK(&ldata[i].led_delayed_work,
					  led_blink_do_work);
		case PM8058_LED_PWM:
			ldata[i].pwm_led = pwm_request(ldata[i].bank,
						       ldata[i].ldev.name);
			ldata[i].ldev.brightness_set =
					pm8058_pwm_led_brightness_set;
			break;
		case PM8058_LED_DRVX:
			if (ldata[i].flags & PM8058_LED_BLINK_EN)
				INIT_DELAYED_WORK(&ldata[i].led_delayed_work,
						  led_blink_do_work);
			else
				INIT_DELAYED_WORK(&ldata[i].led_delayed_work,
						  pwm_lut_delayed_fade_out);
			ldata[i].pwm_led = pwm_request(ldata[i].bank,
						ldata[i].ldev.name);
			ldata[i].ldev.brightness_set =
					pm8058_drvx_led_brightness_set;
			break;
		}

		if (ldata[i].bank == 6) {
			if (board_mfg_mode() == 0) {
				pwm_config(ldata[i].pwm_led, 64000, 64000);
				pwm_enable(ldata[i].pwm_led);
			} else {
				pwm_disable(ldata->pwm_led);
				pm8058_pwm_config_led(ldata->pwm_led, 2, 3, 0);
			}
		}

		ret = led_classdev_register(&pdev->dev, &ldata[i].ldev);
		if (ret < 0) {
			pr_err("%s: failed on led_classdev_register [%s]\n",
				__func__, ldata[i].ldev.name);
			goto err_register_led_cdev;
		}
	}

	for (i = 0; i < pdata->num_leds; i++) {
		if (pdata->led_config[i].type == PM8058_LED_RGB ||
		    ldata[i].flags & PM8058_LED_BLINK_EN) {
			ret = device_create_file(ldata[i].ldev.dev,
						 &dev_attr_blink);
			if (ret < 0) {
				pr_err("%s: Failed to create attr blink"
				       " [%d]\n", __func__, i);
				goto err_register_attr_blink;
			}
		}
	}

	for (i = 0; i < pdata->num_leds; i++) {
		if (pdata->led_config[i].type == PM8058_LED_RGB ||
		    ldata[i].flags & PM8058_LED_BLINK_EN) {
			ret = device_create_file(ldata[i].ldev.dev,
						 &dev_attr_off_timer);
			if (ret < 0) {
				pr_err("%s: Failed to create attr off timer"
				       " [%d]\n", __func__, i);
				goto err_register_attr_off_timer;
			}
			INIT_WORK(&ldata[i].led_work, led_work_func);
			alarm_init(&ldata[i].led_alarm,
				   ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP,
				   led_alarm_handler);
		}
	}

	for (i = 0; i < pdata->num_leds; i++) {
		if (ldata[i].bank < 3)
			continue;
		ret = device_create_file(ldata[i].ldev.dev, &dev_attr_currents);
		if (ret < 0) {
			pr_err("%s: Failed to create attr blink [%d]\n",
			       __func__, i);
			goto err_register_attr_currents;
		}
	}

	return 0;

err_register_attr_currents:
	for (i--; i >= 0; i--) {
		if (ldata[i].bank < 3)
			continue;
		device_remove_file(ldata[i].ldev.dev, &dev_attr_currents);
	}
	i = pdata->num_leds;

err_register_attr_off_timer:
	for (i--; i >= 0; i--) {
		if (pdata->led_config[i].type == PM8058_LED_RGB ||
		    ldata[i].flags & PM8058_LED_BLINK_EN) {
			device_remove_file(ldata[i].ldev.dev,
					   &dev_attr_off_timer);
		}
	}
	i = pdata->num_leds;

err_register_attr_blink:
	for (i--; i >= 0; i--) {
		if (pdata->led_config[i].type == PM8058_LED_RGB ||
		    ldata[i].flags & PM8058_LED_BLINK_EN) {
			device_remove_file(ldata[i].ldev.dev, &dev_attr_blink);
		}
	}
	i = pdata->num_leds;

err_register_led_cdev:
	for (i--; i >= 0; i--) {
		switch (pdata->led_config[i].type) {
		case PM8058_LED_RGB:
		case PM8058_LED_PWM:
		case PM8058_LED_DRVX:
			pwm_free(ldata[i].pwm_led);
			break;
		}
		led_classdev_unregister(&ldata[i].ldev);
	}
	destroy_workqueue(g_led_work_queue);

err_create_work_queue:
	kfree(ldata);

err_exit:
	wake_lock_destroy(&pmic_led_wake_lock);
	return ret;
}
Пример #6
0
static ssize_t pm8058_led_blink_store(struct device *dev,
				       struct device_attribute *attr,
				       const char *buf, size_t count)
{
	struct led_classdev *led_cdev;
	struct pm8058_led_data *ldata;
	int id, mode;
	int val;

/*struct timespec ts1, ts2;*/

	val = -1;
	sscanf(buf, "%u", &val);
	if (val < 0 || val > 255)
		return -EINVAL;

	led_cdev = (struct led_classdev *) dev_get_drvdata(dev);
	ldata = container_of(led_cdev, struct pm8058_led_data, ldev);

	id = bank_to_id(ldata->bank);
	mode = (id == PM_PWM_LED_KPD) ? PM_PWM_CONF_PWM1 :
					PM_PWM_CONF_PWM1 + (ldata->bank - 4);

	if (ldata->flags & PM8058_LED_BLINK_EN)
		pm8058_pwm_config_led(ldata->pwm_led, id, mode,
				      ldata->out_current);

	printk(KERN_INFO "%s: bank %d blink %d +\n", __func__, ldata->bank, val);

	switch (val) {
	case -1: /* stop flashing */
		pwm_disable(ldata->pwm_led);
		if (ldata->flags & PM8058_LED_BLINK_EN)
			pm8058_pwm_config_led(ldata->pwm_led, id, mode, 0);
		break;
	case 0:
		pwm_disable(ldata->pwm_led);
		if (led_cdev->brightness) {
			pwm_config(ldata->pwm_led, 64000, 64000);
			pwm_enable(ldata->pwm_led);
		} else {
			if (ldata->flags & PM8058_LED_BLINK_EN)
				pm8058_pwm_config_led(ldata->pwm_led, id,
						      mode, 0);
		}
		break;
	case 1:
		pwm_disable(ldata->pwm_led);
		pwm_config(ldata->pwm_led, 64000, 2000000);
		pwm_enable(ldata->pwm_led);
		break;
	case 2:
		cancel_delayed_work_sync(&ldata->led_delayed_work);
		pwm_disable(ldata->pwm_led);
		ldata->duty_time_ms = 64;
		ldata->period_us = 2000000;
		queue_delayed_work(g_led_work_queue, &ldata->led_delayed_work,
				   msecs_to_jiffies(310));
		break;
	case 3:
		cancel_delayed_work_sync(&ldata->led_delayed_work);
		pwm_disable(ldata->pwm_led);
		ldata->duty_time_ms = 64;
		ldata->period_us = 2000000;
		queue_delayed_work(g_led_work_queue, &ldata->led_delayed_work,
				   msecs_to_jiffies(1000));
		break;
	case 4:
		pwm_disable(ldata->pwm_led);
		pwm_config(ldata->pwm_led, 1000000, 2000000);
#if 0
		pwm_conf.pwm_size = 9;
		pwm_conf.clk = PM_PWM_CLK_1KHZ;
		pwm_conf.pre_div = PM_PWM_PREDIVIDE_2;
		pwm_conf.pre_div_exp = 1;
		pwm_conf.pwm_value = 512/2;
		pwm_conf.bypass_lut = 1;
		pwm_configure(ldata->pwm_led, &pwm_conf);
#endif
		pwm_enable(ldata->pwm_led);
		break;
	default:
		printk(KERN_INFO "%s: bank %d blink %d -\n", __func__, ldata->bank, val);
		return -EINVAL;
	}

	printk(KERN_INFO "%s: bank %d blink %d -\n", __func__, ldata->bank, val);
	return count;
}
Пример #7
0
static void pm8058_drvx_led_brightness_set(struct led_classdev *led_cdev,
					   enum led_brightness brightness)
{
	struct pm8058_led_data *ldata;
	int *pduties;
	int id, mode;
	int milliamps;

	ldata = container_of(led_cdev, struct pm8058_led_data, ldev);

	pwm_disable(ldata->pwm_led);
	cancel_delayed_work_sync(&ldata->led_delayed_work);

	id = bank_to_id(ldata->bank);
	mode = (id == PM_PWM_LED_KPD) ? PM_PWM_CONF_PWM1 :
					PM_PWM_CONF_PWM1 + (ldata->bank - 4);

	brightness = (brightness > LED_FULL) ? LED_FULL : brightness;
	brightness = (brightness < LED_OFF) ? LED_OFF : brightness;
	printk(KERN_INFO "%s: bank %d brightness %d +\n", __func__,
	       ldata->bank, brightness);

	if (brightness) {
		milliamps = (ldata->flags & PM8058_LED_DYNAMIC_BRIGHTNESS_EN) ?
			    ldata->out_current * brightness / LED_FULL :
			    ldata->out_current;
		pm8058_pwm_config_led(ldata->pwm_led, id, mode, milliamps);
		if (ldata->flags & PM8058_LED_LTU_EN) {
			pduties = &duties[ldata->start_index];
			pm8058_pwm_lut_config(ldata->pwm_led,
					      ldata->period_us,
					      pduties,
					      ldata->duty_time_ms,
					      ldata->start_index,
					      ldata->duites_size,
					      0, 0,
					      ldata->lut_flag);
			pm8058_pwm_lut_enable(ldata->pwm_led, 0);
			pm8058_pwm_lut_enable(ldata->pwm_led, 1);
		} else {
			pwm_config(ldata->pwm_led, 64000, 64000);
			pwm_enable(ldata->pwm_led);
		}
	} else {
		if (ldata->flags & PM8058_LED_LTU_EN) {
			wake_lock(&pmic_led_wake_lock);
			pduties = &duties[ldata->start_index +
					  ldata->duites_size];
			pm8058_pwm_lut_config(ldata->pwm_led,
					      ldata->period_us,
					      pduties,
					      ldata->duty_time_ms,
					      ldata->start_index +
					      ldata->duites_size,
					      ldata->duites_size,
					      0, 0,
					      ldata->lut_flag);
			pm8058_pwm_lut_enable(ldata->pwm_led, 1);
			queue_delayed_work(g_led_work_queue,
					   &ldata->led_delayed_work,
					   msecs_to_jiffies(ldata->duty_time_ms * ldata->duty_time_ms));

			printk(KERN_INFO "%s: bank %d fade out brightness %d -\n", __func__,
			ldata->bank, brightness);
			return;
		} else
			pwm_disable(ldata->pwm_led);
		pm8058_pwm_config_led(ldata->pwm_led, id, mode, 0);
	}
	printk(KERN_INFO "%s: bank %d brightness %d -\n", __func__, ldata->bank, brightness);
}