/*
 * Copyright 2004 Freescale Semiconductor, Inc. All Rights Reserved.
 *
 * 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
 */

/*!
 * @file mxc_keyb.h
 *
 * @brief MXC keypad header file. 
 * 
 * @ingroup keypad
 */ 
#ifndef _MXC_KEYB_H
#define _MXC_KEYB_H

/*!
 * Keypad Module Name 
 */
#define MOD_NAME  "mxckpd"
 
/*!
 * Keypad irq number
 */ 
#define KPP_IRQ  INT_KPP
 
/*!
 * Comment KPP_DEBUG to disable debug messages
 */
/* #define KPP_DEBUG        1  */

/*!
 * XLATE mode selection
 */
#define KEYPAD_XLATE        0

/*!
 * RAW mode selection
 */
#define KEYPAD_RAW          1

/*
 * _reg_KPP_KPCR   _reg_KPP_KPSR _reg_KPP_KDDR _reg_KPP_KPDR       
 * Keypad Control Register Address
 */ 
#define KPCR    IO_ADDRESS(KPP_BASE_ADDR + 0x00)

/*
 * Keypad Status Register Address
 */ 
#define KPSR    IO_ADDRESS(KPP_BASE_ADDR + 0x02)
 
/*
 * Keypad Data Direction Address
 */ 
#define KDDR    IO_ADDRESS(KPP_BASE_ADDR + 0x04)
 
/*
 * Keypad Data Register
 */ 
#define KPDR    IO_ADDRESS(KPP_BASE_ADDR + 0x06)
 
/*
 * Key Press Interrupt Status bit
 */
#define KBD_STAT_KPKD        0x01
 
/*
 * Key Release Interrupt Status bit
 */ 
#define KBD_STAT_KPKR        0x02
 
/*
 * Key Depress Synchronizer Chain Status bit
 */ 
#define KBD_STAT_KDSC        0x04
 
/*
 * Key Release Synchronizer Status bit
 */ 
#define KBD_STAT_KRSS        0x08
 
/*
 * Key Depress Interrupt Enable Status bit
 */ 
#define KBD_STAT_KDIE        0x100
 
/*
 * Key Release Interrupt Enable
 */ 
#define KBD_STAT_KRIE        0x200
 
/*
 * Keypad Clock Enable 
 */ 
#define KBD_STAT_KPPEN       0x400

/*!
 * Buffer size of keypad queue. Should be a power of 2.
 */ 
#define KPP_BUF_SIZE    128
 
/*!
 * Test whether bit is set for integer c
 */ 
#define TEST_BIT(c, n) ((c) & (0x1 << (n)))
 
/*!
 * Set nth bit in the integer c
 */
#define BITSET(c, n)   ((c) | (1 << (n)))
 
/*!
 * Reset nth bit in the integer c 
 */ 
#define BITRESET(c, n) ((c) & ~(1 << (n)))

/*!
 * This enum represents the keypad state machine to maintain debounce logic
 * for key press/release.
 */
enum KeyState {

        /*!
         * Key press state.
         */
        KStateUp,

        /*!
         * Key press debounce state.
         */
        KStateFirstDown,

        /*!
         * Key release state.
         */
        KStateDown,

        /*!
         * Key release debounce state.
         */
        KStateFirstUp
};

/*!
 * This structure represents the keypad queue where scancode/mapcode 
 * for key press/release are queued.
 */
typedef struct keypad_queue {
        /*!
         * Head of queue
         */
        unsigned short head;
    
        /*!
         * Tail of queue
         */
        unsigned short tail;
    
        /*!
         * Number of data in queue
         */
        unsigned short len;
    
        /*!
         * Spinlock operation
         */
        spinlock_t s_lock;
    
        /*!
         * Wait queue head
         */
        wait_queue_head_t waitq;
    
        /*!
         * Keypad queue buffer size
         */
        unsigned char buf[KPP_BUF_SIZE];
} keypad_queue;

/*!
 * Keypad Private Data Structure 
 */
typedef struct keypad_priv {

        /*!
         * Major number
         */
        int major;

        /*!
         * Keypad state machine.
         */
        enum KeyState iKeyState;
        
        /*!
         * Keypad Queue Structure
         */
        struct keypad_queue queue;

        /*!
         * Number of rows configured in the keypad matrix
         */
        unsigned long kpp_rows;

        /*!
         * Number of Columns configured in the keypad matrix
         */
        unsigned long kpp_cols;

        /*!  
         * This variable represents the keypad mode of operation. The keypad
         * can be configured either in raw mode or map mode using ioctl call.
         * In raw mode the scancode of key press and key release are queued
         * into keypad queue, while in map mode the mapcode of the key press
         * and key release are queued into keypad queue.
         */
        unsigned char kpp_mode;

        /*!
         * Timer used for Keypad polling.
         */
        struct timer_list poll_timer;

} keypad_priv;

#endif  /* _MXC_KEYB_H */

