2019-06-04 10:11:33 +02:00
// SPDX-License-Identifier: GPL-2.0-only
2013-12-24 01:53:00 +00:00
/*
* Copyright ( C ) 2013 Capella Microsystems Inc .
* Author : Kevin Tsai < ktsai @ capellamicro . com >
*/
2020-04-28 19:29:22 +02:00
# include <linux/acpi.h>
2013-12-24 01:53:00 +00:00
# include <linux/delay.h>
# include <linux/err.h>
# include <linux/i2c.h>
# include <linux/mutex.h>
# include <linux/module.h>
2020-04-19 16:02:01 +01:00
# include <linux/mod_devicetable.h>
2013-12-24 01:53:00 +00:00
# include <linux/interrupt.h>
# include <linux/regulator/consumer.h>
# include <linux/iio/iio.h>
# include <linux/iio/sysfs.h>
# include <linux/iio/events.h>
# include <linux/init.h>
/* Registers Address */
# define CM32181_REG_ADDR_CMD 0x00
2020-04-28 19:29:15 +02:00
# define CM32181_REG_ADDR_WH 0x01
# define CM32181_REG_ADDR_WL 0x02
# define CM32181_REG_ADDR_TEST 0x03
2013-12-24 01:53:00 +00:00
# define CM32181_REG_ADDR_ALS 0x04
# define CM32181_REG_ADDR_STATUS 0x06
# define CM32181_REG_ADDR_ID 0x07
/* Number of Configurable Registers */
2020-04-28 19:29:19 +02:00
# define CM32181_CONF_REG_NUM 4
2013-12-24 01:53:00 +00:00
/* CMD register */
2020-04-28 19:29:15 +02:00
# define CM32181_CMD_ALS_DISABLE BIT(0)
# define CM32181_CMD_ALS_INT_EN BIT(1)
# define CM32181_CMD_ALS_THRES_WINDOW BIT(2)
# define CM32181_CMD_ALS_PERS_SHIFT 4
# define CM32181_CMD_ALS_PERS_MASK (0x03 << CM32181_CMD_ALS_PERS_SHIFT)
# define CM32181_CMD_ALS_PERS_DEFAULT (0x01 << CM32181_CMD_ALS_PERS_SHIFT)
2013-12-24 01:53:00 +00:00
# define CM32181_CMD_ALS_IT_SHIFT 6
# define CM32181_CMD_ALS_IT_MASK (0x0F << CM32181_CMD_ALS_IT_SHIFT)
# define CM32181_CMD_ALS_IT_DEFAULT (0x00 << CM32181_CMD_ALS_IT_SHIFT)
# define CM32181_CMD_ALS_SM_SHIFT 11
# define CM32181_CMD_ALS_SM_MASK (0x03 << CM32181_CMD_ALS_SM_SHIFT)
# define CM32181_CMD_ALS_SM_DEFAULT (0x01 << CM32181_CMD_ALS_SM_SHIFT)
2020-04-28 19:29:20 +02:00
# define CM32181_LUX_PER_BIT 500 /* ALS_SM=01 IT=800ms */
# define CM32181_LUX_PER_BIT_RESOLUTION 100000
# define CM32181_LUX_PER_BIT_BASE_IT 800000 /* Based on IT=800ms */
# define CM32181_CALIBSCALE_DEFAULT 100000
# define CM32181_CALIBSCALE_RESOLUTION 100000
2013-12-24 01:53:00 +00:00
iio: light: cm32181: Handle CM3218 ACPI devices with 2 I2C resources
Some ACPI systems list 2 I2C resources for the CM3218 sensor. On these
systems the first I2cSerialBus ACPI-resource points to the SMBus Alert
Response Address (ARA, 0x0c) and the second I2cSerialBus ACPI-resource
points to the actual CM3218 sensor address:
Method (_CRS, 0, NotSerialized) // _CRS: Current Resource Settings
{
Name (SBUF, ResourceTemplate ()
{
I2cSerialBusV2 (0x000C, ControllerInitiated, 0x00061A80,
AddressingMode7Bit, "\\_SB.I2C3",
0x00, ResourceConsumer, , Exclusive,
)
I2cSerialBusV2 (0x0048, ControllerInitiated, 0x00061A80,
AddressingMode7Bit, "\\_SB.I2C3",
0x00, ResourceConsumer, , Exclusive,
)
Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive, ,, )
{
0x00000033,
}
})
Return (SBUF) /* \_SB_.I2C3.ALSD._CRS.SBUF */
}
Detect this and take the following step to deal with it:
1. When a SMBus Alert capable sensor has an Alert asserted, it will
not respond on its actual I2C address. Read a byte from the ARA
to clear any pending Alerts.
2. Create a "dummy" client for the actual I2C address and
use that client to communicate with the sensor.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
2020-04-28 19:29:18 +02:00
# define SMBUS_ALERT_RESPONSE_ADDRESS 0x0c
2020-04-28 19:29:22 +02:00
/* CPM0 Index 0: device-id (3218 or 32181), 1: Unknown, 2: init_regs_bitmap */
# define CPM0_REGS_BITMAP 2
# define CPM0_HEADER_SIZE 3
/* CPM1 Index 0: lux_per_bit, 1: calibscale, 2: resolution (100000) */
# define CPM1_LUX_PER_BIT 0
# define CPM1_CALIBSCALE 1
# define CPM1_SIZE 3
2020-04-28 19:29:16 +02:00
/* CM3218 Family */
static const int cm3218_als_it_bits [ ] = { 0 , 1 , 2 , 3 } ;
static const int cm3218_als_it_values [ ] = { 100000 , 200000 , 400000 , 800000 } ;
/* CM32181 Family */
static const int cm32181_als_it_bits [ ] = { 12 , 8 , 0 , 1 , 2 , 3 } ;
static const int cm32181_als_it_values [ ] = {
25000 , 50000 , 100000 , 200000 , 400000 , 800000
} ;
2013-12-24 01:53:00 +00:00
struct cm32181_chip {
struct i2c_client * client ;
2020-04-28 19:29:22 +02:00
struct device * dev ;
2013-12-24 01:53:00 +00:00
struct mutex lock ;
u16 conf_regs [ CM32181_CONF_REG_NUM ] ;
2020-04-28 19:29:19 +02:00
unsigned long init_regs_bitmap ;
2013-12-24 01:53:00 +00:00
int calibscale ;
2020-04-28 19:29:21 +02:00
int lux_per_bit ;
int lux_per_bit_base_it ;
2020-04-28 19:29:16 +02:00
int num_als_it ;
const int * als_it_bits ;
const int * als_it_values ;
2013-12-24 01:53:00 +00:00
} ;
2020-04-28 19:29:22 +02:00
static int cm32181_read_als_it ( struct cm32181_chip * cm32181 , int * val2 ) ;
# ifdef CONFIG_ACPI
/**
* cm32181_acpi_get_cpm ( ) - Get CPM object from ACPI
* @ client pointer of struct i2c_client .
* @ obj_name pointer of ACPI object name .
* @ count maximum size of return array .
* @ vals pointer of array for return elements .
*
* Convert ACPI CPM table to array .
*
* Return : - ENODEV for fail . Otherwise is number of elements .
*/
static int cm32181_acpi_get_cpm ( struct device * dev , char * obj_name ,
u64 * values , int count )
{
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER , NULL } ;
union acpi_object * cpm , * elem ;
acpi_handle handle ;
acpi_status status ;
int i ;
handle = ACPI_HANDLE ( dev ) ;
if ( ! handle )
return - ENODEV ;
status = acpi_evaluate_object ( handle , obj_name , NULL , & buffer ) ;
if ( ACPI_FAILURE ( status ) ) {
dev_err ( dev , " object %s not found \n " , obj_name ) ;
return - ENODEV ;
}
cpm = buffer . pointer ;
if ( cpm - > package . count > count )
dev_warn ( dev , " %s table contains %u values, only using first %d values \n " ,
obj_name , cpm - > package . count , count ) ;
count = min_t ( int , cpm - > package . count , count ) ;
for ( i = 0 ; i < count ; i + + ) {
elem = & ( cpm - > package . elements [ i ] ) ;
values [ i ] = elem - > integer . value ;
}
kfree ( buffer . pointer ) ;
return count ;
}
static void cm32181_acpi_parse_cpm_tables ( struct cm32181_chip * cm32181 )
{
u64 vals [ CPM0_HEADER_SIZE + CM32181_CONF_REG_NUM ] ;
struct device * dev = cm32181 - > dev ;
int i , count ;
count = cm32181_acpi_get_cpm ( dev , " CPM0 " , vals , ARRAY_SIZE ( vals ) ) ;
if ( count < = CPM0_HEADER_SIZE )
return ;
count - = CPM0_HEADER_SIZE ;
cm32181 - > init_regs_bitmap = vals [ CPM0_REGS_BITMAP ] ;
cm32181 - > init_regs_bitmap & = GENMASK ( count - 1 , 0 ) ;
for_each_set_bit ( i , & cm32181 - > init_regs_bitmap , count )
cm32181 - > conf_regs [ i ] = vals [ CPM0_HEADER_SIZE + i ] ;
count = cm32181_acpi_get_cpm ( dev , " CPM1 " , vals , ARRAY_SIZE ( vals ) ) ;
if ( count ! = CPM1_SIZE )
return ;
cm32181 - > lux_per_bit = vals [ CPM1_LUX_PER_BIT ] ;
/* Check for uncalibrated devices */
if ( vals [ CPM1_CALIBSCALE ] = = CM32181_CALIBSCALE_DEFAULT )
return ;
cm32181 - > calibscale = vals [ CPM1_CALIBSCALE ] ;
/* CPM1 lux_per_bit is for the current it value */
cm32181_read_als_it ( cm32181 , & cm32181 - > lux_per_bit_base_it ) ;
}
# else
static void cm32181_acpi_parse_cpm_tables ( struct cm32181_chip * cm32181 )
{
}
# endif /* CONFIG_ACPI */
2013-12-24 01:53:00 +00:00
/**
* cm32181_reg_init ( ) - Initialize CM32181 registers
* @ cm32181 : pointer of struct cm32181 .
*
* Initialize CM32181 ambient light sensor register to default values .
*
* Return : 0 for success ; otherwise for error code .
*/
static int cm32181_reg_init ( struct cm32181_chip * cm32181 )
{
struct i2c_client * client = cm32181 - > client ;
int i ;
s32 ret ;
ret = i2c_smbus_read_word_data ( client , CM32181_REG_ADDR_ID ) ;
if ( ret < 0 )
return ret ;
/* check device ID */
2020-04-28 19:29:16 +02:00
switch ( ret & 0xFF ) {
case 0x18 : /* CM3218 */
cm32181 - > num_als_it = ARRAY_SIZE ( cm3218_als_it_bits ) ;
cm32181 - > als_it_bits = cm3218_als_it_bits ;
cm32181 - > als_it_values = cm3218_als_it_values ;
break ;
case 0x81 : /* CM32181 */
case 0x82 : /* CM32182, fully compat. with CM32181 */
cm32181 - > num_als_it = ARRAY_SIZE ( cm32181_als_it_bits ) ;
cm32181 - > als_it_bits = cm32181_als_it_bits ;
cm32181 - > als_it_values = cm32181_als_it_values ;
break ;
default :
2013-12-24 01:53:00 +00:00
return - ENODEV ;
2020-04-28 19:29:16 +02:00
}
2013-12-24 01:53:00 +00:00
/* Default Values */
2020-04-28 19:29:15 +02:00
cm32181 - > conf_regs [ CM32181_REG_ADDR_CMD ] =
2013-12-24 01:53:00 +00:00
CM32181_CMD_ALS_IT_DEFAULT | CM32181_CMD_ALS_SM_DEFAULT ;
2020-04-28 19:29:19 +02:00
cm32181 - > init_regs_bitmap = BIT ( CM32181_REG_ADDR_CMD ) ;
2013-12-24 01:53:00 +00:00
cm32181 - > calibscale = CM32181_CALIBSCALE_DEFAULT ;
2020-04-28 19:29:21 +02:00
cm32181 - > lux_per_bit = CM32181_LUX_PER_BIT ;
cm32181 - > lux_per_bit_base_it = CM32181_LUX_PER_BIT_BASE_IT ;
2013-12-24 01:53:00 +00:00
2020-04-28 19:29:22 +02:00
if ( ACPI_HANDLE ( cm32181 - > dev ) )
cm32181_acpi_parse_cpm_tables ( cm32181 ) ;
2013-12-24 01:53:00 +00:00
/* Initialize registers*/
2020-04-28 19:29:19 +02:00
for_each_set_bit ( i , & cm32181 - > init_regs_bitmap , CM32181_CONF_REG_NUM ) {
ret = i2c_smbus_write_word_data ( client , i ,
cm32181 - > conf_regs [ i ] ) ;
2013-12-24 01:53:00 +00:00
if ( ret < 0 )
return ret ;
}
return 0 ;
}
/**
* cm32181_read_als_it ( ) - Get sensor integration time ( ms )
* @ cm32181 : pointer of struct cm32181
2014-02-14 10:04:00 +00:00
* @ val2 : pointer of int to load the als_it value .
2013-12-24 01:53:00 +00:00
*
2020-04-28 19:29:23 +02:00
* Report the current integration time in milliseconds .
2013-12-24 01:53:00 +00:00
*
2014-02-14 10:04:00 +00:00
* Return : IIO_VAL_INT_PLUS_MICRO for success , otherwise - EINVAL .
2013-12-24 01:53:00 +00:00
*/
2014-02-14 10:04:00 +00:00
static int cm32181_read_als_it ( struct cm32181_chip * cm32181 , int * val2 )
2013-12-24 01:53:00 +00:00
{
u16 als_it ;
int i ;
als_it = cm32181 - > conf_regs [ CM32181_REG_ADDR_CMD ] ;
als_it & = CM32181_CMD_ALS_IT_MASK ;
als_it > > = CM32181_CMD_ALS_IT_SHIFT ;
2020-04-28 19:29:16 +02:00
for ( i = 0 ; i < cm32181 - > num_als_it ; i + + ) {
if ( als_it = = cm32181 - > als_it_bits [ i ] ) {
* val2 = cm32181 - > als_it_values [ i ] ;
2014-02-14 10:04:00 +00:00
return IIO_VAL_INT_PLUS_MICRO ;
2013-12-24 01:53:00 +00:00
}
}
return - EINVAL ;
}
/**
* cm32181_write_als_it ( ) - Write sensor integration time
* @ cm32181 : pointer of struct cm32181 .
* @ val : integration time by millisecond .
*
* Convert integration time ( ms ) to sensor value .
*
* Return : i2c_smbus_write_word_data command return value .
*/
static int cm32181_write_als_it ( struct cm32181_chip * cm32181 , int val )
{
struct i2c_client * client = cm32181 - > client ;
u16 als_it ;
int ret , i , n ;
2020-04-28 19:29:16 +02:00
n = cm32181 - > num_als_it ;
2013-12-24 01:53:00 +00:00
for ( i = 0 ; i < n ; i + + )
2020-04-28 19:29:16 +02:00
if ( val < = cm32181 - > als_it_values [ i ] )
2013-12-24 01:53:00 +00:00
break ;
if ( i > = n )
i = n - 1 ;
2020-04-28 19:29:16 +02:00
als_it = cm32181 - > als_it_bits [ i ] ;
2013-12-24 01:53:00 +00:00
als_it < < = CM32181_CMD_ALS_IT_SHIFT ;
mutex_lock ( & cm32181 - > lock ) ;
cm32181 - > conf_regs [ CM32181_REG_ADDR_CMD ] & =
~ CM32181_CMD_ALS_IT_MASK ;
cm32181 - > conf_regs [ CM32181_REG_ADDR_CMD ] | =
als_it ;
ret = i2c_smbus_write_word_data ( client , CM32181_REG_ADDR_CMD ,
cm32181 - > conf_regs [ CM32181_REG_ADDR_CMD ] ) ;
mutex_unlock ( & cm32181 - > lock ) ;
return ret ;
}
/**
* cm32181_get_lux ( ) - report current lux value
* @ cm32181 : pointer of struct cm32181 .
*
* Convert sensor raw data to lux . It depends on integration
2015-01-16 00:24:41 +02:00
* time and calibscale variable .
2013-12-24 01:53:00 +00:00
*
* Return : Positive value is lux , otherwise is error code .
*/
static int cm32181_get_lux ( struct cm32181_chip * cm32181 )
{
struct i2c_client * client = cm32181 - > client ;
int ret ;
int als_it ;
2020-04-28 19:29:20 +02:00
u64 lux ;
2013-12-24 01:53:00 +00:00
ret = cm32181_read_als_it ( cm32181 , & als_it ) ;
if ( ret < 0 )
return - EINVAL ;
2020-04-28 19:29:21 +02:00
lux = cm32181 - > lux_per_bit ;
lux * = cm32181 - > lux_per_bit_base_it ;
2020-04-28 19:29:20 +02:00
lux = div_u64 ( lux , als_it ) ;
2013-12-24 01:53:00 +00:00
ret = i2c_smbus_read_word_data ( client , CM32181_REG_ADDR_ALS ) ;
if ( ret < 0 )
return ret ;
lux * = ret ;
lux * = cm32181 - > calibscale ;
2020-04-28 19:29:20 +02:00
lux = div_u64 ( lux , CM32181_CALIBSCALE_RESOLUTION ) ;
lux = div_u64 ( lux , CM32181_LUX_PER_BIT_RESOLUTION ) ;
2013-12-24 01:53:00 +00:00
if ( lux > 0xFFFF )
lux = 0xFFFF ;
return lux ;
}
static int cm32181_read_raw ( struct iio_dev * indio_dev ,
struct iio_chan_spec const * chan ,
int * val , int * val2 , long mask )
{
struct cm32181_chip * cm32181 = iio_priv ( indio_dev ) ;
int ret ;
switch ( mask ) {
case IIO_CHAN_INFO_PROCESSED :
ret = cm32181_get_lux ( cm32181 ) ;
if ( ret < 0 )
return ret ;
* val = ret ;
return IIO_VAL_INT ;
case IIO_CHAN_INFO_CALIBSCALE :
* val = cm32181 - > calibscale ;
return IIO_VAL_INT ;
case IIO_CHAN_INFO_INT_TIME :
2014-12-03 00:57:00 +00:00
* val = 0 ;
2014-02-14 10:04:00 +00:00
ret = cm32181_read_als_it ( cm32181 , val2 ) ;
2013-12-24 01:53:00 +00:00
return ret ;
}
return - EINVAL ;
}
static int cm32181_write_raw ( struct iio_dev * indio_dev ,
struct iio_chan_spec const * chan ,
int val , int val2 , long mask )
{
struct cm32181_chip * cm32181 = iio_priv ( indio_dev ) ;
int ret ;
switch ( mask ) {
case IIO_CHAN_INFO_CALIBSCALE :
cm32181 - > calibscale = val ;
return val ;
case IIO_CHAN_INFO_INT_TIME :
2014-02-14 10:04:00 +00:00
ret = cm32181_write_als_it ( cm32181 , val2 ) ;
2013-12-24 01:53:00 +00:00
return ret ;
}
return - EINVAL ;
}
/**
* cm32181_get_it_available ( ) - Get available ALS IT value
* @ dev : pointer of struct device .
* @ attr : pointer of struct device_attribute .
* @ buf : pointer of return string buffer .
*
* Display the available integration time values by millisecond .
*
* Return : string length .
*/
static ssize_t cm32181_get_it_available ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
2020-04-28 19:29:16 +02:00
struct cm32181_chip * cm32181 = iio_priv ( dev_to_iio_dev ( dev ) ) ;
2013-12-24 01:53:00 +00:00
int i , n , len ;
2020-04-28 19:29:16 +02:00
n = cm32181 - > num_als_it ;
2013-12-24 01:53:00 +00:00
for ( i = 0 , len = 0 ; i < n ; i + + )
2020-04-28 19:29:16 +02:00
len + = sprintf ( buf + len , " 0.%06u " , cm32181 - > als_it_values [ i ] ) ;
2013-12-24 01:53:00 +00:00
return len + sprintf ( buf + len , " \n " ) ;
}
static const struct iio_chan_spec cm32181_channels [ ] = {
{
. type = IIO_LIGHT ,
. info_mask_separate =
BIT ( IIO_CHAN_INFO_PROCESSED ) |
BIT ( IIO_CHAN_INFO_CALIBSCALE ) |
BIT ( IIO_CHAN_INFO_INT_TIME ) ,
}
} ;
static IIO_DEVICE_ATTR ( in_illuminance_integration_time_available ,
S_IRUGO , cm32181_get_it_available , NULL , 0 ) ;
static struct attribute * cm32181_attributes [ ] = {
& iio_dev_attr_in_illuminance_integration_time_available . dev_attr . attr ,
NULL ,
} ;
static const struct attribute_group cm32181_attribute_group = {
. attrs = cm32181_attributes
} ;
static const struct iio_info cm32181_info = {
. read_raw = & cm32181_read_raw ,
. write_raw = & cm32181_write_raw ,
. attrs = & cm32181_attribute_group ,
} ;
2020-04-28 19:29:13 +02:00
static int cm32181_probe ( struct i2c_client * client )
2013-12-24 01:53:00 +00:00
{
2020-04-28 19:29:17 +02:00
struct device * dev = & client - > dev ;
2013-12-24 01:53:00 +00:00
struct cm32181_chip * cm32181 ;
struct iio_dev * indio_dev ;
int ret ;
2020-04-28 19:29:17 +02:00
indio_dev = devm_iio_device_alloc ( dev , sizeof ( * cm32181 ) ) ;
if ( ! indio_dev )
2013-12-24 01:53:00 +00:00
return - ENOMEM ;
iio: light: cm32181: Handle CM3218 ACPI devices with 2 I2C resources
Some ACPI systems list 2 I2C resources for the CM3218 sensor. On these
systems the first I2cSerialBus ACPI-resource points to the SMBus Alert
Response Address (ARA, 0x0c) and the second I2cSerialBus ACPI-resource
points to the actual CM3218 sensor address:
Method (_CRS, 0, NotSerialized) // _CRS: Current Resource Settings
{
Name (SBUF, ResourceTemplate ()
{
I2cSerialBusV2 (0x000C, ControllerInitiated, 0x00061A80,
AddressingMode7Bit, "\\_SB.I2C3",
0x00, ResourceConsumer, , Exclusive,
)
I2cSerialBusV2 (0x0048, ControllerInitiated, 0x00061A80,
AddressingMode7Bit, "\\_SB.I2C3",
0x00, ResourceConsumer, , Exclusive,
)
Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive, ,, )
{
0x00000033,
}
})
Return (SBUF) /* \_SB_.I2C3.ALSD._CRS.SBUF */
}
Detect this and take the following step to deal with it:
1. When a SMBus Alert capable sensor has an Alert asserted, it will
not respond on its actual I2C address. Read a byte from the ARA
to clear any pending Alerts.
2. Create a "dummy" client for the actual I2C address and
use that client to communicate with the sensor.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
2020-04-28 19:29:18 +02:00
/*
* Some ACPI systems list 2 I2C resources for the CM3218 sensor , the
* SMBus Alert Response Address ( ARA , 0x0c ) and the actual I2C address .
* Detect this and take the following step to deal with it :
* 1. When a SMBus Alert capable sensor has an Alert asserted , it will
* not respond on its actual I2C address . Read a byte from the ARA
* to clear any pending Alerts .
* 2. Create a " dummy " client for the actual I2C address and
* use that client to communicate with the sensor .
*/
if ( ACPI_HANDLE ( dev ) & & client - > addr = = SMBUS_ALERT_RESPONSE_ADDRESS ) {
struct i2c_board_info board_info = { . type = " dummy " } ;
i2c_smbus_read_byte ( client ) ;
client = i2c_acpi_new_device ( dev , 1 , & board_info ) ;
if ( IS_ERR ( client ) )
return PTR_ERR ( client ) ;
}
2013-12-24 01:53:00 +00:00
cm32181 = iio_priv ( indio_dev ) ;
cm32181 - > client = client ;
2020-04-28 19:29:22 +02:00
cm32181 - > dev = dev ;
2013-12-24 01:53:00 +00:00
mutex_init ( & cm32181 - > lock ) ;
2020-04-28 19:29:17 +02:00
indio_dev - > dev . parent = dev ;
2013-12-24 01:53:00 +00:00
indio_dev - > channels = cm32181_channels ;
indio_dev - > num_channels = ARRAY_SIZE ( cm32181_channels ) ;
indio_dev - > info = & cm32181_info ;
2020-04-28 19:29:17 +02:00
indio_dev - > name = dev_name ( dev ) ;
2013-12-24 01:53:00 +00:00
indio_dev - > modes = INDIO_DIRECT_MODE ;
ret = cm32181_reg_init ( cm32181 ) ;
if ( ret ) {
2020-04-28 19:29:17 +02:00
dev_err ( dev , " %s: register init failed \n " , __func__ ) ;
2013-12-24 01:53:00 +00:00
return ret ;
}
2020-04-28 19:29:17 +02:00
ret = devm_iio_device_register ( dev , indio_dev ) ;
2013-12-24 01:53:00 +00:00
if ( ret ) {
2020-04-28 19:29:17 +02:00
dev_err ( dev , " %s: regist device failed \n " , __func__ ) ;
2013-12-24 01:53:00 +00:00
return ret ;
}
return 0 ;
}
static const struct of_device_id cm32181_of_match [ ] = {
2020-04-28 19:29:16 +02:00
{ . compatible = " capella,cm3218 " } ,
2013-12-24 01:53:00 +00:00
{ . compatible = " capella,cm32181 " } ,
{ }
} ;
2015-07-30 18:18:42 +02:00
MODULE_DEVICE_TABLE ( of , cm32181_of_match ) ;
2013-12-24 01:53:00 +00:00
2020-04-28 19:29:14 +02:00
# ifdef CONFIG_ACPI
static const struct acpi_device_id cm32181_acpi_match [ ] = {
{ " CPLM3218 " , 0 } ,
{ }
} ;
MODULE_DEVICE_TABLE ( acpi , cm32181_acpi_match ) ;
# endif
2013-12-24 01:53:00 +00:00
static struct i2c_driver cm32181_driver = {
. driver = {
. name = " cm32181 " ,
2020-04-28 19:29:14 +02:00
. acpi_match_table = ACPI_PTR ( cm32181_acpi_match ) ,
2020-04-19 16:02:01 +01:00
. of_match_table = cm32181_of_match ,
2013-12-24 01:53:00 +00:00
} ,
2020-04-28 19:29:13 +02:00
. probe_new = cm32181_probe ,
2013-12-24 01:53:00 +00:00
} ;
module_i2c_driver ( cm32181_driver ) ;
MODULE_AUTHOR ( " Kevin Tsai <ktsai@capellamicro.com> " ) ;
MODULE_DESCRIPTION ( " CM32181 ambient light sensor driver " ) ;
MODULE_LICENSE ( " GPL " ) ;