static int max8925_backlight_set(struct backlight_device *bl, int brightness) { struct max8925_backlight_data *data = bl_get_data(bl); struct max8925_chip *chip = data->chip; unsigned char value; int ret; if (brightness > MAX_BRIGHTNESS) value = MAX_BRIGHTNESS; else value = brightness; ret = max8925_reg_write(chip->i2c, MAX8925_WLED_CNTL, value); if (ret < 0) goto out; if (!data->current_brightness && brightness) /* enable WLED output */ ret = max8925_set_bits(chip->i2c, MAX8925_WLED_MODE_CNTL, 1, 1); else if (!brightness) /* disable WLED output */ ret = max8925_set_bits(chip->i2c, MAX8925_WLED_MODE_CNTL, 1, 0); if (ret < 0) goto out; dev_dbg(chip->dev, "set brightness %d\n", value); data->current_brightness = value; return 0; out: dev_dbg(chip->dev, "set brightness %d failure with return value:%d\n", value, ret); return ret; }
static int max8925_init_charger(struct max8925_chip *chip, struct max8925_power_info *info) { int ret; REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_OVP, "ac-ovp"); if (!info->no_insert_detect) { REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_F, "ac-remove"); REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_R, "ac-insert"); } if (!info->no_temp_support) { REQUEST_IRQ(MAX8925_IRQ_VCHG_THM_OK_R, "batt-temp-in-range"); REQUEST_IRQ(MAX8925_IRQ_VCHG_THM_OK_F, "batt-temp-out-range"); } REQUEST_IRQ(MAX8925_IRQ_VCHG_SYSLOW_F, "vsys-high"); REQUEST_IRQ(MAX8925_IRQ_VCHG_SYSLOW_R, "vsys-low"); REQUEST_IRQ(MAX8925_IRQ_VCHG_RST, "charger-reset"); REQUEST_IRQ(MAX8925_IRQ_VCHG_DONE, "charger-done"); REQUEST_IRQ(MAX8925_IRQ_VCHG_TOPOFF, "charger-topoff"); REQUEST_IRQ(MAX8925_IRQ_VCHG_TMR_FAULT, "charger-timer-expire"); info->usb_online = 0; info->bat_online = 0; /* check for power - can miss interrupt at boot time */ if (start_measure(info, MEASURE_VCHG) * 2000 > 500000) info->ac_online = 1; else info->ac_online = 0; ret = max8925_reg_read(info->gpm, MAX8925_CHG_STATUS); if (ret >= 0) { /* * If battery detection is enabled, ID pin of battery is * connected to MBDET pin of MAX8925. It could be used to * detect battery presence. * Otherwise, we have to assume that battery is always on. */ if (info->batt_detect) info->bat_online = (ret & MAX8925_CHG_MBDET) ? 0 : 1; else info->bat_online = 1; if (ret & MAX8925_CHG_AC_RANGE_MASK) info->ac_online = 1; else info->ac_online = 0; } /* disable charge */ max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 1 << 7, 1 << 7); /* set charging current in charge topoff mode */ max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 3 << 5, info->topoff_threshold << 5); /* set charing current in fast charge mode */ max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 7, info->fast_charge); return 0; }
static int max8925_disable(struct regulator_dev *rdev) { struct max8925_regulator_info *info = rdev_get_drvdata(rdev); int ret; ret = max8925_set_bits(info->i2c, info->enable_reg, 1 << info->enable_bit, 0); if (ret < 0) return ret; /* set enable sequence as I2C */ return max8925_set_bits(info->i2c, info->enable_reg, 7 << 2, 7 << 2); }
static int max8925_set_dvm_enable(struct regulator_dev *rdev) { struct max8925_regulator_info *info = rdev_get_drvdata(rdev); return max8925_set_bits(info->i2c, info->vol_reg, 1 << SD1_DVM_EN, 1 << SD1_DVM_EN); }
static int max8925_disable(struct regulator_dev *rdev) { struct max8925_regulator_info *info = rdev_get_drvdata(rdev); return max8925_set_bits(info->i2c, info->enable_reg, 1 << info->enable_bit, 0); }
static int __set_charger(struct max8925_power_info *info, int enable) { struct max8925_chip *chip = info->chip; if (enable) { /* enable charger in platform */ if (info->set_charger) info->set_charger(1); /* enable charger */ max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 1 << 7, 0); } else { /* disable charge */ max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 1 << 7, 1 << 7); if (info->set_charger) info->set_charger(0); } dev_dbg(chip->dev, "%s\n", (enable) ? "Enable charger" : "Disable charger"); return 0; }
static int max8925_set_dvm_voltage(struct regulator_dev *rdev, int uV) { struct max8925_regulator_info *info = rdev_get_drvdata(rdev); unsigned char data, mask; if (uV < SD1_DVM_VMIN || uV > SD1_DVM_VMAX) return -EINVAL; data = (uV - SD1_DVM_VMIN + SD1_DVM_STEP - 1) / SD1_DVM_STEP; data <<= SD1_DVM_SHIFT; mask = 3 << SD1_DVM_SHIFT; return max8925_set_bits(info->i2c, info->enable_reg, mask, data); }
static int max8925_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) { struct max8925_regulator_info *info = rdev_get_drvdata(rdev); unsigned char data, mask; if (check_range(info, min_uV, max_uV)) { dev_err(info->chip->dev, "invalid voltage range (%d, %d) uV\n", min_uV, max_uV); return -EINVAL; } data = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV; data <<= info->vol_shift; mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; return max8925_set_bits(info->i2c, info->vol_reg, mask, data); }
/* * MAX8925 gives us an interrupt when ONKEY is pressed or released. * max8925_set_bits() operates I2C bus and may sleep. So implement * it in thread IRQ handler. */ static irqreturn_t max8925_onkey_handler(int irq, void *data) { struct max8925_onkey_info *info = data; int state; state = max8925_reg_read(info->i2c, MAX8925_ON_OFF_STATUS); input_report_key(info->idev, KEY_POWER, state & SW_INPUT); input_sync(info->idev); dev_dbg(info->dev, "onkey state:%d\n", state); /* Enable hardreset to halt if system isn't shutdown on time */ max8925_set_bits(info->i2c, MAX8925_SYSENSEL, HARDRESET_EN, HARDRESET_EN); return IRQ_HANDLED; }
static int __devinit max8925_backlight_probe(struct platform_device *pdev) { struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); struct max8925_platform_data *max8925_pdata; struct max8925_backlight_pdata *pdata = NULL; struct max8925_backlight_data *data; struct backlight_device *bl; struct backlight_properties props; struct resource *res; char name[MAX8925_NAME_SIZE]; unsigned char value; int ret; res = platform_get_resource(pdev, IORESOURCE_IO, 0); if (res == NULL) { dev_err(&pdev->dev, "No I/O resource!\n"); return -EINVAL; } if (pdev->dev.parent->platform_data) { max8925_pdata = pdev->dev.parent->platform_data; pdata = max8925_pdata->backlight; } if (!pdata) { dev_err(&pdev->dev, "platform data isn't assigned to " "backlight\n"); return -EINVAL; } data = kzalloc(sizeof(struct max8925_backlight_data), GFP_KERNEL); if (data == NULL) return -ENOMEM; strncpy(name, res->name, MAX8925_NAME_SIZE); data->chip = chip; data->current_brightness = 0; memset(&props, 0, sizeof(struct backlight_properties)); props.type = BACKLIGHT_RAW; props.max_brightness = MAX_BRIGHTNESS; bl = backlight_device_register(name, &pdev->dev, data, &max8925_backlight_ops, &props); if (IS_ERR(bl)) { dev_err(&pdev->dev, "failed to register backlight\n"); kfree(data); return PTR_ERR(bl); } bl->props.brightness = MAX_BRIGHTNESS; platform_set_drvdata(pdev, bl); value = 0; if (pdata->lxw_scl) value |= (1 << 7); if (pdata->lxw_freq) value |= (LWX_FREQ(pdata->lxw_freq) << 4); if (pdata->dual_string) value |= (1 << 1); ret = max8925_set_bits(chip->i2c, MAX8925_WLED_MODE_CNTL, 0xfe, value); if (ret < 0) goto out; backlight_update_status(bl); return 0; out: backlight_device_unregister(bl); kfree(data); return ret; }