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;
}