linux/drivers/iio/dac/m62332.c
<<
>>
Prefs
   1/*
   2 *  m62332.c - Support for Mitsubishi m62332 DAC
   3 *
   4 *  Copyright (c) 2014 Dmitry Eremin-Solenikov
   5 *
   6 *  Based on max517 driver:
   7 *  Copyright (C) 2010, 2011 Roland Stigge <stigge@antcom.de>
   8 *
   9 *  This program is free software; you can redistribute it and/or modify
  10 *  it under the terms of the GNU General Public License as published by
  11 *  the Free Software Foundation; either version 2 of the License, or
  12 *  (at your option) any later version.
  13 *
  14 *  This program is distributed in the hope that it will be useful,
  15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17 *  GNU General Public License for more details.
  18 */
  19
  20#include <linux/module.h>
  21#include <linux/slab.h>
  22#include <linux/i2c.h>
  23#include <linux/err.h>
  24
  25#include <linux/iio/iio.h>
  26#include <linux/iio/driver.h>
  27
  28#include <linux/regulator/consumer.h>
  29
  30#define M62332_CHANNELS 2
  31
  32struct m62332_data {
  33        struct i2c_client       *client;
  34        struct regulator        *vcc;
  35        struct mutex            mutex;
  36        u8                      raw[M62332_CHANNELS];
  37#ifdef CONFIG_PM_SLEEP
  38        u8                      save[M62332_CHANNELS];
  39#endif
  40};
  41
  42static int m62332_set_value(struct iio_dev *indio_dev, u8 val, int channel)
  43{
  44        struct m62332_data *data = iio_priv(indio_dev);
  45        struct i2c_client *client = data->client;
  46        u8 outbuf[2];
  47        int res;
  48
  49        if (val == data->raw[channel])
  50                return 0;
  51
  52        outbuf[0] = channel;
  53        outbuf[1] = val;
  54
  55        mutex_lock(&data->mutex);
  56
  57        if (val) {
  58                res = regulator_enable(data->vcc);
  59                if (res)
  60                        goto out;
  61        }
  62
  63        res = i2c_master_send(client, outbuf, ARRAY_SIZE(outbuf));
  64        if (res >= 0 && res != ARRAY_SIZE(outbuf))
  65                res = -EIO;
  66        if (res < 0)
  67                goto out;
  68
  69        data->raw[channel] = val;
  70
  71        if (!val)
  72                regulator_disable(data->vcc);
  73
  74        mutex_unlock(&data->mutex);
  75
  76        return 0;
  77
  78out:
  79        mutex_unlock(&data->mutex);
  80
  81        return res;
  82}
  83
  84static int m62332_read_raw(struct iio_dev *indio_dev,
  85                           struct iio_chan_spec const *chan,
  86                           int *val,
  87                           int *val2,
  88                           long mask)
  89{
  90        struct m62332_data *data = iio_priv(indio_dev);
  91        int ret;
  92
  93        switch (mask) {
  94        case IIO_CHAN_INFO_SCALE:
  95                /* Corresponds to Vref / 2^(bits) */
  96                ret = regulator_get_voltage(data->vcc);
  97                if (ret < 0)
  98                        return ret;
  99
 100                *val = ret / 1000; /* mV */
 101                *val2 = 8;
 102
 103                return IIO_VAL_FRACTIONAL_LOG2;
 104        case IIO_CHAN_INFO_RAW:
 105                *val = data->raw[chan->channel];
 106
 107                return IIO_VAL_INT;
 108        case IIO_CHAN_INFO_OFFSET:
 109                *val = 1;
 110
 111                return IIO_VAL_INT;
 112        default:
 113                break;
 114        }
 115
 116        return -EINVAL;
 117}
 118
 119static int m62332_write_raw(struct iio_dev *indio_dev,
 120                            struct iio_chan_spec const *chan, int val, int val2,
 121                            long mask)
 122{
 123        switch (mask) {
 124        case IIO_CHAN_INFO_RAW:
 125                if (val < 0 || val > 255)
 126                        return -EINVAL;
 127
 128                return m62332_set_value(indio_dev, val, chan->channel);
 129        default:
 130                break;
 131        }
 132
 133        return -EINVAL;
 134}
 135
 136#ifdef CONFIG_PM_SLEEP
 137static int m62332_suspend(struct device *dev)
 138{
 139        struct i2c_client *client = to_i2c_client(dev);
 140        struct iio_dev *indio_dev = i2c_get_clientdata(client);
 141        struct m62332_data *data = iio_priv(indio_dev);
 142        int ret;
 143
 144        data->save[0] = data->raw[0];
 145        data->save[1] = data->raw[1];
 146
 147        ret = m62332_set_value(indio_dev, 0, 0);
 148        if (ret < 0)
 149                return ret;
 150
 151        return m62332_set_value(indio_dev, 0, 1);
 152}
 153
 154static int m62332_resume(struct device *dev)
 155{
 156        struct i2c_client *client = to_i2c_client(dev);
 157        struct iio_dev *indio_dev = i2c_get_clientdata(client);
 158        struct m62332_data *data = iio_priv(indio_dev);
 159        int ret;
 160
 161        ret = m62332_set_value(indio_dev, data->save[0], 0);
 162        if (ret < 0)
 163                return ret;
 164
 165        return m62332_set_value(indio_dev, data->save[1], 1);
 166}
 167
 168static SIMPLE_DEV_PM_OPS(m62332_pm_ops, m62332_suspend, m62332_resume);
 169#define M62332_PM_OPS (&m62332_pm_ops)
 170#else
 171#define M62332_PM_OPS NULL
 172#endif
 173
 174static const struct iio_info m62332_info = {
 175        .read_raw = m62332_read_raw,
 176        .write_raw = m62332_write_raw,
 177        .driver_module = THIS_MODULE,
 178};
 179
 180#define M62332_CHANNEL(chan) {                                  \
 181        .type = IIO_VOLTAGE,                                    \
 182        .indexed = 1,                                           \
 183        .output = 1,                                            \
 184        .channel = (chan),                                      \
 185        .datasheet_name = "CH" #chan,                           \
 186        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),           \
 187        .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
 188                                    BIT(IIO_CHAN_INFO_OFFSET),  \
 189}
 190
 191static const struct iio_chan_spec m62332_channels[M62332_CHANNELS] = {
 192        M62332_CHANNEL(0),
 193        M62332_CHANNEL(1)
 194};
 195
 196static int m62332_probe(struct i2c_client *client,
 197                        const struct i2c_device_id *id)
 198{
 199        struct m62332_data *data;
 200        struct iio_dev *indio_dev;
 201        int ret;
 202
 203        indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
 204        if (!indio_dev)
 205                return -ENOMEM;
 206
 207        data = iio_priv(indio_dev);
 208        i2c_set_clientdata(client, indio_dev);
 209        data->client = client;
 210
 211        mutex_init(&data->mutex);
 212
 213        data->vcc = devm_regulator_get(&client->dev, "VCC");
 214        if (IS_ERR(data->vcc))
 215                return PTR_ERR(data->vcc);
 216
 217        /* establish that the iio_dev is a child of the i2c device */
 218        indio_dev->dev.parent = &client->dev;
 219
 220        indio_dev->num_channels = ARRAY_SIZE(m62332_channels);
 221        indio_dev->channels = m62332_channels;
 222        indio_dev->modes = INDIO_DIRECT_MODE;
 223        indio_dev->info = &m62332_info;
 224
 225        ret = iio_map_array_register(indio_dev, client->dev.platform_data);
 226        if (ret < 0)
 227                return ret;
 228
 229        ret = iio_device_register(indio_dev);
 230        if (ret < 0)
 231                goto err;
 232
 233        return 0;
 234
 235err:
 236        iio_map_array_unregister(indio_dev);
 237
 238        return ret;
 239}
 240
 241static int m62332_remove(struct i2c_client *client)
 242{
 243        struct iio_dev *indio_dev = i2c_get_clientdata(client);
 244
 245        iio_device_unregister(indio_dev);
 246        iio_map_array_unregister(indio_dev);
 247        m62332_set_value(indio_dev, 0, 0);
 248        m62332_set_value(indio_dev, 0, 1);
 249
 250        return 0;
 251}
 252
 253static const struct i2c_device_id m62332_id[] = {
 254        { "m62332", },
 255        { }
 256};
 257MODULE_DEVICE_TABLE(i2c, m62332_id);
 258
 259static struct i2c_driver m62332_driver = {
 260        .driver = {
 261                .name   = "m62332",
 262                .pm     = M62332_PM_OPS,
 263        },
 264        .probe          = m62332_probe,
 265        .remove         = m62332_remove,
 266        .id_table       = m62332_id,
 267};
 268module_i2c_driver(m62332_driver);
 269
 270MODULE_AUTHOR("Dmitry Eremin-Solenikov");
 271MODULE_DESCRIPTION("M62332 8-bit DAC");
 272MODULE_LICENSE("GPL v2");
 273