static ssize_t pm8xxx_led_off_timer_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct led_classdev *led_cdev; struct pm8xxx_led_data *ldata; int min, sec; uint16_t off_timer; ktime_t interval; ktime_t next_alarm; min = -1; sec = -1; sscanf(buf, "%d %d", &min, &sec); if (min < 0 || min > 255) return -EINVAL; if (sec < 0 || sec > 255) return -EINVAL; led_cdev = (struct led_classdev *) dev_get_drvdata(dev); ldata = container_of(led_cdev, struct pm8xxx_led_data, cdev); LED_INFO("Setting %s off_timer to %d min %d sec \n", led_cdev->name, min, sec); off_timer = min * 60 + sec; alarm_cancel(&ldata->led_alarm); cancel_work_sync(&ldata->led_work); if (off_timer) { interval = ktime_set(off_timer, 0); next_alarm = ktime_add(alarm_get_elapsed_realtime(), interval); alarm_start_range(&ldata->led_alarm, next_alarm, next_alarm); } return count; }
static void led_enable_set(u16 reg, int value) { int ret; uint8_t ctrldata; LED_INFO("%s, reg=0x%X, value=%d\n", __func__, reg, value); /* set bit ALTFUNCEN = 0 */ ret = intel_scu_ipc_ioread8(CHGDETGPO_REG, &ctrldata); if (ret) { LED_ERR(" IPC Failed to read %d\n", ret); } ctrldata &= ~(BIT(6)); ret = intel_scu_ipc_iowrite8(CHGDETGPO_REG, ctrldata); if (ret) { LED_ERR(" IPC Failed to write %d\n", ret); } ret = intel_scu_ipc_ioread8(reg, &ctrldata); if (ret) { LED_ERR(" IPC Failed to read %d\n", ret); } if (value) ctrldata |= (BIT(5)|BIT(4)|BIT(0)); else ctrldata &= ~(BIT(5)|BIT(4)|BIT(0)); ret = intel_scu_ipc_iowrite8(reg, ctrldata); if (ret) { LED_ERR(" IPC Failed to write %d\n", ret); } power_on_flag = value; }
static ssize_t pm8xxx_led_currents_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int currents = 0; struct led_classdev *led_cdev; struct pm8xxx_led_data *ldata; sscanf(buf, "%d", ¤ts); if (currents < 0) return -EINVAL; led_cdev = (struct led_classdev *)dev_get_drvdata(dev); ldata = container_of(led_cdev, struct pm8xxx_led_data, cdev); LED_INFO("%s: bank %d currents %d\n", __func__, ldata->bank, currents); if (currents <= 60) ldata->out_current = currents; ldata->cdev.brightness_set(led_cdev, 0); if (currents) ldata->cdev.brightness_set(led_cdev, 255); return count; }
static void led_work_func(struct work_struct *work) { struct pm8xxx_led_data *ldata; int rc, offset; u8 level; ldata = container_of(work, struct pm8xxx_led_data, led_work); LED_INFO("%s: bank %d sync %d\n", __func__, ldata->bank, ldata->led_sync); pwm_disable(ldata->pwm_led); if (ldata->gpio_status_switch != NULL) ldata->gpio_status_switch(0); if(ldata->led_sync) { if (!strcmp(ldata->cdev.name, "green")){ if (green_back_led_data->gpio_status_switch != NULL) green_back_led_data->gpio_status_switch(0); pwm_disable(green_back_led_data->pwm_led); level = ( 0 << PM8XXX_DRV_LED_CTRL_SHIFT) & PM8XXX_DRV_LED_CTRL_MASK; offset = PM8XXX_LED_OFFSET(green_back_led_data->id); green_back_led_data->reg &= ~PM8XXX_DRV_LED_CTRL_MASK; green_back_led_data->reg |= level; rc = pm8xxx_writeb(green_back_led_data->dev->parent, SSBI_REG_ADDR_LED_CTRL(offset), green_back_led_data->reg); } if (!strcmp(ldata->cdev.name, "amber")){ if (amber_back_led_data->gpio_status_switch != NULL) amber_back_led_data->gpio_status_switch(0); pwm_disable(amber_back_led_data->pwm_led); level = ( 0 << PM8XXX_DRV_LED_CTRL_SHIFT) & PM8XXX_DRV_LED_CTRL_MASK; offset = PM8XXX_LED_OFFSET(amber_back_led_data->id); amber_back_led_data->reg &= ~PM8XXX_DRV_LED_CTRL_MASK; amber_back_led_data->reg |= level; rc = pm8xxx_writeb(amber_back_led_data->dev->parent, SSBI_REG_ADDR_LED_CTRL(offset), amber_back_led_data->reg); } } }
void pm8xxx_led_current_set_for_key(int brightness_key) { int rc, offset; static u8 level, register_key; LED_INFO("%s brightness_key: %d\n", __func__,brightness_key); #ifdef CONFIG_BB_MOD printk("[BB] current_set_for_key %d \n", brightness_key); #endif if (brightness_key) { flag_hold_virtual_key = 1; level = (40 << PM8XXX_DRV_LED_CTRL_SHIFT) & PM8XXX_DRV_LED_CTRL_MASK; offset = PM8XXX_LED_OFFSET(for_key_led_data->id); register_key = pm8xxxx_led_pwm_mode(for_key_led_data->id); register_key &= ~PM8XXX_DRV_LED_CTRL_MASK; register_key |= level; rc = pm8xxx_writeb(for_key_led_data->dev->parent, SSBI_REG_ADDR_LED_CTRL(offset), register_key); if (rc) LED_ERR("%s can't set (%d) led value rc=%d\n", __func__, PM8XXX_ID_LED_0, rc); pwm_config(for_key_led_data->pwm_led, 320000, 640000); pwm_enable(for_key_led_data->pwm_led); } else { pwm_disable(for_key_led_data->pwm_led); level = (0 << PM8XXX_DRV_LED_CTRL_SHIFT) & PM8XXX_DRV_LED_CTRL_MASK; offset = PM8XXX_LED_OFFSET(for_key_led_data->id); register_key = pm8xxxx_led_pwm_mode(for_key_led_data->id); register_key &= ~PM8XXX_DRV_LED_CTRL_MASK; register_key |= level; rc = pm8xxx_writeb(for_key_led_data->dev->parent, SSBI_REG_ADDR_LED_CTRL(offset), register_key); if (rc) LED_ERR("%s can't set (%d) led value rc=%d\n", __func__, PM8XXX_ID_LED_0, rc); if (virtual_key_state != 0){ level = 0; register_key = 0; level = (40 << PM8XXX_DRV_LED_CTRL_SHIFT) & PM8XXX_DRV_LED_CTRL_MASK; offset = PM8XXX_LED_OFFSET(for_key_led_data->id); register_key = pm8xxxx_led_pwm_mode(for_key_led_data->id); register_key &= ~PM8XXX_DRV_LED_CTRL_MASK; register_key |= level; rc = pm8xxx_writeb(for_key_led_data->dev->parent, SSBI_REG_ADDR_LED_CTRL(offset), register_key); if (rc) LED_ERR("%s can't set (%d) led value rc=%d\n", __func__, PM8XXX_ID_LED_0, rc); pwm_config(for_key_led_data->pwm_led, 64000, 64000); pwm_enable(for_key_led_data->pwm_led); } flag_hold_virtual_key = 0; } }
static void pm8xxx_led_gpio_set(struct led_classdev *led_cdev, enum led_brightness brightness) { struct pm8xxx_led_data *led = container_of(led_cdev, struct pm8xxx_led_data, cdev); LED_INFO("%s, bank:%d, brightness:%d\n", __func__, led->bank, brightness); if (led->gpio_status_switch != NULL) led->gpio_status_switch(0); pwm_disable(led->pwm_led); if (brightness) { if (led->gpio_status_switch != NULL) led->gpio_status_switch(1); pwm_config(led->pwm_led, 64000, 64000); pwm_enable(led->pwm_led); } }
static ssize_t pm8xxx_led_pwm_coefficient_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int pwm_coefficient1 = 0; struct led_classdev *led_cdev; struct pm8xxx_led_data *ldata; sscanf(buf, "%d", &pwm_coefficient1); if ((pwm_coefficient1 < 0) || (pwm_coefficient1 > 100)) { LED_INFO("%s: pwm_coefficient = %d, out of range.\n", __func__, pwm_coefficient1); return -EINVAL; } led_cdev = (struct led_classdev *)dev_get_drvdata(dev); ldata = container_of(led_cdev, struct pm8xxx_led_data, cdev); LED_INFO("%s: pwm_coefficient %d\n", __func__, pwm_coefficient1); ldata->pwm_coefficient = pwm_coefficient1; return count; }
static int asus_led_remove(struct i2c_client *client) { struct led_info_priv *priv; int i; LED_INFO("%s +++ \n", __func__); priv = dev_get_drvdata(&client->dev); for (i = 0; i < priv->num_leds; i++) { #ifdef CONTROL_LED device_remove_file(priv->leds[i].cdev.dev, &dev_attr_disable); #endif device_remove_file(priv->leds[i].cdev.dev, &dev_attr_blink); delete_led(&priv->leds[i]); } dev_set_drvdata(&client->dev, NULL); kfree(priv); return 0; }
static ssize_t pm8xxx_led_lut_coefficient_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int lut_coefficient1 = 0; int i; struct led_classdev *led_cdev; struct pm8xxx_led_data *ldata; sscanf(buf, "%d", &lut_coefficient1); if (lut_coefficient1 < 0) return -EINVAL; led_cdev = (struct led_classdev *)dev_get_drvdata(dev); ldata = container_of(led_cdev, struct pm8xxx_led_data, cdev); LED_INFO("%s: lut_coefficient %d\n", __func__, lut_coefficient1); for (i = 0; i < 16; i++) { dutys_array[i] = (*(ldata->duties + i)) * lut_coefficient1 / 100; } lut_coefficient = lut_coefficient1; return count; }
void led_brightness_set(int led, int brightness) { //led=0:red, led=1:green LED_INFO("%s +++ , brightness=%d, led=%d\n", __func__, brightness, led); if(brightness==0) { if((led==0)&&(red_led_flag==1)) { led_i2c_write(led_client, SELECT1_REG, (led_i2c_read(led_client, SELECT1_REG)&(~RED_BIT))); red_led_flag = 0; }else if((led==1)&&(green_led_flag==1)) { led_i2c_write(led_client, SELECT1_REG, (led_i2c_read(led_client, SELECT1_REG)&(~GREEN_BIT))); green_led_flag = 0; } if((red_led_flag==0)&&(green_led_flag==0)&&(red_blink_flag==0)&&(green_blink_flag==0)) led_enable_set(INDCAT_EN, 0); }else if(brightness>0&&brightness<=255) { led_enable_set(INDCAT_EN, 1); if(led==0) { led_i2c_write(led_client, SELECT1_REG, (led_i2c_read(led_client, SELECT1_REG)|RED_BIT)); red_led_flag = 1; }else if(led==1) { led_i2c_write(led_client, SELECT1_REG, (led_i2c_read(led_client, SELECT1_REG)|GREEN_BIT)); green_led_flag = 1; } } }
static int __devinit pm8xxx_led_probe(struct platform_device *pdev) { const struct pm8xxx_led_platform_data *pdata = pdev->dev.platform_data; struct pm8xxx_led_configure *curr_led; struct pm8xxx_led_data *led, *led_dat; int i, j, ret = -ENOMEM; if (pdata == NULL) { LED_ERR("platform data not supplied\n"); return -EINVAL; } led = kcalloc(pdata->num_leds + 1, sizeof(*led), GFP_KERNEL); if (led == NULL) { LED_ERR("failed to alloc memory\n"); return -ENOMEM; } wake_lock_init(&pmic_led_wake_lock, WAKE_LOCK_SUSPEND, "pmic_led"); g_led_work_queue = create_workqueue("pm8xxx-led"); if (g_led_work_queue == NULL) { LED_ERR("failed to create workqueue\n"); goto err_create_work_queue; } for (i = 0; i < pdata->num_leds; i++) { curr_led = &pdata->leds[i]; led_dat = &led[i]; led_dat->cdev.name = curr_led->name; led_dat->id = curr_led->flags; led_dat->bank = curr_led->flags; led_dat->function_flags = curr_led->function_flags; led_dat->start_index = curr_led->start_index; led_dat->duty_time_ms = curr_led->duty_time_ms; led_dat->period_us = curr_led->period_us; led_dat->duites_size = curr_led->duites_size; led_dat->lut_flag = curr_led->lut_flag; led_dat->out_current = curr_led->out_current; led_dat->duties = &(curr_led->duties[0]); led_dat->led_sync = curr_led->led_sync; led_dat->pwm_led = pwm_request(led_dat->bank, led_dat->cdev.name); led_dat->lpm_power = curr_led->lpm_power; if (curr_led->duties[1]) { for (j = 0; j < 64; j++) dutys_array[j] = *(led_dat->duties + j); } if( curr_led->pwm_coefficient > 0 ) led_dat->pwm_coefficient = curr_led->pwm_coefficient; else led_dat->pwm_coefficient = 100; if (curr_led->blink_duty_per_2sec > 0) led_dat->blink_duty_per_2sec = curr_led->blink_duty_per_2sec; else led_dat->blink_duty_per_2sec = 64000; switch (led_dat->id) { case PM8XXX_ID_GPIO24: case PM8XXX_ID_GPIO25: case PM8XXX_ID_GPIO26: led_dat->cdev.brightness_set = pm8xxx_led_gpio_set; if (curr_led->gpio_status_switch != NULL) led_dat->gpio_status_switch = curr_led->gpio_status_switch; break; case PM8XXX_ID_LED_0: case PM8XXX_ID_LED_1: case PM8XXX_ID_LED_2: led_dat->cdev.brightness_set = pm8xxx_led_current_set; if (led_dat->function_flags & LED_PWM_FUNCTION) { led_dat->reg = pm8xxxx_led_pwm_mode(led_dat->id); INIT_DELAYED_WORK(&led[i].fade_delayed_work, led_fade_do_work); } else led_dat->reg = PM8XXX_LED_MODE_MANUAL; break; case PM8XXX_ID_LED_KB_LIGHT: break; } led_dat->cdev.brightness = LED_OFF; led_dat->dev = &pdev->dev; ret = led_classdev_register(&pdev->dev, &led_dat->cdev); if (ret) { LED_ERR("unable to register led %d,ret=%d\n", led_dat->id, ret); goto err_register_led_cdev; } // blink buttons if (led_dat->id == PM8XXX_ID_LED_0) { // storing buttons light dev for blinking led_cdev_buttons = &led_dat->cdev; ret = device_create_file(led_dat->cdev.dev, &dev_attr_blink_buttons); if (ret < 0) { LED_ERR("%s: Failed to create %d attr blink_buttons\n", __func__, i); goto err_register_attr_currents; } } // blink buttons end if (led_dat->id >= PM8XXX_ID_LED_2 && led_dat->id <= PM8XXX_ID_LED_0) { ret = device_create_file(led_dat->cdev.dev, &dev_attr_currents); if (ret < 0) { LED_ERR("%s: Failed to create %d attr currents\n", __func__, i); goto err_register_attr_currents; } } if (led_dat->id >= PM8XXX_ID_LED_2 && led_dat->id <= PM8XXX_ID_LED_0) { ret = device_create_file(led_dat->cdev.dev, &dev_attr_lut_coefficient); if (ret < 0) { LED_ERR("%s: Failed to create %d attr lut_coefficient\n", __func__, i); goto err_register_attr_lut_coefficient; } } if ((led_dat->id <= PM8XXX_ID_GPIO26) || (led_dat->id <= PM8XXX_ID_LED_2) || (led_dat->id <= PM8XXX_ID_LED_1)) { ret = device_create_file(led_dat->cdev.dev, &dev_attr_pwm_coefficient); if (ret < 0) { LED_ERR("%s: Failed to create %d attr pwm_coefficient\n", __func__, i); goto err_register_attr_pwm_coefficient; } } if (led_dat->function_flags & LED_BLINK_FUNCTION) { INIT_DELAYED_WORK(&led[i].blink_delayed_work, led_blink_do_work); ret = device_create_file(led_dat->cdev.dev, &dev_attr_blink); if (ret < 0) { LED_ERR("%s: Failed to create %d attr blink\n", __func__, i); goto err_register_attr_blink; } ret = device_create_file(led_dat->cdev.dev, &dev_attr_off_timer); if (ret < 0) { LED_ERR("%s: Failed to create %d attr off timer\n", __func__, i); goto err_register_attr_off_timer; } alarm_init(&led[i].led_alarm, ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP, led_alarm_handler); INIT_WORK(&led[i].led_work, led_work_func); } if (!strcmp(led_dat->cdev.name, "button-backlight")) { for_key_led_data = led_dat; } if (!strcmp(led_dat->cdev.name, "green-back")) { LED_INFO("%s: green-back, 000 probe, led_dat = %x\n", __func__, (unsigned int)led_dat); green_back_led_data = led_dat; } if (!strcmp(led_dat->cdev.name, "amber-back")) { LED_INFO("%s: amber-back\n", __func__); amber_back_led_data = led_dat; } } pm8xxx_leds = led; platform_set_drvdata(pdev, led); return 0; err_register_attr_off_timer: if (i > 0) { for (i = i - 1; i >= 0; i--) { if (led[i].function_flags & LED_BLINK_FUNCTION) device_remove_file(led[i].cdev.dev, &dev_attr_off_timer); } } i = pdata->num_leds; err_register_attr_blink: if (i > 0) { for (i = i - 1; i >= 0; i--) { if (led[i].function_flags & LED_BLINK_FUNCTION) device_remove_file(led[i].cdev.dev, &dev_attr_blink); } } i = pdata->num_leds; err_register_attr_pwm_coefficient: if (i > 0) { for (i = i - 1; i >= 0; i--) { if (led[i].function_flags <= PM8XXX_ID_GPIO26) device_remove_file(led[i].cdev.dev, &dev_attr_pwm_coefficient); } } i = pdata->num_leds; err_register_attr_lut_coefficient: if (i > 0) { for (i = i - 1; i >= 0; i--) { if (led[i].function_flags >= PM8XXX_ID_LED_2 && led[i].function_flags <= PM8XXX_ID_LED_0) device_remove_file(led[i].cdev.dev, &dev_attr_lut_coefficient); } } i = pdata->num_leds; err_register_attr_currents: if (i > 0) { for (i = i - 1; i >= 0; i--) { if (led[i].function_flags >= PM8XXX_ID_LED_2 && led[i].function_flags <= PM8XXX_ID_LED_0) device_remove_file(led[i].cdev.dev, &dev_attr_currents); } } i = pdata->num_leds; err_register_led_cdev: if (i > 0) { for (i = i - 1; i >= 0; i--) { pwm_free(led[i].pwm_led); led_classdev_unregister(&led[i].cdev); } } destroy_workqueue(g_led_work_queue); err_create_work_queue: kfree(led); wake_lock_destroy(&pmic_led_wake_lock); return ret; }
static ssize_t pm8xxx_led_blink_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct led_classdev *led_cdev; struct pm8xxx_led_data *ldata; int val; int level, offset; int led_is_green; val = -1; sscanf(buf, "%u", &val); if (val < 0 || val > 255) return -EINVAL; current_blink= val; led_cdev = (struct led_classdev *) dev_get_drvdata(dev); ldata = container_of(led_cdev, struct pm8xxx_led_data, cdev); LED_INFO("%s: bank %d blink %d sync %d\n", __func__, ldata->bank, val, ldata->led_sync); printk("%s: [BB] bank %d blink %d sync %d\n", __func__, ldata->bank, val, ldata->led_sync); if (!strcmp(ldata->cdev.name, "green")) { led_is_green = 1; } if (!strcmp(ldata->cdev.name, "amber")) { led_is_green = 0; } switch (val) { case BLINK_STOP: if (ldata->gpio_status_switch != NULL) ldata->gpio_status_switch(0); pwm_disable(ldata->pwm_led); if(ldata->led_sync) { if (!strcmp(ldata->cdev.name, "green")) { if (green_back_led_data->gpio_status_switch != NULL) green_back_led_data->gpio_status_switch(0); pwm_disable(green_back_led_data->pwm_led); } if (!strcmp(ldata->cdev.name, "amber")) { if (amber_back_led_data->gpio_status_switch != NULL) amber_back_led_data->gpio_status_switch(0); pwm_disable(amber_back_led_data->pwm_led); } } if (blink_buttons > 0) { if (led_is_green == 1) { green_blink_value = 0; } else { amber_blink_value = 0; } pm8xxx_buttons_blink(0); } break; case BLINK_UNCHANGE: pwm_disable(ldata->pwm_led); if (led_cdev->brightness) { if (ldata->gpio_status_switch != NULL) ldata->gpio_status_switch(1); pwm_config(ldata->pwm_led, 6400 * ldata->pwm_coefficient / 100, 6400); pwm_enable(ldata->pwm_led); if(ldata->led_sync) { if (!strcmp(ldata->cdev.name, "green")) { if (green_back_led_data->gpio_status_switch != NULL) green_back_led_data->gpio_status_switch(1); pwm_config(green_back_led_data->pwm_led, 64000, 64000); pwm_enable(green_back_led_data->pwm_led); } if (!strcmp(ldata->cdev.name, "amber")) { if (amber_back_led_data->gpio_status_switch != NULL) amber_back_led_data->gpio_status_switch(1); pwm_config(amber_back_led_data->pwm_led, 64000, 64000); pwm_enable(amber_back_led_data->pwm_led); } } if (blink_buttons > 0 && val > 0) { if (led_is_green == 1) { green_blink_value = 1; } else { amber_blink_value = 1; } pm8xxx_buttons_blink(1); } } else { pwm_disable(ldata->pwm_led); if (ldata->gpio_status_switch != NULL) ldata->gpio_status_switch(0); if(ldata->led_sync) { if (!strcmp(ldata->cdev.name, "green")){ if (green_back_led_data->gpio_status_switch != NULL) green_back_led_data->gpio_status_switch(0); pwm_disable(green_back_led_data->pwm_led); level = ( 0 << PM8XXX_DRV_LED_CTRL_SHIFT) & PM8XXX_DRV_LED_CTRL_MASK; offset = PM8XXX_LED_OFFSET(green_back_led_data->id); green_back_led_data->reg &= ~PM8XXX_DRV_LED_CTRL_MASK; green_back_led_data->reg |= level; pm8xxx_writeb(green_back_led_data->dev->parent, SSBI_REG_ADDR_LED_CTRL(offset), green_back_led_data->reg); } if (!strcmp(ldata->cdev.name, "amber")){ if (amber_back_led_data->gpio_status_switch != NULL) amber_back_led_data->gpio_status_switch(0); pwm_disable(amber_back_led_data->pwm_led); level = ( 0 << PM8XXX_DRV_LED_CTRL_SHIFT) & PM8XXX_DRV_LED_CTRL_MASK; offset = PM8XXX_LED_OFFSET(amber_back_led_data->id); amber_back_led_data->reg &= ~PM8XXX_DRV_LED_CTRL_MASK; amber_back_led_data->reg |= level; pm8xxx_writeb(amber_back_led_data->dev->parent, SSBI_REG_ADDR_LED_CTRL(offset), amber_back_led_data->reg); } } if (blink_buttons > 0) { if (led_is_green == 1) { green_blink_value = 0; } else { amber_blink_value = 0; } pm8xxx_buttons_blink(0); } } break; case BLINK_64MS_PER_2SEC: if (ldata->gpio_status_switch != NULL) ldata->gpio_status_switch(1); pwm_disable(ldata->pwm_led); pwm_config(ldata->pwm_led, ldata->blink_duty_per_2sec, 2000000); pwm_enable(ldata->pwm_led); if(ldata->led_sync) { if (!strcmp(ldata->cdev.name, "green")) { if (green_back_led_data->gpio_status_switch != NULL) green_back_led_data->gpio_status_switch(1); pwm_disable(green_back_led_data->pwm_led); pwm_config(green_back_led_data->pwm_led, ldata->blink_duty_per_2sec, 2000000); pwm_enable(green_back_led_data->pwm_led); } if (!strcmp(ldata->cdev.name, "amber")) { if (amber_back_led_data->gpio_status_switch != NULL) amber_back_led_data->gpio_status_switch(1); pwm_disable(amber_back_led_data->pwm_led); pwm_config(amber_back_led_data->pwm_led, ldata->blink_duty_per_2sec, 2000000); pwm_enable(amber_back_led_data->pwm_led); } } if (blink_buttons > 0 && val > 0) { if (led_is_green == 1) { green_blink_value = 1; } else { amber_blink_value = 1; } pm8xxx_buttons_blink(1); } break; case BLINK_64MS_ON_310MS_PER_2SEC: cancel_delayed_work_sync(&ldata->blink_delayed_work); pwm_disable(ldata->pwm_led); ldata->duty_time_ms = 64; ldata->period_us = 2000000; if(ldata->led_sync) { if (!strcmp(ldata->cdev.name, "green")) { pwm_disable(green_back_led_data->pwm_led); green_back_led_data->duty_time_ms = 64; green_back_led_data->period_us = 2000000; } if (!strcmp(ldata->cdev.name, "amber")) { pwm_disable(amber_back_led_data->pwm_led); amber_back_led_data->duty_time_ms = 64; amber_back_led_data->period_us = 2000000; } } queue_delayed_work(g_led_work_queue, &ldata->blink_delayed_work, msecs_to_jiffies(310)); break; case BLINK_64MS_ON_2SEC_PER_2SEC: cancel_delayed_work_sync(&ldata->blink_delayed_work); pwm_disable(ldata->pwm_led); ldata->duty_time_ms = 64; ldata->period_us = 2000000; if(ldata->led_sync) { if (!strcmp(ldata->cdev.name, "green")) { pwm_disable(green_back_led_data->pwm_led); green_back_led_data->duty_time_ms = 64; green_back_led_data->period_us = 2000000; } if (!strcmp(ldata->cdev.name, "amber")) { pwm_disable(amber_back_led_data->pwm_led); amber_back_led_data->duty_time_ms = 64; amber_back_led_data->period_us = 2000000; } } queue_delayed_work(g_led_work_queue, &ldata->blink_delayed_work, msecs_to_jiffies(1000)); break; case BLINK_1SEC_PER_2SEC: pwm_disable(ldata->pwm_led); pwm_config(ldata->pwm_led, 1000000, 2000000); pwm_enable(ldata->pwm_led); if(ldata->led_sync) { if (!strcmp(ldata->cdev.name, "green")) { pwm_disable(green_back_led_data->pwm_led); pwm_config(green_back_led_data->pwm_led, 1000000, 2000000); pwm_enable(green_back_led_data->pwm_led); } if (!strcmp(ldata->cdev.name, "amber")) { pwm_disable(amber_back_led_data->pwm_led); pwm_config(amber_back_led_data->pwm_led, 1000000, 2000000); pwm_enable(amber_back_led_data->pwm_led); } } break; default: LED_ERR("%s: bank %d did not support blink type %d\n", __func__, ldata->bank, val); return -EINVAL; } return count; }
static void pm8xxx_led_gpio_set(struct led_classdev *led_cdev, enum led_brightness brightness) { int rc, offset; u8 level; struct pm8xxx_led_data *led = container_of(led_cdev, struct pm8xxx_led_data, cdev); LED_INFO("%s, bank:%d, brightness:%d sync: %d\n", __func__, led->bank, brightness, led->led_sync); if (led->gpio_status_switch != NULL) led->gpio_status_switch(0); pwm_disable(led->pwm_led); if(led->led_sync) { if (!strcmp(led->cdev.name, "green")){ if (green_back_led_data->gpio_status_switch != NULL) green_back_led_data->gpio_status_switch(0); pwm_disable(green_back_led_data->pwm_led); level = ( 0 << PM8XXX_DRV_LED_CTRL_SHIFT) & PM8XXX_DRV_LED_CTRL_MASK; offset = PM8XXX_LED_OFFSET(green_back_led_data->id); green_back_led_data->reg &= ~PM8XXX_DRV_LED_CTRL_MASK; green_back_led_data->reg |= level; rc = pm8xxx_writeb(green_back_led_data->dev->parent, SSBI_REG_ADDR_LED_CTRL(offset), green_back_led_data->reg); } if (!strcmp(led->cdev.name, "amber")){ if (amber_back_led_data->gpio_status_switch != NULL) amber_back_led_data->gpio_status_switch(0); pwm_disable(amber_back_led_data->pwm_led); level = ( 0 << PM8XXX_DRV_LED_CTRL_SHIFT) & PM8XXX_DRV_LED_CTRL_MASK; offset = PM8XXX_LED_OFFSET(amber_back_led_data->id); amber_back_led_data->reg &= ~PM8XXX_DRV_LED_CTRL_MASK; amber_back_led_data->reg |= level; rc = pm8xxx_writeb(amber_back_led_data->dev->parent, SSBI_REG_ADDR_LED_CTRL(offset), amber_back_led_data->reg); } } if (brightness) { if (led->gpio_status_switch != NULL) led->gpio_status_switch(1); pwm_config(led->pwm_led, 6400 * led->pwm_coefficient / 100, 6400); pwm_enable(led->pwm_led); if(led->led_sync) { if (!strcmp(led->cdev.name, "green")) { if (green_back_led_data->gpio_status_switch != NULL) green_back_led_data->gpio_status_switch(1); level = (green_back_led_data->out_current << PM8XXX_DRV_LED_CTRL_SHIFT) & PM8XXX_DRV_LED_CTRL_MASK; offset = PM8XXX_LED_OFFSET(green_back_led_data->id); green_back_led_data->reg &= ~PM8XXX_DRV_LED_CTRL_MASK; green_back_led_data->reg |= level; rc = pm8xxx_writeb(green_back_led_data->dev->parent, SSBI_REG_ADDR_LED_CTRL(offset), green_back_led_data->reg); pwm_config(green_back_led_data->pwm_led, 64000, 64000); pwm_enable(green_back_led_data->pwm_led); } if (!strcmp(led->cdev.name, "amber")) { if (amber_back_led_data->gpio_status_switch != NULL) amber_back_led_data->gpio_status_switch(1); level = (amber_back_led_data->out_current << PM8XXX_DRV_LED_CTRL_SHIFT) & PM8XXX_DRV_LED_CTRL_MASK; offset = PM8XXX_LED_OFFSET(amber_back_led_data->id); amber_back_led_data->reg &= ~PM8XXX_DRV_LED_CTRL_MASK; amber_back_led_data->reg |= level; rc = pm8xxx_writeb(amber_back_led_data->dev->parent, SSBI_REG_ADDR_LED_CTRL(offset), amber_back_led_data->reg); pwm_config(amber_back_led_data->pwm_led, 64000, 64000); pwm_enable(amber_back_led_data->pwm_led); } } } }
static void pm8xxx_led_current_set_flagged(struct led_classdev *led_cdev, enum led_brightness brightness, int blink) { struct pm8xxx_led_data *led = container_of(led_cdev, struct pm8xxx_led_data, cdev); int rc, offset; u8 level; int *pduties; LED_INFO("%s, bank:%d, brightness:%d\n", __func__, led->bank, brightness); cancel_delayed_work_sync(&led->fade_delayed_work); virtual_key_state = brightness; if (flag_hold_virtual_key == 1) { LED_INFO("%s, key control \n", __func__); return; } if(brightness) { level = (led->out_current << PM8XXX_DRV_LED_CTRL_SHIFT) & PM8XXX_DRV_LED_CTRL_MASK; offset = PM8XXX_LED_OFFSET(led->id); led->reg &= ~PM8XXX_DRV_LED_CTRL_MASK; led->reg |= level; rc = pm8xxx_writeb(led->dev->parent, SSBI_REG_ADDR_LED_CTRL(offset), led->reg); if (rc) LED_ERR("%s can't set (%d) led value rc=%d\n", __func__, led->id, rc); if (led->function_flags & LED_BRETH_FUNCTION) { if (blink == 0) { buttons_led_is_on = 1; // no blink needed pduties = &dutys_array[0]; pm8xxx_pwm_lut_config(led->pwm_led, led->period_us, pduties, led->duty_time_ms, led->start_index, led->duites_size, 0, 0, led->lut_flag); } else { pduties = &dutys_array[0]; // LUT_LOOP for blinking pm8xxx_pwm_lut_config(led->pwm_led, led->period_us, pduties, led->duty_time_ms, // slower, 2x led->start_index, led->duites_size * 8, // 16 duty entries -> original size * 2, + 6 * 8 zeroes for pause 0, 0, PM_PWM_LUT_LOOP | PM_PWM_LUT_PAUSE_HI_EN); } pm8xxx_pwm_lut_enable(led->pwm_led, 0); pm8xxx_pwm_lut_enable(led->pwm_led, 1); } else { pwm_config(led->pwm_led, 6400 * led->pwm_coefficient / 100, 6400); pwm_enable(led->pwm_led); } } else { if (led->function_flags & LED_BRETH_FUNCTION) { buttons_led_is_on = 0; wake_lock_timeout(&pmic_led_wake_lock, HZ*2); pduties = &dutys_array[8]; pm8xxx_pwm_lut_config(led->pwm_led, led->period_us, pduties, led->duty_time_ms, led->start_index, led->duites_size, 0, 0, led->lut_flag); pm8xxx_pwm_lut_enable(led->pwm_led, 0); pm8xxx_pwm_lut_enable(led->pwm_led, 1); queue_delayed_work(g_led_work_queue, &led->fade_delayed_work, msecs_to_jiffies(led->duty_time_ms*led->duites_size)); } else { pwm_disable(led->pwm_led); level = (0 << PM8XXX_DRV_LED_CTRL_SHIFT) & PM8XXX_DRV_LED_CTRL_MASK; offset = PM8XXX_LED_OFFSET(led->id); led->reg &= ~PM8XXX_DRV_LED_CTRL_MASK; led->reg |= level; rc = pm8xxx_writeb(led->dev->parent, SSBI_REG_ADDR_LED_CTRL(offset), led->reg); if (rc) LED_ERR("%s can't set (%d) led value rc=%d\n", __func__, led->id, rc); } } }
static ssize_t blink_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct led_classdev *led_cdev = dev_get_drvdata(dev); struct led_info_data *led_dat = container_of(led_cdev, struct led_info_data, cdev); int value; sscanf(buf, "%d", &value); LED_INFO("%s +++, value=%d, led=%s\n", __func__, value, led_dat->cdev.name); #ifdef CONTROL_LED if(disable_led_flag==0) { #endif if(value==0) { /* stop blink */ if((!strcmp(led_dat->cdev.name, "red"))&&(power_on_flag==1)) { led_i2c_write(led_client, SELECT1_REG, (led_i2c_read(led_client, SELECT1_REG)&(~RED_BIT))); led_i2c_write(led_client, SELECT1_REG, (led_i2c_read(led_client, SELECT2_REG)&(~RED_BIT))); red_blink_flag = 0; red_led_flag = 0; }else if((!strcmp(led_dat->cdev.name, "green"))&&(power_on_flag==1)) { led_i2c_write(led_client, SELECT1_REG, (led_i2c_read(led_client, SELECT1_REG)&(~GREEN_BIT))); led_i2c_write(led_client, SELECT1_REG, (led_i2c_read(led_client, SELECT2_REG)&(~GREEN_BIT))); green_blink_flag = 0; green_led_flag = 0; } /*power off*/ if((red_led_flag==0)&&(green_led_flag==0)&&(red_blink_flag==0)&&(green_blink_flag==0)) led_enable_set(INDCAT_EN, 0); } else if(value>0&&value<=100) { /* power on*/ led_enable_set(INDCAT_EN, 1); /* start blink */ if(!strcmp(led_dat->cdev.name, "red")) { led_i2c_write(led_client, SELECT1_REG, (led_i2c_read(led_client, SELECT1_REG)|RED_BIT)); led_i2c_write(led_client, SELECT2_REG, (led_i2c_read(led_client, SELECT2_REG)|RED_BIT)); led_i2c_write(led_client, FADE_ON_TIME_REG, 0x40); led_i2c_write(led_client, FULLY_ON_TIME_REG, 0x41); led_i2c_write(led_client, F_FULLY_OFF_TIME_REG, 0x4C); led_i2c_write(led_client, FADE_OFF_TIME_REG, 0x40); led_i2c_write(led_client, S_FULLY_OFF_TIME_REG, 0x4C); red_led_flag = 1; red_blink_flag = 1; }else if(!strcmp(led_dat->cdev.name, "green")) { led_i2c_write(led_client, SELECT1_REG, (led_i2c_read(led_client, SELECT1_REG)|GREEN_BIT)); led_i2c_write(led_client, SELECT2_REG, (led_i2c_read(led_client, SELECT2_REG)|GREEN_BIT)); led_i2c_write(led_client, FADE_ON_TIME_REG, 0x40); led_i2c_write(led_client, FULLY_ON_TIME_REG, 0x41); led_i2c_write(led_client, F_FULLY_OFF_TIME_REG, 0x4A); led_i2c_write(led_client, FADE_OFF_TIME_REG, 0x40); led_i2c_write(led_client, S_FULLY_OFF_TIME_REG, 0x4A); green_led_flag = 1; green_blink_flag = 1; } }else LED_INFO("%s, incorrect pwm value:%d (0-100).\n", __func__, value); #ifdef CONTROL_LED } #endif return count; }
extern void pm8xxx_led_current_set(struct led_classdev *led_cdev, enum led_brightness brightness) { struct pm8xxx_led_data *led = container_of(led_cdev, struct pm8xxx_led_data, cdev); int rc, offset; u8 level; int *pduties; LED_INFO("%s, bank:%d, brightness:%d\n", __func__, led->bank, brightness); cancel_delayed_work_sync(&led->fade_delayed_work); virtual_key_state = brightness; if (flag_hold_virtual_key == 1) { LED_INFO("%s, key control \n", __func__); return; } if(brightness) { level = (led->out_current << PM8XXX_DRV_LED_CTRL_SHIFT) & PM8XXX_DRV_LED_CTRL_MASK; offset = PM8XXX_LED_OFFSET(led->id); led->reg &= ~PM8XXX_DRV_LED_CTRL_MASK; led->reg |= level; rc = pm8xxx_writeb(led->dev->parent, SSBI_REG_ADDR_LED_CTRL(offset), led->reg); if (rc) LED_ERR("%s can't set (%d) led value rc=%d\n", __func__, led->id, rc); if (led->function_flags & LED_BRETH_FUNCTION) { pduties = led->duties; pm8xxx_pwm_lut_config(led->pwm_led, led->period_us, pduties, led->duty_time_ms, led->start_index, led->duites_size, 0, 0, led->lut_flag); pm8xxx_pwm_lut_enable(led->pwm_led, 0); pm8xxx_pwm_lut_enable(led->pwm_led, 1); } else { pwm_config(led->pwm_led, 64000, 64000); pwm_enable(led->pwm_led); } } else { if (led->function_flags & LED_BRETH_FUNCTION) { wake_lock_timeout(&pmic_led_wake_lock, HZ*2); pduties = led->duties + led->duites_size; pm8xxx_pwm_lut_config(led->pwm_led, led->period_us, pduties, led->duty_time_ms, led->start_index, led->duites_size, 0, 0, led->lut_flag); pm8xxx_pwm_lut_enable(led->pwm_led, 0); pm8xxx_pwm_lut_enable(led->pwm_led, 1); queue_delayed_work(g_led_work_queue, &led->fade_delayed_work, msecs_to_jiffies(led->duty_time_ms*led->duites_size)); } else { pwm_disable(led->pwm_led); level = (0 << PM8XXX_DRV_LED_CTRL_SHIFT) & PM8XXX_DRV_LED_CTRL_MASK; offset = PM8XXX_LED_OFFSET(led->id); led->reg &= ~PM8XXX_DRV_LED_CTRL_MASK; led->reg |= level; rc = pm8xxx_writeb(led->dev->parent, SSBI_REG_ADDR_LED_CTRL(offset), led->reg); if (rc) LED_ERR("%s can't set (%d) led value rc=%d\n", __func__, led->id, rc); } } // checking for buttons device if (led_cdev_buttons == led_cdev) { printk("[BB] led_current_set %d \n", brightness); if (brightness>0) { // screen turning off together with buttons led buttons_turning_on_with_screen_on = 1; } else { // screen turning off together without buttons led buttons_turning_on_with_screen_on = 0; } } // no blink needed pm8xxx_led_current_set_flagged( led_cdev, brightness, 0); }
static ssize_t pm8xxx_led_blink_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct led_classdev *led_cdev; struct pm8xxx_led_data *ldata; int val; 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 pm8xxx_led_data, cdev); LED_INFO("%s: bank %d blink %d\n", __func__, ldata->bank, val); switch (val) { case BLINK_STOP: if (ldata->gpio_status_switch != NULL) ldata->gpio_status_switch(0); pwm_disable(ldata->pwm_led); break; case BLINK_UNCHANGE: pwm_disable(ldata->pwm_led); if (led_cdev->brightness) { if (ldata->gpio_status_switch != NULL) ldata->gpio_status_switch(1); pwm_config(ldata->pwm_led, 64000, 64000); pwm_enable(ldata->pwm_led); } else { pwm_disable(ldata->pwm_led); if (ldata->gpio_status_switch != NULL) ldata->gpio_status_switch(0); } break; case BLINK_64MS_PER_2SEC: if (ldata->gpio_status_switch != NULL) ldata->gpio_status_switch(1); pwm_disable(ldata->pwm_led); pwm_config(ldata->pwm_led, 64000, 2000000); pwm_enable(ldata->pwm_led); break; case BLINK_64MS_ON_310MS_PER_2SEC: cancel_delayed_work_sync(&ldata->blink_delayed_work); pwm_disable(ldata->pwm_led); ldata->duty_time_ms = 64; ldata->period_us = 2000000; queue_delayed_work(g_led_work_queue, &ldata->blink_delayed_work, msecs_to_jiffies(310)); break; case BLINK_64MS_ON_2SEC_PER_2SEC: cancel_delayed_work_sync(&ldata->blink_delayed_work); pwm_disable(ldata->pwm_led); ldata->duty_time_ms = 64; ldata->period_us = 2000000; queue_delayed_work(g_led_work_queue, &ldata->blink_delayed_work, msecs_to_jiffies(1000)); break; case BLINK_1SEC_PER_2SEC: pwm_disable(ldata->pwm_led); pwm_config(ldata->pwm_led, 1000000, 2000000); pwm_enable(ldata->pwm_led); break; default: LED_ERR("%s: bank %d did not support blink type %d\n", __func__, ldata->bank, val); return -EINVAL; } return count; }
static void pm8xxx_led_current_set(struct led_classdev *led_cdev, enum led_brightness brightness) { struct pm8xxx_led_data *led = container_of(led_cdev, struct pm8xxx_led_data, cdev); int rc, offset; u8 level; int *pduties; LED_INFO("%s, bank:%d, brightness:%d\n", __func__, led->bank, brightness); cancel_delayed_work_sync(&led->fade_delayed_work); virtual_key_state = brightness; if (flag_hold_virtual_key == 1) { LED_INFO("%s, key control \n", __func__); return; } if(brightness) { level = (led->out_current << PM8XXX_DRV_LED_CTRL_SHIFT) & PM8XXX_DRV_LED_CTRL_MASK; offset = PM8XXX_LED_OFFSET(led->id); led->reg &= ~PM8XXX_DRV_LED_CTRL_MASK; led->reg |= level; rc = pm8xxx_writeb(led->dev->parent, SSBI_REG_ADDR_LED_CTRL(offset), led->reg); if (rc) LED_ERR("%s can't set (%d) led value rc=%d\n", __func__, led->id, rc); if (led->function_flags & LED_BRETH_FUNCTION) { pduties = led->duties; pm8xxx_pwm_lut_config(led->pwm_led, led->period_us, pduties, led->duty_time_ms, led->start_index, led->duites_size, 0, 0, led->lut_flag); pm8xxx_pwm_lut_enable(led->pwm_led, 0); pm8xxx_pwm_lut_enable(led->pwm_led, 1); } else { pwm_config(led->pwm_led, 64000, 64000); pwm_enable(led->pwm_led); } } else { if (led->function_flags & LED_BRETH_FUNCTION) { pduties = led->duties + led->duites_size; pm8xxx_pwm_lut_config(led->pwm_led, led->period_us, pduties, led->duty_time_ms, led->start_index, led->duites_size, 0, 0, led->lut_flag); pm8xxx_pwm_lut_enable(led->pwm_led, 0); pm8xxx_pwm_lut_enable(led->pwm_led, 1); queue_delayed_work(g_led_work_queue, &led->fade_delayed_work, msecs_to_jiffies(led->duty_time_ms*led->duites_size)); } else { pwm_disable(led->pwm_led); level = (0 << PM8XXX_DRV_LED_CTRL_SHIFT) & PM8XXX_DRV_LED_CTRL_MASK; offset = PM8XXX_LED_OFFSET(led->id); led->reg &= ~PM8XXX_DRV_LED_CTRL_MASK; led->reg |= level; rc = pm8xxx_writeb(led->dev->parent, SSBI_REG_ADDR_LED_CTRL(offset), led->reg); if (rc) LED_ERR("%s can't set (%d) led value rc=%d\n", __func__, led->id, rc); } } }