static int adp5589_setup()

in keyboard/adp5589-keys.c [619:782]


static int adp5589_setup(struct adp5589_kpad *kpad)
{
	struct i2c_client *client = kpad->client;
	const struct adp5589_kpad_platform_data *pdata =
		dev_get_platdata(&client->dev);
	u8 (*reg) (u8) = kpad->var->reg;
	unsigned char evt_mode1 = 0, evt_mode2 = 0, evt_mode3 = 0;
	unsigned char pull_mask = 0;
	int i, ret;

	ret = adp5589_write(client, reg(ADP5589_PIN_CONFIG_A),
			    pdata->keypad_en_mask & kpad->var->row_mask);
	ret |= adp5589_write(client, reg(ADP5589_PIN_CONFIG_B),
			     (pdata->keypad_en_mask >> kpad->var->col_shift) &
			     kpad->var->col_mask);

	if (!kpad->is_adp5585)
		ret |= adp5589_write(client, ADP5589_PIN_CONFIG_C,
				     (pdata->keypad_en_mask >> 16) & 0xFF);

	if (!kpad->is_adp5585 && pdata->en_keylock) {
		ret |= adp5589_write(client, ADP5589_UNLOCK1,
				     pdata->unlock_key1);
		ret |= adp5589_write(client, ADP5589_UNLOCK2,
				     pdata->unlock_key2);
		ret |= adp5589_write(client, ADP5589_UNLOCK_TIMERS,
				     pdata->unlock_timer & LTIME_MASK);
		ret |= adp5589_write(client, ADP5589_LOCK_CFG, LOCK_EN);
	}

	for (i = 0; i < KEYP_MAX_EVENT; i++)
		ret |= adp5589_read(client, ADP5589_5_FIFO_1 + i);

	for (i = 0; i < pdata->gpimapsize; i++) {
		unsigned short pin = pdata->gpimap[i].pin;

		if (pin <= kpad->var->gpi_pin_row_end) {
			evt_mode1 |= BIT(pin - kpad->var->gpi_pin_row_base);
		} else {
			evt_mode2 |=
			    BIT(pin - kpad->var->gpi_pin_col_base) & 0xFF;
			if (!kpad->is_adp5585)
				evt_mode3 |=
				    BIT(pin - kpad->var->gpi_pin_col_base) >> 8;
		}
	}

	if (pdata->gpimapsize) {
		ret |= adp5589_write(client, reg(ADP5589_GPI_EVENT_EN_A),
				     evt_mode1);
		ret |= adp5589_write(client, reg(ADP5589_GPI_EVENT_EN_B),
				     evt_mode2);
		if (!kpad->is_adp5585)
			ret |= adp5589_write(client,
					     reg(ADP5589_GPI_EVENT_EN_C),
					     evt_mode3);
	}

	if (pdata->pull_dis_mask & pdata->pullup_en_100k &
		pdata->pullup_en_300k & pdata->pulldown_en_300k)
		dev_warn(&client->dev, "Conflicting pull resistor config\n");

	for (i = 0; i <= kpad->var->max_row_num; i++) {
		unsigned int val = 0, bit = BIT(i);
		if (pdata->pullup_en_300k & bit)
			val = 0;
		else if (pdata->pulldown_en_300k & bit)
			val = 1;
		else if (pdata->pullup_en_100k & bit)
			val = 2;
		else if (pdata->pull_dis_mask & bit)
			val = 3;

		pull_mask |= val << (2 * (i & 0x3));

		if (i % 4 == 3 || i == kpad->var->max_row_num) {
			ret |= adp5589_write(client, reg(ADP5585_RPULL_CONFIG_A)
					     + (i >> 2), pull_mask);
			pull_mask = 0;
		}
	}

	for (i = 0; i <= kpad->var->max_col_num; i++) {
		unsigned int val = 0, bit = BIT(i + kpad->var->col_shift);
		if (pdata->pullup_en_300k & bit)
			val = 0;
		else if (pdata->pulldown_en_300k & bit)
			val = 1;
		else if (pdata->pullup_en_100k & bit)
			val = 2;
		else if (pdata->pull_dis_mask & bit)
			val = 3;

		pull_mask |= val << (2 * (i & 0x3));

		if (i % 4 == 3 || i == kpad->var->max_col_num) {
			ret |= adp5589_write(client,
					     reg(ADP5585_RPULL_CONFIG_C) +
					     (i >> 2), pull_mask);
			pull_mask = 0;
		}
	}

	if (pdata->reset1_key_1 && pdata->reset1_key_2 && pdata->reset1_key_3) {
		ret |= adp5589_write(client, reg(ADP5589_RESET1_EVENT_A),
				     adp5589_get_evcode(kpad,
							pdata->reset1_key_1));
		ret |= adp5589_write(client, reg(ADP5589_RESET1_EVENT_B),
				     adp5589_get_evcode(kpad,
							pdata->reset1_key_2));
		ret |= adp5589_write(client, reg(ADP5589_RESET1_EVENT_C),
				     adp5589_get_evcode(kpad,
							pdata->reset1_key_3));
		kpad->extend_cfg |= R4_EXTEND_CFG;
	}

	if (pdata->reset2_key_1 && pdata->reset2_key_2) {
		ret |= adp5589_write(client, reg(ADP5589_RESET2_EVENT_A),
				     adp5589_get_evcode(kpad,
							pdata->reset2_key_1));
		ret |= adp5589_write(client, reg(ADP5589_RESET2_EVENT_B),
				     adp5589_get_evcode(kpad,
							pdata->reset2_key_2));
		kpad->extend_cfg |= C4_EXTEND_CFG;
	}

	if (kpad->extend_cfg) {
		ret |= adp5589_write(client, reg(ADP5589_RESET_CFG),
				     pdata->reset_cfg);
		ret |= adp5589_write(client, reg(ADP5589_PIN_CONFIG_D),
				     kpad->extend_cfg);
	}

	ret |= adp5589_write(client, reg(ADP5589_DEBOUNCE_DIS_A),
			    pdata->debounce_dis_mask & kpad->var->row_mask);

	ret |= adp5589_write(client, reg(ADP5589_DEBOUNCE_DIS_B),
			     (pdata->debounce_dis_mask >> kpad->var->col_shift)
			     & kpad->var->col_mask);

	if (!kpad->is_adp5585)
		ret |= adp5589_write(client, reg(ADP5589_DEBOUNCE_DIS_C),
				     (pdata->debounce_dis_mask >> 16) & 0xFF);

	ret |= adp5589_write(client, reg(ADP5589_POLL_PTIME_CFG),
			     pdata->scan_cycle_time & PTIME_MASK);
	ret |= adp5589_write(client, ADP5589_5_INT_STATUS,
			     (kpad->is_adp5585 ? 0 : LOGIC2_INT) |
			     LOGIC1_INT | OVRFLOW_INT |
			     (kpad->is_adp5585 ? 0 : LOCK_INT) |
			     GPI_INT | EVENT_INT);	/* Status is W1C */

	ret |= adp5589_write(client, reg(ADP5589_GENERAL_CFG),
			     INT_CFG | OSC_EN | CORE_CLK(3));
	ret |= adp5589_write(client, reg(ADP5589_INT_EN),
			     OVRFLOW_IEN | GPI_IEN | EVENT_IEN);

	if (ret < 0) {
		dev_err(&client->dev, "Write Error\n");
		return ret;
	}

	return 0;
}