[PATCH V7 5/5] WL12xx: Add support for FM new features

From: manjunatha_halli
Date: Mon May 21 2012 - 13:12:25 EST


From: Manjunatha Halli <x0130808@xxxxxx>

This patch adds below features to TI's V4l2 FM driver for Wilink
chipsets,

1) FM RX RDS AF turn ON/OFF
2) FM RX De-Emphasis mode set/get
3) FM TX Alternate Frequency set/get

Also this patch fixes below issues

1) FM audio volume gain setting
2) Default rssi level is set to 8 instead of 20
3) Enable FM RX AF support in driver
4) In wrap_around seek mode try for once

Acked-by: Hans Verkuil <hans.verkuil@xxxxxxxxx>
Signed-off-by: Manjunatha Halli <x0130808@xxxxxx>
---
drivers/media/radio/wl128x/fmdrv.h | 2 +-
drivers/media/radio/wl128x/fmdrv_common.c | 13 +++++++------
drivers/media/radio/wl128x/fmdrv_common.h | 10 +++++++---
drivers/media/radio/wl128x/fmdrv_rx.c | 11 +++++++++--
drivers/media/radio/wl128x/fmdrv_v4l2.c | 27 +++++++++++++++++++++++++++
5 files changed, 51 insertions(+), 12 deletions(-)

diff --git a/drivers/media/radio/wl128x/fmdrv.h b/drivers/media/radio/wl128x/fmdrv.h
index d84ad9d..e1a3c78 100644
--- a/drivers/media/radio/wl128x/fmdrv.h
+++ b/drivers/media/radio/wl128x/fmdrv.h
@@ -203,7 +203,7 @@ struct fmtx_data {
struct fmdev {
struct video_device *radio_dev; /* V4L2 video device pointer */
struct snd_card *card; /* Card which holds FM mixer controls */
- u16 asci_id;
+ u16 asic_id;
spinlock_t rds_buff_lock; /* To protect access to RDS buffer */
spinlock_t resp_skb_lock; /* To protect access to received SKB */

diff --git a/drivers/media/radio/wl128x/fmdrv_common.c b/drivers/media/radio/wl128x/fmdrv_common.c
index fcce61a..9ab7a63 100644
--- a/drivers/media/radio/wl128x/fmdrv_common.c
+++ b/drivers/media/radio/wl128x/fmdrv_common.c
@@ -596,7 +596,6 @@ static void fm_irq_handle_flag_getcmd_resp(struct fmdev *fmdev)
memcpy(&fmdev->irq_info.flag, skb->data, fm_evt_hdr->dlen);

fmdev->irq_info.flag = be16_to_cpu(fmdev->irq_info.flag);
- fmdbg("irq: flag register(0x%x)\n", fmdev->irq_info.flag);

/* Continue next function in interrupt handler table */
fm_irq_call_stage(fmdev, FM_HW_MAL_FUNC_IDX);
@@ -702,7 +701,7 @@ static void fm_rdsparse_swapbytes(struct fmdev *fmdev,
* in Dolphin they are in big endian, the parsing of the RDS data
* is chip dependent
*/
- if (fmdev->asci_id != 0x6350) {
+ if (fmdev->asic_id != 0x6350) {
rds_buff = &rds_format->data.groupdatabuff.buff[0];
while (index + 1 < FM_RX_RDS_INFO_FIELD_MAX) {
byte1 = rds_buff[index];
@@ -1353,11 +1352,13 @@ static int fm_power_up(struct fmdev *fmdev, u8 mode)
sizeof(asic_ver), &asic_ver, &resp_len))
goto rel;

+ fmdev->asic_id = be16_to_cpu(asic_id);
+
fmdbg("ASIC ID: 0x%x , ASIC Version: %d\n",
- be16_to_cpu(asic_id), be16_to_cpu(asic_ver));
+ fmdev->asic_id, be16_to_cpu(asic_ver));

sprintf(fw_name, "%s_%x.%d.bts", FM_FMC_FW_FILE_START,
- be16_to_cpu(asic_id), be16_to_cpu(asic_ver));
+ fmdev->asic_id, be16_to_cpu(asic_ver));

ret = fm_download_firmware(fmdev, fw_name);
if (ret < 0) {
@@ -1366,7 +1367,7 @@ static int fm_power_up(struct fmdev *fmdev, u8 mode)
}
sprintf(fw_name, "%s_%x.%d.bts", (mode == FM_MODE_RX) ?
FM_RX_FW_FILE_START : FM_TX_FW_FILE_START,
- be16_to_cpu(asic_id), be16_to_cpu(asic_ver));
+ fmdev->asic_id, be16_to_cpu(asic_ver));

ret = fm_download_firmware(fmdev, fw_name);
if (ret < 0) {
@@ -1576,7 +1577,7 @@ int fmc_prepare(struct fmdev *fmdev)
fmdev->rx.rds.flag = FM_RDS_DISABLE;
fmdev->rx.freq = FM_UNDEFINED_FREQ;
fmdev->rx.rds_mode = FM_RDS_SYSTEM_RDS;
- fmdev->rx.af_mode = FM_RX_RDS_AF_SWITCH_MODE_OFF;
+ fmdev->rx.af_mode = FM_RX_RDS_AF_SWITCH_MODE_ON;
fmdev->irq_info.retry = 0;

fmdev->tx_data.tx_frq = FM_UNDEFINED_FREQ;
diff --git a/drivers/media/radio/wl128x/fmdrv_common.h b/drivers/media/radio/wl128x/fmdrv_common.h
index 196ff7d..a57c662 100644
--- a/drivers/media/radio/wl128x/fmdrv_common.h
+++ b/drivers/media/radio/wl128x/fmdrv_common.h
@@ -201,8 +201,8 @@ struct fm_event_msg_hdr {
#define FM_UNDEFINED_FREQ 0xFFFFFFFF

/* Band types */
-#define FM_BAND_EUROPE_US 0
-#define FM_BAND_JAPAN 1
+#define FM_BAND_EUROPE_US 0
+#define FM_BAND_JAPAN 1

/* Seek directions */
#define FM_SEARCH_DIRECTION_DOWN 0
@@ -213,6 +213,10 @@ struct fm_event_msg_hdr {
#define FM_TUNER_PRESET_MODE 1
#define FM_TUNER_AUTONOMOUS_SEARCH_MODE 2
#define FM_TUNER_AF_JUMP_MODE 3
+#define FM_TUNER_PI_MATCH_MODE 4
+#define FM_TUNER_BULK_SEARCH_MODE 5
+#define FM_TUNER_WRAP_SEARCH_MODE 6
+#define FM_TUNER_WEATHER_MODE 7

/* Min and Max volume */
#define FM_RX_VOLUME_MIN 0
@@ -353,7 +357,7 @@ struct fm_event_msg_hdr {
* with this default values after loading RX firmware.
*/
#define FM_DEFAULT_RX_VOLUME 10
-#define FM_DEFAULT_RSSI_THRESHOLD 20
+#define FM_DEFAULT_RSSI_THRESHOLD 8

/* Range for TX power level in units for dB/uV */
#define FM_PWR_LVL_LOW 91
diff --git a/drivers/media/radio/wl128x/fmdrv_rx.c b/drivers/media/radio/wl128x/fmdrv_rx.c
index a806bda..aae4e6d 100644
--- a/drivers/media/radio/wl128x/fmdrv_rx.c
+++ b/drivers/media/radio/wl128x/fmdrv_rx.c
@@ -276,6 +276,10 @@ again:
/* Calculate frequency index to write */
next_frq = (fmdev->rx.freq -
fmdev->rx.region.bot_freq) / FM_FREQ_MUL;
+
+ /* If no valid chanel then report default frequency */
+ wrap_around = 0;
+
goto again;
}
} else {
@@ -636,8 +640,11 @@ int fm_rx_set_deemphasis_mode(struct fmdev *fmdev, u16 mode)
if (fmdev->curr_fmmode != FM_MODE_RX)
return -EPERM;

- if (mode != FM_RX_EMPHASIS_FILTER_50_USEC &&
- mode != FM_RX_EMPHASIS_FILTER_75_USEC) {
+ if (mode == V4L2_PREEMPHASIS_DISABLED)
+ return 0;
+
+ if (mode != V4L2_PREEMPHASIS_50_uS &&
+ mode != V4L2_PREEMPHASIS_75_uS) {
fmerr("Invalid rx de-emphasis mode (%d)\n", mode);
return -EINVAL;
}
diff --git a/drivers/media/radio/wl128x/fmdrv_v4l2.c b/drivers/media/radio/wl128x/fmdrv_v4l2.c
index 494faaf..22ffb39 100644
--- a/drivers/media/radio/wl128x/fmdrv_v4l2.c
+++ b/drivers/media/radio/wl128x/fmdrv_v4l2.c
@@ -258,6 +258,22 @@ static int fm_v4l2_s_ctrl(struct v4l2_ctrl *ctrl)
}
return 0;

+ case V4L2_CID_RDS_TX_AF_FREQ:
+ ret = fm_tx_set_af(fmdev, ctrl->val);
+ if (ret < 0) {
+ fmerr("Failed to set FM TX AF Frequency\n");
+ return ret;
+ }
+ return 0;
+
+ case V4L2_CID_RDS_AF_SWITCH: /* enable/disable FM RX RDS AF*/
+ fmdbg("V4L2_CID_RDS_AF_SWITCH:\n");
+ return fm_rx_set_af_switch(fmdev, (u8)ctrl->val);
+
+ case V4L2_CID_TUNE_DEEMPHASIS:
+ fmdbg("V4L2_CID_TUNE_DEEMPHASIS\n");
+ return fm_rx_set_deemphasis_mode(fmdev, (u8) ctrl->val);
+
default:
return -EINVAL;
}
@@ -320,6 +336,7 @@ static int fm_v4l2_vidioc_g_tuner(struct file *file, void *priv,
((fmdev->rx.rds.flag == FM_RDS_ENABLE) ? V4L2_TUNER_SUB_RDS : 0);
tuner->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS |
V4L2_TUNER_CAP_LOW;
+
tuner->audmode = (stereo_mono_mode ?
V4L2_TUNER_MODE_MONO : V4L2_TUNER_MODE_STEREO);

@@ -596,6 +613,9 @@ int fm_v4l2_init_video_device(struct fmdev *fmdev, int radio_nr)
v4l2_ctrl_new_std(&fmdev->ctrl_handler, &fm_ctrl_ops,
V4L2_CID_RDS_TX_RADIO_TEXT, 0, 0xff, 1, 0);

+ v4l2_ctrl_new_std(&fmdev->ctrl_handler, &fm_ctrl_ops,
+ V4L2_CID_RDS_TX_AF_FREQ, 76000, 180000, 1, 87500);
+
v4l2_ctrl_new_std_menu(&fmdev->ctrl_handler, &fm_ctrl_ops,
V4L2_CID_TUNE_PREEMPHASIS, V4L2_PREEMPHASIS_75_uS,
0, V4L2_PREEMPHASIS_75_uS);
@@ -611,6 +631,13 @@ int fm_v4l2_init_video_device(struct fmdev *fmdev, int radio_nr)
if (ctrl)
ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;

+ v4l2_ctrl_new_std(&fmdev->ctrl_handler, &fm_ctrl_ops,
+ V4L2_CID_RDS_AF_SWITCH, 0, 1, 1, 0);
+
+ v4l2_ctrl_new_std_menu(&fmdev->ctrl_handler, &fm_ctrl_ops,
+ V4L2_CID_TUNE_PREEMPHASIS, V4L2_PREEMPHASIS_75_uS,
+ 0, V4L2_PREEMPHASIS_75_uS);
+
return 0;
}

--
1.7.4.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/