/**
 * Attach to TSIF driver and start TSIF operation.
 *
 * @mpq_demux: the mpq_demux we are working on.
 *
 * Return	error code.
 */
static int mpq_tsif_dmx_start(struct mpq_demux *mpq_demux)
{
	int ret = 0;
	int tsif;
	struct tsif_driver_info *tsif_driver;

	MPQ_DVB_DBG_PRINT("%s executed\n", __func__);

	/* determine the TSIF we are reading from */
	if (mpq_demux->source == DMX_SOURCE_FRONT0) {
		tsif = 0;
	} else if (mpq_demux->source == DMX_SOURCE_FRONT1) {
		tsif = 1;
	} else {
		/* invalid source */
		MPQ_DVB_ERR_PRINT(
			"%s: invalid input source (%d)\n",
			__func__,
			mpq_demux->source);

		return -EINVAL;
	}

	if (mutex_lock_interruptible(&mpq_dmx_tsif_info.tsif[tsif].mutex))
		return -ERESTARTSYS;

	if (mpq_dmx_tsif_info.tsif[tsif].ref_count == 0) {
		tsif_driver = &(mpq_dmx_tsif_info.tsif[tsif].tsif_driver);

		/* Attach to TSIF driver */
		tsif_driver->tsif_handler =
			tsif_attach(tsif, mpq_tsif_callback, (void *)tsif);
		if (IS_ERR_OR_NULL(tsif_driver->tsif_handler)) {
			tsif_driver->tsif_handler = NULL;
			mutex_unlock(&mpq_dmx_tsif_info.tsif[tsif].mutex);
			MPQ_DVB_DBG_PRINT("%s: tsif_attach(%d) failed\n",
					__func__, tsif);
			return -ENODEV;
		}

		ret = tsif_set_clk_inverse(tsif_driver->tsif_handler,
					clock_inv);
		if (ret < 0) {
			MPQ_DVB_ERR_PRINT(
				"%s: tsif_set_clk_inverse (%d) failed\n",
				__func__, clock_inv);
		}

		/* Set TSIF driver mode */
		ret = tsif_set_mode(tsif_driver->tsif_handler, tsif_mode);
		if (ret < 0) {
			MPQ_DVB_ERR_PRINT("%s: tsif_set_mode (%d) failed\n",
				__func__, tsif_mode);
		}

		/* Set TSIF buffer configuration */
		ret = tsif_set_buf_config(tsif_driver->tsif_handler,
						threshold,
						DMX_TSIF_CHUNKS_IN_BUF);
		if (ret < 0) {
			MPQ_DVB_ERR_PRINT(
				"%s: tsif_set_buf_config (%d, %d) failed\n",
				__func__, threshold,
				DMX_TSIF_CHUNKS_IN_BUF);
			MPQ_DVB_ERR_PRINT("Using default TSIF driver values\n");
		}

		/* Start TSIF driver */
		ret = tsif_start(tsif_driver->tsif_handler);
		if (ret < 0) {
			mutex_unlock(&mpq_dmx_tsif_info.tsif[tsif].mutex);
			MPQ_DVB_ERR_PRINT("%s: tsif_start failed\n", __func__);
			return ret;
		}

		/*
		 * Get data buffer information from TSIF driver
		 * (must be called after tsif_start)
		 */
		tsif_get_info(tsif_driver->tsif_handler,
				&(tsif_driver->data_buffer),
				&(tsif_driver->buffer_size));

		/* save pointer to the mpq_demux we are working on */
		mpq_dmx_tsif_info.tsif[tsif].mpq_demux = mpq_demux;
	}
	mpq_dmx_tsif_info.tsif[tsif].ref_count++;

	mutex_unlock(&mpq_dmx_tsif_info.tsif[tsif].mutex);

	return ret;
}
static int mpq_tsif_dmx_start(struct mpq_demux *mpq_demux)
{
	int ret = 0;
	int tsif;
	struct tsif_driver_info *tsif_driver;

	MPQ_DVB_DBG_PRINT("%s executed\n", __func__);

	
	if (mpq_demux->source == DMX_SOURCE_FRONT0) {
		tsif = 0;
	} else if (mpq_demux->source == DMX_SOURCE_FRONT1) {
		tsif = 1;
	} else {
		
		MPQ_DVB_ERR_PRINT(
			"%s: invalid input source (%d)\n",
			__func__,
			mpq_demux->source);

		return -EINVAL;
	}

	if (mutex_lock_interruptible(&mpq_dmx_tsif_info.tsif[tsif].mutex))
		return -ERESTARTSYS;

	if (mpq_dmx_tsif_info.tsif[tsif].ref_count == 0) {
		tsif_driver = &(mpq_dmx_tsif_info.tsif[tsif].tsif_driver);

		
		tsif_driver->tsif_handler =
			tsif_attach(tsif, mpq_tsif_callback, (void *)tsif);
		if (IS_ERR_OR_NULL(tsif_driver->tsif_handler)) {
			tsif_driver->tsif_handler = NULL;
			mutex_unlock(&mpq_dmx_tsif_info.tsif[tsif].mutex);
			MPQ_DVB_DBG_PRINT("%s: tsif_attach(%d) failed\n",
					__func__, tsif);
			return -ENODEV;
		}

		ret = tsif_set_clk_inverse(tsif_driver->tsif_handler,
					clock_inv);
		if (ret < 0) {
			MPQ_DVB_ERR_PRINT(
				"%s: tsif_set_clk_inverse (%d) failed\n",
				__func__, clock_inv);
		}

		
		ret = tsif_set_mode(tsif_driver->tsif_handler, tsif_mode);
		if (ret < 0) {
			MPQ_DVB_ERR_PRINT("%s: tsif_set_mode (%d) failed\n",
				__func__, tsif_mode);
		}

		
		ret = tsif_set_buf_config(tsif_driver->tsif_handler,
						threshold,
						DMX_TSIF_CHUNKS_IN_BUF);
		if (ret < 0) {
			MPQ_DVB_ERR_PRINT(
				"%s: tsif_set_buf_config (%d, %d) failed\n",
				__func__, threshold,
				DMX_TSIF_CHUNKS_IN_BUF);
			MPQ_DVB_ERR_PRINT("Using default TSIF driver values\n");
		}

		
		ret = tsif_start(tsif_driver->tsif_handler);
		if (ret < 0) {
			mutex_unlock(&mpq_dmx_tsif_info.tsif[tsif].mutex);
			MPQ_DVB_ERR_PRINT("%s: tsif_start failed\n", __func__);
			return ret;
		}

		tsif_get_info(tsif_driver->tsif_handler,
				&(tsif_driver->data_buffer),
				&(tsif_driver->buffer_size));

		
		mpq_dmx_tsif_info.tsif[tsif].mpq_demux = mpq_demux;
	}
	mpq_dmx_tsif_info.tsif[tsif].ref_count++;

	mutex_unlock(&mpq_dmx_tsif_info.tsif[tsif].mutex);

	return ret;
}