radio-iris: Add ioctl commands to configure spur table

Provide interfaces to allow host to update the spur table
with spur frequencies specific to platforms.

CRs-Fixed: 352591
Change-Id: I139ac84a4a45578ebab63c26d7176666d47d3e2a
Signed-off-by: Anantha Krishnan <ananthk@codeaurora.org>
This commit is contained in:
Anantha Krishnan
2012-06-06 14:25:49 +05:30
committed by Stephen Boyd
parent fa647e88ae
commit 3e3687e226
2 changed files with 144 additions and 0 deletions

View File

@@ -88,6 +88,7 @@ struct iris_device {
unsigned char power_mode;
int search_on;
unsigned int tone_freq;
unsigned char spur_table_size;
unsigned char g_scan_time;
unsigned int g_antenna;
unsigned int g_rds_grp_proc_ps;
@@ -101,11 +102,13 @@ struct iris_device {
struct hci_fm_sig_threshold_rsp sig_th;
struct hci_fm_ch_det_threshold ch_det_threshold;
struct hci_fm_data_rd_rsp default_data;
struct hci_fm_spur_data spur_data;
};
static struct video_device *priv_videodev;
static int iris_do_calibration(struct iris_device *radio);
static int update_spur_table(struct iris_device *radio);
static struct v4l2_queryctrl iris_v4l2_queryctrl[] = {
{
.id = V4L2_CID_AUDIO_VOLUME,
@@ -2896,6 +2899,7 @@ static int iris_vidioc_s_ctrl(struct file *file, void *priv,
FMDERR("get frequency failed %d\n", retval);
break;
case FM_OFF:
radio->spur_table_size = 0;
switch (radio->mode) {
case FM_RECV:
retval = hci_cmd(HCI_FM_DISABLE_RECV_CMD,
@@ -3248,12 +3252,116 @@ static int iris_vidioc_s_ctrl(struct file *file, void *priv,
*/
retval = 0;
break;
case V4L2_CID_PRIVATE_SPUR_FREQ:
if (radio->spur_table_size >= MAX_SPUR_FREQ_LIMIT) {
FMDERR("%s: Spur Table Full!\n", __func__);
retval = -1;
} else
radio->spur_data.freq[radio->spur_table_size] =
ctrl->value;
break;
case V4L2_CID_PRIVATE_SPUR_FREQ_RMSSI:
if (radio->spur_table_size >= MAX_SPUR_FREQ_LIMIT) {
FMDERR("%s: Spur Table Full!\n", __func__);
retval = -1;
} else
radio->spur_data.rmssi[radio->spur_table_size] =
ctrl->value;
break;
case V4L2_CID_PRIVATE_SPUR_SELECTION:
if (radio->spur_table_size >= MAX_SPUR_FREQ_LIMIT) {
FMDERR("%s: Spur Table Full!\n", __func__);
retval = -1;
} else {
radio->spur_data.enable[radio->spur_table_size] =
ctrl->value;
radio->spur_table_size++;
}
break;
case V4L2_CID_PRIVATE_UPDATE_SPUR_TABLE:
update_spur_table(radio);
break;
default:
retval = -EINVAL;
}
return retval;
}
static int update_spur_table(struct iris_device *radio)
{
struct hci_fm_def_data_wr_req default_data;
int len = 0, index = 0, offset = 0, i = 0;
int retval = 0, temp = 0, cnt = 0;
memset(&default_data, 0, sizeof(default_data));
/* Pass the mode of SPUR_CLK */
default_data.mode = CKK_SPUR;
temp = radio->spur_table_size;
for (cnt = 0; cnt < (temp / 5); cnt++) {
offset = 0;
/*
* Program the spur entries in spur table in following order:
* Spur index
* Length of the spur data
* Spur Data:
* MSB of the spur frequency
* LSB of the spur frequency
* Enable/Disable the spur frequency
* RMSSI value of the spur frequency
*/
default_data.data[offset++] = ENTRY_0 + cnt;
for (i = 0; i < SPUR_ENTRIES_PER_ID; i++) {
default_data.data[offset++] = GET_FREQ(COMPUTE_SPUR(
radio->spur_data.freq[index]), 0);
default_data.data[offset++] = GET_FREQ(COMPUTE_SPUR(
radio->spur_data.freq[index]), 1);
default_data.data[offset++] =
radio->spur_data.enable[index];
default_data.data[offset++] =
radio->spur_data.rmssi[index];
index++;
}
len = (SPUR_ENTRIES_PER_ID * SPUR_DATA_SIZE);
default_data.length = (len + 1);
retval = hci_def_data_write(&default_data, radio->fm_hdev);
if (retval < 0) {
FMDBG("%s: Failed to configure entries for ID : %d\n",
__func__, default_data.data[0]);
return retval;
}
}
/* Compute balance SPUR frequencies to be programmed */
temp %= SPUR_ENTRIES_PER_ID;
if (temp > 0) {
offset = 0;
default_data.data[offset++] = (radio->spur_table_size / 5);
for (i = 0; i < temp; i++) {
default_data.data[offset++] = GET_FREQ(COMPUTE_SPUR(
radio->spur_data.freq[index]), 0);
default_data.data[offset++] = GET_FREQ(COMPUTE_SPUR(
radio->spur_data.freq[index]), 1);
default_data.data[offset++] =
radio->spur_data.enable[index];
default_data.data[offset++] =
radio->spur_data.rmssi[index];
index++;
}
len = (temp * SPUR_DATA_SIZE);
default_data.length = (len + 1);
retval = hci_def_data_write(&default_data, radio->fm_hdev);
if (retval < 0) {
FMDERR("%s: Failed to configure entries for ID : %d\n",
__func__, default_data.data[0]);
return retval;
}
}
return retval;
}
static int iris_vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *tuner)
{

View File

@@ -489,6 +489,29 @@ struct hci_fm_dbg_param_rsp {
__u8 in_det_out;
} __packed;
#define CLKSPURID_INDEX0 0
#define CLKSPURID_INDEX1 5
#define CLKSPURID_INDEX2 10
#define CLKSPURID_INDEX3 15
#define CLKSPURID_INDEX4 20
#define CLKSPURID_INDEX5 25
#define MAX_SPUR_FREQ_LIMIT 30
#define CKK_SPUR 0x3B
#define SPUR_DATA_SIZE 0x4
#define SPUR_ENTRIES_PER_ID 0x5
#define COMPUTE_SPUR(val) ((((val) - (76000)) / (50)))
#define GET_FREQ(val, bit) ((bit == 1) ? ((val) >> 8) : ((val) & 0xFF))
#define GET_SPUR_ENTRY_LEVEL(val) ((val) / (5))
struct hci_fm_spur_data {
__u32 freq[MAX_SPUR_FREQ_LIMIT];
__s8 rmssi[MAX_SPUR_FREQ_LIMIT];
__u8 enable[MAX_SPUR_FREQ_LIMIT];
} __packed;
/* HCI dev events */
#define RADIO_HCI_DEV_REG 1
#define RADIO_HCI_DEV_WRITE 2
@@ -572,6 +595,10 @@ enum v4l2_cid_private_iris_t {
V4L2_CID_PRIVATE_INTF_HIGH_THRESHOLD,
V4L2_CID_PRIVATE_SINR_THRESHOLD,
V4L2_CID_PRIVATE_SINR_SAMPLES,
V4L2_CID_PRIVATE_SPUR_FREQ,
V4L2_CID_PRIVATE_SPUR_FREQ_RMSSI,
V4L2_CID_PRIVATE_SPUR_SELECTION,
V4L2_CID_PRIVATE_UPDATE_SPUR_TABLE,
/*using private CIDs under userclass*/
V4L2_CID_PRIVATE_IRIS_READ_DEFAULT = 0x00980928,
@@ -680,6 +707,14 @@ enum search_t {
RDS_AF_JUMP,
};
enum spur_entry_levels {
ENTRY_0,
ENTRY_1,
ENTRY_2,
ENTRY_3,
ENTRY_4,
ENTRY_5,
};
/* Band limits */
#define REGION_US_EU_BAND_LOW 87500
@@ -774,6 +809,7 @@ struct hci_cc_do_calibration_rsp {
#define RDS_SYNC_INTR (1 << 1)
#define AUDIO_CTRL_INTR (1 << 2)
#define AF_JUMP_ENABLE (1 << 4)
int hci_def_data_read(struct hci_fm_def_data_rd_req *arg,
struct radio_hci_dev *hdev);
int hci_def_data_write(struct hci_fm_def_data_wr_req *arg,