blob: 19cdb408fa95f5926bc4d976a0cddc6d22031421 [file] [log] [blame]
/*
* Copyright 2014 Google Inc.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
*/
#include <assert.h>
#include "base/algorithm.h"
#include "base/coreboot/sysinfo.h"
#include "base/die.h"
#include "drivers/board/board_helpers.h"
#include "drivers/gpio/fwdb.h"
#include "drivers/gpio/tegra.h"
#include "drivers/keyboard/pseudo/keyboard.h"
/* Unique state ids for all possible states in state machine */
enum {
STATE_ID_START,
STATE_ID_CTRL_D,
STATE_ID_CTRL_U,
STATE_ID_CR,
STATE_ID_SPC,
STATE_ID_CTRL_L,
STATE_ID_TAB,
STATE_ID_S1,
STATE_NUM,
};
/* Intermediate stages */
static const int int_states[] = {
STATE_ID_S1,
};
/* Final stages that map to key/modifier codes */
static const struct pk_final_state final_states[] = {
{STATE_ID_CTRL_D, PseudoKb_Modifier_Ctrl, 'D'},
{STATE_ID_CTRL_U, PseudoKb_Modifier_Ctrl, 'U'},
{STATE_ID_CR, PseudoKb_Modifier_None, '\r'},
{STATE_ID_SPC, PseudoKb_Modifier_None, ' '},
{STATE_ID_CTRL_L, PseudoKb_Modifier_Ctrl, 'L'},
{STATE_ID_TAB, PseudoKb_Modifier_None, '\t'},
};
/*
* Input is formatted as follows:
* Bit 0 - Vol down
* Bit 1 - Vol Up
* Bit 2 - Pwr btn
*
* Pwr btn is active high, whereas vol up and down are active low, thus we need
* to mask the input we read for active low buttons to ensure we interpret them
* right.
*
*/
#define KEYSET(pwr, vup, vdn) ((pwr) | (vup) | (vdn))
enum {
VOL_DOWN_SHIFT,
VOL_UP_SHIFT,
PWR_BTN_SHIFT,
VOL_DOWN = (1 << VOL_DOWN_SHIFT),
VOL_UP = (1 << VOL_UP_SHIFT),
PWR_BTN = (1 << PWR_BTN_SHIFT),
NO_BTN_PRESSED = KEYSET(0,0,0),
};
/*
* Key definitions are as follows:
* Buttons:
* Pwr = Power button
* Vup = Volume Up button
* Vdn = Volume Down button
*
* Ctrl - D = Pwr + Vup
* Ctrl - U = Pwr + Vdn
* CR = Vup
* Space = Vdn
* Ctrl - L = Pwr -> Vup
* Tab = Pwr -> Vdn
*/
static const struct pk_trans trans_arr[] = {
{STATE_ID_START, KEYSET(PWR_BTN, VOL_UP, 0), STATE_ID_CTRL_D},
{STATE_ID_START, KEYSET(PWR_BTN, 0, VOL_DOWN), STATE_ID_CTRL_U},
{STATE_ID_START, KEYSET(0, VOL_UP, 0), STATE_ID_CR},
{STATE_ID_START, KEYSET(0, 0, VOL_DOWN), STATE_ID_SPC},
{STATE_ID_START, KEYSET(PWR_BTN, 0, 0), STATE_ID_S1},
{STATE_ID_S1, KEYSET(0, VOL_UP, 0), STATE_ID_CTRL_L},
{STATE_ID_S1, KEYSET(0, 0, VOL_DOWN), STATE_ID_TAB},
};
static void ryu_sm_init(struct pk_sm_desc *desc)
{
desc->total_states_count = STATE_NUM;
desc->start_state = STATE_ID_START;
desc->int_states_count = ARRAY_SIZE(int_states);
desc->int_states_arr = int_states;
desc->final_states_count = ARRAY_SIZE(final_states);
desc->final_states_arr = final_states;
desc->trans_count = ARRAY_SIZE(trans_arr);
desc->trans_arr = trans_arr;
}
void mainboard_keyboard_init(struct pk_sm_desc *desc)
{
ryu_sm_init(desc);
}
PRIV_DYN(power_button_gpio, &new_tegra_gpio_input(GPIO(Q, 0))->ops)
PRIV_DYN(vol_down_gpio, &new_tegra_gpio_input(GPIO(Q, 6))->ops)
PRIV_DYN(vol_down_gpio_n, new_gpio_not(get_vol_down_gpio()))
PRIV_DYN(vol_up_gpio, &new_tegra_gpio_input(GPIO(Q, 7))->ops)
PRIV_DYN(vol_up_gpio_n, new_gpio_not(get_vol_up_gpio()))
int mainboard_read_input(void)
{
int power_button = gpio_get(get_power_button_gpio());
if (get_sysinfo()->board_id >= 2)
power_button = !power_button;
int input = (power_button << PWR_BTN_SHIFT) |
(gpio_get(get_vol_up_gpio_n()) << VOL_UP_SHIFT) |
(gpio_get(get_vol_down_gpio_n()) << VOL_DOWN_SHIFT);
if (input == NO_BTN_PRESSED)
input = -1;
return input;
}