linux/drivers/mfd/wl1273-core.c
<<
>>
Prefs
   1/*
   2 * MFD driver for wl1273 FM radio and audio codec submodules.
   3 *
   4 * Copyright (C) 2011 Nokia Corporation
   5 * Author: Matti Aaltonen <matti.j.aaltonen@nokia.com>
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 as
   9 * published by the Free Software Foundation.
  10 *
  11 * This program is distributed in the hope that it will be useful, but
  12 * WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14 * General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program; if not, write to the Free Software
  18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  19 * 02110-1301 USA
  20 *
  21 */
  22
  23#include <linux/mfd/wl1273-core.h>
  24#include <linux/slab.h>
  25
  26#define DRIVER_DESC "WL1273 FM Radio Core"
  27
  28static const struct i2c_device_id wl1273_driver_id_table[] = {
  29        { WL1273_FM_DRIVER_NAME, 0 },
  30        { }
  31};
  32MODULE_DEVICE_TABLE(i2c, wl1273_driver_id_table);
  33
  34static int wl1273_fm_read_reg(struct wl1273_core *core, u8 reg, u16 *value)
  35{
  36        struct i2c_client *client = core->client;
  37        u8 b[2];
  38        int r;
  39
  40        r = i2c_smbus_read_i2c_block_data(client, reg, sizeof(b), b);
  41        if (r != 2) {
  42                dev_err(&client->dev, "%s: Read: %d fails.\n", __func__, reg);
  43                return -EREMOTEIO;
  44        }
  45
  46        *value = (u16)b[0] << 8 | b[1];
  47
  48        return 0;
  49}
  50
  51static int wl1273_fm_write_cmd(struct wl1273_core *core, u8 cmd, u16 param)
  52{
  53        struct i2c_client *client = core->client;
  54        u8 buf[] = { (param >> 8) & 0xff, param & 0xff };
  55        int r;
  56
  57        r = i2c_smbus_write_i2c_block_data(client, cmd, sizeof(buf), buf);
  58        if (r) {
  59                dev_err(&client->dev, "%s: Cmd: %d fails.\n", __func__, cmd);
  60                return r;
  61        }
  62
  63        return 0;
  64}
  65
  66static int wl1273_fm_write_data(struct wl1273_core *core, u8 *data, u16 len)
  67{
  68        struct i2c_client *client = core->client;
  69        struct i2c_msg msg;
  70        int r;
  71
  72        msg.addr = client->addr;
  73        msg.flags = 0;
  74        msg.buf = data;
  75        msg.len = len;
  76
  77        r = i2c_transfer(client->adapter, &msg, 1);
  78        if (r != 1) {
  79                dev_err(&client->dev, "%s: write error.\n", __func__);
  80                return -EREMOTEIO;
  81        }
  82
  83        return 0;
  84}
  85
  86/**
  87 * wl1273_fm_set_audio() -      Set audio mode.
  88 * @core:                       A pointer to the device struct.
  89 * @new_mode:                   The new audio mode.
  90 *
  91 * Audio modes are WL1273_AUDIO_DIGITAL and WL1273_AUDIO_ANALOG.
  92 */
  93static int wl1273_fm_set_audio(struct wl1273_core *core, unsigned int new_mode)
  94{
  95        int r = 0;
  96
  97        if (core->mode == WL1273_MODE_OFF ||
  98            core->mode == WL1273_MODE_SUSPENDED)
  99                return -EPERM;
 100
 101        if (core->mode == WL1273_MODE_RX && new_mode == WL1273_AUDIO_DIGITAL) {
 102                r = wl1273_fm_write_cmd(core, WL1273_PCM_MODE_SET,
 103                                        WL1273_PCM_DEF_MODE);
 104                if (r)
 105                        goto out;
 106
 107                r = wl1273_fm_write_cmd(core, WL1273_I2S_MODE_CONFIG_SET,
 108                                        core->i2s_mode);
 109                if (r)
 110                        goto out;
 111
 112                r = wl1273_fm_write_cmd(core, WL1273_AUDIO_ENABLE,
 113                                        WL1273_AUDIO_ENABLE_I2S);
 114                if (r)
 115                        goto out;
 116
 117        } else if (core->mode == WL1273_MODE_RX &&
 118                   new_mode == WL1273_AUDIO_ANALOG) {
 119                r = wl1273_fm_write_cmd(core, WL1273_AUDIO_ENABLE,
 120                                        WL1273_AUDIO_ENABLE_ANALOG);
 121                if (r)
 122                        goto out;
 123
 124        } else if (core->mode == WL1273_MODE_TX &&
 125                   new_mode == WL1273_AUDIO_DIGITAL) {
 126                r = wl1273_fm_write_cmd(core, WL1273_I2S_MODE_CONFIG_SET,
 127                                        core->i2s_mode);
 128                if (r)
 129                        goto out;
 130
 131                r = wl1273_fm_write_cmd(core, WL1273_AUDIO_IO_SET,
 132                                        WL1273_AUDIO_IO_SET_I2S);
 133                if (r)
 134                        goto out;
 135
 136        } else if (core->mode == WL1273_MODE_TX &&
 137                   new_mode == WL1273_AUDIO_ANALOG) {
 138                r = wl1273_fm_write_cmd(core, WL1273_AUDIO_IO_SET,
 139                                        WL1273_AUDIO_IO_SET_ANALOG);
 140                if (r)
 141                        goto out;
 142        }
 143
 144        core->audio_mode = new_mode;
 145out:
 146        return r;
 147}
 148
 149/**
 150 * wl1273_fm_set_volume() -     Set volume.
 151 * @core:                       A pointer to the device struct.
 152 * @volume:                     The new volume value.
 153 */
 154static int wl1273_fm_set_volume(struct wl1273_core *core, unsigned int volume)
 155{
 156        u16 val;
 157        int r;
 158
 159        if (volume > WL1273_MAX_VOLUME)
 160                return -EINVAL;
 161
 162        if (core->volume == volume)
 163                return 0;
 164
 165        r = wl1273_fm_write_cmd(core, WL1273_VOLUME_SET, volume);
 166        if (r)
 167                return r;
 168
 169        core->volume = volume;
 170        return 0;
 171}
 172
 173static int wl1273_core_remove(struct i2c_client *client)
 174{
 175        struct wl1273_core *core = i2c_get_clientdata(client);
 176
 177        dev_dbg(&client->dev, "%s\n", __func__);
 178
 179        mfd_remove_devices(&client->dev);
 180        kfree(core);
 181
 182        return 0;
 183}
 184
 185static int __devinit wl1273_core_probe(struct i2c_client *client,
 186                                       const struct i2c_device_id *id)
 187{
 188        struct wl1273_fm_platform_data *pdata = client->dev.platform_data;
 189        struct wl1273_core *core;
 190        struct mfd_cell *cell;
 191        int children = 0;
 192        int r = 0;
 193
 194        dev_dbg(&client->dev, "%s\n", __func__);
 195
 196        if (!pdata) {
 197                dev_err(&client->dev, "No platform data.\n");
 198                return -EINVAL;
 199        }
 200
 201        if (!(pdata->children & WL1273_RADIO_CHILD)) {
 202                dev_err(&client->dev, "Cannot function without radio child.\n");
 203                return -EINVAL;
 204        }
 205
 206        core = kzalloc(sizeof(*core), GFP_KERNEL);
 207        if (!core)
 208                return -ENOMEM;
 209
 210        core->pdata = pdata;
 211        core->client = client;
 212        mutex_init(&core->lock);
 213
 214        i2c_set_clientdata(client, core);
 215
 216        dev_dbg(&client->dev, "%s: Have V4L2.\n", __func__);
 217
 218        cell = &core->cells[children];
 219        cell->name = "wl1273_fm_radio";
 220        cell->mfd_data = &core;
 221        children++;
 222
 223        core->read = wl1273_fm_read_reg;
 224        core->write = wl1273_fm_write_cmd;
 225        core->write_data = wl1273_fm_write_data;
 226        core->set_audio = wl1273_fm_set_audio;
 227        core->set_volume = wl1273_fm_set_volume;
 228
 229        if (pdata->children & WL1273_CODEC_CHILD) {
 230                cell = &core->cells[children];
 231
 232                dev_dbg(&client->dev, "%s: Have codec.\n", __func__);
 233                cell->name = "wl1273-codec";
 234                cell->mfd_data = &core;
 235                children++;
 236        }
 237
 238        dev_dbg(&client->dev, "%s: number of children: %d.\n",
 239                __func__, children);
 240
 241        r = mfd_add_devices(&client->dev, -1, core->cells,
 242                            children, NULL, 0);
 243        if (r)
 244                goto err;
 245
 246        return 0;
 247
 248err:
 249        pdata->free_resources();
 250        kfree(core);
 251
 252        dev_dbg(&client->dev, "%s\n", __func__);
 253
 254        return r;
 255}
 256
 257static struct i2c_driver wl1273_core_driver = {
 258        .driver = {
 259                .name = WL1273_FM_DRIVER_NAME,
 260        },
 261        .probe = wl1273_core_probe,
 262        .id_table = wl1273_driver_id_table,
 263        .remove = __devexit_p(wl1273_core_remove),
 264};
 265
 266static int __init wl1273_core_init(void)
 267{
 268        int r;
 269
 270        r = i2c_add_driver(&wl1273_core_driver);
 271        if (r) {
 272                pr_err(WL1273_FM_DRIVER_NAME
 273                       ": driver registration failed\n");
 274                return r;
 275        }
 276
 277        return r;
 278}
 279
 280static void __exit wl1273_core_exit(void)
 281{
 282        i2c_del_driver(&wl1273_core_driver);
 283}
 284late_initcall(wl1273_core_init);
 285module_exit(wl1273_core_exit);
 286
 287MODULE_AUTHOR("Matti Aaltonen <matti.j.aaltonen@nokia.com>");
 288MODULE_DESCRIPTION(DRIVER_DESC);
 289MODULE_LICENSE("GPL");
 290