summaryrefslogtreecommitdiff
path: root/linux/drivers/media/video
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@infradead.org>2008-04-26 13:13:56 -0300
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-04-26 13:13:56 -0300
commitaac29554759ba1097551414afc35ed9fa13056c2 (patch)
treede3052547dcad0585d2b7fc6b7da07ff6f2be999 /linux/drivers/media/video
parent92541c586e6655f2175fe5ec00836f5ef1ce1cb3 (diff)
downloadmediapointer-dvb-s2-aac29554759ba1097551414afc35ed9fa13056c2.tar.gz
mediapointer-dvb-s2-aac29554759ba1097551414afc35ed9fa13056c2.tar.bz2
From: Mauro Carvalho Chehab <mchehab@infradead.org>
Move tuners to common/tuners There were several issues in the past, caused by the hybrid tuner design, since now, the same tuner can be used by drivers/media/dvb and drivers/media/video. This patch moves those common tuners into a common dir. It also moves saa7146 driver into drivers/media/video, where other hybrid drivers are placed. Kconfig items were rearranged, to split V4L/DVB core from their drivers. Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'linux/drivers/media/video')
-rw-r--r--linux/drivers/media/video/Kconfig48
-rw-r--r--linux/drivers/media/video/Makefile13
-rw-r--r--linux/drivers/media/video/au0828/Makefile2
-rw-r--r--linux/drivers/media/video/bt8xx/Makefile1
-rw-r--r--linux/drivers/media/video/cx23885/Makefile1
-rw-r--r--linux/drivers/media/video/cx88/Makefile1
-rw-r--r--linux/drivers/media/video/em28xx/Makefile1
-rw-r--r--linux/drivers/media/video/ivtv/Makefile1
-rw-r--r--linux/drivers/media/video/mt20xx.c706
-rw-r--r--linux/drivers/media/video/mt20xx.h37
-rw-r--r--linux/drivers/media/video/pvrusb2/Makefile1
-rw-r--r--linux/drivers/media/video/saa7134/Makefile1
-rw-r--r--linux/drivers/media/video/saa7146/Kconfig9
-rw-r--r--linux/drivers/media/video/saa7146/saa7146_core.c601
-rw-r--r--linux/drivers/media/video/saa7146/saa7146_fops.c595
-rw-r--r--linux/drivers/media/video/saa7146/saa7146_hlp.c1045
-rw-r--r--linux/drivers/media/video/saa7146/saa7146_i2c.c433
-rw-r--r--linux/drivers/media/video/saa7146/saa7146_vbi.c511
-rw-r--r--linux/drivers/media/video/saa7146/saa7146_video.c1509
-rw-r--r--linux/drivers/media/video/tda8290.c833
-rw-r--r--linux/drivers/media/video/tda8290.h57
-rw-r--r--linux/drivers/media/video/tda9887.c728
-rw-r--r--linux/drivers/media/video/tda9887.h38
-rw-r--r--linux/drivers/media/video/tea5761.c330
-rw-r--r--linux/drivers/media/video/tea5761.h47
-rw-r--r--linux/drivers/media/video/tea5767.c525
-rw-r--r--linux/drivers/media/video/tea5767.h66
-rw-r--r--linux/drivers/media/video/tuner-i2c.h173
-rw-r--r--linux/drivers/media/video/tuner-simple.c1136
-rw-r--r--linux/drivers/media/video/tuner-simple.h39
-rw-r--r--linux/drivers/media/video/tuner-types.c1653
-rw-r--r--linux/drivers/media/video/tuner-xc2028-types.h153
-rw-r--r--linux/drivers/media/video/tuner-xc2028.c1274
-rw-r--r--linux/drivers/media/video/tuner-xc2028.h63
-rw-r--r--linux/drivers/media/video/usbvision/Makefile1
35 files changed, 4763 insertions, 7869 deletions
diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig
index fe9a4cc14..e0d65f134 100644
--- a/linux/drivers/media/video/Kconfig
+++ b/linux/drivers/media/video/Kconfig
@@ -1,4 +1,50 @@
#
+# Generic video config states
+#
+
+config VIDEO_V4L2
+ tristate
+ depends on VIDEO_DEV && VIDEO_V4L2_COMMON
+ default VIDEO_DEV && VIDEO_V4L2_COMMON
+
+config VIDEO_V4L1
+ tristate
+ depends on VIDEO_DEV && VIDEO_V4L2_COMMON && VIDEO_ALLOW_V4L1
+ default VIDEO_DEV && VIDEO_V4L2_COMMON && VIDEO_ALLOW_V4L1
+
+config VIDEOBUF_GEN
+ tristate
+
+config VIDEOBUF_DMA_SG
+ depends on HAS_DMA
+ select VIDEOBUF_GEN
+ tristate
+
+config VIDEOBUF_VMALLOC
+ select VIDEOBUF_GEN
+ tristate
+
+config VIDEOBUF_DVB
+ tristate
+ select VIDEOBUF_GEN
+ select VIDEOBUF_DMA_SG
+
+config VIDEO_BTCX
+ tristate
+
+config VIDEO_IR_I2C
+ tristate
+
+config VIDEO_IR
+ tristate
+ depends on INPUT
+ select VIDEO_IR_I2C if I2C
+
+config VIDEO_TVEEPROM
+ tristate
+ depends on I2C
+
+#
# Multimedia Video device configuration
#
@@ -640,6 +686,8 @@ config VIDEO_MEYE
source "drivers/media/video/saa7134/Kconfig"
+source "drivers/media/video/saa7146/Kconfig"
+
config VIDEO_MXB
tristate "Siemens-Nixdorf 'Multimedia eXtension Board'"
depends on PCI && VIDEO_V4L1 && I2C
diff --git a/linux/drivers/media/video/Makefile b/linux/drivers/media/video/Makefile
index f190c0702..82ef66600 100644
--- a/linux/drivers/media/video/Makefile
+++ b/linux/drivers/media/video/Makefile
@@ -87,16 +87,6 @@ obj-$(CONFIG_TUNER_3036) += tuner-3036.o
obj-$(CONFIG_VIDEO_TUNER) += tuner.o
-obj-$(CONFIG_TUNER_XC2028) += tuner-xc2028.o
-obj-$(CONFIG_TUNER_SIMPLE) += tuner-simple.o
-# tuner-types will be merged into tuner-simple, in the future
-obj-$(CONFIG_TUNER_SIMPLE) += tuner-types.o
-obj-$(CONFIG_TUNER_MT20XX) += mt20xx.o
-obj-$(CONFIG_TUNER_TDA8290) += tda8290.o
-obj-$(CONFIG_TUNER_TEA5767) += tea5767.o
-obj-$(CONFIG_TUNER_TEA5761) += tea5761.o
-obj-$(CONFIG_TUNER_TDA9887) += tda9887.o
-
obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o
obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o
obj-$(CONFIG_VIDEOBUF_VMALLOC) += videobuf-vmalloc.o
@@ -146,5 +136,8 @@ obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o
obj-$(CONFIG_VIDEO_AU0828) += au0828/
+obj-$(CONFIG_VIDEO_SAA7146) += saa7146/
+
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
diff --git a/linux/drivers/media/video/au0828/Makefile b/linux/drivers/media/video/au0828/Makefile
index 9f4f572c8..cd2c58281 100644
--- a/linux/drivers/media/video/au0828/Makefile
+++ b/linux/drivers/media/video/au0828/Makefile
@@ -2,7 +2,7 @@ au0828-objs := au0828-core.o au0828-i2c.o au0828-cards.o au0828-dvb.o
obj-$(CONFIG_VIDEO_AU0828) += au0828.o
-EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
diff --git a/linux/drivers/media/video/bt8xx/Makefile b/linux/drivers/media/video/bt8xx/Makefile
index 924d216d9..e415f6fc4 100644
--- a/linux/drivers/media/video/bt8xx/Makefile
+++ b/linux/drivers/media/video/bt8xx/Makefile
@@ -9,4 +9,5 @@ bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \
obj-$(CONFIG_VIDEO_BT848) += bttv.o
EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
diff --git a/linux/drivers/media/video/cx23885/Makefile b/linux/drivers/media/video/cx23885/Makefile
index d7b0721af..29c23b44c 100644
--- a/linux/drivers/media/video/cx23885/Makefile
+++ b/linux/drivers/media/video/cx23885/Makefile
@@ -3,6 +3,7 @@ cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o cx23885-core.o cx2
obj-$(CONFIG_VIDEO_CX23885) += cx23885.o
EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
diff --git a/linux/drivers/media/video/cx88/Makefile b/linux/drivers/media/video/cx88/Makefile
index 532cee35e..6ec30f242 100644
--- a/linux/drivers/media/video/cx88/Makefile
+++ b/linux/drivers/media/video/cx88/Makefile
@@ -10,5 +10,6 @@ obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o
obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o
EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
diff --git a/linux/drivers/media/video/em28xx/Makefile b/linux/drivers/media/video/em28xx/Makefile
index 3d1c3cc33..8137a8c94 100644
--- a/linux/drivers/media/video/em28xx/Makefile
+++ b/linux/drivers/media/video/em28xx/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_VIDEO_EM28XX_ALSA) += em28xx-alsa.o
obj-$(CONFIG_VIDEO_EM28XX_DVB) += em28xx-dvb.o
EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
diff --git a/linux/drivers/media/video/ivtv/Makefile b/linux/drivers/media/video/ivtv/Makefile
index a0389014f..26ce0d6ea 100644
--- a/linux/drivers/media/video/ivtv/Makefile
+++ b/linux/drivers/media/video/ivtv/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_VIDEO_IVTV) += ivtv.o
obj-$(CONFIG_VIDEO_FB_IVTV) += ivtvfb.o
EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
diff --git a/linux/drivers/media/video/mt20xx.c b/linux/drivers/media/video/mt20xx.c
deleted file mode 100644
index d2c281aeb..000000000
--- a/linux/drivers/media/video/mt20xx.c
+++ /dev/null
@@ -1,706 +0,0 @@
-/*
- * i2c tv tuner chip device driver
- * controls microtune tuners, mt2032 + mt2050 at the moment.
- *
- * This "mt20xx" module was split apart from the original "tuner" module.
- */
-#include <linux/delay.h>
-#include <linux/i2c.h>
-#include "compat.h"
-#include <linux/videodev.h>
-#include "tuner-i2c.h"
-#include "mt20xx.h"
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-#include "i2c-compat.h"
-#endif
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "enable verbose debug messages");
-
-/* ---------------------------------------------------------------------- */
-
-static unsigned int optimize_vco = 1;
-module_param(optimize_vco, int, 0644);
-
-static unsigned int tv_antenna = 1;
-module_param(tv_antenna, int, 0644);
-
-static unsigned int radio_antenna;
-module_param(radio_antenna, int, 0644);
-
-/* ---------------------------------------------------------------------- */
-
-#define MT2032 0x04
-#define MT2030 0x06
-#define MT2040 0x07
-#define MT2050 0x42
-
-static char *microtune_part[] = {
- [ MT2030 ] = "MT2030",
- [ MT2032 ] = "MT2032",
- [ MT2040 ] = "MT2040",
- [ MT2050 ] = "MT2050",
-};
-
-struct microtune_priv {
- struct tuner_i2c_props i2c_props;
-
- unsigned int xogc;
- //unsigned int radio_if2;
-
- u32 frequency;
-};
-
-static int microtune_release(struct dvb_frontend *fe)
-{
- kfree(fe->tuner_priv);
- fe->tuner_priv = NULL;
-
- return 0;
-}
-
-static int microtune_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
- struct microtune_priv *priv = fe->tuner_priv;
- *frequency = priv->frequency;
- return 0;
-}
-
-// IsSpurInBand()?
-static int mt2032_spurcheck(struct dvb_frontend *fe,
- int f1, int f2, int spectrum_from,int spectrum_to)
-{
- struct microtune_priv *priv = fe->tuner_priv;
- int n1=1,n2,f;
-
- f1=f1/1000; //scale to kHz to avoid 32bit overflows
- f2=f2/1000;
- spectrum_from/=1000;
- spectrum_to/=1000;
-
- tuner_dbg("spurcheck f1=%d f2=%d from=%d to=%d\n",
- f1,f2,spectrum_from,spectrum_to);
-
- do {
- n2=-n1;
- f=n1*(f1-f2);
- do {
- n2--;
- f=f-f2;
- tuner_dbg("spurtest n1=%d n2=%d ftest=%d\n",n1,n2,f);
-
- if( (f>spectrum_from) && (f<spectrum_to))
- tuner_dbg("mt2032 spurcheck triggered: %d\n",n1);
- } while ( (f>(f2-spectrum_to)) || (n2>-5));
- n1++;
- } while (n1<5);
-
- return 1;
-}
-
-static int mt2032_compute_freq(struct dvb_frontend *fe,
- unsigned int rfin,
- unsigned int if1, unsigned int if2,
- unsigned int spectrum_from,
- unsigned int spectrum_to,
- unsigned char *buf,
- int *ret_sel,
- unsigned int xogc) //all in Hz
-{
- struct microtune_priv *priv = fe->tuner_priv;
- unsigned int fref,lo1,lo1n,lo1a,s,sel,lo1freq, desired_lo1,
- desired_lo2,lo2,lo2n,lo2a,lo2num,lo2freq;
-
- fref= 5250 *1000; //5.25MHz
- desired_lo1=rfin+if1;
-
- lo1=(2*(desired_lo1/1000)+(fref/1000)) / (2*fref/1000);
- lo1n=lo1/8;
- lo1a=lo1-(lo1n*8);
-
- s=rfin/1000/1000+1090;
-
- if(optimize_vco) {
- if(s>1890) sel=0;
- else if(s>1720) sel=1;
- else if(s>1530) sel=2;
- else if(s>1370) sel=3;
- else sel=4; // >1090
- }
- else {
- if(s>1790) sel=0; // <1958
- else if(s>1617) sel=1;
- else if(s>1449) sel=2;
- else if(s>1291) sel=3;
- else sel=4; // >1090
- }
- *ret_sel=sel;
-
- lo1freq=(lo1a+8*lo1n)*fref;
-
- tuner_dbg("mt2032: rfin=%d lo1=%d lo1n=%d lo1a=%d sel=%d, lo1freq=%d\n",
- rfin,lo1,lo1n,lo1a,sel,lo1freq);
-
- desired_lo2=lo1freq-rfin-if2;
- lo2=(desired_lo2)/fref;
- lo2n=lo2/8;
- lo2a=lo2-(lo2n*8);
- lo2num=((desired_lo2/1000)%(fref/1000))* 3780/(fref/1000); //scale to fit in 32bit arith
- lo2freq=(lo2a+8*lo2n)*fref + lo2num*(fref/1000)/3780*1000;
-
- tuner_dbg("mt2032: rfin=%d lo2=%d lo2n=%d lo2a=%d num=%d lo2freq=%d\n",
- rfin,lo2,lo2n,lo2a,lo2num,lo2freq);
-
- if(lo1a<0 || lo1a>7 || lo1n<17 ||lo1n>48 || lo2a<0 ||lo2a >7 ||lo2n<17 || lo2n>30) {
- tuner_info("mt2032: frequency parameters out of range: %d %d %d %d\n",
- lo1a, lo1n, lo2a,lo2n);
- return(-1);
- }
-
- mt2032_spurcheck(fe, lo1freq, desired_lo2, spectrum_from, spectrum_to);
- // should recalculate lo1 (one step up/down)
-
- // set up MT2032 register map for transfer over i2c
- buf[0]=lo1n-1;
- buf[1]=lo1a | (sel<<4);
- buf[2]=0x86; // LOGC
- buf[3]=0x0f; //reserved
- buf[4]=0x1f;
- buf[5]=(lo2n-1) | (lo2a<<5);
- if(rfin >400*1000*1000)
- buf[6]=0xe4;
- else
- buf[6]=0xf4; // set PKEN per rev 1.2
- buf[7]=8+xogc;
- buf[8]=0xc3; //reserved
- buf[9]=0x4e; //reserved
- buf[10]=0xec; //reserved
- buf[11]=(lo2num&0xff);
- buf[12]=(lo2num>>8) |0x80; // Lo2RST
-
- return 0;
-}
-
-static int mt2032_check_lo_lock(struct dvb_frontend *fe)
-{
- struct microtune_priv *priv = fe->tuner_priv;
- int try,lock=0;
- unsigned char buf[2];
-
- for(try=0;try<10;try++) {
- buf[0]=0x0e;
- tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
- tuner_i2c_xfer_recv(&priv->i2c_props,buf,1);
- tuner_dbg("mt2032 Reg.E=0x%02x\n",buf[0]);
- lock=buf[0] &0x06;
-
- if (lock==6)
- break;
-
- tuner_dbg("mt2032: pll wait 1ms for lock (0x%2x)\n",buf[0]);
- udelay(1000);
- }
- return lock;
-}
-
-static int mt2032_optimize_vco(struct dvb_frontend *fe,int sel,int lock)
-{
- struct microtune_priv *priv = fe->tuner_priv;
- unsigned char buf[2];
- int tad1;
-
- buf[0]=0x0f;
- tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
- tuner_i2c_xfer_recv(&priv->i2c_props,buf,1);
- tuner_dbg("mt2032 Reg.F=0x%02x\n",buf[0]);
- tad1=buf[0]&0x07;
-
- if(tad1 ==0) return lock;
- if(tad1 ==1) return lock;
-
- if(tad1==2) {
- if(sel==0)
- return lock;
- else sel--;
- }
- else {
- if(sel<4)
- sel++;
- else
- return lock;
- }
-
- tuner_dbg("mt2032 optimize_vco: sel=%d\n",sel);
-
- buf[0]=0x0f;
- buf[1]=sel;
- tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
- lock=mt2032_check_lo_lock(fe);
- return lock;
-}
-
-
-static void mt2032_set_if_freq(struct dvb_frontend *fe, unsigned int rfin,
- unsigned int if1, unsigned int if2,
- unsigned int from, unsigned int to)
-{
- unsigned char buf[21];
- int lint_try,ret,sel,lock=0;
- struct microtune_priv *priv = fe->tuner_priv;
-
- tuner_dbg("mt2032_set_if_freq rfin=%d if1=%d if2=%d from=%d to=%d\n",
- rfin,if1,if2,from,to);
-
- buf[0]=0;
- ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
- tuner_i2c_xfer_recv(&priv->i2c_props,buf,21);
-
- buf[0]=0;
- ret=mt2032_compute_freq(fe,rfin,if1,if2,from,to,&buf[1],&sel,priv->xogc);
- if (ret<0)
- return;
-
- // send only the relevant registers per Rev. 1.2
- buf[0]=0;
- ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,4);
- buf[5]=5;
- ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+5,4);
- buf[11]=11;
- ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+11,3);
- if(ret!=3)
- tuner_warn("i2c i/o error: rc == %d (should be 3)\n",ret);
-
- // wait for PLLs to lock (per manual), retry LINT if not.
- for(lint_try=0; lint_try<2; lint_try++) {
- lock=mt2032_check_lo_lock(fe);
-
- if(optimize_vco)
- lock=mt2032_optimize_vco(fe,sel,lock);
- if(lock==6) break;
-
- tuner_dbg("mt2032: re-init PLLs by LINT\n");
- buf[0]=7;
- buf[1]=0x80 +8+priv->xogc; // set LINT to re-init PLLs
- tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
- mdelay(10);
- buf[1]=8+priv->xogc;
- tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
- }
-
- if (lock!=6)
- tuner_warn("MT2032 Fatal Error: PLLs didn't lock.\n");
-
- buf[0]=2;
- buf[1]=0x20; // LOGC for optimal phase noise
- ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
- if (ret!=2)
- tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret);
-}
-
-
-static int mt2032_set_tv_freq(struct dvb_frontend *fe,
- struct analog_parameters *params)
-{
- int if2,from,to;
-
- // signal bandwidth and picture carrier
- if (params->std & V4L2_STD_525_60) {
- // NTSC
- from = 40750*1000;
- to = 46750*1000;
- if2 = 45750*1000;
- } else {
- // PAL
- from = 32900*1000;
- to = 39900*1000;
- if2 = 38900*1000;
- }
-
- mt2032_set_if_freq(fe, params->frequency*62500,
- 1090*1000*1000, if2, from, to);
-
- return 0;
-}
-
-static int mt2032_set_radio_freq(struct dvb_frontend *fe,
- struct analog_parameters *params)
-{
- struct microtune_priv *priv = fe->tuner_priv;
- int if2;
-
- if (params->std & V4L2_STD_525_60) {
- tuner_dbg("pinnacle ntsc\n");
- if2 = 41300 * 1000;
- } else {
- tuner_dbg("pinnacle pal\n");
- if2 = 33300 * 1000;
- }
-
- // per Manual for FM tuning: first if center freq. 1085 MHz
- mt2032_set_if_freq(fe, params->frequency * 125 / 2,
- 1085*1000*1000,if2,if2,if2);
-
- return 0;
-}
-
-static int mt2032_set_params(struct dvb_frontend *fe,
- struct analog_parameters *params)
-{
- struct microtune_priv *priv = fe->tuner_priv;
- int ret = -EINVAL;
-
- switch (params->mode) {
- case V4L2_TUNER_RADIO:
- ret = mt2032_set_radio_freq(fe, params);
- priv->frequency = params->frequency * 125 / 2;
- break;
- case V4L2_TUNER_ANALOG_TV:
- case V4L2_TUNER_DIGITAL_TV:
- ret = mt2032_set_tv_freq(fe, params);
- priv->frequency = params->frequency * 62500;
- break;
- }
-
- return ret;
-}
-
-static struct dvb_tuner_ops mt2032_tuner_ops = {
-#if 0
- .info = {
- .name = "MT2032",
- .frequency_min = ,
- .frequency_max = ,
- .frequency_step = ,
- },
-#endif
- .set_analog_params = mt2032_set_params,
- .release = microtune_release,
- .get_frequency = microtune_get_frequency,
-};
-
-// Initialization as described in "MT203x Programming Procedures", Rev 1.2, Feb.2001
-static int mt2032_init(struct dvb_frontend *fe)
-{
- struct microtune_priv *priv = fe->tuner_priv;
- unsigned char buf[21];
- int ret,xogc,xok=0;
-
- // Initialize Registers per spec.
- buf[1]=2; // Index to register 2
- buf[2]=0xff;
- buf[3]=0x0f;
- buf[4]=0x1f;
- ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+1,4);
-
- buf[5]=6; // Index register 6
- buf[6]=0xe4;
- buf[7]=0x8f;
- buf[8]=0xc3;
- buf[9]=0x4e;
- buf[10]=0xec;
- ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+5,6);
-
- buf[12]=13; // Index register 13
- buf[13]=0x32;
- ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+12,2);
-
- // Adjust XOGC (register 7), wait for XOK
- xogc=7;
- do {
- tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07);
- mdelay(10);
- buf[0]=0x0e;
- tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
- tuner_i2c_xfer_recv(&priv->i2c_props,buf,1);
- xok=buf[0]&0x01;
- tuner_dbg("mt2032: xok = 0x%02x\n",xok);
- if (xok == 1) break;
-
- xogc--;
- tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07);
- if (xogc == 3) {
- xogc=4; // min. 4 per spec
- break;
- }
- buf[0]=0x07;
- buf[1]=0x88 + xogc;
- ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
- if (ret!=2)
- tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret);
- } while (xok != 1 );
- priv->xogc=xogc;
-
- memcpy(&fe->ops.tuner_ops, &mt2032_tuner_ops, sizeof(struct dvb_tuner_ops));
-
- return(1);
-}
-
-static void mt2050_set_antenna(struct dvb_frontend *fe, unsigned char antenna)
-{
- struct microtune_priv *priv = fe->tuner_priv;
- unsigned char buf[2];
- int ret;
-
- buf[0] = 6;
- buf[1] = antenna ? 0x11 : 0x10;
- ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
- tuner_dbg("mt2050: enabled antenna connector %d\n", antenna);
-}
-
-static void mt2050_set_if_freq(struct dvb_frontend *fe,unsigned int freq, unsigned int if2)
-{
- struct microtune_priv *priv = fe->tuner_priv;
- unsigned int if1=1218*1000*1000;
- unsigned int f_lo1,f_lo2,lo1,lo2,f_lo1_modulo,f_lo2_modulo,num1,num2,div1a,div1b,div2a,div2b;
- int ret;
- unsigned char buf[6];
-
- tuner_dbg("mt2050_set_if_freq freq=%d if1=%d if2=%d\n",
- freq,if1,if2);
-
- f_lo1=freq+if1;
- f_lo1=(f_lo1/1000000)*1000000;
-
- f_lo2=f_lo1-freq-if2;
- f_lo2=(f_lo2/50000)*50000;
-
- lo1=f_lo1/4000000;
- lo2=f_lo2/4000000;
-
- f_lo1_modulo= f_lo1-(lo1*4000000);
- f_lo2_modulo= f_lo2-(lo2*4000000);
-
- num1=4*f_lo1_modulo/4000000;
- num2=4096*(f_lo2_modulo/1000)/4000;
-
- // todo spurchecks
-
- div1a=(lo1/12)-1;
- div1b=lo1-(div1a+1)*12;
-
- div2a=(lo2/8)-1;
- div2b=lo2-(div2a+1)*8;
-
- if (debug > 1) {
- tuner_dbg("lo1 lo2 = %d %d\n", lo1, lo2);
- tuner_dbg("num1 num2 div1a div1b div2a div2b= %x %x %x %x %x %x\n",
- num1,num2,div1a,div1b,div2a,div2b);
- }
-
- buf[0]=1;
- buf[1]= 4*div1b + num1;
- if(freq<275*1000*1000) buf[1] = buf[1]|0x80;
-
- buf[2]=div1a;
- buf[3]=32*div2b + num2/256;
- buf[4]=num2-(num2/256)*256;
- buf[5]=div2a;
- if(num2!=0) buf[5]=buf[5]|0x40;
-
- if (debug > 1) {
- int i;
- tuner_dbg("bufs is: ");
- for(i=0;i<6;i++)
- printk("%x ",buf[i]);
- printk("\n");
- }
-
- ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,6);
- if (ret!=6)
- tuner_warn("i2c i/o error: rc == %d (should be 6)\n",ret);
-}
-
-static int mt2050_set_tv_freq(struct dvb_frontend *fe,
- struct analog_parameters *params)
-{
- unsigned int if2;
-
- if (params->std & V4L2_STD_525_60) {
- // NTSC
- if2 = 45750*1000;
- } else {
- // PAL
- if2 = 38900*1000;
- }
- if (V4L2_TUNER_DIGITAL_TV == params->mode) {
- // DVB (pinnacle 300i)
- if2 = 36150*1000;
- }
- mt2050_set_if_freq(fe, params->frequency*62500, if2);
- mt2050_set_antenna(fe, tv_antenna);
-
- return 0;
-}
-
-static int mt2050_set_radio_freq(struct dvb_frontend *fe,
- struct analog_parameters *params)
-{
- struct microtune_priv *priv = fe->tuner_priv;
- int if2;
-
- if (params->std & V4L2_STD_525_60) {
- tuner_dbg("pinnacle ntsc\n");
- if2 = 41300 * 1000;
- } else {
- tuner_dbg("pinnacle pal\n");
- if2 = 33300 * 1000;
- }
-
- mt2050_set_if_freq(fe, params->frequency * 125 / 2, if2);
- mt2050_set_antenna(fe, radio_antenna);
-
- return 0;
-}
-
-static int mt2050_set_params(struct dvb_frontend *fe,
- struct analog_parameters *params)
-{
- struct microtune_priv *priv = fe->tuner_priv;
- int ret = -EINVAL;
-
- switch (params->mode) {
- case V4L2_TUNER_RADIO:
- ret = mt2050_set_radio_freq(fe, params);
- priv->frequency = params->frequency * 125 / 2;
- break;
- case V4L2_TUNER_ANALOG_TV:
- case V4L2_TUNER_DIGITAL_TV:
- ret = mt2050_set_tv_freq(fe, params);
- priv->frequency = params->frequency * 62500;
- break;
- }
-
- return ret;
-}
-
-static struct dvb_tuner_ops mt2050_tuner_ops = {
-#if 0
- .info = {
- .name = "MT2050",
- .frequency_min = ,
- .frequency_max = ,
- .frequency_step = ,
- },
-#endif
- .set_analog_params = mt2050_set_params,
- .release = microtune_release,
- .get_frequency = microtune_get_frequency,
-};
-
-static int mt2050_init(struct dvb_frontend *fe)
-{
- struct microtune_priv *priv = fe->tuner_priv;
- unsigned char buf[2];
- int ret;
-
- buf[0]=6;
- buf[1]=0x10;
- ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2); // power
-
- buf[0]=0x0f;
- buf[1]=0x0f;
- ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2); // m1lo
-
- buf[0]=0x0d;
- ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
- tuner_i2c_xfer_recv(&priv->i2c_props,buf,1);
-
- tuner_dbg("mt2050: sro is %x\n",buf[0]);
-
- memcpy(&fe->ops.tuner_ops, &mt2050_tuner_ops, sizeof(struct dvb_tuner_ops));
-
- return 0;
-}
-
-struct dvb_frontend *microtune_attach(struct dvb_frontend *fe,
- struct i2c_adapter* i2c_adap,
- u8 i2c_addr)
-{
- struct microtune_priv *priv = NULL;
- char *name;
- unsigned char buf[21];
- int company_code;
-
- priv = kzalloc(sizeof(struct microtune_priv), GFP_KERNEL);
- if (priv == NULL)
- return NULL;
- fe->tuner_priv = priv;
-
- priv->i2c_props.addr = i2c_addr;
- priv->i2c_props.adap = i2c_adap;
- priv->i2c_props.name = "mt20xx";
-
- //priv->radio_if2 = 10700 * 1000; /* 10.7MHz - FM radio */
-
- memset(buf,0,sizeof(buf));
-
- name = "unknown";
-
- tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
- tuner_i2c_xfer_recv(&priv->i2c_props,buf,21);
- if (debug) {
- int i;
- tuner_dbg("MT20xx hexdump:");
- for(i=0;i<21;i++) {
- printk(" %02x",buf[i]);
- if(((i+1)%8)==0) printk(" ");
- }
- printk("\n");
- }
- company_code = buf[0x11] << 8 | buf[0x12];
- tuner_info("microtune: companycode=%04x part=%02x rev=%02x\n",
- company_code,buf[0x13],buf[0x14]);
-
-#if 0
- /* seems to cause more problems than it solves ... */
- switch (company_code) {
- case 0x30bf:
- case 0x3cbf:
- case 0x3dbf:
- case 0x4d54:
- case 0x8e81:
- case 0x8e91:
- /* ok (?) */
- break;
- default:
- tuner_warn("tuner: microtune: unknown companycode\n");
- return 0;
- }
-#endif
-
- if (buf[0x13] < ARRAY_SIZE(microtune_part) &&
- NULL != microtune_part[buf[0x13]])
- name = microtune_part[buf[0x13]];
- switch (buf[0x13]) {
- case MT2032:
- mt2032_init(fe);
- break;
- case MT2050:
- mt2050_init(fe);
- break;
- default:
- tuner_info("microtune %s found, not (yet?) supported, sorry :-/\n",
- name);
- return NULL;
- }
-
- strlcpy(fe->ops.tuner_ops.info.name, name,
- sizeof(fe->ops.tuner_ops.info.name));
- tuner_info("microtune %s found, OK\n",name);
- return fe;
-}
-
-EXPORT_SYMBOL_GPL(microtune_attach);
-
-MODULE_DESCRIPTION("Microtune tuner driver");
-MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
-MODULE_LICENSE("GPL");
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/linux/drivers/media/video/mt20xx.h b/linux/drivers/media/video/mt20xx.h
deleted file mode 100644
index aa848e14c..000000000
--- a/linux/drivers/media/video/mt20xx.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- 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.
-*/
-
-#ifndef __MT20XX_H__
-#define __MT20XX_H__
-
-#include <linux/i2c.h>
-#include "dvb_frontend.h"
-
-#if defined(CONFIG_TUNER_MT20XX) || (defined(CONFIG_TUNER_MT20XX_MODULE) && defined(MODULE))
-extern struct dvb_frontend *microtune_attach(struct dvb_frontend *fe,
- struct i2c_adapter* i2c_adap,
- u8 i2c_addr);
-#else
-static inline struct dvb_frontend *microtune_attach(struct dvb_frontend *fe,
- struct i2c_adapter* i2c_adap,
- u8 i2c_addr)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return NULL;
-}
-#endif
-
-#endif /* __MT20XX_H__ */
diff --git a/linux/drivers/media/video/pvrusb2/Makefile b/linux/drivers/media/video/pvrusb2/Makefile
index 5b3083c89..4fda2de69 100644
--- a/linux/drivers/media/video/pvrusb2/Makefile
+++ b/linux/drivers/media/video/pvrusb2/Makefile
@@ -16,5 +16,6 @@ pvrusb2-objs := pvrusb2-i2c-core.o pvrusb2-i2c-cmd-v4l2.o \
obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2.o
EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
diff --git a/linux/drivers/media/video/saa7134/Makefile b/linux/drivers/media/video/saa7134/Makefile
index 9aff937ba..3dbaa19a6 100644
--- a/linux/drivers/media/video/saa7134/Makefile
+++ b/linux/drivers/media/video/saa7134/Makefile
@@ -11,5 +11,6 @@ obj-$(CONFIG_VIDEO_SAA7134_ALSA) += saa7134-alsa.o
obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o
EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
diff --git a/linux/drivers/media/video/saa7146/Kconfig b/linux/drivers/media/video/saa7146/Kconfig
new file mode 100644
index 000000000..769c6f814
--- /dev/null
+++ b/linux/drivers/media/video/saa7146/Kconfig
@@ -0,0 +1,9 @@
+config VIDEO_SAA7146
+ tristate
+ depends on I2C && PCI
+
+config VIDEO_SAA7146_VV
+ tristate
+ depends on VIDEO_V4L2
+ select VIDEOBUF_DMA_SG
+ select VIDEO_SAA7146
diff --git a/linux/drivers/media/video/saa7146/saa7146_core.c b/linux/drivers/media/video/saa7146/saa7146_core.c
new file mode 100644
index 000000000..973989dd4
--- /dev/null
+++ b/linux/drivers/media/video/saa7146/saa7146_core.c
@@ -0,0 +1,601 @@
+/*
+ saa7146.o - driver for generic saa7146-based hardware
+
+ Copyright (C) 1998-2003 Michael Hunold <michael@mihu.de>
+
+ 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 <media/saa7146.h>
+
+LIST_HEAD(saa7146_devices);
+DEFINE_MUTEX(saa7146_devices_lock);
+
+static int saa7146_num;
+
+unsigned int saa7146_debug;
+
+module_param(saa7146_debug, uint, 0644);
+MODULE_PARM_DESC(saa7146_debug, "debug level (default: 0)");
+
+#if 0 /* keep */
+static void dump_registers(struct saa7146_dev* dev)
+{
+ int i = 0;
+
+ INFO((" @ %li jiffies:\n",jiffies));
+ for(i = 0; i <= 0x148; i+=4) {
+ printk("0x%03x: 0x%08x\n",i,saa7146_read(dev,i));
+ }
+}
+#endif
+
+/****************************************************************************
+ * gpio and debi helper functions
+ ****************************************************************************/
+
+void saa7146_setgpio(struct saa7146_dev *dev, int port, u32 data)
+{
+ u32 value = 0;
+
+ BUG_ON(port > 3);
+
+ value = saa7146_read(dev, GPIO_CTRL);
+ value &= ~(0xff << (8*port));
+ value |= (data << (8*port));
+ saa7146_write(dev, GPIO_CTRL, value);
+}
+
+/* This DEBI code is based on the saa7146 Stradis driver by Nathan Laredo */
+static inline int saa7146_wait_for_debi_done_sleep(struct saa7146_dev *dev,
+ unsigned long us1, unsigned long us2)
+{
+ unsigned long timeout;
+ int err;
+
+ /* wait for registers to be programmed */
+ timeout = jiffies + usecs_to_jiffies(us1);
+ while (1) {
+ err = time_after(jiffies, timeout);
+ if (saa7146_read(dev, MC2) & 2)
+ break;
+ if (err) {
+ printk(KERN_ERR "%s: %s timed out while waiting for "
+ "registers getting programmed\n",
+ dev->name, __func__);
+ return -ETIMEDOUT;
+ }
+ msleep(1);
+ }
+
+ /* wait for transfer to complete */
+ timeout = jiffies + usecs_to_jiffies(us2);
+ while (1) {
+ err = time_after(jiffies, timeout);
+ if (!(saa7146_read(dev, PSR) & SPCI_DEBI_S))
+ break;
+ saa7146_read(dev, MC2);
+ if (err) {
+ DEB_S(("%s: %s timed out while waiting for transfer "
+ "completion\n", dev->name, __func__));
+ return -ETIMEDOUT;
+ }
+ msleep(1);
+ }
+
+ return 0;
+}
+
+static inline int saa7146_wait_for_debi_done_busyloop(struct saa7146_dev *dev,
+ unsigned long us1, unsigned long us2)
+{
+ unsigned long loops;
+
+ /* wait for registers to be programmed */
+ loops = us1;
+ while (1) {
+ if (saa7146_read(dev, MC2) & 2)
+ break;
+ if (!loops--) {
+ printk(KERN_ERR "%s: %s timed out while waiting for "
+ "registers getting programmed\n",
+ dev->name, __func__);
+ return -ETIMEDOUT;
+ }
+ udelay(1);
+ }
+
+ /* wait for transfer to complete */
+ loops = us2 / 5;
+ while (1) {
+ if (!(saa7146_read(dev, PSR) & SPCI_DEBI_S))
+ break;
+ saa7146_read(dev, MC2);
+ if (!loops--) {
+ DEB_S(("%s: %s timed out while waiting for transfer "
+ "completion\n", dev->name, __func__));
+ return -ETIMEDOUT;
+ }
+ udelay(5);
+ }
+
+ return 0;
+}
+
+int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop)
+{
+ if (nobusyloop)
+ return saa7146_wait_for_debi_done_sleep(dev, 50000, 250000);
+ else
+ return saa7146_wait_for_debi_done_busyloop(dev, 50000, 250000);
+}
+
+/****************************************************************************
+ * general helper functions
+ ****************************************************************************/
+
+/* this is videobuf_vmalloc_to_sg() from videobuf-dma-sg.c
+ make sure virt has been allocated with vmalloc_32(), otherwise the BUG()
+ may be triggered on highmem machines */
+static struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages)
+{
+ struct scatterlist *sglist;
+ struct page *pg;
+ int i;
+
+ sglist = kcalloc(nr_pages, sizeof(struct scatterlist), GFP_KERNEL);
+ if (NULL == sglist)
+ return NULL;
+ sg_init_table(sglist, nr_pages);
+ for (i = 0; i < nr_pages; i++, virt += PAGE_SIZE) {
+ pg = vmalloc_to_page(virt);
+ if (NULL == pg)
+ goto err;
+ BUG_ON(PageHighMem(pg));
+ sg_set_page(&sglist[i], pg, PAGE_SIZE, 0);
+ }
+ return sglist;
+
+ err:
+ kfree(sglist);
+ return NULL;
+}
+
+/********************************************************************************/
+/* common page table functions */
+
+void *saa7146_vmalloc_build_pgtable(struct pci_dev *pci, long length, struct saa7146_pgtable *pt)
+{
+ int pages = (length+PAGE_SIZE-1)/PAGE_SIZE;
+ void *mem = vmalloc_32(length);
+ int slen = 0;
+
+ if (NULL == mem)
+ goto err_null;
+
+ if (!(pt->slist = vmalloc_to_sg(mem, pages)))
+ goto err_free_mem;
+
+ if (saa7146_pgtable_alloc(pci, pt))
+ goto err_free_slist;
+
+ pt->nents = pages;
+ slen = pci_map_sg(pci,pt->slist,pt->nents,PCI_DMA_FROMDEVICE);
+ if (0 == slen)
+ goto err_free_pgtable;
+
+ if (0 != saa7146_pgtable_build_single(pci, pt, pt->slist, slen))
+ goto err_unmap_sg;
+
+ return mem;
+
+err_unmap_sg:
+ pci_unmap_sg(pci, pt->slist, pt->nents, PCI_DMA_FROMDEVICE);
+err_free_pgtable:
+ saa7146_pgtable_free(pci, pt);
+err_free_slist:
+ kfree(pt->slist);
+ pt->slist = NULL;
+err_free_mem:
+ vfree(mem);
+err_null:
+ return NULL;
+}
+
+void saa7146_vfree_destroy_pgtable(struct pci_dev *pci, void *mem, struct saa7146_pgtable *pt)
+{
+ pci_unmap_sg(pci, pt->slist, pt->nents, PCI_DMA_FROMDEVICE);
+ saa7146_pgtable_free(pci, pt);
+ kfree(pt->slist);
+ pt->slist = NULL;
+ vfree(mem);
+}
+
+void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt)
+{
+ if (NULL == pt->cpu)
+ return;
+ pci_free_consistent(pci, pt->size, pt->cpu, pt->dma);
+ pt->cpu = NULL;
+}
+
+int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt)
+{
+ u32 *cpu;
+ dma_addr_t dma_addr;
+
+ cpu = pci_alloc_consistent(pci, PAGE_SIZE, &dma_addr);
+ if (NULL == cpu) {
+ return -ENOMEM;
+ }
+ pt->size = PAGE_SIZE;
+ pt->cpu = cpu;
+ pt->dma = dma_addr;
+
+ return 0;
+}
+
+int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt,
+ struct scatterlist *list, int sglen )
+{
+ u32 *ptr, fill;
+ int nr_pages = 0;
+ int i,p;
+
+ BUG_ON(0 == sglen);
+ BUG_ON(list->offset > PAGE_SIZE);
+
+ /* if we have a user buffer, the first page may not be
+ aligned to a page boundary. */
+ pt->offset = list->offset;
+
+ ptr = pt->cpu;
+ for (i = 0; i < sglen; i++, list++) {
+/*
+ printk("i:%d, adr:0x%08x, len:%d, offset:%d\n", i,sg_dma_address(list), sg_dma_len(list), list->offset);
+*/
+ for (p = 0; p * 4096 < list->length; p++, ptr++) {
+ *ptr = cpu_to_le32(sg_dma_address(list) + p * 4096);
+ nr_pages++;
+ }
+ }
+
+
+ /* safety; fill the page table up with the last valid page */
+ fill = *(ptr-1);
+ for(i=nr_pages;i<1024;i++) {
+ *ptr++ = fill;
+ }
+
+/*
+ ptr = pt->cpu;
+ printk("offset: %d\n",pt->offset);
+ for(i=0;i<5;i++) {
+ printk("ptr1 %d: 0x%08x\n",i,ptr[i]);
+ }
+*/
+ return 0;
+}
+
+/********************************************************************************/
+/* interrupt handler */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
+static irqreturn_t interrupt_hw(int irq, void *dev_id, struct pt_regs *regs)
+#else
+static irqreturn_t interrupt_hw(int irq, void *dev_id)
+#endif
+{
+ struct saa7146_dev *dev = dev_id;
+ u32 isr;
+ u32 ack_isr;
+
+ /* read out the interrupt status register */
+ ack_isr = isr = saa7146_read(dev, ISR);
+
+ /* is this our interrupt? */
+ if ( 0 == isr ) {
+ /* nope, some other device */
+ return IRQ_NONE;
+ }
+
+ if (dev->ext) {
+ if (dev->ext->irq_mask & isr) {
+ if (dev->ext->irq_func)
+ dev->ext->irq_func(dev, &isr);
+ isr &= ~dev->ext->irq_mask;
+ }
+ }
+ if (0 != (isr & (MASK_27))) {
+ DEB_INT(("irq: RPS0 (0x%08x).\n",isr));
+ if (dev->vv_data && dev->vv_callback)
+ dev->vv_callback(dev,isr);
+ isr &= ~MASK_27;
+ }
+ if (0 != (isr & (MASK_28))) {
+ if (dev->vv_data && dev->vv_callback)
+ dev->vv_callback(dev,isr);
+ isr &= ~MASK_28;
+ }
+ if (0 != (isr & (MASK_16|MASK_17))) {
+ SAA7146_IER_DISABLE(dev, MASK_16|MASK_17);
+ /* only wake up if we expect something */
+ if (0 != dev->i2c_op) {
+ dev->i2c_op = 0;
+ wake_up(&dev->i2c_wq);
+ } else {
+ u32 psr = saa7146_read(dev, PSR);
+ u32 ssr = saa7146_read(dev, SSR);
+ printk(KERN_WARNING "%s: unexpected i2c irq: isr %08x psr %08x ssr %08x\n",
+ dev->name, isr, psr, ssr);
+ }
+ isr &= ~(MASK_16|MASK_17);
+ }
+ if( 0 != isr ) {
+ ERR(("warning: interrupt enabled, but not handled properly.(0x%08x)\n",isr));
+ ERR(("disabling interrupt source(s)!\n"));
+ SAA7146_IER_DISABLE(dev,isr);
+ }
+ saa7146_write(dev, ISR, ack_isr);
+ return IRQ_HANDLED;
+}
+
+/*********************************************************************************/
+/* configuration-functions */
+
+static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent)
+{
+ struct saa7146_pci_extension_data *pci_ext = (struct saa7146_pci_extension_data *)ent->driver_data;
+ struct saa7146_extension *ext = pci_ext->ext;
+ struct saa7146_dev *dev;
+ int err = -ENOMEM;
+
+ /* clear out mem for sure */
+ dev = kzalloc(sizeof(struct saa7146_dev), GFP_KERNEL);
+ if (!dev) {
+ ERR(("out of memory.\n"));
+ goto out;
+ }
+
+ DEB_EE(("pci:%p\n",pci));
+
+ err = pci_enable_device(pci);
+ if (err < 0) {
+ ERR(("pci_enable_device() failed.\n"));
+ goto err_free;
+ }
+
+ /* enable bus-mastering */
+ pci_set_master(pci);
+
+ dev->pci = pci;
+
+ /* get chip-revision; this is needed to enable bug-fixes */
+ err = pci_read_config_dword(pci, PCI_CLASS_REVISION, &dev->revision);
+ if (err < 0) {
+ ERR(("pci_read_config_dword() failed.\n"));
+ goto err_disable;
+ }
+ dev->revision &= 0xf;
+
+ /* remap the memory from virtual to physical address */
+
+ err = pci_request_region(pci, 0, "saa7146");
+ if (err < 0)
+ goto err_disable;
+
+ dev->mem = ioremap(pci_resource_start(pci, 0),
+ pci_resource_len(pci, 0));
+ if (!dev->mem) {
+ ERR(("ioremap() failed.\n"));
+ err = -ENODEV;
+ goto err_release;
+ }
+
+ /* we don't do a master reset here anymore, it screws up
+ some boards that don't have an i2c-eeprom for configuration
+ values */
+/*
+ saa7146_write(dev, MC1, MASK_31);
+*/
+
+ /* disable all irqs */
+ saa7146_write(dev, IER, 0);
+
+ /* shut down all dma transfers and rps tasks */
+ saa7146_write(dev, MC1, 0x30ff0000);
+
+ /* clear out any rps-signals pending */
+ saa7146_write(dev, MC2, 0xf8000000);
+
+ /* request an interrupt for the saa7146 */
+ err = request_irq(pci->irq, interrupt_hw, IRQF_SHARED | IRQF_DISABLED,
+ dev->name, dev);
+ if (err < 0) {
+ ERR(("request_irq() failed.\n"));
+ goto err_unmap;
+ }
+
+ err = -ENOMEM;
+
+ /* get memory for various stuff */
+ dev->d_rps0.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM,
+ &dev->d_rps0.dma_handle);
+ if (!dev->d_rps0.cpu_addr)
+ goto err_free_irq;
+ memset(dev->d_rps0.cpu_addr, 0x0, SAA7146_RPS_MEM);
+
+ dev->d_rps1.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM,
+ &dev->d_rps1.dma_handle);
+ if (!dev->d_rps1.cpu_addr)
+ goto err_free_rps0;
+ memset(dev->d_rps1.cpu_addr, 0x0, SAA7146_RPS_MEM);
+
+ dev->d_i2c.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM,
+ &dev->d_i2c.dma_handle);
+ if (!dev->d_i2c.cpu_addr)
+ goto err_free_rps1;
+ memset(dev->d_i2c.cpu_addr, 0x0, SAA7146_RPS_MEM);
+
+ /* the rest + print status message */
+
+ /* create a nice device name */
+ sprintf(dev->name, "saa7146 (%d)", saa7146_num);
+
+ INFO(("found saa7146 @ mem %p (revision %d, irq %d) (0x%04x,0x%04x).\n", dev->mem, dev->revision, pci->irq, pci->subsystem_vendor, pci->subsystem_device));
+ dev->ext = ext;
+
+ pci_set_drvdata(pci, dev);
+
+ mutex_init(&dev->lock);
+ spin_lock_init(&dev->int_slock);
+ spin_lock_init(&dev->slock);
+
+ mutex_init(&dev->i2c_lock);
+
+ dev->module = THIS_MODULE;
+ init_waitqueue_head(&dev->i2c_wq);
+
+ /* set some sane pci arbitrition values */
+ saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
+
+ /* TODO: use the status code of the callback */
+
+ err = -ENODEV;
+
+ if (ext->probe && ext->probe(dev)) {
+ DEB_D(("ext->probe() failed for %p. skipping device.\n",dev));
+ goto err_free_i2c;
+ }
+
+ if (ext->attach(dev, pci_ext)) {
+ DEB_D(("ext->attach() failed for %p. skipping device.\n",dev));
+ goto err_unprobe;
+ }
+
+ INIT_LIST_HEAD(&dev->item);
+ list_add_tail(&dev->item,&saa7146_devices);
+ saa7146_num++;
+
+ err = 0;
+out:
+ return err;
+
+err_unprobe:
+ pci_set_drvdata(pci, NULL);
+err_free_i2c:
+ pci_free_consistent(pci, SAA7146_RPS_MEM, dev->d_i2c.cpu_addr,
+ dev->d_i2c.dma_handle);
+err_free_rps1:
+ pci_free_consistent(pci, SAA7146_RPS_MEM, dev->d_rps1.cpu_addr,
+ dev->d_rps1.dma_handle);
+err_free_rps0:
+ pci_free_consistent(pci, SAA7146_RPS_MEM, dev->d_rps0.cpu_addr,
+ dev->d_rps0.dma_handle);
+err_free_irq:
+ free_irq(pci->irq, (void *)dev);
+err_unmap:
+ iounmap(dev->mem);
+err_release:
+ pci_release_region(pci, 0);
+err_disable:
+ pci_disable_device(pci);
+err_free:
+ kfree(dev);
+ goto out;
+}
+
+static void saa7146_remove_one(struct pci_dev *pdev)
+{
+ struct saa7146_dev* dev = pci_get_drvdata(pdev);
+ struct {
+ void *addr;
+ dma_addr_t dma;
+ } dev_map[] = {
+ { dev->d_i2c.cpu_addr, dev->d_i2c.dma_handle },
+ { dev->d_rps1.cpu_addr, dev->d_rps1.dma_handle },
+ { dev->d_rps0.cpu_addr, dev->d_rps0.dma_handle },
+ { NULL, 0 }
+ }, *p;
+
+ DEB_EE(("dev:%p\n",dev));
+
+ dev->ext->detach(dev);
+
+ /* shut down all video dma transfers */
+ saa7146_write(dev, MC1, 0x00ff0000);
+
+ /* disable all irqs, release irq-routine */
+ saa7146_write(dev, IER, 0);
+
+ free_irq(pdev->irq, dev);
+
+ for (p = dev_map; p->addr; p++)
+ pci_free_consistent(pdev, SAA7146_RPS_MEM, p->addr, p->dma);
+
+ iounmap(dev->mem);
+ pci_release_region(pdev, 0);
+ list_del(&dev->item);
+ pci_disable_device(pdev);
+ kfree(dev);
+
+ saa7146_num--;
+}
+
+/*********************************************************************************/
+/* extension handling functions */
+
+int saa7146_register_extension(struct saa7146_extension* ext)
+{
+ DEB_EE(("ext:%p\n",ext));
+
+ ext->driver.name = ext->name;
+ ext->driver.id_table = ext->pci_tbl;
+ ext->driver.probe = saa7146_init_one;
+ ext->driver.remove = saa7146_remove_one;
+
+ printk("saa7146: register extension '%s'.\n",ext->name);
+ return pci_register_driver(&ext->driver);
+}
+
+int saa7146_unregister_extension(struct saa7146_extension* ext)
+{
+ DEB_EE(("ext:%p\n",ext));
+ printk("saa7146: unregister extension '%s'.\n",ext->name);
+ pci_unregister_driver(&ext->driver);
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(saa7146_register_extension);
+EXPORT_SYMBOL_GPL(saa7146_unregister_extension);
+
+/* misc functions used by extension modules */
+EXPORT_SYMBOL_GPL(saa7146_pgtable_alloc);
+EXPORT_SYMBOL_GPL(saa7146_pgtable_free);
+EXPORT_SYMBOL_GPL(saa7146_pgtable_build_single);
+EXPORT_SYMBOL_GPL(saa7146_vmalloc_build_pgtable);
+EXPORT_SYMBOL_GPL(saa7146_vfree_destroy_pgtable);
+EXPORT_SYMBOL_GPL(saa7146_wait_for_debi_done);
+
+EXPORT_SYMBOL_GPL(saa7146_setgpio);
+
+EXPORT_SYMBOL_GPL(saa7146_i2c_adapter_prepare);
+
+EXPORT_SYMBOL_GPL(saa7146_debug);
+EXPORT_SYMBOL_GPL(saa7146_devices);
+EXPORT_SYMBOL_GPL(saa7146_devices_lock);
+
+MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
+MODULE_DESCRIPTION("driver for generic saa7146-based hardware");
+MODULE_LICENSE("GPL");
diff --git a/linux/drivers/media/video/saa7146/saa7146_fops.c b/linux/drivers/media/video/saa7146/saa7146_fops.c
new file mode 100644
index 000000000..ac035cbcf
--- /dev/null
+++ b/linux/drivers/media/video/saa7146/saa7146_fops.c
@@ -0,0 +1,595 @@
+#include <media/saa7146_vv.h>
+#include "compat.h"
+
+#define BOARD_CAN_DO_VBI(dev) (dev->revision != 0 && dev->vv_data->vbi_minor != -1)
+
+/****************************************************************************/
+/* resource management functions, shamelessly stolen from saa7134 driver */
+
+int saa7146_res_get(struct saa7146_fh *fh, unsigned int bit)
+{
+ struct saa7146_dev *dev = fh->dev;
+ struct saa7146_vv *vv = dev->vv_data;
+
+ if (fh->resources & bit) {
+ DEB_D(("already allocated! want: 0x%02x, cur:0x%02x\n",bit,vv->resources));
+ /* have it already allocated */
+ return 1;
+ }
+
+ /* is it free? */
+ mutex_lock(&dev->lock);
+ if (vv->resources & bit) {
+ DEB_D(("locked! vv->resources:0x%02x, we want:0x%02x\n",vv->resources,bit));
+ /* no, someone else uses it */
+ mutex_unlock(&dev->lock);
+ return 0;
+ }
+ /* it's free, grab it */
+ fh->resources |= bit;
+ vv->resources |= bit;
+ DEB_D(("res: get 0x%02x, cur:0x%02x\n",bit,vv->resources));
+ mutex_unlock(&dev->lock);
+ return 1;
+}
+
+void saa7146_res_free(struct saa7146_fh *fh, unsigned int bits)
+{
+ struct saa7146_dev *dev = fh->dev;
+ struct saa7146_vv *vv = dev->vv_data;
+
+ BUG_ON((fh->resources & bits) != bits);
+
+ mutex_lock(&dev->lock);
+ fh->resources &= ~bits;
+ vv->resources &= ~bits;
+ DEB_D(("res: put 0x%02x, cur:0x%02x\n",bits,vv->resources));
+ mutex_unlock(&dev->lock);
+}
+
+
+/********************************************************************************/
+/* common dma functions */
+
+void saa7146_dma_free(struct saa7146_dev *dev,struct videobuf_queue *q,
+ struct saa7146_buf *buf)
+{
+ struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+ DEB_EE(("dev:%p, buf:%p\n",dev,buf));
+
+ BUG_ON(in_interrupt());
+
+ videobuf_waiton(&buf->vb,0,0);
+ videobuf_dma_unmap(q, dma);
+ videobuf_dma_free(dma);
+ buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
+
+/********************************************************************************/
+/* common buffer functions */
+
+int saa7146_buffer_queue(struct saa7146_dev *dev,
+ struct saa7146_dmaqueue *q,
+ struct saa7146_buf *buf)
+{
+ assert_spin_locked(&dev->slock);
+ DEB_EE(("dev:%p, dmaq:%p, buf:%p\n", dev, q, buf));
+
+ BUG_ON(!q);
+
+ if (NULL == q->curr) {
+ q->curr = buf;
+ DEB_D(("immediately activating buffer %p\n", buf));
+ buf->activate(dev,buf,NULL);
+ } else {
+ list_add_tail(&buf->vb.queue,&q->queue);
+ buf->vb.state = VIDEOBUF_QUEUED;
+ DEB_D(("adding buffer %p to queue. (active buffer present)\n", buf));
+ }
+ return 0;
+}
+
+void saa7146_buffer_finish(struct saa7146_dev *dev,
+ struct saa7146_dmaqueue *q,
+ int state)
+{
+ assert_spin_locked(&dev->slock);
+ DEB_EE(("dev:%p, dmaq:%p, state:%d\n", dev, q, state));
+ DEB_EE(("q->curr:%p\n",q->curr));
+
+ BUG_ON(!q->curr);
+
+ /* finish current buffer */
+ if (NULL == q->curr) {
+ DEB_D(("aiii. no current buffer\n"));
+ return;
+ }
+
+ q->curr->vb.state = state;
+ do_gettimeofday(&q->curr->vb.ts);
+ wake_up(&q->curr->vb.done);
+
+ q->curr = NULL;
+}
+
+void saa7146_buffer_next(struct saa7146_dev *dev,
+ struct saa7146_dmaqueue *q, int vbi)
+{
+ struct saa7146_buf *buf,*next = NULL;
+
+ BUG_ON(!q);
+
+ DEB_INT(("dev:%p, dmaq:%p, vbi:%d\n", dev, q, vbi));
+
+ assert_spin_locked(&dev->slock);
+ if (!list_empty(&q->queue)) {
+ /* activate next one from queue */
+ buf = list_entry(q->queue.next,struct saa7146_buf,vb.queue);
+ list_del(&buf->vb.queue);
+ if (!list_empty(&q->queue))
+ next = list_entry(q->queue.next,struct saa7146_buf, vb.queue);
+ q->curr = buf;
+ DEB_INT(("next buffer: buf:%p, prev:%p, next:%p\n", buf, q->queue.prev,q->queue.next));
+ buf->activate(dev,buf,next);
+ } else {
+ DEB_INT(("no next buffer. stopping.\n"));
+ if( 0 != vbi ) {
+ /* turn off video-dma3 */
+ saa7146_write(dev,MC1, MASK_20);
+ } else {
+ /* nothing to do -- just prevent next video-dma1 transfer
+ by lowering the protection address */
+
+ // fixme: fix this for vflip != 0
+
+ saa7146_write(dev, PROT_ADDR1, 0);
+ saa7146_write(dev, MC2, (MASK_02|MASK_18));
+
+ /* write the address of the rps-program */
+ saa7146_write(dev, RPS_ADDR0, dev->d_rps0.dma_handle);
+ /* turn on rps */
+ saa7146_write(dev, MC1, (MASK_12 | MASK_28));
+
+/*
+ printk("vdma%d.base_even: 0x%08x\n", 1,saa7146_read(dev,BASE_EVEN1));
+ printk("vdma%d.base_odd: 0x%08x\n", 1,saa7146_read(dev,BASE_ODD1));
+ printk("vdma%d.prot_addr: 0x%08x\n", 1,saa7146_read(dev,PROT_ADDR1));
+ printk("vdma%d.base_page: 0x%08x\n", 1,saa7146_read(dev,BASE_PAGE1));
+ printk("vdma%d.pitch: 0x%08x\n", 1,saa7146_read(dev,PITCH1));
+ printk("vdma%d.num_line_byte: 0x%08x\n", 1,saa7146_read(dev,NUM_LINE_BYTE1));
+*/
+ }
+ del_timer(&q->timeout);
+ }
+}
+
+void saa7146_buffer_timeout(unsigned long data)
+{
+ struct saa7146_dmaqueue *q = (struct saa7146_dmaqueue*)data;
+ struct saa7146_dev *dev = q->dev;
+ unsigned long flags;
+
+ DEB_EE(("dev:%p, dmaq:%p\n", dev, q));
+
+ spin_lock_irqsave(&dev->slock,flags);
+ if (q->curr) {
+ DEB_D(("timeout on %p\n", q->curr));
+ saa7146_buffer_finish(dev,q,VIDEOBUF_ERROR);
+ }
+
+ /* we don't restart the transfer here like other drivers do. when
+ a streaming capture is disabled, the timeout function will be
+ called for the current buffer. if we activate the next buffer now,
+ we mess up our capture logic. if a timeout occurs on another buffer,
+ then something is seriously broken before, so no need to buffer the
+ next capture IMHO... */
+/*
+ saa7146_buffer_next(dev,q);
+*/
+ spin_unlock_irqrestore(&dev->slock,flags);
+}
+
+/********************************************************************************/
+/* file operations */
+
+static int fops_open(struct inode *inode, struct file *file)
+{
+ unsigned int minor = iminor(inode);
+ struct saa7146_dev *h = NULL, *dev = NULL;
+ struct list_head *list;
+ struct saa7146_fh *fh = NULL;
+ int result = 0;
+
+ enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ DEB_EE(("inode:%p, file:%p, minor:%d\n",inode,file,minor));
+
+ if (mutex_lock_interruptible(&saa7146_devices_lock))
+ return -ERESTARTSYS;
+
+ list_for_each(list,&saa7146_devices) {
+ h = list_entry(list, struct saa7146_dev, item);
+ if( NULL == h->vv_data ) {
+ DEB_D(("device %p has not registered video devices.\n",h));
+ continue;
+ }
+ DEB_D(("trying: %p @ major %d,%d\n",h,h->vv_data->video_minor,h->vv_data->vbi_minor));
+
+ if (h->vv_data->video_minor == minor) {
+ dev = h;
+ }
+ if (h->vv_data->vbi_minor == minor) {
+ type = V4L2_BUF_TYPE_VBI_CAPTURE;
+ dev = h;
+ }
+ }
+ if (NULL == dev) {
+ DEB_S(("no such video device.\n"));
+ result = -ENODEV;
+ goto out;
+ }
+
+ DEB_D(("using: %p\n",dev));
+
+ /* check if an extension is registered */
+ if( NULL == dev->ext ) {
+ DEB_S(("no extension registered for this device.\n"));
+ result = -ENODEV;
+ goto out;
+ }
+
+ /* allocate per open data */
+ fh = kzalloc(sizeof(*fh),GFP_KERNEL);
+ if (NULL == fh) {
+ DEB_S(("cannot allocate memory for per open data.\n"));
+ result = -ENOMEM;
+ goto out;
+ }
+
+ file->private_data = fh;
+ fh->dev = dev;
+ fh->type = type;
+
+ if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
+ DEB_S(("initializing vbi...\n"));
+ if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
+ result = saa7146_vbi_uops.open(dev,file);
+ if (dev->ext_vv_data->vbi_fops.open)
+ dev->ext_vv_data->vbi_fops.open(inode, file);
+ } else {
+ DEB_S(("initializing video...\n"));
+ result = saa7146_video_uops.open(dev,file);
+ }
+
+ if (0 != result) {
+ goto out;
+ }
+
+ if( 0 == try_module_get(dev->ext->module)) {
+ result = -EINVAL;
+ goto out;
+ }
+
+ result = 0;
+out:
+ if (fh && result != 0) {
+ kfree(fh);
+ file->private_data = NULL;
+ }
+ mutex_unlock(&saa7146_devices_lock);
+ return result;
+}
+
+static int fops_release(struct inode *inode, struct file *file)
+{
+ struct saa7146_fh *fh = file->private_data;
+ struct saa7146_dev *dev = fh->dev;
+
+ DEB_EE(("inode:%p, file:%p\n",inode,file));
+
+ if (mutex_lock_interruptible(&saa7146_devices_lock))
+ return -ERESTARTSYS;
+
+ if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
+ if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
+ saa7146_vbi_uops.release(dev,file);
+ if (dev->ext_vv_data->vbi_fops.release)
+ dev->ext_vv_data->vbi_fops.release(inode, file);
+ } else {
+ saa7146_video_uops.release(dev,file);
+ }
+
+ module_put(dev->ext->module);
+ file->private_data = NULL;
+ kfree(fh);
+
+ mutex_unlock(&saa7146_devices_lock);
+
+ return 0;
+}
+
+static int fops_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+/*
+ DEB_EE(("inode:%p, file:%p, cmd:%d, arg:%li\n",inode, file, cmd, arg));
+*/
+ return video_usercopy(inode, file, cmd, arg, saa7146_video_do_ioctl);
+}
+
+static int fops_mmap(struct file *file, struct vm_area_struct * vma)
+{
+ struct saa7146_fh *fh = file->private_data;
+ struct videobuf_queue *q;
+
+ switch (fh->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
+ DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, vma:%p\n",file, vma));
+ q = &fh->video_q;
+ break;
+ }
+ case V4L2_BUF_TYPE_VBI_CAPTURE: {
+ DEB_EE(("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, vma:%p\n",file, vma));
+ q = &fh->vbi_q;
+ break;
+ }
+ default:
+ BUG();
+ return 0;
+ }
+
+ return videobuf_mmap_mapper(q,vma);
+}
+
+static unsigned int fops_poll(struct file *file, struct poll_table_struct *wait)
+{
+ struct saa7146_fh *fh = file->private_data;
+ struct videobuf_buffer *buf = NULL;
+ struct videobuf_queue *q;
+
+ DEB_EE(("file:%p, poll:%p\n",file, wait));
+
+ if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
+ if( 0 == fh->vbi_q.streaming )
+ return videobuf_poll_stream(file, &fh->vbi_q, wait);
+ q = &fh->vbi_q;
+ } else {
+ DEB_D(("using video queue.\n"));
+ q = &fh->video_q;
+ }
+
+ if (!list_empty(&q->stream))
+ buf = list_entry(q->stream.next, struct videobuf_buffer, stream);
+
+ if (!buf) {
+ DEB_D(("buf == NULL!\n"));
+ return POLLERR;
+ }
+
+ poll_wait(file, &buf->done, wait);
+ if (buf->state == VIDEOBUF_DONE || buf->state == VIDEOBUF_ERROR) {
+ DEB_D(("poll succeeded!\n"));
+ return POLLIN|POLLRDNORM;
+ }
+
+ DEB_D(("nothing to poll for, buf->state:%d\n",buf->state));
+ return 0;
+}
+
+static ssize_t fops_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
+{
+ struct saa7146_fh *fh = file->private_data;
+
+ switch (fh->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
+// DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, data:%p, count:%lun", file, data, (unsigned long)count));
+ return saa7146_video_uops.read(file,data,count,ppos);
+ }
+ case V4L2_BUF_TYPE_VBI_CAPTURE: {
+// DEB_EE(("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%lu\n", file, data, (unsigned long)count));
+ if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
+ return saa7146_vbi_uops.read(file,data,count,ppos);
+ else
+ return -EINVAL;
+ }
+ break;
+ default:
+ BUG();
+ return 0;
+ }
+}
+
+static ssize_t fops_write(struct file *file, const char __user *data, size_t count, loff_t *ppos)
+{
+ struct saa7146_fh *fh = file->private_data;
+
+ switch (fh->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ return -EINVAL;
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ if (fh->dev->ext_vv_data->vbi_fops.write)
+ return fh->dev->ext_vv_data->vbi_fops.write(file, data, count, ppos);
+ else
+ return -EINVAL;
+ default:
+ BUG();
+ return -EINVAL;
+ }
+}
+
+static const struct file_operations video_fops =
+{
+ .owner = THIS_MODULE,
+ .open = fops_open,
+ .release = fops_release,
+ .read = fops_read,
+ .write = fops_write,
+ .poll = fops_poll,
+ .mmap = fops_mmap,
+ .ioctl = fops_ioctl,
+ .llseek = no_llseek,
+};
+
+static void vv_callback(struct saa7146_dev *dev, unsigned long status)
+{
+ u32 isr = status;
+
+ DEB_INT(("dev:%p, isr:0x%08x\n",dev,(u32)status));
+
+ if (0 != (isr & (MASK_27))) {
+ DEB_INT(("irq: RPS0 (0x%08x).\n",isr));
+ saa7146_video_uops.irq_done(dev,isr);
+ }
+
+ if (0 != (isr & (MASK_28))) {
+ u32 mc2 = saa7146_read(dev, MC2);
+ if( 0 != (mc2 & MASK_15)) {
+ DEB_INT(("irq: RPS1 vbi workaround (0x%08x).\n",isr));
+ wake_up(&dev->vv_data->vbi_wq);
+ saa7146_write(dev,MC2, MASK_31);
+ return;
+ }
+ DEB_INT(("irq: RPS1 (0x%08x).\n",isr));
+ saa7146_vbi_uops.irq_done(dev,isr);
+ }
+}
+
+static struct video_device device_template =
+{
+ .fops = &video_fops,
+ .minor = -1,
+};
+
+int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
+{
+ struct saa7146_vv *vv = kzalloc (sizeof(struct saa7146_vv),GFP_KERNEL);
+ if( NULL == vv ) {
+ ERR(("out of memory. aborting.\n"));
+ return -1;
+ }
+
+ DEB_EE(("dev:%p\n",dev));
+
+ /* set default values for video parts of the saa7146 */
+ saa7146_write(dev, BCS_CTRL, 0x80400040);
+
+ /* enable video-port pins */
+ saa7146_write(dev, MC1, (MASK_10 | MASK_26));
+
+ /* save per-device extension data (one extension can
+ handle different devices that might need different
+ configuration data) */
+ dev->ext_vv_data = ext_vv;
+
+ vv->video_minor = -1;
+ vv->vbi_minor = -1;
+
+ vv->d_clipping.cpu_addr = pci_alloc_consistent(dev->pci, SAA7146_CLIPPING_MEM, &vv->d_clipping.dma_handle);
+ if( NULL == vv->d_clipping.cpu_addr ) {
+ ERR(("out of memory. aborting.\n"));
+ kfree(vv);
+ return -1;
+ }
+ memset(vv->d_clipping.cpu_addr, 0x0, SAA7146_CLIPPING_MEM);
+
+ saa7146_video_uops.init(dev,vv);
+ if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
+ saa7146_vbi_uops.init(dev,vv);
+
+ dev->vv_data = vv;
+ dev->vv_callback = &vv_callback;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(saa7146_vv_init);
+
+int saa7146_vv_release(struct saa7146_dev* dev)
+{
+ struct saa7146_vv *vv = dev->vv_data;
+
+ DEB_EE(("dev:%p\n",dev));
+
+ pci_free_consistent(dev->pci, SAA7146_CLIPPING_MEM, vv->d_clipping.cpu_addr, vv->d_clipping.dma_handle);
+ kfree(vv);
+ dev->vv_data = NULL;
+ dev->vv_callback = NULL;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(saa7146_vv_release);
+
+int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
+ char *name, int type)
+{
+ struct saa7146_vv *vv = dev->vv_data;
+ struct video_device *vfd;
+
+ DEB_EE(("dev:%p, name:'%s', type:%d\n",dev,name,type));
+
+ // released by vfd->release
+ vfd = video_device_alloc();
+ if (vfd == NULL)
+ return -ENOMEM;
+
+ memcpy(vfd, &device_template, sizeof(struct video_device));
+ strlcpy(vfd->name, name, sizeof(vfd->name));
+ vfd->release = video_device_release;
+ vfd->priv = dev;
+
+ // fixme: -1 should be an insmod parameter *for the extension* (like "video_nr");
+ if (video_register_device(vfd, type, -1) < 0) {
+ ERR(("cannot register v4l2 device. skipping.\n"));
+ video_device_release(vfd);
+ return -1;
+ }
+
+ if( VFL_TYPE_GRABBER == type ) {
+ vv->video_minor = vfd->minor;
+ INFO(("%s: registered device video%d [v4l2]\n",
+ dev->name, vfd->minor & 0x1f));
+ } else {
+ vv->vbi_minor = vfd->minor;
+ INFO(("%s: registered device vbi%d [v4l2]\n",
+ dev->name, vfd->minor & 0x1f));
+ }
+
+ *vid = vfd;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(saa7146_register_device);
+
+int saa7146_unregister_device(struct video_device **vid, struct saa7146_dev* dev)
+{
+ struct saa7146_vv *vv = dev->vv_data;
+
+ DEB_EE(("dev:%p\n",dev));
+
+ if( VFL_TYPE_GRABBER == (*vid)->type ) {
+ vv->video_minor = -1;
+ } else {
+ vv->vbi_minor = -1;
+ }
+
+ video_unregister_device(*vid);
+ *vid = NULL;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(saa7146_unregister_device);
+
+static int __init saa7146_vv_init_module(void)
+{
+ return 0;
+}
+
+
+static void __exit saa7146_vv_cleanup_module(void)
+{
+}
+
+module_init(saa7146_vv_init_module);
+module_exit(saa7146_vv_cleanup_module);
+
+MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
+MODULE_DESCRIPTION("video4linux driver for saa7146-based hardware");
+MODULE_LICENSE("GPL");
diff --git a/linux/drivers/media/video/saa7146/saa7146_hlp.c b/linux/drivers/media/video/saa7146/saa7146_hlp.c
new file mode 100644
index 000000000..c0f3f51f9
--- /dev/null
+++ b/linux/drivers/media/video/saa7146/saa7146_hlp.c
@@ -0,0 +1,1045 @@
+#include <linux/kernel.h>
+#include <media/saa7146_vv.h>
+#include "compat.h"
+
+static void calculate_output_format_register(struct saa7146_dev* saa, u32 palette, u32* clip_format)
+{
+ /* clear out the necessary bits */
+ *clip_format &= 0x0000ffff;
+ /* set these bits new */
+ *clip_format |= (( ((palette&0xf00)>>8) << 30) | ((palette&0x00f) << 24) | (((palette&0x0f0)>>4) << 16));
+}
+
+static void calculate_hps_source_and_sync(struct saa7146_dev *dev, int source, int sync, u32* hps_ctrl)
+{
+ *hps_ctrl &= ~(MASK_30 | MASK_31 | MASK_28);
+ *hps_ctrl |= (source << 30) | (sync << 28);
+}
+
+static void calculate_hxo_and_hyo(struct saa7146_vv *vv, u32* hps_h_scale, u32* hps_ctrl)
+{
+ int hyo = 0, hxo = 0;
+
+ hyo = vv->standard->v_offset;
+ hxo = vv->standard->h_offset;
+
+ *hps_h_scale &= ~(MASK_B0 | 0xf00);
+ *hps_h_scale |= (hxo << 0);
+
+ *hps_ctrl &= ~(MASK_W0 | MASK_B2);
+ *hps_ctrl |= (hyo << 12);
+}
+
+/* helper functions for the calculation of the horizontal- and vertical
+ scaling registers, clip-format-register etc ...
+ these functions take pointers to the (most-likely read-out
+ original-values) and manipulate them according to the requested
+ changes.
+*/
+
+/* hps_coeff used for CXY and CXUV; scale 1/1 -> scale 1/64 */
+static struct {
+ u16 hps_coeff;
+ u16 weight_sum;
+} hps_h_coeff_tab [] = {
+ {0x00, 2}, {0x02, 4}, {0x00, 4}, {0x06, 8}, {0x02, 8},
+ {0x08, 8}, {0x00, 8}, {0x1E, 16}, {0x0E, 8}, {0x26, 8},
+ {0x06, 8}, {0x42, 8}, {0x02, 8}, {0x80, 8}, {0x00, 8},
+ {0xFE, 16}, {0xFE, 8}, {0x7E, 8}, {0x7E, 8}, {0x3E, 8},
+ {0x3E, 8}, {0x1E, 8}, {0x1E, 8}, {0x0E, 8}, {0x0E, 8},
+ {0x06, 8}, {0x06, 8}, {0x02, 8}, {0x02, 8}, {0x00, 8},
+ {0x00, 8}, {0xFE, 16}, {0xFE, 8}, {0xFE, 8}, {0xFE, 8},
+ {0xFE, 8}, {0xFE, 8}, {0xFE, 8}, {0xFE, 8}, {0xFE, 8},
+ {0xFE, 8}, {0xFE, 8}, {0xFE, 8}, {0xFE, 8}, {0xFE, 8},
+ {0xFE, 8}, {0xFE, 8}, {0xFE, 8}, {0xFE, 8}, {0x7E, 8},
+ {0x7E, 8}, {0x3E, 8}, {0x3E, 8}, {0x1E, 8}, {0x1E, 8},
+ {0x0E, 8}, {0x0E, 8}, {0x06, 8}, {0x06, 8}, {0x02, 8},
+ {0x02, 8}, {0x00, 8}, {0x00, 8}, {0xFE, 16}
+};
+
+/* table of attenuation values for horizontal scaling */
+static u8 h_attenuation[] = { 1, 2, 4, 8, 2, 4, 8, 16, 0};
+
+/* calculate horizontal scale registers */
+static int calculate_h_scale_registers(struct saa7146_dev *dev,
+ int in_x, int out_x, int flip_lr,
+ u32* hps_ctrl, u32* hps_v_gain, u32* hps_h_prescale, u32* hps_h_scale)
+{
+ /* horizontal prescaler */
+ u32 dcgx = 0, xpsc = 0, xacm = 0, cxy = 0, cxuv = 0;
+ /* horizontal scaler */
+ u32 xim = 0, xp = 0, xsci =0;
+ /* vertical scale & gain */
+ u32 pfuv = 0;
+
+ /* helper variables */
+ u32 h_atten = 0, i = 0;
+
+ if ( 0 == out_x ) {
+ return -EINVAL;
+ }
+
+ /* mask out vanity-bit */
+ *hps_ctrl &= ~MASK_29;
+
+ /* calculate prescale-(xspc)-value: [n .. 1/2) : 1
+ [1/2 .. 1/3) : 2
+ [1/3 .. 1/4) : 3
+ ... */
+ if (in_x > out_x) {
+ xpsc = in_x / out_x;
+ }
+ else {
+ /* zooming */
+ xpsc = 1;
+ }
+
+ /* if flip_lr-bit is set, number of pixels after
+ horizontal prescaling must be < 384 */
+ if ( 0 != flip_lr ) {
+
+ /* set vanity bit */
+ *hps_ctrl |= MASK_29;
+
+ while (in_x / xpsc >= 384 )
+ xpsc++;
+ }
+ /* if zooming is wanted, number of pixels after
+ horizontal prescaling must be < 768 */
+ else {
+ while ( in_x / xpsc >= 768 )
+ xpsc++;
+ }
+
+ /* maximum prescale is 64 (p.69) */
+ if ( xpsc > 64 )
+ xpsc = 64;
+
+ /* keep xacm clear*/
+ xacm = 0;
+
+ /* set horizontal filter parameters (CXY = CXUV) */
+ cxy = hps_h_coeff_tab[( (xpsc - 1) < 63 ? (xpsc - 1) : 63 )].hps_coeff;
+ cxuv = cxy;
+
+ /* calculate and set horizontal fine scale (xsci) */
+
+ /* bypass the horizontal scaler ? */
+ if ( (in_x == out_x) && ( 1 == xpsc ) )
+ xsci = 0x400;
+ else
+ xsci = ( (1024 * in_x) / (out_x * xpsc) ) + xpsc;
+
+ /* set start phase for horizontal fine scale (xp) to 0 */
+ xp = 0;
+
+ /* set xim, if we bypass the horizontal scaler */
+ if ( 0x400 == xsci )
+ xim = 1;
+ else
+ xim = 0;
+
+ /* if the prescaler is bypassed, enable horizontal
+ accumulation mode (xacm) and clear dcgx */
+ if( 1 == xpsc ) {
+ xacm = 1;
+ dcgx = 0;
+ } else {
+ xacm = 0;
+ /* get best match in the table of attenuations
+ for horizontal scaling */
+ h_atten = hps_h_coeff_tab[( (xpsc - 1) < 63 ? (xpsc - 1) : 63 )].weight_sum;
+
+ for (i = 0; h_attenuation[i] != 0; i++) {
+ if (h_attenuation[i] >= h_atten)
+ break;
+ }
+
+ dcgx = i;
+ }
+
+ /* the horizontal scaling increment controls the UV filter
+ to reduce the bandwidth to improve the display quality,
+ so set it ... */
+ if ( xsci == 0x400)
+ pfuv = 0x00;
+ else if ( xsci < 0x600)
+ pfuv = 0x01;
+ else if ( xsci < 0x680)
+ pfuv = 0x11;
+ else if ( xsci < 0x700)
+ pfuv = 0x22;
+ else
+ pfuv = 0x33;
+
+
+ *hps_v_gain &= MASK_W0|MASK_B2;
+ *hps_v_gain |= (pfuv << 24);
+
+ *hps_h_scale &= ~(MASK_W1 | 0xf000);
+ *hps_h_scale |= (xim << 31) | (xp << 24) | (xsci << 12);
+
+ *hps_h_prescale |= (dcgx << 27) | ((xpsc-1) << 18) | (xacm << 17) | (cxy << 8) | (cxuv << 0);
+
+ return 0;
+}
+
+static struct {
+ u16 hps_coeff;
+ u16 weight_sum;
+} hps_v_coeff_tab [] = {
+ {0x0100, 2}, {0x0102, 4}, {0x0300, 4}, {0x0106, 8}, {0x0502, 8},
+ {0x0708, 8}, {0x0F00, 8}, {0x011E, 16}, {0x110E, 16}, {0x1926, 16},
+ {0x3906, 16}, {0x3D42, 16}, {0x7D02, 16}, {0x7F80, 16}, {0xFF00, 16},
+ {0x01FE, 32}, {0x01FE, 32}, {0x817E, 32}, {0x817E, 32}, {0xC13E, 32},
+ {0xC13E, 32}, {0xE11E, 32}, {0xE11E, 32}, {0xF10E, 32}, {0xF10E, 32},
+ {0xF906, 32}, {0xF906, 32}, {0xFD02, 32}, {0xFD02, 32}, {0xFF00, 32},
+ {0xFF00, 32}, {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64},
+ {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64},
+ {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64},
+ {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64}, {0x817E, 64},
+ {0x817E, 64}, {0xC13E, 64}, {0xC13E, 64}, {0xE11E, 64}, {0xE11E, 64},
+ {0xF10E, 64}, {0xF10E, 64}, {0xF906, 64}, {0xF906, 64}, {0xFD02, 64},
+ {0xFD02, 64}, {0xFF00, 64}, {0xFF00, 64}, {0x01FE, 128}
+};
+
+/* table of attenuation values for vertical scaling */
+static u16 v_attenuation[] = { 2, 4, 8, 16, 32, 64, 128, 256, 0};
+
+/* calculate vertical scale registers */
+static int calculate_v_scale_registers(struct saa7146_dev *dev, enum v4l2_field field,
+ int in_y, int out_y, u32* hps_v_scale, u32* hps_v_gain)
+{
+ int lpi = 0;
+
+ /* vertical scaling */
+ u32 yacm = 0, ysci = 0, yacl = 0, ypo = 0, ype = 0;
+ /* vertical scale & gain */
+ u32 dcgy = 0, cya_cyb = 0;
+
+ /* helper variables */
+ u32 v_atten = 0, i = 0;
+
+ /* error, if vertical zooming */
+ if ( in_y < out_y ) {
+ return -EINVAL;
+ }
+
+ /* linear phase interpolation may be used
+ if scaling is between 1 and 1/2 (both fields used)
+ or scaling is between 1/2 and 1/4 (if only one field is used) */
+
+ if (V4L2_FIELD_HAS_BOTH(field)) {
+ if( 2*out_y >= in_y) {
+ lpi = 1;
+ }
+ } else if (field == V4L2_FIELD_TOP
+ || field == V4L2_FIELD_ALTERNATE
+ || field == V4L2_FIELD_BOTTOM) {
+ if( 4*out_y >= in_y ) {
+ lpi = 1;
+ }
+ out_y *= 2;
+ }
+ if( 0 != lpi ) {
+
+ yacm = 0;
+ yacl = 0;
+ cya_cyb = 0x00ff;
+
+ /* calculate scaling increment */
+ if ( in_y > out_y )
+ ysci = ((1024 * in_y) / (out_y + 1)) - 1024;
+ else
+ ysci = 0;
+
+ dcgy = 0;
+
+ /* calculate ype and ypo */
+ ype = ysci / 16;
+ ypo = ype + (ysci / 64);
+
+ } else {
+ yacm = 1;
+
+ /* calculate scaling increment */
+ ysci = (((10 * 1024 * (in_y - out_y - 1)) / in_y) + 9) / 10;
+
+ /* calculate ype and ypo */
+ ypo = ype = ((ysci + 15) / 16);
+
+ /* the sequence length interval (yacl) has to be set according
+ to the prescale value, e.g. [n .. 1/2) : 0
+ [1/2 .. 1/3) : 1
+ [1/3 .. 1/4) : 2
+ ... */
+ if ( ysci < 512) {
+ yacl = 0;
+ } else {
+ yacl = ( ysci / (1024 - ysci) );
+ }
+
+ /* get filter coefficients for cya, cyb from table hps_v_coeff_tab */
+ cya_cyb = hps_v_coeff_tab[ (yacl < 63 ? yacl : 63 ) ].hps_coeff;
+
+ /* get best match in the table of attenuations for vertical scaling */
+ v_atten = hps_v_coeff_tab[ (yacl < 63 ? yacl : 63 ) ].weight_sum;
+
+ for (i = 0; v_attenuation[i] != 0; i++) {
+ if (v_attenuation[i] >= v_atten)
+ break;
+ }
+
+ dcgy = i;
+ }
+
+ /* ypo and ype swapped in spec ? */
+ *hps_v_scale |= (yacm << 31) | (ysci << 21) | (yacl << 15) | (ypo << 8 ) | (ype << 1);
+
+ *hps_v_gain &= ~(MASK_W0|MASK_B2);
+ *hps_v_gain |= (dcgy << 16) | (cya_cyb << 0);
+
+ return 0;
+}
+
+/* simple bubble-sort algorithm with duplicate elimination */
+static int sort_and_eliminate(u32* values, int* count)
+{
+ int low = 0, high = 0, top = 0, temp = 0;
+ int cur = 0, next = 0;
+
+ /* sanity checks */
+ if( (0 > *count) || (NULL == values) ) {
+ return -EINVAL;
+ }
+
+ /* bubble sort the first @count items of the array @values */
+ for( top = *count; top > 0; top--) {
+ for( low = 0, high = 1; high < top; low++, high++) {
+ if( values[low] > values[high] ) {
+ temp = values[low];
+ values[low] = values[high];
+ values[high] = temp;
+ }
+ }
+ }
+
+ /* remove duplicate items */
+ for( cur = 0, next = 1; next < *count; next++) {
+ if( values[cur] != values[next])
+ values[++cur] = values[next];
+ }
+
+ *count = cur + 1;
+
+ return 0;
+}
+
+static void calculate_clipping_registers_rect(struct saa7146_dev *dev, struct saa7146_fh *fh,
+ struct saa7146_video_dma *vdma2, u32* clip_format, u32* arbtr_ctrl, enum v4l2_field field)
+{
+ struct saa7146_vv *vv = dev->vv_data;
+ u32 *clipping = vv->d_clipping.cpu_addr;
+
+ int width = fh->ov.win.w.width;
+ int height = fh->ov.win.w.height;
+ int clipcount = fh->ov.nclips;
+
+ u32 line_list[32];
+ u32 pixel_list[32];
+ int numdwords = 0;
+
+ int i = 0, j = 0;
+ int cnt_line = 0, cnt_pixel = 0;
+
+ int x[32], y[32], w[32], h[32];
+
+ /* clear out memory */
+ memset(&line_list[0], 0x00, sizeof(u32)*32);
+ memset(&pixel_list[0], 0x00, sizeof(u32)*32);
+ memset(clipping, 0x00, SAA7146_CLIPPING_MEM);
+
+ /* fill the line and pixel-lists */
+ for(i = 0; i < clipcount; i++) {
+ int l = 0, r = 0, t = 0, b = 0;
+
+ x[i] = fh->ov.clips[i].c.left;
+ y[i] = fh->ov.clips[i].c.top;
+ w[i] = fh->ov.clips[i].c.width;
+ h[i] = fh->ov.clips[i].c.height;
+
+ if( w[i] < 0) {
+ x[i] += w[i]; w[i] = -w[i];
+ }
+ if( h[i] < 0) {
+ y[i] += h[i]; h[i] = -h[i];
+ }
+ if( x[i] < 0) {
+ w[i] += x[i]; x[i] = 0;
+ }
+ if( y[i] < 0) {
+ h[i] += y[i]; y[i] = 0;
+ }
+ if( 0 != vv->vflip ) {
+ y[i] = height - y[i] - h[i];
+ }
+
+ l = x[i];
+ r = x[i]+w[i];
+ t = y[i];
+ b = y[i]+h[i];
+
+ /* insert left/right coordinates */
+ pixel_list[ 2*i ] = min_t(int, l, width);
+ pixel_list[(2*i)+1] = min_t(int, r, width);
+ /* insert top/bottom coordinates */
+ line_list[ 2*i ] = min_t(int, t, height);
+ line_list[(2*i)+1] = min_t(int, b, height);
+ }
+
+ /* sort and eliminate lists */
+ cnt_line = cnt_pixel = 2*clipcount;
+ sort_and_eliminate( &pixel_list[0], &cnt_pixel );
+ sort_and_eliminate( &line_list[0], &cnt_line );
+
+ /* calculate the number of used u32s */
+ numdwords = max_t(int, (cnt_line+1), (cnt_pixel+1))*2;
+ numdwords = max_t(int, 4, numdwords);
+ numdwords = min_t(int, 64, numdwords);
+
+ /* fill up cliptable */
+ for(i = 0; i < cnt_pixel; i++) {
+ clipping[2*i] |= cpu_to_le32(pixel_list[i] << 16);
+ }
+ for(i = 0; i < cnt_line; i++) {
+ clipping[(2*i)+1] |= cpu_to_le32(line_list[i] << 16);
+ }
+
+ /* fill up cliptable with the display infos */
+ for(j = 0; j < clipcount; j++) {
+
+ for(i = 0; i < cnt_pixel; i++) {
+
+ if( x[j] < 0)
+ x[j] = 0;
+
+ if( pixel_list[i] < (x[j] + w[j])) {
+
+ if ( pixel_list[i] >= x[j] ) {
+ clipping[2*i] |= cpu_to_le32(1 << j);
+ }
+ }
+ }
+ for(i = 0; i < cnt_line; i++) {
+
+ if( y[j] < 0)
+ y[j] = 0;
+
+ if( line_list[i] < (y[j] + h[j]) ) {
+
+ if( line_list[i] >= y[j] ) {
+ clipping[(2*i)+1] |= cpu_to_le32(1 << j);
+ }
+ }
+ }
+ }
+
+ /* adjust arbitration control register */
+ *arbtr_ctrl &= 0xffff00ff;
+ *arbtr_ctrl |= 0x00001c00;
+
+ vdma2->base_even = vv->d_clipping.dma_handle;
+ vdma2->base_odd = vv->d_clipping.dma_handle;
+ vdma2->prot_addr = vv->d_clipping.dma_handle+((sizeof(u32))*(numdwords));
+ vdma2->base_page = 0x04;
+ vdma2->pitch = 0x00;
+ vdma2->num_line_byte = (0 << 16 | (sizeof(u32))*(numdwords-1) );
+
+ /* set clipping-mode. this depends on the field(s) used */
+ *clip_format &= 0xfffffff7;
+ if (V4L2_FIELD_HAS_BOTH(field)) {
+ *clip_format |= 0x00000008;
+ } else {
+ *clip_format |= 0x00000000;
+ }
+}
+
+/* disable clipping */
+static void saa7146_disable_clipping(struct saa7146_dev *dev)
+{
+ u32 clip_format = saa7146_read(dev, CLIP_FORMAT_CTRL);
+
+ /* mask out relevant bits (=lower word)*/
+ clip_format &= MASK_W1;
+
+ /* upload clipping-registers*/
+ saa7146_write(dev, CLIP_FORMAT_CTRL,clip_format);
+ saa7146_write(dev, MC2, (MASK_05 | MASK_21));
+
+ /* disable video dma2 */
+ saa7146_write(dev, MC1, MASK_21);
+}
+
+static void saa7146_set_clipping_rect(struct saa7146_fh *fh)
+{
+ struct saa7146_dev *dev = fh->dev;
+ enum v4l2_field field = fh->ov.win.field;
+ struct saa7146_video_dma vdma2;
+ u32 clip_format;
+ u32 arbtr_ctrl;
+
+ /* check clipcount, disable clipping if clipcount == 0*/
+ if( fh->ov.nclips == 0 ) {
+ saa7146_disable_clipping(dev);
+ return;
+ }
+
+ clip_format = saa7146_read(dev, CLIP_FORMAT_CTRL);
+ arbtr_ctrl = saa7146_read(dev, PCI_BT_V1);
+
+ calculate_clipping_registers_rect(dev, fh, &vdma2, &clip_format, &arbtr_ctrl, field);
+
+ /* set clipping format */
+ clip_format &= 0xffff0008;
+ clip_format |= (SAA7146_CLIPPING_RECT << 4);
+
+ /* prepare video dma2 */
+ saa7146_write(dev, BASE_EVEN2, vdma2.base_even);
+ saa7146_write(dev, BASE_ODD2, vdma2.base_odd);
+ saa7146_write(dev, PROT_ADDR2, vdma2.prot_addr);
+ saa7146_write(dev, BASE_PAGE2, vdma2.base_page);
+ saa7146_write(dev, PITCH2, vdma2.pitch);
+ saa7146_write(dev, NUM_LINE_BYTE2, vdma2.num_line_byte);
+
+ /* prepare the rest */
+ saa7146_write(dev, CLIP_FORMAT_CTRL,clip_format);
+ saa7146_write(dev, PCI_BT_V1, arbtr_ctrl);
+
+ /* upload clip_control-register, clipping-registers, enable video dma2 */
+ saa7146_write(dev, MC2, (MASK_05 | MASK_21 | MASK_03 | MASK_19));
+ saa7146_write(dev, MC1, (MASK_05 | MASK_21));
+}
+
+static void saa7146_set_window(struct saa7146_dev *dev, int width, int height, enum v4l2_field field)
+{
+ struct saa7146_vv *vv = dev->vv_data;
+
+ int source = vv->current_hps_source;
+ int sync = vv->current_hps_sync;
+
+ u32 hps_v_scale = 0, hps_v_gain = 0, hps_ctrl = 0, hps_h_prescale = 0, hps_h_scale = 0;
+
+ /* set vertical scale */
+ hps_v_scale = 0; /* all bits get set by the function-call */
+ hps_v_gain = 0; /* fixme: saa7146_read(dev, HPS_V_GAIN);*/
+ calculate_v_scale_registers(dev, field, vv->standard->v_field*2, height, &hps_v_scale, &hps_v_gain);
+
+ /* set horizontal scale */
+ hps_ctrl = 0;
+ hps_h_prescale = 0; /* all bits get set in the function */
+ hps_h_scale = 0;
+ calculate_h_scale_registers(dev, vv->standard->h_pixels, width, vv->hflip, &hps_ctrl, &hps_v_gain, &hps_h_prescale, &hps_h_scale);
+
+ /* set hyo and hxo */
+ calculate_hxo_and_hyo(vv, &hps_h_scale, &hps_ctrl);
+ calculate_hps_source_and_sync(dev, source, sync, &hps_ctrl);
+
+ /* write out new register contents */
+ saa7146_write(dev, HPS_V_SCALE, hps_v_scale);
+ saa7146_write(dev, HPS_V_GAIN, hps_v_gain);
+ saa7146_write(dev, HPS_CTRL, hps_ctrl);
+ saa7146_write(dev, HPS_H_PRESCALE,hps_h_prescale);
+ saa7146_write(dev, HPS_H_SCALE, hps_h_scale);
+
+ /* upload shadow-ram registers */
+ saa7146_write(dev, MC2, (MASK_05 | MASK_06 | MASK_21 | MASK_22) );
+}
+
+/* calculate the new memory offsets for a desired position */
+static void saa7146_set_position(struct saa7146_dev *dev, int w_x, int w_y, int w_height, enum v4l2_field field, u32 pixelformat)
+{
+ struct saa7146_vv *vv = dev->vv_data;
+ struct saa7146_format *sfmt = format_by_fourcc(dev, pixelformat);
+
+ int b_depth = vv->ov_fmt->depth;
+ int b_bpl = vv->ov_fb.fmt.bytesperline;
+ /* The unsigned long cast is to remove a 64-bit compile warning since
+ it looks like a 64-bit address is cast to a 32-bit value, even
+ though the base pointer is really a 32-bit physical address that
+ goes into a 32-bit DMA register.
+ FIXME: might not work on some 64-bit platforms, but see the FIXME
+ in struct v4l2_framebuffer (videodev2.h) for that.
+ */
+ u32 base = (u32)(unsigned long)vv->ov_fb.base;
+
+ struct saa7146_video_dma vdma1;
+
+ /* calculate memory offsets for picture, look if we shall top-down-flip */
+ vdma1.pitch = 2*b_bpl;
+ if ( 0 == vv->vflip ) {
+ vdma1.base_even = base + (w_y * (vdma1.pitch/2)) + (w_x * (b_depth / 8));
+ vdma1.base_odd = vdma1.base_even + (vdma1.pitch / 2);
+ vdma1.prot_addr = vdma1.base_even + (w_height * (vdma1.pitch / 2));
+ }
+ else {
+ vdma1.base_even = base + ((w_y+w_height) * (vdma1.pitch/2)) + (w_x * (b_depth / 8));
+ vdma1.base_odd = vdma1.base_even - (vdma1.pitch / 2);
+ vdma1.prot_addr = vdma1.base_odd - (w_height * (vdma1.pitch / 2));
+ }
+
+ if (V4L2_FIELD_HAS_BOTH(field)) {
+ } else if (field == V4L2_FIELD_ALTERNATE) {
+ /* fixme */
+ vdma1.base_odd = vdma1.prot_addr;
+ vdma1.pitch /= 2;
+ } else if (field == V4L2_FIELD_TOP) {
+ vdma1.base_odd = vdma1.prot_addr;
+ vdma1.pitch /= 2;
+ } else if (field == V4L2_FIELD_BOTTOM) {
+ vdma1.base_odd = vdma1.base_even;
+ vdma1.base_even = vdma1.prot_addr;
+ vdma1.pitch /= 2;
+ }
+
+ if ( 0 != vv->vflip ) {
+ vdma1.pitch *= -1;
+ }
+
+ vdma1.base_page = sfmt->swap;
+ vdma1.num_line_byte = (vv->standard->v_field<<16)+vv->standard->h_pixels;
+
+ saa7146_write_out_dma(dev, 1, &vdma1);
+}
+
+static void saa7146_set_output_format(struct saa7146_dev *dev, unsigned long palette)
+{
+ u32 clip_format = saa7146_read(dev, CLIP_FORMAT_CTRL);
+
+ /* call helper function */
+ calculate_output_format_register(dev,palette,&clip_format);
+
+ /* update the hps registers */
+ saa7146_write(dev, CLIP_FORMAT_CTRL, clip_format);
+ saa7146_write(dev, MC2, (MASK_05 | MASK_21));
+}
+
+/* select input-source */
+void saa7146_set_hps_source_and_sync(struct saa7146_dev *dev, int source, int sync)
+{
+ struct saa7146_vv *vv = dev->vv_data;
+ u32 hps_ctrl = 0;
+
+ /* read old state */
+ hps_ctrl = saa7146_read(dev, HPS_CTRL);
+
+ hps_ctrl &= ~( MASK_31 | MASK_30 | MASK_28 );
+ hps_ctrl |= (source << 30) | (sync << 28);
+
+ /* write back & upload register */
+ saa7146_write(dev, HPS_CTRL, hps_ctrl);
+ saa7146_write(dev, MC2, (MASK_05 | MASK_21));
+
+ vv->current_hps_source = source;
+ vv->current_hps_sync = sync;
+}
+EXPORT_SYMBOL_GPL(saa7146_set_hps_source_and_sync);
+
+int saa7146_enable_overlay(struct saa7146_fh *fh)
+{
+ struct saa7146_dev *dev = fh->dev;
+ struct saa7146_vv *vv = dev->vv_data;
+
+ saa7146_set_window(dev, fh->ov.win.w.width, fh->ov.win.w.height, fh->ov.win.field);
+ saa7146_set_position(dev, fh->ov.win.w.left, fh->ov.win.w.top, fh->ov.win.w.height, fh->ov.win.field, vv->ov_fmt->pixelformat);
+ saa7146_set_output_format(dev, vv->ov_fmt->trans);
+ saa7146_set_clipping_rect(fh);
+
+ /* enable video dma1 */
+ saa7146_write(dev, MC1, (MASK_06 | MASK_22));
+ return 0;
+}
+
+void saa7146_disable_overlay(struct saa7146_fh *fh)
+{
+ struct saa7146_dev *dev = fh->dev;
+
+ /* disable clipping + video dma1 */
+ saa7146_disable_clipping(dev);
+ saa7146_write(dev, MC1, MASK_22);
+}
+
+void saa7146_write_out_dma(struct saa7146_dev* dev, int which, struct saa7146_video_dma* vdma)
+{
+ int where = 0;
+
+ if( which < 1 || which > 3) {
+ return;
+ }
+
+ /* calculate starting address */
+ where = (which-1)*0x18;
+
+ saa7146_write(dev, where, vdma->base_odd);
+ saa7146_write(dev, where+0x04, vdma->base_even);
+ saa7146_write(dev, where+0x08, vdma->prot_addr);
+ saa7146_write(dev, where+0x0c, vdma->pitch);
+ saa7146_write(dev, where+0x10, vdma->base_page);
+ saa7146_write(dev, where+0x14, vdma->num_line_byte);
+
+ /* upload */
+ saa7146_write(dev, MC2, (MASK_02<<(which-1))|(MASK_18<<(which-1)));
+/*
+ printk("vdma%d.base_even: 0x%08x\n", which,vdma->base_even);
+ printk("vdma%d.base_odd: 0x%08x\n", which,vdma->base_odd);
+ printk("vdma%d.prot_addr: 0x%08x\n", which,vdma->prot_addr);
+ printk("vdma%d.base_page: 0x%08x\n", which,vdma->base_page);
+ printk("vdma%d.pitch: 0x%08x\n", which,vdma->pitch);
+ printk("vdma%d.num_line_byte: 0x%08x\n", which,vdma->num_line_byte);
+*/
+}
+
+static int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa7146_buf *buf)
+{
+ struct saa7146_vv *vv = dev->vv_data;
+ struct saa7146_video_dma vdma1;
+
+ struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);
+
+ int width = buf->fmt->width;
+ int height = buf->fmt->height;
+ int bytesperline = buf->fmt->bytesperline;
+ enum v4l2_field field = buf->fmt->field;
+
+ int depth = sfmt->depth;
+
+ DEB_CAP(("[size=%dx%d,fields=%s]\n",
+ width,height,v4l2_field_names[field]));
+
+ if( bytesperline != 0) {
+ vdma1.pitch = bytesperline*2;
+ } else {
+ vdma1.pitch = (width*depth*2)/8;
+ }
+ vdma1.num_line_byte = ((vv->standard->v_field<<16) + vv->standard->h_pixels);
+ vdma1.base_page = buf->pt[0].dma | ME1 | sfmt->swap;
+
+ if( 0 != vv->vflip ) {
+ vdma1.prot_addr = buf->pt[0].offset;
+ vdma1.base_even = buf->pt[0].offset+(vdma1.pitch/2)*height;
+ vdma1.base_odd = vdma1.base_even - (vdma1.pitch/2);
+ } else {
+ vdma1.base_even = buf->pt[0].offset;
+ vdma1.base_odd = vdma1.base_even + (vdma1.pitch/2);
+ vdma1.prot_addr = buf->pt[0].offset+(vdma1.pitch/2)*height;
+ }
+
+ if (V4L2_FIELD_HAS_BOTH(field)) {
+ } else if (field == V4L2_FIELD_ALTERNATE) {
+ /* fixme */
+ if ( vv->last_field == V4L2_FIELD_TOP ) {
+ vdma1.base_odd = vdma1.prot_addr;
+ vdma1.pitch /= 2;
+ } else if ( vv->last_field == V4L2_FIELD_BOTTOM ) {
+ vdma1.base_odd = vdma1.base_even;
+ vdma1.base_even = vdma1.prot_addr;
+ vdma1.pitch /= 2;
+ }
+ } else if (field == V4L2_FIELD_TOP) {
+ vdma1.base_odd = vdma1.prot_addr;
+ vdma1.pitch /= 2;
+ } else if (field == V4L2_FIELD_BOTTOM) {
+ vdma1.base_odd = vdma1.base_even;
+ vdma1.base_even = vdma1.prot_addr;
+ vdma1.pitch /= 2;
+ }
+
+ if( 0 != vv->vflip ) {
+ vdma1.pitch *= -1;
+ }
+
+ saa7146_write_out_dma(dev, 1, &vdma1);
+ return 0;
+}
+
+static int calc_planar_422(struct saa7146_vv *vv, struct saa7146_buf *buf, struct saa7146_video_dma *vdma2, struct saa7146_video_dma *vdma3)
+{
+ int height = buf->fmt->height;
+ int width = buf->fmt->width;
+
+ vdma2->pitch = width;
+ vdma3->pitch = width;
+
+ /* fixme: look at bytesperline! */
+
+ if( 0 != vv->vflip ) {
+ vdma2->prot_addr = buf->pt[1].offset;
+ vdma2->base_even = ((vdma2->pitch/2)*height)+buf->pt[1].offset;
+ vdma2->base_odd = vdma2->base_even - (vdma2->pitch/2);
+
+ vdma3->prot_addr = buf->pt[2].offset;
+ vdma3->base_even = ((vdma3->pitch/2)*height)+buf->pt[2].offset;
+ vdma3->base_odd = vdma3->base_even - (vdma3->pitch/2);
+ } else {
+ vdma3->base_even = buf->pt[2].offset;
+ vdma3->base_odd = vdma3->base_even + (vdma3->pitch/2);
+ vdma3->prot_addr = (vdma3->pitch/2)*height+buf->pt[2].offset;
+
+ vdma2->base_even = buf->pt[1].offset;
+ vdma2->base_odd = vdma2->base_even + (vdma2->pitch/2);
+ vdma2->prot_addr = (vdma2->pitch/2)*height+buf->pt[1].offset;
+ }
+
+ return 0;
+}
+
+static int calc_planar_420(struct saa7146_vv *vv, struct saa7146_buf *buf, struct saa7146_video_dma *vdma2, struct saa7146_video_dma *vdma3)
+{
+ int height = buf->fmt->height;
+ int width = buf->fmt->width;
+
+ vdma2->pitch = width/2;
+ vdma3->pitch = width/2;
+
+ if( 0 != vv->vflip ) {
+ vdma2->prot_addr = buf->pt[2].offset;
+ vdma2->base_even = ((vdma2->pitch/2)*height)+buf->pt[2].offset;
+ vdma2->base_odd = vdma2->base_even - (vdma2->pitch/2);
+
+ vdma3->prot_addr = buf->pt[1].offset;
+ vdma3->base_even = ((vdma3->pitch/2)*height)+buf->pt[1].offset;
+ vdma3->base_odd = vdma3->base_even - (vdma3->pitch/2);
+
+ } else {
+ vdma3->base_even = buf->pt[2].offset;
+ vdma3->base_odd = vdma3->base_even + (vdma3->pitch);
+ vdma3->prot_addr = (vdma3->pitch/2)*height+buf->pt[2].offset;
+
+ vdma2->base_even = buf->pt[1].offset;
+ vdma2->base_odd = vdma2->base_even + (vdma2->pitch);
+ vdma2->prot_addr = (vdma2->pitch/2)*height+buf->pt[1].offset;
+ }
+ return 0;
+}
+
+static int calculate_video_dma_grab_planar(struct saa7146_dev* dev, struct saa7146_buf *buf)
+{
+ struct saa7146_vv *vv = dev->vv_data;
+ struct saa7146_video_dma vdma1;
+ struct saa7146_video_dma vdma2;
+ struct saa7146_video_dma vdma3;
+
+ struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);
+
+ int width = buf->fmt->width;
+ int height = buf->fmt->height;
+ enum v4l2_field field = buf->fmt->field;
+
+ BUG_ON(0 == buf->pt[0].dma);
+ BUG_ON(0 == buf->pt[1].dma);
+ BUG_ON(0 == buf->pt[2].dma);
+
+ DEB_CAP(("[size=%dx%d,fields=%s]\n",
+ width,height,v4l2_field_names[field]));
+
+ /* fixme: look at bytesperline! */
+
+ /* fixme: what happens for user space buffers here?. The offsets are
+ most likely wrong, this version here only works for page-aligned
+ buffers, modifications to the pagetable-functions are necessary...*/
+
+ vdma1.pitch = width*2;
+ vdma1.num_line_byte = ((vv->standard->v_field<<16) + vv->standard->h_pixels);
+ vdma1.base_page = buf->pt[0].dma | ME1;
+
+ if( 0 != vv->vflip ) {
+ vdma1.prot_addr = buf->pt[0].offset;
+ vdma1.base_even = ((vdma1.pitch/2)*height)+buf->pt[0].offset;
+ vdma1.base_odd = vdma1.base_even - (vdma1.pitch/2);
+ } else {
+ vdma1.base_even = buf->pt[0].offset;
+ vdma1.base_odd = vdma1.base_even + (vdma1.pitch/2);
+ vdma1.prot_addr = (vdma1.pitch/2)*height+buf->pt[0].offset;
+ }
+
+ vdma2.num_line_byte = 0; /* unused */
+ vdma2.base_page = buf->pt[1].dma | ME1;
+
+ vdma3.num_line_byte = 0; /* unused */
+ vdma3.base_page = buf->pt[2].dma | ME1;
+
+ switch( sfmt->depth ) {
+ case 12: {
+ calc_planar_420(vv,buf,&vdma2,&vdma3);
+ break;
+ }
+ case 16: {
+ calc_planar_422(vv,buf,&vdma2,&vdma3);
+ break;
+ }
+ default: {
+ return -1;
+ }
+ }
+
+ if (V4L2_FIELD_HAS_BOTH(field)) {
+ } else if (field == V4L2_FIELD_ALTERNATE) {
+ /* fixme */
+ vdma1.base_odd = vdma1.prot_addr;
+ vdma1.pitch /= 2;
+ vdma2.base_odd = vdma2.prot_addr;
+ vdma2.pitch /= 2;
+ vdma3.base_odd = vdma3.prot_addr;
+ vdma3.pitch /= 2;
+ } else if (field == V4L2_FIELD_TOP) {
+ vdma1.base_odd = vdma1.prot_addr;
+ vdma1.pitch /= 2;
+ vdma2.base_odd = vdma2.prot_addr;
+ vdma2.pitch /= 2;
+ vdma3.base_odd = vdma3.prot_addr;
+ vdma3.pitch /= 2;
+ } else if (field == V4L2_FIELD_BOTTOM) {
+ vdma1.base_odd = vdma1.base_even;
+ vdma1.base_even = vdma1.prot_addr;
+ vdma1.pitch /= 2;
+ vdma2.base_odd = vdma2.base_even;
+ vdma2.base_even = vdma2.prot_addr;
+ vdma2.pitch /= 2;
+ vdma3.base_odd = vdma3.base_even;
+ vdma3.base_even = vdma3.prot_addr;
+ vdma3.pitch /= 2;
+ }
+
+ if( 0 != vv->vflip ) {
+ vdma1.pitch *= -1;
+ vdma2.pitch *= -1;
+ vdma3.pitch *= -1;
+ }
+
+ saa7146_write_out_dma(dev, 1, &vdma1);
+ if( (sfmt->flags & FORMAT_BYTE_SWAP) != 0 ) {
+ saa7146_write_out_dma(dev, 3, &vdma2);
+ saa7146_write_out_dma(dev, 2, &vdma3);
+ } else {
+ saa7146_write_out_dma(dev, 2, &vdma2);
+ saa7146_write_out_dma(dev, 3, &vdma3);
+ }
+ return 0;
+}
+
+static void program_capture_engine(struct saa7146_dev *dev, int planar)
+{
+ struct saa7146_vv *vv = dev->vv_data;
+ int count = 0;
+
+ unsigned long e_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_E_FID_A : CMD_E_FID_B;
+ unsigned long o_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_O_FID_A : CMD_O_FID_B;
+
+ /* wait for o_fid_a/b / e_fid_a/b toggle only if rps register 0 is not set*/
+ WRITE_RPS0(CMD_PAUSE | CMD_OAN | CMD_SIG0 | o_wait);
+ WRITE_RPS0(CMD_PAUSE | CMD_OAN | CMD_SIG0 | e_wait);
+
+ /* set rps register 0 */
+ WRITE_RPS0(CMD_WR_REG | (1 << 8) | (MC2/4));
+ WRITE_RPS0(MASK_27 | MASK_11);
+
+ /* turn on video-dma1 */
+ WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4));
+ WRITE_RPS0(MASK_06 | MASK_22); /* => mask */
+ WRITE_RPS0(MASK_06 | MASK_22); /* => values */
+ if( 0 != planar ) {
+ /* turn on video-dma2 */
+ WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4));
+ WRITE_RPS0(MASK_05 | MASK_21); /* => mask */
+ WRITE_RPS0(MASK_05 | MASK_21); /* => values */
+
+ /* turn on video-dma3 */
+ WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4));
+ WRITE_RPS0(MASK_04 | MASK_20); /* => mask */
+ WRITE_RPS0(MASK_04 | MASK_20); /* => values */
+ }
+
+ /* wait for o_fid_a/b / e_fid_a/b toggle */
+ if ( vv->last_field == V4L2_FIELD_INTERLACED ) {
+ WRITE_RPS0(CMD_PAUSE | o_wait);
+ WRITE_RPS0(CMD_PAUSE | e_wait);
+ } else if ( vv->last_field == V4L2_FIELD_TOP ) {
+ WRITE_RPS0(CMD_PAUSE | (vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? MASK_10 : MASK_09));
+ WRITE_RPS0(CMD_PAUSE | o_wait);
+ } else if ( vv->last_field == V4L2_FIELD_BOTTOM ) {
+ WRITE_RPS0(CMD_PAUSE | (vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? MASK_10 : MASK_09));
+ WRITE_RPS0(CMD_PAUSE | e_wait);
+ }
+
+ /* turn off video-dma1 */
+ WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4));
+ WRITE_RPS0(MASK_22 | MASK_06); /* => mask */
+ WRITE_RPS0(MASK_22); /* => values */
+ if( 0 != planar ) {
+ /* turn off video-dma2 */
+ WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4));
+ WRITE_RPS0(MASK_05 | MASK_21); /* => mask */
+ WRITE_RPS0(MASK_21); /* => values */
+
+ /* turn off video-dma3 */
+ WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4));
+ WRITE_RPS0(MASK_04 | MASK_20); /* => mask */
+ WRITE_RPS0(MASK_20); /* => values */
+ }
+
+ /* generate interrupt */
+ WRITE_RPS0(CMD_INTERRUPT);
+
+ /* stop */
+ WRITE_RPS0(CMD_STOP);
+}
+
+void saa7146_set_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next)
+{
+ struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);
+ struct saa7146_vv *vv = dev->vv_data;
+ u32 vdma1_prot_addr;
+
+ DEB_CAP(("buf:%p, next:%p\n",buf,next));
+
+ vdma1_prot_addr = saa7146_read(dev, PROT_ADDR1);
+ if( 0 == vdma1_prot_addr ) {
+ /* clear out beginning of streaming bit (rps register 0)*/
+ DEB_CAP(("forcing sync to new frame\n"));
+ saa7146_write(dev, MC2, MASK_27 );
+ }
+
+ saa7146_set_window(dev, buf->fmt->width, buf->fmt->height, buf->fmt->field);
+ saa7146_set_output_format(dev, sfmt->trans);
+ saa7146_disable_clipping(dev);
+
+ if ( vv->last_field == V4L2_FIELD_INTERLACED ) {
+ } else if ( vv->last_field == V4L2_FIELD_TOP ) {
+ vv->last_field = V4L2_FIELD_BOTTOM;
+ } else if ( vv->last_field == V4L2_FIELD_BOTTOM ) {
+ vv->last_field = V4L2_FIELD_TOP;
+ }
+
+ if( 0 != IS_PLANAR(sfmt->trans)) {
+ calculate_video_dma_grab_planar(dev, buf);
+ program_capture_engine(dev,1);
+ } else {
+ calculate_video_dma_grab_packed(dev, buf);
+ program_capture_engine(dev,0);
+ }
+
+/*
+ printk("vdma%d.base_even: 0x%08x\n", 1,saa7146_read(dev,BASE_EVEN1));
+ printk("vdma%d.base_odd: 0x%08x\n", 1,saa7146_read(dev,BASE_ODD1));
+ printk("vdma%d.prot_addr: 0x%08x\n", 1,saa7146_read(dev,PROT_ADDR1));
+ printk("vdma%d.base_page: 0x%08x\n", 1,saa7146_read(dev,BASE_PAGE1));
+ printk("vdma%d.pitch: 0x%08x\n", 1,saa7146_read(dev,PITCH1));
+ printk("vdma%d.num_line_byte: 0x%08x\n", 1,saa7146_read(dev,NUM_LINE_BYTE1));
+ printk("vdma%d => vptr : 0x%08x\n", 1,saa7146_read(dev,PCI_VDP1));
+*/
+
+ /* write the address of the rps-program */
+ saa7146_write(dev, RPS_ADDR0, dev->d_rps0.dma_handle);
+
+ /* turn on rps */
+ saa7146_write(dev, MC1, (MASK_12 | MASK_28));
+}
diff --git a/linux/drivers/media/video/saa7146/saa7146_i2c.c b/linux/drivers/media/video/saa7146/saa7146_i2c.c
new file mode 100644
index 000000000..a2447ff60
--- /dev/null
+++ b/linux/drivers/media/video/saa7146/saa7146_i2c.c
@@ -0,0 +1,433 @@
+#include <media/saa7146_vv.h>
+#include "compat.h"
+
+static u32 saa7146_i2c_func(struct i2c_adapter *adapter)
+{
+//fm DEB_I2C(("'%s'.\n", adapter->name));
+
+ return I2C_FUNC_I2C
+ | I2C_FUNC_SMBUS_QUICK
+ | I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE
+ | I2C_FUNC_SMBUS_READ_BYTE_DATA | I2C_FUNC_SMBUS_WRITE_BYTE_DATA;
+}
+
+/* this function returns the status-register of our i2c-device */
+static inline u32 saa7146_i2c_status(struct saa7146_dev *dev)
+{
+ u32 iicsta = saa7146_read(dev, I2C_STATUS);
+/*
+ DEB_I2C(("status: 0x%08x\n",iicsta));
+*/
+ return iicsta;
+}
+
+/* this function runs through the i2c-messages and prepares the data to be
+ sent through the saa7146. have a look at the specifications p. 122 ff
+ to understand this. it returns the number of u32s to send, or -1
+ in case of an error. */
+static int saa7146_i2c_msg_prepare(const struct i2c_msg *m, int num, u32 *op)
+{
+ int h1, h2;
+ int i, j, addr;
+ int mem = 0, op_count = 0;
+
+ /* first determine size of needed memory */
+ for(i = 0; i < num; i++) {
+ mem += m[i].len + 1;
+ }
+
+ /* worst case: we need one u32 for three bytes to be send
+ plus one extra byte to address the device */
+ mem = 1 + ((mem-1) / 3);
+
+ /* we assume that op points to a memory of at least SAA7146_I2C_MEM bytes
+ size. if we exceed this limit... */
+ if ( (4*mem) > SAA7146_I2C_MEM ) {
+//fm DEB_I2C(("cannot prepare i2c-message.\n"));
+ return -ENOMEM;
+ }
+
+ /* be careful: clear out the i2c-mem first */
+ memset(op,0,sizeof(u32)*mem);
+
+ /* loop through all messages */
+ for(i = 0; i < num; i++) {
+
+ /* insert the address of the i2c-slave.
+ note: we get 7 bit i2c-addresses,
+ so we have to perform a translation */
+ addr = (m[i].addr*2) + ( (0 != (m[i].flags & I2C_M_RD)) ? 1 : 0);
+ h1 = op_count/3; h2 = op_count%3;
+ op[h1] |= ( (u8)addr << ((3-h2)*8));
+ op[h1] |= (SAA7146_I2C_START << ((3-h2)*2));
+ op_count++;
+
+ /* loop through all bytes of message i */
+ for(j = 0; j < m[i].len; j++) {
+ /* insert the data bytes */
+ h1 = op_count/3; h2 = op_count%3;
+ op[h1] |= ( (u32)((u8)m[i].buf[j]) << ((3-h2)*8));
+ op[h1] |= ( SAA7146_I2C_CONT << ((3-h2)*2));
+ op_count++;
+ }
+
+ }
+
+ /* have a look at the last byte inserted:
+ if it was: ...CONT change it to ...STOP */
+ h1 = (op_count-1)/3; h2 = (op_count-1)%3;
+ if ( SAA7146_I2C_CONT == (0x3 & (op[h1] >> ((3-h2)*2))) ) {
+ op[h1] &= ~(0x2 << ((3-h2)*2));
+ op[h1] |= (SAA7146_I2C_STOP << ((3-h2)*2));
+ }
+
+ /* return the number of u32s to send */
+ return mem;
+}
+
+/* this functions loops through all i2c-messages. normally, it should determine
+ which bytes were read through the adapter and write them back to the corresponding
+ i2c-message. but instead, we simply write back all bytes.
+ fixme: this could be improved. */
+static int saa7146_i2c_msg_cleanup(const struct i2c_msg *m, int num, u32 *op)
+{
+ int i, j;
+ int op_count = 0;
+
+ /* loop through all messages */
+ for(i = 0; i < num; i++) {
+
+ op_count++;
+
+ /* loop throgh all bytes of message i */
+ for(j = 0; j < m[i].len; j++) {
+ /* write back all bytes that could have been read */
+ m[i].buf[j] = (op[op_count/3] >> ((3-(op_count%3))*8));
+ op_count++;
+ }
+ }
+
+ return 0;
+}
+
+/* this functions resets the i2c-device and returns 0 if everything was fine, otherwise -1 */
+static int saa7146_i2c_reset(struct saa7146_dev *dev)
+{
+ /* get current status */
+ u32 status = saa7146_i2c_status(dev);
+
+ /* clear registers for sure */
+ saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
+ saa7146_write(dev, I2C_TRANSFER, 0);
+
+ /* check if any operation is still in progress */
+ if ( 0 != ( status & SAA7146_I2C_BUSY) ) {
+
+ /* yes, kill ongoing operation */
+ DEB_I2C(("busy_state detected.\n"));
+
+ /* set "ABORT-OPERATION"-bit (bit 7)*/
+ saa7146_write(dev, I2C_STATUS, (dev->i2c_bitrate | MASK_07));
+ saa7146_write(dev, MC2, (MASK_00 | MASK_16));
+ msleep(SAA7146_I2C_DELAY);
+
+ /* clear all error-bits pending; this is needed because p.123, note 1 */
+ saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
+ saa7146_write(dev, MC2, (MASK_00 | MASK_16));
+ msleep(SAA7146_I2C_DELAY);
+ }
+
+ /* check if any error is (still) present. (this can be necessary because p.123, note 1) */
+ status = saa7146_i2c_status(dev);
+
+ if ( dev->i2c_bitrate != status ) {
+
+ DEB_I2C(("error_state detected. status:0x%08x\n",status));
+
+ /* Repeat the abort operation. This seems to be necessary
+ after serious protocol errors caused by e.g. the SAA7740 */
+ saa7146_write(dev, I2C_STATUS, (dev->i2c_bitrate | MASK_07));
+ saa7146_write(dev, MC2, (MASK_00 | MASK_16));
+ msleep(SAA7146_I2C_DELAY);
+
+ /* clear all error-bits pending */
+ saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
+ saa7146_write(dev, MC2, (MASK_00 | MASK_16));
+ msleep(SAA7146_I2C_DELAY);
+
+ /* the data sheet says it might be necessary to clear the status
+ twice after an abort */
+ saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
+ saa7146_write(dev, MC2, (MASK_00 | MASK_16));
+ msleep(SAA7146_I2C_DELAY);
+ }
+
+ /* if any error is still present, a fatal error has occured ... */
+ status = saa7146_i2c_status(dev);
+ if ( dev->i2c_bitrate != status ) {
+ DEB_I2C(("fatal error. status:0x%08x\n",status));
+ return -1;
+ }
+
+ return 0;
+}
+
+/* this functions writes out the data-byte 'dword' to the i2c-device.
+ it returns 0 if ok, -1 if the transfer failed, -2 if the transfer
+ failed badly (e.g. address error) */
+static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_delay)
+{
+ u32 status = 0, mc2 = 0;
+ int trial = 0;
+ unsigned long timeout;
+
+ /* write out i2c-command */
+ DEB_I2C(("before: 0x%08x (status: 0x%08x), %d\n",*dword,saa7146_read(dev, I2C_STATUS), dev->i2c_op));
+
+ if( 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags)) {
+
+ saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
+ saa7146_write(dev, I2C_TRANSFER, *dword);
+
+ dev->i2c_op = 1;
+ SAA7146_ISR_CLEAR(dev, MASK_16|MASK_17);
+ SAA7146_IER_ENABLE(dev, MASK_16|MASK_17);
+ saa7146_write(dev, MC2, (MASK_00 | MASK_16));
+
+ timeout = HZ/100 + 1; /* 10ms */
+ timeout = wait_event_interruptible_timeout(dev->i2c_wq, dev->i2c_op == 0, timeout);
+ if (timeout == -ERESTARTSYS || dev->i2c_op) {
+ SAA7146_IER_DISABLE(dev, MASK_16|MASK_17);
+ SAA7146_ISR_CLEAR(dev, MASK_16|MASK_17);
+ if (timeout == -ERESTARTSYS)
+ /* a signal arrived */
+ return -ERESTARTSYS;
+
+ printk(KERN_WARNING "%s %s [irq]: timed out waiting for end of xfer\n",
+ dev->name, __func__);
+ return -EIO;
+ }
+ status = saa7146_read(dev, I2C_STATUS);
+ } else {
+ saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
+ saa7146_write(dev, I2C_TRANSFER, *dword);
+ saa7146_write(dev, MC2, (MASK_00 | MASK_16));
+
+ /* do not poll for i2c-status before upload is complete */
+ timeout = jiffies + HZ/100 + 1; /* 10ms */
+ while(1) {
+ mc2 = (saa7146_read(dev, MC2) & 0x1);
+ if( 0 != mc2 ) {
+ break;
+ }
+ if (time_after(jiffies,timeout)) {
+ printk(KERN_WARNING "%s %s: timed out waiting for MC2\n",
+ dev->name, __func__);
+ return -EIO;
+ }
+ }
+ /* wait until we get a transfer done or error */
+ timeout = jiffies + HZ/100 + 1; /* 10ms */
+ /* first read usually delivers bogus results... */
+ saa7146_i2c_status(dev);
+ while(1) {
+ status = saa7146_i2c_status(dev);
+ if ((status & 0x3) != 1)
+ break;
+ if (time_after(jiffies,timeout)) {
+ /* this is normal when probing the bus
+ * (no answer from nonexisistant device...)
+ */
+ printk(KERN_WARNING "%s %s [poll]: timed out waiting for end of xfer\n",
+ dev->name, __func__);
+ return -EIO;
+ }
+ if (++trial < 50 && short_delay)
+ udelay(10);
+ else
+ msleep(1);
+ }
+ }
+
+ /* give a detailed status report */
+ if ( 0 != (status & (SAA7146_I2C_SPERR | SAA7146_I2C_APERR |
+ SAA7146_I2C_DTERR | SAA7146_I2C_DRERR |
+ SAA7146_I2C_AL | SAA7146_I2C_ERR |
+ SAA7146_I2C_BUSY)) ) {
+
+ if ( 0 == (status & SAA7146_I2C_ERR) ||
+ 0 == (status & SAA7146_I2C_BUSY) ) {
+ /* it may take some time until ERR goes high - ignore */
+ DEB_I2C(("unexpected i2c status %04x\n", status));
+ }
+ if( 0 != (status & SAA7146_I2C_SPERR) ) {
+ DEB_I2C(("error due to invalid start/stop condition.\n"));
+ }
+ if( 0 != (status & SAA7146_I2C_DTERR) ) {
+ DEB_I2C(("error in data transmission.\n"));
+ }
+ if( 0 != (status & SAA7146_I2C_DRERR) ) {
+ DEB_I2C(("error when receiving data.\n"));
+ }
+ if( 0 != (status & SAA7146_I2C_AL) ) {
+ DEB_I2C(("error because arbitration lost.\n"));
+ }
+
+ /* we handle address-errors here */
+ if( 0 != (status & SAA7146_I2C_APERR) ) {
+ DEB_I2C(("error in address phase.\n"));
+ return -EREMOTEIO;
+ }
+
+ return -EIO;
+ }
+
+ /* read back data, just in case we were reading ... */
+ *dword = saa7146_read(dev, I2C_TRANSFER);
+
+ DEB_I2C(("after: 0x%08x\n",*dword));
+ return 0;
+}
+
+static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *msgs, int num, int retries)
+{
+ int i = 0, count = 0;
+ u32* buffer = dev->d_i2c.cpu_addr;
+ int err = 0;
+ int address_err = 0;
+ int short_delay = 0;
+
+ if (mutex_lock_interruptible(&dev->i2c_lock))
+ return -ERESTARTSYS;
+
+ for(i=0;i<num;i++) {
+ DEB_I2C(("msg:%d/%d\n",i+1,num));
+ }
+
+ /* prepare the message(s), get number of u32s to transfer */
+ count = saa7146_i2c_msg_prepare(msgs, num, buffer);
+ if ( 0 > count ) {
+ err = -1;
+ goto out;
+ }
+
+ if ( count > 3 || 0 != (SAA7146_I2C_SHORT_DELAY & dev->ext->flags) )
+ short_delay = 1;
+
+ do {
+ /* reset the i2c-device if necessary */
+ err = saa7146_i2c_reset(dev);
+ if ( 0 > err ) {
+ DEB_I2C(("could not reset i2c-device.\n"));
+ goto out;
+ }
+
+ /* write out the u32s one after another */
+ for(i = 0; i < count; i++) {
+ err = saa7146_i2c_writeout(dev, &buffer[i], short_delay);
+ if ( 0 != err) {
+ /* this one is unsatisfying: some i2c slaves on some
+ dvb cards don't acknowledge correctly, so the saa7146
+ thinks that an address error occured. in that case, the
+ transaction should be retrying, even if an address error
+ occured. analog saa7146 based cards extensively rely on
+ i2c address probing, however, and address errors indicate that a
+ device is really *not* there. retrying in that case
+ increases the time the device needs to probe greatly, so
+ it should be avoided. because of the fact, that only
+ analog based cards use irq based i2c transactions (for dvb
+ cards, this screwes up other interrupt sources), we bail out
+ completely for analog cards after an address error and trust
+ the saa7146 address error detection. */
+ if ( -EREMOTEIO == err ) {
+ if( 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags)) {
+ goto out;
+ }
+ address_err++;
+ }
+ DEB_I2C(("error while sending message(s). starting again.\n"));
+ break;
+ }
+ }
+ if( 0 == err ) {
+ err = num;
+ break;
+ }
+
+ /* delay a bit before retrying */
+ msleep(10);
+
+ } while (err != num && retries--);
+
+ /* if every retry had an address error, exit right away */
+ if (address_err == retries) {
+ goto out;
+ }
+
+ /* if any things had to be read, get the results */
+ if ( 0 != saa7146_i2c_msg_cleanup(msgs, num, buffer)) {
+ DEB_I2C(("could not cleanup i2c-message.\n"));
+ err = -1;
+ goto out;
+ }
+
+ /* return the number of delivered messages */
+ DEB_I2C(("transmission successful. (msg:%d).\n",err));
+out:
+ /* another bug in revision 0: the i2c-registers get uploaded randomly by other
+ uploads, so we better clear them out before continueing */
+ if( 0 == dev->revision ) {
+ u32 zero = 0;
+ saa7146_i2c_reset(dev);
+ if( 0 != saa7146_i2c_writeout(dev, &zero, short_delay)) {
+ INFO(("revision 0 error. this should never happen.\n"));
+ }
+ }
+
+ mutex_unlock(&dev->i2c_lock);
+ return err;
+}
+
+/* utility functions */
+static int saa7146_i2c_xfer(struct i2c_adapter* adapter, struct i2c_msg *msg, int num)
+{
+ struct saa7146_dev* dev = i2c_get_adapdata(adapter);
+
+ /* use helper function to transfer data */
+ return saa7146_i2c_transfer(dev, msg, num, adapter->retries);
+}
+
+
+/*****************************************************************************/
+/* i2c-adapter helper functions */
+#include <linux/i2c-id.h>
+
+/* exported algorithm data */
+static struct i2c_algorithm saa7146_algo = {
+ .master_xfer = saa7146_i2c_xfer,
+ .functionality = saa7146_i2c_func,
+};
+
+int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, u32 bitrate)
+{
+ DEB_EE(("bitrate: 0x%08x\n",bitrate));
+
+ /* enable i2c-port pins */
+ saa7146_write(dev, MC1, (MASK_08 | MASK_24));
+
+ dev->i2c_bitrate = bitrate;
+ saa7146_i2c_reset(dev);
+
+ if( NULL != i2c_adapter ) {
+ BUG_ON(!i2c_adapter->class);
+ i2c_set_adapdata(i2c_adapter,dev);
+ i2c_adapter->dev.parent = &dev->pci->dev;
+ i2c_adapter->algo = &saa7146_algo;
+ i2c_adapter->algo_data = NULL;
+ i2c_adapter->id = I2C_HW_SAA7146;
+ i2c_adapter->timeout = SAA7146_I2C_TIMEOUT;
+ i2c_adapter->retries = SAA7146_I2C_RETRIES;
+ }
+
+ return 0;
+}
diff --git a/linux/drivers/media/video/saa7146/saa7146_vbi.c b/linux/drivers/media/video/saa7146/saa7146_vbi.c
new file mode 100644
index 000000000..9a03df7fc
--- /dev/null
+++ b/linux/drivers/media/video/saa7146/saa7146_vbi.c
@@ -0,0 +1,511 @@
+#include <media/saa7146_vv.h>
+#include "compat.h"
+
+static int vbi_pixel_to_capture = 720 * 2;
+
+static int vbi_workaround(struct saa7146_dev *dev)
+{
+ struct saa7146_vv *vv = dev->vv_data;
+
+ u32 *cpu;
+ dma_addr_t dma_addr;
+
+ int count = 0;
+ int i;
+
+ DECLARE_WAITQUEUE(wait, current);
+
+ DEB_VBI(("dev:%p\n",dev));
+
+ /* once again, a bug in the saa7146: the brs acquisition
+ is buggy and especially the BXO-counter does not work
+ as specified. there is this workaround, but please
+ don't let me explain it. ;-) */
+
+ cpu = pci_alloc_consistent(dev->pci, 4096, &dma_addr);
+ if (NULL == cpu)
+ return -ENOMEM;
+
+ /* setup some basic programming, just for the workaround */
+ saa7146_write(dev, BASE_EVEN3, dma_addr);
+ saa7146_write(dev, BASE_ODD3, dma_addr+vbi_pixel_to_capture);
+ saa7146_write(dev, PROT_ADDR3, dma_addr+4096);
+ saa7146_write(dev, PITCH3, vbi_pixel_to_capture);
+ saa7146_write(dev, BASE_PAGE3, 0x0);
+ saa7146_write(dev, NUM_LINE_BYTE3, (2<<16)|((vbi_pixel_to_capture)<<0));
+ saa7146_write(dev, MC2, MASK_04|MASK_20);
+
+ /* load brs-control register */
+ WRITE_RPS1(CMD_WR_REG | (1 << 8) | (BRS_CTRL/4));
+ /* BXO = 1h, BRS to outbound */
+ WRITE_RPS1(0xc000008c);
+ /* wait for vbi_a or vbi_b*/
+ if ( 0 != (SAA7146_USE_PORT_B_FOR_VBI & dev->ext_vv_data->flags)) {
+ DEB_D(("...using port b\n"));
+ WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | CMD_E_FID_B);
+ WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | CMD_O_FID_B);
+/*
+ WRITE_RPS1(CMD_PAUSE | MASK_09);
+*/
+ } else {
+ DEB_D(("...using port a\n"));
+ WRITE_RPS1(CMD_PAUSE | MASK_10);
+ }
+ /* upload brs */
+ WRITE_RPS1(CMD_UPLOAD | MASK_08);
+ /* load brs-control register */
+ WRITE_RPS1(CMD_WR_REG | (1 << 8) | (BRS_CTRL/4));
+ /* BYO = 1, BXO = NQBIL (=1728 for PAL, for NTSC this is 858*2) - NumByte3 (=1440) = 288 */
+ WRITE_RPS1(((1728-(vbi_pixel_to_capture)) << 7) | MASK_19);
+ /* wait for brs_done */
+ WRITE_RPS1(CMD_PAUSE | MASK_08);
+ /* upload brs */
+ WRITE_RPS1(CMD_UPLOAD | MASK_08);
+ /* load video-dma3 NumLines3 and NumBytes3 */
+ WRITE_RPS1(CMD_WR_REG | (1 << 8) | (NUM_LINE_BYTE3/4));
+ /* dev->vbi_count*2 lines, 720 pixel (= 1440 Bytes) */
+ WRITE_RPS1((2 << 16) | (vbi_pixel_to_capture));
+ /* load brs-control register */
+ WRITE_RPS1(CMD_WR_REG | (1 << 8) | (BRS_CTRL/4));
+ /* Set BRS right: note: this is an experimental value for BXO (=> PAL!) */
+ WRITE_RPS1((540 << 7) | (5 << 19)); // 5 == vbi_start
+ /* wait for brs_done */
+ WRITE_RPS1(CMD_PAUSE | MASK_08);
+ /* upload brs and video-dma3*/
+ WRITE_RPS1(CMD_UPLOAD | MASK_08 | MASK_04);
+ /* load mc2 register: enable dma3 */
+ WRITE_RPS1(CMD_WR_REG | (1 << 8) | (MC1/4));
+ WRITE_RPS1(MASK_20 | MASK_04);
+ /* generate interrupt */
+ WRITE_RPS1(CMD_INTERRUPT);
+ /* stop rps1 */
+ WRITE_RPS1(CMD_STOP);
+
+ /* we have to do the workaround twice to be sure that
+ everything is ok */
+ for(i = 0; i < 2; i++) {
+
+ /* indicate to the irq handler that we do the workaround */
+ saa7146_write(dev, MC2, MASK_31|MASK_15);
+
+ saa7146_write(dev, NUM_LINE_BYTE3, (1<<16)|(2<<0));
+ saa7146_write(dev, MC2, MASK_04|MASK_20);
+
+ /* enable rps1 irqs */
+ SAA7146_IER_ENABLE(dev,MASK_28);
+
+ /* prepare to wait to be woken up by the irq-handler */
+ add_wait_queue(&vv->vbi_wq, &wait);
+ current->state = TASK_INTERRUPTIBLE;
+
+ /* start rps1 to enable workaround */
+ saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
+ saa7146_write(dev, MC1, (MASK_13 | MASK_29));
+
+ schedule();
+
+ DEB_VBI(("brs bug workaround %d/1.\n",i));
+
+ remove_wait_queue(&vv->vbi_wq, &wait);
+ current->state = TASK_RUNNING;
+
+ /* disable rps1 irqs */
+ SAA7146_IER_DISABLE(dev,MASK_28);
+
+ /* stop video-dma3 */
+ saa7146_write(dev, MC1, MASK_20);
+
+ if(signal_pending(current)) {
+
+ DEB_VBI(("aborted (rps:0x%08x).\n",saa7146_read(dev,RPS_ADDR1)));
+
+ /* stop rps1 for sure */
+ saa7146_write(dev, MC1, MASK_29);
+
+ pci_free_consistent(dev->pci, 4096, cpu, dma_addr);
+ return -EINTR;
+ }
+ }
+
+ pci_free_consistent(dev->pci, 4096, cpu, dma_addr);
+ return 0;
+}
+
+static void saa7146_set_vbi_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next)
+{
+ struct saa7146_vv *vv = dev->vv_data;
+
+ struct saa7146_video_dma vdma3;
+
+ int count = 0;
+ unsigned long e_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_E_FID_A : CMD_E_FID_B;
+ unsigned long o_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_O_FID_A : CMD_O_FID_B;
+
+/*
+ vdma3.base_even = 0xc8000000+2560*70;
+ vdma3.base_odd = 0xc8000000;
+ vdma3.prot_addr = 0xc8000000+2560*164;
+ vdma3.pitch = 2560;
+ vdma3.base_page = 0;
+ vdma3.num_line_byte = (64<<16)|((vbi_pixel_to_capture)<<0); // set above!
+*/
+ vdma3.base_even = buf->pt[2].offset;
+ vdma3.base_odd = buf->pt[2].offset + 16 * vbi_pixel_to_capture;
+ vdma3.prot_addr = buf->pt[2].offset + 16 * 2 * vbi_pixel_to_capture;
+ vdma3.pitch = vbi_pixel_to_capture;
+ vdma3.base_page = buf->pt[2].dma | ME1;
+ vdma3.num_line_byte = (16 << 16) | vbi_pixel_to_capture;
+
+ saa7146_write_out_dma(dev, 3, &vdma3);
+
+ /* write beginning of rps-program */
+ count = 0;
+
+ /* wait for o_fid_a/b / e_fid_a/b toggle only if bit 1 is not set */
+
+ /* we don't wait here for the first field anymore. this is different from the video
+ capture and might cause that the first buffer is only half filled (with only
+ one field). but since this is some sort of streaming data, this is not that negative.
+ but by doing this, we can use the whole engine from videobuf-dma-sg.c... */
+
+/*
+ WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | e_wait);
+ WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | o_wait);
+*/
+ /* set bit 1 */
+ WRITE_RPS1(CMD_WR_REG | (1 << 8) | (MC2/4));
+ WRITE_RPS1(MASK_28 | MASK_12);
+
+ /* turn on video-dma3 */
+ WRITE_RPS1(CMD_WR_REG_MASK | (MC1/4));
+ WRITE_RPS1(MASK_04 | MASK_20); /* => mask */
+ WRITE_RPS1(MASK_04 | MASK_20); /* => values */
+
+ /* wait for o_fid_a/b / e_fid_a/b toggle */
+ WRITE_RPS1(CMD_PAUSE | o_wait);
+ WRITE_RPS1(CMD_PAUSE | e_wait);
+
+ /* generate interrupt */
+ WRITE_RPS1(CMD_INTERRUPT);
+
+ /* stop */
+ WRITE_RPS1(CMD_STOP);
+
+ /* enable rps1 irqs */
+ SAA7146_IER_ENABLE(dev, MASK_28);
+
+ /* write the address of the rps-program */
+ saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
+
+ /* turn on rps */
+ saa7146_write(dev, MC1, (MASK_13 | MASK_29));
+}
+
+static int buffer_activate(struct saa7146_dev *dev,
+ struct saa7146_buf *buf,
+ struct saa7146_buf *next)
+{
+ struct saa7146_vv *vv = dev->vv_data;
+ buf->vb.state = VIDEOBUF_ACTIVE;
+
+ DEB_VBI(("dev:%p, buf:%p, next:%p\n",dev,buf,next));
+ saa7146_set_vbi_capture(dev,buf,next);
+
+ mod_timer(&vv->vbi_q.timeout, jiffies+BUFFER_TIMEOUT);
+ return 0;
+}
+
+static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,enum v4l2_field field)
+{
+ struct file *file = q->priv_data;
+ struct saa7146_fh *fh = file->private_data;
+ struct saa7146_dev *dev = fh->dev;
+ struct saa7146_buf *buf = (struct saa7146_buf *)vb;
+
+ int err = 0;
+ int lines, llength, size;
+
+ lines = 16 * 2 ; /* 2 fields */
+ llength = vbi_pixel_to_capture;
+ size = lines * llength;
+
+ DEB_VBI(("vb:%p\n",vb));
+
+ if (0 != buf->vb.baddr && buf->vb.bsize < size) {
+ DEB_VBI(("size mismatch.\n"));
+ return -EINVAL;
+ }
+
+ if (buf->vb.size != size)
+ saa7146_dma_free(dev,q,buf);
+
+ if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+ struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+
+ buf->vb.width = llength;
+ buf->vb.height = lines;
+ buf->vb.size = size;
+ buf->vb.field = field; // FIXME: check this
+
+ saa7146_pgtable_free(dev->pci, &buf->pt[2]);
+ saa7146_pgtable_alloc(dev->pci, &buf->pt[2]);
+
+ err = videobuf_iolock(q,&buf->vb, NULL);
+ if (err)
+ goto oops;
+ err = saa7146_pgtable_build_single(dev->pci, &buf->pt[2],
+ dma->sglist, dma->sglen);
+ if (0 != err)
+ return err;
+ }
+ buf->vb.state = VIDEOBUF_PREPARED;
+ buf->activate = buffer_activate;
+
+ return 0;
+
+ oops:
+ DEB_VBI(("error out.\n"));
+ saa7146_dma_free(dev,q,buf);
+
+ return err;
+}
+
+static int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
+{
+ int llength,lines;
+
+ lines = 16 * 2 ; /* 2 fields */
+ llength = vbi_pixel_to_capture;
+
+ *size = lines * llength;
+ *count = 2;
+
+ DEB_VBI(("count:%d, size:%d\n",*count,*size));
+
+ return 0;
+}
+
+static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+ struct file *file = q->priv_data;
+ struct saa7146_fh *fh = file->private_data;
+ struct saa7146_dev *dev = fh->dev;
+ struct saa7146_vv *vv = dev->vv_data;
+ struct saa7146_buf *buf = (struct saa7146_buf *)vb;
+
+ DEB_VBI(("vb:%p\n",vb));
+ saa7146_buffer_queue(dev,&vv->vbi_q,buf);
+}
+
+static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+ struct file *file = q->priv_data;
+ struct saa7146_fh *fh = file->private_data;
+ struct saa7146_dev *dev = fh->dev;
+ struct saa7146_buf *buf = (struct saa7146_buf *)vb;
+
+ DEB_VBI(("vb:%p\n",vb));
+ saa7146_dma_free(dev,q,buf);
+}
+
+static struct videobuf_queue_ops vbi_qops = {
+ .buf_setup = buffer_setup,
+ .buf_prepare = buffer_prepare,
+ .buf_queue = buffer_queue,
+ .buf_release = buffer_release,
+};
+
+/* ------------------------------------------------------------------ */
+
+static void vbi_stop(struct saa7146_fh *fh, struct file *file)
+{
+ struct saa7146_dev *dev = fh->dev;
+ struct saa7146_vv *vv = dev->vv_data;
+ unsigned long flags;
+ DEB_VBI(("dev:%p, fh:%p\n",dev, fh));
+
+ spin_lock_irqsave(&dev->slock,flags);
+
+ /* disable rps1 */
+ saa7146_write(dev, MC1, MASK_29);
+
+ /* disable rps1 irqs */
+ SAA7146_IER_DISABLE(dev, MASK_28);
+
+ /* shut down dma 3 transfers */
+ saa7146_write(dev, MC1, MASK_20);
+
+ if (vv->vbi_q.curr) {
+ saa7146_buffer_finish(dev,&vv->vbi_q,VIDEOBUF_DONE);
+ }
+
+ videobuf_queue_cancel(&fh->vbi_q);
+
+ vv->vbi_streaming = NULL;
+
+ del_timer(&vv->vbi_q.timeout);
+ del_timer(&fh->vbi_read_timeout);
+
+ spin_unlock_irqrestore(&dev->slock, flags);
+}
+
+static void vbi_read_timeout(unsigned long data)
+{
+ struct file *file = (struct file*)data;
+ struct saa7146_fh *fh = file->private_data;
+ struct saa7146_dev *dev = fh->dev;
+
+ DEB_VBI(("dev:%p, fh:%p\n",dev, fh));
+
+ vbi_stop(fh, file);
+}
+
+static void vbi_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
+{
+ DEB_VBI(("dev:%p\n",dev));
+
+ INIT_LIST_HEAD(&vv->vbi_q.queue);
+
+ init_timer(&vv->vbi_q.timeout);
+ vv->vbi_q.timeout.function = saa7146_buffer_timeout;
+ vv->vbi_q.timeout.data = (unsigned long)(&vv->vbi_q);
+ vv->vbi_q.dev = dev;
+
+ init_waitqueue_head(&vv->vbi_wq);
+}
+
+static int vbi_open(struct saa7146_dev *dev, struct file *file)
+{
+ struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
+
+ u32 arbtr_ctrl = saa7146_read(dev, PCI_BT_V1);
+ int ret = 0;
+
+ DEB_VBI(("dev:%p, fh:%p\n",dev,fh));
+
+ ret = saa7146_res_get(fh, RESOURCE_DMA3_BRS);
+ if (0 == ret) {
+ DEB_S(("cannot get vbi RESOURCE_DMA3_BRS resource\n"));
+ return -EBUSY;
+ }
+
+ /* adjust arbitrition control for video dma 3 */
+ arbtr_ctrl &= ~0x1f0000;
+ arbtr_ctrl |= 0x1d0000;
+ saa7146_write(dev, PCI_BT_V1, arbtr_ctrl);
+ saa7146_write(dev, MC2, (MASK_04|MASK_20));
+
+ memset(&fh->vbi_fmt,0,sizeof(fh->vbi_fmt));
+
+ fh->vbi_fmt.sampling_rate = 27000000;
+ fh->vbi_fmt.offset = 248; /* todo */
+ fh->vbi_fmt.samples_per_line = vbi_pixel_to_capture;
+ fh->vbi_fmt.sample_format = V4L2_PIX_FMT_GREY;
+
+ /* fixme: this only works for PAL */
+ fh->vbi_fmt.start[0] = 5;
+ fh->vbi_fmt.count[0] = 16;
+ fh->vbi_fmt.start[1] = 312;
+ fh->vbi_fmt.count[1] = 16;
+
+ videobuf_queue_sg_init(&fh->vbi_q, &vbi_qops,
+ &dev->pci->dev, &dev->slock,
+ V4L2_BUF_TYPE_VBI_CAPTURE,
+ V4L2_FIELD_SEQ_TB, // FIXME: does this really work?
+ sizeof(struct saa7146_buf),
+ file);
+
+ init_timer(&fh->vbi_read_timeout);
+ fh->vbi_read_timeout.function = vbi_read_timeout;
+ fh->vbi_read_timeout.data = (unsigned long)file;
+
+ /* initialize the brs */
+ if ( 0 != (SAA7146_USE_PORT_B_FOR_VBI & dev->ext_vv_data->flags)) {
+ saa7146_write(dev, BRS_CTRL, MASK_30|MASK_29 | (7 << 19));
+ } else {
+ saa7146_write(dev, BRS_CTRL, 0x00000001);
+
+ if (0 != (ret = vbi_workaround(dev))) {
+ DEB_VBI(("vbi workaround failed!\n"));
+ /* return ret;*/
+ }
+ }
+
+ /* upload brs register */
+ saa7146_write(dev, MC2, (MASK_08|MASK_24));
+ return 0;
+}
+
+static void vbi_close(struct saa7146_dev *dev, struct file *file)
+{
+ struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
+ struct saa7146_vv *vv = dev->vv_data;
+ DEB_VBI(("dev:%p, fh:%p\n",dev,fh));
+
+ if( fh == vv->vbi_streaming ) {
+ vbi_stop(fh, file);
+ }
+ saa7146_res_free(fh, RESOURCE_DMA3_BRS);
+}
+
+static void vbi_irq_done(struct saa7146_dev *dev, unsigned long status)
+{
+ struct saa7146_vv *vv = dev->vv_data;
+ spin_lock(&dev->slock);
+
+ if (vv->vbi_q.curr) {
+ DEB_VBI(("dev:%p, curr:%p\n",dev,vv->vbi_q.curr));
+ /* this must be += 2, one count for each field */
+ vv->vbi_fieldcount+=2;
+ vv->vbi_q.curr->vb.field_count = vv->vbi_fieldcount;
+ saa7146_buffer_finish(dev,&vv->vbi_q,VIDEOBUF_DONE);
+ } else {
+ DEB_VBI(("dev:%p\n",dev));
+ }
+ saa7146_buffer_next(dev,&vv->vbi_q,1);
+
+ spin_unlock(&dev->slock);
+}
+
+static ssize_t vbi_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
+{
+ struct saa7146_fh *fh = file->private_data;
+ struct saa7146_dev *dev = fh->dev;
+ struct saa7146_vv *vv = dev->vv_data;
+ ssize_t ret = 0;
+
+ DEB_VBI(("dev:%p, fh:%p\n",dev,fh));
+
+ if( NULL == vv->vbi_streaming ) {
+ // fixme: check if dma3 is available
+ // fixme: activate vbi engine here if necessary. (really?)
+ vv->vbi_streaming = fh;
+ }
+
+ if( fh != vv->vbi_streaming ) {
+ DEB_VBI(("open %p is already using vbi capture.",vv->vbi_streaming));
+ return -EBUSY;
+ }
+
+ mod_timer(&fh->vbi_read_timeout, jiffies+BUFFER_TIMEOUT);
+ ret = videobuf_read_stream(&fh->vbi_q, data, count, ppos, 1,
+ file->f_flags & O_NONBLOCK);
+/*
+ printk("BASE_ODD3: 0x%08x\n", saa7146_read(dev, BASE_ODD3));
+ printk("BASE_EVEN3: 0x%08x\n", saa7146_read(dev, BASE_EVEN3));
+ printk("PROT_ADDR3: 0x%08x\n", saa7146_read(dev, PROT_ADDR3));
+ printk("PITCH3: 0x%08x\n", saa7146_read(dev, PITCH3));
+ printk("BASE_PAGE3: 0x%08x\n", saa7146_read(dev, BASE_PAGE3));
+ printk("NUM_LINE_BYTE3: 0x%08x\n", saa7146_read(dev, NUM_LINE_BYTE3));
+ printk("BRS_CTRL: 0x%08x\n", saa7146_read(dev, BRS_CTRL));
+*/
+ return ret;
+}
+
+struct saa7146_use_ops saa7146_vbi_uops = {
+ .init = vbi_init,
+ .open = vbi_open,
+ .release = vbi_close,
+ .irq_done = vbi_irq_done,
+ .read = vbi_read,
+};
diff --git a/linux/drivers/media/video/saa7146/saa7146_video.c b/linux/drivers/media/video/saa7146/saa7146_video.c
new file mode 100644
index 000000000..b68c6288b
--- /dev/null
+++ b/linux/drivers/media/video/saa7146/saa7146_video.c
@@ -0,0 +1,1509 @@
+#include <media/saa7146_vv.h>
+#include "compat.h"
+
+static int max_memory = 32;
+
+module_param(max_memory, int, 0644);
+MODULE_PARM_DESC(max_memory, "maximum memory usage for capture buffers (default: 32Mb)");
+
+#define IS_CAPTURE_ACTIVE(fh) \
+ (((vv->video_status & STATUS_CAPTURE) != 0) && (vv->video_fh == fh))
+
+#define IS_OVERLAY_ACTIVE(fh) \
+ (((vv->video_status & STATUS_OVERLAY) != 0) && (vv->video_fh == fh))
+
+/* format descriptions for capture and preview */
+static struct saa7146_format formats[] = {
+ {
+ .name = "RGB-8 (3-3-2)",
+ .pixelformat = V4L2_PIX_FMT_RGB332,
+ .trans = RGB08_COMPOSED,
+ .depth = 8,
+ .flags = 0,
+ }, {
+ .name = "RGB-16 (5/B-6/G-5/R)",
+ .pixelformat = V4L2_PIX_FMT_RGB565,
+ .trans = RGB16_COMPOSED,
+ .depth = 16,
+ .flags = 0,
+ }, {
+ .name = "RGB-24 (B-G-R)",
+ .pixelformat = V4L2_PIX_FMT_BGR24,
+ .trans = RGB24_COMPOSED,
+ .depth = 24,
+ .flags = 0,
+ }, {
+ .name = "RGB-32 (B-G-R)",
+ .pixelformat = V4L2_PIX_FMT_BGR32,
+ .trans = RGB32_COMPOSED,
+ .depth = 32,
+ .flags = 0,
+ }, {
+ .name = "RGB-32 (R-G-B)",
+ .pixelformat = V4L2_PIX_FMT_RGB32,
+ .trans = RGB32_COMPOSED,
+ .depth = 32,
+ .flags = 0,
+ .swap = 0x2,
+ }, {
+ .name = "Greyscale-8",
+ .pixelformat = V4L2_PIX_FMT_GREY,
+ .trans = Y8,
+ .depth = 8,
+ .flags = 0,
+ }, {
+ .name = "YUV 4:2:2 planar (Y-Cb-Cr)",
+ .pixelformat = V4L2_PIX_FMT_YUV422P,
+ .trans = YUV422_DECOMPOSED,
+ .depth = 16,
+ .flags = FORMAT_BYTE_SWAP|FORMAT_IS_PLANAR,
+ }, {
+ .name = "YVU 4:2:0 planar (Y-Cb-Cr)",
+ .pixelformat = V4L2_PIX_FMT_YVU420,
+ .trans = YUV420_DECOMPOSED,
+ .depth = 12,
+ .flags = FORMAT_BYTE_SWAP|FORMAT_IS_PLANAR,
+ }, {
+ .name = "YUV 4:2:0 planar (Y-Cb-Cr)",
+ .pixelformat = V4L2_PIX_FMT_YUV420,
+ .trans = YUV420_DECOMPOSED,
+ .depth = 12,
+ .flags = FORMAT_IS_PLANAR,
+ }, {
+ .name = "YUV 4:2:2 (U-Y-V-Y)",
+ .pixelformat = V4L2_PIX_FMT_UYVY,
+ .trans = YUV422_COMPOSED,
+ .depth = 16,
+ .flags = 0,
+ }
+};
+
+/* unfortunately, the saa7146 contains a bug which prevents it from doing on-the-fly byte swaps.
+ due to this, it's impossible to provide additional *packed* formats, which are simply byte swapped
+ (like V4L2_PIX_FMT_YUYV) ... 8-( */
+
+static int NUM_FORMATS = sizeof(formats)/sizeof(struct saa7146_format);
+
+struct saa7146_format* format_by_fourcc(struct saa7146_dev *dev, int fourcc)
+{
+ int i, j = NUM_FORMATS;
+
+ for (i = 0; i < j; i++) {
+ if (formats[i].pixelformat == fourcc) {
+ return formats+i;
+ }
+ }
+
+ DEB_D(("unknown pixelformat:'%4.4s'\n",(char *)&fourcc));
+ return NULL;
+}
+
+static int g_fmt(struct saa7146_fh *fh, struct v4l2_format *f)
+{
+ struct saa7146_dev *dev = fh->dev;
+ DEB_EE(("dev:%p, fh:%p\n",dev,fh));
+
+ switch (f->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ f->fmt.pix = fh->video_fmt;
+ return 0;
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ f->fmt.win = fh->ov.win;
+ return 0;
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ {
+ f->fmt.vbi = fh->vbi_fmt;
+ return 0;
+ }
+ default:
+ DEB_D(("invalid format type '%d'.\n",f->type));
+ return -EINVAL;
+ }
+}
+
+static int try_win(struct saa7146_dev *dev, struct v4l2_window *win)
+{
+ struct saa7146_vv *vv = dev->vv_data;
+ enum v4l2_field field;
+ int maxw, maxh;
+
+ DEB_EE(("dev:%p\n",dev));
+
+ if (NULL == vv->ov_fb.base) {
+ DEB_D(("no fb base set.\n"));
+ return -EINVAL;
+ }
+ if (NULL == vv->ov_fmt) {
+ DEB_D(("no fb fmt set.\n"));
+ return -EINVAL;
+ }
+ if (win->w.width < 48 || win->w.height < 32) {
+ DEB_D(("min width/height. (%d,%d)\n",win->w.width,win->w.height));
+ return -EINVAL;
+ }
+ if (win->clipcount > 16) {
+ DEB_D(("clipcount too big.\n"));
+ return -EINVAL;
+ }
+
+ field = win->field;
+ maxw = vv->standard->h_max_out;
+ maxh = vv->standard->v_max_out;
+
+ if (V4L2_FIELD_ANY == field) {
+ field = (win->w.height > maxh/2)
+ ? V4L2_FIELD_INTERLACED
+ : V4L2_FIELD_TOP;
+ }
+ switch (field) {
+ case V4L2_FIELD_TOP:
+ case V4L2_FIELD_BOTTOM:
+ case V4L2_FIELD_ALTERNATE:
+ maxh = maxh / 2;
+ break;
+ case V4L2_FIELD_INTERLACED:
+ break;
+ default: {
+ DEB_D(("no known field mode '%d'.\n",field));
+ return -EINVAL;
+ }
+ }
+
+ win->field = field;
+ if (win->w.width > maxw)
+ win->w.width = maxw;
+ if (win->w.height > maxh)
+ win->w.height = maxh;
+
+ return 0;
+}
+
+static int try_fmt(struct saa7146_fh *fh, struct v4l2_format *f)
+{
+ struct saa7146_dev *dev = fh->dev;
+ struct saa7146_vv *vv = dev->vv_data;
+ int err;
+
+ switch (f->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ {
+ struct saa7146_format *fmt;
+ enum v4l2_field field;
+ int maxw, maxh;
+ int calc_bpl;
+
+ DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n",dev,fh));
+
+ fmt = format_by_fourcc(dev,f->fmt.pix.pixelformat);
+ if (NULL == fmt) {
+ return -EINVAL;
+ }
+
+ field = f->fmt.pix.field;
+ maxw = vv->standard->h_max_out;
+ maxh = vv->standard->v_max_out;
+
+ if (V4L2_FIELD_ANY == field) {
+ field = (f->fmt.pix.height > maxh/2)
+ ? V4L2_FIELD_INTERLACED
+ : V4L2_FIELD_BOTTOM;
+ }
+ switch (field) {
+ case V4L2_FIELD_ALTERNATE: {
+ vv->last_field = V4L2_FIELD_TOP;
+ maxh = maxh / 2;
+ break;
+ }
+ case V4L2_FIELD_TOP:
+ case V4L2_FIELD_BOTTOM:
+ vv->last_field = V4L2_FIELD_INTERLACED;
+ maxh = maxh / 2;
+ break;
+ case V4L2_FIELD_INTERLACED:
+ vv->last_field = V4L2_FIELD_INTERLACED;
+ break;
+ default: {
+ DEB_D(("no known field mode '%d'.\n",field));
+ return -EINVAL;
+ }
+ }
+
+ f->fmt.pix.field = field;
+ if (f->fmt.pix.width > maxw)
+ f->fmt.pix.width = maxw;
+ if (f->fmt.pix.height > maxh)
+ f->fmt.pix.height = maxh;
+
+ calc_bpl = (f->fmt.pix.width * fmt->depth)/8;
+
+ if (f->fmt.pix.bytesperline < calc_bpl)
+ f->fmt.pix.bytesperline = calc_bpl;
+
+ if (f->fmt.pix.bytesperline > (2*PAGE_SIZE * fmt->depth)/8) /* arbitrary constraint */
+ f->fmt.pix.bytesperline = calc_bpl;
+
+ f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height;
+ DEB_D(("w:%d, h:%d, bytesperline:%d, sizeimage:%d\n",f->fmt.pix.width,f->fmt.pix.height,f->fmt.pix.bytesperline,f->fmt.pix.sizeimage));
+
+ return 0;
+ }
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ DEB_EE(("V4L2_BUF_TYPE_VIDEO_OVERLAY: dev:%p, fh:%p\n",dev,fh));
+ err = try_win(dev,&f->fmt.win);
+ if (0 != err) {
+ return err;
+ }
+ return 0;
+ default:
+ DEB_EE(("unknown format type '%d'\n",f->type));
+ return -EINVAL;
+ }
+}
+
+int saa7146_start_preview(struct saa7146_fh *fh)
+{
+ struct saa7146_dev *dev = fh->dev;
+ struct saa7146_vv *vv = dev->vv_data;
+ int ret = 0, err = 0;
+
+ DEB_EE(("dev:%p, fh:%p\n",dev,fh));
+
+ /* check if we have overlay informations */
+ if( NULL == fh->ov.fh ) {
+ DEB_D(("no overlay data available. try S_FMT first.\n"));
+ return -EAGAIN;
+ }
+
+ /* check if streaming capture is running */
+ if (IS_CAPTURE_ACTIVE(fh) != 0) {
+ DEB_D(("streaming capture is active.\n"));
+ return -EBUSY;
+ }
+
+ /* check if overlay is running */
+ if (IS_OVERLAY_ACTIVE(fh) != 0) {
+ if (vv->video_fh == fh) {
+ DEB_D(("overlay is already active.\n"));
+ return 0;
+ }
+ DEB_D(("overlay is already active in another open.\n"));
+ return -EBUSY;
+ }
+
+ if (0 == saa7146_res_get(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP)) {
+ DEB_D(("cannot get necessary overlay resources\n"));
+ return -EBUSY;
+ }
+
+ err = try_win(dev,&fh->ov.win);
+ if (0 != err) {
+ saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
+ return -EBUSY;
+ }
+
+ vv->ov_data = &fh->ov;
+
+ DEB_D(("%dx%d+%d+%d %s field=%s\n",
+ fh->ov.win.w.width,fh->ov.win.w.height,
+ fh->ov.win.w.left,fh->ov.win.w.top,
+ vv->ov_fmt->name,v4l2_field_names[fh->ov.win.field]));
+
+ if (0 != (ret = saa7146_enable_overlay(fh))) {
+ DEB_D(("enabling overlay failed: %d\n",ret));
+ saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
+ return ret;
+ }
+
+ vv->video_status = STATUS_OVERLAY;
+ vv->video_fh = fh;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(saa7146_start_preview);
+
+int saa7146_stop_preview(struct saa7146_fh *fh)
+{
+ struct saa7146_dev *dev = fh->dev;
+ struct saa7146_vv *vv = dev->vv_data;
+
+ DEB_EE(("dev:%p, fh:%p\n",dev,fh));
+
+ /* check if streaming capture is running */
+ if (IS_CAPTURE_ACTIVE(fh) != 0) {
+ DEB_D(("streaming capture is active.\n"));
+ return -EBUSY;
+ }
+
+ /* check if overlay is running at all */
+ if ((vv->video_status & STATUS_OVERLAY) == 0) {
+ DEB_D(("no active overlay.\n"));
+ return 0;
+ }
+
+ if (vv->video_fh != fh) {
+ DEB_D(("overlay is active, but in another open.\n"));
+ return -EBUSY;
+ }
+
+ vv->video_status = 0;
+ vv->video_fh = NULL;
+
+ saa7146_disable_overlay(fh);
+
+ saa7146_res_free(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(saa7146_stop_preview);
+
+static int s_fmt(struct saa7146_fh *fh, struct v4l2_format *f)
+{
+ struct saa7146_dev *dev = fh->dev;
+ struct saa7146_vv *vv = dev->vv_data;
+
+ int err;
+
+ switch (f->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n",dev,fh));
+ if (IS_CAPTURE_ACTIVE(fh) != 0) {
+ DEB_EE(("streaming capture is active\n"));
+ return -EBUSY;
+ }
+ err = try_fmt(fh,f);
+ if (0 != err)
+ return err;
+ fh->video_fmt = f->fmt.pix;
+ DEB_EE(("set to pixelformat '%4.4s'\n",(char *)&fh->video_fmt.pixelformat));
+ return 0;
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ DEB_EE(("V4L2_BUF_TYPE_VIDEO_OVERLAY: dev:%p, fh:%p\n",dev,fh));
+ err = try_win(dev,&f->fmt.win);
+ if (0 != err)
+ return err;
+ mutex_lock(&dev->lock);
+ fh->ov.win = f->fmt.win;
+ fh->ov.nclips = f->fmt.win.clipcount;
+ if (fh->ov.nclips > 16)
+ fh->ov.nclips = 16;
+ if (copy_from_user(fh->ov.clips,f->fmt.win.clips,sizeof(struct v4l2_clip)*fh->ov.nclips)) {
+ mutex_unlock(&dev->lock);
+ return -EFAULT;
+ }
+
+ /* fh->ov.fh is used to indicate that we have valid overlay informations, too */
+ fh->ov.fh = fh;
+
+ mutex_unlock(&dev->lock);
+
+ /* check if our current overlay is active */
+ if (IS_OVERLAY_ACTIVE(fh) != 0) {
+ saa7146_stop_preview(fh);
+ saa7146_start_preview(fh);
+ }
+ return 0;
+ default:
+ DEB_D(("unknown format type '%d'\n",f->type));
+ return -EINVAL;
+ }
+}
+
+/********************************************************************************/
+/* device controls */
+
+static struct v4l2_queryctrl controls[] = {
+ {
+ .id = V4L2_CID_BRIGHTNESS,
+ .name = "Brightness",
+ .minimum = 0,
+ .maximum = 255,
+ .step = 1,
+ .default_value = 128,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ },{
+ .id = V4L2_CID_CONTRAST,
+ .name = "Contrast",
+ .minimum = 0,
+ .maximum = 127,
+ .step = 1,
+ .default_value = 64,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ },{
+ .id = V4L2_CID_SATURATION,
+ .name = "Saturation",
+ .minimum = 0,
+ .maximum = 127,
+ .step = 1,
+ .default_value = 64,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ },{
+ .id = V4L2_CID_VFLIP,
+ .name = "Vertical flip",
+ .minimum = 0,
+ .maximum = 1,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ },{
+ .id = V4L2_CID_HFLIP,
+ .name = "Horizontal flip",
+ .minimum = 0,
+ .maximum = 1,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ },
+};
+static int NUM_CONTROLS = sizeof(controls)/sizeof(struct v4l2_queryctrl);
+
+#define V4L2_CID_PRIVATE_LASTP1 (V4L2_CID_PRIVATE_BASE + 0)
+
+static struct v4l2_queryctrl* ctrl_by_id(int id)
+{
+ int i;
+
+ for (i = 0; i < NUM_CONTROLS; i++)
+ if (controls[i].id == id)
+ return controls+i;
+ return NULL;
+}
+
+static int get_control(struct saa7146_fh *fh, struct v4l2_control *c)
+{
+ struct saa7146_dev *dev = fh->dev;
+ struct saa7146_vv *vv = dev->vv_data;
+
+ const struct v4l2_queryctrl* ctrl;
+ u32 value = 0;
+
+ ctrl = ctrl_by_id(c->id);
+ if (NULL == ctrl)
+ return -EINVAL;
+ switch (c->id) {
+ case V4L2_CID_BRIGHTNESS:
+ value = saa7146_read(dev, BCS_CTRL);
+ c->value = 0xff & (value >> 24);
+ DEB_D(("V4L2_CID_BRIGHTNESS: %d\n",c->value));
+ break;
+ case V4L2_CID_CONTRAST:
+ value = saa7146_read(dev, BCS_CTRL);
+ c->value = 0x7f & (value >> 16);
+ DEB_D(("V4L2_CID_CONTRAST: %d\n",c->value));
+ break;
+ case V4L2_CID_SATURATION:
+ value = saa7146_read(dev, BCS_CTRL);
+ c->value = 0x7f & (value >> 0);
+ DEB_D(("V4L2_CID_SATURATION: %d\n",c->value));
+ break;
+ case V4L2_CID_VFLIP:
+ c->value = vv->vflip;
+ DEB_D(("V4L2_CID_VFLIP: %d\n",c->value));
+ break;
+ case V4L2_CID_HFLIP:
+ c->value = vv->hflip;
+ DEB_D(("V4L2_CID_HFLIP: %d\n",c->value));
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int set_control(struct saa7146_fh *fh, struct v4l2_control *c)
+{
+ struct saa7146_dev *dev = fh->dev;
+ struct saa7146_vv *vv = dev->vv_data;
+
+ const struct v4l2_queryctrl* ctrl;
+
+ ctrl = ctrl_by_id(c->id);
+ if (NULL == ctrl) {
+ DEB_D(("unknown control %d\n",c->id));
+ return -EINVAL;
+ }
+
+ mutex_lock(&dev->lock);
+
+ switch (ctrl->type) {
+ case V4L2_CTRL_TYPE_BOOLEAN:
+ case V4L2_CTRL_TYPE_MENU:
+ case V4L2_CTRL_TYPE_INTEGER:
+ if (c->value < ctrl->minimum)
+ c->value = ctrl->minimum;
+ if (c->value > ctrl->maximum)
+ c->value = ctrl->maximum;
+ break;
+ default:
+ /* nothing */;
+ };
+
+ switch (c->id) {
+ case V4L2_CID_BRIGHTNESS: {
+ u32 value = saa7146_read(dev, BCS_CTRL);
+ value &= 0x00ffffff;
+ value |= (c->value << 24);
+ saa7146_write(dev, BCS_CTRL, value);
+ saa7146_write(dev, MC2, MASK_22 | MASK_06 );
+ break;
+ }
+ case V4L2_CID_CONTRAST: {
+ u32 value = saa7146_read(dev, BCS_CTRL);
+ value &= 0xff00ffff;
+ value |= (c->value << 16);
+ saa7146_write(dev, BCS_CTRL, value);
+ saa7146_write(dev, MC2, MASK_22 | MASK_06 );
+ break;
+ }
+ case V4L2_CID_SATURATION: {
+ u32 value = saa7146_read(dev, BCS_CTRL);
+ value &= 0xffffff00;
+ value |= (c->value << 0);
+ saa7146_write(dev, BCS_CTRL, value);
+ saa7146_write(dev, MC2, MASK_22 | MASK_06 );
+ break;
+ }
+ case V4L2_CID_HFLIP:
+ /* fixme: we can support changing VFLIP and HFLIP here... */
+ if (IS_CAPTURE_ACTIVE(fh) != 0) {
+ DEB_D(("V4L2_CID_HFLIP while active capture.\n"));
+ mutex_unlock(&dev->lock);
+ return -EINVAL;
+ }
+ vv->hflip = c->value;
+ break;
+ case V4L2_CID_VFLIP:
+ if (IS_CAPTURE_ACTIVE(fh) != 0) {
+ DEB_D(("V4L2_CID_VFLIP while active capture.\n"));
+ mutex_unlock(&dev->lock);
+ return -EINVAL;
+ }
+ vv->vflip = c->value;
+ break;
+ default: {
+ return -EINVAL;
+ }
+ }
+ mutex_unlock(&dev->lock);
+
+ if (IS_OVERLAY_ACTIVE(fh) != 0) {
+ saa7146_stop_preview(fh);
+ saa7146_start_preview(fh);
+ }
+ return 0;
+}
+
+/********************************************************************************/
+/* common pagetable functions */
+
+static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *buf)
+{
+ struct pci_dev *pci = dev->pci;
+ struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+ struct scatterlist *list = dma->sglist;
+ int length = dma->sglen;
+ struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);
+
+ DEB_EE(("dev:%p, buf:%p, sg_len:%d\n",dev,buf,length));
+
+ if( 0 != IS_PLANAR(sfmt->trans)) {
+ struct saa7146_pgtable *pt1 = &buf->pt[0];
+ struct saa7146_pgtable *pt2 = &buf->pt[1];
+ struct saa7146_pgtable *pt3 = &buf->pt[2];
+ u32 *ptr1, *ptr2, *ptr3;
+ u32 fill;
+
+ int size = buf->fmt->width*buf->fmt->height;
+ int i,p,m1,m2,m3,o1,o2;
+
+ switch( sfmt->depth ) {
+ case 12: {
+ /* create some offsets inside the page table */
+ m1 = ((size+PAGE_SIZE)/PAGE_SIZE)-1;
+ m2 = ((size+(size/4)+PAGE_SIZE)/PAGE_SIZE)-1;
+ m3 = ((size+(size/2)+PAGE_SIZE)/PAGE_SIZE)-1;
+ o1 = size%PAGE_SIZE;
+ o2 = (size+(size/4))%PAGE_SIZE;
+ DEB_CAP(("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",size,m1,m2,m3,o1,o2));
+ break;
+ }
+ case 16: {
+ /* create some offsets inside the page table */
+ m1 = ((size+PAGE_SIZE)/PAGE_SIZE)-1;
+ m2 = ((size+(size/2)+PAGE_SIZE)/PAGE_SIZE)-1;
+ m3 = ((2*size+PAGE_SIZE)/PAGE_SIZE)-1;
+ o1 = size%PAGE_SIZE;
+ o2 = (size+(size/2))%PAGE_SIZE;
+ DEB_CAP(("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",size,m1,m2,m3,o1,o2));
+ break;
+ }
+ default: {
+ return -1;
+ }
+ }
+
+ ptr1 = pt1->cpu;
+ ptr2 = pt2->cpu;
+ ptr3 = pt3->cpu;
+
+ /* walk all pages, copy all page addresses to ptr1 */
+ for (i = 0; i < length; i++, list++) {
+ for (p = 0; p * 4096 < list->length; p++, ptr1++) {
+ *ptr1 = cpu_to_le32(sg_dma_address(list) - list->offset);
+ }
+ }
+/*
+ ptr1 = pt1->cpu;
+ for(j=0;j<40;j++) {
+ printk("ptr1 %d: 0x%08x\n",j,ptr1[j]);
+ }
+*/
+
+ /* if we have a user buffer, the first page may not be
+ aligned to a page boundary. */
+ pt1->offset = list->offset;
+ pt2->offset = pt1->offset+o1;
+ pt3->offset = pt1->offset+o2;
+
+ /* create video-dma2 page table */
+ ptr1 = pt1->cpu;
+ for(i = m1; i <= m2 ; i++, ptr2++) {
+ *ptr2 = ptr1[i];
+ }
+ fill = *(ptr2-1);
+ for(;i<1024;i++,ptr2++) {
+ *ptr2 = fill;
+ }
+ /* create video-dma3 page table */
+ ptr1 = pt1->cpu;
+ for(i = m2; i <= m3; i++,ptr3++) {
+ *ptr3 = ptr1[i];
+ }
+ fill = *(ptr3-1);
+ for(;i<1024;i++,ptr3++) {
+ *ptr3 = fill;
+ }
+ /* finally: finish up video-dma1 page table */
+ ptr1 = pt1->cpu+m1;
+ fill = pt1->cpu[m1];
+ for(i=m1;i<1024;i++,ptr1++) {
+ *ptr1 = fill;
+ }
+/*
+ ptr1 = pt1->cpu;
+ ptr2 = pt2->cpu;
+ ptr3 = pt3->cpu;
+ for(j=0;j<40;j++) {
+ printk("ptr1 %d: 0x%08x\n",j,ptr1[j]);
+ }
+ for(j=0;j<40;j++) {
+ printk("ptr2 %d: 0x%08x\n",j,ptr2[j]);
+ }
+ for(j=0;j<40;j++) {
+ printk("ptr3 %d: 0x%08x\n",j,ptr3[j]);
+ }
+*/
+ } else {
+ struct saa7146_pgtable *pt = &buf->pt[0];
+ return saa7146_pgtable_build_single(pci, pt, list, length);
+ }
+
+ return 0;
+}
+
+
+/********************************************************************************/
+/* file operations */
+
+static int video_begin(struct saa7146_fh *fh)
+{
+ struct saa7146_dev *dev = fh->dev;
+ struct saa7146_vv *vv = dev->vv_data;
+ struct saa7146_format *fmt = NULL;
+ unsigned int resource;
+ int ret = 0, err = 0;
+
+ DEB_EE(("dev:%p, fh:%p\n",dev,fh));
+
+ if ((vv->video_status & STATUS_CAPTURE) != 0) {
+ if (vv->video_fh == fh) {
+ DEB_S(("already capturing.\n"));
+ return 0;
+ }
+ DEB_S(("already capturing in another open.\n"));
+ return -EBUSY;
+ }
+
+ if ((vv->video_status & STATUS_OVERLAY) != 0) {
+ DEB_S(("warning: suspending overlay video for streaming capture.\n"));
+ vv->ov_suspend = vv->video_fh;
+ err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */
+ if (0 != err) {
+ DEB_D(("suspending video failed. aborting\n"));
+ return err;
+ }
+ }
+
+ fmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);
+ /* we need to have a valid format set here */
+ BUG_ON(NULL == fmt);
+
+ if (0 != (fmt->flags & FORMAT_IS_PLANAR)) {
+ resource = RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP|RESOURCE_DMA3_BRS;
+ } else {
+ resource = RESOURCE_DMA1_HPS;
+ }
+
+ ret = saa7146_res_get(fh, resource);
+ if (0 == ret) {
+ DEB_S(("cannot get capture resource %d\n",resource));
+ if (vv->ov_suspend != NULL) {
+ saa7146_start_preview(vv->ov_suspend);
+ vv->ov_suspend = NULL;
+ }
+ return -EBUSY;
+ }
+
+ /* clear out beginning of streaming bit (rps register 0)*/
+ saa7146_write(dev, MC2, MASK_27 );
+
+ /* enable rps0 irqs */
+ SAA7146_IER_ENABLE(dev, MASK_27);
+
+ vv->video_fh = fh;
+ vv->video_status = STATUS_CAPTURE;
+
+ return 0;
+}
+
+static int video_end(struct saa7146_fh *fh, struct file *file)
+{
+ struct saa7146_dev *dev = fh->dev;
+ struct saa7146_vv *vv = dev->vv_data;
+ struct saa7146_format *fmt = NULL;
+ unsigned long flags;
+ unsigned int resource;
+ u32 dmas = 0;
+ DEB_EE(("dev:%p, fh:%p\n",dev,fh));
+
+ if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) {
+ DEB_S(("not capturing.\n"));
+ return 0;
+ }
+
+ if (vv->video_fh != fh) {
+ DEB_S(("capturing, but in another open.\n"));
+ return -EBUSY;
+ }
+
+ fmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);
+ /* we need to have a valid format set here */
+ BUG_ON(NULL == fmt);
+
+ if (0 != (fmt->flags & FORMAT_IS_PLANAR)) {
+ resource = RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP|RESOURCE_DMA3_BRS;
+ dmas = MASK_22 | MASK_21 | MASK_20;
+ } else {
+ resource = RESOURCE_DMA1_HPS;
+ dmas = MASK_22;
+ }
+ spin_lock_irqsave(&dev->slock,flags);
+
+ /* disable rps0 */
+ saa7146_write(dev, MC1, MASK_28);
+
+ /* disable rps0 irqs */
+ SAA7146_IER_DISABLE(dev, MASK_27);
+
+ /* shut down all used video dma transfers */
+ saa7146_write(dev, MC1, dmas);
+
+ spin_unlock_irqrestore(&dev->slock, flags);
+
+ vv->video_fh = NULL;
+ vv->video_status = 0;
+
+ saa7146_res_free(fh, resource);
+
+ if (vv->ov_suspend != NULL) {
+ saa7146_start_preview(vv->ov_suspend);
+ vv->ov_suspend = NULL;
+ }
+
+ return 0;
+}
+
+/*
+ * This function is _not_ called directly, but from
+ * video_generic_ioctl (and maybe others). userspace
+ * copying is done already, arg is a kernel pointer.
+ */
+
+int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg)
+{
+ struct saa7146_fh *fh = file->private_data;
+ struct saa7146_dev *dev = fh->dev;
+ struct saa7146_vv *vv = dev->vv_data;
+
+ int err = 0, result = 0, ee = 0;
+
+ struct saa7146_use_ops *ops;
+ struct videobuf_queue *q;
+
+ /* check if extension handles the command */
+ for(ee = 0; dev->ext_vv_data->ioctls[ee].flags != 0; ee++) {
+ if( cmd == dev->ext_vv_data->ioctls[ee].cmd )
+ break;
+ }
+
+ if( 0 != (dev->ext_vv_data->ioctls[ee].flags & SAA7146_EXCLUSIVE) ) {
+ DEB_D(("extension handles ioctl exclusive.\n"));
+ result = dev->ext_vv_data->ioctl(fh, cmd, arg);
+ return result;
+ }
+ if( 0 != (dev->ext_vv_data->ioctls[ee].flags & SAA7146_BEFORE) ) {
+ DEB_D(("extension handles ioctl before.\n"));
+ result = dev->ext_vv_data->ioctl(fh, cmd, arg);
+ if( -EAGAIN != result ) {
+ return result;
+ }
+ }
+
+ /* fixme: add handle "after" case (is it still needed?) */
+
+ switch (fh->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
+ ops = &saa7146_video_uops;
+ q = &fh->video_q;
+ break;
+ }
+ case V4L2_BUF_TYPE_VBI_CAPTURE: {
+ ops = &saa7146_vbi_uops;
+ q = &fh->vbi_q;
+ break;
+ }
+ default:
+ BUG();
+ return 0;
+ }
+
+ switch (cmd) {
+ case VIDIOC_QUERYCAP:
+ {
+ struct v4l2_capability *cap = arg;
+ memset(cap,0,sizeof(*cap));
+
+ DEB_EE(("VIDIOC_QUERYCAP\n"));
+
+ strcpy((char *)cap->driver, "saa7146 v4l2");
+ strlcpy((char *)cap->card, dev->ext->name, sizeof(cap->card));
+ sprintf((char *)cap->bus_info,"PCI:%s", pci_name(dev->pci));
+ cap->version = SAA7146_VERSION_CODE;
+ cap->capabilities =
+ V4L2_CAP_VIDEO_CAPTURE |
+ V4L2_CAP_VIDEO_OVERLAY |
+ V4L2_CAP_READWRITE |
+ V4L2_CAP_STREAMING;
+ cap->capabilities |= dev->ext_vv_data->capabilities;
+ return 0;
+ }
+ case VIDIOC_G_FBUF:
+ {
+ struct v4l2_framebuffer *fb = arg;
+
+ DEB_EE(("VIDIOC_G_FBUF\n"));
+
+ *fb = vv->ov_fb;
+ fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
+ return 0;
+ }
+ case VIDIOC_S_FBUF:
+ {
+ struct v4l2_framebuffer *fb = arg;
+ struct saa7146_format *fmt;
+
+ DEB_EE(("VIDIOC_S_FBUF\n"));
+
+ if(!capable(CAP_SYS_ADMIN) &&
+ !capable(CAP_SYS_RAWIO))
+ return -EPERM;
+
+ /* check args */
+ fmt = format_by_fourcc(dev,fb->fmt.pixelformat);
+ if (NULL == fmt) {
+ return -EINVAL;
+ }
+
+ /* planar formats are not allowed for overlay video, clipping and video dma would clash */
+ if (0 != (fmt->flags & FORMAT_IS_PLANAR)) {
+ DEB_S(("planar pixelformat '%4.4s' not allowed for overlay\n",(char *)&fmt->pixelformat));
+ }
+
+ /* check if overlay is running */
+ if (IS_OVERLAY_ACTIVE(fh) != 0) {
+ if (vv->video_fh != fh) {
+ DEB_D(("refusing to change framebuffer informations while overlay is active in another open.\n"));
+ return -EBUSY;
+ }
+ }
+
+ mutex_lock(&dev->lock);
+
+ /* ok, accept it */
+ vv->ov_fb = *fb;
+ vv->ov_fmt = fmt;
+ if (0 == vv->ov_fb.fmt.bytesperline)
+ vv->ov_fb.fmt.bytesperline =
+ vv->ov_fb.fmt.width*fmt->depth/8;
+
+ mutex_unlock(&dev->lock);
+
+ return 0;
+ }
+ case VIDIOC_ENUM_FMT:
+ {
+ struct v4l2_fmtdesc *f = arg;
+ int index;
+
+ switch (f->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY: {
+ index = f->index;
+ if (index < 0 || index >= NUM_FORMATS) {
+ return -EINVAL;
+ }
+ memset(f,0,sizeof(*f));
+ f->index = index;
+ strlcpy((char *)f->description,formats[index].name,sizeof(f->description));
+ f->pixelformat = formats[index].pixelformat;
+ break;
+ }
+ default:
+ return -EINVAL;
+ }
+
+ DEB_EE(("VIDIOC_ENUM_FMT: type:%d, index:%d\n",f->type,f->index));
+ return 0;
+ }
+ case VIDIOC_QUERYCTRL:
+ {
+ const struct v4l2_queryctrl *ctrl;
+ struct v4l2_queryctrl *c = arg;
+
+ if ((c->id < V4L2_CID_BASE ||
+ c->id >= V4L2_CID_LASTP1) &&
+ (c->id < V4L2_CID_PRIVATE_BASE ||
+ c->id >= V4L2_CID_PRIVATE_LASTP1))
+ return -EINVAL;
+
+ ctrl = ctrl_by_id(c->id);
+ if( NULL == ctrl ) {
+ return -EINVAL;
+/*
+ c->flags = V4L2_CTRL_FLAG_DISABLED;
+ return 0;
+*/
+ }
+
+ DEB_EE(("VIDIOC_QUERYCTRL: id:%d\n",c->id));
+ *c = *ctrl;
+ return 0;
+ }
+ case VIDIOC_G_CTRL: {
+ DEB_EE(("VIDIOC_G_CTRL\n"));
+ return get_control(fh,arg);
+ }
+ case VIDIOC_S_CTRL:
+ {
+ DEB_EE(("VIDIOC_S_CTRL\n"));
+ err = set_control(fh,arg);
+ return err;
+ }
+ case VIDIOC_G_PARM:
+ {
+ struct v4l2_streamparm *parm = arg;
+ if( parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ) {
+ return -EINVAL;
+ }
+ memset(&parm->parm.capture,0,sizeof(struct v4l2_captureparm));
+ parm->parm.capture.readbuffers = 1;
+ // fixme: only for PAL!
+ parm->parm.capture.timeperframe.numerator = 1;
+ parm->parm.capture.timeperframe.denominator = 25;
+ return 0;
+ }
+ case VIDIOC_G_FMT:
+ {
+ struct v4l2_format *f = arg;
+ DEB_EE(("VIDIOC_G_FMT\n"));
+ return g_fmt(fh,f);
+ }
+ case VIDIOC_S_FMT:
+ {
+ struct v4l2_format *f = arg;
+ DEB_EE(("VIDIOC_S_FMT\n"));
+ return s_fmt(fh,f);
+ }
+ case VIDIOC_TRY_FMT:
+ {
+ struct v4l2_format *f = arg;
+ DEB_EE(("VIDIOC_TRY_FMT\n"));
+ return try_fmt(fh,f);
+ }
+ case VIDIOC_G_STD:
+ {
+ v4l2_std_id *id = arg;
+ DEB_EE(("VIDIOC_G_STD\n"));
+ *id = vv->standard->id;
+ return 0;
+ }
+ /* the saa7146 supfhrts (used in conjunction with the saa7111a for example)
+ PAL / NTSC / SECAM. if your hardware does not (or does more)
+ -- override this function in your extension */
+ case VIDIOC_ENUMSTD:
+ {
+ struct v4l2_standard *e = arg;
+ if (e->index < 0 )
+ return -EINVAL;
+ if( e->index < dev->ext_vv_data->num_stds ) {
+ DEB_EE(("VIDIOC_ENUMSTD: index:%d\n",e->index));
+ v4l2_video_std_construct(e, dev->ext_vv_data->stds[e->index].id, dev->ext_vv_data->stds[e->index].name);
+ return 0;
+ }
+ return -EINVAL;
+ }
+ case VIDIOC_S_STD:
+ {
+ v4l2_std_id *id = arg;
+ int found = 0;
+ int i, err;
+
+ DEB_EE(("VIDIOC_S_STD\n"));
+
+ if ((vv->video_status & STATUS_CAPTURE) == STATUS_CAPTURE) {
+ DEB_D(("cannot change video standard while streaming capture is active\n"));
+ return -EBUSY;
+ }
+
+ if ((vv->video_status & STATUS_OVERLAY) != 0) {
+ vv->ov_suspend = vv->video_fh;
+ err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */
+ if (0 != err) {
+ DEB_D(("suspending video failed. aborting\n"));
+ return err;
+ }
+ }
+
+ mutex_lock(&dev->lock);
+
+ for(i = 0; i < dev->ext_vv_data->num_stds; i++)
+ if (*id & dev->ext_vv_data->stds[i].id)
+ break;
+ if (i != dev->ext_vv_data->num_stds) {
+ vv->standard = &dev->ext_vv_data->stds[i];
+ if( NULL != dev->ext_vv_data->std_callback )
+ dev->ext_vv_data->std_callback(dev, vv->standard);
+ found = 1;
+ }
+
+ mutex_unlock(&dev->lock);
+
+ if (vv->ov_suspend != NULL) {
+ saa7146_start_preview(vv->ov_suspend);
+ vv->ov_suspend = NULL;
+ }
+
+ if( 0 == found ) {
+ DEB_EE(("VIDIOC_S_STD: standard not found.\n"));
+ return -EINVAL;
+ }
+
+ DEB_EE(("VIDIOC_S_STD: set to standard to '%s'\n",vv->standard->name));
+ return 0;
+ }
+ case VIDIOC_OVERLAY:
+ {
+ int on = *(int *)arg;
+ int err = 0;
+
+ DEB_D(("VIDIOC_OVERLAY on:%d\n",on));
+ if (on != 0) {
+ err = saa7146_start_preview(fh);
+ } else {
+ err = saa7146_stop_preview(fh);
+ }
+ return err;
+ }
+ case VIDIOC_REQBUFS: {
+ struct v4l2_requestbuffers *req = arg;
+ DEB_D(("VIDIOC_REQBUFS, type:%d\n",req->type));
+ return videobuf_reqbufs(q,req);
+ }
+ case VIDIOC_QUERYBUF: {
+ struct v4l2_buffer *buf = arg;
+ DEB_D(("VIDIOC_QUERYBUF, type:%d, offset:%d\n",buf->type,buf->m.offset));
+ return videobuf_querybuf(q,buf);
+ }
+ case VIDIOC_QBUF: {
+ struct v4l2_buffer *buf = arg;
+ int ret = 0;
+ ret = videobuf_qbuf(q,buf);
+ DEB_D(("VIDIOC_QBUF: ret:%d, index:%d\n",ret,buf->index));
+ return ret;
+ }
+ case VIDIOC_DQBUF: {
+ struct v4l2_buffer *buf = arg;
+ int ret = 0;
+ ret = videobuf_dqbuf(q,buf,file->f_flags & O_NONBLOCK);
+ DEB_D(("VIDIOC_DQBUF: ret:%d, index:%d\n",ret,buf->index));
+ return ret;
+ }
+ case VIDIOC_STREAMON: {
+ int *type = arg;
+ DEB_D(("VIDIOC_STREAMON, type:%d\n",*type));
+
+ err = video_begin(fh);
+ if( 0 != err) {
+ return err;
+ }
+ err = videobuf_streamon(q);
+ return err;
+ }
+ case VIDIOC_STREAMOFF: {
+ int *type = arg;
+
+ DEB_D(("VIDIOC_STREAMOFF, type:%d\n",*type));
+
+ /* ugly: we need to copy some checks from video_end(),
+ because videobuf_streamoff() relies on the capture running.
+ check and fix this */
+ if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) {
+ DEB_S(("not capturing.\n"));
+ return 0;
+ }
+
+ if (vv->video_fh != fh) {
+ DEB_S(("capturing, but in another open.\n"));
+ return -EBUSY;
+ }
+
+ err = videobuf_streamoff(q);
+ if (0 != err) {
+ DEB_D(("warning: videobuf_streamoff() failed.\n"));
+ video_end(fh, file);
+ } else {
+ err = video_end(fh, file);
+ }
+ return err;
+ }
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+ case VIDIOCGMBUF:
+ {
+ struct video_mbuf *mbuf = arg;
+ struct videobuf_queue *q;
+ int i;
+
+ /* fixme: number of capture buffers and sizes for v4l apps */
+ int gbuffers = 2;
+ int gbufsize = 768*576*4;
+
+ DEB_D(("VIDIOCGMBUF \n"));
+
+ q = &fh->video_q;
+ err = videobuf_mmap_setup(q,gbuffers,gbufsize,
+ V4L2_MEMORY_MMAP);
+ if (err < 0)
+ return err;
+
+ gbuffers = err;
+ memset(mbuf,0,sizeof(*mbuf));
+ mbuf->frames = gbuffers;
+ mbuf->size = gbuffers * gbufsize;
+ for (i = 0; i < gbuffers; i++)
+ mbuf->offsets[i] = i * gbufsize;
+ return 0;
+ }
+#endif
+ default:
+ return v4l_compat_translate_ioctl(inode,file,cmd,arg,
+ saa7146_video_do_ioctl);
+ }
+ return 0;
+}
+
+/*********************************************************************************/
+/* buffer handling functions */
+
+static int buffer_activate (struct saa7146_dev *dev,
+ struct saa7146_buf *buf,
+ struct saa7146_buf *next)
+{
+ struct saa7146_vv *vv = dev->vv_data;
+
+ buf->vb.state = VIDEOBUF_ACTIVE;
+ saa7146_set_capture(dev,buf,next);
+
+ mod_timer(&vv->video_q.timeout, jiffies+BUFFER_TIMEOUT);
+ return 0;
+}
+
+static int buffer_prepare(struct videobuf_queue *q,
+ struct videobuf_buffer *vb, enum v4l2_field field)
+{
+ struct file *file = q->priv_data;
+ struct saa7146_fh *fh = file->private_data;
+ struct saa7146_dev *dev = fh->dev;
+ struct saa7146_vv *vv = dev->vv_data;
+ struct saa7146_buf *buf = (struct saa7146_buf *)vb;
+ int size,err = 0;
+
+ DEB_CAP(("vbuf:%p\n",vb));
+
+ /* sanity checks */
+ if (fh->video_fmt.width < 48 ||
+ fh->video_fmt.height < 32 ||
+ fh->video_fmt.width > vv->standard->h_max_out ||
+ fh->video_fmt.height > vv->standard->v_max_out) {
+ DEB_D(("w (%d) / h (%d) out of bounds.\n",fh->video_fmt.width,fh->video_fmt.height));
+ return -EINVAL;
+ }
+
+ size = fh->video_fmt.sizeimage;
+ if (0 != buf->vb.baddr && buf->vb.bsize < size) {
+ DEB_D(("size mismatch.\n"));
+ return -EINVAL;
+ }
+
+ DEB_CAP(("buffer_prepare [size=%dx%d,bytes=%d,fields=%s]\n",
+ fh->video_fmt.width,fh->video_fmt.height,size,v4l2_field_names[fh->video_fmt.field]));
+ if (buf->vb.width != fh->video_fmt.width ||
+ buf->vb.bytesperline != fh->video_fmt.bytesperline ||
+ buf->vb.height != fh->video_fmt.height ||
+ buf->vb.size != size ||
+ buf->vb.field != field ||
+ buf->vb.field != fh->video_fmt.field ||
+ buf->fmt != &fh->video_fmt) {
+ saa7146_dma_free(dev,q,buf);
+ }
+
+ if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+ struct saa7146_format *sfmt;
+
+ buf->vb.bytesperline = fh->video_fmt.bytesperline;
+ buf->vb.width = fh->video_fmt.width;
+ buf->vb.height = fh->video_fmt.height;
+ buf->vb.size = size;
+ buf->vb.field = field;
+ buf->fmt = &fh->video_fmt;
+ buf->vb.field = fh->video_fmt.field;
+
+ sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);
+
+ if( 0 != IS_PLANAR(sfmt->trans)) {
+ saa7146_pgtable_free(dev->pci, &buf->pt[0]);
+ saa7146_pgtable_free(dev->pci, &buf->pt[1]);
+ saa7146_pgtable_free(dev->pci, &buf->pt[2]);
+
+ saa7146_pgtable_alloc(dev->pci, &buf->pt[0]);
+ saa7146_pgtable_alloc(dev->pci, &buf->pt[1]);
+ saa7146_pgtable_alloc(dev->pci, &buf->pt[2]);
+ } else {
+ saa7146_pgtable_free(dev->pci, &buf->pt[0]);
+ saa7146_pgtable_alloc(dev->pci, &buf->pt[0]);
+ }
+
+ err = videobuf_iolock(q,&buf->vb, &vv->ov_fb);
+ if (err)
+ goto oops;
+ err = saa7146_pgtable_build(dev,buf);
+ if (err)
+ goto oops;
+ }
+ buf->vb.state = VIDEOBUF_PREPARED;
+ buf->activate = buffer_activate;
+
+ return 0;
+
+ oops:
+ DEB_D(("error out.\n"));
+ saa7146_dma_free(dev,q,buf);
+
+ return err;
+}
+
+static int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
+{
+ struct file *file = q->priv_data;
+ struct saa7146_fh *fh = file->private_data;
+
+ if (0 == *count || *count > MAX_SAA7146_CAPTURE_BUFFERS)
+ *count = MAX_SAA7146_CAPTURE_BUFFERS;
+
+ *size = fh->video_fmt.sizeimage;
+
+ /* check if we exceed the "max_memory" parameter */
+ if( (*count * *size) > (max_memory*1048576) ) {
+ *count = (max_memory*1048576) / *size;
+ }
+
+ DEB_CAP(("%d buffers, %d bytes each.\n",*count,*size));
+
+ return 0;
+}
+
+static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+ struct file *file = q->priv_data;
+ struct saa7146_fh *fh = file->private_data;
+ struct saa7146_dev *dev = fh->dev;
+ struct saa7146_vv *vv = dev->vv_data;
+ struct saa7146_buf *buf = (struct saa7146_buf *)vb;
+
+ DEB_CAP(("vbuf:%p\n",vb));
+ saa7146_buffer_queue(fh->dev,&vv->video_q,buf);
+}
+
+static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+ struct file *file = q->priv_data;
+ struct saa7146_fh *fh = file->private_data;
+ struct saa7146_dev *dev = fh->dev;
+ struct saa7146_buf *buf = (struct saa7146_buf *)vb;
+
+ DEB_CAP(("vbuf:%p\n",vb));
+ saa7146_dma_free(dev,q,buf);
+}
+
+static struct videobuf_queue_ops video_qops = {
+ .buf_setup = buffer_setup,
+ .buf_prepare = buffer_prepare,
+ .buf_queue = buffer_queue,
+ .buf_release = buffer_release,
+};
+
+/********************************************************************************/
+/* file operations */
+
+static void video_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
+{
+ INIT_LIST_HEAD(&vv->video_q.queue);
+
+ init_timer(&vv->video_q.timeout);
+ vv->video_q.timeout.function = saa7146_buffer_timeout;
+ vv->video_q.timeout.data = (unsigned long)(&vv->video_q);
+ vv->video_q.dev = dev;
+
+ /* set some default values */
+ vv->standard = &dev->ext_vv_data->stds[0];
+
+ /* FIXME: what's this? */
+ vv->current_hps_source = SAA7146_HPS_SOURCE_PORT_A;
+ vv->current_hps_sync = SAA7146_HPS_SYNC_PORT_A;
+}
+
+
+static int video_open(struct saa7146_dev *dev, struct file *file)
+{
+ struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
+ struct saa7146_format *sfmt;
+
+ fh->video_fmt.width = 384;
+ fh->video_fmt.height = 288;
+ fh->video_fmt.pixelformat = V4L2_PIX_FMT_BGR24;
+ fh->video_fmt.bytesperline = 0;
+ fh->video_fmt.field = V4L2_FIELD_ANY;
+ sfmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);
+ fh->video_fmt.sizeimage = (fh->video_fmt.width * fh->video_fmt.height * sfmt->depth)/8;
+
+ videobuf_queue_sg_init(&fh->video_q, &video_qops,
+ &dev->pci->dev, &dev->slock,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ V4L2_FIELD_INTERLACED,
+ sizeof(struct saa7146_buf),
+ file);
+
+ return 0;
+}
+
+
+static void video_close(struct saa7146_dev *dev, struct file *file)
+{
+ struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
+ struct saa7146_vv *vv = dev->vv_data;
+ struct videobuf_queue *q = &fh->video_q;
+ int err;
+
+ if (IS_CAPTURE_ACTIVE(fh) != 0) {
+ err = video_end(fh, file);
+ } else if (IS_OVERLAY_ACTIVE(fh) != 0) {
+ err = saa7146_stop_preview(fh);
+ }
+
+ videobuf_stop(q);
+
+ /* hmm, why is this function declared void? */
+ /* return err */
+}
+
+
+static void video_irq_done(struct saa7146_dev *dev, unsigned long st)
+{
+ struct saa7146_vv *vv = dev->vv_data;
+ struct saa7146_dmaqueue *q = &vv->video_q;
+
+ spin_lock(&dev->slock);
+ DEB_CAP(("called.\n"));
+
+ /* only finish the buffer if we have one... */
+ if( NULL != q->curr ) {
+ saa7146_buffer_finish(dev,q,VIDEOBUF_DONE);
+ }
+ saa7146_buffer_next(dev,q,0);
+
+ spin_unlock(&dev->slock);
+}
+
+static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
+{
+ struct saa7146_fh *fh = file->private_data;
+ struct saa7146_dev *dev = fh->dev;
+ struct saa7146_vv *vv = dev->vv_data;
+ ssize_t ret = 0;
+
+ DEB_EE(("called.\n"));
+
+ if ((vv->video_status & STATUS_CAPTURE) != 0) {
+ /* fixme: should we allow read() captures while streaming capture? */
+ if (vv->video_fh == fh) {
+ DEB_S(("already capturing.\n"));
+ return -EBUSY;
+ }
+ DEB_S(("already capturing in another open.\n"));
+ return -EBUSY;
+ }
+
+ ret = video_begin(fh);
+ if( 0 != ret) {
+ goto out;
+ }
+
+ ret = videobuf_read_one(&fh->video_q , data, count, ppos,
+ file->f_flags & O_NONBLOCK);
+ if (ret != 0) {
+ video_end(fh, file);
+ } else {
+ ret = video_end(fh, file);
+ }
+out:
+ /* restart overlay if it was active before */
+ if (vv->ov_suspend != NULL) {
+ saa7146_start_preview(vv->ov_suspend);
+ vv->ov_suspend = NULL;
+ }
+
+ return ret;
+}
+
+struct saa7146_use_ops saa7146_video_uops = {
+ .init = video_init,
+ .open = video_open,
+ .release = video_close,
+ .irq_done = video_irq_done,
+ .read = video_read,
+};
diff --git a/linux/drivers/media/video/tda8290.c b/linux/drivers/media/video/tda8290.c
deleted file mode 100644
index d57602d22..000000000
--- a/linux/drivers/media/video/tda8290.c
+++ /dev/null
@@ -1,833 +0,0 @@
-/*
-
- i2c tv tuner chip device driver
- controls the philips tda8290+75 tuner chip combo.
-
- 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.
-
- This "tda8290" module was split apart from the original "tuner" module.
-*/
-
-#include <linux/i2c.h>
-#include <linux/delay.h>
-#include "compat.h"
-#include <linux/videodev.h>
-#include "tuner-i2c.h"
-#include "tda8290.h"
-#include "tda827x.h"
-#include "tda18271.h"
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-#include "i2c-compat.h"
-#endif
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "enable verbose debug messages");
-
-/* ---------------------------------------------------------------------- */
-
-struct tda8290_priv {
- struct tuner_i2c_props i2c_props;
-
- unsigned char tda8290_easy_mode;
-
- unsigned char tda827x_addr;
-
- unsigned char ver;
-#define TDA8290 1
-#define TDA8295 2
-#define TDA8275 4
-#define TDA8275A 8
-#define TDA18271 16
-
- struct tda827x_config cfg;
-};
-
-/*---------------------------------------------------------------------*/
-
-static int tda8290_i2c_bridge(struct dvb_frontend *fe, int close)
-{
- struct tda8290_priv *priv = fe->analog_demod_priv;
-
- unsigned char enable[2] = { 0x21, 0xC0 };
- unsigned char disable[2] = { 0x21, 0x00 };
- unsigned char *msg;
-
- if (close) {
- msg = enable;
- tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
- /* let the bridge stabilize */
- msleep(20);
- } else {
- msg = disable;
- tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
- }
-
- return 0;
-}
-
-#if 1
-static int tda8295_i2c_bridge(struct dvb_frontend *fe, int close)
-{
- struct tda8290_priv *priv = fe->analog_demod_priv;
-
- unsigned char enable[2] = { 0x45, 0xc1 };
- unsigned char disable[2] = { 0x46, 0x00 };
- unsigned char buf[3] = { 0x45, 0x01, 0x00 };
- unsigned char *msg;
-
- if (close) {
- msg = enable;
- tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
- /* let the bridge stabilize */
- msleep(20);
- } else {
- msg = disable;
- tuner_i2c_xfer_send(&priv->i2c_props, msg, 1);
- tuner_i2c_xfer_recv(&priv->i2c_props, &msg[1], 1);
-
- buf[2] = msg[1];
- buf[2] &= ~0x04;
- tuner_i2c_xfer_send(&priv->i2c_props, buf, 3);
- msleep(5);
-
- msg[1] |= 0x04;
- tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
- }
-
- return 0;
-}
-#else
-static int tda8295_i2c_bridge(struct dvb_frontend *fe, int close)
-{
- struct tda8290_priv *priv = fe->analog_demod_priv;
-
- unsigned char buf[] = { 0x45, 0x00 };
-
- tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1);
- tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1);
-
- buf[1] &= 0x3f;
- if (close)
- buf[1] |= 0xc0;
- else
- buf[1] |= 0x80;
-
- tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
-
- return 0;
-}
-#endif
-
-/*---------------------------------------------------------------------*/
-
-static void set_audio(struct dvb_frontend *fe,
- struct analog_parameters *params)
-{
- struct tda8290_priv *priv = fe->analog_demod_priv;
- char* mode;
-
- if (params->std & V4L2_STD_MN) {
- priv->tda8290_easy_mode = 0x01;
- mode = "MN";
- } else if (params->std & V4L2_STD_B) {
- priv->tda8290_easy_mode = 0x02;
- mode = "B";
- } else if (params->std & V4L2_STD_GH) {
- priv->tda8290_easy_mode = 0x04;
- mode = "GH";
- } else if (params->std & V4L2_STD_PAL_I) {
- priv->tda8290_easy_mode = 0x08;
- mode = "I";
- } else if (params->std & V4L2_STD_DK) {
- priv->tda8290_easy_mode = 0x10;
- mode = "DK";
- } else if (params->std & V4L2_STD_SECAM_L) {
- priv->tda8290_easy_mode = 0x20;
- mode = "L";
- } else if (params->std & V4L2_STD_SECAM_LC) {
- priv->tda8290_easy_mode = 0x40;
- mode = "LC";
- } else {
- priv->tda8290_easy_mode = 0x10;
- mode = "xx";
- }
-
- tuner_dbg("setting tda829x to system %s\n", mode);
-}
-
-static void tda8290_set_params(struct dvb_frontend *fe,
- struct analog_parameters *params)
-{
- struct tda8290_priv *priv = fe->analog_demod_priv;
-
- unsigned char soft_reset[] = { 0x00, 0x00 };
- unsigned char easy_mode[] = { 0x01, priv->tda8290_easy_mode };
- unsigned char expert_mode[] = { 0x01, 0x80 };
- unsigned char agc_out_on[] = { 0x02, 0x00 };
- unsigned char gainset_off[] = { 0x28, 0x14 };
- unsigned char if_agc_spd[] = { 0x0f, 0x88 };
- unsigned char adc_head_6[] = { 0x05, 0x04 };
- unsigned char adc_head_9[] = { 0x05, 0x02 };
- unsigned char adc_head_12[] = { 0x05, 0x01 };
- unsigned char pll_bw_nom[] = { 0x0d, 0x47 };
- unsigned char pll_bw_low[] = { 0x0d, 0x27 };
- unsigned char gainset_2[] = { 0x28, 0x64 };
- unsigned char agc_rst_on[] = { 0x0e, 0x0b };
- unsigned char agc_rst_off[] = { 0x0e, 0x09 };
- unsigned char if_agc_set[] = { 0x0f, 0x81 };
- unsigned char addr_adc_sat = 0x1a;
- unsigned char addr_agc_stat = 0x1d;
- unsigned char addr_pll_stat = 0x1b;
- unsigned char adc_sat, agc_stat,
- pll_stat;
- int i;
-
- set_audio(fe, params);
-
- if (priv->cfg.config)
- tuner_dbg("tda827xa config is 0x%02x\n", priv->cfg.config);
- tuner_i2c_xfer_send(&priv->i2c_props, easy_mode, 2);
- tuner_i2c_xfer_send(&priv->i2c_props, agc_out_on, 2);
- tuner_i2c_xfer_send(&priv->i2c_props, soft_reset, 2);
- msleep(1);
-
- expert_mode[1] = priv->tda8290_easy_mode + 0x80;
- tuner_i2c_xfer_send(&priv->i2c_props, expert_mode, 2);
- tuner_i2c_xfer_send(&priv->i2c_props, gainset_off, 2);
- tuner_i2c_xfer_send(&priv->i2c_props, if_agc_spd, 2);
- if (priv->tda8290_easy_mode & 0x60)
- tuner_i2c_xfer_send(&priv->i2c_props, adc_head_9, 2);
- else
- tuner_i2c_xfer_send(&priv->i2c_props, adc_head_6, 2);
- tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_nom, 2);
-
- tda8290_i2c_bridge(fe, 1);
-
- if (fe->ops.tuner_ops.set_analog_params)
- fe->ops.tuner_ops.set_analog_params(fe, params);
-
- for (i = 0; i < 3; i++) {
- tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1);
- tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1);
- if (pll_stat & 0x80) {
- tuner_i2c_xfer_send(&priv->i2c_props, &addr_adc_sat, 1);
- tuner_i2c_xfer_recv(&priv->i2c_props, &adc_sat, 1);
- tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1);
- tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1);
- tuner_dbg("tda8290 is locked, AGC: %d\n", agc_stat);
- break;
- } else {
- tuner_dbg("tda8290 not locked, no signal?\n");
- msleep(100);
- }
- }
- /* adjust headroom resp. gain */
- if ((agc_stat > 115) || (!(pll_stat & 0x80) && (adc_sat < 20))) {
- tuner_dbg("adjust gain, step 1. Agc: %d, ADC stat: %d, lock: %d\n",
- agc_stat, adc_sat, pll_stat & 0x80);
- tuner_i2c_xfer_send(&priv->i2c_props, gainset_2, 2);
- msleep(100);
- tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1);
- tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1);
- tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1);
- tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1);
- if ((agc_stat > 115) || !(pll_stat & 0x80)) {
- tuner_dbg("adjust gain, step 2. Agc: %d, lock: %d\n",
- agc_stat, pll_stat & 0x80);
- if (priv->cfg.agcf)
- priv->cfg.agcf(fe);
- msleep(100);
- tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1);
- tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1);
- tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1);
- tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1);
- if((agc_stat > 115) || !(pll_stat & 0x80)) {
- tuner_dbg("adjust gain, step 3. Agc: %d\n", agc_stat);
- tuner_i2c_xfer_send(&priv->i2c_props, adc_head_12, 2);
- tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_low, 2);
- msleep(100);
- }
- }
- }
-
- /* l/ l' deadlock? */
- if(priv->tda8290_easy_mode & 0x60) {
- tuner_i2c_xfer_send(&priv->i2c_props, &addr_adc_sat, 1);
- tuner_i2c_xfer_recv(&priv->i2c_props, &adc_sat, 1);
- tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1);
- tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1);
- if ((adc_sat > 20) || !(pll_stat & 0x80)) {
- tuner_dbg("trying to resolve SECAM L deadlock\n");
- tuner_i2c_xfer_send(&priv->i2c_props, agc_rst_on, 2);
- msleep(40);
- tuner_i2c_xfer_send(&priv->i2c_props, agc_rst_off, 2);
- }
- }
-
- tda8290_i2c_bridge(fe, 0);
- tuner_i2c_xfer_send(&priv->i2c_props, if_agc_set, 2);
-}
-
-/*---------------------------------------------------------------------*/
-
-static void tda8295_power(struct dvb_frontend *fe, int enable)
-{
- struct tda8290_priv *priv = fe->analog_demod_priv;
- unsigned char buf[] = { 0x30, 0x00 }; /* clb_stdbt */
-
- tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1);
- tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1);
-
- if (enable)
- buf[1] = 0x01;
- else
- buf[1] = 0x03;
-
- tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
-}
-
-static void tda8295_set_easy_mode(struct dvb_frontend *fe, int enable)
-{
- struct tda8290_priv *priv = fe->analog_demod_priv;
- unsigned char buf[] = { 0x01, 0x00 };
-
- tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1);
- tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1);
-
- if (enable)
- buf[1] = 0x01; /* rising edge sets regs 0x02 - 0x23 */
- else
- buf[1] = 0x00; /* reset active bit */
-
- tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
-}
-
-static void tda8295_set_video_std(struct dvb_frontend *fe)
-{
- struct tda8290_priv *priv = fe->analog_demod_priv;
- unsigned char buf[] = { 0x00, priv->tda8290_easy_mode };
-
- tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
-
- tda8295_set_easy_mode(fe, 1);
- msleep(20);
- tda8295_set_easy_mode(fe, 0);
-}
-
-/*---------------------------------------------------------------------*/
-
-static void tda8295_agc1_out(struct dvb_frontend *fe, int enable)
-{
- struct tda8290_priv *priv = fe->analog_demod_priv;
- unsigned char buf[] = { 0x02, 0x00 }; /* DIV_FUNC */
-
- tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1);
- tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1);
-
- if (enable)
- buf[1] &= ~0x40;
- else
- buf[1] |= 0x40;
-
- tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
-}
-
-static void tda8295_agc2_out(struct dvb_frontend *fe, int enable)
-{
- struct tda8290_priv *priv = fe->analog_demod_priv;
- unsigned char set_gpio_cf[] = { 0x44, 0x00 };
- unsigned char set_gpio_val[] = { 0x46, 0x00 };
-
- tuner_i2c_xfer_send(&priv->i2c_props, &set_gpio_cf[0], 1);
- tuner_i2c_xfer_recv(&priv->i2c_props, &set_gpio_cf[1], 1);
- tuner_i2c_xfer_send(&priv->i2c_props, &set_gpio_val[0], 1);
- tuner_i2c_xfer_recv(&priv->i2c_props, &set_gpio_val[1], 1);
-
- set_gpio_cf[1] &= 0xf0; /* clear GPIO_0 bits 3-0 */
-
- if (enable) {
- set_gpio_cf[1] |= 0x01; /* config GPIO_0 as Open Drain Out */
- set_gpio_val[1] &= 0xfe; /* set GPIO_0 pin low */
- }
- tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_cf, 2);
- tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_val, 2);
-}
-
-static int tda8295_has_signal(struct dvb_frontend *fe)
-{
- struct tda8290_priv *priv = fe->analog_demod_priv;
-
- unsigned char hvpll_stat = 0x26;
- unsigned char ret;
-
- tuner_i2c_xfer_send(&priv->i2c_props, &hvpll_stat, 1);
- tuner_i2c_xfer_recv(&priv->i2c_props, &ret, 1);
- return (ret & 0x01) ? 65535 : 0;
-}
-
-/*---------------------------------------------------------------------*/
-
-static void tda8295_set_params(struct dvb_frontend *fe,
- struct analog_parameters *params)
-{
- struct tda8290_priv *priv = fe->analog_demod_priv;
-
- unsigned char blanking_mode[] = { 0x1d, 0x00 };
-
- set_audio(fe, params);
-
- tuner_dbg("%s: freq = %d\n", __func__, params->frequency);
-
- tda8295_power(fe, 1);
- tda8295_agc1_out(fe, 1);
-
- tuner_i2c_xfer_send(&priv->i2c_props, &blanking_mode[0], 1);
- tuner_i2c_xfer_recv(&priv->i2c_props, &blanking_mode[1], 1);
-
- tda8295_set_video_std(fe);
-
- blanking_mode[1] = 0x03;
- tuner_i2c_xfer_send(&priv->i2c_props, blanking_mode, 2);
- msleep(20);
-
- tda8295_i2c_bridge(fe, 1);
-
- if (fe->ops.tuner_ops.set_analog_params)
- fe->ops.tuner_ops.set_analog_params(fe, params);
-
- if (priv->cfg.agcf)
- priv->cfg.agcf(fe);
-
- if (tda8295_has_signal(fe))
- tuner_dbg("tda8295 is locked\n");
- else
- tuner_dbg("tda8295 not locked, no signal?\n");
-
- tda8295_i2c_bridge(fe, 0);
-}
-
-/*---------------------------------------------------------------------*/
-
-static int tda8290_has_signal(struct dvb_frontend *fe)
-{
- struct tda8290_priv *priv = fe->analog_demod_priv;
-
- unsigned char i2c_get_afc[1] = { 0x1B };
- unsigned char afc = 0;
-
- tuner_i2c_xfer_send(&priv->i2c_props, i2c_get_afc, ARRAY_SIZE(i2c_get_afc));
- tuner_i2c_xfer_recv(&priv->i2c_props, &afc, 1);
- return (afc & 0x80)? 65535:0;
-}
-
-/*---------------------------------------------------------------------*/
-
-static void tda8290_standby(struct dvb_frontend *fe)
-{
- struct tda8290_priv *priv = fe->analog_demod_priv;
-
- unsigned char cb1[] = { 0x30, 0xD0 };
- unsigned char tda8290_standby[] = { 0x00, 0x02 };
- unsigned char tda8290_agc_tri[] = { 0x02, 0x20 };
- struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0, .buf=cb1, .len = 2};
-
- tda8290_i2c_bridge(fe, 1);
- if (priv->ver & TDA8275A)
- cb1[1] = 0x90;
- i2c_transfer(priv->i2c_props.adap, &msg, 1);
- tda8290_i2c_bridge(fe, 0);
- tuner_i2c_xfer_send(&priv->i2c_props, tda8290_agc_tri, 2);
- tuner_i2c_xfer_send(&priv->i2c_props, tda8290_standby, 2);
-}
-
-static void tda8295_standby(struct dvb_frontend *fe)
-{
- tda8295_agc1_out(fe, 0); /* Put AGC in tri-state */
-
- tda8295_power(fe, 0);
-}
-
-static void tda8290_init_if(struct dvb_frontend *fe)
-{
- struct tda8290_priv *priv = fe->analog_demod_priv;
-
- unsigned char set_VS[] = { 0x30, 0x6F };
- unsigned char set_GP00_CF[] = { 0x20, 0x01 };
- unsigned char set_GP01_CF[] = { 0x20, 0x0B };
-
- if ((priv->cfg.config == 1) || (priv->cfg.config == 2))
- tuner_i2c_xfer_send(&priv->i2c_props, set_GP00_CF, 2);
- else
- tuner_i2c_xfer_send(&priv->i2c_props, set_GP01_CF, 2);
- tuner_i2c_xfer_send(&priv->i2c_props, set_VS, 2);
-}
-
-static void tda8295_init_if(struct dvb_frontend *fe)
-{
- struct tda8290_priv *priv = fe->analog_demod_priv;
-
- static unsigned char set_adc_ctl[] = { 0x33, 0x14 };
- static unsigned char set_adc_ctl2[] = { 0x34, 0x00 };
- static unsigned char set_pll_reg6[] = { 0x3e, 0x63 };
- static unsigned char set_pll_reg0[] = { 0x38, 0x23 };
- static unsigned char set_pll_reg7[] = { 0x3f, 0x01 };
- static unsigned char set_pll_reg10[] = { 0x42, 0x61 };
- static unsigned char set_gpio_reg0[] = { 0x44, 0x0b };
-
- tda8295_power(fe, 1);
-
- tda8295_set_easy_mode(fe, 0);
- tda8295_set_video_std(fe);
-
- tuner_i2c_xfer_send(&priv->i2c_props, set_adc_ctl, 2);
- tuner_i2c_xfer_send(&priv->i2c_props, set_adc_ctl2, 2);
- tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg6, 2);
- tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg0, 2);
- tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg7, 2);
- tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg10, 2);
- tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_reg0, 2);
-
- tda8295_agc1_out(fe, 0);
- tda8295_agc2_out(fe, 0);
-}
-
-static void tda8290_init_tuner(struct dvb_frontend *fe)
-{
- struct tda8290_priv *priv = fe->analog_demod_priv;
- unsigned char tda8275_init[] = { 0x00, 0x00, 0x00, 0x40, 0xdC, 0x04, 0xAf,
- 0x3F, 0x2A, 0x04, 0xFF, 0x00, 0x00, 0x40 };
- unsigned char tda8275a_init[] = { 0x00, 0x00, 0x00, 0x00, 0xdC, 0x05, 0x8b,
- 0x0c, 0x04, 0x20, 0xFF, 0x00, 0x00, 0x4b };
- struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0,
- .buf=tda8275_init, .len = 14};
- if (priv->ver & TDA8275A)
- msg.buf = tda8275a_init;
-
- tda8290_i2c_bridge(fe, 1);
- i2c_transfer(priv->i2c_props.adap, &msg, 1);
- tda8290_i2c_bridge(fe, 0);
-}
-
-/*---------------------------------------------------------------------*/
-
-static void tda829x_release(struct dvb_frontend *fe)
-{
- struct tda8290_priv *priv = fe->analog_demod_priv;
-
- /* only try to release the tuner if we've
- * attached it from within this module */
- if (priv->ver & (TDA18271 | TDA8275 | TDA8275A))
- if (fe->ops.tuner_ops.release)
- fe->ops.tuner_ops.release(fe);
-
- kfree(fe->analog_demod_priv);
- fe->analog_demod_priv = NULL;
-}
-
-static struct tda18271_config tda829x_tda18271_config = {
- .gate = TDA18271_GATE_ANALOG,
-};
-
-static int tda829x_find_tuner(struct dvb_frontend *fe)
-{
- struct tda8290_priv *priv = fe->analog_demod_priv;
- struct analog_demod_ops *analog_ops = &fe->ops.analog_ops;
- int i, ret, tuners_found;
- u32 tuner_addrs;
- u8 data;
- struct i2c_msg msg = { .flags = I2C_M_RD, .buf = &data, .len = 1 };
-
- if (NULL == analog_ops->i2c_gate_ctrl)
- return -EINVAL;
-
- analog_ops->i2c_gate_ctrl(fe, 1);
-
- /* probe for tuner chip */
- tuners_found = 0;
- tuner_addrs = 0;
- for (i = 0x60; i <= 0x63; i++) {
- msg.addr = i;
- ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
- if (ret == 1) {
- tuners_found++;
- tuner_addrs = (tuner_addrs << 8) + i;
- }
- }
- /* if there is more than one tuner, we expect the right one is
- behind the bridge and we choose the highest address that doesn't
- give a response now
- */
-
- analog_ops->i2c_gate_ctrl(fe, 0);
-
- if (tuners_found > 1)
- for (i = 0; i < tuners_found; i++) {
- msg.addr = tuner_addrs & 0xff;
- ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
- if (ret == 1)
- tuner_addrs = tuner_addrs >> 8;
- else
- break;
- }
-
- if (tuner_addrs == 0) {
- tuner_addrs = 0x60;
- tuner_info("could not clearly identify tuner address, "
- "defaulting to %x\n", tuner_addrs);
- } else {
- tuner_addrs = tuner_addrs & 0xff;
- tuner_info("setting tuner address to %x\n", tuner_addrs);
- }
- priv->tda827x_addr = tuner_addrs;
- msg.addr = tuner_addrs;
-
- analog_ops->i2c_gate_ctrl(fe, 1);
- ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
-
- if (ret != 1) {
- tuner_warn("tuner access failed!\n");
- return -EREMOTEIO;
- }
-
- if ((data == 0x83) || (data == 0x84)) {
- priv->ver |= TDA18271;
- tda18271_attach(fe, priv->tda827x_addr,
- priv->i2c_props.adap,
- &tda829x_tda18271_config);
- } else {
- if ((data & 0x3c) == 0)
- priv->ver |= TDA8275;
- else
- priv->ver |= TDA8275A;
-
- tda827x_attach(fe, priv->tda827x_addr, priv->i2c_props.adap, &priv->cfg);
- priv->cfg.switch_addr = priv->i2c_props.addr;
- }
- if (fe->ops.tuner_ops.init)
- fe->ops.tuner_ops.init(fe);
-
- if (fe->ops.tuner_ops.sleep)
- fe->ops.tuner_ops.sleep(fe);
-
- analog_ops->i2c_gate_ctrl(fe, 0);
-
- return 0;
-}
-
-static int tda8290_probe(struct tuner_i2c_props *i2c_props)
-{
-#define TDA8290_ID 0x89
- unsigned char tda8290_id[] = { 0x1f, 0x00 };
-
- /* detect tda8290 */
- tuner_i2c_xfer_send(i2c_props, &tda8290_id[0], 1);
- tuner_i2c_xfer_recv(i2c_props, &tda8290_id[1], 1);
-
- if (tda8290_id[1] == TDA8290_ID) {
- if (debug)
- printk(KERN_DEBUG "%s: tda8290 detected @ %d-%04x\n",
- __func__, i2c_adapter_id(i2c_props->adap),
- i2c_props->addr);
- return 0;
- }
-
- return -ENODEV;
-}
-
-static int tda8295_probe(struct tuner_i2c_props *i2c_props)
-{
-#define TDA8295_ID 0x8a
- unsigned char tda8295_id[] = { 0x2f, 0x00 };
-
- /* detect tda8295 */
- tuner_i2c_xfer_send(i2c_props, &tda8295_id[0], 1);
- tuner_i2c_xfer_recv(i2c_props, &tda8295_id[1], 1);
-
- if (tda8295_id[1] == TDA8295_ID) {
- if (debug)
- printk(KERN_DEBUG "%s: tda8295 detected @ %d-%04x\n",
- __func__, i2c_adapter_id(i2c_props->adap),
- i2c_props->addr);
- return 0;
- }
-
- return -ENODEV;
-}
-
-static struct analog_demod_ops tda8290_ops = {
- .set_params = tda8290_set_params,
- .has_signal = tda8290_has_signal,
- .standby = tda8290_standby,
- .release = tda829x_release,
- .i2c_gate_ctrl = tda8290_i2c_bridge,
-};
-
-static struct analog_demod_ops tda8295_ops = {
- .set_params = tda8295_set_params,
- .has_signal = tda8295_has_signal,
- .standby = tda8295_standby,
- .release = tda829x_release,
- .i2c_gate_ctrl = tda8295_i2c_bridge,
-};
-
-struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
- struct i2c_adapter *i2c_adap, u8 i2c_addr,
- struct tda829x_config *cfg)
-{
- struct tda8290_priv *priv = NULL;
- char *name;
-
- priv = kzalloc(sizeof(struct tda8290_priv), GFP_KERNEL);
- if (priv == NULL)
- return NULL;
- fe->analog_demod_priv = priv;
-
- priv->i2c_props.addr = i2c_addr;
- priv->i2c_props.adap = i2c_adap;
- priv->i2c_props.name = "tda829x";
- if (cfg) {
- priv->cfg.config = cfg->lna_cfg;
- priv->cfg.tuner_callback = cfg->tuner_callback;
- }
-
- if (tda8290_probe(&priv->i2c_props) == 0) {
- priv->ver = TDA8290;
- memcpy(&fe->ops.analog_ops, &tda8290_ops,
- sizeof(struct analog_demod_ops));
- }
-
- if (tda8295_probe(&priv->i2c_props) == 0) {
- priv->ver = TDA8295;
- memcpy(&fe->ops.analog_ops, &tda8295_ops,
- sizeof(struct analog_demod_ops));
- }
-
- if ((!(cfg) || (TDA829X_PROBE_TUNER == cfg->probe_tuner)) &&
- (tda829x_find_tuner(fe) < 0))
- goto fail;
-
- switch (priv->ver) {
- case TDA8290:
- name = "tda8290";
- break;
- case TDA8295:
- name = "tda8295";
- break;
- case TDA8290 | TDA8275:
- name = "tda8290+75";
- break;
- case TDA8295 | TDA8275:
- name = "tda8295+75";
- break;
- case TDA8290 | TDA8275A:
- name = "tda8290+75a";
- break;
- case TDA8295 | TDA8275A:
- name = "tda8295+75a";
- break;
- case TDA8290 | TDA18271:
- name = "tda8290+18271";
- break;
- case TDA8295 | TDA18271:
- name = "tda8295+18271";
- break;
- default:
- goto fail;
- }
- tuner_info("type set to %s\n", name);
-
- fe->ops.analog_ops.info.name = name;
-
- if (priv->ver & TDA8290) {
- tda8290_init_tuner(fe);
- tda8290_init_if(fe);
- } else if (priv->ver & TDA8295)
- tda8295_init_if(fe);
-
-#if 0
- t->mode = V4L2_TUNER_ANALOG_TV;
-#endif
- return fe;
-
-fail:
- tda829x_release(fe);
- return NULL;
-}
-EXPORT_SYMBOL_GPL(tda829x_attach);
-
-int tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr)
-{
- struct tuner_i2c_props i2c_props = {
- .adap = i2c_adap,
- .addr = i2c_addr,
- };
-
- unsigned char soft_reset[] = { 0x00, 0x00 };
- unsigned char easy_mode_b[] = { 0x01, 0x02 };
- unsigned char easy_mode_g[] = { 0x01, 0x04 };
- unsigned char restore_9886[] = { 0x00, 0xd6, 0x30 };
- unsigned char addr_dto_lsb = 0x07;
- unsigned char data;
-#define PROBE_BUFFER_SIZE 8
- unsigned char buf[PROBE_BUFFER_SIZE];
- int i;
-
- /* rule out tda9887, which would return the same byte repeatedly */
- tuner_i2c_xfer_send(&i2c_props, soft_reset, 1);
- tuner_i2c_xfer_recv(&i2c_props, buf, PROBE_BUFFER_SIZE);
- for (i = 1; i < PROBE_BUFFER_SIZE; i++) {
- if (buf[i] != buf[0])
- break;
- }
-
- /* all bytes are equal, not a tda829x - probably a tda9887 */
- if (i == PROBE_BUFFER_SIZE)
- return -ENODEV;
-
- if ((tda8290_probe(&i2c_props) == 0) ||
- (tda8295_probe(&i2c_props) == 0))
- return 0;
-
- /* fall back to old probing method */
- tuner_i2c_xfer_send(&i2c_props, easy_mode_b, 2);
- tuner_i2c_xfer_send(&i2c_props, soft_reset, 2);
- tuner_i2c_xfer_send(&i2c_props, &addr_dto_lsb, 1);
- tuner_i2c_xfer_recv(&i2c_props, &data, 1);
- if (data == 0) {
- tuner_i2c_xfer_send(&i2c_props, easy_mode_g, 2);
- tuner_i2c_xfer_send(&i2c_props, soft_reset, 2);
- tuner_i2c_xfer_send(&i2c_props, &addr_dto_lsb, 1);
- tuner_i2c_xfer_recv(&i2c_props, &data, 1);
- if (data == 0x7b) {
- return 0;
- }
- }
- tuner_i2c_xfer_send(&i2c_props, restore_9886, 3);
- return -ENODEV;
-}
-EXPORT_SYMBOL_GPL(tda829x_probe);
-
-MODULE_DESCRIPTION("Philips/NXP TDA8290/TDA8295 analog IF demodulator driver");
-MODULE_AUTHOR("Gerd Knorr, Hartmut Hackmann, Michael Krufky");
-MODULE_LICENSE("GPL");
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/linux/drivers/media/video/tda8290.h b/linux/drivers/media/video/tda8290.h
deleted file mode 100644
index d3bbf276a..000000000
--- a/linux/drivers/media/video/tda8290.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- 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.
-*/
-
-#ifndef __TDA8290_H__
-#define __TDA8290_H__
-
-#include <linux/i2c.h>
-#include "dvb_frontend.h"
-
-struct tda829x_config {
- unsigned int lna_cfg;
- int (*tuner_callback) (void *dev, int command, int arg);
-
- unsigned int probe_tuner:1;
-#define TDA829X_PROBE_TUNER 0
-#define TDA829X_DONT_PROBE 1
-};
-
-#if defined(CONFIG_TUNER_TDA8290) || (defined(CONFIG_TUNER_TDA8290_MODULE) && defined(MODULE))
-extern int tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr);
-
-extern struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
- struct i2c_adapter *i2c_adap,
- u8 i2c_addr,
- struct tda829x_config *cfg);
-#else
-static inline int tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -EINVAL;
-}
-
-static inline struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
- struct i2c_adapter *i2c_adap,
- u8 i2c_addr,
- struct tda829x_config *cfg)
-{
- printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
- __func__);
- return NULL;
-}
-#endif
-
-#endif /* __TDA8290_H__ */
diff --git a/linux/drivers/media/video/tda9887.c b/linux/drivers/media/video/tda9887.c
deleted file mode 100644
index e98de7d40..000000000
--- a/linux/drivers/media/video/tda9887.c
+++ /dev/null
@@ -1,728 +0,0 @@
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/i2c.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include "compat.h"
-#include <linux/videodev.h>
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-#include "i2c-compat.h"
-#endif
-#include <media/v4l2-common.h>
-#include <media/tuner.h>
-#include "tuner-i2c.h"
-#include "tda9887.h"
-
-
-/* Chips:
- TDA9885 (PAL, NTSC)
- TDA9886 (PAL, SECAM, NTSC)
- TDA9887 (PAL, SECAM, NTSC, FM Radio)
-
- Used as part of several tuners
-*/
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "enable verbose debug messages");
-
-static DEFINE_MUTEX(tda9887_list_mutex);
-static LIST_HEAD(hybrid_tuner_instance_list);
-
-struct tda9887_priv {
- struct tuner_i2c_props i2c_props;
- struct list_head hybrid_tuner_instance_list;
-
- unsigned char data[4];
- unsigned int config;
- unsigned int mode;
- unsigned int audmode;
- v4l2_std_id std;
-};
-
-/* ---------------------------------------------------------------------- */
-
-#define UNSET (-1U)
-
-struct tvnorm {
- v4l2_std_id std;
- char *name;
- unsigned char b;
- unsigned char c;
- unsigned char e;
-};
-
-/* ---------------------------------------------------------------------- */
-
-//
-// TDA defines
-//
-
-//// first reg (b)
-#define cVideoTrapBypassOFF 0x00 // bit b0
-#define cVideoTrapBypassON 0x01 // bit b0
-
-#define cAutoMuteFmInactive 0x00 // bit b1
-#define cAutoMuteFmActive 0x02 // bit b1
-
-#define cIntercarrier 0x00 // bit b2
-#define cQSS 0x04 // bit b2
-
-#define cPositiveAmTV 0x00 // bit b3:4
-#define cFmRadio 0x08 // bit b3:4
-#define cNegativeFmTV 0x10 // bit b3:4
-
-
-#define cForcedMuteAudioON 0x20 // bit b5
-#define cForcedMuteAudioOFF 0x00 // bit b5
-
-#define cOutputPort1Active 0x00 // bit b6
-#define cOutputPort1Inactive 0x40 // bit b6
-
-#define cOutputPort2Active 0x00 // bit b7
-#define cOutputPort2Inactive 0x80 // bit b7
-
-
-//// second reg (c)
-#define cDeemphasisOFF 0x00 // bit c5
-#define cDeemphasisON 0x20 // bit c5
-
-#define cDeemphasis75 0x00 // bit c6
-#define cDeemphasis50 0x40 // bit c6
-
-#define cAudioGain0 0x00 // bit c7
-#define cAudioGain6 0x80 // bit c7
-
-#define cTopMask 0x1f // bit c0:4
-#define cTopDefault 0x10 // bit c0:4
-
-//// third reg (e)
-#define cAudioIF_4_5 0x00 // bit e0:1
-#define cAudioIF_5_5 0x01 // bit e0:1
-#define cAudioIF_6_0 0x02 // bit e0:1
-#define cAudioIF_6_5 0x03 // bit e0:1
-
-
-#define cVideoIFMask 0x1c // bit e2:4
-/* Video IF selection in TV Mode (bit B3=0) */
-#define cVideoIF_58_75 0x00 // bit e2:4
-#define cVideoIF_45_75 0x04 // bit e2:4
-#define cVideoIF_38_90 0x08 // bit e2:4
-#define cVideoIF_38_00 0x0C // bit e2:4
-#define cVideoIF_33_90 0x10 // bit e2:4
-#define cVideoIF_33_40 0x14 // bit e2:4
-#define cRadioIF_45_75 0x18 // bit e2:4
-#define cRadioIF_38_90 0x1C // bit e2:4
-
-/* IF1 selection in Radio Mode (bit B3=1) */
-#define cRadioIF_33_30 0x00 // bit e2,4 (also 0x10,0x14)
-#define cRadioIF_41_30 0x04 // bit e2,4
-
-/* Output of AFC pin in radio mode when bit E7=1 */
-#define cRadioAGC_SIF 0x00 // bit e3
-#define cRadioAGC_FM 0x08 // bit e3
-
-#define cTunerGainNormal 0x00 // bit e5
-#define cTunerGainLow 0x20 // bit e5
-
-#define cGating_18 0x00 // bit e6
-#define cGating_36 0x40 // bit e6
-
-#define cAgcOutON 0x80 // bit e7
-#define cAgcOutOFF 0x00 // bit e7
-
-/* ---------------------------------------------------------------------- */
-
-static struct tvnorm tvnorms[] = {
- {
- .std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H | V4L2_STD_PAL_N,
- .name = "PAL-BGHN",
- .b = ( cNegativeFmTV |
- cQSS ),
- .c = ( cDeemphasisON |
- cDeemphasis50 |
- cTopDefault),
- .e = ( cGating_36 |
- cAudioIF_5_5 |
- cVideoIF_38_90 ),
- },{
- .std = V4L2_STD_PAL_I,
- .name = "PAL-I",
- .b = ( cNegativeFmTV |
- cQSS ),
- .c = ( cDeemphasisON |
- cDeemphasis50 |
- cTopDefault),
- .e = ( cGating_36 |
- cAudioIF_6_0 |
- cVideoIF_38_90 ),
- },{
- .std = V4L2_STD_PAL_DK,
- .name = "PAL-DK",
- .b = ( cNegativeFmTV |
- cQSS ),
- .c = ( cDeemphasisON |
- cDeemphasis50 |
- cTopDefault),
- .e = ( cGating_36 |
- cAudioIF_6_5 |
- cVideoIF_38_90 ),
- },{
- .std = V4L2_STD_PAL_M | V4L2_STD_PAL_Nc,
- .name = "PAL-M/Nc",
- .b = ( cNegativeFmTV |
- cQSS ),
- .c = ( cDeemphasisON |
- cDeemphasis75 |
- cTopDefault),
- .e = ( cGating_36 |
- cAudioIF_4_5 |
- cVideoIF_45_75 ),
- },{
- .std = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H,
- .name = "SECAM-BGH",
- .b = ( cPositiveAmTV |
- cQSS ),
- .c = ( cTopDefault),
- .e = ( cGating_36 |
- cAudioIF_5_5 |
- cVideoIF_38_90 ),
- },{
- .std = V4L2_STD_SECAM_L,
- .name = "SECAM-L",
- .b = ( cPositiveAmTV |
- cQSS ),
- .c = ( cTopDefault),
- .e = ( cGating_36 |
- cAudioIF_6_5 |
- cVideoIF_38_90 ),
- },{
- .std = V4L2_STD_SECAM_LC,
- .name = "SECAM-L'",
- .b = ( cOutputPort2Inactive |
- cPositiveAmTV |
- cQSS ),
- .c = ( cTopDefault),
- .e = ( cGating_36 |
- cAudioIF_6_5 |
- cVideoIF_33_90 ),
- },{
- .std = V4L2_STD_SECAM_DK,
- .name = "SECAM-DK",
- .b = ( cNegativeFmTV |
- cQSS ),
- .c = ( cDeemphasisON |
- cDeemphasis50 |
- cTopDefault),
- .e = ( cGating_36 |
- cAudioIF_6_5 |
- cVideoIF_38_90 ),
- },{
- .std = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR,
- .name = "NTSC-M",
- .b = ( cNegativeFmTV |
- cQSS ),
- .c = ( cDeemphasisON |
- cDeemphasis75 |
- cTopDefault),
- .e = ( cGating_36 |
- cAudioIF_4_5 |
- cVideoIF_45_75 ),
- },{
- .std = V4L2_STD_NTSC_M_JP,
- .name = "NTSC-M-JP",
- .b = ( cNegativeFmTV |
- cQSS ),
- .c = ( cDeemphasisON |
- cDeemphasis50 |
- cTopDefault),
- .e = ( cGating_36 |
- cAudioIF_4_5 |
- cVideoIF_58_75 ),
- }
-};
-
-static struct tvnorm radio_stereo = {
- .name = "Radio Stereo",
- .b = ( cFmRadio |
- cQSS ),
- .c = ( cDeemphasisOFF |
- cAudioGain6 |
- cTopDefault),
- .e = ( cTunerGainLow |
- cAudioIF_5_5 |
- cRadioIF_38_90 ),
-};
-
-static struct tvnorm radio_mono = {
- .name = "Radio Mono",
- .b = ( cFmRadio |
- cQSS ),
- .c = ( cDeemphasisON |
- cDeemphasis75 |
- cTopDefault),
- .e = ( cTunerGainLow |
- cAudioIF_5_5 |
- cRadioIF_38_90 ),
-};
-
-/* ---------------------------------------------------------------------- */
-
-static void dump_read_message(struct dvb_frontend *fe, unsigned char *buf)
-{
- struct tda9887_priv *priv = fe->analog_demod_priv;
-
- static char *afc[16] = {
- "- 12.5 kHz",
- "- 37.5 kHz",
- "- 62.5 kHz",
- "- 87.5 kHz",
- "-112.5 kHz",
- "-137.5 kHz",
- "-162.5 kHz",
- "-187.5 kHz [min]",
- "+187.5 kHz [max]",
- "+162.5 kHz",
- "+137.5 kHz",
- "+112.5 kHz",
- "+ 87.5 kHz",
- "+ 62.5 kHz",
- "+ 37.5 kHz",
- "+ 12.5 kHz",
- };
- tuner_info("read: 0x%2x\n", buf[0]);
- tuner_info(" after power on : %s\n", (buf[0] & 0x01) ? "yes" : "no");
- tuner_info(" afc : %s\n", afc[(buf[0] >> 1) & 0x0f]);
- tuner_info(" fmif level : %s\n", (buf[0] & 0x20) ? "high" : "low");
- tuner_info(" afc window : %s\n", (buf[0] & 0x40) ? "in" : "out");
- tuner_info(" vfi level : %s\n", (buf[0] & 0x80) ? "high" : "low");
-}
-
-static void dump_write_message(struct dvb_frontend *fe, unsigned char *buf)
-{
- struct tda9887_priv *priv = fe->analog_demod_priv;
-
- static char *sound[4] = {
- "AM/TV",
- "FM/radio",
- "FM/TV",
- "FM/radio"
- };
- static char *adjust[32] = {
- "-16", "-15", "-14", "-13", "-12", "-11", "-10", "-9",
- "-8", "-7", "-6", "-5", "-4", "-3", "-2", "-1",
- "0", "+1", "+2", "+3", "+4", "+5", "+6", "+7",
- "+8", "+9", "+10", "+11", "+12", "+13", "+14", "+15"
- };
- static char *deemph[4] = {
- "no", "no", "75", "50"
- };
- static char *carrier[4] = {
- "4.5 MHz",
- "5.5 MHz",
- "6.0 MHz",
- "6.5 MHz / AM"
- };
- static char *vif[8] = {
- "58.75 MHz",
- "45.75 MHz",
- "38.9 MHz",
- "38.0 MHz",
- "33.9 MHz",
- "33.4 MHz",
- "45.75 MHz + pin13",
- "38.9 MHz + pin13",
- };
- static char *rif[4] = {
- "44 MHz",
- "52 MHz",
- "52 MHz",
- "44 MHz",
- };
-
- tuner_info("write: byte B 0x%02x\n", buf[1]);
- tuner_info(" B0 video mode : %s\n",
- (buf[1] & 0x01) ? "video trap" : "sound trap");
- tuner_info(" B1 auto mute fm : %s\n",
- (buf[1] & 0x02) ? "yes" : "no");
- tuner_info(" B2 carrier mode : %s\n",
- (buf[1] & 0x04) ? "QSS" : "Intercarrier");
- tuner_info(" B3-4 tv sound/radio : %s\n",
- sound[(buf[1] & 0x18) >> 3]);
- tuner_info(" B5 force mute audio: %s\n",
- (buf[1] & 0x20) ? "yes" : "no");
- tuner_info(" B6 output port 1 : %s\n",
- (buf[1] & 0x40) ? "high (inactive)" : "low (active)");
- tuner_info(" B7 output port 2 : %s\n",
- (buf[1] & 0x80) ? "high (inactive)" : "low (active)");
-
- tuner_info("write: byte C 0x%02x\n", buf[2]);
- tuner_info(" C0-4 top adjustment : %s dB\n",
- adjust[buf[2] & 0x1f]);
- tuner_info(" C5-6 de-emphasis : %s\n",
- deemph[(buf[2] & 0x60) >> 5]);
- tuner_info(" C7 audio gain : %s\n",
- (buf[2] & 0x80) ? "-6" : "0");
-
- tuner_info("write: byte E 0x%02x\n", buf[3]);
- tuner_info(" E0-1 sound carrier : %s\n",
- carrier[(buf[3] & 0x03)]);
- tuner_info(" E6 l pll gating : %s\n",
- (buf[3] & 0x40) ? "36" : "13");
-
- if (buf[1] & 0x08) {
- /* radio */
- tuner_info(" E2-4 video if : %s\n",
- rif[(buf[3] & 0x0c) >> 2]);
- tuner_info(" E7 vif agc output : %s\n",
- (buf[3] & 0x80)
- ? ((buf[3] & 0x10) ? "fm-agc radio" :
- "sif-agc radio")
- : "fm radio carrier afc");
- } else {
- /* video */
- tuner_info(" E2-4 video if : %s\n",
- vif[(buf[3] & 0x1c) >> 2]);
- tuner_info(" E5 tuner gain : %s\n",
- (buf[3] & 0x80)
- ? ((buf[3] & 0x20) ? "external" : "normal")
- : ((buf[3] & 0x20) ? "minimum" : "normal"));
- tuner_info(" E7 vif agc output : %s\n",
- (buf[3] & 0x80) ? ((buf[3] & 0x20)
- ? "pin3 port, pin22 vif agc out"
- : "pin22 port, pin3 vif acg ext in")
- : "pin3+pin22 port");
- }
- tuner_info("--\n");
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int tda9887_set_tvnorm(struct dvb_frontend *fe)
-{
- struct tda9887_priv *priv = fe->analog_demod_priv;
- struct tvnorm *norm = NULL;
- char *buf = priv->data;
- int i;
-
- if (priv->mode == V4L2_TUNER_RADIO) {
- if (priv->audmode == V4L2_TUNER_MODE_MONO)
- norm = &radio_mono;
- else
- norm = &radio_stereo;
- } else {
- for (i = 0; i < ARRAY_SIZE(tvnorms); i++) {
- if (tvnorms[i].std & priv->std) {
- norm = tvnorms+i;
- break;
- }
- }
- }
- if (NULL == norm) {
- tuner_dbg("Unsupported tvnorm entry - audio muted\n");
- return -1;
- }
-
- tuner_dbg("configure for: %s\n", norm->name);
- buf[1] = norm->b;
- buf[2] = norm->c;
- buf[3] = norm->e;
- return 0;
-}
-
-static unsigned int port1 = UNSET;
-static unsigned int port2 = UNSET;
-static unsigned int qss = UNSET;
-static unsigned int adjust = UNSET;
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-MODULE_PARM(port1, "i");
-MODULE_PARM(port2, "i");
-MODULE_PARM(qss, "i");
-MODULE_PARM(adjust, "i");
-#else
-module_param(port1, int, 0644);
-module_param(port2, int, 0644);
-module_param(qss, int, 0644);
-module_param(adjust, int, 0644);
-#endif
-
-static int tda9887_set_insmod(struct dvb_frontend *fe)
-{
- struct tda9887_priv *priv = fe->analog_demod_priv;
- char *buf = priv->data;
-
- if (UNSET != port1) {
- if (port1)
- buf[1] |= cOutputPort1Inactive;
- else
- buf[1] &= ~cOutputPort1Inactive;
- }
- if (UNSET != port2) {
- if (port2)
- buf[1] |= cOutputPort2Inactive;
- else
- buf[1] &= ~cOutputPort2Inactive;
- }
-
- if (UNSET != qss) {
- if (qss)
- buf[1] |= cQSS;
- else
- buf[1] &= ~cQSS;
- }
-
- if (adjust >= 0x00 && adjust < 0x20) {
- buf[2] &= ~cTopMask;
- buf[2] |= adjust;
- }
- return 0;
-}
-
-static int tda9887_do_config(struct dvb_frontend *fe)
-{
- struct tda9887_priv *priv = fe->analog_demod_priv;
- char *buf = priv->data;
-
- if (priv->config & TDA9887_PORT1_ACTIVE)
- buf[1] &= ~cOutputPort1Inactive;
- if (priv->config & TDA9887_PORT1_INACTIVE)
- buf[1] |= cOutputPort1Inactive;
- if (priv->config & TDA9887_PORT2_ACTIVE)
- buf[1] &= ~cOutputPort2Inactive;
- if (priv->config & TDA9887_PORT2_INACTIVE)
- buf[1] |= cOutputPort2Inactive;
-
- if (priv->config & TDA9887_QSS)
- buf[1] |= cQSS;
- if (priv->config & TDA9887_INTERCARRIER)
- buf[1] &= ~cQSS;
-
- if (priv->config & TDA9887_AUTOMUTE)
- buf[1] |= cAutoMuteFmActive;
- if (priv->config & TDA9887_DEEMPHASIS_MASK) {
- buf[2] &= ~0x60;
- switch (priv->config & TDA9887_DEEMPHASIS_MASK) {
- case TDA9887_DEEMPHASIS_NONE:
- buf[2] |= cDeemphasisOFF;
- break;
- case TDA9887_DEEMPHASIS_50:
- buf[2] |= cDeemphasisON | cDeemphasis50;
- break;
- case TDA9887_DEEMPHASIS_75:
- buf[2] |= cDeemphasisON | cDeemphasis75;
- break;
- }
- }
- if (priv->config & TDA9887_TOP_SET) {
- buf[2] &= ~cTopMask;
- buf[2] |= (priv->config >> 8) & cTopMask;
- }
- if ((priv->config & TDA9887_INTERCARRIER_NTSC) &&
- (priv->std & V4L2_STD_NTSC))
- buf[1] &= ~cQSS;
- if (priv->config & TDA9887_GATING_18)
- buf[3] &= ~cGating_36;
-
- if (priv->mode == V4L2_TUNER_RADIO) {
- if (priv->config & TDA9887_RIF_41_3) {
- buf[3] &= ~cVideoIFMask;
- buf[3] |= cRadioIF_41_30;
- }
- if (priv->config & TDA9887_GAIN_NORMAL)
- buf[3] &= ~cTunerGainLow;
- }
-
- return 0;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int tda9887_status(struct dvb_frontend *fe)
-{
- struct tda9887_priv *priv = fe->analog_demod_priv;
- unsigned char buf[1];
- int rc;
-
- memset(buf,0,sizeof(buf));
- if (1 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props,buf,1)))
- tuner_info("i2c i/o error: rc == %d (should be 1)\n", rc);
- dump_read_message(fe, buf);
- return 0;
-}
-
-static void tda9887_configure(struct dvb_frontend *fe)
-{
- struct tda9887_priv *priv = fe->analog_demod_priv;
- int rc;
-
- memset(priv->data,0,sizeof(priv->data));
- tda9887_set_tvnorm(fe);
-
- /* A note on the port settings:
- These settings tend to depend on the specifics of the board.
- By default they are set to inactive (bit value 1) by this driver,
- overwriting any changes made by the tvnorm. This means that it
- is the responsibility of the module using the tda9887 to set
- these values in case of changes in the tvnorm.
- In many cases port 2 should be made active (0) when selecting
- SECAM-L, and port 2 should remain inactive (1) for SECAM-L'.
-
- For the other standards the tda9887 application note says that
- the ports should be set to active (0), but, again, that may
- differ depending on the precise hardware configuration.
- */
- priv->data[1] |= cOutputPort1Inactive;
- priv->data[1] |= cOutputPort2Inactive;
-
- tda9887_do_config(fe);
- tda9887_set_insmod(fe);
-
- if (priv->mode == T_STANDBY)
- priv->data[1] |= cForcedMuteAudioON;
-
- tuner_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n",
- priv->data[1], priv->data[2], priv->data[3]);
- if (debug > 1)
- dump_write_message(fe, priv->data);
-
- if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,priv->data,4)))
- tuner_info("i2c i/o error: rc == %d (should be 4)\n", rc);
-
- if (debug > 2) {
- msleep_interruptible(1000);
- tda9887_status(fe);
- }
-}
-
-/* ---------------------------------------------------------------------- */
-
-static void tda9887_tuner_status(struct dvb_frontend *fe)
-{
- struct tda9887_priv *priv = fe->analog_demod_priv;
- tuner_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n",
- priv->data[1], priv->data[2], priv->data[3]);
-}
-
-static int tda9887_get_afc(struct dvb_frontend *fe)
-{
- struct tda9887_priv *priv = fe->analog_demod_priv;
- static int AFC_BITS_2_kHz[] = {
- -12500, -37500, -62500, -97500,
- -112500, -137500, -162500, -187500,
- 187500, 162500, 137500, 112500,
- 97500 , 62500, 37500 , 12500
- };
- int afc=0;
- __u8 reg = 0;
-
- if (1 == tuner_i2c_xfer_recv(&priv->i2c_props,&reg,1))
- afc = AFC_BITS_2_kHz[(reg>>1)&0x0f];
-
- return afc;
-}
-
-static void tda9887_standby(struct dvb_frontend *fe)
-{
- struct tda9887_priv *priv = fe->analog_demod_priv;
-
- priv->mode = T_STANDBY;
-
- tda9887_configure(fe);
-}
-
-static void tda9887_set_params(struct dvb_frontend *fe,
- struct analog_parameters *params)
-{
- struct tda9887_priv *priv = fe->analog_demod_priv;
-
- priv->mode = params->mode;
- priv->audmode = params->audmode;
- priv->std = params->std;
- tda9887_configure(fe);
-}
-
-static int tda9887_set_config(struct dvb_frontend *fe, void *priv_cfg)
-{
- struct tda9887_priv *priv = fe->analog_demod_priv;
-
- priv->config = *(unsigned int *)priv_cfg;
- tda9887_configure(fe);
-
- return 0;
-}
-
-static void tda9887_release(struct dvb_frontend *fe)
-{
- struct tda9887_priv *priv = fe->analog_demod_priv;
-
- mutex_lock(&tda9887_list_mutex);
-
- if (priv)
- hybrid_tuner_release_state(priv);
-
- mutex_unlock(&tda9887_list_mutex);
-
- fe->analog_demod_priv = NULL;
-}
-
-static struct analog_demod_ops tda9887_ops = {
- .info = {
- .name = "tda9887",
- },
- .set_params = tda9887_set_params,
- .standby = tda9887_standby,
- .tuner_status = tda9887_tuner_status,
- .get_afc = tda9887_get_afc,
- .release = tda9887_release,
- .set_config = tda9887_set_config,
-};
-
-struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe,
- struct i2c_adapter *i2c_adap,
- u8 i2c_addr)
-{
- struct tda9887_priv *priv = NULL;
- int instance;
-
- mutex_lock(&tda9887_list_mutex);
-
- instance = hybrid_tuner_request_state(struct tda9887_priv, priv,
- hybrid_tuner_instance_list,
- i2c_adap, i2c_addr, "tda9887");
- switch (instance) {
- case 0:
- mutex_unlock(&tda9887_list_mutex);
- return NULL;
- break;
- case 1:
- fe->analog_demod_priv = priv;
- priv->mode = T_STANDBY;
- tuner_info("tda988[5/6/7] found\n");
- break;
- default:
- fe->analog_demod_priv = priv;
- break;
- }
-
- mutex_unlock(&tda9887_list_mutex);
-
- memcpy(&fe->ops.analog_ops, &tda9887_ops,
- sizeof(struct analog_demod_ops));
-
- return fe;
-}
-EXPORT_SYMBOL_GPL(tda9887_attach);
-
-MODULE_LICENSE("GPL");
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/linux/drivers/media/video/tda9887.h b/linux/drivers/media/video/tda9887.h
deleted file mode 100644
index be49dcbfc..000000000
--- a/linux/drivers/media/video/tda9887.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- 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.
-*/
-
-#ifndef __TDA9887_H__
-#define __TDA9887_H__
-
-#include <linux/i2c.h>
-#include "dvb_frontend.h"
-
-/* ------------------------------------------------------------------------ */
-#if defined(CONFIG_TUNER_TDA9887) || (defined(CONFIG_TUNER_TDA9887_MODULE) && defined(MODULE))
-extern struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe,
- struct i2c_adapter *i2c_adap,
- u8 i2c_addr);
-#else
-static inline struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe,
- struct i2c_adapter *i2c_adap,
- u8 i2c_addr)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return NULL;
-}
-#endif
-
-#endif /* __TDA9887_H__ */
diff --git a/linux/drivers/media/video/tea5761.c b/linux/drivers/media/video/tea5761.c
deleted file mode 100644
index 11e2991ef..000000000
--- a/linux/drivers/media/video/tea5761.c
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
- * For Philips TEA5761 FM Chip
- * I2C address is allways 0x20 (0x10 at 7-bit mode).
- *
- * Copyright (c) 2005-2007 Mauro Carvalho Chehab (mchehab@infradead.org)
- * This code is placed under the terms of the GNUv2 General Public License
- *
- */
-
-#include <linux/i2c.h>
-#include <linux/delay.h>
-#include "compat.h"
-#include <linux/videodev.h>
-#include <media/tuner.h>
-#include "tuner-i2c.h"
-#include "tea5761.h"
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "enable verbose debug messages");
-
-struct tea5761_priv {
- struct tuner_i2c_props i2c_props;
-
- u32 frequency;
-};
-
-/*****************************************************************************/
-
-/***************************
- * TEA5761HN I2C registers *
- ***************************/
-
-/* INTREG - Read: bytes 0 and 1 / Write: byte 0 */
-
- /* first byte for reading */
-#define TEA5761_INTREG_IFFLAG 0x10
-#define TEA5761_INTREG_LEVFLAG 0x8
-#define TEA5761_INTREG_FRRFLAG 0x2
-#define TEA5761_INTREG_BLFLAG 0x1
-
- /* second byte for reading / byte for writing */
-#define TEA5761_INTREG_IFMSK 0x10
-#define TEA5761_INTREG_LEVMSK 0x8
-#define TEA5761_INTREG_FRMSK 0x2
-#define TEA5761_INTREG_BLMSK 0x1
-
-/* FRQSET - Read: bytes 2 and 3 / Write: byte 1 and 2 */
-
- /* First byte */
-#define TEA5761_FRQSET_SEARCH_UP 0x80 /* 1=Station search from botton to up */
-#define TEA5761_FRQSET_SEARCH_MODE 0x40 /* 1=Search mode */
-
- /* Bits 0-5 for divider MSB */
-
- /* Second byte */
- /* Bits 0-7 for divider LSB */
-
-/* TNCTRL - Read: bytes 4 and 5 / Write: Bytes 3 and 4 */
-
- /* first byte */
-
-#define TEA5761_TNCTRL_PUPD_0 0x40 /* Power UP/Power Down MSB */
-#define TEA5761_TNCTRL_BLIM 0X20 /* 1= Japan Frequencies, 0= European frequencies */
-#define TEA5761_TNCTRL_SWPM 0x10 /* 1= software port is FRRFLAG */
-#define TEA5761_TNCTRL_IFCTC 0x08 /* 1= IF count time 15.02 ms, 0= IF count time 2.02 ms */
-#define TEA5761_TNCTRL_AFM 0x04
-#define TEA5761_TNCTRL_SMUTE 0x02 /* 1= Soft mute */
-#define TEA5761_TNCTRL_SNC 0x01
-
- /* second byte */
-
-#define TEA5761_TNCTRL_MU 0x80 /* 1=Hard mute */
-#define TEA5761_TNCTRL_SSL_1 0x40
-#define TEA5761_TNCTRL_SSL_0 0x20
-#define TEA5761_TNCTRL_HLSI 0x10
-#define TEA5761_TNCTRL_MST 0x08 /* 1 = mono */
-#define TEA5761_TNCTRL_SWP 0x04
-#define TEA5761_TNCTRL_DTC 0x02 /* 1 = deemphasis 50 us, 0 = deemphasis 75 us */
-#define TEA5761_TNCTRL_AHLSI 0x01
-
-/* FRQCHECK - Read: bytes 6 and 7 */
- /* First byte */
-
- /* Bits 0-5 for divider MSB */
-
- /* Second byte */
- /* Bits 0-7 for divider LSB */
-
-/* TUNCHECK - Read: bytes 8 and 9 */
-
- /* First byte */
-#define TEA5761_TUNCHECK_IF_MASK 0x7e /* IF count */
-#define TEA5761_TUNCHECK_TUNTO 0x01
-
- /* Second byte */
-#define TEA5761_TUNCHECK_LEV_MASK 0xf0 /* Level Count */
-#define TEA5761_TUNCHECK_LD 0x08
-#define TEA5761_TUNCHECK_STEREO 0x04
-
-/* TESTREG - Read: bytes 10 and 11 / Write: bytes 5 and 6 */
-
- /* All zero = no test mode */
-
-/* MANID - Read: bytes 12 and 13 */
-
- /* First byte - should be 0x10 */
-#define TEA5767_MANID_VERSION_MASK 0xf0 /* Version = 1 */
-#define TEA5767_MANID_ID_MSB_MASK 0x0f /* Manufacurer ID - should be 0 */
-
- /* Second byte - Should be 0x2b */
-
-#define TEA5767_MANID_ID_LSB_MASK 0xfe /* Manufacturer ID - should be 0x15 */
-#define TEA5767_MANID_IDAV 0x01 /* 1 = Chip has ID, 0 = Chip has no ID */
-
-/* Chip ID - Read: bytes 14 and 15 */
-
- /* First byte - should be 0x57 */
-
- /* Second byte - should be 0x61 */
-
-/*****************************************************************************/
-
-#define FREQ_OFFSET 0 /* for TEA5767, it is 700 to give the right freq */
-static void tea5761_status_dump(unsigned char *buffer)
-{
- unsigned int div, frq;
-
- div = ((buffer[2] & 0x3f) << 8) | buffer[3];
-
- frq = 1000 * (div * 32768 / 1000 + FREQ_OFFSET + 225) / 4; /* Freq in KHz */
-
- printk(KERN_INFO "tea5761: Frequency %d.%03d KHz (divider = 0x%04x)\n",
- frq / 1000, frq % 1000, div);
-}
-
-/* Freq should be specifyed at 62.5 Hz */
-static int set_radio_freq(struct dvb_frontend *fe,
- struct analog_parameters *params)
-{
- struct tea5761_priv *priv = fe->tuner_priv;
- unsigned int frq = params->frequency;
- unsigned char buffer[7] = {0, 0, 0, 0, 0, 0, 0 };
- unsigned div;
- int rc;
-
- tuner_dbg("radio freq counter %d\n", frq);
-
- if (params->mode == T_STANDBY) {
- tuner_dbg("TEA5761 set to standby mode\n");
- buffer[5] |= TEA5761_TNCTRL_MU;
- } else {
- buffer[4] |= TEA5761_TNCTRL_PUPD_0;
- }
-
-
- if (params->audmode == V4L2_TUNER_MODE_MONO) {
- tuner_dbg("TEA5761 set to mono\n");
- buffer[5] |= TEA5761_TNCTRL_MST;
- } else {
- tuner_dbg("TEA5761 set to stereo\n");
- }
-
- div = (1000 * (frq * 4 / 16 + 700 + 225) ) >> 15;
- buffer[1] = (div >> 8) & 0x3f;
- buffer[2] = div & 0xff;
-
- if (debug)
- tea5761_status_dump(buffer);
-
- if (7 != (rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 7)))
- tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
-
- priv->frequency = frq * 125 / 2;
-
- return 0;
-}
-
-static int tea5761_read_status(struct dvb_frontend *fe, char *buffer)
-{
- struct tea5761_priv *priv = fe->tuner_priv;
- int rc;
-
- memset(buffer, 0, 16);
- if (16 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props, buffer, 16))) {
- tuner_warn("i2c i/o error: rc == %d (should be 16)\n", rc);
- return -EREMOTEIO;
- }
-
- return 0;
-}
-
-static inline int tea5761_signal(struct dvb_frontend *fe, const char *buffer)
-{
- struct tea5761_priv *priv = fe->tuner_priv;
-
- int signal = ((buffer[9] & TEA5761_TUNCHECK_LEV_MASK) << (13 - 4));
-
- tuner_dbg("Signal strength: %d\n", signal);
-
- return signal;
-}
-
-static inline int tea5761_stereo(struct dvb_frontend *fe, const char *buffer)
-{
- struct tea5761_priv *priv = fe->tuner_priv;
-
- int stereo = buffer[9] & TEA5761_TUNCHECK_STEREO;
-
- tuner_dbg("Radio ST GET = %02x\n", stereo);
-
- return (stereo ? V4L2_TUNER_SUB_STEREO : 0);
-}
-
-static int tea5761_get_status(struct dvb_frontend *fe, u32 *status)
-{
- unsigned char buffer[16];
-
- *status = 0;
-
- if (0 == tea5761_read_status(fe, buffer)) {
- if (tea5761_signal(fe, buffer))
- *status = TUNER_STATUS_LOCKED;
- if (tea5761_stereo(fe, buffer))
- *status |= TUNER_STATUS_STEREO;
- }
-
- return 0;
-}
-
-static int tea5761_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
-{
- unsigned char buffer[16];
-
- *strength = 0;
-
- if (0 == tea5761_read_status(fe, buffer))
- *strength = tea5761_signal(fe, buffer);
-
- return 0;
-}
-
-int tea5761_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr)
-{
- unsigned char buffer[16];
- int rc;
- struct tuner_i2c_props i2c = { .adap = i2c_adap, .addr = i2c_addr };
-
- if (16 != (rc = tuner_i2c_xfer_recv(&i2c, buffer, 16))) {
- printk(KERN_WARNING "it is not a TEA5761. Received %i chars.\n", rc);
- return -EINVAL;
- }
-
- if ((buffer[13] != 0x2b) || (buffer[14] != 0x57) || (buffer[15] != 0x061)) {
- printk(KERN_WARNING "Manufacturer ID= 0x%02x, Chip ID = %02x%02x."
- " It is not a TEA5761\n",
- buffer[13], buffer[14], buffer[15]);
- return -EINVAL;
- }
- printk(KERN_WARNING "tea5761: TEA%02x%02x detected. "
- "Manufacturer ID= 0x%02x\n",
- buffer[14], buffer[15], buffer[13]);
-
- return 0;
-}
-
-static int tea5761_release(struct dvb_frontend *fe)
-{
- kfree(fe->tuner_priv);
- fe->tuner_priv = NULL;
-
- return 0;
-}
-
-static int tea5761_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
- struct tea5761_priv *priv = fe->tuner_priv;
- *frequency = priv->frequency;
- return 0;
-}
-
-static struct dvb_tuner_ops tea5761_tuner_ops = {
- .info = {
- .name = "tea5761", // Philips TEA5761HN FM Radio
-#if 0
- .frequency_min = ,
- .frequency_max = ,
- .frequency_step = ,
-#endif
- },
- .set_analog_params = set_radio_freq,
- .release = tea5761_release,
- .get_frequency = tea5761_get_frequency,
- .get_status = tea5761_get_status,
- .get_rf_strength = tea5761_get_rf_strength,
-};
-
-struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe,
- struct i2c_adapter* i2c_adap,
- u8 i2c_addr)
-{
- struct tea5761_priv *priv = NULL;
-
- if (tea5761_autodetection(i2c_adap, i2c_addr) == EINVAL)
- return NULL;
-
- priv = kzalloc(sizeof(struct tea5761_priv), GFP_KERNEL);
- if (priv == NULL)
- return NULL;
- fe->tuner_priv = priv;
-
- priv->i2c_props.addr = i2c_addr;
- priv->i2c_props.adap = i2c_adap;
- priv->i2c_props.name = "tea5761";
-
- memcpy(&fe->ops.tuner_ops, &tea5761_tuner_ops,
- sizeof(struct dvb_tuner_ops));
-
- tuner_info("type set to %s\n", "Philips TEA5761HN FM Radio");
-
- return fe;
-}
-
-
-EXPORT_SYMBOL_GPL(tea5761_attach);
-EXPORT_SYMBOL_GPL(tea5761_autodetection);
-
-MODULE_DESCRIPTION("Philips TEA5761 FM tuner driver");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
-MODULE_LICENSE("GPL");
diff --git a/linux/drivers/media/video/tea5761.h b/linux/drivers/media/video/tea5761.h
deleted file mode 100644
index 8eb62722b..000000000
--- a/linux/drivers/media/video/tea5761.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- 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.
-*/
-
-#ifndef __TEA5761_H__
-#define __TEA5761_H__
-
-#include <linux/i2c.h>
-#include "dvb_frontend.h"
-
-#if defined(CONFIG_TUNER_TEA5761) || (defined(CONFIG_TUNER_TEA5761_MODULE) && defined(MODULE))
-extern int tea5761_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr);
-
-extern struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe,
- struct i2c_adapter* i2c_adap,
- u8 i2c_addr);
-#else
-static inline int tea5761_autodetection(struct i2c_adapter* i2c_adap,
- u8 i2c_addr)
-{
- printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
- __func__);
- return -EINVAL;
-}
-
-static inline struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe,
- struct i2c_adapter* i2c_adap,
- u8 i2c_addr)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return NULL;
-}
-#endif
-
-#endif /* __TEA5761_H__ */
diff --git a/linux/drivers/media/video/tea5767.c b/linux/drivers/media/video/tea5767.c
deleted file mode 100644
index e5bfc72a4..000000000
--- a/linux/drivers/media/video/tea5767.c
+++ /dev/null
@@ -1,525 +0,0 @@
-/*
- * For Philips TEA5767 FM Chip used on some TV Cards like Prolink Pixelview
- * I2C address is allways 0xC0.
- *
- *
- * Copyright (c) 2005 Mauro Carvalho Chehab (mchehab@infradead.org)
- * This code is placed under the terms of the GNU General Public License
- *
- * tea5767 autodetection thanks to Torsten Seeboth and Atsushi Nakagawa
- * from their contributions on DScaler.
- */
-
-#include <linux/i2c.h>
-#include <linux/delay.h>
-#include "compat.h"
-#include <linux/videodev.h>
-#include "tuner-i2c.h"
-#include "tea5767.h"
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-#include "i2c-compat.h"
-#endif
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "enable verbose debug messages");
-
-/*****************************************************************************/
-
-struct tea5767_priv {
- struct tuner_i2c_props i2c_props;
- u32 frequency;
- struct tea5767_ctrl ctrl;
-};
-
-/*****************************************************************************/
-
-/******************************
- * Write mode register values *
- ******************************/
-
-/* First register */
-#define TEA5767_MUTE 0x80 /* Mutes output */
-#define TEA5767_SEARCH 0x40 /* Activates station search */
-/* Bits 0-5 for divider MSB */
-
-/* Second register */
-/* Bits 0-7 for divider LSB */
-
-/* Third register */
-
-/* Station search from botton to up */
-#define TEA5767_SEARCH_UP 0x80
-
-/* Searches with ADC output = 10 */
-#define TEA5767_SRCH_HIGH_LVL 0x60
-
-/* Searches with ADC output = 10 */
-#define TEA5767_SRCH_MID_LVL 0x40
-
-/* Searches with ADC output = 5 */
-#define TEA5767_SRCH_LOW_LVL 0x20
-
-/* if on, div=4*(Frf+Fif)/Fref otherwise, div=4*(Frf-Fif)/Freq) */
-#define TEA5767_HIGH_LO_INJECT 0x10
-
-/* Disable stereo */
-#define TEA5767_MONO 0x08
-
-/* Disable right channel and turns to mono */
-#define TEA5767_MUTE_RIGHT 0x04
-
-/* Disable left channel and turns to mono */
-#define TEA5767_MUTE_LEFT 0x02
-
-#define TEA5767_PORT1_HIGH 0x01
-
-/* Fourth register */
-#define TEA5767_PORT2_HIGH 0x80
-/* Chips stops working. Only I2C bus remains on */
-#define TEA5767_STDBY 0x40
-
-/* Japan freq (76-108 MHz. If disabled, 87.5-108 MHz */
-#define TEA5767_JAPAN_BAND 0x20
-
-/* Unselected means 32.768 KHz freq as reference. Otherwise Xtal at 13 MHz */
-#define TEA5767_XTAL_32768 0x10
-
-/* Cuts weak signals */
-#define TEA5767_SOFT_MUTE 0x08
-
-/* Activates high cut control */
-#define TEA5767_HIGH_CUT_CTRL 0x04
-
-/* Activates stereo noise control */
-#define TEA5767_ST_NOISE_CTL 0x02
-
-/* If activate PORT 1 indicates SEARCH or else it is used as PORT1 */
-#define TEA5767_SRCH_IND 0x01
-
-/* Fifth register */
-
-/* By activating, it will use Xtal at 13 MHz as reference for divider */
-#define TEA5767_PLLREF_ENABLE 0x80
-
-/* By activating, deemphasis=50, or else, deemphasis of 50us */
-#define TEA5767_DEEMPH_75 0X40
-
-/*****************************
- * Read mode register values *
- *****************************/
-
-/* First register */
-#define TEA5767_READY_FLAG_MASK 0x80
-#define TEA5767_BAND_LIMIT_MASK 0X40
-/* Bits 0-5 for divider MSB after search or preset */
-
-/* Second register */
-/* Bits 0-7 for divider LSB after search or preset */
-
-/* Third register */
-#define TEA5767_STEREO_MASK 0x80
-#define TEA5767_IF_CNTR_MASK 0x7f
-
-/* Fourth register */
-#define TEA5767_ADC_LEVEL_MASK 0xf0
-
-/* should be 0 */
-#define TEA5767_CHIP_ID_MASK 0x0f
-
-/* Fifth register */
-/* Reserved for future extensions */
-#define TEA5767_RESERVED_MASK 0xff
-
-/*****************************************************************************/
-
-static void tea5767_status_dump(struct tea5767_priv *priv,
- unsigned char *buffer)
-{
- unsigned int div, frq;
-
- if (TEA5767_READY_FLAG_MASK & buffer[0])
- tuner_info("Ready Flag ON\n");
- else
- tuner_info("Ready Flag OFF\n");
-
- if (TEA5767_BAND_LIMIT_MASK & buffer[0])
- tuner_info("Tuner at band limit\n");
- else
- tuner_info("Tuner not at band limit\n");
-
- div = ((buffer[0] & 0x3f) << 8) | buffer[1];
-
- switch (priv->ctrl.xtal_freq) {
- case TEA5767_HIGH_LO_13MHz:
- frq = (div * 50000 - 700000 - 225000) / 4; /* Freq in KHz */
- break;
- case TEA5767_LOW_LO_13MHz:
- frq = (div * 50000 + 700000 + 225000) / 4; /* Freq in KHz */
- break;
- case TEA5767_LOW_LO_32768:
- frq = (div * 32768 + 700000 + 225000) / 4; /* Freq in KHz */
- break;
- case TEA5767_HIGH_LO_32768:
- default:
- frq = (div * 32768 - 700000 - 225000) / 4; /* Freq in KHz */
- break;
- }
- buffer[0] = (div >> 8) & 0x3f;
- buffer[1] = div & 0xff;
-
- tuner_info("Frequency %d.%03d KHz (divider = 0x%04x)\n",
- frq / 1000, frq % 1000, div);
-
- if (TEA5767_STEREO_MASK & buffer[2])
- tuner_info("Stereo\n");
- else
- tuner_info("Mono\n");
-
- tuner_info("IF Counter = %d\n", buffer[2] & TEA5767_IF_CNTR_MASK);
-
- tuner_info("ADC Level = %d\n",
- (buffer[3] & TEA5767_ADC_LEVEL_MASK) >> 4);
-
- tuner_info("Chip ID = %d\n", (buffer[3] & TEA5767_CHIP_ID_MASK));
-
- tuner_info("Reserved = 0x%02x\n",
- (buffer[4] & TEA5767_RESERVED_MASK));
-}
-
-/* Freq should be specifyed at 62.5 Hz */
-static int set_radio_freq(struct dvb_frontend *fe,
- struct analog_parameters *params)
-{
- struct tea5767_priv *priv = fe->tuner_priv;
- unsigned int frq = params->frequency;
- unsigned char buffer[5];
- unsigned div;
- int rc;
-
- tuner_dbg("radio freq = %d.%03d MHz\n", frq/16000,(frq/16)%1000);
-
- buffer[2] = 0;
-
- if (priv->ctrl.port1)
- buffer[2] |= TEA5767_PORT1_HIGH;
-
- if (params->audmode == V4L2_TUNER_MODE_MONO) {
- tuner_dbg("TEA5767 set to mono\n");
- buffer[2] |= TEA5767_MONO;
- } else {
- tuner_dbg("TEA5767 set to stereo\n");
- }
-
-
- buffer[3] = 0;
-
- if (priv->ctrl.port2)
- buffer[3] |= TEA5767_PORT2_HIGH;
-
- if (priv->ctrl.high_cut)
- buffer[3] |= TEA5767_HIGH_CUT_CTRL;
-
- if (priv->ctrl.st_noise)
- buffer[3] |= TEA5767_ST_NOISE_CTL;
-
- if (priv->ctrl.soft_mute)
- buffer[3] |= TEA5767_SOFT_MUTE;
-
- if (priv->ctrl.japan_band)
- buffer[3] |= TEA5767_JAPAN_BAND;
-
- buffer[4] = 0;
-
- if (priv->ctrl.deemph_75)
- buffer[4] |= TEA5767_DEEMPH_75;
-
- if (priv->ctrl.pllref)
- buffer[4] |= TEA5767_PLLREF_ENABLE;
-
-
- /* Rounds freq to next decimal value - for 62.5 KHz step */
- /* frq = 20*(frq/16)+radio_frq[frq%16]; */
-
- switch (priv->ctrl.xtal_freq) {
- case TEA5767_HIGH_LO_13MHz:
- tuner_dbg("radio HIGH LO inject xtal @ 13 MHz\n");
- buffer[2] |= TEA5767_HIGH_LO_INJECT;
- div = (frq * (4000 / 16) + 700000 + 225000 + 25000) / 50000;
- break;
- case TEA5767_LOW_LO_13MHz:
- tuner_dbg("radio LOW LO inject xtal @ 13 MHz\n");
-
- div = (frq * (4000 / 16) - 700000 - 225000 + 25000) / 50000;
- break;
- case TEA5767_LOW_LO_32768:
- tuner_dbg("radio LOW LO inject xtal @ 32,768 MHz\n");
- buffer[3] |= TEA5767_XTAL_32768;
- /* const 700=4000*175 Khz - to adjust freq to right value */
- div = ((frq * (4000 / 16) - 700000 - 225000) + 16384) >> 15;
- break;
- case TEA5767_HIGH_LO_32768:
- default:
- tuner_dbg("radio HIGH LO inject xtal @ 32,768 MHz\n");
-
- buffer[2] |= TEA5767_HIGH_LO_INJECT;
- buffer[3] |= TEA5767_XTAL_32768;
- div = ((frq * (4000 / 16) + 700000 + 225000) + 16384) >> 15;
- break;
- }
- buffer[0] = (div >> 8) & 0x3f;
- buffer[1] = div & 0xff;
-
- if (5 != (rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 5)))
- tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
-
- if (debug) {
- if (5 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props, buffer, 5)))
- tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
- else
- tea5767_status_dump(priv, buffer);
- }
-
- priv->frequency = frq * 125 / 2;
-
- return 0;
-}
-
-static int tea5767_read_status(struct dvb_frontend *fe, char *buffer)
-{
- struct tea5767_priv *priv = fe->tuner_priv;
- int rc;
-
- memset(buffer, 0, 5);
- if (5 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props, buffer, 5))) {
- tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
- return -EREMOTEIO;
- }
-
- return 0;
-}
-
-static inline int tea5767_signal(struct dvb_frontend *fe, const char *buffer)
-{
- struct tea5767_priv *priv = fe->tuner_priv;
-
- int signal = ((buffer[3] & TEA5767_ADC_LEVEL_MASK) << 8);
-
- tuner_dbg("Signal strength: %d\n", signal);
-
- return signal;
-}
-
-static inline int tea5767_stereo(struct dvb_frontend *fe, const char *buffer)
-{
- struct tea5767_priv *priv = fe->tuner_priv;
-
- int stereo = buffer[2] & TEA5767_STEREO_MASK;
-
- tuner_dbg("Radio ST GET = %02x\n", stereo);
-
- return (stereo ? V4L2_TUNER_SUB_STEREO : 0);
-}
-
-static int tea5767_get_status(struct dvb_frontend *fe, u32 *status)
-{
- unsigned char buffer[5];
-
- *status = 0;
-
- if (0 == tea5767_read_status(fe, buffer)) {
- if (tea5767_signal(fe, buffer))
- *status = TUNER_STATUS_LOCKED;
- if (tea5767_stereo(fe, buffer))
- *status |= TUNER_STATUS_STEREO;
- }
-
- return 0;
-}
-
-static int tea5767_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
-{
- unsigned char buffer[5];
-
- *strength = 0;
-
- if (0 == tea5767_read_status(fe, buffer))
- *strength = tea5767_signal(fe, buffer);
-
- return 0;
-}
-
-static int tea5767_standby(struct dvb_frontend *fe)
-{
- unsigned char buffer[5];
- struct tea5767_priv *priv = fe->tuner_priv;
- unsigned div, rc;
-
- div = (87500 * 4 + 700 + 225 + 25) / 50; /* Set frequency to 87.5 MHz */
- buffer[0] = (div >> 8) & 0x3f;
- buffer[1] = div & 0xff;
- buffer[2] = TEA5767_PORT1_HIGH;
- buffer[3] = TEA5767_PORT2_HIGH | TEA5767_HIGH_CUT_CTRL |
- TEA5767_ST_NOISE_CTL | TEA5767_JAPAN_BAND | TEA5767_STDBY;
- buffer[4] = 0;
-
- if (5 != (rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 5)))
- tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
-
- return 0;
-}
-
-int tea5767_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr)
-{
- struct tuner_i2c_props i2c = { .adap = i2c_adap, .addr = i2c_addr };
- unsigned char buffer[7] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
- int rc;
-#if 0 /* Needed if uncomment I2C send code below */
- int div;
-#endif
-
- if ((rc = tuner_i2c_xfer_recv(&i2c, buffer, 7))< 5) {
- printk(KERN_WARNING "It is not a TEA5767. Received %i bytes.\n", rc);
- return EINVAL;
- }
-
- /* If all bytes are the same then it's a TV tuner and not a tea5767 */
- if (buffer[0] == buffer[1] && buffer[0] == buffer[2] &&
- buffer[0] == buffer[3] && buffer[0] == buffer[4]) {
- printk(KERN_WARNING "All bytes are equal. It is not a TEA5767\n");
- return EINVAL;
- }
-
- /* Status bytes:
- * Byte 4: bit 3:1 : CI (Chip Identification) == 0
- * bit 0 : internally set to 0
- * Byte 5: bit 7:0 : == 0
- */
- if (((buffer[3] & 0x0f) != 0x00) || (buffer[4] != 0x00)) {
- printk(KERN_WARNING "Chip ID is not zero. It is not a TEA5767\n");
- return EINVAL;
- }
-
-#if 0 /* Not working for TEA5767 in Beholder Columbus card */
- /* It seems that tea5767 returns 0xff after the 5th byte */
- if ((buffer[5] != 0xff) || (buffer[6] != 0xff)) {
- printk(KERN_WARNING "Returned more than 5 bytes. It is not a TEA5767\n");
- return EINVAL;
- }
-#endif
-
-#if 0 /*Sometimes, this code doesn't work */
- /* Sets tuner at some freq (87.5 MHz) and see if it is ok */
- div = ((87500 * 4000 + 700000 + 225000) + 16768) >> 15;
- buffer[0] = ((div >> 8) & 0x3f) | TEA5767_MUTE;
- buffer[1] = div & 0xff;
- buffer[2] = TEA5767_PORT1_HIGH;
- buffer[3] = TEA5767_PORT2_HIGH | TEA5767_HIGH_CUT_CTRL |
- TEA5767_ST_NOISE_CTL;
- buffer[4] = 0;
-
- if (5 != (rc = tuner_i2c_xfer_send(&i2c, buffer, 5)))
- printk(KERN_WARNING "i2c i/o error: rc == %d (should be 5)\n", rc);
-
- msleep(15);
-
- if (5 != (rc = tuner_i2c_xfer_recv(&i2c, buffer, 5))) {
- printk(KERN_WARNING "It is not a TEA5767. Received %i bytes.\n", rc);
- return EINVAL;
- }
-
- /* Initial freq for 32.768KHz clock */
- if ((buffer[1] != (div & 0xff) ) || ((buffer[0] & 0x3f) != ((div >> 8) & 0x3f))) {
- printk(KERN_WARNING "It is not a TEA5767. div=%d, Return: %02x %02x %02x %02x %02x\n",
- div,buffer[0],buffer[1],buffer[2],buffer[3],buffer[4]);
- tea5767_status_dump(buffer);
- return EINVAL;
- }
-#endif
- return 0;
-}
-
-static int tea5767_release(struct dvb_frontend *fe)
-{
- kfree(fe->tuner_priv);
- fe->tuner_priv = NULL;
-
- return 0;
-}
-
-static int tea5767_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
- struct tea5767_priv *priv = fe->tuner_priv;
- *frequency = priv->frequency;
-
- return 0;
-}
-
-static int tea5767_set_config (struct dvb_frontend *fe, void *priv_cfg)
-{
- struct tea5767_priv *priv = fe->tuner_priv;
-
- memcpy(&priv->ctrl, priv_cfg, sizeof(priv->ctrl));
-
- return 0;
-}
-
-static struct dvb_tuner_ops tea5767_tuner_ops = {
- .info = {
- .name = "tea5767", // Philips TEA5767HN FM Radio
-#if 0
- .frequency_min = ,
- .frequency_max = ,
- .frequency_step = ,
-#endif
- },
-
- .set_analog_params = set_radio_freq,
- .set_config = tea5767_set_config,
- .sleep = tea5767_standby,
- .release = tea5767_release,
- .get_frequency = tea5767_get_frequency,
- .get_status = tea5767_get_status,
- .get_rf_strength = tea5767_get_rf_strength,
-};
-
-struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe,
- struct i2c_adapter* i2c_adap,
- u8 i2c_addr)
-{
- struct tea5767_priv *priv = NULL;
-
-#if 0 /* By removing autodetection allows forcing TEA chip */
- if (tea5767_autodetection(i2c_adap, i2c_addr) == EINVAL)
- return EINVAL;
-#endif
- priv = kzalloc(sizeof(struct tea5767_priv), GFP_KERNEL);
- if (priv == NULL)
- return NULL;
- fe->tuner_priv = priv;
-
- priv->i2c_props.addr = i2c_addr;
- priv->i2c_props.adap = i2c_adap;
- priv->i2c_props.name = "tea5767";
-
- priv->ctrl.xtal_freq = TEA5767_HIGH_LO_32768;
- priv->ctrl.port1 = 1;
- priv->ctrl.port2 = 1;
- priv->ctrl.high_cut = 1;
- priv->ctrl.st_noise = 1;
- priv->ctrl.japan_band = 1;
-
- memcpy(&fe->ops.tuner_ops, &tea5767_tuner_ops,
- sizeof(struct dvb_tuner_ops));
-
- tuner_info("type set to %s\n", "Philips TEA5767HN FM Radio");
-
- return fe;
-}
-
-EXPORT_SYMBOL_GPL(tea5767_attach);
-EXPORT_SYMBOL_GPL(tea5767_autodetection);
-
-MODULE_DESCRIPTION("Philips TEA5767 FM tuner driver");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
-MODULE_LICENSE("GPL");
diff --git a/linux/drivers/media/video/tea5767.h b/linux/drivers/media/video/tea5767.h
deleted file mode 100644
index 7b547c092..000000000
--- a/linux/drivers/media/video/tea5767.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- 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.
-*/
-
-#ifndef __TEA5767_H__
-#define __TEA5767_H__
-
-#include <linux/i2c.h>
-#include "dvb_frontend.h"
-
-enum tea5767_xtal {
- TEA5767_LOW_LO_32768 = 0,
- TEA5767_HIGH_LO_32768 = 1,
- TEA5767_LOW_LO_13MHz = 2,
- TEA5767_HIGH_LO_13MHz = 3,
-};
-
-struct tea5767_ctrl {
- unsigned int port1:1;
- unsigned int port2:1;
- unsigned int high_cut:1;
- unsigned int st_noise:1;
- unsigned int soft_mute:1;
- unsigned int japan_band:1;
- unsigned int deemph_75:1;
- unsigned int pllref:1;
- enum tea5767_xtal xtal_freq;
-};
-
-#if defined(CONFIG_TUNER_TEA5767) || (defined(CONFIG_TUNER_TEA5767_MODULE) && defined(MODULE))
-extern int tea5767_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr);
-
-extern struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe,
- struct i2c_adapter* i2c_adap,
- u8 i2c_addr);
-#else
-static inline int tea5767_autodetection(struct i2c_adapter* i2c_adap,
- u8 i2c_addr)
-{
- printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
- __func__);
- return -EINVAL;
-}
-
-static inline struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe,
- struct i2c_adapter* i2c_adap,
- u8 i2c_addr)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return NULL;
-}
-#endif
-
-#endif /* __TEA5767_H__ */
diff --git a/linux/drivers/media/video/tuner-i2c.h b/linux/drivers/media/video/tuner-i2c.h
deleted file mode 100644
index 3ad6c8e0b..000000000
--- a/linux/drivers/media/video/tuner-i2c.h
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- tuner-i2c.h - i2c interface for different tuners
-
- Copyright (C) 2007 Michael Krufky (mkrufky@linuxtv.org)
-
- 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.
-*/
-
-#ifndef __TUNER_I2C_H__
-#define __TUNER_I2C_H__
-
-#include <linux/i2c.h>
-
-struct tuner_i2c_props {
- u8 addr;
- struct i2c_adapter *adap;
-
- /* used for tuner instance management */
- int count;
- char *name;
-};
-
-static inline int tuner_i2c_xfer_send(struct tuner_i2c_props *props, char *buf, int len)
-{
- struct i2c_msg msg = { .addr = props->addr, .flags = 0,
- .buf = buf, .len = len };
- int ret = i2c_transfer(props->adap, &msg, 1);
-
- return (ret == 1) ? len : ret;
-}
-
-static inline int tuner_i2c_xfer_recv(struct tuner_i2c_props *props, char *buf, int len)
-{
- struct i2c_msg msg = { .addr = props->addr, .flags = I2C_M_RD,
- .buf = buf, .len = len };
- int ret = i2c_transfer(props->adap, &msg, 1);
-
- return (ret == 1) ? len : ret;
-}
-
-static inline int tuner_i2c_xfer_send_recv(struct tuner_i2c_props *props,
- char *obuf, int olen,
- char *ibuf, int ilen)
-{
- struct i2c_msg msg[2] = { { .addr = props->addr, .flags = 0,
- .buf = obuf, .len = olen },
- { .addr = props->addr, .flags = I2C_M_RD,
- .buf = ibuf, .len = ilen } };
- int ret = i2c_transfer(props->adap, msg, 2);
-
- return (ret == 2) ? ilen : ret;
-}
-
-/* Callers must declare as a global for the module:
- *
- * static LIST_HEAD(hybrid_tuner_instance_list);
- *
- * hybrid_tuner_instance_list should be the third argument
- * passed into hybrid_tuner_request_state().
- *
- * state structure must contain the following:
- *
- * struct list_head hybrid_tuner_instance_list;
- * struct tuner_i2c_props i2c_props;
- *
- * hybrid_tuner_instance_list (both within state structure and globally)
- * is only required if the driver is using hybrid_tuner_request_state
- * and hybrid_tuner_release_state to manage state sharing between
- * multiple instances of hybrid tuners.
- */
-
-#define tuner_printk(kernlvl, i2cprops, fmt, arg...) do { \
- printk(kernlvl "%s %d-%04x: " fmt, i2cprops.name, \
- i2cprops.adap ? \
- i2c_adapter_id(i2cprops.adap) : -1, \
- i2cprops.addr, ##arg); \
- } while (0)
-
-/* TO DO: convert all callers of these macros to pass in
- * struct tuner_i2c_props, then remove the macro wrappers */
-
-#define __tuner_warn(i2cprops, fmt, arg...) do { \
- tuner_printk(KERN_WARNING, i2cprops, fmt, ##arg); \
- } while (0)
-
-#define __tuner_info(i2cprops, fmt, arg...) do { \
- tuner_printk(KERN_INFO, i2cprops, fmt, ##arg); \
- } while (0)
-
-#define __tuner_err(i2cprops, fmt, arg...) do { \
- tuner_printk(KERN_ERR, i2cprops, fmt, ##arg); \
- } while (0)
-
-#define __tuner_dbg(i2cprops, fmt, arg...) do { \
- if ((debug)) \
- tuner_printk(KERN_DEBUG, i2cprops, fmt, ##arg); \
- } while (0)
-
-#define tuner_warn(fmt, arg...) __tuner_warn(priv->i2c_props, fmt, ##arg)
-#define tuner_info(fmt, arg...) __tuner_info(priv->i2c_props, fmt, ##arg)
-#define tuner_err(fmt, arg...) __tuner_err(priv->i2c_props, fmt, ##arg)
-#define tuner_dbg(fmt, arg...) __tuner_dbg(priv->i2c_props, fmt, ##arg)
-
-/****************************************************************************/
-
-/* The return value of hybrid_tuner_request_state indicates the number of
- * instances using this tuner object.
- *
- * 0 - no instances, indicates an error - kzalloc must have failed
- *
- * 1 - one instance, indicates that the tuner object was created successfully
- *
- * 2 (or more) instances, indicates that an existing tuner object was found
- */
-
-#define hybrid_tuner_request_state(type, state, list, i2cadap, i2caddr, devname)\
-({ \
- int __ret = 0; \
- list_for_each_entry(state, &list, hybrid_tuner_instance_list) { \
- if (((i2cadap) && (state->i2c_props.adap)) && \
- ((i2c_adapter_id(state->i2c_props.adap) == \
- i2c_adapter_id(i2cadap)) && \
- (i2caddr == state->i2c_props.addr))) { \
- __tuner_info(state->i2c_props, \
- "attaching existing instance\n"); \
- state->i2c_props.count++; \
- __ret = state->i2c_props.count; \
- break; \
- } \
- } \
- if (0 == __ret) { \
- state = kzalloc(sizeof(type), GFP_KERNEL); \
- if (NULL == state) \
- goto __fail; \
- state->i2c_props.addr = i2caddr; \
- state->i2c_props.adap = i2cadap; \
- state->i2c_props.name = devname; \
- __tuner_info(state->i2c_props, \
- "creating new instance\n"); \
- list_add_tail(&state->hybrid_tuner_instance_list, &list);\
- state->i2c_props.count++; \
- __ret = state->i2c_props.count; \
- } \
-__fail: \
- __ret; \
-})
-
-#define hybrid_tuner_release_state(state) \
-({ \
- int __ret; \
- state->i2c_props.count--; \
- __ret = state->i2c_props.count; \
- if (!state->i2c_props.count) { \
- __tuner_info(state->i2c_props, "destroying instance\n");\
- list_del(&state->hybrid_tuner_instance_list); \
- kfree(state); \
- } \
- __ret; \
-})
-
-#endif /* __TUNER_I2C_H__ */
diff --git a/linux/drivers/media/video/tuner-simple.c b/linux/drivers/media/video/tuner-simple.c
deleted file mode 100644
index 29c14a4c6..000000000
--- a/linux/drivers/media/video/tuner-simple.c
+++ /dev/null
@@ -1,1136 +0,0 @@
-/*
- * i2c tv tuner chip device driver
- * controls all those simple 4-control-bytes style tuners.
- *
- * This "tuner-simple" module was split apart from the original "tuner" module.
- */
-#include <linux/delay.h>
-#include <linux/i2c.h>
-#include "compat.h"
-#include <linux/videodev.h>
-#include <media/tuner.h>
-#include <media/v4l2-common.h>
-#include <media/tuner-types.h>
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-#include "i2c-compat.h"
-#endif
-#include "tuner-i2c.h"
-#include "tuner-simple.h"
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "enable verbose debug messages");
-
-#define TUNER_SIMPLE_MAX 64
-static unsigned int simple_devcount;
-
-static int offset;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-MODULE_PARM(offset, "i");
-#else
-module_param(offset, int, 0664);
-#endif
-MODULE_PARM_DESC(offset, "Allows to specify an offset for tuner");
-
-static unsigned int atv_input[TUNER_SIMPLE_MAX] = \
- { [0 ... (TUNER_SIMPLE_MAX-1)] = 0 };
-static unsigned int dtv_input[TUNER_SIMPLE_MAX] = \
- { [0 ... (TUNER_SIMPLE_MAX-1)] = 0 };
-module_param_array(atv_input, int, NULL, 0644);
-module_param_array(dtv_input, int, NULL, 0644);
-MODULE_PARM_DESC(atv_input, "specify atv rf input, 0 for autoselect");
-MODULE_PARM_DESC(dtv_input, "specify dtv rf input, 0 for autoselect");
-
-/* ---------------------------------------------------------------------- */
-
-/* tv standard selection for Temic 4046 FM5
- this value takes the low bits of control byte 2
- from datasheet Rev.01, Feb.00
- standard BG I L L2 D
- picture IF 38.9 38.9 38.9 33.95 38.9
- sound 1 33.4 32.9 32.4 40.45 32.4
- sound 2 33.16
- NICAM 33.05 32.348 33.05 33.05
- */
-#define TEMIC_SET_PAL_I 0x05
-#define TEMIC_SET_PAL_DK 0x09
-#define TEMIC_SET_PAL_L 0x0a /* SECAM ? */
-#define TEMIC_SET_PAL_L2 0x0b /* change IF ! */
-#define TEMIC_SET_PAL_BG 0x0c
-
-/* tv tuner system standard selection for Philips FQ1216ME
- this value takes the low bits of control byte 2
- from datasheet "1999 Nov 16" (supersedes "1999 Mar 23")
- standard BG DK I L L`
- picture carrier 38.90 38.90 38.90 38.90 33.95
- colour 34.47 34.47 34.47 34.47 38.38
- sound 1 33.40 32.40 32.90 32.40 40.45
- sound 2 33.16 - - - -
- NICAM 33.05 33.05 32.35 33.05 39.80
- */
-#define PHILIPS_SET_PAL_I 0x01 /* Bit 2 always zero !*/
-#define PHILIPS_SET_PAL_BGDK 0x09
-#define PHILIPS_SET_PAL_L2 0x0a
-#define PHILIPS_SET_PAL_L 0x0b
-
-/* system switching for Philips FI1216MF MK2
- from datasheet "1996 Jul 09",
- standard BG L L'
- picture carrier 38.90 38.90 33.95
- colour 34.47 34.37 38.38
- sound 1 33.40 32.40 40.45
- sound 2 33.16 - -
- NICAM 33.05 33.05 39.80
- */
-#define PHILIPS_MF_SET_STD_BG 0x01 /* Bit 2 must be zero, Bit 3 is system output */
-#define PHILIPS_MF_SET_STD_L 0x03 /* Used on Secam France */
-#define PHILIPS_MF_SET_STD_LC 0x02 /* Used on SECAM L' */
-
-/* Control byte */
-
-#define TUNER_RATIO_MASK 0x06 /* Bit cb1:cb2 */
-#define TUNER_RATIO_SELECT_50 0x00
-#define TUNER_RATIO_SELECT_32 0x02
-#define TUNER_RATIO_SELECT_166 0x04
-#define TUNER_RATIO_SELECT_62 0x06
-
-#define TUNER_CHARGE_PUMP 0x40 /* Bit cb6 */
-
-/* Status byte */
-
-#define TUNER_POR 0x80
-#define TUNER_FL 0x40
-#define TUNER_MODE 0x38
-#define TUNER_AFC 0x07
-#define TUNER_SIGNAL 0x07
-#define TUNER_STEREO 0x10
-
-#define TUNER_PLL_LOCKED 0x40
-#define TUNER_STEREO_MK3 0x04
-
-static DEFINE_MUTEX(tuner_simple_list_mutex);
-static LIST_HEAD(hybrid_tuner_instance_list);
-
-struct tuner_simple_priv {
- unsigned int nr;
- u16 last_div;
-
- struct tuner_i2c_props i2c_props;
- struct list_head hybrid_tuner_instance_list;
-
- unsigned int type;
- struct tunertype *tun;
-
- u32 frequency;
- u32 bandwidth;
-};
-
-/* ---------------------------------------------------------------------- */
-
-static int tuner_read_status(struct dvb_frontend *fe)
-{
- struct tuner_simple_priv *priv = fe->tuner_priv;
- unsigned char byte;
-
- if (1 != tuner_i2c_xfer_recv(&priv->i2c_props, &byte, 1))
- return 0;
-
- return byte;
-}
-
-static inline int tuner_signal(const int status)
-{
- return (status & TUNER_SIGNAL) << 13;
-}
-
-static inline int tuner_stereo(const int type, const int status)
-{
- switch (type) {
- case TUNER_PHILIPS_FM1216ME_MK3:
- case TUNER_PHILIPS_FM1236_MK3:
- case TUNER_PHILIPS_FM1256_IH3:
- case TUNER_LG_NTSC_TAPE:
- return ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3);
- default:
- return status & TUNER_STEREO;
- }
-}
-
-static inline int tuner_islocked(const int status)
-{
- return (status & TUNER_FL);
-}
-
-static inline int tuner_afcstatus(const int status)
-{
- return (status & TUNER_AFC) - 2;
-}
-
-#if 0 /* unused */
-static inline int tuner_mode(const int status)
-{
- return (status & TUNER_MODE) >> 3;
-}
-#endif
-
-static int simple_get_status(struct dvb_frontend *fe, u32 *status)
-{
- struct tuner_simple_priv *priv = fe->tuner_priv;
- int tuner_status;
-
- if (priv->i2c_props.adap == NULL)
- return -EINVAL;
-
- tuner_status = tuner_read_status(fe);
-
- *status = 0;
-
- if (tuner_islocked(tuner_status))
- *status = TUNER_STATUS_LOCKED;
- if (tuner_stereo(priv->type, tuner_status))
- *status |= TUNER_STATUS_STEREO;
-
- tuner_dbg("AFC Status: %d\n", tuner_afcstatus(tuner_status));
-
- return 0;
-}
-
-static int simple_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
-{
- struct tuner_simple_priv *priv = fe->tuner_priv;
- int signal;
-
- if (priv->i2c_props.adap == NULL)
- return -EINVAL;
-
- signal = tuner_signal(tuner_read_status(fe));
-
- *strength = signal;
-
- tuner_dbg("Signal strength: %d\n", signal);
-
- return 0;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static inline char *tuner_param_name(enum param_type type)
-{
- char *name;
-
- switch (type) {
- case TUNER_PARAM_TYPE_RADIO:
- name = "radio";
- break;
- case TUNER_PARAM_TYPE_PAL:
- name = "pal";
- break;
- case TUNER_PARAM_TYPE_SECAM:
- name = "secam";
- break;
- case TUNER_PARAM_TYPE_NTSC:
- name = "ntsc";
- break;
- case TUNER_PARAM_TYPE_DIGITAL:
- name = "digital";
- break;
- default:
- name = "unknown";
- break;
- }
- return name;
-}
-
-static struct tuner_params *simple_tuner_params(struct dvb_frontend *fe,
- enum param_type desired_type)
-{
- struct tuner_simple_priv *priv = fe->tuner_priv;
- struct tunertype *tun = priv->tun;
- int i;
-
- for (i = 0; i < tun->count; i++)
- if (desired_type == tun->params[i].type)
- break;
-
- /* use default tuner params if desired_type not available */
- if (i == tun->count) {
- tuner_dbg("desired params (%s) undefined for tuner %d\n",
- tuner_param_name(desired_type), priv->type);
- i = 0;
- }
-
- tuner_dbg("using tuner params #%d (%s)\n", i,
- tuner_param_name(tun->params[i].type));
-
- return &tun->params[i];
-}
-
-static int simple_config_lookup(struct dvb_frontend *fe,
- struct tuner_params *t_params,
- int *frequency, u8 *config, u8 *cb)
-{
- struct tuner_simple_priv *priv = fe->tuner_priv;
- int i;
-
- for (i = 0; i < t_params->count; i++) {
- if (*frequency > t_params->ranges[i].limit)
- continue;
- break;
- }
- if (i == t_params->count) {
- tuner_dbg("frequency out of range (%d > %d)\n",
- *frequency, t_params->ranges[i - 1].limit);
- *frequency = t_params->ranges[--i].limit;
- }
- *config = t_params->ranges[i].config;
- *cb = t_params->ranges[i].cb;
-
- tuner_dbg("freq = %d.%02d (%d), range = %d, "
- "config = 0x%02x, cb = 0x%02x\n",
- *frequency / 16, *frequency % 16 * 100 / 16, *frequency,
- i, *config, *cb);
-
- return i;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static void simple_set_rf_input(struct dvb_frontend *fe,
- u8 *config, u8 *cb, unsigned int rf)
-{
- struct tuner_simple_priv *priv = fe->tuner_priv;
-
- switch (priv->type) {
- case TUNER_PHILIPS_TUV1236D:
- switch (rf) {
- case 1:
- *cb |= 0x08;
- break;
- default:
- *cb &= ~0x08;
- break;
- }
- break;
- case TUNER_PHILIPS_FCV1236D:
- switch (rf) {
- case 1:
- *cb |= 0x01;
- break;
- default:
- *cb &= ~0x01;
- break;
- }
- break;
- default:
- break;
- }
-}
-
-static int simple_std_setup(struct dvb_frontend *fe,
- struct analog_parameters *params,
- u8 *config, u8 *cb)
-{
- struct tuner_simple_priv *priv = fe->tuner_priv;
- u8 tuneraddr;
- int rc;
-
- /* tv norm specific stuff for multi-norm tuners */
- switch (priv->type) {
- case TUNER_PHILIPS_SECAM: /* FI1216MF */
- /* 0x01 -> ??? no change ??? */
- /* 0x02 -> PAL BDGHI / SECAM L */
- /* 0x04 -> ??? PAL others / SECAM others ??? */
- *cb &= ~0x03;
- if (params->std & V4L2_STD_SECAM_L)
- /* also valid for V4L2_STD_SECAM */
- *cb |= PHILIPS_MF_SET_STD_L;
- else if (params->std & V4L2_STD_SECAM_LC)
- *cb |= PHILIPS_MF_SET_STD_LC;
- else /* V4L2_STD_B|V4L2_STD_GH */
- *cb |= PHILIPS_MF_SET_STD_BG;
- break;
-
- case TUNER_TEMIC_4046FM5:
- *cb &= ~0x0f;
-
- if (params->std & V4L2_STD_PAL_BG) {
- *cb |= TEMIC_SET_PAL_BG;
-
- } else if (params->std & V4L2_STD_PAL_I) {
- *cb |= TEMIC_SET_PAL_I;
-
- } else if (params->std & V4L2_STD_PAL_DK) {
- *cb |= TEMIC_SET_PAL_DK;
-
- } else if (params->std & V4L2_STD_SECAM_L) {
- *cb |= TEMIC_SET_PAL_L;
-
- }
- break;
-
- case TUNER_PHILIPS_FQ1216ME:
- *cb &= ~0x0f;
-
- if (params->std & (V4L2_STD_PAL_BG|V4L2_STD_PAL_DK)) {
- *cb |= PHILIPS_SET_PAL_BGDK;
-
- } else if (params->std & V4L2_STD_PAL_I) {
- *cb |= PHILIPS_SET_PAL_I;
-
- } else if (params->std & V4L2_STD_SECAM_L) {
- *cb |= PHILIPS_SET_PAL_L;
-
- }
- break;
-
- case TUNER_PHILIPS_FCV1236D:
- /* 0x00 -> ATSC antenna input 1 */
- /* 0x01 -> ATSC antenna input 2 */
- /* 0x02 -> NTSC antenna input 1 */
- /* 0x03 -> NTSC antenna input 2 */
- *cb &= ~0x03;
- if (!(params->std & V4L2_STD_ATSC))
- *cb |= 2;
- break;
-
- case TUNER_MICROTUNE_4042FI5:
- /* Set the charge pump for fast tuning */
- *config |= TUNER_CHARGE_PUMP;
- break;
-
- case TUNER_PHILIPS_TUV1236D:
- {
- /* 0x40 -> ATSC antenna input 1 */
- /* 0x48 -> ATSC antenna input 2 */
- /* 0x00 -> NTSC antenna input 1 */
- /* 0x08 -> NTSC antenna input 2 */
- u8 buffer[4] = { 0x14, 0x00, 0x17, 0x00};
- *cb &= ~0x40;
- if (params->std & V4L2_STD_ATSC) {
- *cb |= 0x40;
- buffer[1] = 0x04;
- }
- /* set to the correct mode (analog or digital) */
- tuneraddr = priv->i2c_props.addr;
- priv->i2c_props.addr = 0x0a;
- rc = tuner_i2c_xfer_send(&priv->i2c_props, &buffer[0], 2);
- if (2 != rc)
- tuner_warn("i2c i/o error: rc == %d "
- "(should be 2)\n", rc);
- rc = tuner_i2c_xfer_send(&priv->i2c_props, &buffer[2], 2);
- if (2 != rc)
- tuner_warn("i2c i/o error: rc == %d "
- "(should be 2)\n", rc);
- priv->i2c_props.addr = tuneraddr;
- break;
- }
- }
- if (atv_input[priv->nr])
- simple_set_rf_input(fe, config, cb, atv_input[priv->nr]);
-
- return 0;
-}
-
-static int simple_post_tune(struct dvb_frontend *fe, u8 *buffer,
- u16 div, u8 config, u8 cb)
-{
- struct tuner_simple_priv *priv = fe->tuner_priv;
- int rc;
-
- switch (priv->type) {
- case TUNER_LG_TDVS_H06XF:
- /* Set the Auxiliary Byte. */
-#if 0
- buffer[2] &= ~0x20;
- buffer[2] |= 0x18;
- buffer[3] = 0x20;
- tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
- buffer[0], buffer[1], buffer[2], buffer[3]);
-
- rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4);
- if (4 != rc)
- tuner_warn("i2c i/o error: rc == %d "
- "(should be 4)\n", rc);
-#else
- buffer[0] = buffer[2];
- buffer[0] &= ~0x20;
- buffer[0] |= 0x18;
- buffer[1] = 0x20;
- tuner_dbg("tv 0x%02x 0x%02x\n", buffer[0], buffer[1]);
-
- rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 2);
- if (2 != rc)
- tuner_warn("i2c i/o error: rc == %d "
- "(should be 2)\n", rc);
-#endif
- break;
- case TUNER_MICROTUNE_4042FI5:
- {
- /* FIXME - this may also work for other tuners */
- unsigned long timeout = jiffies + msecs_to_jiffies(1);
- u8 status_byte = 0;
-
- /* Wait until the PLL locks */
- for (;;) {
- if (time_after(jiffies, timeout))
- return 0;
- rc = tuner_i2c_xfer_recv(&priv->i2c_props,
- &status_byte, 1);
- if (1 != rc) {
- tuner_warn("i2c i/o read error: rc == %d "
- "(should be 1)\n", rc);
- break;
- }
- if (status_byte & TUNER_PLL_LOCKED)
- break;
- udelay(10);
- }
-
- /* Set the charge pump for optimized phase noise figure */
- config &= ~TUNER_CHARGE_PUMP;
- buffer[0] = (div>>8) & 0x7f;
- buffer[1] = div & 0xff;
- buffer[2] = config;
- buffer[3] = cb;
- tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
- buffer[0], buffer[1], buffer[2], buffer[3]);
-
- rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4);
- if (4 != rc)
- tuner_warn("i2c i/o error: rc == %d "
- "(should be 4)\n", rc);
- break;
- }
- }
-
- return 0;
-}
-
-static int simple_radio_bandswitch(struct dvb_frontend *fe, u8 *buffer)
-{
- struct tuner_simple_priv *priv = fe->tuner_priv;
-
- switch (priv->type) {
- case TUNER_TENA_9533_DI:
- case TUNER_YMEC_TVF_5533MF:
- tuner_dbg("This tuner doesn't have FM. "
- "Most cards have a TEA5767 for FM\n");
- return 0;
- case TUNER_PHILIPS_FM1216ME_MK3:
- case TUNER_PHILIPS_FM1236_MK3:
- case TUNER_PHILIPS_FMD1216ME_MK3:
- case TUNER_LG_NTSC_TAPE:
- case TUNER_PHILIPS_FM1256_IH3:
- buffer[3] = 0x19;
- break;
- case TUNER_TNF_5335MF:
- buffer[3] = 0x11;
- break;
- case TUNER_LG_PAL_FM:
- buffer[3] = 0xa5;
- break;
- case TUNER_THOMSON_DTT761X:
- buffer[3] = 0x39;
- break;
- case TUNER_MICROTUNE_4049FM5:
- default:
- buffer[3] = 0xa4;
- break;
- }
-
- return 0;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int simple_set_tv_freq(struct dvb_frontend *fe,
- struct analog_parameters *params)
-{
- struct tuner_simple_priv *priv = fe->tuner_priv;
- u8 config, cb;
- u16 div;
- struct tunertype *tun;
- u8 buffer[4];
- int rc, IFPCoff, i;
- enum param_type desired_type;
- struct tuner_params *t_params;
-
- tun = priv->tun;
-
- /* IFPCoff = Video Intermediate Frequency - Vif:
- 940 =16*58.75 NTSC/J (Japan)
- 732 =16*45.75 M/N STD
- 704 =16*44 ATSC (at DVB code)
- 632 =16*39.50 I U.K.
- 622.4=16*38.90 B/G D/K I, L STD
- 592 =16*37.00 D China
- 590 =16.36.875 B Australia
- 543.2=16*33.95 L' STD
- 171.2=16*10.70 FM Radio (at set_radio_freq)
- */
-
- if (params->std == V4L2_STD_NTSC_M_JP) {
- IFPCoff = 940;
- desired_type = TUNER_PARAM_TYPE_NTSC;
- } else if ((params->std & V4L2_STD_MN) &&
- !(params->std & ~V4L2_STD_MN)) {
- IFPCoff = 732;
- desired_type = TUNER_PARAM_TYPE_NTSC;
- } else if (params->std == V4L2_STD_SECAM_LC) {
- IFPCoff = 543;
- desired_type = TUNER_PARAM_TYPE_SECAM;
- } else {
- IFPCoff = 623;
- desired_type = TUNER_PARAM_TYPE_PAL;
- }
-
- t_params = simple_tuner_params(fe, desired_type);
-
- i = simple_config_lookup(fe, t_params, &params->frequency,
- &config, &cb);
-
- div = params->frequency + IFPCoff + offset;
-
- tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, "
- "Offset=%d.%02d MHz, div=%0d\n",
- params->frequency / 16, params->frequency % 16 * 100 / 16,
- IFPCoff / 16, IFPCoff % 16 * 100 / 16,
- offset / 16, offset % 16 * 100 / 16, div);
-
- /* tv norm specific stuff for multi-norm tuners */
- simple_std_setup(fe, params, &config, &cb);
-
- if (t_params->cb_first_if_lower_freq && div < priv->last_div) {
- buffer[0] = config;
- buffer[1] = cb;
- buffer[2] = (div>>8) & 0x7f;
- buffer[3] = div & 0xff;
- } else {
- buffer[0] = (div>>8) & 0x7f;
- buffer[1] = div & 0xff;
- buffer[2] = config;
- buffer[3] = cb;
- }
- priv->last_div = div;
- if (t_params->has_tda9887) {
- struct v4l2_priv_tun_config tda9887_cfg;
- int config = 0;
- int is_secam_l = (params->std & (V4L2_STD_SECAM_L |
- V4L2_STD_SECAM_LC)) &&
- !(params->std & ~(V4L2_STD_SECAM_L |
- V4L2_STD_SECAM_LC));
-
- tda9887_cfg.tuner = TUNER_TDA9887;
- tda9887_cfg.priv = &config;
-
- if (params->std == V4L2_STD_SECAM_LC) {
- if (t_params->port1_active ^ t_params->port1_invert_for_secam_lc)
- config |= TDA9887_PORT1_ACTIVE;
- if (t_params->port2_active ^ t_params->port2_invert_for_secam_lc)
- config |= TDA9887_PORT2_ACTIVE;
- } else {
- if (t_params->port1_active)
- config |= TDA9887_PORT1_ACTIVE;
- if (t_params->port2_active)
- config |= TDA9887_PORT2_ACTIVE;
- }
- if (t_params->intercarrier_mode)
- config |= TDA9887_INTERCARRIER;
- if (is_secam_l) {
- if (i == 0 && t_params->default_top_secam_low)
- config |= TDA9887_TOP(t_params->default_top_secam_low);
- else if (i == 1 && t_params->default_top_secam_mid)
- config |= TDA9887_TOP(t_params->default_top_secam_mid);
- else if (t_params->default_top_secam_high)
- config |= TDA9887_TOP(t_params->default_top_secam_high);
- } else {
- if (i == 0 && t_params->default_top_low)
- config |= TDA9887_TOP(t_params->default_top_low);
- else if (i == 1 && t_params->default_top_mid)
- config |= TDA9887_TOP(t_params->default_top_mid);
- else if (t_params->default_top_high)
- config |= TDA9887_TOP(t_params->default_top_high);
- }
- if (t_params->default_pll_gating_18)
- config |= TDA9887_GATING_18;
- i2c_clients_command(priv->i2c_props.adap, TUNER_SET_CONFIG,
- &tda9887_cfg);
- }
- tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
- buffer[0], buffer[1], buffer[2], buffer[3]);
-
- rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4);
- if (4 != rc)
- tuner_warn("i2c i/o error: rc == %d (should be 4)\n", rc);
-
- simple_post_tune(fe, &buffer[0], div, config, cb);
-
- return 0;
-}
-
-static int simple_set_radio_freq(struct dvb_frontend *fe,
- struct analog_parameters *params)
-{
- struct tunertype *tun;
- struct tuner_simple_priv *priv = fe->tuner_priv;
- u8 buffer[4];
- u16 div;
- int rc, j;
- struct tuner_params *t_params;
- unsigned int freq = params->frequency;
-
- tun = priv->tun;
-
- for (j = tun->count-1; j > 0; j--)
- if (tun->params[j].type == TUNER_PARAM_TYPE_RADIO)
- break;
- /* default t_params (j=0) will be used if desired type wasn't found */
- t_params = &tun->params[j];
-
- /* Select Radio 1st IF used */
- switch (t_params->radio_if) {
- case 0: /* 10.7 MHz */
- freq += (unsigned int)(10.7*16000);
- break;
- case 1: /* 33.3 MHz */
- freq += (unsigned int)(33.3*16000);
- break;
- case 2: /* 41.3 MHz */
- freq += (unsigned int)(41.3*16000);
- break;
- default:
- tuner_warn("Unsupported radio_if value %d\n",
- t_params->radio_if);
- return 0;
- }
-
- /* Bandswitch byte */
- simple_radio_bandswitch(fe, &buffer[0]);
-
- buffer[2] = (t_params->ranges[0].config & ~TUNER_RATIO_MASK) |
- TUNER_RATIO_SELECT_50; /* 50 kHz step */
-
- /* Convert from 1/16 kHz V4L steps to 1/20 MHz (=50 kHz) PLL steps
- freq * (1 Mhz / 16000 V4L steps) * (20 PLL steps / 1 MHz) =
- freq * (1/800) */
- div = (freq + 400) / 800;
-
- if (t_params->cb_first_if_lower_freq && div < priv->last_div) {
- buffer[0] = buffer[2];
- buffer[1] = buffer[3];
- buffer[2] = (div>>8) & 0x7f;
- buffer[3] = div & 0xff;
- } else {
- buffer[0] = (div>>8) & 0x7f;
- buffer[1] = div & 0xff;
- }
-
- tuner_dbg("radio 0x%02x 0x%02x 0x%02x 0x%02x\n",
- buffer[0], buffer[1], buffer[2], buffer[3]);
- priv->last_div = div;
-
- if (t_params->has_tda9887) {
- int config = 0;
- struct v4l2_priv_tun_config tda9887_cfg;
-
- tda9887_cfg.tuner = TUNER_TDA9887;
- tda9887_cfg.priv = &config;
-
- if (t_params->port1_active &&
- !t_params->port1_fm_high_sensitivity)
- config |= TDA9887_PORT1_ACTIVE;
- if (t_params->port2_active &&
- !t_params->port2_fm_high_sensitivity)
- config |= TDA9887_PORT2_ACTIVE;
- if (t_params->intercarrier_mode)
- config |= TDA9887_INTERCARRIER;
-/* if (t_params->port1_set_for_fm_mono)
- config &= ~TDA9887_PORT1_ACTIVE;*/
- if (t_params->fm_gain_normal)
- config |= TDA9887_GAIN_NORMAL;
- if (t_params->radio_if == 2)
- config |= TDA9887_RIF_41_3;
- i2c_clients_command(priv->i2c_props.adap, TUNER_SET_CONFIG,
- &tda9887_cfg);
- }
- rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4);
- if (4 != rc)
- tuner_warn("i2c i/o error: rc == %d (should be 4)\n", rc);
-
- return 0;
-}
-
-static int simple_set_params(struct dvb_frontend *fe,
- struct analog_parameters *params)
-{
- struct tuner_simple_priv *priv = fe->tuner_priv;
- int ret = -EINVAL;
-
- if (priv->i2c_props.adap == NULL)
- return -EINVAL;
-
- switch (params->mode) {
- case V4L2_TUNER_RADIO:
- ret = simple_set_radio_freq(fe, params);
- priv->frequency = params->frequency * 125 / 2;
- break;
- case V4L2_TUNER_ANALOG_TV:
- case V4L2_TUNER_DIGITAL_TV:
- ret = simple_set_tv_freq(fe, params);
- priv->frequency = params->frequency * 62500;
- break;
- }
- priv->bandwidth = 0;
-
- return ret;
-}
-
-static void simple_set_dvb(struct dvb_frontend *fe, u8 *buf,
- const struct dvb_frontend_parameters *params)
-{
- struct tuner_simple_priv *priv = fe->tuner_priv;
-
- switch (priv->type) {
- case TUNER_PHILIPS_FMD1216ME_MK3:
- if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ &&
- params->frequency >= 158870000)
- buf[3] |= 0x08;
- break;
- case TUNER_PHILIPS_TD1316:
- /* determine band */
- buf[3] |= (params->frequency < 161000000) ? 1 :
- (params->frequency < 444000000) ? 2 : 4;
-
- /* setup PLL filter */
- if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ)
- buf[3] |= 1 << 3;
- break;
- case TUNER_PHILIPS_TUV1236D:
- case TUNER_PHILIPS_FCV1236D:
- {
- unsigned int new_rf;
-
- if (dtv_input[priv->nr])
- new_rf = dtv_input[priv->nr];
- else
- switch (params->u.vsb.modulation) {
- case QAM_64:
- case QAM_256:
- new_rf = 1;
- break;
- case VSB_8:
- default:
- new_rf = 0;
- break;
- }
- simple_set_rf_input(fe, &buf[2], &buf[3], new_rf);
- break;
- }
- default:
- break;
- }
-}
-
-static u32 simple_dvb_configure(struct dvb_frontend *fe, u8 *buf,
- const struct dvb_frontend_parameters *params)
-{
- /* This function returns the tuned frequency on success, 0 on error */
- struct tuner_simple_priv *priv = fe->tuner_priv;
- struct tunertype *tun = priv->tun;
- static struct tuner_params *t_params;
- u8 config, cb;
- u32 div;
- int ret, frequency = params->frequency / 62500;
-
- t_params = simple_tuner_params(fe, TUNER_PARAM_TYPE_DIGITAL);
- ret = simple_config_lookup(fe, t_params, &frequency, &config, &cb);
- if (ret < 0)
- return 0; /* failure */
-
- div = ((frequency + t_params->iffreq) * 62500 + offset +
- tun->stepsize/2) / tun->stepsize;
-
- buf[0] = div >> 8;
- buf[1] = div & 0xff;
- buf[2] = config;
- buf[3] = cb;
-
- simple_set_dvb(fe, buf, params);
-
- tuner_dbg("%s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n",
- tun->name, div, buf[0], buf[1], buf[2], buf[3]);
-
- /* calculate the frequency we set it to */
- return (div * tun->stepsize) - t_params->iffreq;
-}
-
-static int simple_dvb_calc_regs(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params,
- u8 *buf, int buf_len)
-{
- struct tuner_simple_priv *priv = fe->tuner_priv;
- u32 frequency;
-
- if (buf_len < 5)
- return -EINVAL;
-
- frequency = simple_dvb_configure(fe, buf+1, params);
- if (frequency == 0)
- return -EINVAL;
-
- buf[0] = priv->i2c_props.addr;
-
- priv->frequency = frequency;
- priv->bandwidth = (fe->ops.info.type == FE_OFDM) ?
- params->u.ofdm.bandwidth : 0;
-
- return 5;
-}
-
-static int simple_dvb_set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
-{
- struct tuner_simple_priv *priv = fe->tuner_priv;
- u32 prev_freq, prev_bw;
- int ret;
- u8 buf[5];
-
- if (priv->i2c_props.adap == NULL)
- return -EINVAL;
-
- prev_freq = priv->frequency;
- prev_bw = priv->bandwidth;
-
- ret = simple_dvb_calc_regs(fe, params, buf, 5);
- if (ret != 5)
- goto fail;
-
- /* put analog demod in standby when tuning digital */
- if (fe->ops.analog_ops.standby)
- fe->ops.analog_ops.standby(fe);
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
-
- /* buf[0] contains the i2c address, but *
- * we already have it in i2c_props.addr */
- ret = tuner_i2c_xfer_send(&priv->i2c_props, buf+1, 4);
- if (ret != 4)
- goto fail;
-
- return 0;
-fail:
- /* calc_regs sets frequency and bandwidth. if we failed, unset them */
- priv->frequency = prev_freq;
- priv->bandwidth = prev_bw;
-
- return ret;
-}
-
-static int simple_init(struct dvb_frontend *fe)
-{
- struct tuner_simple_priv *priv = fe->tuner_priv;
-
- if (priv->i2c_props.adap == NULL)
- return -EINVAL;
-
- if (priv->tun->initdata) {
- int ret;
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
-
- ret = tuner_i2c_xfer_send(&priv->i2c_props,
- priv->tun->initdata + 1,
- priv->tun->initdata[0]);
- if (ret != priv->tun->initdata[0])
- return ret;
- }
-
- return 0;
-}
-
-static int simple_sleep(struct dvb_frontend *fe)
-{
- struct tuner_simple_priv *priv = fe->tuner_priv;
-
- if (priv->i2c_props.adap == NULL)
- return -EINVAL;
-
- if (priv->tun->sleepdata) {
- int ret;
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
-
- ret = tuner_i2c_xfer_send(&priv->i2c_props,
- priv->tun->sleepdata + 1,
- priv->tun->sleepdata[0]);
- if (ret != priv->tun->sleepdata[0])
- return ret;
- }
-
- return 0;
-}
-
-static int simple_release(struct dvb_frontend *fe)
-{
- struct tuner_simple_priv *priv = fe->tuner_priv;
-
- mutex_lock(&tuner_simple_list_mutex);
-
- if (priv)
- hybrid_tuner_release_state(priv);
-
- mutex_unlock(&tuner_simple_list_mutex);
-
- fe->tuner_priv = NULL;
-
- return 0;
-}
-
-static int simple_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
- struct tuner_simple_priv *priv = fe->tuner_priv;
- *frequency = priv->frequency;
- return 0;
-}
-
-static int simple_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
-{
- struct tuner_simple_priv *priv = fe->tuner_priv;
- *bandwidth = priv->bandwidth;
- return 0;
-}
-
-static struct dvb_tuner_ops simple_tuner_ops = {
-#if 0
- .info = {
- .name = "tuner-simple",
- .frequency_min = ,
- .frequency_max = ,
- .frequency_step = ,
- },
-#endif
- .init = simple_init,
- .sleep = simple_sleep,
- .set_analog_params = simple_set_params,
- .set_params = simple_dvb_set_params,
- .calc_regs = simple_dvb_calc_regs,
- .release = simple_release,
- .get_frequency = simple_get_frequency,
- .get_bandwidth = simple_get_bandwidth,
- .get_status = simple_get_status,
- .get_rf_strength = simple_get_rf_strength,
-};
-
-struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
- struct i2c_adapter *i2c_adap,
- u8 i2c_addr,
- unsigned int type)
-{
- struct tuner_simple_priv *priv = NULL;
- int instance;
-
- if (type >= tuner_count) {
- printk(KERN_WARNING "%s: invalid tuner type: %d (max: %d)\n",
- __func__, type, tuner_count-1);
- return NULL;
- }
-
- /* If i2c_adap is set, check that the tuner is at the correct address.
- * Otherwise, if i2c_adap is NULL, the tuner will be programmed directly
- * by the digital demod via calc_regs.
- */
- if (i2c_adap != NULL) {
- u8 b[1];
- struct i2c_msg msg = {
- .addr = i2c_addr, .flags = I2C_M_RD,
- .buf = b, .len = 1,
- };
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
-
- if (1 != i2c_transfer(i2c_adap, &msg, 1))
- tuner_warn("unable to probe %s, proceeding anyway.",
- tuners[type].name);
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 0);
- }
-
- mutex_lock(&tuner_simple_list_mutex);
-
- instance = hybrid_tuner_request_state(struct tuner_simple_priv, priv,
- hybrid_tuner_instance_list,
- i2c_adap, i2c_addr,
- "tuner-simple");
- switch (instance) {
- case 0:
- mutex_unlock(&tuner_simple_list_mutex);
- return NULL;
- break;
- case 1:
- fe->tuner_priv = priv;
-
- priv->type = type;
- priv->tun = &tuners[type];
- priv->nr = simple_devcount++;
- break;
- default:
- fe->tuner_priv = priv;
-#if 0
- /* caller didn't pass in a configuration last time
- * use current configuration, instead */
- if (!priv->tun) {
- priv->type = type;
- priv->tun = &tuners[type];
- }
-#endif
- break;
- }
-
- mutex_unlock(&tuner_simple_list_mutex);
-
- memcpy(&fe->ops.tuner_ops, &simple_tuner_ops,
- sizeof(struct dvb_tuner_ops));
-
- tuner_info("type set to %d (%s)\n", type, priv->tun->name);
-
- if ((debug) || ((atv_input[priv->nr] > 0) ||
- (dtv_input[priv->nr] > 0))) {
- if (0 == atv_input[priv->nr])
- tuner_info("tuner %d atv rf input will be "
- "autoselected\n", priv->nr);
- else
- tuner_info("tuner %d atv rf input will be "
- "set to input %d (insmod option)\n",
- priv->nr, atv_input[priv->nr]);
- if (0 == dtv_input[priv->nr])
- tuner_info("tuner %d dtv rf input will be "
- "autoselected\n", priv->nr);
- else
- tuner_info("tuner %d dtv rf input will be "
- "set to input %d (insmod option)\n",
- priv->nr, dtv_input[priv->nr]);
- }
-
- strlcpy(fe->ops.tuner_ops.info.name, priv->tun->name,
- sizeof(fe->ops.tuner_ops.info.name));
-
- return fe;
-}
-EXPORT_SYMBOL_GPL(simple_tuner_attach);
-
-MODULE_DESCRIPTION("Simple 4-control-bytes style tuner driver");
-MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
-MODULE_LICENSE("GPL");
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/linux/drivers/media/video/tuner-simple.h b/linux/drivers/media/video/tuner-simple.h
deleted file mode 100644
index e46cf0121..000000000
--- a/linux/drivers/media/video/tuner-simple.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- 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.
-*/
-
-#ifndef __TUNER_SIMPLE_H__
-#define __TUNER_SIMPLE_H__
-
-#include <linux/i2c.h>
-#include "dvb_frontend.h"
-
-#if defined(CONFIG_TUNER_SIMPLE) || (defined(CONFIG_TUNER_SIMPLE_MODULE) && defined(MODULE))
-extern struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
- struct i2c_adapter *i2c_adap,
- u8 i2c_addr,
- unsigned int type);
-#else
-static inline struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
- struct i2c_adapter *i2c_adap,
- u8 i2c_addr,
- unsigned int type)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return NULL;
-}
-#endif
-
-#endif /* __TUNER_SIMPLE_H__ */
diff --git a/linux/drivers/media/video/tuner-types.c b/linux/drivers/media/video/tuner-types.c
deleted file mode 100644
index b3f0f62e0..000000000
--- a/linux/drivers/media/video/tuner-types.c
+++ /dev/null
@@ -1,1653 +0,0 @@
-/*
- *
- * i2c tv tuner chip device type database.
- *
- */
-
-#include <linux/i2c.h>
-#include <media/tuner.h>
-#include <media/tuner-types.h>
-#include "compat.h"
-
-/* ---------------------------------------------------------------------- */
-
-/*
- * The floats in the tuner struct are computed at compile time
- * by gcc and cast back to integers. Thus we don't violate the
- * "no float in kernel" rule.
- *
- * A tuner_range may be referenced by multiple tuner_params structs.
- * There are many duplicates in here. Reusing tuner_range structs,
- * rather than defining new ones for each tuner, will cut down on
- * memory usage, and is preferred when possible.
- *
- * Each tuner_params array may contain one or more elements, one
- * for each video standard.
- *
- * FIXME: tuner_params struct contains an element, tda988x. We must
- * set this for all tuners that contain a tda988x chip, and then we
- * can remove this setting from the various card structs.
- *
- * FIXME: Right now, all tuners are using the first tuner_params[]
- * array element for analog mode. In the future, we will be merging
- * similar tuner definitions together, such that each tuner definition
- * will have a tuner_params struct for each available video standard.
- * At that point, the tuner_params[] array element will be chosen
- * based on the video standard in use.
- */
-
-/* The following was taken from dvb-pll.c: */
-
-/* Set AGC TOP value to 103 dBuV:
- * 0x80 = Control Byte
- * 0x40 = 250 uA charge pump (irrelevant)
- * 0x18 = Aux Byte to follow
- * 0x06 = 64.5 kHz divider (irrelevant)
- * 0x01 = Disable Vt (aka sleep)
- *
- * 0x00 = AGC Time constant 2s Iagc = 300 nA (vs 0x80 = 9 nA)
- * 0x50 = AGC Take over point = 103 dBuV
- */
-static u8 tua603x_agc103[] = { 2, 0x80|0x40|0x18|0x06|0x01, 0x00|0x50 };
-
-/* 0x04 = 166.67 kHz divider
- *
- * 0x80 = AGC Time constant 50ms Iagc = 9 uA
- * 0x20 = AGC Take over point = 112 dBuV
- */
-static u8 tua603x_agc112[] = { 2, 0x80|0x40|0x18|0x04|0x01, 0x80|0x20 };
-
-/* 0-9 */
-/* ------------ TUNER_TEMIC_PAL - TEMIC PAL ------------ */
-
-static struct tuner_range tuner_temic_pal_ranges[] = {
- { 16 * 140.25 /*MHz*/, 0x8e, 0x02, },
- { 16 * 463.25 /*MHz*/, 0x8e, 0x04, },
- { 16 * 999.99 , 0x8e, 0x01, },
-};
-
-static struct tuner_params tuner_temic_pal_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_temic_pal_ranges,
- .count = ARRAY_SIZE(tuner_temic_pal_ranges),
- },
-};
-
-/* ------------ TUNER_PHILIPS_PAL_I - Philips PAL_I ------------ */
-
-static struct tuner_range tuner_philips_pal_i_ranges[] = {
- { 16 * 140.25 /*MHz*/, 0x8e, 0xa0, },
- { 16 * 463.25 /*MHz*/, 0x8e, 0x90, },
- { 16 * 999.99 , 0x8e, 0x30, },
-};
-
-static struct tuner_params tuner_philips_pal_i_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_philips_pal_i_ranges,
- .count = ARRAY_SIZE(tuner_philips_pal_i_ranges),
- },
-};
-
-/* ------------ TUNER_PHILIPS_NTSC - Philips NTSC ------------ */
-
-static struct tuner_range tuner_philips_ntsc_ranges[] = {
- { 16 * 157.25 /*MHz*/, 0x8e, 0xa0, },
- { 16 * 451.25 /*MHz*/, 0x8e, 0x90, },
- { 16 * 999.99 , 0x8e, 0x30, },
-};
-
-static struct tuner_params tuner_philips_ntsc_params[] = {
- {
- .type = TUNER_PARAM_TYPE_NTSC,
- .ranges = tuner_philips_ntsc_ranges,
- .count = ARRAY_SIZE(tuner_philips_ntsc_ranges),
- .cb_first_if_lower_freq = 1,
- },
-};
-
-/* ------------ TUNER_PHILIPS_SECAM - Philips SECAM ------------ */
-
-static struct tuner_range tuner_philips_secam_ranges[] = {
- { 16 * 168.25 /*MHz*/, 0x8e, 0xa7, },
- { 16 * 447.25 /*MHz*/, 0x8e, 0x97, },
- { 16 * 999.99 , 0x8e, 0x37, },
-};
-
-static struct tuner_params tuner_philips_secam_params[] = {
- {
- .type = TUNER_PARAM_TYPE_SECAM,
- .ranges = tuner_philips_secam_ranges,
- .count = ARRAY_SIZE(tuner_philips_secam_ranges),
- .cb_first_if_lower_freq = 1,
- },
-};
-
-/* ------------ TUNER_PHILIPS_PAL - Philips PAL ------------ */
-
-static struct tuner_range tuner_philips_pal_ranges[] = {
- { 16 * 168.25 /*MHz*/, 0x8e, 0xa0, },
- { 16 * 447.25 /*MHz*/, 0x8e, 0x90, },
- { 16 * 999.99 , 0x8e, 0x30, },
-};
-
-static struct tuner_params tuner_philips_pal_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_philips_pal_ranges,
- .count = ARRAY_SIZE(tuner_philips_pal_ranges),
- .cb_first_if_lower_freq = 1,
- },
-};
-
-/* ------------ TUNER_TEMIC_NTSC - TEMIC NTSC ------------ */
-
-static struct tuner_range tuner_temic_ntsc_ranges[] = {
- { 16 * 157.25 /*MHz*/, 0x8e, 0x02, },
- { 16 * 463.25 /*MHz*/, 0x8e, 0x04, },
- { 16 * 999.99 , 0x8e, 0x01, },
-};
-
-static struct tuner_params tuner_temic_ntsc_params[] = {
- {
- .type = TUNER_PARAM_TYPE_NTSC,
- .ranges = tuner_temic_ntsc_ranges,
- .count = ARRAY_SIZE(tuner_temic_ntsc_ranges),
- },
-};
-
-/* ------------ TUNER_TEMIC_PAL_I - TEMIC PAL_I ------------ */
-
-static struct tuner_range tuner_temic_pal_i_ranges[] = {
- { 16 * 170.00 /*MHz*/, 0x8e, 0x02, },
- { 16 * 450.00 /*MHz*/, 0x8e, 0x04, },
- { 16 * 999.99 , 0x8e, 0x01, },
-};
-
-static struct tuner_params tuner_temic_pal_i_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_temic_pal_i_ranges,
- .count = ARRAY_SIZE(tuner_temic_pal_i_ranges),
- },
-};
-
-/* ------------ TUNER_TEMIC_4036FY5_NTSC - TEMIC NTSC ------------ */
-
-static struct tuner_range tuner_temic_4036fy5_ntsc_ranges[] = {
- { 16 * 157.25 /*MHz*/, 0x8e, 0xa0, },
- { 16 * 463.25 /*MHz*/, 0x8e, 0x90, },
- { 16 * 999.99 , 0x8e, 0x30, },
-};
-
-static struct tuner_params tuner_temic_4036fy5_ntsc_params[] = {
- {
- .type = TUNER_PARAM_TYPE_NTSC,
- .ranges = tuner_temic_4036fy5_ntsc_ranges,
- .count = ARRAY_SIZE(tuner_temic_4036fy5_ntsc_ranges),
- },
-};
-
-/* ------------ TUNER_ALPS_TSBH1_NTSC - TEMIC NTSC ------------ */
-
-static struct tuner_range tuner_alps_tsb_1_ranges[] = {
- { 16 * 137.25 /*MHz*/, 0x8e, 0x01, },
- { 16 * 385.25 /*MHz*/, 0x8e, 0x02, },
- { 16 * 999.99 , 0x8e, 0x08, },
-};
-
-static struct tuner_params tuner_alps_tsbh1_ntsc_params[] = {
- {
- .type = TUNER_PARAM_TYPE_NTSC,
- .ranges = tuner_alps_tsb_1_ranges,
- .count = ARRAY_SIZE(tuner_alps_tsb_1_ranges),
- },
-};
-
-/* 10-19 */
-/* ------------ TUNER_ALPS_TSBE1_PAL - TEMIC PAL ------------ */
-
-static struct tuner_params tuner_alps_tsb_1_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_alps_tsb_1_ranges,
- .count = ARRAY_SIZE(tuner_alps_tsb_1_ranges),
- },
-};
-
-/* ------------ TUNER_ALPS_TSBB5_PAL_I - Alps PAL_I ------------ */
-
-static struct tuner_range tuner_alps_tsb_5_pal_ranges[] = {
- { 16 * 133.25 /*MHz*/, 0x8e, 0x01, },
- { 16 * 351.25 /*MHz*/, 0x8e, 0x02, },
- { 16 * 999.99 , 0x8e, 0x08, },
-};
-
-static struct tuner_params tuner_alps_tsbb5_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_alps_tsb_5_pal_ranges,
- .count = ARRAY_SIZE(tuner_alps_tsb_5_pal_ranges),
- },
-};
-
-/* ------------ TUNER_ALPS_TSBE5_PAL - Alps PAL ------------ */
-
-static struct tuner_params tuner_alps_tsbe5_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_alps_tsb_5_pal_ranges,
- .count = ARRAY_SIZE(tuner_alps_tsb_5_pal_ranges),
- },
-};
-
-/* ------------ TUNER_ALPS_TSBC5_PAL - Alps PAL ------------ */
-
-static struct tuner_params tuner_alps_tsbc5_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_alps_tsb_5_pal_ranges,
- .count = ARRAY_SIZE(tuner_alps_tsb_5_pal_ranges),
- },
-};
-
-/* ------------ TUNER_TEMIC_4006FH5_PAL - TEMIC PAL ------------ */
-
-static struct tuner_range tuner_lg_pal_ranges[] = {
- { 16 * 170.00 /*MHz*/, 0x8e, 0xa0, },
- { 16 * 450.00 /*MHz*/, 0x8e, 0x90, },
- { 16 * 999.99 , 0x8e, 0x30, },
-};
-
-static struct tuner_params tuner_temic_4006fh5_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_lg_pal_ranges,
- .count = ARRAY_SIZE(tuner_lg_pal_ranges),
- },
-};
-
-/* ------------ TUNER_ALPS_TSHC6_NTSC - Alps NTSC ------------ */
-
-static struct tuner_range tuner_alps_tshc6_ntsc_ranges[] = {
- { 16 * 137.25 /*MHz*/, 0x8e, 0x14, },
- { 16 * 385.25 /*MHz*/, 0x8e, 0x12, },
- { 16 * 999.99 , 0x8e, 0x11, },
-};
-
-static struct tuner_params tuner_alps_tshc6_params[] = {
- {
- .type = TUNER_PARAM_TYPE_NTSC,
- .ranges = tuner_alps_tshc6_ntsc_ranges,
- .count = ARRAY_SIZE(tuner_alps_tshc6_ntsc_ranges),
- },
-};
-
-/* ------------ TUNER_TEMIC_PAL_DK - TEMIC PAL ------------ */
-
-static struct tuner_range tuner_temic_pal_dk_ranges[] = {
- { 16 * 168.25 /*MHz*/, 0x8e, 0xa0, },
- { 16 * 456.25 /*MHz*/, 0x8e, 0x90, },
- { 16 * 999.99 , 0x8e, 0x30, },
-};
-
-static struct tuner_params tuner_temic_pal_dk_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_temic_pal_dk_ranges,
- .count = ARRAY_SIZE(tuner_temic_pal_dk_ranges),
- },
-};
-
-/* ------------ TUNER_PHILIPS_NTSC_M - Philips NTSC ------------ */
-
-static struct tuner_range tuner_philips_ntsc_m_ranges[] = {
- { 16 * 160.00 /*MHz*/, 0x8e, 0xa0, },
- { 16 * 454.00 /*MHz*/, 0x8e, 0x90, },
- { 16 * 999.99 , 0x8e, 0x30, },
-};
-
-static struct tuner_params tuner_philips_ntsc_m_params[] = {
- {
- .type = TUNER_PARAM_TYPE_NTSC,
- .ranges = tuner_philips_ntsc_m_ranges,
- .count = ARRAY_SIZE(tuner_philips_ntsc_m_ranges),
- },
-};
-
-/* ------------ TUNER_TEMIC_4066FY5_PAL_I - TEMIC PAL_I ------------ */
-
-static struct tuner_range tuner_temic_40x6f_5_pal_ranges[] = {
- { 16 * 169.00 /*MHz*/, 0x8e, 0xa0, },
- { 16 * 454.00 /*MHz*/, 0x8e, 0x90, },
- { 16 * 999.99 , 0x8e, 0x30, },
-};
-
-static struct tuner_params tuner_temic_4066fy5_pal_i_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_temic_40x6f_5_pal_ranges,
- .count = ARRAY_SIZE(tuner_temic_40x6f_5_pal_ranges),
- },
-};
-
-/* ------------ TUNER_TEMIC_4006FN5_MULTI_PAL - TEMIC PAL ------------ */
-
-static struct tuner_params tuner_temic_4006fn5_multi_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_temic_40x6f_5_pal_ranges,
- .count = ARRAY_SIZE(tuner_temic_40x6f_5_pal_ranges),
- },
-};
-
-/* 20-29 */
-/* ------------ TUNER_TEMIC_4009FR5_PAL - TEMIC PAL ------------ */
-
-static struct tuner_range tuner_temic_4009f_5_pal_ranges[] = {
- { 16 * 141.00 /*MHz*/, 0x8e, 0xa0, },
- { 16 * 464.00 /*MHz*/, 0x8e, 0x90, },
- { 16 * 999.99 , 0x8e, 0x30, },
-};
-
-static struct tuner_params tuner_temic_4009f_5_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_temic_4009f_5_pal_ranges,
- .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges),
- },
-};
-
-/* ------------ TUNER_TEMIC_4039FR5_NTSC - TEMIC NTSC ------------ */
-
-static struct tuner_range tuner_temic_4x3x_f_5_ntsc_ranges[] = {
- { 16 * 158.00 /*MHz*/, 0x8e, 0xa0, },
- { 16 * 453.00 /*MHz*/, 0x8e, 0x90, },
- { 16 * 999.99 , 0x8e, 0x30, },
-};
-
-static struct tuner_params tuner_temic_4039fr5_params[] = {
- {
- .type = TUNER_PARAM_TYPE_NTSC,
- .ranges = tuner_temic_4x3x_f_5_ntsc_ranges,
- .count = ARRAY_SIZE(tuner_temic_4x3x_f_5_ntsc_ranges),
- },
-};
-
-/* ------------ TUNER_TEMIC_4046FM5 - TEMIC PAL ------------ */
-
-static struct tuner_params tuner_temic_4046fm5_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_temic_40x6f_5_pal_ranges,
- .count = ARRAY_SIZE(tuner_temic_40x6f_5_pal_ranges),
- },
-};
-
-/* ------------ TUNER_PHILIPS_PAL_DK - Philips PAL ------------ */
-
-static struct tuner_params tuner_philips_pal_dk_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_lg_pal_ranges,
- .count = ARRAY_SIZE(tuner_lg_pal_ranges),
- },
-};
-
-/* ------------ TUNER_PHILIPS_FQ1216ME - Philips PAL ------------ */
-
-static struct tuner_params tuner_philips_fq1216me_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_lg_pal_ranges,
- .count = ARRAY_SIZE(tuner_lg_pal_ranges),
- .has_tda9887 = 1,
- .port1_active = 1,
- .port2_active = 1,
- .port2_invert_for_secam_lc = 1,
- },
-};
-
-/* ------------ TUNER_LG_PAL_I_FM - LGINNOTEK PAL_I ------------ */
-
-static struct tuner_params tuner_lg_pal_i_fm_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_lg_pal_ranges,
- .count = ARRAY_SIZE(tuner_lg_pal_ranges),
- },
-};
-
-/* ------------ TUNER_LG_PAL_I - LGINNOTEK PAL_I ------------ */
-
-static struct tuner_params tuner_lg_pal_i_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_lg_pal_ranges,
- .count = ARRAY_SIZE(tuner_lg_pal_ranges),
- },
-};
-
-/* ------------ TUNER_LG_NTSC_FM - LGINNOTEK NTSC ------------ */
-
-static struct tuner_range tuner_lg_ntsc_fm_ranges[] = {
- { 16 * 210.00 /*MHz*/, 0x8e, 0xa0, },
- { 16 * 497.00 /*MHz*/, 0x8e, 0x90, },
- { 16 * 999.99 , 0x8e, 0x30, },
-};
-
-static struct tuner_params tuner_lg_ntsc_fm_params[] = {
- {
- .type = TUNER_PARAM_TYPE_NTSC,
- .ranges = tuner_lg_ntsc_fm_ranges,
- .count = ARRAY_SIZE(tuner_lg_ntsc_fm_ranges),
- },
-};
-
-/* ------------ TUNER_LG_PAL_FM - LGINNOTEK PAL ------------ */
-
-static struct tuner_params tuner_lg_pal_fm_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_lg_pal_ranges,
- .count = ARRAY_SIZE(tuner_lg_pal_ranges),
- },
-};
-
-/* ------------ TUNER_LG_PAL - LGINNOTEK PAL ------------ */
-
-static struct tuner_params tuner_lg_pal_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_lg_pal_ranges,
- .count = ARRAY_SIZE(tuner_lg_pal_ranges),
- },
-};
-
-/* 30-39 */
-/* ------------ TUNER_TEMIC_4009FN5_MULTI_PAL_FM - TEMIC PAL ------------ */
-
-static struct tuner_params tuner_temic_4009_fn5_multi_pal_fm_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_temic_4009f_5_pal_ranges,
- .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges),
- },
-};
-
-/* ------------ TUNER_SHARP_2U5JF5540_NTSC - SHARP NTSC ------------ */
-
-static struct tuner_range tuner_sharp_2u5jf5540_ntsc_ranges[] = {
- { 16 * 137.25 /*MHz*/, 0x8e, 0x01, },
- { 16 * 317.25 /*MHz*/, 0x8e, 0x02, },
- { 16 * 999.99 , 0x8e, 0x08, },
-};
-
-static struct tuner_params tuner_sharp_2u5jf5540_params[] = {
- {
- .type = TUNER_PARAM_TYPE_NTSC,
- .ranges = tuner_sharp_2u5jf5540_ntsc_ranges,
- .count = ARRAY_SIZE(tuner_sharp_2u5jf5540_ntsc_ranges),
- },
-};
-
-/* ------------ TUNER_Samsung_PAL_TCPM9091PD27 - Samsung PAL ------------ */
-
-static struct tuner_range tuner_samsung_pal_tcpm9091pd27_ranges[] = {
- { 16 * 169 /*MHz*/, 0x8e, 0xa0, },
- { 16 * 464 /*MHz*/, 0x8e, 0x90, },
- { 16 * 999.99 , 0x8e, 0x30, },
-};
-
-static struct tuner_params tuner_samsung_pal_tcpm9091pd27_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_samsung_pal_tcpm9091pd27_ranges,
- .count = ARRAY_SIZE(tuner_samsung_pal_tcpm9091pd27_ranges),
- },
-};
-
-/* ------------ TUNER_TEMIC_4106FH5 - TEMIC PAL ------------ */
-
-static struct tuner_params tuner_temic_4106fh5_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_temic_4009f_5_pal_ranges,
- .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges),
- },
-};
-
-/* ------------ TUNER_TEMIC_4012FY5 - TEMIC PAL ------------ */
-
-static struct tuner_params tuner_temic_4012fy5_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_temic_pal_ranges,
- .count = ARRAY_SIZE(tuner_temic_pal_ranges),
- },
-};
-
-/* ------------ TUNER_TEMIC_4136FY5 - TEMIC NTSC ------------ */
-
-static struct tuner_params tuner_temic_4136_fy5_params[] = {
- {
- .type = TUNER_PARAM_TYPE_NTSC,
- .ranges = tuner_temic_4x3x_f_5_ntsc_ranges,
- .count = ARRAY_SIZE(tuner_temic_4x3x_f_5_ntsc_ranges),
- },
-};
-
-/* ------------ TUNER_LG_PAL_NEW_TAPC - LGINNOTEK PAL ------------ */
-
-static struct tuner_range tuner_lg_new_tapc_ranges[] = {
- { 16 * 170.00 /*MHz*/, 0x8e, 0x01, },
- { 16 * 450.00 /*MHz*/, 0x8e, 0x02, },
- { 16 * 999.99 , 0x8e, 0x08, },
-};
-
-static struct tuner_params tuner_lg_pal_new_tapc_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_lg_new_tapc_ranges,
- .count = ARRAY_SIZE(tuner_lg_new_tapc_ranges),
- },
-};
-
-/* ------------ TUNER_PHILIPS_FM1216ME_MK3 - Philips PAL ------------ */
-
-static struct tuner_range tuner_fm1216me_mk3_pal_ranges[] = {
- { 16 * 158.00 /*MHz*/, 0x8e, 0x01, },
- { 16 * 442.00 /*MHz*/, 0x8e, 0x02, },
- { 16 * 999.99 , 0x8e, 0x04, },
-};
-
-static struct tuner_params tuner_fm1216me_mk3_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_fm1216me_mk3_pal_ranges,
- .count = ARRAY_SIZE(tuner_fm1216me_mk3_pal_ranges),
- .cb_first_if_lower_freq = 1,
- .has_tda9887 = 1,
- .port1_active = 1,
- .port2_active = 1,
- .port2_invert_for_secam_lc = 1,
- .port1_fm_high_sensitivity = 1,
- .default_top_mid = -2,
- .default_top_secam_mid = -2,
- .default_top_secam_high = -2,
- },
-};
-
-/* ------------ TUNER_LG_NTSC_NEW_TAPC - LGINNOTEK NTSC ------------ */
-
-static struct tuner_params tuner_lg_ntsc_new_tapc_params[] = {
- {
- .type = TUNER_PARAM_TYPE_NTSC,
- .ranges = tuner_lg_new_tapc_ranges,
- .count = ARRAY_SIZE(tuner_lg_new_tapc_ranges),
- },
-};
-
-/* 40-49 */
-/* ------------ TUNER_HITACHI_NTSC - HITACHI NTSC ------------ */
-
-static struct tuner_params tuner_hitachi_ntsc_params[] = {
- {
- .type = TUNER_PARAM_TYPE_NTSC,
- .ranges = tuner_lg_new_tapc_ranges,
- .count = ARRAY_SIZE(tuner_lg_new_tapc_ranges),
- },
-};
-
-/* ------------ TUNER_PHILIPS_PAL_MK - Philips PAL ------------ */
-
-static struct tuner_range tuner_philips_pal_mk_pal_ranges[] = {
- { 16 * 140.25 /*MHz*/, 0x8e, 0x01, },
- { 16 * 463.25 /*MHz*/, 0x8e, 0xc2, },
- { 16 * 999.99 , 0x8e, 0xcf, },
-};
-
-static struct tuner_params tuner_philips_pal_mk_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_philips_pal_mk_pal_ranges,
- .count = ARRAY_SIZE(tuner_philips_pal_mk_pal_ranges),
- },
-};
-
-/* ---- TUNER_PHILIPS_FCV1236D - Philips FCV1236D (ATSC/NTSC) ---- */
-
-static struct tuner_range tuner_philips_fcv1236d_ntsc_ranges[] = {
- { 16 * 157.25 /*MHz*/, 0x8e, 0xa2, },
- { 16 * 451.25 /*MHz*/, 0x8e, 0x92, },
- { 16 * 999.99 , 0x8e, 0x32, },
-};
-
-static struct tuner_range tuner_philips_fcv1236d_atsc_ranges[] = {
- { 16 * 159.00 /*MHz*/, 0x8e, 0xa0, },
- { 16 * 453.00 /*MHz*/, 0x8e, 0x90, },
- { 16 * 999.99 , 0x8e, 0x30, },
-};
-
-static struct tuner_params tuner_philips_fcv1236d_params[] = {
- {
- .type = TUNER_PARAM_TYPE_NTSC,
- .ranges = tuner_philips_fcv1236d_ntsc_ranges,
- .count = ARRAY_SIZE(tuner_philips_fcv1236d_ntsc_ranges),
- },
- {
- .type = TUNER_PARAM_TYPE_DIGITAL,
- .ranges = tuner_philips_fcv1236d_atsc_ranges,
- .count = ARRAY_SIZE(tuner_philips_fcv1236d_atsc_ranges),
- .iffreq = 16 * 44.00,
- },
-};
-
-/* ------------ TUNER_PHILIPS_FM1236_MK3 - Philips NTSC ------------ */
-
-static struct tuner_range tuner_fm1236_mk3_ntsc_ranges[] = {
- { 16 * 160.00 /*MHz*/, 0x8e, 0x01, },
- { 16 * 442.00 /*MHz*/, 0x8e, 0x02, },
- { 16 * 999.99 , 0x8e, 0x04, },
-};
-
-static struct tuner_params tuner_fm1236_mk3_params[] = {
- {
- .type = TUNER_PARAM_TYPE_NTSC,
- .ranges = tuner_fm1236_mk3_ntsc_ranges,
- .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges),
- .cb_first_if_lower_freq = 1,
- .has_tda9887 = 1,
- .port1_active = 1,
- .port2_active = 1,
- .port1_fm_high_sensitivity = 1,
- },
-};
-
-/* ------------ TUNER_PHILIPS_4IN1 - Philips NTSC ------------ */
-
-static struct tuner_params tuner_philips_4in1_params[] = {
- {
- .type = TUNER_PARAM_TYPE_NTSC,
- .ranges = tuner_fm1236_mk3_ntsc_ranges,
- .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges),
- },
-};
-
-/* ------------ TUNER_MICROTUNE_4049FM5 - Microtune PAL ------------ */
-
-static struct tuner_params tuner_microtune_4049_fm5_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_temic_4009f_5_pal_ranges,
- .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges),
- .has_tda9887 = 1,
- .port1_invert_for_secam_lc = 1,
- .default_pll_gating_18 = 1,
- .fm_gain_normal=1,
- .radio_if = 1, /* 33.3 MHz */
- },
-};
-
-/* ------------ TUNER_PANASONIC_VP27 - Panasonic NTSC ------------ */
-
-static struct tuner_range tuner_panasonic_vp27_ntsc_ranges[] = {
- { 16 * 160.00 /*MHz*/, 0xce, 0x01, },
- { 16 * 454.00 /*MHz*/, 0xce, 0x02, },
- { 16 * 999.99 , 0xce, 0x08, },
-};
-
-static struct tuner_params tuner_panasonic_vp27_params[] = {
- {
- .type = TUNER_PARAM_TYPE_NTSC,
- .ranges = tuner_panasonic_vp27_ntsc_ranges,
- .count = ARRAY_SIZE(tuner_panasonic_vp27_ntsc_ranges),
- .has_tda9887 = 1,
- .intercarrier_mode = 1,
- .default_top_low = -3,
- .default_top_mid = -3,
- .default_top_high = -3,
- },
-};
-
-/* ------------ TUNER_TNF_8831BGFF - Philips PAL ------------ */
-
-static struct tuner_range tuner_tnf_8831bgff_pal_ranges[] = {
- { 16 * 161.25 /*MHz*/, 0x8e, 0xa0, },
- { 16 * 463.25 /*MHz*/, 0x8e, 0x90, },
- { 16 * 999.99 , 0x8e, 0x30, },
-};
-
-static struct tuner_params tuner_tnf_8831bgff_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_tnf_8831bgff_pal_ranges,
- .count = ARRAY_SIZE(tuner_tnf_8831bgff_pal_ranges),
- },
-};
-
-/* ------------ TUNER_MICROTUNE_4042FI5 - Microtune NTSC ------------ */
-
-static struct tuner_range tuner_microtune_4042fi5_ntsc_ranges[] = {
- { 16 * 162.00 /*MHz*/, 0x8e, 0xa2, },
- { 16 * 457.00 /*MHz*/, 0x8e, 0x94, },
- { 16 * 999.99 , 0x8e, 0x31, },
-};
-
-static struct tuner_range tuner_microtune_4042fi5_atsc_ranges[] = {
- { 16 * 162.00 /*MHz*/, 0x8e, 0xa1, },
- { 16 * 457.00 /*MHz*/, 0x8e, 0x91, },
- { 16 * 999.99 , 0x8e, 0x31, },
-};
-
-static struct tuner_params tuner_microtune_4042fi5_params[] = {
- {
- .type = TUNER_PARAM_TYPE_NTSC,
- .ranges = tuner_microtune_4042fi5_ntsc_ranges,
- .count = ARRAY_SIZE(tuner_microtune_4042fi5_ntsc_ranges),
- },
- {
- .type = TUNER_PARAM_TYPE_DIGITAL,
- .ranges = tuner_microtune_4042fi5_atsc_ranges,
- .count = ARRAY_SIZE(tuner_microtune_4042fi5_atsc_ranges),
- .iffreq = 16 * 44.00 /*MHz*/,
- },
-};
-
-/* 50-59 */
-/* ------------ TUNER_TCL_2002N - TCL NTSC ------------ */
-
-static struct tuner_range tuner_tcl_2002n_ntsc_ranges[] = {
- { 16 * 172.00 /*MHz*/, 0x8e, 0x01, },
- { 16 * 448.00 /*MHz*/, 0x8e, 0x02, },
- { 16 * 999.99 , 0x8e, 0x08, },
-};
-
-static struct tuner_params tuner_tcl_2002n_params[] = {
- {
- .type = TUNER_PARAM_TYPE_NTSC,
- .ranges = tuner_tcl_2002n_ntsc_ranges,
- .count = ARRAY_SIZE(tuner_tcl_2002n_ntsc_ranges),
- .cb_first_if_lower_freq = 1,
- },
-};
-
-/* ------------ TUNER_PHILIPS_FM1256_IH3 - Philips PAL ------------ */
-
-static struct tuner_params tuner_philips_fm1256_ih3_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_fm1236_mk3_ntsc_ranges,
- .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges),
- .radio_if = 1, /* 33.3 MHz */
- },
-};
-
-/* ------------ TUNER_THOMSON_DTT7610 - THOMSON ATSC ------------ */
-
-/* single range used for both ntsc and atsc */
-static struct tuner_range tuner_thomson_dtt7610_ntsc_ranges[] = {
- { 16 * 157.25 /*MHz*/, 0x8e, 0x39, },
- { 16 * 454.00 /*MHz*/, 0x8e, 0x3a, },
- { 16 * 999.99 , 0x8e, 0x3c, },
-};
-
-static struct tuner_params tuner_thomson_dtt7610_params[] = {
- {
- .type = TUNER_PARAM_TYPE_NTSC,
- .ranges = tuner_thomson_dtt7610_ntsc_ranges,
- .count = ARRAY_SIZE(tuner_thomson_dtt7610_ntsc_ranges),
- },
- {
- .type = TUNER_PARAM_TYPE_DIGITAL,
- .ranges = tuner_thomson_dtt7610_ntsc_ranges,
- .count = ARRAY_SIZE(tuner_thomson_dtt7610_ntsc_ranges),
- .iffreq = 16 * 44.00 /*MHz*/,
- },
-};
-
-/* ------------ TUNER_PHILIPS_FQ1286 - Philips NTSC ------------ */
-
-static struct tuner_range tuner_philips_fq1286_ntsc_ranges[] = {
- { 16 * 160.00 /*MHz*/, 0x8e, 0x41, },
- { 16 * 454.00 /*MHz*/, 0x8e, 0x42, },
- { 16 * 999.99 , 0x8e, 0x04, },
-};
-
-static struct tuner_params tuner_philips_fq1286_params[] = {
- {
- .type = TUNER_PARAM_TYPE_NTSC,
- .ranges = tuner_philips_fq1286_ntsc_ranges,
- .count = ARRAY_SIZE(tuner_philips_fq1286_ntsc_ranges),
- },
-};
-
-/* ------------ TUNER_TCL_2002MB - TCL PAL ------------ */
-
-static struct tuner_range tuner_tcl_2002mb_pal_ranges[] = {
- { 16 * 170.00 /*MHz*/, 0xce, 0x01, },
- { 16 * 450.00 /*MHz*/, 0xce, 0x02, },
- { 16 * 999.99 , 0xce, 0x08, },
-};
-
-static struct tuner_params tuner_tcl_2002mb_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_tcl_2002mb_pal_ranges,
- .count = ARRAY_SIZE(tuner_tcl_2002mb_pal_ranges),
- },
-};
-
-/* ------------ TUNER_PHILIPS_FQ1216AME_MK4 - Philips PAL ------------ */
-
-static struct tuner_range tuner_philips_fq12_6a___mk4_pal_ranges[] = {
- { 16 * 160.00 /*MHz*/, 0xce, 0x01, },
- { 16 * 442.00 /*MHz*/, 0xce, 0x02, },
- { 16 * 999.99 , 0xce, 0x04, },
-};
-
-static struct tuner_params tuner_philips_fq1216ame_mk4_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_philips_fq12_6a___mk4_pal_ranges,
- .count = ARRAY_SIZE(tuner_philips_fq12_6a___mk4_pal_ranges),
- .has_tda9887 = 1,
- .port1_active = 1,
- .port2_invert_for_secam_lc = 1,
- .default_top_mid = -2,
- .default_top_secam_low = -2,
- .default_top_secam_mid = -2,
- .default_top_secam_high = -2,
- },
-};
-
-/* ------------ TUNER_PHILIPS_FQ1236A_MK4 - Philips NTSC ------------ */
-
-static struct tuner_params tuner_philips_fq1236a_mk4_params[] = {
- {
- .type = TUNER_PARAM_TYPE_NTSC,
- .ranges = tuner_fm1236_mk3_ntsc_ranges,
- .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges),
- },
-};
-
-/* ------------ TUNER_YMEC_TVF_8531MF - Philips NTSC ------------ */
-
-static struct tuner_params tuner_ymec_tvf_8531mf_params[] = {
- {
- .type = TUNER_PARAM_TYPE_NTSC,
- .ranges = tuner_philips_ntsc_m_ranges,
- .count = ARRAY_SIZE(tuner_philips_ntsc_m_ranges),
- },
-};
-
-/* ------------ TUNER_YMEC_TVF_5533MF - Philips NTSC ------------ */
-
-static struct tuner_range tuner_ymec_tvf_5533mf_ntsc_ranges[] = {
- { 16 * 160.00 /*MHz*/, 0x8e, 0x01, },
- { 16 * 454.00 /*MHz*/, 0x8e, 0x02, },
- { 16 * 999.99 , 0x8e, 0x04, },
-};
-
-static struct tuner_params tuner_ymec_tvf_5533mf_params[] = {
- {
- .type = TUNER_PARAM_TYPE_NTSC,
- .ranges = tuner_ymec_tvf_5533mf_ntsc_ranges,
- .count = ARRAY_SIZE(tuner_ymec_tvf_5533mf_ntsc_ranges),
- },
-};
-
-/* 60-69 */
-/* ------------ TUNER_THOMSON_DTT761X - THOMSON ATSC ------------ */
-/* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */
-
-static struct tuner_range tuner_thomson_dtt761x_ntsc_ranges[] = {
- { 16 * 145.25 /*MHz*/, 0x8e, 0x39, },
- { 16 * 415.25 /*MHz*/, 0x8e, 0x3a, },
- { 16 * 999.99 , 0x8e, 0x3c, },
-};
-
-static struct tuner_range tuner_thomson_dtt761x_atsc_ranges[] = {
- { 16 * 147.00 /*MHz*/, 0x8e, 0x39, },
- { 16 * 417.00 /*MHz*/, 0x8e, 0x3a, },
- { 16 * 999.99 , 0x8e, 0x3c, },
-};
-
-static struct tuner_params tuner_thomson_dtt761x_params[] = {
- {
- .type = TUNER_PARAM_TYPE_NTSC,
- .ranges = tuner_thomson_dtt761x_ntsc_ranges,
- .count = ARRAY_SIZE(tuner_thomson_dtt761x_ntsc_ranges),
- .has_tda9887 = 1,
- .fm_gain_normal = 1,
- .radio_if = 2, /* 41.3 MHz */
- },
- {
- .type = TUNER_PARAM_TYPE_DIGITAL,
- .ranges = tuner_thomson_dtt761x_atsc_ranges,
- .count = ARRAY_SIZE(tuner_thomson_dtt761x_atsc_ranges),
- .iffreq = 16 * 44.00, /*MHz*/
- },
-};
-
-/* ------------ TUNER_TENA_9533_DI - Philips PAL ------------ */
-
-static struct tuner_range tuner_tena_9533_di_pal_ranges[] = {
- { 16 * 160.25 /*MHz*/, 0x8e, 0x01, },
- { 16 * 464.25 /*MHz*/, 0x8e, 0x02, },
- { 16 * 999.99 , 0x8e, 0x04, },
-};
-
-static struct tuner_params tuner_tena_9533_di_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_tena_9533_di_pal_ranges,
- .count = ARRAY_SIZE(tuner_tena_9533_di_pal_ranges),
- },
-};
-
-/* ------------ TUNER_PHILIPS_FMD1216ME_MK3 - Philips PAL ------------ */
-
-static struct tuner_range tuner_philips_fmd1216me_mk3_pal_ranges[] = {
- { 16 * 160.00 /*MHz*/, 0x86, 0x51, },
- { 16 * 442.00 /*MHz*/, 0x86, 0x52, },
- { 16 * 999.99 , 0x86, 0x54, },
-};
-
-static struct tuner_range tuner_philips_fmd1216me_mk3_dvb_ranges[] = {
- { 16 * 143.87 /*MHz*/, 0xbc, 0x41 },
- { 16 * 158.87 /*MHz*/, 0xf4, 0x41 },
- { 16 * 329.87 /*MHz*/, 0xbc, 0x42 },
- { 16 * 441.87 /*MHz*/, 0xf4, 0x42 },
- { 16 * 625.87 /*MHz*/, 0xbc, 0x44 },
- { 16 * 803.87 /*MHz*/, 0xf4, 0x44 },
- { 16 * 999.99 , 0xfc, 0x44 },
-};
-
-static struct tuner_params tuner_philips_fmd1216me_mk3_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_philips_fmd1216me_mk3_pal_ranges,
- .count = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_pal_ranges),
- .has_tda9887 = 1,
- .port1_active = 1,
- .port2_active = 1,
- .port2_fm_high_sensitivity = 1,
- .port2_invert_for_secam_lc = 1,
- .port1_set_for_fm_mono = 1,
- },
- {
- .type = TUNER_PARAM_TYPE_DIGITAL,
- .ranges = tuner_philips_fmd1216me_mk3_dvb_ranges,
- .count = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_dvb_ranges),
- .iffreq = 16 * 36.125, /*MHz*/
- },
-};
-
-
-/* ------ TUNER_LG_TDVS_H06XF - LG INNOTEK / INFINEON ATSC ----- */
-
-static struct tuner_range tuner_tua6034_ntsc_ranges[] = {
- { 16 * 165.00 /*MHz*/, 0x8e, 0x01 },
- { 16 * 450.00 /*MHz*/, 0x8e, 0x02 },
- { 16 * 999.99 , 0x8e, 0x04 },
-};
-
-static struct tuner_range tuner_tua6034_atsc_ranges[] = {
- { 16 * 165.00 /*MHz*/, 0xce, 0x01 },
- { 16 * 450.00 /*MHz*/, 0xce, 0x02 },
- { 16 * 999.99 , 0xce, 0x04 },
-};
-
-static struct tuner_params tuner_lg_tdvs_h06xf_params[] = {
- {
- .type = TUNER_PARAM_TYPE_NTSC,
- .ranges = tuner_tua6034_ntsc_ranges,
- .count = ARRAY_SIZE(tuner_tua6034_ntsc_ranges),
- },
- {
- .type = TUNER_PARAM_TYPE_DIGITAL,
- .ranges = tuner_tua6034_atsc_ranges,
- .count = ARRAY_SIZE(tuner_tua6034_atsc_ranges),
- .iffreq = 16 * 44.00,
- },
-};
-
-/* ------------ TUNER_YMEC_TVF66T5_B_DFF - Philips PAL ------------ */
-
-static struct tuner_range tuner_ymec_tvf66t5_b_dff_pal_ranges[] = {
- { 16 * 160.25 /*MHz*/, 0x8e, 0x01, },
- { 16 * 464.25 /*MHz*/, 0x8e, 0x02, },
- { 16 * 999.99 , 0x8e, 0x08, },
-};
-
-static struct tuner_params tuner_ymec_tvf66t5_b_dff_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_ymec_tvf66t5_b_dff_pal_ranges,
- .count = ARRAY_SIZE(tuner_ymec_tvf66t5_b_dff_pal_ranges),
- },
-};
-
-/* ------------ TUNER_LG_NTSC_TALN_MINI - LGINNOTEK NTSC ------------ */
-
-static struct tuner_range tuner_lg_taln_ntsc_ranges[] = {
- { 16 * 137.25 /*MHz*/, 0x8e, 0x01, },
- { 16 * 373.25 /*MHz*/, 0x8e, 0x02, },
- { 16 * 999.99 , 0x8e, 0x08, },
-};
-
-static struct tuner_range tuner_lg_taln_pal_secam_ranges[] = {
- { 16 * 150.00 /*MHz*/, 0x8e, 0x01, },
- { 16 * 425.00 /*MHz*/, 0x8e, 0x02, },
- { 16 * 999.99 , 0x8e, 0x08, },
-};
-
-static struct tuner_params tuner_lg_taln_params[] = {
- {
- .type = TUNER_PARAM_TYPE_NTSC,
- .ranges = tuner_lg_taln_ntsc_ranges,
- .count = ARRAY_SIZE(tuner_lg_taln_ntsc_ranges),
- },{
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_lg_taln_pal_secam_ranges,
- .count = ARRAY_SIZE(tuner_lg_taln_pal_secam_ranges),
- },
-};
-
-/* ------------ TUNER_PHILIPS_TD1316 - Philips PAL ------------ */
-
-static struct tuner_range tuner_philips_td1316_pal_ranges[] = {
- { 16 * 160.00 /*MHz*/, 0xc8, 0xa1, },
- { 16 * 442.00 /*MHz*/, 0xc8, 0xa2, },
- { 16 * 999.99 , 0xc8, 0xa4, },
-};
-
-static struct tuner_range tuner_philips_td1316_dvb_ranges[] = {
- { 16 * 93.834 /*MHz*/, 0xca, 0x60, },
- { 16 * 123.834 /*MHz*/, 0xca, 0xa0, },
- { 16 * 163.834 /*MHz*/, 0xca, 0xc0, },
- { 16 * 253.834 /*MHz*/, 0xca, 0x60, },
- { 16 * 383.834 /*MHz*/, 0xca, 0xa0, },
- { 16 * 443.834 /*MHz*/, 0xca, 0xc0, },
- { 16 * 583.834 /*MHz*/, 0xca, 0x60, },
- { 16 * 793.834 /*MHz*/, 0xca, 0xa0, },
- { 16 * 999.999 , 0xca, 0xe0, },
-};
-
-static struct tuner_params tuner_philips_td1316_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_philips_td1316_pal_ranges,
- .count = ARRAY_SIZE(tuner_philips_td1316_pal_ranges),
- },
- {
- .type = TUNER_PARAM_TYPE_DIGITAL,
- .ranges = tuner_philips_td1316_dvb_ranges,
- .count = ARRAY_SIZE(tuner_philips_td1316_dvb_ranges),
- .iffreq = 16 * 36.166667 /*MHz*/,
- },
-};
-
-/* ------------ TUNER_PHILIPS_TUV1236D - Philips ATSC ------------ */
-
-static struct tuner_range tuner_tuv1236d_ntsc_ranges[] = {
- { 16 * 157.25 /*MHz*/, 0xce, 0x01, },
- { 16 * 454.00 /*MHz*/, 0xce, 0x02, },
- { 16 * 999.99 , 0xce, 0x04, },
-};
-
-static struct tuner_range tuner_tuv1236d_atsc_ranges[] = {
- { 16 * 157.25 /*MHz*/, 0xc6, 0x41, },
- { 16 * 454.00 /*MHz*/, 0xc6, 0x42, },
- { 16 * 999.99 , 0xc6, 0x44, },
-};
-
-static struct tuner_params tuner_tuv1236d_params[] = {
- {
- .type = TUNER_PARAM_TYPE_NTSC,
- .ranges = tuner_tuv1236d_ntsc_ranges,
- .count = ARRAY_SIZE(tuner_tuv1236d_ntsc_ranges),
- },
- {
- .type = TUNER_PARAM_TYPE_DIGITAL,
- .ranges = tuner_tuv1236d_atsc_ranges,
- .count = ARRAY_SIZE(tuner_tuv1236d_atsc_ranges),
- .iffreq = 16 * 44.00,
- },
-};
-
-/* ------------ TUNER_TNF_xxx5 - Texas Instruments--------- */
-/* This is known to work with Tenna TVF58t5-MFF and TVF5835 MFF
- * but it is expected to work also with other Tenna/Ymec
- * models based on TI SN 761677 chip on both PAL and NTSC
- */
-
-static struct tuner_range tuner_tnf_5335_d_if_pal_ranges[] = {
- { 16 * 168.25 /*MHz*/, 0x8e, 0x01, },
- { 16 * 471.25 /*MHz*/, 0x8e, 0x02, },
- { 16 * 999.99 , 0x8e, 0x08, },
-};
-
-static struct tuner_range tuner_tnf_5335mf_ntsc_ranges[] = {
- { 16 * 169.25 /*MHz*/, 0x8e, 0x01, },
- { 16 * 469.25 /*MHz*/, 0x8e, 0x02, },
- { 16 * 999.99 , 0x8e, 0x08, },
-};
-
-static struct tuner_params tuner_tnf_5335mf_params[] = {
- {
- .type = TUNER_PARAM_TYPE_NTSC,
- .ranges = tuner_tnf_5335mf_ntsc_ranges,
- .count = ARRAY_SIZE(tuner_tnf_5335mf_ntsc_ranges),
- },
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_tnf_5335_d_if_pal_ranges,
- .count = ARRAY_SIZE(tuner_tnf_5335_d_if_pal_ranges),
- },
-};
-
-/* 70-79 */
-/* ------------ TUNER_SAMSUNG_TCPN_2121P30A - Samsung NTSC ------------ */
-
-/* '+ 4' turns on the Low Noise Amplifier */
-static struct tuner_range tuner_samsung_tcpn_2121p30a_ntsc_ranges[] = {
- { 16 * 130.00 /*MHz*/, 0xce, 0x01 + 4, },
- { 16 * 364.50 /*MHz*/, 0xce, 0x02 + 4, },
- { 16 * 999.99 , 0xce, 0x08 + 4, },
-};
-
-static struct tuner_params tuner_samsung_tcpn_2121p30a_params[] = {
- {
- .type = TUNER_PARAM_TYPE_NTSC,
- .ranges = tuner_samsung_tcpn_2121p30a_ntsc_ranges,
- .count = ARRAY_SIZE(tuner_samsung_tcpn_2121p30a_ntsc_ranges),
- },
-};
-
-/* ------------ TUNER_THOMSON_FE6600 - DViCO Hybrid PAL ------------ */
-
-static struct tuner_range tuner_thomson_fe6600_pal_ranges[] = {
- { 16 * 160.00 /*MHz*/, 0xfe, 0x11, },
- { 16 * 442.00 /*MHz*/, 0xf6, 0x12, },
- { 16 * 999.99 , 0xf6, 0x18, },
-};
-
-static struct tuner_range tuner_thomson_fe6600_dvb_ranges[] = {
- { 16 * 250.00 /*MHz*/, 0xb4, 0x12, },
- { 16 * 455.00 /*MHz*/, 0xfe, 0x11, },
- { 16 * 775.50 /*MHz*/, 0xbc, 0x18, },
- { 16 * 999.99 , 0xf4, 0x18, },
-};
-
-static struct tuner_params tuner_thomson_fe6600_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_thomson_fe6600_pal_ranges,
- .count = ARRAY_SIZE(tuner_thomson_fe6600_pal_ranges),
- },
- {
- .type = TUNER_PARAM_TYPE_DIGITAL,
- .ranges = tuner_thomson_fe6600_dvb_ranges,
- .count = ARRAY_SIZE(tuner_thomson_fe6600_dvb_ranges),
- .iffreq = 16 * 36.125 /*MHz*/,
- },
-};
-
-/* ------------ TUNER_SAMSUNG_TCPG_6121P30A - Samsung PAL ------------ */
-
-/* '+ 4' turns on the Low Noise Amplifier */
-static struct tuner_range tuner_samsung_tcpg_6121p30a_pal_ranges[] = {
- { 16 * 146.25 /*MHz*/, 0xce, 0x01 + 4, },
- { 16 * 428.50 /*MHz*/, 0xce, 0x02 + 4, },
- { 16 * 999.99 , 0xce, 0x08 + 4, },
-};
-
-static struct tuner_params tuner_samsung_tcpg_6121p30a_params[] = {
- {
- .type = TUNER_PARAM_TYPE_PAL,
- .ranges = tuner_samsung_tcpg_6121p30a_pal_ranges,
- .count = ARRAY_SIZE(tuner_samsung_tcpg_6121p30a_pal_ranges),
- .has_tda9887 = 1,
- .port1_active = 1,
- .port2_active = 1,
- .port2_invert_for_secam_lc = 1,
- },
-};
-
-/* --------------------------------------------------------------------- */
-
-struct tunertype tuners[] = {
- /* 0-9 */
- [TUNER_TEMIC_PAL] = { /* TEMIC PAL */
- .name = "Temic PAL (4002 FH5)",
- .params = tuner_temic_pal_params,
- .count = ARRAY_SIZE(tuner_temic_pal_params),
- },
- [TUNER_PHILIPS_PAL_I] = { /* Philips PAL_I */
- .name = "Philips PAL_I (FI1246 and compatibles)",
- .params = tuner_philips_pal_i_params,
- .count = ARRAY_SIZE(tuner_philips_pal_i_params),
- },
- [TUNER_PHILIPS_NTSC] = { /* Philips NTSC */
- .name = "Philips NTSC (FI1236,FM1236 and compatibles)",
- .params = tuner_philips_ntsc_params,
- .count = ARRAY_SIZE(tuner_philips_ntsc_params),
- },
- [TUNER_PHILIPS_SECAM] = { /* Philips SECAM */
- .name = "Philips (SECAM+PAL_BG) (FI1216MF, FM1216MF, FR1216MF)",
- .params = tuner_philips_secam_params,
- .count = ARRAY_SIZE(tuner_philips_secam_params),
- },
- [TUNER_ABSENT] = { /* Tuner Absent */
- .name = "NoTuner",
- },
- [TUNER_PHILIPS_PAL] = { /* Philips PAL */
- .name = "Philips PAL_BG (FI1216 and compatibles)",
- .params = tuner_philips_pal_params,
- .count = ARRAY_SIZE(tuner_philips_pal_params),
- },
- [TUNER_TEMIC_NTSC] = { /* TEMIC NTSC */
- .name = "Temic NTSC (4032 FY5)",
- .params = tuner_temic_ntsc_params,
- .count = ARRAY_SIZE(tuner_temic_ntsc_params),
- },
- [TUNER_TEMIC_PAL_I] = { /* TEMIC PAL_I */
- .name = "Temic PAL_I (4062 FY5)",
- .params = tuner_temic_pal_i_params,
- .count = ARRAY_SIZE(tuner_temic_pal_i_params),
- },
- [TUNER_TEMIC_4036FY5_NTSC] = { /* TEMIC NTSC */
- .name = "Temic NTSC (4036 FY5)",
- .params = tuner_temic_4036fy5_ntsc_params,
- .count = ARRAY_SIZE(tuner_temic_4036fy5_ntsc_params),
- },
- [TUNER_ALPS_TSBH1_NTSC] = { /* TEMIC NTSC */
- .name = "Alps HSBH1",
- .params = tuner_alps_tsbh1_ntsc_params,
- .count = ARRAY_SIZE(tuner_alps_tsbh1_ntsc_params),
- },
-
- /* 10-19 */
- [TUNER_ALPS_TSBE1_PAL] = { /* TEMIC PAL */
- .name = "Alps TSBE1",
- .params = tuner_alps_tsb_1_params,
- .count = ARRAY_SIZE(tuner_alps_tsb_1_params),
- },
- [TUNER_ALPS_TSBB5_PAL_I] = { /* Alps PAL_I */
- .name = "Alps TSBB5",
- .params = tuner_alps_tsbb5_params,
- .count = ARRAY_SIZE(tuner_alps_tsbb5_params),
- },
- [TUNER_ALPS_TSBE5_PAL] = { /* Alps PAL */
- .name = "Alps TSBE5",
- .params = tuner_alps_tsbe5_params,
- .count = ARRAY_SIZE(tuner_alps_tsbe5_params),
- },
- [TUNER_ALPS_TSBC5_PAL] = { /* Alps PAL */
- .name = "Alps TSBC5",
- .params = tuner_alps_tsbc5_params,
- .count = ARRAY_SIZE(tuner_alps_tsbc5_params),
- },
- [TUNER_TEMIC_4006FH5_PAL] = { /* TEMIC PAL */
- .name = "Temic PAL_BG (4006FH5)",
- .params = tuner_temic_4006fh5_params,
- .count = ARRAY_SIZE(tuner_temic_4006fh5_params),
- },
- [TUNER_ALPS_TSHC6_NTSC] = { /* Alps NTSC */
- .name = "Alps TSCH6",
- .params = tuner_alps_tshc6_params,
- .count = ARRAY_SIZE(tuner_alps_tshc6_params),
- },
- [TUNER_TEMIC_PAL_DK] = { /* TEMIC PAL */
- .name = "Temic PAL_DK (4016 FY5)",
- .params = tuner_temic_pal_dk_params,
- .count = ARRAY_SIZE(tuner_temic_pal_dk_params),
- },
- [TUNER_PHILIPS_NTSC_M] = { /* Philips NTSC */
- .name = "Philips NTSC_M (MK2)",
- .params = tuner_philips_ntsc_m_params,
- .count = ARRAY_SIZE(tuner_philips_ntsc_m_params),
- },
- [TUNER_TEMIC_4066FY5_PAL_I] = { /* TEMIC PAL_I */
- .name = "Temic PAL_I (4066 FY5)",
- .params = tuner_temic_4066fy5_pal_i_params,
- .count = ARRAY_SIZE(tuner_temic_4066fy5_pal_i_params),
- },
- [TUNER_TEMIC_4006FN5_MULTI_PAL] = { /* TEMIC PAL */
- .name = "Temic PAL* auto (4006 FN5)",
- .params = tuner_temic_4006fn5_multi_params,
- .count = ARRAY_SIZE(tuner_temic_4006fn5_multi_params),
- },
-
- /* 20-29 */
- [TUNER_TEMIC_4009FR5_PAL] = { /* TEMIC PAL */
- .name = "Temic PAL_BG (4009 FR5) or PAL_I (4069 FR5)",
- .params = tuner_temic_4009f_5_params,
- .count = ARRAY_SIZE(tuner_temic_4009f_5_params),
- },
- [TUNER_TEMIC_4039FR5_NTSC] = { /* TEMIC NTSC */
- .name = "Temic NTSC (4039 FR5)",
- .params = tuner_temic_4039fr5_params,
- .count = ARRAY_SIZE(tuner_temic_4039fr5_params),
- },
- [TUNER_TEMIC_4046FM5] = { /* TEMIC PAL */
- .name = "Temic PAL/SECAM multi (4046 FM5)",
- .params = tuner_temic_4046fm5_params,
- .count = ARRAY_SIZE(tuner_temic_4046fm5_params),
- },
- [TUNER_PHILIPS_PAL_DK] = { /* Philips PAL */
- .name = "Philips PAL_DK (FI1256 and compatibles)",
- .params = tuner_philips_pal_dk_params,
- .count = ARRAY_SIZE(tuner_philips_pal_dk_params),
- },
- [TUNER_PHILIPS_FQ1216ME] = { /* Philips PAL */
- .name = "Philips PAL/SECAM multi (FQ1216ME)",
- .params = tuner_philips_fq1216me_params,
- .count = ARRAY_SIZE(tuner_philips_fq1216me_params),
- },
- [TUNER_LG_PAL_I_FM] = { /* LGINNOTEK PAL_I */
- .name = "LG PAL_I+FM (TAPC-I001D)",
- .params = tuner_lg_pal_i_fm_params,
- .count = ARRAY_SIZE(tuner_lg_pal_i_fm_params),
- },
- [TUNER_LG_PAL_I] = { /* LGINNOTEK PAL_I */
- .name = "LG PAL_I (TAPC-I701D)",
- .params = tuner_lg_pal_i_params,
- .count = ARRAY_SIZE(tuner_lg_pal_i_params),
- },
- [TUNER_LG_NTSC_FM] = { /* LGINNOTEK NTSC */
- .name = "LG NTSC+FM (TPI8NSR01F)",
- .params = tuner_lg_ntsc_fm_params,
- .count = ARRAY_SIZE(tuner_lg_ntsc_fm_params),
- },
- [TUNER_LG_PAL_FM] = { /* LGINNOTEK PAL */
- .name = "LG PAL_BG+FM (TPI8PSB01D)",
- .params = tuner_lg_pal_fm_params,
- .count = ARRAY_SIZE(tuner_lg_pal_fm_params),
- },
- [TUNER_LG_PAL] = { /* LGINNOTEK PAL */
- .name = "LG PAL_BG (TPI8PSB11D)",
- .params = tuner_lg_pal_params,
- .count = ARRAY_SIZE(tuner_lg_pal_params),
- },
-
- /* 30-39 */
- [TUNER_TEMIC_4009FN5_MULTI_PAL_FM] = { /* TEMIC PAL */
- .name = "Temic PAL* auto + FM (4009 FN5)",
- .params = tuner_temic_4009_fn5_multi_pal_fm_params,
- .count = ARRAY_SIZE(tuner_temic_4009_fn5_multi_pal_fm_params),
- },
- [TUNER_SHARP_2U5JF5540_NTSC] = { /* SHARP NTSC */
- .name = "SHARP NTSC_JP (2U5JF5540)",
- .params = tuner_sharp_2u5jf5540_params,
- .count = ARRAY_SIZE(tuner_sharp_2u5jf5540_params),
- },
- [TUNER_Samsung_PAL_TCPM9091PD27] = { /* Samsung PAL */
- .name = "Samsung PAL TCPM9091PD27",
- .params = tuner_samsung_pal_tcpm9091pd27_params,
- .count = ARRAY_SIZE(tuner_samsung_pal_tcpm9091pd27_params),
- },
- [TUNER_MT2032] = { /* Microtune PAL|NTSC */
- .name = "MT20xx universal",
- /* see mt20xx.c for details */ },
- [TUNER_TEMIC_4106FH5] = { /* TEMIC PAL */
- .name = "Temic PAL_BG (4106 FH5)",
- .params = tuner_temic_4106fh5_params,
- .count = ARRAY_SIZE(tuner_temic_4106fh5_params),
- },
- [TUNER_TEMIC_4012FY5] = { /* TEMIC PAL */
- .name = "Temic PAL_DK/SECAM_L (4012 FY5)",
- .params = tuner_temic_4012fy5_params,
- .count = ARRAY_SIZE(tuner_temic_4012fy5_params),
- },
- [TUNER_TEMIC_4136FY5] = { /* TEMIC NTSC */
- .name = "Temic NTSC (4136 FY5)",
- .params = tuner_temic_4136_fy5_params,
- .count = ARRAY_SIZE(tuner_temic_4136_fy5_params),
- },
- [TUNER_LG_PAL_NEW_TAPC] = { /* LGINNOTEK PAL */
- .name = "LG PAL (newer TAPC series)",
- .params = tuner_lg_pal_new_tapc_params,
- .count = ARRAY_SIZE(tuner_lg_pal_new_tapc_params),
- },
- [TUNER_PHILIPS_FM1216ME_MK3] = { /* Philips PAL */
- .name = "Philips PAL/SECAM multi (FM1216ME MK3)",
- .params = tuner_fm1216me_mk3_params,
- .count = ARRAY_SIZE(tuner_fm1216me_mk3_params),
- },
- [TUNER_LG_NTSC_NEW_TAPC] = { /* LGINNOTEK NTSC */
- .name = "LG NTSC (newer TAPC series)",
- .params = tuner_lg_ntsc_new_tapc_params,
- .count = ARRAY_SIZE(tuner_lg_ntsc_new_tapc_params),
- },
-
- /* 40-49 */
- [TUNER_HITACHI_NTSC] = { /* HITACHI NTSC */
- .name = "HITACHI V7-J180AT",
- .params = tuner_hitachi_ntsc_params,
- .count = ARRAY_SIZE(tuner_hitachi_ntsc_params),
- },
- [TUNER_PHILIPS_PAL_MK] = { /* Philips PAL */
- .name = "Philips PAL_MK (FI1216 MK)",
- .params = tuner_philips_pal_mk_params,
- .count = ARRAY_SIZE(tuner_philips_pal_mk_params),
- },
- [TUNER_PHILIPS_FCV1236D] = { /* Philips ATSC */
- .name = "Philips FCV1236D ATSC/NTSC dual in",
- .params = tuner_philips_fcv1236d_params,
- .count = ARRAY_SIZE(tuner_philips_fcv1236d_params),
- .min = 16 * 53.00,
- .max = 16 * 803.00,
- .stepsize = 62500,
- },
- [TUNER_PHILIPS_FM1236_MK3] = { /* Philips NTSC */
- .name = "Philips NTSC MK3 (FM1236MK3 or FM1236/F)",
- .params = tuner_fm1236_mk3_params,
- .count = ARRAY_SIZE(tuner_fm1236_mk3_params),
- },
- [TUNER_PHILIPS_4IN1] = { /* Philips NTSC */
- .name = "Philips 4 in 1 (ATI TV Wonder Pro/Conexant)",
- .params = tuner_philips_4in1_params,
- .count = ARRAY_SIZE(tuner_philips_4in1_params),
- },
- [TUNER_MICROTUNE_4049FM5] = { /* Microtune PAL */
- .name = "Microtune 4049 FM5",
- .params = tuner_microtune_4049_fm5_params,
- .count = ARRAY_SIZE(tuner_microtune_4049_fm5_params),
- },
- [TUNER_PANASONIC_VP27] = { /* Panasonic NTSC */
- .name = "Panasonic VP27s/ENGE4324D",
- .params = tuner_panasonic_vp27_params,
- .count = ARRAY_SIZE(tuner_panasonic_vp27_params),
- },
- [TUNER_LG_NTSC_TAPE] = { /* LGINNOTEK NTSC */
- .name = "LG NTSC (TAPE series)",
- .params = tuner_fm1236_mk3_params,
- .count = ARRAY_SIZE(tuner_fm1236_mk3_params),
- },
- [TUNER_TNF_8831BGFF] = { /* Philips PAL */
- .name = "Tenna TNF 8831 BGFF)",
- .params = tuner_tnf_8831bgff_params,
- .count = ARRAY_SIZE(tuner_tnf_8831bgff_params),
- },
- [TUNER_MICROTUNE_4042FI5] = { /* Microtune NTSC */
- .name = "Microtune 4042 FI5 ATSC/NTSC dual in",
- .params = tuner_microtune_4042fi5_params,
- .count = ARRAY_SIZE(tuner_microtune_4042fi5_params),
- .min = 16 * 57.00,
- .max = 16 * 858.00,
- .stepsize = 62500,
- },
-
- /* 50-59 */
- [TUNER_TCL_2002N] = { /* TCL NTSC */
- .name = "TCL 2002N",
- .params = tuner_tcl_2002n_params,
- .count = ARRAY_SIZE(tuner_tcl_2002n_params),
- },
- [TUNER_PHILIPS_FM1256_IH3] = { /* Philips PAL */
- .name = "Philips PAL/SECAM_D (FM 1256 I-H3)",
- .params = tuner_philips_fm1256_ih3_params,
- .count = ARRAY_SIZE(tuner_philips_fm1256_ih3_params),
- },
- [TUNER_THOMSON_DTT7610] = { /* THOMSON ATSC */
- .name = "Thomson DTT 7610 (ATSC/NTSC)",
- .params = tuner_thomson_dtt7610_params,
- .count = ARRAY_SIZE(tuner_thomson_dtt7610_params),
- .min = 16 * 44.00,
- .max = 16 * 958.00,
- .stepsize = 62500,
- },
- [TUNER_PHILIPS_FQ1286] = { /* Philips NTSC */
- .name = "Philips FQ1286",
- .params = tuner_philips_fq1286_params,
- .count = ARRAY_SIZE(tuner_philips_fq1286_params),
- },
- [TUNER_PHILIPS_TDA8290] = { /* Philips PAL|NTSC */
- .name = "Philips/NXP TDA 8290/8295 + 8275/8275A/18271",
- /* see tda8290.c for details */ },
- [TUNER_TCL_2002MB] = { /* TCL PAL */
- .name = "TCL 2002MB",
- .params = tuner_tcl_2002mb_params,
- .count = ARRAY_SIZE(tuner_tcl_2002mb_params),
- },
- [TUNER_PHILIPS_FQ1216AME_MK4] = { /* Philips PAL */
- .name = "Philips PAL/SECAM multi (FQ1216AME MK4)",
- .params = tuner_philips_fq1216ame_mk4_params,
- .count = ARRAY_SIZE(tuner_philips_fq1216ame_mk4_params),
- },
- [TUNER_PHILIPS_FQ1236A_MK4] = { /* Philips NTSC */
- .name = "Philips FQ1236A MK4",
- .params = tuner_philips_fq1236a_mk4_params,
- .count = ARRAY_SIZE(tuner_philips_fq1236a_mk4_params),
- },
- [TUNER_YMEC_TVF_8531MF] = { /* Philips NTSC */
- .name = "Ymec TVision TVF-8531MF/8831MF/8731MF",
- .params = tuner_ymec_tvf_8531mf_params,
- .count = ARRAY_SIZE(tuner_ymec_tvf_8531mf_params),
- },
- [TUNER_YMEC_TVF_5533MF] = { /* Philips NTSC */
- .name = "Ymec TVision TVF-5533MF",
- .params = tuner_ymec_tvf_5533mf_params,
- .count = ARRAY_SIZE(tuner_ymec_tvf_5533mf_params),
- },
-
- /* 60-69 */
- [TUNER_THOMSON_DTT761X] = { /* THOMSON ATSC */
- /* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */
- .name = "Thomson DTT 761X (ATSC/NTSC)",
- .params = tuner_thomson_dtt761x_params,
- .count = ARRAY_SIZE(tuner_thomson_dtt761x_params),
- .min = 16 * 57.00,
- .max = 16 * 863.00,
- .stepsize = 62500,
- .initdata = tua603x_agc103,
- },
- [TUNER_TENA_9533_DI] = { /* Philips PAL */
- .name = "Tena TNF9533-D/IF/TNF9533-B/DF",
- .params = tuner_tena_9533_di_params,
- .count = ARRAY_SIZE(tuner_tena_9533_di_params),
- },
- [TUNER_TEA5767] = { /* Philips RADIO */
- .name = "Philips TEA5767HN FM Radio",
- /* see tea5767.c for details */
- },
- [TUNER_PHILIPS_FMD1216ME_MK3] = { /* Philips PAL */
- .name = "Philips FMD1216ME MK3 Hybrid Tuner",
- .params = tuner_philips_fmd1216me_mk3_params,
- .count = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_params),
- .min = 16 * 50.87,
- .max = 16 * 858.00,
- .stepsize = 166667,
- .initdata = tua603x_agc112,
- .sleepdata = (u8[]){ 4, 0x9c, 0x60, 0x85, 0x54 },
- },
- [TUNER_LG_TDVS_H06XF] = { /* LGINNOTEK ATSC */
- .name = "LG TDVS-H06xF", /* H061F, H062F & H064F */
- .params = tuner_lg_tdvs_h06xf_params,
- .count = ARRAY_SIZE(tuner_lg_tdvs_h06xf_params),
- .min = 16 * 54.00,
- .max = 16 * 863.00,
- .stepsize = 62500,
- .initdata = tua603x_agc103,
- },
- [TUNER_YMEC_TVF66T5_B_DFF] = { /* Philips PAL */
- .name = "Ymec TVF66T5-B/DFF",
- .params = tuner_ymec_tvf66t5_b_dff_params,
- .count = ARRAY_SIZE(tuner_ymec_tvf66t5_b_dff_params),
- },
- [TUNER_LG_TALN] = { /* LGINNOTEK NTSC / PAL / SECAM */
- .name = "LG TALN series",
- .params = tuner_lg_taln_params,
- .count = ARRAY_SIZE(tuner_lg_taln_params),
- },
- [TUNER_PHILIPS_TD1316] = { /* Philips PAL */
- .name = "Philips TD1316 Hybrid Tuner",
- .params = tuner_philips_td1316_params,
- .count = ARRAY_SIZE(tuner_philips_td1316_params),
- .min = 16 * 87.00,
- .max = 16 * 895.00,
- .stepsize = 166667,
- },
- [TUNER_PHILIPS_TUV1236D] = { /* Philips ATSC */
- .name = "Philips TUV1236D ATSC/NTSC dual in",
- .params = tuner_tuv1236d_params,
- .count = ARRAY_SIZE(tuner_tuv1236d_params),
- .min = 16 * 54.00,
- .max = 16 * 864.00,
- .stepsize = 62500,
- },
- [TUNER_TNF_5335MF] = { /* Tenna PAL/NTSC */
- .name = "Tena TNF 5335 and similar models",
- .params = tuner_tnf_5335mf_params,
- .count = ARRAY_SIZE(tuner_tnf_5335mf_params),
- },
-
- /* 70-79 */
- [TUNER_SAMSUNG_TCPN_2121P30A] = { /* Samsung NTSC */
- .name = "Samsung TCPN 2121P30A",
- .params = tuner_samsung_tcpn_2121p30a_params,
- .count = ARRAY_SIZE(tuner_samsung_tcpn_2121p30a_params),
- },
- [TUNER_XC2028] = { /* Xceive 2028 */
- .name = "Xceive xc2028/xc3028 tuner",
- /* see tuner-xc2028.c for details */
- },
- [TUNER_THOMSON_FE6600] = { /* Thomson PAL / DVB-T */
- .name = "Thomson FE6600",
- .params = tuner_thomson_fe6600_params,
- .count = ARRAY_SIZE(tuner_thomson_fe6600_params),
- .min = 16 * 44.25,
- .max = 16 * 858.00,
- .stepsize = 166667,
- },
- [TUNER_SAMSUNG_TCPG_6121P30A] = { /* Samsung PAL */
- .name = "Samsung TCPG 6121P30A",
- .params = tuner_samsung_tcpg_6121p30a_params,
- .count = ARRAY_SIZE(tuner_samsung_tcpg_6121p30a_params),
- },
- [TUNER_TDA9887] = { /* Philips TDA 9887 IF PLL Demodulator.
- This chip is part of some modern tuners */
- .name = "Philips TDA988[5,6,7] IF PLL Demodulator",
- /* see tda9887.c for details */
- },
- [TUNER_TEA5761] = { /* Philips RADIO */
- .name = "Philips TEA5761 FM Radio",
- /* see tea5767.c for details */
- },
- [TUNER_XC5000] = { /* Xceive 5000 */
- .name = "Xceive 5000 tuner",
- /* see xc5000.c for details */
- },
-};
-EXPORT_SYMBOL(tuners);
-
-unsigned const int tuner_count = ARRAY_SIZE(tuners);
-EXPORT_SYMBOL(tuner_count);
-
-MODULE_DESCRIPTION("Simple tuner device type database");
-MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
-MODULE_LICENSE("GPL");
diff --git a/linux/drivers/media/video/tuner-xc2028-types.h b/linux/drivers/media/video/tuner-xc2028-types.h
deleted file mode 100644
index 216665c2c..000000000
--- a/linux/drivers/media/video/tuner-xc2028-types.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/* tuner-xc2028_types
- *
- * This file includes internal tipes to be used inside tuner-xc2028.
- * Shouldn't be included outside tuner-xc2028
- *
- * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab@infradead.org)
- * This code is placed under the terms of the GNU General Public License v2
- */
-
-/* xc3028 firmware types */
-
-/* BASE firmware should be loaded before any other firmware */
-#define BASE (1<<0)
-#define BASE_TYPES (BASE|F8MHZ|MTS|FM|INPUT1|INPUT2|INIT1)
-
-/* F8MHZ marks BASE firmwares for 8 MHz Bandwidth */
-#define F8MHZ (1<<1)
-
-/* Multichannel Television Sound (MTS)
- Those firmwares are capable of using xc2038 DSP to decode audio and
- produce a baseband audio output on some pins of the chip.
- There are MTS firmwares for the most used video standards. It should be
- required to use MTS firmwares, depending on the way audio is routed into
- the bridge chip
- */
-#define MTS (1<<2)
-
-/* FIXME: I have no idea what's the difference between
- D2620 and D2633 firmwares
- */
-#define D2620 (1<<3)
-#define D2633 (1<<4)
-
-/* DTV firmwares for 6, 7 and 8 MHz
- DTV6 - 6MHz - ATSC/DVB-C/DVB-T/ISDB-T/DOCSIS
- DTV8 - 8MHz - DVB-C/DVB-T
- */
-#define DTV6 (1 << 5)
-#define QAM (1 << 6)
-#define DTV7 (1<<7)
-#define DTV78 (1<<8)
-#define DTV8 (1<<9)
-
-#define DTV_TYPES (D2620|D2633|DTV6|QAM|DTV7|DTV78|DTV8|ATSC)
-
-/* There's a FM | BASE firmware + FM specific firmware (std=0) */
-#define FM (1<<10)
-
-#define STD_SPECIFIC_TYPES (MTS|FM|LCD|NOGD)
-
-/* Applies only for FM firmware
- Makes it use RF input 1 (pin #2) instead of input 2 (pin #4)
- */
-#define INPUT1 (1<<11)
-
-
-/* LCD firmwares exist only for MTS STD/MN (PAL or NTSC/M)
- and for non-MTS STD/MN (PAL, NTSC/M or NTSC/Kr)
- There are variants both with and without NOGD
- Those firmwares produce better result with LCD displays
- */
-#define LCD (1<<12)
-
-/* NOGD firmwares exist only for MTS STD/MN (PAL or NTSC/M)
- and for non-MTS STD/MN (PAL, NTSC/M or NTSC/Kr)
- The NOGD firmwares don't have group delay compensation filter
- */
-#define NOGD (1<<13)
-
-/* Old firmwares were broken into init0 and init1 */
-#define INIT1 (1<<14)
-
-/* SCODE firmware selects particular behaviours */
-#define MONO (1 << 15)
-#define ATSC (1 << 16)
-#define IF (1 << 17)
-#define LG60 (1 << 18)
-#define ATI638 (1 << 19)
-#define OREN538 (1 << 20)
-#define OREN36 (1 << 21)
-#define TOYOTA388 (1 << 22)
-#define TOYOTA794 (1 << 23)
-#define DIBCOM52 (1 << 24)
-#define ZARLINK456 (1 << 25)
-#define CHINA (1 << 26)
-#define F6MHZ (1 << 27)
-#define INPUT2 (1 << 28)
-#define SCODE (1 << 29)
-
-/* This flag identifies that the scode table has a new format */
-#define HAS_IF (1 << 30)
-
-#if 0
-/* The current seek algorithm doesn'use those flags. Instead, this is
- currently useful only for debug process, since this is a HINT table
- associating an alias to an IF table that can be used by that digital
- video standard (in the case of DTV6/7/78/8, QAM and ATSC), or to a
- particular demod type
- */
-#define SCODE_TYPES (DTV6|QAM|DTV7|DTV78|DTV8|LCD|NOGD|MONO|ATSC|IF| \
- LG60|ATI638|OREN538|OREN36|TOYOTA388|TOYOTA794| \
- DIBCOM52|ZARLINK456|CHINA|F6MHZ|SCODE)
-#else
-/* There are different scode tables for MTS and non-MTS.
- The MTS firmwares support mono only
- */
-#define SCODE_TYPES (SCODE | MTS)
-#endif
-
-
-/* Newer types not defined on videodev2.h.
- The original idea were to move all those types to videodev2.h, but
- it seemed overkill, since, with the exception of SECAM/K3, the other
- types seem to be autodetected.
- It is not clear where secam/k3 is used, nor we have a feedback of this
- working or being autodetected by the standard secam firmware.
- */
-
-#define V4L2_STD_SECAM_K3 (0x04000000)
-
-/* Audio types */
-
-#define V4L2_STD_A2_A (1LL<<32)
-#define V4L2_STD_A2_B (1LL<<33)
-#define V4L2_STD_NICAM_A (1LL<<34)
-#define V4L2_STD_NICAM_B (1LL<<35)
-#define V4L2_STD_AM (1LL<<36)
-#define V4L2_STD_BTSC (1LL<<37)
-#define V4L2_STD_EIAJ (1LL<<38)
-
-#define V4L2_STD_A2 (V4L2_STD_A2_A | V4L2_STD_A2_B)
-#define V4L2_STD_NICAM (V4L2_STD_NICAM_A | V4L2_STD_NICAM_B)
-
-/* To preserve backward compatibilty,
- (std & V4L2_STD_AUDIO) = 0 means that ALL audio stds are supported
- */
-
-#define V4L2_STD_AUDIO (V4L2_STD_A2 | \
- V4L2_STD_NICAM | \
- V4L2_STD_AM | \
- V4L2_STD_BTSC | \
- V4L2_STD_EIAJ)
-
-/* Used standards with audio restrictions */
-
-#define V4L2_STD_PAL_BG_A2_A (V4L2_STD_PAL_BG | V4L2_STD_A2_A)
-#define V4L2_STD_PAL_BG_A2_B (V4L2_STD_PAL_BG | V4L2_STD_A2_B)
-#define V4L2_STD_PAL_BG_NICAM_A (V4L2_STD_PAL_BG | V4L2_STD_NICAM_A)
-#define V4L2_STD_PAL_BG_NICAM_B (V4L2_STD_PAL_BG | V4L2_STD_NICAM_B)
-#define V4L2_STD_PAL_DK_A2 (V4L2_STD_PAL_DK | V4L2_STD_A2)
-#define V4L2_STD_PAL_DK_NICAM (V4L2_STD_PAL_DK | V4L2_STD_NICAM)
-#define V4L2_STD_SECAM_L_NICAM (V4L2_STD_SECAM_L | V4L2_STD_NICAM)
-#define V4L2_STD_SECAM_L_AM (V4L2_STD_SECAM_L | V4L2_STD_AM)
diff --git a/linux/drivers/media/video/tuner-xc2028.c b/linux/drivers/media/video/tuner-xc2028.c
deleted file mode 100644
index 3aa81ae99..000000000
--- a/linux/drivers/media/video/tuner-xc2028.c
+++ /dev/null
@@ -1,1274 +0,0 @@
-/* tuner-xc2028
- *
- * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab@infradead.org)
- *
- * Copyright (c) 2007 Michel Ludwig (michel.ludwig@gmail.com)
- * - frontend interface
- *
- * This code is placed under the terms of the GNU General Public License v2
- */
-
-#include <linux/i2c.h>
-#include <asm/div64.h>
-#include <linux/firmware.h>
-#include <linux/videodev2.h>
-#include <linux/delay.h>
-#include <media/tuner.h>
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 16)
-#include <linux/mutex.h>
-#else
-#include <asm/semaphore.h>
-#endif
-#include "compat.h"
-#include "tuner-i2c.h"
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
-#include "i2c-compat.h"
-#endif
-#include "tuner-xc2028.h"
-#include "tuner-xc2028-types.h"
-
-#include <linux/dvb/frontend.h>
-#include "dvb_frontend.h"
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
-#define strcasecmp(a, b) strnicmp(a, b, sizeof(a))
-#endif
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "enable verbose debug messages");
-
-static char audio_std[8];
-module_param_string(audio_std, audio_std, sizeof(audio_std), 0);
-MODULE_PARM_DESC(audio_std,
- "Audio standard. XC3028 audio decoder explicitly "
- "needs to know what audio\n"
- "standard is needed for some video standards with audio A2 or NICAM.\n"
- "The valid values are:\n"
- "A2\n"
- "A2/A\n"
- "A2/B\n"
- "NICAM\n"
- "NICAM/A\n"
- "NICAM/B\n");
-
-static char firmware_name[FIRMWARE_NAME_MAX];
-module_param_string(firmware_name, firmware_name, sizeof(firmware_name), 0);
-MODULE_PARM_DESC(firmware_name, "Firmware file name. Allows overriding the "
- "default firmware name\n");
-
-static LIST_HEAD(xc2028_list);
-static DEFINE_MUTEX(xc2028_list_mutex);
-
-/* struct for storing firmware table */
-struct firmware_description {
- unsigned int type;
- v4l2_std_id id;
- __u16 int_freq;
- unsigned char *ptr;
- unsigned int size;
-};
-
-struct firmware_properties {
- unsigned int type;
- v4l2_std_id id;
- v4l2_std_id std_req;
- __u16 int_freq;
- unsigned int scode_table;
- int scode_nr;
-};
-
-struct xc2028_data {
- struct list_head xc2028_list;
- struct tuner_i2c_props i2c_props;
- int (*tuner_callback) (void *dev,
- int command, int arg);
- void *video_dev;
- int count;
- __u32 frequency;
-
- struct firmware_description *firm;
- int firm_size;
- __u16 firm_version;
-
- __u16 hwmodel;
- __u16 hwvers;
-
- struct xc2028_ctrl ctrl;
-
- struct firmware_properties cur_fw;
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 16)
- struct mutex lock;
-#else
- struct semaphore lock;
-#endif
-};
-
-#define i2c_send(priv, buf, size) ({ \
- int _rc; \
- _rc = tuner_i2c_xfer_send(&priv->i2c_props, buf, size); \
- if (size != _rc) \
- tuner_info("i2c output error: rc = %d (should be %d)\n",\
- _rc, (int)size); \
- _rc; \
-})
-
-#define i2c_rcv(priv, buf, size) ({ \
- int _rc; \
- _rc = tuner_i2c_xfer_recv(&priv->i2c_props, buf, size); \
- if (size != _rc) \
- tuner_err("i2c input error: rc = %d (should be %d)\n", \
- _rc, (int)size); \
- _rc; \
-})
-
-#define i2c_send_recv(priv, obuf, osize, ibuf, isize) ({ \
- int _rc; \
- _rc = tuner_i2c_xfer_send_recv(&priv->i2c_props, obuf, osize, \
- ibuf, isize); \
- if (isize != _rc) \
- tuner_err("i2c input error: rc = %d (should be %d)\n", \
- _rc, (int)isize); \
- _rc; \
-})
-
-#define send_seq(priv, data...) ({ \
- static u8 _val[] = data; \
- int _rc; \
- if (sizeof(_val) != \
- (_rc = tuner_i2c_xfer_send(&priv->i2c_props, \
- _val, sizeof(_val)))) { \
- tuner_err("Error on line %d: %d\n", __LINE__, _rc); \
- } else \
- msleep(10); \
- _rc; \
-})
-
-static int xc2028_get_reg(struct xc2028_data *priv, u16 reg, u16 *val)
-{
- unsigned char buf[2];
- unsigned char ibuf[2];
-
- tuner_dbg("%s %04x called\n", __func__, reg);
-
- buf[0] = reg >> 8;
- buf[1] = (unsigned char) reg;
-
- if (i2c_send_recv(priv, buf, 2, ibuf, 2) != 2)
- return -EIO;
-
- *val = (ibuf[1]) | (ibuf[0] << 8);
- return 0;
-}
-
-#define dump_firm_type(t) dump_firm_type_and_int_freq(t, 0)
-static void dump_firm_type_and_int_freq(unsigned int type, u16 int_freq)
-{
- if (type & BASE)
- printk("BASE ");
- if (type & INIT1)
- printk("INIT1 ");
- if (type & F8MHZ)
- printk("F8MHZ ");
- if (type & MTS)
- printk("MTS ");
- if (type & D2620)
- printk("D2620 ");
- if (type & D2633)
- printk("D2633 ");
- if (type & DTV6)
- printk("DTV6 ");
- if (type & QAM)
- printk("QAM ");
- if (type & DTV7)
- printk("DTV7 ");
- if (type & DTV78)
- printk("DTV78 ");
- if (type & DTV8)
- printk("DTV8 ");
- if (type & FM)
- printk("FM ");
- if (type & INPUT1)
- printk("INPUT1 ");
- if (type & LCD)
- printk("LCD ");
- if (type & NOGD)
- printk("NOGD ");
- if (type & MONO)
- printk("MONO ");
- if (type & ATSC)
- printk("ATSC ");
- if (type & IF)
- printk("IF ");
- if (type & LG60)
- printk("LG60 ");
- if (type & ATI638)
- printk("ATI638 ");
- if (type & OREN538)
- printk("OREN538 ");
- if (type & OREN36)
- printk("OREN36 ");
- if (type & TOYOTA388)
- printk("TOYOTA388 ");
- if (type & TOYOTA794)
- printk("TOYOTA794 ");
- if (type & DIBCOM52)
- printk("DIBCOM52 ");
- if (type & ZARLINK456)
- printk("ZARLINK456 ");
- if (type & CHINA)
- printk("CHINA ");
- if (type & F6MHZ)
- printk("F6MHZ ");
- if (type & INPUT2)
- printk("INPUT2 ");
- if (type & SCODE)
- printk("SCODE ");
- if (type & HAS_IF)
- printk("HAS_IF_%d ", int_freq);
-}
-
-static v4l2_std_id parse_audio_std_option(void)
-{
- if (strcasecmp(audio_std, "A2") == 0)
- return V4L2_STD_A2;
- if (strcasecmp(audio_std, "A2/A") == 0)
- return V4L2_STD_A2_A;
- if (strcasecmp(audio_std, "A2/B") == 0)
- return V4L2_STD_A2_B;
- if (strcasecmp(audio_std, "NICAM") == 0)
- return V4L2_STD_NICAM;
- if (strcasecmp(audio_std, "NICAM/A") == 0)
- return V4L2_STD_NICAM_A;
- if (strcasecmp(audio_std, "NICAM/B") == 0)
- return V4L2_STD_NICAM_B;
-
- return 0;
-}
-
-static void free_firmware(struct xc2028_data *priv)
-{
- int i;
- tuner_dbg("%s called\n", __func__);
-
- if (!priv->firm)
- return;
-
- for (i = 0; i < priv->firm_size; i++)
- kfree(priv->firm[i].ptr);
-
- kfree(priv->firm);
-
- priv->firm = NULL;
- priv->firm_size = 0;
-
- memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
-}
-
-static int load_all_firmwares(struct dvb_frontend *fe)
-{
- struct xc2028_data *priv = fe->tuner_priv;
- const struct firmware *fw = NULL;
- unsigned char *p, *endp;
- int rc = 0;
- int n, n_array;
- char name[33];
- char *fname;
-
- tuner_dbg("%s called\n", __func__);
-
- if (!firmware_name[0])
- fname = priv->ctrl.fname;
- else
- fname = firmware_name;
-
- tuner_dbg("Reading firmware %s\n", fname);
- rc = request_firmware(&fw, fname, &priv->i2c_props.adap->dev);
- if (rc < 0) {
- if (rc == -ENOENT)
- tuner_err("Error: firmware %s not found.\n",
- fname);
- else
- tuner_err("Error %d while requesting firmware %s \n",
- rc, fname);
-
- return rc;
- }
- p = fw->data;
- endp = p + fw->size;
-
- if (fw->size < sizeof(name) - 1 + 2 + 2) {
- tuner_err("Error: firmware file %s has invalid size!\n",
- fname);
- goto corrupt;
- }
-
- memcpy(name, p, sizeof(name) - 1);
- name[sizeof(name) - 1] = 0;
- p += sizeof(name) - 1;
-
- priv->firm_version = le16_to_cpu(*(__u16 *) p);
- p += 2;
-
- n_array = le16_to_cpu(*(__u16 *) p);
- p += 2;
-
- tuner_info("Loading %d firmware images from %s, type: %s, ver %d.%d\n",
- n_array, fname, name,
- priv->firm_version >> 8, priv->firm_version & 0xff);
-
- priv->firm = kzalloc(sizeof(*priv->firm) * n_array, GFP_KERNEL);
- if (priv->firm == NULL) {
- tuner_err("Not enough memory to load firmware file.\n");
- rc = -ENOMEM;
- goto err;
- }
- priv->firm_size = n_array;
-
- n = -1;
- while (p < endp) {
- __u32 type, size;
- v4l2_std_id id;
- __u16 int_freq = 0;
-
- n++;
- if (n >= n_array) {
- tuner_err("More firmware images in file than "
- "were expected!\n");
- goto corrupt;
- }
-
- /* Checks if there's enough bytes to read */
- if (p + sizeof(type) + sizeof(id) + sizeof(size) > endp) {
- tuner_err("Firmware header is incomplete!\n");
- goto corrupt;
- }
-
- type = le32_to_cpu(*(__u32 *) p);
- p += sizeof(type);
-
- id = le64_to_cpu(*(v4l2_std_id *) p);
- p += sizeof(id);
-
- if (type & HAS_IF) {
- int_freq = le16_to_cpu(*(__u16 *) p);
- p += sizeof(int_freq);
- }
-
- size = le32_to_cpu(*(__u32 *) p);
- p += sizeof(size);
-
- if ((!size) || (size + p > endp)) {
- tuner_err("Firmware type ");
- dump_firm_type(type);
- printk("(%x), id %llx is corrupted "
- "(size=%d, expected %d)\n",
- type, (unsigned long long)id,
- (unsigned)(endp - p), size);
- goto corrupt;
- }
-
- priv->firm[n].ptr = kzalloc(size, GFP_KERNEL);
- if (priv->firm[n].ptr == NULL) {
- tuner_err("Not enough memory to load firmware file.\n");
- rc = -ENOMEM;
- goto err;
- }
- tuner_dbg("Reading firmware type ");
- if (debug) {
- dump_firm_type_and_int_freq(type, int_freq);
- printk("(%x), id %llx, size=%d.\n",
- type, (unsigned long long)id, size);
- }
-
- memcpy(priv->firm[n].ptr, p, size);
- priv->firm[n].type = type;
- priv->firm[n].id = id;
- priv->firm[n].size = size;
- priv->firm[n].int_freq = int_freq;
-
- p += size;
- }
-
- if (n + 1 != priv->firm_size) {
- tuner_err("Firmware file is incomplete!\n");
- goto corrupt;
- }
-
- goto done;
-
-corrupt:
- rc = -EINVAL;
- tuner_err("Error: firmware file is corrupted!\n");
-
-err:
- tuner_info("Releasing partially loaded firmware file.\n");
- free_firmware(priv);
-
-done:
- release_firmware(fw);
- if (rc == 0)
- tuner_dbg("Firmware files loaded.\n");
-
- return rc;
-}
-
-static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
- v4l2_std_id *id)
-{
- struct xc2028_data *priv = fe->tuner_priv;
- int i, best_i = -1, best_nr_matches = 0;
- unsigned int type_mask = 0;
-
- tuner_dbg("%s called, want type=", __func__);
- if (debug) {
- dump_firm_type(type);
- printk("(%x), id %016llx.\n", type, (unsigned long long)*id);
- }
-
- if (!priv->firm) {
- tuner_err("Error! firmware not loaded\n");
- return -EINVAL;
- }
-
- if (((type & ~SCODE) == 0) && (*id == 0))
- *id = V4L2_STD_PAL;
-
- if (type & BASE)
- type_mask = BASE_TYPES;
- else if (type & SCODE) {
- type &= SCODE_TYPES;
- type_mask = SCODE_TYPES &~ HAS_IF;
- } else if (type & DTV_TYPES)
- type_mask = DTV_TYPES;
- else if (type & STD_SPECIFIC_TYPES)
- type_mask = STD_SPECIFIC_TYPES;
-
- type &= type_mask;
-
- if (!(type & SCODE))
- type_mask = ~0;
-
- /* Seek for exact match */
- for (i = 0; i < priv->firm_size; i++) {
- if ((type == (priv->firm[i].type & type_mask)) &&
- (*id == priv->firm[i].id))
- goto found;
- }
-
- /* Seek for generic video standard match */
- for (i = 0; i < priv->firm_size; i++) {
- v4l2_std_id match_mask;
- int nr_matches;
-
- if (type != (priv->firm[i].type & type_mask))
- continue;
-
- match_mask = *id & priv->firm[i].id;
- if (!match_mask)
- continue;
-
- if ((*id & match_mask) == *id)
- goto found; /* Supports all the requested standards */
-
- nr_matches = hweight64(match_mask);
- if (nr_matches > best_nr_matches) {
- best_nr_matches = nr_matches;
- best_i = i;
- }
- }
-
- if (best_nr_matches > 0) {
- tuner_dbg("Selecting best matching firmware (%d bits) for "
- "type=", best_nr_matches);
- dump_firm_type(type);
- printk("(%x), id %016llx:\n", type, (unsigned long long)*id);
- i = best_i;
- goto found;
- }
-
- /*FIXME: Would make sense to seek for type "hint" match ? */
-
- i = -ENOENT;
- goto ret;
-
-found:
- *id = priv->firm[i].id;
-
-ret:
- tuner_dbg("%s firmware for type=", (i < 0) ? "Can't find" : "Found");
- if (debug) {
- dump_firm_type(type);
- printk("(%x), id %016llx.\n", type, (unsigned long long)*id);
- }
- return i;
-}
-
-static int load_firmware(struct dvb_frontend *fe, unsigned int type,
- v4l2_std_id *id)
-{
- struct xc2028_data *priv = fe->tuner_priv;
- int pos, rc;
- unsigned char *p, *endp, buf[priv->ctrl.max_len];
-
- tuner_dbg("%s called\n", __func__);
-
- pos = seek_firmware(fe, type, id);
- if (pos < 0)
- return pos;
-
- tuner_info("Loading firmware for type=");
- dump_firm_type(priv->firm[pos].type);
- printk("(%x), id %016llx.\n", priv->firm[pos].type,
- (unsigned long long)*id);
-
- p = priv->firm[pos].ptr;
- endp = p + priv->firm[pos].size;
-
- while (p < endp) {
- __u16 size;
-
- /* Checks if there's enough bytes to read */
- if (p + sizeof(size) > endp) {
- tuner_err("Firmware chunk size is wrong\n");
- return -EINVAL;
- }
-
- size = le16_to_cpu(*(__u16 *) p);
- p += sizeof(size);
-
- if (size == 0xffff)
- return 0;
-
- if (!size) {
- /* Special callback command received */
- rc = priv->tuner_callback(priv->video_dev,
- XC2028_TUNER_RESET, 0);
- if (rc < 0) {
- tuner_err("Error at RESET code %d\n",
- (*p) & 0x7f);
- return -EINVAL;
- }
- continue;
- }
- if (size >= 0xff00) {
- switch (size) {
- case 0xff00:
- rc = priv->tuner_callback(priv->video_dev,
- XC2028_RESET_CLK, 0);
- if (rc < 0) {
- tuner_err("Error at RESET code %d\n",
- (*p) & 0x7f);
- return -EINVAL;
- }
- break;
- default:
- tuner_info("Invalid RESET code %d\n",
- size & 0x7f);
- return -EINVAL;
-
- }
- continue;
- }
-
- /* Checks for a sleep command */
- if (size & 0x8000) {
- msleep(size & 0x7fff);
- continue;
- }
-
- if ((size + p > endp)) {
- tuner_err("missing bytes: need %d, have %d\n",
- size, (int)(endp - p));
- return -EINVAL;
- }
-
- buf[0] = *p;
- p++;
- size--;
-
- /* Sends message chunks */
- while (size > 0) {
- int len = (size < priv->ctrl.max_len - 1) ?
- size : priv->ctrl.max_len - 1;
-
- memcpy(buf + 1, p, len);
-
- rc = i2c_send(priv, buf, len + 1);
- if (rc < 0) {
- tuner_err("%d returned from send\n", rc);
- return -EINVAL;
- }
-
- p += len;
- size -= len;
- }
- }
- return 0;
-}
-
-static int load_scode(struct dvb_frontend *fe, unsigned int type,
- v4l2_std_id *id, __u16 int_freq, int scode)
-{
- struct xc2028_data *priv = fe->tuner_priv;
- int pos, rc;
- unsigned char *p;
-
- tuner_dbg("%s called\n", __func__);
-
- if (!int_freq) {
- pos = seek_firmware(fe, type, id);
- if (pos < 0)
- return pos;
- } else {
- for (pos = 0; pos < priv->firm_size; pos++) {
- if ((priv->firm[pos].int_freq == int_freq) &&
- (priv->firm[pos].type & HAS_IF))
- break;
- }
- if (pos == priv->firm_size)
- return -ENOENT;
- }
-
- p = priv->firm[pos].ptr;
-
- if (priv->firm[pos].type & HAS_IF) {
- if (priv->firm[pos].size != 12 * 16 || scode >= 16)
- return -EINVAL;
- p += 12 * scode;
- } else {
- /* 16 SCODE entries per file; each SCODE entry is 12 bytes and
- * has a 2-byte size header in the firmware format. */
- if (priv->firm[pos].size != 14 * 16 || scode >= 16 ||
- le16_to_cpu(*(__u16 *)(p + 14 * scode)) != 12)
- return -EINVAL;
- p += 14 * scode + 2;
- }
-
- tuner_info("Loading SCODE for type=");
- dump_firm_type_and_int_freq(priv->firm[pos].type,
- priv->firm[pos].int_freq);
- printk("(%x), id %016llx.\n", priv->firm[pos].type,
- (unsigned long long)*id);
-
- if (priv->firm_version < 0x0202)
- rc = send_seq(priv, {0x20, 0x00, 0x00, 0x00});
- else
- rc = send_seq(priv, {0xa0, 0x00, 0x00, 0x00});
- if (rc < 0)
- return -EIO;
-
- rc = i2c_send(priv, p, 12);
- if (rc < 0)
- return -EIO;
-
- rc = send_seq(priv, {0x00, 0x8c});
- if (rc < 0)
- return -EIO;
-
- return 0;
-}
-
-static int check_firmware(struct dvb_frontend *fe, unsigned int type,
- v4l2_std_id std, __u16 int_freq)
-{
- struct xc2028_data *priv = fe->tuner_priv;
- struct firmware_properties new_fw;
- int rc = 0, is_retry = 0;
- u16 version, hwmodel;
- v4l2_std_id std0;
-
- tuner_dbg("%s called\n", __func__);
-
- if (!priv->firm) {
- if (!priv->ctrl.fname) {
- tuner_info("xc2028/3028 firmware name not set!\n");
- return -EINVAL;
- }
-
- rc = load_all_firmwares(fe);
- if (rc < 0)
- return rc;
- }
-
- if (priv->ctrl.mts && !(type & FM))
- type |= MTS;
-
-retry:
- new_fw.type = type;
- new_fw.id = std;
- new_fw.std_req = std;
- new_fw.scode_table = SCODE | priv->ctrl.scode_table;
- new_fw.scode_nr = 0;
- new_fw.int_freq = int_freq;
-
- tuner_dbg("checking firmware, user requested type=");
- if (debug) {
- dump_firm_type(new_fw.type);
- printk("(%x), id %016llx, ", new_fw.type,
- (unsigned long long)new_fw.std_req);
- if (!int_freq) {
- printk("scode_tbl ");
- dump_firm_type(priv->ctrl.scode_table);
- printk("(%x), ", priv->ctrl.scode_table);
- } else
- printk("int_freq %d, ", new_fw.int_freq);
- printk("scode_nr %d\n", new_fw.scode_nr);
- }
-
- /* No need to reload base firmware if it matches */
- if (((BASE | new_fw.type) & BASE_TYPES) ==
- (priv->cur_fw.type & BASE_TYPES)) {
- tuner_dbg("BASE firmware not changed.\n");
- goto skip_base;
- }
-
- /* Updating BASE - forget about all currently loaded firmware */
- memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
-
- /* Reset is needed before loading firmware */
- rc = priv->tuner_callback(priv->video_dev,
- XC2028_TUNER_RESET, 0);
- if (rc < 0)
- goto fail;
-
- /* BASE firmwares are all std0 */
- std0 = 0;
- rc = load_firmware(fe, BASE | new_fw.type, &std0);
- if (rc < 0) {
- tuner_err("Error %d while loading base firmware\n",
- rc);
- goto fail;
- }
-
- /* Load INIT1, if needed */
- tuner_dbg("Load init1 firmware, if exists\n");
-
- rc = load_firmware(fe, BASE | INIT1 | new_fw.type, &std0);
- if (rc == -ENOENT)
- rc = load_firmware(fe, (BASE | INIT1 | new_fw.type) & ~F8MHZ,
- &std0);
- if (rc < 0 && rc != -ENOENT) {
- tuner_err("Error %d while loading init1 firmware\n",
- rc);
- goto fail;
- }
-
-skip_base:
- /*
- * No need to reload standard specific firmware if base firmware
- * was not reloaded and requested video standards have not changed.
- */
- if (priv->cur_fw.type == (BASE | new_fw.type) &&
- priv->cur_fw.std_req == std) {
- tuner_dbg("Std-specific firmware already loaded.\n");
- goto skip_std_specific;
- }
-
- /* Reloading std-specific firmware forces a SCODE update */
- priv->cur_fw.scode_table = 0;
-
- rc = load_firmware(fe, new_fw.type, &new_fw.id);
- if (rc == -ENOENT)
- rc = load_firmware(fe, new_fw.type & ~F8MHZ, &new_fw.id);
-
- if (rc < 0)
- goto fail;
-
-skip_std_specific:
- if (priv->cur_fw.scode_table == new_fw.scode_table &&
- priv->cur_fw.scode_nr == new_fw.scode_nr) {
- tuner_dbg("SCODE firmware already loaded.\n");
- goto check_device;
- }
-
- if (new_fw.type & FM)
- goto check_device;
-
- /* Load SCODE firmware, if exists */
- tuner_dbg("Trying to load scode %d\n", new_fw.scode_nr);
-
- rc = load_scode(fe, new_fw.type | new_fw.scode_table, &new_fw.id,
- new_fw.int_freq, new_fw.scode_nr);
-
-check_device:
- if (xc2028_get_reg(priv, 0x0004, &version) < 0 ||
- xc2028_get_reg(priv, 0x0008, &hwmodel) < 0) {
- tuner_err("Unable to read tuner registers.\n");
- goto fail;
- }
-
- tuner_dbg("Device is Xceive %d version %d.%d, "
- "firmware version %d.%d\n",
- hwmodel, (version & 0xf000) >> 12, (version & 0xf00) >> 8,
- (version & 0xf0) >> 4, version & 0xf);
-
- /* Check firmware version against what we downloaded. */
- if (priv->firm_version != ((version & 0xf0) << 4 | (version & 0x0f))) {
- tuner_err("Incorrect readback of firmware version.\n");
- goto fail;
- }
-
- /* Check that the tuner hardware model remains consistent over time. */
- if (priv->hwmodel == 0 && (hwmodel == 2028 || hwmodel == 3028)) {
- priv->hwmodel = hwmodel;
- priv->hwvers = version & 0xff00;
- } else if (priv->hwmodel == 0 || priv->hwmodel != hwmodel ||
- priv->hwvers != (version & 0xff00)) {
- tuner_err("Read invalid device hardware information - tuner "
- "hung?\n");
- goto fail;
- }
-
- memcpy(&priv->cur_fw, &new_fw, sizeof(priv->cur_fw));
-
- /*
- * By setting BASE in cur_fw.type only after successfully loading all
- * firmwares, we can:
- * 1. Identify that BASE firmware with type=0 has been loaded;
- * 2. Tell whether BASE firmware was just changed the next time through.
- */
- priv->cur_fw.type |= BASE;
-
- return 0;
-
-fail:
- memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
- if (!is_retry) {
- msleep(50);
- is_retry = 1;
- tuner_dbg("Retrying firmware load\n");
- goto retry;
- }
-
- if (rc == -ENOENT)
- rc = -EINVAL;
- return rc;
-}
-
-static int xc2028_signal(struct dvb_frontend *fe, u16 *strength)
-{
- struct xc2028_data *priv = fe->tuner_priv;
- u16 frq_lock, signal = 0;
- int rc;
-
- tuner_dbg("%s called\n", __func__);
-
- mutex_lock(&priv->lock);
-
- /* Sync Lock Indicator */
- rc = xc2028_get_reg(priv, 0x0002, &frq_lock);
- if (rc < 0)
- goto ret;
-
- /* Frequency is locked */
- if (frq_lock == 1)
- signal = 32768;
-
- /* Get SNR of the video signal */
- rc = xc2028_get_reg(priv, 0x0040, &signal);
- if (rc < 0)
- goto ret;
-
- /* Use both frq_lock and signal to generate the result */
- signal = signal || ((signal & 0x07) << 12);
-
-ret:
- mutex_unlock(&priv->lock);
-
- *strength = signal;
-
- tuner_dbg("signal strength is %d\n", signal);
-
- return rc;
-}
-
-#define DIV 15625
-
-static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
- enum tuner_mode new_mode,
- unsigned int type,
- v4l2_std_id std,
- u16 int_freq)
-{
- struct xc2028_data *priv = fe->tuner_priv;
- int rc = -EINVAL;
- unsigned char buf[4];
- u32 div, offset = 0;
-
- tuner_dbg("%s called\n", __func__);
-
- mutex_lock(&priv->lock);
-
- tuner_dbg("should set frequency %d kHz\n", freq / 1000);
-
- if (check_firmware(fe, type, std, int_freq) < 0)
- goto ret;
-
- /* On some cases xc2028 can disable video output, if
- * very weak signals are received. By sending a soft
- * reset, this is re-enabled. So, it is better to always
- * send a soft reset before changing channels, to be sure
- * that xc2028 will be in a safe state.
- * Maybe this might also be needed for DTV.
- */
- if (new_mode == T_ANALOG_TV) {
- rc = send_seq(priv, {0x00, 0x00});
- } else if (priv->cur_fw.type & ATSC) {
- offset = 1750000;
- } else {
- offset = 2750000;
- /*
- * We must adjust the offset by 500kHz in two cases in order
- * to correctly center the IF output:
- * 1) When the ZARLINK456 or DIBCOM52 tables were explicitly
- * selected and a 7MHz channel is tuned;
- * 2) When tuning a VHF channel with DTV78 firmware.
- */
- if (((priv->cur_fw.type & DTV7) &&
- (priv->cur_fw.scode_table & (ZARLINK456 | DIBCOM52))) ||
- ((priv->cur_fw.type & DTV78) && freq < 470000000))
- offset -= 500000;
- }
-
- div = (freq - offset + DIV / 2) / DIV;
-
- /* CMD= Set frequency */
- if (priv->firm_version < 0x0202)
- rc = send_seq(priv, {0x00, 0x02, 0x00, 0x00});
- else
- rc = send_seq(priv, {0x80, 0x02, 0x00, 0x00});
- if (rc < 0)
- goto ret;
-
- /* Return code shouldn't be checked.
- The reset CLK is needed only with tm6000.
- Driver should work fine even if this fails.
- */
- priv->tuner_callback(priv->video_dev, XC2028_RESET_CLK, 1);
-
- msleep(10);
-
- buf[0] = 0xff & (div >> 24);
- buf[1] = 0xff & (div >> 16);
- buf[2] = 0xff & (div >> 8);
- buf[3] = 0xff & (div);
-
- rc = i2c_send(priv, buf, sizeof(buf));
- if (rc < 0)
- goto ret;
- msleep(100);
-
- priv->frequency = freq;
-
- tuner_dbg("divisor= %02x %02x %02x %02x (freq=%d.%03d)\n",
- buf[0], buf[1], buf[2], buf[3],
- freq / 1000000, (freq % 1000000) / 1000);
-
- rc = 0;
-
-ret:
- mutex_unlock(&priv->lock);
-
- return rc;
-}
-
-static int xc2028_set_analog_freq(struct dvb_frontend *fe,
- struct analog_parameters *p)
-{
- struct xc2028_data *priv = fe->tuner_priv;
- unsigned int type=0;
-
- tuner_dbg("%s called\n", __func__);
-
- if (p->mode == V4L2_TUNER_RADIO) {
- type |= FM;
- if (priv->ctrl.input1)
- type |= INPUT1;
- return generic_set_freq(fe, (625l * p->frequency) / 10,
- T_ANALOG_TV, type, 0, 0);
- }
-
- /* if std is not defined, choose one */
- if (!p->std)
- p->std = V4L2_STD_MN;
-
- /* PAL/M, PAL/N, PAL/Nc and NTSC variants should use 6MHz firmware */
- if (!(p->std & V4L2_STD_MN))
- type |= F8MHZ;
-
- /* Add audio hack to std mask */
- p->std |= parse_audio_std_option();
-
- return generic_set_freq(fe, 62500l * p->frequency,
- T_ANALOG_TV, type, p->std, 0);
-}
-
-static int xc2028_set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
-{
- struct xc2028_data *priv = fe->tuner_priv;
- unsigned int type=0;
- fe_bandwidth_t bw = BANDWIDTH_8_MHZ;
- u16 demod = 0;
-
- tuner_dbg("%s called\n", __func__);
-
- if (priv->ctrl.d2633)
- type |= D2633;
- else
- type |= D2620;
-
- switch(fe->ops.info.type) {
- case FE_OFDM:
- bw = p->u.ofdm.bandwidth;
- break;
- case FE_QAM:
- tuner_info("WARN: There are some reports that "
- "QAM 6 MHz doesn't work.\n"
- "If this works for you, please report by "
- "e-mail to: v4l-dvb-maintainer@linuxtv.org\n");
- bw = BANDWIDTH_6_MHZ;
- type |= QAM;
- break;
- case FE_ATSC:
- bw = BANDWIDTH_6_MHZ;
- /* The only ATSC firmware (at least on v2.7) is D2633,
- so overrides ctrl->d2633 */
- type |= ATSC| D2633;
- type &= ~D2620;
- break;
- /* DVB-S is not supported */
- default:
- return -EINVAL;
- }
-
- switch (bw) {
- case BANDWIDTH_8_MHZ:
- if (p->frequency < 470000000)
- priv->ctrl.vhfbw7 = 0;
- else
- priv->ctrl.uhfbw8 = 1;
- type |= (priv->ctrl.vhfbw7 && priv->ctrl.uhfbw8) ? DTV78 : DTV8;
- type |= F8MHZ;
- break;
- case BANDWIDTH_7_MHZ:
- if (p->frequency < 470000000)
- priv->ctrl.vhfbw7 = 1;
- else
- priv->ctrl.uhfbw8 = 0;
- type |= (priv->ctrl.vhfbw7 && priv->ctrl.uhfbw8) ? DTV78 : DTV7;
- type |= F8MHZ;
- break;
- case BANDWIDTH_6_MHZ:
- type |= DTV6;
- priv->ctrl.vhfbw7 = 0;
- priv->ctrl.uhfbw8 = 0;
- break;
- default:
- tuner_err("error: bandwidth not supported.\n");
- };
-
- /* All S-code tables need a 200kHz shift */
- if (priv->ctrl.demod)
- demod = priv->ctrl.demod + 200;
-
- return generic_set_freq(fe, p->frequency,
- T_DIGITAL_TV, type, 0, demod);
-}
-
-#if 0
-/* This is needed at sleep (S1/S3), but not at fe_standby. Otherwise,
- firmware will be loaded on every open()
- */
-static int xc2028_sleep(struct dvb_frontend *fe)
-{
- struct xc2028_data *priv = fe->tuner_priv;
- int rc = 0;
-
- tuner_dbg("%s called\n", __func__);
-
- mutex_lock(&priv->lock);
-
- if (priv->firm_version < 0x0202)
- rc = send_seq(priv, {0x00, 0x08, 0x00, 0x00});
- else
- rc = send_seq(priv, {0x80, 0x08, 0x00, 0x00});
-
- priv->cur_fw.type = 0; /* need firmware reload */
-
- mutex_unlock(&priv->lock);
-
- return rc;
-}
-#endif
-
-static int xc2028_dvb_release(struct dvb_frontend *fe)
-{
- struct xc2028_data *priv = fe->tuner_priv;
-
- tuner_dbg("%s called\n", __func__);
-
- mutex_lock(&xc2028_list_mutex);
-
- priv->count--;
-
- if (!priv->count) {
- list_del(&priv->xc2028_list);
-
- kfree(priv->ctrl.fname);
-
- free_firmware(priv);
- kfree(priv);
- fe->tuner_priv = NULL;
- }
-
- mutex_unlock(&xc2028_list_mutex);
-
- return 0;
-}
-
-static int xc2028_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
- struct xc2028_data *priv = fe->tuner_priv;
-
- tuner_dbg("%s called\n", __func__);
-
- *frequency = priv->frequency;
-
- return 0;
-}
-
-static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg)
-{
- struct xc2028_data *priv = fe->tuner_priv;
- struct xc2028_ctrl *p = priv_cfg;
- int rc = 0;
-
- tuner_dbg("%s called\n", __func__);
-
- mutex_lock(&priv->lock);
-
- memcpy(&priv->ctrl, p, sizeof(priv->ctrl));
- if (priv->ctrl.max_len < 9)
- priv->ctrl.max_len = 13;
-
- if (p->fname) {
- if (priv->ctrl.fname && strcmp(p->fname, priv->ctrl.fname)) {
- kfree(priv->ctrl.fname);
- free_firmware(priv);
- }
-
- priv->ctrl.fname = kstrdup(p->fname, GFP_KERNEL);
- if (priv->ctrl.fname == NULL)
- rc = -ENOMEM;
- }
-
- mutex_unlock(&priv->lock);
-
- return rc;
-}
-
-static const struct dvb_tuner_ops xc2028_dvb_tuner_ops = {
- .info = {
- .name = "Xceive XC3028",
- .frequency_min = 42000000,
- .frequency_max = 864000000,
- .frequency_step = 50000,
- },
-
- .set_config = xc2028_set_config,
- .set_analog_params = xc2028_set_analog_freq,
- .release = xc2028_dvb_release,
- .get_frequency = xc2028_get_frequency,
- .get_rf_strength = xc2028_signal,
- .set_params = xc2028_set_params,
-#if 0
- .sleep = xc2028_sleep,
-#endif
-#if 0
- int (*get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth);
- int (*get_status)(struct dvb_frontend *fe, u32 *status);
-#endif
-};
-
-struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
- struct xc2028_config *cfg)
-{
- struct xc2028_data *priv;
- void *video_dev;
-
- if (debug)
- printk(KERN_DEBUG "xc2028: Xcv2028/3028 init called!\n");
-
- if (NULL == cfg)
- return NULL;
-
- if (!fe) {
- printk(KERN_ERR "xc2028: No frontend!\n");
- return NULL;
- }
-
- video_dev = cfg->i2c_adap->algo_data;
-
- if (debug)
- printk(KERN_DEBUG "xc2028: video_dev =%p\n", video_dev);
-
- mutex_lock(&xc2028_list_mutex);
-
- list_for_each_entry(priv, &xc2028_list, xc2028_list) {
- if (&priv->i2c_props.adap->dev == &cfg->i2c_adap->dev) {
- video_dev = NULL;
- if (debug)
- printk(KERN_DEBUG "xc2028: reusing device\n");
-
- break;
- }
- }
-
- if (video_dev) {
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- if (priv == NULL) {
- mutex_unlock(&xc2028_list_mutex);
- return NULL;
- }
-
- priv->i2c_props.addr = cfg->i2c_addr;
- priv->i2c_props.adap = cfg->i2c_adap;
- priv->i2c_props.name = "xc2028";
-
- priv->video_dev = video_dev;
- priv->tuner_callback = cfg->callback;
- priv->ctrl.max_len = 13;
-
- mutex_init(&priv->lock);
-
- list_add_tail(&priv->xc2028_list, &xc2028_list);
- }
-
- fe->tuner_priv = priv;
- priv->count++;
-
- if (debug)
- printk(KERN_DEBUG "xc2028: usage count is %i\n", priv->count);
-
- memcpy(&fe->ops.tuner_ops, &xc2028_dvb_tuner_ops,
- sizeof(xc2028_dvb_tuner_ops));
-
- tuner_info("type set to %s\n", "XCeive xc2028/xc3028 tuner");
-
- if (cfg->ctrl)
- xc2028_set_config(fe, cfg->ctrl);
-
- mutex_unlock(&xc2028_list_mutex);
-
- return fe;
-}
-
-EXPORT_SYMBOL(xc2028_attach);
-
-MODULE_DESCRIPTION("Xceive xc2028/xc3028 tuner driver");
-MODULE_AUTHOR("Michel Ludwig <michel.ludwig@gmail.com>");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
-MODULE_LICENSE("GPL");
diff --git a/linux/drivers/media/video/tuner-xc2028.h b/linux/drivers/media/video/tuner-xc2028.h
deleted file mode 100644
index fc2f132a5..000000000
--- a/linux/drivers/media/video/tuner-xc2028.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* tuner-xc2028
- *
- * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab@infradead.org)
- * This code is placed under the terms of the GNU General Public License v2
- */
-
-#ifndef __TUNER_XC2028_H__
-#define __TUNER_XC2028_H__
-
-#include "dvb_frontend.h"
-
-#define XC2028_DEFAULT_FIRMWARE "xc3028-v27.fw"
-
-/* Dmoduler IF (kHz) */
-#define XC3028_FE_DEFAULT 0 /* Don't load SCODE */
-#define XC3028_FE_LG60 6000
-#define XC3028_FE_ATI638 6380
-#define XC3028_FE_OREN538 5380
-#define XC3028_FE_OREN36 3600
-#define XC3028_FE_TOYOTA388 3880
-#define XC3028_FE_TOYOTA794 7940
-#define XC3028_FE_DIBCOM52 5200
-#define XC3028_FE_ZARLINK456 4560
-#define XC3028_FE_CHINA 5200
-
-struct xc2028_ctrl {
- char *fname;
- int max_len;
- unsigned int scode_table;
- unsigned int mts :1;
- unsigned int d2633 :1;
- unsigned int input1:1;
- unsigned int vhfbw7:1;
- unsigned int uhfbw8:1;
- unsigned int demod;
-};
-
-struct xc2028_config {
- struct i2c_adapter *i2c_adap;
- u8 i2c_addr;
- void *video_dev;
- struct xc2028_ctrl *ctrl;
- int (*callback) (void *dev, int command, int arg);
-};
-
-/* xc2028 commands for callback */
-#define XC2028_TUNER_RESET 0
-#define XC2028_RESET_CLK 1
-
-#if defined(CONFIG_TUNER_XC2028) || (defined(CONFIG_TUNER_XC2028_MODULE) && defined(MODULE))
-extern struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
- struct xc2028_config *cfg);
-#else
-static inline struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
- struct xc2028_config *cfg)
-{
- printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
- __func__);
- return NULL;
-}
-#endif
-
-#endif /* __TUNER_XC2028_H__ */
diff --git a/linux/drivers/media/video/usbvision/Makefile b/linux/drivers/media/video/usbvision/Makefile
index 9ac92a80c..338718750 100644
--- a/linux/drivers/media/video/usbvision/Makefile
+++ b/linux/drivers/media/video/usbvision/Makefile
@@ -3,3 +3,4 @@ usbvision-objs := usbvision-core.o usbvision-video.o usbvision-i2c.o usbvision-
obj-$(CONFIG_VIDEO_USBVISION) += usbvision.o
EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/common/tuners