Ejemplo n.º 1
0
static void m5mols_irq_work(struct work_struct *work)
{
	struct m5mols_info *info =
		container_of(work, struct m5mols_info, work_irq);
	struct v4l2_subdev *sd = &info->sd;
	u8 reg;
	int ret;

	if (!is_powered(info) ||
			m5mols_read_u8(sd, SYSTEM_INT_FACTOR, &info->interrupt))
		return;

	switch (info->interrupt & REG_INT_MASK) {
	case REG_INT_AF:
		if (!is_available_af(info))
			break;
		ret = m5mols_read_u8(sd, AF_STATUS, &reg);
		v4l2_dbg(2, m5mols_debug, sd, "AF %s\n",
			 reg == REG_AF_FAIL ? "Failed" :
			 reg == REG_AF_SUCCESS ? "Success" :
			 reg == REG_AF_IDLE ? "Idle" : "Busy");
		break;
	case REG_INT_CAPTURE:
		if (!test_and_set_bit(ST_CAPT_IRQ, &info->flags))
			wake_up_interruptible(&info->irq_waitq);

		v4l2_dbg(2, m5mols_debug, sd, "CAPTURE\n");
		break;
	default:
		v4l2_dbg(2, m5mols_debug, sd, "Undefined: %02x\n", reg);
		break;
	};
}
Ejemplo n.º 2
0
static int m5mols_sensor_power(struct m5mols_info *info, bool enable)
{
	struct v4l2_subdev *sd = &info->sd;
	struct i2c_client *client = v4l2_get_subdevdata(sd);
	const struct m5mols_platform_data *pdata = info->pdata;
	int ret;

	if (enable) {
		if (is_powered(info))
			return 0;

		if (info->set_power) {
			ret = info->set_power(&client->dev, 1);
			if (ret)
				return ret;
		}

		ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies);
		if (ret) {
			info->set_power(&client->dev, 0);
			return ret;
		}

		gpio_set_value(pdata->gpio_reset, !pdata->reset_polarity);
		usleep_range(1000, 1000);
		info->power = true;

		return ret;
	}

	if (!is_powered(info))
		return 0;

	ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies);
	if (ret)
		return ret;

	if (info->set_power)
		info->set_power(&client->dev, 0);

	gpio_set_value(pdata->gpio_reset, pdata->reset_polarity);
	usleep_range(1000, 1000);
	info->power = false;

	return ret;
}
Ejemplo n.º 3
0
static void charger_check_battery_level(struct charger_info *di)
{
	/* check for battery full condition */
	if (is_charging(di) && di->gg_capacity == 100) {
		if (di->gg_status == POWER_SUPPLY_STATUS_FULL) {
			dev_warn(di->dev, "gas gauge reports full capacity\n");
			di->battery_full = 1;
		} else if (di->gg_current_uA < CHARGER_TAPER_CURRENT) {
			dev_warn(di->dev, "gas gauge did not report full capacity\n");
			di->battery_full = 1;
		}
	}

	if (!is_powered(di))
		di->battery_full = 0;

	if (di->battery_full && di->gg_capacity <= di->recharge_capacity) {
		if (is_powered(di) && !is_charging(di))
			dev_warn(di->dev, "battery drained from full to %d%%, charging again\n", di->gg_capacity);
		di->battery_full = 0;
	}
}
Ejemplo n.º 4
0
static void charger_work(struct work_struct *work)
{
	struct charger_info *di = container_of(work, struct charger_info, work);
	int next_state;
	bool limiting_active;
	bool charge_source;

	if (is_charging(di))
		charger_pet_watchdog(di);

	charger_lock(di);

	/* update inputs and limit conditions */
	charger_gas_gauge_update(di);
	charger_check_temp_limits(di);
	charger_check_battery_level(di);

	/* aggregate limiting factors */
	limiting_active = di->battery_full || di->charge_disabled ||
		di->temperature_lockout;

	/* hardware ready for charging? */
	charge_source = di->vbus_online && !di->otg_online;

	dev_dbg(di->dev, "%s: battery_full=%d charge_disabled=%d temperature_lockout=%d "
			"invalid_charger=%d vbus_online=%d usb_online=%d otg_online=%d\n", __func__,
			di->battery_full, di->charge_disabled, di->temperature_lockout,
			di->invalid_charger, di->vbus_online, di->usb_online, di->otg_online);

	/* determine the next charger state */
	switch (di->state) {
		case CHARGER_STATE_UNPLUGGED:
		case CHARGER_STATE_CHARGING:
			if (charge_source) {
				if (limiting_active)
					next_state = CHARGER_STATE_NOT_CHARGING;
				else
					next_state = CHARGER_STATE_CHARGING;
			} else {
				next_state = CHARGER_STATE_UNPLUGGED;
			}
			break;

		case CHARGER_STATE_NOT_CHARGING:
			if (charge_source) {
				if (limiting_active)
					next_state = CHARGER_STATE_NOT_CHARGING;
				else
					next_state = CHARGER_STATE_CHARGING;
			} else {
				next_state = CHARGER_STATE_UNPLUGGED;
			}
			break;

		default:
			next_state = di->state; // silence compiler warning
	}

	/* if the state changed, fulfill the required changes */
	if (next_state != di->state) {
		dev_info(di->dev, "transitioning from %s to %s\n", state_to_str(di->state),
				state_to_str(next_state));

		switch (next_state) {
			case CHARGER_STATE_UNPLUGGED:
				wake_lock_timeout(&di->wake_lock, HZ / 2);
				charger_stop_usb_charger(di);
				break;

			case CHARGER_STATE_NOT_CHARGING:
				if (!is_powered(di))
					wake_lock(&di->wake_lock);

				charger_stop_usb_charger(di);
				break;

			case CHARGER_STATE_CHARGING:
				if (!is_powered(di))
					wake_lock(&di->wake_lock);

				charger_start_usb_charger(di);
				break;
		}

		di->state = next_state;
		power_supply_changed(&di->usb);

		twl6030_eval_led_state(di->led, is_powered(di), is_charging(di));
	}

	charger_unlock(di);

	/* update timer */
	mod_timer(&di->timer, di->monitor_interval_jiffies + jiffies);
}