Hello. On Wed, 2010-08-18 at 20:14 +0200, ext Pavan Savoy wrote: > --- On Wed, 7/7/10, Pavan Savoy <pavan_savoy@xxxxxx> wrote: > > > > From: Pavan Savoy <pavan_savoy@xxxxxx> > > Subject: Re: [PATCH v4 2/5] MFD: WL1273 FM Radio: MFD driver for the FM radio. > > To: "Matti J. Aaltonen" <matti.j.aaltonen@xxxxxxxxx>, "Mauro Carvalho Chehab" <mchehab@xxxxxxxxxx> > > Cc: linux-media@xxxxxxxxxxxxxxx, hverkuil@xxxxxxxxx, eduardo.valentin@xxxxxxxxx, "pavan savoy" <pavan_savoy@xxxxxxxxxxx> > > Date: Wednesday, 7 July, 2010, 10:51 AM > > > > --- On Tue, 6/7/10, Mauro Carvalho Chehab <mchehab@xxxxxxxxxx> > > wrote: > > > > > From: Mauro Carvalho Chehab <mchehab@xxxxxxxxxx> > > > Subject: Re: [PATCH v4 2/5] MFD: WL1273 FM Radio: MFD > > driver for the FM radio. > > > To: "Matti J. Aaltonen" <matti.j.aaltonen@xxxxxxxxx> > > > Cc: linux-media@xxxxxxxxxxxxxxx, > > hverkuil@xxxxxxxxx, > > eduardo.valentin@xxxxxxxxx > > > Date: Tuesday, 6 July, 2010, 8:04 AM > > > Em 04-06-2010 07:34, Matti J. > > > Aaltonen escreveu: > > > > This is a parent driver for two child drivers: > > the > > > V4L2 driver and > > > > the ALSA codec driver. The MFD part provides the > > I2C > > > communication > > > > to the device and a couple of functions that are > > > called from both > > > > children. > > > > Where can I have a look at the whole code ? As in some > > local tree, where all codes are put up ? > > Basically, we have a V4L2 driver for WL128x (using TTY as > > transport) and plan to push them soon ... > > > > This would be a nice input ... > > Anywhere I can have a look at the whole code? > We are trying to push out V4L2 drivers for FM on 128x, and intend to use several V4L2 new ioctls which you have defined (_BAND_) being one of them. > > Also we plan to push FM Tx of it too.. TX_CLASS from V4L2 has most of the ioctls and plan to introduce the rest. I'm sorry for not answering to you earlier. But I don't have my own public repository. But to create the whole thing is extremely simple: just take the current mainline tree and apply my patches on top of it... Best Regards, Matti > > > > > > > Signed-off-by: Matti J. Aaltonen <matti.j.aaltonen@xxxxxxxxx> > > > > --- > > > > drivers/mfd/Kconfig > > > | 6 + > > > > drivers/mfd/Makefile > > > | 2 + > > > > drivers/mfd/wl1273-core.c > > > | 616 > > > +++++++++++++++++++++++++++++++++++++++ > > > > include/linux/mfd/wl1273-core.h | 326 > > > +++++++++++++++++++++ > > > > 4 files changed, 950 insertions(+), 0 > > > deletions(-) > > > > create mode 100644 drivers/mfd/wl1273-core.c > > > > create mode 100644 > > > include/linux/mfd/wl1273-core.h > > > > > > > > diff --git a/drivers/mfd/Kconfig > > > b/drivers/mfd/Kconfig > > > > index 413576a..5998a94 100644 > > > > --- a/drivers/mfd/Kconfig > > > > +++ b/drivers/mfd/Kconfig > > > > @@ -135,6 +135,12 @@ config TWL4030_CODEC > > > > select MFD_CORE > > > > default n > > > > > > > > +config WL1273_CORE > > > > + bool > > > > + depends on I2C > > > > + select MFD_CORE > > > > + default n > > > > + > > > > config MFD_TMIO > > > > bool > > > > default n > > > > diff --git a/drivers/mfd/Makefile > > > b/drivers/mfd/Makefile > > > > index 78295d6..46e611d 100644 > > > > --- a/drivers/mfd/Makefile > > > > +++ b/drivers/mfd/Makefile > > > > @@ -30,6 +30,8 @@ > > > obj-$(CONFIG_TWL4030_CORE) += twl-core.o > > > twl4030-irq.o twl6030-irq.o > > > > obj-$(CONFIG_TWL4030_POWER) += > > > twl4030-power.o > > > > obj-$(CONFIG_TWL4030_CODEC) += > > > twl4030-codec.o > > > > > > > > +obj-$(CONFIG_WL1273_CORE) += > > > wl1273-core.o > > > > + > > > > obj-$(CONFIG_MFD_MC13783) += > > > mc13783-core.o > > > > > > > > obj-$(CONFIG_MFD_CORE) > > > += mfd-core.o > > > > diff --git a/drivers/mfd/wl1273-core.c > > > b/drivers/mfd/wl1273-core.c > > > > new file mode 100644 > > > > index 0000000..6c7dbba > > > > --- /dev/null > > > > +++ b/drivers/mfd/wl1273-core.c > > > > @@ -0,0 +1,616 @@ > > > > +/* > > > > + * MFD driver for wl1273 FM radio and audio > > codec > > > submodules. > > > > + * > > > > + * Author: Matti Aaltonen <matti.j.aaltonen@xxxxxxxxx> > > > > + * > > > > + * Copyright: (C) 2010 Nokia > > > Corporation > > > > + * > > > > + * This program is free software; you can > > > redistribute it and/or modify > > > > + * it under the terms of the GNU General Public > > > License version 2 as > > > > + * published by the Free Software Foundation. > > > > + * > > > > + * This program is distributed in the hope that > > it > > > will be useful, but > > > > + * WITHOUT ANY WARRANTY; without even the > > implied > > > warranty of > > > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR > > > PURPOSE. See the GNU > > > > + * General Public License for more details. > > > > + * > > > > + * You should have received a copy of the GNU > > General > > > Public License > > > > + * along with this program; if not, write to the > > Free > > > Software > > > > + * Foundation, Inc., 51 Franklin St, Fifth > > Floor, > > > Boston, MA > > > > + * 02110-1301 USA > > > > + * > > > > + */ > > > > + > > > > +#undef DEBUG > > > > + > > > > +#include <asm/unaligned.h> > > > > +#include <linux/completion.h> > > > > +#include <linux/delay.h> > > > > +#include <linux/i2c.h> > > > > +#include <linux/interrupt.h> > > > > +#include <linux/module.h> > > > > +#include <linux/types.h> > > > > +#include <linux/kernel.h> > > > > +#include <linux/fs.h> > > > > +#include <linux/platform_device.h> > > > > +#include <linux/mfd/core.h> > > > > +#include <linux/mfd/wl1273-core.h> > > > > +#include <media/v4l2-common.h> > > > > + > > > > +#define DRIVER_DESC "WL1273 FM Radio Core" > > > > + > > > > +#define > > > WL1273_IRQ_MASK (WL1273_FR_EVENT > > > | \ > > > > + > > > WL1273_POW_ENB_EVENT) > > > > + > > > > +static const struct band_info bands[] = { > > > > + /* USA & Europe */ > > > > + { > > > > + > > > .bottom_frequency = 87500, > > > > + > > > .top_frequency = > > > 108000, > > > > + > > > .band > > > = V4L2_FM_BAND_OTHER, > > > > + }, > > > > + /* Japan */ > > > > + { > > > > + > > > .bottom_frequency = 76000, > > > > + > > > .top_frequency = > > > 90000, > > > > + > > > .band > > > = V4L2_FM_BAND_JAPAN, > > > > + }, > > > > +}; > > > > + > > > > +/* > > > > + * static unsigned char radio_band - Band > > > > + * > > > > + * The bands are 0=Japan, 1=USA-Europe. > > USA-Europe is > > > the default. > > > > + */ > > > > +static unsigned char radio_band = 1; > > > > +module_param(radio_band, byte, 0); > > > > +MODULE_PARM_DESC(radio_band, "Band: 0=Japan, > > > 1=USA-Europe*"); > > > > + > > > > +/* > > > > + * static unsigned int rds_buf - the number of > > RDS > > > buffer blocks used. > > > > + * > > > > + * The default number is 100. > > > > + */ > > > > +static unsigned int rds_buf = 100; > > > > +module_param(rds_buf, uint, 0); > > > > +MODULE_PARM_DESC(rds_buf, "RDS buffer entries: > > > *100*"); > > > > + > > > > +int wl1273_fm_read_reg(struct wl1273_core *core, > > u8 > > > reg, u16 *value) > > > > +{ > > > > + struct i2c_client *client = > > > core->i2c_dev; > > > > + u8 b[2]; > > > > + int r; > > > > + > > > > + r = > > > i2c_smbus_read_i2c_block_data(client, reg, 2, b); > > > > + if (r != 2) { > > > > + > > > dev_err(&client->dev, "%s: Read: %d fails.\n", > > > __func__, reg); > > > > + return > > > -EREMOTEIO; > > > > + } > > > > + > > > > + *value = (u16)b[0] << 8 | > > > b[1]; > > > > + > > > > + return 0; > > > > +} > > > > +EXPORT_SYMBOL(wl1273_fm_read_reg); > > > > + > > > > +int wl1273_fm_write_cmd(struct wl1273_core > > *core, u8 > > > cmd, u16 param) > > > > +{ > > > > + struct i2c_client *client = > > > core->i2c_dev; > > > > + u8 buf[] = { (param >> 8) > > > & 0xff, param & 0xff }; > > > > + int r; > > > > + > > > > + r = > > > i2c_smbus_write_i2c_block_data(client, cmd, 2, buf); > > > > + if (r) { > > > > + > > > dev_err(&client->dev, "%s: Cmd: %d fails.\n", > > > __func__, cmd); > > > > + return r; > > > > + } > > > > + > > > > + return 0; > > > > +} > > > > +EXPORT_SYMBOL(wl1273_fm_write_cmd); > > > > + > > > > +int wl1273_fm_write_data(struct wl1273_core > > *core, u8 > > > *data, u16 len) > > > > +{ > > > > + struct i2c_client *client = > > > core->i2c_dev; > > > > + struct i2c_msg msg[1]; > > > > + int r; > > > > + > > > > + msg[0].addr = client->addr; > > > > + msg[0].flags = 0; > > > > + msg[0].buf = data; > > > > + msg[0].len = len; > > > > + > > > > + r = > > > i2c_transfer(client->adapter, msg, 1); > > > > + > > > > + if (r != 1) { > > > > + > > > dev_err(&client->dev, "%s: write error.\n", > > > __func__); > > > > + return > > > -EREMOTEIO; > > > > + } > > > > + > > > > + return 0; > > > > +} > > > > +EXPORT_SYMBOL(wl1273_fm_write_data); > > > > + > > > > +/** > > > > + * wl1273_fm_set_audio() - Set > > > audio mode. > > > > + * @core: > > > A pointer to the device struct. > > > > + * @new_mode: > > > The new audio mode. > > > > + * > > > > + * Audio modes are WL1273_AUDIO_DIGITAL and > > > WL1273_AUDIO_ANALOG. > > > > + */ > > > > +int wl1273_fm_set_audio(struct wl1273_core > > *core, > > > unsigned int new_mode) > > > > +{ > > > > + int r = 0; > > > > + > > > > + if (core->mode == > > > WL1273_MODE_OFF || > > > > + core->mode == > > > WL1273_MODE_SUSPENDED) > > > > + return -EPERM; > > > > + > > > > + if (core->mode == > > > WL1273_MODE_RX && new_mode == > > WL1273_AUDIO_DIGITAL) > > > { > > > > + r = > > > wl1273_fm_write_cmd(core, WL1273_PCM_MODE_SET, > > > > + > > > > > > WL1273_PCM_DEF_MODE); > > > > + if (r) > > > > + > > > goto out; > > > > + > > > > + r = > > > wl1273_fm_write_cmd(core, WL1273_I2S_MODE_CONFIG_SET, > > > > + > > > > > > core->i2s_mode); > > > > + if (r) > > > > + > > > goto out; > > > > + > > > > + r = > > > wl1273_fm_write_cmd(core, WL1273_AUDIO_ENABLE, > > > > + > > > > > > WL1273_AUDIO_ENABLE_I2S); > > > > + if (r) > > > > + > > > goto out; > > > > + > > > > + } else if (core->mode == > > > WL1273_MODE_RX && > > > > + > > > new_mode == WL1273_AUDIO_ANALOG) { > > > > + r = > > > wl1273_fm_write_cmd(core, WL1273_AUDIO_ENABLE, > > > > + > > > > > > WL1273_AUDIO_ENABLE_ANALOG); > > > > + if (r) > > > > + > > > goto out; > > > > + > > > > + } else if (core->mode == > > > WL1273_MODE_TX && > > > > + > > > new_mode == WL1273_AUDIO_DIGITAL) { > > > > + r = > > > wl1273_fm_write_cmd(core, WL1273_I2S_MODE_CONFIG_SET, > > > > + > > > > > > core->i2s_mode); > > > > + if (r) > > > > + > > > goto out; > > > > + > > > > + r = > > > wl1273_fm_write_cmd(core, WL1273_AUDIO_IO_SET, > > > > + > > > > > > WL1273_AUDIO_IO_SET_I2S); > > > > + if (r) > > > > + > > > goto out; > > > > + > > > > + } else if (core->mode == > > > WL1273_MODE_TX && > > > > + > > > new_mode == WL1273_AUDIO_ANALOG) { > > > > + r = > > > wl1273_fm_write_cmd(core, WL1273_AUDIO_IO_SET, > > > > + > > > > > > WL1273_AUDIO_IO_SET_ANALOG); > > > > + if (r) > > > > + > > > goto out; > > > > + } > > > > + > > > > + core->audio_mode = new_mode; > > > > + > > > > +out: > > > > + return r; > > > > +} > > > > +EXPORT_SYMBOL(wl1273_fm_set_audio); > > > > + > > > > +/** > > > > + * wl1273_fm_set_volume() - Set > > > volume. > > > > + * @core: > > > A pointer to the device struct. > > > > + * @volume: > > > The new volume value. > > > > + */ > > > > +int wl1273_fm_set_volume(struct wl1273_core > > *core, > > > unsigned int volume) > > > > +{ > > > > + u16 val; > > > > + int r; > > > > + > > > > + if (volume > > > > WL1273_MAX_VOLUME) > > > > + return > > > -EINVAL; > > > > + > > > > + if (core->volume == volume) > > > > + return 0; > > > > + > > > > + val = volume; > > > > + r = wl1273_fm_read_reg(core, > > > WL1273_VOLUME_SET, &val); > > > > + if (r) > > > > + return r; > > > > + > > > > + core->volume = volume; > > > > + return 0; > > > > +} > > > > +EXPORT_SYMBOL(wl1273_fm_set_volume); > > > > + > > > > +#define > > > WL1273_RDS_FIFO_EMPTY(status) (!(1 > > > << 6 & status)) > > > > + > > > > +#define > > > WL1273_RDS_CORRECTABLE_ERROR (1 << > > > 3) > > > > +#define > > > WL1273_RDS_UNCORRECTABLE_ERROR (1 << > > > 4) > > > > + > > > > +static int wl1273_fm_rds(struct wl1273_core > > *core) > > > > +{ > > > > + struct i2c_client *client = > > > core->i2c_dev; > > > > + struct device *dev = > > > &client->dev; > > > > + struct v4l2_rds_data rds = { 0, 0, > > > 0 }; > > > > + struct i2c_msg msg[] = { > > > > + { > > > > + > > > .addr = client->addr, > > > > + > > > .flags = 0, > > > > + > > > .buf = b0, > > > > + > > > .len = 1 > > > > + }, > > > > + { > > > > + > > > .addr = client->addr, > > > > + > > > .flags = I2C_M_RD, > > > > + > > > .buf = (u8 *) &rds, > > > > + > > > .len = 3 > > > > + } > > > > + }; > > > > + u8 b0[] = { WL1273_RDS_DATA_GET }, > > > status; > > > > + u16 val; > > > > + int r; > > > > + > > > > + r = wl1273_fm_read_reg(core, > > > WL1273_RDS_SYNC_GET, &val); > > > > + if (r) > > > > + return r; > > > > + > > > > + /* Is RDS decoder synchronized? > > > */ > > > > + if ((val & 0x01) == 0) > > > > + return > > > -EAGAIN; > > > > + > > > > + /* copy all four RDS blocks to > > > internal buffer */ > > > > + do { > > > > + r = > > > i2c_transfer(client->adapter, msg, 2); > > > > + if (r != 2) { > > > > + > > > dev_err(dev, WL1273_FM_DRIVER_NAME > > > > + > > > ": %s: read_rds error > > > r == %i)\n", > > > > + > > > __func__, r); > > > > + } > > > > + > > > > + status = > > > rds.block; > > > > + > > > > + if > > > (WL1273_RDS_FIFO_EMPTY(status)) > > > > + > > > break; > > > > + > > > > + /* copy RDS > > > block to internal buffer */ > > > > + > > > memcpy(&core->buffer[core->wr_index], > > &rds, > > > 3); > > > > + > > > core->wr_index += 3; > > > > + > > > > + /* copy the > > > error bits to standard positions */ > > > > + if > > > (WL1273_RDS_UNCORRECTABLE_ERROR & status) { > > > > + > > > rds.block |= V4L2_RDS_BLOCK_ERROR; > > > > + > > > rds.block &= > > > ~V4L2_RDS_BLOCK_CORRECTED; > > > > + } else if > > > (WL1273_RDS_CORRECTABLE_ERROR & status) { > > > > + > > > rds.block &= ~V4L2_RDS_BLOCK_ERROR; > > > > + > > > rds.block |= V4L2_RDS_BLOCK_CORRECTED; > > > > + } else { > > > > + > > > rds.block &= ~V4L2_RDS_BLOCK_ERROR; > > > > + > > > rds.block &= > > > ~V4L2_RDS_BLOCK_CORRECTED; > > > > + } > > > > + > > > > + /* wrap write > > > pointer */ > > > > + if > > > (core->wr_index >= core->buf_size) > > > > + > > > core->wr_index = 0; > > > > + > > > > + /* check for > > > overflow & start over */ > > > > + if > > > (core->wr_index == core->rd_index) { > > > > + > > > dev_dbg(dev, "RDS OVERFLOW"); > > > > + > > > > + > > > core->rd_index = 0; > > > > + > > > core->wr_index = 0; > > > > + > > > break; > > > > + } > > > > + } while > > > (!WL1273_RDS_FIFO_EMPTY(status)); > > > > + > > > > + /* wake up read queue */ > > > > + if (core->wr_index != > > > core->rd_index) > > > > + > > > wake_up_interruptible(&core->read_queue); > > > > + > > > > + return 0; > > > > +} > > > > + > > > > +static void wl1273_fm_rds_work(struct > > wl1273_core > > > *core) > > > > +{ > > > > + wl1273_fm_rds(core); > > > > +} > > > > + > > > > +static irqreturn_t > > wl1273_fm_irq_thread_handler(int > > > irq, void *dev_id) > > > > +{ > > > > + int r; > > > > + u16 flags; > > > > + struct wl1273_core *core = > > > dev_id; > > > > + > > > > + r = wl1273_fm_read_reg(core, > > > WL1273_FLAG_GET, &flags); > > > > + if (r) > > > > + goto out; > > > > + > > > > + if (flags & WL1273_BL_EVENT) > > > { > > > > + > > > core->irq_received = flags; > > > > + > > > dev_dbg(&core->i2c_dev->dev, "IRQ: BL\n"); > > > > + } > > > > + > > > > + if (flags & WL1273_RDS_EVENT) > > > { > > > > + msleep(200); > > > > + > > > > + > > > wl1273_fm_rds_work(core); > > > > + } > > > > + > > > > + if (flags & > > > WL1273_BBLK_EVENT) > > > > + > > > dev_dbg(&core->i2c_dev->dev, "IRQ: > > BBLK\n"); > > > > + > > > > + if (flags & > > > WL1273_LSYNC_EVENT) > > > > + > > > dev_dbg(&core->i2c_dev->dev, "IRQ: > > LSYNC\n"); > > > > + > > > > + if (flags & WL1273_LEV_EVENT) > > > { > > > > + u16 level; > > > > + > > > > + r = > > > wl1273_fm_read_reg(core, WL1273_RSSI_LVL_GET, > > &level); > > > > + > > > > + if (r) > > > > + > > > goto out; > > > > + > > > > + if (level > > > > 14) > > > > + > > > dev_dbg(&core->i2c_dev->dev, > > > "IRQ: LEV: 0x%x04\n", > > > > + > > > level); > > > > + } > > > > + > > > > + if (flags & > > > WL1273_IFFR_EVENT) > > > > + > > > dev_dbg(&core->i2c_dev->dev, "IRQ: > > IFFR\n"); > > > > + > > > > + if (flags & WL1273_PI_EVENT) > > > > + > > > dev_dbg(&core->i2c_dev->dev, "IRQ: PI\n"); > > > > + > > > > + if (flags & WL1273_PD_EVENT) > > > > + > > > dev_dbg(&core->i2c_dev->dev, "IRQ: PD\n"); > > > > + > > > > + if (flags & > > > WL1273_STIC_EVENT) > > > > + > > > dev_dbg(&core->i2c_dev->dev, "IRQ: > > STIC\n"); > > > > + > > > > + if (flags & WL1273_MAL_EVENT) > > > > + > > > dev_dbg(&core->i2c_dev->dev, "IRQ: MAL\n"); > > > > + > > > > + if (flags & > > > WL1273_POW_ENB_EVENT) { > > > > + > > > complete(&core->busy); > > > > + > > > dev_dbg(&core->i2c_dev->dev, "NOT BUSY\n"); > > > > + > > > dev_dbg(&core->i2c_dev->dev, "IRQ: > > POW_ENB\n"); > > > > + } > > > > + > > > > + if (flags & > > > WL1273_SCAN_OVER_EVENT) > > > > + > > > dev_dbg(&core->i2c_dev->dev, "IRQ: > > SCAN_OVER\n"); > > > > + > > > > + if (flags & > > > WL1273_ERROR_EVENT) > > > > + > > > dev_dbg(&core->i2c_dev->dev, "IRQ: > > ERROR\n"); > > > > + > > > > + if (flags & WL1273_FR_EVENT) > > > { > > > > + u16 freq; > > > > + > > > > + > > > dev_dbg(&core->i2c_dev->dev, "IRQ: FR:\n"); > > > > + > > > > + if > > > (core->mode == WL1273_MODE_RX) { > > > > + > > > r = wl1273_fm_write_cmd(core, > > > WL1273_TUNER_MODE_SET, > > > > + > > > > > > TUNER_MODE_STOP_SEARCH); > > > > + > > > if (r) { > > > > + > > > > > > dev_err(&core->i2c_dev->dev, > > > > + > > > > > > "%s: TUNER_MODE_SET fails: %d\n", > > > > + > > > > > > __func__, r); > > > > + > > > goto out; > > > > + > > > } > > > > + > > > > + > > > r = wl1273_fm_read_reg(core, > > > WL1273_FREQ_SET, &freq); > > > > + > > > if (r) > > > > + > > > goto out; > > > > + > > > > + > > > core->rx_frequency = > > > > + > > > > > > bands[core->band].bottom_frequency + > > > > + > > > freq * 50; > > > > + > > > > + > > > /* > > > > + > > > * The driver works > > > better with this msleep, > > > > + > > > * the documentation > > > doesn't mention it. > > > > + > > > */ > > > > + > > > msleep(10); > > > > > > > > > msleep on an irq handler? You shouldn't be doing it! > > You're > > > not allowed to sleep > > > during IRQ time. Kernel can panic here. You'll > > probably > > > need to defer work and > > > handle it outside irq time. > > > > + > > > > + > > > dev_dbg(&core->i2c_dev->dev, > > > "%dkHz\n", > > > > + > > > > > > core->rx_frequency); > > > > + > > > > + } else { > > > > + > > > r = wl1273_fm_read_reg(core, > > > WL1273_CHANL_SET, &freq); > > > > + > > > if (r) > > > > + > > > goto out; > > > > + > > > > + > > > dev_dbg(&core->i2c_dev->dev, > > > "%dkHz\n", freq); > > > > + } > > > > + > > > dev_dbg(&core->i2c_dev->dev, "%s: NOT > > BUSY\n", > > > __func__); > > > > + } > > > > + > > > > +out: > > > > + wl1273_fm_write_cmd(core, > > > WL1273_INT_MASK_SET, > > > > + > > > core->irq_flags); > > > > + complete(&core->busy); > > > > + > > > > + return IRQ_HANDLED; > > > > +} > > > > + > > > > +static struct i2c_device_id > > wl1273_driver_id_table[] > > > = { > > > > + { WL1273_FM_DRIVER_NAME, 0 }, > > > > + { } > > > > +}; > > > > +MODULE_DEVICE_TABLE(i2c, > > wl1273_driver_id_table); > > > > + > > > > +static int wl1273_core_remove(struct i2c_client > > > *client) > > > > +{ > > > > + struct wl1273_core *core = > > > i2c_get_clientdata(client); > > > > + struct wl1273_fm_platform_data > > > *pdata = > > > > + > > > client->dev.platform_data; > > > > + > > > > + dev_dbg(&client->dev, > > > "%s\n", __func__); > > > > + > > > > + > > > mfd_remove_devices(&client->dev); > > > > + i2c_set_clientdata(client, core); > > > > + > > > > + free_irq(client->irq, core); > > > > + pdata->free_resources(); > > > > + > > > > + kfree(core->buffer); > > > > + kfree(core); > > > > + > > > > + return 0; > > > > +} > > > > + > > > > +static int __devinit wl1273_core_probe(struct > > > i2c_client *client, > > > > + > > > > > > const struct i2c_device_id *id) > > > > +{ > > > > + struct wl1273_fm_platform_data > > > *pdata = client->dev.platform_data; > > > > + int r = 0; > > > > + struct wl1273_core *core; > > > > + int children = 0; > > > > + > > > > + dev_dbg(&client->dev, > > > "%s\n", __func__); > > > > + > > > > + if (!pdata) { > > > > + > > > dev_err(&client->dev, "No platform data.\n"); > > > > + return > > > -EINVAL; > > > > + } > > > > + > > > > + core = kzalloc(sizeof(*core), > > > GFP_KERNEL); > > > > + if (!core) > > > > + return > > > -ENOMEM; > > > > + > > > > + /* RDS buffer allocation */ > > > > + core->buf_size = rds_buf * 3; > > > > + core->buffer = > > > kmalloc(core->buf_size, GFP_KERNEL); > > > > + if (!core->buffer) { > > > > + > > > dev_err(&client->dev, > > > > + > > > "Cannot allocate memory for RDS > > > buffer.\n"); > > > > + r = -ENOMEM; > > > > + goto > > > err_kmalloc; > > > > + } > > > > + > > > > + core->irq_flags = > > > WL1273_IRQ_MASK; > > > > + core->i2c_dev = client; > > > > + core->rds_on = false; > > > > + core->mode = WL1273_MODE_OFF; > > > > + core->tx_power = 4; > > > > + core->audio_mode = > > > WL1273_AUDIO_ANALOG; > > > > + core->band = radio_band; > > > > + core->bands = bands; > > > > + core->number_of_bands = > > > ARRAY_SIZE(bands); > > > > + core->i2s_mode = > > > WL1273_I2S_DEF_MODE; > > > > + core->channel_number = 2; > > > > + core->volume = > > > WL1273_DEFAULT_VOLUME; > > > > + core->rx_frequency = > > > bands[core->band].bottom_frequency; > > > > + core->tx_frequency = > > > bands[core->band].top_frequency; > > > > + > > > > + dev_dbg(&client->dev, > > > "radio_band: %d\n", radio_band); > > > > + > > > > + mutex_init(&core->lock); > > > > + > > > > + pdata = > > > client->dev.platform_data; > > > > + if (pdata) { > > > > + r = > > > pdata->request_resources(client); > > > > + if (r) { > > > > + > > > dev_err(&client->dev, > > > WL1273_FM_DRIVER_NAME > > > > + > > > ": Cannot get platform > > > data\n"); > > > > + > > > goto err_new_mixer; > > > > + } > > > > + > > > > + r = > > > request_threaded_irq(client->irq, NULL, > > > > + > > > > > > wl1273_fm_irq_thread_handler, > > > > + > > > > > > IRQF_ONESHOT | > > > IRQF_TRIGGER_FALLING, > > > > + > > > > > > "wl1273-fm", core); > > > > + if (r < 0) > > > { > > > > + > > > dev_err(&client->dev, > > > WL1273_FM_DRIVER_NAME > > > > + > > > ": Unable to register > > > IRQ handler\n"); > > > > + > > > goto err_request_irq; > > > > + } > > > > + } else { > > > > + > > > dev_err(&client->dev, WL1273_FM_DRIVER_NAME ": > > Core > > > WL1273 IRQ" > > > > + > > > " not configured"); > > > > + r = -EINVAL; > > > > + goto > > > err_new_mixer; > > > > + } > > > > + > > > > + > > > init_completion(&core->busy); > > > > + > > > init_waitqueue_head(&core->read_queue); > > > > + > > > > + i2c_set_clientdata(client, core); > > > > + > > > > + if (pdata->children & > > > WL1273_RADIO_CHILD) { > > > > + struct mfd_cell > > > *cell = &core->cells[children]; > > > > + > > > dev_dbg(&client->dev, "%s: Have V4L2.\n", > > __func__); > > > > + cell->name = > > > "wl1273_fm_radio"; > > > > + > > > cell->platform_data = &core; > > > > + > > > cell->data_size = sizeof(core); > > > > + children++; > > > > + } > > > > + > > > > + if (pdata->children & > > > WL1273_CODEC_CHILD) { > > > > + struct mfd_cell > > > *cell = &core->cells[children]; > > > > + > > > dev_dbg(&client->dev, "%s: Have codec.\n", > > > __func__); > > > > + cell->name = > > > "wl1273_codec_audio"; > > > > + > > > cell->platform_data = &core; > > > > + > > > cell->data_size = sizeof(core); > > > > + children++; > > > > + } > > > > + > > > > + if (children) { > > > > + > > > dev_dbg(&client->dev, "%s: Have children.\n", > > > __func__); > > > > + r = > > > mfd_add_devices(&client->dev, -1, > > core->cells, > > > > + > > > > > > children, NULL, 0); > > > > + } else { > > > > + > > > dev_err(&client->dev, "No platform data found > > for > > > children.\n"); > > > > + r = -ENODEV; > > > > + } > > > > + > > > > + if (!r) > > > > + return 0; > > > > + > > > > + i2c_set_clientdata(client, NULL); > > > > + kfree(core); > > > > + free_irq(client->irq, core); > > > > +err_request_irq: > > > > + pdata->free_resources(); > > > > +err_new_mixer: > > > > + kfree(core->buffer); > > > > +err_kmalloc: > > > > + kfree(core); > > > > + dev_dbg(&client->dev, > > > "%s\n", __func__); > > > > + > > > > + return r; > > > > +} > > > > + > > > > +static struct i2c_driver wl1273_core_driver = { > > > > + .driver = { > > > > + .name = > > > WL1273_FM_DRIVER_NAME, > > > > + }, > > > > + .probe = wl1273_core_probe, > > > > + .id_table = > > > wl1273_driver_id_table, > > > > + .remove = > > > __devexit_p(wl1273_core_remove), > > > > +}; > > > > + > > > > +static int __init wl1273_core_init(void) > > > > +{ > > > > + int r; > > > > + > > > > + r = > > > i2c_add_driver(&wl1273_core_driver); > > > > + if (r) { > > > > + > > > pr_err(WL1273_FM_DRIVER_NAME > > > > + > > > ": driver registration failed\n"); > > > > + return r; > > > > + } > > > > + > > > > + return 0; > > > > +} > > > > + > > > > +static void __exit wl1273_core_exit(void) > > > > +{ > > > > + flush_scheduled_work(); > > > > + > > > > + > > > i2c_del_driver(&wl1273_core_driver); > > > > +} > > > > +late_initcall(wl1273_core_init); > > > > +module_exit(wl1273_core_exit); > > > > + > > > > +MODULE_AUTHOR("Matti Aaltonen <matti.j.aaltonen@xxxxxxxxx>"); > > > > +MODULE_DESCRIPTION(DRIVER_DESC); > > > > +MODULE_LICENSE("GPL"); > > > > diff --git a/include/linux/mfd/wl1273-core.h > > > b/include/linux/mfd/wl1273-core.h > > > > new file mode 100644 > > > > index 0000000..81c9743 > > > > --- /dev/null > > > > +++ b/include/linux/mfd/wl1273-core.h > > > > @@ -0,0 +1,326 @@ > > > > +/* > > > > + * include/media/radio/radio-wl1273.h > > > > + * > > > > + * Some definitions for the wl1273 radio > > > receiver/transmitter chip. > > > > + * > > > > + * Copyright (C) Nokia Corporation > > > > + * Author: Matti J. Aaltonen <matti.j.aaltonen@xxxxxxxxx> > > > > + * > > > > + * This program is free software; you can > > > redistribute it and/or > > > > + * modify it under the terms of the GNU General > > > Public License > > > > + * version 2 as published by the Free Software > > > Foundation. > > > > + * > > > > + * This program is distributed in the hope that > > it > > > will be useful, but > > > > + * WITHOUT ANY WARRANTY; without even the > > implied > > > warranty of > > > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR > > > PURPOSE. See the GNU > > > > + * General Public License for more details. > > > > + * > > > > + * You should have received a copy of the GNU > > General > > > Public License > > > > + * along with this program; if not, write to the > > Free > > > Software > > > > + * Foundation, Inc., 51 Franklin St, Fifth > > Floor, > > > Boston, MA > > > > + * 02110-1301 USA > > > > + */ > > > > + > > > > +#ifndef RADIO_WL1273_H > > > > +#define RADIO_WL1273_H > > > > + > > > > +#include <linux/i2c.h> > > > > +#include <linux/mfd/core.h> > > > > + > > > > +#define WL1273_FM_DRIVER_NAME > > > "wl1273-fm" > > > > +#define RX71_FM_I2C_ADDR 0x22 > > > > + > > > > +#define WL1273_STEREO_GET > > > 0 > > > > +#define WL1273_RSSI_LVL_GET > > > 1 > > > > +#define WL1273_IF_COUNT_GET > > > 2 > > > > +#define WL1273_FLAG_GET > > > 3 > > > > +#define WL1273_RDS_SYNC_GET > > > 4 > > > > +#define WL1273_RDS_DATA_GET > > > 5 > > > > +#define WL1273_FREQ_SET > > > 10 > > > > +#define WL1273_AF_FREQ_SET > > > 11 > > > > +#define WL1273_MOST_MODE_SET > > > 12 > > > > +#define WL1273_MOST_BLEND_SET > > > 13 > > > > +#define WL1273_DEMPH_MODE_SET > > > 14 > > > > +#define WL1273_SEARCH_LVL_SET > > > 15 > > > > +#define WL1273_BAND_SET > > > 16 > > > > +#define WL1273_MUTE_STATUS_SET > > > 17 > > > > +#define WL1273_RDS_PAUSE_LVL_SET > > > 18 > > > > +#define WL1273_RDS_PAUSE_DUR_SET > > > 19 > > > > +#define WL1273_RDS_MEM_SET > > > 20 > > > > +#define WL1273_RDS_BLK_B_SET > > > 21 > > > > +#define WL1273_RDS_MSK_B_SET > > > 22 > > > > +#define WL1273_RDS_PI_MASK_SET > > > 23 > > > > +#define WL1273_RDS_PI_SET > > > 24 > > > > +#define WL1273_RDS_SYSTEM_SET > > > 25 > > > > +#define WL1273_INT_MASK_SET > > > 26 > > > > +#define WL1273_SEARCH_DIR_SET > > > 27 > > > > +#define WL1273_VOLUME_SET > > > 28 > > > > +#define WL1273_AUDIO_ENABLE > > > 29 > > > > +#define WL1273_PCM_MODE_SET > > > 30 > > > > +#define WL1273_I2S_MODE_CONFIG_SET > > > 31 > > > > +#define WL1273_POWER_SET > > > 32 > > > > +#define WL1273_INTX_CONFIG_SET > > > 33 > > > > +#define WL1273_PULL_EN_SET > > > 34 > > > > +#define WL1273_HILO_SET > > > 35 > > > > +#define WL1273_SWITCH2FREF > > > 36 > > > > +#define WL1273_FREQ_DRIFT_REPORT > > > 37 > > > > + > > > > +#define WL1273_PCE_GET > > > 40 > > > > +#define WL1273_FIRM_VER_GET > > > 41 > > > > +#define WL1273_ASIC_VER_GET > > > 42 > > > > +#define WL1273_ASIC_ID_GET > > > 43 > > > > +#define WL1273_MAN_ID_GET > > > 44 > > > > +#define WL1273_TUNER_MODE_SET > > > 45 > > > > +#define WL1273_STOP_SEARCH > > > 46 > > > > +#define WL1273_RDS_CNTRL_SET > > > 47 > > > > + > > > > +#define WL1273_WRITE_HARDWARE_REG > > > 100 > > > > +#define WL1273_CODE_DOWNLOAD > > > 101 > > > > +#define WL1273_RESET > > > 102 > > > > + > > > > +#define WL1273_FM_POWER_MODE > > > 254 > > > > +#define WL1273_FM_INTERRUPT > > > 255 > > > > + > > > > +/* Transmitter API */ > > > > + > > > > +#define WL1273_CHANL_SET > > > 55 > > > > +#define WL1273_SCAN_SPACING_SET > > > 56 > > > > +#define WL1273_REF_SET > > > 57 > > > > +#define WL1273_POWER_ENB_SET > > > 90 > > > > +#define WL1273_POWER_ATT_SET > > > 58 > > > > +#define WL1273_POWER_LEV_SET > > > 59 > > > > +#define WL1273_AUDIO_DEV_SET > > > 60 > > > > +#define WL1273_PILOT_DEV_SET > > > 61 > > > > +#define WL1273_RDS_DEV_SET > > > 62 > > > > +#define WL1273_PUPD_SET > > > 91 > > > > +#define WL1273_AUDIO_IO_SET > > > 63 > > > > +#define WL1273_PREMPH_SET > > > 64 > > > > +#define WL1273_MONO_SET > > > 66 > > > > +#define WL1273_MUTE > > > 92 > > > > +#define WL1273_MPX_LMT_ENABLE > > > 67 > > > > +#define WL1273_PI_SET > > > 93 > > > > +#define WL1273_ECC_SET > > > 69 > > > > +#define WL1273_PTY > > > 70 > > > > +#define WL1273_AF > > > 71 > > > > +#define WL1273_DISPLAY_MODE > > > 74 > > > > +#define WL1273_RDS_REP_SET > > > 77 > > > > +#define WL1273_RDS_CONFIG_DATA_SET > > > 98 > > > > +#define WL1273_RDS_DATA_SET > > > 99 > > > > +#define WL1273_RDS_DATA_ENB > > > 94 > > > > +#define WL1273_TA_SET > > > 78 > > > > +#define WL1273_TP_SET > > > 79 > > > > +#define WL1273_DI_SET > > > 80 > > > > +#define WL1273_MS_SET > > > 81 > > > > +#define WL1273_PS_SCROLL_SPEED > > > 82 > > > > +#define WL1273_TX_AUDIO_LEVEL_TEST > > > 96 > > > > +#define > > > WL1273_TX_AUDIO_LEVEL_TEST_THRESHOLD 73 > > > > +#define > > > WL1273_TX_AUDIO_INPUT_LEVEL_RANGE_SET 54 > > > > +#define WL1273_RX_ANTENNA_SELECT > > > 87 > > > > +#define WL1273_I2C_DEV_ADDR_SET > > > 86 > > > > +#define > > > WL1273_REF_ERR_CALIB_PARAM_SET > > > 88 > > > > +#define > > > WL1273_REF_ERR_CALIB_PERIODICITY_SET 89 > > > > +#define WL1273_SOC_INT_TRIGGER > > > 52 > > > > +#define WL1273_SOC_AUDIO_PATH_SET > > > 83 > > > > +#define WL1273_SOC_PCMI_OVERRIDE > > > 84 > > > > +#define WL1273_SOC_I2S_OVERRIDE > > > 85 > > > > +#define > > > WL1273_RSSI_BLOCK_SCAN_FREQ_SET 95 > > > > +#define > > > WL1273_RSSI_BLOCK_SCAN_START 97 > > > > +#define > > > WL1273_RSSI_BLOCK_SCAN_DATA_GET 5 > > > > +#define > > > WL1273_READ_FMANT_TUNE_VALUE > > > 104 > > > > + > > > > +#define WL1273_RDS_OFF > > > 0 > > > > +#define WL1273_RDS_ON > > > 1 > > > > +#define WL1273_RDS_RESET 2 > > > > + > > > > +#define WL1273_AUDIO_DIGITAL 0 > > > > +#define WL1273_AUDIO_ANALOG 1 > > > > + > > > > +#define WL1273_MODE_RX > > > 0 > > > > +#define WL1273_MODE_TX > > > 1 > > > > +#define WL1273_MODE_OFF > > > 2 > > > > +#define WL1273_MODE_SUSPENDED 3 > > > > + > > > > +#define WL1273_RADIO_CHILD (1 > > > << 0) > > > > +#define WL1273_CODEC_CHILD (1 > > > << 1) > > > > + > > > > +#define WL1273_RX_MONO > > > 1 > > > > +#define WL1273_RX_STEREO 0 > > > > +#define WL1273_TX_MONO > > > 0 > > > > +#define WL1273_TX_STEREO 1 > > > > + > > > > +#define WL1273_MAX_VOLUME 0xffff > > > > +#define WL1273_DEFAULT_VOLUME > > > 0x78b8 > > > > + > > > > +/* I2S protocol, left channel first, data width > > 16 > > > bits */ > > > > +#define WL1273_PCM_DEF_MODE > > > 0x00 > > > > + > > > > +/* Rx */ > > > > +#define WL1273_AUDIO_ENABLE_I2S > > > (1 << 0) > > > > +#define WL1273_AUDIO_ENABLE_ANALOG > > > (1 << 1) > > > > + > > > > +/* Tx */ > > > > +#define WL1273_AUDIO_IO_SET_ANALOG > > > 0 > > > > +#define WL1273_AUDIO_IO_SET_I2S > > > 1 > > > > + > > > > +#define WL1273_POWER_SET_OFF > > > 0 > > > > +#define WL1273_POWER_SET_FM > > > (1 << 0) > > > > +#define WL1273_POWER_SET_RDS > > > (1 << 1) > > > > +#define WL1273_POWER_SET_RETENTION > > > (1 << 4) > > > > + > > > > +#define WL1273_PUPD_SET_OFF > > > 0x00 > > > > +#define WL1273_PUPD_SET_ON > > > 0x01 > > > > +#define WL1273_PUPD_SET_RETENTION > > > 0x10 > > > > + > > > > +/* I2S mode */ > > > > +#define WL1273_IS2_WIDTH_32 0x0 > > > > +#define WL1273_IS2_WIDTH_40 0x1 > > > > +#define WL1273_IS2_WIDTH_22_23 0x2 > > > > +#define WL1273_IS2_WIDTH_23_22 0x3 > > > > +#define WL1273_IS2_WIDTH_48 0x4 > > > > +#define WL1273_IS2_WIDTH_50 0x5 > > > > +#define WL1273_IS2_WIDTH_60 0x6 > > > > +#define WL1273_IS2_WIDTH_64 0x7 > > > > +#define WL1273_IS2_WIDTH_80 0x8 > > > > +#define WL1273_IS2_WIDTH_96 0x9 > > > > +#define WL1273_IS2_WIDTH_128 0xa > > > > +#define WL1273_IS2_WIDTH 0xf > > > > + > > > > +#define WL1273_IS2_FORMAT_STD (0x0 > > > << 4) > > > > +#define WL1273_IS2_FORMAT_LEFT (0x1 > > > << 4) > > > > +#define WL1273_IS2_FORMAT_RIGHT > > > (0x2 << 4) > > > > +#define WL1273_IS2_FORMAT_USER (0x3 > > > << 4) > > > > + > > > > +#define WL1273_IS2_MASTER (0x0 > > > << 6) > > > > +#define WL1273_IS2_SLAVEW (0x1 > > > << 6) > > > > + > > > > +#define > > > WL1273_IS2_TRI_AFTER_SENDING (0x0 << > > > 7) > > > > +#define > > > WL1273_IS2_TRI_ALWAYS_ACTIVE (0x1 << > > > 7) > > > > + > > > > +#define WL1273_IS2_SDOWS_RR (0x0 > > > << 8) > > > > +#define WL1273_IS2_SDOWS_RF (0x1 > > > << 8) > > > > +#define WL1273_IS2_SDOWS_FR (0x2 > > > << 8) > > > > +#define WL1273_IS2_SDOWS_FF (0x3 > > > << 8) > > > > + > > > > +#define WL1273_IS2_TRI_OPT (0x0 > > > << 10) > > > > +#define WL1273_IS2_TRI_ALWAYS (0x1 > > > << 10) > > > > + > > > > +#define WL1273_IS2_RATE_48K (0x0 > > > << 12) > > > > +#define WL1273_IS2_RATE_44_1K (0x1 > > > << 12) > > > > +#define WL1273_IS2_RATE_32K (0x2 > > > << 12) > > > > +#define WL1273_IS2_RATE_22_05K (0x4 > > > << 12) > > > > +#define WL1273_IS2_RATE_16K (0x5 > > > << 12) > > > > +#define WL1273_IS2_RATE_12K (0x8 > > > << 12) > > > > +#define WL1273_IS2_RATE_11_025 (0x9 > > > << 12) > > > > +#define WL1273_IS2_RATE_8K (0xa > > > << 12) > > > > +#define WL1273_IS2_RATE > > > (0xf << 12) > > > > + > > > > +#define WL1273_I2S_DEF_MODE > > > (WL1273_IS2_WIDTH_32 | \ > > > > + > > > > > > WL1273_IS2_FORMAT_STD | \ > > > > + > > > > > > WL1273_IS2_MASTER | \ > > > > + > > > > > > WL1273_IS2_TRI_AFTER_SENDING | > > > \ > > > > + > > > > > > WL1273_IS2_SDOWS_RR | \ > > > > + > > > > > > WL1273_IS2_TRI_OPT | \ > > > > + > > > > > > WL1273_IS2_RATE_48K) > > > > + > > > > +/* Private IOCTL */ > > > > +#define WL1273_CID_FM_BAND > > > (V4L2_CID_PRIVATE_BASE + 2) > > > > + > > > > +#define SCHAR_MIN (-128) > > > > +#define SCHAR_MAX 127 > > > > + > > > > +#define WL1273_FR_EVENT > > > (1 << 0) > > > > +#define WL1273_BL_EVENT > > > (1 << 1) > > > > +#define WL1273_RDS_EVENT > > > (1 << 2) > > > > +#define WL1273_BBLK_EVENT > > > (1 << 3) > > > > +#define WL1273_LSYNC_EVENT > > > (1 << 4) > > > > +#define WL1273_LEV_EVENT > > > (1 << 5) > > > > +#define WL1273_IFFR_EVENT > > > (1 << 6) > > > > +#define WL1273_PI_EVENT > > > (1 << 7) > > > > +#define WL1273_PD_EVENT > > > (1 << 8) > > > > +#define WL1273_STIC_EVENT > > > (1 << 9) > > > > +#define WL1273_MAL_EVENT > > > (1 << 10) > > > > +#define WL1273_POW_ENB_EVENT > > > (1 << 11) > > > > +#define WL1273_SCAN_OVER_EVENT > > > (1 << 12) > > > > +#define WL1273_ERROR_EVENT > > > (1 << 13) > > > > + > > > > +#define TUNER_MODE_STOP_SEARCH > > > 0 > > > > +#define TUNER_MODE_PRESET > > > 1 > > > > +#define TUNER_MODE_AUTO_SEEK > > > 2 > > > > +#define TUNER_MODE_AF > > > 3 > > > > +#define TUNER_MODE_AUTO_SEEK_PI > > > 4 > > > > +#define TUNER_MODE_AUTO_SEEK_BULK > > > 5 > > > > + > > > > +/* Allowed modes */ > > > > +#define WL1273_RX_ALLOWED 0x01 > > > > +#define WL1273_TX_ALLOWED 0x02 > > > > +#define WL1273_RXTX_ALLOWED > > > (WL1273_RX_ALLOWED | WL1273_TX_ALLOWED) > > > > + > > > > +struct band_info { > > > > + u32 bottom_frequency; > > > > + u32 top_frequency; > > > > + u8 band; > > > > +}; > > > > + > > > > +struct wl1273_fm_platform_data { > > > > + int (*request_resources) (struct > > > i2c_client *client); > > > > + void (*free_resources) (void); > > > > + void (*enable) (void); > > > > + void (*disable) (void); > > > > + > > > > + u8 modes; > > > > + unsigned int children; > > > > +}; > > > > + > > > > +#define WL1273_FM_CORE_CELLS 2 > > > > + > > > > +/* Allowed modes */ > > > > +#define WL1273_RX_ALLOWED 0x01 > > > > +#define WL1273_TX_ALLOWED 0x02 > > > > +#define WL1273_RXTX_ALLOWED > > > (WL1273_RX_ALLOWED | WL1273_TX_ALLOWED) > > > > + > > > > +struct wl1273_core { > > > > + struct mfd_cell > > > cells[WL1273_FM_CORE_CELLS]; > > > > + struct i2c_client *i2c_dev; > > > > + > > > > + u8 allowed_modes; > > > > + unsigned int mode; > > > > + unsigned int preemphasis; > > > > + unsigned int audio_mode; > > > > + unsigned int spacing; > > > > + unsigned int tx_power; > > > > + unsigned int rx_frequency; > > > > + unsigned int tx_frequency; > > > > + unsigned int band; > > > > + unsigned int i2s_mode; > > > > + unsigned int channel_number; > > > > + unsigned int number_of_bands; > > > > + unsigned int volume; > > > > + > > > > + const struct band_info *bands; > > > > + > > > > + /* RDS */ > > > > + bool rds_on; > > > > + struct delayed_work work; > > > > + > > > > + wait_queue_head_t read_queue; > > > > + struct mutex lock; /* for > > > serializing fm radio operations */ > > > > + struct completion busy; > > > > + > > > > + unsigned char *buffer; > > > > + unsigned int buf_size; > > > > + unsigned int rd_index; > > > > + unsigned int wr_index; > > > > + > > > > + /* Selected interrupts */ > > > > + u16 irq_flags; > > > > + u16 irq_received; > > > > +}; > > > > + > > > > +int wl1273_fm_write_cmd(struct wl1273_core > > *core, u8 > > > cmd, u16 param); > > > > +int wl1273_fm_write_data(struct wl1273_core > > *core, u8 > > > *data, u16 len); > > > > +int wl1273_fm_read_reg(struct wl1273_core *core, > > u8 > > > reg, u16 *value); > > > > + > > > > +int wl1273_fm_set_audio(struct wl1273_core > > *core, > > > unsigned int mode); > > > > +int wl1273_fm_set_volume(struct wl1273_core > > *core, > > > unsigned int volume); > > > > + > > > > +#endif /* ifndef RADIO_WL1273_H */ > > > > > > -- > > > To unsubscribe from this list: send the line > > "unsubscribe > > > linux-media" in > > > the body of a message to majordomo@xxxxxxxxxxxxxxx > > > More majordomo info at http://vger.kernel.org/majordomo-info.html > > > > > > > > > > > -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html