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); } } }
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; }
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 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); }
static void handle_twi_command(void) { uint8_t command; // Get the command from the receive buffer. command = twi_receive_byte(); switch (command) { case TWI_CMD_RESET: // Reset the servo. watchdog_hard_reset(); break; case TWI_CMD_PWM_ENABLE: // Enable PWM to the servo motor. pwm_enable(); break; case TWI_CMD_PWM_DISABLE: // Disable PWM to the servo motor. pwm_disable(); break; case TWI_CMD_WRITE_ENABLE: // Enable write to read/write protected registers. registers_write_enable(); break; case TWI_CMD_WRITE_DISABLE: // Disable write to read/write protected registers. registers_write_disable(); break; case TWI_CMD_REGISTERS_SAVE: // Save register values into EEPROM. eeprom_save_registers(); break; case TWI_CMD_REGISTERS_RESTORE: // Restore register values into EEPROM. eeprom_restore_registers(); break; case TWI_CMD_REGISTERS_DEFAULT: // Restore register values to factory defaults. registers_defaults(); break; case TWI_CMD_EEPROM_ERASE: // Erase the EEPROM. eeprom_erase(); break; case TWI_CMD_VOLTAGE_READ: // Request a voltage reading. adc_read_voltage(); break; #if CURVE_MOTION_ENABLED case TWI_CMD_CURVE_MOTION_ENABLE: // Enable curve motion handling. motion_enable(); break; case TWI_CMD_CURVE_MOTION_DISABLE: // Disable curve motion handling. motion_disable(); break; case TWI_CMD_CURVE_MOTION_RESET: // Reset the motion to the current position. #if ENCODER_ENABLED motion_reset(enc_get_position_value()); #else motion_reset(adc_get_position_value()); #endif break; case TWI_CMD_CURVE_MOTION_APPEND: // Append motion curve data stored in the registers. motion_append(); break; #endif default: // Ignore unknown command. break; } }
void max77833_vibtonz_en(bool en) { int error = 0, temperature_level; if (g_hap_data == NULL) { pr_err("[VIB] the motor is not ready!!!"); return ; } if (en) { if (g_hap_data->running) return; max77833_haptic_i2c(g_hap_data, true); temperature_level = temperature_check(); if (temperature_level != prev_temperature_level) { switch(temperature_level) { case 0: error = max77833_write_reg(g_hap_data->i2c, MAX77833_AUTORES_MIN_FREQ_LOW, g_hap_data->pdata->auto_res_min_low_low_temp); if (error < 0) { pr_err("[VIB] %s Failed to write REG(0x%02x) [%d]\n", __func__, MAX77833_AUTORES_MIN_FREQ_LOW, error); } error = max77833_write_reg(g_hap_data->i2c, MAX77833_AUTORES_MAX_FREQ_LOW, g_hap_data->pdata->auto_res_max_low_low_temp); if (error < 0) { pr_err("[VIB] %s Failed to write REG(0x%02x) [%d]\n", __func__, MAX77833_AUTORES_MAX_FREQ_LOW, error); } error = max77833_write_reg(g_hap_data->i2c, MAX77833_AUTORES_INIT_GUESS_LOW, g_hap_data->pdata->auto_res_init_low_low_temp); if (error < 0) { pr_err("[VIB] %s Failed to write REG(0x%02x) [%d]\n", __func__, MAX77833_AUTORES_INIT_GUESS_LOW, error); } break; case 1: error = max77833_write_reg(g_hap_data->i2c, MAX77833_AUTORES_MIN_FREQ_LOW, g_hap_data->pdata->auto_res_min_low); if (error < 0) { pr_err("[VIB] %s Failed to write REG(0x%02x) [%d]\n", __func__, MAX77833_AUTORES_MIN_FREQ_LOW, error); } error = max77833_write_reg(g_hap_data->i2c, MAX77833_AUTORES_MAX_FREQ_LOW, g_hap_data->pdata->auto_res_max_low); if (error < 0) { pr_err("[VIB] %s Failed to write REG(0x%02x) [%d]\n", __func__, MAX77833_AUTORES_MAX_FREQ_LOW, error); } error = max77833_write_reg(g_hap_data->i2c, MAX77833_AUTORES_INIT_GUESS_LOW, g_hap_data->pdata->auto_res_init_low); if (error < 0) { pr_err("[VIB] %s Failed to write REG(0x%02x) [%d]\n", __func__, MAX77833_AUTORES_INIT_GUESS_LOW, error); } break; case 2: error = max77833_write_reg(g_hap_data->i2c, MAX77833_AUTORES_MIN_FREQ_LOW, g_hap_data->pdata->auto_res_min_low_high_temp); if (error < 0) { pr_err("[VIB] %s Failed to write REG(0x%02x) [%d]\n", __func__, MAX77833_AUTORES_MIN_FREQ_LOW, error); } error = max77833_write_reg(g_hap_data->i2c, MAX77833_AUTORES_MAX_FREQ_LOW, g_hap_data->pdata->auto_res_max_low_high_temp); if (error < 0) { pr_err("[VIB] %s Failed to write REG(0x%02x) [%d]\n", __func__, MAX77833_AUTORES_MAX_FREQ_LOW, error); } error = max77833_write_reg(g_hap_data->i2c, MAX77833_AUTORES_INIT_GUESS_LOW, g_hap_data->pdata->auto_res_init_low_high_temp); if (error < 0) { pr_err("[VIB] %s Failed to write REG(0x%02x) [%d]\n", __func__, MAX77833_AUTORES_INIT_GUESS_LOW, error); } break; default: pr_err("[VIB] %s Failed to read temperature [%d]\n", __func__, temperature_level); break; } } prev_temperature_level = temperature_level; pwm_config(g_hap_data->pwm, prev_duty, g_hap_data->pdata->period); pwm_enable(g_hap_data->pwm); g_hap_data->running = true; } else { if (!g_hap_data->running) return; pwm_disable(g_hap_data->pwm); max77833_haptic_i2c(g_hap_data, false); g_hap_data->running = false; } }
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 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 int pwm_test_probe(struct platform_device *pdev) { struct pwm_test *pwm_test; struct pinctrl *pinctrl; struct device_node *node = (&pdev->dev)->of_node; int rc; pinctrl = devm_pinctrl_get_select_default(&pdev->dev); if (IS_ERR(pinctrl)) dev_warn(&pdev->dev, "unable to select pin group. PWM not muxed right\n"); pwm_test = devm_kzalloc(&pdev->dev, sizeof(*pwm_test), GFP_KERNEL); if (!pwm_test) { dev_err(&pdev->dev, "memory error\n"); return -ENOMEM; } if (pwm_test_class_init(&pdev->dev)) { dev_err(&pdev->dev, "sysfs creation failed\n"); return -EINVAL; } pwm_test->pwm = devm_pwm_get(&pdev->dev, NULL); if (IS_ERR(pwm_test->pwm)) { dev_err(&pdev->dev, "unable to request PWM\n"); return -EINVAL; } pwm_test->requested = 1; pr_debug("pwm_test got PWM\n"); /* Get the properties of the pwm. This is set in the device driver (tiehrpwm) */ pwm_test->period = pwm_get_period(pwm_test->pwm); /* Determine running or not from the device tree */ rc = of_property_read_u32(node, "enabled", (u32*) &(pwm_test->run)); if (rc < 0) return rc; if(pwm_test->run){ rc = pwm_enable(pwm_test->pwm); if (rc < 0) return rc; } /* Determine the duty from the device tree */ rc = of_property_read_u32(node, "duty", (u32*) &(pwm_test->duty_s)); if (rc < 0) return rc; rc = pwm_config(pwm_test->pwm, pwm_test->duty_s, pwm_test->period); if (rc) { pr_err("Unable to set pwm duty %d\n", rc); return rc; } platform_set_drvdata(pdev, pwm_test); return 0; }
int backlight_pwm_gpio_config(void) { int rc; struct pm_gpio backlight_drv = { .direction = PM_GPIO_DIR_OUT, .output_buffer = PM_GPIO_OUT_BUF_CMOS, .output_value = 0, .pull = PM_GPIO_PULL_NO, .vin_sel = 0, .out_strength = PM_GPIO_STRENGTH_HIGH, .function = PM_GPIO_FUNC_2, .inv_int_pol = 1, }; /* U8800 use PM_GPIO25 as backlight's PWM,but U8820 use PM_GPIO26 */ if(machine_is_msm7x30_u8800() || machine_is_msm7x30_u8800_51() || machine_is_msm8255_u8800_pro() || machine_is_msm8255_u8860() || machine_is_msm8255_c8860() || machine_is_msm8255_u8860lp() || machine_is_msm8255_u8860_r() || machine_is_msm8255_u8860_92() || machine_is_msm8255_u8680() || machine_is_msm8255_u8667() || machine_is_msm8255_u8860_51() || machine_is_msm8255_u8730()) { rc = pm8xxx_gpio_config( 24, &backlight_drv); } else if(machine_is_msm7x30_u8820()) { rc = pm8xxx_gpio_config( 25, &backlight_drv); } else { rc = -1; } if (rc) { pr_err("%s LCD backlight GPIO config failed\n", __func__); return rc; } return 0; } /* use the mmp pin like three-leds */ void msm_backlight_set(int level) { static uint8 last_level = 0; /*fix bug in new base-line 1025*/ #ifdef CONFIG_ARCH_MSM7X30 static boolean first_set_bl = TRUE; static struct pwm_device *bl_pwm; #endif //CONFIG_ARCH_MSM7X30 /* keep duty 10% < level < 100% */ #ifdef CONFIG_ARCH_MSM7X27A if(level) { if (level < BL_MIN_LEVEL) { level = BL_MIN_LEVEL; } } if (last_level == level) { return ; } last_level = level; pmapp_disp_backlight_set_brightness(last_level); #endif #ifdef CONFIG_ARCH_MSM7X30 if(TRUE == first_set_bl) { backlight_pwm_gpio_config(); /* U8800 use PM_GPIO25 as backlight's PWM,but U8820 use PM_GPIO26 */ if(machine_is_msm7x30_u8800() || machine_is_msm7x30_u8800_51() || machine_is_msm8255_u8800_pro() || machine_is_msm8255_u8860() || machine_is_msm8255_c8860() || machine_is_msm8255_u8860lp() || machine_is_msm8255_u8860_r() || machine_is_msm8255_u8860_92() || machine_is_msm8255_u8680() || machine_is_msm8255_u8667() || machine_is_msm8255_u8860_51() || machine_is_msm8255_u8730()) { bl_pwm = pwm_request(PM_GPIO25_PWM_ID, "backlight"); } else if(machine_is_msm7x30_u8820()) { bl_pwm = pwm_request(PM_GPIO26_PWM_ID, "backlight"); } else { bl_pwm = NULL; } if (NULL == bl_pwm || IS_ERR(bl_pwm)) { pr_err("%s: pwm_request() failed\n", __func__); bl_pwm = NULL; } first_set_bl = FALSE; } if (bl_pwm) { if(level) { level = ((level * PWM_LEVEL_ADJUST) / PWM_LEVEL + ADD_VALUE); if (level < BL_MIN_LEVEL) { level = BL_MIN_LEVEL; } } if (last_level == level) { return ; } last_level = level; pwm_config(bl_pwm, PWM_DUTY_LEVEL*level/NSEC_PER_USEC, PWM_PERIOD/NSEC_PER_USEC); pwm_enable(bl_pwm); } #endif } void cabc_backlight_set(struct msm_fb_data_type * mfd) { struct msm_fb_panel_data *pdata = NULL; uint32 bl_level = mfd->bl_level; /* keep duty 10% < level < 100% */ if (bl_level) { /****delete one line codes for backlight*****/ if (bl_level < BL_MIN_LEVEL) { bl_level = BL_MIN_LEVEL; } } /* backlight ctrl by LCD-self, like as CABC */ pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data; if ((pdata) && (pdata->set_cabc_brightness)) { pdata->set_cabc_brightness(mfd,bl_level); } } void pwm_set_backlight(struct msm_fb_data_type *mfd) { /*< Delete unused variable */ /*When all the device are resume that can turn the light*/ if(atomic_read(&suspend_flag)) { mfd_local = mfd; backlight_set = TRUE; return; } /*< Delete some lines,control backlight in hardware lights.c by property */ if (get_hw_lcd_ctrl_bl_type() == CTRL_BL_BY_MSM) { msm_backlight_set(mfd->bl_level); } else { cabc_backlight_set(mfd); } return; } #ifdef CONFIG_HAS_EARLYSUSPEND static void pwm_backlight_suspend( struct early_suspend *h) { atomic_set(&suspend_flag,1); }
/** **************************************************************************************** * @brief Switch buzzer off **************************************************************************************** */ void buzzer_off(void) { pwm_enable(PWM_CH1, MASK_DISABLE); }
int backlight_pwm_gpio_config(void) { int rc; struct pm_gpio backlight_drv = { .direction = PM_GPIO_DIR_OUT, .output_buffer = PM_GPIO_OUT_BUF_CMOS, .output_value = 0, .pull = PM_GPIO_PULL_NO, .vin_sel = 0, .out_strength = PM_GPIO_STRENGTH_HIGH, .function = PM_GPIO_FUNC_2, .inv_int_pol = 1, }; /* U8800 use PM_GPIO25 as backlight's PWM,but U8820 use PM_GPIO26 */ /* < DTS2011102401822 liwei 20111024 begin */ if(machine_is_msm7x30_u8800() || machine_is_msm7x30_u8800_51() || machine_is_msm8255_u8800_pro() || machine_is_msm8255_u8860() || machine_is_msm8255_c8860() || machine_is_msm8255_u8860lp() /* < DTS2012022905490 ganfan 20120301 begin */ || machine_is_msm8255_u8860_r() /* DTS2012022905490 ganfan 20120301 end > */ || machine_is_msm8255_u8860_92() || machine_is_msm8255_u8680() || machine_is_msm8255_u8667() || machine_is_msm8255_u8860_51() || machine_is_msm8255_u8730()) /* DTS2011102401822 liwei 20111024 end > */ /*< DTS2012051704510 houming 20120517 begin */ /* renew config the gpio value */ { rc = pm8xxx_gpio_config( PM8058_GPIO_PM_TO_SYS(24), &backlight_drv); } else if(machine_is_msm7x30_u8820()) { rc = pm8xxx_gpio_config( PM8058_GPIO_PM_TO_SYS(25), &backlight_drv); } /* DTS2012051704510 houming 20120517 end >*/ else { rc = -1; } if (rc) { pr_err("%s LCD backlight GPIO config failed\n", __func__); return rc; } return 0; } /* use the mmp pin like three-leds */ /*< DTS2012012101194 lijianzhao 20120121 begin */ void msm_backlight_set(int level) { static uint8 last_level = 0; static boolean first_set_bl = TRUE; /*< DTS2012042605475 zhongjinrong 20120426 begin */ /*< DTS2012032101654 liweiwu 20120321 begin */ /* keep duty 10% < level < 100% */ /* DTS2012032101654 liweiwu 20120321 end >*/ /* DTS2012042605475 zhongjinrong 20120426 end >*/ /*< DTS2012021602342 zhongjinrong 20120224 begin */ #ifdef CONFIG_ARCH_MSM7X27A /* DTS2012021602342 zhongjinrong 20120224 end >*/ if(level) { level = ((level * PWM_LEVEL_ADJUST_LPG) / PWM_LEVEL ); if (level < BL_MIN_LEVEL_LPG) { level = BL_MIN_LEVEL_LPG; } } if (last_level == level) { return ; } last_level = level; pmapp_disp_backlight_set_brightness(last_level); #endif #ifdef CONFIG_ARCH_MSM7X30 if(TRUE == first_set_bl) { backlight_pwm_gpio_config(); /* U8800 use PM_GPIO25 as backlight's PWM,but U8820 use PM_GPIO26 */ /* < DTS2011102401822 liwei 20111024 begin */ if(machine_is_msm7x30_u8800() || machine_is_msm7x30_u8800_51() || machine_is_msm8255_u8800_pro() || machine_is_msm8255_u8860() || machine_is_msm8255_c8860() || machine_is_msm8255_u8860lp() /* < DTS2012022905490 ganfan 20120301 begin */ || machine_is_msm8255_u8860_r() /* DTS2012022905490 ganfan 20120301 end > */ || machine_is_msm8255_u8860_92() || machine_is_msm8255_u8680() || machine_is_msm8255_u8667() || machine_is_msm8255_u8860_51() || machine_is_msm8255_u8730()) /* DTS2011102401822 liwei 20111024 end > */ { bl_pwm = pwm_request(PM_GPIO25_PWM_ID, "backlight"); } else if(machine_is_msm7x30_u8820()) { bl_pwm = pwm_request(PM_GPIO26_PWM_ID, "backlight"); } else { bl_pwm = NULL; } if (NULL == bl_pwm || IS_ERR(bl_pwm)) { pr_err("%s: pwm_request() failed\n", __func__); bl_pwm = NULL; } first_set_bl = FALSE; } if (bl_pwm) { if(level) { level = ((level * PWM_LEVEL_ADJUST) / PWM_LEVEL + ADD_VALUE); if (level < BL_MIN_LEVEL) { level = BL_MIN_LEVEL; } } if (last_level == level) { return ; } last_level = level; pwm_config(bl_pwm, PWM_DUTY_LEVEL*level/NSEC_PER_USEC, PWM_PERIOD/NSEC_PER_USEC); pwm_enable(bl_pwm); } #endif } /* DTS2012012101194 lijianzhao 20120121 end >*/ void cabc_backlight_set(struct msm_fb_data_type * mfd) { struct msm_fb_panel_data *pdata = NULL; uint32 bl_level = mfd->bl_level; /*< DTS2012042605475 zhongjinrong 20120426 begin */ /*< DTS2012032101654 liweiwu 20120321 begin */ /* keep duty 10% < level < 100% */ /* DTS2012032101654 liweiwu 20120321 end >*/ if (bl_level) { /*< DTS2012032101654 liweiwu 20120321 begin */ /****delete one line codes for backlight*****/ /* DTS2012032101654 liweiwu 20120321 end >*/ /* DTS2012042605475 zhongjinrong 20120426 end >*/ if (bl_level < BL_MIN_LEVEL) { bl_level = BL_MIN_LEVEL; } } /* backlight ctrl by LCD-self, like as CABC */ /*< DTS2012012101194 lijianzhao 20120121 begin */ pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data; if ((pdata) && (pdata->set_cabc_brightness)) { pdata->set_cabc_brightness(mfd,bl_level); } /* DTS2012012101194 lijianzhao 20120121 end >*/ } /*< DTS2012022408079 zhongjinrong 20120306 begin */ void pwm_set_backlight(struct msm_fb_data_type *mfd) { lcd_panel_type lcd_panel_wvga = LCD_NONE; /*< DTS2011122704239 liuyuntao 20111229 begin */ /*When all the device are resume that can turn the light*/ if(atomic_read(&suspend_flag)) { mfd_local = mfd; backlight_set = TRUE; return; } /* DTS2011122704239 liuyuntao 20111229 end >*/ /*< DTS2012021601331 duanfei 20120216 begin */ /*< DTS2012021602342 zhongjinrong 20120224 begin */ #ifdef CONFIG_ARCH_MSM7X27A /* DTS2012021602342 zhongjinrong 20120224 end >*/ lcd_panel_wvga = get_lcd_panel_type(); /* <DTS2012022501992 liguosheng 20120229 begin */ if ((MIPI_RSP61408_CHIMEI_WVGA == lcd_panel_wvga ) || (MIPI_RSP61408_BYD_WVGA == lcd_panel_wvga ) || (MIPI_RSP61408_TRULY_WVGA == lcd_panel_wvga ) || (MIPI_HX8369A_TIANMA_WVGA == lcd_panel_wvga )) { /* keep duty is 75% of the quondam duty */ mfd->bl_level = mfd->bl_level * 75 / 100; } /* DTS2012022501992 liguosheng 20120229 end> */ #endif /* DTS2012021601331 duanfei 20120216 end >*/ if (get_hw_lcd_ctrl_bl_type() == CTRL_BL_BY_MSM) { msm_backlight_set(mfd->bl_level); } else { cabc_backlight_set(mfd); } return; }
/** **************************************************************************************** * @brief Switch buzzer on * @param[in] volume buzzer's volume **************************************************************************************** */ void buzzer_on(enum buzz_vol volume) { pwm_init(PWM_CH1); pwm_config(PWM_CH1, PWM_PSCAL_DIV, PWM_COUNT_US(BUZZ_PWM_PERIOD, PWM_PSCAL_DIV), PWM_COUNT_US(volume, PWM_PSCAL_DIV)); pwm_enable(PWM_CH1, MASK_ENABLE); }
/*configure GPIO 25 Of PIMIC as PWM to driver LED*/ int led_pwm_gpio_config(void) { int rc; struct pm_gpio backlight_drv = { .direction = PM_GPIO_DIR_OUT, .output_buffer = PM_GPIO_OUT_BUF_CMOS, .output_value = 0, .pull = PM_GPIO_PULL_NO, .vin_sel = 0, .out_strength = PM_GPIO_STRENGTH_HIGH, .function = PM_GPIO_FUNC_2, .inv_int_pol = 1, }; if(machine_is_msm8255_u8860lp() || machine_is_msm8255_u8860_r() ||machine_is_msm8255_u8860_51()) { rc = pm8xxx_gpio_config( 24, &backlight_drv); } else { rc = -1; } if (rc) { pr_err("%s LED backlight GPIO config failed\n", __func__); return rc; } return 0; } #endif static void msm_keypad_bl_led_set(struct led_classdev *led_cdev, enum led_brightness value) { #ifdef CONFIG_HUAWEI_LEDS_PMIC int ret = 0; /* 7x27a platform use mpp7 as keypad backlight */ #ifdef CONFIG_ARCH_MSM7X27A if(machine_is_msm7x27a_C8820()) { ret = pmic_secure_mpp_config_i_sink(PM_MPP_7, PM_MPP__I_SINK__LEVEL_5mA, \ (!!value) ? PM_MPP__I_SINK__SWITCH_ENA : PM_MPP__I_SINK__SWITCH_DIS); } else { /* use pwm to control the brightness of keypad backlight*/ /* make sure the led is drived by pwm when */ /* the system sleep indicator switch is on */ pmapp_button_backlight_init(); ret = pmapp_button_backlight_set_brightness(value); } #else if(machine_is_msm7x30_u8800() || machine_is_msm7x30_u8800_51() || machine_is_msm8255_u8800_pro() ) { ret = pmic_set_led_intensity(LED_KEYPAD, !( ! value)); } else if( machine_is_msm8255_u8860lp() || machine_is_msm8255_u8860_r() ||machine_is_msm8255_u8860_51()) { pwm_config(bl_pwm, LED_PWM_DUTY_LEVEL*value/NSEC_PER_USEC, LED_PWM_PERIOD/NSEC_PER_USEC); pwm_enable(bl_pwm); } else if(machine_is_msm7x30_u8820() || (machine_is_msm8255_u8730())) { ret = pmic_set_mpp6_led_intensity(!( ! value)); } /*< when the value between 0 and 255,set the key brightness is LED_BRIGHRNESS_LEVEL or set the brightness is 0 */ else if( machine_is_msm8255_u8860() || machine_is_msm8255_c8860() || machine_is_msm8255_u8860_92()) { if(LED_BRIGHTNESS_OFF >= value || LED_PWM_LEVEL < value ) { ret = pmic_set_keyled_intensity(LED_KEYPAD,LED_BRIGHTNESS_OFF ); } else { ret = pmic_set_keyled_intensity(LED_KEYPAD, LED_BRIGHTNESS_LEVEL); } } else if(machine_is_msm8255_u8680()) { /* Set keypad led brightness level 12 for U8680 */ if(LED_BRIGHTNESS_OFF >= value || LED_PWM_LEVEL < value) { ret = pmic_set_keyled_intensity(LED_KEYPAD,LED_BRIGHTNESS_OFF); } else { ret = pmic_set_keyled_intensity(LED_KEYPAD, LED_BRIGHTNESS_LEVEL_U8680); } } else if(machine_is_msm8255_u8667()) { /* Set keypad led brightness level 16 for U8667 */ if(LED_BRIGHTNESS_OFF >= value || LED_PWM_LEVEL < value) { ret = pmic_set_keyled_intensity(LED_KEYPAD, LED_BRIGHTNESS_OFF); } else { ret = pmic_set_keyled_intensity(LED_KEYPAD, LED_BRIGHTNESS_LEVEL_U8667); } } #endif if (ret) dev_err(led_cdev->dev, "can't set keypad backlight\n"); #else int ret; ret = pmic_set_led_intensity(LED_KEYPAD, value / MAX_KEYPAD_BL_LEVEL); if (ret) dev_err(led_cdev->dev, "can't set keypad backlight\n"); #endif }
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; }
void mcu_main() { // by default, the edison has ID 0 int edisonID = 0; // if we pass in an argument, use it for the edisonID // please pass in an integer //if (argc == 2) { //edisonID = atoi(argv[1]); //} int temp; while (1) { //int host_receive(unsigned char *buf, int length) temp = host_receive((unsigned char *)host_message, BUFFER_LENGTH); if (temp > 0) { debug_print(DBG_INFO, "Received a Message!\n"); host_send((unsigned char*)"hello mcu\n", 10); preamble_length = host_message[0]; } // Preamble - Signals the Receiver Message Incoming send_preamble_sequence(preamble_length); // Sending Edison Board ID # - 2 bits, MSB then LSB switch (edisonID) { case 0: send_low_bit(); // Send lsb bit 0 = LOW send_low_bit(); // Send msb bit 1 = LOW break; case 1: send_high_bit(); // Send lsb bit 0 = HIGH send_low_bit(); // Send msb bit 1 = LOW break; case 2: send_low_bit(); // Send lsb bit 0 = LOW send_high_bit(); // Send msb bit 1 = break; case 3: send_high_bit(); // Send lsb bit 0 = HIGH send_high_bit(); // Send msb bit 1 = HIGH break; default: send_low_bit(); // Send lsb bit 0 = LOW send_low_bit(); // Send msb bit 1 = LOW } // Sending Edison IR Emitter ID # - 2 bits, MSB then LSB // pwm1 = 00 = short-long/short-long = 5-20/5-20 // pwm2 = 01 = short-long/long-short = 5-20/20-5 // pwm3 = 10 = long-short/short-long = 20-5/5-20 // pwm4 = 11 = long-short/long-short = 20-5/20-5 // First Bit pwm_configure(pwm1, MESSAGE_DUTY_LOW, MESSAGE_PERIOD); // 0 pwm_configure(pwm2, MESSAGE_DUTY_LOW, MESSAGE_PERIOD); // 0 pwm_configure(pwm3, MESSAGE_DUTY_HIGH, MESSAGE_PERIOD); // 1 pwm_configure(pwm4, MESSAGE_DUTY_HIGH, MESSAGE_PERIOD); // 1 pwm_enable(pwm1); pwm_enable(pwm2); pwm_enable(pwm3); pwm_enable(pwm4); mcu_delay(MESSAGE_SLEEP); // Second Bit pwm_configure(pwm1, MESSAGE_DUTY_LOW, MESSAGE_PERIOD); // 0 pwm_configure(pwm2, MESSAGE_DUTY_HIGH, MESSAGE_PERIOD); // 1 pwm_configure(pwm3, MESSAGE_DUTY_LOW, MESSAGE_PERIOD); // 0 pwm_configure(pwm4, MESSAGE_DUTY_HIGH, MESSAGE_PERIOD); // 1 pwm_enable(pwm1); pwm_enable(pwm2); pwm_enable(pwm3); pwm_enable(pwm4); mcu_delay(MESSAGE_SLEEP); } }
int display_init(void *lcdbase, int fb_bits_per_pixel, struct display_timing *timing) { struct dc_ctlr *dc_ctlr; const void *blob = gd->fdt_blob; struct udevice *dp_dev; const int href_to_sync = 1, vref_to_sync = 1; int panel_bpp = 18; /* default 18 bits per pixel */ u32 plld_rate; struct gpio_desc vdd_gpio, enable_gpio; int pwm; int node; int ret; ret = uclass_get_device(UCLASS_DISPLAY, 0, &dp_dev); if (ret) return ret; node = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA124_DC); if (node < 0) return -ENOENT; dc_ctlr = (struct dc_ctlr *)fdtdec_get_addr(blob, node, "reg"); if (fdtdec_decode_display_timing(blob, node, 0, timing)) return -EINVAL; ret = display_update_config_from_edid(dp_dev, &panel_bpp, timing); if (ret) { debug("%s: Failed to decode EDID, using defaults\n", __func__); dump_config(panel_bpp, timing); } if (!get_backlight_info(blob, &vdd_gpio, &enable_gpio, &pwm)) { dm_gpio_set_value(&vdd_gpio, 1); debug("%s: backlight vdd setting gpio %08x to %d\n", __func__, gpio_get_number(&vdd_gpio), 1); } /* * The plld is programmed with the assumption of the SHIFT_CLK_DIVIDER * and PIXEL_CLK_DIVIDER are zero (divide by 1). See the * update_display_mode() for detail. */ plld_rate = clock_set_display_rate(timing->pixelclock.typ * 2); if (plld_rate == 0) { printf("dc: clock init failed\n"); return -EIO; } else if (plld_rate != timing->pixelclock.typ * 2) { debug("dc: plld rounded to %u\n", plld_rate); timing->pixelclock.typ = plld_rate / 2; } /* Init dc */ ret = tegra_dc_init(dc_ctlr); if (ret) { debug("dc: init failed\n"); return ret; } /* Configure dc mode */ ret = update_display_mode(dc_ctlr, timing, href_to_sync, vref_to_sync); if (ret) { debug("dc: failed to configure display mode\n"); return ret; } /* Enable dp */ ret = display_enable(dp_dev, panel_bpp, timing); if (ret) return ret; ret = update_window(dc_ctlr, (ulong)lcdbase, fb_bits_per_pixel, timing); if (ret) return ret; /* Set up Tegra PWM to drive the panel backlight */ pwm_enable(pwm, 0, 220, 0x2e); udelay(10 * 1000); if (dm_gpio_is_valid(&enable_gpio)) { dm_gpio_set_value(&enable_gpio, 1); debug("%s: backlight enable setting gpio %08x to %d\n", __func__, gpio_get_number(&enable_gpio), 1); } return 0; }
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); }
/** * Handle the next stage of device init */ static int handle_stage(const void *blob) { debug("%s: stage %d\n", __func__, stage); /* do the things for this stage */ switch (stage) { case STAGE_START: /* Initialize the Tegra display controller */ if (tegra_display_probe(gd->fdt_blob, (void *)gd->fb_base)) { printf("%s: Failed to probe display driver\n", __func__); return -1; } /* get panel details */ if (fdt_decode_lcd(blob, &config)) { printf("No valid LCD information in device tree\n"); return -1; } /* * It is possible that the FDT has requested that the LCD be * disabled. We currently don't support this. It would require * changes to U-Boot LCD subsystem to have LCD support * compiled in but not used. An easier option might be to * still have a frame buffer, but leave the backlight off and * remove all mention of lcd in the stdout environment * variable. */ funcmux_select(PERIPH_ID_DISP1, FUNCMUX_DEFAULT); break; case STAGE_PANEL_VDD: if (dm_gpio_is_valid(&config.panel_vdd)) dm_gpio_set_value(&config.panel_vdd, 1); break; case STAGE_LVDS: if (dm_gpio_is_valid(&config.lvds_shutdown)) dm_gpio_set_value(&config.lvds_shutdown, 1); break; case STAGE_BACKLIGHT_VDD: if (dm_gpio_is_valid(&config.backlight_vdd)) dm_gpio_set_value(&config.backlight_vdd, 1); break; case STAGE_PWM: /* Enable PWM at 15/16 high, 32768 Hz with divider 1 */ pinmux_set_func(PMUX_PINGRP_GPU, PMUX_FUNC_PWM); pinmux_tristate_disable(PMUX_PINGRP_GPU); pwm_enable(config.pwm_channel, 32768, 0xdf, 1); break; case STAGE_BACKLIGHT_EN: if (dm_gpio_is_valid(&config.backlight_en)) dm_gpio_set_value(&config.backlight_en, 1); break; case STAGE_DONE: break; } /* set up timer for next stage */ timer_next = timer_get_us(); if (stage < FDT_LCD_TIMINGS) timer_next += config.panel_timings[stage] * 1000; /* move to next stage */ stage++; return 0; }
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); } } } }
/* * channel: pwm channel,0/1 * pwm_info->freq: pwm freq, in hz * pwm_info->active_state: 0:low level; 1:high level */ __s32 pwm_set_para(__u32 channel, __pwm_info_t *pwm_info) { __u32 pre_scal[10] = { 120, 180, 240, 360, 480, 12000, 24000, 36000, 48000, 72000 }; __u32 pre_scal_id = 0, entire_cycle = 256, active_cycle = 192; __u32 i = 0, tmp = 0; __u32 freq; freq = 1000000 / pwm_info->period_ns; if (freq > 200000) { DE_WRN("pwm preq is large then 200khz, fix to 200khz\n"); freq = 200000; } if (freq > 781) { pre_scal_id = 0; entire_cycle = (24000000 / pre_scal[pre_scal_id] + (freq / 2)) / freq; DE_INF("pre_scal:%d, entire_cycle:%d, pwm_freq:%d\n", pre_scal[i], entire_cycle, 24000000 / pre_scal[pre_scal_id] / entire_cycle); } else { for (i = 0; i < 10; i++) { __u32 pwm_freq = 0; pwm_freq = 24000000 / (pre_scal[i] * 256); if (abs(pwm_freq - freq) < abs(tmp - freq)) { tmp = pwm_freq; pre_scal_id = i; entire_cycle = 256; DE_INF("pre_scal:%d, entire_cycle:%d, " "pwm_freq:%d\n", pre_scal[i], 256, pwm_freq); DE_INF("----%d\n", tmp); } } } active_cycle = (pwm_info->duty_ns * entire_cycle + (pwm_info->period_ns / 2)) / pwm_info->period_ns; gdisp.pwm[channel].enable = pwm_info->enable; gdisp.pwm[channel].freq = freq; gdisp.pwm[channel].pre_scal = pre_scal[pre_scal_id]; gdisp.pwm[channel].active_state = pwm_info->active_state; gdisp.pwm[channel].duty_ns = pwm_info->duty_ns; gdisp.pwm[channel].period_ns = pwm_info->period_ns; gdisp.pwm[channel].entire_cycle = entire_cycle; gdisp.pwm[channel].active_cycle = active_cycle; if (pre_scal_id >= 5) pre_scal_id += 3; if (channel == 0) { pwm_write_reg(0x204, ((entire_cycle - 1) << 16) | active_cycle); tmp = pwm_read_reg(0x200) & 0xffffff00; /* * bit6: gating the special clock for pwm0 * bit5: pwm0: active state is high level */ tmp |= (1 << 6) | (pwm_info->active_state << 5) | pre_scal_id; pwm_write_reg(0x200, tmp); } else { pwm_write_reg(0x208, ((entire_cycle - 1) << 16) | active_cycle); tmp = pwm_read_reg(0x200) & 0xff807fff; /* * bit21: gating the special clock for pwm1 * bit20: pwm1: active state is high level */ tmp |= (1 << 21) | (pwm_info->active_state << 20) | (pre_scal_id << 15); pwm_write_reg(0x200, tmp); } pwm_enable(channel, pwm_info->enable); return 0; }
int main (void) { // Configure pins to the default states. config_pin_defaults(); // Initialize the watchdog module. watchdog_init(); // First, initialize registers that control servo operation. registers_init(); // Initialize the PWM module. pwm_init(); // Initialize the ADC module. adc_init(); // Initialize the PID algorithm module. pid_init(); #if CURVE_MOTION_ENABLED // Initialize curve motion module. motion_init(); #endif // Initialize the power module. power_init(); #if PULSE_CONTROL_ENABLED pulse_control_init(); #endif #if ENCODER_ENABLED // Initialize software I2C to talk with encoder. swi2c_init(); #endif // Initialize the TWI slave module. twi_slave_init(registers_read_byte(REG_TWI_ADDRESS)); // Finally initialize the timer. timer_set(0); // Enable interrupts. sei(); // Wait until initial position value is ready. { int16_t position; // Get start-up position #if ENCODER_ENABLED position=(int16_t) enc_get_position_value(); #else while (!adc_position_value_is_ready()); position=(int16_t) adc_get_position_value(); #endif #if CURVE_MOTION_ENABLED // Reset the curve motion with the current position of the servo. motion_reset(position); #endif // Set the initial seek position and velocity. registers_write_word(REG_SEEK_POSITION_HI, REG_SEEK_POSITION_LO, position); registers_write_word(REG_SEEK_VELOCITY_HI, REG_SEEK_VELOCITY_LO, 0); } // XXX Enable PWM and writing. I do this for now to make development and // XXX tuning a bit easier. Constantly manually setting these values to // XXX turn the servo on and write the gain values get's to be a pain. pwm_enable(); registers_write_enable(); // This is the main processing loop for the servo. It basically looks // for new position, power or TWI commands to be processed. for (;;) { uint8_t tick; int16_t pwm; int16_t position; // Is ADC position value ready? // NOTE: Even when the encoder is enabled, we still need the ADC potmeasurement as the // clock because that is how the original firmware was written. tick=adc_position_value_is_ready(); if(tick) { #if PULSE_CONTROL_ENABLED // Give pulse control a chance to update the seek position. pulse_control_update(); #endif #if CURVE_MOTION_ENABLED // Give the motion curve a chance to update the seek position and velocity. motion_next(10); #endif } // Get the new position value. if(tick) { position = (int16_t) adc_get_position_value(); // NOTE: For encoder builds, this is the clock: clear the flag #if ENCODER_ENABLED } // Always run the encoder (faster PID to PWM loop = better?) position = (int16_t) enc_get_position_value(); if (position >= 0) { #endif // Call the PID algorithm module to get a new PWM value. pwm = pid_position_to_pwm(position, tick); // Update the servo movement as indicated by the PWM value. // Sanity checks are performed against the position value. pwm_update(position, pwm); } // Is a power value ready? if (adc_power_value_is_ready()) { // Get the new power value. uint16_t power = adc_get_power_value(); // Update the power value for reporting. power_update(power); } // Was a command recieved? if (twi_data_in_receive_buffer()) { // Handle any TWI command. handle_twi_command(); } #if MAIN_MOTION_TEST_ENABLED // This code is in place for having the servo drive itself between // two positions to aid in the servo tuning process. This code // should normally be disabled in config.h. #if CURVE_MOTION_ENABLED if (motion_time_left() == 0) { registers_write_word(REG_CURVE_DELTA_HI, REG_CURVE_DELTA_LO, 2000); registers_write_word(REG_CURVE_POSITION_HI, REG_CURVE_POSITION_LO, 0x0100); motion_append(); registers_write_word(REG_CURVE_DELTA_HI, REG_CURVE_DELTA_LO, 1000); registers_write_word(REG_CURVE_POSITION_HI, REG_CURVE_POSITION_LO, 0x0300); motion_append(); registers_write_word(REG_CURVE_DELTA_HI, REG_CURVE_DELTA_LO, 2000); registers_write_word(REG_CURVE_POSITION_HI, REG_CURVE_POSITION_LO, 0x0300); motion_append(); registers_write_word(REG_CURVE_DELTA_HI, REG_CURVE_DELTA_LO, 1000); registers_write_word(REG_CURVE_POSITION_HI, REG_CURVE_POSITION_LO, 0x0100); motion_append(); } #else { // Get the timer. uint16_t timer = timer_get(); // Reset the timer if greater than 800. if (timer > 800) timer_set(0); // Look for specific events. if (timer == 0) { registers_write_word(REG_SEEK_HI, REG_SEEK_LO, 0x0100); } else if (timer == 400) { registers_write_word(REG_SEEK_HI, REG_SEEK_LO, 0x0300); } } #endif #endif } return 0; }
/* * channel: pwm channel,0/1 * pwm_info->freq: pwm freq, in hz * pwm_info->active_state: 0:low level; 1:high level */ __s32 pwm_set_para(__u32 channel, __pwm_info_t *pwm_info) { __u32 pre_scal[11][2] = { {1, 0xf}, {120, 0}, {180, 1}, {240, 2}, {360, 3}, {480, 4}, {12000, 8}, {24000, 9}, {36000, 0xa}, {48000, 0xb}, {72000, 0xc} }; __u32 pre_scal_id = 0, entire_cycle = 16, active_cycle = 12; __u32 i = 0, j = 0, tmp = 0; __u32 freq; freq = 1000000 / pwm_info->period_ns; if (freq > 366) { pre_scal_id = 0; entire_cycle = 24000000 / freq; } else { for (i = 1; i < 11; i++) { for (j = 16;; j += 16) { __u32 pwm_freq = 0; pwm_freq = 24000000 / (pre_scal[i][0] * j); if (abs(pwm_freq - freq) < abs(tmp - freq)) { tmp = pwm_freq; pre_scal_id = i; entire_cycle = j; DE_INF("pre_scal:%d, entire_cycle:%d, " "pwm_freq:%d\n", pre_scal[i][0], j, pwm_freq); DE_INF("----%d\n", tmp); } else if ((tmp < freq) && (pwm_freq < tmp)) { break; } } } } active_cycle = (pwm_info->duty_ns * entire_cycle + (pwm_info->period_ns / 2)) / pwm_info->period_ns; gdisp.pwm[channel].enable = pwm_info->enable; gdisp.pwm[channel].freq = freq; gdisp.pwm[channel].pre_scal = pre_scal[pre_scal_id][0]; gdisp.pwm[channel].active_state = pwm_info->active_state; gdisp.pwm[channel].duty_ns = pwm_info->duty_ns; gdisp.pwm[channel].period_ns = pwm_info->period_ns; gdisp.pwm[channel].entire_cycle = entire_cycle; gdisp.pwm[channel].active_cycle = active_cycle; if (channel == 0) { pwm_write_reg(0x204, ((entire_cycle - 1) << 16) | active_cycle); tmp = pwm_read_reg(0x200) & 0xffffff00; /* * bit6: gating the special clock for pwm0 * bit5: pwm0: active state is high level */ tmp |= ((1 << 6) | (pwm_info->active_state << 5) | pre_scal[pre_scal_id][1]); pwm_write_reg(0x200, tmp); } else { pwm_write_reg(0x208, ((entire_cycle - 1) << 16) | active_cycle); tmp = pwm_read_reg(0x200) & 0xff807fff; /* * bit21: gating the special clock for pwm1 * bit20: pwm1: active state is high level */ tmp |= ((1 << 21) | (pwm_info->active_state << 20) | (pre_scal[pre_scal_id][1] << 15)); pwm_write_reg(0x200, tmp); } pwm_enable(channel, pwm_info->enable); return 0; }
static void haptic_work(struct work_struct *work) { struct max77833_haptic_data *hap_data = container_of(work, struct max77833_haptic_data, work); int error = 0, temperature_level; pr_info("[VIB] %s\n", __func__); if (hap_data->timeout > 0) { if (hap_data->running) return; max77833_haptic_i2c(hap_data, true); temperature_level = temperature_check(); if (temperature_level != prev_temperature_level) { switch(temperature_level) { case 0: error = max77833_write_reg(hap_data->i2c, MAX77833_AUTORES_MIN_FREQ_LOW, hap_data->pdata->auto_res_min_low_low_temp); if (error < 0) { pr_err("[VIB] %s Failed to write REG(0x%02x) [%d]\n", __func__, MAX77833_AUTORES_MIN_FREQ_LOW, error); } error = max77833_write_reg(hap_data->i2c, MAX77833_AUTORES_MAX_FREQ_LOW, hap_data->pdata->auto_res_max_low_low_temp); if (error < 0) { pr_err("[VIB] %s Failed to write REG(0x%02x) [%d]\n", __func__, MAX77833_AUTORES_MAX_FREQ_LOW, error); } error = max77833_write_reg(hap_data->i2c, MAX77833_AUTORES_INIT_GUESS_LOW, hap_data->pdata->auto_res_init_low_low_temp); if (error < 0) { pr_err("[VIB] %s Failed to write REG(0x%02x) [%d]\n", __func__, MAX77833_AUTORES_INIT_GUESS_LOW, error); } break; case 1: error = max77833_write_reg(hap_data->i2c, MAX77833_AUTORES_MIN_FREQ_LOW, hap_data->pdata->auto_res_min_low); if (error < 0) { pr_err("[VIB] %s Failed to write REG(0x%02x) [%d]\n", __func__, MAX77833_AUTORES_MIN_FREQ_LOW, error); } error = max77833_write_reg(hap_data->i2c, MAX77833_AUTORES_MAX_FREQ_LOW, hap_data->pdata->auto_res_max_low); if (error < 0) { pr_err("[VIB] %s Failed to write REG(0x%02x) [%d]\n", __func__, MAX77833_AUTORES_MAX_FREQ_LOW, error); } error = max77833_write_reg(hap_data->i2c, MAX77833_AUTORES_INIT_GUESS_LOW, hap_data->pdata->auto_res_init_low); if (error < 0) { pr_err("[VIB] %s Failed to write REG(0x%02x) [%d]\n", __func__, MAX77833_AUTORES_INIT_GUESS_LOW, error); } break; case 2: error = max77833_write_reg(hap_data->i2c, MAX77833_AUTORES_MIN_FREQ_LOW, hap_data->pdata->auto_res_min_low_high_temp); if (error < 0) { pr_err("[VIB] %s Failed to write REG(0x%02x) [%d]\n", __func__, MAX77833_AUTORES_MIN_FREQ_LOW, error); } error = max77833_write_reg(hap_data->i2c, MAX77833_AUTORES_MAX_FREQ_LOW, hap_data->pdata->auto_res_max_low_high_temp); if (error < 0) { pr_err("[VIB] %s Failed to write REG(0x%02x) [%d]\n", __func__, MAX77833_AUTORES_MAX_FREQ_LOW, error); } error = max77833_write_reg(hap_data->i2c, MAX77833_AUTORES_INIT_GUESS_LOW, hap_data->pdata->auto_res_init_low_high_temp); if (error < 0) { pr_err("[VIB] %s Failed to write REG(0x%02x) [%d]\n", __func__, MAX77833_AUTORES_INIT_GUESS_LOW, error); } break; default: pr_err("[VIB] %s Failed to read temperature [%d]\n", __func__, temperature_level); break; } } prev_temperature_level = temperature_level; pwm_config(hap_data->pwm, hap_data->pdata->duty, hap_data->pdata->period); pwm_enable(hap_data->pwm); hap_data->running = true; } else { if (!hap_data->running) return; pwm_disable(hap_data->pwm); max77833_haptic_i2c(hap_data, false); hap_data->running = false; } return; }
static void pwm_kblight_lid_change(void) { pwm_enable(PWM_CH_KBLIGHT, lid_is_open()); }
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); }
int main (void) { // Configure pins to the default states. config_pin_defaults(); // Initialize the watchdog module. watchdog_init(); // First, initialize registers that control servo operation. registers_init(); // Initialize the PWM module. pwm_init(); // Initialize the ADC module. adc_init(); #if ESTIMATOR_ENABLED // Initialize the state estimator module. estimator_init(); #endif #if REGULATOR_MOTION_ENABLED // Initialize the regulator algorithm module. regulator_init(); #endif #if PID_MOTION_ENABLED // Initialize the PID algorithm module. pid_init(); #endif #if IPD_MOTION_ENABLED // Initialize the IPD algorithm module. ipd_init(); #endif #if CURVE_MOTION_ENABLED // Initialize curve motion module. motion_init(); #endif // Initialize the power module. power_init(); #if PULSE_CONTROL_ENABLED pulse_control_init(); #endif // Initialize the TWI slave module. twi_slave_init(registers_read_byte(REG_TWI_ADDRESS)); // Finally initialize the timer. timer_set(0); // Enable interrupts. sei(); // Wait until initial position value is ready. while (!adc_position_value_is_ready()); #if CURVE_MOTION_ENABLED // Reset the curve motion with the current position of the servo. motion_reset(adc_get_position_value()); #endif // Set the initial seek position and velocity. registers_write_word(REG_SEEK_POSITION_HI, REG_SEEK_POSITION_LO, adc_get_position_value()); registers_write_word(REG_SEEK_VELOCITY_HI, REG_SEEK_VELOCITY_LO, 0); // XXX Enable PWM and writing. I do this for now to make development and // XXX tuning a bit easier. Constantly manually setting these values to // XXX turn the servo on and write the gain values get's to be a pain. pwm_enable(); registers_write_enable(); // This is the main processing loop for the servo. It basically looks // for new position, power or TWI commands to be processed. for (;;) { // Is position value ready? if (adc_position_value_is_ready()) { int16_t pwm; int16_t position; #if PULSE_CONTROL_ENABLED // Give pulse control a chance to update the seek position. pulse_control_update(); #endif #if CURVE_MOTION_ENABLED // Give the motion curve a chance to update the seek position and velocity. motion_next(10); #endif // Get the new position value. position = (int16_t) adc_get_position_value(); #if ESTIMATOR_ENABLED // Estimate velocity. estimate_velocity(position); #endif #if PID_MOTION_ENABLED // Call the PID algorithm module to get a new PWM value. pwm = pid_position_to_pwm(position); #endif #if IPD_MOTION_ENABLED // Call the IPD algorithm module to get a new PWM value. pwm = ipd_position_to_pwm(position); #endif #if REGULATOR_MOTION_ENABLED // Call the state regulator algorithm module to get a new PWM value. pwm = regulator_position_to_pwm(position); #endif // Update the servo movement as indicated by the PWM value. // Sanity checks are performed against the position value. pwm_update(position, pwm); } // Is a power value ready? if (adc_power_value_is_ready()) { // Get the new power value. uint16_t power = adc_get_power_value(); // Update the power value for reporting. power_update(power); } // Was a command recieved? if (twi_data_in_receive_buffer()) { // Handle any TWI command. handle_twi_command(); } #if MAIN_MOTION_TEST_ENABLED // This code is in place for having the servo drive itself between // two positions to aid in the servo tuning process. This code // should normally be disabled in config.h. #if CURVE_MOTION_ENABLED if (motion_time_left() == 0) { registers_write_word(REG_CURVE_DELTA_HI, REG_CURVE_DELTA_LO, 2000); registers_write_word(REG_CURVE_POSITION_HI, REG_CURVE_POSITION_LO, 0x0100); motion_append(); registers_write_word(REG_CURVE_DELTA_HI, REG_CURVE_DELTA_LO, 1000); registers_write_word(REG_CURVE_POSITION_HI, REG_CURVE_POSITION_LO, 0x0300); motion_append(); registers_write_word(REG_CURVE_DELTA_HI, REG_CURVE_DELTA_LO, 2000); registers_write_word(REG_CURVE_POSITION_HI, REG_CURVE_POSITION_LO, 0x0300); motion_append(); registers_write_word(REG_CURVE_DELTA_HI, REG_CURVE_DELTA_LO, 1000); registers_write_word(REG_CURVE_POSITION_HI, REG_CURVE_POSITION_LO, 0x0100); motion_append(); } #else { // Get the timer. uint16_t timer = timer_get(); // Reset the timer if greater than 800. if (timer > 800) timer_set(0); // Look for specific events. if (timer == 0) { registers_write_word(REG_SEEK_HI, REG_SEEK_LO, 0x0100); } else if (timer == 400) { registers_write_word(REG_SEEK_HI, REG_SEEK_LO, 0x0300); } } #endif #endif } return 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; }
int main (void) { SystemInit(); adc_pin_enable(AIN0, MASK_ENABLE); adc_pin_enable(AIN1, MASK_ENABLE); #if ADC_EXT_REF_EN==TRUE adc_pin_enable(AIN2, MASK_ENABLE); adc_pin_enable(AIN3, MASK_ENABLE); #endif #if (__AHB_CLK == 32000UL) uart_init(QN_UART0, __USART_CLK, UART_1200); #else uart_init(QN_UART0, __USART_CLK, UART_115200); #endif uart_tx_enable(QN_UART0, MASK_ENABLE); // ADC initialization #if ADC_WORKING_AT_32K==TRUE clk32k_enable(__32K_TYPE); adc_init(ADC_SINGLE_WITHOUT_BUF_DRV, ADC_CLK32K_16000, ADC_INT_REF, ADC_12BIT); #else #if ADC_EXT_REF_EN==TRUE adc_init(ADC_SINGLE_WITHOUT_BUF_DRV, ADC_CLK_1000000, ADC_EXT_REF2, ADC_12BIT); //adc_init(ADC_SINGLE_WITHOUT_BUF_DRV, ADC_CLK_1000000, ADC_EXT_REF1, ADC_12BIT); #else adc_init(ADC_SINGLE_WITHOUT_BUF_DRV, ADC_CLK_1000000, ADC_INT_REF, ADC_12BIT); #endif #endif // Read configuration adc_read_configuration read_cfg; #if ADC_TRIG_BY_GPIO == TRUE read_cfg.trig_src = ADC_TRIG_GPIO; syscon_SetPMCR2WithMask(QN_SYSCON, SYSCON_MASK_ADCT_PIN_SEL, ADC_GPIO15_TRIG); // triger by gpio in single or single scan mode, connect PWM output to ADC trigger PIN pwm_init(PWM_CH0); pwm_config(PWM_CH0, PWM_PSCAL_DIV, PWM_COUNT_US(50, PWM_PSCAL_DIV), PWM_COUNT_US(25, PWM_PSCAL_DIV)); pwm_enable(PWM_CH0, MASK_ENABLE); #elif ADC_TRIG_BY_TOF == TRUE read_cfg.trig_src = ADC_TRIG_TOVF1; // triger by timer1 overflow timer_init(QN_TIMER1, NULL); timer_pwm_config(QN_TIMER1, TIMER_PSCAL_DIV, TIMER_COUNT_US(100, TIMER_PSCAL_DIV), TIMER_COUNT_US(50, TIMER_PSCAL_DIV)); timer_enable(QN_TIMER1, MASK_ENABLE); #elif ADC_TRIG_BY_SOFT == TRUE read_cfg.trig_src = ADC_TRIG_SOFT; #endif #if ADC_DECIMATION_EN == TRUE adc_decimation_enable(DECI_RATE_64, MASK_ENABLE); #endif #if ADC_COMPARATOR_EN == TRUE //adc_compare_init(DECI_DATA, 2500, -2000, adc_WCMP_cb); adc_compare_init(ADC_DATA, 600, -600, adc_WCMP_cb); #endif #if (ADC_TRIG_BY_GPIO==TRUE || ADC_TRIG_BY_TOF==TRUE || ADC_TRIG_BY_SOFT==TRUE) adc_done = 0; // modify here read_cfg.mode = SINGLE_MOD; read_cfg.start_ch = AIN0; read_cfg.end_ch = AIN0; adc_read(&read_cfg, buf, 512, adc_test_cb); while (adc_done == 0); #endif #if ADC_COMPARATOR_EN == TRUE int m = 0; int n = 0; for (int i = 0; i < 512; i++) { if (buf[i] > 600) { m++; } else if (buf[i] < -600) { n++; } } printf("m = %d\t n = %d\r\n", m, n); #endif for (int i = 0; i < 512; i++) { printf("%d\t %d\r\n", buf[i], ADC_RESULT_mV(buf[i])); } int sum = 0; for (int i = 0; i < 10; i++) { sum += buf[511 - 2*i]; } sum = sum / 10; printf("average: %d\t %d\r\n", sum, ADC_RESULT_mV(sum)); #if ADC_TEMP_SENSOR_EN==TRUE temp_sensor_enable(MASK_ENABLE); int16_t tempv; adc_init(ADC_DIFF_WITH_BUF_DRV, ADC_CLK_1000000, ADC_INT_REF, ADC_12BIT); adc_done = 0; read_cfg.trig_src = ADC_TRIG_SOFT; read_cfg.mode = SINGLE_MOD; read_cfg.start_ch = TEMP; read_cfg.end_ch = TEMP; adc_read(&read_cfg, &tempv, 1, adc_test_cb); while (adc_done == 0); printf("temperature: %0.1f\r\n", (float)(TEMPERATURE_X10(tempv)/10.0)); #endif #if ADC_BATT_MONITOR_EN==TRUE battery_monitor_enable(MASK_ENABLE); int16_t battv; adc_init(ADC_SINGLE_WITH_BUF_DRV, ADC_CLK_1000000, ADC_INT_REF, ADC_12BIT); adc_done = 0; read_cfg.trig_src = ADC_TRIG_SOFT; read_cfg.mode = SINGLE_MOD; read_cfg.start_ch = BATT; read_cfg.end_ch = BATT; adc_read(&read_cfg, &battv, 1, adc_test_cb); while (adc_done == 0); printf("battery voltage: %d\r\n", 4*ADC_RESULT_mV(battv)); #endif while (1) /* Loop forever */ { } }
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; }
static void servo_pwm_enable(struct servo_t * m) { struct servo_pwm_pdata_t * pdat = (struct servo_pwm_pdata_t *)m->priv; pwm_enable(pdat->pwm); }