Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 671386bb authored by Michael Hennerich's avatar Michael Hennerich Committed by Dmitry Torokhov
Browse files

Input: adxl34x - add support for ADXL346 orientation sensing

parent e27c7292
Loading
Loading
Loading
Loading
+58 −4
Original line number Diff line number Diff line
@@ -196,6 +196,8 @@ struct adxl34x {
	struct axis_triple hwcal;
	struct axis_triple saved;
	char phys[32];
	unsigned orient2d_saved;
	unsigned orient3d_saved;
	bool disabled;	/* P: mutex */
	bool opened;	/* P: mutex */
	bool fifo_delay;
@@ -296,7 +298,7 @@ static irqreturn_t adxl34x_irq(int irq, void *handle)
{
	struct adxl34x *ac = handle;
	struct adxl34x_platform_data *pdata = &ac->pdata;
	int int_stat, tap_stat, samples;
	int int_stat, tap_stat, samples, orient, orient_code;

	/*
	 * ACT_TAP_STATUS should be read before clearing the interrupt
@@ -332,6 +334,36 @@ static irqreturn_t adxl34x_irq(int irq, void *handle)
					 pdata->ev_code_act_inactivity, 0);
	}

	/*
	 * ORIENTATION SENSING ADXL346 only
	 */
	if (pdata->orientation_enable) {
		orient = AC_READ(ac, ORIENT);
		if ((pdata->orientation_enable & ADXL_EN_ORIENTATION_2D) &&
		    (orient & ADXL346_2D_VALID)) {

			orient_code = ADXL346_2D_ORIENT(orient);
			/* Report orientation only when it changes */
			if (ac->orient2d_saved != orient_code) {
				ac->orient2d_saved = orient_code;
				adxl34x_report_key_single(ac->input,
					pdata->ev_codes_orient_2d[orient_code]);
			}
		}

		if ((pdata->orientation_enable & ADXL_EN_ORIENTATION_3D) &&
		    (orient & ADXL346_3D_VALID)) {

			orient_code = ADXL346_3D_ORIENT(orient) - 1;
			/* Report orientation only when it changes */
			if (ac->orient3d_saved != orient_code) {
				ac->orient3d_saved = orient_code;
				adxl34x_report_key_single(ac->input,
					pdata->ev_codes_orient_3d[orient_code]);
			}
		}
	}

	if (int_stat & (DATA_READY | WATERMARK)) {

		if (pdata->fifo_mode)
@@ -641,7 +673,7 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq,
	struct adxl34x *ac;
	struct input_dev *input_dev;
	const struct adxl34x_platform_data *pdata;
	int err, range;
	int err, range, i;
	unsigned char revid;

	if (!irq) {
@@ -797,12 +829,34 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq,
	AC_WRITE(ac, FIFO_CTL, FIFO_MODE(pdata->fifo_mode) |
			SAMPLES(pdata->watermark));

	if (pdata->use_int2)
	if (pdata->use_int2) {
		/* Map all INTs to INT2 */
		AC_WRITE(ac, INT_MAP, ac->int_mask | OVERRUN);
	else
	} else {
		/* Map all INTs to INT1 */
		AC_WRITE(ac, INT_MAP, 0);
	}

	if (ac->model == 346 && ac->pdata.orientation_enable) {
		AC_WRITE(ac, ORIENT_CONF,
			ORIENT_DEADZONE(ac->pdata.deadzone_angle) |
			ORIENT_DIVISOR(ac->pdata.divisor_length));

		ac->orient2d_saved = 1234;
		ac->orient3d_saved = 1234;

		if (pdata->orientation_enable & ADXL_EN_ORIENTATION_3D)
			for (i = 0; i < ARRAY_SIZE(pdata->ev_codes_orient_3d); i++)
				__set_bit(pdata->ev_codes_orient_3d[i],
					  input_dev->keybit);

		if (pdata->orientation_enable & ADXL_EN_ORIENTATION_2D)
			for (i = 0; i < ARRAY_SIZE(pdata->ev_codes_orient_2d); i++)
				__set_bit(pdata->ev_codes_orient_2d[i],
					  input_dev->keybit);
	} else {
		ac->pdata.orientation_enable = 0;
	}

	AC_WRITE(ac, INT_ENABLE, ac->int_mask | OVERRUN);

+56 −0
Original line number Diff line number Diff line
@@ -288,6 +288,62 @@ struct adxl34x_platform_data {
	u32 ev_code_ff;	/* EV_KEY */
	u32 ev_code_act_inactivity;	/* EV_KEY */

	/*
	 * Use ADXL34x INT2 instead of INT1
	 */
	u8 use_int2;

	/*
	 * ADXL346 only ORIENTATION SENSING feature
	 * The orientation function of the ADXL346 reports both 2-D and
	 * 3-D orientation concurrently.
	 */

#define ADXL_EN_ORIENTATION_2D		1
#define ADXL_EN_ORIENTATION_3D		2
#define ADXL_EN_ORIENTATION_2D_3D	3

	u8 orientation_enable;

	/*
	 * The width of the deadzone region between two or more
	 * orientation positions is determined by setting the Deadzone
	 * value. The deadzone region size can be specified with a
	 * resolution of 3.6deg. The deadzone angle represents the total
	 * angle where the orientation is considered invalid.
	 */

#define ADXL_DEADZONE_ANGLE_0p0		0	/* !!!0.0 [deg] */
#define ADXL_DEADZONE_ANGLE_3p6		1	/* 3.6 [deg] */
#define ADXL_DEADZONE_ANGLE_7p2		2	/* 7.2 [deg] */
#define ADXL_DEADZONE_ANGLE_10p8	3	/* 10.8 [deg] */
#define ADXL_DEADZONE_ANGLE_14p4	4	/* 14.4 [deg] */
#define ADXL_DEADZONE_ANGLE_18p0	5	/* 18.0 [deg] */
#define ADXL_DEADZONE_ANGLE_21p6	6	/* 21.6 [deg] */
#define ADXL_DEADZONE_ANGLE_25p2	7	/* 25.2 [deg] */

	u8 deadzone_angle;

	/*
	 * To eliminate most human motion such as walking or shaking,
	 * a Divisor value should be selected to effectively limit the
	 * orientation bandwidth. Set the depth of the filter used to
	 * low-pass filter the measured acceleration for stable
	 * orientation sensing
	 */

#define ADXL_LP_FILTER_DIVISOR_2	0
#define ADXL_LP_FILTER_DIVISOR_4	1
#define ADXL_LP_FILTER_DIVISOR_8	2
#define ADXL_LP_FILTER_DIVISOR_16	3
#define ADXL_LP_FILTER_DIVISOR_32	4
#define ADXL_LP_FILTER_DIVISOR_64	5
#define ADXL_LP_FILTER_DIVISOR_128	6
#define ADXL_LP_FILTER_DIVISOR_256	7

	u8 divisor_length;

	u32 ev_codes_orient_2d[4];	/* EV_KEY {+X, -X, +Y, -Y} */
	u32 ev_codes_orient_3d[6];	/* EV_KEY {+Z, +Y, +X, -X, -Y, -Z} */
};
#endif