All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: saa7134 and μPD61151 MPEG2 coder
       [not found]     ` <201001130838.23949.hverkuil@xs4all.nl>
@ 2010-01-27  5:36       ` Dmitri Belimov
  2010-01-27 11:14         ` Hans Verkuil
  2010-02-22 22:38         ` eb1a:2860 eMPIA em28xx device to usb1 ??? usb hub problem? j
  0 siblings, 2 replies; 14+ messages in thread
From: Dmitri Belimov @ 2010-01-27  5:36 UTC (permalink / raw)
  To: Hans Verkuil, Mauro Carvalho Chehab, linux-media, video4linux-list

[-- Attachment #1: Type: text/plain, Size: 7315 bytes --]

Hi Hans.

I finished saa7134 part of SPI. Please review saa7134-spi.c and diff saa7134-core and etc.
I wrote config of SPI to board structure. Use this config for register master and slave devices.

SPI other then I2C, do not need call request_module. Udev do it. 
I spend 10 days for understanding :(  

I need help with v4l2-common.c -> function v4l2_spi_new_subdev_board
The module of SPI slave loading after some time and spi device hasn't v4l2_subdev structure
for v4l2_device_register_subdev.

Now I get kernel crash when call v4l2_device_register_subdev.

Need use a callback metod or other. I don't know.

Copy to Mauro Carvalho Chehab and mailing lists for review my code too.

Dmesg log without call v4l2_device_register_subdev.
[    4.742279] Linux video capture interface: v2.00
[    4.816171] saa7130/34: v4l2 driver version 0.2.15 loaded
[    4.816253] saa7134 0000:04:01.0: PCI INT A -> GSI 19 (level, low) -> IRQ 19
[    4.816304] saa7133[0]: found at 0000:04:01.0, rev: 209, irq: 19, latency: 32, mmio: 0xe5100000
[    4.816363] saa7133[0]: subsystem: 5ace:7595, board: Beholder BeholdTV X7 [card=171,autodetected]
[    4.816430] saa7133[0]: board init: gpio is 200000
[    4.816481] IRQ 19/saa7133[0]: IRQF_DISABLED is not guaranteed on shared IRQs
[    4.976010] saa7133[0]: i2c eeprom 00: ce 5a 95 75 54 20 00 00 00 00 00 00 00 00 00 01
[    4.976635] saa7133[0]: i2c eeprom 10: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.977231] saa7133[0]: i2c eeprom 20: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.977827] saa7133[0]: i2c eeprom 30: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.978423] saa7133[0]: i2c eeprom 40: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.979019] saa7133[0]: i2c eeprom 50: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.979615] saa7133[0]: i2c eeprom 60: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.980223] saa7133[0]: i2c eeprom 70: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.980820] saa7133[0]: i2c eeprom 80: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.981416] saa7133[0]: i2c eeprom 90: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.982012] saa7133[0]: i2c eeprom a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.982608] saa7133[0]: i2c eeprom b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.983204] saa7133[0]: i2c eeprom c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.983800] saa7133[0]: i2c eeprom d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.984437] saa7133[0]: i2c eeprom e0: 00 00 00 00 ff ff ff ff ff ff ff ff ff ff ff ff
[    4.985033] saa7133[0]: i2c eeprom f0: 42 54 56 30 30 30 30 ff ff ff ff ff ff ff ff ff
[    5.008041] tuner 1-0061: chip found @ 0xc2 (saa7133[0])
[    5.024036] HDA Intel 0000:00:1b.0: PCI INT A -> GSI 16 (level, low) -> IRQ 16
[    5.024109] HDA Intel 0000:00:1b.0: setting latency timer to 64
[    5.066725] xc5000 1-0061: creating new instance
[    5.076009] xc5000: Successfully identified at address 0x61
[    5.076060] xc5000: Firmware has not been loaded previously

[   33.381216] saa7134 0000:04:01.0: spi master registered: bus_num=32766 num_chipselect=1
[   33.381274] saa7133[0]: found muPD61151 MPEG encoder
[   33.381430] saa7133[0]: registered device video0 [v4l2]
[   33.381491] saa7133[0]: registered device vbi0
[   33.381551] saa7133[0]: registered device radio0
[   33.406256] saa7133[0]: registered device video1 [mpeg]
[   33.407628] upd61151_probe function
[   33.407672] Read test REG 0xD8 :
[   33.409502] REG = 0x0
[   33.409547] Write test 0x03 to REG 0xD8 :
[   33.411353] Next read test REG 0xD8 :
[   33.413176] REG = 0x3
[   33.431308] saa7134 ALSA driver for DMA sound loaded
[   33.431363] IRQ 19/saa7133[0]: IRQF_DISABLED is not guaranteed on shared IRQs
[   33.431425] saa7133[0]/alsa: saa7133[0] at 0xe5100000 irq 19 registered as card -1

[   48.657067] xc5000: I2C write failed (len=4)
[   48.760018] xc5000: I2C write failed (len=4)
[   48.762960] xc5000: I2C read failed
[   48.763011] xc5000: I2C read failed
[   48.763054] xc5000: waiting for firmware upload (dvb-fe-xc5000-1.6.114.fw)...
[   48.763102] saa7134 0000:04:01.0: firmware: requesting dvb-fe-xc5000-1.6.114.fw
[   48.802473] xc5000: firmware read 12401 bytes.
[   48.802477] xc5000: firmware uploading...
[   49.328504] eth0: no IPv6 routers present
[   52.132007] xc5000: firmware upload complete...
[   53.366772] ------------[ cut here ]------------
[   53.366820] kernel BUG at lib/kernel_lock.c:126!
[   53.366865] invalid opcode: 0000 [#1] SMP 
[   53.366973] last sysfs file: /sys/class/firmware/0000:04:01.0/loading
[   53.367019] Modules linked in: ipv6 dm_snapshot dm_mirror dm_region_hash dm_log dm_mod loop saa7134_alsa upd61151 saa7134_empress ir_kbd_i2c snd_hda_codec_realtek xc5000 snd_hda_intel snd_hda_codec tuner snd_pcm_oss snd_mixer_oss snd_pcm snd_seq_dummy snd_seq_oss snd_seq_midi snd_rawmidi snd_seq_midi_event snd_seq saa7134 snd_timer ir_common v4l2_common videodev snd_seq_device v4l1_compat videobuf_dma_sg videobuf_core spi_bitbang psmouse snd ir_core serio_raw tveeprom soundcore parport_pc parport processor i2c_i801 button snd_page_alloc i2c_core intel_agp agpgart rng_core pcspkr evdev ext3 jbd mbcache sg sr_mod cdrom sd_mod ata_generic ata_piix libata scsi_mod ide_pci_generic ide_core ehci_hcd uhci_hcd r8169 mii usbcore thermal fan thermal_sys [last unloaded: scsi_wait_scan]
[   53.369624] 
[   53.369666] Pid: 2659, comm: hald-probe-vide Not tainted (2.6.30.5 #1) G31M-ES2L
[   53.369721] EIP: 0060:[<c02f81e3>] EFLAGS: 00010286 CPU: 0
[   53.369770] EIP is at unlock_kernel+0xd/0x24
[   53.369814] EAX: f6bc26ac EBX: f6bc2000 ECX: f6bc26ac EDX: f707e4d0
[   53.369860] ESI: 00000000 EDI: f6aa90c0 EBP: f6bc26ac ESP: f65b1e68
[   53.369906]  DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068
[   53.369952] Process hald-probe-vide (pid: 2659, ti=f65b0000 task=f707e4d0 task.ti=f65b0000)
[   53.370008] Stack:
[   53.370049]  f873e9c9 00000000 f687c804 f6aa90c0 00000000 f848e309 00000000 f6b4d680
[   53.370298]  f6b4d680 c0190049 f6aa90c0 f6a144e4 00000000 f6aa90c0 00000000 f6a144e4
[   53.370298]  c018ff24 c018c3b9 f701ef40 f6d11a5c f6aa90c0 f65b1f0c f65b1f0c 00008001
[   53.370298] Call Trace:
[   53.370298]  [<f873e9c9>] ? ts_open+0x8c/0x93 [saa7134_empress]
[   53.370298]  [<f848e309>] ? v4l2_open+0x65/0x78 [videodev]
[   53.370298]  [<c0190049>] ? chrdev_open+0x125/0x13c
[   53.370298]  [<c018ff24>] ? chrdev_open+0x0/0x13c
[   53.370298]  [<c018c3b9>] ? __dentry_open+0x119/0x208
[   53.370298]  [<c018c539>] ? nameidata_to_filp+0x29/0x3c
[   53.370298]  [<c0197338>] ? do_filp_open+0x41e/0x7bc
[   53.370298]  [<c017bb3c>] ? handle_mm_fault+0x294/0x5fd
[   53.370298]  [<c019e267>] ? alloc_fd+0x52/0xb8
[   53.370298]  [<c018c1d1>] ? do_sys_open+0x44/0xb4
[   53.370298]  [<c018c285>] ? sys_open+0x1e/0x23
[   53.370298]  [<c0102f74>] ? sysenter_do_call+0x12/0x28
[   53.370298] Code: 0f c1 05 e0 4b 3e c0 38 e0 74 09 f3 90 a0 e0 4b 3e c0 eb f3 64 a1 00 b0 43 c0 89 50 14 c3 64 8b 15 00 b0 43 c0 83 7a 14 00 79 04 <0f> 0b eb fe 8b 42 14 48 85 c0 89 42 14 79 07 f0 fe 05 e0 4b 3e 
[   53.370298] EIP: [<c02f81e3>] unlock_kernel+0xd/0x24 SS:ESP 0068:f65b1e68
[   53.374302] ---[ end trace 05965e9e089c46c7 ]---


With my best regards, Dmitry.

[-- Attachment #2: behold_spi.diff --]
[-- Type: text/x-patch, Size: 13592 bytes --]

diff -r b6b82258cf5e linux/drivers/media/video/saa7134/Makefile
--- a/linux/drivers/media/video/saa7134/Makefile	Thu Dec 31 19:14:54 2009 -0200
+++ b/linux/drivers/media/video/saa7134/Makefile	Wed Jan 27 07:54:50 2010 +0900
@@ -1,9 +1,9 @@
 
 saa7134-objs :=	saa7134-cards.o saa7134-core.o saa7134-i2c.o	\
 		saa7134-ts.o saa7134-tvaudio.o saa7134-vbi.o    \
-		saa7134-video.o saa7134-input.o
+		saa7134-video.o saa7134-input.o saa7134-spi.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 -r b6b82258cf5e linux/drivers/media/video/saa7134/saa7134-cards.c
--- a/linux/drivers/media/video/saa7134/saa7134-cards.c	Thu Dec 31 19:14:54 2009 -0200
+++ b/linux/drivers/media/video/saa7134/saa7134-cards.c	Wed Jan 27 07:54:50 2010 +0900
@@ -4619,6 +4619,7 @@
 			.name = name_radio,
 			.amux = LINE2,
 		},
+		.encoder_type = SAA7134_ENCODER_SAA6752HS,
 		.mpeg  = SAA7134_MPEG_EMPRESS,
 		.video_out = CCIR656,
 		.vid_port_opts  = (SET_T_CODE_POLARITY_NON_INVERTED |
@@ -4656,6 +4657,7 @@
 			.name = name_radio,
 			.amux = LINE2,
 		},
+		.encoder_type = SAA7134_ENCODER_SAA6752HS,
 		.mpeg  = SAA7134_MPEG_EMPRESS,
 		.video_out = CCIR656,
 		.vid_port_opts  = (SET_T_CODE_POLARITY_NON_INVERTED |
@@ -4695,6 +4697,7 @@
 			.name = name_radio,
 			.amux = LINE2,
 		},
+		.encoder_type = SAA7134_ENCODER_SAA6752HS,
 		.mpeg  = SAA7134_MPEG_EMPRESS,
 		.video_out = CCIR656,
 		.vid_port_opts  = (SET_T_CODE_POLARITY_NON_INVERTED |
@@ -5279,23 +5282,51 @@
 		.tuner_addr     = ADDR_UNSET,
 		.radio_addr     = ADDR_UNSET,
 		.mpeg           = SAA7134_MPEG_DVB,
+		.gpiomask       = 0x00860000,
 		.inputs         = { {
 			.name = name_tv,
 			.vmux = 2,
 			.amux = TV,
 			.tv   = 1,
-		}, {
-			.name = name_comp1,
-			.vmux = 0,
-			.amux = LINE1,
+			.gpio = 0x00860000
+		}, {
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE1,
+			.gpio = 0x00860000
 		}, {
 			.name = name_svideo,
 			.vmux = 9,
 			.amux = LINE1,
-		} },
-		.radio = {
-			.name = name_radio,
-			.amux = TV,
+			.gpio = 0x00860000
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = TV,
+			.gpio = 0x00860000
+		},
+		.encoder_type = SAA7134_ENCODER_muPD61151,
+		.mpeg  = SAA7134_MPEG_EMPRESS,
+		.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,
+		},
+		.spi_conf = {
+			.modalias	= "upd61151",
+			.max_speed_hz	= 10000000,
+			.chip_select	= 0,
+			.mode		= SPI_MODE_0,
+			.controller_data = NULL,
+			.platform_data  = NULL,
 		},
 	},
 	[SAA7134_BOARD_ZOLID_HYBRID_PCI] = {
diff -r b6b82258cf5e linux/drivers/media/video/saa7134/saa7134-core.c
--- a/linux/drivers/media/video/saa7134/saa7134-core.c	Thu Dec 31 19:14:54 2009 -0200
+++ b/linux/drivers/media/video/saa7134/saa7134-core.c	Wed Jan 27 07:54:50 2010 +0900
@@ -139,6 +139,18 @@
 		break;
 	}
 }
+
+unsigned long 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;
+}
+
 
 /* ------------------------------------------------------------------ */
 
@@ -1057,12 +1069,42 @@
 
 	saa7134_hwinit2(dev);
 
-	/* load i2c helpers */
+	/* initialize software SPI bus */
+	if (saa7134_boards[dev->board].spi.spi_enable)
+	{
+		dev->spi = saa7134_boards[dev->board].spi;
+
+		/* register SPI master and SPI slave */
+		if (saa7134_spi_register(dev, &saa7134_boards[dev->board].spi_conf))
+			saa7134_boards[dev->board].spi.spi_enable = 0;
+	}
+
+	/* 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 (saa7134_boards[dev->board].spi.spi_enable)
+				sd = v4l2_spi_new_subdev(&dev->v4l2_dev, dev->spi_adap, &saa7134_boards[dev->board].spi_conf);
+		}
+			break;
+		case SAA7134_ENCODER_SAA6752HS:
+		{
+			sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
 				"saa6752hs", "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;
@@ -1139,6 +1181,8 @@
 	return 0;
 
  fail4:
+	if ((card_is_empress(dev)) && (dev->encoder_type == SAA7134_ENCODER_muPD61151))
+		saa7134_spi_unregister(dev);
 	saa7134_unregister_video(dev);
 	saa7134_i2c_unregister(dev);
 	free_irq(pci_dev->irq, dev);
@@ -1412,6 +1456,7 @@
 /* ----------------------------------------------------------- */
 
 EXPORT_SYMBOL(saa7134_set_gpio);
+EXPORT_SYMBOL(saa7134_get_gpio);
 EXPORT_SYMBOL(saa7134_boards);
 
 /* ----------------- for the DMA sound modules --------------- */
diff -r b6b82258cf5e linux/drivers/media/video/saa7134/saa7134.h
--- a/linux/drivers/media/video/saa7134/saa7134.h	Thu Dec 31 19:14:54 2009 -0200
+++ b/linux/drivers/media/video/saa7134/saa7134.h	Wed Jan 27 07:54:50 2010 +0900
@@ -30,6 +30,13 @@
 #include <linux/notifier.h>
 #include <linux/delay.h>
 #include <linux/mutex.h>
+
+/* ifdef software SPI insert here start */
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_gpio.h>
+#include <linux/spi/spi_bitbang.h>
+/* ifdef software SPI insert here stop */
 
 #include <asm/io.h>
 
@@ -337,6 +344,21 @@
 	SAA7134_MPEG_TS_SERIAL,
 };
 
+enum saa7134_encoder_type {
+	SAA7134_ENCODER_UNUSED,
+	SAA7134_ENCODER_SAA6752HS,
+	SAA7134_ENCODER_muPD61151,
+};
+
+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 {
 	char                    *name;
 	unsigned int            audio_clock;
@@ -355,6 +377,10 @@
 	unsigned char		empress_addr;
 	unsigned char		rds_addr;
 
+	/* SPI info */
+	struct saa7134_software_spi	spi;
+	struct spi_board_info   spi_conf;
+
 	unsigned int            tda9887_conf;
 	unsigned int            tuner_config;
 
@@ -362,6 +388,7 @@
 	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;
 };
@@ -506,6 +533,12 @@
 	void                       (*signal_change)(struct saa7134_dev *dev);
 };
 
+struct saa7134_spi_gpio {
+	struct spi_bitbang         bitbang;
+	struct spi_master          *master;
+	struct saa7134_dev         *controller_data;
+};
+
 /* global device status */
 struct saa7134_dev {
 	struct list_head           devlist;
@@ -553,6 +586,10 @@
 	struct i2c_client          i2c_client;
 	unsigned char              eedata[256];
 	int 			   has_rds;
+
+	/* software spi */
+	struct saa7134_software_spi spi;
+	struct spi_master          *spi_adap;
 
 	/* video overlay */
 	struct v4l2_framebuffer    ovbuf;
@@ -615,6 +652,7 @@
 	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 */
@@ -681,6 +719,7 @@
 
 void saa7134_track_gpio(struct saa7134_dev *dev, char *msg);
 void saa7134_set_gpio(struct saa7134_dev *dev, int bit_no, int value);
+unsigned long saa7134_get_gpio(struct saa7134_dev *dev);
 
 #define SAA7134_PGTABLE_SIZE 4096
 
@@ -726,6 +765,11 @@
 int saa7134_i2c_register(struct saa7134_dev *dev);
 int saa7134_i2c_unregister(struct saa7134_dev *dev);
 
+/* ----------------------------------------------------------- */
+/* saa7134-spi.c                                               */
+
+int saa7134_spi_register(struct saa7134_dev *dev, struct spi_board_info *info);
+int saa7134_spi_unregister(struct saa7134_dev *dev);
 
 /* ----------------------------------------------------------- */
 /* saa7134-video.c                                             */
diff -r b6b82258cf5e linux/drivers/media/video/v4l2-common.c
--- a/linux/drivers/media/video/v4l2-common.c	Thu Dec 31 19:14:54 2009 -0200
+++ b/linux/drivers/media/video/v4l2-common.c	Wed Jan 27 07:54:50 2010 +0900
@@ -51,6 +51,7 @@
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/i2c.h>
+#include <linux/spi/spi.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/pgtable.h>
@@ -1069,6 +1070,87 @@
 
 #endif /* defined(CONFIG_I2C) */
 
+//#if defined(CONFIG_SPI) || (defined(CONFIG_SPI_MODULE) && defined(MODULE)) + SPI_BITBANG
+
+/* Load an spi sub-device. */
+
+void v4l2_spi_subdev_init(struct v4l2_subdev *sd, struct spi_device *spi,
+		const struct v4l2_subdev_ops *ops)
+{
+	v4l2_subdev_init(sd, ops);
+	sd->flags |= V4L2_SUBDEV_FL_IS_SPI;
+	/* the owner is the same as the spi_device's driver owner */
+	sd->owner = spi->dev.driver->owner;
+	/* spi_device and v4l2_subdev point to one another */
+	v4l2_set_subdevdata(sd, spi);
+	dev_set_drvdata(&spi->dev, sd);
+	/* initialize name */
+	snprintf(sd->name, sizeof(sd->name), "%s",
+		spi->dev.driver->name);
+}
+EXPORT_SYMBOL_GPL(v4l2_spi_subdev_init);
+
+struct v4l2_subdev *v4l2_spi_new_subdev_board(struct v4l2_device *v4l2_dev,
+		struct spi_master *spi, struct spi_board_info *info)
+{
+	struct v4l2_subdev *sd = NULL;
+
+	BUG_ON(!v4l2_dev);
+
+	if (spi == NULL)
+		goto error;
+
+	spi_new_device(spi,info);
+
+#if 0
+	if (module_name)
+		request_module(module_name);
+
+	if (!try_module_get(spi->dev.driver->owner))
+		goto error;
+
+	sd = dev_get_drvdata(&spi->dev);
+
+	/* Register with the v4l2_device which increases the module's
+	   use count as well. */
+
+	if (v4l2_device_register_subdev(v4l2_dev, sd))
+		sd = NULL;
+
+	/* Decrease the module use count to match the first try_module_get. */
+	module_put(spi->dev.driver->owner);
+#endif
+error:
+	/* If we have a client but no subdev, then something went wrong and
+	   we must unregister the client. */
+#if 0
+	if (spi && sd == NULL)
+		spi_unregister_device(spi);
+#endif
+	return sd;
+}
+EXPORT_SYMBOL_GPL(v4l2_spi_new_subdev_board);
+
+struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev,
+		struct spi_master *spi, struct spi_board_info *spi_slave)
+{
+	struct spi_board_info info;
+
+	memset(&info, 0, sizeof(info));
+	strlcpy(info.modalias,spi_slave->modalias,sizeof(info.modalias));
+	info.max_speed_hz = spi_slave->max_speed_hz;
+	info.chip_select = spi_slave->chip_select;
+	info.mode = spi_slave->mode;
+	info.bus_num = spi_slave->bus_num;
+	info.platform_data = spi_slave->platform_data;
+	info.controller_data = spi_slave->controller_data;
+
+	return v4l2_spi_new_subdev_board(v4l2_dev, spi, &info);
+}
+EXPORT_SYMBOL_GPL(v4l2_spi_new_subdev);
+
+//#endif /* defined(CONFIG_SPI) */
+
 /* Clamp x to be between min and max, aligned to a multiple of 2^align.  min
  * and max don't have to be aligned, but there must be at least one valid
  * value.  E.g., min=17,max=31,align=4 is not allowed as there are no multiples
diff -r b6b82258cf5e linux/include/media/v4l2-common.h
--- a/linux/include/media/v4l2-common.h	Thu Dec 31 19:14:54 2009 -0200
+++ b/linux/include/media/v4l2-common.h	Wed Jan 27 07:54:50 2010 +0900
@@ -191,6 +191,28 @@
 
 /* ------------------------------------------------------------------------- */
 
+/* SPI Helper functions */
+
+#include <linux/spi/spi.h>
+
+struct spi_device_id;
+struct spi_device;
+
+/* Load an spi module and return an initialized v4l2_subdev struct.
+   Only call request_module if module_name != NULL.
+   The client_type argument is the name of the chip that's on the adapter. */
+struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev,
+		struct spi_master *spi, struct spi_board_info *spi_slave);
+
+struct v4l2_subdev *v4l2_spi_new_subdev_board(struct v4l2_device *v4l2_dev,
+		struct spi_master *spi, struct spi_board_info *info);
+
+/* Initialize an v4l2_subdev with data from an spi_device struct */
+void v4l2_spi_subdev_init(struct v4l2_subdev *sd, struct spi_device *spi,
+		const struct v4l2_subdev_ops *ops);
+
+/* ------------------------------------------------------------------------- */
+
 /* Note: these remaining ioctls/structs should be removed as well, but they are
    still used in tuner-simple.c (TUNER_SET_CONFIG), cx18/ivtv (RESET) and
    v4l2-int-device.h (v4l2_routing). To remove these ioctls some more cleanup
diff -r b6b82258cf5e linux/include/media/v4l2-subdev.h
--- a/linux/include/media/v4l2-subdev.h	Thu Dec 31 19:14:54 2009 -0200
+++ b/linux/include/media/v4l2-subdev.h	Wed Jan 27 07:54:50 2010 +0900
@@ -387,6 +387,8 @@
 
 /* Set this flag if this subdev is a i2c device. */
 #define V4L2_SUBDEV_FL_IS_I2C (1U << 0)
+/* Set this flag if this subdev is a spi device. */
+#define V4L2_SUBDEV_FL_IS_SPI (1U << 1)
 
 /* Each instance of a subdev driver should create this struct, either
    stand-alone or embedded in a larger struct.

[-- Attachment #3: dmesg.log --]
[-- Type: text/x-log, Size: 6544 bytes --]

[    4.742279] Linux video capture interface: v2.00
[    4.816171] saa7130/34: v4l2 driver version 0.2.15 loaded
[    4.816253] saa7134 0000:04:01.0: PCI INT A -> GSI 19 (level, low) -> IRQ 19
[    4.816304] saa7133[0]: found at 0000:04:01.0, rev: 209, irq: 19, latency: 32, mmio: 0xe5100000
[    4.816363] saa7133[0]: subsystem: 5ace:7595, board: Beholder BeholdTV X7 [card=171,autodetected]
[    4.816430] saa7133[0]: board init: gpio is 200000
[    4.816481] IRQ 19/saa7133[0]: IRQF_DISABLED is not guaranteed on shared IRQs
[    4.976010] saa7133[0]: i2c eeprom 00: ce 5a 95 75 54 20 00 00 00 00 00 00 00 00 00 01
[    4.976635] saa7133[0]: i2c eeprom 10: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.977231] saa7133[0]: i2c eeprom 20: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.977827] saa7133[0]: i2c eeprom 30: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.978423] saa7133[0]: i2c eeprom 40: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.979019] saa7133[0]: i2c eeprom 50: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.979615] saa7133[0]: i2c eeprom 60: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.980223] saa7133[0]: i2c eeprom 70: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.980820] saa7133[0]: i2c eeprom 80: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.981416] saa7133[0]: i2c eeprom 90: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.982012] saa7133[0]: i2c eeprom a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.982608] saa7133[0]: i2c eeprom b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.983204] saa7133[0]: i2c eeprom c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.983800] saa7133[0]: i2c eeprom d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.984437] saa7133[0]: i2c eeprom e0: 00 00 00 00 ff ff ff ff ff ff ff ff ff ff ff ff
[    4.985033] saa7133[0]: i2c eeprom f0: 42 54 56 30 30 30 30 ff ff ff ff ff ff ff ff ff
[    5.008041] tuner 1-0061: chip found @ 0xc2 (saa7133[0])
[    5.024036] HDA Intel 0000:00:1b.0: PCI INT A -> GSI 16 (level, low) -> IRQ 16
[    5.024109] HDA Intel 0000:00:1b.0: setting latency timer to 64
[    5.066725] xc5000 1-0061: creating new instance
[    5.076009] xc5000: Successfully identified at address 0x61
[    5.076060] xc5000: Firmware has not been loaded previously

[   33.381216] saa7134 0000:04:01.0: spi master registered: bus_num=32766 num_chipselect=1
[   33.381274] saa7133[0]: found muPD61151 MPEG encoder
[   33.381430] saa7133[0]: registered device video0 [v4l2]
[   33.381491] saa7133[0]: registered device vbi0
[   33.381551] saa7133[0]: registered device radio0
[   33.406256] saa7133[0]: registered device video1 [mpeg]
[   33.407628] upd61151_probe function
[   33.407672] Read test REG 0xD8 :
[   33.409502] REG = 0x0
[   33.409547] Write test 0x03 to REG 0xD8 :
[   33.411353] Next read test REG 0xD8 :
[   33.413176] REG = 0x3
[   33.431308] saa7134 ALSA driver for DMA sound loaded
[   33.431363] IRQ 19/saa7133[0]: IRQF_DISABLED is not guaranteed on shared IRQs
[   33.431425] saa7133[0]/alsa: saa7133[0] at 0xe5100000 irq 19 registered as card -1

[   48.657067] xc5000: I2C write failed (len=4)
[   48.760018] xc5000: I2C write failed (len=4)
[   48.762960] xc5000: I2C read failed
[   48.763011] xc5000: I2C read failed
[   48.763054] xc5000: waiting for firmware upload (dvb-fe-xc5000-1.6.114.fw)...
[   48.763102] saa7134 0000:04:01.0: firmware: requesting dvb-fe-xc5000-1.6.114.fw
[   48.802473] xc5000: firmware read 12401 bytes.
[   48.802477] xc5000: firmware uploading...
[   49.328504] eth0: no IPv6 routers present
[   52.132007] xc5000: firmware upload complete...
[   53.366772] ------------[ cut here ]------------
[   53.366820] kernel BUG at lib/kernel_lock.c:126!
[   53.366865] invalid opcode: 0000 [#1] SMP 
[   53.366973] last sysfs file: /sys/class/firmware/0000:04:01.0/loading
[   53.367019] Modules linked in: ipv6 dm_snapshot dm_mirror dm_region_hash dm_log dm_mod loop saa7134_alsa upd61151 saa7134_empress ir_kbd_i2c snd_hda_codec_realtek xc5000 snd_hda_intel snd_hda_codec tuner snd_pcm_oss snd_mixer_oss snd_pcm snd_seq_dummy snd_seq_oss snd_seq_midi snd_rawmidi snd_seq_midi_event snd_seq saa7134 snd_timer ir_common v4l2_common videodev snd_seq_device v4l1_compat videobuf_dma_sg videobuf_core spi_bitbang psmouse snd ir_core serio_raw tveeprom soundcore parport_pc parport processor i2c_i801 button snd_page_alloc i2c_core intel_agp agpgart rng_core pcspkr evdev ext3 jbd mbcache sg sr_mod cdrom sd_mod ata_generic ata_piix libata scsi_mod ide_pci_generic ide_core ehci_hcd uhci_hcd r8169 mii usbcore thermal fan thermal_sys [last unloaded: scsi_wait_scan]
[   53.369624] 
[   53.369666] Pid: 2659, comm: hald-probe-vide Not tainted (2.6.30.5 #1) G31M-ES2L
[   53.369721] EIP: 0060:[<c02f81e3>] EFLAGS: 00010286 CPU: 0
[   53.369770] EIP is at unlock_kernel+0xd/0x24
[   53.369814] EAX: f6bc26ac EBX: f6bc2000 ECX: f6bc26ac EDX: f707e4d0
[   53.369860] ESI: 00000000 EDI: f6aa90c0 EBP: f6bc26ac ESP: f65b1e68
[   53.369906]  DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068
[   53.369952] Process hald-probe-vide (pid: 2659, ti=f65b0000 task=f707e4d0 task.ti=f65b0000)
[   53.370008] Stack:
[   53.370049]  f873e9c9 00000000 f687c804 f6aa90c0 00000000 f848e309 00000000 f6b4d680
[   53.370298]  f6b4d680 c0190049 f6aa90c0 f6a144e4 00000000 f6aa90c0 00000000 f6a144e4
[   53.370298]  c018ff24 c018c3b9 f701ef40 f6d11a5c f6aa90c0 f65b1f0c f65b1f0c 00008001
[   53.370298] Call Trace:
[   53.370298]  [<f873e9c9>] ? ts_open+0x8c/0x93 [saa7134_empress]
[   53.370298]  [<f848e309>] ? v4l2_open+0x65/0x78 [videodev]
[   53.370298]  [<c0190049>] ? chrdev_open+0x125/0x13c
[   53.370298]  [<c018ff24>] ? chrdev_open+0x0/0x13c
[   53.370298]  [<c018c3b9>] ? __dentry_open+0x119/0x208
[   53.370298]  [<c018c539>] ? nameidata_to_filp+0x29/0x3c
[   53.370298]  [<c0197338>] ? do_filp_open+0x41e/0x7bc
[   53.370298]  [<c017bb3c>] ? handle_mm_fault+0x294/0x5fd
[   53.370298]  [<c019e267>] ? alloc_fd+0x52/0xb8
[   53.370298]  [<c018c1d1>] ? do_sys_open+0x44/0xb4
[   53.370298]  [<c018c285>] ? sys_open+0x1e/0x23
[   53.370298]  [<c0102f74>] ? sysenter_do_call+0x12/0x28
[   53.370298] Code: 0f c1 05 e0 4b 3e c0 38 e0 74 09 f3 90 a0 e0 4b 3e c0 eb f3 64 a1 00 b0 43 c0 89 50 14 c3 64 8b 15 00 b0 43 c0 83 7a 14 00 79 04 <0f> 0b eb fe 8b 42 14 48 85 c0 89 42 14 79 07 f0 fe 05 e0 4b 3e 
[   53.370298] EIP: [<c02f81e3>] unlock_kernel+0xd/0x24 SS:ESP 0068:f65b1e68
[   53.374302] ---[ end trace 05965e9e089c46c7 ]---

[-- Attachment #4: saa7134-spi.c --]
[-- Type: text/x-c++src, Size: 4869 bytes --]

/*
 *
 * 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.
 */

#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)
{
	udelay(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);
	if ( status & (1 << sb->controller_data->spi.miso))
		return 1;
	else
		return 0;
}

#define EXPAND_BITBANG_TXRX 1
#include <linux/spi/spi_bitbang.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, word, bits);
}

static int saa7134_setup(struct spi_device *spi, struct spi_transfer *t)
{
	return spi_bitbang_setup_transfer(spi, t);
}

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;
	sb->bitbang.setup_transfer = saa7134_setup;

	/* 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;
}

int 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);

	return 0;
}


/*
 * Overrides for Emacs so that we follow Linus's tabbing style.
 * ---------------------------------------------------------------------------
 * Local variables:
 * c-basic-offset: 8
 * End:
 */
 

[-- Attachment #5: upd61151.c --]
[-- Type: text/x-c++src, Size: 9458 bytes --]

 /*
    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 <linux/mod_devicetable.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 MPEG_VIDEO_TARGET_BITRATE_MAX  27000
#define MPEG_VIDEO_MAX_BITRATE_MAX     27000
#define MPEG_TOTAL_TARGET_BITRATE_MAX  27000
#define MPEG_PID_MAX ((1 << 14) - 1)

#define DRVNAME		"upd61151"

MODULE_DESCRIPTION("device driver for uPD61151 MPEG2 encoder");
MODULE_AUTHOR("Dmitry V Belimov");
MODULE_LICENSE("GPL");

enum upd61151_videoformat {
	UPD61151_VF_D1 = 0,    /* standard D1 video format: 720x576 */
	UPD61151_VF_2_3_D1 = 1,/* 2/3D1 video format: 480x576 */
	UPD61151_VF_1_2_D1 = 2,/* 1/2D1 video format: 352x576 */
	UPD61151_VF_SIF = 3,   /* SIF video format: 352x288 */
	UPD61151_VF_UNKNOWN,
};

struct upd61151_mpeg_params {
	/* transport streams */
	__u16				ts_pid_pmt;
	__u16				ts_pid_audio;
	__u16				ts_pid_video;
	__u16				ts_pid_pcr;

	/* audio */
	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;
};

static const struct v4l2_format v4l2_format_table[] =
{
	[UPD61151_VF_D1] =
		{ .fmt = { .pix = { .width = 720, .height = 576 }}},
	[UPD61151_VF_2_3_D1] =
		{ .fmt = { .pix = { .width = 480, .height = 576 }}},
	[UPD61151_VF_1_2_D1] =
		{ .fmt = { .pix = { .width = 352, .height = 576 }}},
	[UPD61151_VF_SIF] =
		{ .fmt = { .pix = { .width = 352, .height = 288 }}},
	[UPD61151_VF_UNKNOWN] =
		{ .fmt = { .pix = { .width = 0, .height = 0}}},
};

struct upd61151_state {
	struct v4l2_subdev            sd;
//	struct spi_board_info         info;
	int 			      chip;
	u32 			      revision;
	struct upd61151_mpeg_params   params;
	enum upd61151_videoformat     video_format;
	v4l2_std_id                   standard;
};

enum upd61151_command {
	UPD61151_COMMAND_RESET = 0,
	UPD61151_COMMAND_STOP = 1,
	UPD61151_COMMAND_START = 2,
	UPD61151_COMMAND_PAUSE = 3,
	UPD61151_COMMAND_RECONFIGURE = 4,
	UPD61151_COMMAND_SLEEP = 5,
	UPD61151_COMMAND_RECONFIGURE_FORCE = 6,

	UPD61151_COMMAND_MAX
};


#if 0
static int write_reg( ??struct device *dev??, int address, unsigned char data)
{
	struct spi_device *spi = to_spi_device(dev);
	unsigned char buf[2];

	buf[0] = address & 0x7f;
	buf[1] = data;

	return spi_write(spi, buf, ARRAY_SIZE(buf));
}

static int read_regs( ??struct device *dev??, unsigned char *regs, int no_regs)
{
	struct spi_device *spi = to_spi_device(dev);
	u8 txbuf[1], rxbuf[1];
	int k, ret;

	ret = 0;

	for (k = 0; ret == 0 && k < no_regs; k++) {
		txbuf[0] = 0x80 | regs[k];
		ret = spi_write_then_read(spi, txbuf, 1, rxbuf, 1);
		regs[k] = rxbuf[0];
	}

	return ret;
}
#endif

static struct upd61151_mpeg_params param_defaults =
{
	.ts_pid_pmt      = 16,
	.ts_pid_video    = 260,
	.ts_pid_audio    = 256,
	.ts_pid_pcr      = 259,

	.vi_aspect       = V4L2_MPEG_VIDEO_ASPECT_4x3,
	.vi_bitrate      = 4000,
	.vi_bitrate_peak = 6000,
	.vi_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,

	.au_encoding     = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
	.au_l2_bitrate   = V4L2_MPEG_AUDIO_L2_BITRATE_256K,
};

#if 0
static int upd61151_chip_command(struct spi_device *spi,
				  enum upd61151_command command)
{
printk("DEBUG uPD61151: upd61151_chip_command\n");
	return 0;
}

static int upd61151_set_bitrate(struct spi_device *spi,
				 struct upd61151_state *h)
{
printk("DEBUG uPD61151: upd61151_set_bitrate\n");
	return 0;
}
#endif

static int upd61151_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qctrl)
{
printk("DEBUG uPD61151: upd61151_queryctrl\n");
	return 0;
}

static int upd61151_querymenu(struct v4l2_subdev *sd, struct v4l2_querymenu *qmenu)
{
printk("DEBUG uPD61151: upd61151_querymenu\n");
	return 0;
}

static int upd61151_init(struct v4l2_subdev *sd, u32 flags)
{
printk("DEBUG uPD61151: upd61151_init\n");
	return 0;
}

static int upd61151_do_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls, int set)
{
printk("DEBUG uPD61151: upd61151_do_ext_ctrls\n");
	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)
{
printk("DEBUG uPD61151: upd61151_g_ext_ctrls\n");
	return 0;
}

static int upd61151_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
{
printk("DEBUG uPD61151: upd61151_g_fmt\n");
	return 0;
}

static int upd61151_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
{
printk("DEBUG uPD61151: upd61151_s_fmt\n");
	return 0;
}

static int upd61151_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
{
printk("DEBUG uPD61151: upd61151_s_std\n");
	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");
	return 0;
}

/* ----------------------------------------------------------------------- */

static const struct v4l2_subdev_core_ops upd61151_core_ops = {
	.g_chip_ident = upd61151_g_chip_ident,
	.init = upd61151_init,
	.queryctrl = upd61151_queryctrl,
	.querymenu = upd61151_querymenu,
	.g_ext_ctrls = upd61151_g_ext_ctrls,
	.s_ext_ctrls = upd61151_s_ext_ctrls,
	.try_ext_ctrls = upd61151_try_ext_ctrls,
	.s_std = upd61151_s_std,
};

static const struct v4l2_subdev_video_ops upd61151_video_ops = {
	.s_fmt = upd61151_s_fmt,
	.g_fmt = upd61151_g_fmt,
};

static const struct v4l2_subdev_ops upd61151_ops = {
	.core = &upd61151_core_ops,
	.video = &upd61151_video_ops,
};

static int __devinit upd61151_probe(struct spi_device *spi)
{
	struct upd61151_state *h = kzalloc(sizeof(*h), GFP_KERNEL);
	struct v4l2_subdev *sd;
	u8 tx_buf_r[2];
	u8 tx_buf_w[2];
	u8 rx_buf[2];
	int status;

printk("upd61151_probe function\n");

printk("Read test REG 0xD8 :\n");
	tx_buf_r[0] = ((0xD8 >> 2) << 2) | 0x02;

	status = spi_write_then_read(spi, tx_buf_r, 1, rx_buf, 1);
	if (status < 0) {
		printk("spi_write_then_read failed with status %d\n",
				status);
//		goto out;
	}

printk("REG = 0x%X\n",rx_buf[0]);

printk("Write test 0x03 to REG 0xD8 :\n");

	tx_buf_w[0] = ((0xD8 >> 2) << 2);
	tx_buf_w[1] = 0x03;
	spi_write(spi, tx_buf_w, 2);

printk("Next read test REG 0xD8 :\n");

	status = spi_write_then_read(spi, tx_buf_r, 1, rx_buf, 1);
	if (status < 0) {
		printk("spi_write_then_read failed with status %d\n",
				status);
//		goto out;
	}

printk("REG = 0x%X\n",rx_buf[0]);

	if (h == NULL)
		return -ENOMEM;
	sd = &h->sd;
//	v4l2_spi_subdev_init(sd, spi, &upd61151_ops);

	spi_set_drvdata(spi, h);

/* function for detect a chip here */
//	h->chip = upd61151_detect(h);

	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->sd);
	spi_unregister_device(spi);
	return 0;
}

#if 0
static const struct spi_device_id upd61151_ids[] = {
	{ "upd61151", 1 },
	{ "upd61152", 2 },
	{ },
};
MODULE_DEVICE_TABLE(spi, upd61151_ids);
#endif

static struct spi_driver upd61151_driver = {
	.driver = {
		.name   = DRVNAME,
		.bus    = &spi_bus_type,
		.owner  = THIS_MODULE,
	},
//	.id_table = upd61151_ids,
	.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);

/*
 * Overrides for Emacs so that we follow Linus's tabbing style.
 * ---------------------------------------------------------------------------
 * Local variables:
 * c-basic-offset: 8
 * End:
 */

[-- Attachment #6: upd61151.h --]
[-- Type: text/x-chdr, Size: 2276 bytes --]

/*
    upd61151.h - definition for muPD61151 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.
*/

#if 0 /* ndef _UPD61151_H */
#define _UPD61151_H

#include <linux/firmware.h>

#define MUPD61151_DEFAULT_PS_FIRMWARE "D61151_PS_64_byte_7133_v22_031031.bin"
#define MUPD61151_DEFAULT_PS_FIRMWARE_SIZE 97002

#define MUPD61151_DEFAULT_AUDIO_FIRMWARE "audrey_MPE_V1r51.bin"
#define MUPD61151_DEFAULT_AUDIO_FIRMWARE_SIZE 40064

enum mpeg_video_bitrate_mode {
	MPEG_VIDEO_BITRATE_MODE_VBR = 0, /* Variable bitrate */
	MPEG_VIDEO_BITRATE_MODE_CBR = 1, /* Constant bitrate */

	MPEG_VIDEO_BITRATE_MODE_MAX
};

enum mpeg_audio_bitrate {
	MPEG_AUDIO_BITRATE_256 = 0, /* 256 kBit/sec */
	MPEG_AUDIO_BITRATE_384 = 1, /* 384 kBit/sec */

	MPEG_AUDIO_BITRATE_MAX
};

enum mpeg_video_format {
	MPEG_VIDEO_FORMAT_D1 = 0,
	MPEG_VIDEO_FORMAT_2_3_D1 = 1,
	MPEG_VIDEO_FORMAT_1_2_D1 = 2,
	MPEG_VIDEO_FORMAT_SIF = 3,

	MPEG_VIDEO_FORMAT_MAX
};

#define MPEG_VIDEO_TARGET_BITRATE_MAX 27000
#define MPEG_VIDEO_MAX_BITRATE_MAX 27000
#define MPEG_TOTAL_BITRATE_MAX 27000
#define MPEG_PID_MAX ((1 << 14) - 1)

struct mpeg_params {
	enum mpeg_video_bitrate_mode video_bitrate_mode;
	unsigned int video_target_bitrate;
	unsigned int video_max_bitrate; // only used for VBR
	enum mpeg_audio_bitrate audio_bitrate;
	unsigned int total_bitrate;

	unsigned int pmt_pid;
	unsigned int video_pid;
	unsigned int audio_pid;
	unsigned int pcr_pid;

	enum mpeg_video_format video_format;
};

#endif // _UPD61151_H

/*
 * Local variables:
 * c-basic-offset: 8
 * End:
 */

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: saa7134 and μPD61151 MPEG2 coder
  2010-01-27  5:36       ` saa7134 and μPD61151 MPEG2 coder Dmitri Belimov
@ 2010-01-27 11:14         ` Hans Verkuil
  2010-01-28  2:09           ` Dmitri Belimov
  2010-02-22 22:38         ` eb1a:2860 eMPIA em28xx device to usb1 ??? usb hub problem? j
  1 sibling, 1 reply; 14+ messages in thread
From: Hans Verkuil @ 2010-01-27 11:14 UTC (permalink / raw)
  To: Dmitri Belimov; +Cc: Mauro Carvalho Chehab, linux-media

Hi Dmitri,

Just a quick note: the video4linux mailinglist is obsolete, just use linux-media.

On Wednesday 27 January 2010 06:36:37 Dmitri Belimov wrote:
> Hi Hans.
> 
> I finished saa7134 part of SPI. Please review saa7134-spi.c and diff saa7134-core and etc.
> I wrote config of SPI to board structure. Use this config for register master and slave devices.
> 
> SPI other then I2C, do not need call request_module. Udev do it. 
> I spend 10 days for understanding :(  

I'm almost certain that spi works the same way as i2c and that means that you
must call request_module. Yes, udev will load it for you, but that is a delayed
load: i.e. the module may not be loaded when we need it. The idea behind this
is that usually i2c or spi modules are standalone, but in the context of v4l
such modules are required to be present before the bridge can properly configure
itself.

The easiest way to ensure the correct load sequence is to do a request_module
at the start.

Now, I haven't compiled this, but I think this will work:

struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev,
               struct spi_master *master, struct spi_board_info *info)
{
	struct v4l2_subdev *sd = NULL;
        struct spi_device *spi;
	
	BUG_ON(!v4l2_dev);

	if (module_name)
        	request_module(module_name);

	spi = spi_new_device(master, info);

	if (spi == NULL || spi->dev.driver == NULL)
		goto error;

       if (!try_module_get(spi->dev.driver->owner))
               goto error;

       sd = spi_get_drvdata(spi);

       /* Register with the v4l2_device which increases the module's
          use count as well. */

       if (v4l2_device_register_subdev(v4l2_dev, sd))
               sd = NULL;

       /* Decrease the module use count to match the first try_module_get. */
       module_put(spi->dev.driver->owner);

error:
       /* If we have a client but no subdev, then something went wrong and
          we must unregister the client. */

       if (spi && sd == NULL)
               spi_unregister_device(spi);

       return sd;
}
EXPORT_SYMBOL_GPL(v4l2_spi_new_subdev);

Note that you mixed up the spi master and spi client in your original code. So
it is no wonder you experienced crashes.

Also note that there is no need for a separate v4l2_spi_new_subdev_board function.

And in v4l2_spi_subdev_init() you should use spi_set_drvdata instead of
dev_set_drvdata.

I hope this helps.

Regards,

	Hans

> 
> I need help with v4l2-common.c -> function v4l2_spi_new_subdev_board
> The module of SPI slave loading after some time and spi device hasn't v4l2_subdev structure
> for v4l2_device_register_subdev.
> 
> Now I get kernel crash when call v4l2_device_register_subdev.
> 
> Need use a callback metod or other. I don't know.
> 
> Copy to Mauro Carvalho Chehab and mailing lists for review my code too.
> 
> Dmesg log without call v4l2_device_register_subdev.
> [    4.742279] Linux video capture interface: v2.00
> [    4.816171] saa7130/34: v4l2 driver version 0.2.15 loaded
> [    4.816253] saa7134 0000:04:01.0: PCI INT A -> GSI 19 (level, low) -> IRQ 19
> [    4.816304] saa7133[0]: found at 0000:04:01.0, rev: 209, irq: 19, latency: 32, mmio: 0xe5100000
> [    4.816363] saa7133[0]: subsystem: 5ace:7595, board: Beholder BeholdTV X7 [card=171,autodetected]
> [    4.816430] saa7133[0]: board init: gpio is 200000
> [    4.816481] IRQ 19/saa7133[0]: IRQF_DISABLED is not guaranteed on shared IRQs
> [    4.976010] saa7133[0]: i2c eeprom 00: ce 5a 95 75 54 20 00 00 00 00 00 00 00 00 00 01
> [    4.976635] saa7133[0]: i2c eeprom 10: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
> [    4.977231] saa7133[0]: i2c eeprom 20: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
> [    4.977827] saa7133[0]: i2c eeprom 30: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
> [    4.978423] saa7133[0]: i2c eeprom 40: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
> [    4.979019] saa7133[0]: i2c eeprom 50: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
> [    4.979615] saa7133[0]: i2c eeprom 60: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
> [    4.980223] saa7133[0]: i2c eeprom 70: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
> [    4.980820] saa7133[0]: i2c eeprom 80: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
> [    4.981416] saa7133[0]: i2c eeprom 90: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
> [    4.982012] saa7133[0]: i2c eeprom a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
> [    4.982608] saa7133[0]: i2c eeprom b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
> [    4.983204] saa7133[0]: i2c eeprom c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
> [    4.983800] saa7133[0]: i2c eeprom d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
> [    4.984437] saa7133[0]: i2c eeprom e0: 00 00 00 00 ff ff ff ff ff ff ff ff ff ff ff ff
> [    4.985033] saa7133[0]: i2c eeprom f0: 42 54 56 30 30 30 30 ff ff ff ff ff ff ff ff ff
> [    5.008041] tuner 1-0061: chip found @ 0xc2 (saa7133[0])
> [    5.024036] HDA Intel 0000:00:1b.0: PCI INT A -> GSI 16 (level, low) -> IRQ 16
> [    5.024109] HDA Intel 0000:00:1b.0: setting latency timer to 64
> [    5.066725] xc5000 1-0061: creating new instance
> [    5.076009] xc5000: Successfully identified at address 0x61
> [    5.076060] xc5000: Firmware has not been loaded previously
> 
> [   33.381216] saa7134 0000:04:01.0: spi master registered: bus_num=32766 num_chipselect=1
> [   33.381274] saa7133[0]: found muPD61151 MPEG encoder
> [   33.381430] saa7133[0]: registered device video0 [v4l2]
> [   33.381491] saa7133[0]: registered device vbi0
> [   33.381551] saa7133[0]: registered device radio0
> [   33.406256] saa7133[0]: registered device video1 [mpeg]
> [   33.407628] upd61151_probe function
> [   33.407672] Read test REG 0xD8 :
> [   33.409502] REG = 0x0
> [   33.409547] Write test 0x03 to REG 0xD8 :
> [   33.411353] Next read test REG 0xD8 :
> [   33.413176] REG = 0x3
> [   33.431308] saa7134 ALSA driver for DMA sound loaded
> [   33.431363] IRQ 19/saa7133[0]: IRQF_DISABLED is not guaranteed on shared IRQs
> [   33.431425] saa7133[0]/alsa: saa7133[0] at 0xe5100000 irq 19 registered as card -1
> 
> [   48.657067] xc5000: I2C write failed (len=4)
> [   48.760018] xc5000: I2C write failed (len=4)
> [   48.762960] xc5000: I2C read failed
> [   48.763011] xc5000: I2C read failed
> [   48.763054] xc5000: waiting for firmware upload (dvb-fe-xc5000-1.6.114.fw)...
> [   48.763102] saa7134 0000:04:01.0: firmware: requesting dvb-fe-xc5000-1.6.114.fw
> [   48.802473] xc5000: firmware read 12401 bytes.
> [   48.802477] xc5000: firmware uploading...
> [   49.328504] eth0: no IPv6 routers present
> [   52.132007] xc5000: firmware upload complete...
> [   53.366772] ------------[ cut here ]------------
> [   53.366820] kernel BUG at lib/kernel_lock.c:126!
> [   53.366865] invalid opcode: 0000 [#1] SMP 
> [   53.366973] last sysfs file: /sys/class/firmware/0000:04:01.0/loading
> [   53.367019] Modules linked in: ipv6 dm_snapshot dm_mirror dm_region_hash dm_log dm_mod loop saa7134_alsa upd61151 saa7134_empress ir_kbd_i2c snd_hda_codec_realtek xc5000 snd_hda_intel snd_hda_codec tuner snd_pcm_oss snd_mixer_oss snd_pcm snd_seq_dummy snd_seq_oss snd_seq_midi snd_rawmidi snd_seq_midi_event snd_seq saa7134 snd_timer ir_common v4l2_common videodev snd_seq_device v4l1_compat videobuf_dma_sg videobuf_core spi_bitbang psmouse snd ir_core serio_raw tveeprom soundcore parport_pc parport processor i2c_i801 button snd_page_alloc i2c_core intel_agp agpgart rng_core pcspkr evdev ext3 jbd mbcache sg sr_mod cdrom sd_mod ata_generic ata_piix libata scsi_mod ide_pci_generic ide_core ehci_hcd uhci_hcd r8169 mii usbcore thermal fan thermal_sys [last unloaded: scsi_wait_scan]
> [   53.369624] 
> [   53.369666] Pid: 2659, comm: hald-probe-vide Not tainted (2.6.30.5 #1) G31M-ES2L
> [   53.369721] EIP: 0060:[<c02f81e3>] EFLAGS: 00010286 CPU: 0
> [   53.369770] EIP is at unlock_kernel+0xd/0x24
> [   53.369814] EAX: f6bc26ac EBX: f6bc2000 ECX: f6bc26ac EDX: f707e4d0
> [   53.369860] ESI: 00000000 EDI: f6aa90c0 EBP: f6bc26ac ESP: f65b1e68
> [   53.369906]  DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068
> [   53.369952] Process hald-probe-vide (pid: 2659, ti=f65b0000 task=f707e4d0 task.ti=f65b0000)
> [   53.370008] Stack:
> [   53.370049]  f873e9c9 00000000 f687c804 f6aa90c0 00000000 f848e309 00000000 f6b4d680
> [   53.370298]  f6b4d680 c0190049 f6aa90c0 f6a144e4 00000000 f6aa90c0 00000000 f6a144e4
> [   53.370298]  c018ff24 c018c3b9 f701ef40 f6d11a5c f6aa90c0 f65b1f0c f65b1f0c 00008001
> [   53.370298] Call Trace:
> [   53.370298]  [<f873e9c9>] ? ts_open+0x8c/0x93 [saa7134_empress]
> [   53.370298]  [<f848e309>] ? v4l2_open+0x65/0x78 [videodev]
> [   53.370298]  [<c0190049>] ? chrdev_open+0x125/0x13c
> [   53.370298]  [<c018ff24>] ? chrdev_open+0x0/0x13c
> [   53.370298]  [<c018c3b9>] ? __dentry_open+0x119/0x208
> [   53.370298]  [<c018c539>] ? nameidata_to_filp+0x29/0x3c
> [   53.370298]  [<c0197338>] ? do_filp_open+0x41e/0x7bc
> [   53.370298]  [<c017bb3c>] ? handle_mm_fault+0x294/0x5fd
> [   53.370298]  [<c019e267>] ? alloc_fd+0x52/0xb8
> [   53.370298]  [<c018c1d1>] ? do_sys_open+0x44/0xb4
> [   53.370298]  [<c018c285>] ? sys_open+0x1e/0x23
> [   53.370298]  [<c0102f74>] ? sysenter_do_call+0x12/0x28
> [   53.370298] Code: 0f c1 05 e0 4b 3e c0 38 e0 74 09 f3 90 a0 e0 4b 3e c0 eb f3 64 a1 00 b0 43 c0 89 50 14 c3 64 8b 15 00 b0 43 c0 83 7a 14 00 79 04 <0f> 0b eb fe 8b 42 14 48 85 c0 89 42 14 79 07 f0 fe 05 e0 4b 3e 
> [   53.370298] EIP: [<c02f81e3>] unlock_kernel+0xd/0x24 SS:ESP 0068:f65b1e68
> [   53.374302] ---[ end trace 05965e9e089c46c7 ]---
> 
> 
> With my best regards, Dmitry.
> 

-- 
Hans Verkuil - video4linux developer - sponsored by TANDBERG

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: saa7134 and μPD61151 MPEG2 coder
  2010-01-27 11:14         ` Hans Verkuil
@ 2010-01-28  2:09           ` Dmitri Belimov
  2010-01-28 12:00             ` Hans Verkuil
  0 siblings, 1 reply; 14+ messages in thread
From: Dmitri Belimov @ 2010-01-28  2:09 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: Mauro Carvalho Chehab, linux-media

HIi Hans

> Hi Dmitri,
> 
> Just a quick note: the video4linux mailinglist is obsolete, just use
> linux-media.

OK

> On Wednesday 27 January 2010 06:36:37 Dmitri Belimov wrote:
> > Hi Hans.
> > 
> > I finished saa7134 part of SPI. Please review saa7134-spi.c and
> > diff saa7134-core and etc. I wrote config of SPI to board
> > structure. Use this config for register master and slave devices.
> > 
> > SPI other then I2C, do not need call request_module. Udev do it. 
> > I spend 10 days for understanding :(  
> 
> I'm almost certain that spi works the same way as i2c and that means
> that you must call request_module. Yes, udev will load it for you,
> but that is a delayed load: i.e. the module may not be loaded when we
> need it. The idea behind this is that usually i2c or spi modules are
> standalone, but in the context of v4l such modules are required to be
> present before the bridge can properly configure itself.
> 
> The easiest way to ensure the correct load sequence is to do a
> request_module at the start.
> 
> Now, I haven't compiled this, but I think this will work:
> 
> struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev,
>                struct spi_master *master, struct spi_board_info *info)
> {
> 	struct v4l2_subdev *sd = NULL;
>         struct spi_device *spi;
> 	
> 	BUG_ON(!v4l2_dev);
> 
> 	if (module_name)
>         	request_module(module_name);
> 
> 	spi = spi_new_device(master, info);
> 
> 	if (spi == NULL || spi->dev.driver == NULL)
> 		goto error;
> 
>        if (!try_module_get(spi->dev.driver->owner))
>                goto error;
> 
>        sd = spi_get_drvdata(spi);
> 
>        /* Register with the v4l2_device which increases the module's
>           use count as well. */
> 
>        if (v4l2_device_register_subdev(v4l2_dev, sd))
>                sd = NULL;
> 
>        /* Decrease the module use count to match the first
> try_module_get. */ module_put(spi->dev.driver->owner);
> 
> error:
>        /* If we have a client but no subdev, then something went
> wrong and we must unregister the client. */
> 
>        if (spi && sd == NULL)
>                spi_unregister_device(spi);
> 
>        return sd;
> }
> EXPORT_SYMBOL_GPL(v4l2_spi_new_subdev);

Not work

[    6.048195] Linux video capture interface: v2.00
[    6.112987] saa7130/34: v4l2 driver version 0.2.15 loaded
[    6.113067] saa7134 0000:04:01.0: PCI INT A -> GSI 19 (level, low) -> IRQ 19
[    6.113117] saa7133[0]: found at 0000:04:01.0, rev: 209, irq: 19, latency: 32, mmio: 0xe5100000
[    6.113176] saa7133[0]: subsystem: 5ace:7595, board: Beholder BeholdTV X7 [card=171,autodetected]
[    6.113241] saa7133[0]: board init: gpio is 200000
[    6.113292] IRQ 19/saa7133[0]: IRQF_DISABLED is not guaranteed on shared IRQs
[    6.264512] saa7133[0]: i2c eeprom 00: ce 5a 95 75 54 20 00 00 00 00 00 00 00 00 00 01
[    6.265136] saa7133[0]: i2c eeprom 10: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    6.265731] saa7133[0]: i2c eeprom 20: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    6.266327] saa7133[0]: i2c eeprom 30: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    6.266922] saa7133[0]: i2c eeprom 40: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    6.267517] saa7133[0]: i2c eeprom 50: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    6.268113] saa7133[0]: i2c eeprom 60: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    6.268718] saa7133[0]: i2c eeprom 70: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    6.269313] saa7133[0]: i2c eeprom 80: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    6.269908] saa7133[0]: i2c eeprom 90: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    6.270503] saa7133[0]: i2c eeprom a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    6.271098] saa7133[0]: i2c eeprom b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    6.271693] saa7133[0]: i2c eeprom c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    6.272289] saa7133[0]: i2c eeprom d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    6.272895] saa7133[0]: i2c eeprom e0: 00 00 00 00 ff ff ff ff ff ff ff ff ff ff ff ff
[    6.273490] saa7133[0]: i2c eeprom f0: 42 54 56 30 30 30 30 ff ff ff ff ff ff ff ff ff
[    6.360023] tuner 1-0061: chip found @ 0xc2 (saa7133[0])
[    6.401952] xc5000 1-0061: creating new instance
[    6.412005] xc5000: Successfully identified at address 0x61
[    6.412054] xc5000: Firmware has not been loaded previously
[    6.477742] HDA Intel 0000:00:1b.0: PCI INT A -> GSI 16 (level, low) -> IRQ 16
[    6.477816] HDA Intel 0000:00:1b.0: setting latency timer to 64

[   34.752763] saa7134 0000:04:01.0: spi master registered: bus_num=32766 num_chipselect=1
[   34.752823] saa7133[0]: found muPD61151 MPEG encoder
[   34.752883] befor request_module

[  240.476013] INFO: task modprobe:1404 blocked for more than 120 seconds.
[  240.476016] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[  240.476018] modprobe      D f6b913c0     0  1404      1
[  240.476021]  c200f0c0 00000086 00989680 f6b913c0 c011b1fd c043f0c0 00000003 00000000
[  240.476027]  f711faa0 f711fc54 00000000 0001ecac 176f9ddf 00000008 f711facc f711faa0
[  240.476031]  f7070490 c011cc8e 00000000 c200f0c0 c02ff658 00000001 f7070490 00000046
[  240.476036] Call Trace:
[  240.476042]  [<c011b1fd>] ? wakeup_preempt_entity+0xf0/0x110
[  240.476046]  [<c011cc8e>] ? check_preempt_wakeup+0x139/0x173
[  240.476050]  [<c02f6984>] ? schedule+0x5/0x13
[  240.476052]  [<c02f6ab0>] ? schedule_timeout+0x15/0x16a
[  240.476055]  [<c011bba4>] ? __wake_up_common+0x34/0x59
[  240.476057]  [<c011c477>] ? __wake_up+0x29/0x39
[  240.476060]  [<c02f6069>] ? wait_for_common+0xba/0x115
[  240.476063]  [<c0122170>] ? default_wake_function+0x0/0x8
[  240.476067]  [<c0133e10>] ? call_usermodehelper_exec+0x6e/0xae
[  240.476069]  [<c0133fd5>] ? __request_module+0xdb/0xee
[  240.476076]  [<f847c647>] ? spi_bitbang_setup+0xe7/0xfb [spi_bitbang]
[  240.476082]  [<f84c8f3b>] ? v4l2_spi_new_subdev_board+0x2e/0x35 [v4l2_common]
[  240.476086]  [<f84c8fa6>] ? v4l2_spi_new_subdev+0x64/0x6c [v4l2_common]
[  240.476099]  [<f852c0b5>] ? saa7134_initdev+0x6dd/0xa96 [saa7134]
[  240.476103]  [<c0213045>] ? local_pci_probe+0xb/0xc
[  240.476105]  [<c02139bd>] ? pci_device_probe+0x41/0x63
[  240.476109]  [<c026d03c>] ? driver_probe_device+0x76/0xfe
[  240.476112]  [<c026d104>] ? __driver_attach+0x40/0x5b
[  240.476115]  [<c026cad8>] ? bus_for_each_dev+0x37/0x5f
[  240.476117]  [<c026cf23>] ? driver_attach+0x11/0x13
[  240.476120]  [<c026d0c4>] ? __driver_attach+0x0/0x5b
[  240.476122]  [<c026c56a>] ? bus_add_driver+0xcb/0x1ee
[  240.476131]  [<f854b000>] ? saa7134_init+0x0/0x3b [saa7134]
[  240.476134]  [<c026d31f>] ? driver_register+0x87/0xe0
[  240.476143]  [<f854b000>] ? saa7134_init+0x0/0x3b [saa7134]
[  240.476146]  [<c0213cf5>] ? __pci_register_driver+0x33/0x8a
[  240.476154]  [<f854b000>] ? saa7134_init+0x0/0x3b [saa7134]
[  240.476157]  [<c010112d>] ? do_one_initcall+0x44/0x111
[  240.476160]  [<c016107f>] ? tracepoint_module_notify+0x21/0x24
[  240.476164]  [<c013a5b6>] ? notifier_call_chain+0x2a/0x47
[  240.476167]  [<c013a80b>] ? __blocking_notifier_call_chain+0x3f/0x49
[  240.476171]  [<c0147a67>] ? sys_init_module+0x87/0x187
[  240.476173]  [<c0102f74>] ? sysenter_do_call+0x12/0x28
[  240.476177] INFO: task modprobe:1705 blocked for more than 120 seconds.
[  240.476178] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[  240.476180] modprobe      D f6a54040     0  1705   1704
[  240.476182]  c200f0c0 00000082 c0202b29 f6a54040 c04b8eb0 c043f0c0 c019c7f4 00000001
[  240.476187]  f7188450 f7188604 00000000 c04b8ea0 1894fb69 00000008 00000001 f7020774
[  240.476192]  c0202998 f68e7e68 c04b8ea0 00000006 00000001 00000000 ffffffc1 00000001
[  240.476196] Call Trace:
[  240.476199]  [<c0202b29>] ? ida_get_new_above+0xd4/0x178
[  240.476203]  [<c019c7f4>] ? find_inode+0x1b/0x56
[  240.476205]  [<c0202998>] ? idr_get_empty_slot+0x145/0x202
[  240.476208]  [<c0202b29>] ? ida_get_new_above+0xd4/0x178
[  240.476211]  [<c02f6984>] ? schedule+0x5/0x13
[  240.476213]  [<c02f6ab0>] ? schedule_timeout+0x15/0x16a
[  240.476216]  [<c019c44c>] ? iput+0x21/0x4a
[  240.476219]  [<c01cad13>] ? sysfs_addrm_finish+0x46/0x1a6
[  240.476221]  [<c01caa40>] ? sysfs_add_one+0x10/0xad
[  240.476224]  [<c02f761e>] ? __down+0x4e/0x73
[  240.476227]  [<c013a54c>] ? down+0x1f/0x2a
[  240.476229]  [<c026d0eb>] ? __driver_attach+0x27/0x5b
[  240.476232]  [<c026cad8>] ? bus_for_each_dev+0x37/0x5f
[  240.476234]  [<c026cf23>] ? driver_attach+0x11/0x13
[  240.476237]  [<c026d0c4>] ? __driver_attach+0x0/0x5b
[  240.476239]  [<c026c56a>] ? bus_add_driver+0xcb/0x1ee
[  240.476243]  [<f874f000>] ? init_upd61151+0x0/0xa [upd61151]
[  240.476245]  [<c026d31f>] ? driver_register+0x87/0xe0
[  240.476248]  [<f874f000>] ? init_upd61151+0x0/0xa [upd61151]
[  240.476250]  [<c010112d>] ? do_one_initcall+0x44/0x111
[  240.476253]  [<c016107f>] ? tracepoint_module_notify+0x21/0x24
[  240.476256]  [<c013a5b6>] ? notifier_call_chain+0x2a/0x47
[  240.476259]  [<c013a80b>] ? __blocking_notifier_call_chain+0x3f/0x49
[  240.476261]  [<c0147a67>] ? sys_init_module+0x87/0x187
[  240.476264]  [<c0102f74>] ? sysenter_do_call+0x12/0x28
[  240.476267]  [<c013007b>] ? prepare_signal+0x10f/0x184
[  240.476269]  [<c0130000>] ? prepare_signal+0x94/0x184

Module not load successfull. As I see spi_register_driver in upd61151.c not finished a long long long time
and killed by kernel. I see this message last 10 days befor removing request_module from function.

> Note that you mixed up the spi master and spi client in your original
> code. So it is no wonder you experienced crashes.

Yes, this is my error you are right. :((

         struct spi_device *spi;
 	
 
 	spi = spi_new_device(master, info);

> And in v4l2_spi_subdev_init() you should use spi_set_drvdata instead
> of dev_set_drvdata.

Ok

> I hope this helps.

Thank you.
 
> Regards,
> 
> 	Hans
> 
> > 
> > I need help with v4l2-common.c -> function v4l2_spi_new_subdev_board
> > The module of SPI slave loading after some time and spi device
> > hasn't v4l2_subdev structure for v4l2_device_register_subdev.
> > 
> > Now I get kernel crash when call v4l2_device_register_subdev.
> > 
> > Need use a callback metod or other. I don't know.
> > 
> > Copy to Mauro Carvalho Chehab and mailing lists for review my code
> > too.
> > 
> > Dmesg log without call v4l2_device_register_subdev.
> > [    4.742279] Linux video capture interface: v2.00
> > [    4.816171] saa7130/34: v4l2 driver version 0.2.15 loaded
> > [    4.816253] saa7134 0000:04:01.0: PCI INT A -> GSI 19 (level,
> > low) -> IRQ 19 [    4.816304] saa7133[0]: found at 0000:04:01.0,
> > rev: 209, irq: 19, latency: 32, mmio: 0xe5100000 [    4.816363]
> > saa7133[0]: subsystem: 5ace:7595, board: Beholder BeholdTV X7
> > [card=171,autodetected] [    4.816430] saa7133[0]: board init: gpio
> > is 200000 [    4.816481] IRQ 19/saa7133[0]: IRQF_DISABLED is not
> > guaranteed on shared IRQs [    4.976010] saa7133[0]: i2c eeprom 00:
> > ce 5a 95 75 54 20 00 00 00 00 00 00 00 00 00 01 [    4.976635]
> > saa7133[0]: i2c eeprom 10: ff ff ff ff ff ff ff ff ff ff ff ff ff
> > ff ff ff [    4.977231] saa7133[0]: i2c eeprom 20: ff ff ff ff ff
> > ff ff ff ff ff ff ff ff ff ff ff [    4.977827] saa7133[0]: i2c
> > eeprom 30: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
> > [    4.978423] saa7133[0]: i2c eeprom 40: ff ff ff ff ff ff ff ff
> > ff ff ff ff ff ff ff ff [    4.979019] saa7133[0]: i2c eeprom 50:
> > ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff [    4.979615]
> > saa7133[0]: i2c eeprom 60: ff ff ff ff ff ff ff ff ff ff ff ff ff
> > ff ff ff [    4.980223] saa7133[0]: i2c eeprom 70: ff ff ff ff ff
> > ff ff ff ff ff ff ff ff ff ff ff [    4.980820] saa7133[0]: i2c
> > eeprom 80: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
> > [    4.981416] saa7133[0]: i2c eeprom 90: ff ff ff ff ff ff ff ff
> > ff ff ff ff ff ff ff ff [    4.982012] saa7133[0]: i2c eeprom a0:
> > ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff [    4.982608]
> > saa7133[0]: i2c eeprom b0: ff ff ff ff ff ff ff ff ff ff ff ff ff
> > ff ff ff [    4.983204] saa7133[0]: i2c eeprom c0: ff ff ff ff ff
> > ff ff ff ff ff ff ff ff ff ff ff [    4.983800] saa7133[0]: i2c
> > eeprom d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
> > [    4.984437] saa7133[0]: i2c eeprom e0: 00 00 00 00 ff ff ff ff
> > ff ff ff ff ff ff ff ff [    4.985033] saa7133[0]: i2c eeprom f0:
> > 42 54 56 30 30 30 30 ff ff ff ff ff ff ff ff ff [    5.008041]
> > tuner 1-0061: chip found @ 0xc2 (saa7133[0]) [    5.024036] HDA
> > Intel 0000:00:1b.0: PCI INT A -> GSI 16 (level, low) -> IRQ 16
> > [    5.024109] HDA Intel 0000:00:1b.0: setting latency timer to 64
> > [    5.066725] xc5000 1-0061: creating new instance [    5.076009]
> > xc5000: Successfully identified at address 0x61 [    5.076060]
> > xc5000: Firmware has not been loaded previously
> > 
> > [   33.381216] saa7134 0000:04:01.0: spi master registered:
> > bus_num=32766 num_chipselect=1 [   33.381274] saa7133[0]: found
> > muPD61151 MPEG encoder [   33.381430] saa7133[0]: registered device
> > video0 [v4l2] [   33.381491] saa7133[0]: registered device vbi0
> > [   33.381551] saa7133[0]: registered device radio0
> > [   33.406256] saa7133[0]: registered device video1 [mpeg]
> > [   33.407628] upd61151_probe function
> > [   33.407672] Read test REG 0xD8 :
> > [   33.409502] REG = 0x0
> > [   33.409547] Write test 0x03 to REG 0xD8 :
> > [   33.411353] Next read test REG 0xD8 :
> > [   33.413176] REG = 0x3
> > [   33.431308] saa7134 ALSA driver for DMA sound loaded
> > [   33.431363] IRQ 19/saa7133[0]: IRQF_DISABLED is not guaranteed
> > on shared IRQs [   33.431425] saa7133[0]/alsa: saa7133[0] at
> > 0xe5100000 irq 19 registered as card -1
> > 
> > [   48.657067] xc5000: I2C write failed (len=4)
> > [   48.760018] xc5000: I2C write failed (len=4)
> > [   48.762960] xc5000: I2C read failed
> > [   48.763011] xc5000: I2C read failed
> > [   48.763054] xc5000: waiting for firmware upload
> > (dvb-fe-xc5000-1.6.114.fw)... [   48.763102] saa7134 0000:04:01.0:
> > firmware: requesting dvb-fe-xc5000-1.6.114.fw [   48.802473]
> > xc5000: firmware read 12401 bytes. [   48.802477] xc5000: firmware
> > uploading... [   49.328504] eth0: no IPv6 routers present
> > [   52.132007] xc5000: firmware upload complete...
> > [   53.366772] ------------[ cut here ]------------
> > [   53.366820] kernel BUG at lib/kernel_lock.c:126!
> > [   53.366865] invalid opcode: 0000 [#1] SMP 
> > [   53.366973] last sysfs
> > file: /sys/class/firmware/0000:04:01.0/loading [   53.367019]
> > Modules linked in: ipv6 dm_snapshot dm_mirror dm_region_hash dm_log
> > dm_mod loop saa7134_alsa upd61151 saa7134_empress ir_kbd_i2c
> > snd_hda_codec_realtek xc5000 snd_hda_intel snd_hda_codec tuner
> > snd_pcm_oss snd_mixer_oss snd_pcm snd_seq_dummy snd_seq_oss
> > snd_seq_midi snd_rawmidi snd_seq_midi_event snd_seq saa7134
> > snd_timer ir_common v4l2_common videodev snd_seq_device v4l1_compat
> > videobuf_dma_sg videobuf_core spi_bitbang psmouse snd ir_core
> > serio_raw tveeprom soundcore parport_pc parport processor i2c_i801
> > button snd_page_alloc i2c_core intel_agp agpgart rng_core pcspkr
> > evdev ext3 jbd mbcache sg sr_mod cdrom sd_mod ata_generic ata_piix
> > libata scsi_mod ide_pci_generic ide_core ehci_hcd uhci_hcd r8169
> > mii usbcore thermal fan thermal_sys [last unloaded: scsi_wait_scan]
> > [   53.369624] [   53.369666] Pid: 2659, comm: hald-probe-vide Not
> > tainted (2.6.30.5 #1) G31M-ES2L [   53.369721] EIP:
> > 0060:[<c02f81e3>] EFLAGS: 00010286 CPU: 0 [   53.369770] EIP is at
> > unlock_kernel+0xd/0x24 [   53.369814] EAX: f6bc26ac EBX: f6bc2000
> > ECX: f6bc26ac EDX: f707e4d0 [   53.369860] ESI: 00000000 EDI:
> > f6aa90c0 EBP: f6bc26ac ESP: f65b1e68 [   53.369906]  DS: 007b ES:
> > 007b FS: 00d8 GS: 0033 SS: 0068 [   53.369952] Process
> > hald-probe-vide (pid: 2659, ti=f65b0000 task=f707e4d0
> > task.ti=f65b0000) [   53.370008] Stack: [   53.370049]  f873e9c9
> > 00000000 f687c804 f6aa90c0 00000000 f848e309 00000000 f6b4d680
> > [   53.370298]  f6b4d680 c0190049 f6aa90c0 f6a144e4 00000000
> > f6aa90c0 00000000 f6a144e4 [   53.370298]  c018ff24 c018c3b9
> > f701ef40 f6d11a5c f6aa90c0 f65b1f0c f65b1f0c 00008001
> > [   53.370298] Call Trace: [   53.370298]  [<f873e9c9>] ?
> > ts_open+0x8c/0x93 [saa7134_empress] [   53.370298]  [<f848e309>] ?
> > v4l2_open+0x65/0x78 [videodev] [   53.370298]  [<c0190049>] ?
> > chrdev_open+0x125/0x13c [   53.370298]  [<c018ff24>] ?
> > chrdev_open+0x0/0x13c [   53.370298]  [<c018c3b9>] ?
> > __dentry_open+0x119/0x208 [   53.370298]  [<c018c539>] ?
> > nameidata_to_filp+0x29/0x3c [   53.370298]  [<c0197338>] ?
> > do_filp_open+0x41e/0x7bc [   53.370298]  [<c017bb3c>] ?
> > handle_mm_fault+0x294/0x5fd [   53.370298]  [<c019e267>] ?
> > alloc_fd+0x52/0xb8 [   53.370298]  [<c018c1d1>] ?
> > do_sys_open+0x44/0xb4 [   53.370298]  [<c018c285>] ?
> > sys_open+0x1e/0x23 [   53.370298]  [<c0102f74>] ?
> > sysenter_do_call+0x12/0x28 [   53.370298] Code: 0f c1 05 e0 4b 3e
> > c0 38 e0 74 09 f3 90 a0 e0 4b 3e c0 eb f3 64 a1 00 b0 43 c0 89 50
> > 14 c3 64 8b 15 00 b0 43 c0 83 7a 14 00 79 04 <0f> 0b eb fe 8b 42 14
> > 48 85 c0 89 42 14 79 07 f0 fe 05 e0 4b 3e [   53.370298] EIP:
> > [<c02f81e3>] unlock_kernel+0xd/0x24 SS:ESP 0068:f65b1e68
> > [   53.374302] ---[ end trace 05965e9e089c46c7 ]---
> > 
> > 
> > With my best regards, Dmitry.
> > 
> 
> -- 
> Hans Verkuil - video4linux developer - sponsored by TANDBERG

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: saa7134 and μPD61151 MPEG2 coder
  2010-01-28  2:09           ` Dmitri Belimov
@ 2010-01-28 12:00             ` Hans Verkuil
  2010-01-29  7:12               ` Dmitri Belimov
  0 siblings, 1 reply; 14+ messages in thread
From: Hans Verkuil @ 2010-01-28 12:00 UTC (permalink / raw)
  To: Dmitri Belimov; +Cc: Mauro Carvalho Chehab, linux-media

On Thursday 28 January 2010 03:09:41 Dmitri Belimov wrote:
> HIi Hans
> 
> > Hi Dmitri,
> > 
> > Just a quick note: the video4linux mailinglist is obsolete, just use
> > linux-media.
> 
> OK
> 
> > On Wednesday 27 January 2010 06:36:37 Dmitri Belimov wrote:
> > > Hi Hans.
> > > 
> > > I finished saa7134 part of SPI. Please review saa7134-spi.c and
> > > diff saa7134-core and etc. I wrote config of SPI to board
> > > structure. Use this config for register master and slave devices.
> > > 
> > > SPI other then I2C, do not need call request_module. Udev do it. 
> > > I spend 10 days for understanding :(  
> > 
> > I'm almost certain that spi works the same way as i2c and that means
> > that you must call request_module. Yes, udev will load it for you,
> > but that is a delayed load: i.e. the module may not be loaded when we
> > need it. The idea behind this is that usually i2c or spi modules are
> > standalone, but in the context of v4l such modules are required to be
> > present before the bridge can properly configure itself.
> > 
> > The easiest way to ensure the correct load sequence is to do a
> > request_module at the start.
> > 
> > Now, I haven't compiled this, but I think this will work:
> > 
> > struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev,
> >                struct spi_master *master, struct spi_board_info *info)
> > {
> > 	struct v4l2_subdev *sd = NULL;
> >         struct spi_device *spi;
> > 	
> > 	BUG_ON(!v4l2_dev);
> > 
> > 	if (module_name)
> >         	request_module(module_name);

There is one thing missing here: module_name should be passed in as argument
to v4l2_spi_new_subdev. Does this code actually compile? If so, then I suspect
module_name must be some global variable with some bogus value which causes
request_module to time out.

> [  240.476082]  [<f84c8f3b>] ? v4l2_spi_new_subdev_board+0x2e/0x35 [v4l2_common]
> [  240.476086]  [<f84c8fa6>] ? v4l2_spi_new_subdev+0x64/0x6c [v4l2_common]

Remove v4l2_spi_new_subdev_board. Just have a v4l2_spi_new_subdev as in my code.

Regards,

	Hans

-- 
Hans Verkuil - video4linux developer - sponsored by TANDBERG

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: saa7134 and μPD61151 MPEG2 coder
  2010-01-28 12:00             ` Hans Verkuil
@ 2010-01-29  7:12               ` Dmitri Belimov
  2010-02-09  5:41                 ` Dmitri Belimov
  0 siblings, 1 reply; 14+ messages in thread
From: Dmitri Belimov @ 2010-01-29  7:12 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: Mauro Carvalho Chehab, linux-media

[-- Attachment #1: Type: text/plain, Size: 9333 bytes --]

Hi Hans

> > > On Wednesday 27 January 2010 06:36:37 Dmitri Belimov wrote:
> > > > Hi Hans.
> > > > 
> > > > I finished saa7134 part of SPI. Please review saa7134-spi.c and
> > > > diff saa7134-core and etc. I wrote config of SPI to board
> > > > structure. Use this config for register master and slave
> > > > devices.
> > > > 
> > > > SPI other then I2C, do not need call request_module. Udev do
> > > > it. I spend 10 days for understanding :(  
> > > 
> > > I'm almost certain that spi works the same way as i2c and that
> > > means that you must call request_module. Yes, udev will load it
> > > for you, but that is a delayed load: i.e. the module may not be
> > > loaded when we need it. The idea behind this is that usually i2c
> > > or spi modules are standalone, but in the context of v4l such
> > > modules are required to be present before the bridge can properly
> > > configure itself.
> > > 
> > > The easiest way to ensure the correct load sequence is to do a
> > > request_module at the start.
> > > 
> > > Now, I haven't compiled this, but I think this will work:
> > > 
> > > struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device
> > > *v4l2_dev, struct spi_master *master, struct spi_board_info *info)
> > > {
> > > 	struct v4l2_subdev *sd = NULL;
> > >         struct spi_device *spi;
> > > 	
> > > 	BUG_ON(!v4l2_dev);
> > > 
> > > 	if (module_name)
> > >         	request_module(module_name);
> 
> There is one thing missing here: module_name should be passed in as
> argument to v4l2_spi_new_subdev. Does this code actually compile? If
> so, then I suspect module_name must be some global variable with some
> bogus value which causes request_module to time out.
> 
> > [  240.476082]  [<f84c8f3b>] ? v4l2_spi_new_subdev_board+0x2e/0x35
> > [v4l2_common] [  240.476086]  [<f84c8fa6>] ?
> > v4l2_spi_new_subdev+0x64/0x6c [v4l2_common]
> 
> Remove v4l2_spi_new_subdev_board. Just have a v4l2_spi_new_subdev as
> in my code.

I found my error. Calling request_module befor spi_new_device is good.

As I see new v4l2_subdev ops hooked and calling
[   52.796008] DEBUG uPD61151: upd61151_s_std

My next task move our MPEG2 code to upd61151.c
Please review my changes for v4l2_spi_new_subdev.

[    4.743008] Linux video capture interface: v2.00
[    4.788866] saa7130/34: v4l2 driver version 0.2.15 loaded
[    4.788946] saa7134 0000:04:01.0: PCI INT A -> GSI 19 (level, low) -> IRQ 19
[    4.788996] saa7133[0]: found at 0000:04:01.0, rev: 209, irq: 19, latency: 32, mmio: 0xe5100000
[    4.789055] saa7133[0]: subsystem: 5ace:7595, board: Beholder BeholdTV X7 [card=171,autodetected]
[    4.789122] saa7133[0]: board init: gpio is 200000
[    4.789172] IRQ 19/saa7133[0]: IRQF_DISABLED is not guaranteed on shared IRQs
[    4.868459] HDA Intel 0000:00:1b.0: PCI INT A -> GSI 16 (level, low) -> IRQ 16
[    4.868533] HDA Intel 0000:00:1b.0: setting latency timer to 64
[    4.952004] saa7133[0]: i2c eeprom 00: ce 5a 95 75 54 20 00 00 00 00 00 00 00 00 00 01
[    4.952604] saa7133[0]: i2c eeprom 10: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.953202] saa7133[0]: i2c eeprom 20: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.953799] saa7133[0]: i2c eeprom 30: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.954397] saa7133[0]: i2c eeprom 40: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.954994] saa7133[0]: i2c eeprom 50: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.955592] saa7133[0]: i2c eeprom 60: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.956200] saa7133[0]: i2c eeprom 70: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.956798] saa7133[0]: i2c eeprom 80: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.957395] saa7133[0]: i2c eeprom 90: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.957993] saa7133[0]: i2c eeprom a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.958591] saa7133[0]: i2c eeprom b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.959189] saa7133[0]: i2c eeprom c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.959786] saa7133[0]: i2c eeprom d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.960394] saa7133[0]: i2c eeprom e0: 00 00 00 00 ff ff ff ff ff ff ff ff ff ff ff ff
[    4.960991] saa7133[0]: i2c eeprom f0: 42 54 56 30 30 30 30 ff ff ff ff ff ff ff ff ff
[    5.012044] tuner 1-0061: chip found @ 0xc2 (saa7133[0])
[    5.128672] xc5000 1-0061: creating new instance
[    5.136014] xc5000: Successfully identified at address 0x61
[    5.136067] xc5000: Firmware has not been loaded previously

[   33.425823] saa7134 0000:04:01.0: spi master registered: bus_num=32766 num_chipselect=1
[   33.425883] saa7133[0]: found muPD61151 MPEG encoder
[   33.425928] befor request_module upd61151
[   33.435609] upd61151_probe function
[   33.435654] Read test REG 0xD8 :
[   33.437463] REG = 0x0
[   33.437505] Write test 0x03 to REG 0xD8 :
[   33.439310] Next read test REG 0xD8 :
[   33.441123] REG = 0x3
[   33.441167] befor spi_get_drvdata
[   33.441210] subdev pointer = f646e7c0
[   33.441253] befor register_subdev
[   33.441297] DEBIG SPI:
[   33.441298] 	spi pointer = f7087580
[   33.441298] 	spi->dev.driver = f873dd70
[   33.441299] 	sd pointer = f646e7c0
[   33.441579] saa7133[0]: registered device video0 [v4l2]
[   33.441640] saa7133[0]: registered device vbi0
[   33.441700] saa7133[0]: registered device radio0
[   33.459770] saa7133[0]: registered device video1 [mpeg]
[   33.486244] saa7134 ALSA driver for DMA sound loaded
[   33.486301] IRQ 19/saa7133[0]: IRQF_DISABLED is not guaranteed on shared IRQs
[   33.486364] saa7133[0]/alsa: saa7133[0] at 0xe5100000 irq 19 registered as card -1

[   48.557569] xc5000: I2C write failed (len=4)
[   48.660019] xc5000: I2C write failed (len=4)
[   48.662966] xc5000: I2C read failed
[   48.663016] xc5000: I2C read failed
[   48.663060] xc5000: waiting for firmware upload (dvb-fe-xc5000-1.6.114.fw)...
[   48.663108] saa7134 0000:04:01.0: firmware: requesting dvb-fe-xc5000-1.6.114.fw
[   48.705533] xc5000: firmware read 12401 bytes.
[   48.705535] xc5000: firmware uploading...

[   52.044007] xc5000: firmware upload complete...
[   52.796008] DEBUG uPD61151: upd61151_s_std
[   52.796058] DEBUG uPD61151: upd61151_s_std
[   53.268008] DEBUG uPD61151: upd61151_s_std
[   53.268060] DEBUG uPD61151: upd61151_s_std
[   53.270837] ------------[ cut here ]------------
[   53.270884] kernel BUG at lib/kernel_lock.c:126!
[   53.270929] invalid opcode: 0000 [#1] SMP 
[   53.271037] last sysfs file: /sys/class/firmware/0000:04:01.0/loading
[   53.271084] Modules linked in: ipv6 dm_snapshot dm_mirror dm_region_hash dm_log dm_mod loop saa7134_alsa saa7134_empress upd61151 ir_kbd_i2c xc5000 tuner snd_hda_codec_realtek snd_hda_intel snd_hda_codec snd_pcm_oss snd_mixer_oss snd_pcm snd_seq_dummy saa7134 ir_common v4l2_common videodev snd_seq_oss v4l1_compat videobuf_dma_sg videobuf_core spi_bitbang snd_seq_midi ir_core snd_rawmidi tveeprom psmouse snd_seq_midi_event serio_raw snd_seq snd_timer snd_seq_device i2c_i801 i2c_core rng_core pcspkr snd soundcore parport_pc parport snd_page_alloc button processor intel_agp agpgart evdev ext3 jbd mbcache sg sr_mod cdrom sd_mod ata_generic ata_piix libata scsi_mod ehci_hcd ide_pci_generic uhci_hcd ide_core usbcore r8169 mii thermal fan thermal_sys [last unloaded: scsi_wait_scan]
[   53.273694] 
[   53.273737] Pid: 2675, comm: hald-probe-vide Not tainted (2.6.30.5 #1) G31M-ES2L
[   53.273793] EIP: 0060:[<c02f81e3>] EFLAGS: 00010286 CPU: 0
[   53.273841] EIP is at unlock_kernel+0xd/0x24
[   53.273885] EAX: f6b7f6ac EBX: f6b7f000 ECX: f6b7f6ac EDX: f7168b20
[   53.273932] ESI: 00000000 EDI: f6860640 EBP: f6b7f6ac ESP: f66c9e68
[   53.273978]  DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068
[   53.274024] Process hald-probe-vide (pid: 2675, ti=f66c8000 task=f7168b20 task.ti=f66c8000)
[   53.274079] Stack:
[   53.274121]  f87499c9 00000000 f69c9804 f6860640 00000000 f8504309 00000000 f6940e00
[   53.274360]  f6940e00 c0190049 f6860640 f6aec86c 00000000 f6860640 00000000 f6aec86c
[   53.274360]  c018ff24 c018c3b9 f701e1c0 f6d148d0 f6860640 f66c9f0c f66c9f0c 00008001
[   53.274360] Call Trace:
[   53.274360]  [<f87499c9>] ? ts_open+0x8c/0x93 [saa7134_empress]
[   53.274360]  [<f8504309>] ? v4l2_open+0x65/0x78 [videodev]
[   53.274360]  [<c0190049>] ? chrdev_open+0x125/0x13c
[   53.274360]  [<c018ff24>] ? chrdev_open+0x0/0x13c
[   53.274360]  [<c018c3b9>] ? __dentry_open+0x119/0x208
[   53.274360]  [<c018c539>] ? nameidata_to_filp+0x29/0x3c
[   53.274360]  [<c0197338>] ? do_filp_open+0x41e/0x7bc
[   53.274360]  [<c017bb3c>] ? handle_mm_fault+0x294/0x5fd
[   53.274360]  [<c019e267>] ? alloc_fd+0x52/0xb8
[   53.274360]  [<c018c1d1>] ? do_sys_open+0x44/0xb4
[   53.274360]  [<c018c285>] ? sys_open+0x1e/0x23
[   53.274360]  [<c0102f74>] ? sysenter_do_call+0x12/0x28
[   53.274360] Code: 0f c1 05 e0 4b 3e c0 38 e0 74 09 f3 90 a0 e0 4b 3e c0 eb f3 64 a1 00 b0 43 c0 89 50 14 c3 64 8b 15 00 b0 43 c0 83 7a 14 00 79 04 <0f> 0b eb fe 8b 42 14 48 85 c0 89 42 14 79 07 f0 fe 05 e0 4b 3e 
[   53.274360] EIP: [<c02f81e3>] unlock_kernel+0xd/0x24 SS:ESP 0068:f66c9e68
[   53.278380] ---[ end trace 717d799b0d534ca3 ]---

With my best regards, Dmitry.

> Regards,
> 
> 	Hans
> 
> -- 
> Hans Verkuil - video4linux developer - sponsored by TANDBERG

[-- Attachment #2: behold_spi.diff --]
[-- Type: text/x-patch, Size: 13162 bytes --]

diff -r b6b82258cf5e linux/drivers/media/video/saa7134/Makefile
--- a/linux/drivers/media/video/saa7134/Makefile	Thu Dec 31 19:14:54 2009 -0200
+++ b/linux/drivers/media/video/saa7134/Makefile	Fri Jan 29 09:57:54 2010 +0900
@@ -1,9 +1,9 @@
 
 saa7134-objs :=	saa7134-cards.o saa7134-core.o saa7134-i2c.o	\
 		saa7134-ts.o saa7134-tvaudio.o saa7134-vbi.o    \
-		saa7134-video.o saa7134-input.o
+		saa7134-video.o saa7134-input.o saa7134-spi.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 -r b6b82258cf5e linux/drivers/media/video/saa7134/saa7134-cards.c
--- a/linux/drivers/media/video/saa7134/saa7134-cards.c	Thu Dec 31 19:14:54 2009 -0200
+++ b/linux/drivers/media/video/saa7134/saa7134-cards.c	Fri Jan 29 09:57:54 2010 +0900
@@ -4619,6 +4619,7 @@
 			.name = name_radio,
 			.amux = LINE2,
 		},
+		.encoder_type = SAA7134_ENCODER_SAA6752HS,
 		.mpeg  = SAA7134_MPEG_EMPRESS,
 		.video_out = CCIR656,
 		.vid_port_opts  = (SET_T_CODE_POLARITY_NON_INVERTED |
@@ -4656,6 +4657,7 @@
 			.name = name_radio,
 			.amux = LINE2,
 		},
+		.encoder_type = SAA7134_ENCODER_SAA6752HS,
 		.mpeg  = SAA7134_MPEG_EMPRESS,
 		.video_out = CCIR656,
 		.vid_port_opts  = (SET_T_CODE_POLARITY_NON_INVERTED |
@@ -4695,6 +4697,7 @@
 			.name = name_radio,
 			.amux = LINE2,
 		},
+		.encoder_type = SAA7134_ENCODER_SAA6752HS,
 		.mpeg  = SAA7134_MPEG_EMPRESS,
 		.video_out = CCIR656,
 		.vid_port_opts  = (SET_T_CODE_POLARITY_NON_INVERTED |
@@ -5279,23 +5282,51 @@
 		.tuner_addr     = ADDR_UNSET,
 		.radio_addr     = ADDR_UNSET,
 		.mpeg           = SAA7134_MPEG_DVB,
+		.gpiomask       = 0x00860000,
 		.inputs         = { {
 			.name = name_tv,
 			.vmux = 2,
 			.amux = TV,
 			.tv   = 1,
-		}, {
-			.name = name_comp1,
-			.vmux = 0,
-			.amux = LINE1,
+			.gpio = 0x00860000
+		}, {
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE1,
+			.gpio = 0x00860000
 		}, {
 			.name = name_svideo,
 			.vmux = 9,
 			.amux = LINE1,
-		} },
-		.radio = {
-			.name = name_radio,
-			.amux = TV,
+			.gpio = 0x00860000
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = TV,
+			.gpio = 0x00860000
+		},
+		.encoder_type = SAA7134_ENCODER_muPD61151,
+		.mpeg  = SAA7134_MPEG_EMPRESS,
+		.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,
+		},
+		.spi_conf = {
+			.modalias	= "upd61151",
+			.max_speed_hz	= 10000000,
+			.chip_select	= 0,
+			.mode		= SPI_MODE_0,
+			.controller_data = NULL,
+			.platform_data  = NULL,
 		},
 	},
 	[SAA7134_BOARD_ZOLID_HYBRID_PCI] = {
diff -r b6b82258cf5e linux/drivers/media/video/saa7134/saa7134-core.c
--- a/linux/drivers/media/video/saa7134/saa7134-core.c	Thu Dec 31 19:14:54 2009 -0200
+++ b/linux/drivers/media/video/saa7134/saa7134-core.c	Fri Jan 29 09:57:54 2010 +0900
@@ -139,6 +139,18 @@
 		break;
 	}
 }
+
+unsigned long 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;
+}
+
 
 /* ------------------------------------------------------------------ */
 
@@ -1057,12 +1069,42 @@
 
 	saa7134_hwinit2(dev);
 
-	/* load i2c helpers */
+	/* initialize software SPI bus */
+	if (saa7134_boards[dev->board].spi.spi_enable)
+	{
+		dev->spi = saa7134_boards[dev->board].spi;
+
+		/* register SPI master and SPI slave */
+		if (saa7134_spi_register(dev, &saa7134_boards[dev->board].spi_conf))
+			saa7134_boards[dev->board].spi.spi_enable = 0;
+	}
+
+	/* 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 (saa7134_boards[dev->board].spi.spi_enable)
+				sd = v4l2_spi_new_subdev(&dev->v4l2_dev, dev->spi_adap, &saa7134_boards[dev->board].spi_conf);
+		}
+			break;
+		case SAA7134_ENCODER_SAA6752HS:
+		{
+			sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
 				"saa6752hs", "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;
@@ -1139,6 +1181,8 @@
 	return 0;
 
  fail4:
+	if ((card_is_empress(dev)) && (dev->encoder_type == SAA7134_ENCODER_muPD61151))
+		saa7134_spi_unregister(dev);
 	saa7134_unregister_video(dev);
 	saa7134_i2c_unregister(dev);
 	free_irq(pci_dev->irq, dev);
@@ -1412,6 +1456,7 @@
 /* ----------------------------------------------------------- */
 
 EXPORT_SYMBOL(saa7134_set_gpio);
+EXPORT_SYMBOL(saa7134_get_gpio);
 EXPORT_SYMBOL(saa7134_boards);
 
 /* ----------------- for the DMA sound modules --------------- */
diff -r b6b82258cf5e linux/drivers/media/video/saa7134/saa7134.h
--- a/linux/drivers/media/video/saa7134/saa7134.h	Thu Dec 31 19:14:54 2009 -0200
+++ b/linux/drivers/media/video/saa7134/saa7134.h	Fri Jan 29 09:57:54 2010 +0900
@@ -30,6 +30,13 @@
 #include <linux/notifier.h>
 #include <linux/delay.h>
 #include <linux/mutex.h>
+
+/* ifdef software SPI insert here start */
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_gpio.h>
+#include <linux/spi/spi_bitbang.h>
+/* ifdef software SPI insert here stop */
 
 #include <asm/io.h>
 
@@ -337,6 +344,21 @@
 	SAA7134_MPEG_TS_SERIAL,
 };
 
+enum saa7134_encoder_type {
+	SAA7134_ENCODER_UNUSED,
+	SAA7134_ENCODER_SAA6752HS,
+	SAA7134_ENCODER_muPD61151,
+};
+
+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 {
 	char                    *name;
 	unsigned int            audio_clock;
@@ -355,6 +377,10 @@
 	unsigned char		empress_addr;
 	unsigned char		rds_addr;
 
+	/* SPI info */
+	struct saa7134_software_spi	spi;
+	struct spi_board_info   spi_conf;
+
 	unsigned int            tda9887_conf;
 	unsigned int            tuner_config;
 
@@ -362,6 +388,7 @@
 	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;
 };
@@ -506,6 +533,12 @@
 	void                       (*signal_change)(struct saa7134_dev *dev);
 };
 
+struct saa7134_spi_gpio {
+	struct spi_bitbang         bitbang;
+	struct spi_master          *master;
+	struct saa7134_dev         *controller_data;
+};
+
 /* global device status */
 struct saa7134_dev {
 	struct list_head           devlist;
@@ -553,6 +586,10 @@
 	struct i2c_client          i2c_client;
 	unsigned char              eedata[256];
 	int 			   has_rds;
+
+	/* software spi */
+	struct saa7134_software_spi spi;
+	struct spi_master          *spi_adap;
 
 	/* video overlay */
 	struct v4l2_framebuffer    ovbuf;
@@ -615,6 +652,7 @@
 	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 */
@@ -681,6 +719,7 @@
 
 void saa7134_track_gpio(struct saa7134_dev *dev, char *msg);
 void saa7134_set_gpio(struct saa7134_dev *dev, int bit_no, int value);
+unsigned long saa7134_get_gpio(struct saa7134_dev *dev);
 
 #define SAA7134_PGTABLE_SIZE 4096
 
@@ -726,6 +765,11 @@
 int saa7134_i2c_register(struct saa7134_dev *dev);
 int saa7134_i2c_unregister(struct saa7134_dev *dev);
 
+/* ----------------------------------------------------------- */
+/* saa7134-spi.c                                               */
+
+int saa7134_spi_register(struct saa7134_dev *dev, struct spi_board_info *info);
+int saa7134_spi_unregister(struct saa7134_dev *dev);
 
 /* ----------------------------------------------------------- */
 /* saa7134-video.c                                             */
diff -r b6b82258cf5e linux/drivers/media/video/v4l2-common.c
--- a/linux/drivers/media/video/v4l2-common.c	Thu Dec 31 19:14:54 2009 -0200
+++ b/linux/drivers/media/video/v4l2-common.c	Fri Jan 29 09:57:54 2010 +0900
@@ -51,6 +51,7 @@
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/i2c.h>
+#include <linux/spi/spi.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/pgtable.h>
@@ -1069,6 +1070,75 @@
 
 #endif /* defined(CONFIG_I2C) */
 
+//#if defined(CONFIG_SPI) || (defined(CONFIG_SPI_MODULE) && defined(MODULE)) + SPI_BITBANG
+
+/* Load an spi sub-device. */
+
+void v4l2_spi_subdev_init(struct v4l2_subdev *sd, struct spi_device *spi,
+		const struct v4l2_subdev_ops *ops)
+{
+	v4l2_subdev_init(sd, ops);
+	sd->flags |= V4L2_SUBDEV_FL_IS_SPI;
+	/* the owner is the same as the spi_device's driver owner */
+	sd->owner = spi->dev.driver->owner;
+	/* spi_device and v4l2_subdev point to one another */
+	v4l2_set_subdevdata(sd, spi);
+	spi_set_drvdata(spi, sd);
+	/* initialize name */
+	snprintf(sd->name, sizeof(sd->name), "%s",
+		spi->dev.driver->name);
+}
+EXPORT_SYMBOL_GPL(v4l2_spi_subdev_init);
+
+struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev,
+		struct spi_master *master, struct spi_board_info *info)
+{
+	struct v4l2_subdev *sd = NULL;
+	struct spi_device *spi = NULL;
+
+	BUG_ON(!v4l2_dev);
+
+printk("befor request_module %s\n",info->modalias);
+	if (info->modalias)
+		request_module(info->modalias);
+
+	spi = spi_new_device(master,info);
+
+	if (spi == NULL || spi->dev.driver ==NULL)
+		goto error;
+
+	if (!try_module_get(spi->dev.driver->owner))
+		goto error;
+
+printk("befor spi_get_drvdata\n");
+	sd = spi_get_drvdata(spi);
+printk("subdev pointer = %p\n",sd);
+	/* Register with the v4l2_device which increases the module's
+	   use count as well. */
+printk("befor register_subdev\n");
+	if (v4l2_device_register_subdev(v4l2_dev, sd))
+		sd = NULL;
+
+	/* Decrease the module use count to match the first try_module_get. */
+	module_put(spi->dev.driver->owner);
+
+error:
+printk("DEBIG SPI:\n\tspi pointer = %p\n\tspi->dev.driver = %p\n\tsd pointer = %p\n",spi,spi->dev.driver,sd);
+	/* If we have a client but no subdev, then something went wrong and
+	   we must unregister the client. */
+	if (spi && sd == NULL)
+	{
+printk("null pointer in SPI part\n");
+
+		spi_unregister_device(spi);
+	}
+
+	return sd;
+}
+EXPORT_SYMBOL_GPL(v4l2_spi_new_subdev);
+
+//#endif /* defined(CONFIG_SPI) */
+
 /* Clamp x to be between min and max, aligned to a multiple of 2^align.  min
  * and max don't have to be aligned, but there must be at least one valid
  * value.  E.g., min=17,max=31,align=4 is not allowed as there are no multiples
diff -r b6b82258cf5e linux/include/media/v4l2-common.h
--- a/linux/include/media/v4l2-common.h	Thu Dec 31 19:14:54 2009 -0200
+++ b/linux/include/media/v4l2-common.h	Fri Jan 29 09:57:54 2010 +0900
@@ -191,6 +191,25 @@
 
 /* ------------------------------------------------------------------------- */
 
+/* SPI Helper functions */
+
+#include <linux/spi/spi.h>
+
+struct spi_device_id;
+struct spi_device;
+
+/* Load an spi module and return an initialized v4l2_subdev struct.
+   Only call request_module if module_name != NULL.
+   The client_type argument is the name of the chip that's on the adapter. */
+struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev,
+		struct spi_master *master, struct spi_board_info *info);
+
+/* Initialize an v4l2_subdev with data from an spi_device struct */
+void v4l2_spi_subdev_init(struct v4l2_subdev *sd, struct spi_device *spi,
+		const struct v4l2_subdev_ops *ops);
+
+/* ------------------------------------------------------------------------- */
+
 /* Note: these remaining ioctls/structs should be removed as well, but they are
    still used in tuner-simple.c (TUNER_SET_CONFIG), cx18/ivtv (RESET) and
    v4l2-int-device.h (v4l2_routing). To remove these ioctls some more cleanup
diff -r b6b82258cf5e linux/include/media/v4l2-subdev.h
--- a/linux/include/media/v4l2-subdev.h	Thu Dec 31 19:14:54 2009 -0200
+++ b/linux/include/media/v4l2-subdev.h	Fri Jan 29 09:57:54 2010 +0900
@@ -387,6 +387,8 @@
 
 /* Set this flag if this subdev is a i2c device. */
 #define V4L2_SUBDEV_FL_IS_I2C (1U << 0)
+/* Set this flag if this subdev is a spi device. */
+#define V4L2_SUBDEV_FL_IS_SPI (1U << 1)
 
 /* Each instance of a subdev driver should create this struct, either
    stand-alone or embedded in a larger struct.

[-- Attachment #3: dmesg.log --]
[-- Type: text/x-log, Size: 6990 bytes --]

[    4.743008] Linux video capture interface: v2.00
[    4.788866] saa7130/34: v4l2 driver version 0.2.15 loaded
[    4.788946] saa7134 0000:04:01.0: PCI INT A -> GSI 19 (level, low) -> IRQ 19
[    4.788996] saa7133[0]: found at 0000:04:01.0, rev: 209, irq: 19, latency: 32, mmio: 0xe5100000
[    4.789055] saa7133[0]: subsystem: 5ace:7595, board: Beholder BeholdTV X7 [card=171,autodetected]
[    4.789122] saa7133[0]: board init: gpio is 200000
[    4.789172] IRQ 19/saa7133[0]: IRQF_DISABLED is not guaranteed on shared IRQs
[    4.868459] HDA Intel 0000:00:1b.0: PCI INT A -> GSI 16 (level, low) -> IRQ 16
[    4.868533] HDA Intel 0000:00:1b.0: setting latency timer to 64
[    4.952004] saa7133[0]: i2c eeprom 00: ce 5a 95 75 54 20 00 00 00 00 00 00 00 00 00 01
[    4.952604] saa7133[0]: i2c eeprom 10: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.953202] saa7133[0]: i2c eeprom 20: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.953799] saa7133[0]: i2c eeprom 30: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.954397] saa7133[0]: i2c eeprom 40: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.954994] saa7133[0]: i2c eeprom 50: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.955592] saa7133[0]: i2c eeprom 60: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.956200] saa7133[0]: i2c eeprom 70: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.956798] saa7133[0]: i2c eeprom 80: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.957395] saa7133[0]: i2c eeprom 90: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.957993] saa7133[0]: i2c eeprom a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.958591] saa7133[0]: i2c eeprom b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.959189] saa7133[0]: i2c eeprom c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.959786] saa7133[0]: i2c eeprom d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    4.960394] saa7133[0]: i2c eeprom e0: 00 00 00 00 ff ff ff ff ff ff ff ff ff ff ff ff
[    4.960991] saa7133[0]: i2c eeprom f0: 42 54 56 30 30 30 30 ff ff ff ff ff ff ff ff ff
[    5.012044] tuner 1-0061: chip found @ 0xc2 (saa7133[0])
[    5.128672] xc5000 1-0061: creating new instance
[    5.136014] xc5000: Successfully identified at address 0x61
[    5.136067] xc5000: Firmware has not been loaded previously

[   33.425823] saa7134 0000:04:01.0: spi master registered: bus_num=32766 num_chipselect=1
[   33.425883] saa7133[0]: found muPD61151 MPEG encoder
[   33.425928] befor request_module upd61151
[   33.435609] upd61151_probe function
[   33.435654] Read test REG 0xD8 :
[   33.437463] REG = 0x0
[   33.437505] Write test 0x03 to REG 0xD8 :
[   33.439310] Next read test REG 0xD8 :
[   33.441123] REG = 0x3
[   33.441167] befor spi_get_drvdata
[   33.441210] subdev pointer = f646e7c0
[   33.441253] befor register_subdev
[   33.441297] DEBIG SPI:
[   33.441298] 	spi pointer = f7087580
[   33.441298] 	spi->dev.driver = f873dd70
[   33.441299] 	sd pointer = f646e7c0
[   33.441579] saa7133[0]: registered device video0 [v4l2]
[   33.441640] saa7133[0]: registered device vbi0
[   33.441700] saa7133[0]: registered device radio0
[   33.459770] saa7133[0]: registered device video1 [mpeg]
[   33.486244] saa7134 ALSA driver for DMA sound loaded
[   33.486301] IRQ 19/saa7133[0]: IRQF_DISABLED is not guaranteed on shared IRQs
[   33.486364] saa7133[0]/alsa: saa7133[0] at 0xe5100000 irq 19 registered as card -1

[   48.557569] xc5000: I2C write failed (len=4)
[   48.660019] xc5000: I2C write failed (len=4)
[   48.662966] xc5000: I2C read failed
[   48.663016] xc5000: I2C read failed
[   48.663060] xc5000: waiting for firmware upload (dvb-fe-xc5000-1.6.114.fw)...
[   48.663108] saa7134 0000:04:01.0: firmware: requesting dvb-fe-xc5000-1.6.114.fw
[   48.705533] xc5000: firmware read 12401 bytes.
[   48.705535] xc5000: firmware uploading...

[   52.044007] xc5000: firmware upload complete...
[   52.796008] DEBUG uPD61151: upd61151_s_std
[   52.796058] DEBUG uPD61151: upd61151_s_std
[   53.268008] DEBUG uPD61151: upd61151_s_std
[   53.268060] DEBUG uPD61151: upd61151_s_std
[   53.270837] ------------[ cut here ]------------
[   53.270884] kernel BUG at lib/kernel_lock.c:126!
[   53.270929] invalid opcode: 0000 [#1] SMP 
[   53.271037] last sysfs file: /sys/class/firmware/0000:04:01.0/loading
[   53.271084] Modules linked in: ipv6 dm_snapshot dm_mirror dm_region_hash dm_log dm_mod loop saa7134_alsa saa7134_empress upd61151 ir_kbd_i2c xc5000 tuner snd_hda_codec_realtek snd_hda_intel snd_hda_codec snd_pcm_oss snd_mixer_oss snd_pcm snd_seq_dummy saa7134 ir_common v4l2_common videodev snd_seq_oss v4l1_compat videobuf_dma_sg videobuf_core spi_bitbang snd_seq_midi ir_core snd_rawmidi tveeprom psmouse snd_seq_midi_event serio_raw snd_seq snd_timer snd_seq_device i2c_i801 i2c_core rng_core pcspkr snd soundcore parport_pc parport snd_page_alloc button processor intel_agp agpgart evdev ext3 jbd mbcache sg sr_mod cdrom sd_mod ata_generic ata_piix libata scsi_mod ehci_hcd ide_pci_generic uhci_hcd ide_core usbcore r8169 mii thermal fan thermal_sys [last unloaded: scsi_wait_scan]
[   53.273694] 
[   53.273737] Pid: 2675, comm: hald-probe-vide Not tainted (2.6.30.5 #1) G31M-ES2L
[   53.273793] EIP: 0060:[<c02f81e3>] EFLAGS: 00010286 CPU: 0
[   53.273841] EIP is at unlock_kernel+0xd/0x24
[   53.273885] EAX: f6b7f6ac EBX: f6b7f000 ECX: f6b7f6ac EDX: f7168b20
[   53.273932] ESI: 00000000 EDI: f6860640 EBP: f6b7f6ac ESP: f66c9e68
[   53.273978]  DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068
[   53.274024] Process hald-probe-vide (pid: 2675, ti=f66c8000 task=f7168b20 task.ti=f66c8000)
[   53.274079] Stack:
[   53.274121]  f87499c9 00000000 f69c9804 f6860640 00000000 f8504309 00000000 f6940e00
[   53.274360]  f6940e00 c0190049 f6860640 f6aec86c 00000000 f6860640 00000000 f6aec86c
[   53.274360]  c018ff24 c018c3b9 f701e1c0 f6d148d0 f6860640 f66c9f0c f66c9f0c 00008001
[   53.274360] Call Trace:
[   53.274360]  [<f87499c9>] ? ts_open+0x8c/0x93 [saa7134_empress]
[   53.274360]  [<f8504309>] ? v4l2_open+0x65/0x78 [videodev]
[   53.274360]  [<c0190049>] ? chrdev_open+0x125/0x13c
[   53.274360]  [<c018ff24>] ? chrdev_open+0x0/0x13c
[   53.274360]  [<c018c3b9>] ? __dentry_open+0x119/0x208
[   53.274360]  [<c018c539>] ? nameidata_to_filp+0x29/0x3c
[   53.274360]  [<c0197338>] ? do_filp_open+0x41e/0x7bc
[   53.274360]  [<c017bb3c>] ? handle_mm_fault+0x294/0x5fd
[   53.274360]  [<c019e267>] ? alloc_fd+0x52/0xb8
[   53.274360]  [<c018c1d1>] ? do_sys_open+0x44/0xb4
[   53.274360]  [<c018c285>] ? sys_open+0x1e/0x23
[   53.274360]  [<c0102f74>] ? sysenter_do_call+0x12/0x28
[   53.274360] Code: 0f c1 05 e0 4b 3e c0 38 e0 74 09 f3 90 a0 e0 4b 3e c0 eb f3 64 a1 00 b0 43 c0 89 50 14 c3 64 8b 15 00 b0 43 c0 83 7a 14 00 79 04 <0f> 0b eb fe 8b 42 14 48 85 c0 89 42 14 79 07 f0 fe 05 e0 4b 3e 
[   53.274360] EIP: [<c02f81e3>] unlock_kernel+0xd/0x24 SS:ESP 0068:f66c9e68
[   53.278380] ---[ end trace 717d799b0d534ca3 ]---

[-- Attachment #4: saa7134-spi.c --]
[-- Type: text/x-c++src, Size: 4869 bytes --]

/*
 *
 * 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.
 */

#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)
{
	udelay(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);
	if ( status & (1 << sb->controller_data->spi.miso))
		return 1;
	else
		return 0;
}

#define EXPAND_BITBANG_TXRX 1
#include <linux/spi/spi_bitbang.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, word, bits);
}

static int saa7134_setup(struct spi_device *spi, struct spi_transfer *t)
{
	return spi_bitbang_setup_transfer(spi, t);
}

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;
	sb->bitbang.setup_transfer = saa7134_setup;

	/* 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;
}

int 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);

	return 0;
}


/*
 * Overrides for Emacs so that we follow Linus's tabbing style.
 * ---------------------------------------------------------------------------
 * Local variables:
 * c-basic-offset: 8
 * End:
 */
 

[-- Attachment #5: upd61151.c --]
[-- Type: text/x-c++src, Size: 9221 bytes --]

 /*
    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 <linux/mod_devicetable.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 MPEG_VIDEO_TARGET_BITRATE_MAX  27000
#define MPEG_VIDEO_MAX_BITRATE_MAX     27000
#define MPEG_TOTAL_TARGET_BITRATE_MAX  27000
#define MPEG_PID_MAX ((1 << 14) - 1)

#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 if (1 == spi_debug) printk
#define d2printk if (2 == spi_debug) printk

MODULE_DESCRIPTION("device driver for uPD61151 MPEG2 encoder");
MODULE_AUTHOR("Dmitry V Belimov");
MODULE_LICENSE("GPL");

enum upd61151_videoformat {
	UPD61151_VF_D1 = 0,    /* standard D1 video format: 720x576 */
	UPD61151_VF_2_3_D1 = 1,/* 2/3D1 video format: 480x576 */
	UPD61151_VF_1_2_D1 = 2,/* 1/2D1 video format: 352x576 */
	UPD61151_VF_SIF = 3,   /* SIF video format: 352x288 */
	UPD61151_VF_UNKNOWN,
};

struct upd61151_mpeg_params {
	/* transport streams */
	__u16				ts_pid_pmt;
	__u16				ts_pid_audio;
	__u16				ts_pid_video;
	__u16				ts_pid_pcr;

	/* audio */
	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;
};

static const struct v4l2_format v4l2_format_table[] =
{
	[UPD61151_VF_D1] =
		{ .fmt = { .pix = { .width = 720, .height = 576 }}},
	[UPD61151_VF_2_3_D1] =
		{ .fmt = { .pix = { .width = 480, .height = 576 }}},
	[UPD61151_VF_1_2_D1] =
		{ .fmt = { .pix = { .width = 352, .height = 576 }}},
	[UPD61151_VF_SIF] =
		{ .fmt = { .pix = { .width = 352, .height = 288 }}},
	[UPD61151_VF_UNKNOWN] =
		{ .fmt = { .pix = { .width = 0, .height = 0}}},
};

struct upd61151_state {
	struct v4l2_subdev            sd;
	int 			      chip;
	u32 			      revision;
	struct upd61151_mpeg_params   params;
	enum upd61151_videoformat     video_format;
	v4l2_std_id                   standard;
};

enum upd61151_command {
	UPD61151_COMMAND_RESET = 0,
	UPD61151_COMMAND_STOP = 1,
	UPD61151_COMMAND_START = 2,
	UPD61151_COMMAND_PAUSE = 3,
	UPD61151_COMMAND_RECONFIGURE = 4,
	UPD61151_COMMAND_SLEEP = 5,
	UPD61151_COMMAND_RECONFIGURE_FORCE = 6,

	UPD61151_COMMAND_MAX
};

static int write_reg(struct spi_device *spi, u8 address, u8 data)
{
	u8 buf[2];

	buf[0] = ((address >> 2) << 2);
	buf[1] = data;

	d2printk(KERN_DEBUG "%s: spi data 0x%x <= 0x%x\n",spi->modalias,address,data);

	return spi_write(spi, buf, ARRAY_SIZE(buf));
}

static int read_reg(struct spi_device *spi, unsigned char address, unsigned char *data)
{
	u8 txbuf[1];
	int ret;

	ret = 0;

	txbuf[0] = ((address >> 2) << 2) | 0x02;

	ret = spi_write_then_read(spi, txbuf, 1, data, 1);

	d2printk(KERN_DEBUG "%s: spi data 0x%x => 0x%x, status %d\n",spi->modalias, address, *data, ret);

	return ret;
}

static struct upd61151_mpeg_params param_defaults =
{
	.ts_pid_pmt      = 16,
	.ts_pid_video    = 260,
	.ts_pid_audio    = 256,
	.ts_pid_pcr      = 259,

	.vi_aspect       = V4L2_MPEG_VIDEO_ASPECT_4x3,
	.vi_bitrate      = 4000,
	.vi_bitrate_peak = 6000,
	.vi_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,

	.au_encoding     = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
	.au_l2_bitrate   = V4L2_MPEG_AUDIO_L2_BITRATE_256K,
};

#if 0
static int upd61151_chip_command(struct spi_device *spi,
				  enum upd61151_command command)
{
printk("DEBUG uPD61151: upd61151_chip_command\n");
	return 0;
}

static int upd61151_set_bitrate(struct spi_device *spi,
				 struct upd61151_state *h)
{
printk("DEBUG uPD61151: upd61151_set_bitrate\n");
	return 0;
}
#endif

static int upd61151_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qctrl)
{
printk("DEBUG uPD61151: upd61151_queryctrl\n");
	return 0;
}

static int upd61151_querymenu(struct v4l2_subdev *sd, struct v4l2_querymenu *qmenu)
{
printk("DEBUG uPD61151: upd61151_querymenu\n");
	return 0;
}

static int upd61151_init(struct v4l2_subdev *sd, u32 flags)
{
printk("DEBUG uPD61151: upd61151_init\n");
	return 0;
}

static int upd61151_do_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls, int set)
{
printk("DEBUG uPD61151: upd61151_do_ext_ctrls\n");
	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)
{
printk("DEBUG uPD61151: upd61151_g_ext_ctrls\n");
	return 0;
}

static int upd61151_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
{
printk("DEBUG uPD61151: upd61151_g_fmt\n");
	return 0;
}

static int upd61151_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
{
printk("DEBUG uPD61151: upd61151_s_fmt\n");
	return 0;
}

static int upd61151_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
{
printk("DEBUG uPD61151: upd61151_s_std\n");
	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");
	return 0;
}

/* ----------------------------------------------------------------------- */

static const struct v4l2_subdev_core_ops upd61151_core_ops = {
	.g_chip_ident = upd61151_g_chip_ident,
	.init = upd61151_init,
	.queryctrl = upd61151_queryctrl,
	.querymenu = upd61151_querymenu,
	.g_ext_ctrls = upd61151_g_ext_ctrls,
	.s_ext_ctrls = upd61151_s_ext_ctrls,
	.try_ext_ctrls = upd61151_try_ext_ctrls,
	.s_std = upd61151_s_std,
};

static const struct v4l2_subdev_video_ops upd61151_video_ops = {
	.s_fmt = upd61151_s_fmt,
	.g_fmt = upd61151_g_fmt,
};

static const struct v4l2_subdev_ops upd61151_ops = {
	.core = &upd61151_core_ops,
	.video = &upd61151_video_ops,
};

static int __devinit upd61151_probe(struct spi_device *spi)
{
	struct upd61151_state *h = kzalloc(sizeof(*h), GFP_KERNEL);
	struct v4l2_subdev *sd;
	u8 rx_buf[2];

printk("upd61151_probe function\n");

printk("Read test REG 0xD8 :\n");

	read_reg(spi, 0xD8, &rx_buf[0]);

printk("REG = 0x%X\n",rx_buf[0]);

printk("Write test 0x03 to REG 0xD8 :\n");

	write_reg(spi, 0xD8, 0x03);

printk("Next read test REG 0xD8 :\n");

	read_reg(spi, 0xD8, &rx_buf[0]);

printk("REG = 0x%X\n",rx_buf[0]);

	if (h == NULL)
		return -ENOMEM;
	sd = &h->sd;

	v4l2_spi_subdev_init(sd, spi, &upd61151_ops);

	spi_set_drvdata(spi, h);

/* function for detect a chip here */
//	h->chip = upd61151_detect(h);

	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->sd);
	spi_unregister_device(spi);
	return 0;
}

#if 0
static const struct spi_device_id upd61151_ids[] = {
	{ "upd61151", 1 },
	{ "upd61152", 2 },
	{ },
};
MODULE_DEVICE_TABLE(spi, upd61151_ids);
#endif

static struct spi_driver upd61151_driver = {
	.driver = {
		.name   = DRVNAME,
		.bus    = &spi_bus_type,
		.owner  = THIS_MODULE,
	},
//	.id_table = upd61151_ids,
	.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);

/*
 * Overrides for Emacs so that we follow Linus's tabbing style.
 * ---------------------------------------------------------------------------
 * Local variables:
 * c-basic-offset: 8
 * End:
 */

[-- Attachment #6: upd61151.h --]
[-- Type: text/x-chdr, Size: 2276 bytes --]

/*
    upd61151.h - definition for muPD61151 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.
*/

#if 0 /* ndef _UPD61151_H */
#define _UPD61151_H

#include <linux/firmware.h>

#define MUPD61151_DEFAULT_PS_FIRMWARE "D61151_PS_64_byte_7133_v22_031031.bin"
#define MUPD61151_DEFAULT_PS_FIRMWARE_SIZE 97002

#define MUPD61151_DEFAULT_AUDIO_FIRMWARE "audrey_MPE_V1r51.bin"
#define MUPD61151_DEFAULT_AUDIO_FIRMWARE_SIZE 40064

enum mpeg_video_bitrate_mode {
	MPEG_VIDEO_BITRATE_MODE_VBR = 0, /* Variable bitrate */
	MPEG_VIDEO_BITRATE_MODE_CBR = 1, /* Constant bitrate */

	MPEG_VIDEO_BITRATE_MODE_MAX
};

enum mpeg_audio_bitrate {
	MPEG_AUDIO_BITRATE_256 = 0, /* 256 kBit/sec */
	MPEG_AUDIO_BITRATE_384 = 1, /* 384 kBit/sec */

	MPEG_AUDIO_BITRATE_MAX
};

enum mpeg_video_format {
	MPEG_VIDEO_FORMAT_D1 = 0,
	MPEG_VIDEO_FORMAT_2_3_D1 = 1,
	MPEG_VIDEO_FORMAT_1_2_D1 = 2,
	MPEG_VIDEO_FORMAT_SIF = 3,

	MPEG_VIDEO_FORMAT_MAX
};

#define MPEG_VIDEO_TARGET_BITRATE_MAX 27000
#define MPEG_VIDEO_MAX_BITRATE_MAX 27000
#define MPEG_TOTAL_BITRATE_MAX 27000
#define MPEG_PID_MAX ((1 << 14) - 1)

struct mpeg_params {
	enum mpeg_video_bitrate_mode video_bitrate_mode;
	unsigned int video_target_bitrate;
	unsigned int video_max_bitrate; // only used for VBR
	enum mpeg_audio_bitrate audio_bitrate;
	unsigned int total_bitrate;

	unsigned int pmt_pid;
	unsigned int video_pid;
	unsigned int audio_pid;
	unsigned int pcr_pid;

	enum mpeg_video_format video_format;
};

#endif // _UPD61151_H

/*
 * Local variables:
 * c-basic-offset: 8
 * End:
 */

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: saa7134 and μPD61151 MPEG2 coder
  2010-01-29  7:12               ` Dmitri Belimov
@ 2010-02-09  5:41                 ` Dmitri Belimov
  2010-02-12 15:44                   ` Hans Verkuil
  0 siblings, 1 reply; 14+ messages in thread
From: Dmitri Belimov @ 2010-02-09  5:41 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: Mauro Carvalho Chehab, linux-media

[-- Attachment #1: Type: text/plain, Size: 22381 bytes --]

Hi Hans

This is my last state for review.
After small time I'll finish process of initialize the encoder.
Configure some register, upload two firmware for video and for audio.
Configure the frontends.

I have the questions.
For configuring audio frontend need know samplerate of audio.
saa7134 can only 32kHz
saa7131/3/5 on I2S 32кГц from SIF source and 32/44.1/48 from external i.e.
RCA stereo audio input. 

Hardcode 32kHz or need a function for determine mode of audio??

Other question. For configure VideoFrontend need know 50 or 60Hz
Now I use videomode from h structure. I think more correct detect it
on saa7134.

What you think??

Dmesg with normal and junk debug printk.

[    4.901675] Linux video capture interface: v2.00
[    5.046878] saa7130/34: v4l2 driver version 0.2.15 loaded
[    5.046964] saa7134 0000:04:01.0: PCI INT A -> GSI 19 (level, low) -> IRQ 19
[    5.047018] saa7133[0]: found at 0000:04:01.0, rev: 209, irq: 19, latency: 32, mmio: 0xe5100000
[    5.047080] saa7133[0]: subsystem: 5ace:7595, board: Beholder BeholdTV X7 [card=171,autodetected]
[    5.047153] saa7133[0]: board init: gpio is 200000
[    5.047205] IRQ 19/saa7133[0]: IRQF_DISABLED is not guaranteed on shared IRQs
[    5.196517] saa7133[0]: i2c eeprom 00: ce 5a<6>HDA Intel 0000:00:1b.0: PCI INT A -> GSI 16 (level, low) -> IRQ 16
[    5.196620] HDA Intel 0000:00:1b.0: setting latency timer to 64
[    5.196687]  95 75 54 20 00 00 00 00 00 00 00 00 00 01
[    5.197190] saa7133[0]: i2c eeprom 10: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    5.197787] saa7133[0]: i2c eeprom 20: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    5.198385] saa7133[0]: i2c eeprom 30: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    5.198982] saa7133[0]: i2c eeprom 40: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    5.199579] saa7133[0]: i2c eeprom 50: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    5.200176] saa7133[0]: i2c eeprom 60: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    5.200785] saa7133[0]: i2c eeprom 70: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    5.201382] saa7133[0]: i2c eeprom 80: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    5.201979] saa7133[0]: i2c eeprom 90: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    5.202576] saa7133[0]: i2c eeprom a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    5.203174] saa7133[0]: i2c eeprom b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    5.203771] saa7133[0]: i2c eeprom c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    5.204371] saa7133[0]: i2c eeprom d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    5.204982] saa7133[0]: i2c eeprom e0: 00 00 00 00 ff ff ff ff ff ff ff ff ff ff ff ff
[    5.205579] saa7133[0]: i2c eeprom f0: 42 54 56 30 30 30 30 ff ff ff ff ff ff ff ff ff
[    5.228577] tuner 1-0061: chip found @ 0xc2 (saa7133[0])
[    5.286091] xc5000 1-0061: creating new instance
[    5.292505] xc5000: Successfully identified at address 0x61
[    5.292552] xc5000: Firmware has not been loaded previously
[   33.571875] saa7134 0000:04:01.0: spi master registered: bus_num=32766 num_chipselect=1
[   33.571933] saa7133[0]: found muPD61151 MPEG encoder
[   33.601819] upd61151_probe function
[   33.602057] upd61151: MPEG2 core status 0
[   33.602058] upd61151: need reload firmware
[   33.602059] Start load firmware...
[   33.602103] DEBUG: upd61151_download_firmware
[   33.603325] DEBUG: upd61151_load_base_firmware
[   33.603370] upd61151: waiting for base firmware upload (D61151_PS_7133_v22_031031.bin)...
[   33.603427] saa7134 0000:04:01.0: firmware: requesting D61151_PS_7133_v22_031031.bin
[   33.676430] upd61151: firmware read 97002 bytes.
[   33.676432] upd61151: base firmware uploading...
[   33.677071] upd61151: Transfer IRQ status 0x0
[   33.678539] fw upload start
[   51.433446] fw upload stop
[   51.433677] upd61151: Transfer IRQ status 0x1
[   51.434043] upd61151: base firmware upload complete...
[   51.434285] DEBUG: upd61151_load_audio_firmware
[   51.434330] upd61151: waiting for audio firmware upload (audrey_MPE_V1r51.bin)...
[   51.434386] saa7134 0000:04:01.0: firmware: requesting audrey_MPE_V1r51.bin
[   51.482980] upd61151: firmware read 40064 bytes.
[   51.482982] upd61151: audio firmware uploading...
[   51.483231] upd61151: Transfer IRQ status 0x1
[   51.484700] fw upload start
[   51.508682] upd61151: Transfer IRQ status 0x2
[   51.532479] upd61151: Transfer IRQ status 0x2
[   51.556280] upd61151: Transfer IRQ status 0x2
[   51.580081] upd61151: Transfer IRQ status 0x2
[   51.603877] upd61151: Transfer IRQ status 0x2
[   51.627677] upd61151: Transfer IRQ status 0x2
[   51.651476] upd61151: Transfer IRQ status 0x2
[   51.675275] upd61151: Transfer IRQ status 0x2
[   51.699072] upd61151: Transfer IRQ status 0x2
[   51.722870] upd61151: Transfer IRQ status 0x2
[   51.746669] upd61151: Transfer IRQ status 0x2
[   51.770467] upd61151: Transfer IRQ status 0x2
[   51.794267] upd61151: Transfer IRQ status 0x2
[   51.818092] upd61151: Transfer IRQ status 0x2
[   51.841896] upd61151: Transfer IRQ status 0x2
[   51.865691] upd61151: Transfer IRQ status 0x2
[   51.889493] upd61151: Transfer IRQ status 0x2
[   51.913290] upd61151: Transfer IRQ status 0x2
[   51.937091] upd61151: Transfer IRQ status 0x2
[   51.960889] upd61151: Transfer IRQ status 0x2
[   51.984690] upd61151: Transfer IRQ status 0x2
[   52.008479] upd61151: Transfer IRQ status 0x2
[   52.032279] upd61151: Transfer IRQ status 0x2
[   52.056076] upd61151: Transfer IRQ status 0x2
[   52.079877] upd61151: Transfer IRQ status 0x2
[   52.103674] upd61151: Transfer IRQ status 0x2
[   52.127474] upd61151: Transfer IRQ status 0x2
[   52.151273] upd61151: Transfer IRQ status 0x2
[   52.175072] upd61151: Transfer IRQ status 0x2
[   52.198874] upd61151: Transfer IRQ status 0x2
[   52.222672] upd61151: Transfer IRQ status 0x2
[   52.246474] upd61151: Transfer IRQ status 0x2
[   52.270272] upd61151: Transfer IRQ status 0x2
[   52.294074] upd61151: Transfer IRQ status 0x2
[   52.317873] upd61151: Transfer IRQ status 0x2
[   52.341674] upd61151: Transfer IRQ status 0x2
[   52.365472] upd61151: Transfer IRQ status 0x2
[   52.389274] upd61151: Transfer IRQ status 0x2
[   52.413073] upd61151: Transfer IRQ status 0x2
[   52.436873] upd61151: Transfer IRQ status 0x2
[   52.460672] upd61151: Transfer IRQ status 0x2
[   52.484670] upd61151: Transfer IRQ status 0x2
[   52.508459] upd61151: Transfer IRQ status 0x2
[   52.532260] upd61151: Transfer IRQ status 0x2
[   52.556055] upd61151: Transfer IRQ status 0x2
[   52.579856] upd61151: Transfer IRQ status 0x2
[   52.603651] upd61151: Transfer IRQ status 0x2
[   52.627447] upd61151: Transfer IRQ status 0x2
[   52.651246] upd61151: Transfer IRQ status 0x2
[   52.675042] upd61151: Transfer IRQ status 0x2
[   52.698844] upd61151: Transfer IRQ status 0x2
[   52.722641] upd61151: Transfer IRQ status 0x2
[   52.746440] upd61151: Transfer IRQ status 0x2
[   52.770234] upd61151: Transfer IRQ status 0x2
[   52.794035] upd61151: Transfer IRQ status 0x2
[   52.817838] upd61151: Transfer IRQ status 0x2
[   52.841642] upd61151: Transfer IRQ status 0x2
[   52.865437] upd61151: Transfer IRQ status 0x2
[   52.889237] upd61151: Transfer IRQ status 0x2
[   52.913035] upd61151: Transfer IRQ status 0x2
[   52.936835] upd61151: Transfer IRQ status 0x2
[   52.960630] upd61151: Transfer IRQ status 0x2
[   52.984419] upd61151: Transfer IRQ status 0x2
[   53.008218] upd61151: Transfer IRQ status 0x2
[   53.032021] upd61151: Transfer IRQ status 0x2
[   53.055820] upd61151: Transfer IRQ status 0x2
[   53.079619] upd61151: Transfer IRQ status 0x2
[   53.103421] upd61151: Transfer IRQ status 0x2
[   53.127220] upd61151: Transfer IRQ status 0x2
[   53.151024] upd61151: Transfer IRQ status 0x2
[   53.174821] upd61151: Transfer IRQ status 0x2
[   53.198623] upd61151: Transfer IRQ status 0x2
[   53.222422] upd61151: Transfer IRQ status 0x2
[   53.246223] upd61151: Transfer IRQ status 0x2
[   53.270022] upd61151: Transfer IRQ status 0x2
[   53.293824] upd61151: Transfer IRQ status 0x2
[   53.317621] upd61151: Transfer IRQ status 0x2
[   53.341422] upd61151: Transfer IRQ status 0x2
[   53.365220] upd61151: Transfer IRQ status 0x2
[   53.389024] upd61151: Transfer IRQ status 0x2
[   53.412826] upd61151: Transfer IRQ status 0x2
[   53.436626] upd61151: Transfer IRQ status 0x2
[   53.460413] upd61151: Transfer IRQ status 0x2
[   53.484231] upd61151: Transfer IRQ status 0x2
[   53.508029] upd61151: Transfer IRQ status 0x2
[   53.531827] upd61151: Transfer IRQ status 0x2
[   53.555627] upd61151: Transfer IRQ status 0x2
[   53.579425] upd61151: Transfer IRQ status 0x2
[   53.603224] upd61151: Transfer IRQ status 0x2
[   53.627018] upd61151: Transfer IRQ status 0x2
[   53.650820] upd61151: Transfer IRQ status 0x2
[   53.674617] upd61151: Transfer IRQ status 0x2
[   53.698418] upd61151: Transfer IRQ status 0x2
[   53.722216] upd61151: Transfer IRQ status 0x2
[   53.746019] upd61151: Transfer IRQ status 0x2
[   53.769817] upd61151: Transfer IRQ status 0x2
[   53.793618] upd61151: Transfer IRQ status 0x2
[   53.817443] upd61151: Transfer IRQ status 0x2
[   53.841246] upd61151: Transfer IRQ status 0x2
[   53.865044] upd61151: Transfer IRQ status 0x2
[   53.888846] upd61151: Transfer IRQ status 0x2
[   53.912644] upd61151: Transfer IRQ status 0x2
[   53.936435] upd61151: Transfer IRQ status 0x2
[   53.960233] upd61151: Transfer IRQ status 0x2
[   53.984035] upd61151: Transfer IRQ status 0x2
[   54.007833] upd61151: Transfer IRQ status 0x2
[   54.031631] upd61151: Transfer IRQ status 0x2
[   54.055433] upd61151: Transfer IRQ status 0x2
[   54.079230] upd61151: Transfer IRQ status 0x2
[   54.103030] upd61151: Transfer IRQ status 0x2
[   54.126828] upd61151: Transfer IRQ status 0x2
[   54.150631] upd61151: Transfer IRQ status 0x2
[   54.174428] upd61151: Transfer IRQ status 0x2
[   54.198228] upd61151: Transfer IRQ status 0x2
[   54.222026] upd61151: Transfer IRQ status 0x2
[   54.245827] upd61151: Transfer IRQ status 0x2
[   54.269624] upd61151: Transfer IRQ status 0x2
[   54.293426] upd61151: Transfer IRQ status 0x2
[   54.317223] upd61151: Transfer IRQ status 0x2
[   54.341024] upd61151: Transfer IRQ status 0x2
[   54.364821] upd61151: Transfer IRQ status 0x2
[   54.388621] upd61151: Transfer IRQ status 0x2
[   54.412408] upd61151: Transfer IRQ status 0x2
[   54.436209] upd61151: Transfer IRQ status 0x2
[   54.460007] upd61151: Transfer IRQ status 0x2
[   54.483824] upd61151: Transfer IRQ status 0x2
[   54.507626] upd61151: Transfer IRQ status 0x2
[   54.531422] upd61151: Transfer IRQ status 0x2
[   54.555223] upd61151: Transfer IRQ status 0x2
[   54.579020] upd61151: Transfer IRQ status 0x2
[   54.602822] upd61151: Transfer IRQ status 0x2
[   54.626620] upd61151: Transfer IRQ status 0x2
[   54.650421] upd61151: Transfer IRQ status 0x2
[   54.674217] upd61151: Transfer IRQ status 0x2
[   54.698018] upd61151: Transfer IRQ status 0x2
[   54.721816] upd61151: Transfer IRQ status 0x2
[   54.745616] upd61151: Transfer IRQ status 0x2
[   54.769414] upd61151: Transfer IRQ status 0x2
[   54.793215] upd61151: Transfer IRQ status 0x2
[   54.817014] upd61151: Transfer IRQ status 0x2
[   54.840815] upd61151: Transfer IRQ status 0x2
[   54.864614] upd61151: Transfer IRQ status 0x2
[   54.888404] upd61151: Transfer IRQ status 0x2
[   54.912203] upd61151: Transfer IRQ status 0x2
[   54.936005] upd61151: Transfer IRQ status 0x2
[   54.959804] upd61151: Transfer IRQ status 0x2
[   54.983601] upd61151: Transfer IRQ status 0x2
[   55.007405] upd61151: Transfer IRQ status 0x2
[   55.031203] upd61151: Transfer IRQ status 0x2
[   55.055004] upd61151: Transfer IRQ status 0x2
[   55.078802] upd61151: Transfer IRQ status 0x2
[   55.102603] upd61151: Transfer IRQ status 0x2
[   55.126401] upd61151: Transfer IRQ status 0x2
[   55.150202] upd61151: Transfer IRQ status 0x2
[   55.174000] upd61151: Transfer IRQ status 0x2
[   55.197802] upd61151: Transfer IRQ status 0x2
[   55.221599] upd61151: Transfer IRQ status 0x2
[   55.245398] upd61151: Transfer IRQ status 0x2
[   55.269196] upd61151: Transfer IRQ status 0x2
[   55.292997] upd61151: Transfer IRQ status 0x2
[   55.316794] upd61151: Transfer IRQ status 0x2
[   55.340595] upd61151: Transfer IRQ status 0x2
[   55.364383] upd61151: Transfer IRQ status 0x2
[   55.388184] upd61151: Transfer IRQ status 0x2
[   55.411983] upd61151: Transfer IRQ status 0x2
[   55.435779] upd61151: Transfer IRQ status 0x2
[   55.459581] upd61151: Transfer IRQ status 0x2
[   55.483393] upd61151: Transfer IRQ status 0x2
[   55.507195] upd61151: Transfer IRQ status 0x2
[   55.530992] upd61151: Transfer IRQ status 0x2
[   55.554793] upd61151: Transfer IRQ status 0x2
[   55.578591] upd61151: Transfer IRQ status 0x2
[   55.602391] upd61151: Transfer IRQ status 0x2
[   55.626189] upd61151: Transfer IRQ status 0x2
[   55.649991] upd61151: Transfer IRQ status 0x2
[   55.673788] upd61151: Transfer IRQ status 0x2
[   55.697606] upd61151: Transfer IRQ status 0x2
[   55.721404] upd61151: Transfer IRQ status 0x2
[   55.745206] upd61151: Transfer IRQ status 0x2
[   55.769003] upd61151: Transfer IRQ status 0x2
[   55.792804] upd61151: Transfer IRQ status 0x2
[   55.816633] upd61151: Transfer IRQ status 0x2
[   55.840426] upd61151: Transfer IRQ status 0x2
[   55.864222] upd61151: Transfer IRQ status 0x2
[   55.888018] upd61151: Transfer IRQ status 0x2
[   55.911820] upd61151: Transfer IRQ status 0x2
[   55.935618] upd61151: Transfer IRQ status 0x2
[   55.959420] upd61151: Transfer IRQ status 0x2
[   55.983214] upd61151: Transfer IRQ status 0x2
[   56.007017] upd61151: Transfer IRQ status 0x2
[   56.030816] upd61151: Transfer IRQ status 0x2
[   56.054618] upd61151: Transfer IRQ status 0x2
[   56.078417] upd61151: Transfer IRQ status 0x2
[   56.102219] upd61151: Transfer IRQ status 0x2
[   56.126018] upd61151: Transfer IRQ status 0x2
[   56.149820] upd61151: Transfer IRQ status 0x2
[   56.173619] upd61151: Transfer IRQ status 0x2
[   56.197419] upd61151: Transfer IRQ status 0x2
[   56.221217] upd61151: Transfer IRQ status 0x2
[   56.245019] upd61151: Transfer IRQ status 0x2
[   56.268816] upd61151: Transfer IRQ status 0x2
[   56.292616] upd61151: Transfer IRQ status 0x2
[   56.316404] upd61151: Transfer IRQ status 0x2
[   56.340203] upd61151: Transfer IRQ status 0x2
[   56.364005] upd61151: Transfer IRQ status 0x2
[   56.387804] upd61151: Transfer IRQ status 0x2
[   56.411606] upd61151: Transfer IRQ status 0x2
[   56.435405] upd61151: Transfer IRQ status 0x2
[   56.459209] upd61151: Transfer IRQ status 0x2
[   56.483029] upd61151: Transfer IRQ status 0x2
[   56.506831] upd61151: Transfer IRQ status 0x2
[   56.530626] upd61151: Transfer IRQ status 0x2
[   56.554428] upd61151: Transfer IRQ status 0x2
[   56.578225] upd61151: Transfer IRQ status 0x2
[   56.602026] upd61151: Transfer IRQ status 0x2
[   56.625825] upd61151: Transfer IRQ status 0x2
[   56.649628] upd61151: Transfer IRQ status 0x2
[   56.673427] upd61151: Transfer IRQ status 0x2
[   56.697230] upd61151: Transfer IRQ status 0x2
[   56.721026] upd61151: Transfer IRQ status 0x2
[   56.744827] upd61151: Transfer IRQ status 0x2
[   56.768626] upd61151: Transfer IRQ status 0x2
[   56.792418] upd61151: Transfer IRQ status 0x2
[   56.816220] upd61151: Transfer IRQ status 0x2
[   56.840019] upd61151: Transfer IRQ status 0x2
[   56.863821] upd61151: Transfer IRQ status 0x2
[   56.887620] upd61151: Transfer IRQ status 0x2
[   56.911424] upd61151: Transfer IRQ status 0x2
[   56.935223] upd61151: Transfer IRQ status 0x2
[   56.959024] upd61151: Transfer IRQ status 0x2
[   56.982823] upd61151: Transfer IRQ status 0x2
[   57.006626] upd61151: Transfer IRQ status 0x2
[   57.030426] upd61151: Transfer IRQ status 0x2
[   57.054228] upd61151: Transfer IRQ status 0x2
[   57.078025] upd61151: Transfer IRQ status 0x2
[   57.101827] upd61151: Transfer IRQ status 0x2
[   57.125625] upd61151: Transfer IRQ status 0x2
[   57.149428] upd61151: Transfer IRQ status 0x2
[   57.173227] upd61151: Transfer IRQ status 0x2
[   57.197028] upd61151: Transfer IRQ status 0x2
[   57.220826] upd61151: Transfer IRQ status 0x2
[   57.244628] upd61151: Transfer IRQ status 0x2
[   57.268415] upd61151: Transfer IRQ status 0x2
[   57.292211] upd61151: Transfer IRQ status 0x2
[   57.316014] upd61151: Transfer IRQ status 0x2
[   57.339811] upd61151: Transfer IRQ status 0x2
[   57.363613] upd61151: Transfer IRQ status 0x2
[   57.387411] upd61151: Transfer IRQ status 0x2
[   57.411213] upd61151: Transfer IRQ status 0x2
[   57.435010] upd61151: Transfer IRQ status 0x2
[   57.458813] upd61151: Transfer IRQ status 0x2
[   57.482625] upd61151: Transfer IRQ status 0x2
[   57.506425] upd61151: Transfer IRQ status 0x2
[   57.530219] upd61151: Transfer IRQ status 0x2
[   57.554020] upd61151: Transfer IRQ status 0x2
[   57.577818] upd61151: Transfer IRQ status 0x2
[   57.601620] upd61151: Transfer IRQ status 0x2
[   57.625414] upd61151: Transfer IRQ status 0x2
[   57.649215] upd61151: Transfer IRQ status 0x2
[   57.673011] upd61151: Transfer IRQ status 0x2
[   57.696814] upd61151: Transfer IRQ status 0x2
[   57.720613] upd61151: Transfer IRQ status 0x2
[   57.744402] upd61151: Transfer IRQ status 0x2
[   57.768203] upd61151: Transfer IRQ status 0x2
[   57.792002] upd61151: Transfer IRQ status 0x2
[   57.815820] upd61151: Transfer IRQ status 0x2
[   57.839620] upd61151: Transfer IRQ status 0x2
[   57.863423] upd61151: Transfer IRQ status 0x2
[   57.887222] upd61151: Transfer IRQ status 0x2
[   57.911025] upd61151: Transfer IRQ status 0x2
[   57.934822] upd61151: Transfer IRQ status 0x2
[   57.958626] upd61151: Transfer IRQ status 0x2
[   57.982424] upd61151: Transfer IRQ status 0x2
[   58.006228] upd61151: Transfer IRQ status 0x2
[   58.030026] upd61151: Transfer IRQ status 0x2
[   58.053827] upd61151: Transfer IRQ status 0x2
[   58.077625] upd61151: Transfer IRQ status 0x2
[   58.101427] upd61151: Transfer IRQ status 0x2
[   58.125225] upd61151: Transfer IRQ status 0x2
[   58.149028] upd61151: Transfer IRQ status 0x2
[   58.172826] upd61151: Transfer IRQ status 0x2
[   58.196628] upd61151: Transfer IRQ status 0x2
[   58.220417] upd61151: Transfer IRQ status 0x2
[   58.244214] upd61151: Transfer IRQ status 0x2
[   58.268016] upd61151: Transfer IRQ status 0x2
[   58.291814] upd61151: Transfer IRQ status 0x2
[   58.315616] upd61151: Transfer IRQ status 0x2
[   58.339416] upd61151: Transfer IRQ status 0x2
[   58.363218] upd61151: Transfer IRQ status 0x2
[   58.387017] upd61151: Transfer IRQ status 0x2
[   58.410820] upd61151: Transfer IRQ status 0x2
[   58.434619] upd61151: Transfer IRQ status 0x2
[   58.458420] upd61151: Transfer IRQ status 0x2
[   58.482236] upd61151: Transfer IRQ status 0x2
[   58.506039] upd61151: Transfer IRQ status 0x2
[   58.529837] upd61151: Transfer IRQ status 0x2
[   58.553638] upd61151: Transfer IRQ status 0x2
[   58.577436] upd61151: Transfer IRQ status 0x2
[   58.601238] upd61151: Transfer IRQ status 0x2
[   58.625036] upd61151: Transfer IRQ status 0x2
[   58.648837] upd61151: Transfer IRQ status 0x2
[   58.672635] upd61151: Transfer IRQ status 0x2
[   58.696422] upd61151: Transfer IRQ status 0x2
[   58.720223] upd61151: Transfer IRQ status 0x2
[   58.744020] upd61151: Transfer IRQ status 0x2
[   58.767822] upd61151: Transfer IRQ status 0x2
[   58.791618] upd61151: Transfer IRQ status 0x2
[   58.815423] upd61151: Transfer IRQ status 0x2
[   58.839222] upd61151: Transfer IRQ status 0x2
[   58.863026] upd61151: Transfer IRQ status 0x2
[   58.886824] upd61151: Transfer IRQ status 0x2
[   58.910625] upd61151: Transfer IRQ status 0x2
[   58.934422] upd61151: Transfer IRQ status 0x1
[   58.934606] fw upload stop
[   58.934834] upd61151: audio firmware upload complete...
[   58.935073] upd61151: IRQ status 0x19
[   58.935256] DEBUG uPD61151: upd61151_chip_command
[   58.935484] upd61151: IRQ error status 0x0
[   58.935850] upd61151: MPEG2 core status 0
[   58.936034] upd61151: IRQ error status 0x0
[   58.948204] upd61151: MPEG2 core status 1
[   58.948388] upd61151: IRQ status 0x8
[   58.948576] upd61151: SetState 1 SUCCESS, delay [10 ms].
[   58.948577] upd61151_setup_video_frontend
[   58.948622] dbyte = 0x0     0x0     0x0  
[   58.949646] upd61151_setup_audio_frontend
[   58.950619] upd61151_config_encoder
[   58.950662] upd61151_set_state
[   58.950705] DEBUG uPD61151: upd61151_chip_command
[   58.950932] upd61151: IRQ error status 0x0
[   58.951299] upd61151: MPEG2 core status 1
[   58.951483] upd61151: IRQ status 0x0
[   58.951484] upd61151: SetState 1 SUCCESS, delay [0 ms].
[   58.951485] Firmware downloaded SUCCESS!!!
[   58.951643] saa7133[0]: registered device video0 [v4l2]
[   58.951709] saa7133[0]: registered device vbi0
[   58.951771] saa7133[0]: registered device radio0
[   58.993549] saa7133[0]: registered device video1 [mpeg]
[   59.017327] saa7134 ALSA driver for DMA sound loaded
[   59.017387] IRQ 19/saa7133[0]: IRQF_DISABLED is not guaranteed on shared IRQs
[   59.017449] saa7133[0]/alsa: saa7133[0] at 0xe5100000 irq 19 registered as card -1

[   72.129075] xc5000: I2C write failed (len=4)
[   72.232014] xc5000: I2C write failed (len=4)
[   72.235009] xc5000: I2C read failed
[   72.235060] xc5000: I2C read failed
[   72.235104] xc5000: waiting for firmware upload (dvb-fe-xc5000-1.6.114.fw)...
[   72.235152] saa7134 0000:04:01.0: firmware: requesting dvb-fe-xc5000-1.6.114.fw
[   72.384735] xc5000: firmware read 12401 bytes.
[   72.384739] xc5000: firmware uploading...
[   75.716007] xc5000: firmware upload complete...
[   76.468008] DEBUG uPD61151: upd61151_s_std
[   76.468059] set standart to 255
[   76.468107] DEBUG uPD61151: upd61151_s_std
[   76.468155] set standart to 255
[   76.940008] DEBUG uPD61151: upd61151_s_std
[   76.940061] set standart to 255
[   76.940109] DEBUG uPD61151: upd61151_s_std
[   76.940157] set standart to 255


With my best regards, Dmitry.

[-- Attachment #2: behold_spi.diff --]
[-- Type: text/x-patch, Size: 12842 bytes --]

diff -r b6b82258cf5e linux/drivers/media/video/saa7134/Makefile
--- a/linux/drivers/media/video/saa7134/Makefile	Thu Dec 31 19:14:54 2009 -0200
+++ b/linux/drivers/media/video/saa7134/Makefile	Tue Feb 09 07:38:53 2010 +0900
@@ -1,9 +1,9 @@
 
 saa7134-objs :=	saa7134-cards.o saa7134-core.o saa7134-i2c.o	\
 		saa7134-ts.o saa7134-tvaudio.o saa7134-vbi.o    \
-		saa7134-video.o saa7134-input.o
+		saa7134-video.o saa7134-input.o saa7134-spi.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 -r b6b82258cf5e linux/drivers/media/video/saa7134/saa7134-cards.c
--- a/linux/drivers/media/video/saa7134/saa7134-cards.c	Thu Dec 31 19:14:54 2009 -0200
+++ b/linux/drivers/media/video/saa7134/saa7134-cards.c	Tue Feb 09 07:38:53 2010 +0900
@@ -4619,6 +4619,7 @@
 			.name = name_radio,
 			.amux = LINE2,
 		},
+		.encoder_type = SAA7134_ENCODER_SAA6752HS,
 		.mpeg  = SAA7134_MPEG_EMPRESS,
 		.video_out = CCIR656,
 		.vid_port_opts  = (SET_T_CODE_POLARITY_NON_INVERTED |
@@ -4656,6 +4657,7 @@
 			.name = name_radio,
 			.amux = LINE2,
 		},
+		.encoder_type = SAA7134_ENCODER_SAA6752HS,
 		.mpeg  = SAA7134_MPEG_EMPRESS,
 		.video_out = CCIR656,
 		.vid_port_opts  = (SET_T_CODE_POLARITY_NON_INVERTED |
@@ -4695,6 +4697,7 @@
 			.name = name_radio,
 			.amux = LINE2,
 		},
+		.encoder_type = SAA7134_ENCODER_SAA6752HS,
 		.mpeg  = SAA7134_MPEG_EMPRESS,
 		.video_out = CCIR656,
 		.vid_port_opts  = (SET_T_CODE_POLARITY_NON_INVERTED |
@@ -5279,23 +5282,51 @@
 		.tuner_addr     = ADDR_UNSET,
 		.radio_addr     = ADDR_UNSET,
 		.mpeg           = SAA7134_MPEG_DVB,
+		.gpiomask       = 0x00860000,
 		.inputs         = { {
 			.name = name_tv,
 			.vmux = 2,
 			.amux = TV,
 			.tv   = 1,
-		}, {
-			.name = name_comp1,
-			.vmux = 0,
-			.amux = LINE1,
+			.gpio = 0x00860000
+		}, {
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE1,
+			.gpio = 0x00860000
 		}, {
 			.name = name_svideo,
 			.vmux = 9,
 			.amux = LINE1,
-		} },
-		.radio = {
-			.name = name_radio,
-			.amux = TV,
+			.gpio = 0x00860000
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = TV,
+			.gpio = 0x00860000
+		},
+		.encoder_type = SAA7134_ENCODER_muPD61151,
+		.mpeg  = SAA7134_MPEG_EMPRESS,
+		.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,
+		},
+		.spi_conf = {
+			.modalias	= "upd61151",
+			.max_speed_hz	= 50000000,
+			.chip_select	= 0,
+			.mode		= SPI_MODE_0,
+			.controller_data = NULL,
+			.platform_data  = NULL,
 		},
 	},
 	[SAA7134_BOARD_ZOLID_HYBRID_PCI] = {
diff -r b6b82258cf5e linux/drivers/media/video/saa7134/saa7134-core.c
--- a/linux/drivers/media/video/saa7134/saa7134-core.c	Thu Dec 31 19:14:54 2009 -0200
+++ b/linux/drivers/media/video/saa7134/saa7134-core.c	Tue Feb 09 07:38:53 2010 +0900
@@ -139,6 +139,18 @@
 		break;
 	}
 }
+
+unsigned long 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;
+}
+
 
 /* ------------------------------------------------------------------ */
 
@@ -1057,12 +1069,42 @@
 
 	saa7134_hwinit2(dev);
 
-	/* load i2c helpers */
+	/* initialize software SPI bus */
+	if (saa7134_boards[dev->board].spi.spi_enable)
+	{
+		dev->spi = saa7134_boards[dev->board].spi;
+
+		/* register SPI master and SPI slave */
+		if (saa7134_spi_register(dev, &saa7134_boards[dev->board].spi_conf))
+			saa7134_boards[dev->board].spi.spi_enable = 0;
+	}
+
+	/* 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 (saa7134_boards[dev->board].spi.spi_enable)
+				sd = v4l2_spi_new_subdev(&dev->v4l2_dev, dev->spi_adap, &saa7134_boards[dev->board].spi_conf);
+		}
+			break;
+		case SAA7134_ENCODER_SAA6752HS:
+		{
+			sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
 				"saa6752hs", "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;
@@ -1139,6 +1181,8 @@
 	return 0;
 
  fail4:
+	if ((card_is_empress(dev)) && (dev->encoder_type == SAA7134_ENCODER_muPD61151))
+		saa7134_spi_unregister(dev);
 	saa7134_unregister_video(dev);
 	saa7134_i2c_unregister(dev);
 	free_irq(pci_dev->irq, dev);
@@ -1412,6 +1456,7 @@
 /* ----------------------------------------------------------- */
 
 EXPORT_SYMBOL(saa7134_set_gpio);
+EXPORT_SYMBOL(saa7134_get_gpio);
 EXPORT_SYMBOL(saa7134_boards);
 
 /* ----------------- for the DMA sound modules --------------- */
diff -r b6b82258cf5e linux/drivers/media/video/saa7134/saa7134.h
--- a/linux/drivers/media/video/saa7134/saa7134.h	Thu Dec 31 19:14:54 2009 -0200
+++ b/linux/drivers/media/video/saa7134/saa7134.h	Tue Feb 09 07:38:53 2010 +0900
@@ -30,6 +30,13 @@
 #include <linux/notifier.h>
 #include <linux/delay.h>
 #include <linux/mutex.h>
+
+/* ifdef software SPI insert here start */
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_gpio.h>
+#include <linux/spi/spi_bitbang.h>
+/* ifdef software SPI insert here stop */
 
 #include <asm/io.h>
 
@@ -337,6 +344,21 @@
 	SAA7134_MPEG_TS_SERIAL,
 };
 
+enum saa7134_encoder_type {
+	SAA7134_ENCODER_UNUSED,
+	SAA7134_ENCODER_SAA6752HS,
+	SAA7134_ENCODER_muPD61151,
+};
+
+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 {
 	char                    *name;
 	unsigned int            audio_clock;
@@ -355,6 +377,10 @@
 	unsigned char		empress_addr;
 	unsigned char		rds_addr;
 
+	/* SPI info */
+	struct saa7134_software_spi	spi;
+	struct spi_board_info   spi_conf;
+
 	unsigned int            tda9887_conf;
 	unsigned int            tuner_config;
 
@@ -362,6 +388,7 @@
 	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;
 };
@@ -506,6 +533,12 @@
 	void                       (*signal_change)(struct saa7134_dev *dev);
 };
 
+struct saa7134_spi_gpio {
+	struct spi_bitbang         bitbang;
+	struct spi_master          *master;
+	struct saa7134_dev         *controller_data;
+};
+
 /* global device status */
 struct saa7134_dev {
 	struct list_head           devlist;
@@ -553,6 +586,10 @@
 	struct i2c_client          i2c_client;
 	unsigned char              eedata[256];
 	int 			   has_rds;
+
+	/* software spi */
+	struct saa7134_software_spi spi;
+	struct spi_master          *spi_adap;
 
 	/* video overlay */
 	struct v4l2_framebuffer    ovbuf;
@@ -615,6 +652,7 @@
 	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 */
@@ -681,6 +719,7 @@
 
 void saa7134_track_gpio(struct saa7134_dev *dev, char *msg);
 void saa7134_set_gpio(struct saa7134_dev *dev, int bit_no, int value);
+unsigned long saa7134_get_gpio(struct saa7134_dev *dev);
 
 #define SAA7134_PGTABLE_SIZE 4096
 
@@ -726,6 +765,11 @@
 int saa7134_i2c_register(struct saa7134_dev *dev);
 int saa7134_i2c_unregister(struct saa7134_dev *dev);
 
+/* ----------------------------------------------------------- */
+/* saa7134-spi.c                                               */
+
+int saa7134_spi_register(struct saa7134_dev *dev, struct spi_board_info *info);
+int saa7134_spi_unregister(struct saa7134_dev *dev);
 
 /* ----------------------------------------------------------- */
 /* saa7134-video.c                                             */
diff -r b6b82258cf5e linux/drivers/media/video/v4l2-common.c
--- a/linux/drivers/media/video/v4l2-common.c	Thu Dec 31 19:14:54 2009 -0200
+++ b/linux/drivers/media/video/v4l2-common.c	Tue Feb 09 07:38:53 2010 +0900
@@ -51,6 +51,7 @@
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/i2c.h>
+#include <linux/spi/spi.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/pgtable.h>
@@ -1069,6 +1070,67 @@
 
 #endif /* defined(CONFIG_I2C) */
 
+//#if defined(CONFIG_SPI) || (defined(CONFIG_SPI_MODULE) && defined(MODULE)) + SPI_BITBANG
+
+/* Load an spi sub-device. */
+
+void v4l2_spi_subdev_init(struct v4l2_subdev *sd, struct spi_device *spi,
+		const struct v4l2_subdev_ops *ops)
+{
+	v4l2_subdev_init(sd, ops);
+	sd->flags |= V4L2_SUBDEV_FL_IS_SPI;
+	/* the owner is the same as the spi_device's driver owner */
+	sd->owner = spi->dev.driver->owner;
+	/* spi_device and v4l2_subdev point to one another */
+	v4l2_set_subdevdata(sd, spi);
+	spi_set_drvdata(spi, sd);
+	/* initialize name */
+	snprintf(sd->name, sizeof(sd->name), "%s",
+		spi->dev.driver->name);
+}
+EXPORT_SYMBOL_GPL(v4l2_spi_subdev_init);
+
+struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev,
+		struct spi_master *master, struct spi_board_info *info)
+{
+	struct v4l2_subdev *sd = NULL;
+	struct spi_device *spi = NULL;
+
+	BUG_ON(!v4l2_dev);
+
+	if (info->modalias)
+		request_module(info->modalias);
+
+	spi = spi_new_device(master,info);
+
+	if (spi == NULL || spi->dev.driver ==NULL)
+		goto error;
+
+	if (!try_module_get(spi->dev.driver->owner))
+		goto error;
+
+	sd = spi_get_drvdata(spi);
+
+	/* Register with the v4l2_device which increases the module's
+	   use count as well. */
+	if (v4l2_device_register_subdev(v4l2_dev, sd))
+		sd = NULL;
+
+	/* Decrease the module use count to match the first try_module_get. */
+	module_put(spi->dev.driver->owner);
+
+error:
+	/* If we have a client but no subdev, then something went wrong and
+	   we must unregister the client. */
+	if (spi && sd == NULL)
+		spi_unregister_device(spi);
+
+	return sd;
+}
+EXPORT_SYMBOL_GPL(v4l2_spi_new_subdev);
+
+//#endif /* defined(CONFIG_SPI) */
+
 /* Clamp x to be between min and max, aligned to a multiple of 2^align.  min
  * and max don't have to be aligned, but there must be at least one valid
  * value.  E.g., min=17,max=31,align=4 is not allowed as there are no multiples
diff -r b6b82258cf5e linux/include/media/v4l2-common.h
--- a/linux/include/media/v4l2-common.h	Thu Dec 31 19:14:54 2009 -0200
+++ b/linux/include/media/v4l2-common.h	Tue Feb 09 07:38:53 2010 +0900
@@ -191,6 +191,25 @@
 
 /* ------------------------------------------------------------------------- */
 
+/* SPI Helper functions */
+
+#include <linux/spi/spi.h>
+
+struct spi_device_id;
+struct spi_device;
+
+/* Load an spi module and return an initialized v4l2_subdev struct.
+   Only call request_module if module_name != NULL.
+   The client_type argument is the name of the chip that's on the adapter. */
+struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev,
+		struct spi_master *master, struct spi_board_info *info);
+
+/* Initialize an v4l2_subdev with data from an spi_device struct */
+void v4l2_spi_subdev_init(struct v4l2_subdev *sd, struct spi_device *spi,
+		const struct v4l2_subdev_ops *ops);
+
+/* ------------------------------------------------------------------------- */
+
 /* Note: these remaining ioctls/structs should be removed as well, but they are
    still used in tuner-simple.c (TUNER_SET_CONFIG), cx18/ivtv (RESET) and
    v4l2-int-device.h (v4l2_routing). To remove these ioctls some more cleanup
diff -r b6b82258cf5e linux/include/media/v4l2-subdev.h
--- a/linux/include/media/v4l2-subdev.h	Thu Dec 31 19:14:54 2009 -0200
+++ b/linux/include/media/v4l2-subdev.h	Tue Feb 09 07:38:53 2010 +0900
@@ -387,6 +387,8 @@
 
 /* Set this flag if this subdev is a i2c device. */
 #define V4L2_SUBDEV_FL_IS_I2C (1U << 0)
+/* Set this flag if this subdev is a spi device. */
+#define V4L2_SUBDEV_FL_IS_SPI (1U << 1)
 
 /* Each instance of a subdev driver should create this struct, either
    stand-alone or embedded in a larger struct.

[-- Attachment #3: dmesg.log --]
[-- Type: text/x-log, Size: 21225 bytes --]

[    4.901675] Linux video capture interface: v2.00
[    5.046878] saa7130/34: v4l2 driver version 0.2.15 loaded
[    5.046964] saa7134 0000:04:01.0: PCI INT A -> GSI 19 (level, low) -> IRQ 19
[    5.047018] saa7133[0]: found at 0000:04:01.0, rev: 209, irq: 19, latency: 32, mmio: 0xe5100000
[    5.047080] saa7133[0]: subsystem: 5ace:7595, board: Beholder BeholdTV X7 [card=171,autodetected]
[    5.047153] saa7133[0]: board init: gpio is 200000
[    5.047205] IRQ 19/saa7133[0]: IRQF_DISABLED is not guaranteed on shared IRQs
[    5.196517] saa7133[0]: i2c eeprom 00: ce 5a<6>HDA Intel 0000:00:1b.0: PCI INT A -> GSI 16 (level, low) -> IRQ 16
[    5.196620] HDA Intel 0000:00:1b.0: setting latency timer to 64
[    5.196687]  95 75 54 20 00 00 00 00 00 00 00 00 00 01
[    5.197190] saa7133[0]: i2c eeprom 10: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    5.197787] saa7133[0]: i2c eeprom 20: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    5.198385] saa7133[0]: i2c eeprom 30: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    5.198982] saa7133[0]: i2c eeprom 40: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    5.199579] saa7133[0]: i2c eeprom 50: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    5.200176] saa7133[0]: i2c eeprom 60: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    5.200785] saa7133[0]: i2c eeprom 70: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    5.201382] saa7133[0]: i2c eeprom 80: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    5.201979] saa7133[0]: i2c eeprom 90: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    5.202576] saa7133[0]: i2c eeprom a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    5.203174] saa7133[0]: i2c eeprom b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    5.203771] saa7133[0]: i2c eeprom c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    5.204371] saa7133[0]: i2c eeprom d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[    5.204982] saa7133[0]: i2c eeprom e0: 00 00 00 00 ff ff ff ff ff ff ff ff ff ff ff ff
[    5.205579] saa7133[0]: i2c eeprom f0: 42 54 56 30 30 30 30 ff ff ff ff ff ff ff ff ff
[    5.228577] tuner 1-0061: chip found @ 0xc2 (saa7133[0])
[    5.286091] xc5000 1-0061: creating new instance
[    5.292505] xc5000: Successfully identified at address 0x61
[    5.292552] xc5000: Firmware has not been loaded previously
[   33.571875] saa7134 0000:04:01.0: spi master registered: bus_num=32766 num_chipselect=1
[   33.571933] saa7133[0]: found muPD61151 MPEG encoder
[   33.601819] upd61151_probe function
[   33.602057] upd61151: MPEG2 core status 0
[   33.602058] upd61151: need reload firmware
[   33.602059] Start load firmware...
[   33.602103] DEBUG: upd61151_download_firmware
[   33.603325] DEBUG: upd61151_load_base_firmware
[   33.603370] upd61151: waiting for base firmware upload (D61151_PS_7133_v22_031031.bin)...
[   33.603427] saa7134 0000:04:01.0: firmware: requesting D61151_PS_7133_v22_031031.bin
[   33.676430] upd61151: firmware read 97002 bytes.
[   33.676432] upd61151: base firmware uploading...
[   33.677071] upd61151: Transfer IRQ status 0x0
[   33.678539] fw upload start
[   51.433446] fw upload stop
[   51.433677] upd61151: Transfer IRQ status 0x1
[   51.434043] upd61151: base firmware upload complete...
[   51.434285] DEBUG: upd61151_load_audio_firmware
[   51.434330] upd61151: waiting for audio firmware upload (audrey_MPE_V1r51.bin)...
[   51.434386] saa7134 0000:04:01.0: firmware: requesting audrey_MPE_V1r51.bin
[   51.482980] upd61151: firmware read 40064 bytes.
[   51.482982] upd61151: audio firmware uploading...
[   51.483231] upd61151: Transfer IRQ status 0x1
[   51.484700] fw upload start
[   51.508682] upd61151: Transfer IRQ status 0x2
[   51.532479] upd61151: Transfer IRQ status 0x2
[   51.556280] upd61151: Transfer IRQ status 0x2
[   51.580081] upd61151: Transfer IRQ status 0x2
[   51.603877] upd61151: Transfer IRQ status 0x2
[   51.627677] upd61151: Transfer IRQ status 0x2
[   51.651476] upd61151: Transfer IRQ status 0x2
[   51.675275] upd61151: Transfer IRQ status 0x2
[   51.699072] upd61151: Transfer IRQ status 0x2
[   51.722870] upd61151: Transfer IRQ status 0x2
[   51.746669] upd61151: Transfer IRQ status 0x2
[   51.770467] upd61151: Transfer IRQ status 0x2
[   51.794267] upd61151: Transfer IRQ status 0x2
[   51.818092] upd61151: Transfer IRQ status 0x2
[   51.841896] upd61151: Transfer IRQ status 0x2
[   51.865691] upd61151: Transfer IRQ status 0x2
[   51.889493] upd61151: Transfer IRQ status 0x2
[   51.913290] upd61151: Transfer IRQ status 0x2
[   51.937091] upd61151: Transfer IRQ status 0x2
[   51.960889] upd61151: Transfer IRQ status 0x2
[   51.984690] upd61151: Transfer IRQ status 0x2
[   52.008479] upd61151: Transfer IRQ status 0x2
[   52.032279] upd61151: Transfer IRQ status 0x2
[   52.056076] upd61151: Transfer IRQ status 0x2
[   52.079877] upd61151: Transfer IRQ status 0x2
[   52.103674] upd61151: Transfer IRQ status 0x2
[   52.127474] upd61151: Transfer IRQ status 0x2
[   52.151273] upd61151: Transfer IRQ status 0x2
[   52.175072] upd61151: Transfer IRQ status 0x2
[   52.198874] upd61151: Transfer IRQ status 0x2
[   52.222672] upd61151: Transfer IRQ status 0x2
[   52.246474] upd61151: Transfer IRQ status 0x2
[   52.270272] upd61151: Transfer IRQ status 0x2
[   52.294074] upd61151: Transfer IRQ status 0x2
[   52.317873] upd61151: Transfer IRQ status 0x2
[   52.341674] upd61151: Transfer IRQ status 0x2
[   52.365472] upd61151: Transfer IRQ status 0x2
[   52.389274] upd61151: Transfer IRQ status 0x2
[   52.413073] upd61151: Transfer IRQ status 0x2
[   52.436873] upd61151: Transfer IRQ status 0x2
[   52.460672] upd61151: Transfer IRQ status 0x2
[   52.484670] upd61151: Transfer IRQ status 0x2
[   52.508459] upd61151: Transfer IRQ status 0x2
[   52.532260] upd61151: Transfer IRQ status 0x2
[   52.556055] upd61151: Transfer IRQ status 0x2
[   52.579856] upd61151: Transfer IRQ status 0x2
[   52.603651] upd61151: Transfer IRQ status 0x2
[   52.627447] upd61151: Transfer IRQ status 0x2
[   52.651246] upd61151: Transfer IRQ status 0x2
[   52.675042] upd61151: Transfer IRQ status 0x2
[   52.698844] upd61151: Transfer IRQ status 0x2
[   52.722641] upd61151: Transfer IRQ status 0x2
[   52.746440] upd61151: Transfer IRQ status 0x2
[   52.770234] upd61151: Transfer IRQ status 0x2
[   52.794035] upd61151: Transfer IRQ status 0x2
[   52.817838] upd61151: Transfer IRQ status 0x2
[   52.841642] upd61151: Transfer IRQ status 0x2
[   52.865437] upd61151: Transfer IRQ status 0x2
[   52.889237] upd61151: Transfer IRQ status 0x2
[   52.913035] upd61151: Transfer IRQ status 0x2
[   52.936835] upd61151: Transfer IRQ status 0x2
[   52.960630] upd61151: Transfer IRQ status 0x2
[   52.984419] upd61151: Transfer IRQ status 0x2
[   53.008218] upd61151: Transfer IRQ status 0x2
[   53.032021] upd61151: Transfer IRQ status 0x2
[   53.055820] upd61151: Transfer IRQ status 0x2
[   53.079619] upd61151: Transfer IRQ status 0x2
[   53.103421] upd61151: Transfer IRQ status 0x2
[   53.127220] upd61151: Transfer IRQ status 0x2
[   53.151024] upd61151: Transfer IRQ status 0x2
[   53.174821] upd61151: Transfer IRQ status 0x2
[   53.198623] upd61151: Transfer IRQ status 0x2
[   53.222422] upd61151: Transfer IRQ status 0x2
[   53.246223] upd61151: Transfer IRQ status 0x2
[   53.270022] upd61151: Transfer IRQ status 0x2
[   53.293824] upd61151: Transfer IRQ status 0x2
[   53.317621] upd61151: Transfer IRQ status 0x2
[   53.341422] upd61151: Transfer IRQ status 0x2
[   53.365220] upd61151: Transfer IRQ status 0x2
[   53.389024] upd61151: Transfer IRQ status 0x2
[   53.412826] upd61151: Transfer IRQ status 0x2
[   53.436626] upd61151: Transfer IRQ status 0x2
[   53.460413] upd61151: Transfer IRQ status 0x2
[   53.484231] upd61151: Transfer IRQ status 0x2
[   53.508029] upd61151: Transfer IRQ status 0x2
[   53.531827] upd61151: Transfer IRQ status 0x2
[   53.555627] upd61151: Transfer IRQ status 0x2
[   53.579425] upd61151: Transfer IRQ status 0x2
[   53.603224] upd61151: Transfer IRQ status 0x2
[   53.627018] upd61151: Transfer IRQ status 0x2
[   53.650820] upd61151: Transfer IRQ status 0x2
[   53.674617] upd61151: Transfer IRQ status 0x2
[   53.698418] upd61151: Transfer IRQ status 0x2
[   53.722216] upd61151: Transfer IRQ status 0x2
[   53.746019] upd61151: Transfer IRQ status 0x2
[   53.769817] upd61151: Transfer IRQ status 0x2
[   53.793618] upd61151: Transfer IRQ status 0x2
[   53.817443] upd61151: Transfer IRQ status 0x2
[   53.841246] upd61151: Transfer IRQ status 0x2
[   53.865044] upd61151: Transfer IRQ status 0x2
[   53.888846] upd61151: Transfer IRQ status 0x2
[   53.912644] upd61151: Transfer IRQ status 0x2
[   53.936435] upd61151: Transfer IRQ status 0x2
[   53.960233] upd61151: Transfer IRQ status 0x2
[   53.984035] upd61151: Transfer IRQ status 0x2
[   54.007833] upd61151: Transfer IRQ status 0x2
[   54.031631] upd61151: Transfer IRQ status 0x2
[   54.055433] upd61151: Transfer IRQ status 0x2
[   54.079230] upd61151: Transfer IRQ status 0x2
[   54.103030] upd61151: Transfer IRQ status 0x2
[   54.126828] upd61151: Transfer IRQ status 0x2
[   54.150631] upd61151: Transfer IRQ status 0x2
[   54.174428] upd61151: Transfer IRQ status 0x2
[   54.198228] upd61151: Transfer IRQ status 0x2
[   54.222026] upd61151: Transfer IRQ status 0x2
[   54.245827] upd61151: Transfer IRQ status 0x2
[   54.269624] upd61151: Transfer IRQ status 0x2
[   54.293426] upd61151: Transfer IRQ status 0x2
[   54.317223] upd61151: Transfer IRQ status 0x2
[   54.341024] upd61151: Transfer IRQ status 0x2
[   54.364821] upd61151: Transfer IRQ status 0x2
[   54.388621] upd61151: Transfer IRQ status 0x2
[   54.412408] upd61151: Transfer IRQ status 0x2
[   54.436209] upd61151: Transfer IRQ status 0x2
[   54.460007] upd61151: Transfer IRQ status 0x2
[   54.483824] upd61151: Transfer IRQ status 0x2
[   54.507626] upd61151: Transfer IRQ status 0x2
[   54.531422] upd61151: Transfer IRQ status 0x2
[   54.555223] upd61151: Transfer IRQ status 0x2
[   54.579020] upd61151: Transfer IRQ status 0x2
[   54.602822] upd61151: Transfer IRQ status 0x2
[   54.626620] upd61151: Transfer IRQ status 0x2
[   54.650421] upd61151: Transfer IRQ status 0x2
[   54.674217] upd61151: Transfer IRQ status 0x2
[   54.698018] upd61151: Transfer IRQ status 0x2
[   54.721816] upd61151: Transfer IRQ status 0x2
[   54.745616] upd61151: Transfer IRQ status 0x2
[   54.769414] upd61151: Transfer IRQ status 0x2
[   54.793215] upd61151: Transfer IRQ status 0x2
[   54.817014] upd61151: Transfer IRQ status 0x2
[   54.840815] upd61151: Transfer IRQ status 0x2
[   54.864614] upd61151: Transfer IRQ status 0x2
[   54.888404] upd61151: Transfer IRQ status 0x2
[   54.912203] upd61151: Transfer IRQ status 0x2
[   54.936005] upd61151: Transfer IRQ status 0x2
[   54.959804] upd61151: Transfer IRQ status 0x2
[   54.983601] upd61151: Transfer IRQ status 0x2
[   55.007405] upd61151: Transfer IRQ status 0x2
[   55.031203] upd61151: Transfer IRQ status 0x2
[   55.055004] upd61151: Transfer IRQ status 0x2
[   55.078802] upd61151: Transfer IRQ status 0x2
[   55.102603] upd61151: Transfer IRQ status 0x2
[   55.126401] upd61151: Transfer IRQ status 0x2
[   55.150202] upd61151: Transfer IRQ status 0x2
[   55.174000] upd61151: Transfer IRQ status 0x2
[   55.197802] upd61151: Transfer IRQ status 0x2
[   55.221599] upd61151: Transfer IRQ status 0x2
[   55.245398] upd61151: Transfer IRQ status 0x2
[   55.269196] upd61151: Transfer IRQ status 0x2
[   55.292997] upd61151: Transfer IRQ status 0x2
[   55.316794] upd61151: Transfer IRQ status 0x2
[   55.340595] upd61151: Transfer IRQ status 0x2
[   55.364383] upd61151: Transfer IRQ status 0x2
[   55.388184] upd61151: Transfer IRQ status 0x2
[   55.411983] upd61151: Transfer IRQ status 0x2
[   55.435779] upd61151: Transfer IRQ status 0x2
[   55.459581] upd61151: Transfer IRQ status 0x2
[   55.483393] upd61151: Transfer IRQ status 0x2
[   55.507195] upd61151: Transfer IRQ status 0x2
[   55.530992] upd61151: Transfer IRQ status 0x2
[   55.554793] upd61151: Transfer IRQ status 0x2
[   55.578591] upd61151: Transfer IRQ status 0x2
[   55.602391] upd61151: Transfer IRQ status 0x2
[   55.626189] upd61151: Transfer IRQ status 0x2
[   55.649991] upd61151: Transfer IRQ status 0x2
[   55.673788] upd61151: Transfer IRQ status 0x2
[   55.697606] upd61151: Transfer IRQ status 0x2
[   55.721404] upd61151: Transfer IRQ status 0x2
[   55.745206] upd61151: Transfer IRQ status 0x2
[   55.769003] upd61151: Transfer IRQ status 0x2
[   55.792804] upd61151: Transfer IRQ status 0x2
[   55.816633] upd61151: Transfer IRQ status 0x2
[   55.840426] upd61151: Transfer IRQ status 0x2
[   55.864222] upd61151: Transfer IRQ status 0x2
[   55.888018] upd61151: Transfer IRQ status 0x2
[   55.911820] upd61151: Transfer IRQ status 0x2
[   55.935618] upd61151: Transfer IRQ status 0x2
[   55.959420] upd61151: Transfer IRQ status 0x2
[   55.983214] upd61151: Transfer IRQ status 0x2
[   56.007017] upd61151: Transfer IRQ status 0x2
[   56.030816] upd61151: Transfer IRQ status 0x2
[   56.054618] upd61151: Transfer IRQ status 0x2
[   56.078417] upd61151: Transfer IRQ status 0x2
[   56.102219] upd61151: Transfer IRQ status 0x2
[   56.126018] upd61151: Transfer IRQ status 0x2
[   56.149820] upd61151: Transfer IRQ status 0x2
[   56.173619] upd61151: Transfer IRQ status 0x2
[   56.197419] upd61151: Transfer IRQ status 0x2
[   56.221217] upd61151: Transfer IRQ status 0x2
[   56.245019] upd61151: Transfer IRQ status 0x2
[   56.268816] upd61151: Transfer IRQ status 0x2
[   56.292616] upd61151: Transfer IRQ status 0x2
[   56.316404] upd61151: Transfer IRQ status 0x2
[   56.340203] upd61151: Transfer IRQ status 0x2
[   56.364005] upd61151: Transfer IRQ status 0x2
[   56.387804] upd61151: Transfer IRQ status 0x2
[   56.411606] upd61151: Transfer IRQ status 0x2
[   56.435405] upd61151: Transfer IRQ status 0x2
[   56.459209] upd61151: Transfer IRQ status 0x2
[   56.483029] upd61151: Transfer IRQ status 0x2
[   56.506831] upd61151: Transfer IRQ status 0x2
[   56.530626] upd61151: Transfer IRQ status 0x2
[   56.554428] upd61151: Transfer IRQ status 0x2
[   56.578225] upd61151: Transfer IRQ status 0x2
[   56.602026] upd61151: Transfer IRQ status 0x2
[   56.625825] upd61151: Transfer IRQ status 0x2
[   56.649628] upd61151: Transfer IRQ status 0x2
[   56.673427] upd61151: Transfer IRQ status 0x2
[   56.697230] upd61151: Transfer IRQ status 0x2
[   56.721026] upd61151: Transfer IRQ status 0x2
[   56.744827] upd61151: Transfer IRQ status 0x2
[   56.768626] upd61151: Transfer IRQ status 0x2
[   56.792418] upd61151: Transfer IRQ status 0x2
[   56.816220] upd61151: Transfer IRQ status 0x2
[   56.840019] upd61151: Transfer IRQ status 0x2
[   56.863821] upd61151: Transfer IRQ status 0x2
[   56.887620] upd61151: Transfer IRQ status 0x2
[   56.911424] upd61151: Transfer IRQ status 0x2
[   56.935223] upd61151: Transfer IRQ status 0x2
[   56.959024] upd61151: Transfer IRQ status 0x2
[   56.982823] upd61151: Transfer IRQ status 0x2
[   57.006626] upd61151: Transfer IRQ status 0x2
[   57.030426] upd61151: Transfer IRQ status 0x2
[   57.054228] upd61151: Transfer IRQ status 0x2
[   57.078025] upd61151: Transfer IRQ status 0x2
[   57.101827] upd61151: Transfer IRQ status 0x2
[   57.125625] upd61151: Transfer IRQ status 0x2
[   57.149428] upd61151: Transfer IRQ status 0x2
[   57.173227] upd61151: Transfer IRQ status 0x2
[   57.197028] upd61151: Transfer IRQ status 0x2
[   57.220826] upd61151: Transfer IRQ status 0x2
[   57.244628] upd61151: Transfer IRQ status 0x2
[   57.268415] upd61151: Transfer IRQ status 0x2
[   57.292211] upd61151: Transfer IRQ status 0x2
[   57.316014] upd61151: Transfer IRQ status 0x2
[   57.339811] upd61151: Transfer IRQ status 0x2
[   57.363613] upd61151: Transfer IRQ status 0x2
[   57.387411] upd61151: Transfer IRQ status 0x2
[   57.411213] upd61151: Transfer IRQ status 0x2
[   57.435010] upd61151: Transfer IRQ status 0x2
[   57.458813] upd61151: Transfer IRQ status 0x2
[   57.482625] upd61151: Transfer IRQ status 0x2
[   57.506425] upd61151: Transfer IRQ status 0x2
[   57.530219] upd61151: Transfer IRQ status 0x2
[   57.554020] upd61151: Transfer IRQ status 0x2
[   57.577818] upd61151: Transfer IRQ status 0x2
[   57.601620] upd61151: Transfer IRQ status 0x2
[   57.625414] upd61151: Transfer IRQ status 0x2
[   57.649215] upd61151: Transfer IRQ status 0x2
[   57.673011] upd61151: Transfer IRQ status 0x2
[   57.696814] upd61151: Transfer IRQ status 0x2
[   57.720613] upd61151: Transfer IRQ status 0x2
[   57.744402] upd61151: Transfer IRQ status 0x2
[   57.768203] upd61151: Transfer IRQ status 0x2
[   57.792002] upd61151: Transfer IRQ status 0x2
[   57.815820] upd61151: Transfer IRQ status 0x2
[   57.839620] upd61151: Transfer IRQ status 0x2
[   57.863423] upd61151: Transfer IRQ status 0x2
[   57.887222] upd61151: Transfer IRQ status 0x2
[   57.911025] upd61151: Transfer IRQ status 0x2
[   57.934822] upd61151: Transfer IRQ status 0x2
[   57.958626] upd61151: Transfer IRQ status 0x2
[   57.982424] upd61151: Transfer IRQ status 0x2
[   58.006228] upd61151: Transfer IRQ status 0x2
[   58.030026] upd61151: Transfer IRQ status 0x2
[   58.053827] upd61151: Transfer IRQ status 0x2
[   58.077625] upd61151: Transfer IRQ status 0x2
[   58.101427] upd61151: Transfer IRQ status 0x2
[   58.125225] upd61151: Transfer IRQ status 0x2
[   58.149028] upd61151: Transfer IRQ status 0x2
[   58.172826] upd61151: Transfer IRQ status 0x2
[   58.196628] upd61151: Transfer IRQ status 0x2
[   58.220417] upd61151: Transfer IRQ status 0x2
[   58.244214] upd61151: Transfer IRQ status 0x2
[   58.268016] upd61151: Transfer IRQ status 0x2
[   58.291814] upd61151: Transfer IRQ status 0x2
[   58.315616] upd61151: Transfer IRQ status 0x2
[   58.339416] upd61151: Transfer IRQ status 0x2
[   58.363218] upd61151: Transfer IRQ status 0x2
[   58.387017] upd61151: Transfer IRQ status 0x2
[   58.410820] upd61151: Transfer IRQ status 0x2
[   58.434619] upd61151: Transfer IRQ status 0x2
[   58.458420] upd61151: Transfer IRQ status 0x2
[   58.482236] upd61151: Transfer IRQ status 0x2
[   58.506039] upd61151: Transfer IRQ status 0x2
[   58.529837] upd61151: Transfer IRQ status 0x2
[   58.553638] upd61151: Transfer IRQ status 0x2
[   58.577436] upd61151: Transfer IRQ status 0x2
[   58.601238] upd61151: Transfer IRQ status 0x2
[   58.625036] upd61151: Transfer IRQ status 0x2
[   58.648837] upd61151: Transfer IRQ status 0x2
[   58.672635] upd61151: Transfer IRQ status 0x2
[   58.696422] upd61151: Transfer IRQ status 0x2
[   58.720223] upd61151: Transfer IRQ status 0x2
[   58.744020] upd61151: Transfer IRQ status 0x2
[   58.767822] upd61151: Transfer IRQ status 0x2
[   58.791618] upd61151: Transfer IRQ status 0x2
[   58.815423] upd61151: Transfer IRQ status 0x2
[   58.839222] upd61151: Transfer IRQ status 0x2
[   58.863026] upd61151: Transfer IRQ status 0x2
[   58.886824] upd61151: Transfer IRQ status 0x2
[   58.910625] upd61151: Transfer IRQ status 0x2
[   58.934422] upd61151: Transfer IRQ status 0x1
[   58.934606] fw upload stop
[   58.934834] upd61151: audio firmware upload complete...
[   58.935073] upd61151: IRQ status 0x19
[   58.935256] DEBUG uPD61151: upd61151_chip_command
[   58.935484] upd61151: IRQ error status 0x0
[   58.935850] upd61151: MPEG2 core status 0
[   58.936034] upd61151: IRQ error status 0x0
[   58.948204] upd61151: MPEG2 core status 1
[   58.948388] upd61151: IRQ status 0x8
[   58.948576] upd61151: SetState 1 SUCCESS, delay [10 ms].
[   58.948577] upd61151_setup_video_frontend
[   58.948622] dbyte = 0x0     0x0     0x0  
[   58.949646] upd61151_setup_audio_frontend
[   58.950619] upd61151_config_encoder
[   58.950662] upd61151_set_state
[   58.950705] DEBUG uPD61151: upd61151_chip_command
[   58.950932] upd61151: IRQ error status 0x0
[   58.951299] upd61151: MPEG2 core status 1
[   58.951483] upd61151: IRQ status 0x0
[   58.951484] upd61151: SetState 1 SUCCESS, delay [0 ms].
[   58.951485] Firmware downloaded SUCCESS!!!
[   58.951643] saa7133[0]: registered device video0 [v4l2]
[   58.951709] saa7133[0]: registered device vbi0
[   58.951771] saa7133[0]: registered device radio0
[   58.993549] saa7133[0]: registered device video1 [mpeg]
[   59.017327] saa7134 ALSA driver for DMA sound loaded
[   59.017387] IRQ 19/saa7133[0]: IRQF_DISABLED is not guaranteed on shared IRQs
[   59.017449] saa7133[0]/alsa: saa7133[0] at 0xe5100000 irq 19 registered as card -1

[   72.129075] xc5000: I2C write failed (len=4)
[   72.232014] xc5000: I2C write failed (len=4)
[   72.235009] xc5000: I2C read failed
[   72.235060] xc5000: I2C read failed
[   72.235104] xc5000: waiting for firmware upload (dvb-fe-xc5000-1.6.114.fw)...
[   72.235152] saa7134 0000:04:01.0: firmware: requesting dvb-fe-xc5000-1.6.114.fw
[   72.384735] xc5000: firmware read 12401 bytes.
[   72.384739] xc5000: firmware uploading...
[   75.716007] xc5000: firmware upload complete...
[   76.468008] DEBUG uPD61151: upd61151_s_std
[   76.468059] set standart to 255
[   76.468107] DEBUG uPD61151: upd61151_s_std
[   76.468155] set standart to 255
[   76.940008] DEBUG uPD61151: upd61151_s_std
[   76.940061] set standart to 255
[   76.940109] DEBUG uPD61151: upd61151_s_std
[   76.940157] set standart to 255

[-- Attachment #4: saa7134-spi.c --]
[-- Type: text/x-c++src, Size: 4704 bytes --]

/*
 *
 * 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.
 */

#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);
	if ( status & (1 << sb->controller_data->spi.miso))
		return 1;
	else
		return 0;
}

#define EXPAND_BITBANG_TXRX 1
#include <linux/spi/spi_bitbang.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, 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;
}

int 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);

	return 0;
}


/*
 * Overrides for Emacs so that we follow Linus's tabbing style.
 * ---------------------------------------------------------------------------
 * Local variables:
 * c-basic-offset: 8
 * End:
 */
 

[-- Attachment #5: upd61151.c --]
[-- Type: text/x-c++src, Size: 22956 bytes --]

 /*
    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 MPEG_VIDEO_TARGET_BITRATE_MAX  27000
#define MPEG_VIDEO_MAX_BITRATE_MAX     27000
#define MPEG_TOTAL_TARGET_BITRATE_MAX  27000
#define MPEG_PID_MAX ((1 << 14) - 1)

#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

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 {
	/* transport streams */
	__u16				ts_pid_pmt;
	__u16				ts_pid_audio;
	__u16				ts_pid_video;
	__u16				ts_pid_pcr;

	/* audio */
	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;
};

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 =
{
	.ts_pid_pmt      = 16,
	.ts_pid_video    = 260,
	.ts_pid_audio    = 256,
	.ts_pid_pcr      = 259,

	.vi_aspect       = V4L2_MPEG_VIDEO_ASPECT_4x3,
	.vi_bitrate      = 4000,
	.vi_bitrate_peak = 6000,
	.vi_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,

	.au_encoding     = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
	.au_l2_bitrate   = V4L2_MPEG_AUDIO_L2_BITRATE_256K,
};

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 u8 upd61151_get_state(struct spi_device *spi)
{
	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)
{
printk("upd61151_set_state\n");
	return RESULT_SUCCESS;
}

static void upd61151_reset_core(struct spi_device *spi)
{
	write_reg(spi, UPD61151_SOFTWARE_RST, 0x01);
}

static void upd61151_set_dest_addr(struct spi_device *spi, u32 addr)
{
	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 spi_device *spi, u32 dsize)
{
	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 spi_device *spi)
{
	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 spi_device *spi)
{
	u8 rbyte;
printk("upd61151_handle_transfer_err\n");
	/* Set data transfer count size = 1 */
	upd61151_set_data_size(spi, 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(spi);

	/* Set destination address to 0x000000 */
	upd61151_set_dest_addr(spi, 0x000000);

	/* Set data transfer count size = 3 */
	upd61151_set_data_size(spi, 0x03);

	/* Set transfer mode SDRAM -> Host */
	write_reg(spi, UPD61151_TRANSFER_MODE, 0x01);

	/* Clear IRQ */
	upd61151_clear_transfer_irq(spi);

	/* 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(spi);

	/* Set transfer mode SDRAM -> Host */
	write_reg(spi, UPD61151_TRANSFER_MODE, 0x00);

	/* Clear IRQ */
	upd61151_clear_transfer_irq(spi);
}

static int upd61151_wait_transfer_irq(struct spi_device *spi)
{
	u8 i, rstatus;

	rstatus = 0;
	/* Wait transfer interrupt */
	for (i=0; i<5; i++)
	{
		rstatus = upd61151_clear_transfer_irq(spi);
		if (rstatus)
			break;
		msleep(1);
	}

	if (!rstatus)
		return STATUS_DEVICE_NOT_READY;

	if (rstatus & 0x04)
	{
		/* Data transfer error */
		upd61151_handle_transfer_err(spi);
		return STATUS_DEVICE_DATA_ERROR;
	}

	return RESULT_SUCCESS;
}

static u8 upd61151_clear_info_irq(struct spi_device *spi)
{
	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 spi_device *spi)
{
	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 spi_device *spi)
{
	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 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 = RESULT_FAILURE;
		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 = RESULT_FAILURE;
		goto out;
	}
	printk(KERN_INFO "%s: base firmware uploading...\n", spi->modalias);

	upd61151_clear_transfer_irq(spi);

	/* CPU reset ON */
	write_reg(spi, UPD61151_SOFTWARE_RST, 0x02);

	/* Set destination address to 0x000000 */
	upd61151_set_dest_addr(spi, 0x000000);

	/* Set transfer data count to firmware size / 4 */
	upd61151_set_data_size(spi, 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");

	if (upd61151_wait_transfer_irq(spi) == 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 = RESULT_FAILURE;
		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 = RESULT_FAILURE;
		goto out;
	}
	printk(KERN_INFO "%s: audio firmware uploading...\n", spi->modalias);

	addr = 0x308F00;
	addr >>= 5;

	upd61151_clear_transfer_irq(spi);

	/* Set destination address */
	upd61151_set_dest_addr(spi, addr);

	/* Set transfer data count to firmware size */
	upd61151_set_data_size(spi, 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(spi);
			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 spi_device *spi, enum upd61151_command command)
{
	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 = 200;
		wait = 1;
		break;

	default:
		return RESULT_FAILURE;
	}

	/* Clear IRQ */
	upd61151_clear_error_irq(spi);

	write_reg(spi, UPD61151_COMMAND, command);

	for (i=0; i < cycles; i++)
	{
		/* Check state */
		want_state = upd61151_get_state(spi);
		if (want_state == command)
		{
			upd61151_clear_info_irq(spi);
			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(spi);

		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 RESULT_FAILURE;
}

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);
	int ret = RESULT_SUCCESS;
	u8 dbyte;

printk("upd61151_setup_video_frontend\n");

	dbyte = 0x00;
printk("dbyte = 0x%x  ",dbyte);
	/* 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 ret;
}

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);
	int ret = RESULT_SUCCESS;
	u8 dbyte;

printk("upd61151_setup_audio_frontend\n");

//UPD61151_AUDIO_ATTRIBUTE1

	return ret;
}

static int upd61151_config_encoder(struct v4l2_subdev *sd)
{
printk("upd61151_config_encoder\n");
	return RESULT_SUCCESS;
}

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);

printk("DEBUG: upd61151_download_firmware\n");
	h->enstate = UPD61151_ENCODE_STATE_IDLE;

	upd61151_reset_core(spi);

	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);

	if (upd61151_load_base_firmware(sd))
		return RESULT_FAILURE;

	if (upd61151_load_audio_firmware(sd))
		return RESULT_FAILURE;

	/* Clear IRQ flags */
	if ( !(upd61151_clear_info_irq(spi) & 0x10) )
	{
		/* INICM not running */
		d1printk_core(KERN_DEBUG "%s: download firmware FAILED. INICM is not run.\n", spi->modalias);
		return RESULT_FAILURE;
	}

	/* Set STANDBY state */
	if (upd61151_chip_command(spi, UPD61151_COMMAND_STANDBY_STOP))
		return RESULT_FAILURE;

	/* 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 */
	if (upd61151_set_state(sd, UPD61151_CONFIG_ALL))
		return RESULT_FAILURE;

	/* Return to STANDBY state */
	if (upd61151_chip_command(spi, UPD61151_COMMAND_STANDBY_STOP))
		return RESULT_FAILURE;

	return RESULT_SUCCESS;
}

static int upd61151_is_need_reload_fw(struct spi_device *spi)
{
	if (upd61151_get_state(spi) == UPD61151_COMMAND_INITIAL)
	{
		d1printk_core(KERN_DEBUG "%s: need reload firmware\n", spi->modalias);
		return 1;
	}

	if (upd61151_clear_except_irq(spi) & 0x04)
	{
		d1printk_core(KERN_DEBUG "%s: mainly buffer of encoder is overflowed\n", spi->modalias);
		return 1;
	}

	return 0;
}

#if 0

static int upd61151_set_bitrate(struct spi_device *spi,
				 struct upd61151_state *h)
{
printk("DEBUG uPD61151: upd61151_set_bitrate\n");
	return RESULT_SUCCESS;
}
#endif

static int upd61151_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qctrl)
{
printk("DEBUG uPD61151: upd61151_queryctrl\n");
	return RESULT_SUCCESS;
}

static int upd61151_querymenu(struct v4l2_subdev *sd, struct v4l2_querymenu *qmenu)
{
printk("DEBUG uPD61151: upd61151_querymenu\n");
	return RESULT_SUCCESS;
}

static int upd61151_init(struct v4l2_subdev *sd, u32 flags)
{
printk("DEBUG uPD61151: upd61151_init\n");
	return RESULT_SUCCESS;
}

static int upd61151_do_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls, int set)
{
printk("DEBUG uPD61151: upd61151_do_ext_ctrls\n");
	return RESULT_SUCCESS;
}

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)
{
printk("DEBUG uPD61151: upd61151_g_ext_ctrls\n");
	return RESULT_SUCCESS;
}

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)
{
printk("DEBUG uPD61151: upd61151_s_fmt\n");
	return RESULT_SUCCESS;
}

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");
	return RESULT_SUCCESS;
}

/* ----------------------------------------------------------------------- */

static const struct v4l2_subdev_core_ops upd61151_core_ops = {
	.g_chip_ident = upd61151_g_chip_ident,
	.init = upd61151_init,
	.queryctrl = upd61151_queryctrl,
	.querymenu = upd61151_querymenu,
	.g_ext_ctrls = upd61151_g_ext_ctrls,
	.s_ext_ctrls = upd61151_s_ext_ctrls,
	.try_ext_ctrls = upd61151_try_ext_ctrls,
	.s_std = upd61151_s_std,
};

static const struct v4l2_subdev_video_ops upd61151_video_ops = {
	.s_fmt = upd61151_s_fmt,
	.g_fmt = upd61151_g_fmt,
};

static const struct v4l2_subdev_ops upd61151_ops = {
	.core = &upd61151_core_ops,
	.video = &upd61151_video_ops,
};

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);

/* function for detect a chip here */
//	h->chip = upd61151_detect(h);

	if (upd61151_is_need_reload_fw(spi))
	{
		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");

	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->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);

/*
 * Overrides for Emacs so that we follow Linus's tabbing style.
 * ---------------------------------------------------------------------------
 * Local variables:
 * c-basic-offset: 8
 * End:
 */

[-- Attachment #6: upd61151.h --]
[-- Type: text/x-chdr, Size: 3998 bytes --]

/*
    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

/* FIXME START: OLD FROM SAA6752HS */

enum mpeg_video_bitrate_mode {
	MPEG_VIDEO_BITRATE_MODE_VBR = 0, /* Variable bitrate */
	MPEG_VIDEO_BITRATE_MODE_CBR = 1, /* Constant bitrate */

	MPEG_VIDEO_BITRATE_MODE_MAX
};

enum mpeg_audio_bitrate {
	MPEG_AUDIO_BITRATE_256 = 0, /* 256 kBit/sec */
	MPEG_AUDIO_BITRATE_384 = 1, /* 384 kBit/sec */

	MPEG_AUDIO_BITRATE_MAX
};

enum mpeg_video_format {
	MPEG_VIDEO_FORMAT_D1 = 0,
	MPEG_VIDEO_FORMAT_2_3_D1 = 1,
	MPEG_VIDEO_FORMAT_1_2_D1 = 2,
	MPEG_VIDEO_FORMAT_SIF = 3,

	MPEG_VIDEO_FORMAT_MAX
};

#define MPEG_VIDEO_TARGET_BITRATE_MAX 27000
#define MPEG_VIDEO_MAX_BITRATE_MAX 27000
#define MPEG_TOTAL_BITRATE_MAX 27000
#define MPEG_PID_MAX ((1 << 14) - 1)

struct mpeg_params {
	enum mpeg_video_bitrate_mode video_bitrate_mode;
	unsigned int video_target_bitrate;
	unsigned int video_max_bitrate; // only used for VBR
	enum mpeg_audio_bitrate audio_bitrate;
	unsigned int total_bitrate;

	unsigned int pmt_pid;
	unsigned int video_pid;
	unsigned int audio_pid;
	unsigned int pcr_pid;

	enum mpeg_video_format video_format;
};

/* FIXME STOP: OLD FROM SAA6752HS */

enum upd61151_command {
	UPD61151_COMMAND_INITIAL           = 0,
	UPD61151_COMMAND_STANDBY_STOP      = 1,
	UPD61151_COMMAND_CONFIG            = 2,
	UPD61151_COMMAND_START_RESTART     = 3,
	UPD61151_COMMAND_PAUSE             = 4,
	UPD61151_COMMAND_CHANGE            = 5,
};

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_VIDEO_ATTRIBUTE     0x1C
#define UPD61151_AUDIO_ATTRIBUTE1    0x2C
#define UPD61151_VIDEO_SYNC          0x54
#define UPD61151_VIDEO_HOFFSET       0x58
#define UPD61151_VIDEO_VOFFSET       0x5C
#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_SOFTWARE_RST        0xF8
#define UPD61151_TRANSFER_DATA       0xFC

/*
 * Local variables:
 * c-basic-offset: 8
 * End:
 */

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: saa7134 and μPD61151 MPEG2 coder
  2010-02-09  5:41                 ` Dmitri Belimov
@ 2010-02-12 15:44                   ` Hans Verkuil
  2010-02-16  7:53                     ` Dmitri Belimov
  0 siblings, 1 reply; 14+ messages in thread
From: Hans Verkuil @ 2010-02-12 15:44 UTC (permalink / raw)
  To: Dmitri Belimov; +Cc: Mauro Carvalho Chehab, linux-media

On Tuesday 09 February 2010 06:41:50 Dmitri Belimov wrote:
> Hi Hans
> 
> This is my last state for review.
> After small time I'll finish process of initialize the encoder.
> Configure some register, upload two firmware for video and for audio.
> Configure the frontends.
> 
> I have the questions.
> For configuring audio frontend need know samplerate of audio.
> saa7134 can only 32kHz
> saa7131/3/5 on I2S 32кГц from SIF source and 32/44.1/48 from external i.e.
> RCA stereo audio input. 
> 
> Hardcode 32kHz or need a function for determine mode of audio??

See struct v4l2_subdev_audio_ops: it has a s_clock_freq op for precisely that
purpose. The saa7134 should call that whenever it sets a new samplerate.

> 
> Other question. For configure VideoFrontend need know 50 or 60Hz
> Now I use videomode from h structure. I think more correct detect it
> on saa7134.

Whether it is 50 or 60 Hz depends on the video standard that you receive via
the s_std core op. Just implement that and when you get a new standard you
can use something like this: is_60hz = (std & V4L2_STD_525_60) ? 1 : 0;

Some more review comments:

linux/drivers/media/video/saa7134/saa7134.h:

@@ -355,6 +377,10 @@
        unsigned char           empress_addr;
        unsigned char           rds_addr;
 
+       /* SPI info */
+       struct saa7134_software_spi     spi;
+       struct spi_board_info   spi_conf;

Make this a struct spi_board_info *. This struct is too large: it is only used
in one board but all elements of the board array will suddenly get this whole
struct increasing the memory footprint substantially. In this case you can just
make it a pointer, that will work just as well.

+
        unsigned int            tda9887_conf;
        unsigned int            tuner_config;

linux/drivers/media/video/v4l2-common.c, in v4l2_spi_subdev_init():

+       /* initialize name */
+       snprintf(sd->name, sizeof(sd->name), "%s",
+               spi->dev.driver->name);

Use strlcpy here.

saa7134-spi.c:


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);
        if ( status & (1 << sb->controller_data->spi.miso))
                return 1;
        else
                return 0;
}

Simplify to:

static inline u32 getmiso(struct spi_device *dev)
{
        struct saa7134_spi_gpio *sb = to_sb(dev);
        u32 status;

        status = saa7134_get_gpio(sb->controller_data);
        return !!(status & (1 << sb->controller_data->spi.miso));
}

Also note that saa7134_get_gpio should return an u32 since unsigned long is
64 bits when compiled on a 64-bit kernel, which is probably not what you want.

saa7134_spi_unregister can be a void function as the result code is always 0.

There seems to be some old stuff in upd61151.h. Please remove what is not
needed.

In upd61151.c I highly recommend that all functions will use struct v4l2_subdev *sd
as argument. Only at the lowest level should you go from sd to spi. Among
others this allows you to use the standard v4l2_info/dbg etc. logging functions.

Don't use RESULT_SUCCESS. Just return 0.

Remove upd61151_init. The init op is rarely needed and should in general not
be used.

Remove those emacs editor comments at the end of the files. That's bad practice.

Regards,

	Hans

-- 
Hans Verkuil - video4linux developer - sponsored by TANDBERG

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: saa7134 and μPD61151 MPEG2 coder
  2010-02-12 15:44                   ` Hans Verkuil
@ 2010-02-16  7:53                     ` Dmitri Belimov
  0 siblings, 0 replies; 14+ messages in thread
From: Dmitri Belimov @ 2010-02-16  7:53 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: Mauro Carvalho Chehab, linux-media

[-- Attachment #1: Type: text/plain, Size: 4293 bytes --]

Hi

Some fixes

> On Tuesday 09 February 2010 06:41:50 Dmitri Belimov wrote:
> > Hi Hans
> > 
> > This is my last state for review.
> > After small time I'll finish process of initialize the encoder.
> > Configure some register, upload two firmware for video and for
> > audio. Configure the frontends.
> > 
> > I have the questions.
> > For configuring audio frontend need know samplerate of audio.
> > saa7134 can only 32kHz
> > saa7131/3/5 on I2S 32кГц from SIF source and 32/44.1/48 from
> > external i.e. RCA stereo audio input. 
> > 
> > Hardcode 32kHz or need a function for determine mode of audio??
> 
> See struct v4l2_subdev_audio_ops: it has a s_clock_freq op for
> precisely that purpose. The saa7134 should call that whenever it sets
> a new samplerate.

This op is not used in saa7134 sources. Now hardcoded 32kHz.

> > 
> > Other question. For configure VideoFrontend need know 50 or 60Hz
> > Now I use videomode from h structure. I think more correct detect it
> > on saa7134.
> 
> Whether it is 50 or 60 Hz depends on the video standard that you
> receive via the s_std core op. Just implement that and when you get a
> new standard you can use something like this: is_60hz = (std &
> V4L2_STD_525_60) ? 1 : 0;

I do it, if(std & V4L2_STD_625_50) then ....

This data is not real information about input signal. It's what we set from end-user programm.
But OK, I used it.

> Some more review comments:
> 
> linux/drivers/media/video/saa7134/saa7134.h:
> 
> @@ -355,6 +377,10 @@
>         unsigned char           empress_addr;
>         unsigned char           rds_addr;
>  
> +       /* SPI info */
> +       struct saa7134_software_spi     spi;
> +       struct spi_board_info   spi_conf;
> 
> Make this a struct spi_board_info *. This struct is too large: it is
> only used in one board but all elements of the board array will
> suddenly get this whole struct increasing the memory footprint
> substantially. In this case you can just make it a pointer, that will
> work just as well.

Yes. I don't know what is more good. Now all config data in saa7134-cards description.
In your case need move spi_board_info to SPI part of code. We will mix code and data.
For add new cards and devices need edit some files for add configs.
May be it's good in my case.

> +
>         unsigned int            tda9887_conf;
>         unsigned int            tuner_config;
> 
> linux/drivers/media/video/v4l2-common.c, in v4l2_spi_subdev_init():
> 
> +       /* initialize name */
> +       snprintf(sd->name, sizeof(sd->name), "%s",
> +               spi->dev.driver->name);
> 
> Use strlcpy here.

Done

> saa7134-spi.c:
> 
> 
> 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);
>         if ( status & (1 << sb->controller_data->spi.miso))
>                 return 1;
>         else
>                 return 0;
> }
> 
> Simplify to:
> 
> static inline u32 getmiso(struct spi_device *dev)
> {
>         struct saa7134_spi_gpio *sb = to_sb(dev);
>         u32 status;
> 
>         status = saa7134_get_gpio(sb->controller_data);
>         return !!(status & (1 << sb->controller_data->spi.miso));
> }

Thank you.

> Also note that saa7134_get_gpio should return an u32 since unsigned
> long is 64 bits when compiled on a 64-bit kernel, which is probably
> not what you want.

Done

> saa7134_spi_unregister can be a void function as the result code is
> always 0.

Done
 
> There seems to be some old stuff in upd61151.h. Please remove what is
> not needed.

Done

> In upd61151.c I highly recommend that all functions will use struct
> v4l2_subdev *sd as argument. Only at the lowest level should you go
> from sd to spi. Among others this allows you to use the standard
> v4l2_info/dbg etc. logging functions.

Done

> Don't use RESULT_SUCCESS. Just return 0.

Done
 
> Remove upd61151_init. The init op is rarely needed and should in
> general not be used.

Done 

> Remove those emacs editor comments at the end of the files. That's
> bad practice.

Done
 
With my best regards, Dmitry.

[-- Attachment #2: behold_spi.diff --]
[-- Type: text/x-patch, Size: 13704 bytes --]

diff -r b6b82258cf5e linux/drivers/media/video/saa7134/Makefile
--- a/linux/drivers/media/video/saa7134/Makefile	Thu Dec 31 19:14:54 2009 -0200
+++ b/linux/drivers/media/video/saa7134/Makefile	Tue Feb 16 10:23:52 2010 +0900
@@ -1,9 +1,9 @@
 
 saa7134-objs :=	saa7134-cards.o saa7134-core.o saa7134-i2c.o	\
 		saa7134-ts.o saa7134-tvaudio.o saa7134-vbi.o    \
-		saa7134-video.o saa7134-input.o
+		saa7134-video.o saa7134-input.o saa7134-spi.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 -r b6b82258cf5e linux/drivers/media/video/saa7134/saa7134-cards.c
--- a/linux/drivers/media/video/saa7134/saa7134-cards.c	Thu Dec 31 19:14:54 2009 -0200
+++ b/linux/drivers/media/video/saa7134/saa7134-cards.c	Tue Feb 16 10:23:52 2010 +0900
@@ -4619,6 +4619,7 @@
 			.name = name_radio,
 			.amux = LINE2,
 		},
+		.encoder_type = SAA7134_ENCODER_SAA6752HS,
 		.mpeg  = SAA7134_MPEG_EMPRESS,
 		.video_out = CCIR656,
 		.vid_port_opts  = (SET_T_CODE_POLARITY_NON_INVERTED |
@@ -4656,6 +4657,7 @@
 			.name = name_radio,
 			.amux = LINE2,
 		},
+		.encoder_type = SAA7134_ENCODER_SAA6752HS,
 		.mpeg  = SAA7134_MPEG_EMPRESS,
 		.video_out = CCIR656,
 		.vid_port_opts  = (SET_T_CODE_POLARITY_NON_INVERTED |
@@ -4695,6 +4697,7 @@
 			.name = name_radio,
 			.amux = LINE2,
 		},
+		.encoder_type = SAA7134_ENCODER_SAA6752HS,
 		.mpeg  = SAA7134_MPEG_EMPRESS,
 		.video_out = CCIR656,
 		.vid_port_opts  = (SET_T_CODE_POLARITY_NON_INVERTED |
@@ -5279,23 +5282,43 @@
 		.tuner_addr     = ADDR_UNSET,
 		.radio_addr     = ADDR_UNSET,
 		.mpeg           = SAA7134_MPEG_DVB,
+		.gpiomask       = 0x00860000,
 		.inputs         = { {
 			.name = name_tv,
 			.vmux = 2,
 			.amux = TV,
 			.tv   = 1,
-		}, {
-			.name = name_comp1,
-			.vmux = 0,
-			.amux = LINE1,
+			.gpio = 0x00860000
+		}, {
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE1,
+			.gpio = 0x00860000
 		}, {
 			.name = name_svideo,
 			.vmux = 9,
 			.amux = LINE1,
-		} },
-		.radio = {
-			.name = name_radio,
-			.amux = TV,
+			.gpio = 0x00860000
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = TV,
+			.gpio = 0x00860000
+		},
+		.encoder_type = SAA7134_ENCODER_muPD61151,
+		.mpeg  = SAA7134_MPEG_EMPRESS,
+		.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 -r b6b82258cf5e linux/drivers/media/video/saa7134/saa7134-core.c
--- a/linux/drivers/media/video/saa7134/saa7134-core.c	Thu Dec 31 19:14:54 2009 -0200
+++ b/linux/drivers/media/video/saa7134/saa7134-core.c	Tue Feb 16 10:23:52 2010 +0900
@@ -139,6 +139,18 @@
 		break;
 	}
 }
+
+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;
+}
+
 
 /* ------------------------------------------------------------------ */
 
@@ -1057,12 +1069,42 @@
 
 	saa7134_hwinit2(dev);
 
-	/* load i2c helpers */
+	/* initialize software SPI bus */
+	if (saa7134_boards[dev->board].spi.spi_enable)
+	{
+		dev->spi = saa7134_boards[dev->board].spi;
+
+		/* register SPI master and SPI slave */
+		if (saa7134_spi_register(dev, &saa7134_boards[dev->board].spi_conf))
+			saa7134_boards[dev->board].spi.spi_enable = 0;
+	}
+
+	/* 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 (saa7134_boards[dev->board].spi.spi_enable)
+				sd = v4l2_spi_new_subdev(&dev->v4l2_dev, dev->spi_adap, &saa7134_boards[dev->board].spi_conf);
+		}
+			break;
+		case SAA7134_ENCODER_SAA6752HS:
+		{
+			sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
 				"saa6752hs", "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;
@@ -1139,6 +1181,8 @@
 	return 0;
 
  fail4:
+	if ((card_is_empress(dev)) && (dev->encoder_type == SAA7134_ENCODER_muPD61151))
+		saa7134_spi_unregister(dev);
 	saa7134_unregister_video(dev);
 	saa7134_i2c_unregister(dev);
 	free_irq(pci_dev->irq, dev);
@@ -1412,6 +1456,7 @@
 /* ----------------------------------------------------------- */
 
 EXPORT_SYMBOL(saa7134_set_gpio);
+EXPORT_SYMBOL(saa7134_get_gpio);
 EXPORT_SYMBOL(saa7134_boards);
 
 /* ----------------- for the DMA sound modules --------------- */
diff -r b6b82258cf5e linux/drivers/media/video/saa7134/saa7134.h
--- a/linux/drivers/media/video/saa7134/saa7134.h	Thu Dec 31 19:14:54 2009 -0200
+++ b/linux/drivers/media/video/saa7134/saa7134.h	Tue Feb 16 10:23:52 2010 +0900
@@ -30,6 +30,13 @@
 #include <linux/notifier.h>
 #include <linux/delay.h>
 #include <linux/mutex.h>
+
+/* ifdef software SPI insert here start */
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_gpio.h>
+#include <linux/spi/spi_bitbang.h>
+/* ifdef software SPI insert here stop */
 
 #include <asm/io.h>
 
@@ -337,6 +344,21 @@
 	SAA7134_MPEG_TS_SERIAL,
 };
 
+enum saa7134_encoder_type {
+	SAA7134_ENCODER_UNUSED,
+	SAA7134_ENCODER_SAA6752HS,
+	SAA7134_ENCODER_muPD61151,
+};
+
+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 {
 	char                    *name;
 	unsigned int            audio_clock;
@@ -355,6 +377,10 @@
 	unsigned char		empress_addr;
 	unsigned char		rds_addr;
 
+	/* SPI info */
+	struct saa7134_software_spi	spi;
+	struct spi_board_info   spi_conf;
+
 	unsigned int            tda9887_conf;
 	unsigned int            tuner_config;
 
@@ -362,6 +388,7 @@
 	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;
 };
@@ -506,6 +533,12 @@
 	void                       (*signal_change)(struct saa7134_dev *dev);
 };
 
+struct saa7134_spi_gpio {
+	struct spi_bitbang         bitbang;
+	struct spi_master          *master;
+	struct saa7134_dev         *controller_data;
+};
+
 /* global device status */
 struct saa7134_dev {
 	struct list_head           devlist;
@@ -553,6 +586,10 @@
 	struct i2c_client          i2c_client;
 	unsigned char              eedata[256];
 	int 			   has_rds;
+
+	/* software spi */
+	struct saa7134_software_spi spi;
+	struct spi_master          *spi_adap;
 
 	/* video overlay */
 	struct v4l2_framebuffer    ovbuf;
@@ -615,6 +652,7 @@
 	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 */
@@ -681,6 +719,7 @@
 
 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
 
@@ -726,6 +765,11 @@
 int saa7134_i2c_register(struct saa7134_dev *dev);
 int saa7134_i2c_unregister(struct saa7134_dev *dev);
 
+/* ----------------------------------------------------------- */
+/* saa7134-spi.c                                               */
+
+int saa7134_spi_register(struct saa7134_dev *dev, struct spi_board_info *info);
+void saa7134_spi_unregister(struct saa7134_dev *dev);
 
 /* ----------------------------------------------------------- */
 /* saa7134-video.c                                             */
diff -r b6b82258cf5e linux/drivers/media/video/v4l2-common.c
--- a/linux/drivers/media/video/v4l2-common.c	Thu Dec 31 19:14:54 2009 -0200
+++ b/linux/drivers/media/video/v4l2-common.c	Tue Feb 16 10:23:52 2010 +0900
@@ -51,6 +51,7 @@
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/i2c.h>
+#include <linux/spi/spi.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/pgtable.h>
@@ -1069,6 +1070,66 @@
 
 #endif /* defined(CONFIG_I2C) */
 
+//#if defined(CONFIG_SPI) || (defined(CONFIG_SPI_MODULE) && defined(MODULE)) + SPI_BITBANG
+
+/* Load an spi sub-device. */
+
+void v4l2_spi_subdev_init(struct v4l2_subdev *sd, struct spi_device *spi,
+		const struct v4l2_subdev_ops *ops)
+{
+	v4l2_subdev_init(sd, ops);
+	sd->flags |= V4L2_SUBDEV_FL_IS_SPI;
+	/* the owner is the same as the spi_device's driver owner */
+	sd->owner = spi->dev.driver->owner;
+	/* spi_device and v4l2_subdev point to one another */
+	v4l2_set_subdevdata(sd, spi);
+	spi_set_drvdata(spi, sd);
+	/* initialize name */
+	strlcpy(sd->name, spi->dev.driver->name, sizeof(sd->name));
+}
+EXPORT_SYMBOL_GPL(v4l2_spi_subdev_init);
+
+struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev,
+		struct spi_master *master, struct spi_board_info *info)
+{
+	struct v4l2_subdev *sd = NULL;
+	struct spi_device *spi = NULL;
+
+	BUG_ON(!v4l2_dev);
+
+	if (info->modalias)
+		request_module(info->modalias);
+
+	spi = spi_new_device(master,info);
+
+	if (spi == NULL || spi->dev.driver ==NULL)
+		goto error;
+
+	if (!try_module_get(spi->dev.driver->owner))
+		goto error;
+
+	sd = spi_get_drvdata(spi);
+
+	/* Register with the v4l2_device which increases the module's
+	   use count as well. */
+	if (v4l2_device_register_subdev(v4l2_dev, sd))
+		sd = NULL;
+
+	/* Decrease the module use count to match the first try_module_get. */
+	module_put(spi->dev.driver->owner);
+
+error:
+	/* If we have a client but no subdev, then something went wrong and
+	   we must unregister the client. */
+	if (spi && sd == NULL)
+		spi_unregister_device(spi);
+
+	return sd;
+}
+EXPORT_SYMBOL_GPL(v4l2_spi_new_subdev);
+
+//#endif /* defined(CONFIG_SPI) */
+
 /* Clamp x to be between min and max, aligned to a multiple of 2^align.  min
  * and max don't have to be aligned, but there must be at least one valid
  * value.  E.g., min=17,max=31,align=4 is not allowed as there are no multiples
diff -r b6b82258cf5e linux/drivers/media/video/v4l2-device.c
--- a/linux/drivers/media/video/v4l2-device.c	Thu Dec 31 19:14:54 2009 -0200
+++ b/linux/drivers/media/video/v4l2-device.c	Tue Feb 16 10:23:52 2010 +0900
@@ -100,6 +100,14 @@
 		}
 #endif
 #endif
+/* FIXME: ADD if def's for SPI subdevices */
+		if (sd->flags & V4L2_SUBDEV_FL_IS_SPI) {
+			struct spi_device *spi = v4l2_get_subdevdata(sd);
+
+			if (spi)
+				spi_unregister_device(spi);
+		}
+
 	}
 }
 EXPORT_SYMBOL_GPL(v4l2_device_unregister);
diff -r b6b82258cf5e linux/include/media/v4l2-chip-ident.h
--- a/linux/include/media/v4l2-chip-ident.h	Thu Dec 31 19:14:54 2009 -0200
+++ b/linux/include/media/v4l2-chip-ident.h	Tue Feb 16 10:23:52 2010 +0900
@@ -278,6 +278,11 @@
 	/* module cs53132a: just ident 53132 */
 	V4L2_IDENT_CS53l32A = 53132,
 
+	/* modules upd61151 MPEG2 encoder: just ident 54000 */
+	V4L2_IDENT_UPD61161 = 54000,
+	/* modules upd61152 MPEG2 encoder with AC3: just ident 54001 */
+	V4L2_IDENT_UPD61162 = 54001,
+
 	/* module upd64031a: just ident 64031 */
 	V4L2_IDENT_UPD64031A = 64031,
 
diff -r b6b82258cf5e linux/include/media/v4l2-common.h
--- a/linux/include/media/v4l2-common.h	Thu Dec 31 19:14:54 2009 -0200
+++ b/linux/include/media/v4l2-common.h	Tue Feb 16 10:23:52 2010 +0900
@@ -191,6 +191,25 @@
 
 /* ------------------------------------------------------------------------- */
 
+/* SPI Helper functions */
+
+#include <linux/spi/spi.h>
+
+struct spi_device_id;
+struct spi_device;
+
+/* Load an spi module and return an initialized v4l2_subdev struct.
+   Only call request_module if module_name != NULL.
+   The client_type argument is the name of the chip that's on the adapter. */
+struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev,
+		struct spi_master *master, struct spi_board_info *info);
+
+/* Initialize an v4l2_subdev with data from an spi_device struct */
+void v4l2_spi_subdev_init(struct v4l2_subdev *sd, struct spi_device *spi,
+		const struct v4l2_subdev_ops *ops);
+
+/* ------------------------------------------------------------------------- */
+
 /* Note: these remaining ioctls/structs should be removed as well, but they are
    still used in tuner-simple.c (TUNER_SET_CONFIG), cx18/ivtv (RESET) and
    v4l2-int-device.h (v4l2_routing). To remove these ioctls some more cleanup
diff -r b6b82258cf5e linux/include/media/v4l2-subdev.h
--- a/linux/include/media/v4l2-subdev.h	Thu Dec 31 19:14:54 2009 -0200
+++ b/linux/include/media/v4l2-subdev.h	Tue Feb 16 10:23:52 2010 +0900
@@ -387,6 +387,8 @@
 
 /* Set this flag if this subdev is a i2c device. */
 #define V4L2_SUBDEV_FL_IS_I2C (1U << 0)
+/* Set this flag if this subdev is a spi device. */
+#define V4L2_SUBDEV_FL_IS_SPI (1U << 1)
 
 /* Each instance of a subdev driver should create this struct, either
    stand-alone or embedded in a larger struct.

[-- Attachment #3: saa7134-spi.c --]
[-- Type: text/x-c++src, Size: 4670 bytes --]

/*
 *
 * 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.
 */

#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_bitbang.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, 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);
}


/*
 * Overrides for Emacs so that we follow Linus's tabbing style.
 * ---------------------------------------------------------------------------
 * Local variables:
 * c-basic-offset: 8
 * End:
 */
 

[-- Attachment #4: upd61151.c --]
[-- Type: text/x-c++src, Size: 24911 bytes --]

 /*
    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

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 {
	/* transport streams */
	__u16				ts_pid_pmt;
	__u16				ts_pid_audio;
	__u16				ts_pid_video;
	__u16				ts_pid_pcr;

	/* audio */
	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;
};

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 =
{
	.ts_pid_pmt      = 16,
	.ts_pid_video    = 260,
	.ts_pid_audio    = 256,
	.ts_pid_pcr      = 259,

	.vi_aspect       = V4L2_MPEG_VIDEO_ASPECT_4x3,
	.vi_bitrate      = 4000,
	.vi_bitrate_peak = 6000,
	.vi_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,

	.au_encoding     = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
	.au_l2_bitrate   = V4L2_MPEG_AUDIO_L2_BITRATE_256K,
};

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 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)
{
printk("upd61151_set_state\n");
printk("WARNING: The function upd61151_set_state is EMPTY\n");
	return RESULT_SUCCESS;
}

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)
{
	struct spi_device *spi = v4l2_get_subdevdata(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 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 = RESULT_FAILURE;
		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 = RESULT_FAILURE;
		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");

	if (upd61151_wait_transfer_irq(sd) == 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 = RESULT_FAILURE;
		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 = RESULT_FAILURE;
		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 = 200;
		wait = 1;
		break;

	default:
		return RESULT_FAILURE;
	}

	/* 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 0;
		}

		/* 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 RESULT_FAILURE;
}

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;
printk("dbyte = 0x%x  ",dbyte);
	/* 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);

printk("upd61151_setup_audio_frontend\n");
	/* Setup AUDIO attribute 1 */
	/* FIXME: hardcoded samplerate of audio to 32kHz */
	/* default bitrate is 256Kbit */
	write_reg(spi, UPD61151_AUDIO_ATTRIBUTE1, 0x29);

	/* PLLs = internal, AMCLK = 384fs, AQ = 16bit & 64bck, APCMI = I2S, APCMO = OFF*/
	write_reg(spi, UPD61151_AUDIO_INTERFACE, 0x5B);
	return 0;
}

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);

printk("upd61151_config_encoder\n");
printk("WARNING: The function upd61151_config_encoder is EMPTY\n");

	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);

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);

	if (upd61151_load_base_firmware(sd))
		return RESULT_FAILURE;

	if (upd61151_load_audio_firmware(sd))
		return RESULT_FAILURE;

	/* 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 RESULT_FAILURE;
	}

	/* Set STANDBY state */
	if (upd61151_chip_command(sd, UPD61151_COMMAND_STANDBY_STOP))
		return RESULT_FAILURE;

	/* 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 */
	if (upd61151_set_state(sd, UPD61151_CONFIG_ALL))
		return RESULT_FAILURE;

	/* Return to STANDBY state */
	if (upd61151_chip_command(sd, UPD61151_COMMAND_STANDBY_STOP))
		return RESULT_FAILURE;

	return 0;
}

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;
}

static int upd61151_set_bitrate(struct v4l2_subdev *sd,
				 struct upd61151_state *h)
{
printk("DEBUG uPD61151: upd61151_set_bitrate\n");
printk("WARNING: The function upd61151_set_bitrate is EMPTY\n");
	return 0;
}

static int upd61151_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qctrl)
{
printk("DEBUG uPD61151: upd61151_queryctrl\n");
printk("WARNING: The function upd61151_queryctrl is EMPTY\n");
	return 0;
}

static int upd61151_querymenu(struct v4l2_subdev *sd, struct v4l2_querymenu *qmenu)
{
printk("DEBUG uPD61151: upd61151_querymenu\n");
printk("WARNING: The function upd61151_querymenu is EMPTY\n");
	return 0;
}

static int upd61151_do_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls, int set)
{
printk("DEBUG uPD61151: upd61151_do_ext_ctrls\n");
printk("WARNING: The function upd61151_do_ext_ctrls is EMPTY\n");
	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)
{
printk("DEBUG uPD61151: upd61151_g_ext_ctrls\n");
printk("WARNING: The function upd61151_g_ext_ctrls is EMPTY\n");
	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,
	.queryctrl = upd61151_queryctrl,
	.querymenu = upd61151_querymenu,
	.g_ext_ctrls = upd61151_g_ext_ctrls,
	.s_ext_ctrls = upd61151_s_ext_ctrls,
	.try_ext_ctrls = upd61151_try_ext_ctrls,
	.s_std = upd61151_s_std,
};

static const struct v4l2_subdev_video_ops upd61151_video_ops = {
	.s_fmt = upd61151_s_fmt,
	.g_fmt = upd61151_g_fmt,
};

static const struct v4l2_subdev_ops upd61151_ops = {
	.core = &upd61151_core_ops,
	.video = &upd61151_video_ops,
};

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 (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");

	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->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);

[-- Attachment #5: upd61151.h --]
[-- Type: text/x-chdr, Size: 4732 bytes --]

/*
    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_video_bitrate_mode {
	MPEG_VIDEO_BITRATE_MODE_VBR = 0, /* Variable bitrate */
	MPEG_VIDEO_BITRATE_MODE_CBR = 1, /* Constant bitrate */

	MPEG_VIDEO_BITRATE_MODE_MAX
};

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)

/* FIXME START: OLD FROM SAA6752HS */

struct mpeg_params {
	enum mpeg_video_bitrate_mode video_bitrate_mode;
	unsigned int video_target_bitrate;
	unsigned int video_max_bitrate; // only used for VBR
	enum mpeg_audio_bitrate audio_bitrate;
	unsigned int total_bitrate;

	unsigned int pmt_pid;
	unsigned int video_pid;
	unsigned int audio_pid;
	unsigned int pcr_pid;

	enum mpeg_video_format video_format;
};

/* FIXME STOP: OLD FROM SAA6752HS */

enum upd61151_command {
	UPD61151_COMMAND_INITIAL           = 0,
	UPD61151_COMMAND_STANDBY_STOP      = 1,
	UPD61151_COMMAND_CONFIG            = 2,
	UPD61151_COMMAND_START_RESTART     = 3,
	UPD61151_COMMAND_PAUSE             = 4,
	UPD61151_COMMAND_CHANGE            = 5,
};

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_VIDEO_ATTRIBUTE     0x1C
#define UPD61151_VIDEO_MODE          0x20
#define UPD61151_AUDIO_ATTRIBUTE1    0x2C
#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_SOFTWARE_RST        0xF8
#define UPD61151_TRANSFER_DATA       0xFC

/*
 * Local variables:
 * c-basic-offset: 8
 * End:
 */

^ permalink raw reply	[flat|nested] 14+ messages in thread

* eb1a:2860 eMPIA em28xx device to usb1 ??? usb hub problem?
  2010-01-27  5:36       ` saa7134 and μPD61151 MPEG2 coder Dmitri Belimov
  2010-01-27 11:14         ` Hans Verkuil
@ 2010-02-22 22:38         ` j
  2010-02-22 22:52           ` Devin Heitmueller
  1 sibling, 1 reply; 14+ messages in thread
From: j @ 2010-02-22 22:38 UTC (permalink / raw)
  To: Dmitri Belimov
  Cc: Hans Verkuil, Mauro Carvalho Chehab, linux-media, video4linux-list

Hi I get trouble with my Kworld em28xx device, anyone can help any 
kernel issue found somewhere about that?

Bus 001 Device 005: ID eb1a:2860 eMPIA Technology, Inc.

The device seems to go to usb1 hub and its usb2

Using kernel : 2.6.27-7-generic

LSUSB

Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 005: ID eb1a:2860 eMPIA Technology, Inc.
Bus 001 Device 004: ID 046d:c404 Logitech, Inc. TrackMan Wheel
Bus 001 Device 003: ID 04d9:1603 Holtek Semiconductor, Inc.
Bus 001 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub


DMESG

[    2.429146] usbcore: registered new interface driver usbfs
[    2.429164] usbcore: registered new interface driver hub
[    2.429216] usbcore: registered new device driver usb
[    2.518153] usb usb1: configuration #1 chosen from 1 choice
[    2.900018] usb 1-1: new low speed USB device using ohci_hcd and 
address 2
[    2.912659] usb usb2: configuration #1 chosen from 1 choice
[    3.576015] usb 2-3: new high speed USB device using ehci_hcd and 
address 4
[    4.096019] usb 2-3: device not accepting address 4, error -71
[    4.208015] usb 2-3: new high speed USB device using ehci_hcd and 
address 5
[    4.340706] usb 2-3: configuration #1 chosen from 1 choice
[    4.644571] usb 1-1: new low speed USB device using ohci_hcd and 
address 3
[    4.876163] usb 1-1: configuration #1 chosen from 1 choice
[    5.180015] usb 1-2: new low speed USB device using ohci_hcd and 
address 4
[    5.393407] usb 1-2: configuration #1 chosen from 1 choice
[    5.396625] usb 2-3: USB disconnect, address 5
[    5.636017] usb 2-3: new high speed USB device using ehci_hcd and 
address 6
[    5.768459] usb 2-3: configuration #1 chosen from 1 choice
[    5.768794] usbcore: registered new interface driver hiddev
[    5.772486] usb 2-3: USB disconnect, address 6
[    5.781319] input:   USB Keyboard as 
/devices/pci0000:00/0000:00:02.0/usb1/1-1/1-1:1.0/input/input1
[    5.784136] input,hidraw0: USB HID v1.10 Keyboard [  USB Keyboard] on 
usb-0000:00:02.0-1
[    5.807105] input:   USB Keyboard as 
/devices/pci0000:00/0000:00:02.0/usb1/1-1/1-1:1.1/input/input2
[    5.807351] input,hidraw1: USB HID v1.10 Device [  USB Keyboard] on 
usb-0000:00:02.0-1
[    5.814365] input: Logitech Trackball as 
/devices/pci0000:00/0000:00:02.0/usb1/1-2/1-2:1.0/input/input3
[    5.814594] input,hidraw2: USB HID v1.10 Mouse [Logitech Trackball] 
on usb-0000:00:02.0-2
[    5.814611] usbcore: registered new interface driver usbhid
[    5.814614] usbhid: v2.6:USB HID core driver
[    6.048518] usb 2-3: new high speed USB device using ehci_hcd and 
address 7
[    6.568017] usb 2-3: device not accepting address 7, error -71
[    6.680026] usb 2-3: new high speed USB device using ehci_hcd and 
address 8
[    7.192521] usb 1-3: new full speed USB device using ohci_hcd and 
address 5
[    7.393043] usb 1-3: not running at top speed; connect to a high 
speed hub
[    7.399169] usb 1-3: configuration #1 chosen from 1 choice
[   13.927208] em28xx Doesn't have usb audio class
[   14.934118] input: em28xx snapshot button as 
/devices/pci0000:00/0000:00:02.0/usb1/1-3/input/input7
[   16.785083] usbcore: registered new interface driver em28xx
[   16.909506] em28xx-audio.c: probing for em28x1 non standard usbaudio
[   18.609828] usbcore: usbfs: unrecognised mount option "default" or 
missing value
[   18.609834] usbcore: usbfs: mount parameter error:


LSPCI

00:00.0 RAM memory: nVidia Corporation MCP61 Memory Controller (rev a1)
00:01.0 ISA bridge: nVidia Corporation MCP61 LPC Bridge (rev a2)
00:01.1 SMBus: nVidia Corporation MCP61 SMBus (rev a2)
00:01.2 RAM memory: nVidia Corporation MCP61 Memory Controller (rev a2)
00:02.0 USB Controller: nVidia Corporation MCP61 USB Controller (rev a3)
00:02.1 USB Controller: nVidia Corporation MCP61 USB Controller (rev a3)
00:04.0 PCI bridge: nVidia Corporation MCP61 PCI bridge (rev a1)
00:05.0 Audio device: nVidia Corporation MCP61 High Definition Audio 
(rev a2)
00:07.0 Bridge: nVidia Corporation MCP61 Ethernet (rev a2)
00:08.0 IDE interface: nVidia Corporation MCP61 SATA Controller (rev a2)
00:09.0 PCI bridge: nVidia Corporation MCP61 PCI Express bridge (rev a2)
00:0b.0 PCI bridge: nVidia Corporation MCP61 PCI Express bridge (rev a2)
00:0c.0 PCI bridge: nVidia Corporation MCP61 PCI Express bridge (rev a2)
00:0d.0 VGA compatible controller: nVidia Corporation GeForce 6150SE 
nForce 430 (rev a2)
00:18.0 Host bridge: Advanced Micro Devices [AMD] K8 [Athlon64/Opteron] 
HyperTransport Technology Configuration
00:18.1 Host bridge: Advanced Micro Devices [AMD] K8 [Athlon64/Opteron] 
Address Map
00:18.2 Host bridge: Advanced Micro Devices [AMD] K8 [Athlon64/Opteron] 
DRAM Controller
00:18.3 Host bridge: Advanced Micro Devices [AMD] K8 [Athlon64/Opteron] 
Miscellaneous Control
01:07.0 Ethernet controller: VIA Technologies, Inc. VT6105/VT6106S 
[Rhine-III] (rev 86)




--
 
This message has been verified by LastSpam (http://www.lastspam.com) eMail security service, provided by SoluLAN 
Ce courriel a ete verifie par le service de securite pour courriels LastSpam (http://www.lastspam.com), fourni par SoluLAN (http://www.solulan.com) 
www.solulan.com


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: eb1a:2860 eMPIA em28xx device to usb1 ??? usb hub problem?
  2010-02-22 22:38         ` eb1a:2860 eMPIA em28xx device to usb1 ??? usb hub problem? j
@ 2010-02-22 22:52           ` Devin Heitmueller
  2010-02-23  6:37             ` Dean
  0 siblings, 1 reply; 14+ messages in thread
From: Devin Heitmueller @ 2010-02-22 22:52 UTC (permalink / raw)
  To: j
  Cc: Dmitri Belimov, Hans Verkuil, video4linux-list,
	Mauro Carvalho Chehab, linux-media

On Mon, Feb 22, 2010 at 5:38 PM, j <jlafontaine@ctecworld.com> wrote:
> Hi I get trouble with my Kworld em28xx device, anyone can help any kernel
> issue found somewhere about that?

Hi J,

Is this device plugged directly into the USB port on the motherboard?
Or do you have a USB hub that the device is connected to.  Sometimes
low quality USB hubs will not work properly with high speed isoc
devices.

Also, I would suggest that you leave the device unplugged when
powering up the system.  Then once it is up, plug it in and send the
full dmesg output.  This will make it easier to analyze the dmesg
output because the driver will not be initializing at the same time as
all the other USB devices.

Also, please provide the *full* dmesg output, so we have more context
information about the system (things such as the kernel version, etc).

Cheers,

Devin

-- 
Devin J. Heitmueller - Kernel Labs
http://www.kernellabs.com

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: eb1a:2860 eMPIA em28xx device to usb1 ??? usb hub problem?
  2010-02-22 22:52           ` Devin Heitmueller
@ 2010-02-23  6:37             ` Dean
  2010-02-23 16:46               ` Devin Heitmueller
  0 siblings, 1 reply; 14+ messages in thread
From: Dean @ 2010-02-23  6:37 UTC (permalink / raw)
  To: Devin Heitmueller
  Cc: j, Hans Verkuil, linux-media, video4linux-list, Mauro Carvalho Chehab

[-- Attachment #1: Type: text/plain, Size: 420 bytes --]

Hi,

I have the KWorld DVB-T 305U, an em28xx device.  Only the video works for me under Linux, no audio.  In case anyone wants to see it, I have attached the full dmesg text, solely from this device.

Cheers,
Dean


Devin Heitmueller wrote:
> ....
> Also, please provide the *full* dmesg output, so we have more context
> information about the system (things such as the kernel version, etc).
> 
> Cheers,
> 
> Devin
> 

[-- Attachment #2: em28xx_KWorld_DVB-T_305U_dmesg.txt.gz --]
[-- Type: application/x-gzip, Size: 1227 bytes --]

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: eb1a:2860 eMPIA em28xx device to usb1 ??? usb hub problem?
  2010-02-23  6:37             ` Dean
@ 2010-02-23 16:46               ` Devin Heitmueller
  2010-02-23 21:17                 ` Dean
  0 siblings, 1 reply; 14+ messages in thread
From: Devin Heitmueller @ 2010-02-23 16:46 UTC (permalink / raw)
  To: Dean
  Cc: j, Hans Verkuil, linux-media, video4linux-list, Mauro Carvalho Chehab

On Tue, Feb 23, 2010 at 1:37 AM, Dean <red1@linuxstation.net> wrote:
> Hi,
>
> I have the KWorld DVB-T 305U, an em28xx device.  Only the video works for me under Linux, no audio.  In case anyone wants to see it, I have attached the full dmesg text, solely from this device.
>
> Cheers,
> Dean

Hi Dean,

How are you testing the audio, and under what video standard are you
trying to use the device (NTSC/PAL/SECAM)?

Devin

-- 
Devin J. Heitmueller - Kernel Labs
http://www.kernellabs.com

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: eb1a:2860 eMPIA em28xx device to usb1 ??? usb hub problem?
  2010-02-23 16:46               ` Devin Heitmueller
@ 2010-02-23 21:17                 ` Dean
  2010-02-23 21:22                   ` Devin Heitmueller
  0 siblings, 1 reply; 14+ messages in thread
From: Dean @ 2010-02-23 21:17 UTC (permalink / raw)
  To: Devin Heitmueller
  Cc: Dean, j, Hans Verkuil, linux-media, video4linux-list,
	Mauro Carvalho Chehab

Devin Heitmueller wrote:
> On Tue, Feb 23, 2010 at 1:37 AM, Dean <red1@linuxstation.net> wrote:
>> Hi,
>>
>> I have the KWorld DVB-T 305U, an em28xx device.  Only the video works for me under Linux, no audio.  In case anyone wants to see it, I have attached the full dmesg text, solely from this device.
>>
>> Cheers,
>> Dean
> 
> Hi Dean,
> 
> How are you testing the audio, and under what video standard are you
> trying to use the device (NTSC/PAL/SECAM)?
> 
> Devin
>

Devin

I am receiving NTSC TV signals.  I test with mplayer.  Example;

mplayer tv://9 -tv driver=v4l2:alsa:immediatemode=0:adevice=hw.Em28xxAudio,0:norm=ntsc:chanlist=us-cable -vf pp=ci

The above command works fine (both audio and video) with my Hauppauge HVR-850, but for the Kworld 305U I must change 'immediatemode=0' to 'immediatemode=1' otherwise the video frame rate is about 1/2 normal speed and about 1 minute later mplayer starts printing 'video buffer full - dropping frame'.

According to dmesg the Kworld 305U loads the same firmware as my Hauppauge HVR-850, and (during separate test sessions) installs the same ALSA device;

card 1: Em28xxAudio [Em28xx Audio], device 0: Em28xx Audio [Empia 28xx Capture]
  Subdevices: 0/1
  Subdevice #0: subdevice #0


Dean

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: eb1a:2860 eMPIA em28xx device to usb1 ??? usb hub problem?
  2010-02-23 21:17                 ` Dean
@ 2010-02-23 21:22                   ` Devin Heitmueller
  0 siblings, 0 replies; 14+ messages in thread
From: Devin Heitmueller @ 2010-02-23 21:22 UTC (permalink / raw)
  To: Dean
  Cc: j, Hans Verkuil, linux-media, video4linux-list, Mauro Carvalho Chehab

On Tue, Feb 23, 2010 at 4:17 PM, Dean <red1@linuxstation.net> wrote:

> I am receiving NTSC TV signals.  I test with mplayer.  Example;
>
> mplayer tv://9 -tv driver=v4l2:alsa:immediatemode=0:adevice=hw.Em28xxAudio,0:norm=ntsc:chanlist=us-cable -vf pp=ci
>
> The above command works fine (both audio and video) with my Hauppauge HVR-850, but for the Kworld 305U I must change 'immediatemode=0' to 'immediatemode=1' otherwise the video frame rate is about 1/2 normal speed and about 1 minute later mplayer starts printing 'video buffer full - dropping frame'.
>
> According to dmesg the Kworld 305U loads the same firmware as my Hauppauge HVR-850, and (during separate test sessions) installs the same ALSA device;
>
> card 1: Em28xxAudio [Em28xx Audio], device 0: Em28xx Audio [Empia 28xx Capture]
>  Subdevices: 0/1
>  Subdevice #0: subdevice #0

Try this:  open em28xx-cards.c, and change the board profile for the
entry EM2880_BOARD_KWORLD_DVB_305U such that it includes the following
field:

.mts_firmware = 1,

Then recompile and see if it starts working.

Devin


-- 
Devin J. Heitmueller - Kernel Labs
http://www.kernellabs.com

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2010-02-23 21:22 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20091007101142.3b83dbf2@glory.loctelecom.ru>
     [not found] ` <200912160849.17005.hverkuil@xs4all.nl>
     [not found]   ` <20100112172209.464e88cd@glory.loctelecom.ru>
     [not found]     ` <201001130838.23949.hverkuil@xs4all.nl>
2010-01-27  5:36       ` saa7134 and μPD61151 MPEG2 coder Dmitri Belimov
2010-01-27 11:14         ` Hans Verkuil
2010-01-28  2:09           ` Dmitri Belimov
2010-01-28 12:00             ` Hans Verkuil
2010-01-29  7:12               ` Dmitri Belimov
2010-02-09  5:41                 ` Dmitri Belimov
2010-02-12 15:44                   ` Hans Verkuil
2010-02-16  7:53                     ` Dmitri Belimov
2010-02-22 22:38         ` eb1a:2860 eMPIA em28xx device to usb1 ??? usb hub problem? j
2010-02-22 22:52           ` Devin Heitmueller
2010-02-23  6:37             ` Dean
2010-02-23 16:46               ` Devin Heitmueller
2010-02-23 21:17                 ` Dean
2010-02-23 21:22                   ` Devin Heitmueller

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.