[media] V4L2: WL1273 FM Radio: TI WL1273 FM radio driver

This module implements V4L2 controls for the Texas Instruments
WL1273 FM Radio and handles the communication with the chip.

Signed-off-by: Matti J. Aaltonen <matti.j.aaltonen@nokia.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
diff --git a/drivers/media/radio/radio-wl1273.c b/drivers/media/radio/radio-wl1273.c
index 7ecc8e6..9e177dc 100644
--- a/drivers/media/radio/radio-wl1273.c
+++ b/drivers/media/radio/radio-wl1273.c
@@ -1,7 +1,7 @@
 /*
  * Driver for the Texas Instruments WL1273 FM radio.
  *
- * Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2011 Nokia Corporation
  * Author: Matti J. Aaltonen <matti.j.aaltonen@nokia.com>
  *
  * This program is free software; you can redistribute it and/or
@@ -104,58 +104,6 @@
 module_param(rds_buf, uint, 0);
 MODULE_PARM_DESC(rds_buf, "Number of RDS buffer entries. Default = 100");
 
-static int wl1273_fm_read_reg(struct wl1273_core *core, u8 reg, u16 *value)
-{
-	struct i2c_client *client = core->client;
-	u8 b[2];
-	int r;
-
-	r = i2c_smbus_read_i2c_block_data(client, reg, sizeof(b), 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;
-}
-
-static int wl1273_fm_write_cmd(struct wl1273_core *core, u8 cmd, u16 param)
-{
-	struct i2c_client *client = core->client;
-	u8 buf[] = { (param >> 8) & 0xff, param & 0xff };
-	int r;
-
-	r = i2c_smbus_write_i2c_block_data(client, cmd, sizeof(buf), buf);
-	if (r) {
-		dev_err(&client->dev, "%s: Cmd: %d fails.\n", __func__, cmd);
-		return r;
-	}
-
-	return 0;
-}
-
-static int wl1273_fm_write_data(struct wl1273_core *core, u8 *data, u16 len)
-{
-	struct i2c_client *client = core->client;
-	struct i2c_msg msg;
-	int r;
-
-	msg.addr = client->addr;
-	msg.flags = 0;
-	msg.buf = data;
-	msg.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;
-}
-
 static int wl1273_fm_write_fw(struct wl1273_core *core,
 			      __u8 *fw, int len)
 {
@@ -188,94 +136,6 @@
 	return r;
 }
 
-/**
- * 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.
- */
-static 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;
-}
-
-/**
- * wl1273_fm_set_volume() -	Set volume.
- * @core:			A pointer to the device struct.
- * @volume:			The new volume value.
- */
-static 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;
-}
-
 #define WL1273_FIFO_HAS_DATA(status)	(1 << 5 & status)
 #define WL1273_RDS_CORRECTABLE_ERROR	(1 << 3)
 #define WL1273_RDS_UNCORRECTABLE_ERROR	(1 << 4)
@@ -306,7 +166,7 @@
 	if (core->mode != WL1273_MODE_RX)
 		return 0;
 
-	r = wl1273_fm_read_reg(core, WL1273_RDS_SYNC_GET, &val);
+	r = core->read(core, WL1273_RDS_SYNC_GET, &val);
 	if (r)
 		return r;
 
@@ -374,7 +234,7 @@
 	u16 flags;
 	int r;
 
-	r = wl1273_fm_read_reg(core, WL1273_FLAG_GET, &flags);
+	r = core->read(core, WL1273_FLAG_GET, &flags);
 	if (r)
 		goto out;
 
@@ -398,7 +258,7 @@
 	if (flags & WL1273_LEV_EVENT) {
 		u16 level;
 
-		r = wl1273_fm_read_reg(core, WL1273_RSSI_LVL_GET, &level);
+		r = core->read(core, WL1273_RSSI_LVL_GET, &level);
 		if (r)
 			goto out;
 
@@ -439,8 +299,8 @@
 		dev_dbg(radio->dev, "IRQ: FR:\n");
 
 		if (core->mode == WL1273_MODE_RX) {
-			r = wl1273_fm_write_cmd(core, WL1273_TUNER_MODE_SET,
-						TUNER_MODE_STOP_SEARCH);
+			r = core->write(core, WL1273_TUNER_MODE_SET,
+					TUNER_MODE_STOP_SEARCH);
 			if (r) {
 				dev_err(radio->dev,
 					"%s: TUNER_MODE_SET fails: %d\n",
@@ -448,7 +308,7 @@
 				goto out;
 			}
 
-			r = wl1273_fm_read_reg(core, WL1273_FREQ_SET, &freq);
+			r = core->read(core, WL1273_FREQ_SET, &freq);
 			if (r)
 				goto out;
 
@@ -467,7 +327,7 @@
 			dev_dbg(radio->dev, "%dkHz\n", radio->rx_frequency);
 
 		} else {
-			r = wl1273_fm_read_reg(core, WL1273_CHANL_SET, &freq);
+			r = core->read(core, WL1273_CHANL_SET, &freq);
 			if (r)
 				goto out;
 
@@ -477,8 +337,7 @@
 	}
 
 out:
-	wl1273_fm_write_cmd(core, WL1273_INT_MASK_SET,
-			    radio->irq_flags);
+	core->write(core, WL1273_INT_MASK_SET, radio->irq_flags);
 	complete(&radio->busy);
 
 	return IRQ_HANDLED;
@@ -512,7 +371,7 @@
 	dev_dbg(radio->dev, "%s: freq: %d kHz\n", __func__, freq);
 
 	/* Set the current tx channel */
-	r = wl1273_fm_write_cmd(core, WL1273_CHANL_SET, freq / 10);
+	r = core->write(core, WL1273_CHANL_SET, freq / 10);
 	if (r)
 		return r;
 
@@ -526,7 +385,7 @@
 	dev_dbg(radio->dev, "WL1273_CHANL_SET: %d\n", r);
 
 	/* Enable the output power */
-	r = wl1273_fm_write_cmd(core, WL1273_POWER_ENB_SET, 1);
+	r = core->write(core, WL1273_POWER_ENB_SET, 1);
 	if (r)
 		return r;
 
@@ -566,20 +425,20 @@
 
 	dev_dbg(radio->dev, "%s: %dkHz\n", __func__, freq);
 
-	wl1273_fm_write_cmd(core, WL1273_INT_MASK_SET, radio->irq_flags);
+	core->write(core, WL1273_INT_MASK_SET, radio->irq_flags);
 
 	if (radio->band == WL1273_BAND_JAPAN)
 		f = (freq - WL1273_BAND_JAPAN_LOW) / 50;
 	else
 		f = (freq - WL1273_BAND_OTHER_LOW) / 50;
 
-	r = wl1273_fm_write_cmd(core, WL1273_FREQ_SET, f);
+	r = core->write(core, WL1273_FREQ_SET, f);
 	if (r) {
 		dev_err(radio->dev, "FREQ_SET fails\n");
 		goto err;
 	}
 
-	r = wl1273_fm_write_cmd(core, WL1273_TUNER_MODE_SET, TUNER_MODE_PRESET);
+	r = core->write(core, WL1273_TUNER_MODE_SET, TUNER_MODE_PRESET);
 	if (r) {
 		dev_err(radio->dev, "TUNER_MODE_SET fails\n");
 		goto err;
@@ -609,7 +468,7 @@
 	int r;
 
 	if (core->mode == WL1273_MODE_RX) {
-		r = wl1273_fm_read_reg(core, WL1273_FREQ_SET, &f);
+		r = core->read(core, WL1273_FREQ_SET, &f);
 		if (r)
 			return r;
 
@@ -619,7 +478,7 @@
 		else
 			freq = WL1273_BAND_OTHER_LOW + 50 * f;
 	} else {
-		r = wl1273_fm_read_reg(core, WL1273_CHANL_SET, &f);
+		r = core->read(core, WL1273_CHANL_SET, &f);
 		if (r)
 			return r;
 
@@ -670,7 +529,7 @@
 	}
 
 	/* ignore possible error here */
-	wl1273_fm_write_cmd(core, WL1273_RESET, 0);
+	core->write(core, WL1273_RESET, 0);
 
 	dev_dbg(dev, "%s - download OK, r: %d\n", __func__, r);
 out:
@@ -683,14 +542,14 @@
 	struct wl1273_core *core = radio->core;
 
 	if (core->mode == WL1273_MODE_RX) {
-		int r = wl1273_fm_write_cmd(core, WL1273_POWER_SET,
+		int r = core->write(core, WL1273_POWER_SET,
 				    WL1273_POWER_SET_OFF);
 		if (r)
 			dev_err(radio->dev, "%s: POWER_SET fails: %d\n",
 				__func__, r);
 	} else if (core->mode == WL1273_MODE_TX) {
-		int r = wl1273_fm_write_cmd(core, WL1273_PUPD_SET,
-					    WL1273_PUPD_SET_OFF);
+		int r = core->write(core, WL1273_PUPD_SET,
+				    WL1273_PUPD_SET_OFF);
 		if (r)
 			dev_err(radio->dev,
 				"%s: PUPD_SET fails: %d\n", __func__, r);
@@ -725,11 +584,11 @@
 			val |= WL1273_POWER_SET_RDS;
 
 		/* If this fails try again */
-		r = wl1273_fm_write_cmd(core, WL1273_POWER_SET, val);
+		r = core->write(core, WL1273_POWER_SET, val);
 		if (r) {
 			msleep(100);
 
-			r = wl1273_fm_write_cmd(core, WL1273_POWER_SET, val);
+			r = core->write(core, WL1273_POWER_SET, val);
 			if (r) {
 				dev_err(dev, "%s: POWER_SET fails\n", __func__);
 				goto fail;
@@ -742,11 +601,10 @@
 
 	} else if (new_mode == WL1273_MODE_TX) {
 		/* If this fails try again once */
-		r = wl1273_fm_write_cmd(core, WL1273_PUPD_SET,
-					WL1273_PUPD_SET_ON);
+		r = core->write(core, WL1273_PUPD_SET, WL1273_PUPD_SET_ON);
 		if (r) {
 			msleep(100);
-			r = wl1273_fm_write_cmd(core, WL1273_PUPD_SET,
+			r = core->write(core, WL1273_PUPD_SET,
 					WL1273_PUPD_SET_ON);
 			if (r) {
 				dev_err(dev, "%s: PUPD_SET fails\n", __func__);
@@ -755,9 +613,9 @@
 		}
 
 		if (radio->rds_on)
-			r = wl1273_fm_write_cmd(core, WL1273_RDS_DATA_ENB, 1);
+			r = core->write(core, WL1273_RDS_DATA_ENB, 1);
 		else
-			r = wl1273_fm_write_cmd(core, WL1273_RDS_DATA_ENB, 0);
+			r = core->write(core, WL1273_RDS_DATA_ENB, 0);
 	} else {
 		dev_warn(dev, "%s: Illegal mode.\n", __func__);
 	}
@@ -777,14 +635,14 @@
 			if (radio->rds_on)
 				val |= WL1273_POWER_SET_RDS;
 
-			r = wl1273_fm_write_cmd(core, WL1273_POWER_SET, val);
+			r = core->write(core, WL1273_POWER_SET, val);
 			if (r) {
 				dev_err(dev, "%s: POWER_SET fails\n", __func__);
 				goto fail;
 			}
 		} else if (new_mode == WL1273_MODE_TX) {
-			r = wl1273_fm_write_cmd(core, WL1273_PUPD_SET,
-						WL1273_PUPD_SET_ON);
+			r = core->write(core, WL1273_PUPD_SET,
+					WL1273_PUPD_SET_ON);
 			if (r) {
 				dev_err(dev, "%s: PUPD_SET fails\n", __func__);
 				goto fail;
@@ -808,10 +666,10 @@
 
 	/* Cannot go from OFF to SUSPENDED */
 	if (core->mode == WL1273_MODE_RX)
-		r = wl1273_fm_write_cmd(core, WL1273_POWER_SET,
+		r = core->write(core, WL1273_POWER_SET,
 				WL1273_POWER_SET_RETENTION);
 	else if (core->mode == WL1273_MODE_TX)
-		r = wl1273_fm_write_cmd(core, WL1273_PUPD_SET,
+		r = core->write(core, WL1273_PUPD_SET,
 				WL1273_PUPD_SET_RETENTION);
 	else
 		r = -EINVAL;
@@ -852,8 +710,7 @@
 		}
 
 		core->mode = mode;
-		r = wl1273_fm_write_cmd(core, WL1273_INT_MASK_SET,
-					radio->irq_flags);
+		r = core->write(core, WL1273_INT_MASK_SET, radio->irq_flags);
 		if (r) {
 			dev_err(dev, "INT_MASK_SET fails.\n");
 			goto out;
@@ -951,22 +808,21 @@
 	INIT_COMPLETION(radio->busy);
 	dev_dbg(radio->dev, "%s: BUSY\n", __func__);
 
-	r = wl1273_fm_write_cmd(core, WL1273_INT_MASK_SET, radio->irq_flags);
+	r = core->write(core, WL1273_INT_MASK_SET, radio->irq_flags);
 	if (r)
 		goto out;
 
 	dev_dbg(radio->dev, "%s\n", __func__);
 
-	r = wl1273_fm_write_cmd(core, WL1273_SEARCH_LVL_SET, level);
+	r = core->write(core, WL1273_SEARCH_LVL_SET, level);
 	if (r)
 		goto out;
 
-	r = wl1273_fm_write_cmd(core, WL1273_SEARCH_DIR_SET, dir);
+	r = core->write(core, WL1273_SEARCH_DIR_SET, dir);
 	if (r)
 		goto out;
 
-	r = wl1273_fm_write_cmd(core, WL1273_TUNER_MODE_SET,
-				TUNER_MODE_AUTO_SEEK);
+	r = core->write(core, WL1273_TUNER_MODE_SET, TUNER_MODE_AUTO_SEEK);
 	if (r)
 		goto out;
 
@@ -994,8 +850,7 @@
 	INIT_COMPLETION(radio->busy);
 	dev_dbg(radio->dev, "%s: BUSY\n", __func__);
 
-	r = wl1273_fm_write_cmd(core, WL1273_TUNER_MODE_SET,
-				TUNER_MODE_AUTO_SEEK);
+	r = core->write(core, WL1273_TUNER_MODE_SET, TUNER_MODE_AUTO_SEEK);
 	if (r)
 		goto out;
 
@@ -1020,7 +875,7 @@
 	    core->mode == WL1273_MODE_SUSPENDED)
 		return -EPERM;
 
-	r = wl1273_fm_read_reg(core, WL1273_READ_FMANT_TUNE_VALUE, &val);
+	r = core->read(core, WL1273_READ_FMANT_TUNE_VALUE, &val);
 	if (r) {
 		dev_err(dev, "%s: read error: %d\n", __func__, r);
 		goto out;
@@ -1066,7 +921,7 @@
 		goto out;
 	}
 
-	r = wl1273_fm_write_cmd(core, WL1273_PREMPH_SET, em);
+	r = core->write(core, WL1273_PREMPH_SET, em);
 	if (r)
 		goto out;
 
@@ -1086,7 +941,7 @@
 	if (radio->rds_on)
 		return 0;
 
-	r = wl1273_fm_write_cmd(core, WL1273_POWER_SET,
+	r = core->write(core, WL1273_POWER_SET,
 			WL1273_POWER_SET_FM | WL1273_POWER_SET_RDS);
 	if (r)
 		goto out;
@@ -1108,7 +963,7 @@
 
 	radio->irq_flags &= ~WL1273_RDS_EVENT;
 
-	r = wl1273_fm_write_cmd(core, WL1273_INT_MASK_SET, radio->irq_flags);
+	r = core->write(core, WL1273_INT_MASK_SET, radio->irq_flags);
 	if (r)
 		goto out;
 
@@ -1120,7 +975,7 @@
 
 	dev_dbg(radio->dev, "%s\n", __func__);
 
-	r = wl1273_fm_write_cmd(core, WL1273_POWER_SET, WL1273_POWER_SET_FM);
+	r = core->write(core, WL1273_POWER_SET, WL1273_POWER_SET_FM);
 	if (r)
 		goto out;
 
@@ -1143,14 +998,14 @@
 		return -EPERM;
 
 	if (new_mode == WL1273_RDS_RESET) {
-		r = wl1273_fm_write_cmd(core, WL1273_RDS_CNTRL_SET, 1);
+		r = core->write(core, WL1273_RDS_CNTRL_SET, 1);
 		return r;
 	}
 
 	if (core->mode == WL1273_MODE_TX && new_mode == WL1273_RDS_OFF) {
-		r = wl1273_fm_write_cmd(core, WL1273_RDS_DATA_ENB, 0);
+		r = core->write(core, WL1273_RDS_DATA_ENB, 0);
 	} else if (core->mode == WL1273_MODE_TX && new_mode == WL1273_RDS_ON) {
-		r = wl1273_fm_write_cmd(core, WL1273_RDS_DATA_ENB, 1);
+		r = core->write(core, WL1273_RDS_DATA_ENB, 1);
 	} else if (core->mode == WL1273_MODE_RX && new_mode == WL1273_RDS_OFF) {
 		r = wl1273_fm_rds_off(radio);
 	} else if (core->mode == WL1273_MODE_RX && new_mode == WL1273_RDS_ON) {
@@ -1171,12 +1026,13 @@
 				    size_t count, loff_t *ppos)
 {
 	struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
+	struct wl1273_core *core = radio->core;
 	u16 val;
 	int r;
 
 	dev_dbg(radio->dev, "%s\n", __func__);
 
-	if (radio->core->mode != WL1273_MODE_TX)
+	if (core->mode != WL1273_MODE_TX)
 		return count;
 
 	if (radio->rds_users == 0) {
@@ -1184,7 +1040,7 @@
 		return 0;
 	}
 
-	if (mutex_lock_interruptible(&radio->core->lock))
+	if (mutex_lock_interruptible(&core->lock))
 		return -EINTR;
 	/*
 	 * Multiple processes can open the device, but only
@@ -1202,7 +1058,7 @@
 	else
 		val = count;
 
-	wl1273_fm_write_cmd(radio->core, WL1273_RDS_CONFIG_DATA_SET, val);
+	core->write(core, WL1273_RDS_CONFIG_DATA_SET, val);
 
 	if (copy_from_user(radio->write_buf + 1, buf, val)) {
 		r = -EFAULT;
@@ -1213,11 +1069,11 @@
 	dev_dbg(radio->dev, "From user: \"%s\"\n", radio->write_buf);
 
 	radio->write_buf[0] = WL1273_RDS_DATA_SET;
-	wl1273_fm_write_data(radio->core, radio->write_buf, val + 1);
+	core->write_data(core, radio->write_buf, val + 1);
 
 	r = val;
 out:
-	mutex_unlock(&radio->core->lock);
+	mutex_unlock(&core->lock);
 
 	return r;
 }
@@ -1263,8 +1119,8 @@
 
 		radio->irq_flags |= WL1273_RDS_EVENT;
 
-		r = wl1273_fm_write_cmd(core, WL1273_INT_MASK_SET,
-					radio->irq_flags);
+		r = core->write(core, WL1273_INT_MASK_SET,
+				radio->irq_flags);
 		if (r) {
 			mutex_unlock(&core->lock);
 			goto out;
@@ -1295,9 +1151,9 @@
 			radio->irq_flags &= ~WL1273_RDS_EVENT;
 
 			if (core->mode == WL1273_MODE_RX) {
-				r = wl1273_fm_write_cmd(core,
-							WL1273_INT_MASK_SET,
-							radio->irq_flags);
+				r = core->write(core,
+						WL1273_INT_MASK_SET,
+						radio->irq_flags);
 				if (r) {
 					mutex_unlock(&core->lock);
 					goto out;
@@ -1324,7 +1180,7 @@
 
 	dev_dbg(radio->dev, "%s\n", __func__);
 
-	if (radio->core->mode != WL1273_MODE_RX)
+	if (core->mode != WL1273_MODE_RX)
 		return 0;
 
 	if (radio->rds_users == 0) {
@@ -1345,7 +1201,7 @@
 	}
 	radio->owner = file;
 
-	r = wl1273_fm_read_reg(core, WL1273_RDS_SYNC_GET, &val);
+	r = core->read(core, WL1273_RDS_SYNC_GET, &val);
 	if (r) {
 		dev_err(radio->dev, "%s: Get RDS_SYNC fails.\n", __func__);
 		goto out;
@@ -1466,23 +1322,24 @@
  */
 static int wl1273_fm_set_tx_power(struct wl1273_device *radio, u16 power)
 {
+	struct wl1273_core *core = radio->core;
 	int r;
 
-	if (radio->core->mode == WL1273_MODE_OFF ||
-	    radio->core->mode == WL1273_MODE_SUSPENDED)
+	if (core->mode == WL1273_MODE_OFF ||
+	    core->mode == WL1273_MODE_SUSPENDED)
 		return -EPERM;
 
-	mutex_lock(&radio->core->lock);
+	mutex_lock(&core->lock);
 
 	/* Convert the dBuV value to chip presentation */
-	r = wl1273_fm_write_cmd(radio->core, WL1273_POWER_LEV_SET, 122 - power);
+	r = core->write(core, WL1273_POWER_LEV_SET, 122 - power);
 	if (r)
 		goto out;
 
 	radio->tx_power = power;
 
 out:
-	mutex_unlock(&radio->core->lock);
+	mutex_unlock(&core->lock);
 	return r;
 }
 
@@ -1493,23 +1350,24 @@
 static int wl1273_fm_tx_set_spacing(struct wl1273_device *radio,
 				    unsigned int spacing)
 {
+	struct wl1273_core *core = radio->core;
 	int r;
 
 	if (spacing == 0) {
-		r = wl1273_fm_write_cmd(radio->core, WL1273_SCAN_SPACING_SET,
-					WL1273_SPACING_100kHz);
+		r = core->write(core, WL1273_SCAN_SPACING_SET,
+				WL1273_SPACING_100kHz);
 		radio->spacing = 100;
 	} else if (spacing - 50000 < 25000) {
-		r = wl1273_fm_write_cmd(radio->core, WL1273_SCAN_SPACING_SET,
-					WL1273_SPACING_50kHz);
+		r = core->write(core, WL1273_SCAN_SPACING_SET,
+				WL1273_SPACING_50kHz);
 		radio->spacing = 50;
 	} else if (spacing - 100000 < 50000) {
-		r = wl1273_fm_write_cmd(radio->core, WL1273_SCAN_SPACING_SET,
-					WL1273_SPACING_100kHz);
+		r = core->write(core, WL1273_SCAN_SPACING_SET,
+				WL1273_SPACING_100kHz);
 		radio->spacing = 100;
 	} else {
-		r = wl1273_fm_write_cmd(radio->core, WL1273_SCAN_SPACING_SET,
-					WL1273_SPACING_200kHz);
+		r = core->write(core, WL1273_SCAN_SPACING_SET,
+				WL1273_SPACING_200kHz);
 		radio->spacing = 200;
 	}
 
@@ -1567,17 +1425,17 @@
 			return -EINTR;
 
 		if (core->mode == WL1273_MODE_RX && ctrl->val)
-			r = wl1273_fm_write_cmd(core,
-						WL1273_MUTE_STATUS_SET,
-						WL1273_MUTE_HARD_LEFT |
-						WL1273_MUTE_HARD_RIGHT);
+			r = core->write(core,
+					WL1273_MUTE_STATUS_SET,
+					WL1273_MUTE_HARD_LEFT |
+					WL1273_MUTE_HARD_RIGHT);
 		else if (core->mode == WL1273_MODE_RX)
-			r = wl1273_fm_write_cmd(core,
-						WL1273_MUTE_STATUS_SET, 0x0);
+			r = core->write(core,
+					WL1273_MUTE_STATUS_SET, 0x0);
 		else if (core->mode == WL1273_MODE_TX && ctrl->val)
-			r = wl1273_fm_write_cmd(core, WL1273_MUTE, 1);
+			r = core->write(core, WL1273_MUTE, 1);
 		else if (core->mode == WL1273_MODE_TX)
-			r = wl1273_fm_write_cmd(core, WL1273_MUTE, 0);
+			r = core->write(core, WL1273_MUTE, 0);
 
 		mutex_unlock(&core->lock);
 		break;
@@ -1672,7 +1530,7 @@
 	if (mutex_lock_interruptible(&core->lock))
 		return -EINTR;
 
-	r = wl1273_fm_read_reg(core, WL1273_STEREO_GET, &val);
+	r = core->read(core, WL1273_STEREO_GET, &val);
 	if (r)
 		goto out;
 
@@ -1681,7 +1539,7 @@
 	else
 		tuner->rxsubchans = V4L2_TUNER_SUB_MONO;
 
-	r = wl1273_fm_read_reg(core, WL1273_RSSI_LVL_GET, &val);
+	r = core->read(core, WL1273_RSSI_LVL_GET, &val);
 	if (r)
 		goto out;
 
@@ -1690,7 +1548,7 @@
 
 	tuner->afc = 0;
 
-	r = wl1273_fm_read_reg(core, WL1273_RDS_SYNC_GET, &val);
+	r = core->read(core, WL1273_RDS_SYNC_GET, &val);
 	if (r)
 		goto out;
 
@@ -1736,8 +1594,7 @@
 		dev_warn(radio->dev, "%s: RDS fails: %d\n", __func__, r);
 
 	if (tuner->audmode == V4L2_TUNER_MODE_MONO) {
-		r = wl1273_fm_write_cmd(core, WL1273_MOST_MODE_SET,
-					WL1273_RX_MONO);
+		r = core->write(core, WL1273_MOST_MODE_SET, WL1273_RX_MONO);
 		if (r < 0) {
 			dev_warn(radio->dev, "%s: MOST_MODE fails: %d\n",
 				 __func__, r);
@@ -1745,8 +1602,7 @@
 		}
 		radio->stereo = false;
 	} else if (tuner->audmode == V4L2_TUNER_MODE_STEREO) {
-		r = wl1273_fm_write_cmd(core, WL1273_MOST_MODE_SET,
-					WL1273_RX_STEREO);
+		r = core->write(core, WL1273_MOST_MODE_SET, WL1273_RX_STEREO);
 		if (r < 0) {
 			dev_warn(radio->dev, "%s: MOST_MODE fails: %d\n",
 				 __func__, r);
@@ -1885,10 +1741,10 @@
 		r = wl1273_fm_set_rds(radio, WL1273_RDS_OFF);
 
 	if (modulator->txsubchans & V4L2_TUNER_SUB_MONO)
-		r = wl1273_fm_write_cmd(core, WL1273_MONO_SET, WL1273_TX_MONO);
+		r = core->write(core, WL1273_MONO_SET, WL1273_TX_MONO);
 	else
-		r = wl1273_fm_write_cmd(core, WL1273_MONO_SET,
-					WL1273_RX_STEREO);
+		r = core->write(core, WL1273_MONO_SET,
+				WL1273_RX_STEREO);
 	if (r < 0)
 		dev_warn(radio->dev, WL1273_FM_DRIVER_NAME
 			 "MONO_SET fails: %d\n", r);
@@ -1923,7 +1779,7 @@
 	if (mutex_lock_interruptible(&core->lock))
 		return -EINTR;
 
-	r = wl1273_fm_read_reg(core, WL1273_MONO_SET, &val);
+	r = core->read(core, WL1273_MONO_SET, &val);
 	if (r)
 		goto out;
 
@@ -1960,38 +1816,38 @@
 		return 0;
 	}
 
-	r = wl1273_fm_read_reg(core, WL1273_ASIC_ID_GET, &val);
+	r = core->read(core, WL1273_ASIC_ID_GET, &val);
 	if (r)
 		dev_err(dev, "%s: Get ASIC_ID fails.\n", __func__);
 	else
 		dev_info(dev, "ASIC_ID: 0x%04x\n", val);
 
-	r = wl1273_fm_read_reg(core, WL1273_ASIC_VER_GET, &val);
+	r = core->read(core, WL1273_ASIC_VER_GET, &val);
 	if (r)
 		dev_err(dev, "%s: Get ASIC_VER fails.\n", __func__);
 	else
 		dev_info(dev, "ASIC Version: 0x%04x\n", val);
 
-	r = wl1273_fm_read_reg(core, WL1273_FIRM_VER_GET, &val);
+	r = core->read(core, WL1273_FIRM_VER_GET, &val);
 	if (r)
 		dev_err(dev, "%s: Get FIRM_VER fails.\n", __func__);
 	else
 		dev_info(dev, "FW version: %d(0x%04x)\n", val, val);
 
-	r = wl1273_fm_read_reg(core, WL1273_BAND_SET, &val);
+	r = core->read(core, WL1273_BAND_SET, &val);
 	if (r)
 		dev_err(dev, "%s: Get BAND fails.\n", __func__);
 	else
 		dev_info(dev, "BAND: %d\n", val);
 
 	if (core->mode == WL1273_MODE_TX) {
-		r = wl1273_fm_read_reg(core, WL1273_PUPD_SET, &val);
+		r = core->read(core, WL1273_PUPD_SET, &val);
 		if (r)
 			dev_err(dev, "%s: Get PUPD fails.\n", __func__);
 		else
 			dev_info(dev, "PUPD: 0x%04x\n", val);
 
-		r = wl1273_fm_read_reg(core, WL1273_CHANL_SET, &val);
+		r = core->read(core, WL1273_CHANL_SET, &val);
 		if (r)
 			dev_err(dev, "%s: Get CHANL fails.\n", __func__);
 		else
@@ -1999,13 +1855,13 @@
 	} else if (core->mode == WL1273_MODE_RX) {
 		int bf = radio->rangelow;
 
-		r = wl1273_fm_read_reg(core, WL1273_FREQ_SET, &val);
+		r = core->read(core, WL1273_FREQ_SET, &val);
 		if (r)
 			dev_err(dev, "%s: Get FREQ fails.\n", __func__);
 		else
 			dev_info(dev, "RX Frequency: %dkHz\n", bf + val*50);
 
-		r = wl1273_fm_read_reg(core, WL1273_MOST_MODE_SET, &val);
+		r = core->read(core, WL1273_MOST_MODE_SET, &val);
 		if (r)
 			dev_err(dev, "%s: Get MOST_MODE fails.\n",
 				__func__);
@@ -2016,7 +1872,7 @@
 		else
 			dev_info(dev, "MOST_MODE: Unexpected value: %d\n", val);
 
-		r = wl1273_fm_read_reg(core, WL1273_MOST_BLEND_SET, &val);
+		r = core->read(core, WL1273_MOST_BLEND_SET, &val);
 		if (r)
 			dev_err(dev, "%s: Get MOST_BLEND fails.\n", __func__);
 		else if (val == 0)
@@ -2027,7 +1883,7 @@
 		else
 			dev_info(dev, "MOST_BLEND: Unexpected val: %d\n", val);
 
-		r = wl1273_fm_read_reg(core, WL1273_STEREO_GET, &val);
+		r = core->read(core, WL1273_STEREO_GET, &val);
 		if (r)
 			dev_err(dev, "%s: Get STEREO fails.\n", __func__);
 		else if (val == 0)
@@ -2037,25 +1893,25 @@
 		else
 			dev_info(dev, "STEREO: Unexpected value: %d\n", val);
 
-		r = wl1273_fm_read_reg(core, WL1273_RSSI_LVL_GET, &val);
+		r = core->read(core, WL1273_RSSI_LVL_GET, &val);
 		if (r)
 			dev_err(dev, "%s: Get RSSI_LVL fails.\n", __func__);
 		else
 			dev_info(dev, "RX signal strength: %d\n", (s16) val);
 
-		r = wl1273_fm_read_reg(core, WL1273_POWER_SET, &val);
+		r = core->read(core, WL1273_POWER_SET, &val);
 		if (r)
 			dev_err(dev, "%s: Get POWER fails.\n", __func__);
 		else
 			dev_info(dev, "POWER: 0x%04x\n", val);
 
-		r = wl1273_fm_read_reg(core, WL1273_INT_MASK_SET, &val);
+		r = core->read(core, WL1273_INT_MASK_SET, &val);
 		if (r)
 			dev_err(dev, "%s: Get INT_MASK fails.\n", __func__);
 		else
 			dev_info(dev, "INT_MASK: 0x%04x\n", val);
 
-		r = wl1273_fm_read_reg(core, WL1273_RDS_SYNC_GET, &val);
+		r = core->read(core, WL1273_RDS_SYNC_GET, &val);
 		if (r)
 			dev_err(dev, "%s: Get RDS_SYNC fails.\n",
 				__func__);
@@ -2067,14 +1923,14 @@
 		else
 			dev_info(dev, "RDS_SYNC: Unexpected value: %d\n", val);
 
-		r = wl1273_fm_read_reg(core, WL1273_I2S_MODE_CONFIG_SET, &val);
+		r = core->read(core, WL1273_I2S_MODE_CONFIG_SET, &val);
 		if (r)
 			dev_err(dev, "%s: Get I2S_MODE_CONFIG fails.\n",
 				__func__);
 		else
 			dev_info(dev, "I2S_MODE_CONFIG: 0x%04x\n", val);
 
-		r = wl1273_fm_read_reg(core, WL1273_VOLUME_SET, &val);
+		r = core->read(core, WL1273_VOLUME_SET, &val);
 		if (r)
 			dev_err(dev, "%s: Get VOLUME fails.\n", __func__);
 		else
@@ -2184,10 +2040,6 @@
 	radio->stereo = true;
 	radio->bus_type = "I2C";
 
-	radio->core->write = wl1273_fm_write_cmd;
-	radio->core->set_audio = wl1273_fm_set_audio;
-	radio->core->set_volume = wl1273_fm_set_volume;
-
 	if (radio->core->pdata->request_resources) {
 		r = radio->core->pdata->request_resources(radio->core->client);
 		if (r) {