/* initialize chip */ static int lm3630a_chip_init(struct lm3630a_chip *pchip) { int rval; struct lm3630a_platform_data *pdata = pchip->pdata; usleep_range(1000, 2000); /* set Filter Strength Register */ rval = lm3630a_write(pchip, 0x50, 0x03); /* set Cofig. register */ rval |= lm3630a_update(pchip, REG_CONFIG, 0x07, pdata->pwm_ctrl); /* set boost control */ rval |= lm3630a_write(pchip, REG_BOOST, 0x38); /* set current A */ rval |= lm3630a_update(pchip, REG_I_A, 0x1F, 0x1F); /* set current B */ rval |= lm3630a_write(pchip, REG_I_B, 0x1F); /* set control */ rval |= lm3630a_update(pchip, REG_CTRL, 0x14, pdata->leda_ctrl); rval |= lm3630a_update(pchip, REG_CTRL, 0x0B, pdata->ledb_ctrl); usleep_range(1000, 2000); /* set brightness A and B */ rval |= lm3630a_write(pchip, REG_BRT_A, pdata->leda_init_brt); rval |= lm3630a_write(pchip, REG_BRT_B, pdata->ledb_init_brt); if (rval < 0) dev_err(pchip->dev, "i2c failed to access register\n"); return rval; }
/* update and get brightness */ static int lm3630a_bank_b_update_status(struct backlight_device *bl) { int ret; struct lm3630a_chip *pchip = bl_get_data(bl); enum lm3630a_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl; /* pwm control */ if ((pwm_ctrl & LM3630A_PWM_BANK_B) != 0) { lm3630a_pwm_ctrl(pchip, bl->props.brightness, bl->props.max_brightness); return bl->props.brightness; } /* disable sleep */ ret = lm3630a_update(pchip, REG_CTRL, 0x80, 0x00); if (ret < 0) goto out_i2c_err; usleep_range(1000, 2000); /* minimum brightness is 0x04 */ ret = lm3630a_write(pchip, REG_BRT_B, bl->props.brightness); if (bl->props.brightness < 0x4) ret |= lm3630a_update(pchip, REG_CTRL, LM3630A_LEDB_ENABLE, 0); else ret |= lm3630a_update(pchip, REG_CTRL, LM3630A_LEDB_ENABLE, LM3630A_LEDB_ENABLE); if (ret < 0) goto out_i2c_err; return bl->props.brightness; out_i2c_err: dev_err(pchip->dev, "i2c failed to access REG_CTRL\n"); return bl->props.brightness; }
/* Configure chip registers */ static int lm3630a_chip_config(struct lm3630a_chip *pchip) { int rval = 0; struct lm3630a_platform_data *pdata = pchip->pdata; dev_dbg(pchip->dev, "Configure registers\n"); /* exit sleep mode */ rval |= lm3630a_update(pchip, REG_CTRL, 0x80, 0x00); /* set Filter Strength Register */ rval = lm3630a_write(pchip, 0x50, pdata->flt_str); /* set Cofig. register */ rval |= lm3630a_update(pchip, REG_CONFIG, 0x1f, pdata->config); /* set boost control */ rval |= lm3630a_write(pchip, REG_BOOST, pdata->boost_ctrl); /* set current A */ rval |= lm3630a_update(pchip, REG_I_A, 0x1F, pdata->leda_max_cur); /* set current B */ rval |= lm3630a_write(pchip, REG_I_B, pdata->ledb_max_cur); /* set control */ rval |= lm3630a_update(pchip, REG_CTRL, 0x14, pdata->leda_ctrl); rval |= lm3630a_update(pchip, REG_CTRL, 0x0B, pdata->ledb_ctrl); /* wait for a while to make sure configuration effective */ usleep_range(1000, 2000); if (rval < 0) dev_err(pchip->dev, "Failed to configure registers\n"); return rval; }
static int lm3630a_bank_b_get_brightness(struct backlight_device *bl) { int brightness, rval; struct lm3630a_chip *pchip = bl_get_data(bl); enum lm3630a_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl; if ((pwm_ctrl & LM3630A_PWM_BANK_B) != 0) { rval = lm3630a_read(pchip, REG_PWM_OUTHIGH); if (rval < 0) goto out_i2c_err; brightness = (rval & 0x01) << 8; rval = lm3630a_read(pchip, REG_PWM_OUTLOW); if (rval < 0) goto out_i2c_err; brightness |= rval; goto out; } /* disable sleep */ rval = lm3630a_update(pchip, REG_CTRL, 0x80, 0x00); if (rval < 0) goto out_i2c_err; usleep_range(1000, 2000); rval = lm3630a_read(pchip, REG_BRT_B); if (rval < 0) goto out_i2c_err; brightness = rval; out: bl->props.brightness = brightness; return bl->props.brightness; out_i2c_err: dev_err(pchip->dev, "i2c failed to access register\n"); return 0; }
static irqreturn_t lm3630a_isr_func(int irq, void *chip) { int rval; struct lm3630a_chip *pchip = chip; unsigned long delay = msecs_to_jiffies(INT_DEBOUNCE_MSEC); queue_delayed_work(pchip->irqthread, &pchip->work, delay); rval = lm3630a_update(pchip, REG_CTRL, 0x80, 0x00); if (rval < 0) { dev_err(pchip->dev, "i2c failed to access register\n"); return IRQ_NONE; } return IRQ_HANDLED; }
static void lm3630a_led_set_func(struct work_struct *work) { struct lm3630a_chip *pchip; struct lm3630a_platform_data *pdata; int ret = 0, brt, ledval; bool new_hbm = false; static bool cur_hbm; static int cur_brt = LM3630A_MAX_BRIGHTNESS; pchip = container_of(work, struct lm3630a_chip, ledwork); ledval = pchip->ledval; pdata = pchip->pdata; dev_dbg(pchip->dev, "led value = %d\n", ledval); if (ledval == LM3630A_HBM_ON_BRIGHTNESS || ledval == LM3630A_HBM_OFF_BRIGHTNESS) { new_hbm = ledval == LM3630A_HBM_ON_BRIGHTNESS ? true : false; if (new_hbm == cur_hbm) { dev_warn(pchip->dev, "HBM state is %s already\n", new_hbm ? "ON" : "OFF"); goto out; } } else { cur_brt = ledval; /* In HBM mode, brightness setting is not effective */ if (cur_hbm) goto out; } if (lm3630a_read(pchip, REG_CTRL) & LM3630A_SLEEP_STATUS) { dev_info(pchip->dev, "wake up and re-init chip\n"); ret = lm3630a_chip_config(pchip); if (ret < 0) goto out; } if (new_hbm != cur_hbm) { cur_hbm = new_hbm; dev_info(pchip->dev, "HBM state: %s\n", new_hbm ? "ON" : "OFF"); ledval = new_hbm ? max(pdata->leda_max_brt, pdata->ledb_max_brt) : cur_brt; ret |= lm3630a_update(pchip, REG_I_A, 0x1F, new_hbm ? pdata->leda_max_hbm_cur : pdata->leda_max_cur); ret |= lm3630a_write(pchip, REG_I_B, new_hbm ? pdata->ledb_max_hbm_cur : pdata->ledb_max_cur); } if (pdata->leda_ctrl != LM3630A_LEDA_DISABLE) { /* pwm control */ if ((pdata->pwm_ctrl & LM3630A_PWM_BANK_A) != 0) lm3630a_pwm_ctrl(pchip, ledval, pdata->leda_max_brt); else { brt = ledval > pdata->leda_max_brt ? pdata->leda_max_brt : ledval; if (!brt) ret = lm3630a_update(pchip, REG_CTRL, LM3630A_LEDA_ENABLE, 0); else { ret = lm3630a_update(pchip, REG_CTRL, LM3630A_LEDA_ENABLE, LM3630A_LEDA_ENABLE); ret |= lm3630a_write(pchip, REG_BRT_A, brt); } if (ret < 0) goto out; } } if ((pdata->ledb_ctrl != LM3630A_LEDB_DISABLE) && (pdata->ledb_ctrl != LM3630A_LEDB_ON_A)) { /* pwm control */ if ((pdata->pwm_ctrl & LM3630A_PWM_BANK_B) != 0) lm3630a_pwm_ctrl(pchip, ledval, pdata->ledb_max_brt); else { brt = ledval > pdata->ledb_max_brt ? pdata->ledb_max_brt : ledval; if (!brt) ret = lm3630a_update(pchip, REG_CTRL, LM3630A_LEDB_ENABLE, 0); else { ret = lm3630a_update(pchip, REG_CTRL, LM3630A_LEDB_ENABLE, LM3630A_LEDB_ENABLE); ret |= lm3630a_write(pchip, REG_BRT_B, brt); } if (ret < 0) goto out; } } if (!ledval) ret = lm3630a_update(pchip, REG_CTRL, LM3630A_SLEEP_ENABLE, LM3630A_SLEEP_ENABLE); out: if (ret < 0) dev_err(pchip->dev, "fail to set brightness\n"); return; }