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