wl1273-core.c revision 94fd5b7401e330498331ea3667d796e74c63d08a
1383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen/* 2383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen * MFD driver for wl1273 FM radio and audio codec submodules. 3383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen * 494fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen * Copyright (C) 2011 Nokia Corporation 5383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen * Author: Matti Aaltonen <matti.j.aaltonen@nokia.com> 6383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen * 7383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen * This program is free software; you can redistribute it and/or modify 8383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen * it under the terms of the GNU General Public License version 2 as 9383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen * published by the Free Software Foundation. 10383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen * 11383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen * This program is distributed in the hope that it will be useful, but 12383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen * WITHOUT ANY WARRANTY; without even the implied warranty of 13383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen * General Public License for more details. 15383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen * 16383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen * You should have received a copy of the GNU General Public License 17383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen * along with this program; if not, write to the Free Software 18383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 19383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen * 02110-1301 USA 20383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen * 21383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen */ 22383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 23383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen#include <linux/mfd/wl1273-core.h> 24383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen#include <linux/slab.h> 25383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 26383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen#define DRIVER_DESC "WL1273 FM Radio Core" 27383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 28383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonenstatic struct i2c_device_id wl1273_driver_id_table[] = { 29383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen { WL1273_FM_DRIVER_NAME, 0 }, 30383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen { } 31383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen}; 32383268a8e282fb549dabe3a33ccafc9434ab6006Matti AaltonenMODULE_DEVICE_TABLE(i2c, wl1273_driver_id_table); 33383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 3494fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonenstatic int wl1273_fm_read_reg(struct wl1273_core *core, u8 reg, u16 *value) 3594fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen{ 3694fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen struct i2c_client *client = core->client; 3794fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen u8 b[2]; 3894fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen int r; 3994fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 4094fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen r = i2c_smbus_read_i2c_block_data(client, reg, sizeof(b), b); 4194fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen if (r != 2) { 4294fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen dev_err(&client->dev, "%s: Read: %d fails.\n", __func__, reg); 4394fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen return -EREMOTEIO; 4494fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen } 4594fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 4694fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen *value = (u16)b[0] << 8 | b[1]; 4794fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 4894fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen return 0; 4994fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen} 5094fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 5194fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonenstatic int wl1273_fm_write_cmd(struct wl1273_core *core, u8 cmd, u16 param) 5294fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen{ 5394fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen struct i2c_client *client = core->client; 5494fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen u8 buf[] = { (param >> 8) & 0xff, param & 0xff }; 5594fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen int r; 5694fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 5794fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen r = i2c_smbus_write_i2c_block_data(client, cmd, sizeof(buf), buf); 5894fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen if (r) { 5994fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen dev_err(&client->dev, "%s: Cmd: %d fails.\n", __func__, cmd); 6094fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen return r; 6194fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen } 6294fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 6394fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen return 0; 6494fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen} 6594fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 6694fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonenstatic int wl1273_fm_write_data(struct wl1273_core *core, u8 *data, u16 len) 6794fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen{ 6894fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen struct i2c_client *client = core->client; 6994fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen struct i2c_msg msg; 7094fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen int r; 7194fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 7294fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen msg.addr = client->addr; 7394fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen msg.flags = 0; 7494fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen msg.buf = data; 7594fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen msg.len = len; 7694fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 7794fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen r = i2c_transfer(client->adapter, &msg, 1); 7894fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen if (r != 1) { 7994fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen dev_err(&client->dev, "%s: write error.\n", __func__); 8094fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen return -EREMOTEIO; 8194fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen } 8294fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 8394fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen return 0; 8494fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen} 8594fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 8694fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen/** 8794fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen * wl1273_fm_set_audio() - Set audio mode. 8894fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen * @core: A pointer to the device struct. 8994fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen * @new_mode: The new audio mode. 9094fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen * 9194fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen * Audio modes are WL1273_AUDIO_DIGITAL and WL1273_AUDIO_ANALOG. 9294fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen */ 9394fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonenstatic int wl1273_fm_set_audio(struct wl1273_core *core, unsigned int new_mode) 9494fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen{ 9594fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen int r = 0; 9694fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 9794fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen if (core->mode == WL1273_MODE_OFF || 9894fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen core->mode == WL1273_MODE_SUSPENDED) 9994fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen return -EPERM; 10094fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 10194fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen if (core->mode == WL1273_MODE_RX && new_mode == WL1273_AUDIO_DIGITAL) { 10294fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen r = wl1273_fm_write_cmd(core, WL1273_PCM_MODE_SET, 10394fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen WL1273_PCM_DEF_MODE); 10494fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen if (r) 10594fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen goto out; 10694fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 10794fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen r = wl1273_fm_write_cmd(core, WL1273_I2S_MODE_CONFIG_SET, 10894fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen core->i2s_mode); 10994fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen if (r) 11094fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen goto out; 11194fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 11294fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen r = wl1273_fm_write_cmd(core, WL1273_AUDIO_ENABLE, 11394fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen WL1273_AUDIO_ENABLE_I2S); 11494fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen if (r) 11594fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen goto out; 11694fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 11794fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen } else if (core->mode == WL1273_MODE_RX && 11894fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen new_mode == WL1273_AUDIO_ANALOG) { 11994fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen r = wl1273_fm_write_cmd(core, WL1273_AUDIO_ENABLE, 12094fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen WL1273_AUDIO_ENABLE_ANALOG); 12194fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen if (r) 12294fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen goto out; 12394fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 12494fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen } else if (core->mode == WL1273_MODE_TX && 12594fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen new_mode == WL1273_AUDIO_DIGITAL) { 12694fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen r = wl1273_fm_write_cmd(core, WL1273_I2S_MODE_CONFIG_SET, 12794fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen core->i2s_mode); 12894fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen if (r) 12994fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen goto out; 13094fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 13194fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen r = wl1273_fm_write_cmd(core, WL1273_AUDIO_IO_SET, 13294fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen WL1273_AUDIO_IO_SET_I2S); 13394fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen if (r) 13494fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen goto out; 13594fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 13694fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen } else if (core->mode == WL1273_MODE_TX && 13794fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen new_mode == WL1273_AUDIO_ANALOG) { 13894fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen r = wl1273_fm_write_cmd(core, WL1273_AUDIO_IO_SET, 13994fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen WL1273_AUDIO_IO_SET_ANALOG); 14094fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen if (r) 14194fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen goto out; 14294fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen } 14394fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 14494fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen core->audio_mode = new_mode; 14594fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonenout: 14694fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen return r; 14794fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen} 14894fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 14994fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen/** 15094fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen * wl1273_fm_set_volume() - Set volume. 15194fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen * @core: A pointer to the device struct. 15294fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen * @volume: The new volume value. 15394fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen */ 15494fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonenstatic int wl1273_fm_set_volume(struct wl1273_core *core, unsigned int volume) 15594fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen{ 15694fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen u16 val; 15794fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen int r; 15894fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 15994fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen if (volume > WL1273_MAX_VOLUME) 16094fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen return -EINVAL; 16194fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 16294fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen if (core->volume == volume) 16394fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen return 0; 16494fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 16594fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen r = wl1273_fm_write_cmd(core, WL1273_VOLUME_SET, volume); 16694fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen if (r) 16794fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen return r; 16894fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 16994fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen core->volume = volume; 17094fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen return 0; 17194fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen} 17294fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 173383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonenstatic int wl1273_core_remove(struct i2c_client *client) 174383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen{ 175383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen struct wl1273_core *core = i2c_get_clientdata(client); 176383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 177383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen dev_dbg(&client->dev, "%s\n", __func__); 178383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 179383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen mfd_remove_devices(&client->dev); 180383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen kfree(core); 181383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 182383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen return 0; 183383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen} 184383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 185383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonenstatic int __devinit wl1273_core_probe(struct i2c_client *client, 186383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen const struct i2c_device_id *id) 187383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen{ 188383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen struct wl1273_fm_platform_data *pdata = client->dev.platform_data; 189383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen struct wl1273_core *core; 190383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen struct mfd_cell *cell; 191383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen int children = 0; 192383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen int r = 0; 193383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 194383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen dev_dbg(&client->dev, "%s\n", __func__); 195383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 196383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen if (!pdata) { 197383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen dev_err(&client->dev, "No platform data.\n"); 198383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen return -EINVAL; 199383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen } 200383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 201383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen if (!(pdata->children & WL1273_RADIO_CHILD)) { 202383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen dev_err(&client->dev, "Cannot function without radio child.\n"); 203383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen return -EINVAL; 204383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen } 205383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 206383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen core = kzalloc(sizeof(*core), GFP_KERNEL); 207383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen if (!core) 208383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen return -ENOMEM; 209383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 210383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen core->pdata = pdata; 211383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen core->client = client; 212383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen mutex_init(&core->lock); 213383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 214383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen i2c_set_clientdata(client, core); 215383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 216383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen dev_dbg(&client->dev, "%s: Have V4L2.\n", __func__); 217383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 218383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen cell = &core->cells[children]; 219383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen cell->name = "wl1273_fm_radio"; 220383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen cell->platform_data = &core; 221383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen cell->data_size = sizeof(core); 222383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen children++; 223383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 22494fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen core->read = wl1273_fm_read_reg; 22594fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen core->write = wl1273_fm_write_cmd; 22694fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen core->write_data = wl1273_fm_write_data; 22794fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen core->set_audio = wl1273_fm_set_audio; 22894fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen core->set_volume = wl1273_fm_set_volume; 22994fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 230383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen if (pdata->children & WL1273_CODEC_CHILD) { 231383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen cell = &core->cells[children]; 232383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 233383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen dev_dbg(&client->dev, "%s: Have codec.\n", __func__); 234383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen cell->name = "wl1273-codec"; 235383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen cell->platform_data = &core; 236383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen cell->data_size = sizeof(core); 237383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen children++; 238383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen } 239383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 240383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen dev_dbg(&client->dev, "%s: number of children: %d.\n", 241383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen __func__, children); 242383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 243383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen r = mfd_add_devices(&client->dev, -1, core->cells, 244383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen children, NULL, 0); 245383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen if (r) 246383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen goto err; 247383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 248383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen return 0; 249383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 250383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonenerr: 251383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen pdata->free_resources(); 252383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen kfree(core); 253383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 254383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen dev_dbg(&client->dev, "%s\n", __func__); 255383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 256383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen return r; 257383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen} 258383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 259383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonenstatic struct i2c_driver wl1273_core_driver = { 260383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen .driver = { 261383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen .name = WL1273_FM_DRIVER_NAME, 262383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen }, 263383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen .probe = wl1273_core_probe, 264383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen .id_table = wl1273_driver_id_table, 265383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen .remove = __devexit_p(wl1273_core_remove), 266383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen}; 267383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 268383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonenstatic int __init wl1273_core_init(void) 269383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen{ 270383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen int r; 271383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 272383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen r = i2c_add_driver(&wl1273_core_driver); 273383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen if (r) { 274383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen pr_err(WL1273_FM_DRIVER_NAME 275383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen ": driver registration failed\n"); 276383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen return r; 277383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen } 278383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 279383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen return r; 280383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen} 281383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 282383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonenstatic void __exit wl1273_core_exit(void) 283383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen{ 284383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen i2c_del_driver(&wl1273_core_driver); 285383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen} 286383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonenlate_initcall(wl1273_core_init); 287383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonenmodule_exit(wl1273_core_exit); 288383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 289383268a8e282fb549dabe3a33ccafc9434ab6006Matti AaltonenMODULE_AUTHOR("Matti Aaltonen <matti.j.aaltonen@nokia.com>"); 290383268a8e282fb549dabe3a33ccafc9434ab6006Matti AaltonenMODULE_DESCRIPTION(DRIVER_DESC); 291383268a8e282fb549dabe3a33ccafc9434ab6006Matti AaltonenMODULE_LICENSE("GPL"); 292