/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id$ * * Copyright (C) 2014 by Amaury Pouly * * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/ #ifndef __button_imx233__ #define __button_imx233__ #include "button.h" #include "button-target.h" #include "lradc-imx233.h" #include "pinctrl-imx233.h" #include "power-imx233.h" /* special values for .btn field */ #define IMX233_BUTTON_END -1 /* end of the list */ #define IMX233_BUTTON_HOLD -2 /* HOLD button */ #define IMX233_BUTTON_JACK -3 /* JACK detect */ #define IMX233_BUTTON_VDDIO -4 /* VDDIO value */ /* values for .periph field */ #define IMX233_BUTTON_GPIO 0 /* GPIO pin */ #define IMX233_BUTTON_LRADC 1 /* LRADC channel */ #define IMX233_BUTTON_PSWITCH 2 /* PSWITCH */ /* values for the .flags field */ #define IMX233_BUTTON_INVERTED (1 << 0) /* invert button detection */ #define IMX233_BUTTON_PULLUP (1 << 1) /* pin needs a pullup (GPIO) */ /** target-defined * NOTE for proper operation: * - the table must end which a dummy entry of type IMX233_BUTTON_END * - default is active: high for GPIO, around value for LRADC, exact value for PSWITCH * - inverted flags reverses the above behaviour * - if lradc channel is relative, the .relative field specify a entry in the * button table to which it is relative. This entry must have <0 .btn value * and be of type LRADC. For example, if a channel is VDDIO relative, set * .relative to IMX233_BUTTON_VDDIO and create an entry which .btn set to * IMX233_BUTTON_VDDIO, channel set to VDDIO source and value set to the ideal values * for which no correction is necessary. Note that the IMX233_BUTTON_VDDIO value is * defined for convenience */ struct imx233_button_map_t { int btn; /* target button or magic value (END, HOLD, JACK) */ int periph; /* GPIO, LRADC, or PSWITCH, ... */ union { struct { int bank; int pin; }gpio; struct { int src; /* source channel */ int value; /* expected value */ int relative; /* button to which it is relative or -1 if none */ }lradc; struct { int level; /* value of the PSWITCH field: low, mid, high */ }pswitch; }u; int flags; /* flags */ const char *name; /* name of the button */ /** private fields */ bool last_val; /* last interpreted value */ int rounds; /* how many rounds it survived (debouncing) */ int threshold; /* round threshold for acceptance */ }; /* macros for the common cases */ #define IMX233_BUTTON_PATH_GPIO(bank_, pin_) .periph = IMX233_BUTTON_GPIO, \ .u = {.gpio = {.bank = bank_, .pin = pin_}} #define IMX233_BUTTON_PATH_LRADC_REL(src_, val_, rel_) .periph = IMX233_BUTTON_LRADC, \ .u = {.lradc = {.src = src_, .value = val_, .relative = rel_}} #define IMX233_BUTTON_PATH_LRADC(src_, val_) IMX233_BUTTON_PATH_LRADC_REL(src_, val_, -1) #define IMX233_BUTTON_PATH_PSWITCH(lvl_) .periph = IMX233_BUTTON_PSWITCH, \ .u = {.pswitch = {.level = lvl_}} #define IMX233_BUTTON_PATH_END() .periph = -1 /* special macro for VDDIO, for convenience */ #define IMX233_BUTTON_PATH_VDDIO(val_) IMX233_BUTTON_PATH_LRADC(LRADC_SRC_VDDIO, val_) #define IMX233_BUTTON_NAMEFLAGS1(_,name_) .name = name_ #define IMX233_BUTTON_NAMEFLAGS2(_,name_,f1) .name = name_, .flags = IMX233_BUTTON_##f1 #define IMX233_BUTTON_NAMEFLAGS3(_,name_,f1,f2) .name = name_, \ .flags = IMX233_BUTTON_##f1 | IMX233_BUTTON_##f2 #define IMX233_BUTTON_NAMEFLAGS4(_,name_,f1,f2,f3) .name = name_, \ .flags =IMX233_BUTTON_##f1 | IMX233_BUTTON_##f2 | IMX233_BUTTON_##f3 #define IMX233_BUTTON__(btn_, path_, ...) \ {.btn = btn_, IMX233_BUTTON_PATH_##path_, \ REG_VARIADIC(IMX233_BUTTON_NAMEFLAGS, dummy, __VA_ARGS__)} #define IMX233_BUTTON_(btn_, path_, ...) \ IMX233_BUTTON__(IMX233_BUTTON_##btn_, path_, __VA_ARGS__) #define IMX233_BUTTON(btn_, path_, ...) \ IMX233_BUTTON__(BUTTON_##btn_, path_, __VA_ARGS__) #define IMX233_BUTTON_END_() \ {.btn = IMX233_BUTTON_END} /** * This header provides macro to ease definition of buttons. There three types of * buttons: * - normal buttons: BUTTON_X -> defined using IMX233_BUTTON(X, ...) * - special buttons IMX233_BUTTON_X -> defined using IMX233_BUTTON_(X, ...) * - others: X -> defined using IMX233_BUTTON__(X, ...) * A definition contains three mandatory parts and a fourth optional: * IMX233_BUTTON(btn, path_spec, name [, flags]) * The path_spec can be of the form: * - GPIO(bank, pin) * - LRADC(src, value) * - LRADC_REL(src, value, rel_idx) * - PSWITCH(level) * - END() * The optional flags are specified as a list, without the IMX233_BUTTON_ prefix. * Examples: * - BUTTON_POWER named "power", mapped to PSWITCH mid level, no flags: * IMX233_BUTTON(POWER, PSWICTH(1), "power") * - IMX233_BUTTON_JACK named "jack", mapped to GPIO B2P17 inverted and pullup: * IMX233_BUTTON_(JACK, GPIO(2, 17), "jack", INVERTED, PULLUP) * - BIZARRE named "bizarre", mapped to LRADC channel 0, expected value 42: * IMX233_BUTTON__(BIZARRE, LRADC(0, 42), "bizarre") * - BUTTON_PLAY named "play", mapped to LRADc channel 2, expected value 300 related * to button entry IDX * IMX233_BUTTON(PLAY, LRADC_REL(2, 300, IDX), "play") * - VDDIO entry, expected value 4000 (for relative entries): * IMX233_BUTTON_(VDDIO, VDDIO(4000), "vddio") * - last entry: * IMX233_BUTTON_(END, END(), "") * * The driver also provides default implementations for headphones_inserted() * and button_hold() which can be overriden since they have weak linkage. */ extern struct imx233_button_map_t imx233_button_map[]; /* initialise button driver */ void imx233_button_init(void); /* others gives the bitmask of other buttons: the function will OR the result * with them except if hold is detected in which case 0 is always returned */ int imx233_button_read(int others); #ifdef HAS_BUTTON_HOLD bool imx233_button_read_hold(void); bool button_hold(void); #endif #ifdef HAVE_HEADPHONE_DETECTION bool imx233_button_read_jack(void); bool headphones_inserted(void); #endif /* return interpreted button value, after processing. * Argument is an index into the imx233_button_map table */ bool imx233_button_read_btn(int idx); /* return raw value for a button, before any processing: GPIO state, LRADC * channel value, PSWITCH value. Return -1 if there is no match. * Argument is an index into the imx233_button_map table */ int imx233_button_read_raw(int idx); #endif /* __button_imx233__ */