diff -urN linux-2.6.17-rc4.orig/drivers/media/video/Makefile linux-2.6.17-rc4/drivers/media/video/Makefile
--- linux-2.6.17-rc4.orig/drivers/media/video/Makefile	2006-05-23 21:32:31.000000000 +0900
+++ linux-2.6.17-rc4/drivers/media/video/Makefile	2006-05-23 22:15:21.000000000 +0900
@@ -6,7 +6,8 @@
 zr36067-objs	:=	zoran_procfs.o zoran_device.o \
 			zoran_driver.o zoran_card.o
 tuner-objs	:=	tuner-core.o tuner-types.o tuner-simple.o \
-			mt20xx.o tda8290.o tea5767.o
+			mt20xx.o tda8290.o tea5767.o \
+			xc3028_motv.o xc3028_meta.o
 
 msp3400-objs	:=	msp3400-driver.o msp3400-kthreads.o
 
diff -urN linux-2.6.17-rc4.orig/drivers/media/video/msp34x5.h linux-2.6.17-rc4/drivers/media/video/msp34x5.h
--- linux-2.6.17-rc4.orig/drivers/media/video/msp34x5.h	1970-01-01 09:00:00.000000000 +0900
+++ linux-2.6.17-rc4/drivers/media/video/msp34x5.h	2006-05-23 22:15:21.000000000 +0900
@@ -0,0 +1,37 @@
+/*
+ * Header for MICRONAS MSP34x5
+ * Modify FROM msp3400 driver @ v2.4.20pre6 
+ * 2002-09-15 K.Ohta
+ */
+#ifndef MSP34x5_H
+#define MSP34x5_H
+
+/* ---------------------------------------------------------------------- */
+
+struct msp_dfpreg {
+    int reg;
+    int value;
+};
+
+#define MSP_SET_DFPREG     _IOW('m',15,struct msp_dfpreg)
+#define MSP_GET_DFPREG     _IOW('m',16,struct msp_dfpreg)
+#define MSP_AUDC_SET_INPUT -1 /* Temporally value 20030325 K.O */
+#define MSP_AUDC_SET_RADIO -2 /* Temporally value 20030325 K.O */
+
+#define MSP_FLAG_NORM      0
+#define MSP_FLAG_EIAJ      1
+#define MSP_FLAG_KOREA     2
+/* After 0.2.7+2.4.21pre6 */
+static inline int MAX(int a,int b)
+{
+   if(a>b) return a;
+   return b;
+}
+
+static inline int MIN(int a,int b)
+{
+   if(a<b) return a;
+   return b;
+}
+
+#endif /* MSP34x5_H */
diff -urN linux-2.6.17-rc4.orig/drivers/media/video/saa7134/Makefile linux-2.6.17-rc4/drivers/media/video/saa7134/Makefile
--- linux-2.6.17-rc4.orig/drivers/media/video/saa7134/Makefile	2006-05-23 21:32:31.000000000 +0900
+++ linux-2.6.17-rc4/drivers/media/video/saa7134/Makefile	2006-05-23 22:15:21.000000000 +0900
@@ -2,6 +2,7 @@
 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
+#		xc3028_motv.o
 
 obj-$(CONFIG_VIDEO_SAA7134) +=  saa7134.o saa7134-empress.o \
 				saa6752hs.o
diff -urN linux-2.6.17-rc4.orig/drivers/media/video/saa7134/doc/README.monstertv linux-2.6.17-rc4/drivers/media/video/saa7134/doc/README.monstertv
--- linux-2.6.17-rc4.orig/drivers/media/video/saa7134/doc/README.monstertv	1970-01-01 09:00:00.000000000 +0900
+++ linux-2.6.17-rc4/drivers/media/video/saa7134/doc/README.monstertv	2006-05-23 22:15:21.000000000 +0900
@@ -0,0 +1,39 @@
+*Usage for Japan-NTSC user.
+
+ build kernel,saa7134 as module.
+ make all;make install;make install_modules
+ insmod saa7134
+
+ 
+*Why tvaudio?( Obsolete Article)
+
+ Monster TV 1,2 (Vender is SKNet Corp. http://www.sknet-web.co.jp/ )
+ contains MSP3445 as Japanese Multi voice decoder,but msp3400 driver of
+ upstream not support decoding Japanese-NTSC with MSP3445.
+ I tried apply Japan-NTSC to msp3400 driver,but it is unstable,driver locks up
+ kernel sometimes.
+ As of,I added MSP3445 with Japan-NTSC driver to tvaudio module.
+
+*Support status (2005/11/22)
+
+ Monster TV : Complete.
+ Monster TV2: May be OKay,but not be checked,please notify.
+ Monster TV3/3 Lite : Testing. (ID Reserved),
+                      I don't have card yet,please tell me 
+                      result of card. (lspci -n).
+ Monster TV PH-R    : Not Support Yet.
+                      Please tell me information of PCI ID and TUNER.
+ Monster TV PH-GTR  : Not support Yet (I will wish to support). 
+                      I need Datasheet of Panasonic MN82832 (Y/C Sep.) and
+		      Oren 433006MOC (Ghost Reducer),please send me these sheets.
+ Monster TV Pocket etc.... : I will not support, please help!
+ 
+ Monster TV V Series: Testing "Pure V" only.
+                      "VF" "VFM" "VM" is not tested yet. Pls,Help!
+                      Using silicon chip as tuner,I'm hacking it:-)
+ *Author
+ 
+  Ohta Kyuma <whatisthis@jcom.home.ne.jp>
+  
+
+ 
diff -urN linux-2.6.17-rc4.orig/drivers/media/video/saa7134/doc/README.saa7134.oss linux-2.6.17-rc4/drivers/media/video/saa7134/doc/README.saa7134.oss
--- linux-2.6.17-rc4.orig/drivers/media/video/saa7134/doc/README.saa7134.oss	1970-01-01 09:00:00.000000000 +0900
+++ linux-2.6.17-rc4/drivers/media/video/saa7134/doc/README.saa7134.oss	2006-05-23 22:15:21.000000000 +0900
@@ -0,0 +1,10 @@
+Synopsys:
+ Now,OSS driver for SAA7134 seems to be imcomplete.
+ When using OSS-SAA7134 (i.e. MythTv),you should do when update driver.
+ 1. Compile,install driver.
+ 2. run ./u script (module parameter: oss=1 oss_rate=32000 good).
+ 3. run ./test-oss script,and press ^C.
+ 4. run anything using OSS-SAA7134 (typically /dev/dsp1).
+ 
+Good Luck!
+ Artane.
diff -urN linux-2.6.17-rc4.orig/drivers/media/video/saa7134/doc/README.xc3028 linux-2.6.17-rc4/drivers/media/video/saa7134/doc/README.xc3028
--- linux-2.6.17-rc4.orig/drivers/media/video/saa7134/doc/README.xc3028	1970-01-01 09:00:00.000000000 +0900
+++ linux-2.6.17-rc4/drivers/media/video/saa7134/doc/README.xc3028	2006-05-23 22:15:21.000000000 +0900
@@ -0,0 +1,37 @@
+== Hauppauge HVR 900 ==
+
+==== Installation ====
+
+1. get the v4l-dvb repository from linuxtv and type make for generating all symlinks in v4l-dvb/v4l
+2. copy tuner.h into v4l-dvb/linux/include/media/ in your v4l directory
+3. simply replace following files in the repository  
+ * Makefile
+ * em28xx-cards.c  
+ * em28xx.h  
+ * tuner-core.c  
+ * tuner-types.c  
+ * xc3028.c 
+with the files in this directory and simply recompile (copy these files to v4l-dvb/v4l)
+
+==== Firmware ====
+
+this device needs a firmware, which is stored in emBDA.sys
+build the firmwareextractor with
+$ gcc convert.c -o convert
+and extract the firmware
+$ ./convert emBDA.sys > /lib/firmware/xceive_xc_3028.fw
+(I only tested that tool with Hauppauge HVR 900, Terratec might work too but without any guarantee - please send me BDA files of other xc3028 devices)
+
+==== General ====
+
+ * the xc3028 works very reliable and the frequencies are correct for europe
+ * Please add your email, product name, vendor/product id to the discussion in the v4l wiki at www.linuxtv.org
+ * I'll not be responsible for any damage caused by this driver, use it with your own risk
+ 
+==== TODO ====
+
+ * some cleanup
+ * figuring out channel locks
+
+
+Markus Rechberger <mrechberger@gmail.com>
diff -urN linux-2.6.17-rc4.orig/drivers/media/video/saa7134/doc/convert.c linux-2.6.17-rc4/drivers/media/video/saa7134/doc/convert.c
--- linux-2.6.17-rc4.orig/drivers/media/video/saa7134/doc/convert.c	1970-01-01 09:00:00.000000000 +0900
+++ linux-2.6.17-rc4/drivers/media/video/saa7134/doc/convert.c	2006-05-23 22:15:21.000000000 +0900
@@ -0,0 +1,84 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define ARRAY_SIZE(fw) sizeof(fw)/sizeof(fw[0])
+struct{
+	char *fwname;
+	char *fwstart;
+	char *fwstart2;
+	int length1;
+	int length2;
+} xc_firmware[]={{"Terratec","\x2a\x03\xe5\xe0\x00\x07\xf4\xd0\x01\xc0\x70\xe0\x00\x07","\x2a\x00\xc3\xe0\x00\x07\xb9\xf1\x05\x01\x6e\x82\x02\x82",2480,3876},
+              {"Hauppauge","\x2a\x03\xcc\xe0\x00\x07\xf4\xd0\x01\xc0\x70\xe0\x00\x07","\x2a\x00\xbe\xe0\x00\x07\xb9\xf1\x05\x01\x69\x82\x02\x82",2532,3886}};
+
+int main(int argc, char **argv){
+	FILE *file;
+	char buffer[1024];
+	char *fwmem=0;
+	int len;
+	long fleng=0;
+	int i;
+	int n=0;
+	int x;
+	int done=0;
+	int d=0;
+	int e=0;
+	if(argc!=2){
+		printf("./convert <filename>\n");
+		exit(1);
+	}
+	file=fopen(argv[1],"r");
+	fprintf(stderr,"Firmware extractor 0.1\n");
+	while((len=fread(buffer,1,1024,file))){
+		fleng+=len;
+		fwmem=realloc(fwmem,fleng);
+		memcpy(&fwmem[fleng-len],buffer,len);
+	}
+	fprintf(stderr,"Stored in memory: %ld\n",fleng);
+	for(n=0;n<ARRAY_SIZE(xc_firmware);n++){
+		for(i=0;i<fleng&&done!=2;i++){
+			if(xc_firmware[n].fwstart[d]==fwmem[i]&&done!=1){
+				if(d==13){
+					fprintf(stderr,"==== %s ====\n",xc_firmware[n].fwname);
+					printf("%d\n",xc_firmware[n].length1);
+					fprintf(stderr,"FW part 1 found!\n");
+					fprintf(stderr,"Length: %d bytes\n",xc_firmware[n].length1);
+					for(x=1;x<=xc_firmware[n].length1;x++){
+						fprintf(stderr,"%02x ",((unsigned char*)fwmem)[i-13+x]);
+						printf("%c",((unsigned char*)fwmem)[i-13+x]);
+						if(x%63==0){
+							fprintf(stderr,"\n");
+						}
+					}
+					fprintf(stderr,"\n");
+					done++;
+				}
+				d++;
+			} else {
+				d=0;
+			}
+			if(xc_firmware[n].fwstart2[e]==fwmem[i]){
+				if(e==13){
+					fprintf(stderr,"-------------------------------------------\n");
+					fprintf(stderr,"FW part 2 found!\n");
+					fprintf(stderr,"Length: %d bytes\n",xc_firmware[n].length2);
+					for(x=1;x<=xc_firmware[n].length2;x++){
+						printf("%c",((unsigned char*)fwmem)[i-13+x]);
+						fprintf(stderr,"%02x ",((unsigned char*)fwmem)[i-13+x]);
+						if(x%63==0){
+							fprintf(stderr,"\n");
+						}
+					}
+					done++;
+				}
+				e++;
+			} else {
+				e=0;
+			}
+		}
+	}
+	free(fwmem);
+	fclose(file);
+	exit(0);
+}
diff -urN linux-2.6.17-rc4.orig/drivers/media/video/saa7134/doc/test-oss linux-2.6.17-rc4/drivers/media/video/saa7134/doc/test-oss
--- linux-2.6.17-rc4.orig/drivers/media/video/saa7134/doc/test-oss	1970-01-01 09:00:00.000000000 +0900
+++ linux-2.6.17-rc4/drivers/media/video/saa7134/doc/test-oss	2006-05-23 22:15:22.000000000 +0900
@@ -0,0 +1,13 @@
+#!/bin/sh
+args="$*"
+
+v4l="/dev/video0"
+dsp="/dev/dsp1"
+mix="/dev/mixer1"
+out="/dev/dsp"
+
+set -ex
+v4lctl -c $v4l volume mute off
+v4lctl -c $v4l setchannel 1
+#aumix -I -d $mix &
+exec sox $args -t ossdsp $dsp -t ossdsp $out
diff -urN linux-2.6.17-rc4.orig/drivers/media/video/saa7134/doc/xc3028.c linux-2.6.17-rc4/drivers/media/video/saa7134/doc/xc3028.c
--- linux-2.6.17-rc4.orig/drivers/media/video/saa7134/doc/xc3028.c	1970-01-01 09:00:00.000000000 +0900
+++ linux-2.6.17-rc4/drivers/media/video/saa7134/doc/xc3028.c	2006-05-23 22:15:22.000000000 +0900
@@ -0,0 +1,236 @@
+/*
+
+   Xceive -  xc3028 tuner interface
+
+   Copyright (c) 2006 Markus Rechberger <mrechberger@gmail.com>
+
+
+TODO: - remove em28xx dependency
+      - add channel locking (requires some more reverse engineering)
+      - try to get the datasheet from Xceive :)
+
+   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/i2c.h>
+#include <linux/usb.h>
+#include "compat.h"
+#include <linux/videodev.h>
+#include "em28xx.h"
+#include <linux/firmware.h>
+#include <linux/delay.h>
+#include <media/tuner.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+#include "i2c-compat.h"
+#endif
+
+#define XC3028_DEFAULT_FIRMWARE "xceive_xc_3028.fw"
+
+int xceive_set_color(struct i2c_client *c);
+
+/* ---------------------------------------------------------------------- */
+
+int xc3028_probe(struct i2c_client *c)
+{
+	printk("xc3028: probe function unknown\n");
+	return -1;
+}
+
+static void xc3028_set_tv_freq(struct i2c_client *c, unsigned int freq){
+	/*
+	   the frequency is just shifted and there's a 1:1 relation for all frequencies
+	   E11 is Das Erste in Germany/Ulm all other channels match their frequency too
+	*/
+
+	unsigned char chanbuf[4];
+	freq<<=2;
+	chanbuf[0]=0;
+	chanbuf[1]=0;
+	chanbuf[2]=(freq&0xff00)>>8;
+	chanbuf[3]=freq&0x00ff;
+	i2c_master_send(c,"\xa0\x00\x00\x00",4);
+	i2c_master_send(c,"\x1e\x1f\x13\x87\x18\x02\x93\x91\x44\x86\x96\x8c",12);
+	i2c_master_send(c,"\x00\x8c",2);
+	i2c_master_send(c,"\x80\x02\x00\x00",4);
+	i2c_master_send(c,chanbuf,4);
+}
+
+int xc3028_init(struct i2c_client *c)
+{
+	struct tuner *t = i2c_get_clientdata(c);
+	struct em28xx *dev;
+	const struct firmware *fw = NULL;
+	size_t firmware_size;
+	int ret=-1;
+	int i=0;
+	int d=0;
+	int txtlen;
+	long fwoff;
+	u8 *firmware;
+	u8 linebuffer[100];
+	char *fwoffset;
+
+	/*
+	  request firmware from /lib/firmware, note that the file got extracted by the convert application I wrote and which is available
+	  on linuxtv.org / xc3028
+	*/
+
+	ret = request_firmware(&fw, XC3028_DEFAULT_FIRMWARE, &t->i2c.dev);
+	if (ret) {
+		printk("xc3028: no firmware uploaded please check %s\n",XC3028_DEFAULT_FIRMWARE);
+		return ret;
+	}
+	firmware = fw->data;
+	firmware_size = fw->size;
+
+	/* small firmware check, both firmwares I have are between 6 and 7k bytes */
+
+	if(fw->size>7000||fw->size<6000){
+		printk("xc3028: wrong firmware provided!\n");
+		release_firmware(fw);
+		return(ret);
+	}
+	for(i=0;i<8&&firmware[i]!='\n';i++);
+	txtlen=i;
+	firmware[i++]=0;
+	fwoff=simple_strtol(firmware,&fwoffset,10);
+	if(fwoff>fw->size){
+		printk("xc3028: firmware offset doesn't match!\n");
+		release_firmware(fw);
+		return(-1);
+	}
+
+	linebuffer[d++]=0x2a;
+	dev=c->adapter->algo_data;
+
+	/* 0x08 is a GPIO address of the em28xx has to get replaced with something generic here */
+
+	dev->em28xx_write_regs(dev, 0x08, "\x6d", 1);
+	dev->em28xx_write_regs(dev, 0x08, "\x7d", 1);
+
+	/*
+	   the firmware always starts with 0x2a + 0x40 bytes payload I use to add the offset of the first part
+	   as the first line into the firmware binary
+	*/
+	while(i!=fw->size){
+		linebuffer[d++]=firmware[i];
+		if((d%64==0&&d!=0)||i==fwoff+txtlen){
+			i2c_master_send(c,linebuffer,d);
+			if(i==(fwoff+txtlen)){
+				i2c_master_send(c,"\x02\x02",2);
+				i2c_master_send(c,"\x02\x03",2);
+				i2c_master_send(c,"\x00\x8c",2);
+				i2c_master_send(c,"\x00\x00\x00\x00",4);
+				/* at least 100 ms delay here, if less terratec FW won't work */
+				msleep(100);
+				/* another reset here */
+				dev->em28xx_write_regs(dev, 0x08, "\x6d", 1);
+				dev->em28xx_write_regs(dev, 0x08, "\x7d", 1);
+
+			}
+			linebuffer[0]=0x2a;
+			d=1;
+		}
+		i++;
+	}
+	printk("xc3024: Firmware uploaded\n");
+	release_firmware(fw);
+
+	/* MAGIC VALUES Hauppauge */
+	i2c_master_send(c,"\x13\x39",2);
+	i2c_master_send(c,"\x0c\x80\xf0\xf7\x3e\x75\xc1\x8a\xe4\x02\x00",11);
+	i2c_master_send(c,"\x05\x0f\xee\xaa\x5f\xea\x90",7);
+	i2c_master_send(c,"\x06\x00\x0a\x4d\x8c\xf2\xd8\xcf\x30\x79\x9f",11);
+	i2c_master_send(c,"\x0b\x0d\xa4\x6c",4);
+	i2c_master_send(c,"\x0a\x01\x67\x24\x40\x08\xc3\x20\x10\x64\x3c\xfa\xf7\xe1\x0c\x2c",0x10);
+	i2c_master_send(c,"\x09\x0b",0x2);
+	i2c_master_send(c,"\x10\x13",0x2);
+	i2c_master_send(c,"\x16\x12",0x2);
+	i2c_master_send(c,"\x1f\x02",0x2);
+	i2c_master_send(c,"\x21\x02",0x2);
+	i2c_master_send(c,"\x01\x02",0x2);
+	i2c_master_send(c,"\x2b\x10",0x2);
+	i2c_master_send(c,"\x02\x02",0x2);
+	i2c_master_send(c,"\x02\x03",0x2);
+	i2c_master_send(c,"\x00\x8c",0x2);
+
+#if 0
+	/* MAGIC Values Terratec - dvb init*/
+	i2c_master_send(c,"\x13\x39",0x02);
+	i2c_master_send(c,"\x0c\x80\xf0\xf7\x3e\x75\xc1\x8a\xe4\x02\x00",11);
+	i2c_master_send(c,"\x05\x0f\xee\xaa\x5f\xea\x90",7);
+	i2c_master_send(c,"\x06\x00\x0a\x4d\x8c\xf2\xd8\xcf\x30\x79\x9f",11);
+	i2c_master_send(c,"\x0b\x0d\xa4\x6c",4);
+	i2c_master_send(c,"\x0a\x01\x67\x24\x40\x08\xc3\x20\x10\x64\x3c\xfa\xf7\xe1\x0c\x2c",0x10);
+	i2c_master_send(c,"\x09\x0b",0x02);
+	i2c_master_send(c,"\x10\x13",0x02);
+	i2c_master_send(c,"\x16\x12",0x02);
+	i2c_master_send(c,"\x1f\x02",0x02);
+	i2c_master_send(c,"\x21\x02",0x02);
+	i2c_master_send(c,"\x01\x02",0x02);
+	i2c_master_send(c,"\x2b\x10",0x02);
+	i2c_master_send(c,"\x02\x02",0x02);
+	i2c_master_send(c,"\x02\x03",0x02);
+	i2c_master_send(c,"\x00\x8c",0x02);
+#endif
+#if 0
+	/* if set video will mostly be black/white  - if set_color is called instead the video will have color */
+	i2c_master_send(c,"\x80\x01\x00\x00",0x4);
+	i2c_master_send(c,"\x00\x5e\x00\x29",0x4);
+	i2c_master_send(c,"\x2b\x1a",0x2);
+#endif
+	xceive_set_color(c);
+	t->set_tv_freq    = xc3028_set_tv_freq;
+	return(0);
+}
+
+int xceive_set_color(struct i2c_client *c){
+	/* I found this codeblock within the sniffed logfile it got called as it is a several times after 0x00 0x04 tuner settings are made */
+	/* codeblock hauppauge/terratec - analog */
+	i2c_master_send(c,"\x80\x01\x00\x00",4);
+	i2c_master_send(c,"\x00\x5e\x00\x29",4);
+	i2c_master_send(c,"\x2b\x1a",2);
+	i2c_master_send(c,"\x2b\x1b",2);
+	i2c_master_send(c,"\x14\x01\x6c\x25\x82\x38\xa4\x49\xa9\x24\x96\x69",0x0c);
+	i2c_master_send(c,"\x13\x14\x08\x30\x10\x6c\x18\x12\x0d\x19\x32\xad",0x0c);
+	i2c_master_send(c,"\x0d\x01\x4b\x03\x97\x55\xc7\xd7\x00\xa1\xeb\x8f\x5c",0x0d);
+	i2c_master_send(c,"\x1a\x00\x00\x16\x8a\x40\x00\x00\x00\x20",0x0a);
+	i2c_master_send(c,"\x2d\x01",2);
+	i2c_master_send(c,"\x18\x01",2);
+	i2c_master_send(c,"\x1b\x01\xb6\x15\x16\xb1\xa6\xd2\xa9\x12\x41\x66",0x0c);
+	i2c_master_send(c,"\x1d\x00",2);
+	i2c_master_send(c,"\x0f\x00\x29\x56\xb0\x00\xb6",0x07);
+	i2c_master_send(c,"\x20\x00",0x02);
+	i2c_master_send(c,"\x1e\x10\x32\x00\x00\x02\xe4\x81\x00\x06\xa9\x04",0x0c);
+	i2c_master_send(c,"\x22\x29",0x02);
+	i2c_master_send(c,"\x23\x06",0x02);
+	i2c_master_send(c,"\x25\x00\x09\x90\x09\x06\x64\x02\x41",0x09);
+	i2c_master_send(c,"\x26\xcc",0x02);
+	i2c_master_send(c,"\x29\x40",0x02);
+	i2c_master_send(c,"\x21\x03",0x02);
+	i2c_master_send(c,"\x00\x8c",0x02);
+	i2c_master_send(c,"\x00\x00\x00\x00",0x04); /* just wonder no sleep here regarding the logs */
+	i2c_master_send(c,"\x00\x04",0x02);
+	return(0);
+}
+
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -urN linux-2.6.17-rc4.orig/drivers/media/video/saa7134/msp34x5.h linux-2.6.17-rc4/drivers/media/video/saa7134/msp34x5.h
--- linux-2.6.17-rc4.orig/drivers/media/video/saa7134/msp34x5.h	1970-01-01 09:00:00.000000000 +0900
+++ linux-2.6.17-rc4/drivers/media/video/saa7134/msp34x5.h	2006-05-23 22:15:22.000000000 +0900
@@ -0,0 +1,37 @@
+/*
+ * Header for MICRONAS MSP34x5
+ * Modify FROM msp3400 driver @ v2.4.20pre6 
+ * 2002-09-15 K.Ohta
+ */
+#ifndef MSP34x5_H
+#define MSP34x5_H
+
+/* ---------------------------------------------------------------------- */
+
+struct msp_dfpreg {
+    int reg;
+    int value;
+};
+
+#define MSP_SET_DFPREG     _IOW('m',15,struct msp_dfpreg)
+#define MSP_GET_DFPREG     _IOW('m',16,struct msp_dfpreg)
+#define MSP_AUDC_SET_INPUT -1 /* Temporally value 20030325 K.O */
+#define MSP_AUDC_SET_RADIO -2 /* Temporally value 20030325 K.O */
+
+#define MSP_FLAG_NORM      0
+#define MSP_FLAG_EIAJ      1
+#define MSP_FLAG_KOREA     2
+/* After 0.2.7+2.4.21pre6 */
+static inline int MAX(int a,int b)
+{
+   if(a>b) return a;
+   return b;
+}
+
+static inline int MIN(int a,int b)
+{
+   if(a<b) return a;
+   return b;
+}
+
+#endif /* MSP34x5_H */
diff -urN linux-2.6.17-rc4.orig/drivers/media/video/saa7134/saa7134-cards.c linux-2.6.17-rc4/drivers/media/video/saa7134/saa7134-cards.c
--- linux-2.6.17-rc4.orig/drivers/media/video/saa7134/saa7134-cards.c	2006-05-23 21:32:31.000000000 +0900
+++ linux-2.6.17-rc4/drivers/media/video/saa7134/saa7134-cards.c	2006-05-23 22:15:22.000000000 +0900
@@ -289,15 +289,16 @@
 		/* "K.Ohta" <alpha292@bremen.or.jp> */
 		.name           = "SKNet Monster TV",
 		.audio_clock    = 0x00187de7,
-		.tuner_type     = TUNER_PHILIPS_NTSC_M,
+		.tuner_type     = TUNER_PHILIPS_FM1236_MK3,
+	        /* .needs_tvaudio  = 1,*/ /* 20041005 K.Ohta */
 		.radio_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
-
+	        .needs_tvaudio = 1, /* 20060203 K.Ohta */
 		.inputs         = {{
 			.name = name_tv,
 			.vmux = 1,
-			.amux = TV,
+			.amux = LINE2,
 			.tv   = 1,
 		},{
 			.name = name_comp1,
@@ -1022,7 +1023,7 @@
 			.vmux = 8,
 			.amux = LINE2,
 		}},
-	},
+          },
 	[SAA7134_BOARD_MANLI_MTV002] = {
 		/* Ognjen Nastic <ognjen@logosoft.ba> */
 		.name           = "Manli MuchTV M-TV002/Behold TV 403 FM",
@@ -2842,6 +2843,88 @@
 			.gpio = 0x000000,	/* GPIO21=Low for FM radio antenna */
 		},
 	},
+        [SAA7134_BOARD_MONSTERTV2] = {
+                  /* K.Ohta : Thanx to http://pc.2ch.net/linux/1017186805/184 */
+                   .name           = "SKNet Monster TV2",
+                   .audio_clock    = 0x00187de7,
+                   .tuner_type     = TUNER_PHILIPS_FM1236_MK3,
+                   /* .needs_tvaudio  = 1,*/  /* 20040105 K.Ohta */
+	           .radio_type     = UNSET,
+	           .tuner_addr	   = ADDR_UNSET,
+		   .radio_addr	   = ADDR_UNSET,
+
+                   .inputs         = {{
+                           .name = name_tv,
+                           .vmux = 1,
+                           .amux = LINE2,
+                           .tv   = 1,
+                   },{
+                           .name = name_comp1,
+                           .vmux = 0,
+                           .amux = LINE1,
+                   },{
+                           .name = name_svideo,
+                           .vmux = 8,
+                           .amux = LINE1,
+                   }},
+                   .radio = {
+                           .name = name_radio,
+                           .amux = LINE2,
+                   },
+ 	   
+ 	},
+       	[SAA7134_BOARD_MONSTERTV3] = {
+                /* "K.Ohta" <alpha292@bremen.or.jp> Skelton...Pls.Test! 20050317*/
+                .name           = "SKNet Monster TV3/Lite",
+                .audio_clock    = 0x00187de7,
+                .tuner_type     = TUNER_PHILIPS_FQ1286, /* Philips FQ1286 (Testing) */
+     		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+                .inputs         = {{
+                        .name = name_tv,
+                        .vmux = 1,
+                        .amux = TV,
+                        .tv   = 1,
+                },{
+                        .name = name_comp1,
+                        .vmux = 0,
+                        .amux = LINE1,
+                },{
+                        .name = name_svideo,
+                        .vmux = 8,
+                        .amux = LINE1,
+                }},
+ 	},
+       	[SAA7134_BOARD_MONSTERTV_V] = {
+                /* "K.Ohta" <whatisthis@jcom.home.ne.jp> Skelton...Pls.Test! 20050730*/
+                .name           = "SKNet Monster TV V/VF",
+                .audio_clock    = 0x00187de7,
+                .tuner_type     = TUNER_XCEIVE_XC_x028_MOTV, /* XCEIVE's Silicon tuner (Testing) */
+     		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET, // Testing
+		.radio_addr	= ADDR_UNSET,
+                .inputs         = {{
+                        .name = name_tv,
+                        .vmux = 1,
+                        .amux = TV,
+                        .tv   = 1,
+                },{
+                        .name = name_comp1,
+                        .vmux = 2,
+                        .amux = LINE1,
+                },{
+                        .name = name_svideo,
+                        .vmux = 0,
+                        .amux = LINE1,
+                }},
+                   .radio = {
+                           .name = name_radio,
+                           .amux = TV,
+		},
+
+ 	},
+   
 };
 
 const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
@@ -3391,6 +3474,24 @@
 		.subdevice    = 0x3502,  /* whats the difference to 0x3306 ?*/
 		.driver_data  = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS,
 	},{
+  		.vendor       = PCI_VENDOR_ID_PHILIPS, /* Add 20040101 */
+  		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+                .subvendor    = 0x1131,
+                .subdevice    = 0x4f4d,
+ 		.driver_data  = SAA7134_BOARD_MONSTERTV2,
+        },{
+ 		.vendor       = PCI_VENDOR_ID_PHILIPS,
+  		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133, /* OKay? 20050716 K.Ohta*/
+                .subvendor    = 0x1131,
+                .subdevice    = 0x4ee9,
+  		.driver_data  = SAA7134_BOARD_MONSTERTV3,
+	},{
+ 		.vendor       = PCI_VENDOR_ID_PHILIPS,
+  		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133, /* OKay? 20050730 K.Ohta*/
+                .subvendor    = 0x1131,
+                .subdevice    = 0x4ef3,
+  		.driver_data  = SAA7134_BOARD_MONSTERTV_V,
+	},{
 		/* --- boards without eeprom + subsystem ID --- */
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
@@ -3429,7 +3530,7 @@
 		.subvendor    = PCI_ANY_ID,
 		.subdevice    = PCI_ANY_ID,
 		.driver_data  = SAA7134_BOARD_UNKNOWN,
-	},{
+        },{
 		/* --- end of list --- */
 	}
 };
@@ -3557,6 +3658,7 @@
 	return 0;
 }
 
+
 /* stuff which needs working i2c */
 int saa7134_board_init2(struct saa7134_dev *dev)
 {
@@ -3712,6 +3814,19 @@
 					       dev->name, i);
 		}
 		break;
+	case SAA7134_BOARD_MONSTERTV: // 20060127 K.Ohta
+	case SAA7134_BOARD_MONSTERTV2: // 20060127 K.Ohta
+	case SAA7134_BOARD_MONSTERTV3: // 20060127 K.Ohta
+	       break; //20060129
+	case SAA7134_BOARD_MONSTERTV_V: // 20060127 K.Ohta
+               {
+		  struct tuner_setup tun_setup;
+		  tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV;
+		  tun_setup.type = dev->tuner_type;
+		  tun_setup.addr = dev->tuner_addr;		  
+		  saa7134_i2c_call_clients (dev, TUNER_SET_TYPE_ADDR,&tun_setup);
+	       }
+	       break;
 	}
 	return 0;
 }
diff -urN linux-2.6.17-rc4.orig/drivers/media/video/saa7134/saa7134-core.c linux-2.6.17-rc4/drivers/media/video/saa7134/saa7134-core.c
--- linux-2.6.17-rc4.orig/drivers/media/video/saa7134/saa7134-core.c	2006-05-23 21:32:31.000000000 +0900
+++ linux-2.6.17-rc4/drivers/media/video/saa7134/saa7134-core.c	2006-05-23 22:15:22.000000000 +0900
@@ -934,7 +934,7 @@
 	/* initialize hardware #2 */
 	saa7134_board_init2(dev);
 	saa7134_hwinit2(dev);
-
+        /* printk("TUNER=%d\n",dev->tuner_type); // For DEBUG */
 	/* load i2c helpers */
 	if (TUNER_ABSENT != dev->tuner_type)
 		request_module("tuner");
@@ -944,10 +944,11 @@
 		request_module("saa6752hs");
 		request_module_depend("saa7134-empress",&need_empress);
 	}
-
+  	if (saa7134_boards[dev->board].needs_tvaudio) /* 20040105 K.Ohta */
+ 		request_module("tvaudio");
 	if (card_is_dvb(dev))
 		request_module_depend("saa7134-dvb",&need_dvb);
-
+ 
 
 	if (alsa)
 		request_module_depend("saa7134-alsa",&need_alsa);
diff -urN linux-2.6.17-rc4.orig/drivers/media/video/saa7134/saa7134-i2c.c linux-2.6.17-rc4/drivers/media/video/saa7134/saa7134-i2c.c
--- linux-2.6.17-rc4.orig/drivers/media/video/saa7134/saa7134-i2c.c	2006-03-20 14:53:29.000000000 +0900
+++ linux-2.6.17-rc4/drivers/media/video/saa7134/saa7134-i2c.c	2006-05-23 22:15:23.000000000 +0900
@@ -268,6 +268,7 @@
 			if (rc < 0)
 				 goto err;
 		}
+	        msleep(10); /* WAIT FOR PROCESSING MSP */
 		if (msgs[i].flags & I2C_M_RD) {
 			/* read bytes */
 			d2printk("read bytes\n");
@@ -333,7 +334,7 @@
 	int conf  = dev->tda9887_conf;
 	struct tuner_setup tun_setup;
 
-	d1printk( "%s i2c attach [addr=0x%x,client=%s]\n",
+	printk( "%s i2c attach [addr=0x%x,client=%s]\n",
 		client->driver->driver.name, client->addr, client->name);
 
 	/* Am I an i2c remote control? */
@@ -349,7 +350,7 @@
 			break;
 		}
 	}
-
+        /* printk("TUNER=%d\n",tuner); // Debug */
 	if (!client->driver->command)
 		return 0;
 
@@ -369,7 +370,7 @@
 
 		tun_setup.type = tuner;
 		tun_setup.addr = saa7134_boards[dev->board].tuner_addr;
-
+	        printk("TUNER=%d ADDR=%02x\n",tun_setup.type,tun_setup.addr); // Debug */
 		if ((tun_setup.addr == ADDR_UNSET)||(tun_setup.addr == client->addr)) {
 
 			tun_setup.mode_mask = T_ANALOG_TV;
@@ -444,7 +445,7 @@
 	unsigned char buf;
 	int i,rc;
 
-	for (i = 0; i < 128; i++) {
+	for (i = 0; i < 255; i++) {
 		c->addr = i;
 		rc = i2c_master_recv(c,&buf,0);
 		if (rc < 0)
diff -urN linux-2.6.17-rc4.orig/drivers/media/video/saa7134/saa7134-tvaudio.c linux-2.6.17-rc4/drivers/media/video/saa7134/saa7134-tvaudio.c
--- linux-2.6.17-rc4.orig/drivers/media/video/saa7134/saa7134-tvaudio.c	2006-05-23 21:32:31.000000000 +0900
+++ linux-2.6.17-rc4/drivers/media/video/saa7134/saa7134-tvaudio.c	2006-05-23 22:41:14.000000000 +0900
@@ -29,6 +29,7 @@
 #include <linux/delay.h>
 #include <linux/smp_lock.h>
 #include <asm/div64.h>
+#include <linux/videodev.h> /* ADD 20060514 K.Ohta */
 
 #include "saa7134-reg.h"
 #include "saa7134.h"
@@ -163,7 +164,14 @@
 		.carr1         = 4500,
 		.carr2         = 4724,
 		.mode          = TVAUDIO_FM_K_STEREO,
+	},{
+		.name          = "NTSC-EIAJ FM-stereo",
+		.std           = V4L2_STD_NTSC,
+		.carr1         = 4500,
+		.carr2         = 4500,
+		.mode          = TVAUDIO_FM_EIAJ_STEREO,
 	}
+
 };
 #define TVAUDIO (sizeof(tvaudio)/sizeof(struct saa7134_tvaudio))
 
@@ -272,7 +280,18 @@
 		saa_andorb(SAA7134_SIF_SAMPLE_FREQ,   0x03, 0x00);
 	else
 		saa_andorb(SAA7134_SIF_SAMPLE_FREQ,   0x03, 0x01);
-
+         /* TVAUDIO ENHANSMENT 20060514 K.Ohta */
+       if(saa7134_boards[dev->board].needs_tvaudio==1) {
+	        struct video_audio va;
+                saa7134_i2c_call_clients(dev,VIDIOCGAUDIO,&va);
+	        if(mute) {
+		   va.volume=0;
+		}
+	        va.balance=32768; /* CENTER */
+	        /* va.mode=0; *//* No Change */
+	        saa7134_i2c_call_clients(dev,VIDIOCSAUDIO,&va);
+	} 
+   
 	/* switch gpio-connected external audio mux */
 	if (0 == card(dev).gpiomask)
 		return;
@@ -349,6 +368,13 @@
 	case TVAUDIO_FM_SAT_STEREO:
 		/* not implemented (yet) */
 		break;
+	case TVAUDIO_FM_EIAJ_STEREO: /* Temporally */
+		saa_writeb(SAA7134_DEMODULATOR,               0x00);
+		saa_writeb(SAA7134_DCXO_IDENT_CTRL,           0x01);
+		saa_writeb(SAA7134_FM_DEEMPHASIS,             0x22);
+		saa_writeb(SAA7134_FM_DEMATRIX,               0x80);
+		saa_writeb(SAA7134_STEREO_DAC_OUTPUT_SELECT,  0xa0);
+		break;	   
 	}
 }
 
@@ -423,48 +449,65 @@
 {
 	__u32 idp, nicam, nicam_status;
 	int retval = -1;
-
-	switch (audio->mode) {
-	case TVAUDIO_FM_MONO:
-	case TVAUDIO_AM_MONO:
-		return V4L2_TUNER_SUB_MONO;
-	case TVAUDIO_FM_K_STEREO:
-	case TVAUDIO_FM_BG_STEREO:
-		idp = (saa_readb(SAA7134_IDENT_SIF) & 0xe0) >> 5;
-		dprintk("getstereo: fm/stereo: idp=0x%x\n",idp);
-		if (0x03 == (idp & 0x03))
-			retval = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
-		else if (0x05 == (idp & 0x05))
-			retval = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
-		else if (0x01 == (idp & 0x01))
-			retval = V4L2_TUNER_SUB_MONO;
-		break;
-	case TVAUDIO_FM_SAT_STEREO:
-		/* not implemented (yet) */
-		break;
-	case TVAUDIO_NICAM_FM:
-	case TVAUDIO_NICAM_AM:
-		nicam = saa_readb(SAA7134_AUDIO_STATUS);
-		dprintk("getstereo: nicam=0x%x\n",nicam);
-		if (nicam & 0x1) {
-			nicam_status = saa_readb(SAA7134_NICAM_STATUS);
-			dprintk("getstereo: nicam_status=0x%x\n", nicam_status);
-
-			switch (nicam_status & 0x03) {
-			    case 0x01:
-				retval = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
-				break;
-			    case 0x02:
-				retval = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
-				break;
-			    default:
-				retval = V4L2_TUNER_SUB_MONO;
-			}
-		} else {
-			/* No nicam detected */
-		}
-		break;
-	}
+        if(saa7134_boards[dev->board].needs_tvaudio==1) {
+ 	        struct v4l2_tuner v;
+ 	        int amode;
+                saa7134_i2c_call_clients(dev,VIDIOC_G_TUNER,&v);
+ 	        amode=v.audmode; /* Fix 20060522 */
+ 	        retval = 0;
+ 	        if(amode == V4L2_TUNER_SUB_MONO) 
+ 	                  retval |= V4L2_TUNER_SUB_MONO;
+ 	        if(amode == V4L2_TUNER_SUB_STEREO) 
+ 	                  retval |= V4L2_TUNER_SUB_STEREO;
+ 	        if(amode == V4L2_TUNER_SUB_LANG1) 
+ 	                  retval |= V4L2_TUNER_SUB_LANG1;
+ 	        if(amode == V4L2_TUNER_SUB_LANG2) 
+ 	                  retval |= V4L2_TUNER_SUB_LANG2;
+ 	} else { /* END MODIFY */ 
+               switch (audio->mode) {
+		    case TVAUDIO_FM_MONO:
+		    case TVAUDIO_AM_MONO:
+		         return V4L2_TUNER_SUB_MONO;
+		    case TVAUDIO_FM_K_STEREO:
+		    case TVAUDIO_FM_BG_STEREO:
+		         idp = (saa_readb(SAA7134_IDENT_SIF) & 0xe0) >> 5;
+		         dprintk("getstereo: fm/stereo: idp=0x%x\n",idp);
+		         if (0x03 == (idp & 0x03))
+		             retval = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+		         else if (0x05 == (idp & 0x05))
+		             retval = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
+		         else if (0x01 == (idp & 0x01))
+		             retval = V4L2_TUNER_SUB_MONO;
+		         break;
+		     case TVAUDIO_FM_SAT_STEREO:
+		         /* not implemented (yet) */
+		         break;
+		     case TVAUDIO_NICAM_FM:
+		     case TVAUDIO_NICAM_AM:
+		         nicam = saa_readb(SAA7134_AUDIO_STATUS);
+		         dprintk("getstereo: nicam=0x%x\n",nicam);
+		         if (nicam & 0x1) {
+		             nicam_status = saa_readb(SAA7134_NICAM_STATUS);
+		             dprintk("getstereo: nicam_status=0x%x\n", nicam_status);
+		     
+		              switch (nicam_status & 0x03) {
+		                    case 0x01:
+			                 retval = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+			                 break;
+		                    case 0x02:
+			                 retval = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
+			                 break;
+		                    default:
+			                 retval = V4L2_TUNER_SUB_MONO;
+		              }
+			 } else {
+			    /* No nicam detected */
+			 }
+		         break;
+		default:
+		         break;
+	       }
+	}  
 	if (retval != -1)
 		dprintk("found audio subchannels:%s%s%s%s\n",
 			(retval & V4L2_TUNER_SUB_MONO)   ? " mono"   : "",
@@ -491,8 +534,21 @@
 		[ V4L2_TUNER_MODE_LANG2  ] = 0x01,  /* ch2  */
 		[ V4L2_TUNER_MODE_LANG1_LANG2 ] = 0x80,  /* auto */
 	};
-	u32 reg;
-
+  	static u32 tvaudio_msp[] = {
+		[ V4L2_TUNER_MODE_MONO   ] = V4L2_TUNER_SUB_MONO,  /* ch1  */
+		[ V4L2_TUNER_MODE_STEREO ] = V4L2_TUNER_SUB_STEREO,  /* auto */
+		[ V4L2_TUNER_MODE_LANG1  ] = V4L2_TUNER_SUB_LANG1,  /* ch1  */
+		[ V4L2_TUNER_MODE_LANG2  ] = V4L2_TUNER_SUB_LANG2,  /* ch2  */
+	};
+        u32 reg;
+   
+        if(saa7134_boards[dev->board].needs_tvaudio==1) {
+	        struct v4l2_tuner v;
+	        saa7134_i2c_call_clients(dev,VIDIOC_G_TUNER,&v);
+	        v.audmode=tvaudio_msp[ mode % ARRAY_SIZE(tvaudio_msp) ];
+                saa7134_i2c_call_clients(dev,VIDIOC_S_TUNER,&v);
+	        return 0; /* Escape unsetting saa7134 :-) */
+	}
 	switch (audio->mode) {
 	case TVAUDIO_FM_MONO:
 	case TVAUDIO_AM_MONO:
@@ -510,6 +566,9 @@
 	case TVAUDIO_FM_SAT_STEREO:
 		/* Not implemented */
 		break;
+	 case TVAUDIO_FM_EIAJ_STEREO: /* 20040105 K.Ohta */
+	   /* Not Implemented Yet. */
+	   break;
 	}
 	return 0;
 }
@@ -970,6 +1029,18 @@
 		saa_writeb(SAA7134_NICAM_LEVEL_ADJUST, level & 0x1f);
 		break;
 	}
+
+        /* TVAUDIO ENHANSMENT 20060514 K.Ohta */
+        if(saa7134_boards[dev->board].needs_tvaudio==1) {
+	        struct video_audio va;
+	   	//saa7134_i2c_call_clients(dev,VIDIOCGAUDIO,&va);
+	        va.volume=65535;
+	        //va.volume=((level+15)*0x7400)/30;
+	        va.balance=32768; /* CENTER */
+	        va.mode=0; /* No Change */
+	        saa7134_i2c_call_clients(dev,VIDIOCSAUDIO,&va);
+	}   
+
 }
 
 int saa7134_tvaudio_getstereo(struct saa7134_dev *dev)
diff -urN linux-2.6.17-rc4.orig/drivers/media/video/saa7134/saa7134-video.c linux-2.6.17-rc4/drivers/media/video/saa7134/saa7134-video.c
--- linux-2.6.17-rc4.orig/drivers/media/video/saa7134/saa7134-video.c	2006-05-23 21:32:31.000000000 +0900
+++ linux-2.6.17-rc4/drivers/media/video/saa7134/saa7134-video.c	2006-05-23 22:15:24.000000000 +0900
@@ -1859,7 +1859,7 @@
 		dev->crop_current = crop->c;
 		return 0;
 	}
-
+	
 	/* --- tuner ioctls ------------------------------------------ */
 	case VIDIOC_G_TUNER:
 	{
@@ -1939,17 +1939,50 @@
 	case VIDIOC_G_CTRL:
 	case VIDIOC_S_CTRL:
 		return saa7134_common_ioctl(dev, cmd, arg);
+ 	/* Add VIDIOC_S_MODULATOR  20040118 K.O */ 
+ 	case VIDIOC_S_MODULATOR:
+ 	{
+ 	        /* WRAPPER...SHOULD BE REPLACE VIDIOCSMODULATOR */
+ 	        struct v4l2_modulator *a=arg;
+ 	        struct video_audio t;
+ 	        memset(&t,0,sizeof(t));
+ 	        strcpy(t.name,"modulator");
+ 	        t.mode = (__u16)((a->txsubchans)%65536); /* right cast?*/
+ 	        saa7134_i2c_call_clients(dev,VIDIOCSAUDIO,&t);
+ 	        return 0;
+ 	}
+ 	/* Add VIDIOC_S_MODULATOR  20040118 K.O */ 
+ 	case VIDIOC_G_MODULATOR:
+ 	{
+ 	        /* WRAPPER */
+ 	        struct v4l2_modulator *a=arg;
+ 	        struct video_audio t;
+ 	        saa7134_i2c_call_clients(dev,VIDIOCGAUDIO,&t);
+ 		memset(a,0,sizeof(*a));
+ 		strcpy(a->name,"audio");
+ 	        a->txsubchans=(__u32)(t.mode);
+ 	        return 0;
+  
+ 	}
 
 	case VIDIOC_G_AUDIO:
 	{
 		struct v4l2_audio *a = arg;
-
+ 	        struct video_audio t;
+ 	        saa7134_i2c_call_clients(dev,VIDIOCGAUDIO,&t);
 		memset(a,0,sizeof(*a));
 		strcpy(a->name,"audio");
+ 	        /* SET MPX MODE WAS MOVED TO MODULATOR */
 		return 0;
 	}
 	case VIDIOC_S_AUDIO:
-		return 0;
+ 	{
+ 	       struct video_audio t;
+ 	       memcpy(&t,arg,sizeof(t));
+                /* SET MPX MODE WAS MOVED TO MODULATOR */
+ 	       saa7134_i2c_call_clients(dev,VIDIOCSAUDIO,&t);
+ 	       return 0;
+ 	}
 	case VIDIOC_G_PARM:
 	{
 		struct v4l2_captureparm *parm = arg;
diff -urN linux-2.6.17-rc4.orig/drivers/media/video/saa7134/saa7134.h linux-2.6.17-rc4/drivers/media/video/saa7134/saa7134.h
--- linux-2.6.17-rc4.orig/drivers/media/video/saa7134/saa7134.h	2006-05-23 21:32:31.000000000 +0900
+++ linux-2.6.17-rc4/drivers/media/video/saa7134/saa7134.h	2006-05-23 22:31:16.000000000 +0900
@@ -60,7 +60,8 @@
 	TVAUDIO_FM_K_STEREO   = 4,
 	TVAUDIO_NICAM_AM      = 5,
 	TVAUDIO_NICAM_FM      = 6,
-	TVAUDIO_AM_MONO	      = 7
+	TVAUDIO_AM_MONO	      = 7,
+        TVAUDIO_FM_EIAJ_STEREO= 8, /* Add 20040101 K.Ohta */
 };
 
 enum saa7134_audio_in {
@@ -221,6 +222,11 @@
 #define SAA7134_BOARD_AVERMEDIA_A169_B1 92
 #define SAA7134_BOARD_MD7134_BRIDGE_2     93
 #define SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS 94
+/* MONSTER TV Series: Patched by K.Ohta <whatisthis@jcom.home.ne.jp */
+#define SAA7134_BOARD_MONSTERTV2  95 /* Add: 2004.01.01 Pls.Test! */
+#define SAA7134_BOARD_MONSTERTV3  96 /* Add: 2004.11.10 Pls.Test! */
+#define SAA7134_BOARD_MONSTERTV_V 97 /* Add: 2005.07.30 Pls.Test! */
+
 
 #define SAA7134_MAXBOARDS 8
 #define SAA7134_INPUT_MAX 8
@@ -268,9 +274,9 @@
 	unsigned int		radio_type;
 	unsigned char		tuner_addr;
 	unsigned char		radio_addr;
-
+        unsigned int            needs_tvaudio;
 	unsigned int            tda9887_conf;
-
+   
 	/* peripheral I/O */
 	enum saa7134_video_out  video_out;
 	enum saa7134_mpeg_type  mpeg;
diff -urN linux-2.6.17-rc4.orig/drivers/media/video/tuner-core.c linux-2.6.17-rc4/drivers/media/video/tuner-core.c
--- linux-2.6.17-rc4.orig/drivers/media/video/tuner-core.c	2006-05-23 21:32:31.000000000 +0900
+++ linux-2.6.17-rc4/drivers/media/video/tuner-core.c	2006-05-23 22:15:24.000000000 +0900
@@ -18,6 +18,7 @@
 #include <linux/types.h>
 #include <linux/videodev.h>
 #include <linux/init.h>
+#include "saa7134/saa7134.h"
 
 #include <media/tuner.h>
 #include <media/v4l2-common.h>
@@ -72,6 +73,9 @@
 
 /* ---------------------------------------------------------------------- */
 
+extern void xc3028_meta_set_tv_freq(struct i2c_client *c,unsigned int freq);
+extern int xc3028_motv_init(struct i2c_client *c,struct  saa7134_dev *dev);
+
 /* Set tuner frequency,  freq in Units of 62.5kHz = 1/16MHz */
 static void set_tv_freq(struct i2c_client *c, unsigned int freq)
 {
@@ -96,7 +100,11 @@
 		else
 			freq = tv_range[1] * 16;
 	}
-	t->set_tv_freq(c, freq);
+	if(t->type==TUNER_XCEIVE_XC_x028_MOTV) { // 20060127 K.Ohta
+		xc3028_meta_set_tv_freq(c,freq); 
+	} else {
+		t->set_tv_freq(c, freq);
+	}
 }
 
 static void set_radio_freq(struct i2c_client *c, unsigned int freq)
@@ -122,8 +130,11 @@
 		else
 			freq = radio_range[1] * 16000;
 	}
-
-	t->set_radio_freq(c, freq);
+	if(t->type==TUNER_XCEIVE_XC_x028_MOTV) { // 20060127 K.Ohta
+		xc3028_meta_set_tv_freq(c,freq); 
+	} else {
+		t->set_radio_freq(c, freq);
+	}
 }
 
 static void set_freq(struct i2c_client *c, unsigned long freq)
@@ -147,6 +158,7 @@
 	}
 }
 
+
 static void set_type(struct i2c_client *c, unsigned int type,
 		     unsigned int new_mode_mask)
 {
@@ -215,6 +227,11 @@
 		i2c_master_send(c,buffer,4);
 		default_tuner_init(c);
 		break;
+ 	case TUNER_XCEIVE_XC_x028_MOTV: /* 20060127 K.Ohta */
+ 		/* WIP! NEED GPIO in SAA7133 TO RESET Tuner?*/
+ 	        xc3028_motv_init(c, &(t->i2c.dev));
+ 	        printk("WARNING: XCEIVE's TUNER DRIVER for MonstetTV V is non imcomplete\n");
+ 		break;
 	default:
 		default_tuner_init(c);
 		break;
@@ -246,6 +263,9 @@
 		tun_setup->addr == c->addr)) {
 			set_type(c, tun_setup->type, tun_setup->mode_mask);
 	}
+   
+	   
+	
 }
 
 static inline int check_mode(struct tuner *t, char *cmd)
@@ -640,9 +660,8 @@
 				return 0;
 			if (check_v4l2(t) == EINVAL)
 				return 0;
-
-			set_freq(client, *v);
-			return 0;
+		       set_freq(client, *v);
+		       return 0;
 		}
 	case VIDIOCGTUNER:
 		{
diff -urN linux-2.6.17-rc4.orig/drivers/media/video/tuner-types.c linux-2.6.17-rc4/drivers/media/video/tuner-types.c
--- linux-2.6.17-rc4.orig/drivers/media/video/tuner-types.c	2006-05-23 21:32:31.000000000 +0900
+++ linux-2.6.17-rc4/drivers/media/video/tuner-types.c	2006-05-23 22:23:15.000000000 +0900
@@ -1024,6 +1024,24 @@
 	},
 };
 
+/* ------------ TUNER_SAMSUNG_TCPN_2121P30A - Samsung NTSC ------------ */
+/*
+ * ADD for MonsterTV V 20060203
+ */
+static struct tuner_range tuner_xceive_xcx028_motv_ntsc_ranges[] = {
+	{ 16 * 175.75 /*MHz*/, 0x01, },
+	{ 16 * 410.25 /*MHz*/, 0x02, },
+	{ 16 * 999.99        , 0x08, },
+};
+
+static struct tuner_params tuner_xceive_xcx028_motv_params[] = {
+	{
+		.type   = TUNER_PARAM_TYPE_NTSC,
+		.ranges = tuner_xceive_xcx028_motv_ntsc_ranges,
+		.count  = ARRAY_SIZE(tuner_xceive_xcx028_motv_ntsc_ranges),
+	},
+};
+
 /* --------------------------------------------------------------------- */
 
 struct tunertype tuners[] = {
@@ -1400,6 +1418,10 @@
 		.params = tuner_thomson_fe6600_params,
 		.count  = ARRAY_SIZE(tuner_thomson_fe6600_params),
 	},
+        [TUNER_XCEIVE_XC_x028_MOTV] = { /* XCWEIVE XC?028 for MonsterTV V (OOPS!) */
+	        .name   = "Xeive XC?028 Silicon tuner for SKNet Monster TV VSeries",
+	        .params = tuner_xceive_xcx028_motv_params,
+	},
 };
 
 unsigned const int tuner_count = ARRAY_SIZE(tuners);
diff -urN linux-2.6.17-rc4.orig/drivers/media/video/tvaudio.c linux-2.6.17-rc4/drivers/media/video/tvaudio.c
--- linux-2.6.17-rc4.orig/drivers/media/video/tvaudio.c	2006-05-23 21:32:31.000000000 +0900
+++ linux-2.6.17-rc4/drivers/media/video/tvaudio.c	2006-05-23 23:24:15.000000000 +0900
@@ -7,6 +7,8 @@
  *   Steve VanDeBogart (vandebo@uclink.berkeley.edu)
  *   Greg Alexander (galexand@acm.org)
  *
+ * Add: MSP34x5 20031025 K.Ohta (alpha292@bremen.or.jp)
+ * 
  * This code is placed under the terms of the GNU General Public License
  *
  * OPTIONS:
@@ -35,6 +37,9 @@
 
 #include <media/i2c-addr.h>
 
+#include "msp34x5.h"
+
+
 /* ---------------------------------------------------------------------- */
 /* insmod args                                                            */
 
@@ -42,7 +47,7 @@
 module_param(debug, int, 0644);
 
 MODULE_DESCRIPTION("device driver for various i2c TV sound decoder / audiomux chips");
-MODULE_AUTHOR("Eric Sandeen, Steve VanDeBogart, Greg Alexander, Gerd Knorr");
+MODULE_AUTHOR("Eric Sandeen, Steve VanDeBogart, Greg Alexander, Gerd Knorr, Ohta Kyuma");
 MODULE_LICENSE("GPL");
 
 #define UNSET    (-1U)
@@ -146,6 +151,7 @@
 	I2C_ADDR_TDA985x_H >> 1,
 	I2C_ADDR_TDA9874   >> 1,
 	I2C_ADDR_PIC16C54  >> 1,
+        I2C_ADDR_MSP3445   >> 1, /* Okay? */
 	I2C_CLIENT_END };
 I2C_CLIENT_INSMOD;
 
@@ -185,6 +191,7 @@
 	return 0;
 }
 
+
 static int chip_write_masked(struct CHIPSTATE *chip, int subaddr, int val, int mask)
 {
 	if (mask != 0) {
@@ -1236,6 +1243,363 @@
 	return ((rc & 0x1f) == 0x1f) ? 1 : 0;
 }
 
+/*-----------------------------------------------------------------------
+ * MSP3445G
+ * ----------------------------------------------------------------------*/
+/* MODULE OPTIONS */
+static int msp3445  = 1;
+module_param(msp3445, int, 0444);
+
+
+/* EIA-J ONLY Now :-( */
+#define MSP3445_DEM 0x10
+#define MSP3445_DFP 0x12
+#define I2C_MSP_CONTROL 0x00
+#define I2C_MSP_DEM MSP3445_DEM
+#define I2C_MSP_DSP MSP3445_DFP
+
+
+
+/* MSP3445 MPX TYPE */
+#define MSP3445_EIAJ 1
+
+static int msp_reset(struct i2c_client *client)
+{
+	/* reset and read revision code */
+	static u8 reset_off[3] = { I2C_MSP_CONTROL, 0x80, 0x00 };
+	static u8 reset_on[3]  = { I2C_MSP_CONTROL, 0x00, 0x00 };
+	static u8 write[3]     = { I2C_MSP_DSP + 1, 0x00, 0x1e };
+        static u8 reset_chk[3] = { I2C_MSP_CONTROL, 0x00,  0x00};
+	
+	u8 read[2];
+   
+	struct i2c_msg reset[2] = {
+		{ client->addr, I2C_M_IGNORE_NAK, 3, reset_off },
+		{ client->addr, I2C_M_IGNORE_NAK, 3, reset_on  },
+	};
+	struct i2c_msg test[2] = {
+		{ client->addr, 0,        3, write },
+		{ client->addr, I2C_M_RD, 2, read  },
+	};
+
+	v4l_dbg(3, debug, client, "msp_reset\n");
+	if (i2c_transfer(client->adapter, &reset[0], 1) != 1 ||
+	    i2c_transfer(client->adapter, &reset[1], 1) != 1 ||
+	    i2c_transfer(client->adapter, test, 2) != 2) {
+	        v4l_err(client, "chip reset failed\n");
+		return -1;
+	}
+	return 0;
+}
+
+static int msp3445_reset(struct CHIPSTATE *chip)
+{
+   return msp_reset(&chip->c);
+}
+
+static int msp3445_read(struct CHIPSTATE *chip,int subaddr,int reg,unsigned char *read)
+{
+        int err;
+        unsigned char write[3];
+        struct i2c_msg msgs[2] = {
+	     { chip->c.addr,0,3,write},
+	     { chip->c.addr,I2C_M_RD ,2,read},
+        };
+        /* send CMD */
+        write[0]=subaddr+1 ;
+        write[1]=reg >> 8;
+        write[2]=reg & 0xff;
+
+	for (err = 0; err < 3; err++) {
+		if (i2c_transfer(chip->c.adapter, msgs, 2) == 2)
+			break;
+		v4l_warn(&chip->c, "I/O error #%d (read 0x%02x/0x%02x)\n", err,
+		       subaddr+1 , reg);
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout(msecs_to_jiffies(10));
+	}
+	if (err == 3) {
+		v4l_warn(&chip->c, "giving up, resetting chip. Sound will go off, sorry folks :-|\n");
+		msp3445_reset(chip);
+		return -1;
+	}
+        v4l_dbg(3, debug, &chip->c,"%s: read: subadr:reg %04x:%04x=0x%02x%02x\n",
+		chip->c.name,subaddr+1,reg,read[0],read[1]);
+        
+
+        return 2;
+}
+
+static int msp3445_write(struct CHIPSTATE *chip,int subaddr,int reg,int cmd)
+{
+   	int err;
+	u8 buffer[5];
+
+	buffer[0] = subaddr;
+	buffer[1] = reg >> 8;
+	buffer[2] = reg &  0xff;
+	buffer[3] = cmd  >> 8;
+	buffer[4] = cmd  &  0xff;
+
+	v4l_dbg(3, debug, &chip->c, "msp_write(0x%x, 0x%x, 0x%x)\n", subaddr, reg, cmd);
+	for (err = 0; err < 3; err++) {
+		if (i2c_master_send(&chip->c, buffer, 5) == 5)
+			break;
+		v4l_warn(&chip->c, "I/O error #%d (write 0x%02x/0x%02x)\n", err,
+		       subaddr, reg);
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout(msecs_to_jiffies(10));
+	}
+	if (err == 3) {
+		v4l_warn(&chip->c, "giving up, resetting chip. Sound will go off, sorry folks :-|\n");
+		msp3445_reset(chip);
+		return -1;
+	}
+ 
+  return 5;
+}
+
+/* Set Volume : right,left <- 65536=0dB */
+static void msp3445_setvolume(struct CHIPSTATE *chip,int left,int right)
+{
+        int vol,val,balance;
+        balance = 0;
+        vol     = (left > right) ? left : right;
+	val     = ((vol * 0x73) / 65536) << 8;
+        if (vol > 0) {
+		balance = ((right-left) * 127) / vol;
+	}
+         
+   	msp3445_write(chip,MSP3445_DFP, 0x0000, val); /* loudspeaker */
+	msp3445_write(chip,MSP3445_DFP, 0x0006, val); /* headphones  */
+	/* scart - on/off only */
+	msp3445_write(chip,MSP3445_DFP, 0x0007, val ? 0x4001 : 1);
+	msp3445_write(chip,MSP3445_DFP, 0x0001, balance << 8);
+}
+
+static void msp3445_setmode(struct CHIPSTATE *chip,int mode)
+{
+	int src,matrix;
+        switch(msp3445) {
+        /* EIA-J Only :-( */
+	 case MSP3445_EIAJ:
+	   matrix=0x3002;
+	   break;
+	 default:
+	   matrix=0x3002;
+	   break;
+	}
+        /* End EIA-J */
+        msp3445_write(chip,MSP3445_DFP,0x000e,matrix);
+        switch(mode) {
+	 case VIDEO_SOUND_STEREO:
+	   src=0x0120;
+	   break;
+	 case VIDEO_SOUND_LANG1:
+	   src=0x0300;
+	   break;
+	 case VIDEO_SOUND_LANG2:
+	   src=0x0410;
+	   break;
+	 case VIDEO_SOUND_MONO:
+	   src=0x0030;
+	   break;
+	 default:
+	   src=0x0030;
+	   break;
+	}
+        v4l_dbg(1, debug, &chip->c,
+	  "tvaudio: setmode : chip->mode = 0x%04x\n",chip->mode);
+        v4l_dbg(1, debug, &chip->c,
+	   "tvaudio: setstereo final source/matrix = 0x%04x\n", src);
+        msp3445_write(chip,MSP3445_DFP, 0x0008,src);
+        /* msp3445_write(chip,MSP3445_DFP, 0x0009,src); */
+        msp3445_write(chip,MSP3445_DFP, 0x000c,src);
+        msp3445_write(chip,MSP3445_DFP, 0x000a,src);
+        msp3445_write(chip,MSP3445_DFP, 0x000b,src);
+        chip->prevmode = mode;
+}
+#define MSP_CARRIER(freq) ((int)((float)(freq/18.432)*(1<<24)))
+
+	        
+static void msp3445_setcarrier(struct CHIPSTATE *chip, int cdo1, int cdo2)
+{
+#if 0
+        msp3445_write(chip,MSP3445_DEM, 0x0093, cdo1 & 0xfff);
+	msp3445_write(chip,MSP3445_DEM, 0x009b, cdo1 >> 12);
+	msp3445_write(chip,MSP3445_DEM, 0x00a3, cdo2 & 0xfff);
+	msp3445_write(chip,MSP3445_DEM, 0x00ab, cdo2 >> 12);
+	msp3445_write(chip,MSP3445_DEM, 0x0056, 0); /*LOAD_REG_1/2*/
+#endif
+}
+
+
+#define SCART_MASK    0
+#define SCART_IN1     1
+#define SCART_IN2     2
+#define SCART_IN1_DA  3
+#define SCART_IN2_DA  4
+#define SCART_IN3     5
+#define SCART_IN4     6
+#define SCART_MONO    7
+#define SCART_MUTE    8
+
+static int msp3445_scarts[3][9] = {
+  /* MASK    IN1     IN2     IN1_DA  IN2_DA  IN3     IN4     MONO    MUTE   */
+  {  0x0320, 0x0000, 0x0200, -1,     -1,     0x0300, 0x0020, 0x0100, 0x0320 },
+  {  0x0c40, 0x0440, 0x0400, 0x0c00, 0x0040, 0x0000, 0x0840, 0x0800, 0x0c40 },
+  {  0x3080, 0x1000, 0x1080, 0x0000, 0x0080, 0x2080, 0x3080, 0x2000, 0x3000 },
+};
+
+static void msp3445_setscart(struct CHIPSTATE *chip, int in, int out)
+{
+        int acb=0;
+	if (-1 == msp3445_scarts[out][in])
+		return;
+	acb |=  msp3445_scarts[out][in];
+	msp3445_write(chip,MSP3445_DFP, 0x0013, acb);
+}
+
+
+static void msp3445_setinput(struct CHIPSTATE *chip,int in)
+{
+   /* TUNER ONLY...Temporally :) */
+   switch(in){
+    case TVAUDIO_INPUT_TUNER:
+      /* Monster TV */
+      msp3445_setscart(chip,SCART_IN1_DA,1);
+      msp3445_write(chip,MSP3445_DFP,0x000d,0x1900);
+      /* End Monster TV */
+      break;
+    default:
+      msp3445_setscart(chip,SCART_IN1_DA,1);
+      msp3445_write(chip,MSP3445_DFP,0x000d,0x1900);
+      break;
+   }
+}
+
+static int msp3445_getmode(struct CHIPSTATE *chip)
+{
+	unsigned int val;
+        int mode;
+        unsigned char read[2];
+   
+        mode=VIDEO_SOUND_MONO;
+   
+        if(msp3445_read(chip,MSP3445_DEM,0x0200,read)<=0) return -1;
+        val=((unsigned int)read[0])<<8+(unsigned int)read[1];
+        /* EIA-J */
+        if((val & 0x0040)!=0) {
+	     mode = VIDEO_SOUND_STEREO;
+	   /* Dirty? */
+	   } else if((val & 0x0100)!=0){
+	      if(chip->mode == VIDEO_SOUND_LANG2) {
+		 mode = VIDEO_SOUND_LANG2;
+	      } else if(chip->mode == VIDEO_SOUND_LANG1) {
+		 mode = VIDEO_SOUND_LANG1;
+	      }
+	   }
+	v4l_dbg(1, debug, &chip->c,
+		"tvaudio: getstereo mode = 0x%04x val = 0x%04x\n", mode,val);
+        return mode;
+}
+
+static int msp3445_detect(struct CHIPSTATE *chip)
+{
+   unsigned char rev1[2],rev2[2];
+   char name[32];
+   if(msp3445_read(chip,MSP3445_DFP,0x1e,rev1)<0) return 0;
+   if(msp3445_read(chip,MSP3445_DFP,0x1f,rev2)<0) return 0;
+   sprintf(name,"MSP34%02d%c-%c%d",
+	   rev2[0], (rev1[1]&0x0f)+'@' , rev1[0]+'@', rev2[1] & 0x0f);   
+   printk("msp34xx: detected as %s\n",name);
+   return 1;
+}
+
+static int msp3445_initialize(struct CHIPSTATE *chip)
+{
+   int std,demvar,matrix;
+   int cf1,cf2 ; /* CARRIER */
+   unsigned char read[2];
+   int right,left;
+   msp3445_reset(chip);
+   msleep(100); /* 20060523 */
+   /* EIA-J */
+   switch(msp3445) {
+    case MSP3445_EIAJ:
+      std = 0x0030;
+      demvar = 0x4003;
+      matrix = 0x3002;
+      cf1 = MSP_CARRIER(4.5);
+      cf2 = MSP_CARRIER(4.5);
+      break;
+    default:
+      std = 0x0030;
+      demvar = 0x4003;
+      matrix = 0x3002;
+      cf1 = MSP_CARRIER(4.5);
+      cf2 = MSP_CARRIER(4.5);
+      break;
+   }
+      /* End EIA-J */
+   /* Genelic */
+   right=65536;
+   left=65536;
+   /* End Genelic */
+   
+   msp3445_write(chip,MSP3445_DEM,0x0020,std);    /* WRITE STD */
+   msp3445_read(chip,MSP3445_DEM,0x200,read);     /* Read status */
+   msp3445_write(chip,MSP3445_DEM,0x0030,demvar); /* WRITE DEM */
+   msp3445_write(chip,MSP3445_DFP,0x000e,matrix); /* Write MATRIX */
+   msp3445_setcarrier(chip, cf1, cf2);
+   msp3445_setinput(chip,TVAUDIO_INPUT_TUNER);
+   msp3445_setmode(chip,VIDEO_SOUND_STEREO);
+   msp3445_setvolume(chip,right,left);
+   msp3445_detect(chip);
+   
+   chip->prevmode = msp3445_getmode(chip); /* Get First Mode */
+   chip->mode = chip->prevmode; /* Get First Mode */
+   return 0;
+}
+
+
+
+static int msp3445_checkit(struct CHIPSTATE *chip)
+{
+#if 0
+   unsigned char rev1[2],rev2[2];
+   char name[32];
+   msp3445_reset(chip); /* 20060523 K.O */
+   msleep(100);
+   if(msp3445_read(chip,MSP3445_DFP,0x1e,rev1)<0) return 0;
+   if(msp3445_read(chip,MSP3445_DFP,0x1f,rev2)<0) return 0;
+   sprintf(name,"MSP34%02d%c-%c%d",
+	   rev2[0], (rev1[1]&0x0f)+'@' , rev1[0]+'@', rev2[1] & 0x0f);   
+   printk("msp34xx: detected as %s\n",name);
+#endif
+   return 1;
+}
+
+static void msp3445_checkmode(struct CHIPSTATE *chip)
+{
+	int mode;
+        mode = msp3445_getmode(chip);
+        if(chip->prevmode == mode) return;
+   	chip->prevmode = mode;
+	v4l_dbg(1, debug, &chip->c,
+	       "%s: thread checkmode\n", chip->c.name);
+	if ((mode & VIDEO_SOUND_LANG2)!=0)
+		msp3445_setmode(chip,VIDEO_SOUND_LANG2);
+	else if ((mode & VIDEO_SOUND_LANG1)!=0)
+		msp3445_setmode(chip,VIDEO_SOUND_LANG1);
+	else if ((mode & VIDEO_SOUND_STEREO)!=0)
+		msp3445_setmode(chip,VIDEO_SOUND_STEREO);
+	else
+		msp3445_setmode(chip,VIDEO_SOUND_MONO);
+
+}
+
+
 /* ---------------------------------------------------------------------- */
 /* audio chip descriptions - struct CHIPDESC                              */
 
@@ -1465,6 +1829,23 @@
 
 		.init       = {2, { TA8874Z_MONO_SET, TA8874Z_SEPARATION_DEFAULT}},
 	},
+   	{
+		.name       = "msp3445",
+		//.id         = -1,
+	        .insmodopt  = &msp3445,
+		.id         = I2C_DRIVERID_MSP3400, /* FIXME */
+		.checkit    = msp3445_checkit,
+		.addr_lo    = I2C_ADDR_MSP3445 >>1,
+		.addr_hi    = (I2C_ADDR_MSP3445+4) >>1,
+		.registers  = 5,
+                .flags      = 0 | CHIP_HAS_VOLUME,
+		.getmode    = msp3445_getmode,
+		.setmode    = msp3445_setmode,
+	        .initialize = msp3445_initialize,
+                .checkmode  = msp3445_checkmode,
+	        //.checkmode  = generic_checkmode,
+	},
+   
 	{ .name = NULL } /* EOF */
 };
 
@@ -1527,8 +1908,12 @@
 	if (desc->flags & CHIP_HAS_VOLUME) {
 		chip->left   = desc->leftinit   ? desc->leftinit   : 65535;
 		chip->right  = desc->rightinit  ? desc->rightinit  : 65535;
-		chip_write(chip,desc->leftreg,desc->volfunc(chip->left));
-		chip_write(chip,desc->rightreg,desc->volfunc(chip->right));
+	        if(desc->id == I2C_DRIVERID_MSP3400) {
+		     msp3445_setvolume(chip,chip->left,chip->right);
+		} else {		
+		     chip_write(chip,desc->leftreg,desc->volfunc(chip->left));
+		     chip_write(chip,desc->rightreg,desc->volfunc(chip->right));
+		}
 	}
 	if (desc->flags & CHIP_HAS_BASSTREBLE) {
 		chip->treble = desc->trebleinit ? desc->trebleinit : 32768;
@@ -1661,8 +2046,12 @@
 				va->volume) / 32768;
 			chip->right = (min(va->balance,(__u16)32768) *
 				va->volume) / 32768;
-			chip_write(chip,desc->leftreg,desc->volfunc(chip->left));
-			chip_write(chip,desc->rightreg,desc->volfunc(chip->right));
+	   	        if(desc->id == I2C_DRIVERID_MSP3400) {
+			        msp3445_setvolume(chip,chip->left,chip->right);
+			} else {		
+				chip_write(chip,desc->leftreg,desc->volfunc(chip->left));
+			        chip_write(chip,desc->rightreg,desc->volfunc(chip->right));
+			}
 		}
 		if (desc->flags & CHIP_HAS_BASSTREBLE) {
 			chip->bass = va->bass;
@@ -1670,12 +2059,17 @@
 			chip_write(chip,desc->bassreg,desc->bassfunc(chip->bass));
 			chip_write(chip,desc->treblereg,desc->treblefunc(chip->treble));
 		}
-		if (desc->setmode && va->mode) {
-			chip->watch_stereo = 0;
-			/* del_timer(&chip->wt); */
-			chip->mode = va->mode;
-			desc->setmode(chip,va->mode);
-		}
+		   if (desc->setmode) {
+		      chip->watch_stereo = 0;
+		      del_timer(&chip->wt);
+		      /* 
+		       * OOPS...V4L2 method "arg->mode" is not SOUND-MODE,
+		       * auto volume support flag only,MPX mode was moved
+		       * to VIDIOC_S_MODULATOR :-(
+		       */
+		      if(va->mode != 0) chip->mode = va->mode;/* wrapper spec*/
+		      desc->setmode(chip,chip->mode); 
+		   }
 		break;
 	}
 
diff -urN linux-2.6.17-rc4.orig/drivers/media/video/tveeprom.c linux-2.6.17-rc4/drivers/media/video/tveeprom.c
--- linux-2.6.17-rc4.orig/drivers/media/video/tveeprom.c	2006-05-23 21:32:31.000000000 +0900
+++ linux-2.6.17-rc4/drivers/media/video/tveeprom.c	2006-05-23 22:16:08.000000000 +0900
@@ -229,6 +229,7 @@
 	/* 120-129 */
 	{ TUNER_ABSENT,        "Xceive XC3028"},
 	{ TUNER_ABSENT,        "Philips FQ1216LME MK5"},
+	{ TUNER_XCEIVE_XC_x028_MOTV,        "Xceive XC3028 for MonsterTV"}, /* XCEIVE TUNER for MonsterTV */
 };
 
 static struct HAUPPAUGE_AUDIOIC
diff -urN linux-2.6.17-rc4.orig/drivers/media/video/v4l1-compat.c linux-2.6.17-rc4/drivers/media/video/v4l1-compat.c
--- linux-2.6.17-rc4.orig/drivers/media/video/v4l1-compat.c	2006-03-20 14:53:29.000000000 +0900
+++ linux-2.6.17-rc4/drivers/media/video/v4l1-compat.c	2006-05-23 22:16:08.000000000 +0900
@@ -820,8 +820,9 @@
 			switch (aud->mode) {
 			default:
 			case VIDEO_SOUND_MONO:
+			        tun2.audmode = V4L2_TUNER_MODE_MONO;
 			case VIDEO_SOUND_LANG1:
-				tun2.audmode = V4L2_TUNER_MODE_MONO;
+				tun2.audmode = V4L2_TUNER_MODE_LANG1;
 				break;
 			case VIDEO_SOUND_STEREO:
 				tun2.audmode = V4L2_TUNER_MODE_STEREO;
diff -urN linux-2.6.17-rc4.orig/drivers/media/video/xc3028_meta.c linux-2.6.17-rc4/drivers/media/video/xc3028_meta.c
--- linux-2.6.17-rc4.orig/drivers/media/video/xc3028_meta.c	1970-01-01 09:00:00.000000000 +0900
+++ linux-2.6.17-rc4/drivers/media/video/xc3028_meta.c	2006-05-23 22:16:08.000000000 +0900
@@ -0,0 +1,107 @@
+/*
+
+   Xceive -  xc3028 tuner interface
+
+   Copyright (c) 2006 Markus Rechberger <mrechberger@gmail.com>
+
+
+TODO: - remove em28xx dependency
+      - add channel locking (requires some more reverse engineering)
+      - try to get the datasheet from Xceive :)
+
+   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.
+
+ Modified Information: 20060127 K.Ohta
+ * Depends for SKNet Monster TV V (WIP!) 
+ 20060523 K.Ohta
+ * Track with New Code.
+ * Change Functions name.
+*/
+
+#include <linux/i2c.h>
+#include <linux/videodev.h>
+
+//#include "saa7134.h" /* APPLY TO SAA713x (MonsterTV V) */
+//#include "saa7134-reg.h" /* APPLY TO SAA713x (MonsterTV V) */
+
+#include <linux/delay.h>
+#include <media/tuner.h>
+
+
+/* ---------------------------------------------------------------------- */
+
+int xc3028_meta_probe(struct i2c_client *c)
+{
+	printk("xc3028: probe function unknown\n");
+	return -1;
+}
+
+void xc3028_meta_set_tv_freq(struct i2c_client *c, unsigned int freq){
+	/*
+	   the frequency is just shifted and there's a 1:1 relation for all frequencies
+	   E11 is Das Erste in Germany/Ulm all other channels match their frequency too
+	*/
+	unsigned char chanbuf[4];
+	freq<<=2;
+	chanbuf[0]=0;
+	chanbuf[1]=0;
+	chanbuf[2]=(freq&0xff00)>>8;
+	chanbuf[3]=freq&0x00ff;
+	i2c_master_send(c,"\xa0\x00\x00\x00",4);
+	i2c_master_send(c,"\x1e\x1f\x13\x87\x18\x02\x93\x91\x44\x86\x96\x8c",12);
+	i2c_master_send(c,"\x00\x8c",2);
+	i2c_master_send(c,"\x80\x02\x00\x00",4);
+	i2c_master_send(c,chanbuf,4);
+}
+
+
+int xceive_meta_set_color(struct i2c_client *c){
+	/* I found this codeblock within the sniffed logfile it got called as it is a several times after 0x00 0x04 tuner settings are made */
+	/* codeblock hauppauge/terratec - analog */
+	i2c_master_send(c,"\x80\x01\x00\x00",4);
+	i2c_master_send(c,"\x00\x5e\x00\x29",4);
+	i2c_master_send(c,"\x2b\x1a",2);
+	i2c_master_send(c,"\x2b\x1b",2);
+	i2c_master_send(c,"\x14\x01\x6c\x25\x82\x38\xa4\x49\xa9\x24\x96\x69",0x0c);
+	i2c_master_send(c,"\x13\x14\x08\x30\x10\x6c\x18\x12\x0d\x19\x32\xad",0x0c);
+	i2c_master_send(c,"\x0d\x01\x4b\x03\x97\x55\xc7\xd7\x00\xa1\xeb\x8f\x5c",0x0d);
+	i2c_master_send(c,"\x1a\x00\x00\x16\x8a\x40\x00\x00\x00\x20",0x0a);
+	i2c_master_send(c,"\x2d\x01",2);
+	i2c_master_send(c,"\x18\x01",2);
+	i2c_master_send(c,"\x1b\x01\xb6\x15\x16\xb1\xa6\xd2\xa9\x12\x41\x66",0x0c);
+	i2c_master_send(c,"\x1d\x00",2);
+	i2c_master_send(c,"\x0f\x00\x29\x56\xb0\x00\xb6",0x07);
+	i2c_master_send(c,"\x20\x00",0x02);
+	i2c_master_send(c,"\x1e\x10\x32\x00\x00\x02\xe4\x81\x00\x06\xa9\x04",0x0c);
+	i2c_master_send(c,"\x22\x29",0x02);
+	i2c_master_send(c,"\x23\x06",0x02);
+	i2c_master_send(c,"\x25\x00\x09\x90\x09\x06\x64\x02\x41",0x09);
+	i2c_master_send(c,"\x26\xcc",0x02);
+	i2c_master_send(c,"\x29\x40",0x02);
+	i2c_master_send(c,"\x21\x03",0x02);
+	i2c_master_send(c,"\x00\x8c",0x02);
+	i2c_master_send(c,"\x00\x00\x00\x00",0x04); /* just wonder no sleep here regarding the logs */
+	i2c_master_send(c,"\x00\x04",0x02);
+	return(0);
+}
+
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -urN linux-2.6.17-rc4.orig/drivers/media/video/xc3028_motv.c linux-2.6.17-rc4/drivers/media/video/xc3028_motv.c
--- linux-2.6.17-rc4.orig/drivers/media/video/xc3028_motv.c	1970-01-01 09:00:00.000000000 +0900
+++ linux-2.6.17-rc4/drivers/media/video/xc3028_motv.c	2006-05-23 22:16:08.000000000 +0900
@@ -0,0 +1,196 @@
+/*
+
+   Xceive -  xc3028 tuner interface
+
+   Copyright (c) 2006 Markus Rechberger <mrechberger@gmail.com>
+
+
+TODO: - remove em28xx dependency
+      - add channel locking (requires some more reverse engineering)
+      - try to get the datasheet from Xceive :)
+
+   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.
+
+ Modified Information: 20060127 K.Ohta
+ * Depends for SKNet Monster TV V (WIP!) 
+ 20060523 K.Ohta
+ * Track with New Code.
+ * Change Functions name.
+
+*/
+
+#include <linux/i2c.h>
+#include <linux/videodev.h>
+#include "saa7134/saa7134.h"
+#include "saa7134/saa7134-reg.h"
+#include <linux/firmware.h>
+#include <linux/delay.h>
+#include <media/tuner.h>
+
+#define XC3028_DEFAULT_FIRMWARE "xceive_xc_3028.fw"
+
+
+extern void xc3028_meta_set_tv_freq(struct i2c_client *c, unsigned int freq);
+extern int xceive_meta_set_color(struct i2c_client *c);
+
+static void xc3028_motv_reset(struct saa7134_dev *dev)
+{
+	saa_clearb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_27_25);
+	msleep(5); /* Testing..WIP! */
+	saa_setb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_27_25);
+	msleep(5); /* Testing..WIP! */
+	saa_clearb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_27_25);
+	msleep(5); /* Testing..WIP! */
+
+}
+
+/* ---------------------------------------------------------------------- */
+
+int xc3028_motv_init(struct i2c_client *c,struct saa7134_dev *dev)
+{
+	struct tuner *t = i2c_get_clientdata(c);
+	const struct firmware *fw = NULL;
+	size_t firmware_size;
+	int ret=-1;
+	int i=0;
+	int d=0;
+	int txtlen;
+	long fwoff;
+	u8 *firmware;
+	u8 linebuffer[100];
+	char *fwoffset;
+
+	/*
+	  request firmware from /lib/firmware, note that the file got extracted by the convert application I wrote and which is available
+	  on linuxtv.org / xc3028
+	*/
+
+	ret = request_firmware(&fw, XC3028_DEFAULT_FIRMWARE, &t->i2c.dev);
+	if (ret) {
+		printk("xc3028: no firmware uploaded please check %s\n",XC3028_DEFAULT_FIRMWARE);
+		return ret;
+	}
+	firmware = fw->data;
+	firmware_size = fw->size;
+
+	/* small firmware check, both firmwares I have are between 6 and 7k bytes */
+
+	if(fw->size>7000||fw->size<6000){
+		printk("xc3028: wrong firmware provided!\n");
+		release_firmware(fw);
+		return(ret);
+	}
+	for(i=0;i<8&&firmware[i]!='\n';i++);
+	txtlen=i;
+	firmware[i++]=0;
+	fwoff=simple_strtol(firmware,&fwoffset,10);
+	if(fwoff>fw->size){
+		printk("xc3028: firmware offset doesn't match!\n");
+		release_firmware(fw);
+		return(-1);
+	}
+
+	linebuffer[d++]=0x2a;
+	/* dev=c->adapter->algo_data; */
+        /*
+	  Apply to monstertv V Series
+	  20060203 K.Ohta
+	*/
+	xc3028_motv_reset(dev);
+        printk("xc3028: reset!\n");
+
+	/*
+	   the firmware always starts with 0x2a + 0x40 bytes payload I use to add the offset of the first part
+	   as the first line into the firmware binary
+	*/
+	while(i!=fw->size){
+		linebuffer[d++]=firmware[i];
+		if((d%64==0&&d!=0)||i==fwoff+txtlen){
+			i2c_master_send(c,linebuffer,d);
+			if(i==(fwoff+txtlen)){
+				i2c_master_send(c,"\x02\x02",2);
+				i2c_master_send(c,"\x02\x03",2);
+				i2c_master_send(c,"\x00\x8c",2);
+				i2c_master_send(c,"\x00\x00\x00\x00",4);
+				/* at least 100 ms delay here, if less terratec FW won't work */
+				msleep(100);
+				/* another reset here */
+				xc3028_motv_reset(dev);
+
+			}
+			linebuffer[0]=0x2a;
+			d=1;
+		}
+		i++;
+	}
+	printk("xc3028: Firmware uploaded\n");
+	release_firmware(fw);
+
+	/* MAGIC VALUES Hauppauge */
+	i2c_master_send(c,"\x13\x39",2);
+	i2c_master_send(c,"\x0c\x80\xf0\xf7\x3e\x75\xc1\x8a\xe4\x02\x00",11);
+	i2c_master_send(c,"\x05\x0f\xee\xaa\x5f\xea\x90",7);
+	i2c_master_send(c,"\x06\x00\x0a\x4d\x8c\xf2\xd8\xcf\x30\x79\x9f",11);
+	i2c_master_send(c,"\x0b\x0d\xa4\x6c",4);
+	i2c_master_send(c,"\x0a\x01\x67\x24\x40\x08\xc3\x20\x10\x64\x3c\xfa\xf7\xe1\x0c\x2c",0x10);
+	i2c_master_send(c,"\x09\x0b",0x2);
+	i2c_master_send(c,"\x10\x13",0x2);
+	i2c_master_send(c,"\x16\x12",0x2);
+	i2c_master_send(c,"\x1f\x02",0x2);
+	i2c_master_send(c,"\x21\x02",0x2);
+	i2c_master_send(c,"\x01\x02",0x2);
+	i2c_master_send(c,"\x2b\x10",0x2);
+	i2c_master_send(c,"\x02\x02",0x2);
+	i2c_master_send(c,"\x02\x03",0x2);
+	i2c_master_send(c,"\x00\x8c",0x2);
+
+#if 0
+	/* MAGIC Values Terratec - dvb init*/
+	i2c_master_send(c,"\x13\x39",0x02);
+	i2c_master_send(c,"\x0c\x80\xf0\xf7\x3e\x75\xc1\x8a\xe4\x02\x00",11);
+	i2c_master_send(c,"\x05\x0f\xee\xaa\x5f\xea\x90",7);
+	i2c_master_send(c,"\x06\x00\x0a\x4d\x8c\xf2\xd8\xcf\x30\x79\x9f",11);
+	i2c_master_send(c,"\x0b\x0d\xa4\x6c",4);
+	i2c_master_send(c,"\x0a\x01\x67\x24\x40\x08\xc3\x20\x10\x64\x3c\xfa\xf7\xe1\x0c\x2c",0x10);
+	i2c_master_send(c,"\x09\x0b",0x02);
+	i2c_master_send(c,"\x10\x13",0x02);
+	i2c_master_send(c,"\x16\x12",0x02);
+	i2c_master_send(c,"\x1f\x02",0x02);
+	i2c_master_send(c,"\x21\x02",0x02);
+	i2c_master_send(c,"\x01\x02",0x02);
+	i2c_master_send(c,"\x2b\x10",0x02);
+	i2c_master_send(c,"\x02\x02",0x02);
+	i2c_master_send(c,"\x02\x03",0x02);
+	i2c_master_send(c,"\x00\x8c",0x02);
+#endif
+#if 0
+	/* if set video will mostly be black/white  - if set_color is called instead the video will have color */
+	i2c_master_send(c,"\x80\x01\x00\x00",0x4);
+	i2c_master_send(c,"\x00\x5e\x00\x29",0x4);
+	i2c_master_send(c,"\x2b\x1a",0x2);
+#endif
+	xceive_meta_set_color(c);
+	t->set_tv_freq    = xc3028_meta_set_tv_freq;
+	return(0);
+}
+
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -urN linux-2.6.17-rc4.orig/include/media/i2c-addr.h linux-2.6.17-rc4/include/media/i2c-addr.h
--- linux-2.6.17-rc4.orig/include/media/i2c-addr.h	2006-05-23 21:32:46.000000000 +0900
+++ linux-2.6.17-rc4/include/media/i2c-addr.h	2006-05-23 22:28:46.000000000 +0900
@@ -28,6 +28,7 @@
 #define I2C_ADDR_DPL3518	0x84
 #define I2C_ADDR_TDA9887	0x86
 
+
 /*
  * i2c bus addresses for the chips supported by tvaudio.c
  */
@@ -42,3 +43,4 @@
 #define I2C_ADDR_TEA6420	0x98
 
 #define I2C_ADDR_PIC16C54	0x96 /* PV951 */
+#define I2C_ADDR_MSP3445	0x80 /* Used for tvaudio.c 20060523 */
diff -urN linux-2.6.17-rc4.orig/include/media/tuner.h linux-2.6.17-rc4/include/media/tuner.h
--- linux-2.6.17-rc4.orig/include/media/tuner.h	2006-05-23 21:32:46.000000000 +0900
+++ linux-2.6.17-rc4/include/media/tuner.h	2006-05-23 22:27:30.000000000 +0900
@@ -119,6 +119,7 @@
 #define TUNER_XCEIVE_XC3028		71
 
 #define TUNER_THOMSON_FE6600		72	/* DViCO FusionHDTV DVB-T Hybrid */
+#define TUNER_XCEIVE_XC_x028_MOTV       73	/* XCEIVE Sil.tuner for MONSTERTV_V SERIES : RESERVED by K.Ohta 20060127 */
 
 /* tv card specific */
 #define TDA9887_PRESENT 		(1<<0)
@@ -219,6 +220,7 @@
 extern int default_tuner_init(struct i2c_client *c);
 extern int tea5767_autodetection(struct i2c_client *c);
 
+
 #define tuner_warn(fmt, arg...) do {\
 	printk(KERN_WARNING "%s %d-%04x: " fmt, t->i2c.driver->driver.name, \
 			i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0)
