/*
- * srf08.c - Support for Devantech SRF08 ultrasonic ranger
+ * srf08.c - Support for Devantech SRFxx ultrasonic ranger
+ *           with i2c interface
+ * actually supported are srf08, srf10
  *
  * Copyright (c) 2016 Andreas Klinger <ak@it-klinger.de>
  *
  *
  * For details about the device see:
  * http://www.robot-electronics.co.uk/htm/srf08tech.html
+ * http://www.robot-electronics.co.uk/htm/srf10tech.htm
  */
 
 #include <linux/err.h>
 
 #define SRF08_CMD_RANGING_CM   0x51    /* Ranging Mode - Result in cm */
 
-#define SRF08_DEFAULT_GAIN     1025    /* default analogue value of Gain */
 #define SRF08_DEFAULT_RANGE    6020    /* default value of Range in mm */
 
+enum srf08_sensor_type {
+       SRF08,
+       SRF10,
+       SRF_MAX_TYPE
+};
+
+struct srf08_chip_info {
+       const int               *sensitivity_avail;
+       int                     num_sensitivity_avail;
+       int                     sensitivity_default;
+};
+
 struct srf08_data {
        struct i2c_client       *client;
 
         * 1x16-bit channel + 3x16 padding + 4x16 timestamp
         */
        s16                     buffer[8];
+
+       /* Sensor-Type */
+       enum srf08_sensor_type  sensor_type;
+
+       /* Chip-specific information */
+       const struct srf08_chip_info    *chip_info;
 };
 
 /*
  * But with ADC's this term is already used differently and that's why it
  * is called "Sensitivity" here.
  */
-static const int srf08_sensitivity[] = {
+static const int srf08_sensitivity_avail[] = {
         94,  97, 100, 103, 107, 110, 114, 118,
        123, 128, 133, 139, 145, 152, 159, 168,
        177, 187, 199, 212, 227, 245, 265, 288,
-       317, 352, 395, 450, 524, 626, 777, 1025 };
+       317, 352, 395, 450, 524, 626, 777, 1025
+       };
+
+static const struct srf08_chip_info srf08_chip_info = {
+       .sensitivity_avail      = srf08_sensitivity_avail,
+       .num_sensitivity_avail  = ARRAY_SIZE(srf08_sensitivity_avail),
+       .sensitivity_default    = 1025,
+};
+
+static const int srf10_sensitivity_avail[] = {
+        40,  40,  50,  60,  70,  80, 100, 120,
+       140, 200, 250, 300, 350, 400, 500, 600,
+       700,
+       };
+
+static const struct srf08_chip_info srf10_chip_info = {
+       .sensitivity_avail      = srf10_sensitivity_avail,
+       .num_sensitivity_avail  = ARRAY_SIZE(srf10_sensitivity_avail),
+       .sensitivity_default    = 700,
+};
 
 static int srf08_read_ranging(struct srf08_data *data)
 {
                                struct device_attribute *attr, char *buf)
 {
        int i, len = 0;
+       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+       struct srf08_data *data = iio_priv(indio_dev);
 
-       for (i = 0; i < ARRAY_SIZE(srf08_sensitivity); i++)
-               len += sprintf(buf + len, "%d ", srf08_sensitivity[i]);
+       for (i = 0; i < data->chip_info->num_sensitivity_avail; i++)
+               if (data->chip_info->sensitivity_avail[i])
+                       len += sprintf(buf + len, "%d ",
+                               data->chip_info->sensitivity_avail[i]);
 
        len += sprintf(buf + len, "\n");
 
        int ret, i;
        u8 regval;
 
-       for (i = 0; i < ARRAY_SIZE(srf08_sensitivity); i++)
-               if (val == srf08_sensitivity[i]) {
+       if (!val)
+               return -EINVAL;
+
+       for (i = 0; i < data->chip_info->num_sensitivity_avail; i++)
+               if (val && (val == data->chip_info->sensitivity_avail[i])) {
                        regval = i;
                        break;
                }
 
-       if (i >= ARRAY_SIZE(srf08_sensitivity))
+       if (i >= data->chip_info->num_sensitivity_avail)
                return -EINVAL;
 
        mutex_lock(&data->lock);
 
-       ret = i2c_smbus_write_byte_data(client,
-                                               SRF08_WRITE_MAX_GAIN, regval);
+       ret = i2c_smbus_write_byte_data(client, SRF08_WRITE_MAX_GAIN, regval);
        if (ret < 0) {
                dev_err(&client->dev, "write_sensitivity - err: %d\n", ret);
                mutex_unlock(&data->lock);
        data = iio_priv(indio_dev);
        i2c_set_clientdata(client, indio_dev);
        data->client = client;
+       data->sensor_type = (enum srf08_sensor_type)id->driver_data;
+
+       switch (data->sensor_type) {
+       case SRF08:
+               data->chip_info = &srf08_chip_info;
+               break;
+       case SRF10:
+               data->chip_info = &srf10_chip_info;
+               break;
+       default:
+               return -EINVAL;
+       }
 
-       indio_dev->name = "srf08";
+       indio_dev->name = id->name;
        indio_dev->dev.parent = &client->dev;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &srf08_info;
        if (ret < 0)
                return ret;
 
-       ret = srf08_write_sensitivity(data, SRF08_DEFAULT_GAIN);
+       ret = srf08_write_sensitivity(data,
+                               data->chip_info->sensitivity_default);
        if (ret < 0)
                return ret;
 
 }
 
 static const struct of_device_id of_srf08_match[] = {
-       { .compatible = "devantech,srf08", 0},
+       { .compatible = "devantech,srf08", (void *)SRF08},
+       { .compatible = "devantech,srf10", (void *)SRF10},
        {},
 };
 
 MODULE_DEVICE_TABLE(of, of_srf08_match);
 
 static const struct i2c_device_id srf08_id[] = {
-       { "srf08", 0 },
+       { "srf08", SRF08 },
+       { "srf10", SRF10 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, srf08_id);