Merge "media: dvb: mpq: Secure demux API updates"
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
index 2c9a0b8..4701f69 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
@@ -3455,11 +3455,15 @@
 	struct sdmx_buff_descr data_buff_desc[DMX_MAX_DECODER_BUFFER_NUM];
 	u32 data_buf_num = DMX_MAX_DECODER_BUFFER_NUM;
 	enum sdmx_buf_mode buf_mode;
+	enum sdmx_raw_out_format ts_out_format = SDMX_188_OUTPUT;
+	u32 filter_flags = 0;
 
 	feed = dvbdmx_feed->priv;
 
 	if (mpq_dmx_is_sec_feed(dvbdmx_feed)) {
 		feed->filter_type = SDMX_SECTION_FILTER;
+		if (dvbdmx_feed->feed.sec.check_crc)
+			filter_flags |= SDMX_FILTER_FLAG_VERIFY_SECTION_CRC;
 		MPQ_DVB_DBG_PRINT("%s: SDMX_SECTION_FILTER\n", __func__);
 	} else if (mpq_dmx_is_pcr_feed(dvbdmx_feed)) {
 		feed->filter_type = SDMX_PCR_FILTER;
@@ -3469,6 +3473,22 @@
 		MPQ_DVB_DBG_PRINT("%s: SDMX_SEPARATED_PES_FILTER\n", __func__);
 	} else if (mpq_dmx_is_rec_feed(dvbdmx_feed)) {
 		feed->filter_type = SDMX_RAW_FILTER;
+		switch (dvbdmx_feed->tsp_out_format) {
+		case (DMX_TSP_FORMAT_188):
+			ts_out_format = SDMX_188_OUTPUT;
+			break;
+		case (DMX_TSP_FORMAT_192_HEAD):
+			ts_out_format = SDMX_192_HEAD_OUTPUT;
+			break;
+		case (DMX_TSP_FORMAT_192_TAIL):
+			ts_out_format = SDMX_192_TAIL_OUTPUT;
+			break;
+		default:
+			MPQ_DVB_ERR_PRINT(
+				"%s: Unsupported TS output format %d\n",
+				__func__, dvbdmx_feed->tsp_out_format);
+			return -EINVAL;
+		}
 		MPQ_DVB_DBG_PRINT("%s: SDMX_RAW_FILTER\n", __func__);
 	} else {
 		feed->filter_type = SDMX_PES_FILTER;
@@ -3498,8 +3518,9 @@
 		feed->secondary_feed = 0;
 
 		MPQ_DVB_DBG_PRINT(
-			"%s: Adding new sdmx filter, pid %d\n",
-			__func__, dvbdmx_feed->pid);
+			"%s: Adding new sdmx filter, pid %d, flags=0x%X, ts_out_format=%d\n",
+			__func__, dvbdmx_feed->pid, filter_flags,
+			ts_out_format);
 
 		/* Meta-data initialization,
 		 * Recording filters do no need meta-data buffers.
@@ -3534,7 +3555,9 @@
 			buf_mode,
 			data_buf_num,
 			data_buff_desc,
-			&feed->sdmx_filter_handle);
+			&feed->sdmx_filter_handle,
+			ts_out_format,
+			filter_flags);
 		if (ret) {
 			MPQ_DVB_ERR_PRINT(
 				"%s: SDMX_add_filter failed. ret = %d\n",
@@ -3869,6 +3892,7 @@
 {
 	int ret;
 	struct sdmx_metadata_header header;
+	struct sdmx_pes_counters counters;
 	struct dmx_data_ready data_event;
 	struct dmx_data_ready pes_event;
 	struct dvb_demux_feed *feed = mpq_feed->dvb_demux_feed;
@@ -3906,22 +3930,26 @@
 
 	while (sts->metadata_fill_count) {
 		if (dvb_ringbuffer_avail(&mpq_feed->metadata_buf) <
-			sizeof(header)) {
+			(sizeof(header) + sizeof(counters))) {
 			MPQ_DVB_ERR_PRINT(
 				"%s: metadata_fill_count is %d but actual buffer has less than %d bytes\n",
 				__func__,
 				sts->metadata_fill_count,
-				sizeof(header));
+				sizeof(header) + sizeof(counters));
 			break;
 		}
 
-		dvb_ringbuffer_read(&mpq_feed->metadata_buf, (u8 *) &header,
+		dvb_ringbuffer_read(&mpq_feed->metadata_buf, (u8 *)&header,
 			sizeof(header));
 		MPQ_DVB_DBG_PRINT(
 			"%s: metadata header: start=%u, length=%u\n",
 			__func__, header.payload_start, header.payload_length);
 		sts->metadata_fill_count -= sizeof(header);
 
+		dvb_ringbuffer_read(&mpq_feed->metadata_buf, (u8 *)&counters,
+			sizeof(counters));
+		sts->metadata_fill_count -= sizeof(counters);
+
 		/* Notify new data in buffer */
 		data_event.status = DMX_OK;
 		data_event.data_length = header.payload_length;
@@ -3947,11 +3975,13 @@
 			pes_event.pes_end.pes_length_mismatch = 1;
 		if (sts->error_indicators & SDMX_FILTER_ERR_CONT_CNT_INVALID)
 			pes_event.pes_end.disc_indicator_set = 0;
-		/* TODO: report these when SDMX returns them */
+
 		pes_event.pes_end.stc = 0;
-		pes_event.pes_end.tei_counter = 0;
-		pes_event.pes_end.cont_err_counter = 0;
-		pes_event.pes_end.ts_packets_num = 0;
+		pes_event.pes_end.tei_counter = counters.transport_err_count;
+		pes_event.pes_end.cont_err_counter =
+			counters.continuity_err_count;
+		pes_event.pes_end.ts_packets_num =
+			counters.pes_ts_count;
 
 		ret = mpq_sdmx_check_ts_stall(mpq_demux, mpq_feed, sts, 0, 1);
 		if (ret) {
@@ -4024,6 +4054,7 @@
 	struct sdmx_filter_status *sts)
 {
 	struct sdmx_metadata_header header;
+	struct sdmx_pes_counters counters;
 	int pes_header_offset;
 	struct ts_packet_header *ts_header;
 	struct ts_adaptation_field *ts_adapt;
@@ -4060,7 +4091,7 @@
 		struct mpq_adapter_video_meta_data meta_data;
 
 		pes_cnt++;
-		/* Read header & metadata */
+		/* Read metadata header */
 		dvb_ringbuffer_read(&mpq_feed->metadata_buf, (u8 *)&header,
 			sizeof(header));
 		sts->metadata_fill_count -= sizeof(header);
@@ -4069,17 +4100,23 @@
 			__func__, header.payload_start, header.payload_length,
 			header.metadata_length);
 
-		/* Read actual metadata */
+		/* Read metadata - PES counters */
+		dvb_ringbuffer_read(&mpq_feed->metadata_buf, (u8 *)&counters,
+					sizeof(counters));
+		sts->metadata_fill_count -= sizeof(counters);
+
+		/* Read metadata - TS & PES headers */
 		if (header.metadata_length < MAX_SDMX_METADATA_LENGTH)
 			dvb_ringbuffer_read(&mpq_feed->metadata_buf,
 				metadata_buf,
-				header.metadata_length);
+				header.metadata_length - sizeof(counters));
 		else
 			MPQ_DVB_ERR_PRINT(
 				"%s: meta-data size=%d is too big for meta-data buffer=%d\n",
 				__func__, header.metadata_length,
 				MAX_SDMX_METADATA_LENGTH);
-		sts->metadata_fill_count -= header.metadata_length;
+		sts->metadata_fill_count -=
+			(header.metadata_length - sizeof(counters));
 
 		ts_header = (struct ts_packet_header *)&metadata_buf[0];
 		if (1 == ts_header->adaptation_field_control) {
@@ -4119,6 +4156,16 @@
 		}
 
 		spin_lock(&mpq_feed->video_info.video_buffer_lock);
+
+		mpq_feed->video_info.tei_errs =
+			counters.transport_err_count;
+		mpq_feed->video_info.continuity_errs =
+			counters.continuity_err_count;
+		mpq_feed->video_info.ts_packets_num =
+			counters.pes_ts_count;
+		mpq_feed->video_info.ts_dropped_bytes =
+			counters.drop_count * mpq_demux->demux.ts_packet_size;
+
 		sbuf = mpq_feed->video_info.video_buffer;
 		if (sbuf == NULL) {
 			MPQ_DVB_ERR_PRINT(
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_sdmx.c b/drivers/media/platform/msm/dvb/demux/mpq_sdmx.c
index 0f91930..946b055 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_sdmx.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_sdmx.c
@@ -110,6 +110,8 @@
 	enum sdmx_filter filter_type;
 	struct sdmx_buff_descr meta_data_buf;
 	enum sdmx_buf_mode buffer_mode;
+	enum sdmx_raw_out_format ts_out_format;
+	u32 flags;
 	u32 num_data_bufs;
 	struct sdmx_buff_descr data_bufs[];
 };
@@ -453,6 +455,9 @@
  * @num_data_bufs: number of data buffers (use 1 for a ring buffer)
  * @data_bufs: data buffers descriptors array
  * @filter_handle: returned filter handle
+ * @ts_out_format: output format for raw filters
+ * @flags: optional flags for filter
+ *	   (currently only clear section CRC verification is supported)
  *
  * Return error code
  */
@@ -463,7 +468,9 @@
 	enum sdmx_buf_mode d_buf_mode,
 	u32 num_data_bufs,
 	struct sdmx_buff_descr *data_bufs,
-	int *filter_handle)
+	int *filter_handle,
+	enum sdmx_raw_out_format ts_out_format,
+	u32 flags)
 {
 	int res, cmd_len, rsp_len;
 	struct sdmx_add_filt_req *cmd;
@@ -493,6 +500,8 @@
 	cmd->session_handle = session_handle;
 	cmd->pid = (u32)pid;
 	cmd->filter_type = filterype;
+	cmd->ts_out_format = ts_out_format;
+	cmd->flags = flags;
 	if (meta_data_buf != NULL)
 		memcpy(&(cmd->meta_data_buf), meta_data_buf,
 			sizeof(struct sdmx_buff_descr));
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_sdmx.h b/drivers/media/platform/msm/dvb/demux/mpq_sdmx.h
index ffb9046..0bd04e8 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_sdmx.h
+++ b/drivers/media/platform/msm/dvb/demux/mpq_sdmx.h
@@ -27,24 +27,26 @@
 #define SDMX_FILTER_ERR_INVALID_SCRAMBLE_BITS     BIT(3)
 #define SDMX_FILTER_ERR_KL_IND_NOT_SET            BIT(4)
 #define SDMX_FILTER_ERR_CAS_DECRYPT_ERROR         BIT(5)
-#define SDMX_FILTER_ERR_SEC_VERIF_GENERAL_FAIL    BIT(6)
-#define SDMX_FILTER_ERR_SEC_VERIF_CRC32_FAIL      BIT(7)
-#define SDMX_FILTER_ERR_SEC_INTERNAL_MALLOC_FAIL  BIT(8)
-#define SDMX_FILTER_ERR_SEC_LEN_INVALID           BIT(9)
-#define SDMX_FILTER_ERR_SEC_PUSI_PTR_INVALID      BIT(10)
-#define SDMX_FILTER_ERR_TS_SYNC_BYTE_INVALID      BIT(11)
-#define SDMX_FILTER_ERR_TS_TRANSPORT_ERR          BIT(12)
-#define SDMX_FILTER_ERR_CONT_CNT_INVALID          BIT(13)
-#define SDMX_FILTER_ERR_CONT_CNT_DUPLICATE        BIT(14)
-#define SDMX_FILTER_ERR_INVALID_PES_HDR           BIT(15)
-#define SDMX_FILTER_ERR_INVALID_PES_LEN           BIT(16)
-#define SDMX_FILTER_ERR_INVALID_PES_ENCRYPTION    BIT(17)
-#define SDMX_FILTER_ERR_SECURITY_FAULT            BIT(18)
-#define SDMX_FILTER_ERR_IN_NS_BUFFER              BIT(19)
+#define SDMX_FILTER_ERR_SEC_VERIF_CRC32_FAIL      BIT(6)
+#define SDMX_FILTER_ERR_SEC_INTERNAL_MALLOC_FAIL  BIT(7)
+#define SDMX_FILTER_ERR_SEC_LEN_INVALID           BIT(8)
+#define SDMX_FILTER_ERR_SEC_PUSI_PTR_INVALID      BIT(9)
+#define SDMX_FILTER_ERR_TS_SYNC_BYTE_INVALID      BIT(10)
+#define SDMX_FILTER_ERR_TS_TRANSPORT_ERR          BIT(11)
+#define SDMX_FILTER_ERR_CONT_CNT_INVALID          BIT(12)
+#define SDMX_FILTER_ERR_CONT_CNT_DUPLICATE        BIT(13)
+#define SDMX_FILTER_ERR_INVALID_PES_HDR           BIT(14)
+#define SDMX_FILTER_ERR_INVALID_PES_LEN           BIT(15)
+#define SDMX_FILTER_ERR_INVALID_PES_ENCRYPTION    BIT(16)
+#define SDMX_FILTER_ERR_SECURITY_FAULT            BIT(17)
+#define SDMX_FILTER_ERR_IN_NS_BUFFER              BIT(18)
 
 /* Filter-level status indicators */
 #define SDMX_FILTER_STATUS_EOS                    BIT(0)
 
+/* Filter-level flags */
+#define SDMX_FILTER_FLAG_VERIFY_SECTION_CRC	BIT(0)
+
 #define SDMX_INVALID_SESSION_HANDLE		(-1)
 #define SDMX_INVALID_FILTER_HANDLE		(-1)
 
@@ -103,6 +105,12 @@
 	SDMX_RAW_FILTER,		/* Recording */
 };
 
+enum sdmx_raw_out_format {
+	SDMX_188_OUTPUT,
+	SDMX_192_HEAD_OUTPUT,
+	SDMX_192_TAIL_OUTPUT
+};
+
 struct sdmx_session_dbg_counters {
 	/* Total number of TS-packets input to SDMX. */
 	u32 ts_pkt_in;
@@ -130,6 +138,20 @@
 	u32 ts_pkt_key_not_ready;
 };
 
+struct sdmx_pes_counters {
+	/* Number of TS packets with the TEI flag set */
+	u32 transport_err_count;
+
+	/* Number of TS packets with continuity counter errors */
+	u32 continuity_err_count;
+
+	/* Number of TS packets composing this PES frame */
+	u32 pes_ts_count;
+
+	/* Number of TS packets dropped due to full buffer */
+	u32 drop_count;
+};
+
 struct sdmx_buff_descr {
 	/* Physical address where buffer starts */
 	void *base_addr;
@@ -204,7 +226,7 @@
 int sdmx_add_filter(int session_handle, u16 pid, enum sdmx_filter filter_type,
 	struct sdmx_buff_descr *meta_data_buf, enum sdmx_buf_mode data_buf_mode,
 	u32 num_data_bufs, struct sdmx_buff_descr *data_bufs,
-	int *filter_handle);
+	int *filter_handle, enum sdmx_raw_out_format ts_out_format, u32 flags);
 
 int sdmx_remove_filter(int session_handle, int filter_handle);