radio:iris:Adding support for FM debug commands
This patch adds new debug commands for FM driver
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 7a67c4b..23cf034 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -83,6 +83,9 @@
enum iris_region_t region;
struct hci_fm_dbg_param_rsp st_dbg_param;
struct hci_ev_srch_list_compl srch_st_result;
+ struct hci_fm_riva_poke riva_data_req;
+ struct hci_fm_ssbi_req ssbi_data_accs;
+ struct hci_fm_ssbi_peek ssbi_peek_reg;
};
static struct video_device *priv_videodev;
@@ -304,6 +307,69 @@
.minimum = 0,
.maximum = 1,
},
+ {
+ .id = V4L2_CID_PRIVATE_IRIS_SOFT_MUTE,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Soft Mute",
+ .minimum = 0,
+ .maximum = 1,
+ },
+ {
+ .id = V4L2_CID_PRIVATE_IRIS_RIVA_ACCS_ADDR,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Riva addr",
+ .minimum = 0,
+ .maximum = 0x31E0004,
+ },
+ {
+ .id = V4L2_CID_PRIVATE_IRIS_RIVA_ACCS_LEN,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Data len",
+ .minimum = 0,
+ .maximum = 0xFF,
+ },
+ {
+ .id = V4L2_CID_PRIVATE_IRIS_RIVA_PEEK,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Riva peek",
+ .minimum = 0,
+ .maximum = 1,
+ },
+ {
+ .id = V4L2_CID_PRIVATE_IRIS_RIVA_POKE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Riva poke",
+ .minimum = 0,
+ .maximum = 0x31E0004,
+ },
+ {
+ .id = V4L2_CID_PRIVATE_IRIS_SSBI_ACCS_ADDR,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Ssbi addr",
+ .minimum = 0,
+ .maximum = 0x37F,
+ },
+ {
+ .id = V4L2_CID_PRIVATE_IRIS_SSBI_PEEK,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Ssbi peek",
+ .minimum = 0,
+ .maximum = 0x37F,
+ },
+ {
+ .id = V4L2_CID_PRIVATE_IRIS_SSBI_POKE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "ssbi poke",
+ .minimum = 0x01,
+ .maximum = 0xFF,
+ },
+ {
+ .id = V4L2_CID_PRIVATE_IRIS_HLSI,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "set hlsi",
+ .minimum = 0,
+ .maximum = 2,
+ },
};
@@ -763,9 +829,9 @@
static int hci_peek_data_req(struct radio_hci_dev *hdev, unsigned long param)
{
__u16 opcode = 0;
- struct hci_fm_peek_req *peek_data = (struct hci_fm_peek_req *) param;
+ struct hci_fm_riva_data *peek_data = (struct hci_fm_riva_data *)param;
- opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+ opcode = hci_opcode_pack(HCI_OGF_FM_DIAGNOSTIC_CMD_REQ,
HCI_OCF_FM_PEEK_DATA);
return radio_hci_send_cmd(hdev, opcode, sizeof((*peek_data)),
peek_data);
@@ -774,7 +840,7 @@
static int hci_poke_data_req(struct radio_hci_dev *hdev, unsigned long param)
{
__u16 opcode = 0;
- struct hci_fm_poke_req *poke_data = (struct hci_fm_poke_req *) param;
+ struct hci_fm_riva_poke *poke_data = (struct hci_fm_riva_poke *) param;
opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
HCI_OCF_FM_POKE_DATA);
@@ -786,9 +852,9 @@
unsigned long param)
{
__u16 opcode = 0;
- struct hci_fm_ssbi_req *ssbi_peek = (struct hci_fm_ssbi_req *) param;
+ struct hci_fm_ssbi_peek *ssbi_peek = (struct hci_fm_ssbi_peek *) param;
- opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+ opcode = hci_opcode_pack(HCI_OGF_FM_DIAGNOSTIC_CMD_REQ,
HCI_OCF_FM_SSBI_PEEK_REG);
return radio_hci_send_cmd(hdev, opcode, sizeof((*ssbi_peek)),
ssbi_peek);
@@ -800,7 +866,7 @@
__u16 opcode = 0;
struct hci_fm_ssbi_req *ssbi_poke = (struct hci_fm_ssbi_req *) param;
- opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+ opcode = hci_opcode_pack(HCI_OGF_FM_DIAGNOSTIC_CMD_REQ,
HCI_OCF_FM_SSBI_POKE_REG);
return radio_hci_send_cmd(hdev, opcode, sizeof((*ssbi_poke)),
ssbi_poke);
@@ -1065,10 +1131,11 @@
return ret;
}
-int hci_peek_data(struct hci_fm_peek_req *arg, struct radio_hci_dev *hdev)
+static int hci_peek_data(struct hci_fm_riva_data *arg,
+ struct radio_hci_dev *hdev)
{
int ret = 0;
- struct hci_fm_peek_req *peek_data = arg;
+ struct hci_fm_riva_data *peek_data = arg;
ret = radio_hci_request(hdev, hci_peek_data_req, (unsigned
long)peek_data, RADIO_HCI_TIMEOUT);
@@ -1076,10 +1143,11 @@
return ret;
}
-int hci_poke_data(struct hci_fm_poke_req *arg, struct radio_hci_dev *hdev)
+static int hci_poke_data(struct hci_fm_riva_poke *arg,
+ struct radio_hci_dev *hdev)
{
int ret = 0;
- struct hci_fm_poke_req *poke_data = arg;
+ struct hci_fm_riva_poke *poke_data = arg;
ret = radio_hci_request(hdev, hci_poke_data_req, (unsigned
long)poke_data, RADIO_HCI_TIMEOUT);
@@ -1087,11 +1155,11 @@
return ret;
}
-int hci_ssbi_peek_reg(struct hci_fm_ssbi_req *arg,
+static int hci_ssbi_peek_reg(struct hci_fm_ssbi_peek *arg,
struct radio_hci_dev *hdev)
{
int ret = 0;
- struct hci_fm_ssbi_req *ssbi_peek_reg = arg;
+ struct hci_fm_ssbi_peek *ssbi_peek_reg = arg;
ret = radio_hci_request(hdev, hci_ssbi_peek_reg_req, (unsigned
long)ssbi_peek_reg, RADIO_HCI_TIMEOUT);
@@ -1099,7 +1167,8 @@
return ret;
}
-int hci_ssbi_poke_reg(struct hci_fm_ssbi_req *arg, struct radio_hci_dev *hdev)
+static int hci_ssbi_poke_reg(struct hci_fm_ssbi_req *arg,
+ struct radio_hci_dev *hdev)
{
int ret = 0;
struct hci_fm_ssbi_req *ssbi_poke_reg = arg;
@@ -1308,16 +1377,6 @@
radio_hci_req_complete(hdev, rsp->status);
}
-static void hci_cc_data_rd_rsp(struct radio_hci_dev *hdev, struct sk_buff *skb)
-{
- struct hci_fm_data_rd_rsp *rsp = (void *)skb->data;
-
- if (rsp->status)
- return;
-
- radio_hci_req_complete(hdev, rsp->status);
-}
-
static void hci_cc_feature_list_rsp(struct radio_hci_dev *hdev,
struct sk_buff *skb)
{
@@ -1346,6 +1405,59 @@
radio_hci_req_complete(hdev, radio->st_dbg_param.status);
}
+static void iris_q_evt_data(struct iris_device *radio,
+ char *data, int len, int event)
+{
+ struct kfifo *data_b = &radio->data_buf[event];
+ if (kfifo_in_locked(data_b, data, len, &radio->buf_lock[event]))
+ wake_up_interruptible(&radio->event_queue);
+}
+
+static void hci_cc_riva_peek_rsp(struct radio_hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct iris_device *radio = video_get_drvdata(video_get_dev());
+ struct hci_fm_af_list_rsp *rsp = (void *)skb->data;
+ int len;
+ char *data;
+
+ if (rsp->status)
+ return;
+ len = skb->data[RIVA_PEEK_LEN_OFSET] + RIVA_PEEK_PARAM;
+ data = kmalloc(len, GFP_ATOMIC);
+
+ if (!data) {
+ FMDERR("Memory allocation failed");
+ return;
+ }
+
+ 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);
+
+
+}
+static void hci_cc_ssbi_peek_rsp(struct radio_hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct iris_device *radio = video_get_drvdata(video_get_dev());
+ struct hci_fm_af_list_rsp *rsp = (void *)skb->data;
+ char *data;
+
+ if (rsp->status)
+ return;
+ data = kmalloc(SSBI_PEEK_LEN, GFP_ATOMIC);
+ if (!data) {
+ FMDERR("Memory allocation failed");
+ return;
+ }
+
+ 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);
+ kfree(data);
+}
+
static inline void hci_cmd_complete_event(struct radio_hci_dev *hdev,
struct sk_buff *skb)
{
@@ -1380,13 +1492,15 @@
case hci_recv_ctrl_cmd_op_pack(HCI_OCF_FM_EN_NOTCH_CTRL):
case hci_common_cmd_op_pack(HCI_OCF_FM_DEFAULT_DATA_WRITE):
case hci_common_cmd_op_pack(HCI_OCF_FM_RESET):
- case hci_status_param_op_pack(HCI_OCF_FM_READ_GRP_COUNTERS):
- case hci_diagnostic_cmd_op_pack(HCI_OCF_FM_POKE_DATA):
- case hci_diagnostic_cmd_op_pack(HCI_OCF_FM_SSBI_PEEK_REG):
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):
hci_cc_rsp(hdev, skb);
break;
+ case hci_diagnostic_cmd_op_pack(HCI_OCF_FM_SSBI_PEEK_REG):
+ hci_cc_ssbi_peek_rsp(hdev, skb);
+ break;
case hci_recv_ctrl_cmd_op_pack(HCI_OCF_FM_GET_SIGNAL_THRESHOLD):
hci_cc_sig_threshold_rsp(hdev, skb);
break;
@@ -1409,7 +1523,7 @@
case hci_common_cmd_op_pack(HCI_OCF_FM_DEFAULT_DATA_READ):
case hci_diagnostic_cmd_op_pack(HCI_OCF_FM_PEEK_DATA):
- hci_cc_data_rd_rsp(hdev, skb);
+ hci_cc_riva_peek_rsp(hdev, skb);
break;
case hci_common_cmd_op_pack(HCI_OCF_FM_GET_FEATURE_LIST):
@@ -1477,14 +1591,6 @@
iris_q_event(radio, IRIS_EVT_SEEK_COMPLETE);
}
-
-static void iris_q_evt_data(struct iris_device *radio,
- char *data, int len, int event)
-{
- struct kfifo *data_b = &radio->data_buf[event];
- if (kfifo_in_locked(data_b, data, len, &radio->buf_lock[event]))
- wake_up_interruptible(&radio->event_queue);
-}
static inline void hci_ev_srch_st_list_compl(struct radio_hci_dev *hdev,
struct sk_buff *skb)
{
@@ -1885,6 +1991,9 @@
case V4L2_CID_PRIVATE_IRIS_ANTENNA:
ctrl->value = radio->g_antenna;
break;
+ case V4L2_CID_PRIVATE_IRIS_SOFT_MUTE:
+ ctrl->value = radio->mute_mode.soft_mute;
+ break;
default:
retval = -EINVAL;
}
@@ -2026,6 +2135,45 @@
break;
case V4L2_CID_TUNE_POWER_LEVEL:
break;
+ case V4L2_CID_PRIVATE_IRIS_SOFT_MUTE:
+ radio->mute_mode.soft_mute = ctrl->value;
+ retval = hci_set_fm_mute_mode(
+ &radio->mute_mode,
+ radio->fm_hdev);
+ if (retval < 0)
+ FMDERR("Error while setting FM soft mute"" %d\n",
+ retval);
+ break;
+ case V4L2_CID_PRIVATE_IRIS_RIVA_ACCS_ADDR:
+ radio->riva_data_req.cmd_params.start_addr = ctrl->value;
+ break;
+ case V4L2_CID_PRIVATE_IRIS_RIVA_ACCS_LEN:
+ radio->riva_data_req.cmd_params.length = ctrl->value;
+ break;
+ case V4L2_CID_PRIVATE_IRIS_RIVA_POKE:
+ memcpy(radio->riva_data_req.data, (void *)ctrl->value,
+ radio->riva_data_req.cmd_params.length);
+ radio->riva_data_req.cmd_params.subopcode = RIVA_POKE_OPCODE;
+ retval = hci_poke_data(&radio->riva_data_req , radio->fm_hdev);
+ break;
+ case V4L2_CID_PRIVATE_IRIS_SSBI_ACCS_ADDR:
+ radio->ssbi_data_accs.start_addr = ctrl->value;
+ break;
+ case V4L2_CID_PRIVATE_IRIS_SSBI_POKE:
+ radio->ssbi_data_accs.data = ctrl->value;
+ retval = hci_ssbi_poke_reg(&radio->ssbi_data_accs ,
+ radio->fm_hdev);
+ break;
+ case V4L2_CID_PRIVATE_IRIS_RIVA_PEEK:
+ radio->riva_data_req.cmd_params.subopcode = RIVA_PEEK_OPCODE;
+ ctrl->value = hci_peek_data(&radio->riva_data_req.cmd_params ,
+ radio->fm_hdev);
+ break;
+ case V4L2_CID_PRIVATE_IRIS_SSBI_PEEK:
+ radio->ssbi_peek_reg.start_address = ctrl->value;
+ hci_ssbi_peek_reg(&radio->ssbi_peek_reg, radio->fm_hdev);
+ break;
+
default:
retval = -EINVAL;
}
@@ -2238,7 +2386,7 @@
int kfifo_alloc_rc = 0;
spin_lock_init(&radio->buf_lock[i]);
- if (i == IRIS_BUF_RAW_RDS)
+ if ((i == IRIS_BUF_RAW_RDS) | (i == IRIS_BUF_PEEK))
kfifo_alloc_rc = kfifo_alloc(&radio->data_buf[i],
rds_buf*3, GFP_KERNEL);
else
diff --git a/include/media/radio-iris.h b/include/media/radio-iris.h
index 040a5ab..04e3240 100644
--- a/include/media/radio-iris.h
+++ b/include/media/radio-iris.h
@@ -39,6 +39,8 @@
/* HCI data types */
#define RADIO_HCI_COMMAND_PKT 0x11
#define RADIO_HCI_EVENT_PKT 0x14
+/*HCI reponce packets*/
+#define MAX_RIVA_PEEK_RSP_SIZE 251
/* HCI timeouts */
#define RADIO_HCI_TIMEOUT (10000) /* 10 seconds */
@@ -239,23 +241,27 @@
struct hci_fm_def_data_wr_req {
struct hci_fm_def_data_rd_req data_rd;
- __u8 data[256];
+ __u8 data[256];
} __packed;
-struct hci_fm_peek_req {
+struct hci_fm_riva_data {
+ __u8 subopcode;
__u32 start_addr;
__u8 length;
} __packed;
-struct hci_fm_poke_req {
- struct hci_fm_peek_req peek_req;
- __u8 data[256];
+struct hci_fm_riva_poke {
+ struct hci_fm_riva_data cmd_params;
+ __u8 data[MAX_RIVA_PEEK_RSP_SIZE];
} __packed;
struct hci_fm_ssbi_req {
__u16 start_addr;
__u8 data;
} __packed;
+struct hci_fm_ssbi_peek {
+ __u16 start_address;
+} __packed;
/*HCI events*/
#define HCI_EV_TUNE_STATUS 0x01
@@ -451,12 +457,25 @@
V4L2_CID_PRIVATE_IRIS_ANTENNA,
V4L2_CID_PRIVATE_IRIS_RDSD_BUF,
V4L2_CID_PRIVATE_IRIS_PSALL,
+
/*v4l2 Tx controls*/
V4L2_CID_PRIVATE_IRIS_TX_SETPSREPEATCOUNT,
V4L2_CID_PRIVATE_IRIS_STOP_RDS_TX_PS_NAME,
V4L2_CID_PRIVATE_IRIS_STOP_RDS_TX_RT,
V4L2_CID_PRIVATE_IRIS_IOVERC,
V4L2_CID_PRIVATE_IRIS_INTDET,
+
+ /*Diagnostic commands*/
+ V4L2_CID_PRIVATE_IRIS_SOFT_MUTE,
+ V4L2_CID_PRIVATE_IRIS_RIVA_ACCS_ADDR,
+ V4L2_CID_PRIVATE_IRIS_RIVA_ACCS_LEN,
+ V4L2_CID_PRIVATE_IRIS_RIVA_PEEK,
+ V4L2_CID_PRIVATE_IRIS_RIVA_POKE,
+ 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,
};
enum iris_evt_t {
@@ -497,6 +516,8 @@
IRIS_BUF_PS_RDS,
IRIS_BUF_RAW_RDS,
IRIS_BUF_AF_LIST,
+ IRIS_BUF_PEEK,
+ IRIS_BUF_SSBI_PEEK,
IRIS_BUF_MAX
};
@@ -568,15 +589,20 @@
#define CTRL_ON (1)
#define CTRL_OFF (0)
+/*Diagnostic commands*/
+
+#define RIVA_PEEK_OPCODE 0x0D
+#define RIVA_POKE_OPCODE 0x0C
+
+#define PEEK_DATA_OFSET 0x1
+#define RIVA_PEEK_PARAM 0x6
+#define RIVA_PEEK_LEN_OFSET 0x6
+#define SSBI_PEEK_LEN 0x01
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,
struct radio_hci_dev *hdev);
int hci_fm_do_calibration(__u8 *arg, struct radio_hci_dev *hdev);
int hci_fm_do_calibration(__u8 *arg, struct radio_hci_dev *hdev);
-int hci_peek_data(struct hci_fm_peek_req *arg, struct radio_hci_dev *hdev);
-int hci_poke_data(struct hci_fm_poke_req *arg, struct radio_hci_dev *hdev);
-int hci_poke_data(struct hci_fm_poke_req *arg, struct radio_hci_dev *hdev);
-int hci_poke_data(struct hci_fm_poke_req *arg, struct radio_hci_dev *hdev);
#endif /* __RADIO_HCI_CORE_H */