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> 254e36dd331423fce1f996d93b991453a1a702ca5cPaul Gortmaker#include <linux/module.h> 26383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 27383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen#define DRIVER_DESC "WL1273 FM Radio Core" 28383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 291206552b02f725bdc603e3153b4a32403d7da9e4Axel Linstatic const struct i2c_device_id wl1273_driver_id_table[] = { 30383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen { WL1273_FM_DRIVER_NAME, 0 }, 31383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen { } 32383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen}; 33383268a8e282fb549dabe3a33ccafc9434ab6006Matti AaltonenMODULE_DEVICE_TABLE(i2c, wl1273_driver_id_table); 34383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 3594fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonenstatic int wl1273_fm_read_reg(struct wl1273_core *core, u8 reg, u16 *value) 3694fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen{ 3794fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen struct i2c_client *client = core->client; 3894fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen u8 b[2]; 3994fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen int r; 4094fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 4194fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen r = i2c_smbus_read_i2c_block_data(client, reg, sizeof(b), b); 4294fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen if (r != 2) { 4394fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen dev_err(&client->dev, "%s: Read: %d fails.\n", __func__, reg); 4494fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen return -EREMOTEIO; 4594fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen } 4694fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 4794fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen *value = (u16)b[0] << 8 | b[1]; 4894fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 4994fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen return 0; 5094fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen} 5194fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 5294fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonenstatic int wl1273_fm_write_cmd(struct wl1273_core *core, u8 cmd, u16 param) 5394fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen{ 5494fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen struct i2c_client *client = core->client; 5594fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen u8 buf[] = { (param >> 8) & 0xff, param & 0xff }; 5694fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen int r; 5794fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 5894fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen r = i2c_smbus_write_i2c_block_data(client, cmd, sizeof(buf), buf); 5994fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen if (r) { 6094fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen dev_err(&client->dev, "%s: Cmd: %d fails.\n", __func__, cmd); 6194fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen return r; 6294fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen } 6394fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 6494fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen return 0; 6594fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen} 6694fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 6794fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonenstatic int wl1273_fm_write_data(struct wl1273_core *core, u8 *data, u16 len) 6894fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen{ 6994fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen struct i2c_client *client = core->client; 7094fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen struct i2c_msg msg; 7194fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen int r; 7294fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 7394fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen msg.addr = client->addr; 7494fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen msg.flags = 0; 7594fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen msg.buf = data; 7694fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen msg.len = len; 7794fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 7894fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen r = i2c_transfer(client->adapter, &msg, 1); 7994fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen if (r != 1) { 8094fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen dev_err(&client->dev, "%s: write error.\n", __func__); 8194fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen return -EREMOTEIO; 8294fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen } 8394fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 8494fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen return 0; 8594fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen} 8694fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 8794fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen/** 8894fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen * wl1273_fm_set_audio() - Set audio mode. 8994fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen * @core: A pointer to the device struct. 9094fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen * @new_mode: The new audio mode. 9194fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen * 9294fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen * Audio modes are WL1273_AUDIO_DIGITAL and WL1273_AUDIO_ANALOG. 9394fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen */ 9494fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonenstatic int wl1273_fm_set_audio(struct wl1273_core *core, unsigned int new_mode) 9594fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen{ 9694fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen int r = 0; 9794fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 9894fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen if (core->mode == WL1273_MODE_OFF || 9994fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen core->mode == WL1273_MODE_SUSPENDED) 10094fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen return -EPERM; 10194fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 10294fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen if (core->mode == WL1273_MODE_RX && new_mode == WL1273_AUDIO_DIGITAL) { 10394fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen r = wl1273_fm_write_cmd(core, WL1273_PCM_MODE_SET, 10494fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen WL1273_PCM_DEF_MODE); 10594fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen if (r) 10694fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen goto out; 10794fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 10894fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen r = wl1273_fm_write_cmd(core, WL1273_I2S_MODE_CONFIG_SET, 10994fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen core->i2s_mode); 11094fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen if (r) 11194fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen goto out; 11294fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 11394fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen r = wl1273_fm_write_cmd(core, WL1273_AUDIO_ENABLE, 11494fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen WL1273_AUDIO_ENABLE_I2S); 11594fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen if (r) 11694fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen goto out; 11794fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 11894fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen } else if (core->mode == WL1273_MODE_RX && 11994fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen new_mode == WL1273_AUDIO_ANALOG) { 12094fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen r = wl1273_fm_write_cmd(core, WL1273_AUDIO_ENABLE, 12194fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen WL1273_AUDIO_ENABLE_ANALOG); 12294fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen if (r) 12394fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen goto out; 12494fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 12594fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen } else if (core->mode == WL1273_MODE_TX && 12694fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen new_mode == WL1273_AUDIO_DIGITAL) { 12794fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen r = wl1273_fm_write_cmd(core, WL1273_I2S_MODE_CONFIG_SET, 12894fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen core->i2s_mode); 12994fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen if (r) 13094fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen goto out; 13194fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 13294fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen r = wl1273_fm_write_cmd(core, WL1273_AUDIO_IO_SET, 13394fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen WL1273_AUDIO_IO_SET_I2S); 13494fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen if (r) 13594fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen goto out; 13694fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 13794fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen } else if (core->mode == WL1273_MODE_TX && 13894fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen new_mode == WL1273_AUDIO_ANALOG) { 13994fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen r = wl1273_fm_write_cmd(core, WL1273_AUDIO_IO_SET, 14094fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen WL1273_AUDIO_IO_SET_ANALOG); 14194fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen if (r) 14294fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen goto out; 14394fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen } 14494fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 14594fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen core->audio_mode = new_mode; 14694fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonenout: 14794fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen return r; 14894fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen} 14994fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 15094fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen/** 15194fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen * wl1273_fm_set_volume() - Set volume. 15294fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen * @core: A pointer to the device struct. 15394fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen * @volume: The new volume value. 15494fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen */ 15594fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonenstatic int wl1273_fm_set_volume(struct wl1273_core *core, unsigned int volume) 15694fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen{ 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 dev_dbg(&client->dev, "%s\n", __func__); 176383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 177383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen mfd_remove_devices(&client->dev); 178383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 179383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen return 0; 180383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen} 181383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 182f791be492f76dea7b0641ed227a60eeb2fa7e255Bill Pembertonstatic int wl1273_core_probe(struct i2c_client *client, 183383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen const struct i2c_device_id *id) 184383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen{ 185334a41ce9b753ec615e8c6c50ee07d6197190610Jingoo Han struct wl1273_fm_platform_data *pdata = dev_get_platdata(&client->dev); 186383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen struct wl1273_core *core; 187383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen struct mfd_cell *cell; 188383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen int children = 0; 189383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen int r = 0; 190383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 191383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen dev_dbg(&client->dev, "%s\n", __func__); 192383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 193383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen if (!pdata) { 194383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen dev_err(&client->dev, "No platform data.\n"); 195383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen return -EINVAL; 196383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen } 197383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 198383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen if (!(pdata->children & WL1273_RADIO_CHILD)) { 199383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen dev_err(&client->dev, "Cannot function without radio child.\n"); 200383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen return -EINVAL; 201383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen } 202383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 203bba078273e259c7eff729ac00a1476987ad5413aJingoo Han core = devm_kzalloc(&client->dev, sizeof(*core), GFP_KERNEL); 204383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen if (!core) 205383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen return -ENOMEM; 206383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 207383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen core->pdata = pdata; 208383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen core->client = client; 209383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen mutex_init(&core->lock); 210383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 211383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen i2c_set_clientdata(client, core); 212383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 213383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen dev_dbg(&client->dev, "%s: Have V4L2.\n", __func__); 214383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 215383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen cell = &core->cells[children]; 216383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen cell->name = "wl1273_fm_radio"; 2179e554696c03e04c51d095c1c451e26a8cb6a84faSamuel Ortiz cell->platform_data = &core; 2189e554696c03e04c51d095c1c451e26a8cb6a84faSamuel Ortiz cell->pdata_size = sizeof(core); 219383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen children++; 220383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 22194fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen core->read = wl1273_fm_read_reg; 22294fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen core->write = wl1273_fm_write_cmd; 22394fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen core->write_data = wl1273_fm_write_data; 22494fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen core->set_audio = wl1273_fm_set_audio; 22594fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen core->set_volume = wl1273_fm_set_volume; 22694fd5b7401e330498331ea3667d796e74c63d08aMatti Aaltonen 227383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen if (pdata->children & WL1273_CODEC_CHILD) { 228383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen cell = &core->cells[children]; 229383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 230383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen dev_dbg(&client->dev, "%s: Have codec.\n", __func__); 231383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen cell->name = "wl1273-codec"; 2329e554696c03e04c51d095c1c451e26a8cb6a84faSamuel Ortiz cell->platform_data = &core; 2339e554696c03e04c51d095c1c451e26a8cb6a84faSamuel Ortiz cell->pdata_size = sizeof(core); 234383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen children++; 235383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen } 236383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 237383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen dev_dbg(&client->dev, "%s: number of children: %d.\n", 238383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen __func__, children); 239383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 240383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen r = mfd_add_devices(&client->dev, -1, core->cells, 2410848c94fb4a5cc213a7fb0fb3a5721ad6e16f096Mark Brown children, NULL, 0, NULL); 242383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen if (r) 243383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen goto err; 244383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 245383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen return 0; 246383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 247383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonenerr: 248383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen pdata->free_resources(); 249383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 250383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen dev_dbg(&client->dev, "%s\n", __func__); 251383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 252383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen return r; 253383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen} 254383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 255383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonenstatic struct i2c_driver wl1273_core_driver = { 256383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen .driver = { 257383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen .name = WL1273_FM_DRIVER_NAME, 258383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen }, 259383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen .probe = wl1273_core_probe, 260383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen .id_table = wl1273_driver_id_table, 26184449216b01f9c2b4c9b1882f9d6abba07b7b7caBill Pemberton .remove = wl1273_core_remove, 262383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen}; 263383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 264383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonenstatic int __init wl1273_core_init(void) 265383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen{ 266383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen int r; 267383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 268383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen r = i2c_add_driver(&wl1273_core_driver); 269383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen if (r) { 270383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen pr_err(WL1273_FM_DRIVER_NAME 271383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen ": driver registration failed\n"); 272383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen return r; 273383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen } 274383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 275383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen return r; 276383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen} 277383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 278383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonenstatic void __exit wl1273_core_exit(void) 279383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen{ 280383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen i2c_del_driver(&wl1273_core_driver); 281383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen} 282383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonenlate_initcall(wl1273_core_init); 283383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonenmodule_exit(wl1273_core_exit); 284383268a8e282fb549dabe3a33ccafc9434ab6006Matti Aaltonen 285383268a8e282fb549dabe3a33ccafc9434ab6006Matti AaltonenMODULE_AUTHOR("Matti Aaltonen <matti.j.aaltonen@nokia.com>"); 286383268a8e282fb549dabe3a33ccafc9434ab6006Matti AaltonenMODULE_DESCRIPTION(DRIVER_DESC); 287383268a8e282fb549dabe3a33ccafc9434ab6006Matti AaltonenMODULE_LICENSE("GPL"); 288