commit cb57f465d8c395b66898e49f1dc4f3e7bd01a2e8
Author: dimon <dimon@habar.ttk-chita.ru>
Date:   Tue May 31 08:27:47 2011 +1000

    test commit

diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c
index aa1b2e8..ab8c479 100644
--- a/drivers/media/common/tuners/xc5000.c
+++ b/drivers/media/common/tuners/xc5000.c
@@ -383,6 +383,7 @@ static int xc_SetTVStandard(struct xc5000_priv *priv,
 	u16 VideoMode, u16 AudioMode)
 {
 	int ret;
+	dprintk(1, "%s()\n", __func__);
 	dprintk(1, "%s(0x%04x,0x%04x)\n", __func__, VideoMode, AudioMode);
 	dprintk(1, "%s() Standard = %s\n",
 		__func__,
@@ -397,6 +398,7 @@ static int xc_SetTVStandard(struct xc5000_priv *priv,
 
 static int xc_SetSignalSource(struct xc5000_priv *priv, u16 rf_mode)
 {
+	dprintk(1, "%s()\n", __func__);
 	dprintk(1, "%s(%d) Source = %s\n", __func__, rf_mode,
 		rf_mode == XC_RF_MODE_AIR ? "ANTENNA" : "CABLE");
 
@@ -433,6 +435,7 @@ static int xc_set_RF_frequency(struct xc5000_priv *priv, u32 freq_hz)
 static int xc_set_IF_frequency(struct xc5000_priv *priv, u32 freq_khz)
 {
 	u32 freq_code = (freq_khz * 1024)/1000;
+	dprintk(1, "%s()\n", __func__);
 	dprintk(1, "%s(freq_khz = %d) freq_code = 0x%x\n",
 		__func__, freq_khz, freq_code);
 
@@ -442,6 +445,8 @@ static int xc_set_IF_frequency(struct xc5000_priv *priv, u32 freq_khz)
 
 static int xc_get_ADC_Envelope(struct xc5000_priv *priv, u16 *adc_envelope)
 {
+	dprintk(1, "%s()\n", __func__);
+
 	return xc5000_readreg(priv, XREG_ADC_ENV, adc_envelope);
 }
 
@@ -451,6 +456,8 @@ static int xc_get_frequency_error(struct xc5000_priv *priv, u32 *freq_error_hz)
 	u16 regData;
 	u32 tmp;
 
+	dprintk(1, "%s()\n", __func__);
+
 	result = xc5000_readreg(priv, XREG_FREQ_ERROR, &regData);
 	if (result != XC_RESULT_SUCCESS)
 		return result;
@@ -462,6 +469,8 @@ static int xc_get_frequency_error(struct xc5000_priv *priv, u32 *freq_error_hz)
 
 static int xc_get_lock_status(struct xc5000_priv *priv, u16 *lock_status)
 {
+	dprintk(1, "%s()\n", __func__);
+
 	return xc5000_readreg(priv, XREG_LOCK, lock_status);
 }
 
@@ -472,6 +481,8 @@ static int xc_get_version(struct xc5000_priv *priv,
 	u16 data;
 	int result;
 
+	dprintk(1, "%s()\n", __func__);
+
 	result = xc5000_readreg(priv, XREG_VERSION, &data);
 	if (result != XC_RESULT_SUCCESS)
 		return result;
@@ -486,6 +497,8 @@ static int xc_get_version(struct xc5000_priv *priv,
 
 static int xc_get_buildversion(struct xc5000_priv *priv, u16 *buildrev)
 {
+	dprintk(1, "%s()\n", __func__);
+
 	return xc5000_readreg(priv, XREG_BUILD, buildrev);
 }
 
@@ -494,6 +507,8 @@ static int xc_get_hsync_freq(struct xc5000_priv *priv, u32 *hsync_freq_hz)
 	u16 regData;
 	int result;
 
+	dprintk(1, "%s()\n", __func__);
+
 	result = xc5000_readreg(priv, XREG_HSYNC_FREQ, &regData);
 	if (result != XC_RESULT_SUCCESS)
 		return result;
@@ -504,11 +519,15 @@ static int xc_get_hsync_freq(struct xc5000_priv *priv, u32 *hsync_freq_hz)
 
 static int xc_get_frame_lines(struct xc5000_priv *priv, u16 *frame_lines)
 {
+	dprintk(1, "%s()\n", __func__);
+
 	return xc5000_readreg(priv, XREG_FRAME_LINES, frame_lines);
 }
 
 static int xc_get_quality(struct xc5000_priv *priv, u16 *quality)
 {
+	dprintk(1, "%s()\n", __func__);
+
 	return xc5000_readreg(priv, XREG_QUALITY, quality);
 }
 
@@ -517,6 +536,8 @@ static u16 WaitForLock(struct xc5000_priv *priv)
 	u16 lockState = 0;
 	int watchDogCount = 40;
 
+	dprintk(1, "%s()\n", __func__);
+
 	while ((lockState == 0) && (watchDogCount > 0)) {
 		xc_get_lock_status(priv, &lockState);
 		if (lockState != 1) {
@@ -552,7 +573,7 @@ static int xc5000_fwupload(struct dvb_frontend *fe)
 	struct xc5000_priv *priv = fe->tuner_priv;
 	const struct firmware *fw;
 	int ret;
-
+	dprintk(1, "%s()\n", __func__);
 	/* request the firmware, this will block and timeout */
 	printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n",
 		XC5000_DEFAULT_FIRMWARE);
@@ -642,6 +663,8 @@ static int xc5000_set_params(struct dvb_frontend *fe,
 {
 	struct xc5000_priv *priv = fe->tuner_priv;
 	int ret;
+printk("sp\n");
+//	dprintk(1, "%s()\n", __func__);
 
 	if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) {
 		if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) {
@@ -772,6 +795,8 @@ static int xc5000_is_firmware_loaded(struct dvb_frontend *fe)
 	int ret;
 	u16 id;
 
+//	dprintk(1, "%s()\n", __func__);
+
 	ret = xc5000_readreg(priv, XREG_PRODUCT_ID, &id);
 	if (ret == XC_RESULT_SUCCESS) {
 		if (id == XC_PRODUCT_ID_FW_NOT_LOADED)
@@ -790,7 +815,7 @@ static int xc5000_set_tv_freq(struct dvb_frontend *fe,
 {
 	struct xc5000_priv *priv = fe->tuner_priv;
 	int ret;
-
+	dprintk(1, "%s()\n", __func__);
 	dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n",
 		__func__, params->frequency);
 
@@ -878,7 +903,7 @@ static int xc5000_set_radio_freq(struct dvb_frontend *fe,
 	struct xc5000_priv *priv = fe->tuner_priv;
 	int ret = -EINVAL;
 	u8 radio_input;
-
+	dprintk(1, "%s()\n", __func__);
 	dprintk(1, "%s() frequency=%d (in units of khz)\n",
 		__func__, params->frequency);
 
@@ -935,14 +960,17 @@ static int xc5000_set_analog_params(struct dvb_frontend *fe,
 {
 	struct xc5000_priv *priv = fe->tuner_priv;
 	int ret = -EINVAL;
+printk("sap\n");
+	mutex_lock(&xc5000_list_mutex);
+//	dprintk(1, "%s()\n", __func__);
 
 	if (priv->i2c_props.adap == NULL)
-		return -EINVAL;
+		goto errexit;
 
 	if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) {
 		if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) {
 			dprintk(1, "Unable to load firmware and init tuner\n");
-			return -EINVAL;
+			goto errexit;
 		}
 	}
 
@@ -956,7 +984,12 @@ static int xc5000_set_analog_params(struct dvb_frontend *fe,
 		break;
 	}
 
+	mutex_unlock(&xc5000_list_mutex);
 	return ret;
+
+errexit:
+	mutex_unlock(&xc5000_list_mutex);
+	return -EINVAL;
 }
 
 
@@ -982,6 +1015,8 @@ static int xc5000_get_status(struct dvb_frontend *fe, u32 *status)
 	struct xc5000_priv *priv = fe->tuner_priv;
 	u16 lock_status = 0;
 
+	dprintk(1, "%s()\n", __func__);
+
 	xc_get_lock_status(priv, &lock_status);
 
 	dprintk(1, "%s() lock_status = 0x%08x\n", __func__, lock_status);
@@ -996,6 +1031,10 @@ static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe)
 	struct xc5000_priv *priv = fe->tuner_priv;
 	int ret = 0;
 
+	dprintk(1, "%s()\n", __func__);
+
+//	mutex_lock(&xc5000_list_mutex);
+
 	if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) {
 		ret = xc5000_fwupload(fe);
 		if (ret != XC_RESULT_SUCCESS)
@@ -1015,6 +1054,8 @@ static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe)
 	/* Default to "CABLE" mode */
 	ret |= xc_write_reg(priv, XREG_SIGNALSOURCE, XC_RF_MODE_CABLE);
 
+//	mutex_unlock(&xc5000_list_mutex);
+
 	return ret;
 }
 
diff --git a/drivers/media/video/saa7134/Makefile b/drivers/media/video/saa7134/Makefile
index 8a5ff4d..d698ddc 100644
--- a/drivers/media/video/saa7134/Makefile
+++ b/drivers/media/video/saa7134/Makefile
@@ -1,10 +1,10 @@
 
 saa7134-y :=	saa7134-cards.o saa7134-core.o saa7134-i2c.o
 saa7134-y +=	saa7134-ts.o saa7134-tvaudio.o saa7134-vbi.o
-saa7134-y +=	saa7134-video.o
+saa7134-y +=	saa7134-video.o saa7134-spi.o
 saa7134-$(CONFIG_VIDEO_SAA7134_RC) += saa7134-input.o
 
-obj-$(CONFIG_VIDEO_SAA7134) +=  saa6752hs.o saa7134.o saa7134-empress.o
+obj-$(CONFIG_VIDEO_SAA7134) +=  saa6752hs.o saa7134.o saa7134-empress.o upd61151.o
 
 obj-$(CONFIG_VIDEO_SAA7134_ALSA) += saa7134-alsa.o
 
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index 61c6007..83a0622 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -5347,24 +5347,43 @@ struct saa7134_board saa7134_boards[] = {
 		.radio_type     = UNSET,
 		.tuner_addr     = ADDR_UNSET,
 		.radio_addr     = ADDR_UNSET,
-		.mpeg           = SAA7134_MPEG_DVB,
+		.mpeg           = (SAA7134_MPEG_EMPRESS | SAA7134_MPEG_DVB),
+		.encoder_type   = SAA7134_ENCODER_muPD61151,
+		.gpiomask       = 0x00860000,
 		.inputs         = { {
 			.name = name_tv,
 			.vmux = 2,
 			.amux = TV,
 			.tv   = 1,
+			.gpio = 0x00860000
 		}, {
 			.name = name_comp1,
 			.vmux = 0,
 			.amux = LINE1,
+			.gpio = 0x00860000
 		}, {
 			.name = name_svideo,
 			.vmux = 9,
 			.amux = LINE1,
+			.gpio = 0x00860000
 		} },
 		.radio = {
 			.name = name_radio,
 			.amux = TV,
+			.gpio = 0x00860000
+		},
+		.video_out = CCIR656,
+		.vid_port_opts  = (SET_T_CODE_POLARITY_NON_INVERTED |
+					SET_CLOCK_NOT_DELAYED |
+					SET_CLOCK_INVERTED |
+					SET_VSYNC_OFF),
+		.spi = {
+			.cs    = 17,
+			.clock = 18,
+			.mosi  = 23,
+			.miso  = 21,
+			.num_chipselect = 1,
+			.spi_enable = 1,
 		},
 	},
 	[SAA7134_BOARD_ZOLID_HYBRID_PCI] = {
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
index 41f836f..b5bb0af 100644
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -140,6 +140,17 @@ void saa7134_set_gpio(struct saa7134_dev *dev, int bit_no, int value)
 	}
 }
 
+u32 saa7134_get_gpio(struct saa7134_dev *dev)
+{
+	unsigned long status;
+
+	/* rising SAA7134_GPIO_GPRESCAN reads the status */
+	saa_andorb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN,0);
+	saa_andorb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN,SAA7134_GPIO_GPRESCAN);
+	status = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & 0xfffffff;
+	return status;
+}
+
 /* ------------------------------------------------------------------ */
 
 
@@ -150,10 +161,18 @@ void saa7134_set_gpio(struct saa7134_dev *dev, int bit_no, int value)
 
 static void request_module_async(struct work_struct *work){
 	struct saa7134_dev* dev = container_of(work, struct saa7134_dev, request_module_wk);
+printk("request_mod_async\n");
 	if (card_is_empress(dev))
+	{
+	printk("request mod empress\n");
 		request_module("saa7134-empress");
+	}
+printk("dvb = %d\n", card_is_dvb(dev));
 	if (card_is_dvb(dev))
+	{
+		printk("request mod dvb\n");
 		request_module("saa7134-dvb");
+	}
 	if (alsa) {
 		if (dev->pci->device != PCI_DEVICE_ID_PHILIPS_SAA7130)
 			request_module("saa7134-alsa");
@@ -836,15 +855,54 @@ static void mpeg_ops_attach(struct saa7134_mpeg_ops *ops,
 			    struct saa7134_dev *dev)
 {
 	int err;
-
+printk("mpeg_ops_attach start\n");
+#if 0
 	if (NULL != dev->mops)
+	{
+		printk("mpeg_ops_attach FAIL stop, mops already exist FAILURE\n");
 		return;
-	if (saa7134_boards[dev->board].mpeg != ops->type)
+	}
+	if ( !(saa7134_boards[dev->board].mpeg & ops->type))
+	{
+		printk("mpeg_ops_attach FAIL stop, type FAILURE\n");
 		return;
+	}
 	err = ops->init(dev);
 	if (0 != err)
+	{
+	printk("mpeg_ops_attach FAIL stop, init FAILURE\n");
 		return;
+	}
+printk("mpeg_ops_attach OK stop\n");
 	dev->mops = ops;
+#endif
+}
+
+static void dvb_ops_attach(struct saa7134_mpeg_ops *ops,
+			    struct saa7134_dev *dev)
+{
+	int err;
+printk("dvb_ops_attach start\n");
+#if 0
+	if (NULL != dev->dops)
+	{
+		printk("dvb_ops_attach FAIL stop, mops already exist FAILURE\n");
+		return;
+	}
+	if ( !(saa7134_boards[dev->board].mpeg & ops->type))
+	{
+		printk("dvb_ops_attach FAIL stop, type FAILURE\n");
+		return;
+	}
+	err = ops->init(dev);
+	if (0 != err)
+	{
+	printk("dvb_ops_attach FAIL stop, init FAILURE\n");
+		return;
+	}
+printk("dvb_ops_attach OK stop\n");
+	dev->dops = ops;
+#endif
 }
 
 static void mpeg_ops_detach(struct saa7134_mpeg_ops *ops,
@@ -858,13 +916,29 @@ static void mpeg_ops_detach(struct saa7134_mpeg_ops *ops,
 	dev->mops = NULL;
 }
 
+static void dvb_ops_detach(struct saa7134_mpeg_ops *ops,
+			    struct saa7134_dev *dev)
+{
+	if (NULL == dev->dops)
+		return;
+	if (dev->dops != ops)
+		return;
+	dev->dops->fini(dev);
+	dev->dops = NULL;
+}
+
 static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
 				     const struct pci_device_id *pci_id)
 {
 	struct saa7134_dev *dev;
 	struct saa7134_mpeg_ops *mops;
+	struct saa7134_mpeg_ops *dops;
 	int err;
 
+#if defined(CONFIG_SPI) && (defined(CONFIG_SPI_BITBANG_MODULE) || defined(CONFIG_SPI_BITBANG))
+	struct spi_board_info   spi_conf;
+#endif
+
 	if (saa7134_devcount == SAA7134_MAXBOARDS)
 		return -ENOMEM;
 
@@ -1004,12 +1078,61 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
 
 	saa7134_hwinit2(dev);
 
-	/* load i2c helpers */
+#if defined(CONFIG_SPI) && (defined(CONFIG_SPI_BITBANG_MODULE) || defined(CONFIG_SPI_BITBANG))
+	/* initialize software SPI bus */
+	if (saa7134_boards[dev->board].spi.spi_enable)
+	{
+		switch (dev->board)
+		{
+		case SAA7134_BOARD_BEHOLD_X7:
+			strlcpy(spi_conf.modalias, "upd61151", sizeof(spi_conf.modalias));
+			spi_conf.max_speed_hz = 50000000;
+			spi_conf.chip_select = 0;
+			spi_conf.mode = SPI_MODE_0;
+			spi_conf.controller_data = NULL;
+			spi_conf.platform_data = NULL;
+			break;
+		}
+
+		dev->spi = saa7134_boards[dev->board].spi;
+
+		/* register SPI master and SPI slave */
+		if (saa7134_spi_register(dev, &spi_conf))
+			saa7134_boards[dev->board].spi.spi_enable = 0;
+	}
+#endif
+
+	/* load bus helpers */
 	if (card_is_empress(dev)) {
-		struct v4l2_subdev *sd =
-			v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
+		struct v4l2_subdev *sd = NULL;
+
+		dev->encoder_type = saa7134_boards[dev->board].encoder_type;
+
+		switch (dev->encoder_type) {
+		case SAA7134_ENCODER_muPD61151:
+		{
+			printk(KERN_INFO "%s: found muPD61151 MPEG encoder\n", dev->name);
+
+#if defined(CONFIG_SPI) && (defined(CONFIG_SPI_BITBANG_MODULE) || defined(CONFIG_SPI_BITBANG))
+			if (saa7134_boards[dev->board].spi.spi_enable)
+				sd = v4l2_spi_new_subdev(&dev->v4l2_dev, dev->spi_adap, &spi_conf);
+#else
+			printk(KERN_INFO "%s: You can't use muPD61151 MPEG2 encoder. SPI subsystem not included into kernel.\n", dev->name);
+#endif
+
+		}
+			break;
+		case SAA7134_ENCODER_SAA6752HS:
+		{
+			sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
 				"saa6752hs",
 				saa7134_boards[dev->board].empress_addr, NULL);
+		}
+			break;
+		default:
+			printk(KERN_INFO "%s: MPEG encoder is not configured\n", dev->name);
+		    break;
+		}
 
 		if (sd)
 			sd->grp_id = GRP_EMPRESS;
@@ -1032,6 +1155,9 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
 	mutex_lock(&saa7134_devlist_lock);
 	list_for_each_entry(mops, &mops_list, next)
 		mpeg_ops_attach(mops, dev);
+//	list_add_tail(&dev->devlist, &saa7134_devlist);
+	list_for_each_entry(dops, &mops_list, next)
+		dvb_ops_attach(dops, dev);
 	list_add_tail(&dev->devlist, &saa7134_devlist);
 	mutex_unlock(&saa7134_devlist_lock);
 
@@ -1080,11 +1206,15 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
 
 	if (saa7134_dmasound_init && !dev->dmasound.priv_data)
 		saa7134_dmasound_init(dev);
-
+printk("befor request_submodules\n");
 	request_submodules(dev);
 	return 0;
 
  fail4:
+#if defined(CONFIG_SPI) && (defined(CONFIG_SPI_BITBANG_MODULE) || defined(CONFIG_SPI_BITBANG))
+	if ((card_is_empress(dev)) && (dev->encoder_type == SAA7134_ENCODER_muPD61151))
+		saa7134_spi_unregister(dev);
+#endif
 	saa7134_unregister_video(dev);
 	saa7134_i2c_unregister(dev);
 	free_irq(pci_dev->irq, dev);
@@ -1106,6 +1236,7 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
 	struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
 	struct saa7134_dev *dev = container_of(v4l2_dev, struct saa7134_dev, v4l2_dev);
 	struct saa7134_mpeg_ops *mops;
+	struct saa7134_mpeg_ops *dops;
 
 	flush_request_submodules(dev);
 
@@ -1137,6 +1268,8 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
 	list_del(&dev->devlist);
 	list_for_each_entry(mops, &mops_list, next)
 		mpeg_ops_detach(mops, dev);
+	list_for_each_entry(dops, &mops_list, next)
+		dvb_ops_detach(dops, dev);
 	mutex_unlock(&saa7134_devlist_lock);
 	saa7134_devcount--;
 
@@ -1293,12 +1426,24 @@ static int saa7134_resume(struct pci_dev *pci_dev)
 int saa7134_ts_register(struct saa7134_mpeg_ops *ops)
 {
 	struct saa7134_dev *dev;
-
-	mutex_lock(&saa7134_devlist_lock);
-	list_for_each_entry(dev, &saa7134_devlist, devlist)
-		mpeg_ops_attach(ops, dev);
-	list_add_tail(&ops->next,&mops_list);
-	mutex_unlock(&saa7134_devlist_lock);
+printk("saa7134_ts_register start\n");
+	if (ops -> type == SAA7134_MPEG_EMPRESS) {
+	printk("SAA7134_MPEG_EMPRESS found\n");
+		mutex_lock(&saa7134_devlist_lock);
+		list_for_each_entry(dev, &saa7134_devlist, devlist)
+			mpeg_ops_attach(ops, dev);
+		list_add_tail(&ops->next,&mops_list);
+		mutex_unlock(&saa7134_devlist_lock);
+	}
+	if (ops -> type == SAA7134_MPEG_DVB) {
+	printk("SAA7134_MPEG_DVB found\n");
+		mutex_lock(&saa7134_devlist_lock);
+		list_for_each_entry(dev, &saa7134_devlist, devlist)
+			dvb_ops_attach(ops, dev);
+		list_add_tail(&ops->next,&mops_list);
+		mutex_unlock(&saa7134_devlist_lock);
+	}
+printk("saa7134_ts_register stop\n");
 	return 0;
 }
 
@@ -1306,11 +1451,20 @@ void saa7134_ts_unregister(struct saa7134_mpeg_ops *ops)
 {
 	struct saa7134_dev *dev;
 
-	mutex_lock(&saa7134_devlist_lock);
-	list_del(&ops->next);
-	list_for_each_entry(dev, &saa7134_devlist, devlist)
-		mpeg_ops_detach(ops, dev);
-	mutex_unlock(&saa7134_devlist_lock);
+	if (ops -> type == SAA7134_MPEG_EMPRESS) {
+		mutex_lock(&saa7134_devlist_lock);
+		list_del(&ops->next);
+		list_for_each_entry(dev, &saa7134_devlist, devlist)
+			mpeg_ops_detach(ops, dev);
+		mutex_unlock(&saa7134_devlist_lock);
+	}
+	if (ops -> type == SAA7134_MPEG_DVB) {
+		mutex_lock(&saa7134_devlist_lock);
+		list_del(&ops->next);
+		list_for_each_entry(dev, &saa7134_devlist, devlist)
+			dvb_ops_detach(ops, dev);
+		mutex_unlock(&saa7134_devlist_lock);
+	}
 }
 
 EXPORT_SYMBOL(saa7134_ts_register);
@@ -1354,6 +1508,7 @@ module_exit(saa7134_fini);
 /* ----------------------------------------------------------- */
 
 EXPORT_SYMBOL(saa7134_set_gpio);
+EXPORT_SYMBOL(saa7134_get_gpio);
 EXPORT_SYMBOL(saa7134_boards);
 
 /* ----------------- for the DMA sound modules --------------- */
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c
index f65cad2..d9438e3 100644
--- a/drivers/media/video/saa7134/saa7134-dvb.c
+++ b/drivers/media/video/saa7134/saa7134-dvb.c
@@ -938,6 +938,41 @@ static struct zl10353_config behold_x7_config = {
 	.disable_i2c_gate_ctrl = 1,
 };
 
+static int zl10353_dvb_bus_ctrl_behold_x7(struct dvb_frontend *fe, int acquire) {
+	struct saa7134_dev *dev = fe->dvb->priv;
+	static u8 zl10353_ts_enable[]  = { 0x50, 0x03};
+	static u8 zl10353_ts_disable[] = { 0x50, 0x05};
+	struct i2c_msg zl10353_msg = {.addr = behold_x7_config.demod_address,
+					.flags = 0, .len = 2};
+
+printk("zl10353_dvb_bus_ctrl() acquire = %d\n",acquire);
+
+	if (acquire)
+	{
+		zl10353_msg.buf = zl10353_ts_enable;
+		dev->ts.mpeg = SAA7134_MPEG_DVB;
+		saa7134_boards[dev->board].ts_type = SAA7134_MPEG_TS_PARALLEL;
+printk("set SAA7134_MPEG_DVB\n");
+	}
+	else
+	{
+		zl10353_msg.buf = zl10353_ts_disable;
+		dev->ts.mpeg = SAA7134_MPEG_EMPRESS;
+		saa7134_boards[dev->board].ts_type = SAA7134_MPEG_PS_PARALLEL;
+printk("set SAA7134_MPEG_EMPRESS\n");
+	}
+
+	/* Switch TS bus of the zl10353 */
+	if (i2c_transfer(&dev->i2c_adap, &zl10353_msg, 1) != 1) {
+		wprintk("could not access zl10353 TS bus gate control\n");
+		return -EIO;
+	}
+
+	msleep(10);
+
+	return 0;
+}
+
 /* ==================================================================
  * tda10086 based DVB-S cards, helper functions
  */
@@ -1132,18 +1167,18 @@ static int dvb_init(struct saa7134_dev *dev)
 	int ret;
 	int attach_xc3028 = 0;
 	struct videobuf_dvb_frontend *fe0;
-
+printk("saa7134-dvb init start\n");
 	/* FIXME: add support for multi-frontend */
 	mutex_init(&dev->frontends.lock);
 	INIT_LIST_HEAD(&dev->frontends.felist);
-
+printk("befor dvb_alloc_frontend\n");
 	printk(KERN_INFO "%s() allocating 1 frontend\n", __func__);
 	fe0 = videobuf_dvb_alloc_frontend(&dev->frontends, 1);
 	if (!fe0) {
 		printk(KERN_ERR "%s() failed to alloc\n", __func__);
 		return -ENOMEM;
 	}
-
+printk("befor videobuf_dvb\n");
 	/* init struct videobuf_dvb */
 	dev->ts.nr_bufs    = 32;
 	dev->ts.nr_packets = 32*4;
@@ -1154,7 +1189,7 @@ static int dvb_init(struct saa7134_dev *dev)
 			    V4L2_FIELD_ALTERNATE,
 			    sizeof(struct saa7134_buf),
 			    dev, NULL);
-
+printk("befor switch dev->board\n");
 	switch (dev->board) {
 	case SAA7134_BOARD_PINNACLE_300I_DVBT_PAL:
 		dprintk("pinnacle 300i dvb setup\n");
@@ -1592,6 +1627,7 @@ static int dvb_init(struct saa7134_dev *dev)
 		fe0->dvb.frontend = dvb_attach(zl10353_attach,
 						&behold_x7_config,
 						&dev->i2c_adap);
+		printk("dvb.frontend = %p\n", fe0->dvb.frontend);
 		if (fe0->dvb.frontend) {
 			dvb_attach(xc5000_attach, fe0->dvb.frontend,
 				   &dev->i2c_adap, &behold_x7_tunerconfig);
@@ -1602,6 +1638,7 @@ static int dvb_init(struct saa7134_dev *dev)
 						&behold_x7_config,
 						&dev->i2c_adap);
 		if (fe0->dvb.frontend) {
+			fe0->dvb.frontend->ops.ts_bus_ctrl = zl10353_dvb_bus_ctrl_behold_x7;
 			dvb_attach(xc5000_attach, fe0->dvb.frontend,
 				   &dev->i2c_adap, &behold_x7_tunerconfig);
 		}
@@ -1719,10 +1756,12 @@ static int dvb_init(struct saa7134_dev *dev)
 		if (fe0->dvb.frontend->ops.tuner_ops.sleep)
 			fe0->dvb.frontend->ops.tuner_ops.sleep(fe0->dvb.frontend);
 	}
+printk("saa7134-dvb init OK stop\n");
 	return ret;
 
 dettach_frontend:
 	videobuf_dvb_dealloc_frontends(&dev->frontends);
+printk("saa7134-dvb init FAIL stop\n");
 	return -EINVAL;
 }
 
@@ -1774,6 +1813,7 @@ static struct saa7134_mpeg_ops dvb_ops = {
 
 static int __init dvb_register(void)
 {
+printk("call saa7134_ts_register\n");
 	return saa7134_ts_register(&dvb_ops);
 }
 
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c
index 18294db..2f9d4f8 100644
--- a/drivers/media/video/saa7134/saa7134-empress.c
+++ b/drivers/media/video/saa7134/saa7134-empress.c
@@ -51,6 +51,7 @@ MODULE_PARM_DESC(debug,"enable debug messages");
 
 static void ts_reset_encoder(struct saa7134_dev* dev)
 {
+printk("ts_reset_encoder() start\n");
 	if (!dev->empress_started)
 		return;
 
@@ -59,12 +60,13 @@ static void ts_reset_encoder(struct saa7134_dev* dev)
 	saa_writeb(SAA7134_SPECIAL_MODE, 0x01);
 	msleep(100);
 	dev->empress_started = 0;
+printk("ts_reset_encoder() stop\n");
 }
 
 static int ts_init_encoder(struct saa7134_dev* dev)
 {
 	u32 leading_null_bytes = 0;
-
+printk("ts_init_encoder() start\n");
 	/* If more cards start to need this, then this
 	   should probably be added to the card definitions. */
 	switch (dev->board) {
@@ -77,6 +79,7 @@ static int ts_init_encoder(struct saa7134_dev* dev)
 	ts_reset_encoder(dev);
 	saa_call_all(dev, core, init, leading_null_bytes);
 	dev->empress_started = 1;
+printk("ts_init_encoder() stop\n");
 	return 0;
 }
 
@@ -87,7 +90,7 @@ static int ts_open(struct file *file)
 	struct video_device *vdev = video_devdata(file);
 	struct saa7134_dev *dev = video_drvdata(file);
 	int err;
-
+printk("ts_open() start\n");
 	dprintk("open dev=%s\n", video_device_node_name(vdev));
 	err = -EBUSY;
 	if (!mutex_trylock(&dev->empress_tsq.vb_lock))
@@ -105,13 +108,14 @@ static int ts_open(struct file *file)
 
 done:
 	mutex_unlock(&dev->empress_tsq.vb_lock);
+printk("ts_open() stop\n");
 	return err;
 }
 
 static int ts_release(struct file *file)
 {
 	struct saa7134_dev *dev = file->private_data;
-
+printk("ts_release() start\n");
 	videobuf_stop(&dev->empress_tsq);
 	videobuf_mmap_free(&dev->empress_tsq);
 
@@ -123,7 +127,7 @@ static int ts_release(struct file *file)
 		saa_readb(SAA7134_AUDIO_MUTE_CTRL) | (1 << 6));
 
 	atomic_dec(&dev->empress_users);
-
+printk("ts_release() stop\n");
 	return 0;
 }
 
@@ -167,7 +171,7 @@ static int empress_querycap(struct file *file, void  *priv,
 					struct v4l2_capability *cap)
 {
 	struct saa7134_dev *dev = file->private_data;
-
+printk("empress_querycap() start\n");
 	strcpy(cap->driver, "saa7134");
 	strlcpy(cap->card, saa7134_boards[dev->board].name,
 		sizeof(cap->card));
@@ -177,44 +181,49 @@ static int empress_querycap(struct file *file, void  *priv,
 		V4L2_CAP_VIDEO_CAPTURE |
 		V4L2_CAP_READWRITE |
 		V4L2_CAP_STREAMING;
+printk("empress_querycap() stop\n");
 	return 0;
 }
 
 static int empress_enum_input(struct file *file, void *priv,
 					struct v4l2_input *i)
 {
+printk("empress_enum_input() start\n");
 	if (i->index != 0)
 		return -EINVAL;
 
 	i->type = V4L2_INPUT_TYPE_CAMERA;
 	strcpy(i->name, "CCIR656");
-
+printk("empress_enum_input() stop\n");
 	return 0;
 }
 
 static int empress_g_input(struct file *file, void *priv, unsigned int *i)
 {
 	*i = 0;
+printk("empress_g_input() start\n");
 	return 0;
 }
 
 static int empress_s_input(struct file *file, void *priv, unsigned int i)
 {
+printk("empress_s_input() start\n");
 	if (i != 0)
 		return -EINVAL;
-
+printk("empress_s_input() stop\n");
 	return 0;
 }
 
 static int empress_enum_fmt_vid_cap(struct file *file, void  *priv,
 					struct v4l2_fmtdesc *f)
 {
+printk("empress_enum_fmt_vid_cap() start\n");
 	if (f->index != 0)
 		return -EINVAL;
 
 	strlcpy(f->description, "MPEG TS", sizeof(f->description));
 	f->pixelformat = V4L2_PIX_FMT_MPEG;
-
+printk("empress_enum_fmt_vid_cap() stop\n");
 	return 0;
 }
 
@@ -223,13 +232,13 @@ static int empress_g_fmt_vid_cap(struct file *file, void *priv,
 {
 	struct saa7134_dev *dev = file->private_data;
 	struct v4l2_mbus_framefmt mbus_fmt;
-
+printk("empress_g_fmt_vid_cap() start\n");
 	saa_call_all(dev, video, g_mbus_fmt, &mbus_fmt);
 
 	v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
 	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
 	f->fmt.pix.sizeimage    = TS_PACKET_SIZE * dev->ts.nr_packets;
-
+printk("empress_g_fmt_vid_cap() stop\n");
 	return 0;
 }
 
@@ -238,14 +247,14 @@ static int empress_s_fmt_vid_cap(struct file *file, void *priv,
 {
 	struct saa7134_dev *dev = file->private_data;
 	struct v4l2_mbus_framefmt mbus_fmt;
-
+printk("empress_s_fmt_vid_cap() start\n");
 	v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
 	saa_call_all(dev, video, s_mbus_fmt, &mbus_fmt);
 	v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
 
 	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
 	f->fmt.pix.sizeimage    = TS_PACKET_SIZE * dev->ts.nr_packets;
-
+printk("empress_s_fmt_vid_cap() stop\n");
 	return 0;
 }
 
@@ -253,10 +262,10 @@ static int empress_try_fmt_vid_cap(struct file *file, void *priv,
 				struct v4l2_format *f)
 {
 	struct saa7134_dev *dev = file->private_data;
-
+printk("empress_try_fmt_vid_cap() start\n");
 	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
 	f->fmt.pix.sizeimage    = TS_PACKET_SIZE * dev->ts.nr_packets;
-
+printk("empress_try_fmt_vid_cap() stop\n");
 	return 0;
 }
 
@@ -264,7 +273,7 @@ static int empress_reqbufs(struct file *file, void *priv,
 					struct v4l2_requestbuffers *p)
 {
 	struct saa7134_dev *dev = file->private_data;
-
+printk("empress_reqbufs()\n");
 	return videobuf_reqbufs(&dev->empress_tsq, p);
 }
 
@@ -272,21 +281,21 @@ static int empress_querybuf(struct file *file, void *priv,
 					struct v4l2_buffer *b)
 {
 	struct saa7134_dev *dev = file->private_data;
-
+printk("empress_querybuf()\n");
 	return videobuf_querybuf(&dev->empress_tsq, b);
 }
 
 static int empress_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
 {
 	struct saa7134_dev *dev = file->private_data;
-
+printk("empress_qbuf()\n");
 	return videobuf_qbuf(&dev->empress_tsq, b);
 }
 
 static int empress_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
 {
 	struct saa7134_dev *dev = file->private_data;
-
+printk("empress_dqbuf()\n");
 	return videobuf_dqbuf(&dev->empress_tsq, b,
 				file->f_flags & O_NONBLOCK);
 }
@@ -295,7 +304,7 @@ static int empress_streamon(struct file *file, void *priv,
 					enum v4l2_buf_type type)
 {
 	struct saa7134_dev *dev = file->private_data;
-
+printk("empress_streamon()\n");
 	return videobuf_streamon(&dev->empress_tsq);
 }
 
@@ -303,7 +312,7 @@ static int empress_streamoff(struct file *file, void *priv,
 					enum v4l2_buf_type type)
 {
 	struct saa7134_dev *dev = file->private_data;
-
+printk("empress_streamoff()\n");
 	return videobuf_streamoff(&dev->empress_tsq);
 }
 
@@ -312,7 +321,7 @@ static int empress_s_ext_ctrls(struct file *file, void *priv,
 {
 	struct saa7134_dev *dev = file->private_data;
 	int err;
-
+printk("empress_s_ext_ctrls() start\n");
 	/* count == 0 is abused in saa6752hs.c, so that special
 		case is handled here explicitly. */
 	if (ctrls->count == 0)
@@ -323,7 +332,7 @@ static int empress_s_ext_ctrls(struct file *file, void *priv,
 
 	err = saa_call_empress(dev, core, s_ext_ctrls, ctrls);
 	ts_init_encoder(dev);
-
+printk("empress_s_ext_ctrls() stop\n");
 	return err;
 }
 
@@ -331,9 +340,10 @@ static int empress_g_ext_ctrls(struct file *file, void *priv,
 			       struct v4l2_ext_controls *ctrls)
 {
 	struct saa7134_dev *dev = file->private_data;
-
+printk("empress_g_ext_ctrls() start\n");
 	if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
 		return -EINVAL;
+printk("empress_g_ext_ctrls() stop\n");
 	return saa_call_empress(dev, core, g_ext_ctrls, ctrls);
 }
 
@@ -341,7 +351,7 @@ static int empress_g_ctrl(struct file *file, void *priv,
 					struct v4l2_control *c)
 {
 	struct saa7134_dev *dev = file->private_data;
-
+printk("empress_g_ctrl()\n");
 	return saa7134_g_ctrl_internal(dev, NULL, c);
 }
 
@@ -349,13 +359,14 @@ static int empress_s_ctrl(struct file *file, void *priv,
 					struct v4l2_control *c)
 {
 	struct saa7134_dev *dev = file->private_data;
-
+printk("empress_s_ctrl()\n");
 	return saa7134_s_ctrl_internal(dev, NULL, c);
 }
 
 static int empress_queryctrl(struct file *file, void *priv,
 					struct v4l2_queryctrl *c)
 {
+printk("empress_queryctrl() start\n");
 	/* Must be sorted from low to high control ID! */
 	static const u32 user_ctrls[] = {
 		V4L2_CID_USER_CLASS,
@@ -401,6 +412,7 @@ static int empress_queryctrl(struct file *file, void *priv,
 		return v4l2_ctrl_query_fill(c, 0, 0, 0, 0);
 	if (V4L2_CTRL_ID2CLASS(c->id) != V4L2_CTRL_CLASS_MPEG)
 		return saa7134_queryctrl(file, priv, c);
+printk("empress_queryctrl() stop\n");
 	return saa_call_empress(dev, core, queryctrl, c);
 }
 
@@ -408,9 +420,10 @@ static int empress_querymenu(struct file *file, void *priv,
 					struct v4l2_querymenu *c)
 {
 	struct saa7134_dev *dev = file->private_data;
-
+printk("empress_querymenu() start\n");
 	if (V4L2_CTRL_ID2CLASS(c->id) != V4L2_CTRL_CLASS_MPEG)
 		return -EINVAL;
+printk("empress_querymenu() stop\n");
 	return saa_call_empress(dev, core, querymenu, c);
 }
 
@@ -418,7 +431,7 @@ static int empress_g_chip_ident(struct file *file, void *fh,
 	       struct v4l2_dbg_chip_ident *chip)
 {
 	struct saa7134_dev *dev = file->private_data;
-
+printk("empress_g_chip_ident() start\n");
 	chip->ident = V4L2_IDENT_NONE;
 	chip->revision = 0;
 	if (chip->match.type == V4L2_CHIP_MATCH_I2C_DRIVER &&
@@ -426,20 +439,21 @@ static int empress_g_chip_ident(struct file *file, void *fh,
 		return saa_call_empress(dev, core, g_chip_ident, chip);
 	if (chip->match.type == V4L2_CHIP_MATCH_I2C_ADDR)
 		return saa_call_empress(dev, core, g_chip_ident, chip);
++printk("empress_g_chip_ident() stop FAIL\n");
 	return -EINVAL;
 }
 
 static int empress_s_std(struct file *file, void *priv, v4l2_std_id *id)
 {
 	struct saa7134_dev *dev = file->private_data;
-
+printk("empress_s_std()\n");
 	return saa7134_s_std_internal(dev, NULL, id);
 }
 
 static int empress_g_std(struct file *file, void *priv, v4l2_std_id *id)
 {
 	struct saa7134_dev *dev = file->private_data;
-
+printk("empress_g_std()\n");
 	*id = dev->tvnorm->id;
 	return 0;
 }
diff --git a/drivers/media/video/saa7134/saa7134-spi.c b/drivers/media/video/saa7134/saa7134-spi.c
new file mode 100644
index 0000000..35a1eaa
--- /dev/null
+++ b/drivers/media/video/saa7134/saa7134-spi.c
@@ -0,0 +1,159 @@
+/*
+ *
+ * Device driver for philips saa7134 based TV cards
+ * SPI software interface support
+ *
+ * (c) 2009 Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com>
+ *
+ *  Important: now support ONLY SPI_MODE_0, see FIXME
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#if defined(CONFIG_SPI) && (defined(CONFIG_SPI_BITBANG_MODULE) || defined(CONFIG_SPI_BITBANG))
+
+#include "saa7134-reg.h"
+#include "saa7134.h"
+#include <media/v4l2-common.h>
+
+/* ----------------------------------------------------------- */
+
+static unsigned int spi_debug;
+module_param(spi_debug, int, 0644);
+MODULE_PARM_DESC(spi_debug,"enable debug messages [spi]");
+
+#define d1printk if (1 == spi_debug) printk
+#define d2printk if (2 == spi_debug) printk
+
+static inline void spidelay(unsigned d)
+{
+	ndelay(d);
+}
+
+static inline struct saa7134_spi_gpio *to_sb(struct spi_device *spi)
+{
+	return spi_master_get_devdata(spi->master);
+}
+
+static inline void setsck(struct spi_device *dev, int on)
+{
+	struct saa7134_spi_gpio *sb = to_sb(dev);
+
+	saa7134_set_gpio(sb->controller_data, sb->controller_data->spi.clock, on ? 1 : 0);
+}
+
+static inline void setmosi(struct spi_device *dev, int on)
+{
+	struct saa7134_spi_gpio *sb = to_sb(dev);
+
+	saa7134_set_gpio(sb->controller_data, sb->controller_data->spi.mosi, on ? 1 : 0);
+}
+
+static inline u32 getmiso(struct spi_device *dev)
+{
+	struct saa7134_spi_gpio *sb = to_sb(dev);
+	unsigned long status;
+
+	status = saa7134_get_gpio(sb->controller_data);
+	return !!( status & (1 << sb->controller_data->spi.miso));
+}
+
+#define EXPAND_BITBANG_TXRX 1
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+#include "spi_bitbang_txrx.h"
+
+static void saa7134_spi_gpio_chipsel(struct spi_device *dev, int on)
+{
+	struct saa7134_spi_gpio *sb = to_sb(dev);
+
+	if (on)
+	{
+		/* FIXME: set clock to zero by default, only SPI_MODE_0 compatible */
+		saa7134_set_gpio(sb->controller_data, sb->controller_data->spi.clock, 0);
+		saa7134_set_gpio(sb->controller_data, sb->controller_data->spi.cs, 0);
+	}
+	else
+		saa7134_set_gpio(sb->controller_data, sb->controller_data->spi.cs, 1);
+}
+
+/* Our actual bitbanger routine. */
+static u32 saa7134_txrx(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits)
+{
+	return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits);
+}
+
+int saa7134_spi_register(struct saa7134_dev *dev, struct spi_board_info *info)
+{
+	struct spi_master *master = NULL;
+	struct saa7134_spi_gpio *sb = NULL;
+	int ret = 0;
+
+	master = spi_alloc_master(&dev->pci->dev, sizeof(struct saa7134_spi_gpio));
+
+	if (master == NULL) 
+	{
+		dev_err(&dev->pci->dev, "failed to allocate spi master\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	sb = spi_master_get_devdata(master);
+
+	master->num_chipselect = dev->spi.num_chipselect;
+	master->bus_num = -1;
+	sb->master = spi_master_get(master);
+	sb->bitbang.master = sb->master;
+	sb->bitbang.master->bus_num = -1;
+	sb->bitbang.master->num_chipselect = dev->spi.num_chipselect;
+	sb->bitbang.chipselect = saa7134_spi_gpio_chipsel;
+	sb->bitbang.txrx_word[SPI_MODE_0] = saa7134_txrx;
+
+	/* set state of spi pins */
+	saa7134_set_gpio(dev, dev->spi.cs, 1);
+	/* FIXME: set clock to zero by default, only SPI_MODE_0 compatible */
+	saa7134_set_gpio(dev, dev->spi.clock, 0);
+	saa7134_set_gpio(dev, dev->spi.mosi, 1);
+	saa7134_set_gpio(dev, dev->spi.miso, 3);
+
+	/* start SPI bitbang master */
+	ret = spi_bitbang_start(&sb->bitbang);
+	if (ret) {
+		dev_err(&dev->pci->dev, "Failed to register SPI master\n");
+		goto err_no_bitbang;
+	}
+	dev_info(&dev->pci->dev,
+		"spi master registered: bus_num=%d num_chipselect=%d\n",
+		master->bus_num, master->num_chipselect);
+
+	sb->controller_data = dev;
+	info->bus_num = sb->master->bus_num;
+	info->controller_data = master;
+	dev->spi_adap = master;
+
+err_no_bitbang:
+	spi_master_put(master);
+err:
+	return ret;
+}
+
+void saa7134_spi_unregister(struct saa7134_dev *dev)
+{
+	struct saa7134_spi_gpio *sb = spi_master_get_devdata(dev->spi_adap);
+
+	spi_bitbang_stop(&sb->bitbang);
+	spi_master_put(sb->master);
+}
+
+#endif
diff --git a/drivers/media/video/saa7134/saa7134-ts.c b/drivers/media/video/saa7134/saa7134-ts.c
index 2e3f4b4..9df27fb 100644
--- a/drivers/media/video/saa7134/saa7134-ts.c
+++ b/drivers/media/video/saa7134/saa7134-ts.c
@@ -85,6 +85,10 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
 	llength = TS_PACKET_SIZE;
 	lines = dev->ts.nr_packets;
 
+	if (saa7134_boards[dev->board].ts_type == SAA7134_MPEG_PS_PARALLEL)
+		llength = PS_PACKET_SIZE;
+printk("buffer_prepare set llength = %d\n", llength);
+
 	size = lines * llength;
 	if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
 		return -EINVAL;
@@ -129,8 +133,14 @@ static int
 buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
 {
 	struct saa7134_dev *dev = q->priv_data;
+	unsigned int psize;
+
+	psize = TS_PACKET_SIZE;
+	if (saa7134_boards[dev->board].ts_type == SAA7134_MPEG_PS_PARALLEL)
+		psize = PS_PACKET_SIZE;
+printk("buffer_setup set psize = %d\n", psize);
+	*size = psize * dev->ts.nr_packets;
 
-	*size = TS_PACKET_SIZE * dev->ts.nr_packets;
 	if (0 == *count)
 		*count = dev->ts.nr_bufs;
 	*count = saa7134_buffer_count(*size,*count);
@@ -178,11 +188,18 @@ MODULE_PARM_DESC(ts_nr_packets,"size of a ts buffers (in ts packets)");
 
 int saa7134_ts_init_hw(struct saa7134_dev *dev)
 {
+	unsigned int psize;
+
+	psize = TS_PACKET_SIZE;
+	if (saa7134_boards[dev->board].ts_type == SAA7134_MPEG_PS_PARALLEL)
+		psize = PS_PACKET_SIZE;
+printk("buffer_setup set psize = %d\n", psize);
+
 	/* deactivate TS softreset */
 	saa_writeb(SAA7134_TS_SERIAL1, 0x00);
 	/* TSSOP high active, TSVAL high active, TSLOCK ignored */
 	saa_writeb(SAA7134_TS_PARALLEL, 0x6c);
-	saa_writeb(SAA7134_TS_PARALLEL_SERIAL, (TS_PACKET_SIZE-1));
+	saa_writeb(SAA7134_TS_PARALLEL_SERIAL, (psize - 1));
 	saa_writeb(SAA7134_TS_DMA0, ((dev->ts.nr_packets-1)&0xff));
 	saa_writeb(SAA7134_TS_DMA1, (((dev->ts.nr_packets-1)>>8)&0xff));
 	/* TSNOPIT=0, TSCOLAP=0 */
@@ -238,6 +255,11 @@ int saa7134_ts_stop(struct saa7134_dev *dev)
 		saa_writeb(SAA7134_TS_SERIAL0, 0x40);
 		dev->ts_started = 0;
 		break;
+	case SAA7134_MPEG_PS_PARALLEL:
+	printk("Stop SAA7134_MPEG_PS_PARALLEL\n");
+		saa_writeb(SAA7134_TS_PARALLEL, 0x5e);
+		dev->ts_started = 0;
+		break;
 	}
 	return 0;
 }
@@ -245,10 +267,16 @@ int saa7134_ts_stop(struct saa7134_dev *dev)
 /* Function for start TS */
 int saa7134_ts_start(struct saa7134_dev *dev)
 {
+	unsigned int psize;
 	dprintk("TS start\n");
 
 	BUG_ON(dev->ts_started);
 
+	psize = TS_PACKET_SIZE;
+	if (saa7134_boards[dev->board].ts_type == SAA7134_MPEG_PS_PARALLEL)
+		psize = PS_PACKET_SIZE;
+printk("buffer_setup set psize = %d\n", psize);
+
 	/* dma: setup channel 5 (= TS) */
 	saa_writeb(SAA7134_TS_DMA0, (dev->ts.nr_packets - 1) & 0xff);
 	saa_writeb(SAA7134_TS_DMA1,
@@ -256,7 +284,7 @@ int saa7134_ts_start(struct saa7134_dev *dev)
 	/* TSNOPIT=0, TSCOLAP=0 */
 	saa_writeb(SAA7134_TS_DMA2,
 		(((dev->ts.nr_packets - 1) >> 16) & 0x3f) | 0x00);
-	saa_writel(SAA7134_RS_PITCH(5), TS_PACKET_SIZE);
+	saa_writel(SAA7134_RS_PITCH(5), psize);
 	saa_writel(SAA7134_RS_CONTROL(5), SAA7134_RS_CONTROL_BURST_16 |
 					  SAA7134_RS_CONTROL_ME |
 					  (dev->ts.pt_ts.dma >> 12));
@@ -284,10 +312,19 @@ int saa7134_ts_start(struct saa7134_dev *dev)
 		saa_writeb(SAA7134_TS_PARALLEL_SERIAL, 0xbc);
 		saa_writeb(SAA7134_TS_SERIAL1, 0x02);
 		break;
+	case SAA7134_MPEG_PS_PARALLEL:
+	printk("Start SAA7134_MPEG_PS_PARALLEL\n");
+		/* TS clock inverted */
+		saa_writeb(SAA7134_TS_SERIAL1, 0x02);
+
+		saa_writeb(SAA7134_TS_SERIAL0, 0x40);
+		saa_writeb(SAA7134_TS_PARALLEL, 0xde |
+			(saa7134_boards[dev->board].ts_force_val << 4));
+		break;
 	}
 
 	dev->ts_started = 1;
-
+printk("start TS HERE \n");
 	return 0;
 }
 
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index f96cd5d..e2fc9e6 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -45,6 +45,11 @@
 #if defined(CONFIG_VIDEO_SAA7134_DVB) || defined(CONFIG_VIDEO_SAA7134_DVB_MODULE)
 #include <media/videobuf-dvb.h>
 #endif
+#if defined(CONFIG_SPI) && (defined(CONFIG_SPI_BITBANG_MODULE) || defined(CONFIG_SPI_BITBANG))
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_gpio.h>
+#include <linux/spi/spi_bitbang.h>
+#endif
 
 #define UNSET (-1U)
 
@@ -355,14 +360,30 @@ struct saa7134_input {
 };
 
 enum saa7134_mpeg_type {
-	SAA7134_MPEG_UNUSED,
-	SAA7134_MPEG_EMPRESS,
-	SAA7134_MPEG_DVB,
+	SAA7134_MPEG_UNUSED  = 0,
+	SAA7134_MPEG_EMPRESS = 1,
+	SAA7134_MPEG_DVB     = 2,
 };
 
 enum saa7134_mpeg_ts_type {
 	SAA7134_MPEG_TS_PARALLEL = 0,
 	SAA7134_MPEG_TS_SERIAL,
+	SAA7134_MPEG_PS_PARALLEL,
+};
+
+enum saa7134_encoder_type {
+	SAA7134_ENCODER_UNUSED    = 0,
+	SAA7134_ENCODER_SAA6752HS = 1,
+	SAA7134_ENCODER_muPD61151 = 2,
+};
+
+struct saa7134_software_spi {
+	unsigned char cs:5;
+	unsigned char clock:5;
+	unsigned char mosi:5;
+	unsigned char miso:5;
+	unsigned char num_chipselect:3;
+	unsigned char spi_enable:1;
 };
 
 struct saa7134_board {
@@ -383,6 +404,9 @@ struct saa7134_board {
 	unsigned char		empress_addr;
 	unsigned char		rds_addr;
 
+	/* SPI info */
+	struct saa7134_software_spi	spi;
+
 	unsigned int            tda9887_conf;
 	unsigned int            tuner_config;
 
@@ -390,13 +414,14 @@ struct saa7134_board {
 	enum saa7134_video_out  video_out;
 	enum saa7134_mpeg_type  mpeg;
 	enum saa7134_mpeg_ts_type ts_type;
+	enum saa7134_encoder_type encoder_type;
 	unsigned int            vid_port_opts;
 	unsigned int            ts_force_val:1;
 };
 
 #define card_has_radio(dev)   (NULL != saa7134_boards[dev->board].radio.name)
-#define card_is_empress(dev)  (SAA7134_MPEG_EMPRESS == saa7134_boards[dev->board].mpeg)
-#define card_is_dvb(dev)      (SAA7134_MPEG_DVB     == saa7134_boards[dev->board].mpeg)
+#define card_is_empress(dev)  (SAA7134_MPEG_EMPRESS & saa7134_boards[dev->board].mpeg)
+#define card_is_dvb(dev)      (SAA7134_MPEG_DVB     & saa7134_boards[dev->board].mpeg)
 #define card_has_mpeg(dev)    (SAA7134_MPEG_UNUSED  != saa7134_boards[dev->board].mpeg)
 #define card(dev)             (saa7134_boards[dev->board])
 #define card_in(dev,n)        (saa7134_boards[dev->board].inputs[n])
@@ -519,6 +544,7 @@ struct saa7134_ts {
 	struct saa7134_pgtable     pt_ts;
 	int                        nr_packets;
 	int                        nr_bufs;
+	enum saa7134_mpeg_type     mpeg;
 };
 
 /* ts/mpeg ops */
@@ -530,6 +556,14 @@ struct saa7134_mpeg_ops {
 	void                       (*signal_change)(struct saa7134_dev *dev);
 };
 
+#if defined(CONFIG_SPI) && (defined(CONFIG_SPI_BITBANG_MODULE) || defined(CONFIG_SPI_BITBANG))
+struct saa7134_spi_gpio {
+	struct spi_bitbang         bitbang;
+	struct spi_master          *master;
+	struct saa7134_dev         *controller_data;
+};
+#endif
+
 /* global device status */
 struct saa7134_dev {
 	struct list_head           devlist;
@@ -578,6 +612,12 @@ struct saa7134_dev {
 	unsigned char              eedata[256];
 	int 			   has_rds;
 
+	/* software spi */
+	struct saa7134_software_spi spi;
+#if defined(CONFIG_SPI) && (defined(CONFIG_SPI_BITBANG_MODULE) || defined(CONFIG_SPI_BITBANG))
+	struct spi_master          *spi_adap;
+#endif
+
 	/* video overlay */
 	struct v4l2_framebuffer    ovbuf;
 	struct saa7134_format      *ovfmt;
@@ -637,9 +677,11 @@ struct saa7134_dev {
 	atomic_t 		   empress_users;
 	struct work_struct         empress_workqueue;
 	int                        empress_started;
+	enum saa7134_encoder_type  encoder_type;
 
 #if defined(CONFIG_VIDEO_SAA7134_DVB) || defined(CONFIG_VIDEO_SAA7134_DVB_MODULE)
 	/* SAA7134_MPEG_DVB only */
+	struct saa7134_mpeg_ops    *dops;
 	struct videobuf_dvb_frontends frontends;
 	int (*original_demod_sleep)(struct dvb_frontend *fe);
 	int (*original_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
@@ -703,6 +745,7 @@ extern int saa7134_no_overlay;
 
 void saa7134_track_gpio(struct saa7134_dev *dev, char *msg);
 void saa7134_set_gpio(struct saa7134_dev *dev, int bit_no, int value);
+u32 saa7134_get_gpio(struct saa7134_dev *dev);
 
 #define SAA7134_PGTABLE_SIZE 4096
 
@@ -748,6 +791,13 @@ int saa7134_tuner_callback(void *priv, int component, int command, int arg);
 int saa7134_i2c_register(struct saa7134_dev *dev);
 int saa7134_i2c_unregister(struct saa7134_dev *dev);
 
+/* ----------------------------------------------------------- */
+/* saa7134-spi.c                                               */
+
+#if defined(CONFIG_SPI) && (defined(CONFIG_SPI_BITBANG_MODULE) || defined(CONFIG_SPI_BITBANG))
+int saa7134_spi_register(struct saa7134_dev *dev, struct spi_board_info *info);
+void saa7134_spi_unregister(struct saa7134_dev *dev);
+#endif
 
 /* ----------------------------------------------------------- */
 /* saa7134-video.c                                             */
@@ -774,6 +824,7 @@ void saa7134_irq_video_done(struct saa7134_dev *dev, unsigned long status);
 /* saa7134-ts.c                                                */
 
 #define TS_PACKET_SIZE 188 /* TS packets 188 bytes */
+#define PS_PACKET_SIZE 128 /* PS packets 128 bytes */
 
 extern struct videobuf_queue_ops saa7134_ts_qops;
 
diff --git a/drivers/media/video/saa7134/upd61151.c b/drivers/media/video/saa7134/upd61151.c
new file mode 100644
index 0000000..3c792bd
--- /dev/null
+++ b/drivers/media/video/saa7134/upd61151.c
@@ -0,0 +1,1546 @@
+ /*
+    upd61151 - driver for the uPD61151 by NEC
+
+    Copyright (C) Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com>
+
+    Based on the saa6752s.c driver.
+    Copyright (C) 2004 Andrew de Quincey
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License vs published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mvss Ave, Cambridge, MA 02139, USA.
+  */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/sysfs.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/spi/spi.h>
+#include <linux/types.h>
+//#include "compat.h"
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/upd61151.h>
+
+#include <linux/crc32.h>
+#include "saa7134.h"
+
+#define DRVNAME		"upd61151"
+
+static unsigned int spi_debug;
+module_param(spi_debug, int, 0644);
+MODULE_PARM_DESC(spi_debug,"enable debug messages [spi]");
+
+#define d1printk_spi if (1 <= spi_debug) printk
+#define d2printk_spi if (2 <= spi_debug) printk
+
+static unsigned int core_debug;
+module_param(core_debug, int, 0644);
+MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
+
+#define d1printk_core if (1 <= core_debug) printk
+#define d2printk_core if (2 <= core_debug) printk
+
+MODULE_DESCRIPTION("device driver for uPD61151 MPEG2 encoder");
+MODULE_AUTHOR("Dmitry V Belimov");
+MODULE_LICENSE("GPL");
+
+/* Result codes */
+#define RESULT_SUCCESS              0
+#define RESULT_FAILURE              1
+#define STATUS_DEVICE_NOT_READY     2
+#define STATUS_DEVICE_DATA_ERROR    3
+#define STATUS_INVALID_PARAMETER    4
+
+enum upd61151_videoformat {
+	UPD61151_VF_D1 = 0,    /* 720x480/720x576 */
+	UPD61151_VF_D2 = 1,    /* 704x480/704x576 */
+	UPD61151_VF_D3 = 2,    /* 352x480/352x576 */
+	UPD61151_VF_D4 = 3,    /* 352x240/352x288 */
+	UPD61151_VF_D5 = 4,    /* 544x480/544x576 */
+	UPD61151_VF_D6 = 5,    /* 480x480/480x576 */
+	UPD61151_VF_D7 = 6,    /* 352x240/352x288 */
+	UPD61151_VF_D8 = 8,    /* 640x480/640x576 */
+	UPD61151_VF_D9 = 9,    /* 320x480/320x576 */
+	UPD61151_VF_D10 = 10,  /* 320x240/320x288 */
+	UPD61151_VF_UNKNOWN,
+};
+
+struct upd61151_mpeg_params {
+	/* audio */
+	enum v4l2_mpeg_audio_sampling_freq au_sampling;
+	enum v4l2_mpeg_audio_encoding    au_encoding;
+	enum v4l2_mpeg_audio_l2_bitrate  au_l2_bitrate;
+
+	/* video */
+	enum v4l2_mpeg_video_aspect	vi_aspect;
+	enum v4l2_mpeg_video_bitrate_mode vi_bitrate_mode;
+	__u32 				vi_bitrate;
+	__u32 				vi_bitrate_peak;
+
+	/* encoder */
+	u8				video_gop_size;
+	u8				video_gop_closure;
+};
+
+static const struct v4l2_format v4l2_format_table[] =
+{
+	[UPD61151_VF_D1] =
+		{ .fmt = { .pix = { .width = 720, .height = 576 }}},
+	[UPD61151_VF_D2] =
+		{ .fmt = { .pix = { .width = 704, .height = 576 }}},
+	[UPD61151_VF_D3] =
+		{ .fmt = { .pix = { .width = 352, .height = 576 }}},
+	[UPD61151_VF_D4] =
+		{ .fmt = { .pix = { .width = 352, .height = 288 }}},
+	[UPD61151_VF_D5] =
+		{ .fmt = { .pix = { .width = 544, .height = 576 }}},
+	[UPD61151_VF_D6] =
+		{ .fmt = { .pix = { .width = 480, .height = 576 }}},
+	[UPD61151_VF_D7] =
+		{ .fmt = { .pix = { .width = 352, .height = 288 }}},
+	[UPD61151_VF_D8] =
+		{ .fmt = { .pix = { .width = 640, .height = 576 }}},
+	[UPD61151_VF_D9] =
+		{ .fmt = { .pix = { .width = 320, .height = 576 }}},
+	[UPD61151_VF_D10] =
+		{ .fmt = { .pix = { .width = 320, .height = 288 }}},
+	[UPD61151_VF_UNKNOWN] =
+		{ .fmt = { .pix = { .width = 0, .height = 0}}},
+};
+
+struct upd61151_state {
+	struct v4l2_subdev            sd;
+	struct upd61151_mpeg_params   params;
+	enum upd61151_videoformat     video_format;
+	v4l2_std_id                   standard;
+	enum upd61151_encode_state    enstate;
+};
+
+static struct upd61151_mpeg_params param_defaults =
+{
+	.vi_aspect       = V4L2_MPEG_VIDEO_ASPECT_4x3,
+	.vi_bitrate      = 4000,
+	.vi_bitrate_peak = 6000,
+	.vi_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
+
+	.au_sampling     = V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000,
+	.au_encoding     = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
+	.au_l2_bitrate   = V4L2_MPEG_AUDIO_L2_BITRATE_256K,
+
+	.video_gop_size  = 1,
+	.video_gop_closure = 0,
+};
+
+static int write_reg(struct spi_device *spi, u8 address, u8 data)
+{
+	u8 buf[2];
+
+	buf[0] = ((address >> 2) << 2);
+	buf[1] = data;
+
+	d2printk_spi(KERN_DEBUG "%s: spi data 0x%x <= 0x%x\n",spi->modalias,address,data);
+
+	return spi_write(spi, buf, ARRAY_SIZE(buf));
+}
+
+static void write_fw(struct spi_device *spi, u8 address, const struct firmware *fw)
+{
+	u8 buf[2];
+	u32 i;
+
+	buf[0] = ((address >> 2) << 2);
+
+	for (i=0; i < fw->size; i++)
+	{
+		buf[1] = *(fw->data+i);
+		spi_write(spi, buf, 2);
+	}
+}
+
+static int read_reg(struct spi_device *spi, unsigned char address, unsigned char *data)
+{
+	u8 buf[1];
+	int ret;
+
+	ret = 0;
+	buf[0] = ((address >> 2) << 2) | 0x02;
+	ret = spi_write_then_read(spi, buf, 1, data, 1);
+
+	d2printk_spi(KERN_DEBUG "%s: spi data 0x%x => 0x%x, status %d\n",spi->modalias, address, *data, ret);
+
+	return ret;
+}
+
+static void upd61151_reset_core(struct v4l2_subdev *sd)
+{
+	struct spi_device *spi = v4l2_get_subdevdata(sd);
+
+	write_reg(spi, UPD61151_SOFTWARE_RST, 0x01);
+}
+
+static void upd61151_set_dest_addr(struct v4l2_subdev *sd, u32 addr)
+{
+	struct spi_device *spi = v4l2_get_subdevdata(sd);
+
+	write_reg(spi, UPD61151_TRANSFER_ADDR1, (u8)((addr >> 16) & 0xFF));
+	write_reg(spi, UPD61151_TRANSFER_ADDR2, (u8)((addr >> 8) & 0xFF));
+	write_reg(spi, UPD61151_TRANSFER_ADDR3, (u8)(addr & 0xFF));
+}
+
+static void upd61151_set_data_size(struct v4l2_subdev *sd, u32 dsize)
+{
+	struct spi_device *spi = v4l2_get_subdevdata(sd);
+
+	write_reg(spi, UPD61151_DATA_COUNTER1, (u8)((dsize >> 16) & 0xFF));
+	write_reg(spi, UPD61151_DATA_COUNTER2, (u8)((dsize >> 8) & 0xFF));
+	write_reg(spi, UPD61151_DATA_COUNTER3, (u8)(dsize & 0xFF));
+}
+
+static u8 upd61151_clear_transfer_irq(struct v4l2_subdev *sd)
+{
+	struct spi_device *spi = v4l2_get_subdevdata(sd);
+	u8 rbyte = 0x00;
+
+	read_reg(spi, UPD61151_TRANSFER_IRQ, &rbyte);
+
+	d2printk_core(KERN_DEBUG "%s: Transfer IRQ status 0x%x\n", spi->modalias, rbyte);
+
+	if (rbyte)
+		write_reg(spi, UPD61151_IRQ, rbyte);
+
+	return rbyte;
+}
+
+static void upd61151_handle_transfer_err(struct v4l2_subdev *sd)
+{
+	struct spi_device *spi = v4l2_get_subdevdata(sd);
+	u8 rbyte;
+printk("upd61151_handle_transfer_err\n");
+	/* Set data transfer count size = 1 */
+	upd61151_set_data_size(sd, 0x01);
+
+	/* Set transfer mode SDRAM -> Host */
+	write_reg(spi, UPD61151_TRANSFER_MODE, 0x01);
+
+	/* Read one byte from SDRAM */
+	read_reg(spi, UPD61151_TRANSFER_DATA, &rbyte);
+
+	/* Release transfer mode */
+	write_reg(spi, UPD61151_TRANSFER_MODE, 0x00);
+
+	/* Clear IRQ */
+	upd61151_clear_transfer_irq(sd);
+
+	/* Set destination address to 0x000000 */
+	upd61151_set_dest_addr(sd, 0x000000);
+
+	/* Set data transfer count size = 3 */
+	upd61151_set_data_size(sd, 0x03);
+
+	/* Set transfer mode SDRAM -> Host */
+	write_reg(spi, UPD61151_TRANSFER_MODE, 0x01);
+
+	/* Clear IRQ */
+	upd61151_clear_transfer_irq(sd);
+
+	/* Read 3 byte from SDRAM */
+	read_reg(spi, UPD61151_TRANSFER_DATA, &rbyte);
+	read_reg(spi, UPD61151_TRANSFER_DATA, &rbyte);
+	read_reg(spi, UPD61151_TRANSFER_DATA, &rbyte);
+
+	/* Clear IRQ */
+	upd61151_clear_transfer_irq(sd);
+
+	/* Set transfer mode SDRAM -> Host */
+	write_reg(spi, UPD61151_TRANSFER_MODE, 0x00);
+
+	/* Clear IRQ */
+	upd61151_clear_transfer_irq(sd);
+}
+
+static int upd61151_wait_transfer_irq(struct v4l2_subdev *sd)
+{
+	u8 i, rstatus;
+
+	rstatus = 0;
+	/* Wait transfer interrupt */
+	for (i=0; i<5; i++)
+	{
+		rstatus = upd61151_clear_transfer_irq(sd);
+		if (rstatus)
+			break;
+		msleep(1);
+	}
+
+	if (!rstatus)
+		return STATUS_DEVICE_NOT_READY;
+
+	if (rstatus & 0x04)
+	{
+		/* Data transfer error */
+		upd61151_handle_transfer_err(sd);
+		return STATUS_DEVICE_DATA_ERROR;
+	}
+
+	return RESULT_SUCCESS;
+}
+
+static u8 upd61151_clear_info_irq(struct v4l2_subdev *sd)
+{
+	struct spi_device *spi = v4l2_get_subdevdata(sd);
+	u8 rbyte = 0x00;
+
+	read_reg(spi, UPD61151_IRQ, &rbyte);
+
+	d2printk_core(KERN_DEBUG "%s: IRQ status 0x%x\n", spi->modalias, rbyte);
+
+	if (rbyte)
+		write_reg(spi, UPD61151_IRQ, rbyte);
+
+	return rbyte;
+}
+
+static u8 upd61151_clear_error_irq(struct v4l2_subdev *sd)
+{
+	struct spi_device *spi = v4l2_get_subdevdata(sd);
+	u8 rbyte = 0x00;
+
+	read_reg(spi, UPD61151_ERROR_IRQ, &rbyte);
+
+	d2printk_core(KERN_DEBUG "%s: IRQ error status 0x%x\n", spi->modalias, rbyte);
+
+	if (rbyte)
+		write_reg(spi, UPD61151_ERROR_IRQ, rbyte);
+
+	return rbyte;
+}
+
+static u8 upd61151_clear_except_irq(struct v4l2_subdev *sd)
+{
+	struct spi_device *spi = v4l2_get_subdevdata(sd);
+	u8 rbyte = 0x00;
+
+	read_reg(spi, UPD61151_EXCEPT_IRQ, &rbyte);
+
+	d2printk_core(KERN_DEBUG "%s: IRQ exception status 0x%x\n", spi->modalias, rbyte);
+
+	if (rbyte)
+		write_reg(spi, UPD61151_EXCEPT_IRQ, rbyte);
+
+	return rbyte;
+}
+
+static u8 upd61151_get_state(struct v4l2_subdev *sd)
+{
+	struct spi_device *spi = v4l2_get_subdevdata(sd);
+	u8 rbyte = 0x00;
+
+	read_reg(spi, UPD61151_STATUS, &rbyte);
+
+	d2printk_core(KERN_DEBUG "%s: MPEG2 core status %d\n", spi->modalias, rbyte & 0x07);
+
+	return rbyte & 0x07;
+}
+
+static int upd61151_set_state(struct v4l2_subdev *sd, enum upd61151_config nstate)
+{
+	struct spi_device *spi = v4l2_get_subdevdata(sd);
+	u8 enstate, k, get_error;
+	enum upd61151_config wait_state;
+printk("upd61151_set_state\n");
+
+	enstate = (u8)(nstate) | (u8)(UPD61151_COMMAND_CONFIG);
+
+	/* Clear IRQ */
+	upd61151_clear_error_irq(sd);
+
+	/* Set state */
+	write_reg(spi, UPD61151_COMMAND, enstate);
+
+	/* Wait max 100ms */
+	for (k = 0; k < 200; k++)
+	{
+		wait_state = upd61151_get_state(sd);
+		if (wait_state == UPD61151_COMMAND_CONFIG)
+		{
+			/* Clear IRQ flags */
+			upd61151_clear_info_irq(sd);
+
+			d2printk_core(KERN_DEBUG "%s: MPEG2 SetState(%d), SUCCESS! Delay(%d ms)\n", spi->modalias, nstate, k << 1);
+
+			return RESULT_SUCCESS;
+		}
+
+		/* Check error interrupt */
+		get_error = upd61151_clear_error_irq(sd);
+		if (get_error & 0x01)
+		{
+			/* Invalid command found */
+			d2printk_core(KERN_DEBUG "%s: MPEG2 SetState(%d), FAIL! Invalid Command (IC)!!!\n", spi->modalias, nstate);
+			break;
+		}
+
+		if (get_error & 0x02)
+		{
+			/* Invalid parameter found */
+			d2printk_core(KERN_DEBUG "%s: MPEG2 SetState(%d), FAIL! Invalid Parameter (IP)!!!\n", spi->modalias, nstate);
+			break;
+		}
+
+		if (get_error & 0x04)
+		{
+			/* Invalid audio firmware download IADL */
+			d2printk_core(KERN_DEBUG "%s: MPEG2 SetState(%d), FAIL! Invalid Audio Firmware Download (IADL)!!!\n", spi->modalias, nstate);
+			break;
+		}
+
+		if (get_error & 0x08)
+		{
+			/* Invalid system bitrate */
+			d2printk_core(KERN_DEBUG "%s: MPEG2 SetState(%d), FAIL! Invalid System Bit Rate (ISBR)!!!\n", spi->modalias, nstate);
+			break;
+		}
+
+		mdelay(2);
+	}
+
+	if (k >= 100)
+	{
+		d2printk_core(KERN_DEBUG "%s: MPEG2 SetState(%d), FAIL! TIMEOUT(%d ms)\n", spi->modalias, nstate, k << 1);
+	}
+
+	return STATUS_DEVICE_NOT_READY;
+}
+
+static int upd61151_load_base_firmware(struct v4l2_subdev *sd)
+{
+	struct spi_device *spi = v4l2_get_subdevdata(sd);
+	u32 size;
+	const struct firmware *fw;
+	int ret = RESULT_SUCCESS;
+
+printk("DEBUG: upd61151_load_base_firmware\n");
+
+	size = UPD61151_DEFAULT_PS_FIRMWARE_SIZE / 4;
+
+	/* request the firmware, this will block and timeout */
+	printk(KERN_INFO "%s: waiting for base firmware upload (%s)...\n",
+		spi->modalias, UPD61151_DEFAULT_PS_FIRMWARE);
+
+	ret = request_firmware(&fw, UPD61151_DEFAULT_PS_FIRMWARE,
+		spi->dev.parent);
+	if (ret)
+	{
+		printk(KERN_ERR "%s: Upload failed. (file not found?)\n",spi->modalias);
+		ret = STATUS_INVALID_PARAMETER;
+		goto out;
+	}
+	else
+		printk(KERN_DEBUG "%s: firmware read %Zu bytes.\n", spi->modalias,
+		       fw->size);
+
+	if (fw->size != UPD61151_DEFAULT_PS_FIRMWARE_SIZE)
+	{
+		printk(KERN_ERR "%s: firmware incorrect size\n", spi->modalias);
+		ret = STATUS_INVALID_PARAMETER;
+		goto out;
+	}
+	printk(KERN_INFO "%s: base firmware uploading...\n", spi->modalias);
+
+	upd61151_clear_transfer_irq(sd);
+
+	/* CPU reset ON */
+	write_reg(spi, UPD61151_SOFTWARE_RST, 0x02);
+
+	/* Set destination address to 0x000000 */
+	upd61151_set_dest_addr(sd, 0x000000);
+
+	/* Set transfer data count to firmware size / 4 */
+	upd61151_set_data_size(sd, size);
+
+	/* Set transfer mode to Host -> iRAM */
+	write_reg(spi, UPD61151_TRANSFER_MODE, 0x80);
+printk("fw upload start\n");
+	write_fw(spi, UPD61151_TRANSFER_DATA, fw);
+printk("fw upload stop\n");
+
+	ret = upd61151_wait_transfer_irq(sd);
+	if (ret == RESULT_SUCCESS)
+	{
+		/* Release transfer mode */
+		write_reg(spi, UPD61151_TRANSFER_MODE, 0x00);
+		printk(KERN_INFO "%s: base firmware upload complete...\n", spi->modalias);
+	}
+	else
+		printk(KERN_INFO "%s: base firmware upload FAIL...\n", spi->modalias);
+
+out:
+	/* CPU reset OFF */
+	write_reg(spi, UPD61151_SOFTWARE_RST, 0x00);
+	release_firmware(fw);
+	return ret;
+}
+
+static int upd61151_load_audio_firmware(struct v4l2_subdev *sd)
+{
+	struct spi_device *spi = v4l2_get_subdevdata(sd);
+	const struct firmware *fw;
+	u32 addr, i;
+	int ret = RESULT_SUCCESS;
+
+printk("DEBUG: upd61151_load_audio_firmware\n");
+
+	/* request the firmware, this will block and timeout */
+	printk(KERN_INFO "%s: waiting for audio firmware upload (%s)...\n",
+		spi->modalias, UPD61151_DEFAULT_AUDIO_FIRMWARE);
+
+	ret = request_firmware(&fw, UPD61151_DEFAULT_AUDIO_FIRMWARE,
+		spi->dev.parent);
+	if (ret)
+	{
+		printk(KERN_ERR "%s: Upload failed. (file not found?)\n",spi->modalias);
+		ret = STATUS_INVALID_PARAMETER;
+		goto out;
+	}
+	else
+		printk(KERN_DEBUG "%s: firmware read %Zu bytes.\n", spi->modalias,
+		       fw->size);
+
+	if (fw->size != UPD61151_DEFAULT_AUDIO_FIRMWARE_SIZE)
+	{
+		printk(KERN_ERR "%s: firmware incorrect size\n", spi->modalias);
+		ret = STATUS_INVALID_PARAMETER;
+		goto out;
+	}
+	printk(KERN_INFO "%s: audio firmware uploading...\n", spi->modalias);
+
+	addr = 0x308F00;
+	addr >>= 5;
+
+	upd61151_clear_transfer_irq(sd);
+
+	/* Set destination address */
+	upd61151_set_dest_addr(sd, addr);
+
+	/* Set transfer data count to firmware size */
+	upd61151_set_data_size(sd, UPD61151_DEFAULT_AUDIO_FIRMWARE_SIZE);
+
+	/* Set transfer mode to Host -> SDRAM */
+	write_reg(spi, UPD61151_TRANSFER_MODE, 0x02);
+
+printk("fw upload start\n");
+
+	for (i = 0; i < UPD61151_DEFAULT_AUDIO_FIRMWARE_SIZE; i++)
+	{
+		write_reg(spi, UPD61151_TRANSFER_DATA, *(fw->data+i));
+
+		/* Check Transfer interrupt each 128 bytes */
+		if ( ((i+1) % 128) ==0 )
+		{
+			ret = upd61151_wait_transfer_irq(sd);
+			if (ret != RESULT_SUCCESS)
+				break;
+		}
+	}
+
+printk("fw upload stop\n");
+
+	if (ret == RESULT_SUCCESS)
+	{
+		/* Release transfer mode */
+		write_reg(spi, UPD61151_TRANSFER_MODE, 0x00);
+		printk(KERN_INFO "%s: audio firmware upload complete...\n", spi->modalias);
+	}
+	else
+		printk(KERN_INFO "%s: audio firmware upload FAIL...\n", spi->modalias);
+
+out:
+	release_firmware(fw);
+	return ret;
+}
+
+static int upd61151_chip_command(struct v4l2_subdev *sd, enum upd61151_command command)
+{
+	struct spi_device *spi = v4l2_get_subdevdata(sd);
+	u8 cycles, wait, i, irqerr;
+	enum upd61151_command want_state;
+
+printk("DEBUG uPD61151: upd61151_chip_command\n");
+
+	/* calculate delay */
+	cycles = 100;
+	wait = 10;
+
+	switch (command)
+	{
+	case UPD61151_COMMAND_STANDBY_STOP:
+	case UPD61151_COMMAND_PAUSE:
+		break;
+
+	case UPD61151_COMMAND_START_RESTART:
+		cycles = 100;
+		wait = 2;
+		break;
+
+	default:
+		return STATUS_INVALID_PARAMETER;
+	}
+
+	/* Clear IRQ */
+	upd61151_clear_error_irq(sd);
+
+	write_reg(spi, UPD61151_COMMAND, command);
+
+	for (i=0; i < cycles; i++)
+	{
+		/* Check state */
+		want_state = upd61151_get_state(sd);
+		if (want_state == command)
+		{
+			upd61151_clear_info_irq(sd);
+			d2printk_core(KERN_DEBUG "%s: SetState(%d) SUCCESS!!! Delay [%d ms].\n", spi->modalias, want_state, i*wait);
+			return RESULT_SUCCESS;
+		}
+
+		/* Check error interrupt */
+		irqerr = upd61151_clear_error_irq(sd);
+
+		if (irqerr & 0x01)
+		{
+			d2printk_core(KERN_DEBUG "%s: SetState(%d) FAIL!!! Invalid Command (IC).\n", spi->modalias, command);
+			break;
+		}
+
+		if (irqerr & 0x02)
+		{
+			d2printk_core(KERN_DEBUG "%s: SetState(%d) FAIL!!! Invalid Parameter (IP).\n", spi->modalias, command);
+			break;
+		}
+
+		if (irqerr & 0x04)
+		{
+			d2printk_core(KERN_DEBUG "%s: SetState(%d) FAIL!!! Invalid Audio Firmware Download (IADL).\n", spi->modalias, command);
+			break;
+		}
+
+		if (irqerr & 0x08)
+		{
+			d2printk_core(KERN_DEBUG "%s: SetState(%d) FAIL!!! Invalid System Bit Rate (ISBR).\n", spi->modalias, command);
+			break;
+		}
+
+		msleep(wait);
+	}
+
+	if (i >= cycles)
+	{
+		d2printk_core(KERN_DEBUG "%s: SetState(%d) FAIL!!! TIMEOUT [%d ms].\n", spi->modalias, command, cycles*wait);
+	}
+
+	return STATUS_DEVICE_NOT_READY;
+}
+
+static int upd61151_setup_video_frontend(struct v4l2_subdev *sd)
+{
+	struct spi_device *spi = v4l2_get_subdevdata(sd);
+	struct upd61151_state *h = spi_get_drvdata(spi);
+	u8 dbyte;
+
+printk("upd61151_setup_video_frontend\n");
+
+	dbyte = 0x00;
+	/* Update FIDT */
+	if (h->standard & V4L2_STD_625_50)
+		dbyte |= 0x10;
+printk("   0x%x  ",dbyte);
+	dbyte |= h->video_format;
+printk("   0x%x  \n",dbyte);
+	write_reg(spi, UPD61151_VIDEO_ATTRIBUTE, dbyte);
+
+	/* SAV/EAV (ITU-656), FID not inverted */
+	write_reg(spi, UPD61151_VIDEO_SYNC, 0x80);
+
+	/* Set H offset */
+	write_reg(spi, UPD61151_VIDEO_HOFFSET, 0x00);
+
+	/* Set V offset */
+	if (h->standard & V4L2_STD_625_50)
+		dbyte = 0x01;
+	else
+		dbyte = 0x03;
+	write_reg(spi, UPD61151_VIDEO_VOFFSET, dbyte);
+
+	/* Setup VBI */
+	/* SLCEN = 0, VBIOFFV = 4, VBIOFFH = 8*/
+	write_reg(spi, UPD61151_VBI_ADJ1, 0x48);
+
+	return 0;
+}
+
+static int upd61151_setup_audio_frontend(struct v4l2_subdev *sd)
+{
+	struct spi_device *spi = v4l2_get_subdevdata(sd);
+	struct upd61151_state *h = spi_get_drvdata(spi);
+	struct upd61151_mpeg_params *params = &h->params;
+	u8 dbyte;
+
+printk("upd61151_setup_audio_frontend\n");
+	dbyte = 0x00;
+	/* Setup AUDIO attribute 1 */
+	switch (params->au_sampling)
+	{
+	case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000:
+		dbyte |= 0x20;
+		break;
+	case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100:
+		dbyte |= 0x10;
+		break;
+	default:
+		break;
+	}
+
+	switch (params->au_l2_bitrate)
+	{
+	case V4L2_MPEG_AUDIO_L2_BITRATE_128K :
+		dbyte |= 0x05;
+		break;
+	case V4L2_MPEG_AUDIO_L2_BITRATE_160K :
+		dbyte |= 0x06;
+		break;
+	case V4L2_MPEG_AUDIO_L2_BITRATE_192K :
+		dbyte |= 0x07;
+		break;
+	case V4L2_MPEG_AUDIO_L2_BITRATE_224K :
+		dbyte |= 0x08;
+		break;
+	case V4L2_MPEG_AUDIO_L2_BITRATE_320K :
+		dbyte |= 0x0A;
+		break;
+	case V4L2_MPEG_AUDIO_L2_BITRATE_384K :
+		dbyte |= 0x0B;
+		break;
+	default:
+		dbyte |= 0x09;
+		break;
+	}
+
+	write_reg(spi, UPD61151_AUDIO_ATTRIBUTE2, dbyte);
+
+	/* PLLs = internal, AMCLK = 384fs, AQ = 16bit & 64bck, APCMI = I2S, APCMO = OFF*/
+	write_reg(spi, UPD61151_AUDIO_INTERFACE, 0x5B);
+	return 0;
+}
+
+static void upd61151_prepare_bitrates(struct v4l2_subdev *sd)
+{
+	struct spi_device *spi = v4l2_get_subdevdata(sd);
+	struct upd61151_state *h = spi_get_drvdata(spi);
+	u32 mindelta, minvbr;
+printk("upd61151_prepare_bitrates\n");
+
+	if (h->params.vi_bitrate_peak > 15000)
+		h->params.vi_bitrate_peak = 15000;
+
+
+	if (h->params.vi_bitrate_mode)
+	{
+		if (h->params.vi_bitrate_peak < 1200)
+			h->params.vi_bitrate_peak = 1200;
+
+		h->params.vi_bitrate = 0;
+		minvbr = 1000;
+	}
+	else
+	{
+		if (h->params.vi_bitrate_peak < 1500)
+			h->params.vi_bitrate_peak = 1500;
+
+		if (h->params.vi_bitrate < 1200)
+			h->params.vi_bitrate = 1200;
+
+		if (h->params.vi_bitrate <= 3000)
+			/* Min = Average - 20% */
+			mindelta = (h->params.vi_bitrate * 2) / 100;
+		else
+			/* Min = Average - 30% */
+			mindelta = (h->params.vi_bitrate * 3) / 100;
+
+		minvbr = h->params.vi_bitrate - mindelta;
+
+		if (minvbr < 1000)
+			minvbr = 1000;
+	}
+
+	/* Set Video bitrates */
+	write_reg(spi, UPD61151_VMAXRATE, (u8)(h->params.vi_bitrate_peak / 100));
+	write_reg(spi, UPD61151_VAVRATE, (u8)(h->params.vi_bitrate / 100));
+	write_reg(spi, UPD61151_VMINRATE, (u8)(minvbr / 100));
+
+	/* Set VMAXDEBT - 252Mbps */
+	write_reg(spi, UPD61151_VMAXDEBT, 0xFC);
+
+}
+
+static int upd61151_config_encoder(struct v4l2_subdev *sd)
+{
+	struct spi_device *spi = v4l2_get_subdevdata(sd);
+	struct upd61151_state *h = spi_get_drvdata(spi);
+	u8 video_attrib1, video_attrib2;
+	u8 audio_attrib1, audio_attrib2;
+	u8 mux, mute, aspr;
+
+printk("upd61151_config_encoder\n");
+
+	video_attrib1 = 0x00;
+	/* Set Video resolution*/
+	video_attrib1 |= h->video_format;
+	/* Set GOP */
+	/* for gop_size = 0, GOP M=3, N=15 */
+	/* for gop_size = 1, GOP M=1, N=15 */
+	if (!h->params.video_gop_size)
+		video_attrib1 |= 0x80;
+	/* Set TV system */
+	if (h->standard & V4L2_STD_625_50)
+		video_attrib1 |= 0x10;
+printk("Video attrib1 = 0x%x\n",video_attrib1);
+
+	video_attrib2 = 0x00;
+	/* Set Rate control */
+	if (!h->params.vi_bitrate_mode)
+		video_attrib2 |= 0x04;
+	/* Set GOP, Open GOP = 0, Closed GOP = 1 */
+	if (h->params.video_gop_closure)
+		video_attrib2 |= 0x10;
+	/* Set adaptive M control */
+	/* FIXME: hardcoded adaptive M to enabled */
+	video_attrib2 |= 0x20;
+	/* Set DC precision control */
+	/* FIXME: hardcoded 9 bit */
+	video_attrib2 |= 0x01;
+
+	/* Set Audio mode */
+	/* FIXME: hardcoded audio to MPEG layer 2, 2ch stereo */
+	audio_attrib1 = 0x41;
+
+	audio_attrib2 = 0x00;
+	switch (h->params.au_sampling)
+	{
+	case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000:
+		audio_attrib2 |= 0x20;
+		break;
+	case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100:
+		audio_attrib2 |= 0x10;
+		break;
+	default:
+		break;
+	}
+
+	/* Set audio bitrate */
+	switch (h->params.au_l2_bitrate)
+	{
+	case V4L2_MPEG_AUDIO_L2_BITRATE_128K :
+		audio_attrib2 |= 0x05;
+		break;
+	case V4L2_MPEG_AUDIO_L2_BITRATE_160K :
+		audio_attrib2 |= 0x06;
+		break;
+	case V4L2_MPEG_AUDIO_L2_BITRATE_192K :
+		audio_attrib2 |= 0x07;
+		break;
+	case V4L2_MPEG_AUDIO_L2_BITRATE_224K :
+		audio_attrib2 |= 0x08;
+		break;
+	case V4L2_MPEG_AUDIO_L2_BITRATE_320K :
+		audio_attrib2 |= 0x0A;
+		break;
+	case V4L2_MPEG_AUDIO_L2_BITRATE_384K :
+		audio_attrib2 |= 0x0B;
+		break;
+	default:
+		audio_attrib2 |= 0x09;
+		break;
+	}
+
+	/* Set aspect */
+	aspr = 0x00;
+	if (h->params.vi_aspect == V4L2_MPEG_VIDEO_ASPECT_16x9)
+		aspr = 0x20;
+
+	/* Enable Audio */
+	/* FIXME: hardcoded enable Audio at all time */
+	mux = 0x03;
+	write_reg(spi, UPD61151_MUX_CTRL, mux);
+
+	/* Enable Video or blue screen */
+	mute = 0x00;
+	/* FIXME: hardcoded enable Video at all time */
+	write_reg(spi, UPD61151_ENCODING_TYPE, mute);
+
+	/* Prepare bitrates */
+	upd61151_prepare_bitrates(sd);
+
+	write_reg(spi, UPD61151_VIDEO_ATTRIBUTE, video_attrib1);
+	write_reg(spi, UPD61151_VIDEO_MODE, video_attrib2);
+	write_reg(spi, UPD61151_AUDIO_ATTRIBUTE1, audio_attrib1);
+	write_reg(spi, UPD61151_AUDIO_ATTRIBUTE2, audio_attrib2);
+
+	/* FIXME: hardcoded value */
+	/* Set brightness noise reducer to level 1 */
+	/* Set color noise reducer to level 1 */
+	write_reg(spi, UPD61151_VIDEO_NOISE, 0x05);
+
+	write_reg(spi, UPD61151_ASPR, aspr);
+	return 0;
+}
+
+static int upd61151_download_firmware(struct v4l2_subdev *sd)
+{
+	struct spi_device *spi = v4l2_get_subdevdata(sd);
+	struct upd61151_state *h = spi_get_drvdata(spi);
+	int res_cmd;
+
+printk("DEBUG: upd61151_download_firmware\n");
+	h->enstate = UPD61151_ENCODE_STATE_IDLE;
+
+	upd61151_reset_core(sd);
+
+	udelay(1);
+
+	/* Init SDRAM */
+	write_reg(spi, UPD61151_SDRAM_IF_DELAY_ADJ, 0x01);
+	write_reg(spi, UPD61151_SDRAM_FCLK_SEL, 0xA0);
+
+	udelay(200);
+
+	/* Set SDRAM to STANDBY */
+	write_reg(spi, UPD61151_SDRAM_STANDBY, 0x01);
+
+	udelay(10);
+
+	/* Release SDRAM from STANDBY */
+	write_reg(spi, UPD61151_SDRAM_STANDBY, 0x00);
+
+	res_cmd = upd61151_load_base_firmware(sd);
+	if (res_cmd != RESULT_SUCCESS)
+		return res_cmd;
+
+	res_cmd = upd61151_load_audio_firmware(sd);
+	if (res_cmd != RESULT_SUCCESS)
+		return res_cmd;
+
+	/* Clear IRQ flags */
+	if ( !(upd61151_clear_info_irq(sd) & 0x10) )
+	{
+		/* INICM not running */
+		d1printk_core(KERN_DEBUG "%s: download firmware FAILED. INICM is not run.\n", spi->modalias);
+		return STATUS_DEVICE_NOT_READY;
+	}
+
+	/* Set STANDBY state */
+	res_cmd = upd61151_chip_command(sd, UPD61151_COMMAND_STANDBY_STOP);
+	if (res_cmd != RESULT_SUCCESS)
+		return res_cmd;
+
+	/* Setup video input frontend */
+	upd61151_setup_video_frontend(sd);
+
+	/* Setup audio input frontend */
+	upd61151_setup_audio_frontend(sd);
+
+	/* Config encoder params */
+	upd61151_config_encoder(sd);
+
+	/* Set all config and upload audio firmware */
+	res_cmd = upd61151_set_state(sd, UPD61151_CONFIG_ALL);
+	if (res_cmd != RESULT_SUCCESS)
+		return res_cmd;
+
+	/* Return to STANDBY state */
+	res_cmd = upd61151_chip_command(sd, UPD61151_COMMAND_STANDBY_STOP);
+	if (res_cmd != RESULT_SUCCESS)
+		return res_cmd;
+
+	return RESULT_SUCCESS;
+}
+
+static int upd61151_is_need_reload_fw(struct v4l2_subdev *sd)
+{
+	struct spi_device *spi = v4l2_get_subdevdata(sd);
+
+	if (upd61151_get_state(sd) == UPD61151_COMMAND_INITIAL)
+	{
+		d1printk_core(KERN_DEBUG "%s: need reload firmware\n", spi->modalias);
+		return 1;
+	}
+
+	if (upd61151_clear_except_irq(sd) & 0x04)
+	{
+		d1printk_core(KERN_DEBUG "%s: mainly buffer of encoder is overflowed\n", spi->modalias);
+		return 1;
+	}
+
+	return 0;
+}
+
+/* Prepare audio PLLs */
+static void upd61151_prepare_i2s(struct v4l2_subdev *sd)
+{
+printk("DEBUG uPD61151: upd61151_prepare_i2s\n");
+printk("WARNING: The function upd61151_prepare_i2s is EMPTY\n");
+}
+
+static int upd61151_init(struct v4l2_subdev *sd, u32 leading_null_bytes)
+{
+	int res;
+
+printk("DEBUG uPD61151: upd61151_init\n");
+
+	if (upd61151_is_need_reload_fw(sd))
+	{
+		printk("Start load firmware...\n");
+		if (!upd61151_download_firmware(sd))
+			printk("Firmware downloaded SUCCESS!!!\n");
+		else
+			printk("Firmware downloaded FAIL!!!\n");
+	}
+	else
+		printk("Firmware is OK\n");
+
+	/* Prepare bitrates */
+	upd61151_prepare_bitrates(sd);
+
+	/* Prepare audio PLLs */
+	upd61151_prepare_i2s(sd);
+printk("switch ON TS MGEP2\n");
+	/* FIXME: Hardcoded for SAA7134_BOARD_BEHOLD_X7 */
+	/* enable TS out via manipulation with GPIO5    */
+//	write_reg(spi, UPD61151_GPIO_CTRLS, 0x10);
+
+	res = upd61151_chip_command(sd, UPD61151_COMMAND_START_RESTART);
+	if (res != RESULT_SUCCESS)
+		return res;
+
+	return 0;
+}
+
+
+static int get_ctrl(struct upd61151_mpeg_params *params, struct v4l2_ext_control *ctrl)
+{
+	switch (ctrl->id) {
+	case V4L2_CID_MPEG_STREAM_TYPE:
+		ctrl->value = V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
+		break;
+	case V4L2_CID_MPEG_AUDIO_ENCODING:
+		ctrl->value = params->au_encoding;
+		break;
+	case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
+		ctrl->value = params->au_l2_bitrate;
+		break;
+	case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
+		ctrl->value = params->au_sampling;
+		break;
+	case V4L2_CID_MPEG_VIDEO_ENCODING:
+		ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
+		break;
+	case V4L2_CID_MPEG_VIDEO_ASPECT:
+		ctrl->value = params->vi_aspect;
+		break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE:
+		ctrl->value = params->vi_bitrate * 1000;
+		break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+		ctrl->value = params->vi_bitrate_peak * 1000;
+		break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+		ctrl->value = params->vi_bitrate_mode;
+		break;
+	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+		ctrl->value = params->video_gop_size;
+		break;
+	case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
+		ctrl->value = params->video_gop_closure;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int handle_ctrl(struct upd61151_mpeg_params *params, struct v4l2_ext_control *ctrl, int set)
+{
+	int old = 0, new;
+
+	new = ctrl->value;
+	switch (ctrl->id) {
+	case V4L2_CID_MPEG_STREAM_TYPE:
+		old = V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
+		if (set && new != old)
+			return -ERANGE;
+		new = old;
+		break;
+	case V4L2_CID_MPEG_AUDIO_ENCODING:
+		old = params->au_encoding;
+		if (set && new != V4L2_MPEG_AUDIO_ENCODING_LAYER_2)
+			return -ERANGE;
+		params->au_encoding = new;
+		break;
+	case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
+		old = params->au_l2_bitrate;
+		if (set && new < V4L2_MPEG_AUDIO_L2_BITRATE_128K &&
+			   new > V4L2_MPEG_AUDIO_L2_BITRATE_384K)
+			return -ERANGE;
+		params->au_l2_bitrate = new;
+		break;
+	case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
+		old = params->au_sampling;
+		if (set && new > V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000 &&
+			    new < V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100)
+			return -ERANGE;
+		params->au_sampling = new;
+		break;
+	case V4L2_CID_MPEG_VIDEO_ENCODING:
+		old = V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
+		if (set && new != old)
+			return -ERANGE;
+		new = old;
+		break;
+	case V4L2_CID_MPEG_VIDEO_ASPECT:
+		old = params->vi_aspect;
+		if (set && new != V4L2_MPEG_VIDEO_ASPECT_16x9 &&
+			   new != V4L2_MPEG_VIDEO_ASPECT_4x3)
+			return -ERANGE;
+		if (new != V4L2_MPEG_VIDEO_ASPECT_16x9)
+			new = V4L2_MPEG_VIDEO_ASPECT_4x3;
+		params->vi_aspect = new;
+		break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE:
+		old = params->vi_bitrate * 1000;
+		new = 1000 * (new / 1000);
+		if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)
+			return -ERANGE;
+		if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)
+			new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000;
+		params->vi_bitrate = new / 1000;
+		break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+		old = params->vi_bitrate_peak * 1000;
+		new = 1000 * (new / 1000);
+		if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)
+			return -ERANGE;
+		if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)
+			new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000;
+		params->vi_bitrate_peak = new / 1000;
+		break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+		old = params->vi_bitrate_mode;
+		params->vi_bitrate_mode = new;
+		break;
+	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+		old = params->video_gop_size;
+		if (set && new != 0 && new != 1)
+			return -ERANGE;
+		params->video_gop_size = new;
+		break;
+	case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
+		old = params->video_gop_closure;
+		if (set && new != 0 && new != 1)
+			return -ERANGE;
+		params->video_gop_closure = new;
+		break;
+	default:
+		return -EINVAL;
+	}
+	ctrl->value = new;
+	return 0;
+}
+
+static int upd61151_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qctrl)
+{
+	struct spi_device *spi = v4l2_get_subdevdata(sd);
+	struct upd61151_state *h = spi_get_drvdata(spi);
+	struct upd61151_mpeg_params *params = &h->params;
+	int err;
+
+printk("DEBUG uPD61151: upd61151_queryctrl\n");
+	switch (qctrl->id) {
+	case V4L2_CID_MPEG_AUDIO_ENCODING:
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
+				V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
+				1, V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
+
+	case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
+		return v4l2_ctrl_query_fill(qctrl, V4L2_MPEG_AUDIO_L2_BITRATE_128K,
+				V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
+				V4L2_MPEG_AUDIO_L2_BITRATE_256K);
+
+	case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100,
+				V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000, 3,
+				V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000);
+
+	case V4L2_CID_MPEG_VIDEO_ENCODING:
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_VIDEO_ENCODING_MPEG_2,
+				V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1,
+				V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
+
+	case V4L2_CID_MPEG_VIDEO_ASPECT:
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_VIDEO_ASPECT_4x3,
+				V4L2_MPEG_VIDEO_ASPECT_16x9, 1,
+				V4L2_MPEG_VIDEO_ASPECT_4x3);
+
+	case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+		err = v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 8000000);
+		if (err == 0 &&
+		    params->vi_bitrate_mode ==
+				V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
+			qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+		return err;
+
+	case V4L2_CID_MPEG_STREAM_TYPE:
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
+				V4L2_MPEG_STREAM_TYPE_MPEG2_PS, 1,
+				V4L2_MPEG_STREAM_TYPE_MPEG2_PS);
+
+	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
+				V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1,
+				V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
+	case V4L2_CID_MPEG_VIDEO_BITRATE:
+		return v4l2_ctrl_query_fill(qctrl, 0, 15000000, 1, 6000000);
+	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+		return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 1);
+	case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
+		return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0);
+
+	default:
+		break;
+	}
+	return -EINVAL;
+}
+
+static int upd61151_querymenu(struct v4l2_subdev *sd, struct v4l2_querymenu *qmenu)
+{
+	static const u32 mpeg_audio_sampling[] = {
+		V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100,
+		V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
+		V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000,
+		V4L2_CTRL_MENU_IDS_END
+	};
+	static const u32 mpeg_audio_encoding[] = {
+		V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
+		V4L2_CTRL_MENU_IDS_END
+	};
+	static u32 mpeg_audio_l2_bitrate[] = {
+		V4L2_MPEG_AUDIO_L2_BITRATE_128K,
+		V4L2_MPEG_AUDIO_L2_BITRATE_160K,
+		V4L2_MPEG_AUDIO_L2_BITRATE_192K,
+		V4L2_MPEG_AUDIO_L2_BITRATE_224K,
+		V4L2_MPEG_AUDIO_L2_BITRATE_256K,
+		V4L2_MPEG_AUDIO_L2_BITRATE_320K,
+		V4L2_MPEG_AUDIO_L2_BITRATE_384K,
+		V4L2_CTRL_MENU_IDS_END
+	};
+	struct v4l2_queryctrl qctrl;
+	int err;
+printk("DEBUG uPD61151: upd61151_querymenu\n");
+	qctrl.id = qmenu->id;
+	err = upd61151_queryctrl(sd, &qctrl);
+	if (err)
+		return err;
+	switch (qmenu->id) {
+	case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
+		return v4l2_ctrl_query_menu_valid_items(qmenu, mpeg_audio_l2_bitrate);
+	case V4L2_CID_MPEG_AUDIO_ENCODING:
+		return v4l2_ctrl_query_menu_valid_items(qmenu, mpeg_audio_encoding);
+	case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
+		return v4l2_ctrl_query_menu_valid_items(qmenu, mpeg_audio_sampling);
+	}
+	return v4l2_ctrl_query_menu(qmenu, &qctrl, NULL);
+}
+
+static int upd61151_do_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls, int set)
+{
+	struct spi_device *spi = v4l2_get_subdevdata(sd);
+	struct upd61151_state *h = spi_get_drvdata(spi);
+	struct upd61151_mpeg_params params;
+	int i;
+printk("DEBUG uPD61151: upd61151_do_ext_ctrls\n");
+
+	if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+		return -EINVAL;
+
+	params = h->params;
+	for (i = 0; i < ctrls->count; i++) {
+		int err = handle_ctrl(&params, ctrls->controls + i, set);
+
+		if (err) {
+			ctrls->error_idx = i;
+			return err;
+		}
+	}
+	if (set)
+		h->params = params;
+
+	return 0;
+}
+
+static int upd61151_s_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls)
+{
+printk("DEBUG uPD61151: upd61151_s_ext_ctrls\n");
+	return upd61151_do_ext_ctrls(sd, ctrls, 1);
+}
+
+static int upd61151_try_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls)
+{
+printk("DEBUG uPD61151: upd61151_s_ext_ctrls\n");
+	return upd61151_do_ext_ctrls(sd, ctrls, 0);
+}
+
+static int upd61151_g_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls)
+{
+	struct spi_device *spi = v4l2_get_subdevdata(sd);
+	struct upd61151_state *h = spi_get_drvdata(spi);
+	int i;
+printk("DEBUG uPD61151: upd61151_g_ext_ctrls\n");
+
+	if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+		return -EINVAL;
+
+	for (i = 0; i < ctrls->count; i++) {
+		int err = get_ctrl(&h->params, ctrls->controls + i);
+
+		if (err) {
+			ctrls->error_idx = i;
+			return err;
+		}
+	}
+	return 0;
+}
+
+static int upd61151_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+{
+	struct spi_device *spi = v4l2_get_subdevdata(sd);
+	struct upd61151_state *h = spi_get_drvdata(spi);
+
+	if (h->video_format == UPD61151_VF_UNKNOWN)
+		h->video_format = UPD61151_VF_D1;
+	f->fmt.pix.width =
+		v4l2_format_table[h->video_format].fmt.pix.width;
+	f->fmt.pix.height =
+		v4l2_format_table[h->video_format].fmt.pix.height;
+
+printk("DEBUG uPD61151: upd61151_g_fmt\n");
+	return 0;
+}
+
+static int upd61151_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+{
+	struct spi_device *spi = v4l2_get_subdevdata(sd);
+	struct upd61151_state *h = spi_get_drvdata(spi);
+
+printk("DEBUG uPD61151: upd61151_s_fmt\n");
+
+	if (f->fmt.pix.width <= 320)
+	{
+		if (f->fmt.pix.height <= 288)
+		{
+			f->fmt.pix.width = 320;
+			f->fmt.pix.height = 288;
+			h->video_format = UPD61151_VF_D10;
+			return 0;
+		}
+		else
+		{
+			f->fmt.pix.width = 320;
+			f->fmt.pix.height = 576;
+			h->video_format = UPD61151_VF_D9;
+			return 0;
+		}
+	}
+
+	if (f->fmt.pix.width <= 352)
+	{
+		if (f->fmt.pix.height <= 288)
+		{
+			f->fmt.pix.width = 352;
+			f->fmt.pix.height = 288;
+			h->video_format = UPD61151_VF_D4;
+			return 0;
+		}
+		else
+		{
+			f->fmt.pix.width = 352;
+			f->fmt.pix.height = 576;
+			h->video_format = UPD61151_VF_D3;
+			return 0;
+		}
+	}
+
+	if (f->fmt.pix.width <= 480)
+	{
+		f->fmt.pix.width = 480;
+		f->fmt.pix.height = 576;
+		h->video_format = UPD61151_VF_D6;
+		return 0;
+	}
+
+	if (f->fmt.pix.width <= 544)
+	{
+		f->fmt.pix.width = 544;
+		f->fmt.pix.height = 576;
+		h->video_format = UPD61151_VF_D5;
+		return 0;
+	}
+
+	if (f->fmt.pix.width <= 640)
+	{
+		f->fmt.pix.width = 640;
+		f->fmt.pix.height = 576;
+		h->video_format = UPD61151_VF_D8;
+		return 0;
+	}
+
+	if (f->fmt.pix.width <= 704)
+	{
+		f->fmt.pix.width = 704;
+		f->fmt.pix.height = 576;
+		h->video_format = UPD61151_VF_D2;
+		return 0;
+	}
+
+	f->fmt.pix.width = 720;
+	f->fmt.pix.height = 576;
+	h->video_format = UPD61151_VF_D1;
+	return 0;
+}
+
+static int upd61151_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	struct spi_device *spi = v4l2_get_subdevdata(sd);
+	struct upd61151_state *h = spi_get_drvdata(spi);
+printk("DEBUG uPD61151: upd61151_s_std\n");
+	h->standard = std;
+	return 0;
+}
+
+static int upd61151_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
+{
+printk("DEBUG uPD61151: upd61151_g_chip_ident\n");
+	chip->ident	= V4L2_IDENT_UPD61161;
+	chip->revision	= 0;
+
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_subdev_core_ops upd61151_core_ops = {
+	.g_chip_ident = upd61151_g_chip_ident,    /* done */
+	.init = upd61151_init,
+	.queryctrl = upd61151_queryctrl,          /* done */
+	.querymenu = upd61151_querymenu,          /* done */
+	.g_ext_ctrls = upd61151_g_ext_ctrls,      /* done */
+	.s_ext_ctrls = upd61151_s_ext_ctrls,      /* done */
+	.try_ext_ctrls = upd61151_try_ext_ctrls,  /* done */
+	.s_std = upd61151_s_std,                  /* done */
+};
+
+static const struct v4l2_subdev_video_ops upd61151_video_ops = {
+//	.s_fmt = upd61151_s_fmt,                  /* done */
+//	.g_fmt = upd61151_g_fmt,                  /* done */
+};
+
+static const struct v4l2_subdev_ops upd61151_ops = {
+	.core = &upd61151_core_ops,               /* done */
+	.video = &upd61151_video_ops,             /* done */
+};
+
+static int __devinit upd61151_probe(struct spi_device *spi)
+{
+	struct upd61151_state *h = kzalloc(sizeof(*h), GFP_KERNEL);
+	struct v4l2_subdev *sd;
+
+printk("upd61151_probe function\n");
+
+	if (h == NULL)
+		return -ENOMEM;
+	sd = &h->sd;
+
+	v4l2_spi_subdev_init(sd, spi, &upd61151_ops);
+
+	spi_set_drvdata(spi, h);
+#if 0
+	if (upd61151_is_need_reload_fw(sd))
+	{
+		printk("Start load firmware...\n");
+		if (!upd61151_download_firmware(sd))
+			printk("Firmware downloaded SUCCESS!!!\n");
+		else
+			printk("Firmware downloaded FAIL!!!\n");
+	}
+	else
+		printk("Firmware is OK\n");
+#endif
+	h->params = param_defaults;
+	h->standard = 0; /* Assume 625 input lines */
+	return 0;
+}
+
+static int __devexit upd61151_remove(struct spi_device *spi)
+{
+	struct upd61151_state *h = spi_get_drvdata(spi);
+printk("upd61151_remove function\n");
+	v4l2_device_unregister_subdev(&h->sd);
+	kfree(h);
+	spi_unregister_device(spi);
+	return 0;
+}
+
+static struct spi_driver upd61151_driver = {
+	.driver = {
+		.name   = DRVNAME,
+		.bus    = &spi_bus_type,
+		.owner  = THIS_MODULE,
+	},
+	.probe = upd61151_probe,
+	.remove = __devexit_p(upd61151_remove),
+};
+
+
+static int __init init_upd61151(void)
+{
+	return spi_register_driver(&upd61151_driver);
+}
+module_init(init_upd61151);
+
+static void __exit exit_upd61151(void)
+{
+	spi_unregister_driver(&upd61151_driver);
+}
+module_exit(exit_upd61151);
diff --git a/include/media/upd61151.h b/include/media/upd61151.h
new file mode 100644
index 0000000..49d2a30
--- /dev/null
+++ b/include/media/upd61151.h
@@ -0,0 +1,125 @@
+/*
+    upd61151.h - definition for NEC uPD61151 MPEG encoder
+
+    Copyright (C) Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#include <linux/firmware.h>
+
+#define UPD61151_DEFAULT_PS_FIRMWARE "D61151_PS_7133_v22_031031.bin"
+#define UPD61151_DEFAULT_PS_FIRMWARE_SIZE 97002
+
+#define UPD61151_DEFAULT_AUDIO_FIRMWARE "audrey_MPE_V1r51.bin"
+#define UPD61151_DEFAULT_AUDIO_FIRMWARE_SIZE 40064
+
+enum mpeg_audio_bitrate {
+	MPEG_AUDIO_BITRATE_128 = 5,  /* 128 kBit/sec */
+	MPEG_AUDIO_BITRATE_160 = 6,  /* 160 kBit/sec */
+	MPEG_AUDIO_BITRATE_192 = 7,  /* 192 kBit/sec */
+	MPEG_AUDIO_BITRATE_224 = 8,  /* 224 kBit/sec */
+	MPEG_AUDIO_BITRATE_256 = 9,  /* 256 kBit/sec */
+	MPEG_AUDIO_BITRATE_320 = 10, /* 320 kBit/sec */
+	MPEG_AUDIO_BITRATE_384 = 11, /* 384 kBit/sec */
+
+	MPEG_AUDIO_BITRATE_MAX
+};
+
+enum mpeg_video_format {
+	MPEG_VIDEO_FORMAT_D1 = 0,    /* 720x480/720x576 */
+	MPEG_VIDEO_FORMAT_D2 = 1,    /* 704x480/704x576 */
+	MPEG_VIDEO_FORMAT_D3 = 2,    /* 352x480/352x576 */
+	MPEG_VIDEO_FORMAT_D4 = 3,    /* 352x240/352x288 */
+	MPEG_VIDEO_FORMAT_D5 = 4,    /* 544x480/544x576 */
+	MPEG_VIDEO_FORMAT_D6 = 5,    /* 480x480/480x576 */
+	MPEG_VIDEO_FORMAT_D7 = 6,    /* 352x240/352x288 */
+	MPEG_VIDEO_FORMAT_D8 = 8,    /* 640x480/640x576 */
+	MPEG_VIDEO_FORMAT_D9 = 9,    /* 320x480/320x576 */
+	MPEG_VIDEO_FORMAT_D10 = 10,  /* 320x240/320x288 */
+
+	MPEG_VIDEO_FORMAT_MAX
+};
+
+#define MPEG_VIDEO_TARGET_BITRATE_MAX 15000
+#define MPEG_VIDEO_MAX_BITRATE_MAX 15000
+#define MPEG_TOTAL_BITRATE_MAX 15000
+#define MPEG_PID_MAX ((1 << 14) - 1)
+
+enum upd61151_command {
+	UPD61151_COMMAND_INITIAL           = 0x00,
+	UPD61151_COMMAND_STANDBY_STOP      = 0x01,
+	UPD61151_COMMAND_CONFIG            = 0x02,
+	UPD61151_COMMAND_START_RESTART     = 0x03,
+	UPD61151_COMMAND_PAUSE             = 0x04,
+	UPD61151_COMMAND_CHANGE            = 0x05,
+};
+
+enum upd61151_encode_state {
+	UPD61151_ENCODE_STATE_IDLE         = 0,
+	UPD61151_ENCODE_STATE_ENCODE       = 1,
+	UPD61151_ENCODE_STATE_PAUSE        = 2,
+};
+
+enum upd61151_config {
+	UPD61151_CONFIG_ALL                = 0x00,
+	UPD61151_CONFIG_AUDIO_FW           = 0x10,
+	UPD61151_CONFIG_VIDEO_INPUT        = 0x20,
+	UPD61151_CONFIG_VBI_INPUT          = 0x30,
+	UPD61151_CONFIG_AUDIO_INPUT        = 0x40,
+};
+
+#define UPD61151_COMMAND             0x00
+#define UPD61151_STATUS              0x04
+#define UPD61151_ENCODING_TYPE       0x08
+#define UPD61151_MUX_CTRL            0x0C
+#define UPD61151_VMAXRATE            0x10
+#define UPD61151_VAVRATE             0x14
+#define UPD61151_VIDEO_ATTRIBUTE     0x1C
+#define UPD61151_VIDEO_MODE          0x20
+#define UPD61151_VIDEO_NOISE         0x24
+#define UPD61151_AUDIO_ATTRIBUTE1    0x28
+#define UPD61151_AUDIO_ATTRIBUTE2    0x2C
+#define UPD61151_VMINRATE            0x30
+#define UPD61151_VMAXDEBT            0x34
+#define UPD61151_ASPR                0x38
+#define UPD61151_VIDEO_SYNC          0x54
+#define UPD61151_VIDEO_HOFFSET       0x58
+#define UPD61151_VIDEO_VOFFSET       0x5C
+#define UPD61151_AUDIO_INTERFACE     0x60
+#define UPD61151_VBI_ADJ1            0x74
+#define UPD61151_VBI_ADJ2            0x78
+#define UPD61151_TRANSFER_MODE       0x80
+#define UPD61151_TRANSFER_ADDR1      0x90
+#define UPD61151_TRANSFER_ADDR2      0x94
+#define UPD61151_TRANSFER_ADDR3      0x98
+#define UPD61151_DATA_COUNTER1       0x9C
+#define UPD61151_DATA_COUNTER2       0xA0
+#define UPD61151_DATA_COUNTER3       0xA4
+#define UPD61151_TRANSFER_IRQ        0xC0
+#define UPD61151_IRQ                 0xC4
+#define UPD61151_ERROR_IRQ           0xCC
+#define UPD61151_EXCEPT_IRQ          0xD0
+#define UPD61151_SDRAM_IF_DELAY_ADJ  0xDC
+#define UPD61151_SDRAM_FCLK_SEL      0xE0
+#define UPD61151_SDRAM_STANDBY       0xE8
+#define UPD61151_GPIO_CTRLS          0xF0
+#define UPD61151_SOFTWARE_RST        0xF8
+#define UPD61151_TRANSFER_DATA       0xFC
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
