radio: iris: Added support for FTM commands
This patch adds support for RDS group counters,
Set HLsi and Set notch filter FTM commands.
Signed-off-by: Srinivasa Rao Uppala <uppalas@codeaurora.org>
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index f57f8ef..b5aa668 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -293,7 +293,6 @@
.maximum = 1,
.default_value = 0,
},
-
{
.id = V4L2_CID_PRIVATE_IRIS_TX_SETPSREPEATCOUNT,
.type = V4L2_CTRL_TYPE_INTEGER,
@@ -326,7 +325,7 @@
.id = V4L2_CID_PRIVATE_IRIS_RIVA_ACCS_ADDR,
.type = V4L2_CTRL_TYPE_BOOLEAN,
.name = "Riva addr",
- .minimum = 0,
+ .minimum = 0x3180000,
.maximum = 0x31E0004,
},
{
@@ -347,14 +346,14 @@
.id = V4L2_CID_PRIVATE_IRIS_RIVA_POKE,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Riva poke",
- .minimum = 0,
+ .minimum = 0x3180000,
.maximum = 0x31E0004,
},
{
.id = V4L2_CID_PRIVATE_IRIS_SSBI_ACCS_ADDR,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Ssbi addr",
- .minimum = 0,
+ .minimum = 0x280,
.maximum = 0x37F,
},
{
@@ -378,6 +377,20 @@
.minimum = 0,
.maximum = 2,
},
+ {
+ .id = V4L2_CID_PRIVATE_IRIS_RDS_GRP_COUNTERS,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "RDS grp",
+ .minimum = 0,
+ .maximum = 1,
+ },
+ {
+ .id = V4L2_CID_PRIVATE_IRIS_SET_NOTCH_FILTER,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Notch filter",
+ .minimum = 0,
+ .maximum = 2,
+ },
};
@@ -865,6 +878,20 @@
def_data_wr);
}
+static int hci_set_notch_filter_req(struct radio_hci_dev *hdev,
+ unsigned long param)
+{
+ __u16 opcode = 0;
+ __u8 notch_filter_val = param;
+
+ opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+ HCI_OCF_FM_EN_NOTCH_CTRL);
+ return radio_hci_send_cmd(hdev, opcode, sizeof(notch_filter_val),
+ ¬ch_filter_val);
+}
+
+
+
static int hci_fm_reset_req(struct radio_hci_dev *hdev, unsigned long param)
{
__u16 opcode = 0;
@@ -902,8 +929,7 @@
__u16 opcode = 0;
__u8 reset_counters = param;
-
- opcode = hci_opcode_pack(HCI_OGF_FM_COMMON_CTRL_CMD_REQ,
+ opcode = hci_opcode_pack(HCI_OGF_FM_STATUS_PARAMETERS_CMD_REQ,
HCI_OCF_FM_READ_GRP_COUNTERS);
return radio_hci_send_cmd(hdev, opcode, sizeof(reset_counters),
&reset_counters);
@@ -1215,17 +1241,26 @@
return ret;
}
-int hci_read_grp_counters(__u8 *arg, struct radio_hci_dev *hdev)
+static int hci_read_grp_counters(__u8 *arg, struct radio_hci_dev *hdev)
{
int ret = 0;
__u8 reset_counters = *arg;
-
ret = radio_hci_request(hdev, hci_read_grp_counters_req,
reset_counters, RADIO_HCI_TIMEOUT);
return ret;
}
+static int hci_set_notch_filter(__u8 *arg, struct radio_hci_dev *hdev)
+{
+ int ret = 0;
+ __u8 notch_filter = *arg;
+ ret = radio_hci_request(hdev, hci_set_notch_filter_req,
+ notch_filter, RADIO_HCI_TIMEOUT);
+
+ return ret;
+}
+
static int hci_peek_data(struct hci_fm_riva_data *arg,
struct radio_hci_dev *hdev)
{
@@ -1386,7 +1421,6 @@
if (status)
return;
-
radio_hci_req_complete(hdev, status);
}
@@ -1541,11 +1575,11 @@
struct sk_buff *skb)
{
struct iris_device *radio = video_get_drvdata(video_get_dev());
- struct hci_fm_af_list_rsp *rsp = (void *)skb->data;
+ __u8 status = *((__u8 *) skb->data);
int len;
char *data;
- if (rsp->status)
+ if (status)
return;
len = skb->data[RIVA_PEEK_LEN_OFSET] + RIVA_PEEK_PARAM;
data = kmalloc(len, GFP_ATOMIC);
@@ -1557,7 +1591,7 @@
memcpy(data, &skb->data[PEEK_DATA_OFSET], len);
iris_q_evt_data(radio, data, len, IRIS_BUF_PEEK);
- radio_hci_req_complete(hdev, rsp->status);
+ radio_hci_req_complete(hdev, status);
}
@@ -1565,10 +1599,10 @@
struct sk_buff *skb)
{
struct iris_device *radio = video_get_drvdata(video_get_dev());
- struct hci_fm_af_list_rsp *rsp = (void *)skb->data;
+ __u8 status = *((__u8 *) skb->data);
char *data;
- if (rsp->status)
+ if (status)
return;
data = kmalloc(SSBI_PEEK_LEN, GFP_ATOMIC);
if (!data) {
@@ -1578,10 +1612,30 @@
data[0] = skb->data[PEEK_DATA_OFSET];
iris_q_evt_data(radio, data, SSBI_PEEK_LEN, IRIS_BUF_SSBI_PEEK);
- radio_hci_req_complete(hdev, rsp->status);
+ radio_hci_req_complete(hdev, status);
kfree(data);
}
+static void hci_cc_rds_grp_cntrs_rsp(struct radio_hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct iris_device *radio = video_get_drvdata(video_get_dev());
+ __u8 status = *((__u8 *) skb->data);
+ char *data;
+ if (status)
+ return;
+ data = kmalloc(RDS_GRP_CNTR_LEN, GFP_ATOMIC);
+ if (!data) {
+ FMDERR("memory allocation failed");
+ return;
+ }
+ memcpy(data, &skb->data[1], RDS_GRP_CNTR_LEN);
+ iris_q_evt_data(radio, data, RDS_GRP_CNTR_LEN, IRIS_BUF_RDS_CNTRS);
+ radio_hci_req_complete(hdev, status);
+ kfree(data);
+
+}
+
static inline void hci_cmd_complete_event(struct radio_hci_dev *hdev,
struct sk_buff *skb)
{
@@ -1622,7 +1676,6 @@
case hci_common_cmd_op_pack(HCI_OCF_FM_RESET):
case hci_diagnostic_cmd_op_pack(HCI_OCF_FM_SSBI_POKE_REG):
case hci_diagnostic_cmd_op_pack(HCI_OCF_FM_POKE_DATA):
- case hci_status_param_op_pack(HCI_OCF_FM_READ_GRP_COUNTERS):
case hci_diagnostic_cmd_op_pack(HCI_FM_SET_INTERNAL_TONE_GENRATOR):
hci_cc_rsp(hdev, skb);
break;
@@ -1662,11 +1715,14 @@
case hci_diagnostic_cmd_op_pack(HCI_OCF_FM_STATION_DBG_PARAM):
hci_cc_dbg_param_rsp(hdev, skb);
break;
-
case hci_trans_ctrl_cmd_op_pack(HCI_OCF_FM_SET_TRANS_CONF_REQ):
hci_cc_fm_trans_set_conf_rsp(hdev, skb);
break;
+ case hci_status_param_op_pack(HCI_OCF_FM_READ_GRP_COUNTERS):
+ hci_cc_rds_grp_cntrs_rsp(hdev, skb);
+ break;
+
default:
FMDERR("%s opcode 0x%x", hdev->name, opcode);
break;
@@ -1690,7 +1746,6 @@
struct iris_device *radio = video_get_drvdata(video_get_dev());
len = sizeof(struct hci_fm_station_rsp);
-
memcpy(&radio->fm_st_rsp.station_rsp, skb_pull(skb, len), len);
iris_q_event(radio, IRIS_EVT_TUNE_SUCC);
@@ -1699,7 +1754,6 @@
if (i >= IRIS_BUF_RT_RDS)
kfifo_reset(&radio->data_buf[i]);
}
-
if (radio->fm_st_rsp.station_rsp.rssi)
iris_q_event(radio, IRIS_EVT_ABOVE_TH);
else
@@ -2239,7 +2293,7 @@
unsigned long arg = 0;
switch (ctrl->id) {
- case VL2_CID_PRIVATE_IRIS_TX_TONE:
+ case V4L2_CID_PRIVATE_IRIS_TX_TONE:
radio->tone_freq = ctrl->value;
retval = radio_hci_request(radio->fm_hdev,
hci_fm_tone_generator, arg,
@@ -2514,6 +2568,24 @@
radio->ssbi_peek_reg.start_address = ctrl->value;
hci_ssbi_peek_reg(&radio->ssbi_peek_reg, radio->fm_hdev);
break;
+ case V4L2_CID_PRIVATE_IRIS_RDS_GRP_COUNTERS:
+ temp_val = ctrl->value;
+ hci_read_grp_counters(&temp_val, radio->fm_hdev);
+ break;
+ case V4L2_CID_PRIVATE_IRIS_HLSI:
+ retval = hci_cmd(HCI_FM_GET_RECV_CONF_CMD,
+ radio->fm_hdev);
+ if (retval)
+ break;
+ radio->recv_conf.hlsi = ctrl->value;
+ retval = hci_set_fm_recv_conf(
+ &radio->recv_conf,
+ radio->fm_hdev);
+ break;
+ case V4L2_CID_PRIVATE_IRIS_SET_NOTCH_FILTER:
+ temp_val = ctrl->value;
+ retval = hci_set_notch_filter(&temp_val, radio->fm_hdev);
+ break;
default:
retval = -EINVAL;
diff --git a/include/media/radio-iris.h b/include/media/radio-iris.h
index 8dd1ee6..fa4ac8e 100644
--- a/include/media/radio-iris.h
+++ b/include/media/radio-iris.h
@@ -512,7 +512,7 @@
V4L2_CID_PRIVATE_IRIS_LP_MODE,
V4L2_CID_PRIVATE_IRIS_ANTENNA,
V4L2_CID_PRIVATE_IRIS_RDSD_BUF,
- V4L2_CID_PRIVATE_IRIS_PSALL,
+ V4L2_CID_PRIVATE_IRIS_PSALL, /*0x8000014*/
/*v4l2 Tx controls*/
V4L2_CID_PRIVATE_IRIS_TX_SETPSREPEATCOUNT,
@@ -520,6 +520,10 @@
V4L2_CID_PRIVATE_IRIS_STOP_RDS_TX_RT,
V4L2_CID_PRIVATE_IRIS_IOVERC,
V4L2_CID_PRIVATE_IRIS_INTDET,
+ V4L2_CID_PRIVATE_IRIS_MPX_DCC,
+ V4L2_CID_PRIVATE_IRIS_AF_JUMP,
+ V4L2_CID_PRIVATE_IRIS_RSSI_DELTA,
+ V4L2_CID_PRIVATE_IRIS_HLSI, /*0x800001d*/
/*Diagnostic commands*/
V4L2_CID_PRIVATE_IRIS_SOFT_MUTE,
@@ -530,8 +534,9 @@
V4L2_CID_PRIVATE_IRIS_SSBI_ACCS_ADDR,
V4L2_CID_PRIVATE_IRIS_SSBI_PEEK,
V4L2_CID_PRIVATE_IRIS_SSBI_POKE,
- V4L2_CID_PRIVATE_IRIS_HLSI,
- VL2_CID_PRIVATE_IRIS_TX_TONE,
+ V4L2_CID_PRIVATE_IRIS_TX_TONE,
+ V4L2_CID_PRIVATE_IRIS_RDS_GRP_COUNTERS,
+ V4L2_CID_PRIVATE_IRIS_SET_NOTCH_FILTER,/*0x8000028*/
};
@@ -597,6 +602,7 @@
IRIS_BUF_AF_LIST,
IRIS_BUF_PEEK,
IRIS_BUF_SSBI_PEEK,
+ IRIS_BUF_RDS_CNTRS,
IRIS_BUF_MAX
};
@@ -663,6 +669,7 @@
#define BYTES_PER_BLOCK (3)
#define MAX_PS_LENGTH (96)
#define MAX_RT_LENGTH (64)
+#define RDS_GRP_CNTR_LEN (36)
/* Search direction */
#define SRCH_DIR_UP (0)