1bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski/* 2bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * Copyright (C) 2013 Samsung Electronics Co., Ltd. 3bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * Author: Jacek Anaszewski <j.anaszewski@samsung.com> 4bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * 5bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * IIO features supported by the driver: 6bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * 7bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * Read-only raw channels: 889a9430f1e65bc5b0eef78587d54306f813cd028Peter Meerwald * - illuminance_clear [lux] 989a9430f1e65bc5b0eef78587d54306f813cd028Peter Meerwald * - illuminance_ir 10bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * - proximity 11bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * 12bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * Triggered buffer: 1389a9430f1e65bc5b0eef78587d54306f813cd028Peter Meerwald * - illuminance_clear 1489a9430f1e65bc5b0eef78587d54306f813cd028Peter Meerwald * - illuminance_ir 15bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * - proximity 16bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * 17bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * Events: 18bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * - illuminance_clear (rising and falling) 19bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * - proximity (rising and falling) 20bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * - both falling and rising thresholds for the proximity events 21bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * must be set to the values greater than 0. 22bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * 23bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * The driver supports triggered buffers for all the three 24bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * channels as well as high and low threshold events for the 25bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * illuminance_clear and proxmimity channels. Triggers 26bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * can be enabled simultaneously with both illuminance_clear 27bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * events. Proximity events cannot be enabled simultaneously 28bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * with any triggers or illuminance events. Enabling/disabling 29bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * one of the proximity events automatically enables/disables 30bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * the other one. 31bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * 32bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * This program is free software; you can redistribute it and/or modify 33bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * it under the terms of the GNU General Public License version 2, as 34bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * published by the Free Software Foundation. 35bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski */ 36bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 37bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#include <linux/debugfs.h> 38bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#include <linux/delay.h> 39bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#include <linux/i2c.h> 40bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#include <linux/interrupt.h> 41bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#include <linux/irq.h> 42bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#include <linux/irq_work.h> 43bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#include <linux/module.h> 44bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#include <linux/mutex.h> 4543e01beda4b578e947aafb5b5ee19e5bb598e8caSachin Kamat#include <linux/of.h> 46bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#include <linux/regmap.h> 47bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#include <linux/regulator/consumer.h> 48bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#include <linux/slab.h> 49bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#include <linux/iio/buffer.h> 50bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#include <linux/iio/events.h> 51bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#include <linux/iio/iio.h> 52bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#include <linux/iio/sysfs.h> 53bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#include <linux/iio/trigger.h> 54bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#include <linux/iio/trigger_consumer.h> 55bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#include <linux/iio/triggered_buffer.h> 56bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 57bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2A_I2C_NAME "gp2ap020a00f" 58bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 59bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski/* Registers */ 60bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_OP_REG 0x00 /* Basic operations */ 61bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_ALS_REG 0x01 /* ALS related settings */ 62bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_PS_REG 0x02 /* PS related settings */ 63bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_LED_REG 0x03 /* LED reg */ 64bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_TL_L_REG 0x04 /* ALS: Threshold low LSB */ 65bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_TL_H_REG 0x05 /* ALS: Threshold low MSB */ 66bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_TH_L_REG 0x06 /* ALS: Threshold high LSB */ 67bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_TH_H_REG 0x07 /* ALS: Threshold high MSB */ 68bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_PL_L_REG 0x08 /* PS: Threshold low LSB */ 69bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_PL_H_REG 0x09 /* PS: Threshold low MSB */ 70bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_PH_L_REG 0x0a /* PS: Threshold high LSB */ 71bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_PH_H_REG 0x0b /* PS: Threshold high MSB */ 72bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_D0_L_REG 0x0c /* ALS result: Clear/Illuminance LSB */ 73bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_D0_H_REG 0x0d /* ALS result: Clear/Illuminance MSB */ 74bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_D1_L_REG 0x0e /* ALS result: IR LSB */ 75bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_D1_H_REG 0x0f /* ALS result: IR LSB */ 76bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_D2_L_REG 0x10 /* PS result LSB */ 77bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_D2_H_REG 0x11 /* PS result MSB */ 78bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_NUM_REGS 0x12 /* Number of registers */ 79bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 80bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski/* OP_REG bits */ 81bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_OP3_MASK 0x80 /* Software shutdown */ 82bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_OP3_SHUTDOWN 0x00 83bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_OP3_OPERATION 0x80 84bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_OP2_MASK 0x40 /* Auto shutdown/Continuous mode */ 85bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_OP2_AUTO_SHUTDOWN 0x00 86bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_OP2_CONT_OPERATION 0x40 87bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_OP_MASK 0x30 /* Operating mode selection */ 88bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_OP_ALS_AND_PS 0x00 89bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_OP_ALS 0x10 90bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_OP_PS 0x20 91bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_OP_DEBUG 0x30 92bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_PROX_MASK 0x08 /* PS: detection/non-detection */ 93bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_PROX_NON_DETECT 0x00 94bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_PROX_DETECT 0x08 95bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_FLAG_P 0x04 /* PS: interrupt result */ 96bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_FLAG_A 0x02 /* ALS: interrupt result */ 97bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_TYPE_MASK 0x01 /* Output data type selection */ 98bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_TYPE_MANUAL_CALC 0x00 99bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_TYPE_AUTO_CALC 0x01 100bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 101bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski/* ALS_REG bits */ 102bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_PRST_MASK 0xc0 /* Number of measurement cycles */ 103bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_PRST_ONCE 0x00 104bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_PRST_4_CYCLES 0x40 105bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_PRST_8_CYCLES 0x80 106bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_PRST_16_CYCLES 0xc0 107bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RES_A_MASK 0x38 /* ALS: Resolution */ 108bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RES_A_800ms 0x00 109bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RES_A_400ms 0x08 110bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RES_A_200ms 0x10 111bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RES_A_100ms 0x18 112bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RES_A_25ms 0x20 113bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RES_A_6_25ms 0x28 114bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RES_A_1_56ms 0x30 115bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RES_A_0_39ms 0x38 116bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RANGE_A_MASK 0x07 /* ALS: Max measurable range */ 117bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RANGE_A_x1 0x00 118bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RANGE_A_x2 0x01 119bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RANGE_A_x4 0x02 120bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RANGE_A_x8 0x03 121bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RANGE_A_x16 0x04 122bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RANGE_A_x32 0x05 123bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RANGE_A_x64 0x06 124bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RANGE_A_x128 0x07 125bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 126bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski/* PS_REG bits */ 127bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_ALC_MASK 0x80 /* Auto light cancel */ 128bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_ALC_ON 0x80 129bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_ALC_OFF 0x00 130bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_INTTYPE_MASK 0x40 /* Interrupt type setting */ 131bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_INTTYPE_LEVEL 0x00 132bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_INTTYPE_PULSE 0x40 133bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RES_P_MASK 0x38 /* PS: Resolution */ 134bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RES_P_800ms_x2 0x00 135bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RES_P_400ms_x2 0x08 136bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RES_P_200ms_x2 0x10 137bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RES_P_100ms_x2 0x18 138bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RES_P_25ms_x2 0x20 139bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RES_P_6_25ms_x2 0x28 140bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RES_P_1_56ms_x2 0x30 141bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RES_P_0_39ms_x2 0x38 142bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RANGE_P_MASK 0x07 /* PS: Max measurable range */ 143bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RANGE_P_x1 0x00 144bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RANGE_P_x2 0x01 145bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RANGE_P_x4 0x02 146bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RANGE_P_x8 0x03 147bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RANGE_P_x16 0x04 148bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RANGE_P_x32 0x05 149bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RANGE_P_x64 0x06 150bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RANGE_P_x128 0x07 151bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 152bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski/* LED reg bits */ 153bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_INTVAL_MASK 0xc0 /* Intermittent operating */ 154bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_INTVAL_0 0x00 155bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_INTVAL_4 0x40 156bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_INTVAL_8 0x80 157bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_INTVAL_16 0xc0 158bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_IS_MASK 0x30 /* ILED drive peak current */ 159bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_IS_13_8mA 0x00 160bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_IS_27_5mA 0x10 161bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_IS_55mA 0x20 162bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_IS_110mA 0x30 163bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_PIN_MASK 0x0c /* INT terminal setting */ 164bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_PIN_ALS_OR_PS 0x00 165bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_PIN_ALS 0x04 166bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_PIN_PS 0x08 167bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_PIN_PS_DETECT 0x0c 168bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_FREQ_MASK 0x02 /* LED modulation frequency */ 169bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_FREQ_327_5kHz 0x00 170bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_FREQ_81_8kHz 0x02 171bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_RST 0x01 /* Software reset */ 172bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 173bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR 0 174bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_SCAN_MODE_LIGHT_IR 1 175bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_SCAN_MODE_PROXIMITY 2 176bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_CHAN_TIMESTAMP 3 177bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 178bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_DATA_READY_TIMEOUT msecs_to_jiffies(1000) 179bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_DATA_REG(chan) (GP2AP020A00F_D0_L_REG + \ 180bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski (chan) * 2) 181bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_THRESH_REG(th_val_id) (GP2AP020A00F_TL_L_REG + \ 182bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski (th_val_id) * 2) 183bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_THRESH_VAL_ID(reg_addr) ((reg_addr - 4) / 2) 184bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 185bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_SUBTRACT_MODE 0 186bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_ADD_MODE 1 187bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 188bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#define GP2AP020A00F_MAX_CHANNELS 3 189bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 190bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskienum gp2ap020a00f_opmode { 191bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OPMODE_READ_RAW_CLEAR, 192bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OPMODE_READ_RAW_IR, 193bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OPMODE_READ_RAW_PROXIMITY, 194bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OPMODE_ALS, 195bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OPMODE_PS, 196bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OPMODE_ALS_AND_PS, 197bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OPMODE_PROX_DETECT, 198bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OPMODE_SHUTDOWN, 199bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_NUM_OPMODES, 200bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski}; 201bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 202bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskienum gp2ap020a00f_cmd { 203bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_CMD_READ_RAW_CLEAR, 204bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_CMD_READ_RAW_IR, 205bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_CMD_READ_RAW_PROXIMITY, 206bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_CMD_TRIGGER_CLEAR_EN, 207bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_CMD_TRIGGER_CLEAR_DIS, 208bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_CMD_TRIGGER_IR_EN, 209bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_CMD_TRIGGER_IR_DIS, 210bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_CMD_TRIGGER_PROX_EN, 211bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_CMD_TRIGGER_PROX_DIS, 212bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_CMD_ALS_HIGH_EV_EN, 213bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_CMD_ALS_HIGH_EV_DIS, 214bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_CMD_ALS_LOW_EV_EN, 215bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_CMD_ALS_LOW_EV_DIS, 216bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_CMD_PROX_HIGH_EV_EN, 217bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_CMD_PROX_HIGH_EV_DIS, 218bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_CMD_PROX_LOW_EV_EN, 219bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_CMD_PROX_LOW_EV_DIS, 220bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski}; 221bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 222bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskienum gp2ap020a00f_flags { 223bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_FLAG_ALS_CLEAR_TRIGGER, 224bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_FLAG_ALS_IR_TRIGGER, 225bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_FLAG_PROX_TRIGGER, 226bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_FLAG_PROX_RISING_EV, 227bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_FLAG_PROX_FALLING_EV, 228bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_FLAG_ALS_RISING_EV, 229bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_FLAG_ALS_FALLING_EV, 230bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_FLAG_LUX_MODE_HI, 231bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_FLAG_DATA_READY, 232bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski}; 233bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 234bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskienum gp2ap020a00f_thresh_val_id { 235bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_THRESH_TL, 236bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_THRESH_TH, 237bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_THRESH_PL, 238bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_THRESH_PH, 239bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski}; 240bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 241bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistruct gp2ap020a00f_data { 242bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski const struct gp2ap020a00f_platform_data *pdata; 243bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski struct i2c_client *client; 244bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski struct mutex lock; 245bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski char *buffer; 246bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski struct regulator *vled_reg; 247bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski unsigned long flags; 248bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski enum gp2ap020a00f_opmode cur_opmode; 249bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski struct iio_trigger *trig; 250bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski struct regmap *regmap; 251bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski unsigned int thresh_val[4]; 252bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski u8 debug_reg_addr; 253bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski struct irq_work work; 254bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski wait_queue_head_t data_ready_queue; 255bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski}; 256bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 257bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistatic const u8 gp2ap020a00f_reg_init_tab[] = { 258bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski [GP2AP020A00F_OP_REG] = GP2AP020A00F_OP3_SHUTDOWN, 259bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski [GP2AP020A00F_ALS_REG] = GP2AP020A00F_RES_A_25ms | 260bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_RANGE_A_x8, 261bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski [GP2AP020A00F_PS_REG] = GP2AP020A00F_ALC_ON | 262bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_RES_P_1_56ms_x2 | 263bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_RANGE_P_x4, 264bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski [GP2AP020A00F_LED_REG] = GP2AP020A00F_INTVAL_0 | 265bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_IS_110mA | 266bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_FREQ_327_5kHz, 267bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski [GP2AP020A00F_TL_L_REG] = 0, 268bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski [GP2AP020A00F_TL_H_REG] = 0, 269bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski [GP2AP020A00F_TH_L_REG] = 0, 270bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski [GP2AP020A00F_TH_H_REG] = 0, 271bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski [GP2AP020A00F_PL_L_REG] = 0, 272bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski [GP2AP020A00F_PL_H_REG] = 0, 273bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski [GP2AP020A00F_PH_L_REG] = 0, 274bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski [GP2AP020A00F_PH_H_REG] = 0, 275bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski}; 276bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 277bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistatic bool gp2ap020a00f_is_volatile_reg(struct device *dev, unsigned int reg) 278bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski{ 279bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski switch (reg) { 280bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_OP_REG: 281bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_D0_L_REG: 282bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_D0_H_REG: 283bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_D1_L_REG: 284bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_D1_H_REG: 285bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_D2_L_REG: 286bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_D2_H_REG: 287bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return true; 288bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski default: 289bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return false; 290bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 291bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski} 292bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 293bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistatic const struct regmap_config gp2ap020a00f_regmap_config = { 294bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .reg_bits = 8, 295bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .val_bits = 8, 296bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 297bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .max_register = GP2AP020A00F_D2_H_REG, 298bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .cache_type = REGCACHE_RBTREE, 299bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 300bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .volatile_reg = gp2ap020a00f_is_volatile_reg, 301bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski}; 302bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 303bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistatic const struct gp2ap020a00f_mutable_config_regs { 304bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski u8 op_reg; 305bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski u8 als_reg; 306bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski u8 ps_reg; 307bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski u8 led_reg; 308bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski} opmode_regs_settings[GP2AP020A00F_NUM_OPMODES] = { 309bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski [GP2AP020A00F_OPMODE_READ_RAW_CLEAR] = { 310bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OP_ALS | GP2AP020A00F_OP2_CONT_OPERATION 311bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski | GP2AP020A00F_OP3_OPERATION 312bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski | GP2AP020A00F_TYPE_AUTO_CALC, 313bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_PRST_ONCE, 314bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_INTTYPE_LEVEL, 315bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_PIN_ALS 316bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski }, 317bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski [GP2AP020A00F_OPMODE_READ_RAW_IR] = { 318bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OP_ALS | GP2AP020A00F_OP2_CONT_OPERATION 319bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski | GP2AP020A00F_OP3_OPERATION 320bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski | GP2AP020A00F_TYPE_MANUAL_CALC, 321bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_PRST_ONCE, 322bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_INTTYPE_LEVEL, 323bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_PIN_ALS 324bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski }, 325bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski [GP2AP020A00F_OPMODE_READ_RAW_PROXIMITY] = { 326bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OP_PS | GP2AP020A00F_OP2_CONT_OPERATION 327bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski | GP2AP020A00F_OP3_OPERATION 328bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski | GP2AP020A00F_TYPE_MANUAL_CALC, 329bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_PRST_ONCE, 330bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_INTTYPE_LEVEL, 331bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_PIN_PS 332bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski }, 333bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski [GP2AP020A00F_OPMODE_PROX_DETECT] = { 334bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OP_PS | GP2AP020A00F_OP2_CONT_OPERATION 335bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski | GP2AP020A00F_OP3_OPERATION 336bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski | GP2AP020A00F_TYPE_MANUAL_CALC, 337bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_PRST_4_CYCLES, 338bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_INTTYPE_PULSE, 339bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_PIN_PS_DETECT 340bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski }, 341bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski [GP2AP020A00F_OPMODE_ALS] = { 342bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OP_ALS | GP2AP020A00F_OP2_CONT_OPERATION 343bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski | GP2AP020A00F_OP3_OPERATION 344bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski | GP2AP020A00F_TYPE_AUTO_CALC, 345bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_PRST_ONCE, 346bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_INTTYPE_LEVEL, 347bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_PIN_ALS 348bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski }, 349bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski [GP2AP020A00F_OPMODE_PS] = { 350bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OP_PS | GP2AP020A00F_OP2_CONT_OPERATION 351bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski | GP2AP020A00F_OP3_OPERATION 352bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski | GP2AP020A00F_TYPE_MANUAL_CALC, 353bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_PRST_4_CYCLES, 354bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_INTTYPE_LEVEL, 355bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_PIN_PS 356bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski }, 357bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski [GP2AP020A00F_OPMODE_ALS_AND_PS] = { 358bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OP_ALS_AND_PS 359bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski | GP2AP020A00F_OP2_CONT_OPERATION 360bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski | GP2AP020A00F_OP3_OPERATION 361bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski | GP2AP020A00F_TYPE_AUTO_CALC, 362bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_PRST_4_CYCLES, 363bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_INTTYPE_LEVEL, 364bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_PIN_ALS_OR_PS 365bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski }, 366bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski [GP2AP020A00F_OPMODE_SHUTDOWN] = { GP2AP020A00F_OP3_SHUTDOWN, }, 367bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski}; 368bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 369bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistatic int gp2ap020a00f_set_operation_mode(struct gp2ap020a00f_data *data, 370bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski enum gp2ap020a00f_opmode op) 371bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski{ 372bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski unsigned int op_reg_val; 373bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski int err; 374bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 375bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (op != GP2AP020A00F_OPMODE_SHUTDOWN) { 376bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = regmap_read(data->regmap, GP2AP020A00F_OP_REG, 377bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski &op_reg_val); 378bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err < 0) 379bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return err; 380bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski /* 381bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * Shutdown the device if the operation being executed entails 382bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * mode transition. 383bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski */ 384bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if ((opmode_regs_settings[op].op_reg & GP2AP020A00F_OP_MASK) != 385bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski (op_reg_val & GP2AP020A00F_OP_MASK)) { 386bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski /* set shutdown mode */ 387bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = regmap_update_bits(data->regmap, 388bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OP_REG, GP2AP020A00F_OP3_MASK, 389bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OP3_SHUTDOWN); 390bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err < 0) 391bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return err; 392bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 393bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 394bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = regmap_update_bits(data->regmap, GP2AP020A00F_ALS_REG, 395bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_PRST_MASK, opmode_regs_settings[op] 396bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .als_reg); 397bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err < 0) 398bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return err; 399bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 400bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = regmap_update_bits(data->regmap, GP2AP020A00F_PS_REG, 401bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_INTTYPE_MASK, opmode_regs_settings[op] 402bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .ps_reg); 403bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err < 0) 404bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return err; 405bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 406bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = regmap_update_bits(data->regmap, GP2AP020A00F_LED_REG, 407bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_PIN_MASK, opmode_regs_settings[op] 408bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .led_reg); 409bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err < 0) 410bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return err; 411bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 412bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 413bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski /* Set OP_REG and apply operation mode (power on / off) */ 414bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = regmap_update_bits(data->regmap, 415bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OP_REG, 416bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OP_MASK | GP2AP020A00F_OP2_MASK | 417bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OP3_MASK | GP2AP020A00F_TYPE_MASK, 418bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski opmode_regs_settings[op].op_reg); 419bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err < 0) 420bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return err; 421bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 422bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski data->cur_opmode = op; 423bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 424bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return 0; 425bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski} 426bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 427bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistatic bool gp2ap020a00f_als_enabled(struct gp2ap020a00f_data *data) 428bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski{ 429bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return test_bit(GP2AP020A00F_FLAG_ALS_CLEAR_TRIGGER, &data->flags) || 430bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski test_bit(GP2AP020A00F_FLAG_ALS_IR_TRIGGER, &data->flags) || 431bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags) || 432bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags); 433bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski} 434bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 435bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistatic bool gp2ap020a00f_prox_detect_enabled(struct gp2ap020a00f_data *data) 436bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski{ 437bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, &data->flags) || 438bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, &data->flags); 439bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski} 440bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 441bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistatic int gp2ap020a00f_write_event_threshold(struct gp2ap020a00f_data *data, 442bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski enum gp2ap020a00f_thresh_val_id th_val_id, 443bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski bool enable) 444bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski{ 445bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski __le16 thresh_buf = 0; 446bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski unsigned int thresh_reg_val; 447bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 448bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (!enable) 449bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski thresh_reg_val = 0; 450bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski else if (test_bit(GP2AP020A00F_FLAG_LUX_MODE_HI, &data->flags) && 451bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski th_val_id != GP2AP020A00F_THRESH_PL && 452bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski th_val_id != GP2AP020A00F_THRESH_PH) 453bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski /* 454bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * For the high lux mode ALS threshold has to be scaled down 455bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * to allow for proper comparison with the output value. 456bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski */ 457bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski thresh_reg_val = data->thresh_val[th_val_id] / 16; 458bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski else 459bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski thresh_reg_val = data->thresh_val[th_val_id] > 16000 ? 460bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 16000 : 461bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski data->thresh_val[th_val_id]; 462bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 463bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski thresh_buf = cpu_to_le16(thresh_reg_val); 464bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 465bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return regmap_bulk_write(data->regmap, 466bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_THRESH_REG(th_val_id), 467bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski (u8 *)&thresh_buf, 2); 468bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski} 469bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 470bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistatic int gp2ap020a00f_alter_opmode(struct gp2ap020a00f_data *data, 471bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski enum gp2ap020a00f_opmode diff_mode, int add_sub) 472bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski{ 473bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski enum gp2ap020a00f_opmode new_mode; 474bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 475bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (diff_mode != GP2AP020A00F_OPMODE_ALS && 476bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski diff_mode != GP2AP020A00F_OPMODE_PS) 477bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return -EINVAL; 478bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 479bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (add_sub == GP2AP020A00F_ADD_MODE) { 480bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (data->cur_opmode == GP2AP020A00F_OPMODE_SHUTDOWN) 481bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski new_mode = diff_mode; 482bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski else 483bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski new_mode = GP2AP020A00F_OPMODE_ALS_AND_PS; 484bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } else { 485bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (data->cur_opmode == GP2AP020A00F_OPMODE_ALS_AND_PS) 486bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski new_mode = (diff_mode == GP2AP020A00F_OPMODE_ALS) ? 487bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OPMODE_PS : 488bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OPMODE_ALS; 489bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski else 490bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski new_mode = GP2AP020A00F_OPMODE_SHUTDOWN; 491bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 492bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 493bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return gp2ap020a00f_set_operation_mode(data, new_mode); 494bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski} 495bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 496bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistatic int gp2ap020a00f_exec_cmd(struct gp2ap020a00f_data *data, 497bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski enum gp2ap020a00f_cmd cmd) 498bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski{ 499bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski int err = 0; 500bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 501bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski switch (cmd) { 502bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_CMD_READ_RAW_CLEAR: 503bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (data->cur_opmode != GP2AP020A00F_OPMODE_SHUTDOWN) 504bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return -EBUSY; 505bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_set_operation_mode(data, 506bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OPMODE_READ_RAW_CLEAR); 507bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 508bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_CMD_READ_RAW_IR: 509bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (data->cur_opmode != GP2AP020A00F_OPMODE_SHUTDOWN) 510bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return -EBUSY; 511bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_set_operation_mode(data, 512bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OPMODE_READ_RAW_IR); 513bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 514bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_CMD_READ_RAW_PROXIMITY: 515bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (data->cur_opmode != GP2AP020A00F_OPMODE_SHUTDOWN) 516bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return -EBUSY; 517bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_set_operation_mode(data, 518bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OPMODE_READ_RAW_PROXIMITY); 519bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 520bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_CMD_TRIGGER_CLEAR_EN: 521bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (data->cur_opmode == GP2AP020A00F_OPMODE_PROX_DETECT) 522bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return -EBUSY; 523bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (!gp2ap020a00f_als_enabled(data)) 524bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_alter_opmode(data, 525bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OPMODE_ALS, 526bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_ADD_MODE); 527bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski set_bit(GP2AP020A00F_FLAG_ALS_CLEAR_TRIGGER, &data->flags); 528bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 529bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_CMD_TRIGGER_CLEAR_DIS: 530bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski clear_bit(GP2AP020A00F_FLAG_ALS_CLEAR_TRIGGER, &data->flags); 531bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (gp2ap020a00f_als_enabled(data)) 532bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 533bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_alter_opmode(data, 534bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OPMODE_ALS, 535bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_SUBTRACT_MODE); 536bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 537bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_CMD_TRIGGER_IR_EN: 538bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (data->cur_opmode == GP2AP020A00F_OPMODE_PROX_DETECT) 539bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return -EBUSY; 540bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (!gp2ap020a00f_als_enabled(data)) 541bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_alter_opmode(data, 542bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OPMODE_ALS, 543bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_ADD_MODE); 544bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski set_bit(GP2AP020A00F_FLAG_ALS_IR_TRIGGER, &data->flags); 545bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 546bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_CMD_TRIGGER_IR_DIS: 547bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski clear_bit(GP2AP020A00F_FLAG_ALS_IR_TRIGGER, &data->flags); 548bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (gp2ap020a00f_als_enabled(data)) 549bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 550bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_alter_opmode(data, 551bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OPMODE_ALS, 552bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_SUBTRACT_MODE); 553bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 554bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_CMD_TRIGGER_PROX_EN: 555bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (data->cur_opmode == GP2AP020A00F_OPMODE_PROX_DETECT) 556bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return -EBUSY; 557bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_alter_opmode(data, 558bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OPMODE_PS, 559bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_ADD_MODE); 560bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski set_bit(GP2AP020A00F_FLAG_PROX_TRIGGER, &data->flags); 561bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 562bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_CMD_TRIGGER_PROX_DIS: 563bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski clear_bit(GP2AP020A00F_FLAG_PROX_TRIGGER, &data->flags); 564bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_alter_opmode(data, 565bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OPMODE_PS, 566bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_SUBTRACT_MODE); 567bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 568bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_CMD_ALS_HIGH_EV_EN: 569bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags)) 570bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return 0; 571bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (data->cur_opmode == GP2AP020A00F_OPMODE_PROX_DETECT) 572bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return -EBUSY; 573bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (!gp2ap020a00f_als_enabled(data)) { 574bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_alter_opmode(data, 575bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OPMODE_ALS, 576bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_ADD_MODE); 577bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err < 0) 578bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return err; 579bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 580bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski set_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags); 581bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_write_event_threshold(data, 582bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_THRESH_TH, true); 583bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 584bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_CMD_ALS_HIGH_EV_DIS: 585bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (!test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags)) 586bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return 0; 587bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski clear_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags); 588bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (!gp2ap020a00f_als_enabled(data)) { 589bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_alter_opmode(data, 590bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OPMODE_ALS, 591bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_SUBTRACT_MODE); 592bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err < 0) 593bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return err; 594bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 595bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_write_event_threshold(data, 596bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_THRESH_TH, false); 597bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 598bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_CMD_ALS_LOW_EV_EN: 599bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags)) 600bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return 0; 601bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (data->cur_opmode == GP2AP020A00F_OPMODE_PROX_DETECT) 602bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return -EBUSY; 603bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (!gp2ap020a00f_als_enabled(data)) { 604bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_alter_opmode(data, 605bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OPMODE_ALS, 606bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_ADD_MODE); 607bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err < 0) 608bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return err; 609bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 610bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski set_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags); 611bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_write_event_threshold(data, 612bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_THRESH_TL, true); 613bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 614bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_CMD_ALS_LOW_EV_DIS: 615bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (!test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags)) 616bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return 0; 617bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski clear_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags); 618bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (!gp2ap020a00f_als_enabled(data)) { 619bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_alter_opmode(data, 620bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OPMODE_ALS, 621bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_SUBTRACT_MODE); 622bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err < 0) 623bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return err; 624bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 625bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_write_event_threshold(data, 626bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_THRESH_TL, false); 627bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 628bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_CMD_PROX_HIGH_EV_EN: 629bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, &data->flags)) 630bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return 0; 631bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (gp2ap020a00f_als_enabled(data) || 632bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski data->cur_opmode == GP2AP020A00F_OPMODE_PS) 633bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return -EBUSY; 634bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (!gp2ap020a00f_prox_detect_enabled(data)) { 635bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_set_operation_mode(data, 636bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OPMODE_PROX_DETECT); 637bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err < 0) 638bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return err; 639bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 640bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski set_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, &data->flags); 641bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_write_event_threshold(data, 642bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_THRESH_PH, true); 643bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 644bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_CMD_PROX_HIGH_EV_DIS: 645bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (!test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, &data->flags)) 646bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return 0; 647bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski clear_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, &data->flags); 648bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_set_operation_mode(data, 649bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OPMODE_SHUTDOWN); 650bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err < 0) 651bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return err; 652bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_write_event_threshold(data, 653bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_THRESH_PH, false); 654bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 655bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_CMD_PROX_LOW_EV_EN: 656bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, &data->flags)) 657bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return 0; 658bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (gp2ap020a00f_als_enabled(data) || 659bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski data->cur_opmode == GP2AP020A00F_OPMODE_PS) 660bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return -EBUSY; 661bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (!gp2ap020a00f_prox_detect_enabled(data)) { 662bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_set_operation_mode(data, 663bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OPMODE_PROX_DETECT); 664bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err < 0) 665bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return err; 666bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 667bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski set_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, &data->flags); 668bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_write_event_threshold(data, 669bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_THRESH_PL, true); 670bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 671bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_CMD_PROX_LOW_EV_DIS: 672bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (!test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, &data->flags)) 673bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return 0; 674bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski clear_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, &data->flags); 675bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_set_operation_mode(data, 676bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OPMODE_SHUTDOWN); 677bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err < 0) 678bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return err; 679bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_write_event_threshold(data, 680bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_THRESH_PL, false); 681bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 682bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 683bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 684bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return err; 685bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski} 686bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 687bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistatic int wait_conversion_complete_irq(struct gp2ap020a00f_data *data) 688bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski{ 689bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski int ret; 690bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 691bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski ret = wait_event_timeout(data->data_ready_queue, 692bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski test_bit(GP2AP020A00F_FLAG_DATA_READY, 693bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski &data->flags), 694bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_DATA_READY_TIMEOUT); 695bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski clear_bit(GP2AP020A00F_FLAG_DATA_READY, &data->flags); 696bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 697bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return ret > 0 ? 0 : -ETIME; 698bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski} 699bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 700bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistatic int gp2ap020a00f_read_output(struct gp2ap020a00f_data *data, 701bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski unsigned int output_reg, int *val) 702bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski{ 703bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski u8 reg_buf[2]; 704bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski int err; 705bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 706bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = wait_conversion_complete_irq(data); 707bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err < 0) 708bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski dev_dbg(&data->client->dev, "data ready timeout\n"); 709bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 710bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = regmap_bulk_read(data->regmap, output_reg, reg_buf, 2); 711bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err < 0) 712bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return err; 713bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 714bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski *val = le16_to_cpup((__le16 *)reg_buf); 715bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 716bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return err; 717bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski} 718bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 719bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistatic bool gp2ap020a00f_adjust_lux_mode(struct gp2ap020a00f_data *data, 720bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski int output_val) 721bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski{ 722bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski u8 new_range = 0xff; 723bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski int err; 724bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 725bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (!test_bit(GP2AP020A00F_FLAG_LUX_MODE_HI, &data->flags)) { 726bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (output_val > 16000) { 727bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski set_bit(GP2AP020A00F_FLAG_LUX_MODE_HI, &data->flags); 728bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski new_range = GP2AP020A00F_RANGE_A_x128; 729bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 730bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } else { 731bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (output_val < 1000) { 732bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski clear_bit(GP2AP020A00F_FLAG_LUX_MODE_HI, &data->flags); 733bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski new_range = GP2AP020A00F_RANGE_A_x8; 734bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 735bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 736bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 737bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (new_range != 0xff) { 738bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski /* Clear als threshold registers to avoid spurious 739bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * events caused by lux mode transition. 740bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski */ 741bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_write_event_threshold(data, 742bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_THRESH_TH, false); 743bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err < 0) { 744bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski dev_err(&data->client->dev, 745bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski "Clearing als threshold register failed.\n"); 746bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return false; 747bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 748bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 749bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_write_event_threshold(data, 750bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_THRESH_TL, false); 751bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err < 0) { 752bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski dev_err(&data->client->dev, 753bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski "Clearing als threshold register failed.\n"); 754bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return false; 755bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 756bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 757bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski /* Change lux mode */ 758bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = regmap_update_bits(data->regmap, 759bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OP_REG, 760bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OP3_MASK, 761bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OP3_SHUTDOWN); 762bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 763bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err < 0) { 764bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski dev_err(&data->client->dev, 765bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski "Shutting down the device failed.\n"); 766bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return false; 767bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 768bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 769bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = regmap_update_bits(data->regmap, 770bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_ALS_REG, 771bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_RANGE_A_MASK, 772bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski new_range); 773bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 774bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err < 0) { 775bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski dev_err(&data->client->dev, 776bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski "Adjusting device lux mode failed.\n"); 777bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return false; 778bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 779bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 780bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = regmap_update_bits(data->regmap, 781bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OP_REG, 782bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OP3_MASK, 783bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OP3_OPERATION); 784bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 785bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err < 0) { 786bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski dev_err(&data->client->dev, 787bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski "Powering up the device failed.\n"); 788bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return false; 789bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 790bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 791bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski /* Adjust als threshold register values to the new lux mode */ 792bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags)) { 793bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_write_event_threshold(data, 794bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_THRESH_TH, true); 795bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err < 0) { 796bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski dev_err(&data->client->dev, 797bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski "Adjusting als threshold value failed.\n"); 798bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return false; 799bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 800bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 801bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 802bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags)) { 803bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_write_event_threshold(data, 804bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_THRESH_TL, true); 805bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err < 0) { 806bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski dev_err(&data->client->dev, 807bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski "Adjusting als threshold value failed.\n"); 808bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return false; 809bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 810bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 811bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 812bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return true; 813bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 814bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 815bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return false; 816bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski} 817bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 818bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistatic void gp2ap020a00f_output_to_lux(struct gp2ap020a00f_data *data, 819bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski int *output_val) 820bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski{ 821bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (test_bit(GP2AP020A00F_FLAG_LUX_MODE_HI, &data->flags)) 822bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski *output_val *= 16; 823bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski} 824bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 825bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistatic void gp2ap020a00f_iio_trigger_work(struct irq_work *work) 826bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski{ 827bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski struct gp2ap020a00f_data *data = 828bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski container_of(work, struct gp2ap020a00f_data, work); 829bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 830398fd22b6b94cb15c1c299bceecd63644a1b17b4Peter Meerwald iio_trigger_poll(data->trig); 831bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski} 832bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 833bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistatic irqreturn_t gp2ap020a00f_prox_sensing_handler(int irq, void *data) 834bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski{ 835bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski struct iio_dev *indio_dev = data; 836bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski struct gp2ap020a00f_data *priv = iio_priv(indio_dev); 837bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski unsigned int op_reg_val; 838bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski int ret; 839bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 840bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski /* Read interrupt flags */ 841bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski ret = regmap_read(priv->regmap, GP2AP020A00F_OP_REG, &op_reg_val); 842bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (ret < 0) 843bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return IRQ_HANDLED; 844bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 845bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (gp2ap020a00f_prox_detect_enabled(priv)) { 846bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (op_reg_val & GP2AP020A00F_PROX_DETECT) { 847bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski iio_push_event(indio_dev, 848bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski IIO_UNMOD_EVENT_CODE( 849bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski IIO_PROXIMITY, 850bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_SCAN_MODE_PROXIMITY, 851bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski IIO_EV_TYPE_ROC, 852bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski IIO_EV_DIR_RISING), 853bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski iio_get_time_ns()); 854bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } else { 855bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski iio_push_event(indio_dev, 856bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski IIO_UNMOD_EVENT_CODE( 857bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski IIO_PROXIMITY, 858bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_SCAN_MODE_PROXIMITY, 859bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski IIO_EV_TYPE_ROC, 860bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski IIO_EV_DIR_FALLING), 861bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski iio_get_time_ns()); 862bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 863bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 864bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 865bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return IRQ_HANDLED; 866bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski} 867bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 868bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistatic irqreturn_t gp2ap020a00f_thresh_event_handler(int irq, void *data) 869bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski{ 870bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski struct iio_dev *indio_dev = data; 871bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski struct gp2ap020a00f_data *priv = iio_priv(indio_dev); 872bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski u8 op_reg_flags, d0_reg_buf[2]; 873bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski unsigned int output_val, op_reg_val; 874bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski int thresh_val_id, ret; 875bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 876bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski /* Read interrupt flags */ 877bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski ret = regmap_read(priv->regmap, GP2AP020A00F_OP_REG, 878bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski &op_reg_val); 879bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (ret < 0) 880bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski goto done; 881bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 882bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski op_reg_flags = op_reg_val & (GP2AP020A00F_FLAG_A | GP2AP020A00F_FLAG_P 883bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski | GP2AP020A00F_PROX_DETECT); 884bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 885bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski op_reg_val &= (~GP2AP020A00F_FLAG_A & ~GP2AP020A00F_FLAG_P 886bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski & ~GP2AP020A00F_PROX_DETECT); 887bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 888bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski /* Clear interrupt flags (if not in INTTYPE_PULSE mode) */ 889bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (priv->cur_opmode != GP2AP020A00F_OPMODE_PROX_DETECT) { 890bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski ret = regmap_write(priv->regmap, GP2AP020A00F_OP_REG, 891bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski op_reg_val); 892bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (ret < 0) 893bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski goto done; 894bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 895bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 896bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (op_reg_flags & GP2AP020A00F_FLAG_A) { 897bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski /* Check D0 register to assess if the lux mode 898bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * transition is required. 899bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski */ 900bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski ret = regmap_bulk_read(priv->regmap, GP2AP020A00F_D0_L_REG, 901bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski d0_reg_buf, 2); 902bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (ret < 0) 903bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski goto done; 904bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 905bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski output_val = le16_to_cpup((__le16 *)d0_reg_buf); 906bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 907bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (gp2ap020a00f_adjust_lux_mode(priv, output_val)) 908bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski goto done; 909bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 910bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski gp2ap020a00f_output_to_lux(priv, &output_val); 911bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 912bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski /* 913bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * We need to check output value to distinguish 914bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * between high and low ambient light threshold event. 915bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski */ 916bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &priv->flags)) { 917bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski thresh_val_id = 918bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_THRESH_VAL_ID(GP2AP020A00F_TH_L_REG); 919bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (output_val > priv->thresh_val[thresh_val_id]) 920bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski iio_push_event(indio_dev, 921bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski IIO_MOD_EVENT_CODE( 922bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski IIO_LIGHT, 923bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR, 924bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski IIO_MOD_LIGHT_CLEAR, 925bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski IIO_EV_TYPE_THRESH, 926bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski IIO_EV_DIR_RISING), 927bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski iio_get_time_ns()); 928bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 929bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 930bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &priv->flags)) { 931bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski thresh_val_id = 932bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_THRESH_VAL_ID(GP2AP020A00F_TL_L_REG); 933bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (output_val < priv->thresh_val[thresh_val_id]) 934bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski iio_push_event(indio_dev, 935bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski IIO_MOD_EVENT_CODE( 936bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski IIO_LIGHT, 937bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR, 938bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski IIO_MOD_LIGHT_CLEAR, 939bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski IIO_EV_TYPE_THRESH, 940bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski IIO_EV_DIR_FALLING), 941bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski iio_get_time_ns()); 942bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 943bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 944bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 945bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (priv->cur_opmode == GP2AP020A00F_OPMODE_READ_RAW_CLEAR || 946bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski priv->cur_opmode == GP2AP020A00F_OPMODE_READ_RAW_IR || 947bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski priv->cur_opmode == GP2AP020A00F_OPMODE_READ_RAW_PROXIMITY) { 948bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski set_bit(GP2AP020A00F_FLAG_DATA_READY, &priv->flags); 949bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski wake_up(&priv->data_ready_queue); 950bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski goto done; 951bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 952bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 953bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (test_bit(GP2AP020A00F_FLAG_ALS_CLEAR_TRIGGER, &priv->flags) || 954bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski test_bit(GP2AP020A00F_FLAG_ALS_IR_TRIGGER, &priv->flags) || 955bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski test_bit(GP2AP020A00F_FLAG_PROX_TRIGGER, &priv->flags)) 956bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski /* This fires off the trigger. */ 957bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski irq_work_queue(&priv->work); 958bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 959bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskidone: 960bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return IRQ_HANDLED; 961bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski} 962bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 963bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistatic irqreturn_t gp2ap020a00f_trigger_handler(int irq, void *data) 964bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski{ 965bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski struct iio_poll_func *pf = data; 966bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski struct iio_dev *indio_dev = pf->indio_dev; 967bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski struct gp2ap020a00f_data *priv = iio_priv(indio_dev); 968bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski size_t d_size = 0; 969bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski __le32 light_lux; 970bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski int i, out_val, ret; 971bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 972bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski for_each_set_bit(i, indio_dev->active_scan_mask, 973bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski indio_dev->masklength) { 974bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski ret = regmap_bulk_read(priv->regmap, 975bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_DATA_REG(i), 976bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski &priv->buffer[d_size], 2); 977bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (ret < 0) 978bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski goto done; 979bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 980bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (i == GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR || 981bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski i == GP2AP020A00F_SCAN_MODE_LIGHT_IR) { 982bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski out_val = le16_to_cpup((__le16 *)&priv->buffer[d_size]); 983bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski gp2ap020a00f_output_to_lux(priv, &out_val); 984bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski light_lux = cpu_to_le32(out_val); 985bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski memcpy(&priv->buffer[d_size], (u8 *)&light_lux, 4); 986bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski d_size += 4; 987bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } else { 988bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski d_size += 2; 989bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 990bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 991bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 9923b271798330ede49dc41615ce4eceb7a3aef8cd9Lars-Peter Clausen iio_push_to_buffers_with_timestamp(indio_dev, priv->buffer, 9933b271798330ede49dc41615ce4eceb7a3aef8cd9Lars-Peter Clausen pf->timestamp); 994bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskidone: 995bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski iio_trigger_notify_done(indio_dev->trig); 996bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 997bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return IRQ_HANDLED; 998bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski} 999bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 10005d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausenstatic u8 gp2ap020a00f_get_thresh_reg(const struct iio_chan_spec *chan, 10015d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen enum iio_event_direction event_dir) 1002bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski{ 10035d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen switch (chan->type) { 1004bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case IIO_PROXIMITY: 1005bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (event_dir == IIO_EV_DIR_RISING) 1006bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return GP2AP020A00F_PH_L_REG; 1007bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski else 1008bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return GP2AP020A00F_PL_L_REG; 1009bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case IIO_LIGHT: 1010bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (event_dir == IIO_EV_DIR_RISING) 1011bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return GP2AP020A00F_TH_L_REG; 1012bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski else 1013bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return GP2AP020A00F_TL_L_REG; 10145d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen default: 10155d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen break; 1016bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 1017bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1018bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return -EINVAL; 1019bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski} 1020bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1021bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistatic int gp2ap020a00f_write_event_val(struct iio_dev *indio_dev, 10225d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen const struct iio_chan_spec *chan, 10235d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen enum iio_event_type type, 10245d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen enum iio_event_direction dir, 10255d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen enum iio_event_info info, 10265d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen int val, int val2) 1027bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski{ 1028bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski struct gp2ap020a00f_data *data = iio_priv(indio_dev); 1029bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski bool event_en = false; 1030bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski u8 thresh_val_id; 1031bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski u8 thresh_reg_l; 1032bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski int err = 0; 1033bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1034bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski mutex_lock(&data->lock); 1035bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 10365d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen thresh_reg_l = gp2ap020a00f_get_thresh_reg(chan, dir); 1037bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski thresh_val_id = GP2AP020A00F_THRESH_VAL_ID(thresh_reg_l); 1038bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1039bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (thresh_val_id > GP2AP020A00F_THRESH_PH) { 1040bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = -EINVAL; 1041bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski goto error_unlock; 1042bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 1043bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1044bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski switch (thresh_reg_l) { 1045bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_TH_L_REG: 1046bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski event_en = test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, 1047bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski &data->flags); 1048bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 1049bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_TL_L_REG: 1050bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski event_en = test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, 1051bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski &data->flags); 1052bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 1053bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_PH_L_REG: 1054bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (val == 0) { 1055bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = -EINVAL; 1056bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski goto error_unlock; 1057bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 1058bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski event_en = test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, 1059bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski &data->flags); 1060bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 1061bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_PL_L_REG: 1062bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (val == 0) { 1063bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = -EINVAL; 1064bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski goto error_unlock; 1065bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 1066bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski event_en = test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, 1067bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski &data->flags); 1068bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 1069bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 1070bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1071bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski data->thresh_val[thresh_val_id] = val; 1072bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_write_event_threshold(data, thresh_val_id, 1073bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski event_en); 1074bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskierror_unlock: 1075bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski mutex_unlock(&data->lock); 1076bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1077bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return err; 1078bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski} 1079bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1080bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistatic int gp2ap020a00f_read_event_val(struct iio_dev *indio_dev, 10815d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen const struct iio_chan_spec *chan, 10825d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen enum iio_event_type type, 10835d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen enum iio_event_direction dir, 10845d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen enum iio_event_info info, 10855d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen int *val, int *val2) 1086bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski{ 1087bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski struct gp2ap020a00f_data *data = iio_priv(indio_dev); 1088bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski u8 thresh_reg_l; 10895d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen int err = IIO_VAL_INT; 1090bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1091bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski mutex_lock(&data->lock); 1092bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 10935d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen thresh_reg_l = gp2ap020a00f_get_thresh_reg(chan, dir); 1094bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1095bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (thresh_reg_l > GP2AP020A00F_PH_L_REG) { 1096bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = -EINVAL; 1097bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski goto error_unlock; 1098bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 1099bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1100bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski *val = data->thresh_val[GP2AP020A00F_THRESH_VAL_ID(thresh_reg_l)]; 1101bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1102bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskierror_unlock: 1103bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski mutex_unlock(&data->lock); 1104bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1105bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return err; 1106bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski} 1107bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1108bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistatic int gp2ap020a00f_write_prox_event_config(struct iio_dev *indio_dev, 11095d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen int state) 1110bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski{ 1111bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski struct gp2ap020a00f_data *data = iio_priv(indio_dev); 1112bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski enum gp2ap020a00f_cmd cmd_high_ev, cmd_low_ev; 1113bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski int err; 1114bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1115bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski cmd_high_ev = state ? GP2AP020A00F_CMD_PROX_HIGH_EV_EN : 1116bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_CMD_PROX_HIGH_EV_DIS; 1117bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski cmd_low_ev = state ? GP2AP020A00F_CMD_PROX_LOW_EV_EN : 1118bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_CMD_PROX_LOW_EV_DIS; 1119bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1120bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski /* 1121bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * In order to enable proximity detection feature in the device 1122bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * both high and low threshold registers have to be written 1123bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * with different values, greater than zero. 1124bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski */ 1125bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (state) { 1126bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (data->thresh_val[GP2AP020A00F_THRESH_PL] == 0) 1127bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return -EINVAL; 1128bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1129bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (data->thresh_val[GP2AP020A00F_THRESH_PH] == 0) 1130bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return -EINVAL; 1131bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 1132bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1133bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_exec_cmd(data, cmd_high_ev); 1134bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err < 0) 1135bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return err; 1136bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1137bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_exec_cmd(data, cmd_low_ev); 1138bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err < 0) 1139bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return err; 1140bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1141bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski free_irq(data->client->irq, indio_dev); 1142bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1143bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (state) 1144bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = request_threaded_irq(data->client->irq, NULL, 1145bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski &gp2ap020a00f_prox_sensing_handler, 1146bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski IRQF_TRIGGER_RISING | 1147bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski IRQF_TRIGGER_FALLING | 1148bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski IRQF_ONESHOT, 1149bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski "gp2ap020a00f_prox_sensing", 1150bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski indio_dev); 1151bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski else { 1152bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = request_threaded_irq(data->client->irq, NULL, 1153bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski &gp2ap020a00f_thresh_event_handler, 1154bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski IRQF_TRIGGER_FALLING | 1155bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski IRQF_ONESHOT, 1156bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski "gp2ap020a00f_thresh_event", 1157bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski indio_dev); 1158bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 1159bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1160bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return err; 1161bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski} 1162bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1163bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistatic int gp2ap020a00f_write_event_config(struct iio_dev *indio_dev, 11645d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen const struct iio_chan_spec *chan, 11655d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen enum iio_event_type type, 11665d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen enum iio_event_direction dir, 11675d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen int state) 1168bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski{ 1169bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski struct gp2ap020a00f_data *data = iio_priv(indio_dev); 1170bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski enum gp2ap020a00f_cmd cmd; 1171bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski int err; 1172bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1173bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski mutex_lock(&data->lock); 1174bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 11755d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen switch (chan->type) { 1176bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case IIO_PROXIMITY: 11775d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen err = gp2ap020a00f_write_prox_event_config(indio_dev, state); 1178bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 1179bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case IIO_LIGHT: 11805d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen if (dir == IIO_EV_DIR_RISING) { 1181bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski cmd = state ? GP2AP020A00F_CMD_ALS_HIGH_EV_EN : 1182bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_CMD_ALS_HIGH_EV_DIS; 1183bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_exec_cmd(data, cmd); 1184bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } else { 1185bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski cmd = state ? GP2AP020A00F_CMD_ALS_LOW_EV_EN : 1186bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_CMD_ALS_LOW_EV_DIS; 1187bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_exec_cmd(data, cmd); 1188bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 1189bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 1190bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski default: 1191bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = -EINVAL; 1192bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 1193bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1194bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski mutex_unlock(&data->lock); 1195bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1196bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return err; 1197bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski} 1198bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1199bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistatic int gp2ap020a00f_read_event_config(struct iio_dev *indio_dev, 12005d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen const struct iio_chan_spec *chan, 12015d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen enum iio_event_type type, 12025d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen enum iio_event_direction dir) 1203bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski{ 1204bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski struct gp2ap020a00f_data *data = iio_priv(indio_dev); 1205bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski int event_en = 0; 1206bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1207bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski mutex_lock(&data->lock); 1208bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 12095d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen switch (chan->type) { 1210bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case IIO_PROXIMITY: 12115d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen if (dir == IIO_EV_DIR_RISING) 1212bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski event_en = test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, 1213bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski &data->flags); 1214bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski else 1215bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski event_en = test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, 1216bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski &data->flags); 1217bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 1218bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case IIO_LIGHT: 12195d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen if (dir == IIO_EV_DIR_RISING) 1220bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski event_en = test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, 1221bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski &data->flags); 1222bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski else 1223bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski event_en = test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, 1224bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski &data->flags); 1225bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 12265d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen default: 12275d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen event_en = -EINVAL; 12285d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen break; 1229bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 1230bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1231bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski mutex_unlock(&data->lock); 1232bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1233bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return event_en; 1234bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski} 1235bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1236bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistatic int gp2ap020a00f_read_channel(struct gp2ap020a00f_data *data, 1237bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski struct iio_chan_spec const *chan, int *val) 1238bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski{ 1239bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski enum gp2ap020a00f_cmd cmd; 1240bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski int err; 1241bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1242bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski switch (chan->scan_index) { 1243bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR: 1244bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski cmd = GP2AP020A00F_CMD_READ_RAW_CLEAR; 1245bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 1246bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_SCAN_MODE_LIGHT_IR: 1247bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski cmd = GP2AP020A00F_CMD_READ_RAW_IR; 1248bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 1249bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_SCAN_MODE_PROXIMITY: 1250bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski cmd = GP2AP020A00F_CMD_READ_RAW_PROXIMITY; 1251bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 1252bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski default: 1253bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return -EINVAL; 1254bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 1255bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1256bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_exec_cmd(data, cmd); 1257bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err < 0) { 1258bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski dev_err(&data->client->dev, 1259bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski "gp2ap020a00f_exec_cmd failed\n"); 1260bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski goto error_ret; 1261bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 1262bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1263bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_read_output(data, chan->address, val); 1264bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err < 0) 1265bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski dev_err(&data->client->dev, 1266bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski "gp2ap020a00f_read_output failed\n"); 1267bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1268bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_set_operation_mode(data, 1269bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OPMODE_SHUTDOWN); 1270bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err < 0) 1271bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski dev_err(&data->client->dev, 1272bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski "Failed to shut down the device.\n"); 1273bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1274bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (cmd == GP2AP020A00F_CMD_READ_RAW_CLEAR || 1275bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski cmd == GP2AP020A00F_CMD_READ_RAW_IR) 1276bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski gp2ap020a00f_output_to_lux(data, val); 1277bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1278bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskierror_ret: 1279bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return err; 1280bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski} 1281bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1282bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistatic int gp2ap020a00f_read_raw(struct iio_dev *indio_dev, 1283bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski struct iio_chan_spec const *chan, 1284bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski int *val, int *val2, 1285bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski long mask) 1286bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski{ 1287bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski struct gp2ap020a00f_data *data = iio_priv(indio_dev); 1288bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski int err = -EINVAL; 1289bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1290bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski mutex_lock(&data->lock); 1291bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1292bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski switch (mask) { 1293bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case IIO_CHAN_INFO_RAW: 1294bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (iio_buffer_enabled(indio_dev)) { 1295bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = -EBUSY; 1296bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski goto error_unlock; 1297bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 1298bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1299bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_read_channel(data, chan, val); 1300bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 1301bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 1302bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1303bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskierror_unlock: 1304bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski mutex_unlock(&data->lock); 1305bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1306bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return err < 0 ? err : IIO_VAL_INT; 1307bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski} 1308bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 13095d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausenstatic const struct iio_event_spec gp2ap020a00f_event_spec_light[] = { 13105d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen { 13115d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen .type = IIO_EV_TYPE_THRESH, 13125d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen .dir = IIO_EV_DIR_RISING, 13135d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen .mask_separate = BIT(IIO_EV_INFO_VALUE) | 13145d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen BIT(IIO_EV_INFO_ENABLE), 13155d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen }, { 13165d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen .type = IIO_EV_TYPE_THRESH, 13175d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen .dir = IIO_EV_DIR_FALLING, 13185d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen .mask_separate = BIT(IIO_EV_INFO_VALUE) | 13195d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen BIT(IIO_EV_INFO_ENABLE), 13205d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen }, 13215d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen}; 13225d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen 13235d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausenstatic const struct iio_event_spec gp2ap020a00f_event_spec_prox[] = { 13245d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen { 13255d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen .type = IIO_EV_TYPE_ROC, 13265d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen .dir = IIO_EV_DIR_RISING, 13275d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen .mask_separate = BIT(IIO_EV_INFO_VALUE) | 13285d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen BIT(IIO_EV_INFO_ENABLE), 13295d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen }, { 13305d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen .type = IIO_EV_TYPE_ROC, 13315d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen .dir = IIO_EV_DIR_FALLING, 13325d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen .mask_separate = BIT(IIO_EV_INFO_VALUE) | 13335d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen BIT(IIO_EV_INFO_ENABLE), 13345d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen }, 13355d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen}; 13365d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen 1337bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistatic const struct iio_chan_spec gp2ap020a00f_channels[] = { 1338bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski { 1339bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .type = IIO_LIGHT, 1340bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .channel2 = IIO_MOD_LIGHT_CLEAR, 1341bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .modified = 1, 1342bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 1343bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .scan_type = { 1344bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .sign = 'u', 1345bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .realbits = 24, 1346bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .shift = 0, 1347bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .storagebits = 32, 1348bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .endianness = IIO_LE, 1349bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski }, 1350bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .scan_index = GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR, 1351bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .address = GP2AP020A00F_D0_L_REG, 13525d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen .event_spec = gp2ap020a00f_event_spec_light, 13535d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen .num_event_specs = ARRAY_SIZE(gp2ap020a00f_event_spec_light), 1354bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski }, 1355bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski { 1356bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .type = IIO_LIGHT, 1357bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .channel2 = IIO_MOD_LIGHT_IR, 1358bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .modified = 1, 1359bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 1360bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .scan_type = { 1361bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .sign = 'u', 1362bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .realbits = 24, 1363bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .shift = 0, 1364bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .storagebits = 32, 1365bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .endianness = IIO_LE, 1366bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski }, 1367bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .scan_index = GP2AP020A00F_SCAN_MODE_LIGHT_IR, 1368bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .address = GP2AP020A00F_D1_L_REG, 1369bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski }, 1370bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski { 1371bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .type = IIO_PROXIMITY, 1372bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .modified = 0, 1373bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 1374bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .scan_type = { 1375bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .sign = 'u', 1376bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .realbits = 16, 1377bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .shift = 0, 1378bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .storagebits = 16, 1379bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .endianness = IIO_LE, 1380bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski }, 1381bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .scan_index = GP2AP020A00F_SCAN_MODE_PROXIMITY, 1382bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .address = GP2AP020A00F_D2_L_REG, 13835d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen .event_spec = gp2ap020a00f_event_spec_prox, 13845d6a25bad035981b3ceb768ae6164248004e226dLars-Peter Clausen .num_event_specs = ARRAY_SIZE(gp2ap020a00f_event_spec_prox), 1385bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski }, 1386bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski IIO_CHAN_SOFT_TIMESTAMP(GP2AP020A00F_CHAN_TIMESTAMP), 1387bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski}; 1388bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1389bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistatic const struct iio_info gp2ap020a00f_info = { 1390bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .read_raw = &gp2ap020a00f_read_raw, 1391cb955852a48c29ef7bd847ce993102e2b58295d4Lars-Peter Clausen .read_event_value = &gp2ap020a00f_read_event_val, 1392cb955852a48c29ef7bd847ce993102e2b58295d4Lars-Peter Clausen .read_event_config = &gp2ap020a00f_read_event_config, 1393cb955852a48c29ef7bd847ce993102e2b58295d4Lars-Peter Clausen .write_event_value = &gp2ap020a00f_write_event_val, 1394cb955852a48c29ef7bd847ce993102e2b58295d4Lars-Peter Clausen .write_event_config = &gp2ap020a00f_write_event_config, 1395bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .driver_module = THIS_MODULE, 1396bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski}; 1397bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1398bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistatic int gp2ap020a00f_buffer_postenable(struct iio_dev *indio_dev) 1399bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski{ 1400bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski struct gp2ap020a00f_data *data = iio_priv(indio_dev); 1401bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski int i, err = 0; 1402bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1403bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski mutex_lock(&data->lock); 1404bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1405bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski /* 1406bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * Enable triggers according to the scan_mask. Enabling either 1407bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * LIGHT_CLEAR or LIGHT_IR scan mode results in enabling ALS 1408bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * module in the device, which generates samples in both D0 (clear) 1409bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * and D1 (ir) registers. As the two registers are bound to the 1410bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * two separate IIO channels they are treated in the driver logic 1411bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski * as if they were controlled independently. 1412bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski */ 1413bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski for_each_set_bit(i, indio_dev->active_scan_mask, 1414bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski indio_dev->masklength) { 1415bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski switch (i) { 1416bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR: 1417bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_exec_cmd(data, 1418bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_CMD_TRIGGER_CLEAR_EN); 1419bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 1420bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_SCAN_MODE_LIGHT_IR: 1421bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_exec_cmd(data, 1422bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_CMD_TRIGGER_IR_EN); 1423bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 1424bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_SCAN_MODE_PROXIMITY: 1425bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_exec_cmd(data, 1426bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_CMD_TRIGGER_PROX_EN); 1427bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 1428bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 1429bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 1430bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1431bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err < 0) 1432bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski goto error_unlock; 1433bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1434bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski data->buffer = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); 1435bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (!data->buffer) { 1436bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = -ENOMEM; 1437bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski goto error_unlock; 1438bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 1439bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1440bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = iio_triggered_buffer_postenable(indio_dev); 1441bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1442bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskierror_unlock: 1443bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski mutex_unlock(&data->lock); 1444bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1445bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return err; 1446bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski} 1447bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1448bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistatic int gp2ap020a00f_buffer_predisable(struct iio_dev *indio_dev) 1449bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski{ 1450bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski struct gp2ap020a00f_data *data = iio_priv(indio_dev); 1451bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski int i, err; 1452bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1453bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski mutex_lock(&data->lock); 1454bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1455bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = iio_triggered_buffer_predisable(indio_dev); 1456bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err < 0) 1457bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski goto error_unlock; 1458bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1459bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski for_each_set_bit(i, indio_dev->active_scan_mask, 1460bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski indio_dev->masklength) { 1461bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski switch (i) { 1462bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR: 1463bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_exec_cmd(data, 1464bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_CMD_TRIGGER_CLEAR_DIS); 1465bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 1466bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_SCAN_MODE_LIGHT_IR: 1467bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_exec_cmd(data, 1468bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_CMD_TRIGGER_IR_DIS); 1469bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 1470bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski case GP2AP020A00F_SCAN_MODE_PROXIMITY: 1471bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_exec_cmd(data, 1472bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_CMD_TRIGGER_PROX_DIS); 1473bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski break; 1474bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 1475bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 1476bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1477bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err == 0) 1478bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski kfree(data->buffer); 1479bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1480bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskierror_unlock: 1481bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski mutex_unlock(&data->lock); 1482bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1483bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return err; 1484bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski} 1485bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1486bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistatic const struct iio_buffer_setup_ops gp2ap020a00f_buffer_setup_ops = { 1487bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .postenable = &gp2ap020a00f_buffer_postenable, 1488bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .predisable = &gp2ap020a00f_buffer_predisable, 1489bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski}; 1490bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1491bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistatic const struct iio_trigger_ops gp2ap020a00f_trigger_ops = { 1492bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .owner = THIS_MODULE, 1493bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski}; 1494bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1495bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistatic int gp2ap020a00f_probe(struct i2c_client *client, 1496bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski const struct i2c_device_id *id) 1497bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski{ 1498bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski struct gp2ap020a00f_data *data; 1499bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski struct iio_dev *indio_dev; 1500bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski struct regmap *regmap; 1501bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski int err; 1502bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1503bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 1504bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (!indio_dev) 1505bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return -ENOMEM; 1506bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1507bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski data = iio_priv(indio_dev); 1508bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1509bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski data->vled_reg = devm_regulator_get(&client->dev, "vled"); 1510bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (IS_ERR(data->vled_reg)) 1511bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return PTR_ERR(data->vled_reg); 1512bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1513bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = regulator_enable(data->vled_reg); 1514bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err) 1515bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return err; 1516bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1517bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski regmap = devm_regmap_init_i2c(client, &gp2ap020a00f_regmap_config); 1518bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (IS_ERR(regmap)) { 1519bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski dev_err(&client->dev, "Regmap initialization failed.\n"); 1520bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = PTR_ERR(regmap); 1521bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski goto error_regulator_disable; 1522bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 1523bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1524bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski /* Initialize device registers */ 1525bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = regmap_bulk_write(regmap, GP2AP020A00F_OP_REG, 1526bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski gp2ap020a00f_reg_init_tab, 1527bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski ARRAY_SIZE(gp2ap020a00f_reg_init_tab)); 1528bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1529bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err < 0) { 1530bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski dev_err(&client->dev, "Device initialization failed.\n"); 1531bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski goto error_regulator_disable; 1532bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 1533bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1534bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski i2c_set_clientdata(client, indio_dev); 1535bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1536bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski data->client = client; 1537bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski data->cur_opmode = GP2AP020A00F_OPMODE_SHUTDOWN; 1538bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski data->regmap = regmap; 1539bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski init_waitqueue_head(&data->data_ready_queue); 1540bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1541bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski mutex_init(&data->lock); 1542bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski indio_dev->dev.parent = &client->dev; 1543bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski indio_dev->channels = gp2ap020a00f_channels; 1544bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski indio_dev->num_channels = ARRAY_SIZE(gp2ap020a00f_channels); 1545bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski indio_dev->info = &gp2ap020a00f_info; 1546bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski indio_dev->name = id->name; 1547bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski indio_dev->modes = INDIO_DIRECT_MODE; 1548bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1549bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski /* Allocate buffer */ 1550bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, 1551bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski &gp2ap020a00f_trigger_handler, &gp2ap020a00f_buffer_setup_ops); 1552bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err < 0) 1553bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski goto error_regulator_disable; 1554bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1555bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski /* Allocate trigger */ 1556bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski data->trig = devm_iio_trigger_alloc(&client->dev, "%s-trigger", 1557bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski indio_dev->name); 1558bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (data->trig == NULL) { 1559bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = -ENOMEM; 1560bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski dev_err(&indio_dev->dev, "Failed to allocate iio trigger.\n"); 1561bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski goto error_uninit_buffer; 1562bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 1563bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1564bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski /* This needs to be requested here for read_raw calls to work. */ 1565bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = request_threaded_irq(client->irq, NULL, 1566bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski &gp2ap020a00f_thresh_event_handler, 1567bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski IRQF_TRIGGER_FALLING | 1568bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski IRQF_ONESHOT, 1569bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski "gp2ap020a00f_als_event", 1570bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski indio_dev); 1571bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err < 0) { 1572bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski dev_err(&client->dev, "Irq request failed.\n"); 1573bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski goto error_uninit_buffer; 1574bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 1575bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1576bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski data->trig->ops = &gp2ap020a00f_trigger_ops; 1577bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski data->trig->dev.parent = &data->client->dev; 1578bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1579bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski init_irq_work(&data->work, gp2ap020a00f_iio_trigger_work); 1580bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1581bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = iio_trigger_register(data->trig); 1582bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err < 0) { 1583bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski dev_err(&client->dev, "Failed to register iio trigger.\n"); 1584bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski goto error_free_irq; 1585bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski } 1586bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1587bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = iio_device_register(indio_dev); 1588bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err < 0) 1589bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski goto error_trigger_unregister; 1590bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1591bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return 0; 1592bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1593bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskierror_trigger_unregister: 1594bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski iio_trigger_unregister(data->trig); 1595bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskierror_free_irq: 1596bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski free_irq(client->irq, indio_dev); 1597bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskierror_uninit_buffer: 1598bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski iio_triggered_buffer_cleanup(indio_dev); 1599bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskierror_regulator_disable: 1600bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski regulator_disable(data->vled_reg); 1601bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1602bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return err; 1603bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski} 1604bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1605bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistatic int gp2ap020a00f_remove(struct i2c_client *client) 1606bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski{ 1607bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski struct iio_dev *indio_dev = i2c_get_clientdata(client); 1608bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski struct gp2ap020a00f_data *data = iio_priv(indio_dev); 1609bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski int err; 1610bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1611bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski err = gp2ap020a00f_set_operation_mode(data, 1612bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski GP2AP020A00F_OPMODE_SHUTDOWN); 1613bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski if (err < 0) 1614bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski dev_err(&indio_dev->dev, "Failed to power off the device.\n"); 1615bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1616bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski iio_device_unregister(indio_dev); 1617bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski iio_trigger_unregister(data->trig); 1618bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski free_irq(client->irq, indio_dev); 1619bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski iio_triggered_buffer_cleanup(indio_dev); 1620bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski regulator_disable(data->vled_reg); 1621bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1622bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski return 0; 1623bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski} 1624bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1625bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistatic const struct i2c_device_id gp2ap020a00f_id[] = { 1626bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski { GP2A_I2C_NAME, 0 }, 1627bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski { } 1628bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski}; 1629bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1630bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek AnaszewskiMODULE_DEVICE_TABLE(i2c, gp2ap020a00f_id); 1631bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1632bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#ifdef CONFIG_OF 1633bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistatic const struct of_device_id gp2ap020a00f_of_match[] = { 1634bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski { .compatible = "sharp,gp2ap020a00f" }, 1635bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski { } 1636bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski}; 1637bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski#endif 1638bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1639bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskistatic struct i2c_driver gp2ap020a00f_driver = { 1640bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .driver = { 1641bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .name = GP2A_I2C_NAME, 1642bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .of_match_table = of_match_ptr(gp2ap020a00f_of_match), 1643bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .owner = THIS_MODULE, 1644bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski }, 1645bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .probe = gp2ap020a00f_probe, 1646bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .remove = gp2ap020a00f_remove, 1647bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski .id_table = gp2ap020a00f_id, 1648bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski}; 1649bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1650bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewskimodule_i2c_driver(gp2ap020a00f_driver); 1651bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek Anaszewski 1652bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek AnaszewskiMODULE_AUTHOR("Jacek Anaszewski <j.anaszewski@samsung.com>"); 1653bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek AnaszewskiMODULE_DESCRIPTION("Sharp GP2AP020A00F Proximity/ALS sensor driver"); 1654bf29fbeaa13d3350ca71df70c705d8b883c45692Jacek AnaszewskiMODULE_LICENSE("GPL v2"); 1655