summaryrefslogtreecommitdiff
path: root/linux/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'linux/drivers')
-rw-r--r--linux/drivers/media/common/ir-keymaps.c32
-rw-r--r--linux/drivers/media/common/saa7146_fops.c6
-rw-r--r--linux/drivers/media/common/saa7146_video.c4
-rw-r--r--linux/drivers/media/common/tuners/mxl5005s.c16
-rw-r--r--linux/drivers/media/common/tuners/tda9887.c5
-rw-r--r--linux/drivers/media/common/tuners/tuner-simple.c2
-rw-r--r--linux/drivers/media/common/tuners/tuner-types.c33
-rw-r--r--linux/drivers/media/common/tuners/xc5000.c73
-rw-r--r--linux/drivers/media/common/tuners/xc5000.h8
-rw-r--r--linux/drivers/media/dvb/Kconfig13
-rw-r--r--linux/drivers/media/dvb/dm1105/dm1105.c21
-rw-r--r--linux/drivers/media/dvb/dvb-core/dvb_frontend.c190
-rw-r--r--linux/drivers/media/dvb/dvb-core/dvb_frontend.h134
-rw-r--r--linux/drivers/media/dvb/dvb-core/dvbdev.c83
-rw-r--r--linux/drivers/media/dvb/dvb-core/dvbdev.h1
-rw-r--r--linux/drivers/media/dvb/dvb-usb/Kconfig3
-rw-r--r--linux/drivers/media/dvb/dvb-usb/af9015.c43
-rw-r--r--linux/drivers/media/dvb/dvb-usb/af9015.h77
-rw-r--r--linux/drivers/media/dvb/dvb-usb/anysee.c4
-rw-r--r--linux/drivers/media/dvb/dvb-usb/cinergyT2-core.c3
-rw-r--r--linux/drivers/media/dvb/dvb-usb/cinergyT2.h14
-rw-r--r--linux/drivers/media/dvb/dvb-usb/dib0700.h5
-rw-r--r--linux/drivers/media/dvb/dvb-usb/dib0700_core.c16
-rw-r--r--linux/drivers/media/dvb/dvb-usb/dib0700_devices.c139
-rw-r--r--linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h1
-rw-r--r--linux/drivers/media/dvb/dvb-usb/dvb-usb-urb.c6
-rw-r--r--linux/drivers/media/dvb/dvb-usb/dw2102.c25
-rw-r--r--linux/drivers/media/dvb/dvb-usb/usb-urb.c19
-rw-r--r--linux/drivers/media/dvb/frontends/Kconfig45
-rw-r--r--linux/drivers/media/dvb/frontends/Makefile9
-rw-r--r--linux/drivers/media/dvb/frontends/af9013.c6
-rw-r--r--linux/drivers/media/dvb/frontends/cx22702.c506
-rw-r--r--linux/drivers/media/dvb/frontends/cx22702.h20
-rw-r--r--linux/drivers/media/dvb/frontends/cx24116.c593
-rw-r--r--linux/drivers/media/dvb/frontends/cx24116.h21
-rw-r--r--linux/drivers/media/dvb/frontends/cx24123.c228
-rw-r--r--linux/drivers/media/dvb/frontends/cx24123.h10
-rw-r--r--linux/drivers/media/dvb/frontends/dvb-pll.c2
-rw-r--r--linux/drivers/media/dvb/frontends/lgdt3304.c398
-rw-r--r--linux/drivers/media/dvb/frontends/lgdt3304.h45
-rw-r--r--linux/drivers/media/dvb/frontends/s5h1409.c138
-rw-r--r--linux/drivers/media/dvb/frontends/s5h1409.h15
-rw-r--r--linux/drivers/media/dvb/frontends/s5h1411.c95
-rw-r--r--linux/drivers/media/dvb/frontends/s5h1411.h2
-rw-r--r--linux/drivers/media/dvb/frontends/s921_core.c587
-rw-r--r--linux/drivers/media/dvb/frontends/s921_core.h114
-rw-r--r--linux/drivers/media/dvb/frontends/s921_module.c254
-rw-r--r--linux/drivers/media/dvb/frontends/s921_module.h49
-rw-r--r--linux/drivers/media/dvb/frontends/si21xx.c1
-rw-r--r--linux/drivers/media/dvb/frontends/stb0899_algo.c1532
-rw-r--r--linux/drivers/media/dvb/frontends/stb0899_cfg.h421
-rw-r--r--linux/drivers/media/dvb/frontends/stb0899_drv.c1979
-rw-r--r--linux/drivers/media/dvb/frontends/stb0899_drv.h162
-rw-r--r--linux/drivers/media/dvb/frontends/stb0899_priv.h274
-rw-r--r--linux/drivers/media/dvb/frontends/stb0899_reg.h2027
-rw-r--r--linux/drivers/media/dvb/frontends/stb6100.c552
-rw-r--r--linux/drivers/media/dvb/frontends/stb6100.h115
-rw-r--r--linux/drivers/media/dvb/frontends/stb6100_cfg.h108
-rw-r--r--linux/drivers/media/dvb/frontends/tda10048.c100
-rw-r--r--linux/drivers/media/dvb/frontends/tda8261.c230
-rw-r--r--linux/drivers/media/dvb/frontends/tda8261.h55
-rw-r--r--linux/drivers/media/dvb/frontends/tda8261_cfg.h84
-rw-r--r--linux/drivers/media/dvb/frontends/z0194a.h16
-rw-r--r--linux/drivers/media/dvb/frontends/zl10353.c3
-rw-r--r--linux/drivers/media/dvb/siano/sms-cards.c4
-rw-r--r--linux/drivers/media/dvb/ttpci/Kconfig4
-rw-r--r--linux/drivers/media/dvb/ttpci/av7110.c5
-rw-r--r--linux/drivers/media/dvb/ttpci/budget-av.c298
-rw-r--r--linux/drivers/media/dvb/ttpci/budget-ci.c311
-rw-r--r--linux/drivers/media/dvb/ttpci/budget.h1
-rw-r--r--linux/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c15
-rw-r--r--linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c7
-rw-r--r--linux/drivers/media/radio/Kconfig14
-rw-r--r--linux/drivers/media/radio/dsbr100.c148
-rw-r--r--linux/drivers/media/radio/radio-aimslab.c2
-rw-r--r--linux/drivers/media/radio/radio-cadet.c2
-rw-r--r--linux/drivers/media/radio/radio-gemtek.c2
-rw-r--r--linux/drivers/media/radio/radio-mr800.c48
-rw-r--r--linux/drivers/media/radio/radio-rtrack2.c2
-rw-r--r--linux/drivers/media/radio/radio-sf16fmi.c2
-rw-r--r--linux/drivers/media/radio/radio-si470x.c19
-rw-r--r--linux/drivers/media/video/Kconfig14
-rw-r--r--linux/drivers/media/video/Makefile3
-rw-r--r--linux/drivers/media/video/arv.c7
-rw-r--r--linux/drivers/media/video/au0828/au0828-cards.c5
-rw-r--r--linux/drivers/media/video/au0828/au0828-core.c3
-rw-r--r--linux/drivers/media/video/au0828/au0828-dvb.c3
-rw-r--r--linux/drivers/media/video/bt8xx/bttv-driver.c6
-rw-r--r--linux/drivers/media/video/bt8xx/bttv-gpio.c7
-rw-r--r--linux/drivers/media/video/bt8xx/bttv.h2
-rw-r--r--linux/drivers/media/video/bt8xx/bttvp.h2
-rw-r--r--linux/drivers/media/video/bw-qcam.c5
-rw-r--r--linux/drivers/media/video/c-qcam.c9
-rw-r--r--linux/drivers/media/video/cafe_ccic.c23
-rw-r--r--linux/drivers/media/video/cpia.c19
-rw-r--r--linux/drivers/media/video/cpia2/cpia2_core.c2
-rw-r--r--linux/drivers/media/video/cpia2/cpia2_usb.c2
-rw-r--r--linux/drivers/media/video/cpia2/cpia2_v4l.c17
-rw-r--r--linux/drivers/media/video/cx18/cx18-av-audio.c41
-rw-r--r--linux/drivers/media/video/cx18/cx18-av-core.c100
-rw-r--r--linux/drivers/media/video/cx18/cx18-av-core.h3
-rw-r--r--linux/drivers/media/video/cx18/cx18-av-firmware.c22
-rw-r--r--linux/drivers/media/video/cx18/cx18-driver.c32
-rw-r--r--linux/drivers/media/video/cx18/cx18-driver.h40
-rw-r--r--linux/drivers/media/video/cx18/cx18-dvb.c56
-rw-r--r--linux/drivers/media/video/cx18/cx18-dvb.h1
-rw-r--r--linux/drivers/media/video/cx18/cx18-firmware.c95
-rw-r--r--linux/drivers/media/video/cx18/cx18-gpio.c24
-rw-r--r--linux/drivers/media/video/cx18/cx18-i2c.c24
-rw-r--r--linux/drivers/media/video/cx18/cx18-io.c50
-rw-r--r--linux/drivers/media/video/cx18/cx18-io.h30
-rw-r--r--linux/drivers/media/video/cx18/cx18-irq.c106
-rw-r--r--linux/drivers/media/video/cx18/cx18-irq.h9
-rw-r--r--linux/drivers/media/video/cx18/cx18-mailbox.c219
-rw-r--r--linux/drivers/media/video/cx18/cx18-mailbox.h7
-rw-r--r--linux/drivers/media/video/cx18/cx18-queue.c14
-rw-r--r--linux/drivers/media/video/cx18/cx18-scb.h40
-rw-r--r--linux/drivers/media/video/cx18/cx18-streams.c42
-rw-r--r--linux/drivers/media/video/cx18/cx18-version.h2
-rw-r--r--linux/drivers/media/video/cx23885/cx23885-417.c2
-rw-r--r--linux/drivers/media/video/cx23885/cx23885-cards.c152
-rw-r--r--linux/drivers/media/video/cx23885/cx23885-core.c271
-rw-r--r--linux/drivers/media/video/cx23885/cx23885-dvb.c36
-rw-r--r--linux/drivers/media/video/cx23885/cx23885-i2c.c47
-rw-r--r--linux/drivers/media/video/cx23885/cx23885-video.c31
-rw-r--r--linux/drivers/media/video/cx23885/cx23885.h21
-rw-r--r--linux/drivers/media/video/cx25840/Kconfig2
-rw-r--r--linux/drivers/media/video/cx88/cx88-alsa.c2
-rw-r--r--linux/drivers/media/video/cx88/cx88-blackbird.c14
-rw-r--r--linux/drivers/media/video/cx88/cx88-cards.c115
-rw-r--r--linux/drivers/media/video/cx88/cx88-core.c6
-rw-r--r--linux/drivers/media/video/cx88/cx88-dvb.c200
-rw-r--r--linux/drivers/media/video/cx88/cx88-i2c.c2
-rw-r--r--linux/drivers/media/video/cx88/cx88-mpeg.c37
-rw-r--r--linux/drivers/media/video/cx88/cx88-tvaudio.c11
-rw-r--r--linux/drivers/media/video/cx88/cx88-video.c68
-rw-r--r--linux/drivers/media/video/cx88/cx88.h16
-rw-r--r--linux/drivers/media/video/dabusb.c4
-rw-r--r--linux/drivers/media/video/em28xx/em28xx-audio.c21
-rw-r--r--linux/drivers/media/video/em28xx/em28xx-cards.c71
-rw-r--r--linux/drivers/media/video/em28xx/em28xx-core.c84
-rw-r--r--linux/drivers/media/video/em28xx/em28xx-i2c.c21
-rw-r--r--linux/drivers/media/video/em28xx/em28xx-input.c327
-rw-r--r--linux/drivers/media/video/em28xx/em28xx-reg.h86
-rw-r--r--linux/drivers/media/video/em28xx/em28xx-video.c90
-rw-r--r--linux/drivers/media/video/em28xx/em28xx.h23
-rw-r--r--linux/drivers/media/video/et61x251/et61x251_core.c26
-rw-r--r--linux/drivers/media/video/gspca/Kconfig144
-rw-r--r--linux/drivers/media/video/gspca/conex.c3
-rw-r--r--linux/drivers/media/video/gspca/finepix.c11
-rw-r--r--linux/drivers/media/video/gspca/gspca.c102
-rw-r--r--linux/drivers/media/video/gspca/gspca.h21
-rw-r--r--linux/drivers/media/video/gspca/mars.c2
-rw-r--r--linux/drivers/media/video/gspca/ov519.c155
-rw-r--r--linux/drivers/media/video/gspca/pac207.c1
-rw-r--r--linux/drivers/media/video/gspca/pac7311.c3
-rw-r--r--linux/drivers/media/video/gspca/sonixb.c21
-rw-r--r--linux/drivers/media/video/gspca/sonixj.c210
-rw-r--r--linux/drivers/media/video/gspca/spca500.c4
-rw-r--r--linux/drivers/media/video/gspca/spca501.c132
-rw-r--r--linux/drivers/media/video/gspca/spca505.c4
-rw-r--r--linux/drivers/media/video/gspca/spca561.c3
-rw-r--r--linux/drivers/media/video/gspca/tv8532.c140
-rw-r--r--linux/drivers/media/video/gspca/vc032x.c3
-rw-r--r--linux/drivers/media/video/gspca/zc3xx.c293
-rw-r--r--linux/drivers/media/video/ir-kbd-i2c.c6
-rw-r--r--linux/drivers/media/video/ivtv/Kconfig5
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-cards.c17
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-driver.c38
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-driver.h1
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-i2c.c1
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-ioctl.c13
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-ioctl.h3
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-streams.c4
-rw-r--r--linux/drivers/media/video/ivtv/ivtvfb.c6
-rw-r--r--linux/drivers/media/video/ov511.c24
-rw-r--r--linux/drivers/media/video/ov772x.c972
-rw-r--r--linux/drivers/media/video/pms.c9
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c4
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c8
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c4
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c16
-rw-r--r--linux/drivers/media/video/pwc/pwc-if.c4
-rw-r--r--linux/drivers/media/video/pwc/pwc-v4l.c3
-rw-r--r--linux/drivers/media/video/pwc/pwc.h3
-rw-r--r--linux/drivers/media/video/s2255drv.c2
-rw-r--r--linux/drivers/media/video/saa5246a.c7
-rw-r--r--linux/drivers/media/video/saa5249.c7
-rw-r--r--linux/drivers/media/video/saa7110.c4
-rw-r--r--linux/drivers/media/video/saa7127.c2
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-core.c9
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-dvb.c26
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-empress.c2
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-tvaudio.c2
-rw-r--r--linux/drivers/media/video/saa7134/saa7134.h2
-rw-r--r--linux/drivers/media/video/se401.c7
-rw-r--r--linux/drivers/media/video/sh_mobile_ceu_camera.c103
-rw-r--r--linux/drivers/media/video/sn9c102/sn9c102_core.c26
-rw-r--r--linux/drivers/media/video/sn9c102/sn9c102_devtable.h6
-rw-r--r--linux/drivers/media/video/soc_camera.c6
-rw-r--r--linux/drivers/media/video/soc_camera_platform.c20
-rw-r--r--linux/drivers/media/video/stk-webcam.c4
-rw-r--r--linux/drivers/media/video/stv680.c8
-rw-r--r--linux/drivers/media/video/tvaudio.c233
-rw-r--r--linux/drivers/media/video/tveeprom.c2
-rw-r--r--linux/drivers/media/video/tvp5150.c15
-rw-r--r--linux/drivers/media/video/usbvideo/ibmcam.c12
-rw-r--r--linux/drivers/media/video/usbvideo/konicawc.c8
-rw-r--r--linux/drivers/media/video/usbvideo/quickcam_messenger.c14
-rw-r--r--linux/drivers/media/video/usbvideo/usbvideo.c7
-rw-r--r--linux/drivers/media/video/usbvideo/vicam.c3
-rw-r--r--linux/drivers/media/video/usbvision/usbvision-core.c4
-rw-r--r--linux/drivers/media/video/usbvision/usbvision-i2c.c2
-rw-r--r--linux/drivers/media/video/usbvision/usbvision-video.c22
-rw-r--r--linux/drivers/media/video/uvc/uvc_ctrl.c2
-rw-r--r--linux/drivers/media/video/uvc/uvc_driver.c171
-rw-r--r--linux/drivers/media/video/uvc/uvc_status.c12
-rw-r--r--linux/drivers/media/video/uvc/uvc_v4l2.c17
-rw-r--r--linux/drivers/media/video/uvc/uvc_video.c67
-rw-r--r--linux/drivers/media/video/uvc/uvcvideo.h15
-rw-r--r--linux/drivers/media/video/v4l1-compat.c225
-rw-r--r--linux/drivers/media/video/v4l2-common.c6
-rw-r--r--linux/drivers/media/video/v4l2-compat-ioctl32.c (renamed from linux/drivers/media/video/compat_ioctl32.c)98
-rw-r--r--linux/drivers/media/video/v4l2-dev.c4
-rw-r--r--linux/drivers/media/video/v4l2-int-device.c5
-rw-r--r--linux/drivers/media/video/v4l2-ioctl.c115
-rw-r--r--linux/drivers/media/video/videobuf-dvb.c174
-rw-r--r--linux/drivers/media/video/vino.c10
-rw-r--r--linux/drivers/media/video/vivi.c284
-rw-r--r--linux/drivers/media/video/w9966.c5
-rw-r--r--linux/drivers/media/video/w9968cf.c20
-rw-r--r--linux/drivers/media/video/zc0301/zc0301_core.c26
-rw-r--r--linux/drivers/media/video/zoran/zoran_driver.c9
-rw-r--r--linux/drivers/media/video/zr364xx.c2
234 files changed, 16397 insertions, 3356 deletions
diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c
index b58c8907f..6c0a80f45 100644
--- a/linux/drivers/media/common/ir-keymaps.c
+++ b/linux/drivers/media/common/ir-keymaps.c
@@ -2561,3 +2561,35 @@ IR_KEYTAB_TYPE ir_codes_real_audio_220_32_keys[IR_KEYTAB_SIZE] = {
};
EXPORT_SYMBOL_GPL(ir_codes_real_audio_220_32_keys);
+
+/* ATI TV Wonder HD 600 USB
+ Devin Heitmueller <devin.heitmueller@gmail.com>
+ */
+IR_KEYTAB_TYPE ir_codes_ati_tv_wonder_hd_600[IR_KEYTAB_SIZE] = {
+ [0x00] = KEY_RECORD, /* Row 1 */
+ [0x01] = KEY_PLAYPAUSE,
+ [0x02] = KEY_STOP,
+ [0x03] = KEY_POWER,
+ [0x04] = KEY_PREVIOUS, /* Row 2 */
+ [0x05] = KEY_REWIND,
+ [0x06] = KEY_FORWARD,
+ [0x07] = KEY_NEXT,
+ [0x08] = KEY_EPG, /* Row 3 */
+ [0x09] = KEY_HOME,
+ [0x0a] = KEY_MENU,
+ [0x0b] = KEY_CHANNELUP,
+ [0x0c] = KEY_BACK, /* Row 4 */
+ [0x0d] = KEY_UP,
+ [0x0e] = KEY_INFO,
+ [0x0f] = KEY_CHANNELDOWN,
+ [0x10] = KEY_LEFT, /* Row 5 */
+ [0x11] = KEY_SELECT,
+ [0x12] = KEY_RIGHT,
+ [0x13] = KEY_VOLUMEUP,
+ [0x14] = KEY_LAST, /* Row 6 */
+ [0x15] = KEY_DOWN,
+ [0x16] = KEY_MUTE,
+ [0x17] = KEY_VOLUMEDOWN,
+};
+
+EXPORT_SYMBOL_GPL(ir_codes_ati_tv_wonder_hd_600);
diff --git a/linux/drivers/media/common/saa7146_fops.c b/linux/drivers/media/common/saa7146_fops.c
index 37a227d01..cd4f95860 100644
--- a/linux/drivers/media/common/saa7146_fops.c
+++ b/linux/drivers/media/common/saa7146_fops.c
@@ -314,7 +314,7 @@ static int fops_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
/*
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);
+ return video_usercopy(file, cmd, arg, saa7146_video_do_ioctl);
}
static int fops_mmap(struct file *file, struct vm_area_struct * vma)
@@ -546,11 +546,11 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
if( VFL_TYPE_GRABBER == type ) {
vv->video_minor = vfd->minor;
INFO(("%s: registered device video%d [v4l2]\n",
- dev->name, vfd->minor & 0x1f));
+ dev->name, vfd->num));
} else {
vv->vbi_minor = vfd->minor;
INFO(("%s: registered device vbi%d [v4l2]\n",
- dev->name, vfd->minor & 0x1f));
+ dev->name, vfd->num));
}
*vid = vfd;
diff --git a/linux/drivers/media/common/saa7146_video.c b/linux/drivers/media/common/saa7146_video.c
index 8804d4e78..12717058e 100644
--- a/linux/drivers/media/common/saa7146_video.c
+++ b/linux/drivers/media/common/saa7146_video.c
@@ -835,7 +835,7 @@ static int video_end(struct saa7146_fh *fh, struct file *file)
* 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)
+int saa7146_video_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct saa7146_fh *fh = file->private_data;
struct saa7146_dev *dev = fh->dev;
@@ -1216,7 +1216,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
}
#endif
default:
- return v4l_compat_translate_ioctl(inode,file,cmd,arg,
+ return v4l_compat_translate_ioctl(file, cmd, arg,
saa7146_video_do_ioctl);
}
return 0;
diff --git a/linux/drivers/media/common/tuners/mxl5005s.c b/linux/drivers/media/common/tuners/mxl5005s.c
index 20405506a..58418277a 100644
--- a/linux/drivers/media/common/tuners/mxl5005s.c
+++ b/linux/drivers/media/common/tuners/mxl5005s.c
@@ -3483,7 +3483,9 @@ static u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum,
}
ctrlVal = 0;
for (k = 0; k < state->MXL_Ctrl[i].size; k++)
- ctrlVal += state->MXL_Ctrl[i].val[k] * (1 << k);
+ ctrlVal += state->
+ MXL_Ctrl[i].val[k] *
+ (1 << k);
} else
return -1;
}
@@ -3583,7 +3585,7 @@ static void MXL_RegWriteBit(struct dvb_frontend *fe, u8 address, u8 bit,
static u32 MXL_Ceiling(u32 value, u32 resolution)
{
- return (value/resolution + (value % resolution > 0 ? 1 : 0));
+ return value / resolution + (value % resolution > 0 ? 1 : 0);
}
/* Retrieve the Initialzation Registers */
@@ -3598,7 +3600,7 @@ static u16 MXL_GetInitRegister(struct dvb_frontend *fe, u8 *RegNum,
76, 77, 91, 134, 135, 137, 147,
156, 166, 167, 168, 25 };
- *count = sizeof(RegAddr) / sizeof(u8);
+ *count = ARRAY_SIZE(RegAddr);
status += MXL_BlockInit(fe);
@@ -3630,7 +3632,7 @@ static u16 MXL_GetCHRegister(struct dvb_frontend *fe, u8 *RegNum, u8 *RegVal,
*/
#endif
- *count = sizeof(RegAddr) / sizeof(u8);
+ *count = ARRAY_SIZE(RegAddr);
for (i = 0 ; i < *count; i++) {
RegNum[i] = RegAddr[i];
@@ -3648,7 +3650,7 @@ static u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 *RegNum,
u8 RegAddr[] = {43, 136};
- *count = sizeof(RegAddr) / sizeof(u8);
+ *count = ARRAY_SIZE(RegAddr);
for (i = 0; i < *count; i++) {
RegNum[i] = RegAddr[i];
@@ -3912,7 +3914,10 @@ static int mxl5005s_writeregs(struct dvb_frontend *fe, u8 *addrtable,
static int mxl5005s_init(struct dvb_frontend *fe)
{
+ struct mxl5005s_state *state = fe->tuner_priv;
+
dprintk(1, "%s()\n", __func__);
+ state->current_mode = MXL_QAM;
return mxl5005s_reconfigure(fe, MXL_QAM, MXL5005S_BANDWIDTH_6MHZ);
}
@@ -4094,7 +4099,6 @@ struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe,
state->frontend = fe;
state->config = config;
state->i2c = i2c;
- state->current_mode = MXL_QAM;
printk(KERN_INFO "MXL5005S: Attached at address 0x%02x\n",
config->i2c_address);
diff --git a/linux/drivers/media/common/tuners/tda9887.c b/linux/drivers/media/common/tuners/tda9887.c
index effbf31da..8df82bfab 100644
--- a/linux/drivers/media/common/tuners/tda9887.c
+++ b/linux/drivers/media/common/tuners/tda9887.c
@@ -181,11 +181,10 @@ static struct tvnorm tvnorms[] = {
},{
.std = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H,
.name = "SECAM-BGH",
- .b = ( cPositiveAmTV |
+ .b = ( cNegativeFmTV |
cQSS ),
.c = ( cTopDefault),
- .e = ( cGating_36 |
- cAudioIF_5_5 |
+ .e = ( cAudioIF_5_5 |
cVideoIF_38_90 ),
},{
.std = V4L2_STD_SECAM_L,
diff --git a/linux/drivers/media/common/tuners/tuner-simple.c b/linux/drivers/media/common/tuners/tuner-simple.c
index 036504510..0d9fc1bb2 100644
--- a/linux/drivers/media/common/tuners/tuner-simple.c
+++ b/linux/drivers/media/common/tuners/tuner-simple.c
@@ -513,6 +513,7 @@ static int simple_radio_bandswitch(struct dvb_frontend *fe, u8 *buffer)
case TUNER_PHILIPS_FM1216ME_MK3:
case TUNER_PHILIPS_FM1236_MK3:
case TUNER_PHILIPS_FMD1216ME_MK3:
+ case TUNER_PHILIPS_FMD1216MEX_MK3:
case TUNER_LG_NTSC_TAPE:
case TUNER_PHILIPS_FM1256_IH3:
case TUNER_TCL_MF02GIP_5N:
@@ -787,6 +788,7 @@ static void simple_set_dvb(struct dvb_frontend *fe, u8 *buf,
switch (priv->type) {
case TUNER_PHILIPS_FMD1216ME_MK3:
+ case TUNER_PHILIPS_FMD1216MEX_MK3:
if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ &&
params->frequency >= 158870000)
buf[3] |= 0x08;
diff --git a/linux/drivers/media/common/tuners/tuner-types.c b/linux/drivers/media/common/tuners/tuner-types.c
index 861d23872..d83df3604 100644
--- a/linux/drivers/media/common/tuners/tuner-types.c
+++ b/linux/drivers/media/common/tuners/tuner-types.c
@@ -947,7 +947,7 @@ static struct tuner_params tuner_tena_9533_di_params[] = {
},
};
-/* ------------ TUNER_PHILIPS_FMD1216ME_MK3 - Philips PAL ------------ */
+/* ------------ TUNER_PHILIPS_FMD1216ME(X)_MK3 - Philips PAL ------------ */
static struct tuner_range tuner_philips_fmd1216me_mk3_pal_ranges[] = {
{ 16 * 160.00 /*MHz*/, 0x86, 0x51, },
@@ -985,6 +985,27 @@ static struct tuner_params tuner_philips_fmd1216me_mk3_params[] = {
},
};
+static struct tuner_params tuner_philips_fmd1216mex_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,
+ .radio_if = 1,
+ .fm_gain_normal = 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 ----- */
@@ -1664,6 +1685,16 @@ struct tunertype tuners[] = {
.params = tuner_tcl_mf02gip_5n_params,
.count = ARRAY_SIZE(tuner_tcl_mf02gip_5n_params),
},
+ [TUNER_PHILIPS_FMD1216MEX_MK3] = { /* Philips PAL */
+ .name = "Philips FMD1216MEX MK3 Hybrid Tuner",
+ .params = tuner_philips_fmd1216mex_mk3_params,
+ .count = ARRAY_SIZE(tuner_philips_fmd1216mex_mk3_params),
+ .min = 16 * 50.87,
+ .max = 16 * 858.00,
+ .stepsize = 166667,
+ .initdata = tua603x_agc112,
+ .sleepdata = (u8[]){ 4, 0x9c, 0x60, 0x85, 0x54 },
+ },
};
EXPORT_SYMBOL(tuners);
diff --git a/linux/drivers/media/common/tuners/xc5000.c b/linux/drivers/media/common/tuners/xc5000.c
index f3a3c47fe..8cfac7002 100644
--- a/linux/drivers/media/common/tuners/xc5000.c
+++ b/linux/drivers/media/common/tuners/xc5000.c
@@ -43,7 +43,7 @@ MODULE_PARM_DESC(init_fw, "Load firmware during driver initialization.");
static DEFINE_MUTEX(xc5000_list_mutex);
static LIST_HEAD(hybrid_tuner_instance_list);
-#define dprintk(level,fmt, arg...) if (debug >= level) \
+#define dprintk(level, fmt, arg...) if (debug >= level) \
printk(KERN_INFO "%s: " fmt, "xc5000", ## arg)
#define XC5000_DEFAULT_FIRMWARE "dvb-fe-xc5000-1.1.fw"
@@ -138,11 +138,11 @@ struct xc5000_priv {
immediately the length of the following transaction.
*/
-typedef struct {
+struct XC_TV_STANDARD {
char *Name;
u16 AudioMode;
u16 VideoMode;
-} XC_TV_STANDARD;
+};
/* Tuner standards */
#define MN_NTSC_PAL_BTSC 0
@@ -169,7 +169,7 @@ typedef struct {
#define FM_Radio_INPUT2 21
#define FM_Radio_INPUT1 22
-static XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = {
+static struct XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = {
{"M/N-NTSC/PAL-BTSC", 0x0400, 0x8020},
{"M/N-NTSC/PAL-A2", 0x0600, 0x8020},
{"M/N-NTSC/PAL-EIAJ", 0x0440, 0x8020},
@@ -183,7 +183,7 @@ static XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = {
{"D/K-PAL-NICAM", 0x0E80, 0x8009},
{"D/K-PAL-MONO", 0x1478, 0x8009},
{"D/K-SECAM-A2 DK1", 0x1200, 0x8009},
- {"D/K-SECAM-A2 L/DK3",0x0E00, 0x8009},
+ {"D/K-SECAM-A2 L/DK3", 0x0E00, 0x8009},
{"D/K-SECAM-A2 MONO", 0x1478, 0x8009},
{"L-SECAM-NICAM", 0x8E82, 0x0009},
{"L'-SECAM-NICAM", 0x8E82, 0x4009},
@@ -307,9 +307,10 @@ static int xc_load_i2c_sequence(struct dvb_frontend *fe, const u8 *i2c_sequence)
unsigned int len, pos, index;
u8 buf[XC_MAX_I2C_WRITE_LENGTH];
- index=0;
- while ((i2c_sequence[index]!=0xFF) || (i2c_sequence[index+1]!=0xFF)) {
- len = i2c_sequence[index]* 256 + i2c_sequence[index+1];
+ index = 0;
+ while ((i2c_sequence[index] != 0xFF) ||
+ (i2c_sequence[index + 1] != 0xFF)) {
+ len = i2c_sequence[index] * 256 + i2c_sequence[index+1];
if (len == 0x0000) {
/* RESET command */
result = xc_reset(fe);
@@ -329,15 +330,17 @@ static int xc_load_i2c_sequence(struct dvb_frontend *fe, const u8 *i2c_sequence)
buf[1] = i2c_sequence[index + 1];
pos = 2;
while (pos < len) {
- if ((len - pos) > XC_MAX_I2C_WRITE_LENGTH - 2) {
- nbytes_to_send = XC_MAX_I2C_WRITE_LENGTH;
- } else {
+ if ((len - pos) > XC_MAX_I2C_WRITE_LENGTH - 2)
+ nbytes_to_send =
+ XC_MAX_I2C_WRITE_LENGTH;
+ else
nbytes_to_send = (len - pos + 2);
+ for (i = 2; i < nbytes_to_send; i++) {
+ buf[i] = i2c_sequence[index + pos +
+ i - 2];
}
- for (i=2; i<nbytes_to_send; i++) {
- buf[i] = i2c_sequence[index + pos + i - 2];
- }
- result = xc_send_i2c_data(priv, buf, nbytes_to_send);
+ result = xc_send_i2c_data(priv, buf,
+ nbytes_to_send);
if (result != XC_RESULT_SUCCESS)
return result;
@@ -386,8 +389,7 @@ static int xc_SetSignalSource(struct xc5000_priv *priv, u16 rf_mode)
dprintk(1, "%s(%d) Source = %s\n", __func__, rf_mode,
rf_mode == XC_RF_MODE_AIR ? "ANTENNA" : "CABLE");
- if ((rf_mode != XC_RF_MODE_AIR) && (rf_mode != XC_RF_MODE_CABLE))
- {
+ if ((rf_mode != XC_RF_MODE_AIR) && (rf_mode != XC_RF_MODE_CABLE)) {
rf_mode = XC_RF_MODE_CABLE;
printk(KERN_ERR
"%s(), Invalid mode, defaulting to CABLE",
@@ -579,13 +581,13 @@ static int xc5000_readregs(struct xc5000_priv *priv, u8 *buf, u8 len)
.flags = I2C_M_RD, .buf = buf, .len = len };
if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) {
- printk(KERN_ERR "xc5000 I2C read failed (len=%i)\n",(int)len);
+ printk(KERN_ERR "xc5000 I2C read failed (len=%i)\n", (int)len);
return -EREMOTEIO;
}
return 0;
}
-static int xc5000_fwupload(struct dvb_frontend* fe)
+static int xc5000_fwupload(struct dvb_frontend *fe)
{
struct xc5000_priv *priv = fe->tuner_priv;
const struct firmware *fw;
@@ -595,7 +597,8 @@ static int xc5000_fwupload(struct dvb_frontend* fe)
printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n",
XC5000_DEFAULT_FIRMWARE);
- ret = request_firmware(&fw, XC5000_DEFAULT_FIRMWARE, &priv->i2c_props.adap->dev);
+ ret = request_firmware(&fw, XC5000_DEFAULT_FIRMWARE,
+ &priv->i2c_props.adap->dev);
if (ret) {
printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n");
ret = XC_RESULT_RESET_FAILURE;
@@ -611,7 +614,7 @@ static int xc5000_fwupload(struct dvb_frontend* fe)
ret = XC_RESULT_RESET_FAILURE;
} else {
printk(KERN_INFO "xc5000: firmware upload\n");
- ret = xc_load_i2c_sequence(fe, fw->data );
+ ret = xc_load_i2c_sequence(fe, fw->data);
}
out:
@@ -670,7 +673,7 @@ static int xc5000_set_params(struct dvb_frontend *fe,
dprintk(1, "%s() frequency=%d (Hz)\n", __func__, params->frequency);
- switch(params->u.vsb.modulation) {
+ switch (params->u.vsb.modulation) {
case VSB_8:
case VSB_16:
dprintk(1, "%s() VSB modulation\n", __func__);
@@ -767,42 +770,42 @@ static int xc5000_set_analog_params(struct dvb_frontend *fe,
/* FIX ME: Some video standards may have several possible audio
standards. We simply default to one of them here.
*/
- if(params->std & V4L2_STD_MN) {
+ if (params->std & V4L2_STD_MN) {
/* default to BTSC audio standard */
priv->video_standard = MN_NTSC_PAL_BTSC;
goto tune_channel;
}
- if(params->std & V4L2_STD_PAL_BG) {
+ if (params->std & V4L2_STD_PAL_BG) {
/* default to NICAM audio standard */
priv->video_standard = BG_PAL_NICAM;
goto tune_channel;
}
- if(params->std & V4L2_STD_PAL_I) {
+ if (params->std & V4L2_STD_PAL_I) {
/* default to NICAM audio standard */
priv->video_standard = I_PAL_NICAM;
goto tune_channel;
}
- if(params->std & V4L2_STD_PAL_DK) {
+ if (params->std & V4L2_STD_PAL_DK) {
/* default to NICAM audio standard */
priv->video_standard = DK_PAL_NICAM;
goto tune_channel;
}
- if(params->std & V4L2_STD_SECAM_DK) {
+ if (params->std & V4L2_STD_SECAM_DK) {
/* default to A2 DK1 audio standard */
priv->video_standard = DK_SECAM_A2DK1;
goto tune_channel;
}
- if(params->std & V4L2_STD_SECAM_L) {
+ if (params->std & V4L2_STD_SECAM_L) {
priv->video_standard = L_SECAM_NICAM;
goto tune_channel;
}
- if(params->std & V4L2_STD_SECAM_LC) {
+ if (params->std & V4L2_STD_SECAM_LC) {
priv->video_standard = LC_SECAM_NICAM;
goto tune_channel;
}
@@ -810,7 +813,7 @@ static int xc5000_set_analog_params(struct dvb_frontend *fe,
tune_channel:
ret = xc_SetSignalSource(priv, priv->rf_mode);
if (ret != XC_RESULT_SUCCESS) {
- printk(KERN_ERR
+ printk(KERN_ERR
"xc5000: xc_SetSignalSource(%d) failed\n",
priv->rf_mode);
return -EREMOTEIO;
@@ -882,7 +885,7 @@ static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe)
* I2C transactions until calibration is complete. This way we
* don't have to rely on clock stretching working.
*/
- xc_wait( 100 );
+ xc_wait(100);
/* Default to "CABLE" mode */
ret |= xc_write_reg(priv, XREG_SIGNALSOURCE, XC_RF_MODE_CABLE);
@@ -904,15 +907,13 @@ static int xc5000_sleep(struct dvb_frontend *fe)
*/
ret = xc_shutdown(priv);
- if(ret != XC_RESULT_SUCCESS) {
+ if (ret != XC_RESULT_SUCCESS) {
printk(KERN_ERR
"xc5000: %s() unable to shutdown tuner\n",
__func__);
return -EREMOTEIO;
- }
- else {
+ } else
return XC_RESULT_SUCCESS;
- }
}
static int xc5000_init(struct dvb_frontend *fe)
@@ -1008,7 +1009,7 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != 0)
goto fail;
- switch(id) {
+ switch (id) {
case XC_PRODUCT_ID_FW_LOADED:
printk(KERN_INFO
"xc5000: Successfully identified at address 0x%02x\n",
diff --git a/linux/drivers/media/common/tuners/xc5000.h b/linux/drivers/media/common/tuners/xc5000.h
index cf1a558e0..f4c146698 100644
--- a/linux/drivers/media/common/tuners/xc5000.h
+++ b/linux/drivers/media/common/tuners/xc5000.h
@@ -45,17 +45,17 @@ struct xc5000_config {
#if defined(CONFIG_MEDIA_TUNER_XC5000) || \
(defined(CONFIG_MEDIA_TUNER_XC5000_MODULE) && defined(MODULE))
-extern struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe,
+extern struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c,
struct xc5000_config *cfg);
#else
-static inline struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe,
+static inline struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c,
struct xc5000_config *cfg)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
-#endif // CONFIG_MEDIA_TUNER_XC5000
+#endif
-#endif // __XC5000_H__
+#endif
diff --git a/linux/drivers/media/dvb/Kconfig b/linux/drivers/media/dvb/Kconfig
index 0bcd85257..40ebde53b 100644
--- a/linux/drivers/media/dvb/Kconfig
+++ b/linux/drivers/media/dvb/Kconfig
@@ -2,6 +2,19 @@
# DVB device configuration
#
+config DVB_DYNAMIC_MINORS
+ bool "Dynamic DVB minor allocation"
+ depends on DVB_CORE
+ default n
+ help
+ If you say Y here, the DVB subsystem will use dynamic minor
+ allocation for any device that uses the DVB major number.
+ This means that you can have more than 4 of a single type
+ of device (like demuxes and frontends) per adapter, but udev
+ will be required to manage the device nodes.
+
+ If you are unsure about this, say N here.
+
menuconfig DVB_CAPTURE_DRIVERS
bool "DVB/ATSC adapters"
depends on DVB_CORE
diff --git a/linux/drivers/media/dvb/dm1105/dm1105.c b/linux/drivers/media/dvb/dm1105/dm1105.c
index 07ebe639f..100a7f661 100644
--- a/linux/drivers/media/dvb/dm1105/dm1105.c
+++ b/linux/drivers/media/dvb/dm1105/dm1105.c
@@ -19,7 +19,6 @@
*
*/
-#include <linux/version.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/kernel.h>
@@ -368,11 +367,7 @@ static int __devinit dm1105dvb_dma_map(struct dm1105dvb *dm1105dvb)
{
dm1105dvb->ts_buf = pci_alloc_consistent(dm1105dvb->pdev, 6*DM1105_DMA_BYTES, &dm1105dvb->dma_addr);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
- return pci_dma_mapping_error(dm1105dvb->dma_addr);
-#else
- return pci_dma_mapping_error(dm1105dvb->pdev, dm1105dvb->dma_addr);
-#endif
+ return !dm1105dvb->ts_buf;
}
static void dm1105dvb_dma_unmap(struct dm1105dvb *dm1105dvb)
@@ -380,7 +375,7 @@ static void dm1105dvb_dma_unmap(struct dm1105dvb *dm1105dvb)
pci_free_consistent(dm1105dvb->pdev, 6*DM1105_DMA_BYTES, dm1105dvb->ts_buf, dm1105dvb->dma_addr);
}
-static void __devinit dm1105dvb_enable_irqs(struct dm1105dvb *dm1105dvb)
+static void dm1105dvb_enable_irqs(struct dm1105dvb *dm1105dvb)
{
outb(INTMAK_ALLMASK, dm_io_mem(DM1105_INTMAK));
outb(1, dm_io_mem(DM1105_CR));
@@ -603,6 +598,18 @@ static void dm1105dvb_hw_exit(struct dm1105dvb *dm1105dvb)
dm1105dvb_dma_unmap(dm1105dvb);
}
+static struct stv0299_config sharp_z0194a_config = {
+ .demod_address = 0x68,
+ .inittab = sharp_z0194a_inittab,
+ .mclk = 88000000UL,
+ .invert = 1,
+ .skip_reinit = 0,
+ .lock_output = STV0299_LOCKOUTPUT_1,
+ .volt13_op0_op1 = STV0299_VOLT13_OP1,
+ .min_delay_ms = 100,
+ .set_symbol_rate = sharp_z0194a_set_symbol_rate,
+};
+
static struct stv0288_config earda_config = {
.demod_address = 0x68,
.min_delay_ms = 100,
diff --git a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c
index 51fb82edc..e7adf9f47 100644
--- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -133,6 +133,7 @@ struct dvb_frontend_private {
unsigned int step_size;
int quality;
unsigned int check_wrapped;
+ enum dvbfe_search algo_status;
};
static void dvb_frontend_wakeup(struct dvb_frontend *fe);
@@ -228,6 +229,8 @@ static void dvb_frontend_init(struct dvb_frontend *fe)
if (fe->ops.init)
fe->ops.init(fe);
if (fe->ops.tuner_ops.init) {
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
fe->ops.tuner_ops.init(fe);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
@@ -519,6 +522,8 @@ static int dvb_frontend_thread(void *data)
struct dvb_frontend_private *fepriv = fe->frontend_priv;
unsigned long timeout;
fe_status_t s;
+ enum dvbfe_algo algo;
+
struct dvb_frontend_parameters *params;
dprintk("%s\n", __func__);
@@ -571,29 +576,88 @@ restart:
/* do an iteration of the tuning loop */
if (fe->ops.get_frontend_algo) {
- if (fe->ops.get_frontend_algo(fe) == FE_ALGO_HW) {
- /* have we been asked to retune? */
- params = NULL;
+ algo = fe->ops.get_frontend_algo(fe);
+ switch (algo) {
+ case DVBFE_ALGO_HW:
+ dprintk("%s: Frontend ALGO = DVBFE_ALGO_HW\n", __func__);
+ params = NULL; /* have we been asked to RETUNE ? */
+
if (fepriv->state & FESTATE_RETUNE) {
+ dprintk("%s: Retune requested, FESTATE_RETUNE\n", __func__);
params = &fepriv->parameters;
fepriv->state = FESTATE_TUNED;
}
- fe->ops.tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s);
+ if (fe->ops.tune)
+ fe->ops.tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s);
+
if (s != fepriv->status) {
+ dprintk("%s: state changed, adding current state\n", __func__);
dvb_frontend_add_event(fe, s);
fepriv->status = s;
}
- } else
+ break;
+ case DVBFE_ALGO_SW:
+ dprintk("%s: Frontend ALGO = DVBFE_ALGO_SW\n", __func__);
dvb_frontend_swzigzag(fe);
- } else
+ break;
+ case DVBFE_ALGO_CUSTOM:
+ params = NULL; /* have we been asked to RETUNE ? */
+ dprintk("%s: Frontend ALGO = DVBFE_ALGO_CUSTOM, state=%d\n", __func__, fepriv->state);
+ if (fepriv->state & FESTATE_RETUNE) {
+ dprintk("%s: Retune requested, FESTAT_RETUNE\n", __func__);
+ params = &fepriv->parameters;
+ fepriv->state = FESTATE_TUNED;
+ }
+ /* Case where we are going to search for a carrier
+ * User asked us to retune again for some reason, possibly
+ * requesting a search with a new set of parameters
+ */
+ if (fepriv->algo_status & DVBFE_ALGO_SEARCH_AGAIN) {
+ if (fe->ops.search) {
+ fepriv->algo_status = fe->ops.search(fe, &fepriv->parameters);
+ /* We did do a search as was requested, the flags are
+ * now unset as well and has the flags wrt to search.
+ */
+ } else {
+ fepriv->algo_status &= ~DVBFE_ALGO_SEARCH_AGAIN;
+ }
+ }
+ /* Track the carrier if the search was successful */
+ if (fepriv->algo_status == DVBFE_ALGO_SEARCH_SUCCESS) {
+ if (fe->ops.track)
+ fe->ops.track(fe, &fepriv->parameters);
+ } else {
+ fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
+ fepriv->delay = HZ / 2;
+ }
+ fe->ops.read_status(fe, &s);
+ if (s != fepriv->status) {
+ dvb_frontend_add_event(fe, s); /* update event list */
+ fepriv->status = s;
+ if (!(s & FE_HAS_LOCK)) {
+ fepriv->delay = HZ / 10;
+ fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
+ } else {
+ fepriv->delay = 60 * HZ;
+ }
+ }
+ break;
+ default:
+ dprintk("%s: UNDEFINED ALGO !\n", __func__);
+ break;
+ }
+ } else {
dvb_frontend_swzigzag(fe);
+ }
}
if (dvb_powerdown_on_sleep) {
if (fe->ops.set_voltage)
fe->ops.set_voltage(fe, SEC_VOLTAGE_OFF);
if (fe->ops.tuner_ops.sleep) {
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
fe->ops.tuner_ops.sleep(fe);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
@@ -973,36 +1037,37 @@ void dtv_property_dump(struct dtv_property *tvp)
int i;
if (tvp->cmd <= 0 || tvp->cmd > DTV_MAX_COMMAND) {
- printk("%s: tvp.cmd = 0x%08x (undefined/unknown/invalid)\n",
+ printk(KERN_WARNING "%s: tvp.cmd = 0x%08x undefined\n",
__func__, tvp->cmd);
return;
}
- printk("%s() tvp.cmd = 0x%08x (%s)\n"
- ,__FUNCTION__
+ dprintk("%s() tvp.cmd = 0x%08x (%s)\n"
+ ,__func__
,tvp->cmd
,dtv_cmds[ tvp->cmd ].name);
if(dtv_cmds[ tvp->cmd ].buffer) {
- printk("%s() tvp.u.buffer.len = 0x%02x\n"
- ,__FUNCTION__
+ dprintk("%s() tvp.u.buffer.len = 0x%02x\n"
+ ,__func__
,tvp->u.buffer.len);
for(i = 0; i < tvp->u.buffer.len; i++)
- printk("%s() tvp.u.buffer.data[0x%02x] = 0x%02x\n"
- ,__FUNCTION__
+ dprintk("%s() tvp.u.buffer.data[0x%02x] = 0x%02x\n"
+ ,__func__
,i
,tvp->u.buffer.data[i]);
} else
- printk("%s() tvp.u.data = 0x%08x\n", __FUNCTION__, tvp->u.data);
+ dprintk("%s() tvp.u.data = 0x%08x\n", __func__, tvp->u.data);
}
int is_legacy_delivery_system(fe_delivery_system_t s)
{
if((s == SYS_UNDEFINED) || (s == SYS_DVBC_ANNEX_AC) ||
- (s == SYS_DVBC_ANNEX_B) || (s == SYS_DVBT) || (s == SYS_DVBS))
+ (s == SYS_DVBC_ANNEX_B) || (s == SYS_DVBT) || (s == SYS_DVBS) ||
+ (s == SYS_ATSC))
return 1;
return 0;
@@ -1016,8 +1081,6 @@ void dtv_property_cache_sync(struct dvb_frontend *fe, struct dvb_frontend_parame
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
- printk("%s()\n", __FUNCTION__);
-
c->frequency = p->frequency;
c->inversion = p->inversion;
@@ -1072,27 +1135,25 @@ void dtv_property_legacy_params_sync(struct dvb_frontend *fe)
struct dvb_frontend_private *fepriv = fe->frontend_priv;
struct dvb_frontend_parameters *p = &fepriv->parameters;
- printk("%s()\n", __FUNCTION__);
-
p->frequency = c->frequency;
p->inversion = c->inversion;
switch (fe->ops.info.type) {
case FE_QPSK:
- printk("%s() Preparing QPSK req\n", __FUNCTION__);
+ dprintk("%s() Preparing QPSK req\n", __func__);
p->u.qpsk.symbol_rate = c->symbol_rate;
p->u.qpsk.fec_inner = c->fec_inner;
c->delivery_system = SYS_DVBS;
break;
case FE_QAM:
- printk("%s() Preparing QAM req\n", __FUNCTION__);
+ dprintk("%s() Preparing QAM req\n", __func__);
p->u.qam.symbol_rate = c->symbol_rate;
p->u.qam.fec_inner = c->fec_inner;
p->u.qam.modulation = c->modulation;
c->delivery_system = SYS_DVBC_ANNEX_AC;
break;
case FE_OFDM:
- printk("%s() Preparing OFDM req\n", __FUNCTION__);
+ dprintk("%s() Preparing OFDM req\n", __func__);
if (c->bandwidth_hz == 6000000)
p->u.ofdm.bandwidth = BANDWIDTH_6_MHZ;
else if (c->bandwidth_hz == 7000000)
@@ -1110,7 +1171,7 @@ void dtv_property_legacy_params_sync(struct dvb_frontend *fe)
c->delivery_system = SYS_DVBT;
break;
case FE_ATSC:
- printk("%s() Preparing VSB req\n", __FUNCTION__);
+ dprintk("%s() Preparing VSB req\n", __func__);
p->u.vsb.modulation = c->modulation;
if ((c->modulation == VSB_8) || (c->modulation == VSB_16))
c->delivery_system = SYS_ATSC;
@@ -1129,8 +1190,6 @@ void dtv_property_adv_params_sync(struct dvb_frontend *fe)
struct dvb_frontend_private *fepriv = fe->frontend_priv;
struct dvb_frontend_parameters *p = &fepriv->parameters;
- printk("%s()\n", __FUNCTION__);
-
p->frequency = c->frequency;
p->inversion = c->inversion;
@@ -1164,19 +1223,17 @@ void dtv_property_cache_submit(struct dvb_frontend *fe)
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
- printk("%s()\n", __FUNCTION__);
-
/* For legacy delivery systems we don't need the delivery_system to
* be specified, but we populate the older structures from the cache
* so we can call set_frontend on older drivers.
*/
if(is_legacy_delivery_system(c->delivery_system)) {
- printk("%s() legacy, modulation = %d\n", __FUNCTION__, c->modulation);
+ dprintk("%s() legacy, modulation = %d\n", __func__, c->modulation);
dtv_property_legacy_params_sync(fe);
} else {
- printk("%s() adv, modulation = %d\n", __FUNCTION__, c->modulation);
+ dprintk("%s() adv, modulation = %d\n", __func__, c->modulation);
/* For advanced delivery systems / modulation types ...
* we seed the lecacy dvb_frontend_parameters structure
@@ -1198,8 +1255,6 @@ int dtv_property_process_get(struct dvb_frontend *fe, struct dtv_property *tvp,
{
int r = 0;
- printk("%s()\n", __FUNCTION__);
-
dtv_property_dump(tvp);
/* Allow the frontend to validate incoming properties */
@@ -1309,7 +1364,6 @@ int dtv_property_process_set(struct dvb_frontend *fe, struct dtv_property *tvp,
{
int r = 0;
struct dvb_frontend_private *fepriv = fe->frontend_priv;
- printk("%s()\n", __FUNCTION__);
dtv_property_dump(tvp);
/* Allow the frontend to validate incoming properties */
@@ -1324,7 +1378,7 @@ int dtv_property_process_set(struct dvb_frontend *fe, struct dtv_property *tvp,
/* Reset a cache of data specific to the frontend here. This does
* not effect hardware.
*/
- printk("%s() Flushing property cache\n", __FUNCTION__);
+ dprintk("%s() Flushing property cache\n", __func__);
memset(&fe->dtv_property_cache, 0, sizeof(struct dtv_frontend_properties));
fe->dtv_property_cache.state = tvp->cmd;
fe->dtv_property_cache.delivery_system = SYS_UNDEFINED;
@@ -1335,9 +1389,12 @@ int dtv_property_process_set(struct dvb_frontend *fe, struct dtv_property *tvp,
* ioctl.
*/
fe->dtv_property_cache.state = tvp->cmd;
- printk("%s() Finalised property cache\n", __FUNCTION__);
+ dprintk("%s() Finalised property cache\n", __func__);
dtv_property_cache_submit(fe);
+ /* Request the search algorithm to search */
+ fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
+
r |= dvb_frontend_ioctl_legacy(inode, file, FE_SET_FRONTEND,
&fepriv->parameters);
break;
@@ -1455,12 +1512,10 @@ static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file,
dprintk("%s\n", __func__);
if(cmd == FE_SET_PROPERTY) {
- printk("%s() FE_SET_PROPERTY\n", __FUNCTION__);
-
tvps = (struct dtv_properties __user *)parg;
- printk("%s() properties.num = %d\n", __FUNCTION__, tvps->num);
- printk("%s() properties.props = %p\n", __FUNCTION__, tvps->props);
+ dprintk("%s() properties.num = %d\n", __func__, tvps->num);
+ dprintk("%s() properties.props = %p\n", __func__, tvps->props);
/* Put an arbitrary limit on the number of messages that can
* be sent at once */
@@ -1484,18 +1539,16 @@ static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file,
err |= (tvp + i)->result;
}
- if(fe->dtv_property_cache.state == DTV_TUNE) {
- printk("%s() Property cache is full, tuning\n", __FUNCTION__);
- }
+ if(fe->dtv_property_cache.state == DTV_TUNE)
+ dprintk("%s() Property cache is full, tuning\n", __func__);
} else
if(cmd == FE_GET_PROPERTY) {
- printk("%s() FE_GET_PROPERTY\n", __FUNCTION__);
tvps = (struct dtv_properties __user *)parg;
- printk("%s() properties.num = %d\n", __FUNCTION__, tvps->num);
- printk("%s() properties.props = %p\n", __FUNCTION__, tvps->props);
+ dprintk("%s() properties.num = %d\n", __func__, tvps->num);
+ dprintk("%s() properties.props = %p\n", __func__, tvps->props);
/* Put an arbitrary limit on the number of messages that can
* be sent at once */
@@ -1825,39 +1878,46 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
struct dvb_frontend *fe = dvbdev->priv;
struct dvb_frontend_private *fepriv = fe->frontend_priv;
struct dvb_adapter *adapter = fe->dvb;
- struct dvb_device *mfedev;
- struct dvb_frontend *mfe;
- struct dvb_frontend_private *mfepriv;
- int mferetry;
int ret;
dprintk ("%s\n", __func__);
if (adapter->mfe_shared) {
mutex_lock (&adapter->mfe_lock);
- if (adapter->mfe_dvbdev != dvbdev) {
- if (adapter->mfe_dvbdev) {
- mfedev = adapter->mfe_dvbdev;
- mfe = mfedev->priv;
- mfepriv = mfe->frontend_priv;
- mutex_unlock (&adapter->mfe_lock);
- mferetry = (dvb_mfe_wait_time << 1);
- while (mferetry-- && (mfedev->users != -1 || mfepriv->thread != NULL)) {
- if(msleep_interruptible(500)) {
- if(signal_pending(current))
- return -EINTR;
- }
+
+ if (adapter->mfe_dvbdev == NULL)
+ adapter->mfe_dvbdev = dvbdev;
+
+ else if (adapter->mfe_dvbdev != dvbdev) {
+ struct dvb_device
+ *mfedev = adapter->mfe_dvbdev;
+ struct dvb_frontend
+ *mfe = mfedev->priv;
+ struct dvb_frontend_private
+ *mfepriv = mfe->frontend_priv;
+ int mferetry = (dvb_mfe_wait_time << 1);
+
+ mutex_unlock (&adapter->mfe_lock);
+ while (mferetry-- && (mfedev->users != -1 ||
+ mfepriv->thread != NULL)) {
+ if(msleep_interruptible(500)) {
+ if(signal_pending(current))
+ return -EINTR;
}
- mutex_lock (&adapter->mfe_lock);
+ }
+
+ mutex_lock (&adapter->mfe_lock);
+ if(adapter->mfe_dvbdev != dvbdev) {
mfedev = adapter->mfe_dvbdev;
mfe = mfedev->priv;
mfepriv = mfe->frontend_priv;
- if (mfedev->users != -1 || mfepriv->thread != NULL) {
- ret = -EBUSY;
- goto err0;
+ if (mfedev->users != -1 ||
+ mfepriv->thread != NULL) {
+ mutex_unlock (&adapter->mfe_lock);
+ return -EBUSY;
}
+ adapter->mfe_dvbdev = dvbdev;
}
- adapter->mfe_dvbdev = dvbdev;
}
}
diff --git a/linux/drivers/media/dvb/dvb-core/dvb_frontend.h b/linux/drivers/media/dvb/dvb-core/dvb_frontend.h
index 569b72a96..cff26dd66 100644
--- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.h
+++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.h
@@ -69,6 +69,125 @@ struct analog_parameters {
u64 std;
};
+enum dvbfe_modcod {
+ DVBFE_MODCOD_DUMMY_PLFRAME = 0,
+ DVBFE_MODCOD_QPSK_1_4,
+ DVBFE_MODCOD_QPSK_1_3,
+ DVBFE_MODCOD_QPSK_2_5,
+ DVBFE_MODCOD_QPSK_1_2,
+ DVBFE_MODCOD_QPSK_3_5,
+ DVBFE_MODCOD_QPSK_2_3,
+ DVBFE_MODCOD_QPSK_3_4,
+ DVBFE_MODCOD_QPSK_4_5,
+ DVBFE_MODCOD_QPSK_5_6,
+ DVBFE_MODCOD_QPSK_8_9,
+ DVBFE_MODCOD_QPSK_9_10,
+ DVBFE_MODCOD_8PSK_3_5,
+ DVBFE_MODCOD_8PSK_2_3,
+ DVBFE_MODCOD_8PSK_3_4,
+ DVBFE_MODCOD_8PSK_5_6,
+ DVBFE_MODCOD_8PSK_8_9,
+ DVBFE_MODCOD_8PSK_9_10,
+ DVBFE_MODCOD_16APSK_2_3,
+ DVBFE_MODCOD_16APSK_3_4,
+ DVBFE_MODCOD_16APSK_4_5,
+ DVBFE_MODCOD_16APSK_5_6,
+ DVBFE_MODCOD_16APSK_8_9,
+ DVBFE_MODCOD_16APSK_9_10,
+ DVBFE_MODCOD_32APSK_3_4,
+ DVBFE_MODCOD_32APSK_4_5,
+ DVBFE_MODCOD_32APSK_5_6,
+ DVBFE_MODCOD_32APSK_8_9,
+ DVBFE_MODCOD_32APSK_9_10,
+ DVBFE_MODCOD_RESERVED_1,
+ DVBFE_MODCOD_BPSK_1_3,
+ DVBFE_MODCOD_BPSK_1_4,
+ DVBFE_MODCOD_RESERVED_2
+};
+
+enum tuner_param {
+ DVBFE_TUNER_FREQUENCY = (1 << 0),
+ DVBFE_TUNER_TUNERSTEP = (1 << 1),
+ DVBFE_TUNER_IFFREQ = (1 << 2),
+ DVBFE_TUNER_BANDWIDTH = (1 << 3),
+ DVBFE_TUNER_REFCLOCK = (1 << 4),
+ DVBFE_TUNER_IQSENSE = (1 << 5),
+ DVBFE_TUNER_DUMMY = (1 << 31)
+};
+
+/*
+ * ALGO_HW: (Hardware Algorithm)
+ * ----------------------------------------------------------------
+ * Devices that support this algorithm do everything in hardware
+ * and no software support is needed to handle them.
+ * Requesting these devices to LOCK is the only thing required,
+ * device is supposed to do everything in the hardware.
+ *
+ * ALGO_SW: (Software Algorithm)
+ * ----------------------------------------------------------------
+ * These are dumb devices, that require software to do everything
+ *
+ * ALGO_CUSTOM: (Customizable Agorithm)
+ * ----------------------------------------------------------------
+ * Devices having this algorithm can be customized to have specific
+ * algorithms in the frontend driver, rather than simply doing a
+ * software zig-zag. In this case the zigzag maybe hardware assisted
+ * or it maybe completely done in hardware. In all cases, usage of
+ * this algorithm, in conjunction with the search and track
+ * callbacks, utilizes the driver specific algorithm.
+ *
+ * ALGO_RECOVERY: (Recovery Algorithm)
+ * ----------------------------------------------------------------
+ * These devices have AUTO recovery capabilities from LOCK failure
+ */
+enum dvbfe_algo {
+ DVBFE_ALGO_HW = (1 << 0),
+ DVBFE_ALGO_SW = (1 << 1),
+ DVBFE_ALGO_CUSTOM = (1 << 2),
+ DVBFE_ALGO_RECOVERY = (1 << 31)
+};
+
+struct tuner_state {
+ u32 frequency;
+ u32 tunerstep;
+ u32 ifreq;
+ u32 bandwidth;
+ u32 iqsense;
+ u32 refclock;
+};
+
+/*
+ * search callback possible return status
+ *
+ * DVBFE_ALGO_SEARCH_SUCCESS
+ * The frontend search algorithm completed and returned succesfully
+ *
+ * DVBFE_ALGO_SEARCH_ASLEEP
+ * The frontend search algorithm is sleeping
+ *
+ * DVBFE_ALGO_SEARCH_FAILED
+ * The frontend search for a signal failed
+ *
+ * DVBFE_ALGO_SEARCH_INVALID
+ * The frontend search algorith was probably supplied with invalid
+ * parameters and the search is an invalid one
+ *
+ * DVBFE_ALGO_SEARCH_ERROR
+ * The frontend search algorithm failed due to some error
+ *
+ * DVBFE_ALGO_SEARCH_AGAIN
+ * The frontend search algorithm was requested to search again
+ */
+enum dvbfe_search {
+ DVBFE_ALGO_SEARCH_SUCCESS = (1 << 0),
+ DVBFE_ALGO_SEARCH_ASLEEP = (1 << 1),
+ DVBFE_ALGO_SEARCH_FAILED = (1 << 2),
+ DVBFE_ALGO_SEARCH_INVALID = (1 << 3),
+ DVBFE_ALGO_SEARCH_AGAIN = (1 << 4),
+ DVBFE_ALGO_SEARCH_ERROR = (1 << 31),
+};
+
+
struct dvb_tuner_ops {
struct dvb_tuner_info info;
@@ -99,6 +218,13 @@ struct dvb_tuner_ops {
* tuners which require sophisticated tuning loops, controlling each parameter seperately. */
int (*set_frequency)(struct dvb_frontend *fe, u32 frequency);
int (*set_bandwidth)(struct dvb_frontend *fe, u32 bandwidth);
+
+ /*
+ * These are provided seperately from set_params in order to facilitate silicon
+ * tuners which require sophisticated tuning loops, controlling each parameter seperately.
+ */
+ int (*set_state)(struct dvb_frontend *fe, enum tuner_param param, struct tuner_state *state);
+ int (*get_state)(struct dvb_frontend *fe, enum tuner_param param, struct tuner_state *state);
};
struct analog_demod_info {
@@ -142,7 +268,7 @@ struct dvb_frontend_ops {
unsigned int *delay,
fe_status_t *status);
/* get frontend tuning algorithm from the module */
- int (*get_frontend_algo)(struct dvb_frontend *fe);
+ enum dvbfe_algo (*get_frontend_algo)(struct dvb_frontend *fe);
/* these two are only used for the swzigzag code */
int (*set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
@@ -167,6 +293,12 @@ struct dvb_frontend_ops {
int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable);
int (*ts_bus_ctrl)(struct dvb_frontend* fe, int acquire);
+ /* These callbacks are for devices that implement their own
+ * tuning algorithms, rather than a simple swzigzag
+ */
+ enum dvbfe_search (*search)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p);
+ int (*track)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p);
+
struct dvb_tuner_ops tuner_ops;
struct analog_demod_ops analog_ops;
diff --git a/linux/drivers/media/dvb/dvb-core/dvbdev.c b/linux/drivers/media/dvb/dvb-core/dvbdev.c
index 422af5a0d..fa1adf9dd 100644
--- a/linux/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/linux/drivers/media/dvb/dvb-core/dvbdev.c
@@ -51,33 +51,27 @@ static const char * const dnames[] = {
"net", "osd"
};
+#ifdef CONFIG_DVB_DYNAMIC_MINORS
+#define MAX_DVB_MINORS 256
+#define DVB_MAX_IDS MAX_DVB_MINORS
+#else
#define DVB_MAX_IDS 4
#define nums2minor(num,type,id) ((num << 6) | (id << 4) | type)
#define MAX_DVB_MINORS (DVB_MAX_ADAPTERS*64)
+#endif
static struct class *dvb_class;
-static struct dvb_device* dvbdev_find_device (int minor)
-{
- struct dvb_adapter *adap;
-
- list_for_each_entry(adap, &dvb_adapter_list, list_head) {
- struct dvb_device *dev;
- list_for_each_entry(dev, &adap->device_list, list_head)
- if (nums2minor(adap->num, dev->type, dev->id) == minor)
- return dev;
- }
-
- return NULL;
-}
-
+static struct dvb_device *dvb_minors[MAX_DVB_MINORS];
+static DECLARE_RWSEM(minor_rwsem);
static int dvb_device_open(struct inode *inode, struct file *file)
{
struct dvb_device *dvbdev;
lock_kernel();
- dvbdev = dvbdev_find_device (iminor(inode));
+ down_read(&minor_rwsem);
+ dvbdev = dvb_minors[iminor(inode)];
if (dvbdev && dvbdev->fops) {
int err = 0;
@@ -97,9 +91,11 @@ static int dvb_device_open(struct inode *inode, struct file *file)
file->f_op = fops_get(old_fops);
}
fops_put(old_fops);
+ up_read(&minor_rwsem);
unlock_kernel();
return err;
}
+ up_read(&minor_rwsem);
unlock_kernel();
return -ENODEV;
}
@@ -201,6 +197,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
#else
struct class_device *clsdev;
#endif
+ int minor;
int id;
mutex_lock(&dvbdev_register_lock);
@@ -240,15 +237,39 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
list_add_tail (&dvbdev->list_head, &adap->device_list);
+ down_write(&minor_rwsem);
+#ifdef CONFIG_DVB_DYNAMIC_MINORS
+ for (minor = 0; minor < MAX_DVB_MINORS; minor++)
+ if (dvb_minors[minor] == NULL)
+ break;
+
+ if (minor == MAX_DVB_MINORS) {
+ kfree(dvbdevfops);
+ kfree(dvbdev);
+ mutex_unlock(&dvbdev_register_lock);
+ return -EINVAL;
+ }
+#else
+ minor = nums2minor(adap->num, type, id);
+#endif
+
+ dvbdev->minor = minor;
+ dvb_minors[minor] = dvbdev;
+ up_write(&minor_rwsem);
+
mutex_unlock(&dvbdev_register_lock);
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 26)
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 27)
+ clsdev = device_create(dvb_class, adap->device,
+ MKDEV(DVB_MAJOR, minor),
+ dvbdev, "dvb%d.%s%d", adap->num, dnames[type], id);
+#elif LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 27)
clsdev = device_create_drvdata(dvb_class, adap->device,
- MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
- NULL, "dvb%d.%s%d", adap->num, dnames[type], id);
+ MKDEV(DVB_MAJOR, minor),
+ dvbdev, "dvb%d.%s%d", adap->num, dnames[type], id);
#else
clsdev = device_create(dvb_class, adap->device,
- MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
+ MKDEV(DVB_MAJOR, minor),
"dvb%d.%s%d", adap->num, dnames[type], id);
#endif
if (IS_ERR(clsdev)) {
@@ -258,8 +279,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
}
dprintk(KERN_DEBUG "DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
- adap->num, dnames[type], id, nums2minor(adap->num, type, id),
- nums2minor(adap->num, type, id));
+ adap->num, dnames[type], id, minor, minor);
return 0;
}
@@ -271,8 +291,11 @@ void dvb_unregister_device(struct dvb_device *dvbdev)
if (!dvbdev)
return;
- device_destroy(dvb_class, MKDEV(DVB_MAJOR, nums2minor(dvbdev->adapter->num,
- dvbdev->type, dvbdev->id)));
+ down_write(&minor_rwsem);
+ dvb_minors[dvbdev->minor] = NULL;
+ up_write(&minor_rwsem);
+
+ device_destroy(dvb_class, MKDEV(DVB_MAJOR, dvbdev->minor));
list_del (&dvbdev->list_head);
kfree (dvbdev->fops);
@@ -428,6 +451,17 @@ out:
return err;
}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+ struct dvb_device *dvbdev = dev_get_drvdata(dev);
+
+ add_uevent_var(env, "DVB_DEVICE_NUM=%d", dvbdev->id);
+ add_uevent_var(env, "DVB_ADAPTER_NUM=%d", dvbdev->adapter->num);
+ return 0;
+}
+#endif
+
static int __init init_dvbdev(void)
{
int retval;
@@ -454,6 +488,9 @@ static int __init init_dvbdev(void)
retval = PTR_ERR(dvb_class);
goto error;
}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+ dvb_class->dev_uevent = dvb_uevent;
+#endif
return 0;
error:
diff --git a/linux/drivers/media/dvb/dvb-core/dvbdev.h b/linux/drivers/media/dvb/dvb-core/dvbdev.h
index 574e336ba..dca49cf96 100644
--- a/linux/drivers/media/dvb/dvb-core/dvbdev.h
+++ b/linux/drivers/media/dvb/dvb-core/dvbdev.h
@@ -74,6 +74,7 @@ struct dvb_device {
struct file_operations *fops;
struct dvb_adapter *adapter;
int type;
+ int minor;
u32 id;
/* in theory, 'users' can vanish now,
diff --git a/linux/drivers/media/dvb/dvb-usb/Kconfig b/linux/drivers/media/dvb/dvb-usb/Kconfig
index 3c13bcfa6..62b68c291 100644
--- a/linux/drivers/media/dvb/dvb-usb/Kconfig
+++ b/linux/drivers/media/dvb/dvb-usb/Kconfig
@@ -261,7 +261,7 @@ config DVB_USB_DW2102
Say Y here to support the DvbWorld DVB-S/S2 USB2.0 receivers
and the TeVii S650.
-config DVB_USB_CINERGY_T2
+config DVB_USB_CINERGY_T2
tristate "Terratec CinergyT2/qanu USB 2.0 DVB-T receiver"
depends on DVB_USB
help
@@ -283,6 +283,7 @@ config DVB_USB_ANYSEE
config DVB_USB_DTV5100
tristate "AME DTV-5100 USB2.0 DVB-T support"
depends on DVB_USB
+ select DVB_ZL10353 if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE
help
Say Y here to support the AME DTV-5100 USB2.0 DVB-T receiver.
diff --git a/linux/drivers/media/dvb/dvb-usb/af9015.c b/linux/drivers/media/dvb/dvb-usb/af9015.c
index 64d2d0f8c..21e10fa23 100644
--- a/linux/drivers/media/dvb/dvb-usb/af9015.c
+++ b/linux/drivers/media/dvb/dvb-usb/af9015.c
@@ -31,13 +31,13 @@
#include "mc44s80x.h"
#endif
-int dvb_usb_af9015_debug;
+static int dvb_usb_af9015_debug;
module_param_named(debug, dvb_usb_af9015_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
-int dvb_usb_af9015_remote;
+static int dvb_usb_af9015_remote;
module_param_named(remote, dvb_usb_af9015_remote, int, 0644);
MODULE_PARM_DESC(remote, "select remote");
-int dvb_usb_af9015_dual_mode;
+static int dvb_usb_af9015_dual_mode;
module_param_named(dual_mode, dvb_usb_af9015_dual_mode, int, 0644);
MODULE_PARM_DESC(dual_mode, "enable dual mode");
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
@@ -46,7 +46,7 @@ static DEFINE_MUTEX(af9015_usb_mutex);
static struct af9015_config af9015_config;
static struct dvb_usb_device_properties af9015_properties[2];
-int af9015_properties_count = ARRAY_SIZE(af9015_properties);
+static int af9015_properties_count = ARRAY_SIZE(af9015_properties);
static struct af9013_config af9015_af9013_config[] = {
{
@@ -549,7 +549,7 @@ static int af9015_eeprom_dump(struct dvb_usb_device *d)
return 0;
}
-int af9015_download_ir_table(struct dvb_usb_device *d)
+static int af9015_download_ir_table(struct dvb_usb_device *d)
{
int i, packets = 0, ret;
u16 addr = 0x9a56; /* ir-table start address */
@@ -742,7 +742,7 @@ static int af9015_read_config(struct usb_device *udev)
}
} else {
switch (udev->descriptor.idVendor) {
- case USB_VID_LEADTEK:
+ case cpu_to_le16(USB_VID_LEADTEK):
af9015_properties[i].rc_key_map =
af9015_rc_keys_leadtek;
af9015_properties[i].rc_key_map_size =
@@ -752,9 +752,9 @@ static int af9015_read_config(struct usb_device *udev)
af9015_config.ir_table_size =
ARRAY_SIZE(af9015_ir_table_leadtek);
break;
- case USB_VID_VISIONPLUS:
+ case cpu_to_le16(USB_VID_VISIONPLUS):
if (udev->descriptor.idProduct ==
- USB_PID_AZUREWAVE_AD_TU700) {
+ cpu_to_le16(USB_PID_AZUREWAVE_AD_TU700)) {
af9015_properties[i].rc_key_map =
af9015_rc_keys_twinhan;
af9015_properties[i].rc_key_map_size =
@@ -765,7 +765,7 @@ static int af9015_read_config(struct usb_device *udev)
ARRAY_SIZE(af9015_ir_table_twinhan);
}
break;
- case USB_VID_KWORLD_2:
+ case cpu_to_le16(USB_VID_KWORLD_2):
/* TODO: use correct rc keys */
af9015_properties[i].rc_key_map =
af9015_rc_keys_twinhan;
@@ -778,7 +778,7 @@ static int af9015_read_config(struct usb_device *udev)
/* Check USB manufacturer and product strings and try
to determine correct remote in case of chip vendor
reference IDs are used. */
- case USB_VID_AFATECH:
+ case cpu_to_le16(USB_VID_AFATECH):
memset(manufacturer, 0, sizeof(manufacturer));
usb_string(udev, udev->descriptor.iManufacturer,
manufacturer, sizeof(manufacturer));
@@ -806,6 +806,16 @@ static int af9015_read_config(struct usb_device *udev)
ARRAY_SIZE(af9015_ir_table_msi);
}
break;
+ case cpu_to_le16(USB_VID_AVERMEDIA):
+ af9015_properties[i].rc_key_map =
+ af9015_rc_keys_avermedia;
+ af9015_properties[i].rc_key_map_size =
+ ARRAY_SIZE(af9015_rc_keys_avermedia);
+ af9015_config.ir_table =
+ af9015_ir_table_avermedia;
+ af9015_config.ir_table_size =
+ ARRAY_SIZE(af9015_ir_table_avermedia);
+ break;
}
}
}
@@ -999,7 +1009,7 @@ static int af9015_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
}
/* init 2nd I2C adapter */
-int af9015_i2c_init(struct dvb_usb_device *d)
+static int af9015_i2c_init(struct dvb_usb_device *d)
{
int ret;
struct af9015_state *state = d->priv;
@@ -1197,6 +1207,7 @@ static struct usb_device_id af9015_usb_table[] = {
{USB_DEVICE(USB_VID_TELESTAR, USB_PID_TELESTAR_STARSTICK_2)},
{USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A309)},
/* 15 */{USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGI_VOX_MINI_III)},
+ {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U)},
{0},
};
MODULE_DEVICE_TABLE(usb, af9015_usb_table);
@@ -1347,7 +1358,7 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.i2c_algo = &af9015_i2c_algo,
- .num_device_descs = 6,
+ .num_device_descs = 7,
.devices = {
{
.name = "Xtensions XD-380",
@@ -1379,6 +1390,12 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.cold_ids = {&af9015_usb_table[15], NULL},
.warm_ids = {NULL},
},
+ {
+ .name = "KWorld USB DVB-T TV Stick II " \
+ "(VS-DVB-T 395U)",
+ .cold_ids = {&af9015_usb_table[16], NULL},
+ .warm_ids = {NULL},
+ },
}
}
};
@@ -1419,7 +1436,7 @@ static int af9015_usb_probe(struct usb_interface *intf,
return ret;
}
-void af9015_i2c_exit(struct dvb_usb_device *d)
+static void af9015_i2c_exit(struct dvb_usb_device *d)
{
struct af9015_state *state = d->priv;
deb_info("%s: \n", __func__);
diff --git a/linux/drivers/media/dvb/dvb-usb/af9015.h b/linux/drivers/media/dvb/dvb-usb/af9015.h
index 882e8a4b3..1ab86cc6c 100644
--- a/linux/drivers/media/dvb/dvb-usb/af9015.h
+++ b/linux/drivers/media/dvb/dvb-usb/af9015.h
@@ -27,7 +27,6 @@
#define DVB_USB_LOG_PREFIX "af9015"
#include "dvb-usb.h"
-extern int dvb_usb_af9015_debug;
#define deb_info(args...) dprintk(dvb_usb_af9015_debug, 0x01, args)
#define deb_rc(args...) dprintk(dvb_usb_af9015_debug, 0x02, args)
#define deb_xfer(args...) dprintk(dvb_usb_af9015_debug, 0x04, args)
@@ -521,4 +520,80 @@ static u8 af9015_ir_table_kworld[] = {
0x86, 0x6b, 0x23, 0xdc, 0x45, 0x07, 0x00,
};
+/* AverMedia Volar X */
+static struct dvb_usb_rc_key af9015_rc_keys_avermedia[] = {
+ { 0x05, 0x3d, KEY_PROG1 }, /* SOURCE */
+ { 0x05, 0x12, KEY_POWER }, /* POWER */
+ { 0x05, 0x1e, KEY_1 }, /* 1 */
+ { 0x05, 0x1f, KEY_2 }, /* 2 */
+ { 0x05, 0x20, KEY_3 }, /* 3 */
+ { 0x05, 0x21, KEY_4 }, /* 4 */
+ { 0x05, 0x22, KEY_5 }, /* 5 */
+ { 0x05, 0x23, KEY_6 }, /* 6 */
+ { 0x05, 0x24, KEY_7 }, /* 7 */
+ { 0x05, 0x25, KEY_8 }, /* 8 */
+ { 0x05, 0x26, KEY_9 }, /* 9 */
+ { 0x05, 0x3f, KEY_LEFT }, /* L / DISPLAY */
+ { 0x05, 0x27, KEY_0 }, /* 0 */
+ { 0x05, 0x0f, KEY_RIGHT }, /* R / CH RTN */
+ { 0x05, 0x18, KEY_PROG2 }, /* SNAP SHOT */
+ { 0x05, 0x1c, KEY_PROG3 }, /* 16-CH PREV */
+ { 0x05, 0x2d, KEY_VOLUMEDOWN }, /* VOL DOWN */
+ { 0x05, 0x3e, KEY_ZOOM }, /* FULL SCREEN */
+ { 0x05, 0x2e, KEY_VOLUMEUP }, /* VOL UP */
+ { 0x05, 0x10, KEY_MUTE }, /* MUTE */
+ { 0x05, 0x04, KEY_AUDIO }, /* AUDIO */
+ { 0x05, 0x15, KEY_RECORD }, /* RECORD */
+ { 0x05, 0x11, KEY_PLAY }, /* PLAY */
+ { 0x05, 0x16, KEY_STOP }, /* STOP */
+ { 0x05, 0x0c, KEY_PLAYPAUSE }, /* TIMESHIFT / PAUSE */
+ { 0x05, 0x05, KEY_BACK }, /* << / RED */
+ { 0x05, 0x09, KEY_FORWARD }, /* >> / YELLOW */
+ { 0x05, 0x17, KEY_TEXT }, /* TELETEXT */
+ { 0x05, 0x0a, KEY_EPG }, /* EPG */
+ { 0x05, 0x13, KEY_MENU }, /* MENU */
+
+ { 0x05, 0x0e, KEY_CHANNELUP }, /* CH UP */
+ { 0x05, 0x0d, KEY_CHANNELDOWN }, /* CH DOWN */
+ { 0x05, 0x19, KEY_FIRST }, /* |<< / GREEN */
+ { 0x05, 0x08, KEY_LAST }, /* >>| / BLUE */
+};
+
+static u8 af9015_ir_table_avermedia[] = {
+ 0x02, 0xfd, 0x00, 0xff, 0x12, 0x05, 0x00,
+ 0x02, 0xfd, 0x01, 0xfe, 0x3d, 0x05, 0x00,
+ 0x02, 0xfd, 0x03, 0xfc, 0x17, 0x05, 0x00,
+ 0x02, 0xfd, 0x04, 0xfb, 0x0a, 0x05, 0x00,
+ 0x02, 0xfd, 0x05, 0xfa, 0x1e, 0x05, 0x00,
+ 0x02, 0xfd, 0x06, 0xf9, 0x1f, 0x05, 0x00,
+ 0x02, 0xfd, 0x07, 0xf8, 0x20, 0x05, 0x00,
+ 0x02, 0xfd, 0x09, 0xf6, 0x21, 0x05, 0x00,
+ 0x02, 0xfd, 0x0a, 0xf5, 0x22, 0x05, 0x00,
+ 0x02, 0xfd, 0x0b, 0xf4, 0x23, 0x05, 0x00,
+ 0x02, 0xfd, 0x0d, 0xf2, 0x24, 0x05, 0x00,
+ 0x02, 0xfd, 0x0e, 0xf1, 0x25, 0x05, 0x00,
+ 0x02, 0xfd, 0x0f, 0xf0, 0x26, 0x05, 0x00,
+ 0x02, 0xfd, 0x11, 0xee, 0x27, 0x05, 0x00,
+ 0x02, 0xfd, 0x08, 0xf7, 0x04, 0x05, 0x00,
+ 0x02, 0xfd, 0x0c, 0xf3, 0x3e, 0x05, 0x00,
+ 0x02, 0xfd, 0x10, 0xef, 0x1c, 0x05, 0x00,
+ 0x02, 0xfd, 0x12, 0xed, 0x3f, 0x05, 0x00,
+ 0x02, 0xfd, 0x13, 0xec, 0x0f, 0x05, 0x00,
+ 0x02, 0xfd, 0x14, 0xeb, 0x10, 0x05, 0x00,
+ 0x02, 0xfd, 0x15, 0xea, 0x13, 0x05, 0x00,
+ 0x02, 0xfd, 0x17, 0xe8, 0x18, 0x05, 0x00,
+ 0x02, 0xfd, 0x18, 0xe7, 0x11, 0x05, 0x00,
+ 0x02, 0xfd, 0x19, 0xe6, 0x15, 0x05, 0x00,
+ 0x02, 0xfd, 0x1a, 0xe5, 0x0c, 0x05, 0x00,
+ 0x02, 0xfd, 0x1b, 0xe4, 0x16, 0x05, 0x00,
+ 0x02, 0xfd, 0x1c, 0xe3, 0x09, 0x05, 0x00,
+ 0x02, 0xfd, 0x1d, 0xe2, 0x05, 0x05, 0x00,
+ 0x02, 0xfd, 0x1e, 0xe1, 0x2d, 0x05, 0x00,
+ 0x02, 0xfd, 0x1f, 0xe0, 0x2e, 0x05, 0x00,
+ 0x03, 0xfc, 0x00, 0xff, 0x08, 0x05, 0x00,
+ 0x03, 0xfc, 0x01, 0xfe, 0x19, 0x05, 0x00,
+ 0x03, 0xfc, 0x02, 0xfd, 0x0d, 0x05, 0x00,
+ 0x03, 0xfc, 0x03, 0xfc, 0x0e, 0x05, 0x00,
+};
+
#endif
diff --git a/linux/drivers/media/dvb/dvb-usb/anysee.c b/linux/drivers/media/dvb/dvb-usb/anysee.c
index c786359fb..cd2edbcaa 100644
--- a/linux/drivers/media/dvb/dvb-usb/anysee.c
+++ b/linux/drivers/media/dvb/dvb-usb/anysee.c
@@ -46,7 +46,7 @@ module_param_named(delsys, dvb_usb_anysee_delsys, int, 0644);
MODULE_PARM_DESC(delsys, "select delivery mode (0=DVB-C, 1=DVB-T)");
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-static struct mutex anysee_usb_mutex;
+static DEFINE_MUTEX(anysee_usb_mutex);
static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen,
u8 *rbuf, u8 rlen)
@@ -456,8 +456,6 @@ static int anysee_probe(struct usb_interface *intf,
struct usb_host_interface *alt;
int ret;
- mutex_init(&anysee_usb_mutex);
-
/* There is one interface with two alternate settings.
Alternate setting 0 is for bulk transfer.
Alternate setting 1 is for isochronous transfer.
diff --git a/linux/drivers/media/dvb/dvb-usb/cinergyT2-core.c b/linux/drivers/media/dvb/dvb-usb/cinergyT2-core.c
index 3ac9f74e9..80e37a0d0 100644
--- a/linux/drivers/media/dvb/dvb-usb/cinergyT2-core.c
+++ b/linux/drivers/media/dvb/dvb-usb/cinergyT2-core.c
@@ -32,7 +32,6 @@
/* debug */
int dvb_usb_cinergyt2_debug;
-int disable_remote;
module_param_named(debug, dvb_usb_cinergyt2_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=info, xfer=2, rc=4 "
@@ -45,7 +44,7 @@ struct cinergyt2_state {
};
/* We are missing a release hook with usb_device data */
-struct dvb_usb_device *cinergyt2_usb_device;
+static struct dvb_usb_device *cinergyt2_usb_device;
static struct dvb_usb_device_properties cinergyt2_properties;
diff --git a/linux/drivers/media/dvb/dvb-usb/cinergyT2.h b/linux/drivers/media/dvb/dvb-usb/cinergyT2.h
index 11d79eb38..4e3247d04 100644
--- a/linux/drivers/media/dvb/dvb-usb/cinergyT2.h
+++ b/linux/drivers/media/dvb/dvb-usb/cinergyT2.h
@@ -30,7 +30,11 @@
#ifndef _DVB_USB_CINERGYT2_H_
#define _DVB_USB_CINERGYT2_H_
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
#include <linux/usb/input.h>
+#else
+#include <linux/usb_input.h>
+#endif
#define DVB_USB_LOG_PREFIX "cinergyT2"
#include "dvb-usb.h"
@@ -70,11 +74,11 @@ struct dvbt_get_status_msg {
uint8_t bandwidth;
uint16_t tps;
uint8_t flags;
- uint16_t gain;
+ __le16 gain;
uint8_t snr;
- uint32_t viterbi_error_rate;
+ __le32 viterbi_error_rate;
uint32_t rs_error_rate;
- uint32_t uncorrected_block_count;
+ __le32 uncorrected_block_count;
uint8_t lock_bits;
uint8_t prev_lock_bits;
} __attribute__((packed));
@@ -82,9 +86,9 @@ struct dvbt_get_status_msg {
struct dvbt_set_parameters_msg {
uint8_t cmd;
- uint32_t freq;
+ __le32 freq;
uint8_t bandwidth;
- uint16_t tps;
+ __le16 tps;
uint8_t flags;
} __attribute__((packed));
diff --git a/linux/drivers/media/dvb/dvb-usb/dib0700.h b/linux/drivers/media/dvb/dvb-usb/dib0700.h
index 739193943..8b544fe79 100644
--- a/linux/drivers/media/dvb/dvb-usb/dib0700.h
+++ b/linux/drivers/media/dvb/dvb-usb/dib0700.h
@@ -22,7 +22,7 @@ extern int dvb_usb_dib0700_debug;
#define REQUEST_I2C_READ 0x2
#define REQUEST_I2C_WRITE 0x3
-#define REQUEST_POLL_RC 0x4
+#define REQUEST_POLL_RC 0x4 /* deprecated in firmware v1.20 */
#define REQUEST_JUMPRAM 0x8
#define REQUEST_SET_CLOCK 0xB
#define REQUEST_SET_GPIO 0xC
@@ -40,11 +40,14 @@ struct dib0700_state {
u16 mt2060_if1[2];
u8 rc_toggle;
u8 rc_counter;
+ u8 rc_func_version;
u8 is_dib7000pc;
u8 fw_use_new_i2c_api;
u8 disable_streaming_master_mode;
};
+extern int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion,
+ u32 *romversion, u32 *ramversion, u32 *fwtype);
extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val);
extern int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3);
extern int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen);
diff --git a/linux/drivers/media/dvb/dvb-usb/dib0700_core.c b/linux/drivers/media/dvb/dvb-usb/dib0700_core.c
index 3c7bdef28..2fbb7049a 100644
--- a/linux/drivers/media/dvb/dvb-usb/dib0700_core.c
+++ b/linux/drivers/media/dvb/dvb-usb/dib0700_core.c
@@ -19,6 +19,22 @@ MODULE_PARM_DESC(dvb_usb_dib0700_ir_proto, "set ir protocol (0=NEC, 1=RC5 (defau
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion,
+ u32 *romversion, u32 *ramversion, u32 *fwtype)
+{
+ u8 b[16];
+ int ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0),
+ REQUEST_GET_VERSION,
+ USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
+ b, sizeof(b), USB_CTRL_GET_TIMEOUT);
+ *hwversion = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
+ *romversion = (b[4] << 24) | (b[5] << 16) | (b[6] << 8) | b[7];
+ *ramversion = (b[8] << 24) | (b[9] << 16) | (b[10] << 8) | b[11];
+ *fwtype = (b[12] << 24) | (b[13] << 16) | (b[14] << 8) | b[15];
+ return ret;
+}
+
/* expecting rx buffer: request data[0] data[1] ... data[2] */
static int dib0700_ctrl_wr(struct dvb_usb_device *d, u8 *tx, u8 txlen)
{
diff --git a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c
index 0cfccc24b..f28d3ae59 100644
--- a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c
+++ b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c
@@ -38,6 +38,7 @@ static struct mt2060_config bristol_mt2060_config[2] = {
}
};
+
static struct dibx000_agc_config bristol_dib3000p_mt2060_agc_config = {
.band_caps = BAND_VHF | BAND_UHF,
.setup = (1 << 8) | (5 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (2 << 0),
@@ -451,8 +452,13 @@ static u8 rc_request[] = { REQUEST_POLL_RC, 0 };
/* Number of keypresses to ignore before start repeating */
#define RC_REPEAT_DELAY 2
+#define RC_REPEAT_DELAY_V1_20 5
-static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+
+
+/* Used by firmware versions < 1.20 (deprecated) */
+static int dib0700_rc_query_legacy(struct dvb_usb_device *d, u32 *event,
+ int *state)
{
u8 key[4];
int i;
@@ -529,6 +535,137 @@ static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
return 0;
}
+/* This is the structure of the RC response packet starting in firmware 1.20 */
+struct dib0700_rc_response {
+ u8 report_id;
+ u8 data_state;
+ u8 system_msb;
+ u8 system_lsb;
+ u8 data;
+ u8 not_data;
+};
+
+/* This supports the new IR response format for firmware v1.20 */
+static int dib0700_rc_query_v1_20(struct dvb_usb_device *d, u32 *event,
+ int *state)
+{
+ struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
+ struct dib0700_state *st = d->priv;
+ struct dib0700_rc_response poll_reply;
+ u8 buf[6];
+ int i;
+ int status;
+ int actlen;
+ int found = 0;
+
+ /* Set initial results in case we exit the function early */
+ *event = 0;
+ *state = REMOTE_NO_KEY_PRESSED;
+
+ /* Firmware v1.20 provides RC data via bulk endpoint 1 */
+ status = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev, 1), buf,
+ sizeof(buf), &actlen, 50);
+ if (status < 0) {
+ /* No data available (meaning no key press) */
+ return 0;
+ }
+
+ if (actlen != sizeof(buf)) {
+ /* We didn't get back the 6 byte message we expected */
+ err("Unexpected RC response size [%d]", actlen);
+ return -1;
+ }
+
+ poll_reply.report_id = buf[0];
+ poll_reply.data_state = buf[1];
+ poll_reply.system_msb = buf[2];
+ poll_reply.system_lsb = buf[3];
+ poll_reply.data = buf[4];
+ poll_reply.not_data = buf[5];
+
+ /*
+ info("rid=%02x ds=%02x sm=%02x sl=%02x d=%02x nd=%02x\n",
+ poll_reply.report_id, poll_reply.data_state,
+ poll_reply.system_msb, poll_reply.system_lsb,
+ poll_reply.data, poll_reply.not_data);
+ */
+
+ if ((poll_reply.data + poll_reply.not_data) != 0xff) {
+ /* Key failed integrity check */
+ err("key failed integrity check: %02x %02x %02x %02x",
+ poll_reply.system_msb, poll_reply.system_lsb,
+ poll_reply.data, poll_reply.not_data);
+ return -1;
+ }
+
+ /* Find the key in the map */
+ for (i = 0; i < d->props.rc_key_map_size; i++) {
+ if (keymap[i].custom == poll_reply.system_lsb &&
+ keymap[i].data == poll_reply.data) {
+ *event = keymap[i].event;
+ found = 1;
+ break;
+ }
+ }
+
+ if (found == 0) {
+ err("Unknown remote controller key: %02x %02x %02x %02x",
+ poll_reply.system_msb, poll_reply.system_lsb,
+ poll_reply.data, poll_reply.not_data);
+ d->last_event = 0;
+ return 0;
+ }
+
+ if (poll_reply.data_state == 1) {
+ /* New key hit */
+ st->rc_counter = 0;
+ *event = keymap[i].event;
+ *state = REMOTE_KEY_PRESSED;
+ d->last_event = keymap[i].event;
+ } else if (poll_reply.data_state == 2) {
+ /* Key repeated */
+ st->rc_counter++;
+
+ /* prevents unwanted double hits */
+ if (st->rc_counter > RC_REPEAT_DELAY_V1_20) {
+ *event = d->last_event;
+ *state = REMOTE_KEY_PRESSED;
+ st->rc_counter = RC_REPEAT_DELAY_V1_20;
+ }
+ } else {
+ err("Unknown data state [%d]", poll_reply.data_state);
+ }
+
+ return 0;
+}
+
+static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+ struct dib0700_state *st = d->priv;
+
+ /* Because some people may have improperly named firmware files,
+ let's figure out whether to use the new firmware call or the legacy
+ call based on the firmware version embedded in the file */
+ if (st->rc_func_version == 0) {
+ u32 hwver, romver, ramver, fwtype;
+ int ret = dib0700_get_version(d, &hwver, &romver, &ramver,
+ &fwtype);
+ if (ret < 0) {
+ err("Could not determine version info");
+ return -1;
+ }
+ if (ramver < 0x10200)
+ st->rc_func_version = 1;
+ else
+ st->rc_func_version = 2;
+ }
+
+ if (st->rc_func_version == 2)
+ return dib0700_rc_query_v1_20(d, event, state);
+ else
+ return dib0700_rc_query_legacy(d, event, state);
+}
+
static struct dvb_usb_rc_key dib0700_rc_keys[] = {
/* Key codes for the tiny Pinnacle remote*/
{ 0x07, 0x00, KEY_MUTE },
diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index 7380b94b3..a4fca3fca 100644
--- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -96,6 +96,7 @@
#define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0
#define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1
#define USB_PID_KWORLD_399U 0xe399
+#define USB_PID_KWORLD_395U 0xe396
#define USB_PID_KWORLD_PC160_2T 0xc160
#define USB_PID_KWORLD_VSTREAM_COLD 0x17de
#define USB_PID_KWORLD_VSTREAM_WARM 0x17df
diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb-urb.c b/linux/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
index 5cef12a07..6fe71c674 100644
--- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
+++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
@@ -13,14 +13,14 @@ int dvb_usb_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf,
{
int actlen,ret = -ENOMEM;
+ if (!d || wbuf == NULL || wlen == 0)
+ return -EINVAL;
+
if (d->props.generic_bulk_ctrl_endpoint == 0) {
err("endpoint for generic control not specified.");
return -EINVAL;
}
- if (wbuf == NULL || wlen == 0)
- return -EINVAL;
-
if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
return ret;
diff --git a/linux/drivers/media/dvb/dvb-usb/dw2102.c b/linux/drivers/media/dvb/dvb-usb/dw2102.c
index ca53df61c..bc5e47a2b 100644
--- a/linux/drivers/media/dvb/dvb-usb/dw2102.c
+++ b/linux/drivers/media/dvb/dvb-usb/dw2102.c
@@ -9,7 +9,6 @@
*
* see Documentation/dvb/README.dvb-usb for more information
*/
-#include <linux/version.h>
#include "dw2102.h"
#include "si21xx.h"
#include "stv0299.h"
@@ -27,6 +26,10 @@
#define USB_PID_DW2104 0x2104
#endif
+#ifndef USB_PID_CINERGY_S
+#define USB_PID_CINERGY_S 0x0064
+#endif
+
#define DW210X_READ_MSG 0
#define DW210X_WRITE_MSG 1
@@ -422,6 +425,18 @@ static int dw210x_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
return 0;
}
+static struct stv0299_config sharp_z0194a_config = {
+ .demod_address = 0x68,
+ .inittab = sharp_z0194a_inittab,
+ .mclk = 88000000UL,
+ .invert = 1,
+ .skip_reinit = 0,
+ .lock_output = STV0299_LOCKOUTPUT_1,
+ .volt13_op0_op1 = STV0299_VOLT13_OP1,
+ .min_delay_ms = 100,
+ .set_symbol_rate = sharp_z0194a_set_symbol_rate,
+};
+
static struct cx24116_config dw2104_config = {
.demod_address = 0x55,
.mpg_clk_pos_pol = 0x01,
@@ -566,6 +581,7 @@ static struct usb_device_id dw2102_table[] = {
{USB_DEVICE(USB_VID_CYPRESS, 0x2101)},
{USB_DEVICE(USB_VID_CYPRESS, 0x2104)},
{USB_DEVICE(0x9022, 0xd650)},
+ {USB_DEVICE(USB_VID_TERRATEC, USB_PID_CINERGY_S)},
{ }
};
@@ -635,6 +651,7 @@ static int dw2102_load_firmware(struct usb_device *dev,
dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0,
DW210X_WRITE_MSG);
break;
+ case USB_PID_CINERGY_S:
case USB_PID_DW2102:
dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0,
DW210X_WRITE_MSG);
@@ -714,7 +731,7 @@ static struct dvb_usb_device_properties dw2102_properties = {
},
}
},
- .num_device_descs = 2,
+ .num_device_descs = 3,
.devices = {
{"DVBWorld DVB-S 2102 USB2.0",
{&dw2102_table[0], NULL},
@@ -724,6 +741,10 @@ static struct dvb_usb_device_properties dw2102_properties = {
{&dw2102_table[1], NULL},
{NULL},
},
+ {"TerraTec Cinergy S USB",
+ {&dw2102_table[4], NULL},
+ {NULL},
+ },
}
};
diff --git a/linux/drivers/media/dvb/dvb-usb/usb-urb.c b/linux/drivers/media/dvb/dvb-usb/usb-urb.c
index 5caec2034..eb3aaaf7a 100644
--- a/linux/drivers/media/dvb/dvb-usb/usb-urb.c
+++ b/linux/drivers/media/dvb/dvb-usb/usb-urb.c
@@ -139,7 +139,7 @@ stream->buf_list[stream->buf_num], (long long)stream->dma_addr[stream->buf_num])
static int usb_bulk_urb_init(struct usb_data_stream *stream)
{
- int i;
+ int i, j;
if ((i = usb_allocate_stream_buffers(stream,stream->props.count,
stream->props.u.bulk.buffersize)) < 0)
@@ -147,9 +147,13 @@ static int usb_bulk_urb_init(struct usb_data_stream *stream)
/* allocate the URBs */
for (i = 0; i < stream->props.count; i++) {
- if ((stream->urb_list[i] = usb_alloc_urb(0,GFP_ATOMIC)) == NULL)
+ stream->urb_list[i] = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!stream->urb_list[i]) {
+ deb_mem("not enough memory for urb_alloc_urb!.\n");
+ for (j = 0; j < i; j++)
+ usb_free_urb(stream->urb_list[i]);
return -ENOMEM;
-
+ }
usb_fill_bulk_urb( stream->urb_list[i], stream->udev,
usb_rcvbulkpipe(stream->udev,stream->props.endpoint),
stream->buf_list[i],
@@ -174,9 +178,14 @@ static int usb_isoc_urb_init(struct usb_data_stream *stream)
for (i = 0; i < stream->props.count; i++) {
struct urb *urb;
int frame_offset = 0;
- if ((stream->urb_list[i] =
- usb_alloc_urb(stream->props.u.isoc.framesperurb,GFP_ATOMIC)) == NULL)
+
+ stream->urb_list[i] = usb_alloc_urb(stream->props.u.isoc.framesperurb, GFP_ATOMIC);
+ if (!stream->urb_list[i]) {
+ deb_mem("not enough memory for urb_alloc_urb!\n");
+ for (j = 0; j < i; j++)
+ usb_free_urb(stream->urb_list[i]);
return -ENOMEM;
+ }
urb = stream->urb_list[i];
diff --git a/linux/drivers/media/dvb/frontends/Kconfig b/linux/drivers/media/dvb/frontends/Kconfig
index 96b93e21a..2470d88e9 100644
--- a/linux/drivers/media/dvb/frontends/Kconfig
+++ b/linux/drivers/media/dvb/frontends/Kconfig
@@ -12,6 +12,25 @@ config DVB_FE_CUSTOMISE
If unsure say N.
+comment "Multistandard (satellite) frontends"
+ depends on DVB_CORE
+
+config DVB_STB0899
+ tristate "STB0899 based"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ A DVB-S/S2/DSS Multistandard demodulator. Say Y when you want
+ to support this demodulator based frontends
+
+config DVB_STB6100
+ tristate "STB6100 based tuners"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ A Silicon tuner from ST used in conjunction with the STB0899
+ demodulator. Say Y when you want to support this tuner.
+
comment "DVB-S (satellite) frontends"
depends on DVB_CORE
@@ -78,6 +97,13 @@ config DVB_TDA10086
help
A DVB-S tuner module. Say Y when you want to support this frontend.
+config DVB_TDA8261
+ tristate "Philips TDA8261 based"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ A DVB-S tuner module. Say Y when you want to support this frontend.
+
config DVB_VES1X93
tristate "VLSI VES1893 or VES1993 based"
depends on DVB_CORE && I2C
@@ -345,6 +371,14 @@ config DVB_LGDT330X
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
to support this frontend.
+config DVB_LGDT3304
+ tristate "LG Electronics LGDT3304"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
+ to support this frontend.
+
config DVB_S5H1409
tristate "Samsung S5H1409 based"
depends on DVB_CORE && I2C
@@ -369,6 +403,17 @@ config DVB_S5H1411
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
to support this frontend.
+comment "ISDB-T (terrestrial) frontends"
+ depends on DVB_CORE
+
+config DVB_S921
+ tristate "Sharp S921 tuner"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ AN ISDB-T DQPSK, QPSK, 16QAM and 64QAM 1seg tuner module.
+ Say Y when you want to support this frontend.
+
comment "Digital terrestrial only tuners/PLL"
depends on DVB_CORE
diff --git a/linux/drivers/media/dvb/frontends/Makefile b/linux/drivers/media/dvb/frontends/Makefile
index aba79f4a6..7a19c0c7b 100644
--- a/linux/drivers/media/dvb/frontends/Makefile
+++ b/linux/drivers/media/dvb/frontends/Makefile
@@ -5,8 +5,13 @@
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
EXTRA_CFLAGS += -Idrivers/media/common/tuners/
+s921-objs := s921_module.o s921_core.o
+stb0899-objs = stb0899_drv.o stb0899_algo.o
+
obj-$(CONFIG_DVB_PLL) += dvb-pll.o
obj-$(CONFIG_DVB_STV0299) += stv0299.o
+obj-$(CONFIG_DVB_STB0899) += stb0899.o
+obj-$(CONFIG_DVB_STB6100) += stb6100.o
obj-$(CONFIG_DVB_SP8870) += sp8870.o
obj-$(CONFIG_DVB_CX22700) += cx22700.o
obj-$(CONFIG_DVB_CX24110) += cx24110.o
@@ -35,12 +40,14 @@ obj-$(CONFIG_DVB_OR51132) += or51132.o
obj-$(CONFIG_DVB_BCM3510) += bcm3510.o
obj-$(CONFIG_DVB_S5H1420) += s5h1420.o
obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
+obj-$(CONFIG_DVB_LGDT3304) += lgdt3304.o
obj-$(CONFIG_DVB_CX24123) += cx24123.o
obj-$(CONFIG_DVB_LNBP21) += lnbp21.o
obj-$(CONFIG_DVB_ISL6405) += isl6405.o
obj-$(CONFIG_DVB_ISL6421) += isl6421.o
obj-$(CONFIG_DVB_TDA10086) += tda10086.o
obj-$(CONFIG_DVB_TDA826X) += tda826x.o
+obj-$(CONFIG_DVB_TDA8261) += tda8261.o
obj-$(CONFIG_DVB_TUNER_DIB0070) += dib0070.o
obj-$(CONFIG_DVB_TUA6100) += tua6100.o
obj-$(CONFIG_DVB_S5H1409) += s5h1409.o
@@ -55,3 +62,5 @@ obj-$(CONFIG_DVB_CX24116) += cx24116.o
obj-$(CONFIG_DVB_SI21XX) += si21xx.o
obj-$(CONFIG_DVB_STV0288) += stv0288.o
obj-$(CONFIG_DVB_STB6000) += stb6000.o
+obj-$(CONFIG_DVB_S921) += s921.o
+
diff --git a/linux/drivers/media/dvb/frontends/af9013.c b/linux/drivers/media/dvb/frontends/af9013.c
index 21c1060cf..692b68a9e 100644
--- a/linux/drivers/media/dvb/frontends/af9013.c
+++ b/linux/drivers/media/dvb/frontends/af9013.c
@@ -1187,7 +1187,7 @@ static int af9013_read_status(struct dvb_frontend *fe, fe_status_t *status)
if (tmp)
*status |= FE_HAS_SYNC | FE_HAS_LOCK;
- if (!*status & FE_HAS_SIGNAL) {
+ if (!(*status & FE_HAS_SIGNAL)) {
/* AGC lock */
ret = af9013_read_reg_bits(state, 0xd1a0, 6, 1, &tmp);
if (ret)
@@ -1196,7 +1196,7 @@ static int af9013_read_status(struct dvb_frontend *fe, fe_status_t *status)
*status |= FE_HAS_SIGNAL;
}
- if (!*status & FE_HAS_CARRIER) {
+ if (!(*status & FE_HAS_CARRIER)) {
/* CFO lock */
ret = af9013_read_reg_bits(state, 0xd333, 7, 1, &tmp);
if (ret)
@@ -1205,7 +1205,7 @@ static int af9013_read_status(struct dvb_frontend *fe, fe_status_t *status)
*status |= FE_HAS_CARRIER;
}
- if (!*status & FE_HAS_CARRIER) {
+ if (!(*status & FE_HAS_CARRIER)) {
/* SFOE lock */
ret = af9013_read_reg_bits(state, 0xd334, 6, 1, &tmp);
if (ret)
diff --git a/linux/drivers/media/dvb/frontends/cx22702.c b/linux/drivers/media/dvb/frontends/cx22702.c
index 9430e03db..5d1abe34b 100644
--- a/linux/drivers/media/dvb/frontends/cx22702.c
+++ b/linux/drivers/media/dvb/frontends/cx22702.c
@@ -34,13 +34,12 @@
#include "dvb_frontend.h"
#include "cx22702.h"
-
struct cx22702_state {
- struct i2c_adapter* i2c;
+ struct i2c_adapter *i2c;
/* configuration settings */
- const struct cx22702_config* config;
+ const struct cx22702_config *config;
struct dvb_frontend frontend;
@@ -49,10 +48,13 @@ struct cx22702_state {
};
static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Enable verbose debug messages");
+
#define dprintk if (debug) printk
/* Register values to initialise the demod */
-static u8 init_tab [] = {
+static u8 init_tab[] = {
0x00, 0x00, /* Stop aquisition */
0x0B, 0x06,
0x09, 0x01,
@@ -80,65 +82,67 @@ static u8 init_tab [] = {
0xfd, 0x00,
};
-static int cx22702_writereg (struct cx22702_state* state, u8 reg, u8 data)
+static int cx22702_writereg(struct cx22702_state *state, u8 reg, u8 data)
{
int ret;
- u8 buf [] = { reg, data };
- struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
+ u8 buf[] = { reg, data };
+ struct i2c_msg msg = {
+ .addr = state->config->demod_address, .flags = 0,
+ .buf = buf, .len = 2 };
ret = i2c_transfer(state->i2c, &msg, 1);
if (ret != 1)
- printk("%s: writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
+ printk(KERN_ERR
+ "%s: error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
__func__, reg, data, ret);
return (ret != 1) ? -1 : 0;
}
-static u8 cx22702_readreg (struct cx22702_state* state, u8 reg)
+static u8 cx22702_readreg(struct cx22702_state *state, u8 reg)
{
int ret;
- u8 b0 [] = { reg };
- u8 b1 [] = { 0 };
+ u8 b0[] = { reg };
+ u8 b1[] = { 0 };
- struct i2c_msg msg [] = {
- { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
- { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
+ struct i2c_msg msg[] = {
+ { .addr = state->config->demod_address, .flags = 0,
+ .buf = b0, .len = 1 },
+ { .addr = state->config->demod_address, .flags = I2C_M_RD,
+ .buf = b1, .len = 1 } };
ret = i2c_transfer(state->i2c, msg, 2);
if (ret != 2)
- printk("%s: readreg error (ret == %i)\n", __func__, ret);
+ printk(KERN_ERR "%s: readreg error (ret == %i)\n",
+ __func__, ret);
return b1[0];
}
-static int cx22702_set_inversion (struct cx22702_state *state, int inversion)
+static int cx22702_set_inversion(struct cx22702_state *state, int inversion)
{
u8 val;
switch (inversion) {
-
- case INVERSION_AUTO:
- return -EOPNOTSUPP;
-
- case INVERSION_ON:
- val = cx22702_readreg (state, 0x0C);
- return cx22702_writereg (state, 0x0C, val | 0x01);
-
- case INVERSION_OFF:
- val = cx22702_readreg (state, 0x0C);
- return cx22702_writereg (state, 0x0C, val & 0xfe);
-
- default:
- return -EINVAL;
-
+ case INVERSION_AUTO:
+ return -EOPNOTSUPP;
+ case INVERSION_ON:
+ val = cx22702_readreg(state, 0x0C);
+ return cx22702_writereg(state, 0x0C, val | 0x01);
+ case INVERSION_OFF:
+ val = cx22702_readreg(state, 0x0C);
+ return cx22702_writereg(state, 0x0C, val & 0xfe);
+ default:
+ return -EINVAL;
}
}
/* Retrieve the demod settings */
-static int cx22702_get_tps (struct cx22702_state *state, struct dvb_ofdm_parameters *p)
+static int cx22702_get_tps(struct cx22702_state *state,
+ struct dvb_ofdm_parameters *p)
{
u8 val;
@@ -146,180 +150,281 @@ static int cx22702_get_tps (struct cx22702_state *state, struct dvb_ofdm_paramet
if (!(cx22702_readreg(state, 0x0A) & 0x20))
return -EAGAIN;
- val = cx22702_readreg (state, 0x01);
- switch( (val&0x18)>>3) {
- case 0: p->constellation = QPSK; break;
- case 1: p->constellation = QAM_16; break;
- case 2: p->constellation = QAM_64; break;
+ val = cx22702_readreg(state, 0x01);
+ switch ((val & 0x18) >> 3) {
+ case 0:
+ p->constellation = QPSK;
+ break;
+ case 1:
+ p->constellation = QAM_16;
+ break;
+ case 2:
+ p->constellation = QAM_64;
+ break;
}
- switch( val&0x07 ) {
- case 0: p->hierarchy_information = HIERARCHY_NONE; break;
- case 1: p->hierarchy_information = HIERARCHY_1; break;
- case 2: p->hierarchy_information = HIERARCHY_2; break;
- case 3: p->hierarchy_information = HIERARCHY_4; break;
+ switch (val & 0x07) {
+ case 0:
+ p->hierarchy_information = HIERARCHY_NONE;
+ break;
+ case 1:
+ p->hierarchy_information = HIERARCHY_1;
+ break;
+ case 2:
+ p->hierarchy_information = HIERARCHY_2;
+ break;
+ case 3:
+ p->hierarchy_information = HIERARCHY_4;
+ break;
}
- val = cx22702_readreg (state, 0x02);
- switch( (val&0x38)>>3 ) {
- case 0: p->code_rate_HP = FEC_1_2; break;
- case 1: p->code_rate_HP = FEC_2_3; break;
- case 2: p->code_rate_HP = FEC_3_4; break;
- case 3: p->code_rate_HP = FEC_5_6; break;
- case 4: p->code_rate_HP = FEC_7_8; break;
+ val = cx22702_readreg(state, 0x02);
+ switch ((val & 0x38) >> 3) {
+ case 0:
+ p->code_rate_HP = FEC_1_2;
+ break;
+ case 1:
+ p->code_rate_HP = FEC_2_3;
+ break;
+ case 2:
+ p->code_rate_HP = FEC_3_4;
+ break;
+ case 3:
+ p->code_rate_HP = FEC_5_6;
+ break;
+ case 4:
+ p->code_rate_HP = FEC_7_8;
+ break;
}
- switch( val&0x07 ) {
- case 0: p->code_rate_LP = FEC_1_2; break;
- case 1: p->code_rate_LP = FEC_2_3; break;
- case 2: p->code_rate_LP = FEC_3_4; break;
- case 3: p->code_rate_LP = FEC_5_6; break;
- case 4: p->code_rate_LP = FEC_7_8; break;
+ switch (val & 0x07) {
+ case 0:
+ p->code_rate_LP = FEC_1_2;
+ break;
+ case 1:
+ p->code_rate_LP = FEC_2_3;
+ break;
+ case 2:
+ p->code_rate_LP = FEC_3_4;
+ break;
+ case 3:
+ p->code_rate_LP = FEC_5_6;
+ break;
+ case 4:
+ p->code_rate_LP = FEC_7_8;
+ break;
}
-
- val = cx22702_readreg (state, 0x03);
- switch( (val&0x0c)>>2 ) {
- case 0: p->guard_interval = GUARD_INTERVAL_1_32; break;
- case 1: p->guard_interval = GUARD_INTERVAL_1_16; break;
- case 2: p->guard_interval = GUARD_INTERVAL_1_8; break;
- case 3: p->guard_interval = GUARD_INTERVAL_1_4; break;
+ val = cx22702_readreg(state, 0x03);
+ switch ((val & 0x0c) >> 2) {
+ case 0:
+ p->guard_interval = GUARD_INTERVAL_1_32;
+ break;
+ case 1:
+ p->guard_interval = GUARD_INTERVAL_1_16;
+ break;
+ case 2:
+ p->guard_interval = GUARD_INTERVAL_1_8;
+ break;
+ case 3:
+ p->guard_interval = GUARD_INTERVAL_1_4;
+ break;
}
- switch( val&0x03 ) {
- case 0: p->transmission_mode = TRANSMISSION_MODE_2K; break;
- case 1: p->transmission_mode = TRANSMISSION_MODE_8K; break;
+ switch (val & 0x03) {
+ case 0:
+ p->transmission_mode = TRANSMISSION_MODE_2K;
+ break;
+ case 1:
+ p->transmission_mode = TRANSMISSION_MODE_8K;
+ break;
}
return 0;
}
-static int cx22702_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+static int cx22702_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
{
- struct cx22702_state* state = fe->demodulator_priv;
- dprintk ("%s(%d)\n", __func__, enable);
+ struct cx22702_state *state = fe->demodulator_priv;
+ dprintk("%s(%d)\n", __func__, enable);
if (enable)
- return cx22702_writereg (state, 0x0D, cx22702_readreg(state, 0x0D) & 0xfe);
+ return cx22702_writereg(state, 0x0D,
+ cx22702_readreg(state, 0x0D) & 0xfe);
else
- return cx22702_writereg (state, 0x0D, cx22702_readreg(state, 0x0D) | 1);
+ return cx22702_writereg(state, 0x0D,
+ cx22702_readreg(state, 0x0D) | 1);
}
/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
-static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int cx22702_set_tps(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *p)
{
u8 val;
- struct cx22702_state* state = fe->demodulator_priv;
+ struct cx22702_state *state = fe->demodulator_priv;
if (fe->ops.tuner_ops.set_params) {
fe->ops.tuner_ops.set_params(fe, p);
- if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
}
/* set inversion */
- cx22702_set_inversion (state, p->inversion);
+ cx22702_set_inversion(state, p->inversion);
/* set bandwidth */
- switch(p->u.ofdm.bandwidth) {
+ switch (p->u.ofdm.bandwidth) {
case BANDWIDTH_6_MHZ:
- cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xcf) | 0x20 );
+ cx22702_writereg(state, 0x0C,
+ (cx22702_readreg(state, 0x0C) & 0xcf) | 0x20);
break;
case BANDWIDTH_7_MHZ:
- cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xcf) | 0x10 );
+ cx22702_writereg(state, 0x0C,
+ (cx22702_readreg(state, 0x0C) & 0xcf) | 0x10);
break;
case BANDWIDTH_8_MHZ:
- cx22702_writereg(state, 0x0C, cx22702_readreg(state, 0x0C) &0xcf );
+ cx22702_writereg(state, 0x0C,
+ cx22702_readreg(state, 0x0C) & 0xcf);
break;
default:
- dprintk ("%s: invalid bandwidth\n",__func__);
+ dprintk("%s: invalid bandwidth\n", __func__);
return -EINVAL;
}
-
- p->u.ofdm.code_rate_LP = FEC_AUTO; //temp hack as manual not working
+ p->u.ofdm.code_rate_LP = FEC_AUTO; /* temp hack as manual not working */
/* use auto configuration? */
- if((p->u.ofdm.hierarchy_information==HIERARCHY_AUTO) ||
- (p->u.ofdm.constellation==QAM_AUTO) ||
- (p->u.ofdm.code_rate_HP==FEC_AUTO) ||
- (p->u.ofdm.code_rate_LP==FEC_AUTO) ||
- (p->u.ofdm.guard_interval==GUARD_INTERVAL_AUTO) ||
- (p->u.ofdm.transmission_mode==TRANSMISSION_MODE_AUTO) ) {
+ if ((p->u.ofdm.hierarchy_information == HIERARCHY_AUTO) ||
+ (p->u.ofdm.constellation == QAM_AUTO) ||
+ (p->u.ofdm.code_rate_HP == FEC_AUTO) ||
+ (p->u.ofdm.code_rate_LP == FEC_AUTO) ||
+ (p->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO) ||
+ (p->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO)) {
/* TPS Source - use hardware driven values */
cx22702_writereg(state, 0x06, 0x10);
cx22702_writereg(state, 0x07, 0x9);
cx22702_writereg(state, 0x08, 0xC1);
- cx22702_writereg(state, 0x0B, cx22702_readreg(state, 0x0B) & 0xfc );
- cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xBF) | 0x40 );
+ cx22702_writereg(state, 0x0B, cx22702_readreg(state, 0x0B)
+ & 0xfc);
+ cx22702_writereg(state, 0x0C,
+ (cx22702_readreg(state, 0x0C) & 0xBF) | 0x40);
cx22702_writereg(state, 0x00, 0x01); /* Begin aquisition */
- dprintk("%s: Autodetecting\n",__func__);
+ dprintk("%s: Autodetecting\n", __func__);
return 0;
}
/* manually programmed values */
- val=0;
- switch(p->u.ofdm.constellation) {
- case QPSK: val = (val&0xe7); break;
- case QAM_16: val = (val&0xe7)|0x08; break;
- case QAM_64: val = (val&0xe7)|0x10; break;
- default:
- dprintk ("%s: invalid constellation\n",__func__);
- return -EINVAL;
+ val = 0;
+ switch (p->u.ofdm.constellation) {
+ case QPSK:
+ val = (val & 0xe7);
+ break;
+ case QAM_16:
+ val = (val & 0xe7) | 0x08;
+ break;
+ case QAM_64:
+ val = (val & 0xe7) | 0x10;
+ break;
+ default:
+ dprintk("%s: invalid constellation\n", __func__);
+ return -EINVAL;
}
- switch(p->u.ofdm.hierarchy_information) {
- case HIERARCHY_NONE: val = (val&0xf8); break;
- case HIERARCHY_1: val = (val&0xf8)|1; break;
- case HIERARCHY_2: val = (val&0xf8)|2; break;
- case HIERARCHY_4: val = (val&0xf8)|3; break;
- default:
- dprintk ("%s: invalid hierarchy\n",__func__);
- return -EINVAL;
+ switch (p->u.ofdm.hierarchy_information) {
+ case HIERARCHY_NONE:
+ val = (val & 0xf8);
+ break;
+ case HIERARCHY_1:
+ val = (val & 0xf8) | 1;
+ break;
+ case HIERARCHY_2:
+ val = (val & 0xf8) | 2;
+ break;
+ case HIERARCHY_4:
+ val = (val & 0xf8) | 3;
+ break;
+ default:
+ dprintk("%s: invalid hierarchy\n", __func__);
+ return -EINVAL;
}
- cx22702_writereg (state, 0x06, val);
-
- val=0;
- switch(p->u.ofdm.code_rate_HP) {
- case FEC_NONE:
- case FEC_1_2: val = (val&0xc7); break;
- case FEC_2_3: val = (val&0xc7)|0x08; break;
- case FEC_3_4: val = (val&0xc7)|0x10; break;
- case FEC_5_6: val = (val&0xc7)|0x18; break;
- case FEC_7_8: val = (val&0xc7)|0x20; break;
- default:
- dprintk ("%s: invalid code_rate_HP\n",__func__);
- return -EINVAL;
+ cx22702_writereg(state, 0x06, val);
+
+ val = 0;
+ switch (p->u.ofdm.code_rate_HP) {
+ case FEC_NONE:
+ case FEC_1_2:
+ val = (val & 0xc7);
+ break;
+ case FEC_2_3:
+ val = (val & 0xc7) | 0x08;
+ break;
+ case FEC_3_4:
+ val = (val & 0xc7) | 0x10;
+ break;
+ case FEC_5_6:
+ val = (val & 0xc7) | 0x18;
+ break;
+ case FEC_7_8:
+ val = (val & 0xc7) | 0x20;
+ break;
+ default:
+ dprintk("%s: invalid code_rate_HP\n", __func__);
+ return -EINVAL;
}
- switch(p->u.ofdm.code_rate_LP) {
- case FEC_NONE:
- case FEC_1_2: val = (val&0xf8); break;
- case FEC_2_3: val = (val&0xf8)|1; break;
- case FEC_3_4: val = (val&0xf8)|2; break;
- case FEC_5_6: val = (val&0xf8)|3; break;
- case FEC_7_8: val = (val&0xf8)|4; break;
- default:
- dprintk ("%s: invalid code_rate_LP\n",__func__);
- return -EINVAL;
+ switch (p->u.ofdm.code_rate_LP) {
+ case FEC_NONE:
+ case FEC_1_2:
+ val = (val & 0xf8);
+ break;
+ case FEC_2_3:
+ val = (val & 0xf8) | 1;
+ break;
+ case FEC_3_4:
+ val = (val & 0xf8) | 2;
+ break;
+ case FEC_5_6:
+ val = (val & 0xf8) | 3;
+ break;
+ case FEC_7_8:
+ val = (val & 0xf8) | 4;
+ break;
+ default:
+ dprintk("%s: invalid code_rate_LP\n", __func__);
+ return -EINVAL;
}
- cx22702_writereg (state, 0x07, val);
-
- val=0;
- switch(p->u.ofdm.guard_interval) {
- case GUARD_INTERVAL_1_32: val = (val&0xf3); break;
- case GUARD_INTERVAL_1_16: val = (val&0xf3)|0x04; break;
- case GUARD_INTERVAL_1_8: val = (val&0xf3)|0x08; break;
- case GUARD_INTERVAL_1_4: val = (val&0xf3)|0x0c; break;
- default:
- dprintk ("%s: invalid guard_interval\n",__func__);
- return -EINVAL;
+ cx22702_writereg(state, 0x07, val);
+
+ val = 0;
+ switch (p->u.ofdm.guard_interval) {
+ case GUARD_INTERVAL_1_32:
+ val = (val & 0xf3);
+ break;
+ case GUARD_INTERVAL_1_16:
+ val = (val & 0xf3) | 0x04;
+ break;
+ case GUARD_INTERVAL_1_8:
+ val = (val & 0xf3) | 0x08;
+ break;
+ case GUARD_INTERVAL_1_4:
+ val = (val & 0xf3) | 0x0c;
+ break;
+ default:
+ dprintk("%s: invalid guard_interval\n", __func__);
+ return -EINVAL;
}
- switch(p->u.ofdm.transmission_mode) {
- case TRANSMISSION_MODE_2K: val = (val&0xfc); break;
- case TRANSMISSION_MODE_8K: val = (val&0xfc)|1; break;
- default:
- dprintk ("%s: invalid transmission_mode\n",__func__);
- return -EINVAL;
+ switch (p->u.ofdm.transmission_mode) {
+ case TRANSMISSION_MODE_2K:
+ val = (val & 0xfc);
+ break;
+ case TRANSMISSION_MODE_8K:
+ val = (val & 0xfc) | 1;
+ break;
+ default:
+ dprintk("%s: invalid transmission_mode\n", __func__);
+ return -EINVAL;
}
cx22702_writereg(state, 0x08, val);
- cx22702_writereg(state, 0x0B, (cx22702_readreg(state, 0x0B) & 0xfc) | 0x02 );
- cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xBF) | 0x40 );
+ cx22702_writereg(state, 0x0B,
+ (cx22702_readreg(state, 0x0B) & 0xfc) | 0x02);
+ cx22702_writereg(state, 0x0C,
+ (cx22702_readreg(state, 0x0C) & 0xBF) | 0x40);
/* Begin channel aquisition */
cx22702_writereg(state, 0x00, 0x01);
@@ -329,109 +434,111 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
/* Reset the demod hardware and reset all of the configuration registers
to a default state. */
-static int cx22702_init (struct dvb_frontend* fe)
+static int cx22702_init(struct dvb_frontend *fe)
{
int i;
- struct cx22702_state* state = fe->demodulator_priv;
+ struct cx22702_state *state = fe->demodulator_priv;
- cx22702_writereg (state, 0x00, 0x02);
+ cx22702_writereg(state, 0x00, 0x02);
msleep(10);
- for (i=0; i<sizeof(init_tab); i+=2)
- cx22702_writereg (state, init_tab[i], init_tab[i+1]);
+ for (i = 0; i < ARRAY_SIZE(init_tab); i += 2)
+ cx22702_writereg(state, init_tab[i], init_tab[i + 1]);
- cx22702_writereg (state, 0xf8, (state->config->output_mode << 1) & 0x02);
+ cx22702_writereg(state, 0xf8, (state->config->output_mode << 1)
+ & 0x02);
cx22702_i2c_gate_ctrl(fe, 0);
return 0;
}
-static int cx22702_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int cx22702_read_status(struct dvb_frontend *fe, fe_status_t *status)
{
- struct cx22702_state* state = fe->demodulator_priv;
+ struct cx22702_state *state = fe->demodulator_priv;
u8 reg0A;
u8 reg23;
*status = 0;
- reg0A = cx22702_readreg (state, 0x0A);
- reg23 = cx22702_readreg (state, 0x23);
+ reg0A = cx22702_readreg(state, 0x0A);
+ reg23 = cx22702_readreg(state, 0x23);
- dprintk ("%s: status demod=0x%02x agc=0x%02x\n"
- ,__func__,reg0A,reg23);
+ dprintk("%s: status demod=0x%02x agc=0x%02x\n"
+ , __func__, reg0A, reg23);
- if(reg0A & 0x10) {
+ if (reg0A & 0x10) {
*status |= FE_HAS_LOCK;
*status |= FE_HAS_VITERBI;
*status |= FE_HAS_SYNC;
}
- if(reg0A & 0x20)
+ if (reg0A & 0x20)
*status |= FE_HAS_CARRIER;
- if(reg23 < 0xf0)
+ if (reg23 < 0xf0)
*status |= FE_HAS_SIGNAL;
return 0;
}
-static int cx22702_read_ber(struct dvb_frontend* fe, u32* ber)
+static int cx22702_read_ber(struct dvb_frontend *fe, u32 *ber)
{
- struct cx22702_state* state = fe->demodulator_priv;
+ struct cx22702_state *state = fe->demodulator_priv;
- if(cx22702_readreg (state, 0xE4) & 0x02) {
+ if (cx22702_readreg(state, 0xE4) & 0x02) {
/* Realtime statistics */
- *ber = (cx22702_readreg (state, 0xDE) & 0x7F) << 7
- | (cx22702_readreg (state, 0xDF)&0x7F);
+ *ber = (cx22702_readreg(state, 0xDE) & 0x7F) << 7
+ | (cx22702_readreg(state, 0xDF) & 0x7F);
} else {
/* Averagtine statistics */
- *ber = (cx22702_readreg (state, 0xDE) & 0x7F) << 7
- | cx22702_readreg (state, 0xDF);
+ *ber = (cx22702_readreg(state, 0xDE) & 0x7F) << 7
+ | cx22702_readreg(state, 0xDF);
}
return 0;
}
-static int cx22702_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
+static int cx22702_read_signal_strength(struct dvb_frontend *fe,
+ u16 *signal_strength)
{
- struct cx22702_state* state = fe->demodulator_priv;
+ struct cx22702_state *state = fe->demodulator_priv;
u16 rs_ber = 0;
- rs_ber = cx22702_readreg (state, 0x23);
+ rs_ber = cx22702_readreg(state, 0x23);
*signal_strength = (rs_ber << 8) | rs_ber;
return 0;
}
-static int cx22702_read_snr(struct dvb_frontend* fe, u16* snr)
+static int cx22702_read_snr(struct dvb_frontend *fe, u16 *snr)
{
- struct cx22702_state* state = fe->demodulator_priv;
+ struct cx22702_state *state = fe->demodulator_priv;
- u16 rs_ber=0;
- if(cx22702_readreg (state, 0xE4) & 0x02) {
+ u16 rs_ber = 0;
+ if (cx22702_readreg(state, 0xE4) & 0x02) {
/* Realtime statistics */
- rs_ber = (cx22702_readreg (state, 0xDE) & 0x7F) << 7
- | (cx22702_readreg (state, 0xDF)& 0x7F);
+ rs_ber = (cx22702_readreg(state, 0xDE) & 0x7F) << 7
+ | (cx22702_readreg(state, 0xDF) & 0x7F);
} else {
/* Averagine statistics */
- rs_ber = (cx22702_readreg (state, 0xDE) & 0x7F) << 8
- | cx22702_readreg (state, 0xDF);
+ rs_ber = (cx22702_readreg(state, 0xDE) & 0x7F) << 8
+ | cx22702_readreg(state, 0xDF);
}
*snr = ~rs_ber;
return 0;
}
-static int cx22702_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+static int cx22702_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
{
- struct cx22702_state* state = fe->demodulator_priv;
+ struct cx22702_state *state = fe->demodulator_priv;
u8 _ucblocks;
/* RS Uncorrectable Packet Count then reset */
- _ucblocks = cx22702_readreg (state, 0xE3);
+ _ucblocks = cx22702_readreg(state, 0xE3);
if (state->prevUCBlocks < _ucblocks)
*ucblocks = (_ucblocks - state->prevUCBlocks);
else
@@ -441,34 +548,36 @@ static int cx22702_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
return 0;
}
-static int cx22702_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int cx22702_get_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *p)
{
- struct cx22702_state* state = fe->demodulator_priv;
+ struct cx22702_state *state = fe->demodulator_priv;
- u8 reg0C = cx22702_readreg (state, 0x0C);
+ u8 reg0C = cx22702_readreg(state, 0x0C);
p->inversion = reg0C & 0x1 ? INVERSION_ON : INVERSION_OFF;
- return cx22702_get_tps (state, &p->u.ofdm);
+ return cx22702_get_tps(state, &p->u.ofdm);
}
-static int cx22702_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
+static int cx22702_get_tune_settings(struct dvb_frontend *fe,
+ struct dvb_frontend_tune_settings *tune)
{
tune->min_delay_ms = 1000;
return 0;
}
-static void cx22702_release(struct dvb_frontend* fe)
+static void cx22702_release(struct dvb_frontend *fe)
{
- struct cx22702_state* state = fe->demodulator_priv;
+ struct cx22702_state *state = fe->demodulator_priv;
kfree(state);
}
static struct dvb_frontend_ops cx22702_ops;
-struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
- struct i2c_adapter* i2c)
+struct dvb_frontend *cx22702_attach(const struct cx22702_config *config,
+ struct i2c_adapter *i2c)
{
- struct cx22702_state* state = NULL;
+ struct cx22702_state *state = NULL;
/* allocate memory for the internal state */
state = kmalloc(sizeof(struct cx22702_state), GFP_KERNEL);
@@ -485,7 +594,8 @@ struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
goto error;
/* create dvb_frontend */
- memcpy(&state->frontend.ops, &cx22702_ops, sizeof(struct dvb_frontend_ops));
+ memcpy(&state->frontend.ops, &cx22702_ops,
+ sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
return &state->frontend;
@@ -493,6 +603,7 @@ error:
kfree(state);
return NULL;
}
+EXPORT_SYMBOL(cx22702_attach);
static struct dvb_frontend_ops cx22702_ops = {
@@ -525,11 +636,6 @@ static struct dvb_frontend_ops cx22702_ops = {
.read_ucblocks = cx22702_read_ucblocks,
};
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Enable verbose debug messages");
-
MODULE_DESCRIPTION("Conexant CX22702 DVB-T Demodulator driver");
MODULE_AUTHOR("Steven Toth");
MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(cx22702_attach);
diff --git a/linux/drivers/media/dvb/frontends/cx22702.h b/linux/drivers/media/dvb/frontends/cx22702.h
index b1e465c6c..f154e1f42 100644
--- a/linux/drivers/media/dvb/frontends/cx22702.h
+++ b/linux/drivers/media/dvb/frontends/cx22702.h
@@ -30,8 +30,7 @@
#include <linux/dvb/frontend.h>
-struct cx22702_config
-{
+struct cx22702_config {
/* the demodulator's i2c address */
u8 demod_address;
@@ -41,16 +40,19 @@ struct cx22702_config
u8 output_mode;
};
-#if defined(CONFIG_DVB_CX22702) || (defined(CONFIG_DVB_CX22702_MODULE) && defined(MODULE))
-extern struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
- struct i2c_adapter* i2c);
+#if defined(CONFIG_DVB_CX22702) || (defined(CONFIG_DVB_CX22702_MODULE) \
+ && defined(MODULE))
+extern struct dvb_frontend *cx22702_attach(
+ const struct cx22702_config *config,
+ struct i2c_adapter *i2c);
#else
-static inline struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
- struct i2c_adapter* i2c)
+static inline struct dvb_frontend *cx22702_attach(
+ const struct cx22702_config *config,
+ struct i2c_adapter *i2c)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
-#endif // CONFIG_DVB_CX22702
+#endif
-#endif // CX22702_H
+#endif
diff --git a/linux/drivers/media/dvb/frontends/cx24116.c b/linux/drivers/media/dvb/frontends/cx24116.c
index 3c58b9f57..497ea635e 100644
--- a/linux/drivers/media/dvb/frontends/cx24116.c
+++ b/linux/drivers/media/dvb/frontends/cx24116.c
@@ -41,10 +41,14 @@
#include "dvb_frontend.h"
#include "cx24116.h"
-static int debug = 0;
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
+
#define dprintk(args...) \
do { \
- if (debug) printk ("cx24116: " args); \
+ if (debug) \
+ printk(KERN_INFO "cx24116: " args); \
} while (0)
#define CX24116_DEFAULT_FIRMWARE "dvb-fe-cx24116.fw"
@@ -68,13 +72,20 @@ static int debug = 0;
#define CX24116_REG_UCB8 (0xca)
#define CX24116_REG_CLKDIV (0xf3)
#define CX24116_REG_RATEDIV (0xf9)
-#define CX24116_REG_FECSTATUS (0x9c) /* configured fec (not tuned) or actual FEC (tuned) 1=1/2 2=2/3 etc */
+
+/* configured fec (not tuned) or actual FEC (tuned) 1=1/2 2=2/3 etc */
+#define CX24116_REG_FECSTATUS (0x9c)
/* FECSTATUS bits */
-#define CX24116_FEC_FECMASK (0x1f) /* mask to determine configured fec (not tuned) or actual fec (tuned) */
-#define CX24116_FEC_DVBS (0x20) /* Select DVB-S demodulator, else DVB-S2 */
+/* mask to determine configured fec (not tuned) or actual fec (tuned) */
+#define CX24116_FEC_FECMASK (0x1f)
+
+/* Select DVB-S demodulator, else DVB-S2 */
+#define CX24116_FEC_DVBS (0x20)
#define CX24116_FEC_UNKNOWN (0x40) /* Unknown/unused */
-#define CX24116_FEC_PILOT (0x80) /* Pilot mode requested when tuning else always reset when tuned */
+
+/* Pilot mode requested when tuning else always reset when tuned */
+#define CX24116_FEC_PILOT (0x80)
/* arg buffer size */
#define CX24116_ARGLEN (0x1e)
@@ -116,12 +127,17 @@ static int debug = 0;
/* DiSEqC tone burst */
static int toneburst = 1;
+module_param(toneburst, int, 0644);
+MODULE_PARM_DESC(toneburst, "DiSEqC toneburst 0=OFF, 1=TONE CACHE, "\
+ "2=MESSAGE CACHE (default:1)");
/* SNR measurements */
-static int esno_snr = 0;
+static int esno_snr;
+module_param(esno_snr, int, 0644);
+MODULE_PARM_DESC(debug, "SNR return units, 0=PERCENTAGE 0-100, "\
+ "1=ESNO(db * 10) (default:0)");
-enum cmds
-{
+enum cmds {
CMD_SET_VCO = 0x10,
CMD_TUNEREQUEST = 0x11,
CMD_MPEGCONFIG = 0x13,
@@ -138,8 +154,7 @@ enum cmds
};
/* The Demod/Tuner can't easily provide these, we cache them */
-struct cx24116_tuning
-{
+struct cx24116_tuning {
u32 frequency;
u32 symbol_rate;
fe_spectral_inversion_t inversion;
@@ -158,16 +173,14 @@ struct cx24116_tuning
};
/* Basic commands that are sent to the firmware */
-struct cx24116_cmd
-{
+struct cx24116_cmd {
u8 len;
u8 args[CX24116_ARGLEN];
};
-struct cx24116_state
-{
- struct i2c_adapter* i2c;
- const struct cx24116_config* config;
+struct cx24116_state {
+ struct i2c_adapter *i2c;
+ const struct cx24116_config *config;
struct dvb_frontend frontend;
@@ -179,19 +192,20 @@ struct cx24116_state
struct cx24116_cmd dsec_cmd;
};
-static int cx24116_writereg(struct cx24116_state* state, int reg, int data)
+static int cx24116_writereg(struct cx24116_state *state, int reg, int data)
{
u8 buf[] = { reg, data };
struct i2c_msg msg = { .addr = state->config->demod_address,
.flags = 0, .buf = buf, .len = 2 };
int err;
- if (debug>1)
+ if (debug > 1)
printk("cx24116: %s: write reg 0x%02x, value 0x%02x\n",
- __func__,reg, data);
+ __func__, reg, data);
- if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
- printk("%s: writereg error(err == %i, reg == 0x%02x,"
+ err = i2c_transfer(state->i2c, &msg, 1);
+ if (err != 1) {
+ printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x,"
" value == 0x%02x)\n", __func__, err, reg, data);
return -EREMOTEIO;
}
@@ -200,7 +214,8 @@ static int cx24116_writereg(struct cx24116_state* state, int reg, int data)
}
/* Bulk byte writes to a single I2C address, for 32k firmware load */
-static int cx24116_writeregN(struct cx24116_state* state, int reg, u8 *data, u16 len)
+static int cx24116_writeregN(struct cx24116_state *state, int reg,
+ const u8 *data, u16 len)
{
int ret = -EREMOTEIO;
struct i2c_msg msg;
@@ -221,12 +236,13 @@ static int cx24116_writeregN(struct cx24116_state* state, int reg, u8 *data, u16
msg.buf = buf;
msg.len = len + 1;
- if (debug>1)
- printk("cx24116: %s: write regN 0x%02x, len = %d\n",
- __func__,reg, len);
+ if (debug > 1)
+ printk(KERN_INFO "cx24116: %s: write regN 0x%02x, len = %d\n",
+ __func__, reg, len);
- if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1) {
- printk("%s: writereg error(err == %i, reg == 0x%02x\n",
+ ret = i2c_transfer(state->i2c, &msg, 1);
+ if (ret != 1) {
+ printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x\n",
__func__, ret, reg);
ret = -EREMOTEIO;
}
@@ -237,30 +253,35 @@ error:
return ret;
}
-static int cx24116_readreg(struct cx24116_state* state, u8 reg)
+static int cx24116_readreg(struct cx24116_state *state, u8 reg)
{
int ret;
u8 b0[] = { reg };
u8 b1[] = { 0 };
struct i2c_msg msg[] = {
- { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
- { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 }
+ { .addr = state->config->demod_address, .flags = 0,
+ .buf = b0, .len = 1 },
+ { .addr = state->config->demod_address, .flags = I2C_M_RD,
+ .buf = b1, .len = 1 }
};
ret = i2c_transfer(state->i2c, msg, 2);
if (ret != 2) {
- printk("%s: reg=0x%x (error=%d)\n", __func__, reg, ret);
+ printk(KERN_ERR "%s: reg=0x%x (error=%d)\n",
+ __func__, reg, ret);
return ret;
}
- if (debug>1)
- printk("cx24116: read reg 0x%02x, value 0x%02x\n",reg, b1[0]);
+ if (debug > 1)
+ printk(KERN_INFO "cx24116: read reg 0x%02x, value 0x%02x\n",
+ reg, b1[0]);
return b1[0];
}
-static int cx24116_set_inversion(struct cx24116_state* state, fe_spectral_inversion_t inversion)
+static int cx24116_set_inversion(struct cx24116_state *state,
+ fe_spectral_inversion_t inversion)
{
dprintk("%s(%d)\n", __func__, inversion);
@@ -308,10 +329,10 @@ static int cx24116_set_inversion(struct cx24116_state* state, fe_spectral_invers
* Eg.(2/3) szap "Zone Horror"
*
* mask/val = 0x04, 0x20
- * status 1f | signal c3c0 | snr a333 | ber 00000098 | unc 00000000 | FE_HAS_LOCK
+ * status 1f | signal c3c0 | snr a333 | ber 00000098 | unc 0 | FE_HAS_LOCK
*
* mask/val = 0x04, 0x30
- * status 1f | signal c3c0 | snr a333 | ber 00000000 | unc 00000000 | FE_HAS_LOCK
+ * status 1f | signal c3c0 | snr a333 | ber 00000000 | unc 0 | FE_HAS_LOCK
*
* After tuning FECSTATUS contains actual FEC
* in use numbered 1 through to 8 for 1/2 .. 2/3 etc
@@ -389,18 +410,16 @@ struct cx24116_modfec {
*/
};
-static int cx24116_lookup_fecmod(struct cx24116_state* state,
+static int cx24116_lookup_fecmod(struct cx24116_state *state,
fe_modulation_t m, fe_code_rate_t f)
{
int i, ret = -EOPNOTSUPP;
dprintk("%s(0x%02x,0x%02x)\n", __func__, m, f);
- for(i=0 ; i < sizeof(CX24116_MODFEC_MODES) / sizeof(struct cx24116_modfec) ; i++)
- {
- if( (m == CX24116_MODFEC_MODES[i].modulation) &&
- (f == CX24116_MODFEC_MODES[i].fec) )
- {
+ for (i = 0; i < ARRAY_SIZE(CX24116_MODFEC_MODES); i++) {
+ if ((m == CX24116_MODFEC_MODES[i].modulation) &&
+ (f == CX24116_MODFEC_MODES[i].fec)) {
ret = i;
break;
}
@@ -409,7 +428,8 @@ static int cx24116_lookup_fecmod(struct cx24116_state* state,
return ret;
}
-static int cx24116_set_fec(struct cx24116_state* state, fe_modulation_t mod, fe_code_rate_t fec)
+static int cx24116_set_fec(struct cx24116_state *state,
+ fe_modulation_t mod, fe_code_rate_t fec)
{
int ret = 0;
@@ -417,7 +437,7 @@ static int cx24116_set_fec(struct cx24116_state* state, fe_modulation_t mod, fe_
ret = cx24116_lookup_fecmod(state, mod, fec);
- if(ret < 0)
+ if (ret < 0)
return ret;
state->dnxt.fec = fec;
@@ -429,7 +449,7 @@ static int cx24116_set_fec(struct cx24116_state* state, fe_modulation_t mod, fe_
return 0;
}
-static int cx24116_set_symbolrate(struct cx24116_state* state, u32 rate)
+static int cx24116_set_symbolrate(struct cx24116_state *state, u32 rate)
{
dprintk("%s(%d)\n", __func__, rate);
@@ -446,42 +466,49 @@ static int cx24116_set_symbolrate(struct cx24116_state* state, u32 rate)
return 0;
}
-static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware *fw);
+static int cx24116_load_firmware(struct dvb_frontend *fe,
+ const struct firmware *fw);
-static int cx24116_firmware_ondemand(struct dvb_frontend* fe)
+static int cx24116_firmware_ondemand(struct dvb_frontend *fe)
{
struct cx24116_state *state = fe->demodulator_priv;
const struct firmware *fw;
int ret = 0;
- dprintk("%s()\n",__func__);
+ dprintk("%s()\n", __func__);
- if (cx24116_readreg(state, 0x20) > 0)
- {
+ if (cx24116_readreg(state, 0x20) > 0) {
if (state->skip_fw_load)
return 0;
/* Load firmware */
- /* request the firmware, this will block until someone uploads it */
- printk("%s: Waiting for firmware upload (%s)...\n", __func__, CX24116_DEFAULT_FIRMWARE);
- ret = request_firmware(&fw, CX24116_DEFAULT_FIRMWARE, &state->i2c->dev);
- printk("%s: Waiting for firmware upload(2)...\n", __func__);
+ /* request the firmware, this will block until loaded */
+ printk(KERN_INFO "%s: Waiting for firmware upload (%s)...\n",
+ __func__, CX24116_DEFAULT_FIRMWARE);
+ ret = request_firmware(&fw, CX24116_DEFAULT_FIRMWARE,
+ &state->i2c->dev);
+ printk(KERN_INFO "%s: Waiting for firmware upload(2)...\n",
+ __func__);
if (ret) {
- printk("%s: No firmware uploaded (timeout or file not found?)\n", __func__);
+ printk(KERN_ERR "%s: No firmware uploaded "
+ "(timeout or file not found?)\n", __func__);
return ret;
}
- /* Make sure we don't recurse back through here during loading */
+ /* Make sure we don't recurse back through here
+ * during loading */
state->skip_fw_load = 1;
ret = cx24116_load_firmware(fe, fw);
if (ret)
- printk("%s: Writing firmware to device failed\n", __func__);
+ printk(KERN_ERR "%s: Writing firmware to device failed\n",
+ __func__);
release_firmware(fw);
- printk("%s: Firmware upload %s\n", __func__, ret == 0 ? "complete" : "failed");
+ printk(KERN_INFO "%s: Firmware upload %s\n", __func__,
+ ret == 0 ? "complete" : "failed");
/* Ensure firmware is always loaded if required */
state->skip_fw_load = 0;
@@ -490,8 +517,10 @@ static int cx24116_firmware_ondemand(struct dvb_frontend* fe)
return ret;
}
-/* Take a basic firmware command structure, format it and forward it for processing */
-static int cx24116_cmd_execute(struct dvb_frontend* fe, struct cx24116_cmd *cmd)
+/* Take a basic firmware command structure, format it
+ * and forward it for processing
+ */
+static int cx24116_cmd_execute(struct dvb_frontend *fe, struct cx24116_cmd *cmd)
{
struct cx24116_state *state = fe->demodulator_priv;
int i, ret;
@@ -499,49 +528,49 @@ static int cx24116_cmd_execute(struct dvb_frontend* fe, struct cx24116_cmd *cmd)
dprintk("%s()\n", __func__);
/* Load the firmware if required */
- if ( (ret = cx24116_firmware_ondemand(fe)) != 0)
- {
- printk("%s(): Unable initialise the firmware\n", __func__);
+ ret = cx24116_firmware_ondemand(fe);
+ if (ret != 0) {
+ printk(KERN_ERR "%s(): Unable initialise the firmware\n",
+ __func__);
return ret;
}
/* Write the command */
- for(i = 0; i < cmd->len ; i++)
- {
+ for (i = 0; i < cmd->len ; i++) {
dprintk("%s: 0x%02x == 0x%02x\n", __func__, i, cmd->args[i]);
cx24116_writereg(state, i, cmd->args[i]);
}
/* Start execution and wait for cmd to terminate */
cx24116_writereg(state, CX24116_REG_EXECUTE, 0x01);
- while( cx24116_readreg(state, CX24116_REG_EXECUTE) )
- {
+ while (cx24116_readreg(state, CX24116_REG_EXECUTE)) {
msleep(10);
- if(i++ > 64)
- {
- /* Avoid looping forever if the firmware does no respond */
- printk("%s() Firmware not responding\n", __func__);
+ if (i++ > 64) {
+ /* Avoid looping forever if the firmware does
+ not respond */
+ printk(KERN_WARNING "%s() Firmware not responding\n",
+ __func__);
return -EREMOTEIO;
}
}
return 0;
}
-static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware *fw)
+static int cx24116_load_firmware(struct dvb_frontend *fe,
+ const struct firmware *fw)
{
- struct cx24116_state* state = fe->demodulator_priv;
+ struct cx24116_state *state = fe->demodulator_priv;
struct cx24116_cmd cmd;
int i, ret;
unsigned char vers[4];
dprintk("%s\n", __func__);
- dprintk("Firmware is %zu bytes (%02x %02x .. %02x %02x)\n"
- ,fw->size
- ,fw->data[0]
- ,fw->data[1]
- ,fw->data[ fw->size-2 ]
- ,fw->data[ fw->size-1 ]
- );
+ dprintk("Firmware is %zu bytes (%02x %02x .. %02x %02x)\n",
+ fw->size,
+ fw->data[0],
+ fw->data[1],
+ fw->data[fw->size-2],
+ fw->data[fw->size-1]);
/* Toggle 88x SRST pin to reset demod */
if (state->config->reset_device)
@@ -587,7 +616,7 @@ static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware
cmd.args[0x07] = 0x9d;
cmd.args[0x08] = 0xfc;
cmd.args[0x09] = 0x06;
- cmd.len= 0x0a;
+ cmd.len = 0x0a;
ret = cx24116_cmd_execute(fe, &cmd);
if (ret != 0)
return ret;
@@ -598,7 +627,7 @@ static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware
cmd.args[0x00] = CMD_TUNERINIT;
cmd.args[0x01] = 0x00;
cmd.args[0x02] = 0x00;
- cmd.len= 0x03;
+ cmd.len = 0x03;
ret = cx24116_cmd_execute(fe, &cmd);
if (ret != 0)
return ret;
@@ -615,36 +644,38 @@ static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware
else
cmd.args[0x04] = 0x02;
cmd.args[0x05] = 0x00;
- cmd.len= 0x06;
+ cmd.len = 0x06;
ret = cx24116_cmd_execute(fe, &cmd);
if (ret != 0)
return ret;
/* Firmware CMD 35: Get firmware version */
cmd.args[0x00] = CMD_UPDFWVERS;
- cmd.len= 0x02;
- for(i=0; i<4; i++) {
+ cmd.len = 0x02;
+ for (i = 0; i < 4; i++) {
cmd.args[0x01] = i;
ret = cx24116_cmd_execute(fe, &cmd);
if (ret != 0)
return ret;
- vers[i]= cx24116_readreg(state, CX24116_REG_MAILBOX);
+ vers[i] = cx24116_readreg(state, CX24116_REG_MAILBOX);
}
- printk("%s: FW version %i.%i.%i.%i\n", __func__,
+ printk(KERN_INFO "%s: FW version %i.%i.%i.%i\n", __func__,
vers[0], vers[1], vers[2], vers[3]);
return 0;
}
-static int cx24116_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+static int cx24116_set_voltage(struct dvb_frontend *fe,
+ fe_sec_voltage_t voltage)
{
/* The isl6421 module will override this function in the fops. */
- dprintk("%s() This should never appear if the isl6421 module is loaded correctly\n",__func__);
+ dprintk("%s() This should never appear if the isl6421 module "
+ "is loaded correctly\n", __func__);
return -EOPNOTSUPP;
}
-static int cx24116_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int cx24116_read_status(struct dvb_frontend *fe, fe_status_t *status)
{
struct cx24116_state *state = fe->demodulator_priv;
@@ -666,22 +697,23 @@ static int cx24116_read_status(struct dvb_frontend* fe, fe_status_t* status)
return 0;
}
-static int cx24116_read_ber(struct dvb_frontend* fe, u32* ber)
+static int cx24116_read_ber(struct dvb_frontend *fe, u32 *ber)
{
struct cx24116_state *state = fe->demodulator_priv;
dprintk("%s()\n", __func__);
- *ber = ( cx24116_readreg(state, CX24116_REG_BER24) << 24 ) |
- ( cx24116_readreg(state, CX24116_REG_BER16) << 16 ) |
- ( cx24116_readreg(state, CX24116_REG_BER8 ) << 8 ) |
- cx24116_readreg(state, CX24116_REG_BER0 );
+ *ber = (cx24116_readreg(state, CX24116_REG_BER24) << 24) |
+ (cx24116_readreg(state, CX24116_REG_BER16) << 16) |
+ (cx24116_readreg(state, CX24116_REG_BER8) << 8) |
+ cx24116_readreg(state, CX24116_REG_BER0);
return 0;
}
/* TODO Determine function and scale appropriately */
-static int cx24116_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
+static int cx24116_read_signal_strength(struct dvb_frontend *fe,
+ u16 *signal_strength)
{
struct cx24116_state *state = fe->demodulator_priv;
struct cx24116_cmd cmd;
@@ -692,39 +724,43 @@ static int cx24116_read_signal_strength(struct dvb_frontend* fe, u16* signal_str
/* Firmware CMD 19: Get AGC */
cmd.args[0x00] = CMD_GETAGC;
- cmd.len= 0x01;
+ cmd.len = 0x01;
ret = cx24116_cmd_execute(fe, &cmd);
if (ret != 0)
return ret;
- sig_reading = ( cx24116_readreg(state, CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK ) |
- ( cx24116_readreg(state, CX24116_REG_SIGNAL) << 6 );
- *signal_strength= 0 - sig_reading;
+ sig_reading =
+ (cx24116_readreg(state,
+ CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK) |
+ (cx24116_readreg(state, CX24116_REG_SIGNAL) << 6);
+ *signal_strength = 0 - sig_reading;
- dprintk("%s: raw / cooked = 0x%04x / 0x%04x\n", __func__, sig_reading, *signal_strength);
+ dprintk("%s: raw / cooked = 0x%04x / 0x%04x\n",
+ __func__, sig_reading, *signal_strength);
return 0;
}
/* SNR (0..100)% = (sig & 0xf0) * 10 + (sig & 0x0f) * 10 / 16 */
-static int cx24116_read_snr_pct(struct dvb_frontend* fe, u16* snr)
+static int cx24116_read_snr_pct(struct dvb_frontend *fe, u16 *snr)
{
struct cx24116_state *state = fe->demodulator_priv;
u8 snr_reading;
static const u32 snr_tab[] = { /* 10 x Table (rounded up) */
- 0x00000,0x0199A,0x03333,0x04ccD,0x06667,
- 0x08000,0x0999A,0x0b333,0x0cccD,0x0e667,
- 0x10000,0x1199A,0x13333,0x14ccD,0x16667,0x18000 };
+ 0x00000, 0x0199A, 0x03333, 0x04ccD, 0x06667,
+ 0x08000, 0x0999A, 0x0b333, 0x0cccD, 0x0e667,
+ 0x10000, 0x1199A, 0x13333, 0x14ccD, 0x16667,
+ 0x18000 };
dprintk("%s()\n", __func__);
snr_reading = cx24116_readreg(state, CX24116_REG_QUALITY0);
- if(snr_reading >= 0xa0 /* 100% */)
+ if (snr_reading >= 0xa0 /* 100% */)
*snr = 0xffff;
else
- *snr = snr_tab [ ( snr_reading & 0xf0 ) >> 4 ] +
- ( snr_tab [ ( snr_reading & 0x0f ) ] >> 4 );
+ *snr = snr_tab[(snr_reading & 0xf0) >> 4] +
+ (snr_tab[(snr_reading & 0x0f)] >> 4);
dprintk("%s: raw / cooked = 0x%02x / 0x%04x\n", __func__,
snr_reading, *snr);
@@ -736,7 +772,7 @@ static int cx24116_read_snr_pct(struct dvb_frontend* fe, u16* snr)
* ESNO, from 0->30db (values 0->300). We provide this value by
* default.
*/
-static int cx24116_read_snr_esno(struct dvb_frontend* fe, u16* snr)
+static int cx24116_read_snr_esno(struct dvb_frontend *fe, u16 *snr)
{
struct cx24116_state *state = fe->demodulator_priv;
@@ -750,7 +786,7 @@ static int cx24116_read_snr_esno(struct dvb_frontend* fe, u16* snr)
return 0;
}
-static int cx24116_read_snr(struct dvb_frontend* fe, u16* snr)
+static int cx24116_read_snr(struct dvb_frontend *fe, u16 *snr)
{
if (esno_snr == 1)
return cx24116_read_snr_esno(fe, snr);
@@ -758,27 +794,27 @@ static int cx24116_read_snr(struct dvb_frontend* fe, u16* snr)
return cx24116_read_snr_pct(fe, snr);
}
-static int cx24116_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+static int cx24116_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
{
struct cx24116_state *state = fe->demodulator_priv;
dprintk("%s()\n", __func__);
- *ucblocks = ( cx24116_readreg(state, CX24116_REG_UCB8) << 8 ) |
+ *ucblocks = (cx24116_readreg(state, CX24116_REG_UCB8) << 8) |
cx24116_readreg(state, CX24116_REG_UCB0);
return 0;
}
/* Overwrite the current tuning params, we are about to tune */
-static void cx24116_clone_params(struct dvb_frontend* fe)
+static void cx24116_clone_params(struct dvb_frontend *fe)
{
struct cx24116_state *state = fe->demodulator_priv;
memcpy(&state->dcur, &state->dnxt, sizeof(state->dcur));
}
/* Wait for LNB */
-static int cx24116_wait_for_lnb(struct dvb_frontend* fe)
+static int cx24116_wait_for_lnb(struct dvb_frontend *fe)
{
struct cx24116_state *state = fe->demodulator_priv;
int i;
@@ -787,7 +823,7 @@ static int cx24116_wait_for_lnb(struct dvb_frontend* fe)
cx24116_readreg(state, CX24116_REG_QSTATUS));
/* Wait for up to 300 ms */
- for(i = 0; i < 30 ; i++) {
+ for (i = 0; i < 30 ; i++) {
if (cx24116_readreg(state, CX24116_REG_QSTATUS) & 0x20)
return 0;
msleep(10);
@@ -798,20 +834,21 @@ static int cx24116_wait_for_lnb(struct dvb_frontend* fe)
return -ETIMEDOUT; /* -EBUSY ? */
}
-static int cx24116_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+static int cx24116_set_tone(struct dvb_frontend *fe,
+ fe_sec_tone_mode_t tone)
{
struct cx24116_cmd cmd;
int ret;
dprintk("%s(%d)\n", __func__, tone);
- if ( (tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF) ) {
- printk("%s: Invalid, tone=%d\n", __func__, tone);
+ if ((tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF)) {
+ printk(KERN_ERR "%s: Invalid, tone=%d\n", __func__, tone);
return -EINVAL;
}
/* Wait for LNB ready */
ret = cx24116_wait_for_lnb(fe);
- if(ret != 0)
+ if (ret != 0)
return ret;
/* Min delay time after DiSEqC send */
@@ -820,7 +857,7 @@ static int cx24116_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
/* This is always done before the tone is set */
cmd.args[0x00] = CMD_SET_TONEPRE;
cmd.args[0x01] = 0x00;
- cmd.len= 0x02;
+ cmd.len = 0x02;
ret = cx24116_cmd_execute(fe, &cmd);
if (ret != 0)
return ret;
@@ -836,11 +873,11 @@ static int cx24116_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
cmd.args[0x03] = 0x01;
break;
case SEC_TONE_OFF:
- dprintk("%s: setting tone off\n",__func__);
+ dprintk("%s: setting tone off\n", __func__);
cmd.args[0x03] = 0x00;
break;
}
- cmd.len= 0x04;
+ cmd.len = 0x04;
/* Min delay time before DiSEqC send */
msleep(15); /* XXX determine is FW does this, see send_diseqc/burst */
@@ -849,7 +886,7 @@ static int cx24116_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
}
/* Initialise DiSEqC */
-static int cx24116_diseqc_init(struct dvb_frontend* fe)
+static int cx24116_diseqc_init(struct dvb_frontend *fe)
{
struct cx24116_state *state = fe->demodulator_priv;
struct cx24116_cmd cmd;
@@ -864,7 +901,7 @@ static int cx24116_diseqc_init(struct dvb_frontend* fe)
cmd.args[0x05] = 0x28;
cmd.args[0x06] = (toneburst == CX24116_DISEQC_TONEOFF) ? 0x00 : 0x01;
cmd.args[0x07] = 0x01;
- cmd.len= 0x08;
+ cmd.len = 0x08;
ret = cx24116_cmd_execute(fe, &cmd);
if (ret != 0)
return ret;
@@ -878,36 +915,38 @@ static int cx24116_diseqc_init(struct dvb_frontend* fe)
/* Unknown */
state->dsec_cmd.args[CX24116_DISEQC_ARG2_2] = 0x02;
state->dsec_cmd.args[CX24116_DISEQC_ARG3_0] = 0x00;
- state->dsec_cmd.args[CX24116_DISEQC_ARG4_0] = 0x00; /* Continuation flag? */
+ /* Continuation flag? */
+ state->dsec_cmd.args[CX24116_DISEQC_ARG4_0] = 0x00;
/* DiSEqC message length */
state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = 0x00;
/* Command length */
- state->dsec_cmd.len= CX24116_DISEQC_MSGOFS;
+ state->dsec_cmd.len = CX24116_DISEQC_MSGOFS;
return 0;
}
/* Send DiSEqC message with derived burst (hack) || previous burst */
-static int cx24116_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *d)
+static int cx24116_send_diseqc_msg(struct dvb_frontend *fe,
+ struct dvb_diseqc_master_cmd *d)
{
struct cx24116_state *state = fe->demodulator_priv;
int i, ret;
/* Dump DiSEqC message */
if (debug) {
- printk("cx24116: %s(", __func__);
- for(i = 0 ; i < d->msg_len ;) {
- printk("0x%02x", d->msg[i]);
- if(++i < d->msg_len)
- printk(", ");
- }
+ printk(KERN_INFO "cx24116: %s(", __func__);
+ for (i = 0 ; i < d->msg_len ;) {
+ printk(KERN_INFO "0x%02x", d->msg[i]);
+ if (++i < d->msg_len)
+ printk(KERN_INFO ", ");
+ }
printk(") toneburst=%d\n", toneburst);
}
/* Validate length */
- if(d->msg_len > (CX24116_ARGLEN - CX24116_DISEQC_MSGOFS))
+ if (d->msg_len > (CX24116_ARGLEN - CX24116_DISEQC_MSGOFS))
return -EINVAL;
/* DiSEqC message */
@@ -918,18 +957,19 @@ static int cx24116_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_ma
state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = d->msg_len;
/* Command length */
- state->dsec_cmd.len= CX24116_DISEQC_MSGOFS + state->dsec_cmd.args[CX24116_DISEQC_MSGLEN];
+ state->dsec_cmd.len = CX24116_DISEQC_MSGOFS +
+ state->dsec_cmd.args[CX24116_DISEQC_MSGLEN];
/* DiSEqC toneburst */
- if(toneburst == CX24116_DISEQC_MESGCACHE)
+ if (toneburst == CX24116_DISEQC_MESGCACHE)
/* Message is cached */
return 0;
- else if(toneburst == CX24116_DISEQC_TONEOFF)
+ else if (toneburst == CX24116_DISEQC_TONEOFF)
/* Message is sent without burst */
state->dsec_cmd.args[CX24116_DISEQC_BURST] = 0;
- else if(toneburst == CX24116_DISEQC_TONECACHE) {
+ else if (toneburst == CX24116_DISEQC_TONECACHE) {
/*
* Message is sent with derived else cached burst
*
@@ -948,15 +988,17 @@ static int cx24116_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_ma
* Y = VOLTAGE (0=13V, 1=18V)
* Z = BAND (0=LOW, 1=HIGH(22K))
*/
- if(d->msg_len >= 4 && d->msg[2] == 0x38)
- state->dsec_cmd.args[CX24116_DISEQC_BURST] = ((d->msg[3] & 4) >> 2);
- if(debug)
- dprintk("%s burst=%d\n", __func__, state->dsec_cmd.args[CX24116_DISEQC_BURST]);
+ if (d->msg_len >= 4 && d->msg[2] == 0x38)
+ state->dsec_cmd.args[CX24116_DISEQC_BURST] =
+ ((d->msg[3] & 4) >> 2);
+ if (debug)
+ dprintk("%s burst=%d\n", __func__,
+ state->dsec_cmd.args[CX24116_DISEQC_BURST]);
}
/* Wait for LNB ready */
ret = cx24116_wait_for_lnb(fe);
- if(ret != 0)
+ if (ret != 0)
return ret;
/* Wait for voltage/min repeat delay */
@@ -964,7 +1006,7 @@ static int cx24116_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_ma
/* Command */
ret = cx24116_cmd_execute(fe, &state->dsec_cmd);
- if(ret != 0)
+ if (ret != 0)
return ret;
/*
* Wait for send
@@ -976,29 +1018,33 @@ static int cx24116_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_ma
* 12.5ms burst +
* >15ms delay (XXX determine if FW does this, see set_tone)
*/
- msleep( (state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + ((toneburst == CX24116_DISEQC_TONEOFF) ? 30 : 60) );
+ msleep((state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) +
+ ((toneburst == CX24116_DISEQC_TONEOFF) ? 30 : 60));
return 0;
}
/* Send DiSEqC burst */
-static int cx24116_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
+static int cx24116_diseqc_send_burst(struct dvb_frontend *fe,
+ fe_sec_mini_cmd_t burst)
{
struct cx24116_state *state = fe->demodulator_priv;
int ret;
- dprintk("%s(%d) toneburst=%d\n",__func__, burst, toneburst);
+ dprintk("%s(%d) toneburst=%d\n", __func__, burst, toneburst);
/* DiSEqC burst */
if (burst == SEC_MINI_A)
- state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_A;
- else if(burst == SEC_MINI_B)
- state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_B;
+ state->dsec_cmd.args[CX24116_DISEQC_BURST] =
+ CX24116_DISEQC_MINI_A;
+ else if (burst == SEC_MINI_B)
+ state->dsec_cmd.args[CX24116_DISEQC_BURST] =
+ CX24116_DISEQC_MINI_B;
else
return -EINVAL;
/* DiSEqC toneburst */
- if(toneburst != CX24116_DISEQC_MESGCACHE)
+ if (toneburst != CX24116_DISEQC_MESGCACHE)
/* Burst is cached */
return 0;
@@ -1006,7 +1052,7 @@ static int cx24116_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t
/* Wait for LNB ready */
ret = cx24116_wait_for_lnb(fe);
- if(ret != 0)
+ if (ret != 0)
return ret;
/* Wait for voltage/min repeat delay */
@@ -1014,7 +1060,7 @@ static int cx24116_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t
/* Command */
ret = cx24116_cmd_execute(fe, &state->dsec_cmd);
- if(ret != 0)
+ if (ret != 0)
return ret;
/*
@@ -1027,34 +1073,32 @@ static int cx24116_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t
* 12.5ms burst +
* >15ms delay (XXX determine if FW does this, see set_tone)
*/
- msleep( (state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + 60 );
+ msleep((state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + 60);
return 0;
}
-static void cx24116_release(struct dvb_frontend* fe)
+static void cx24116_release(struct dvb_frontend *fe)
{
- struct cx24116_state* state = fe->demodulator_priv;
- dprintk("%s\n",__func__);
+ struct cx24116_state *state = fe->demodulator_priv;
+ dprintk("%s\n", __func__);
kfree(state);
}
static struct dvb_frontend_ops cx24116_ops;
-struct dvb_frontend* cx24116_attach(const struct cx24116_config* config,
- struct i2c_adapter* i2c)
+struct dvb_frontend *cx24116_attach(const struct cx24116_config *config,
+ struct i2c_adapter *i2c)
{
- struct cx24116_state* state = NULL;
+ struct cx24116_state *state = NULL;
int ret;
- dprintk("%s\n",__func__);
+ dprintk("%s\n", __func__);
/* allocate memory for the internal state */
state = kmalloc(sizeof(struct cx24116_state), GFP_KERNEL);
- if (state == NULL) {
- printk("Unable to kmalloc\n");
+ if (state == NULL)
goto error1;
- }
/* setup the state */
memset(state, 0, sizeof(struct cx24116_state));
@@ -1063,27 +1107,31 @@ struct dvb_frontend* cx24116_attach(const struct cx24116_config* config,
state->i2c = i2c;
/* check if the demod is present */
- ret = (cx24116_readreg(state, 0xFF) << 8) | cx24116_readreg(state, 0xFE);
+ ret = (cx24116_readreg(state, 0xFF) << 8) |
+ cx24116_readreg(state, 0xFE);
if (ret != 0x0501) {
- printk("Invalid probe, probably not a CX24116 device\n");
+ printk(KERN_INFO "Invalid probe, probably not a CX24116 device\n");
goto error2;
}
/* create dvb_frontend */
- memcpy(&state->frontend.ops, &cx24116_ops, sizeof(struct dvb_frontend_ops));
+ memcpy(&state->frontend.ops, &cx24116_ops,
+ sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
return &state->frontend;
error2: kfree(state);
error1: return NULL;
}
+EXPORT_SYMBOL(cx24116_attach);
+
#if 0
-static int cx24116_get_params(struct dvb_frontend* fe)
+static int cx24116_get_params(struct dvb_frontend *fe)
{
struct cx24116_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *cache = &fe->dtv_property_cache;
- dprintk("%s()\n",__func__);
+ dprintk("%s()\n", __func__);
cache->frequency = state->dcur.frequency;
cache->inversion = state->dcur.inversion;
@@ -1099,13 +1147,13 @@ static int cx24116_get_params(struct dvb_frontend* fe)
*
* Power config will reset and load initial firmware if required
*/
-static int cx24116_initfe(struct dvb_frontend* fe)
+static int cx24116_initfe(struct dvb_frontend *fe)
{
- struct cx24116_state* state = fe->demodulator_priv;
+ struct cx24116_state *state = fe->demodulator_priv;
struct cx24116_cmd cmd;
int ret;
- dprintk("%s()\n",__func__);
+ dprintk("%s()\n", __func__);
/* Power on */
cx24116_writereg(state, 0xe0, 0);
@@ -1115,9 +1163,9 @@ static int cx24116_initfe(struct dvb_frontend* fe)
/* Firmware CMD 36: Power config */
cmd.args[0x00] = CMD_TUNERSLEEP;
cmd.args[0x01] = 0;
- cmd.len= 0x02;
+ cmd.len = 0x02;
ret = cx24116_cmd_execute(fe, &cmd);
- if(ret != 0)
+ if (ret != 0)
return ret;
return cx24116_diseqc_init(fe);
@@ -1126,20 +1174,20 @@ static int cx24116_initfe(struct dvb_frontend* fe)
/*
* Put device to sleep
*/
-static int cx24116_sleep(struct dvb_frontend* fe)
+static int cx24116_sleep(struct dvb_frontend *fe)
{
- struct cx24116_state* state = fe->demodulator_priv;
+ struct cx24116_state *state = fe->demodulator_priv;
struct cx24116_cmd cmd;
int ret;
- dprintk("%s()\n",__func__);
+ dprintk("%s()\n", __func__);
/* Firmware CMD 36: Power config */
cmd.args[0x00] = CMD_TUNERSLEEP;
cmd.args[0x01] = 1;
- cmd.len= 0x02;
+ cmd.len = 0x02;
ret = cx24116_cmd_execute(fe, &cmd);
- if(ret != 0)
+ if (ret != 0)
return ret;
/* Power off (Shutdown clocks) */
@@ -1150,13 +1198,15 @@ static int cx24116_sleep(struct dvb_frontend* fe)
return 0;
}
-static int cx24116_set_property(struct dvb_frontend *fe, struct dtv_property* tvp)
+static int cx24116_set_property(struct dvb_frontend *fe,
+ struct dtv_property *tvp)
{
dprintk("%s(..)\n", __func__);
return 0;
}
-static int cx24116_get_property(struct dvb_frontend *fe, struct dtv_property* tvp)
+static int cx24116_get_property(struct dvb_frontend *fe,
+ struct dtv_property *tvp)
{
dprintk("%s(..)\n", __func__);
return 0;
@@ -1165,7 +1215,8 @@ static int cx24116_get_property(struct dvb_frontend *fe, struct dtv_property* tv
/* dvb-core told us to tune, the tv property cache will be complete,
* it's safe for is to pull values and use them for tuning purposes.
*/
-static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int cx24116_set_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *p)
{
struct cx24116_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
@@ -1173,96 +1224,102 @@ static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
fe_status_t tunerstat;
int i, status, ret, retune;
- dprintk("%s()\n",__func__);
+ dprintk("%s()\n", __func__);
- switch(c->delivery_system) {
- case SYS_DVBS:
- dprintk("%s: DVB-S delivery system selected\n",__func__);
+ switch (c->delivery_system) {
+ case SYS_DVBS:
+ dprintk("%s: DVB-S delivery system selected\n", __func__);
- /* Only QPSK is supported for DVB-S */
- if(c->modulation != QPSK) {
- dprintk("%s: unsupported modulation selected (%d)\n",
- __func__, c->modulation);
- return -EOPNOTSUPP;
- }
+ /* Only QPSK is supported for DVB-S */
+ if (c->modulation != QPSK) {
+ dprintk("%s: unsupported modulation selected (%d)\n",
+ __func__, c->modulation);
+ return -EOPNOTSUPP;
+ }
- /* Pilot doesn't exist in DVB-S, turn bit off */
- state->dnxt.pilot_val = CX24116_PILOT_OFF;
- retune = 1;
+ /* Pilot doesn't exist in DVB-S, turn bit off */
+ state->dnxt.pilot_val = CX24116_PILOT_OFF;
+ retune = 1;
- /* DVB-S only supports 0.35 */
- if(c->rolloff != ROLLOFF_35) {
- dprintk("%s: unsupported rolloff selected (%d)\n",
- __func__, c->rolloff);
- return -EOPNOTSUPP;
- }
- state->dnxt.rolloff_val = CX24116_ROLLOFF_035;
- break;
+ /* DVB-S only supports 0.35 */
+ if (c->rolloff != ROLLOFF_35) {
+ dprintk("%s: unsupported rolloff selected (%d)\n",
+ __func__, c->rolloff);
+ return -EOPNOTSUPP;
+ }
+ state->dnxt.rolloff_val = CX24116_ROLLOFF_035;
+ break;
- case SYS_DVBS2:
- dprintk("%s: DVB-S2 delivery system selected\n",__func__);
-
- /*
- * NBC 8PSK/QPSK with DVB-S is supported for DVB-S2,
- * but not hardware auto detection
- */
- if(c->modulation != PSK_8 && c->modulation != QPSK) {
- dprintk("%s: unsupported modulation selected (%d)\n",
- __func__, c->modulation);
- return -EOPNOTSUPP;
- }
+ case SYS_DVBS2:
+ dprintk("%s: DVB-S2 delivery system selected\n", __func__);
- switch(c->pilot) {
- case PILOT_AUTO: /* Not supported but emulated */
- retune = 2; /* Fall-through */
- case PILOT_OFF:
- state->dnxt.pilot_val = CX24116_PILOT_OFF;
- break;
- case PILOT_ON:
- state->dnxt.pilot_val = CX24116_PILOT_ON;
- break;
- default:
- dprintk("%s: unsupported pilot mode selected (%d)\n",
- __func__, c->pilot);
- return -EOPNOTSUPP;
- }
+ /*
+ * NBC 8PSK/QPSK with DVB-S is supported for DVB-S2,
+ * but not hardware auto detection
+ */
+ if (c->modulation != PSK_8 && c->modulation != QPSK) {
+ dprintk("%s: unsupported modulation selected (%d)\n",
+ __func__, c->modulation);
+ return -EOPNOTSUPP;
+ }
- switch(c->rolloff) {
- case ROLLOFF_20:
- state->dnxt.rolloff_val= CX24116_ROLLOFF_020;
- break;
- case ROLLOFF_25:
- state->dnxt.rolloff_val= CX24116_ROLLOFF_025;
- break;
- case ROLLOFF_35:
- state->dnxt.rolloff_val= CX24116_ROLLOFF_035;
- break;
- case ROLLOFF_AUTO: /* Rolloff must be explicit */
- default:
- dprintk("%s: unsupported rolloff selected (%d)\n",
- __func__, c->rolloff);
- return -EOPNOTSUPP;
- }
+ switch (c->pilot) {
+ case PILOT_AUTO: /* Not supported but emulated */
+ state->dnxt.pilot_val = (c->modulation == QPSK)
+ ? CX24116_PILOT_OFF : CX24116_PILOT_ON;
+ retune = 2;
+ break;
+ case PILOT_OFF:
+ state->dnxt.pilot_val = CX24116_PILOT_OFF;
+ break;
+ case PILOT_ON:
+ state->dnxt.pilot_val = CX24116_PILOT_ON;
break;
+ default:
+ dprintk("%s: unsupported pilot mode selected (%d)\n",
+ __func__, c->pilot);
+ return -EOPNOTSUPP;
+ }
+ switch (c->rolloff) {
+ case ROLLOFF_20:
+ state->dnxt.rolloff_val = CX24116_ROLLOFF_020;
+ break;
+ case ROLLOFF_25:
+ state->dnxt.rolloff_val = CX24116_ROLLOFF_025;
+ break;
+ case ROLLOFF_35:
+ state->dnxt.rolloff_val = CX24116_ROLLOFF_035;
+ break;
+ case ROLLOFF_AUTO: /* Rolloff must be explicit */
default:
- dprintk("%s: unsupported delivery system selected (%d)\n",
- __func__, c->delivery_system);
+ dprintk("%s: unsupported rolloff selected (%d)\n",
+ __func__, c->rolloff);
return -EOPNOTSUPP;
+ }
+ break;
+
+ default:
+ dprintk("%s: unsupported delivery system selected (%d)\n",
+ __func__, c->delivery_system);
+ return -EOPNOTSUPP;
}
state->dnxt.modulation = c->modulation;
state->dnxt.frequency = c->frequency;
state->dnxt.pilot = c->pilot;
state->dnxt.rolloff = c->rolloff;
- if ((ret = cx24116_set_inversion(state, c->inversion)) != 0)
+ ret = cx24116_set_inversion(state, c->inversion);
+ if (ret != 0)
return ret;
/* FEC_NONE/AUTO for DVB-S2 is not supported and detected here */
- if ((ret = cx24116_set_fec(state, c->modulation, c->fec_inner)) != 0)
+ ret = cx24116_set_fec(state, c->modulation, c->fec_inner);
+ if (ret != 0)
return ret;
- if ((ret = cx24116_set_symbolrate(state, c->symbol_rate)) != 0)
+ ret = cx24116_set_symbolrate(state, c->symbol_rate);
+ if (ret != 0)
return ret;
/* discard the 'current' tuning parameters and prepare to tune */
@@ -1288,7 +1345,7 @@ static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
/* Set/Reset B/W */
cmd.args[0x00] = CMD_BANDWIDTH;
cmd.args[0x01] = 0x01;
- cmd.len= 0x02;
+ cmd.len = 0x02;
ret = cx24116_cmd_execute(fe, &cmd);
if (ret != 0)
return ret;
@@ -1336,7 +1393,7 @@ static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
cx24116_writereg(state, CX24116_REG_RATEDIV, 0x00);
}
- cmd.len= 0x13;
+ cmd.len = 0x13;
/* We need to support pilot and non-pilot tuning in the
* driver automatically. This is a workaround for because
@@ -1344,12 +1401,13 @@ static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
*/
do {
/* Reset status register */
- status = cx24116_readreg(state, CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK;
+ status = cx24116_readreg(state, CX24116_REG_SSTATUS)
+ & CX24116_SIGNAL_MASK;
cx24116_writereg(state, CX24116_REG_SSTATUS, status);
/* Tune */
ret = cx24116_cmd_execute(fe, &cmd);
- if( ret != 0 )
+ if (ret != 0)
break;
/*
@@ -1358,28 +1416,27 @@ static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
* If we are able to tune then generally it occurs within 100ms.
* If it takes longer, try a different toneburst setting.
*/
- for(i = 0; i < 50 ; i++) {
+ for (i = 0; i < 50 ; i++) {
cx24116_read_status(fe, &tunerstat);
status = tunerstat & (FE_HAS_SIGNAL | FE_HAS_SYNC);
- if(status == (FE_HAS_SIGNAL | FE_HAS_SYNC)) {
- dprintk("%s: Tuned\n",__func__);
+ if (status == (FE_HAS_SIGNAL | FE_HAS_SYNC)) {
+ dprintk("%s: Tuned\n", __func__);
goto tuned;
}
msleep(10);
}
- dprintk("%s: Not tuned\n",__func__);
+ dprintk("%s: Not tuned\n", __func__);
/* Toggle pilot bit when in auto-pilot */
- if(state->dcur.pilot == PILOT_AUTO)
+ if (state->dcur.pilot == PILOT_AUTO)
cmd.args[0x07] ^= CX24116_PILOT_ON;
- }
- while(--retune);
+ } while (--retune);
tuned: /* Set/Reset B/W */
cmd.args[0x00] = CMD_BANDWIDTH;
cmd.args[0x01] = 0x00;
- cmd.len= 0x02;
+ cmd.len = 0x02;
ret = cx24116_cmd_execute(fe, &cmd);
if (ret != 0)
return ret;
@@ -1424,17 +1481,7 @@ static struct dvb_frontend_ops cx24116_ops = {
.set_frontend = cx24116_set_frontend,
};
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
-
-module_param(toneburst, int, 0644);
-MODULE_PARM_DESC(toneburst, "DiSEqC toneburst 0=OFF, 1=TONE CACHE, 2=MESSAGE CACHE (default:1)");
-
-module_param(esno_snr, int, 0644);
-MODULE_PARM_DESC(debug, "SNR return units, 0=PERCENTAGE 0-100, 1=ESNO(db * 10) (default:0)");
-
MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24116/cx24118 hardware");
MODULE_AUTHOR("Steven Toth");
MODULE_LICENSE("GPL");
-EXPORT_SYMBOL(cx24116_attach);
diff --git a/linux/drivers/media/dvb/frontends/cx24116.h b/linux/drivers/media/dvb/frontends/cx24116.h
index 8dbcec268..4cb3ddd6c 100644
--- a/linux/drivers/media/dvb/frontends/cx24116.h
+++ b/linux/drivers/media/dvb/frontends/cx24116.h
@@ -23,31 +23,32 @@
#include <linux/dvb/frontend.h>
-struct cx24116_config
-{
+struct cx24116_config {
/* the demodulator's i2c address */
u8 demod_address;
/* Need to set device param for start_dma */
- int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
+ int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured);
/* Need to reset device during firmware loading */
- int (*reset_device)(struct dvb_frontend* fe);
+ int (*reset_device)(struct dvb_frontend *fe);
/* Need to set MPEG parameters */
u8 mpg_clk_pos_pol:0x02;
};
#if defined(CONFIG_DVB_CX24116) || defined(CONFIG_DVB_CX24116_MODULE)
-extern struct dvb_frontend* cx24116_attach(const struct cx24116_config* config,
- struct i2c_adapter* i2c);
+extern struct dvb_frontend *cx24116_attach(
+ const struct cx24116_config *config,
+ struct i2c_adapter *i2c);
#else
-static inline struct dvb_frontend* cx24116_attach(const struct cx24116_config* config,
- struct i2c_adapter* i2c)
+static inline struct dvb_frontend *cx24116_attach(
+ const struct cx24116_config *config,
+ struct i2c_adapter *i2c)
{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
-#endif // CONFIG_DVB_CX24116
+#endif
#endif /* CX24116_H */
diff --git a/linux/drivers/media/dvb/frontends/cx24123.c b/linux/drivers/media/dvb/frontends/cx24123.c
index 970e4df08..fb559369e 100644
--- a/linux/drivers/media/dvb/frontends/cx24123.c
+++ b/linux/drivers/media/dvb/frontends/cx24123.c
@@ -33,7 +33,13 @@
#define XTAL 10111000
static int force_band;
+module_param(force_band, int, 0644);
+MODULE_PARM_DESC(force_band, "Force a specific band select "\
+ "(1-9, default:off).");
+
static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
#define info(args...) do { printk(KERN_INFO "CX24123: " args); } while (0)
#define err(args...) do { printk(KERN_ERR "CX24123: " args); } while (0)
@@ -46,10 +52,9 @@ static int debug;
} \
} while (0)
-struct cx24123_state
-{
- struct i2c_adapter* i2c;
- const struct cx24123_config* config;
+struct cx24123_state {
+ struct i2c_adapter *i2c;
+ const struct cx24123_config *config;
struct dvb_frontend frontend;
@@ -70,8 +75,7 @@ struct cx24123_state
};
/* Various tuner defaults need to be established for a given symbol rate Sps */
-static struct
-{
+static struct cx24123_AGC_val {
u32 symbolrate_low;
u32 symbolrate_high;
u32 VCAprogdata;
@@ -109,8 +113,7 @@ static struct
* fixme: The bounds on the bands do not match the doc in real life.
* fixme: Some of them have been moved, other might need adjustment.
*/
-static struct
-{
+static struct cx24123_bandselect_val {
u32 freq_low;
u32 freq_high;
u32 VCOdivider;
@@ -260,7 +263,8 @@ static int cx24123_i2c_writereg(struct cx24123_state *state,
/* printk(KERN_DEBUG "wr(%02x): %02x %02x\n", i2c_addr, reg, data); */
- if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
+ err = i2c_transfer(state->i2c, &msg, 1);
+ if (err != 1) {
printk("%s: writereg error(err == %i, reg == 0x%02x,"
" data == 0x%02x)\n", __func__, err, reg, data);
return err;
@@ -295,7 +299,8 @@ static int cx24123_i2c_readreg(struct cx24123_state *state, u8 i2c_addr, u8 reg)
#define cx24123_writereg(state, reg, val) \
cx24123_i2c_writereg(state, state->config->demod_address, reg, val)
-static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_inversion_t inversion)
+static int cx24123_set_inversion(struct cx24123_state *state,
+ fe_spectral_inversion_t inversion)
{
u8 nom_reg = cx24123_readreg(state, 0x0e);
u8 auto_reg = cx24123_readreg(state, 0x10);
@@ -322,7 +327,8 @@ static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_invers
return 0;
}
-static int cx24123_get_inversion(struct cx24123_state* state, fe_spectral_inversion_t *inversion)
+static int cx24123_get_inversion(struct cx24123_state *state,
+ fe_spectral_inversion_t *inversion)
{
u8 val;
@@ -339,18 +345,20 @@ static int cx24123_get_inversion(struct cx24123_state* state, fe_spectral_invers
return 0;
}
-static int cx24123_set_fec(struct cx24123_state* state, fe_code_rate_t fec)
+static int cx24123_set_fec(struct cx24123_state *state, fe_code_rate_t fec)
{
u8 nom_reg = cx24123_readreg(state, 0x0e) & ~0x07;
- if ( (fec < FEC_NONE) || (fec > FEC_AUTO) )
+ if ((fec < FEC_NONE) || (fec > FEC_AUTO))
fec = FEC_AUTO;
/* Set the soft decision threshold */
- if(fec == FEC_1_2)
- cx24123_writereg(state, 0x43, cx24123_readreg(state, 0x43) | 0x01);
+ if (fec == FEC_1_2)
+ cx24123_writereg(state, 0x43,
+ cx24123_readreg(state, 0x43) | 0x01);
else
- cx24123_writereg(state, 0x43, cx24123_readreg(state, 0x43) & ~0x01);
+ cx24123_writereg(state, 0x43,
+ cx24123_readreg(state, 0x43) & ~0x01);
switch (fec) {
case FEC_1_2:
@@ -399,11 +407,11 @@ static int cx24123_set_fec(struct cx24123_state* state, fe_code_rate_t fec)
return 0;
}
-static int cx24123_get_fec(struct cx24123_state* state, fe_code_rate_t *fec)
+static int cx24123_get_fec(struct cx24123_state *state, fe_code_rate_t *fec)
{
int ret;
- ret = cx24123_readreg (state, 0x1b);
+ ret = cx24123_readreg(state, 0x1b);
if (ret < 0)
return ret;
ret = ret & 0x07;
@@ -444,16 +452,16 @@ static u32 cx24123_int_log2(u32 a, u32 b)
{
u32 exp, nearest = 0;
u32 div = a / b;
- if(a % b >= b / 2) ++div;
- if(div < (1 << 31))
- {
- for(exp = 1; div > exp; nearest++)
+ if (a % b >= b / 2)
+ ++div;
+ if (div < (1 << 31)) {
+ for (exp = 1; div > exp; nearest++)
exp += exp;
}
return nearest;
}
-static int cx24123_set_symbolrate(struct cx24123_state* state, u32 srate)
+static int cx24123_set_symbolrate(struct cx24123_state *state, u32 srate)
{
u32 tmp, sample_rate, ratio, sample_gain;
u8 pll_mult;
@@ -509,9 +517,9 @@ static int cx24123_set_symbolrate(struct cx24123_state* state, u32 srate)
cx24123_writereg(state, 0x01, pll_mult * 6);
- cx24123_writereg(state, 0x08, (ratio >> 16) & 0x3f );
- cx24123_writereg(state, 0x09, (ratio >> 8) & 0xff );
- cx24123_writereg(state, 0x0a, (ratio ) & 0xff );
+ cx24123_writereg(state, 0x08, (ratio >> 16) & 0x3f);
+ cx24123_writereg(state, 0x09, (ratio >> 8) & 0xff);
+ cx24123_writereg(state, 0x0a, ratio & 0xff);
/* also set the demodulator sample gain */
sample_gain = cx24123_int_log2(sample_rate, srate);
@@ -525,10 +533,12 @@ static int cx24123_set_symbolrate(struct cx24123_state* state, u32 srate)
}
/*
- * Based on the required frequency and symbolrate, the tuner AGC has to be configured
- * and the correct band selected. Calculate those values
+ * Based on the required frequency and symbolrate, the tuner AGC has
+ * to be configured and the correct band selected.
+ * Calculate those values.
*/
-static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int cx24123_pll_calculate(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *p)
{
struct cx24123_state *state = fe->demodulator_priv;
u32 ndiv = 0, adiv = 0, vco_div = 0;
@@ -536,6 +546,8 @@ static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_pa
int pump = 2;
int band = 0;
int num_bands = ARRAY_SIZE(cx24123_bandselect_vals);
+ struct cx24123_bandselect_val *bsv = NULL;
+ struct cx24123_AGC_val *agcv = NULL;
/* Defaults for low freq, low rate */
state->VCAarg = cx24123_AGC_vals[0].VCAprogdata;
@@ -543,58 +555,65 @@ static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_pa
state->bandselectarg = cx24123_bandselect_vals[0].progdata;
vco_div = cx24123_bandselect_vals[0].VCOdivider;
- /* For the given symbol rate, determine the VCA, VGA and FILTUNE programming bits */
- for (i = 0; i < ARRAY_SIZE(cx24123_AGC_vals); i++)
- {
- if ((cx24123_AGC_vals[i].symbolrate_low <= p->u.qpsk.symbol_rate) &&
- (cx24123_AGC_vals[i].symbolrate_high >= p->u.qpsk.symbol_rate) ) {
- state->VCAarg = cx24123_AGC_vals[i].VCAprogdata;
- state->VGAarg = cx24123_AGC_vals[i].VGAprogdata;
- state->FILTune = cx24123_AGC_vals[i].FILTune;
+ /* For the given symbol rate, determine the VCA, VGA and
+ * FILTUNE programming bits */
+ for (i = 0; i < ARRAY_SIZE(cx24123_AGC_vals); i++) {
+ agcv = &cx24123_AGC_vals[i];
+ if ((agcv->symbolrate_low <= p->u.qpsk.symbol_rate) &&
+ (agcv->symbolrate_high >= p->u.qpsk.symbol_rate)) {
+ state->VCAarg = agcv->VCAprogdata;
+ state->VGAarg = agcv->VGAprogdata;
+ state->FILTune = agcv->FILTune;
}
}
/* determine the band to use */
- if(force_band < 1 || force_band > num_bands)
- {
- for (i = 0; i < num_bands; i++)
- {
- if ((cx24123_bandselect_vals[i].freq_low <= p->frequency) &&
- (cx24123_bandselect_vals[i].freq_high >= p->frequency) )
+ if (force_band < 1 || force_band > num_bands) {
+ for (i = 0; i < num_bands; i++) {
+ bsv = &cx24123_bandselect_vals[i];
+ if ((bsv->freq_low <= p->frequency) &&
+ (bsv->freq_high >= p->frequency))
band = i;
}
- }
- else
+ } else
band = force_band - 1;
state->bandselectarg = cx24123_bandselect_vals[band].progdata;
vco_div = cx24123_bandselect_vals[band].VCOdivider;
/* determine the charge pump current */
- if ( p->frequency < (cx24123_bandselect_vals[band].freq_low + cx24123_bandselect_vals[band].freq_high)/2 )
+ if (p->frequency < (cx24123_bandselect_vals[band].freq_low +
+ cx24123_bandselect_vals[band].freq_high) / 2)
pump = 0x01;
else
pump = 0x02;
/* Determine the N/A dividers for the requested lband freq (in kHz). */
- /* Note: the reference divider R=10, frequency is in KHz, XTAL is in Hz */
- ndiv = ( ((p->frequency * vco_div * 10) / (2 * XTAL / 1000)) / 32) & 0x1ff;
- adiv = ( ((p->frequency * vco_div * 10) / (2 * XTAL / 1000)) % 32) & 0x1f;
+ /* Note: the reference divider R=10, frequency is in KHz,
+ * XTAL is in Hz */
+ ndiv = (((p->frequency * vco_div * 10) /
+ (2 * XTAL / 1000)) / 32) & 0x1ff;
+ adiv = (((p->frequency * vco_div * 10) /
+ (2 * XTAL / 1000)) % 32) & 0x1f;
if (adiv == 0 && ndiv > 0)
ndiv--;
- /* control bits 11, refdiv 11, charge pump polarity 1, charge pump current, ndiv, adiv */
- state->pllarg = (3 << 19) | (3 << 17) | (1 << 16) | (pump << 14) | (ndiv << 5) | adiv;
+ /* control bits 11, refdiv 11, charge pump polarity 1,
+ * charge pump current, ndiv, adiv */
+ state->pllarg = (3 << 19) | (3 << 17) | (1 << 16) |
+ (pump << 14) | (ndiv << 5) | adiv;
return 0;
}
/*
* Tuner data is 21 bits long, must be left-aligned in data.
- * Tuner cx24109 is written through a dedicated 3wire interface on the demod chip.
+ * Tuner cx24109 is written through a dedicated 3wire interface
+ * on the demod chip.
*/
-static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_parameters *p, u32 data)
+static int cx24123_pll_writereg(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *p, u32 data)
{
struct cx24123_state *state = fe->demodulator_priv;
unsigned long timeout;
@@ -621,7 +640,7 @@ static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_par
/* send another 8 bytes, wait for the send to be completed */
timeout = jiffies + msecs_to_jiffies(40);
- cx24123_writereg(state, 0x22, (data>>8) & 0xff );
+ cx24123_writereg(state, 0x22, (data >> 8) & 0xff);
while ((cx24123_readreg(state, 0x20) & 0x40) == 0) {
if (time_after(jiffies, timeout)) {
err("%s: demodulator is not responding, "\
@@ -631,9 +650,10 @@ static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_par
msleep(10);
}
- /* send the lower 5 bits of this byte, padded with 3 LBB, wait for the send to be completed */
+ /* send the lower 5 bits of this byte, padded with 3 LBB,
+ * wait for the send to be completed */
timeout = jiffies + msecs_to_jiffies(40);
- cx24123_writereg(state, 0x22, (data) & 0xff );
+ cx24123_writereg(state, 0x22, (data) & 0xff);
while ((cx24123_readreg(state, 0x20) & 0x80)) {
if (time_after(jiffies, timeout)) {
err("%s: demodulator is not responding," \
@@ -650,7 +670,8 @@ static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_par
return 0;
}
-static int cx24123_pll_tune(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int cx24123_pll_tune(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *p)
{
struct cx24123_state *state = fe->demodulator_priv;
u8 val;
@@ -701,7 +722,7 @@ static int cx24123_repeater_mode(struct cx24123_state *state, u8 mode, u8 start)
return cx24123_writereg(state, 0x23, r);
}
-static int cx24123_initfe(struct dvb_frontend* fe)
+static int cx24123_initfe(struct dvb_frontend *fe)
{
struct cx24123_state *state = fe->demodulator_priv;
int i;
@@ -710,19 +731,22 @@ static int cx24123_initfe(struct dvb_frontend* fe)
/* Configure the demod to a good set of defaults */
for (i = 0; i < ARRAY_SIZE(cx24123_regdata); i++)
- cx24123_writereg(state, cx24123_regdata[i].reg, cx24123_regdata[i].data);
+ cx24123_writereg(state, cx24123_regdata[i].reg,
+ cx24123_regdata[i].data);
/* Set the LNB polarity */
- if(state->config->lnb_polarity)
- cx24123_writereg(state, 0x32, cx24123_readreg(state, 0x32) | 0x02);
+ if (state->config->lnb_polarity)
+ cx24123_writereg(state, 0x32,
+ cx24123_readreg(state, 0x32) | 0x02);
if (state->config->dont_use_pll)
- cx24123_repeater_mode(state, 1, 0);
+ cx24123_repeater_mode(state, 1, 0);
return 0;
}
-static int cx24123_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+static int cx24123_set_voltage(struct dvb_frontend *fe,
+ fe_sec_voltage_t voltage)
{
struct cx24123_state *state = fe->demodulator_priv;
u8 val;
@@ -751,7 +775,7 @@ static void cx24123_wait_for_diseqc(struct cx24123_state *state)
{
unsigned long timeout = jiffies + msecs_to_jiffies(200);
while (!(cx24123_readreg(state, 0x29) & 0x40)) {
- if(time_after(jiffies, timeout)) {
+ if (time_after(jiffies, timeout)) {
err("%s: diseqc queue not ready, " \
"command may be lost.\n", __func__);
break;
@@ -760,7 +784,8 @@ static void cx24123_wait_for_diseqc(struct cx24123_state *state)
}
}
-static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd)
+static int cx24123_send_diseqc_msg(struct dvb_frontend *fe,
+ struct dvb_diseqc_master_cmd *cmd)
{
struct cx24123_state *state = fe->demodulator_priv;
int i, val, tone;
@@ -782,20 +807,21 @@ static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_ma
cx24123_writereg(state, 0x2C + i, cmd->msg[i]);
val = cx24123_readreg(state, 0x29);
- cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40) | ((cmd->msg_len-3) & 3));
+ cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40) |
+ ((cmd->msg_len-3) & 3));
/* wait for diseqc message to finish sending */
cx24123_wait_for_diseqc(state);
/* restart continuous tone if enabled */
- if (tone & 0x10) {
+ if (tone & 0x10)
cx24123_writereg(state, 0x29, tone & ~0x40);
- }
return 0;
}
-static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
+static int cx24123_diseqc_send_burst(struct dvb_frontend *fe,
+ fe_sec_mini_cmd_t burst)
{
struct cx24123_state *state = fe->demodulator_priv;
int val, tone;
@@ -825,13 +851,13 @@ static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t
cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xfb);
/* restart continuous tone if enabled */
- if (tone & 0x10) {
+ if (tone & 0x10)
cx24123_writereg(state, 0x29, tone & ~0x40);
- }
+
return 0;
}
-static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int cx24123_read_status(struct dvb_frontend *fe, fe_status_t *status)
{
struct cx24123_state *state = fe->demodulator_priv;
int sync = cx24123_readreg(state, 0x14);
@@ -864,8 +890,9 @@ static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status)
}
/*
- * Configured to return the measurement of errors in blocks, because no UCBLOCKS value
- * is available, so this value doubles up to satisfy both measurements
+ * Configured to return the measurement of errors in blocks,
+ * because no UCBLOCKS value is available, so this value doubles up
+ * to satisfy both measurements.
*/
static int cx24123_read_ber(struct dvb_frontend *fe, u32 *ber)
{
@@ -887,7 +914,8 @@ static int cx24123_read_signal_strength(struct dvb_frontend *fe,
{
struct cx24123_state *state = fe->demodulator_priv;
- *signal_strength = cx24123_readreg(state, 0x3b) << 8; /* larger = better */
+ /* larger = better */
+ *signal_strength = cx24123_readreg(state, 0x3b) << 8;
dprintk("Signal strength = %d\n", *signal_strength);
@@ -918,7 +946,7 @@ static int cx24123_set_frontend(struct dvb_frontend *fe,
if (state->config->set_ts_params)
state->config->set_ts_params(fe, 0);
- state->currentfreq=p->frequency;
+ state->currentfreq = p->frequency;
state->currentsymbolrate = p->u.qpsk.symbol_rate;
cx24123_set_inversion(state, p->inversion);
@@ -943,7 +971,8 @@ static int cx24123_set_frontend(struct dvb_frontend *fe,
return 0;
}
-static int cx24123_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int cx24123_get_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *p)
{
struct cx24123_state *state = fe->demodulator_priv;
@@ -963,7 +992,7 @@ static int cx24123_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
return 0;
}
-static int cx24123_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+static int cx24123_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
{
struct cx24123_state *state = fe->demodulator_priv;
u8 val;
@@ -988,8 +1017,8 @@ static int cx24123_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
return 0;
}
-static int cx24123_tune(struct dvb_frontend* fe,
- struct dvb_frontend_parameters* params,
+static int cx24123_tune(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *params,
unsigned int mode_flags,
unsigned int *delay,
fe_status_t *status)
@@ -1008,12 +1037,12 @@ static int cx24123_tune(struct dvb_frontend* fe,
static int cx24123_get_algo(struct dvb_frontend *fe)
{
- return 1; //FE_ALGO_HW
+ return 1; /* FE_ALGO_HW */
}
-static void cx24123_release(struct dvb_frontend* fe)
+static void cx24123_release(struct dvb_frontend *fe)
{
- struct cx24123_state* state = fe->demodulator_priv;
+ struct cx24123_state *state = fe->demodulator_priv;
dprintk("\n");
i2c_del_adapter(&state->tuner_i2c_adapter);
kfree(state);
@@ -1024,7 +1053,7 @@ static int cx24123_tuner_i2c_tuner_xfer(struct i2c_adapter *i2c_adap,
{
struct cx24123_state *state = i2c_get_adapdata(i2c_adap);
/* this repeater closes after the first stop */
- cx24123_repeater_mode(state, 1, 1);
+ cx24123_repeater_mode(state, 1, 1);
return i2c_transfer(state->i2c, msg, num);
}
@@ -1048,8 +1077,8 @@ EXPORT_SYMBOL(cx24123_get_tuner_i2c_adapter);
static struct dvb_frontend_ops cx24123_ops;
-struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
- struct i2c_adapter* i2c)
+struct dvb_frontend *cx24123_attach(const struct cx24123_config *config,
+ struct i2c_adapter *i2c)
{
struct cx24123_state *state =
kzalloc(sizeof(struct cx24123_state), GFP_KERNEL);
@@ -1068,20 +1097,25 @@ struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
/* check if the demod is there */
state->demod_rev = cx24123_readreg(state, 0x00);
switch (state->demod_rev) {
- case 0xe1: info("detected CX24123C\n"); break;
- case 0xd1: info("detected CX24123\n"); break;
+ case 0xe1:
+ info("detected CX24123C\n");
+ break;
+ case 0xd1:
+ info("detected CX24123\n");
+ break;
default:
err("wrong demod revision: %x\n", state->demod_rev);
goto error;
}
/* create dvb_frontend */
- memcpy(&state->frontend.ops, &cx24123_ops, sizeof(struct dvb_frontend_ops));
+ memcpy(&state->frontend.ops, &cx24123_ops,
+ sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
- /* create tuner i2c adapter */
- if (config->dont_use_pll)
- cx24123_repeater_mode(state, 1, 0);
+ /* create tuner i2c adapter */
+ if (config->dont_use_pll)
+ cx24123_repeater_mode(state, 1, 0);
strlcpy(state->tuner_i2c_adapter.name, "CX24123 tuner I2C bus",
sizeof(state->tuner_i2c_adapter.name));
@@ -1090,7 +1124,7 @@ struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
state->tuner_i2c_adapter.algo_data = NULL;
i2c_set_adapdata(&state->tuner_i2c_adapter, state);
if (i2c_add_adapter(&state->tuner_i2c_adapter) < 0) {
- err("tuner i2c bus could not be initialized\n");
+ err("tuner i2c bus could not be initialized\n");
goto error;
}
@@ -1101,6 +1135,7 @@ error:
return NULL;
}
+EXPORT_SYMBOL(cx24123_attach);
static struct dvb_frontend_ops cx24123_ops = {
@@ -1137,15 +1172,8 @@ static struct dvb_frontend_ops cx24123_ops = {
.get_frontend_algo = cx24123_get_algo,
};
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
-
-module_param(force_band, int, 0644);
-MODULE_PARM_DESC(force_band, "Force a specific band select (1-9, default:off).");
-
MODULE_DESCRIPTION("DVB Frontend module for Conexant " \
"CX24123/CX24109/CX24113 hardware");
MODULE_AUTHOR("Steven Toth");
MODULE_LICENSE("GPL");
-EXPORT_SYMBOL(cx24123_attach);
diff --git a/linux/drivers/media/dvb/frontends/cx24123.h b/linux/drivers/media/dvb/frontends/cx24123.h
index cc6b411d6..51ae866e9 100644
--- a/linux/drivers/media/dvb/frontends/cx24123.h
+++ b/linux/drivers/media/dvb/frontends/cx24123.h
@@ -23,13 +23,12 @@
#include <linux/dvb/frontend.h>
-struct cx24123_config
-{
+struct cx24123_config {
/* the demodulator's i2c address */
u8 demod_address;
/* Need to set device param for start_dma */
- int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
+ int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured);
/* 0 = LNB voltage normal, 1 = LNB voltage inverted */
int lnb_polarity;
@@ -39,7 +38,8 @@ struct cx24123_config
void (*agc_callback) (struct dvb_frontend *);
};
-#if defined(CONFIG_DVB_CX24123) || (defined(CONFIG_DVB_CX24123_MODULE) && defined(MODULE))
+#if defined(CONFIG_DVB_CX24123) || (defined(CONFIG_DVB_CX24123_MODULE) \
+ && defined(MODULE))
extern struct dvb_frontend *cx24123_attach(const struct cx24123_config *config,
struct i2c_adapter *i2c);
extern struct i2c_adapter *cx24123_get_tuner_i2c_adapter(struct dvb_frontend *);
@@ -56,6 +56,6 @@ static struct i2c_adapter *
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
-#endif // CONFIG_DVB_CX24123
+#endif
#endif /* CX24123_H */
diff --git a/linux/drivers/media/dvb/frontends/dvb-pll.c b/linux/drivers/media/dvb/frontends/dvb-pll.c
index bb3e35373..8ef5d1eff 100644
--- a/linux/drivers/media/dvb/frontends/dvb-pll.c
+++ b/linux/drivers/media/dvb/frontends/dvb-pll.c
@@ -312,7 +312,7 @@ static struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261 = {
.count = 4,
.entries = {
{ 1250000, 500, 0xc4, 0x00},
- { 1550000, 500, 0xc4, 0x40},
+ { 1450000, 500, 0xc4, 0x40},
{ 2050000, 500, 0xc4, 0x80},
{ 2150000, 500, 0xc4, 0xc0},
},
diff --git a/linux/drivers/media/dvb/frontends/lgdt3304.c b/linux/drivers/media/dvb/frontends/lgdt3304.c
new file mode 100644
index 000000000..724811744
--- /dev/null
+++ b/linux/drivers/media/dvb/frontends/lgdt3304.c
@@ -0,0 +1,398 @@
+/*
+ * Driver for LG ATSC lgdt3304 driver
+ *
+ * Copyright (C) 2008 Markus Rechberger <mrechberger@sundtek.de>
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include "dvb_frontend.h"
+#include "lgdt3304.h"
+
+static unsigned int debug = 0;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug,"lgdt3304 debugging (default off)");
+
+#define dprintk(fmt, args...) if (debug) do {\
+ printk("lgdt3304 debug: " fmt, ##args); } while (0)
+
+struct lgdt3304_state
+{
+ struct dvb_frontend frontend;
+ fe_modulation_t current_modulation;
+ __u32 snr;
+ __u32 current_frequency;
+ __u8 addr;
+ struct i2c_adapter *i2c;
+};
+
+static int i2c_write_demod_bytes (struct dvb_frontend *fe, __u8 *buf, int len)
+{
+ struct lgdt3304_state *state = fe->demodulator_priv;
+ struct i2c_msg i2cmsgs = {
+ .addr = state->addr,
+ .flags = 0,
+ .len = 3,
+ .buf = buf
+ };
+ int i;
+ int err;
+
+ for (i=0; i<len-1; i+=3){
+ if((err = i2c_transfer(state->i2c, &i2cmsgs, 1))<0) {
+ printk("%s i2c_transfer error %d\n", __FUNCTION__, err);
+ if (err < 0)
+ return err;
+ else
+ return -EREMOTEIO;
+ }
+ i2cmsgs.buf += 3;
+ }
+ return 0;
+}
+
+static int lgdt3304_i2c_read_reg(struct dvb_frontend *fe, unsigned int reg)
+{
+ struct lgdt3304_state *state = fe->demodulator_priv;
+ struct i2c_msg i2cmsgs[2];
+ int ret;
+ __u8 buf;
+
+ __u8 regbuf[2] = { reg>>8, reg&0xff };
+
+ i2cmsgs[0].addr = state->addr;
+ i2cmsgs[0].flags = 0;
+ i2cmsgs[0].len = 2;
+ i2cmsgs[0].buf = regbuf;
+
+ i2cmsgs[1].addr = state->addr;
+ i2cmsgs[1].flags = I2C_M_RD;
+ i2cmsgs[1].len = 1;
+ i2cmsgs[1].buf = &buf;
+
+ if((ret = i2c_transfer(state->i2c, i2cmsgs, 2))<0) {
+ printk("%s i2c_transfer error %d\n", __FUNCTION__, ret);
+ return ret;
+ }
+
+ return buf;
+}
+
+static int lgdt3304_i2c_write_reg(struct dvb_frontend *fe, int reg, int val)
+{
+ struct lgdt3304_state *state = fe->demodulator_priv;
+ char buffer[3] = { reg>>8, reg&0xff, val };
+ int ret;
+
+ struct i2c_msg i2cmsgs = {
+ .addr = state->addr,
+ .flags = 0,
+ .len = 3,
+ .buf=buffer
+ };
+ ret = i2c_transfer(state->i2c, &i2cmsgs, 1);
+ if (ret != 1) {
+ printk("%s i2c_transfer error %d\n", __FUNCTION__, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+
+static int lgdt3304_soft_Reset(struct dvb_frontend *fe)
+{
+ lgdt3304_i2c_write_reg(fe, 0x0002, 0x9a);
+ lgdt3304_i2c_write_reg(fe, 0x0002, 0x9b);
+ mdelay(200);
+ return 0;
+}
+
+static int lgdt3304_set_parameters(struct dvb_frontend *fe, struct dvb_frontend_parameters *param) {
+ int err = 0;
+
+ static __u8 lgdt3304_vsb8_data[] = {
+ /* 16bit , 8bit */
+ /* regs , val */
+ 0x00, 0x00, 0x02,
+ 0x00, 0x00, 0x13,
+ 0x00, 0x0d, 0x02,
+ 0x00, 0x0e, 0x02,
+ 0x00, 0x12, 0x32,
+ 0x00, 0x13, 0xc4,
+ 0x01, 0x12, 0x17,
+ 0x01, 0x13, 0x15,
+ 0x01, 0x14, 0x18,
+ 0x01, 0x15, 0xff,
+ 0x01, 0x16, 0x2c,
+ 0x02, 0x14, 0x67,
+ 0x02, 0x24, 0x8d,
+ 0x04, 0x27, 0x12,
+ 0x04, 0x28, 0x4f,
+ 0x03, 0x08, 0x80,
+ 0x03, 0x09, 0x00,
+ 0x03, 0x0d, 0x00,
+ 0x03, 0x0e, 0x1c,
+ 0x03, 0x14, 0xe1,
+ 0x05, 0x0e, 0x5b,
+ };
+
+ /* not yet tested .. */
+ static __u8 lgdt3304_qam64_data[] = {
+ /* 16bit , 8bit */
+ /* regs , val */
+ 0x00, 0x00, 0x18,
+ 0x00, 0x0d, 0x02,
+ //0x00, 0x0e, 0x02,
+ 0x00, 0x12, 0x2a,
+ 0x00, 0x13, 0x00,
+ 0x03, 0x14, 0xe3,
+ 0x03, 0x0e, 0x1c,
+ 0x03, 0x08, 0x66,
+ 0x03, 0x09, 0x66,
+ 0x03, 0x0a, 0x08,
+ 0x03, 0x0b, 0x9b,
+ 0x05, 0x0e, 0x5b,
+ };
+
+#if 0
+ /* not yet tested */
+ static __u8 lgdt3304_qam256_data[] = {
+ /* 16bit , 8bit */
+ /* regs , val */
+ 0x00, 0x00, 0x19,
+ 0x00, 0x12, 0x2a,
+ 0x00, 0x13, 0x80,
+ 0x00, 0x0d, 0x02,
+ 0x03, 0x14, 0xe3,
+
+ 0x03, 0x0e, 0x1c,
+ 0x03, 0x08, 0x66,
+ 0x03, 0x09, 0x66,
+ 0x03, 0x0a, 0x08,
+ 0x03, 0x0b, 0x9b,
+ 0x03, 0x0d, 0x14,
+ 0x05, 0x0e, 0x5b,
+ };
+#endif
+
+ /* tested with KWorld a340 */
+ static __u8 lgdt3304_qam256_data[] = {
+ /* 16bit , 8bit */
+ /* regs , val */
+ 0x00, 0x00, 0x01, //0x19,
+ 0x00, 0x12, 0x2a,
+ 0x00, 0x13, 0x80,
+ 0x00, 0x0d, 0x02,
+ 0x03, 0x14, 0xe3,
+
+ 0x03, 0x0e, 0x1c,
+ 0x03, 0x08, 0x66,
+ 0x03, 0x09, 0x66,
+ 0x03, 0x0a, 0x08,
+ 0x03, 0x0b, 0x9b,
+
+ 0x03, 0x0d, 0x14,
+ //0x05, 0x0e, 0x5b,
+ 0x01, 0x06, 0x4a,
+ 0x01, 0x07, 0x3d,
+ 0x01, 0x08, 0x70,
+ 0x01, 0x09, 0xa3,
+
+ 0x05, 0x04, 0xfd,
+
+ 0x00, 0x0d, 0x82,
+
+ 0x05, 0x0e, 0x5b,
+
+ 0x05, 0x0e, 0x5b,
+
+ 0x00, 0x02, 0x9a,
+
+ 0x00, 0x02, 0x9b,
+
+ 0x00, 0x00, 0x01,
+ 0x00, 0x12, 0x2a,
+ 0x00, 0x13, 0x80,
+ 0x00, 0x0d, 0x02,
+ 0x03, 0x14, 0xe3,
+
+ 0x03, 0x0e, 0x1c,
+ 0x03, 0x08, 0x66,
+ 0x03, 0x09, 0x66,
+ 0x03, 0x0a, 0x08,
+ 0x03, 0x0b, 0x9b,
+
+ 0x03, 0x0d, 0x14,
+ 0x01, 0x06, 0x4a,
+ 0x01, 0x07, 0x3d,
+ 0x01, 0x08, 0x70,
+ 0x01, 0x09, 0xa3,
+
+ 0x05, 0x04, 0xfd,
+
+ 0x00, 0x0d, 0x82,
+
+ 0x05, 0x0e, 0x5b,
+ };
+
+ struct lgdt3304_state *state = fe->demodulator_priv;
+ if (state->current_modulation != param->u.vsb.modulation) {
+ switch(param->u.vsb.modulation) {
+ case VSB_8:
+ err = i2c_write_demod_bytes(fe, lgdt3304_vsb8_data,
+ sizeof(lgdt3304_vsb8_data));
+ break;
+ case QAM_64:
+ err = i2c_write_demod_bytes(fe, lgdt3304_qam64_data,
+ sizeof(lgdt3304_qam64_data));
+ break;
+ case QAM_256:
+ err = i2c_write_demod_bytes(fe, lgdt3304_qam256_data,
+ sizeof(lgdt3304_qam256_data));
+ break;
+ default:
+ break;
+ }
+
+ if (err) {
+ printk("%s error setting modulation\n", __FUNCTION__);
+ } else {
+ state->current_modulation = param->u.vsb.modulation;
+ }
+ }
+ state->current_frequency = param->frequency;
+
+ lgdt3304_soft_Reset(fe);
+
+
+ if (fe->ops.tuner_ops.set_params)
+ fe->ops.tuner_ops.set_params(fe, param);
+
+ return 0;
+}
+
+static int lgdt3304_init(struct dvb_frontend *fe) {
+ return 0;
+}
+
+static int lgdt3304_sleep(struct dvb_frontend *fe) {
+ return 0;
+}
+
+
+static int lgdt3304_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+ struct lgdt3304_state *state = fe->demodulator_priv;
+ int r011d;
+ int qam_lck;
+
+ *status = 0;
+ dprintk("lgdt read status\n");
+
+ r011d = lgdt3304_i2c_read_reg(fe, 0x011d);
+
+ dprintk("%02x\n", r011d);
+
+ switch(state->current_modulation) {
+ case VSB_8:
+ if (r011d & 0x80) {
+ dprintk("VSB Locked\n");
+ *status |= FE_HAS_CARRIER;
+ *status |= FE_HAS_LOCK;
+ *status |= FE_HAS_SYNC;
+ *status |= FE_HAS_SIGNAL;
+ }
+ break;
+ case QAM_64:
+ case QAM_256:
+ qam_lck = r011d & 0x7;
+ switch(qam_lck) {
+ case 0x0: dprintk("Unlock\n");
+ break;
+ case 0x4: dprintk("1st Lock in acquisition state\n");
+ break;
+ case 0x6: dprintk("2nd Lock in acquisition state\n");
+ break;
+ case 0x7: dprintk("Final Lock in good reception state\n");
+ *status |= FE_HAS_CARRIER;
+ *status |= FE_HAS_LOCK;
+ *status |= FE_HAS_SYNC;
+ *status |= FE_HAS_SIGNAL;
+ break;
+ }
+ break;
+ default:
+ printk("%s unhandled modulation\n", __FUNCTION__);
+ }
+
+
+ return 0;
+}
+
+static int lgdt3304_read_ber(struct dvb_frontend *fe, __u32 *ber)
+{
+ dprintk("read ber\n");
+ return 0;
+}
+
+static int lgdt3304_read_snr(struct dvb_frontend *fe, __u16 *snr)
+{
+ dprintk("read snr\n");
+ return 0;
+}
+
+static int lgdt3304_read_ucblocks(struct dvb_frontend *fe, __u32 *ucblocks)
+{
+ dprintk("read ucblocks\n");
+ return 0;
+}
+
+static void lgdt3304_release(struct dvb_frontend *fe)
+{
+ struct lgdt3304_state *state = (struct lgdt3304_state *)fe->demodulator_priv;
+ kfree(state);
+}
+
+static struct dvb_frontend_ops demod_lgdt3304={
+ .info = {
+ .name = "LG 3304",
+ .type = FE_ATSC,
+ .frequency_min = 54000000,
+ .frequency_max = 858000000,
+ .frequency_stepsize = 62500,
+ .symbol_rate_min = 5056941,
+ .symbol_rate_max = 10762000,
+ .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
+ },
+ .init = lgdt3304_init,
+ .sleep = lgdt3304_sleep,
+ .set_frontend = lgdt3304_set_parameters,
+ .read_snr = lgdt3304_read_snr,
+ .read_ber = lgdt3304_read_ber,
+ .read_status = lgdt3304_read_status,
+ .read_ucblocks = lgdt3304_read_ucblocks,
+ .release = lgdt3304_release,
+};
+
+struct dvb_frontend* lgdt3304_attach(const struct lgdt3304_config *config,
+ struct i2c_adapter *i2c)
+{
+
+ struct lgdt3304_state *state;
+ state = kzalloc(sizeof(struct lgdt3304_state), GFP_KERNEL);
+ memset(state, 0x0, sizeof(struct lgdt3304_state));
+ state->addr = config->i2c_address;
+ state->i2c = i2c;
+
+ memcpy(&state->frontend.ops, &demod_lgdt3304, sizeof(struct dvb_frontend_ops));
+ state->frontend.demodulator_priv = state;
+ return &state->frontend;
+}
+
+EXPORT_SYMBOL_GPL(lgdt3304_attach);
+MODULE_AUTHOR("Markus Rechberger <mrechberger@empiatech.com>");
+MODULE_DESCRIPTION("LGE LGDT3304 DVB-T demodulator driver");
+MODULE_LICENSE("GPL");
diff --git a/linux/drivers/media/dvb/frontends/lgdt3304.h b/linux/drivers/media/dvb/frontends/lgdt3304.h
new file mode 100644
index 000000000..fc409fe59
--- /dev/null
+++ b/linux/drivers/media/dvb/frontends/lgdt3304.h
@@ -0,0 +1,45 @@
+/*
+ * Driver for DVB-T lgdt3304 demodulator
+ *
+ * Copyright (C) 2008 Markus Rechberger <mrechberger@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
+ */
+
+#ifndef LGDT3304_H
+#define LGDT3304_H
+
+#include <linux/dvb/frontend.h>
+
+struct lgdt3304_config
+{
+ /* demodulator's I2C address */
+ u8 i2c_address;
+};
+
+#if defined(CONFIG_DVB_LGDT3304) || (defined(CONFIG_DVB_LGDT3304_MODULE) && defined(MODULE))
+extern struct dvb_frontend* lgdt3304_attach(const struct lgdt3304_config *config,
+ struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend* lgdt3304_attach(const struct lgdt3304_config *config,
+ struct i2c_adapter *i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+#endif /* CONFIG_DVB_LGDT */
+
+#endif /* LGDT3304_H */
diff --git a/linux/drivers/media/dvb/frontends/s5h1409.c b/linux/drivers/media/dvb/frontends/s5h1409.c
index 7500a1c53..cf4d8936b 100644
--- a/linux/drivers/media/dvb/frontends/s5h1409.c
+++ b/linux/drivers/media/dvb/frontends/s5h1409.c
@@ -30,10 +30,10 @@
struct s5h1409_state {
- struct i2c_adapter* i2c;
+ struct i2c_adapter *i2c;
/* configuration settings */
- const struct s5h1409_config* config;
+ const struct s5h1409_config *config;
struct dvb_frontend frontend;
@@ -48,6 +48,9 @@ struct s5h1409_state {
};
static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Enable verbose debug messages");
+
#define dprintk if (debug) printk
/* Register values to initialise the demod, this will set VSB by default */
@@ -299,10 +302,10 @@ static struct qam256_snr_tab {
};
/* 8 bit registers, 16 bit values */
-static int s5h1409_writereg(struct s5h1409_state* state, u8 reg, u16 data)
+static int s5h1409_writereg(struct s5h1409_state *state, u8 reg, u16 data)
{
int ret;
- u8 buf [] = { reg, data >> 8, data & 0xff };
+ u8 buf[] = { reg, data >> 8, data & 0xff };
struct i2c_msg msg = { .addr = state->config->demod_address,
.flags = 0, .buf = buf, .len = 3 };
@@ -310,19 +313,19 @@ static int s5h1409_writereg(struct s5h1409_state* state, u8 reg, u16 data)
ret = i2c_transfer(state->i2c, &msg, 1);
if (ret != 1)
- printk("%s: writereg error (reg == 0x%02x, val == 0x%04x, "
+ printk(KERN_ERR "%s: error (reg == 0x%02x, val == 0x%04x, "
"ret == %i)\n", __func__, reg, data, ret);
return (ret != 1) ? -1 : 0;
}
-static u16 s5h1409_readreg(struct s5h1409_state* state, u8 reg)
+static u16 s5h1409_readreg(struct s5h1409_state *state, u8 reg)
{
int ret;
- u8 b0 [] = { reg };
- u8 b1 [] = { 0, 0 };
+ u8 b0[] = { reg };
+ u8 b1[] = { 0, 0 };
- struct i2c_msg msg [] = {
+ struct i2c_msg msg[] = {
{ .addr = state->config->demod_address, .flags = 0,
.buf = b0, .len = 1 },
{ .addr = state->config->demod_address, .flags = I2C_M_RD,
@@ -335,9 +338,9 @@ static u16 s5h1409_readreg(struct s5h1409_state* state, u8 reg)
return (b1[0] << 8) | b1[1];
}
-static int s5h1409_softreset(struct dvb_frontend* fe)
+static int s5h1409_softreset(struct dvb_frontend *fe)
{
- struct s5h1409_state* state = fe->demodulator_priv;
+ struct s5h1409_state *state = fe->demodulator_priv;
dprintk("%s()\n", __func__);
@@ -349,11 +352,11 @@ static int s5h1409_softreset(struct dvb_frontend* fe)
}
#define S5H1409_VSB_IF_FREQ 5380
-#define S5H1409_QAM_IF_FREQ state->config->qam_if
+#define S5H1409_QAM_IF_FREQ (state->config->qam_if)
-static int s5h1409_set_if_freq(struct dvb_frontend* fe, int KHz)
+static int s5h1409_set_if_freq(struct dvb_frontend *fe, int KHz)
{
- struct s5h1409_state* state = fe->demodulator_priv;
+ struct s5h1409_state *state = fe->demodulator_priv;
dprintk("%s(%d KHz)\n", __func__, KHz);
@@ -376,26 +379,26 @@ static int s5h1409_set_if_freq(struct dvb_frontend* fe, int KHz)
return 0;
}
-static int s5h1409_set_spectralinversion(struct dvb_frontend* fe, int inverted)
+static int s5h1409_set_spectralinversion(struct dvb_frontend *fe, int inverted)
{
- struct s5h1409_state* state = fe->demodulator_priv;
+ struct s5h1409_state *state = fe->demodulator_priv;
dprintk("%s(%d)\n", __func__, inverted);
- if(inverted == 1)
+ if (inverted == 1)
return s5h1409_writereg(state, 0x1b, 0x1101); /* Inverted */
else
return s5h1409_writereg(state, 0x1b, 0x0110); /* Normal */
}
-static int s5h1409_enable_modulation(struct dvb_frontend* fe,
+static int s5h1409_enable_modulation(struct dvb_frontend *fe,
fe_modulation_t m)
{
- struct s5h1409_state* state = fe->demodulator_priv;
+ struct s5h1409_state *state = fe->demodulator_priv;
dprintk("%s(0x%08x)\n", __func__, m);
- switch(m) {
+ switch (m) {
case VSB_8:
dprintk("%s() VSB_8\n", __func__);
if (state->if_freq != S5H1409_VSB_IF_FREQ)
@@ -422,9 +425,9 @@ static int s5h1409_enable_modulation(struct dvb_frontend* fe,
return 0;
}
-static int s5h1409_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+static int s5h1409_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
{
- struct s5h1409_state* state = fe->demodulator_priv;
+ struct s5h1409_state *state = fe->demodulator_priv;
dprintk("%s(%d)\n", __func__, enable);
@@ -434,9 +437,9 @@ static int s5h1409_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
return s5h1409_writereg(state, 0xf3, 0);
}
-static int s5h1409_set_gpio(struct dvb_frontend* fe, int enable)
+static int s5h1409_set_gpio(struct dvb_frontend *fe, int enable)
{
- struct s5h1409_state* state = fe->demodulator_priv;
+ struct s5h1409_state *state = fe->demodulator_priv;
dprintk("%s(%d)\n", __func__, enable);
@@ -448,18 +451,18 @@ static int s5h1409_set_gpio(struct dvb_frontend* fe, int enable)
s5h1409_readreg(state, 0xe3) & 0xfeff);
}
-static int s5h1409_sleep(struct dvb_frontend* fe, int enable)
+static int s5h1409_sleep(struct dvb_frontend *fe, int enable)
{
- struct s5h1409_state* state = fe->demodulator_priv;
+ struct s5h1409_state *state = fe->demodulator_priv;
dprintk("%s(%d)\n", __func__, enable);
return s5h1409_writereg(state, 0xf2, enable);
}
-static int s5h1409_register_reset(struct dvb_frontend* fe)
+static int s5h1409_register_reset(struct dvb_frontend *fe)
{
- struct s5h1409_state* state = fe->demodulator_priv;
+ struct s5h1409_state *state = fe->demodulator_priv;
dprintk("%s()\n", __func__);
@@ -483,7 +486,7 @@ static void s5h1409_set_qam_amhum_mode(struct dvb_frontend *fe)
reg &= 0xff;
s5h1409_writereg(state, 0x96, 0x00c);
- if ((reg < 0x38) || (reg > 0x68) ) {
+ if ((reg < 0x38) || (reg > 0x68)) {
s5h1409_writereg(state, 0x93, 0x3332);
s5h1409_writereg(state, 0x9e, 0x2c37);
} else {
@@ -514,7 +517,7 @@ static void s5h1409_set_qam_interleave_mode(struct dvb_frontend *fe)
s5h1409_writereg(state, 0x96, 0x20);
s5h1409_writereg(state, 0xad,
- ( ((reg1 & 0xf000) >> 4) | (reg2 & 0xf0ff)) );
+ (((reg1 & 0xf000) >> 4) | (reg2 & 0xf0ff)));
s5h1409_writereg(state, 0xab,
s5h1409_readreg(state, 0xab) & 0xeffe);
}
@@ -529,10 +532,10 @@ static void s5h1409_set_qam_interleave_mode(struct dvb_frontend *fe)
}
/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
-static int s5h1409_set_frontend (struct dvb_frontend* fe,
+static int s5h1409_set_frontend(struct dvb_frontend *fe,
struct dvb_frontend_parameters *p)
{
- struct s5h1409_state* state = fe->demodulator_priv;
+ struct s5h1409_state *state = fe->demodulator_priv;
dprintk("%s(frequency=%d)\n", __func__, p->frequency);
@@ -546,9 +549,11 @@ static int s5h1409_set_frontend (struct dvb_frontend* fe,
msleep(100);
if (fe->ops.tuner_ops.set_params) {
- if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
fe->ops.tuner_ops.set_params(fe, p);
- if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
}
/* Optimize the demod for QAM */
@@ -592,17 +597,17 @@ static int s5h1409_set_mpeg_timing(struct dvb_frontend *fe, int mode)
/* Reset the demod hardware and reset all of the configuration registers
to a default state. */
-static int s5h1409_init (struct dvb_frontend* fe)
+static int s5h1409_init(struct dvb_frontend *fe)
{
int i;
- struct s5h1409_state* state = fe->demodulator_priv;
+ struct s5h1409_state *state = fe->demodulator_priv;
dprintk("%s()\n", __func__);
s5h1409_sleep(fe, 0);
s5h1409_register_reset(fe);
- for (i=0; i < ARRAY_SIZE(init_tab); i++)
+ for (i = 0; i < ARRAY_SIZE(init_tab); i++)
s5h1409_writereg(state, init_tab[i].reg, init_tab[i].data);
/* The datasheet says that after initialisation, VSB is default */
@@ -627,9 +632,9 @@ static int s5h1409_init (struct dvb_frontend* fe)
return 0;
}
-static int s5h1409_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int s5h1409_read_status(struct dvb_frontend *fe, fe_status_t *status)
{
- struct s5h1409_state* state = fe->demodulator_priv;
+ struct s5h1409_state *state = fe->demodulator_priv;
u16 reg;
u32 tuner_status = 0;
@@ -637,12 +642,12 @@ static int s5h1409_read_status(struct dvb_frontend* fe, fe_status_t* status)
/* Get the demodulator status */
reg = s5h1409_readreg(state, 0xf1);
- if(reg & 0x1000)
+ if (reg & 0x1000)
*status |= FE_HAS_VITERBI;
- if(reg & 0x8000)
+ if (reg & 0x8000)
*status |= FE_HAS_LOCK | FE_HAS_SYNC;
- switch(state->config->status_mode) {
+ switch (state->config->status_mode) {
case S5H1409_DEMODLOCKING:
if (*status & FE_HAS_VITERBI)
*status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
@@ -668,12 +673,12 @@ static int s5h1409_read_status(struct dvb_frontend* fe, fe_status_t* status)
return 0;
}
-static int s5h1409_qam256_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
+static int s5h1409_qam256_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
{
int i, ret = -EINVAL;
dprintk("%s()\n", __func__);
- for (i=0; i < ARRAY_SIZE(qam256_snr_tab); i++) {
+ for (i = 0; i < ARRAY_SIZE(qam256_snr_tab); i++) {
if (v < qam256_snr_tab[i].val) {
*snr = qam256_snr_tab[i].data;
ret = 0;
@@ -683,12 +688,12 @@ static int s5h1409_qam256_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
return ret;
}
-static int s5h1409_qam64_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
+static int s5h1409_qam64_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
{
int i, ret = -EINVAL;
dprintk("%s()\n", __func__);
- for (i=0; i < ARRAY_SIZE(qam64_snr_tab); i++) {
+ for (i = 0; i < ARRAY_SIZE(qam64_snr_tab); i++) {
if (v < qam64_snr_tab[i].val) {
*snr = qam64_snr_tab[i].data;
ret = 0;
@@ -698,12 +703,12 @@ static int s5h1409_qam64_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
return ret;
}
-static int s5h1409_vsb_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
+static int s5h1409_vsb_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
{
int i, ret = -EINVAL;
dprintk("%s()\n", __func__);
- for (i=0; i < ARRAY_SIZE(vsb_snr_tab); i++) {
+ for (i = 0; i < ARRAY_SIZE(vsb_snr_tab); i++) {
if (v > vsb_snr_tab[i].val) {
*snr = vsb_snr_tab[i].data;
ret = 0;
@@ -714,13 +719,13 @@ static int s5h1409_vsb_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
return ret;
}
-static int s5h1409_read_snr(struct dvb_frontend* fe, u16* snr)
+static int s5h1409_read_snr(struct dvb_frontend *fe, u16 *snr)
{
- struct s5h1409_state* state = fe->demodulator_priv;
+ struct s5h1409_state *state = fe->demodulator_priv;
u16 reg;
dprintk("%s()\n", __func__);
- switch(state->current_modulation) {
+ switch (state->current_modulation) {
case QAM_64:
reg = s5h1409_readreg(state, 0xf0) & 0xff;
return s5h1409_qam64_lookup_snr(fe, snr, reg);
@@ -737,30 +742,30 @@ static int s5h1409_read_snr(struct dvb_frontend* fe, u16* snr)
return -EINVAL;
}
-static int s5h1409_read_signal_strength(struct dvb_frontend* fe,
- u16* signal_strength)
+static int s5h1409_read_signal_strength(struct dvb_frontend *fe,
+ u16 *signal_strength)
{
return s5h1409_read_snr(fe, signal_strength);
}
-static int s5h1409_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+static int s5h1409_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
{
- struct s5h1409_state* state = fe->demodulator_priv;
+ struct s5h1409_state *state = fe->demodulator_priv;
*ucblocks = s5h1409_readreg(state, 0xb5);
return 0;
}
-static int s5h1409_read_ber(struct dvb_frontend* fe, u32* ber)
+static int s5h1409_read_ber(struct dvb_frontend *fe, u32 *ber)
{
return s5h1409_read_ucblocks(fe, ber);
}
-static int s5h1409_get_frontend(struct dvb_frontend* fe,
+static int s5h1409_get_frontend(struct dvb_frontend *fe,
struct dvb_frontend_parameters *p)
{
- struct s5h1409_state* state = fe->demodulator_priv;
+ struct s5h1409_state *state = fe->demodulator_priv;
p->frequency = state->current_frequency;
p->u.vsb.modulation = state->current_modulation;
@@ -768,25 +773,25 @@ static int s5h1409_get_frontend(struct dvb_frontend* fe,
return 0;
}
-static int s5h1409_get_tune_settings(struct dvb_frontend* fe,
+static int s5h1409_get_tune_settings(struct dvb_frontend *fe,
struct dvb_frontend_tune_settings *tune)
{
tune->min_delay_ms = 1000;
return 0;
}
-static void s5h1409_release(struct dvb_frontend* fe)
+static void s5h1409_release(struct dvb_frontend *fe)
{
- struct s5h1409_state* state = fe->demodulator_priv;
+ struct s5h1409_state *state = fe->demodulator_priv;
kfree(state);
}
static struct dvb_frontend_ops s5h1409_ops;
-struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
- struct i2c_adapter* i2c)
+struct dvb_frontend *s5h1409_attach(const struct s5h1409_config *config,
+ struct i2c_adapter *i2c)
{
- struct s5h1409_state* state = NULL;
+ struct s5h1409_state *state = NULL;
u16 reg;
/* allocate memory for the internal state */
@@ -825,6 +830,7 @@ error:
kfree(state);
return NULL;
}
+EXPORT_SYMBOL(s5h1409_attach);
static struct dvb_frontend_ops s5h1409_ops = {
@@ -850,14 +856,10 @@ static struct dvb_frontend_ops s5h1409_ops = {
.release = s5h1409_release,
};
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Enable verbose debug messages");
-
MODULE_DESCRIPTION("Samsung S5H1409 QAM-B/ATSC Demodulator driver");
MODULE_AUTHOR("Steven Toth");
MODULE_LICENSE("GPL");
-EXPORT_SYMBOL(s5h1409_attach);
/*
* Local variables:
diff --git a/linux/drivers/media/dvb/frontends/s5h1409.h b/linux/drivers/media/dvb/frontends/s5h1409.h
index d1a1d2eb8..070d9743e 100644
--- a/linux/drivers/media/dvb/frontends/s5h1409.h
+++ b/linux/drivers/media/dvb/frontends/s5h1409.h
@@ -24,8 +24,7 @@
#include <linux/dvb/frontend.h>
-struct s5h1409_config
-{
+struct s5h1409_config {
/* the demodulator's i2c address */
u8 demod_address;
@@ -60,12 +59,14 @@ struct s5h1409_config
u16 mpeg_timing;
};
-#if defined(CONFIG_DVB_S5H1409) || (defined(CONFIG_DVB_S5H1409_MODULE) && defined(MODULE))
-extern struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
- struct i2c_adapter* i2c);
+#if defined(CONFIG_DVB_S5H1409) || (defined(CONFIG_DVB_S5H1409_MODULE) \
+ && defined(MODULE))
+extern struct dvb_frontend *s5h1409_attach(const struct s5h1409_config *config,
+ struct i2c_adapter *i2c);
#else
-static inline struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
- struct i2c_adapter* i2c)
+static inline struct dvb_frontend *s5h1409_attach(
+ const struct s5h1409_config *config,
+ struct i2c_adapter *i2c)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
diff --git a/linux/drivers/media/dvb/frontends/s5h1411.c b/linux/drivers/media/dvb/frontends/s5h1411.c
index 2da1a3763..66e2dd6d6 100644
--- a/linux/drivers/media/dvb/frontends/s5h1411.c
+++ b/linux/drivers/media/dvb/frontends/s5h1411.c
@@ -38,6 +38,7 @@ struct s5h1411_state {
struct dvb_frontend frontend;
fe_modulation_t current_modulation;
+ unsigned int first_tune:1;
u32 current_frequency;
int if_freq;
@@ -62,7 +63,7 @@ static struct init_tab {
{ S5H1411_I2C_TOP_ADDR, 0x08, 0x0047, },
{ S5H1411_I2C_TOP_ADDR, 0x1c, 0x0400, },
{ S5H1411_I2C_TOP_ADDR, 0x1e, 0x0370, },
- { S5H1411_I2C_TOP_ADDR, 0x1f, 0x342a, },
+ { S5H1411_I2C_TOP_ADDR, 0x1f, 0x342c, },
{ S5H1411_I2C_TOP_ADDR, 0x24, 0x0231, },
{ S5H1411_I2C_TOP_ADDR, 0x25, 0x1011, },
{ S5H1411_I2C_TOP_ADDR, 0x26, 0x0f07, },
@@ -100,7 +101,6 @@ static struct init_tab {
{ S5H1411_I2C_TOP_ADDR, 0x78, 0x3141, },
{ S5H1411_I2C_TOP_ADDR, 0x7a, 0x3141, },
{ S5H1411_I2C_TOP_ADDR, 0xb3, 0x8003, },
- { S5H1411_I2C_TOP_ADDR, 0xb5, 0xafbb, },
{ S5H1411_I2C_TOP_ADDR, 0xb5, 0xa6bb, },
{ S5H1411_I2C_TOP_ADDR, 0xb6, 0x0609, },
{ S5H1411_I2C_TOP_ADDR, 0xb7, 0x2f06, },
@@ -343,7 +343,7 @@ static int s5h1411_writereg(struct s5h1411_state *state,
u8 addr, u8 reg, u16 data)
{
int ret;
- u8 buf [] = { reg, data >> 8, data & 0xff };
+ u8 buf[] = { reg, data >> 8, data & 0xff };
struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 };
@@ -359,10 +359,10 @@ static int s5h1411_writereg(struct s5h1411_state *state,
static u16 s5h1411_readreg(struct s5h1411_state *state, u8 addr, u8 reg)
{
int ret;
- u8 b0 [] = { reg };
- u8 b1 [] = { 0, 0 };
+ u8 b0[] = { reg };
+ u8 b1[] = { 0, 0 };
- struct i2c_msg msg [] = {
+ struct i2c_msg msg[] = {
{ .addr = addr, .flags = 0, .buf = b0, .len = 1 },
{ .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 2 } };
@@ -393,7 +393,7 @@ static int s5h1411_set_if_freq(struct dvb_frontend *fe, int KHz)
switch (KHz) {
case 3250:
- s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x10d9);
+ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x10d5);
s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x39, 0x5342);
s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x2c, 0x10d9);
break;
@@ -464,13 +464,25 @@ static int s5h1411_set_spectralinversion(struct dvb_frontend *fe, int inversion)
if (inversion == 1)
val |= 0x1000; /* Inverted */
- else
- val |= 0x0000;
state->inversion = inversion;
return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x24, val);
}
+static int s5h1411_set_serialmode(struct dvb_frontend *fe, int serial)
+{
+ struct s5h1411_state *state = fe->demodulator_priv;
+ u16 val;
+
+ dprintk("%s(%d)\n", __func__, serial);
+ val = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xbd) & ~0x100;
+
+ if (serial == 1)
+ val |= 0x100;
+
+ return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbd, val);
+}
+
static int s5h1411_enable_modulation(struct dvb_frontend *fe,
fe_modulation_t m)
{
@@ -478,6 +490,12 @@ static int s5h1411_enable_modulation(struct dvb_frontend *fe,
dprintk("%s(0x%08x)\n", __func__, m);
+ if ((state->first_tune == 0) && (m == state->current_modulation)) {
+ dprintk("%s() Already at desired modulation. Skipping...\n",
+ __func__);
+ return 0;
+ }
+
switch (m) {
case VSB_8:
dprintk("%s() VSB_8\n", __func__);
@@ -502,6 +520,7 @@ static int s5h1411_enable_modulation(struct dvb_frontend *fe,
}
state->current_modulation = m;
+ state->first_tune = 0;
s5h1411_softreset(fe);
return 0;
@@ -535,7 +554,7 @@ static int s5h1411_set_gpio(struct dvb_frontend *fe, int enable)
return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xe0, val);
}
-static int s5h1411_sleep(struct dvb_frontend *fe, int enable)
+static int s5h1411_set_powerstate(struct dvb_frontend *fe, int enable)
{
struct s5h1411_state *state = fe->demodulator_priv;
@@ -551,6 +570,11 @@ static int s5h1411_sleep(struct dvb_frontend *fe, int enable)
return 0;
}
+static int s5h1411_sleep(struct dvb_frontend *fe)
+{
+ return s5h1411_set_powerstate(fe, 1);
+}
+
static int s5h1411_register_reset(struct dvb_frontend *fe)
{
struct s5h1411_state *state = fe->demodulator_priv;
@@ -574,9 +598,6 @@ static int s5h1411_set_frontend(struct dvb_frontend *fe,
s5h1411_enable_modulation(fe, p->u.vsb.modulation);
- /* Allow the demod to settle */
- msleep(100);
-
if (fe->ops.tuner_ops.set_params) {
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
@@ -587,6 +608,10 @@ static int s5h1411_set_frontend(struct dvb_frontend *fe,
fe->ops.i2c_gate_ctrl(fe, 0);
}
+ /* Issue a reset to the demod so it knows to resync against the
+ newly tuned frequency */
+ s5h1411_softreset(fe);
+
return 0;
}
@@ -599,7 +624,7 @@ static int s5h1411_init(struct dvb_frontend *fe)
dprintk("%s()\n", __func__);
- s5h1411_sleep(fe, 0);
+ s5h1411_set_powerstate(fe, 0);
s5h1411_register_reset(fe);
for (i = 0; i < ARRAY_SIZE(init_tab); i++)
@@ -610,12 +635,17 @@ static int s5h1411_init(struct dvb_frontend *fe)
/* The datasheet says that after initialisation, VSB is default */
state->current_modulation = VSB_8;
+ /* Although the datasheet says it's in VSB, empirical evidence
+ shows problems getting lock on the first tuning request. Make
+ sure we call enable_modulation the first time around */
+ state->first_tune = 1;
+
if (state->config->output_mode == S5H1411_SERIAL_OUTPUT)
/* Serial */
- s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbd, 0x1101);
+ s5h1411_set_serialmode(fe, 1);
else
/* Parallel */
- s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbd, 0x1001);
+ s5h1411_set_serialmode(fe, 0);
s5h1411_set_spectralinversion(fe, state->config->inversion);
s5h1411_set_if_freq(fe, state->config->vsb_if);
@@ -637,28 +667,29 @@ static int s5h1411_read_status(struct dvb_frontend *fe, fe_status_t *status)
*status = 0;
- /* Get the demodulator status */
- reg = (s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf2) >> 15)
- & 0x0001;
- if (reg)
- *status |= FE_HAS_LOCK | FE_HAS_CARRIER | FE_HAS_SIGNAL;
+ /* Register F2 bit 15 = Master Lock, removed */
switch (state->current_modulation) {
case QAM_64:
case QAM_256:
reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf0);
- if (reg & 0x100)
- *status |= FE_HAS_VITERBI;
- if (reg & 0x10)
- *status |= FE_HAS_SYNC;
+ if (reg & 0x10) /* QAM FEC Lock */
+ *status |= FE_HAS_SYNC | FE_HAS_LOCK;
+ if (reg & 0x100) /* QAM EQ Lock */
+ *status |= FE_HAS_VITERBI | FE_HAS_CARRIER | FE_HAS_SIGNAL;
+
break;
case VSB_8:
- reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0x5e);
- if (reg & 0x0001)
- *status |= FE_HAS_SYNC;
reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf2);
- if (reg & 0x1000)
- *status |= FE_HAS_VITERBI;
+ if (reg & 0x1000) /* FEC Lock */
+ *status |= FE_HAS_SYNC | FE_HAS_LOCK;
+ if (reg & 0x2000) /* EQ Lock */
+ *status |= FE_HAS_VITERBI | FE_HAS_CARRIER | FE_HAS_SIGNAL;
+
+ reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0x53);
+ if (reg & 0x1) /* AFC Lock */
+ *status |= FE_HAS_SIGNAL;
+
break;
default:
return -EINVAL;
@@ -843,6 +874,9 @@ struct dvb_frontend *s5h1411_attach(const struct s5h1411_config *config,
/* Note: Leaving the I2C gate open here. */
s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf5, 1);
+ /* Put the device into low-power mode until first use */
+ s5h1411_set_powerstate(&state->frontend, 1);
+
return &state->frontend;
error:
@@ -863,6 +897,7 @@ static struct dvb_frontend_ops s5h1411_ops = {
},
.init = s5h1411_init,
+ .sleep = s5h1411_sleep,
.i2c_gate_ctrl = s5h1411_i2c_gate_ctrl,
.set_frontend = s5h1411_set_frontend,
.get_frontend = s5h1411_get_frontend,
diff --git a/linux/drivers/media/dvb/frontends/s5h1411.h b/linux/drivers/media/dvb/frontends/s5h1411.h
index 7d542bc00..45ec0f829 100644
--- a/linux/drivers/media/dvb/frontends/s5h1411.h
+++ b/linux/drivers/media/dvb/frontends/s5h1411.h
@@ -47,7 +47,7 @@ struct s5h1411_config {
u16 mpeg_timing;
/* IF Freq for QAM and VSB in KHz */
-#define S5H1411_IF_2500 2500
+#define S5H1411_IF_3250 3250
#define S5H1411_IF_3500 3500
#define S5H1411_IF_4000 4000
#define S5H1411_IF_5380 5380
diff --git a/linux/drivers/media/dvb/frontends/s921_core.c b/linux/drivers/media/dvb/frontends/s921_core.c
new file mode 100644
index 000000000..5b9e6040e
--- /dev/null
+++ b/linux/drivers/media/dvb/frontends/s921_core.c
@@ -0,0 +1,587 @@
+/*
+ * Driver for Sharp s921 driver
+ *
+ * Copyright (C) 2008 Markus Rechberger <mrechberger@sundtek.de>
+ *
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include "s921_core.h"
+
+static int s921_isdb_init(struct s921_isdb_t *dev);
+static int s921_isdb_set_parameters(struct s921_isdb_t *dev, struct s921_isdb_t_transmission_mode_params *params);
+static int s921_isdb_tune(struct s921_isdb_t *dev, struct s921_isdb_t_tune_params *params);
+static int s921_isdb_get_status(struct s921_isdb_t *dev, void *data);
+
+static u8 init_table[]={ 0x01, 0x40, 0x02, 0x00, 0x03, 0x40, 0x04, 0x01,
+ 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08, 0x00,
+ 0x09, 0x00, 0x0a, 0x00, 0x0b, 0x5a, 0x0c, 0x00,
+ 0x0d, 0x00, 0x0f, 0x00, 0x13, 0x1b, 0x14, 0x80,
+ 0x15, 0x40, 0x17, 0x70, 0x18, 0x01, 0x19, 0x12,
+ 0x1a, 0x01, 0x1b, 0x12, 0x1c, 0xa0, 0x1d, 0x00,
+ 0x1e, 0x0a, 0x1f, 0x08, 0x20, 0x40, 0x21, 0xff,
+ 0x22, 0x4c, 0x23, 0x4e, 0x24, 0x4c, 0x25, 0x00,
+ 0x26, 0x00, 0x27, 0xf4, 0x28, 0x60, 0x29, 0x88,
+ 0x2a, 0x40, 0x2b, 0x40, 0x2c, 0xff, 0x2d, 0x00,
+ 0x2e, 0xff, 0x2f, 0x00, 0x30, 0x20, 0x31, 0x06,
+ 0x32, 0x0c, 0x34, 0x0f, 0x37, 0xfe, 0x38, 0x00,
+ 0x39, 0x63, 0x3a, 0x10, 0x3b, 0x10, 0x47, 0x00,
+ 0x49, 0xe5, 0x4b, 0x00, 0x50, 0xc0, 0x52, 0x20,
+ 0x54, 0x5a, 0x55, 0x5b, 0x56, 0x40, 0x57, 0x70,
+ 0x5c, 0x50, 0x5d, 0x00, 0x62, 0x17, 0x63, 0x2f,
+ 0x64, 0x6f, 0x68, 0x00, 0x69, 0x89, 0x6a, 0x00,
+ 0x6b, 0x00, 0x6c, 0x00, 0x6d, 0x00, 0x6e, 0x00,
+ 0x70, 0x00, 0x71, 0x00, 0x75, 0x00, 0x76, 0x30,
+ 0x77, 0x01, 0xaf, 0x00, 0xb0, 0xa0, 0xb2, 0x3d,
+ 0xb3, 0x25, 0xb4, 0x8b, 0xb5, 0x4b, 0xb6, 0x3f,
+ 0xb7, 0xff, 0xb8, 0xff, 0xb9, 0xfc, 0xba, 0x00,
+ 0xbb, 0x00, 0xbc, 0x00, 0xd0, 0x30, 0xe4, 0x84,
+ 0xf0, 0x48, 0xf1, 0x19, 0xf2, 0x5a, 0xf3, 0x8e,
+ 0xf4, 0x2d, 0xf5, 0x07, 0xf6, 0x5a, 0xf7, 0xba,
+ 0xf8, 0xd7 };
+
+static u8 c_table[]={ 0x58, 0x8a, 0x7b, 0x59, 0x8c, 0x7b, 0x5a, 0x8e, 0x5b,
+ 0x5b, 0x90, 0x5b, 0x5c, 0x92, 0x5b, 0x5d, 0x94, 0x5b,
+ 0x5e, 0x96, 0x5b, 0x5f, 0x98, 0x3b, 0x60, 0x9a, 0x3b,
+ 0x61, 0x9c, 0x3b, 0x62, 0x9e, 0x3b, 0x63, 0xa0, 0x3b,
+ 0x64, 0xa2, 0x1b, 0x65, 0xa4, 0x1b, 0x66, 0xa6, 0x1b,
+ 0x67, 0xa8, 0x1b, 0x68, 0xaa, 0x1b, 0x69, 0xac, 0x1b,
+ 0x6a, 0xae, 0x1b, 0x6b, 0xb0, 0x1b, 0x6c, 0xb2, 0x1b,
+ 0x6d, 0xb4, 0xfb, 0x6e, 0xb6, 0xfb, 0x6f, 0xb8, 0xfb,
+ 0x70, 0xba, 0xfb, 0x71, 0xbc, 0xdb, 0x72, 0xbe, 0xdb,
+ 0x73, 0xc0, 0xdb, 0x74, 0xc2, 0xdb, 0x75, 0xc4, 0xdb,
+ 0x76, 0xc6, 0xdb, 0x77, 0xc8, 0xbb, 0x78, 0xca, 0xbb,
+ 0x79, 0xcc, 0xbb, 0x7a, 0xce, 0xbb, 0x7b, 0xd0, 0xbb,
+ 0x7c, 0xd2, 0xbb, 0x7d, 0xd4, 0xbb, 0x7e, 0xd6, 0xbb,
+ 0x7f, 0xd8, 0xbb, 0x80, 0xda, 0x9b, 0x81, 0xdc, 0x9b,
+ 0x82, 0xde, 0x9b, 0x83, 0xe0, 0x9b, 0x84, 0xe2, 0x9b,
+ 0x85, 0xe4, 0x9b, 0x86, 0xe6, 0x9b, 0x87, 0xe8, 0x9b,
+ 0x88, 0xea, 0x9b, 0x89, 0xec, 0x9b };
+
+int s921_isdb_cmd(struct s921_isdb_t *dev, u32 cmd, void *data) {
+ switch(cmd) {
+ case ISDB_T_CMD_INIT:
+ s921_isdb_init(dev);
+ break;
+ case ISDB_T_CMD_SET_PARAM:
+ s921_isdb_set_parameters(dev, data);
+ break;
+ case ISDB_T_CMD_TUNE:
+ s921_isdb_tune(dev, data);
+ break;
+ case ISDB_T_CMD_GET_STATUS:
+ s921_isdb_get_status(dev, data);
+ break;
+ default:
+ printk("unhandled command\n");
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int s921_isdb_init(struct s921_isdb_t *dev) {
+ unsigned int i;
+ unsigned int ret;
+ printk("isdb_init\n");
+ for (i = 0; i < sizeof(init_table); i+=2) {
+ ret = dev->i2c_write(dev->priv_dev, init_table[i], init_table[i+1]);
+ if (ret != 0) {
+ printk("i2c write failed\n");
+ return ret;
+ }
+ }
+ return 0;
+}
+
+static int s921_isdb_set_parameters(struct s921_isdb_t *dev, struct s921_isdb_t_transmission_mode_params *params) {
+
+ int ret;
+ /* auto is sufficient for now, lateron this should be reflected in an extra interface */
+
+#if 0
+ u8 mod_b2 = 0;
+ u8 mod_b3 = 0;
+ u8 mod_b4 = 0;
+ u8 mod_b5 = 0;
+ u8 mod_b6 = 0;
+ u8 mod_b7 = 0;
+ u8 mod_b8 = 0;
+ /* LAYER A Setup */
+
+ switch (params->layer_a_carrier_modulation) {
+ case ISDB_T_LA_CM_DQPSK:
+ mod_b3 |= 0<<5;
+ break;
+ case ISDB_T_LA_CM_QPSK:
+ mod_b3 |= 1<<5;
+ break;
+ case ISDB_T_LA_CM_16QAM:
+ mod_b3 |= 2<<5;
+ break;
+ case ISDB_T_LA_CM_64QAM:
+ mod_b3 |= 3<<5;
+ break;
+ case ISDB_T_LA_CM_NOLAYER:
+ mod_b3 |= 7<<5;
+ break;
+ default:
+ printk("invalid carrier modulation\n");
+ return -EINVAL;
+ }
+
+ switch(params->layer_a_code_rate) {
+ case ISDB_T_LA_CR_1_2:
+ mod_b3 |= 0<<2;
+ break;
+ case ISDB_T_LA_CR_2_3:
+ mod_b3 |= 1<<2;
+ break;
+ case ISDB_T_LA_CR_3_4:
+ mod_b3 |= 2<<2;
+ break;
+ case ISDB_T_LA_CR_5_6:
+ mod_b3 |= 3<<2;
+ break;
+ case ISDB_T_LA_CR_7_8:
+ mod_b3 |= 4<<2;
+ break;
+ default:
+ printk("invalid coderate\n");
+ return -EINVAL;
+ }
+
+ switch (params->layer_a_mode) {
+ case ISDB_T_LA_MODE_1:
+ switch(params->layer_a_time_interleave) {
+ case ISDB_T_LA_TI_0:
+ mod_b3 |= 0;
+ mod_b4 |= 0;
+ break;
+ case ISDB_T_LA_TI_4:
+ mod_b3 |= 1;
+ mod_b4 |= 0;
+ break;
+ case ISDB_T_LA_TI_8:
+ mod_b3 |= 2;
+ mod_b4 |= 0;
+ break;
+ case ISDB_T_LA_TI_16:
+ mod_b3 |= 3;
+ mod_b4 |= 0;
+ break;
+ case ISDB_T_LA_TI_32:
+ mod_b3 |= 0;
+ mod_b4 |= 1<<7;
+ break;
+ default:
+ printk("invalid layer a time interleave\n");
+ return -EINVAL;
+ }
+ break;
+ case ISDB_T_LA_MODE_2:
+ switch(params->layer_a_time_interleave) {
+ case ISDB_T_LA_TI_0:
+ mod_b3 |= 0;
+ mod_b4 |= 0;
+ break;
+ case ISDB_T_LA_TI_2:
+ mod_b3 |= 1;
+ mod_b4 |= 0;
+ break;
+ case ISDB_T_LA_TI_4:
+ mod_b3 |= 2;
+ mod_b4 |= 0;
+ break;
+ case ISDB_T_LA_TI_8:
+ mod_b3 |= 3;
+ mod_b4 |= 0;
+ break;
+ case ISDB_T_LA_TI_16:
+ mod_b3 |= 0;
+ mod_b4 |= 1<<7;
+ break;
+ default:
+
+ printk("invalid layer a time interleave\n");
+ return -EINVAL;
+ }
+ break;
+ case ISDB_T_LA_MODE_3:
+ switch(params->layer_a_time_interleave) {
+ case ISDB_T_LA_TI_0:
+ mod_b3 |= 0;
+ mod_b4 |= 0;
+ break;
+ case ISDB_T_LA_TI_1:
+ mod_b3 |= 1;
+ mod_b4 |= 0;
+ break;
+ case ISDB_T_LA_TI_2:
+ mod_b3 |= 2;
+ mod_b4 |= 0;
+ break;
+ case ISDB_T_LA_TI_4:
+ mod_b3 |= 3;
+ mod_b4 |= 0;
+ break;
+ case ISDB_T_LA_TI_8:
+ mod_b3 |= 0;
+ mod_b4 |= 1<<7;
+ break;
+ default:
+ printk("invalid layer a time interleave\n");
+ return -EINVAL;
+ }
+ break;
+ default:
+ printk("invalid layer mode\n");
+ return -EINVAL;
+ }
+
+
+ /* LAYER B Setup */
+ switch (params->layer_b_carrier_modulation) {
+ case ISDB_T_LB_CM_DQPSK:
+ mod_b4 |= 0;
+ break;
+ case ISDB_T_LB_CM_QPSK:
+ mod_b4 |= 1;
+ break;
+ case ISDB_T_LB_CM_16QAM:
+ mod_b4 |= 2;
+ break;
+ case ISDB_T_LB_CM_64QAM:
+ mod_b4 |= 3;
+ break;
+ case ISDB_T_LB_CM_NOLAYER:
+ mod_b4 |= 7;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch(params->layer_b_code_rate) {
+ case ISDB_T_LB_CR_1_2:
+ mod_b5 |= 0<<5;
+ break;
+ case ISDB_T_LB_CR_2_3:
+ mod_b5 |= 1<<5;
+ break;
+ case ISDB_T_LB_CR_3_4:
+ mod_b5 |= 2<<5;
+ break;
+ case ISDB_T_LB_CR_5_6:
+ mod_b5 |= 3<<5;
+ break;
+ case ISDB_T_LB_CR_7_8:
+ mod_b5 |= 4<<5;
+ break;
+ case ISDB_T_LB_CR_NOLAYER:
+ mod_b5 |= 7<<5;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (params->layer_b_mode) {
+ case ISDB_T_LB_MODE_1:
+ switch(params->layer_b_time_interleave) {
+ case ISDB_T_LB_TI_0:
+ mod_b5 |= 0;
+ break;
+ case ISDB_T_LB_TI_4:
+ mod_b5 |= 1<<2;
+ break;
+ case ISDB_T_LB_TI_8:
+ mod_b5 |= 2<<2;
+ break;
+ case ISDB_T_LB_TI_16:
+ mod_b5 |= 3<<2;
+ break;
+ case ISDB_T_LB_TI_32:
+ mod_b5 |= 4<<2;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ case ISDB_T_LB_MODE_2:
+ switch(params->layer_b_time_interleave) {
+ case ISDB_T_LB_TI_0:
+ mod_b5 |= 0;
+ break;
+ case ISDB_T_LB_TI_2:
+ mod_b5 |= 1<<2;
+ break;
+ case ISDB_T_LB_TI_4:
+ mod_b5 |= 2<<2;
+ break;
+ case ISDB_T_LB_TI_8:
+ mod_b5 |= 3<<2;
+ break;
+ case ISDB_T_LB_TI_16:
+ mod_b5 |= 4<<2;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ case ISDB_T_LB_MODE_3:
+ switch(params->layer_b_time_interleave) {
+ case ISDB_T_LB_TI_0:
+ mod_b5 |= 0;
+ break;
+ case ISDB_T_LB_TI_1:
+ mod_b5 |= 1<<2;
+ break;
+ case ISDB_T_LB_TI_2:
+ mod_b5 |= 2<<2;
+ break;
+ case ISDB_T_LB_TI_4:
+ mod_b5 |= 3<<2;
+ break;
+ case ISDB_T_LB_TI_8:
+ mod_b5 |= 4<<2;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* LAYER C Setup */
+ switch (params->layer_c_carrier_modulation) {
+ case ISDB_T_LC_CM_DQPSK:
+ mod_b5 |= 0<<3;
+ break;
+ case ISDB_T_LC_CM_QPSK:
+ mod_b5 |= 1<<3;
+ break;
+ case ISDB_T_LC_CM_16QAM:
+ mod_b5 |= 2<<3;
+ break;
+ case ISDB_T_LC_CM_64QAM:
+ mod_b5 |= 3<<3;
+ break;
+ case ISDB_T_LC_CM_NOLAYER:
+ mod_b5 |= 7<<3;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch(params->layer_c_code_rate) {
+ case ISDB_T_LC_CR_1_2:
+ mod_b5 |= 0<<0;
+ break;
+ case ISDB_T_LC_CR_2_3:
+ mod_b5 |= 1<<0;
+ break;
+ case ISDB_T_LC_CR_3_4:
+ mod_b5 |= 2<<0;
+ break;
+ case ISDB_T_LC_CR_5_6:
+ mod_b5 |= 3<<0;
+ break;
+ case ISDB_T_LC_CR_7_8:
+ mod_b5 |= 4<<0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (params->layer_c_mode) {
+ case ISDB_T_LC_MODE_1:
+ switch(params->layer_c_time_interleave) {
+ case ISDB_T_LC_TI_0:
+ mod_b7 |= 0<<5;
+ break;
+ case ISDB_T_LC_TI_4:
+ mod_b7 |= 1<<5;
+ break;
+ case ISDB_T_LC_TI_8:
+ mod_b7 |= 2<<5;
+ break;
+ case ISDB_T_LC_TI_16:
+ mod_b7 |= 3<<5;
+ break;
+ case ISDB_T_LC_TI_32:
+ mod_b7 |= 4<<5;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ case ISDB_T_LC_MODE_2:
+ switch(params->layer_c_time_interleave) {
+ case ISDB_T_LC_TI_0:
+ mod_b7 |= 0<<5;
+ break;
+ case ISDB_T_LC_TI_2:
+ mod_b7 |= 1<<5;
+ break;
+ case ISDB_T_LC_TI_4:
+ mod_b7 |= 2<<5;
+ break;
+ case ISDB_T_LC_TI_8:
+ mod_b7 |= 3<<5;
+ break;
+ case ISDB_T_LC_TI_16:
+ mod_b7 |= 4<<5;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ case ISDB_T_LC_MODE_3:
+ switch(params->layer_c_time_interleave) {
+ case ISDB_T_LC_TI_0:
+ mod_b7 |= 0<<5;
+ break;
+ case ISDB_T_LC_TI_1:
+ mod_b7 |= 1<<5;
+ break;
+ case ISDB_T_LC_TI_2:
+ mod_b7 |= 2<<5;
+ break;
+ case ISDB_T_LC_TI_4:
+ mod_b7 |= 3<<5;
+ break;
+ case ISDB_T_LC_TI_8:
+ mod_b7 |= 4<<5;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+#endif
+
+
+ ret = dev->i2c_write(dev->priv_dev, 0xb0, 0xa0); //mod_b2);
+ ret = dev->i2c_write(dev->priv_dev, 0xb2, 0x3d); //mod_b2);
+
+ if (ret < 0)
+ return -EINVAL;
+
+ ret = dev->i2c_write(dev->priv_dev, 0xb3, 0x25); //mod_b3);
+ if (ret < 0)
+ return -EINVAL;
+
+ ret = dev->i2c_write(dev->priv_dev, 0xb4, 0x8b); //mod_b4);
+ if (ret < 0)
+ return -EINVAL;
+
+ ret = dev->i2c_write(dev->priv_dev, 0xb5, 0x4b); //mod_b5);
+ if (ret < 0)
+ return -EINVAL;
+
+ ret = dev->i2c_write(dev->priv_dev, 0xb6, 0x3f); //mod_b6);
+ if (ret < 0)
+ return -EINVAL;
+
+ ret = dev->i2c_write(dev->priv_dev, 0xb7, 0x3f); //mod_b7);
+ if (ret < 0)
+ return -EINVAL;
+
+ return E_OK;
+}
+
+static int s921_isdb_tune(struct s921_isdb_t *dev, struct s921_isdb_t_tune_params *params) {
+
+ int ret;
+ int index;
+
+ index = (params->frequency - 473143000)/6000000;
+
+ if (index > 48) {
+ return -EINVAL;
+ }
+
+ dev->i2c_write(dev->priv_dev, 0x47, 0x60);
+
+ ret = dev->i2c_write(dev->priv_dev, 0x68, 0x00);
+ if (ret < 0)
+ return -EINVAL;
+
+ ret = dev->i2c_write(dev->priv_dev, 0x69, 0x89);
+ if (ret < 0)
+ return -EINVAL;
+
+ ret = dev->i2c_write(dev->priv_dev, 0xf0, 0x48);
+ if (ret < 0)
+ return -EINVAL;
+
+ ret = dev->i2c_write(dev->priv_dev, 0xf1, 0x19);
+ if (ret < 0)
+ return -EINVAL;
+
+ ret = dev->i2c_write(dev->priv_dev, 0xf2, c_table[index*3]);
+ if (ret < 0)
+ return -EINVAL;
+
+ ret = dev->i2c_write(dev->priv_dev, 0xf3, c_table[index*3+1]);
+ if (ret < 0)
+ return -EINVAL;
+
+ ret = dev->i2c_write(dev->priv_dev, 0xf4, c_table[index*3+2]);
+ if (ret < 0)
+ return -EINVAL;
+
+ ret = dev->i2c_write(dev->priv_dev, 0xf5, 0xae);
+ if (ret < 0)
+ return -EINVAL;
+
+ ret = dev->i2c_write(dev->priv_dev, 0xf6, 0xb7);
+ if (ret < 0)
+ return -EINVAL;
+
+ ret = dev->i2c_write(dev->priv_dev, 0xf7, 0xba);
+ if (ret < 0)
+ return -EINVAL;
+
+ ret = dev->i2c_write(dev->priv_dev, 0xf8, 0xd7);
+ if (ret < 0)
+ return -EINVAL;
+
+ ret = dev->i2c_write(dev->priv_dev, 0x68, 0x0a);
+ if (ret < 0)
+ return -EINVAL;
+
+ ret = dev->i2c_write(dev->priv_dev, 0x69, 0x09);
+ if (ret < 0)
+ return -EINVAL;
+
+ dev->i2c_write(dev->priv_dev, 0x01, 0x40);
+ return 0;
+}
+
+static int s921_isdb_get_status(struct s921_isdb_t *dev, void *data) {
+ unsigned int *ret = (unsigned int*)data;
+ u8 ifagc_dt;
+ u8 rfagc_dt;
+
+ mdelay(10);
+ ifagc_dt = dev->i2c_read(dev->priv_dev, 0x81);
+ rfagc_dt = dev->i2c_read(dev->priv_dev, 0x82);
+#if 0
+ *ret = dev->i2c_read(dev->priv_dev, 0x82);
+ printk("status 83: %02x\n", *ret);
+ *ret = dev->i2c_read(dev->priv_dev, 0x80);
+ mdelay(10);
+ *ret = dev->i2c_read(dev->priv_dev, 0x80);
+ mdelay(10);
+ *ret = dev->i2c_read(dev->priv_dev, 0x80);
+#endif
+ if (rfagc_dt == 0x40) {
+ *ret = 1;
+ }
+ return 0;
+}
diff --git a/linux/drivers/media/dvb/frontends/s921_core.h b/linux/drivers/media/dvb/frontends/s921_core.h
new file mode 100644
index 000000000..de2f10a44
--- /dev/null
+++ b/linux/drivers/media/dvb/frontends/s921_core.h
@@ -0,0 +1,114 @@
+#ifndef _S921_CORE_H
+#define _S921_CORE_H
+//#define u8 unsigned int
+//#define u32 unsigned int
+
+
+
+//#define EINVAL -1
+#define E_OK 0
+
+struct s921_isdb_t {
+ void *priv_dev;
+ int (*i2c_write)(void *dev, u8 reg, u8 val);
+ int (*i2c_read)(void *dev, u8 reg);
+};
+
+#define ISDB_T_CMD_INIT 0
+#define ISDB_T_CMD_SET_PARAM 1
+#define ISDB_T_CMD_TUNE 2
+#define ISDB_T_CMD_GET_STATUS 3
+
+struct s921_isdb_t_tune_params {
+ u32 frequency;
+};
+
+struct s921_isdb_t_status {
+};
+
+struct s921_isdb_t_transmission_mode_params {
+ u8 mode;
+ u8 layer_a_mode;
+#define ISDB_T_LA_MODE_1 0
+#define ISDB_T_LA_MODE_2 1
+#define ISDB_T_LA_MODE_3 2
+ u8 layer_a_carrier_modulation;
+#define ISDB_T_LA_CM_DQPSK 0
+#define ISDB_T_LA_CM_QPSK 1
+#define ISDB_T_LA_CM_16QAM 2
+#define ISDB_T_LA_CM_64QAM 3
+#define ISDB_T_LA_CM_NOLAYER 4
+ u8 layer_a_code_rate;
+#define ISDB_T_LA_CR_1_2 0
+#define ISDB_T_LA_CR_2_3 1
+#define ISDB_T_LA_CR_3_4 2
+#define ISDB_T_LA_CR_5_6 4
+#define ISDB_T_LA_CR_7_8 8
+#define ISDB_T_LA_CR_NOLAYER 16
+ u8 layer_a_time_interleave;
+#define ISDB_T_LA_TI_0 0
+#define ISDB_T_LA_TI_1 1
+#define ISDB_T_LA_TI_2 2
+#define ISDB_T_LA_TI_4 4
+#define ISDB_T_LA_TI_8 8
+#define ISDB_T_LA_TI_16 16
+#define ISDB_T_LA_TI_32 32
+ u8 layer_a_nseg;
+
+ u8 layer_b_mode;
+#define ISDB_T_LB_MODE_1 0
+#define ISDB_T_LB_MODE_2 1
+#define ISDB_T_LB_MODE_3 2
+ u8 layer_b_carrier_modulation;
+#define ISDB_T_LB_CM_DQPSK 0
+#define ISDB_T_LB_CM_QPSK 1
+#define ISDB_T_LB_CM_16QAM 2
+#define ISDB_T_LB_CM_64QAM 3
+#define ISDB_T_LB_CM_NOLAYER 4
+ u8 layer_b_code_rate;
+#define ISDB_T_LB_CR_1_2 0
+#define ISDB_T_LB_CR_2_3 1
+#define ISDB_T_LB_CR_3_4 2
+#define ISDB_T_LB_CR_5_6 4
+#define ISDB_T_LB_CR_7_8 8
+#define ISDB_T_LB_CR_NOLAYER 16
+ u8 layer_b_time_interleave;
+#define ISDB_T_LB_TI_0 0
+#define ISDB_T_LB_TI_1 1
+#define ISDB_T_LB_TI_2 2
+#define ISDB_T_LB_TI_4 4
+#define ISDB_T_LB_TI_8 8
+#define ISDB_T_LB_TI_16 16
+#define ISDB_T_LB_TI_32 32
+ u8 layer_b_nseg;
+
+ u8 layer_c_mode;
+#define ISDB_T_LC_MODE_1 0
+#define ISDB_T_LC_MODE_2 1
+#define ISDB_T_LC_MODE_3 2
+ u8 layer_c_carrier_modulation;
+#define ISDB_T_LC_CM_DQPSK 0
+#define ISDB_T_LC_CM_QPSK 1
+#define ISDB_T_LC_CM_16QAM 2
+#define ISDB_T_LC_CM_64QAM 3
+#define ISDB_T_LC_CM_NOLAYER 4
+ u8 layer_c_code_rate;
+#define ISDB_T_LC_CR_1_2 0
+#define ISDB_T_LC_CR_2_3 1
+#define ISDB_T_LC_CR_3_4 2
+#define ISDB_T_LC_CR_5_6 4
+#define ISDB_T_LC_CR_7_8 8
+#define ISDB_T_LC_CR_NOLAYER 16
+ u8 layer_c_time_interleave;
+#define ISDB_T_LC_TI_0 0
+#define ISDB_T_LC_TI_1 1
+#define ISDB_T_LC_TI_2 2
+#define ISDB_T_LC_TI_4 4
+#define ISDB_T_LC_TI_8 8
+#define ISDB_T_LC_TI_16 16
+#define ISDB_T_LC_TI_32 32
+ u8 layer_c_nseg;
+};
+
+int s921_isdb_cmd(struct s921_isdb_t *dev, u32 cmd, void *data);
+#endif
diff --git a/linux/drivers/media/dvb/frontends/s921_module.c b/linux/drivers/media/dvb/frontends/s921_module.c
new file mode 100644
index 000000000..6018ec505
--- /dev/null
+++ b/linux/drivers/media/dvb/frontends/s921_module.c
@@ -0,0 +1,254 @@
+/*
+ * Driver for Sharp s921 driver
+ *
+ * Copyright (C) 2008 Markus Rechberger <mrechberger@sundtek.de>
+ *
+ * All rights reserved.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include "dvb_frontend.h"
+#include "s921_module.h"
+#include "s921_core.h"
+
+static unsigned int debug = 0;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug,"s921 debugging (default off)");
+
+#define dprintk(fmt, args...) if (debug) do {\
+ printk("s921 debug: " fmt, ##args); } while (0)
+
+struct s921_state
+{
+ struct dvb_frontend frontend;
+ fe_modulation_t current_modulation;
+ __u32 snr;
+ __u32 current_frequency;
+ __u8 addr;
+ struct s921_isdb_t dev;
+ struct i2c_adapter *i2c;
+};
+
+static int s921_set_parameters(struct dvb_frontend *fe, struct dvb_frontend_parameters *param) {
+ struct s921_state *state = (struct s921_state *)fe->demodulator_priv;
+ struct s921_isdb_t_transmission_mode_params params;
+ struct s921_isdb_t_tune_params tune_params;
+
+ tune_params.frequency = param->frequency;
+#if 0
+ struct dvb_ofdm_parameters *op = &param->u.ofdm;
+
+ switch (op->bandwidth) {
+ case BANDWIDTH_6_MHZ:
+ case BANDWIDTH_7_MHZ:
+ case BANDWIDTH_8_MHZ:
+ default:
+ break;
+ }
+
+ switch (op->code_rate_HP) {
+ case FEC_2_3:
+ case FEC_3_4:
+ case FEC_5_6:
+ case FEC_7_8:
+ case FEC_1_2:
+ case FEC_AUTO:
+ break;
+ default:
+ break;
+ }
+
+ switch(op->code_rate_LP) {
+ case FEC_2_3:
+ case FEC_3_4:
+ case FEC_5_6:
+ case FEC_7_8:
+ case FEC_1_2:
+ case FEC_AUTO:
+ case FEC_NONE:
+ default:
+ break;
+ }
+
+ switch (op->constellation) {
+ case QPSK:
+ case QAM_AUTO:
+ case QAM_16:
+ default:
+ break;
+ }
+
+ switch (op->guard_interval) {
+ case GUARD_INTERVAL_1_32:
+ case GUARD_INTERVAL_AUTO:
+ case GUARD_INTERVAL_1_16:
+ case GUARD_INTERVAL_1_8:
+ case GUARD_INTERVAL_1_4:
+ default:
+ break;
+ }
+
+ switch (op->hierarchy_information) {
+ case HIERARCHY_AUTO:
+ case HIERARCHY_NONE:
+ case HIERARCHY_1:
+ case HIERARCHY_2:
+ case HIERARCHY_4:
+ default:
+ break;
+ }
+
+#endif
+ s921_isdb_cmd(&state->dev, ISDB_T_CMD_SET_PARAM, &params);
+ s921_isdb_cmd(&state->dev, ISDB_T_CMD_TUNE, &tune_params);
+ mdelay(100);
+ return 0;
+}
+
+static int s921_init(struct dvb_frontend *fe) {
+ printk("s921 init\n");
+ return 0;
+}
+
+static int s921_sleep(struct dvb_frontend *fe) {
+ printk("s921 sleep\n");
+ return 0;
+}
+
+static int s921_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+ struct s921_state *state = (struct s921_state *)fe->demodulator_priv;
+ unsigned int ret;
+ mdelay(5);
+ s921_isdb_cmd(&state->dev, ISDB_T_CMD_GET_STATUS, &ret);
+ *status = 0;
+
+ printk("status: %02x\n", ret);
+ if (ret == 1) {
+ *status |= FE_HAS_CARRIER;
+ *status |= FE_HAS_VITERBI;
+ *status |= FE_HAS_LOCK;
+ *status |= FE_HAS_SYNC;
+ *status |= FE_HAS_SIGNAL;
+ }
+
+ return 0;
+}
+
+static int s921_read_ber(struct dvb_frontend *fe, __u32 *ber)
+{
+ dprintk("read ber\n");
+ return 0;
+}
+
+static int s921_read_snr(struct dvb_frontend *fe, __u16 *snr)
+{
+ dprintk("read snr\n");
+ return 0;
+}
+
+static int s921_read_ucblocks(struct dvb_frontend *fe, __u32 *ucblocks)
+{
+ dprintk("read ucblocks\n");
+ return 0;
+}
+
+static void s921_release(struct dvb_frontend *fe)
+{
+ struct s921_state *state = (struct s921_state *)fe->demodulator_priv;
+ kfree(state);
+}
+
+static struct dvb_frontend_ops demod_s921={
+ .info = {
+ .name = "SHARP S921",
+ .type = FE_OFDM,
+ .frequency_min = 473143000,
+ .frequency_max = 767143000,
+ .frequency_stepsize = 6000000,
+ .frequency_tolerance = 0,
+ .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
+ FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
+ FE_CAN_FEC_AUTO |
+ FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+ FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
+ FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER |
+ FE_CAN_MUTE_TS
+ },
+ .init = s921_init,
+ .sleep = s921_sleep,
+ .set_frontend = s921_set_parameters,
+ .read_snr = s921_read_snr,
+ .read_ber = s921_read_ber,
+ .read_status = s921_read_status,
+ .read_ucblocks = s921_read_ucblocks,
+ .release = s921_release,
+};
+
+static int s921_write(void *dev, u8 reg, u8 val) {
+ struct s921_state *state = dev;
+ char buf[2]={reg,val};
+ int err;
+ struct i2c_msg i2cmsgs = {
+ .addr = state->addr,
+ .flags = 0,
+ .len = 2,
+ .buf = buf
+ };
+
+ if((err = i2c_transfer(state->i2c, &i2cmsgs, 1))<0) {
+ printk("%s i2c_transfer error %d\n", __FUNCTION__, err);
+ if (err < 0)
+ return err;
+ else
+ return -EREMOTEIO;
+ }
+
+ return 0;
+}
+
+static int s921_read(void *dev, u8 reg) {
+ struct s921_state *state = dev;
+ u8 b1;
+ int ret;
+ struct i2c_msg msg[2] = { { .addr = state->addr,
+ .flags = 0,
+ .buf = &reg, .len = 1 },
+ { .addr = state->addr,
+ .flags = I2C_M_RD,
+ .buf = &b1, .len = 1 } };
+
+ ret = i2c_transfer(state->i2c, msg, 2);
+ if (ret != 2)
+ return ret;
+ return b1;
+}
+
+struct dvb_frontend* s921_attach(const struct s921_config *config,
+ struct i2c_adapter *i2c)
+{
+
+ struct s921_state *state;
+ state = kzalloc(sizeof(struct s921_state), GFP_KERNEL);
+ memset(state, 0x0, sizeof(struct s921_state));
+
+ state->addr = config->i2c_address;
+ state->i2c = i2c;
+ state->dev.i2c_write = &s921_write;
+ state->dev.i2c_read = &s921_read;
+ state->dev.priv_dev = state;
+
+ s921_isdb_cmd(&state->dev, ISDB_T_CMD_INIT, NULL);
+
+ memcpy(&state->frontend.ops, &demod_s921, sizeof(struct dvb_frontend_ops));
+ state->frontend.demodulator_priv = state;
+ return &state->frontend;
+}
+
+EXPORT_SYMBOL_GPL(s921_attach);
+MODULE_AUTHOR("Markus Rechberger <mrechberger@empiatech.com>");
+MODULE_DESCRIPTION("Sharp S921 ISDB-T 1Seg");
+MODULE_LICENSE("GPL");
diff --git a/linux/drivers/media/dvb/frontends/s921_module.h b/linux/drivers/media/dvb/frontends/s921_module.h
new file mode 100644
index 000000000..78660424b
--- /dev/null
+++ b/linux/drivers/media/dvb/frontends/s921_module.h
@@ -0,0 +1,49 @@
+/*
+ * Driver for DVB-T s921 demodulator
+ *
+ * Copyright (C) 2008 Markus Rechberger <mrechberger@sundtek.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.=
+ */
+
+#ifndef S921_MODULE_H
+#define S921_MODULE_H
+
+#include <linux/dvb/frontend.h>
+#include "s921_core.h"
+
+int s921_isdb_init(struct s921_isdb_t *dev);
+int s921_isdb_cmd(struct s921_isdb_t *dev, u32 cmd, void *data);
+
+struct s921_config
+{
+ /* demodulator's I2C address */
+ u8 i2c_address;
+};
+
+#if defined(CONFIG_DVB_S921) || (defined(CONFIG_DVB_S921_MODULE) && defined(MODULE))
+extern struct dvb_frontend* s921_attach(const struct s921_config *config,
+ struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend* s921_attach(const struct s921_config *config,
+ struct i2c_adapter *i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+#endif /* CONFIG_DVB_S921 */
+
+#endif /* S921_H */
diff --git a/linux/drivers/media/dvb/frontends/si21xx.c b/linux/drivers/media/dvb/frontends/si21xx.c
index 2f69a173d..216a532ab 100644
--- a/linux/drivers/media/dvb/frontends/si21xx.c
+++ b/linux/drivers/media/dvb/frontends/si21xx.c
@@ -8,7 +8,6 @@
* (at your option) any later version.
*
*/
-#include <linux/version.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
diff --git a/linux/drivers/media/dvb/frontends/stb0899_algo.c b/linux/drivers/media/dvb/frontends/stb0899_algo.c
new file mode 100644
index 000000000..156906f5d
--- /dev/null
+++ b/linux/drivers/media/dvb/frontends/stb0899_algo.c
@@ -0,0 +1,1532 @@
+/*
+ STB0899 Multistandard Frontend driver
+ Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+ Copyright (C) ST Microelectronics
+
+ 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 "stb0899_drv.h"
+#include "stb0899_priv.h"
+#include "stb0899_reg.h"
+
+inline u32 stb0899_do_div(u64 n, u32 d)
+{
+ /* wrap do_div() for ease of use */
+
+ do_div(n, d);
+ return n;
+}
+
+/*
+ * stb0899_calc_srate
+ * Compute symbol rate
+ */
+static u32 stb0899_calc_srate(u32 master_clk, u8 *sfr)
+{
+ u64 tmp;
+
+ /* srate = (SFR * master_clk) >> 20 */
+
+ /* sfr is of size 20 bit, stored with an offset of 4 bit */
+ tmp = (((u32)sfr[0]) << 16) | (((u32)sfr[1]) << 8) | sfr[2];
+ tmp &= ~0xf;
+ tmp *= master_clk;
+ tmp >>= 24;
+
+ return tmp;
+}
+
+/*
+ * stb0899_get_srate
+ * Get the current symbol rate
+ */
+u32 stb0899_get_srate(struct stb0899_state *state)
+{
+ struct stb0899_internal *internal = &state->internal;
+ u8 sfr[3];
+
+ stb0899_read_regs(state, STB0899_SFRH, sfr, 3);
+
+ return stb0899_calc_srate(internal->master_clk, sfr);
+}
+
+/*
+ * stb0899_set_srate
+ * Set symbol frequency
+ * MasterClock: master clock frequency (hz)
+ * SymbolRate: symbol rate (bauds)
+ * return symbol frequency
+ */
+static u32 stb0899_set_srate(struct stb0899_state *state, u32 master_clk, u32 srate)
+{
+ u32 tmp;
+ u8 sfr[3];
+
+ dprintk(state->verbose, FE_DEBUG, 1, "-->");
+ /*
+ * in order to have the maximum precision, the symbol rate entered into
+ * the chip is computed as the closest value of the "true value".
+ * In this purpose, the symbol rate value is rounded (1 is added on the bit
+ * below the LSB )
+ *
+ * srate = (SFR * master_clk) >> 20
+ * <=>
+ * SFR = srate << 20 / master_clk
+ *
+ * rounded:
+ * SFR = (srate << 21 + master_clk) / (2 * master_clk)
+ *
+ * stored as 20 bit number with an offset of 4 bit:
+ * sfr = SFR << 4;
+ */
+
+ tmp = stb0899_do_div((((u64)srate) << 21) + master_clk, 2 * master_clk);
+ tmp <<= 4;
+
+ sfr[0] = tmp >> 16;
+ sfr[1] = tmp >> 8;
+ sfr[2] = tmp;
+
+ stb0899_write_regs(state, STB0899_SFRH, sfr, 3);
+
+ return srate;
+}
+
+/*
+ * stb0899_calc_derot_time
+ * Compute the amount of time needed by the derotator to lock
+ * SymbolRate: Symbol rate
+ * return: derotator time constant (ms)
+ */
+static long stb0899_calc_derot_time(long srate)
+{
+ if (srate > 0)
+ return (100000 / (srate / 1000));
+ else
+ return 0;
+}
+
+/*
+ * stb0899_carr_width
+ * Compute the width of the carrier
+ * return: width of carrier (kHz or Mhz)
+ */
+long stb0899_carr_width(struct stb0899_state *state)
+{
+ struct stb0899_internal *internal = &state->internal;
+
+ return (internal->srate + (internal->srate * internal->rolloff) / 100);
+}
+
+/*
+ * stb0899_first_subrange
+ * Compute the first subrange of the search
+ */
+static void stb0899_first_subrange(struct stb0899_state *state)
+{
+ struct stb0899_internal *internal = &state->internal;
+ struct stb0899_params *params = &state->params;
+ struct stb0899_config *config = state->config;
+
+ int range = 0;
+ u32 bandwidth = 0;
+
+ if (config->tuner_get_bandwidth) {
+ stb0899_i2c_gate_ctrl(&state->frontend, 1);
+ config->tuner_get_bandwidth(&state->frontend, &bandwidth);
+ stb0899_i2c_gate_ctrl(&state->frontend, 0);
+ range = bandwidth - stb0899_carr_width(state) / 2;
+ }
+
+ if (range > 0)
+ internal->sub_range = MIN(internal->srch_range, range);
+ else
+ internal->sub_range = 0;
+
+ internal->freq = params->freq;
+ internal->tuner_offst = 0L;
+ internal->sub_dir = 1;
+}
+
+/*
+ * stb0899_check_tmg
+ * check for timing lock
+ * internal.Ttiming: time to wait for loop lock
+ */
+static enum stb0899_status stb0899_check_tmg(struct stb0899_state *state)
+{
+ struct stb0899_internal *internal = &state->internal;
+ int lock;
+ u8 reg;
+ s8 timing;
+
+ msleep(internal->t_derot);
+
+ stb0899_write_reg(state, STB0899_RTF, 0xf2);
+ reg = stb0899_read_reg(state, STB0899_TLIR);
+ lock = STB0899_GETFIELD(TLIR_TMG_LOCK_IND, reg);
+ timing = stb0899_read_reg(state, STB0899_RTF);
+
+ if (lock >= 42) {
+ if ((lock > 48) && (ABS(timing) >= 110)) {
+ internal->status = ANALOGCARRIER;
+ dprintk(state->verbose, FE_DEBUG, 1, "-->ANALOG Carrier !");
+ } else {
+ internal->status = TIMINGOK;
+ dprintk(state->verbose, FE_DEBUG, 1, "------->TIMING OK !");
+ }
+ } else {
+ internal->status = NOTIMING;
+ dprintk(state->verbose, FE_DEBUG, 1, "-->NO TIMING !");
+ }
+ return internal->status;
+}
+
+/*
+ * stb0899_search_tmg
+ * perform a fs/2 zig-zag to find timing
+ */
+static enum stb0899_status stb0899_search_tmg(struct stb0899_state *state)
+{
+ struct stb0899_internal *internal = &state->internal;
+ struct stb0899_params *params = &state->params;
+
+ short int derot_step, derot_freq = 0, derot_limit, next_loop = 3;
+ int index = 0;
+ u8 cfr[2];
+
+ internal->status = NOTIMING;
+
+ /* timing loop computation & symbol rate optimisation */
+ derot_limit = (internal->sub_range / 2L) / internal->mclk;
+ derot_step = (params->srate / 2L) / internal->mclk;
+
+ while ((stb0899_check_tmg(state) != TIMINGOK) && next_loop) {
+ index++;
+ derot_freq += index * internal->direction * derot_step; /* next derot zig zag position */
+
+ if (ABS(derot_freq) > derot_limit)
+ next_loop--;
+
+ if (next_loop) {
+ STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(state->config->inversion * derot_freq));
+ STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->inversion * derot_freq));
+ stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency */
+ }
+ internal->direction = -internal->direction; /* Change zigzag direction */
+ }
+
+ if (internal->status == TIMINGOK) {
+ stb0899_read_regs(state, STB0899_CFRM, cfr, 2); /* get derotator frequency */
+ internal->derot_freq = state->config->inversion * MAKEWORD16(cfr[0], cfr[1]);
+ dprintk(state->verbose, FE_DEBUG, 1, "------->TIMING OK ! Derot Freq = %d", internal->derot_freq);
+ }
+
+ return internal->status;
+}
+
+/*
+ * stb0899_check_carrier
+ * Check for carrier found
+ */
+static enum stb0899_status stb0899_check_carrier(struct stb0899_state *state)
+{
+ struct stb0899_internal *internal = &state->internal;
+ u8 reg;
+
+ msleep(internal->t_derot); /* wait for derotator ok */
+
+ reg = stb0899_read_reg(state, STB0899_CFD);
+ STB0899_SETFIELD_VAL(CFD_ON, reg, 1);
+ stb0899_write_reg(state, STB0899_CFD, reg);
+
+ reg = stb0899_read_reg(state, STB0899_DSTATUS);
+ dprintk(state->verbose, FE_DEBUG, 1, "--------------------> STB0899_DSTATUS=[0x%02x]", reg);
+ if (STB0899_GETFIELD(CARRIER_FOUND, reg)) {
+ internal->status = CARRIEROK;
+ dprintk(state->verbose, FE_DEBUG, 1, "-------------> CARRIEROK !");
+ } else {
+ internal->status = NOCARRIER;
+ dprintk(state->verbose, FE_DEBUG, 1, "-------------> NOCARRIER !");
+ }
+
+ return internal->status;
+}
+
+/*
+ * stb0899_search_carrier
+ * Search for a QPSK carrier with the derotator
+ */
+static enum stb0899_status stb0899_search_carrier(struct stb0899_state *state)
+{
+ struct stb0899_internal *internal = &state->internal;
+
+ short int derot_freq = 0, last_derot_freq = 0, derot_limit, next_loop = 3;
+ int index = 0;
+ u8 cfr[2];
+ u8 reg;
+
+ internal->status = NOCARRIER;
+ derot_limit = (internal->sub_range / 2L) / internal->mclk;
+ derot_freq = internal->derot_freq;
+
+ reg = stb0899_read_reg(state, STB0899_CFD);
+ STB0899_SETFIELD_VAL(CFD_ON, reg, 1);
+ stb0899_write_reg(state, STB0899_CFD, reg);
+
+ do {
+ dprintk(state->verbose, FE_DEBUG, 1, "Derot Freq=%d, mclk=%d", derot_freq, internal->mclk);
+ if (stb0899_check_carrier(state) == NOCARRIER) {
+ index++;
+ last_derot_freq = derot_freq;
+ derot_freq += index * internal->direction * internal->derot_step; /* next zig zag derotator position */
+
+ if(ABS(derot_freq) > derot_limit)
+ next_loop--;
+
+ if (next_loop) {
+ reg = stb0899_read_reg(state, STB0899_CFD);
+ STB0899_SETFIELD_VAL(CFD_ON, reg, 1);
+ stb0899_write_reg(state, STB0899_CFD, reg);
+
+ STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(state->config->inversion * derot_freq));
+ STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->inversion * derot_freq));
+ stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency */
+ }
+ }
+
+ internal->direction = -internal->direction; /* Change zigzag direction */
+ } while ((internal->status != CARRIEROK) && next_loop);
+
+ if (internal->status == CARRIEROK) {
+ stb0899_read_regs(state, STB0899_CFRM, cfr, 2); /* get derotator frequency */
+ internal->derot_freq = state->config->inversion * MAKEWORD16(cfr[0], cfr[1]);
+ dprintk(state->verbose, FE_DEBUG, 1, "----> CARRIER OK !, Derot Freq=%d", internal->derot_freq);
+ } else {
+ internal->derot_freq = last_derot_freq;
+ }
+
+ return internal->status;
+}
+
+/*
+ * stb0899_check_data
+ * Check for data found
+ */
+static enum stb0899_status stb0899_check_data(struct stb0899_state *state)
+{
+ struct stb0899_internal *internal = &state->internal;
+ struct stb0899_params *params = &state->params;
+
+ int lock = 0, index = 0, dataTime = 500, loop;
+ u8 reg;
+
+ internal->status = NODATA;
+
+ /* RESET FEC */
+ reg = stb0899_read_reg(state, STB0899_TSTRES);
+ STB0899_SETFIELD_VAL(FRESACS, reg, 1);
+ stb0899_write_reg(state, STB0899_TSTRES, reg);
+ msleep(1);
+ reg = stb0899_read_reg(state, STB0899_TSTRES);
+ STB0899_SETFIELD_VAL(FRESACS, reg, 0);
+ stb0899_write_reg(state, STB0899_TSTRES, reg);
+
+ if (params->srate <= 2000000)
+ dataTime = 2000;
+ else if (params->srate <= 5000000)
+ dataTime = 1500;
+ else if (params->srate <= 15000000)
+ dataTime = 1000;
+ else
+ dataTime = 500;
+
+ stb0899_write_reg(state, STB0899_DSTATUS2, 0x00); /* force search loop */
+ while (1) {
+ /* WARNING! VIT LOCKED has to be tested before VIT_END_LOOOP */
+ reg = stb0899_read_reg(state, STB0899_VSTATUS);
+ lock = STB0899_GETFIELD(VSTATUS_LOCKEDVIT, reg);
+ loop = STB0899_GETFIELD(VSTATUS_END_LOOPVIT, reg);
+
+ if (lock || loop || (index > dataTime))
+ break;
+ index++;
+ }
+
+ if (lock) { /* DATA LOCK indicator */
+ internal->status = DATAOK;
+ dprintk(state->verbose, FE_DEBUG, 1, "-----------------> DATA OK !");
+ }
+
+ return internal->status;
+}
+
+/*
+ * stb0899_search_data
+ * Search for a QPSK carrier with the derotator
+ */
+static enum stb0899_status stb0899_search_data(struct stb0899_state *state)
+{
+ short int derot_freq, derot_step, derot_limit, next_loop = 3;
+ u8 cfr[2];
+ u8 reg;
+ int index = 1;
+
+ struct stb0899_internal *internal = &state->internal;
+ struct stb0899_params *params = &state->params;
+
+ derot_step = (params->srate / 4L) / internal->mclk;
+ derot_limit = (internal->sub_range / 2L) / internal->mclk;
+ derot_freq = internal->derot_freq;
+
+ do {
+ if ((internal->status != CARRIEROK) || (stb0899_check_data(state) != DATAOK)) {
+
+ derot_freq += index * internal->direction * derot_step; /* next zig zag derotator position */
+ if (ABS(derot_freq) > derot_limit)
+ next_loop--;
+
+ if (next_loop) {
+ dprintk(state->verbose, FE_DEBUG, 1, "Derot freq=%d, mclk=%d", derot_freq, internal->mclk);
+ reg = stb0899_read_reg(state, STB0899_CFD);
+ STB0899_SETFIELD_VAL(CFD_ON, reg, 1);
+ stb0899_write_reg(state, STB0899_CFD, reg);
+
+ STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(state->config->inversion * derot_freq));
+ STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->inversion * derot_freq));
+ stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency */
+
+ stb0899_check_carrier(state);
+ index++;
+ }
+ }
+ internal->direction = -internal->direction; /* change zig zag direction */
+ } while ((internal->status != DATAOK) && next_loop);
+
+ if (internal->status == DATAOK) {
+ stb0899_read_regs(state, STB0899_CFRM, cfr, 2); /* get derotator frequency */
+ internal->derot_freq = state->config->inversion * MAKEWORD16(cfr[0], cfr[1]);
+ dprintk(state->verbose, FE_DEBUG, 1, "------> DATAOK ! Derot Freq=%d", internal->derot_freq);
+ }
+
+ return internal->status;
+}
+
+/*
+ * stb0899_check_range
+ * check if the found frequency is in the correct range
+ */
+static enum stb0899_status stb0899_check_range(struct stb0899_state *state)
+{
+ struct stb0899_internal *internal = &state->internal;
+ struct stb0899_params *params = &state->params;
+
+ int range_offst, tp_freq;
+
+ range_offst = internal->srch_range / 2000;
+ tp_freq = internal->freq + (internal->derot_freq * internal->mclk) / 1000;
+
+ if ((tp_freq >= params->freq - range_offst) && (tp_freq <= params->freq + range_offst)) {
+ internal->status = RANGEOK;
+ dprintk(state->verbose, FE_DEBUG, 1, "----> RANGEOK !");
+ } else {
+ internal->status = OUTOFRANGE;
+ dprintk(state->verbose, FE_DEBUG, 1, "----> OUT OF RANGE !");
+ }
+
+ return internal->status;
+}
+
+/*
+ * NextSubRange
+ * Compute the next subrange of the search
+ */
+static void next_sub_range(struct stb0899_state *state)
+{
+ struct stb0899_internal *internal = &state->internal;
+ struct stb0899_params *params = &state->params;
+
+ long old_sub_range;
+
+ if (internal->sub_dir > 0) {
+ old_sub_range = internal->sub_range;
+ internal->sub_range = MIN((internal->srch_range / 2) -
+ (internal->tuner_offst + internal->sub_range / 2),
+ internal->sub_range);
+
+ if (internal->sub_range < 0)
+ internal->sub_range = 0;
+
+ internal->tuner_offst += (old_sub_range + internal->sub_range) / 2;
+ }
+
+ internal->freq = params->freq + (internal->sub_dir * internal->tuner_offst) / 1000;
+ internal->sub_dir = -internal->sub_dir;
+}
+
+/*
+ * stb0899_dvbs_algo
+ * Search for a signal, timing, carrier and data for a
+ * given frequency in a given range
+ */
+enum stb0899_status stb0899_dvbs_algo(struct stb0899_state *state)
+{
+ struct stb0899_params *params = &state->params;
+ struct stb0899_internal *internal = &state->internal;
+ struct stb0899_config *config = state->config;
+
+ u8 bclc, reg;
+ u8 cfr[2];
+ u8 eq_const[10];
+ s32 clnI = 3;
+ u32 bandwidth = 0;
+
+ /* BETA values rated @ 99MHz */
+ s32 betaTab[5][4] = {
+ /* 5 10 20 30MBps */
+ { 37, 34, 32, 31 }, /* QPSK 1/2 */
+ { 37, 35, 33, 31 }, /* QPSK 2/3 */
+ { 37, 35, 33, 31 }, /* QPSK 3/4 */
+ { 37, 36, 33, 32 }, /* QPSK 5/6 */
+ { 37, 36, 33, 32 } /* QPSK 7/8 */
+ };
+
+ internal->direction = 1;
+
+ stb0899_set_srate(state, internal->master_clk, params->srate);
+ /* Carrier loop optimization versus symbol rate for acquisition*/
+ if (params->srate <= 5000000) {
+ stb0899_write_reg(state, STB0899_ACLC, 0x89);
+ bclc = stb0899_read_reg(state, STB0899_BCLC);
+ STB0899_SETFIELD_VAL(BETA, bclc, 0x1c);
+ stb0899_write_reg(state, STB0899_BCLC, bclc);
+ clnI = 0;
+ } else if (params->srate <= 15000000) {
+ stb0899_write_reg(state, STB0899_ACLC, 0xc9);
+ bclc = stb0899_read_reg(state, STB0899_BCLC);
+ STB0899_SETFIELD_VAL(BETA, bclc, 0x22);
+ stb0899_write_reg(state, STB0899_BCLC, bclc);
+ clnI = 1;
+ } else if(params->srate <= 25000000) {
+ stb0899_write_reg(state, STB0899_ACLC, 0x89);
+ bclc = stb0899_read_reg(state, STB0899_BCLC);
+ STB0899_SETFIELD_VAL(BETA, bclc, 0x27);
+ stb0899_write_reg(state, STB0899_BCLC, bclc);
+ clnI = 2;
+ } else {
+ stb0899_write_reg(state, STB0899_ACLC, 0xc8);
+ bclc = stb0899_read_reg(state, STB0899_BCLC);
+ STB0899_SETFIELD_VAL(BETA, bclc, 0x29);
+ stb0899_write_reg(state, STB0899_BCLC, bclc);
+ clnI = 3;
+ }
+
+ dprintk(state->verbose, FE_DEBUG, 1, "Set the timing loop to acquisition");
+ /* Set the timing loop to acquisition */
+ stb0899_write_reg(state, STB0899_RTC, 0x46);
+ stb0899_write_reg(state, STB0899_CFD, 0xee);
+
+ /* !! WARNING !!
+ * Do not read any status variables while acquisition,
+ * If any needed, read before the acquisition starts
+ * querying status while acquiring causes the
+ * acquisition to go bad and hence no locks.
+ */
+ dprintk(state->verbose, FE_DEBUG, 1, "Derot Percent=%d Srate=%d mclk=%d",
+ internal->derot_percent, params->srate, internal->mclk);
+
+ /* Initial calculations */
+ internal->derot_step = internal->derot_percent * (params->srate / 1000L) / internal->mclk; /* DerotStep/1000 * Fsymbol */
+ internal->t_derot = stb0899_calc_derot_time(params->srate);
+ internal->t_data = 500;
+
+ dprintk(state->verbose, FE_DEBUG, 1, "RESET stream merger");
+ /* RESET Stream merger */
+ reg = stb0899_read_reg(state, STB0899_TSTRES);
+ STB0899_SETFIELD_VAL(FRESRS, reg, 1);
+ stb0899_write_reg(state, STB0899_TSTRES, reg);
+
+ /*
+ * Set KDIVIDER to an intermediate value between
+ * 1/2 and 7/8 for acquisition
+ */
+ reg = stb0899_read_reg(state, STB0899_DEMAPVIT);
+ STB0899_SETFIELD_VAL(DEMAPVIT_KDIVIDER, reg, 60);
+ stb0899_write_reg(state, STB0899_DEMAPVIT, reg);
+
+ stb0899_write_reg(state, STB0899_EQON, 0x01); /* Equalizer OFF while acquiring */
+ stb0899_write_reg(state, STB0899_VITSYNC, 0x19);
+
+ stb0899_first_subrange(state);
+ do {
+ /* Initialisations */
+ cfr[0] = cfr[1] = 0;
+ stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* RESET derotator frequency */
+
+ stb0899_write_reg(state, STB0899_RTF, 0);
+ reg = stb0899_read_reg(state, STB0899_CFD);
+ STB0899_SETFIELD_VAL(CFD_ON, reg, 1);
+ stb0899_write_reg(state, STB0899_CFD, reg);
+
+ internal->derot_freq = 0;
+ internal->status = NOAGC1;
+
+ /* enable tuner I/O */
+ stb0899_i2c_gate_ctrl(&state->frontend, 1);
+
+ /* Move tuner to frequency */
+ dprintk(state->verbose, FE_DEBUG, 1, "Tuner set frequency");
+ if (state->config->tuner_set_frequency)
+ state->config->tuner_set_frequency(&state->frontend, internal->freq);
+
+ if (state->config->tuner_get_frequency)
+ state->config->tuner_get_frequency(&state->frontend, &internal->freq);
+
+ msleep(internal->t_agc1 + internal->t_agc2 + internal->t_derot); /* AGC1, AGC2 and timing loop */
+ dprintk(state->verbose, FE_DEBUG, 1, "current derot freq=%d", internal->derot_freq);
+ internal->status = AGC1OK;
+
+ /* There is signal in the band */
+ if (config->tuner_get_bandwidth)
+ config->tuner_get_bandwidth(&state->frontend, &bandwidth);
+
+ /* disable tuner I/O */
+ stb0899_i2c_gate_ctrl(&state->frontend, 0);
+
+ if (params->srate <= bandwidth / 2)
+ stb0899_search_tmg(state); /* For low rates (SCPC) */
+ else
+ stb0899_check_tmg(state); /* For high rates (MCPC) */
+
+ if (internal->status == TIMINGOK) {
+ dprintk(state->verbose, FE_DEBUG, 1,
+ "TIMING OK ! Derot freq=%d, mclk=%d",
+ internal->derot_freq, internal->mclk);
+
+ if (stb0899_search_carrier(state) == CARRIEROK) { /* Search for carrier */
+ dprintk(state->verbose, FE_DEBUG, 1,
+ "CARRIER OK ! Derot freq=%d, mclk=%d",
+ internal->derot_freq, internal->mclk);
+
+ if (stb0899_search_data(state) == DATAOK) { /* Check for data */
+ dprintk(state->verbose, FE_DEBUG, 1,
+ "DATA OK ! Derot freq=%d, mclk=%d",
+ internal->derot_freq, internal->mclk);
+
+ if (stb0899_check_range(state) == RANGEOK) {
+ dprintk(state->verbose, FE_DEBUG, 1,
+ "RANGE OK ! derot freq=%d, mclk=%d",
+ internal->derot_freq, internal->mclk);
+
+ internal->freq = params->freq + ((internal->derot_freq * internal->mclk) / 1000);
+ reg = stb0899_read_reg(state, STB0899_PLPARM);
+ internal->fecrate = STB0899_GETFIELD(VITCURPUN, reg);
+ dprintk(state->verbose, FE_DEBUG, 1,
+ "freq=%d, internal resultant freq=%d",
+ params->freq, internal->freq);
+
+ dprintk(state->verbose, FE_DEBUG, 1,
+ "internal puncture rate=%d",
+ internal->fecrate);
+ }
+ }
+ }
+ }
+ if (internal->status != RANGEOK)
+ next_sub_range(state);
+
+ } while (internal->sub_range && internal->status != RANGEOK);
+
+ /* Set the timing loop to tracking */
+ stb0899_write_reg(state, STB0899_RTC, 0x33);
+ stb0899_write_reg(state, STB0899_CFD, 0xf7);
+ /* if locked and range ok, set Kdiv */
+ if (internal->status == RANGEOK) {
+ dprintk(state->verbose, FE_DEBUG, 1, "Locked & Range OK !");
+ stb0899_write_reg(state, STB0899_EQON, 0x41); /* Equalizer OFF while acquiring */
+ stb0899_write_reg(state, STB0899_VITSYNC, 0x39); /* SN to b'11 for acquisition */
+
+ /*
+ * Carrier loop optimization versus
+ * symbol Rate/Puncture Rate for Tracking
+ */
+ reg = stb0899_read_reg(state, STB0899_BCLC);
+ switch (internal->fecrate) {
+ case STB0899_FEC_1_2: /* 13 */
+ stb0899_write_reg(state, STB0899_DEMAPVIT, 0x1a);
+ STB0899_SETFIELD_VAL(BETA, reg, betaTab[0][clnI]);
+ stb0899_write_reg(state, STB0899_BCLC, reg);
+ break;
+ case STB0899_FEC_2_3: /* 18 */
+ stb0899_write_reg(state, STB0899_DEMAPVIT, 44);
+ STB0899_SETFIELD_VAL(BETA, reg, betaTab[1][clnI]);
+ stb0899_write_reg(state, STB0899_BCLC, reg);
+ break;
+ case STB0899_FEC_3_4: /* 21 */
+ stb0899_write_reg(state, STB0899_DEMAPVIT, 60);
+ STB0899_SETFIELD_VAL(BETA, reg, betaTab[2][clnI]);
+ stb0899_write_reg(state, STB0899_BCLC, reg);
+ break;
+ case STB0899_FEC_5_6: /* 24 */
+ stb0899_write_reg(state, STB0899_DEMAPVIT, 75);
+ STB0899_SETFIELD_VAL(BETA, reg, betaTab[3][clnI]);
+ stb0899_write_reg(state, STB0899_BCLC, reg);
+ break;
+ case STB0899_FEC_6_7: /* 25 */
+ stb0899_write_reg(state, STB0899_DEMAPVIT, 88);
+ stb0899_write_reg(state, STB0899_ACLC, 0x88);
+ stb0899_write_reg(state, STB0899_BCLC, 0x9a);
+ break;
+ case STB0899_FEC_7_8: /* 26 */
+ stb0899_write_reg(state, STB0899_DEMAPVIT, 94);
+ STB0899_SETFIELD_VAL(BETA, reg, betaTab[4][clnI]);
+ stb0899_write_reg(state, STB0899_BCLC, reg);
+ break;
+ default:
+ dprintk(state->verbose, FE_DEBUG, 1, "Unsupported Puncture Rate");
+ break;
+ }
+ /* release stream merger RESET */
+ reg = stb0899_read_reg(state, STB0899_TSTRES);
+ STB0899_SETFIELD_VAL(FRESRS, reg, 0);
+ stb0899_write_reg(state, STB0899_TSTRES, reg);
+
+ /* disable carrier detector */
+ reg = stb0899_read_reg(state, STB0899_CFD);
+ STB0899_SETFIELD_VAL(CFD_ON, reg, 0);
+ stb0899_write_reg(state, STB0899_CFD, reg);
+
+ stb0899_read_regs(state, STB0899_EQUAI1, eq_const, 10);
+ }
+
+ return internal->status;
+}
+
+/*
+ * stb0899_dvbs2_config_uwp
+ * Configure UWP state machine
+ */
+static void stb0899_dvbs2_config_uwp(struct stb0899_state *state)
+{
+ struct stb0899_internal *internal = &state->internal;
+ struct stb0899_config *config = state->config;
+ u32 uwp1, uwp2, uwp3, reg;
+
+ uwp1 = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_CNTRL1);
+ uwp2 = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_CNTRL2);
+ uwp3 = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_CNTRL3);
+
+ STB0899_SETFIELD_VAL(UWP_ESN0_AVE, uwp1, config->esno_ave);
+ STB0899_SETFIELD_VAL(UWP_ESN0_QUANT, uwp1, config->esno_quant);
+ STB0899_SETFIELD_VAL(UWP_TH_SOF, uwp1, config->uwp_threshold_sof);
+
+ STB0899_SETFIELD_VAL(FE_COARSE_TRK, uwp2, internal->av_frame_coarse);
+ STB0899_SETFIELD_VAL(FE_FINE_TRK, uwp2, internal->av_frame_fine);
+ STB0899_SETFIELD_VAL(UWP_MISS_TH, uwp2, config->miss_threshold);
+
+ STB0899_SETFIELD_VAL(UWP_TH_ACQ, uwp3, config->uwp_threshold_acq);
+ STB0899_SETFIELD_VAL(UWP_TH_TRACK, uwp3, config->uwp_threshold_track);
+
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_UWP_CNTRL1, STB0899_OFF0_UWP_CNTRL1, uwp1);
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_UWP_CNTRL2, STB0899_OFF0_UWP_CNTRL2, uwp2);
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_UWP_CNTRL3, STB0899_OFF0_UWP_CNTRL3, uwp3);
+
+ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, SOF_SRCH_TO);
+ STB0899_SETFIELD_VAL(SOF_SEARCH_TIMEOUT, reg, config->sof_search_timeout);
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_SOF_SRCH_TO, STB0899_OFF0_SOF_SRCH_TO, reg);
+}
+
+/*
+ * stb0899_dvbs2_config_csm_auto
+ * Set CSM to AUTO mode
+ */
+static void stb0899_dvbs2_config_csm_auto(struct stb0899_state *state)
+{
+ u32 reg;
+
+ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL1);
+ STB0899_SETFIELD_VAL(CSM_AUTO_PARAM, reg, 1);
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, reg);
+}
+
+long Log2Int(int number)
+{
+ int i;
+
+ i = 0;
+ while ((1 << i) <= ABS(number))
+ i++;
+
+ if (number == 0)
+ i = 1;
+
+ return i - 1;
+}
+
+/*
+ * stb0899_dvbs2_calc_srate
+ * compute BTR_NOM_FREQ for the symbol rate
+ */
+static u32 stb0899_dvbs2_calc_srate(struct stb0899_state *state)
+{
+ struct stb0899_internal *internal = &state->internal;
+ struct stb0899_config *config = state->config;
+
+ u32 dec_ratio, dec_rate, decim, remain, intval, btr_nom_freq;
+ u32 master_clk, srate;
+
+ dec_ratio = (internal->master_clk * 2) / (5 * internal->srate);
+ dec_ratio = (dec_ratio == 0) ? 1 : dec_ratio;
+ dec_rate = Log2Int(dec_ratio);
+ decim = 1 << dec_rate;
+ master_clk = internal->master_clk / 1000;
+ srate = internal->srate / 1000;
+
+ if (decim <= 4) {
+ intval = (decim * (1 << (config->btr_nco_bits - 1))) / master_clk;
+ remain = (decim * (1 << (config->btr_nco_bits - 1))) % master_clk;
+ } else {
+ intval = (1 << (config->btr_nco_bits - 1)) / (master_clk / 100) * decim / 100;
+ remain = (decim * (1 << (config->btr_nco_bits - 1))) % master_clk;
+ }
+ btr_nom_freq = (intval * srate) + ((remain * srate) / master_clk);
+
+ return btr_nom_freq;
+}
+
+/*
+ * stb0899_dvbs2_calc_dev
+ * compute the correction to be applied to symbol rate
+ */
+static u32 stb0899_dvbs2_calc_dev(struct stb0899_state *state)
+{
+ struct stb0899_internal *internal = &state->internal;
+ u32 dec_ratio, correction, master_clk, srate;
+
+ dec_ratio = (internal->master_clk * 2) / (5 * internal->srate);
+ dec_ratio = (dec_ratio == 0) ? 1 : dec_ratio;
+
+ master_clk = internal->master_clk / 1000; /* for integer Caculation*/
+ srate = internal->srate / 1000; /* for integer Caculation*/
+ correction = (512 * master_clk) / (2 * dec_ratio * srate);
+
+ return correction;
+}
+
+/*
+ * stb0899_dvbs2_set_srate
+ * Set DVBS2 symbol rate
+ */
+static void stb0899_dvbs2_set_srate(struct stb0899_state *state)
+{
+ struct stb0899_internal *internal = &state->internal;
+
+ u32 dec_ratio, dec_rate, win_sel, decim, f_sym, btr_nom_freq;
+ u32 correction, freq_adj, band_lim, decim_cntrl, reg;
+ u8 anti_alias;
+
+ /*set decimation to 1*/
+ dec_ratio = (internal->master_clk * 2) / (5 * internal->srate);
+ dec_ratio = (dec_ratio == 0) ? 1 : dec_ratio;
+ dec_rate = Log2Int(dec_ratio);
+
+ win_sel = 0;
+ if (dec_rate >= 5)
+ win_sel = dec_rate - 4;
+
+ decim = (1 << dec_rate);
+ /* (FSamp/Fsymbol *100) for integer Caculation */
+ f_sym = internal->master_clk / ((decim * internal->srate) / 1000);
+
+ if (f_sym <= 2250) /* don't band limit signal going into btr block*/
+ band_lim = 1;
+ else
+ band_lim = 0; /* band limit signal going into btr block*/
+
+ decim_cntrl = ((win_sel << 3) & 0x18) + ((band_lim << 5) & 0x20) + (dec_rate & 0x7);
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_DECIM_CNTRL, STB0899_OFF0_DECIM_CNTRL, decim_cntrl);
+
+ if (f_sym <= 3450)
+ anti_alias = 0;
+ else if (f_sym <= 4250)
+ anti_alias = 1;
+ else
+ anti_alias = 2;
+
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_ANTI_ALIAS_SEL, STB0899_OFF0_ANTI_ALIAS_SEL, anti_alias);
+ btr_nom_freq = stb0899_dvbs2_calc_srate(state);
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_NOM_FREQ, STB0899_OFF0_BTR_NOM_FREQ, btr_nom_freq);
+
+ correction = stb0899_dvbs2_calc_dev(state);
+ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, BTR_CNTRL);
+ STB0899_SETFIELD_VAL(BTR_FREQ_CORR, reg, correction);
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_CNTRL, STB0899_OFF0_BTR_CNTRL, reg);
+
+ /* scale UWP+CSM frequency to sample rate*/
+ freq_adj = internal->srate / (internal->master_clk / 4096);
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_FREQ_ADJ_SCALE, STB0899_OFF0_FREQ_ADJ_SCALE, freq_adj);
+}
+
+/*
+ * stb0899_dvbs2_set_btr_loopbw
+ * set bit timing loop bandwidth as a percentage of the symbol rate
+ */
+static void stb0899_dvbs2_set_btr_loopbw(struct stb0899_state *state)
+{
+ struct stb0899_internal *internal = &state->internal;
+ struct stb0899_config *config = state->config;
+
+ u32 sym_peak = 23, zeta = 707, loopbw_percent = 60;
+ s32 dec_ratio, dec_rate, k_btr1_rshft, k_btr1, k_btr0_rshft;
+ s32 k_btr0, k_btr2_rshft, k_direct_shift, k_indirect_shift;
+ u32 decim, K, wn, k_direct, k_indirect;
+ u32 reg;
+
+ dec_ratio = (internal->master_clk * 2) / (5 * internal->srate);
+ dec_ratio = (dec_ratio == 0) ? 1 : dec_ratio;
+ dec_rate = Log2Int(dec_ratio);
+ decim = (1 << dec_rate);
+
+ sym_peak *= 576000;
+ K = (1 << config->btr_nco_bits) / (internal->master_clk / 1000);
+ K *= (internal->srate / 1000000) * decim; /*k=k 10^-8*/
+
+ if (K != 0) {
+ K = sym_peak / K;
+ wn = (4 * zeta * zeta) + 1000000;
+ wn = (2 * (loopbw_percent * 1000) * 40 * zeta) /wn; /*wn =wn 10^-8*/
+
+ k_indirect = (wn * wn) / K;
+ k_indirect = k_indirect; /*kindirect = kindirect 10^-6*/
+ k_direct = (2 * wn * zeta) / K; /*kDirect = kDirect 10^-2*/
+ k_direct *= 100;
+
+ k_direct_shift = Log2Int(k_direct) - Log2Int(10000) - 2;
+ k_btr1_rshft = (-1 * k_direct_shift) + config->btr_gain_shift_offset;
+ k_btr1 = k_direct / (1 << k_direct_shift);
+ k_btr1 /= 10000;
+
+ k_indirect_shift = Log2Int(k_indirect + 15) - 20 /*- 2*/;
+ k_btr0_rshft = (-1 * k_indirect_shift) + config->btr_gain_shift_offset;
+ k_btr0 = k_indirect * (1 << (-k_indirect_shift));
+ k_btr0 /= 1000000;
+
+ k_btr2_rshft = 0;
+ if (k_btr0_rshft > 15) {
+ k_btr2_rshft = k_btr0_rshft - 15;
+ k_btr0_rshft = 15;
+ }
+ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, BTR_LOOP_GAIN);
+ STB0899_SETFIELD_VAL(KBTR0_RSHFT, reg, k_btr0_rshft);
+ STB0899_SETFIELD_VAL(KBTR0, reg, k_btr0);
+ STB0899_SETFIELD_VAL(KBTR1_RSHFT, reg, k_btr1_rshft);
+ STB0899_SETFIELD_VAL(KBTR1, reg, k_btr1);
+ STB0899_SETFIELD_VAL(KBTR2_RSHFT, reg, k_btr2_rshft);
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_LOOP_GAIN, STB0899_OFF0_BTR_LOOP_GAIN, reg);
+ } else
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_LOOP_GAIN, STB0899_OFF0_BTR_LOOP_GAIN, 0xc4c4f);
+}
+
+/*
+ * stb0899_dvbs2_set_carr_freq
+ * set nominal frequency for carrier search
+ */
+static void stb0899_dvbs2_set_carr_freq(struct stb0899_state *state, s32 carr_freq, u32 master_clk)
+{
+ struct stb0899_config *config = state->config;
+ s32 crl_nom_freq;
+ u32 reg;
+
+ crl_nom_freq = (1 << config->crl_nco_bits) / master_clk;
+ crl_nom_freq *= carr_freq;
+ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_NOM_FREQ);
+ STB0899_SETFIELD_VAL(CRL_NOM_FREQ, reg, crl_nom_freq);
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_NOM_FREQ, STB0899_OFF0_CRL_NOM_FREQ, reg);
+}
+
+/*
+ * stb0899_dvbs2_init_calc
+ * Initialize DVBS2 UWP, CSM, carrier and timing loops
+ */
+static void stb0899_dvbs2_init_calc(struct stb0899_state *state)
+{
+ struct stb0899_internal *internal = &state->internal;
+ s32 steps, step_size;
+ u32 range, reg;
+
+ /* config uwp and csm */
+ stb0899_dvbs2_config_uwp(state);
+ stb0899_dvbs2_config_csm_auto(state);
+
+ /* initialize BTR */
+ stb0899_dvbs2_set_srate(state);
+ stb0899_dvbs2_set_btr_loopbw(state);
+
+ if (internal->srate / 1000000 >= 15)
+ step_size = (1 << 17) / 5;
+ else if (internal->srate / 1000000 >= 10)
+ step_size = (1 << 17) / 7;
+ else if (internal->srate / 1000000 >= 5)
+ step_size = (1 << 17) / 10;
+ else
+ step_size = (1 << 17) / 4;
+
+ range = internal->srch_range / 1000000;
+ steps = (10 * range * (1 << 17)) / (step_size * (internal->srate / 1000000));
+ steps = (steps + 6) / 10;
+ steps = (steps == 0) ? 1 : steps;
+ if (steps % 2 == 0)
+ stb0899_dvbs2_set_carr_freq(state, internal->center_freq -
+ (internal->step_size * (internal->srate / 20000000)),
+ (internal->master_clk) / 1000000);
+ else
+ stb0899_dvbs2_set_carr_freq(state, internal->center_freq, (internal->master_clk) / 1000000);
+
+ /*Set Carrier Search params (zigzag, num steps and freq step size*/
+ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, ACQ_CNTRL2);
+ STB0899_SETFIELD_VAL(ZIGZAG, reg, 1);
+ STB0899_SETFIELD_VAL(NUM_STEPS, reg, steps);
+ STB0899_SETFIELD_VAL(FREQ_STEPSIZE, reg, step_size);
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_ACQ_CNTRL2, STB0899_OFF0_ACQ_CNTRL2, reg);
+}
+
+/*
+ * stb0899_dvbs2_btr_init
+ * initialize the timing loop
+ */
+static void stb0899_dvbs2_btr_init(struct stb0899_state *state)
+{
+ u32 reg;
+
+ /* set enable BTR loopback */
+ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, BTR_CNTRL);
+ STB0899_SETFIELD_VAL(INTRP_PHS_SENSE, reg, 1);
+ STB0899_SETFIELD_VAL(BTR_ERR_ENA, reg, 1);
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_CNTRL, STB0899_OFF0_BTR_CNTRL, reg);
+
+ /* fix btr freq accum at 0 */
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_FREQ_INIT, STB0899_OFF0_BTR_FREQ_INIT, 0x10000000);
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_FREQ_INIT, STB0899_OFF0_BTR_FREQ_INIT, 0x00000000);
+
+ /* fix btr freq accum at 0 */
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_PHS_INIT, STB0899_OFF0_BTR_PHS_INIT, 0x10000000);
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_PHS_INIT, STB0899_OFF0_BTR_PHS_INIT, 0x00000000);
+}
+
+/*
+ * stb0899_dvbs2_reacquire
+ * trigger a DVB-S2 acquisition
+ */
+static void stb0899_dvbs2_reacquire(struct stb0899_state *state)
+{
+ u32 reg = 0;
+
+ /* demod soft reset */
+ STB0899_SETFIELD_VAL(DVBS2_RESET, reg, 1);
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_RESET_CNTRL, STB0899_OFF0_RESET_CNTRL, reg);
+
+ /*Reset Timing Loop */
+ stb0899_dvbs2_btr_init(state);
+
+ /* reset Carrier loop */
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_FREQ_INIT, STB0899_OFF0_CRL_FREQ_INIT, (1 << 30));
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_FREQ_INIT, STB0899_OFF0_CRL_FREQ_INIT, 0);
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_LOOP_GAIN, STB0899_OFF0_CRL_LOOP_GAIN, 0);
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_PHS_INIT, STB0899_OFF0_CRL_PHS_INIT, (1 << 30));
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_PHS_INIT, STB0899_OFF0_CRL_PHS_INIT, 0);
+
+ /*release demod soft reset */
+ reg = 0;
+ STB0899_SETFIELD_VAL(DVBS2_RESET, reg, 0);
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_RESET_CNTRL, STB0899_OFF0_RESET_CNTRL, reg);
+
+ /* start acquisition process */
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_ACQUIRE_TRIG, STB0899_OFF0_ACQUIRE_TRIG, 1);
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_LOCK_LOST, STB0899_OFF0_LOCK_LOST, 0);
+
+ /* equalizer Init */
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQUALIZER_INIT, STB0899_OFF0_EQUALIZER_INIT, 1);
+
+ /*Start equilizer */
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQUALIZER_INIT, STB0899_OFF0_EQUALIZER_INIT, 0);
+
+ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, EQ_CNTRL);
+ STB0899_SETFIELD_VAL(EQ_SHIFT, reg, 0);
+ STB0899_SETFIELD_VAL(EQ_DISABLE_UPDATE, reg, 0);
+ STB0899_SETFIELD_VAL(EQ_DELAY, reg, 0x05);
+ STB0899_SETFIELD_VAL(EQ_ADAPT_MODE, reg, 0x01);
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQ_CNTRL, STB0899_OFF0_EQ_CNTRL, reg);
+
+ /* RESET Packet delineator */
+ stb0899_write_reg(state, STB0899_PDELCTRL, 0x4a);
+}
+
+/*
+ * stb0899_dvbs2_get_dmd_status
+ * get DVB-S2 Demod LOCK status
+ */
+static enum stb0899_status stb0899_dvbs2_get_dmd_status(struct stb0899_state *state, int timeout)
+{
+ int time = -10, lock = 0, uwp, csm;
+ u32 reg;
+
+ do {
+ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_STATUS);
+ dprintk(state->verbose, FE_DEBUG, 1, "DMD_STATUS=[0x%02x]", reg);
+ if (STB0899_GETFIELD(IF_AGC_LOCK, reg))
+ dprintk(state->verbose, FE_DEBUG, 1, "------------->IF AGC LOCKED !");
+ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_STAT2);
+ dprintk(state->verbose, FE_DEBUG, 1, "----------->DMD STAT2=[0x%02x]", reg);
+ uwp = STB0899_GETFIELD(UWP_LOCK, reg);
+ csm = STB0899_GETFIELD(CSM_LOCK, reg);
+ if (uwp && csm)
+ lock = 1;
+
+ time += 10;
+ msleep(10);
+
+ } while ((!lock) && (time <= timeout));
+
+ if (lock) {
+ dprintk(state->verbose, FE_DEBUG, 1, "----------------> DVB-S2 LOCK !");
+ return DVBS2_DEMOD_LOCK;
+ } else {
+ return DVBS2_DEMOD_NOLOCK;
+ }
+}
+
+/*
+ * stb0899_dvbs2_get_data_lock
+ * get FEC status
+ */
+static int stb0899_dvbs2_get_data_lock(struct stb0899_state *state, int timeout)
+{
+ int time = 0, lock = 0;
+ u8 reg;
+
+ while ((!lock) && (time < timeout)) {
+ reg = stb0899_read_reg(state, STB0899_CFGPDELSTATUS1);
+ dprintk(state->verbose, FE_DEBUG, 1, "---------> CFGPDELSTATUS=[0x%02x]", reg);
+ lock = STB0899_GETFIELD(CFGPDELSTATUS_LOCK, reg);
+ time++;
+ }
+
+ return lock;
+}
+
+/*
+ * stb0899_dvbs2_get_fec_status
+ * get DVB-S2 FEC LOCK status
+ */
+static enum stb0899_status stb0899_dvbs2_get_fec_status(struct stb0899_state *state, int timeout)
+{
+ int time = 0, Locked;
+
+ do {
+ Locked = stb0899_dvbs2_get_data_lock(state, 1);
+ time++;
+ msleep(1);
+
+ } while ((!Locked) && (time < timeout));
+
+ if (Locked) {
+ dprintk(state->verbose, FE_DEBUG, 1, "---------->DVB-S2 FEC LOCK !");
+ return DVBS2_FEC_LOCK;
+ } else {
+ return DVBS2_FEC_NOLOCK;
+ }
+}
+
+#if 0
+/*
+ * stb0899_dvbs2_get_modcod
+ * get MODCOD
+ */
+static u32 stb0899_dvbs2_get_modcod(struct stb0899_state *state)
+{
+ u32 reg;
+
+ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_STAT2);
+ return (STB0899_GETFIELD(UWP_DECODE_MOD, reg) >> 2);
+}
+#endif
+
+/*
+ * stb0899_dvbs2_init_csm
+ * set parameters for manual mode
+ */
+static void stb0899_dvbs2_init_csm(struct stb0899_state *state, int pilots, enum stb0899_modcod modcod)
+{
+ struct stb0899_internal *internal = &state->internal;
+
+ s32 dvt_tbl = 1, two_pass = 0, agc_gain = 6, agc_shift = 0, loop_shift = 0, phs_diff_thr = 0x80;
+ s32 gamma_acq, gamma_rho_acq, gamma_trk, gamma_rho_trk, lock_count_thr;
+ u32 csm1, csm2, csm3, csm4;
+
+ if (((internal->master_clk / internal->srate) <= 4) && (modcod <= 11) && (pilots == 1)) {
+ switch (modcod) {
+ case STB0899_QPSK_12:
+ gamma_acq = 25;
+ gamma_rho_acq = 2700;
+ gamma_trk = 12;
+ gamma_rho_trk = 180;
+ lock_count_thr = 8;
+ break;
+ case STB0899_QPSK_35:
+ gamma_acq = 38;
+ gamma_rho_acq = 7182;
+ gamma_trk = 14;
+ gamma_rho_trk = 308;
+ lock_count_thr = 8;
+ break;
+ case STB0899_QPSK_23:
+ gamma_acq = 42;
+ gamma_rho_acq = 9408;
+ gamma_trk = 17;
+ gamma_rho_trk = 476;
+ lock_count_thr = 8;
+ break;
+ case STB0899_QPSK_34:
+ gamma_acq = 53;
+ gamma_rho_acq = 16642;
+ gamma_trk = 19;
+ gamma_rho_trk = 646;
+ lock_count_thr = 8;
+ break;
+ case STB0899_QPSK_45:
+ gamma_acq = 53;
+ gamma_rho_acq = 17119;
+ gamma_trk = 22;
+ gamma_rho_trk = 880;
+ lock_count_thr = 8;
+ break;
+ case STB0899_QPSK_56:
+ gamma_acq = 55;
+ gamma_rho_acq = 19250;
+ gamma_trk = 23;
+ gamma_rho_trk = 989;
+ lock_count_thr = 8;
+ break;
+ case STB0899_QPSK_89:
+ gamma_acq = 60;
+ gamma_rho_acq = 24240;
+ gamma_trk = 24;
+ gamma_rho_trk = 1176;
+ lock_count_thr = 8;
+ break;
+ case STB0899_QPSK_910:
+ gamma_acq = 66;
+ gamma_rho_acq = 29634;
+ gamma_trk = 24;
+ gamma_rho_trk = 1176;
+ lock_count_thr = 8;
+ break;
+ default:
+ gamma_acq = 66;
+ gamma_rho_acq = 29634;
+ gamma_trk = 24;
+ gamma_rho_trk = 1176;
+ lock_count_thr = 8;
+ break;
+ }
+
+ csm1 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL1);
+ STB0899_SETFIELD_VAL(CSM_AUTO_PARAM, csm1, 0);
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, csm1);
+
+ csm1 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL1);
+ csm2 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL2);
+ csm3 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL3);
+ csm4 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL4);
+
+ STB0899_SETFIELD_VAL(CSM_DVT_TABLE, csm1, dvt_tbl);
+ STB0899_SETFIELD_VAL(CSM_TWO_PASS, csm1, two_pass);
+ STB0899_SETFIELD_VAL(CSM_AGC_GAIN, csm1, agc_gain);
+ STB0899_SETFIELD_VAL(CSM_AGC_SHIFT, csm1, agc_shift);
+ STB0899_SETFIELD_VAL(FE_LOOP_SHIFT, csm1, loop_shift);
+ STB0899_SETFIELD_VAL(CSM_GAMMA_ACQ, csm2, gamma_acq);
+ STB0899_SETFIELD_VAL(CSM_GAMMA_RHOACQ, csm2, gamma_rho_acq);
+ STB0899_SETFIELD_VAL(CSM_GAMMA_TRACK, csm3, gamma_trk);
+ STB0899_SETFIELD_VAL(CSM_GAMMA_RHOTRACK, csm3, gamma_rho_trk);
+ STB0899_SETFIELD_VAL(CSM_LOCKCOUNT_THRESH, csm4, lock_count_thr);
+ STB0899_SETFIELD_VAL(CSM_PHASEDIFF_THRESH, csm4, phs_diff_thr);
+
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, csm1);
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL2, STB0899_OFF0_CSM_CNTRL2, csm2);
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL3, STB0899_OFF0_CSM_CNTRL3, csm3);
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL4, STB0899_OFF0_CSM_CNTRL4, csm4);
+ }
+}
+
+/*
+ * stb0899_dvbs2_get_srate
+ * get DVB-S2 Symbol Rate
+ */
+static u32 stb0899_dvbs2_get_srate(struct stb0899_state *state)
+{
+ struct stb0899_internal *internal = &state->internal;
+ struct stb0899_config *config = state->config;
+
+ u32 bTrNomFreq, srate, decimRate, intval1, intval2, reg;
+ int div1, div2, rem1, rem2;
+
+ div1 = config->btr_nco_bits / 2;
+ div2 = config->btr_nco_bits - div1 - 1;
+
+ bTrNomFreq = STB0899_READ_S2REG(STB0899_S2DEMOD, BTR_NOM_FREQ);
+
+ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DECIM_CNTRL);
+ decimRate = STB0899_GETFIELD(DECIM_RATE, reg);
+ decimRate = (1 << decimRate);
+
+ intval1 = internal->master_clk / (1 << div1);
+ intval2 = bTrNomFreq / (1 << div2);
+
+ rem1 = internal->master_clk % (1 << div1);
+ rem2 = bTrNomFreq % (1 << div2);
+ /* only for integer calculation */
+ srate = (intval1 * intval2) + ((intval1 * rem2) / (1 << div2)) + ((intval2 * rem1) / (1 << div1));
+ srate /= decimRate; /*symbrate = (btrnomfreq_register_val*MasterClock)/2^(27+decim_rate_field) */
+
+ return srate;
+}
+
+/*
+ * stb0899_dvbs2_algo
+ * Search for signal, timing, carrier and data for a given
+ * frequency in a given range
+ */
+enum stb0899_status stb0899_dvbs2_algo(struct stb0899_state *state)
+{
+ struct stb0899_internal *internal = &state->internal;
+ enum stb0899_modcod modcod;
+
+ s32 offsetfreq, searchTime, FecLockTime, pilots, iqSpectrum;
+ int i = 0;
+ u32 reg, csm1;
+
+ if (internal->srate <= 2000000) {
+ searchTime = 5000; /* 5000 ms max time to lock UWP and CSM, SYMB <= 2Mbs */
+ FecLockTime = 350; /* 350 ms max time to lock FEC, SYMB <= 2Mbs */
+ } else if (internal->srate <= 5000000) {
+ searchTime = 2500; /* 2500 ms max time to lock UWP and CSM, 2Mbs < SYMB <= 5Mbs */
+ FecLockTime = 170; /* 170 ms max time to lock FEC, 2Mbs< SYMB <= 5Mbs */
+ } else if (internal->srate <= 10000000) {
+ searchTime = 1500; /* 1500 ms max time to lock UWP and CSM, 5Mbs <SYMB <= 10Mbs */
+ FecLockTime = 80; /* 80 ms max time to lock FEC, 5Mbs< SYMB <= 10Mbs */
+ } else if (internal->srate <= 15000000) {
+ searchTime = 500; /* 500 ms max time to lock UWP and CSM, 10Mbs <SYMB <= 15Mbs */
+ FecLockTime = 50; /* 50 ms max time to lock FEC, 10Mbs< SYMB <= 15Mbs */
+ } else if (internal->srate <= 20000000) {
+ searchTime = 300; /* 300 ms max time to lock UWP and CSM, 15Mbs < SYMB <= 20Mbs */
+ FecLockTime = 30; /* 50 ms max time to lock FEC, 15Mbs< SYMB <= 20Mbs */
+ } else if (internal->srate <= 25000000) {
+ searchTime = 250; /* 250 ms max time to lock UWP and CSM, 20 Mbs < SYMB <= 25Mbs */
+ FecLockTime = 25; /* 25 ms max time to lock FEC, 20Mbs< SYMB <= 25Mbs */
+ } else {
+ searchTime = 150; /* 150 ms max time to lock UWP and CSM, SYMB > 25Mbs */
+ FecLockTime = 20; /* 20 ms max time to lock FEC, 20Mbs< SYMB <= 25Mbs */
+ }
+
+ /* Maintain Stream Merger in reset during acquisition */
+ reg = stb0899_read_reg(state, STB0899_TSTRES);
+ STB0899_SETFIELD_VAL(FRESRS, reg, 1);
+ stb0899_write_reg(state, STB0899_TSTRES, reg);
+
+ /* enable tuner I/O */
+ stb0899_i2c_gate_ctrl(&state->frontend, 1);
+
+ /* Move tuner to frequency */
+ if (state->config->tuner_set_frequency)
+ state->config->tuner_set_frequency(&state->frontend, internal->freq);
+ if (state->config->tuner_get_frequency)
+ state->config->tuner_get_frequency(&state->frontend, &internal->freq);
+
+ /* disable tuner I/O */
+ stb0899_i2c_gate_ctrl(&state->frontend, 0);
+
+ /* Set IF AGC to acquisition */
+ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_CNTRL);
+ STB0899_SETFIELD_VAL(IF_LOOP_GAIN, reg, 4);
+ STB0899_SETFIELD_VAL(IF_AGC_REF, reg, 32);
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_IF_AGC_CNTRL, STB0899_OFF0_IF_AGC_CNTRL, reg);
+
+ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_CNTRL2);
+ STB0899_SETFIELD_VAL(IF_AGC_DUMP_PER, reg, 0);
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_IF_AGC_CNTRL2, STB0899_OFF0_IF_AGC_CNTRL2, reg);
+
+ /* Initialisation */
+ stb0899_dvbs2_init_calc(state);
+
+ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CNTRL2);
+ switch (internal->inversion) {
+ case IQ_SWAP_OFF:
+ STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, 0);
+ break;
+ case IQ_SWAP_ON:
+ STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, 1);
+ break;
+ case IQ_SWAP_AUTO: /* use last successful search first */
+ STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, 1);
+ break;
+ }
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_DMD_CNTRL2, STB0899_OFF0_DMD_CNTRL2, reg);
+ stb0899_dvbs2_reacquire(state);
+
+ /* Wait for demod lock (UWP and CSM) */
+ internal->status = stb0899_dvbs2_get_dmd_status(state, searchTime);
+
+ if (internal->status == DVBS2_DEMOD_LOCK) {
+ dprintk(state->verbose, FE_DEBUG, 1, "------------> DVB-S2 DEMOD LOCK !");
+ i = 0;
+ /* Demod Locked, check FEC status */
+ internal->status = stb0899_dvbs2_get_fec_status(state, FecLockTime);
+
+ /*If false lock (UWP and CSM Locked but no FEC) try 3 time max*/
+ while ((internal->status != DVBS2_FEC_LOCK) && (i < 3)) {
+ /* Read the frequency offset*/
+ offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ);
+
+ /* Set the Nominal frequency to the found frequency offset for the next reacquire*/
+ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_NOM_FREQ);
+ STB0899_SETFIELD_VAL(CRL_NOM_FREQ, reg, offsetfreq);
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_NOM_FREQ, STB0899_OFF0_CRL_NOM_FREQ, reg);
+ stb0899_dvbs2_reacquire(state);
+ internal->status = stb0899_dvbs2_get_fec_status(state, searchTime);
+ i++;
+ }
+ }
+
+ if (internal->status != DVBS2_FEC_LOCK) {
+ if (internal->inversion == IQ_SWAP_AUTO) {
+ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CNTRL2);
+ iqSpectrum = STB0899_GETFIELD(SPECTRUM_INVERT, reg);
+ /* IQ Spectrum Inversion */
+ STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, !iqSpectrum);
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_DMD_CNTRL2, STB0899_OFF0_DMD_CNTRL2, reg);
+ /* start acquistion process */
+ stb0899_dvbs2_reacquire(state);
+
+ /* Wait for demod lock (UWP and CSM) */
+ internal->status = stb0899_dvbs2_get_dmd_status(state, searchTime);
+ if (internal->status == DVBS2_DEMOD_LOCK) {
+ i = 0;
+ /* Demod Locked, check FEC */
+ internal->status = stb0899_dvbs2_get_fec_status(state, FecLockTime);
+ /*try thrice for false locks, (UWP and CSM Locked but no FEC) */
+ while ((internal->status != DVBS2_FEC_LOCK) && (i < 3)) {
+ /* Read the frequency offset*/
+ offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ);
+
+ /* Set the Nominal frequency to the found frequency offset for the next reacquire*/
+ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_NOM_FREQ);
+ STB0899_SETFIELD_VAL(CRL_NOM_FREQ, reg, offsetfreq);
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_NOM_FREQ, STB0899_OFF0_CRL_NOM_FREQ, reg);
+
+ stb0899_dvbs2_reacquire(state);
+ internal->status = stb0899_dvbs2_get_fec_status(state, searchTime);
+ i++;
+ }
+ }
+/*
+ if (pParams->DVBS2State == FE_DVBS2_FEC_LOCKED)
+ pParams->IQLocked = !iqSpectrum;
+*/
+ }
+ }
+ if (internal->status == DVBS2_FEC_LOCK) {
+ dprintk(state->verbose, FE_DEBUG, 1, "----------------> DVB-S2 FEC Lock !");
+ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_STAT2);
+ modcod = STB0899_GETFIELD(UWP_DECODE_MOD, reg) >> 2;
+ pilots = STB0899_GETFIELD(UWP_DECODE_MOD, reg) & 0x01;
+
+ if ((((10 * internal->master_clk) / (internal->srate / 10)) <= 410) &&
+ (INRANGE(STB0899_QPSK_23, modcod, STB0899_QPSK_910)) &&
+ (pilots == 1)) {
+
+ stb0899_dvbs2_init_csm(state, pilots, modcod);
+ /* Wait for UWP,CSM and data LOCK 20ms max */
+ internal->status = stb0899_dvbs2_get_fec_status(state, FecLockTime);
+
+ i = 0;
+ while ((internal->status != DVBS2_FEC_LOCK) && (i < 3)) {
+ csm1 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL1);
+ STB0899_SETFIELD_VAL(CSM_TWO_PASS, csm1, 1);
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, csm1);
+ csm1 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL1);
+ STB0899_SETFIELD_VAL(CSM_TWO_PASS, csm1, 0);
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, csm1);
+
+ internal->status = stb0899_dvbs2_get_fec_status(state, FecLockTime);
+ i++;
+ }
+ }
+
+ if ((((10 * internal->master_clk) / (internal->srate / 10)) <= 410) &&
+ (INRANGE(STB0899_QPSK_12, modcod, STB0899_QPSK_35)) &&
+ (pilots == 1)) {
+
+ /* Equalizer Disable update */
+ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, EQ_CNTRL);
+ STB0899_SETFIELD_VAL(EQ_DISABLE_UPDATE, reg, 1);
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQ_CNTRL, STB0899_OFF0_EQ_CNTRL, reg);
+ }
+
+ /* slow down the Equalizer once locked */
+ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, EQ_CNTRL);
+ STB0899_SETFIELD_VAL(EQ_SHIFT, reg, 0x02);
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQ_CNTRL, STB0899_OFF0_EQ_CNTRL, reg);
+
+ /* Store signal parameters */
+ offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ);
+
+ offsetfreq = offsetfreq / ((1 << 30) / 1000);
+ offsetfreq *= (internal->master_clk / 1000000);
+ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CNTRL2);
+ if (STB0899_GETFIELD(SPECTRUM_INVERT, reg))
+ offsetfreq *= -1;
+
+ internal->freq = internal->freq - offsetfreq;
+ internal->srate = stb0899_dvbs2_get_srate(state);
+
+ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_STAT2);
+ internal->modcod = STB0899_GETFIELD(UWP_DECODE_MOD, reg) >> 2;
+ internal->pilots = STB0899_GETFIELD(UWP_DECODE_MOD, reg) & 0x01;
+ internal->frame_length = (STB0899_GETFIELD(UWP_DECODE_MOD, reg) >> 1) & 0x01;
+
+ /* Set IF AGC to tracking */
+ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_CNTRL);
+ STB0899_SETFIELD_VAL(IF_LOOP_GAIN, reg, 3);
+
+ /* if QPSK 1/2,QPSK 3/5 or QPSK 2/3 set IF AGC reference to 16 otherwise 32*/
+ if (INRANGE(STB0899_QPSK_12, internal->modcod, STB0899_QPSK_23))
+ STB0899_SETFIELD_VAL(IF_AGC_REF, reg, 16);
+
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_IF_AGC_CNTRL, STB0899_OFF0_IF_AGC_CNTRL, reg);
+
+ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_CNTRL2);
+ STB0899_SETFIELD_VAL(IF_AGC_DUMP_PER, reg, 7);
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_IF_AGC_CNTRL2, STB0899_OFF0_IF_AGC_CNTRL2, reg);
+ }
+
+ /* Release Stream Merger Reset */
+ reg = stb0899_read_reg(state, STB0899_TSTRES);
+ STB0899_SETFIELD_VAL(FRESRS, reg, 0);
+ stb0899_write_reg(state, STB0899_TSTRES, reg);
+
+ return internal->status;
+}
diff --git a/linux/drivers/media/dvb/frontends/stb0899_cfg.h b/linux/drivers/media/dvb/frontends/stb0899_cfg.h
new file mode 100644
index 000000000..1c860e469
--- /dev/null
+++ b/linux/drivers/media/dvb/frontends/stb0899_cfg.h
@@ -0,0 +1,421 @@
+/*
+ STB0899 Multistandard Frontend driver
+ Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+ Copyright (C) ST Microelectronics
+
+ 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 __STB0899_CFG_H
+#define __STB0899_CFG_H
+
+static const struct stb0899_s2_reg stb0899_s2_init_2[] = {
+
+ { STB0899_OFF0_DMD_STATUS , STB0899_BASE_DMD_STATUS , 0x00000103 }, /* DMDSTATUS */
+ { STB0899_OFF0_CRL_FREQ , STB0899_BASE_CRL_FREQ , 0x3ed1da56 }, /* CRLFREQ */
+ { STB0899_OFF0_BTR_FREQ , STB0899_BASE_BTR_FREQ , 0x00004000 }, /* BTRFREQ */
+ { STB0899_OFF0_IF_AGC_GAIN , STB0899_BASE_IF_AGC_GAIN , 0x00002ade }, /* IFAGCGAIN */
+ { STB0899_OFF0_BB_AGC_GAIN , STB0899_BASE_BB_AGC_GAIN , 0x000001bc }, /* BBAGCGAIN */
+ { STB0899_OFF0_DC_OFFSET , STB0899_BASE_DC_OFFSET , 0x00000200 }, /* DCOFFSET */
+ { STB0899_OFF0_DMD_CNTRL , STB0899_BASE_DMD_CNTRL , 0x0000000f }, /* DMDCNTRL */
+
+ { STB0899_OFF0_IF_AGC_CNTRL , STB0899_BASE_IF_AGC_CNTRL , 0x03fb4a20 }, /* IFAGCCNTRL */
+ { STB0899_OFF0_BB_AGC_CNTRL , STB0899_BASE_BB_AGC_CNTRL , 0x00200c97 }, /* BBAGCCNTRL */
+
+ { STB0899_OFF0_CRL_CNTRL , STB0899_BASE_CRL_CNTRL , 0x00000016 }, /* CRLCNTRL */
+ { STB0899_OFF0_CRL_PHS_INIT , STB0899_BASE_CRL_PHS_INIT , 0x00000000 }, /* CRLPHSINIT */
+ { STB0899_OFF0_CRL_FREQ_INIT , STB0899_BASE_CRL_FREQ_INIT , 0x00000000 }, /* CRLFREQINIT */
+ { STB0899_OFF0_CRL_LOOP_GAIN , STB0899_BASE_CRL_LOOP_GAIN , 0x00000000 }, /* CRLLOOPGAIN */
+ { STB0899_OFF0_CRL_NOM_FREQ , STB0899_BASE_CRL_NOM_FREQ , 0x3ed097b6 }, /* CRLNOMFREQ */
+ { STB0899_OFF0_CRL_SWP_RATE , STB0899_BASE_CRL_SWP_RATE , 0x00000000 }, /* CRLSWPRATE */
+ { STB0899_OFF0_CRL_MAX_SWP , STB0899_BASE_CRL_MAX_SWP , 0x00000000 }, /* CRLMAXSWP */
+ { STB0899_OFF0_CRL_LK_CNTRL , STB0899_BASE_CRL_LK_CNTRL , 0x0f6cdc01 }, /* CRLLKCNTRL */
+ { STB0899_OFF0_DECIM_CNTRL , STB0899_BASE_DECIM_CNTRL , 0x00000000 }, /* DECIMCNTRL */
+ { STB0899_OFF0_BTR_CNTRL , STB0899_BASE_BTR_CNTRL , 0x00003993 }, /* BTRCNTRL */
+ { STB0899_OFF0_BTR_LOOP_GAIN , STB0899_BASE_BTR_LOOP_GAIN , 0x000d3c6f }, /* BTRLOOPGAIN */
+ { STB0899_OFF0_BTR_PHS_INIT , STB0899_BASE_BTR_PHS_INIT , 0x00000000 }, /* BTRPHSINIT */
+ { STB0899_OFF0_BTR_FREQ_INIT , STB0899_BASE_BTR_FREQ_INIT , 0x00000000 }, /* BTRFREQINIT */
+ { STB0899_OFF0_BTR_NOM_FREQ , STB0899_BASE_BTR_NOM_FREQ , 0x0238e38e }, /* BTRNOMFREQ */
+ { STB0899_OFF0_BTR_LK_CNTRL , STB0899_BASE_BTR_LK_CNTRL , 0x00000000 }, /* BTRLKCNTRL */
+ { STB0899_OFF0_DECN_CNTRL , STB0899_BASE_DECN_CNTRL , 0x00000000 }, /* DECNCNTRL */
+ { STB0899_OFF0_TP_CNTRL , STB0899_BASE_TP_CNTRL , 0x00000000 }, /* TPCNTRL */
+ { STB0899_OFF0_TP_BUF_STATUS , STB0899_BASE_TP_BUF_STATUS , 0x00000000 }, /* TPBUFSTATUS */
+ { STB0899_OFF0_DC_ESTIM , STB0899_BASE_DC_ESTIM , 0x00000000 }, /* DCESTIM */
+ { STB0899_OFF0_FLL_CNTRL , STB0899_BASE_FLL_CNTRL , 0x00000000 }, /* FLLCNTRL */
+ { STB0899_OFF0_FLL_FREQ_WD , STB0899_BASE_FLL_FREQ_WD , 0x40070000 }, /* FLLFREQWD */
+ { STB0899_OFF0_ANTI_ALIAS_SEL , STB0899_BASE_ANTI_ALIAS_SEL , 0x00000001 }, /* ANTIALIASSEL */
+ { STB0899_OFF0_RRC_ALPHA , STB0899_BASE_RRC_ALPHA , 0x00000002 }, /* RRCALPHA */
+ { STB0899_OFF0_DC_ADAPT_LSHFT , STB0899_BASE_DC_ADAPT_LSHFT , 0x00000000 }, /* DCADAPTISHFT */
+ { STB0899_OFF0_IMB_OFFSET , STB0899_BASE_IMB_OFFSET , 0x0000fe01 }, /* IMBOFFSET */
+ { STB0899_OFF0_IMB_ESTIMATE , STB0899_BASE_IMB_ESTIMATE , 0x00000000 }, /* IMBESTIMATE */
+ { STB0899_OFF0_IMB_CNTRL , STB0899_BASE_IMB_CNTRL , 0x00000001 }, /* IMBCNTRL */
+ { STB0899_OFF0_IF_AGC_CNTRL2 , STB0899_BASE_IF_AGC_CNTRL2 , 0x00005007 }, /* IFAGCCNTRL2 */
+ { STB0899_OFF0_DMD_CNTRL2 , STB0899_BASE_DMD_CNTRL2 , 0x00000002 }, /* DMDCNTRL2 */
+ { STB0899_OFF0_TP_BUFFER , STB0899_BASE_TP_BUFFER , 0x00000000 }, /* TPBUFFER */
+ { STB0899_OFF0_TP_BUFFER1 , STB0899_BASE_TP_BUFFER1 , 0x00000000 }, /* TPBUFFER1 */
+ { STB0899_OFF0_TP_BUFFER2 , STB0899_BASE_TP_BUFFER2 , 0x00000000 }, /* TPBUFFER2 */
+ { STB0899_OFF0_TP_BUFFER3 , STB0899_BASE_TP_BUFFER3 , 0x00000000 }, /* TPBUFFER3 */
+ { STB0899_OFF0_TP_BUFFER4 , STB0899_BASE_TP_BUFFER4 , 0x00000000 }, /* TPBUFFER4 */
+ { STB0899_OFF0_TP_BUFFER5 , STB0899_BASE_TP_BUFFER5 , 0x00000000 }, /* TPBUFFER5 */
+ { STB0899_OFF0_TP_BUFFER6 , STB0899_BASE_TP_BUFFER6 , 0x00000000 }, /* TPBUFFER6 */
+ { STB0899_OFF0_TP_BUFFER7 , STB0899_BASE_TP_BUFFER7 , 0x00000000 }, /* TPBUFFER7 */
+ { STB0899_OFF0_TP_BUFFER8 , STB0899_BASE_TP_BUFFER8 , 0x00000000 }, /* TPBUFFER8 */
+ { STB0899_OFF0_TP_BUFFER9 , STB0899_BASE_TP_BUFFER9 , 0x00000000 }, /* TPBUFFER9 */
+ { STB0899_OFF0_TP_BUFFER10 , STB0899_BASE_TP_BUFFER10 , 0x00000000 }, /* TPBUFFER10 */
+ { STB0899_OFF0_TP_BUFFER11 , STB0899_BASE_TP_BUFFER11 , 0x00000000 }, /* TPBUFFER11 */
+ { STB0899_OFF0_TP_BUFFER12 , STB0899_BASE_TP_BUFFER12 , 0x00000000 }, /* TPBUFFER12 */
+ { STB0899_OFF0_TP_BUFFER13 , STB0899_BASE_TP_BUFFER13 , 0x00000000 }, /* TPBUFFER13 */
+ { STB0899_OFF0_TP_BUFFER14 , STB0899_BASE_TP_BUFFER14 , 0x00000000 }, /* TPBUFFER14 */
+ { STB0899_OFF0_TP_BUFFER15 , STB0899_BASE_TP_BUFFER15 , 0x00000000 }, /* TPBUFFER15 */
+ { STB0899_OFF0_TP_BUFFER16 , STB0899_BASE_TP_BUFFER16 , 0x0000ff00 }, /* TPBUFFER16 */
+ { STB0899_OFF0_TP_BUFFER17 , STB0899_BASE_TP_BUFFER17 , 0x00000100 }, /* TPBUFFER17 */
+ { STB0899_OFF0_TP_BUFFER18 , STB0899_BASE_TP_BUFFER18 , 0x0000fe01 }, /* TPBUFFER18 */
+ { STB0899_OFF0_TP_BUFFER19 , STB0899_BASE_TP_BUFFER19 , 0x000004fe }, /* TPBUFFER19 */
+ { STB0899_OFF0_TP_BUFFER20 , STB0899_BASE_TP_BUFFER20 , 0x0000cfe7 }, /* TPBUFFER20 */
+ { STB0899_OFF0_TP_BUFFER21 , STB0899_BASE_TP_BUFFER21 , 0x0000bec6 }, /* TPBUFFER21 */
+ { STB0899_OFF0_TP_BUFFER22 , STB0899_BASE_TP_BUFFER22 , 0x0000c2bf }, /* TPBUFFER22 */
+ { STB0899_OFF0_TP_BUFFER23 , STB0899_BASE_TP_BUFFER23 , 0x0000c1c1 }, /* TPBUFFER23 */
+ { STB0899_OFF0_TP_BUFFER24 , STB0899_BASE_TP_BUFFER24 , 0x0000c1c1 }, /* TPBUFFER24 */
+ { STB0899_OFF0_TP_BUFFER25 , STB0899_BASE_TP_BUFFER25 , 0x0000c1c1 }, /* TPBUFFER25 */
+ { STB0899_OFF0_TP_BUFFER26 , STB0899_BASE_TP_BUFFER26 , 0x0000c1c1 }, /* TPBUFFER26 */
+ { STB0899_OFF0_TP_BUFFER27 , STB0899_BASE_TP_BUFFER27 , 0x0000c1c0 }, /* TPBUFFER27 */
+ { STB0899_OFF0_TP_BUFFER28 , STB0899_BASE_TP_BUFFER28 , 0x0000c0c0 }, /* TPBUFFER28 */
+ { STB0899_OFF0_TP_BUFFER29 , STB0899_BASE_TP_BUFFER29 , 0x0000c1c1 }, /* TPBUFFER29 */
+ { STB0899_OFF0_TP_BUFFER30 , STB0899_BASE_TP_BUFFER30 , 0x0000c1c1 }, /* TPBUFFER30 */
+ { STB0899_OFF0_TP_BUFFER31 , STB0899_BASE_TP_BUFFER31 , 0x0000c0c1 }, /* TPBUFFER31 */
+ { STB0899_OFF0_TP_BUFFER32 , STB0899_BASE_TP_BUFFER32 , 0x0000c0c1 }, /* TPBUFFER32 */
+ { STB0899_OFF0_TP_BUFFER33 , STB0899_BASE_TP_BUFFER33 , 0x0000c1c1 }, /* TPBUFFER33 */
+ { STB0899_OFF0_TP_BUFFER34 , STB0899_BASE_TP_BUFFER34 , 0x0000c1c1 }, /* TPBUFFER34 */
+ { STB0899_OFF0_TP_BUFFER35 , STB0899_BASE_TP_BUFFER35 , 0x0000c0c1 }, /* TPBUFFER35 */
+ { STB0899_OFF0_TP_BUFFER36 , STB0899_BASE_TP_BUFFER36 , 0x0000c1c1 }, /* TPBUFFER36 */
+ { STB0899_OFF0_TP_BUFFER37 , STB0899_BASE_TP_BUFFER37 , 0x0000c0c1 }, /* TPBUFFER37 */
+ { STB0899_OFF0_TP_BUFFER38 , STB0899_BASE_TP_BUFFER38 , 0x0000c1c1 }, /* TPBUFFER38 */
+ { STB0899_OFF0_TP_BUFFER39 , STB0899_BASE_TP_BUFFER39 , 0x0000c0c0 }, /* TPBUFFER39 */
+ { STB0899_OFF0_TP_BUFFER40 , STB0899_BASE_TP_BUFFER40 , 0x0000c1c0 }, /* TPBUFFER40 */
+ { STB0899_OFF0_TP_BUFFER41 , STB0899_BASE_TP_BUFFER41 , 0x0000c1c1 }, /* TPBUFFER41 */
+ { STB0899_OFF0_TP_BUFFER42 , STB0899_BASE_TP_BUFFER42 , 0x0000c0c0 }, /* TPBUFFER42 */
+ { STB0899_OFF0_TP_BUFFER43 , STB0899_BASE_TP_BUFFER43 , 0x0000c1c0 }, /* TPBUFFER43 */
+ { STB0899_OFF0_TP_BUFFER44 , STB0899_BASE_TP_BUFFER44 , 0x0000c0c1 }, /* TPBUFFER44 */
+ { STB0899_OFF0_TP_BUFFER45 , STB0899_BASE_TP_BUFFER45 , 0x0000c1be }, /* TPBUFFER45 */
+ { STB0899_OFF0_TP_BUFFER46 , STB0899_BASE_TP_BUFFER46 , 0x0000c1c9 }, /* TPBUFFER46 */
+ { STB0899_OFF0_TP_BUFFER47 , STB0899_BASE_TP_BUFFER47 , 0x0000c0da }, /* TPBUFFER47 */
+ { STB0899_OFF0_TP_BUFFER48 , STB0899_BASE_TP_BUFFER48 , 0x0000c0ba }, /* TPBUFFER48 */
+ { STB0899_OFF0_TP_BUFFER49 , STB0899_BASE_TP_BUFFER49 , 0x0000c1c4 }, /* TPBUFFER49 */
+ { STB0899_OFF0_TP_BUFFER50 , STB0899_BASE_TP_BUFFER50 , 0x0000c1bf }, /* TPBUFFER50 */
+ { STB0899_OFF0_TP_BUFFER51 , STB0899_BASE_TP_BUFFER51 , 0x0000c0c1 }, /* TPBUFFER51 */
+ { STB0899_OFF0_TP_BUFFER52 , STB0899_BASE_TP_BUFFER52 , 0x0000c1c0 }, /* TPBUFFER52 */
+ { STB0899_OFF0_TP_BUFFER53 , STB0899_BASE_TP_BUFFER53 , 0x0000c0c1 }, /* TPBUFFER53 */
+ { STB0899_OFF0_TP_BUFFER54 , STB0899_BASE_TP_BUFFER54 , 0x0000c1c1 }, /* TPBUFFER54 */
+ { STB0899_OFF0_TP_BUFFER55 , STB0899_BASE_TP_BUFFER55 , 0x0000c1c1 }, /* TPBUFFER55 */
+ { STB0899_OFF0_TP_BUFFER56 , STB0899_BASE_TP_BUFFER56 , 0x0000c1c1 }, /* TPBUFFER56 */
+ { STB0899_OFF0_TP_BUFFER57 , STB0899_BASE_TP_BUFFER57 , 0x0000c1c1 }, /* TPBUFFER57 */
+ { STB0899_OFF0_TP_BUFFER58 , STB0899_BASE_TP_BUFFER58 , 0x0000c1c1 }, /* TPBUFFER58 */
+ { STB0899_OFF0_TP_BUFFER59 , STB0899_BASE_TP_BUFFER59 , 0x0000c1c1 }, /* TPBUFFER59 */
+ { STB0899_OFF0_TP_BUFFER60 , STB0899_BASE_TP_BUFFER60 , 0x0000c1c1 }, /* TPBUFFER60 */
+ { STB0899_OFF0_TP_BUFFER61 , STB0899_BASE_TP_BUFFER61 , 0x0000c1c1 }, /* TPBUFFER61 */
+ { STB0899_OFF0_TP_BUFFER62 , STB0899_BASE_TP_BUFFER62 , 0x0000c1c1 }, /* TPBUFFER62 */
+ { STB0899_OFF0_TP_BUFFER63 , STB0899_BASE_TP_BUFFER63 , 0x0000c1c0 }, /* TPBUFFER63 */
+ { STB0899_OFF0_RESET_CNTRL , STB0899_BASE_RESET_CNTRL , 0x00000001 }, /* RESETCNTRL */
+ { STB0899_OFF0_ACM_ENABLE , STB0899_BASE_ACM_ENABLE , 0x00005654 }, /* ACMENABLE */
+ { STB0899_OFF0_DESCR_CNTRL , STB0899_BASE_DESCR_CNTRL , 0x00000000 }, /* DESCRCNTRL */
+ { STB0899_OFF0_CSM_CNTRL1 , STB0899_BASE_CSM_CNTRL1 , 0x00020019 }, /* CSMCNTRL1 */
+ { STB0899_OFF0_CSM_CNTRL2 , STB0899_BASE_CSM_CNTRL2 , 0x004b3237 }, /* CSMCNTRL2 */
+ { STB0899_OFF0_CSM_CNTRL3 , STB0899_BASE_CSM_CNTRL3 , 0x0003dd17 }, /* CSMCNTRL3 */
+ { STB0899_OFF0_CSM_CNTRL4 , STB0899_BASE_CSM_CNTRL4 , 0x00008008 }, /* CSMCNTRL4 */
+ { STB0899_OFF0_UWP_CNTRL1 , STB0899_BASE_UWP_CNTRL1 , 0x002a3106 }, /* UWPCNTRL1 */
+ { STB0899_OFF0_UWP_CNTRL2 , STB0899_BASE_UWP_CNTRL2 , 0x0006140a }, /* UWPCNTRL2 */
+ { STB0899_OFF0_UWP_STAT1 , STB0899_BASE_UWP_STAT1 , 0x00008000 }, /* UWPSTAT1 */
+ { STB0899_OFF0_UWP_STAT2 , STB0899_BASE_UWP_STAT2 , 0x00000000 }, /* UWPSTAT2 */
+ { STB0899_OFF0_DMD_STAT2 , STB0899_BASE_DMD_STAT2 , 0x00000000 }, /* DMDSTAT2 */
+ { STB0899_OFF0_FREQ_ADJ_SCALE , STB0899_BASE_FREQ_ADJ_SCALE , 0x00000471 }, /* FREQADJSCALE */
+ { STB0899_OFF0_UWP_CNTRL3 , STB0899_BASE_UWP_CNTRL3 , 0x017b0465 }, /* UWPCNTRL3 */
+ { STB0899_OFF0_SYM_CLK_SEL , STB0899_BASE_SYM_CLK_SEL , 0x00000002 }, /* SYMCLKSEL */
+ { STB0899_OFF0_SOF_SRCH_TO , STB0899_BASE_SOF_SRCH_TO , 0x00196464 }, /* SOFSRCHTO */
+ { STB0899_OFF0_ACQ_CNTRL1 , STB0899_BASE_ACQ_CNTRL1 , 0x00000603 }, /* ACQCNTRL1 */
+ { STB0899_OFF0_ACQ_CNTRL2 , STB0899_BASE_ACQ_CNTRL2 , 0x02046666 }, /* ACQCNTRL2 */
+ { STB0899_OFF0_ACQ_CNTRL3 , STB0899_BASE_ACQ_CNTRL3 , 0x10046583 }, /* ACQCNTRL3 */
+ { STB0899_OFF0_FE_SETTLE , STB0899_BASE_FE_SETTLE , 0x00010404 }, /* FESETTLE */
+ { STB0899_OFF0_AC_DWELL , STB0899_BASE_AC_DWELL , 0x0002aa8a }, /* ACDWELL */
+ { STB0899_OFF0_ACQUIRE_TRIG , STB0899_BASE_ACQUIRE_TRIG , 0x00000000 }, /* ACQUIRETRIG */
+ { STB0899_OFF0_LOCK_LOST , STB0899_BASE_LOCK_LOST , 0x00000001 }, /* LOCKLOST */
+ { STB0899_OFF0_ACQ_STAT1 , STB0899_BASE_ACQ_STAT1 , 0x00000500 }, /* ACQSTAT1 */
+ { STB0899_OFF0_ACQ_TIMEOUT , STB0899_BASE_ACQ_TIMEOUT , 0x0028a0a0 }, /* ACQTIMEOUT */
+ { STB0899_OFF0_ACQ_TIME , STB0899_BASE_ACQ_TIME , 0x00000000 }, /* ACQTIME */
+ { STB0899_OFF0_FINAL_AGC_CNTRL , STB0899_BASE_FINAL_AGC_CNTRL , 0x00800c17 }, /* FINALAGCCNTRL*/
+ { STB0899_OFF0_FINAL_AGC_GAIN , STB0899_BASE_FINAL_AGC_GAIN , 0x00000000 }, /* FINALAGCCGAIN*/
+ { STB0899_OFF0_EQUALIZER_INIT , STB0899_BASE_EQUALIZER_INIT , 0x00000000 }, /* EQUILIZERINIT*/
+ { STB0899_OFF0_EQ_CNTRL , STB0899_BASE_EQ_CNTRL , 0x00054802 }, /* EQCNTL */
+ { STB0899_OFF0_EQ_I_INIT_COEFF_0, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 }, /* EQIINITCOEFF0 */
+ { STB0899_OFF1_EQ_I_INIT_COEFF_1, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 }, /* EQIINITCOEFF1 */
+ { STB0899_OFF2_EQ_I_INIT_COEFF_2, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 }, /* EQIINITCOEFF2 */
+ { STB0899_OFF3_EQ_I_INIT_COEFF_3, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 }, /* EQIINITCOEFF3 */
+ { STB0899_OFF4_EQ_I_INIT_COEFF_4, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 }, /* EQIINITCOEFF4 */
+ { STB0899_OFF5_EQ_I_INIT_COEFF_5, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000400 }, /* EQIINITCOEFF5 */
+ { STB0899_OFF6_EQ_I_INIT_COEFF_6, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 }, /* EQIINITCOEFF6 */
+ { STB0899_OFF7_EQ_I_INIT_COEFF_7, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 }, /* EQIINITCOEFF7 */
+ { STB0899_OFF8_EQ_I_INIT_COEFF_8, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 }, /* EQIINITCOEFF8 */
+ { STB0899_OFF9_EQ_I_INIT_COEFF_9, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 }, /* EQIINITCOEFF9 */
+ { STB0899_OFFa_EQ_I_INIT_COEFF_10,STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 }, /* EQIINITCOEFF10*/
+ { STB0899_OFF0_EQ_Q_INIT_COEFF_0, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 }, /* EQQINITCOEFF0 */
+ { STB0899_OFF1_EQ_Q_INIT_COEFF_1, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 }, /* EQQINITCOEFF1 */
+ { STB0899_OFF2_EQ_Q_INIT_COEFF_2, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 }, /* EQQINITCOEFF2 */
+ { STB0899_OFF3_EQ_Q_INIT_COEFF_3, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 }, /* EQQINITCOEFF3 */
+ { STB0899_OFF4_EQ_Q_INIT_COEFF_4, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 }, /* EQQINITCOEFF4 */
+ { STB0899_OFF5_EQ_Q_INIT_COEFF_5, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 }, /* EQQINITCOEFF5 */
+ { STB0899_OFF6_EQ_Q_INIT_COEFF_6, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 }, /* EQQINITCOEFF6 */
+ { STB0899_OFF7_EQ_Q_INIT_COEFF_7, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 }, /* EQQINITCOEFF7 */
+ { STB0899_OFF8_EQ_Q_INIT_COEFF_8, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 }, /* EQQINITCOEFF8 */
+ { STB0899_OFF9_EQ_Q_INIT_COEFF_9, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 }, /* EQQINITCOEFF9 */
+ { STB0899_OFFa_EQ_Q_INIT_COEFF_10,STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 }, /* EQQINITCOEFF10*/
+ { STB0899_OFF0_EQ_I_OUT_COEFF_0 , STB0899_BASE_EQ_I_OUT_COEFF_N , 0x00000000 }, /* EQICOEFFSOUT0 */
+ { STB0899_OFF1_EQ_I_OUT_COEFF_1 , STB0899_BASE_EQ_I_OUT_COEFF_N , 0x00000000 }, /* EQICOEFFSOUT1 */
+ { STB0899_OFF2_EQ_I_OUT_COEFF_2 , STB0899_BASE_EQ_I_OUT_COEFF_N , 0x00000000 }, /* EQICOEFFSOUT2 */
+ { STB0899_OFF3_EQ_I_OUT_COEFF_3 , STB0899_BASE_EQ_I_OUT_COEFF_N , 0x00000000 }, /* EQICOEFFSOUT3 */
+ { STB0899_OFF4_EQ_I_OUT_COEFF_4 , STB0899_BASE_EQ_I_OUT_COEFF_N , 0x00000000 }, /* EQICOEFFSOUT4 */
+ { STB0899_OFF5_EQ_I_OUT_COEFF_5 , STB0899_BASE_EQ_I_OUT_COEFF_N , 0x00000000 }, /* EQICOEFFSOUT5 */
+ { STB0899_OFF6_EQ_I_OUT_COEFF_6 , STB0899_BASE_EQ_I_OUT_COEFF_N , 0x00000000 }, /* EQICOEFFSOUT6 */
+ { STB0899_OFF7_EQ_I_OUT_COEFF_7 , STB0899_BASE_EQ_I_OUT_COEFF_N , 0x00000000 }, /* EQICOEFFSOUT7 */
+ { STB0899_OFF8_EQ_I_OUT_COEFF_8 , STB0899_BASE_EQ_I_OUT_COEFF_N , 0x00000000 }, /* EQICOEFFSOUT8 */
+ { STB0899_OFF9_EQ_I_OUT_COEFF_9 , STB0899_BASE_EQ_I_OUT_COEFF_N , 0x00000000 }, /* EQICOEFFSOUT9 */
+ { STB0899_OFFa_EQ_I_OUT_COEFF_10,STB0899_BASE_EQ_I_OUT_COEFF_N , 0x00000000 }, /* EQICOEFFSOUT10*/
+ { STB0899_OFF0_EQ_Q_OUT_COEFF_0 , STB0899_BASE_EQ_Q_OUT_COEFF_N , 0x00000000 }, /* EQQCOEFFSOUT0 */
+ { STB0899_OFF1_EQ_Q_OUT_COEFF_1 , STB0899_BASE_EQ_Q_OUT_COEFF_N , 0x00000000 }, /* EQQCOEFFSOUT1 */
+ { STB0899_OFF2_EQ_Q_OUT_COEFF_2 , STB0899_BASE_EQ_Q_OUT_COEFF_N , 0x00000000 }, /* EQQCOEFFSOUT2 */
+ { STB0899_OFF3_EQ_Q_OUT_COEFF_3 , STB0899_BASE_EQ_Q_OUT_COEFF_N , 0x00000000 }, /* EQQCOEFFSOUT3 */
+ { STB0899_OFF4_EQ_Q_OUT_COEFF_4 , STB0899_BASE_EQ_Q_OUT_COEFF_N , 0x00000000 }, /* EQQCOEFFSOUT4 */
+ { STB0899_OFF5_EQ_Q_OUT_COEFF_5 , STB0899_BASE_EQ_Q_OUT_COEFF_N , 0x00000000 }, /* EQQCOEFFSOUT5 */
+ { STB0899_OFF6_EQ_Q_OUT_COEFF_6 , STB0899_BASE_EQ_Q_OUT_COEFF_N , 0x00000000 }, /* EQQCOEFFSOUT6 */
+ { STB0899_OFF7_EQ_Q_OUT_COEFF_7 , STB0899_BASE_EQ_Q_OUT_COEFF_N , 0x00000000 }, /* EQQCOEFFSOUT7 */
+ { STB0899_OFF8_EQ_Q_OUT_COEFF_8 , STB0899_BASE_EQ_Q_OUT_COEFF_N , 0x00000000 }, /* EQQCOEFFSOUT8 */
+ { STB0899_OFF9_EQ_Q_OUT_COEFF_9 , STB0899_BASE_EQ_Q_OUT_COEFF_N , 0x00000000 }, /* EQQCOEFFSOUT9 */
+ { STB0899_OFFa_EQ_Q_OUT_COEFF_10, STB0899_BASE_EQ_Q_OUT_COEFF_N , 0x00000000 }, /* EQQCOEFFSOUT10*/
+ { 0xffff , 0xffffffff , 0xffffffff },
+};
+#if 0
+static const struct stb0899_s1_reg stb0899_s1_init_3[] = {
+ { STB0899_DEMOD , 0x00 },
+ { STB0899_RCOMPC , 0xc9 },
+ { STB0899_AGC1CN , 0x01 },
+ { STB0899_AGC1REF , 0x10 },
+ { STB0899_RTC , 0x23 },
+ { STB0899_TMGCFG , 0x4e },
+ { STB0899_AGC2REF , 0x34 },
+ { STB0899_TLSR , 0x84 },
+ { STB0899_CFD , 0xf7 },
+ { STB0899_ACLC , 0x87 },
+ { STB0899_BCLC , 0x94 },
+ { STB0899_EQON , 0x41 },
+ { STB0899_LDT , 0xf1 },
+ { STB0899_LDT2 , 0xe3 },
+ { STB0899_EQUALREF , 0xb4 },
+ { STB0899_TMGRAMP , 0x10 },
+ { STB0899_TMGTHD , 0x30 },
+ { STB0899_IDCCOMP , 0xfd },
+ { STB0899_QDCCOMP , 0xff },
+ { STB0899_POWERI , 0x0c },
+ { STB0899_POWERQ , 0x0f },
+ { STB0899_RCOMP , 0x6c },
+ { STB0899_AGCIQIN , 0x80 },
+ { STB0899_AGC2I1 , 0x06 },
+ { STB0899_AGC2I2 , 0x00 },
+ { STB0899_TLIR , 0x30 },
+ { STB0899_RTF , 0x7f },
+ { STB0899_DSTATUS , 0x00 },
+ { STB0899_LDI , 0xbc },
+ { STB0899_CFRM , 0xea },
+ { STB0899_CFRL , 0x31 },
+ { STB0899_NIRM , 0x2b },
+ { STB0899_NIRL , 0x80 },
+ { STB0899_ISYMB , 0x1d },
+ { STB0899_QSYMB , 0xa6 },
+ { STB0899_SFRH , 0x2f },
+ { STB0899_SFRM , 0x68 },
+ { STB0899_SFRL , 0x40 },
+ { STB0899_SFRUPH , 0x2f },
+ { STB0899_SFRUPM , 0x68 },
+ { STB0899_SFRUPL , 0x40 },
+ { STB0899_EQUAI1 , 0x02 },
+ { STB0899_EQUAQ1 , 0xff },
+ { STB0899_EQUAI2 , 0x04 },
+ { STB0899_EQUAQ2 , 0x05 },
+ { STB0899_EQUAI3 , 0x02 },
+ { STB0899_EQUAQ3 , 0xfd },
+ { STB0899_EQUAI4 , 0x03 },
+ { STB0899_EQUAQ4 , 0x07 },
+ { STB0899_EQUAI5 , 0x08 },
+ { STB0899_EQUAQ5 , 0xf5 },
+ { STB0899_DSTATUS2 , 0x00 },
+ { STB0899_VSTATUS , 0x00 },
+ { STB0899_VERROR , 0x86 },
+ { STB0899_IQSWAP , 0x2a },
+ { STB0899_ECNT1M , 0x00 },
+ { STB0899_ECNT1L , 0x00 },
+ { STB0899_ECNT2M , 0x00 },
+ { STB0899_ECNT2L , 0x00 },
+ { STB0899_ECNT3M , 0x0a },
+ { STB0899_ECNT3L , 0xad },
+ { STB0899_FECAUTO1 , 0x06 },
+ { STB0899_FECM , 0x01 },
+ { STB0899_VTH12 , 0xb0 },
+ { STB0899_VTH23 , 0x7a },
+ { STB0899_VTH34 , 0x58 },
+ { STB0899_VTH56 , 0x38 },
+ { STB0899_VTH67 , 0x34 },
+ { STB0899_VTH78 , 0x24 },
+ { STB0899_PRVIT , 0xff },
+ { STB0899_VITSYNC , 0x19 },
+ { STB0899_RSULC , 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */
+ { STB0899_TSULC , 0x42 },
+ { STB0899_RSLLC , 0x41 },
+ { STB0899_TSLPL , 0x12 },
+ { STB0899_TSCFGH , 0x0c },
+ { STB0899_TSCFGM , 0x00 },
+ { STB0899_TSCFGL , 0x00 },
+ { STB0899_TSOUT , 0x69 }, /* 0x0d for CAM */
+ { STB0899_RSSYNCDEL , 0x00 },
+ { STB0899_TSINHDELH , 0x02 },
+ { STB0899_TSINHDELM , 0x00 },
+ { STB0899_TSINHDELL , 0x00 },
+ { STB0899_TSLLSTKM , 0x1b },
+ { STB0899_TSLLSTKL , 0xb3 },
+ { STB0899_TSULSTKM , 0x00 },
+ { STB0899_TSULSTKL , 0x00 },
+ { STB0899_PCKLENUL , 0xbc },
+ { STB0899_PCKLENLL , 0xcc },
+ { STB0899_RSPCKLEN , 0xbd },
+ { STB0899_TSSTATUS , 0x90 },
+ { STB0899_ERRCTRL1 , 0xb6 },
+ { STB0899_ERRCTRL2 , 0x95 },
+ { STB0899_ERRCTRL3 , 0x8d },
+ { STB0899_DMONMSK1 , 0x27 },
+ { STB0899_DMONMSK0 , 0x03 },
+ { STB0899_DEMAPVIT , 0x5c },
+ { STB0899_PLPARM , 0x19 },
+ { STB0899_PDELCTRL , 0x48 },
+ { STB0899_PDELCTRL2 , 0x00 },
+ { STB0899_BBHCTRL1 , 0x00 },
+ { STB0899_BBHCTRL2 , 0x00 },
+ { STB0899_HYSTTHRESH , 0x77 },
+ { STB0899_MATCSTM , 0x00 },
+ { STB0899_MATCSTL , 0x00 },
+ { STB0899_UPLCSTM , 0x00 },
+ { STB0899_UPLCSTL , 0x00 },
+ { STB0899_DFLCSTM , 0x00 },
+ { STB0899_DFLCSTL , 0x00 },
+ { STB0899_SYNCCST , 0x00 },
+ { STB0899_SYNCDCSTM , 0x00 },
+ { STB0899_SYNCDCSTL , 0x00 },
+ { STB0899_ISI_ENTRY , 0x00 },
+ { STB0899_ISI_BIT_EN , 0x00 },
+ { STB0899_MATSTRM , 0xf0 },
+ { STB0899_MATSTRL , 0x02 },
+ { STB0899_UPLSTRM , 0x45 },
+ { STB0899_UPLSTRL , 0x60 },
+ { STB0899_DFLSTRM , 0xe3 },
+ { STB0899_DFLSTRL , 0x00 },
+ { STB0899_SYNCSTR , 0x47 },
+ { STB0899_SYNCDSTRM , 0x05 },
+ { STB0899_SYNCDSTRL , 0x18 },
+ { STB0899_CFGPDELSTATUS1 , 0x19 },
+ { STB0899_CFGPDELSTATUS2 , 0x2b },
+ { STB0899_BBFERRORM , 0x00 },
+ { STB0899_BBFERRORL , 0x01 },
+ { STB0899_UPKTERRORM , 0x00 },
+ { STB0899_UPKTERRORL , 0x00 },
+ { 0xffff , 0xff },
+};
+#endif
+static const struct stb0899_s2_reg stb0899_s2_init_4[] = {
+ { STB0899_OFF0_BLOCK_LNGTH , STB0899_BASE_BLOCK_LNGTH , 0x00000008 }, /* BLOCKLNGTH */
+ { STB0899_OFF0_ROW_STR , STB0899_BASE_ROW_STR , 0x000000b4 }, /* ROWSTR */
+ { STB0899_OFF0_BN_END_ADDR , STB0899_BASE_BN_END_ADDR , 0x000004b5 }, /* BNANDADDR */
+ { STB0899_OFF0_CN_END_ADDR , STB0899_BASE_CN_END_ADDR , 0x00000b4b }, /* CNANDADDR */
+ { STB0899_OFF0_INFO_LENGTH , STB0899_BASE_INFO_LENGTH , 0x00000078 }, /* INFOLENGTH */
+ { STB0899_OFF0_BOT_ADDR , STB0899_BASE_BOT_ADDR , 0x000001e0 }, /* BOT_ADDR */
+ { STB0899_OFF0_BCH_BLK_LN , STB0899_BASE_BCH_BLK_LN , 0x0000a8c0 }, /* BCHBLKLN */
+ { STB0899_OFF0_BCH_T , STB0899_BASE_BCH_T , 0x0000000c }, /* BCHT */
+ { STB0899_OFF0_CNFG_MODE , STB0899_BASE_CNFG_MODE , 0x00000001 }, /* CNFGMODE */
+ { STB0899_OFF0_LDPC_STAT , STB0899_BASE_LDPC_STAT , 0x0000000d }, /* LDPCSTAT */
+ { STB0899_OFF0_ITER_SCALE , STB0899_BASE_ITER_SCALE , 0x00000040 }, /* ITERSCALE */
+ { STB0899_OFF0_INPUT_MODE , STB0899_BASE_INPUT_MODE , 0x00000000 }, /* INPUTMODE */
+ { STB0899_OFF0_LDPCDECRST , STB0899_BASE_LDPCDECRST , 0x00000000 }, /* LDPCDECRST */
+ { STB0899_OFF0_CLK_PER_BYTE_RW , STB0899_BASE_CLK_PER_BYTE_RW , 0x00000008 }, /* CLKPERBYTE */
+ { STB0899_OFF0_BCH_ERRORS , STB0899_BASE_BCH_ERRORS , 0x00000000 }, /* BCHERRORS */
+ { STB0899_OFF0_LDPC_ERRORS , STB0899_BASE_LDPC_ERRORS , 0x00000000 }, /* LDPCERRORS */
+ { STB0899_OFF0_BCH_MODE , STB0899_BASE_BCH_MODE , 0x00000000 }, /* BCHMODE */
+ { STB0899_OFF0_ERR_ACC_PER , STB0899_BASE_ERR_ACC_PER , 0x00000008 }, /* ERRACCPER */
+ { STB0899_OFF0_BCH_ERR_ACC , STB0899_BASE_BCH_ERR_ACC , 0x00000000 }, /* BCHERRACC */
+ { STB0899_OFF0_FEC_TP_SEL , STB0899_BASE_FEC_TP_SEL , 0x00000000 }, /* FECTPSEL */
+ { 0xffff , 0xffffffff , 0xffffffff },
+};
+
+static const struct stb0899_s1_reg stb0899_s1_init_5[] = {
+ { STB0899_TSTCK , 0x00 },
+ { STB0899_TSTRES , 0x00 },
+ { STB0899_TSTOUT , 0x00 },
+ { STB0899_TSTIN , 0x00 },
+ { STB0899_TSTSYS , 0x00 },
+ { STB0899_TSTCHIP , 0x00 },
+ { STB0899_TSTFREE , 0x00 },
+ { STB0899_TSTI2C , 0x00 },
+ { STB0899_BITSPEEDM , 0x00 },
+ { STB0899_BITSPEEDL , 0x00 },
+ { STB0899_TBUSBIT , 0x00 },
+ { STB0899_TSTDIS , 0x00 },
+ { STB0899_TSTDISRX , 0x00 },
+ { STB0899_TSTJETON , 0x00 },
+ { STB0899_TSTDCADJ , 0x00 },
+ { STB0899_TSTAGC1 , 0x00 },
+ { STB0899_TSTAGC1N , 0x00 },
+ { STB0899_TSTPOLYPH , 0x00 },
+ { STB0899_TSTR , 0x00 },
+ { STB0899_TSTAGC2 , 0x00 },
+ { STB0899_TSTCTL1 , 0x00 },
+ { STB0899_TSTCTL2 , 0x00 },
+ { STB0899_TSTCTL3 , 0x00 },
+ { STB0899_TSTDEMAP , 0x00 },
+ { STB0899_TSTDEMAP2 , 0x00 },
+ { STB0899_TSTDEMMON , 0x00 },
+ { STB0899_TSTRATE , 0x00 },
+ { STB0899_TSTSELOUT , 0x00 },
+ { STB0899_TSYNC , 0x00 },
+ { STB0899_TSTERR , 0x00 },
+ { STB0899_TSTRAM1 , 0x00 },
+ { STB0899_TSTVSELOUT , 0x00 },
+ { STB0899_TSTFORCEIN , 0x00 },
+ { STB0899_TSTRS1 , 0x00 },
+ { STB0899_TSTRS2 , 0x00 },
+ { STB0899_TSTRS3 , 0x00 },
+ { STB0899_GHOSTREG , 0x81 },
+ { 0xffff , 0xff },
+};
+
+#define STB0899_DVBS2_ESNO_AVE 3
+#define STB0899_DVBS2_ESNO_QUANT 32
+#define STB0899_DVBS2_AVFRAMES_COARSE 10
+#define STB0899_DVBS2_AVFRAMES_FINE 20
+#define STB0899_DVBS2_MISS_THRESHOLD 6
+#define STB0899_DVBS2_UWP_THRESHOLD_ACQ 1125
+#define STB0899_DVBS2_UWP_THRESHOLD_TRACK 758
+#define STB0899_DVBS2_UWP_THRESHOLD_SOF 1350
+#define STB0899_DVBS2_SOF_SEARCH_TIMEOUT 1664100
+
+#define STB0899_DVBS2_BTR_NCO_BITS 28
+#define STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET 15
+#define STB0899_DVBS2_CRL_NCO_BITS 30
+#define STB0899_DVBS2_LDPC_MAX_ITER 70
+
+#endif //__STB0899_CFG_H
diff --git a/linux/drivers/media/dvb/frontends/stb0899_drv.c b/linux/drivers/media/dvb/frontends/stb0899_drv.c
new file mode 100644
index 000000000..63c547f31
--- /dev/null
+++ b/linux/drivers/media/dvb/frontends/stb0899_drv.c
@@ -0,0 +1,1979 @@
+/*
+ STB0899 Multistandard Frontend driver
+ Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+ Copyright (C) ST Microelectronics
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include <linux/dvb/frontend.h>
+#include "dvb_frontend.h"
+
+#include "stb0899_drv.h"
+#include "stb0899_priv.h"
+#include "stb0899_reg.h"
+
+static unsigned int verbose = 0;//1;
+module_param(verbose, int, 0644);
+
+/* C/N in dB/10, NIRM/NIRL */
+static const struct stb0899_tab stb0899_cn_tab[] = {
+ { 200, 2600 },
+ { 190, 2700 },
+ { 180, 2860 },
+ { 170, 3020 },
+ { 160, 3210 },
+ { 150, 3440 },
+ { 140, 3710 },
+ { 130, 4010 },
+ { 120, 4360 },
+ { 110, 4740 },
+ { 100, 5190 },
+ { 90, 5670 },
+ { 80, 6200 },
+ { 70, 6770 },
+ { 60, 7360 },
+ { 50, 7970 },
+ { 40, 8250 },
+ { 30, 9000 },
+ { 20, 9450 },
+ { 15, 9600 },
+};
+
+/* DVB-S AGCIQ_VALUE vs. signal level in dBm/10.
+ * As measured, connected to a modulator.
+ * -8.0 to -50.0 dBm directly connected,
+ * -52.0 to -74.8 with extra attenuation.
+ * Cut-off to AGCIQ_VALUE = 0x80 below -74.8dBm.
+ * Crude linear extrapolation below -84.8dBm and above -8.0dBm.
+ */
+static const struct stb0899_tab stb0899_dvbsrf_tab[] = {
+ { -950, -128 },
+ { -748, -94 },
+ { -745, -92 },
+ { -735, -90 },
+ { -720, -87 },
+ { -670, -77 },
+ { -640, -70 },
+ { -610, -62 },
+ { -600, -60 },
+ { -590, -56 },
+ { -560, -41 },
+ { -540, -25 },
+ { -530, -17 },
+ { -520, -11 },
+ { -500, 1 },
+ { -490, 6 },
+ { -480, 10 },
+ { -440, 22 },
+ { -420, 27 },
+ { -400, 31 },
+ { -380, 34 },
+ { -340, 40 },
+ { -320, 43 },
+ { -280, 48 },
+ { -250, 52 },
+ { -230, 55 },
+ { -180, 61 },
+ { -140, 66 },
+ { -90, 73 },
+ { -80, 74 },
+ { 500, 127 }
+};
+
+/* DVB-S2 IF_AGC_GAIN vs. signal level in dBm/10.
+ * As measured, connected to a modulator.
+ * -8.0 to -50.1 dBm directly connected,
+ * -53.0 to -76.6 with extra attenuation.
+ * Cut-off to IF_AGC_GAIN = 0x3fff below -76.6dBm.
+ * Crude linear extrapolation below -76.6dBm and above -8.0dBm.
+ */
+static const struct stb0899_tab stb0899_dvbs2rf_tab[] = {
+ { 700, 0 },
+ { -80, 3217 },
+ { -150, 3893 },
+ { -190, 4217 },
+ { -240, 4621 },
+ { -280, 4945 },
+ { -320, 5273 },
+ { -350, 5545 },
+ { -370, 5741 },
+ { -410, 6147 },
+ { -450, 6671 },
+ { -490, 7413 },
+ { -501, 7665 },
+ { -530, 8767 },
+ { -560, 10219 },
+ { -580, 10939 },
+ { -590, 11518 },
+ { -600, 11723 },
+ { -650, 12659 },
+ { -690, 13219 },
+ { -730, 13645 },
+ { -750, 13909 },
+ { -766, 14153 },
+ { -999, 16383 }
+};
+
+/* DVB-S2 Es/N0 quant in dB/100 vs read value * 100*/
+struct stb0899_tab stb0899_quant_tab[] = {
+ { 0, 0 },
+ { 0, 100 },
+ { 600, 200 },
+ { 950, 299 },
+ { 1200, 398 },
+ { 1400, 501 },
+ { 1560, 603 },
+ { 1690, 700 },
+ { 1810, 804 },
+ { 1910, 902 },
+ { 2000, 1000 },
+ { 2080, 1096 },
+ { 2160, 1202 },
+ { 2230, 1303 },
+ { 2350, 1496 },
+ { 2410, 1603 },
+ { 2460, 1698 },
+ { 2510, 1799 },
+ { 2600, 1995 },
+ { 2650, 2113 },
+ { 2690, 2213 },
+ { 2720, 2291 },
+ { 2760, 2399 },
+ { 2800, 2512 },
+ { 2860, 2692 },
+ { 2930, 2917 },
+ { 2960, 3020 },
+ { 3010, 3199 },
+ { 3040, 3311 },
+ { 3060, 3388 },
+ { 3120, 3631 },
+ { 3190, 3936 },
+ { 3400, 5012 },
+ { 3610, 6383 },
+ { 3800, 7943 },
+ { 4210, 12735 },
+ { 4500, 17783 },
+ { 4690, 22131 },
+ { 4810, 25410 }
+};
+
+/* DVB-S2 Es/N0 estimate in dB/100 vs read value */
+struct stb0899_tab stb0899_est_tab[] = {
+ { 0, 0 },
+ { 0, 1 },
+ { 301, 2 },
+ { 1204, 16 },
+ { 1806, 64 },
+ { 2408, 256 },
+ { 2709, 512 },
+ { 3010, 1023 },
+ { 3311, 2046 },
+ { 3612, 4093 },
+ { 3823, 6653 },
+ { 3913, 8185 },
+ { 4010, 10233 },
+ { 4107, 12794 },
+ { 4214, 16368 },
+ { 4266, 18450 },
+ { 4311, 20464 },
+ { 4353, 22542 },
+ { 4391, 24604 },
+ { 4425, 26607 },
+ { 4457, 28642 },
+ { 4487, 30690 },
+ { 4515, 32734 },
+ { 4612, 40926 },
+ { 4692, 49204 },
+ { 4816, 65464 },
+ { 4913, 81846 },
+ { 4993, 98401 },
+ { 5060, 114815 },
+ { 5118, 131220 },
+ { 5200, 158489 },
+ { 5300, 199526 },
+ { 5400, 251189 },
+ { 5500, 316228 },
+ { 5600, 398107 },
+ { 5720, 524807 },
+ { 5721, 526017 },
+};
+
+int _stb0899_read_reg(struct stb0899_state *state, unsigned int reg)
+{
+ int ret;
+
+ u8 b0[] = { reg >> 8, reg & 0xff };
+ u8 buf;
+
+ struct i2c_msg msg[] = {
+ {
+ .addr = state->config->demod_address,
+ .flags = 0,
+ .buf = b0,
+ .len = 2
+ },{
+ .addr = state->config->demod_address,
+ .flags = I2C_M_RD,
+ .buf = &buf,
+ .len = 1
+ }
+ };
+
+ ret = i2c_transfer(state->i2c, msg, 2);
+ if (ret != 2) {
+ if (ret != -ERESTARTSYS)
+ dprintk(state->verbose, FE_ERROR, 1,
+ "Read error, Reg=[0x%02x], Status=%d",
+ reg, ret);
+
+ return ret < 0 ? ret : -EREMOTEIO;
+ }
+ if (unlikely(*state->verbose >= FE_DEBUGREG))
+ dprintk(state->verbose, FE_ERROR, 1, "Reg=[0x%02x], data=%02x",
+ reg, buf);
+
+ return (unsigned int)buf;
+}
+
+int stb0899_read_reg(struct stb0899_state *state, unsigned int reg)
+{
+ int result;
+
+ result = _stb0899_read_reg(state, reg);
+ /*
+ * Bug ID 9:
+ * access to 0xf2xx/0xf6xx
+ * must be followed by read from 0xf2ff/0xf6ff.
+ */
+ if ((reg != 0xf2ff) && (reg != 0xf6ff) &&
+ (((reg & 0xff00) == 0xf200) || ((reg & 0xff00) == 0xf600)))
+ _stb0899_read_reg(state, (reg | 0x00ff));
+
+ return result;
+}
+
+u32 _stb0899_read_s2reg(struct stb0899_state *state,
+ u32 stb0899_i2cdev,
+ u32 stb0899_base_addr,
+ u16 stb0899_reg_offset)
+{
+ int status;
+ u32 data;
+ u8 buf[7] = { 0 };
+ u16 tmpaddr;
+
+ u8 buf_0[] = {
+ GETBYTE(stb0899_i2cdev, BYTE1), /* 0xf3 S2 Base Address (MSB) */
+ GETBYTE(stb0899_i2cdev, BYTE0), /* 0xfc S2 Base Address (LSB) */
+ GETBYTE(stb0899_base_addr, BYTE0), /* 0x00 Base Address (LSB) */
+ GETBYTE(stb0899_base_addr, BYTE1), /* 0x04 Base Address (LSB) */
+ GETBYTE(stb0899_base_addr, BYTE2), /* 0x00 Base Address (MSB) */
+ GETBYTE(stb0899_base_addr, BYTE3), /* 0x00 Base Address (MSB) */
+ };
+ u8 buf_1[] = {
+ 0x00, /* 0xf3 Reg Offset */
+ 0x00, /* 0x44 Reg Offset */
+ };
+
+ struct i2c_msg msg_0 = {
+ .addr = state->config->demod_address,
+ .flags = 0,
+ .buf = buf_0,
+ .len = 6
+ };
+
+ struct i2c_msg msg_1 = {
+ .addr = state->config->demod_address,
+ .flags = 0,
+ .buf = buf_1,
+ .len = 2
+ };
+
+ struct i2c_msg msg_r = {
+ .addr = state->config->demod_address,
+ .flags = I2C_M_RD,
+ .buf = buf,
+ .len = 4
+ };
+
+ tmpaddr = stb0899_reg_offset & 0xff00;
+ if (!(stb0899_reg_offset & 0x8))
+ tmpaddr = stb0899_reg_offset | 0x20;
+
+ buf_1[0] = GETBYTE(tmpaddr, BYTE1);
+ buf_1[1] = GETBYTE(tmpaddr, BYTE0);
+
+ status = i2c_transfer(state->i2c, &msg_0, 1);
+ if (status < 1) {
+ if (status != -ERESTARTSYS)
+ printk(KERN_ERR "%s ERR(1), Device=[0x%04x], Base address=[0x%08x], Offset=[0x%04x], Status=%d\n",
+ __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, status);
+
+ goto err;
+ }
+
+ /* Dummy */
+ status = i2c_transfer(state->i2c, &msg_1, 1);
+ if (status < 1)
+ goto err;
+
+ status = i2c_transfer(state->i2c, &msg_r, 1);
+ if (status < 1)
+ goto err;
+
+ buf_1[0] = GETBYTE(stb0899_reg_offset, BYTE1);
+ buf_1[1] = GETBYTE(stb0899_reg_offset, BYTE0);
+
+ /* Actual */
+ status = i2c_transfer(state->i2c, &msg_1, 1);
+ if (status < 1) {
+ if (status != -ERESTARTSYS)
+ printk(KERN_ERR "%s ERR(2), Device=[0x%04x], Base address=[0x%08x], Offset=[0x%04x], Status=%d\n",
+ __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, status);
+ goto err;
+ }
+
+ status = i2c_transfer(state->i2c, &msg_r, 1);
+ if (status < 1) {
+ if (status != -ERESTARTSYS)
+ printk(KERN_ERR "%s ERR(3), Device=[0x%04x], Base address=[0x%08x], Offset=[0x%04x], Status=%d\n",
+ __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, status);
+ return status < 0 ? status : -EREMOTEIO;
+ }
+
+ data = MAKEWORD32(buf[3], buf[2], buf[1], buf[0]);
+ if (unlikely(*state->verbose >= FE_DEBUGREG))
+ printk(KERN_DEBUG "%s Device=[0x%04x], Base address=[0x%08x], Offset=[0x%04x], Data=[0x%08x]\n",
+ __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, data);
+
+ return data;
+
+err:
+ return status < 0 ? status : -EREMOTEIO;
+}
+
+int stb0899_write_s2reg(struct stb0899_state *state,
+ u32 stb0899_i2cdev,
+ u32 stb0899_base_addr,
+ u16 stb0899_reg_offset,
+ u32 stb0899_data)
+{
+ int status;
+
+ /* Base Address Setup */
+ u8 buf_0[] = {
+ GETBYTE(stb0899_i2cdev, BYTE1), /* 0xf3 S2 Base Address (MSB) */
+ GETBYTE(stb0899_i2cdev, BYTE0), /* 0xfc S2 Base Address (LSB) */
+ GETBYTE(stb0899_base_addr, BYTE0), /* 0x00 Base Address (LSB) */
+ GETBYTE(stb0899_base_addr, BYTE1), /* 0x04 Base Address (LSB) */
+ GETBYTE(stb0899_base_addr, BYTE2), /* 0x00 Base Address (MSB) */
+ GETBYTE(stb0899_base_addr, BYTE3), /* 0x00 Base Address (MSB) */
+ };
+ u8 buf_1[] = {
+ 0x00, /* 0xf3 Reg Offset */
+ 0x00, /* 0x44 Reg Offset */
+ 0x00, /* data */
+ 0x00, /* data */
+ 0x00, /* data */
+ 0x00, /* data */
+ };
+
+ struct i2c_msg msg_0 = {
+ .addr = state->config->demod_address,
+ .flags = 0,
+ .buf = buf_0,
+ .len = 6
+ };
+
+ struct i2c_msg msg_1 = {
+ .addr = state->config->demod_address,
+ .flags = 0,
+ .buf = buf_1,
+ .len = 6
+ };
+
+ buf_1[0] = GETBYTE(stb0899_reg_offset, BYTE1);
+ buf_1[1] = GETBYTE(stb0899_reg_offset, BYTE0);
+ buf_1[2] = GETBYTE(stb0899_data, BYTE0);
+ buf_1[3] = GETBYTE(stb0899_data, BYTE1);
+ buf_1[4] = GETBYTE(stb0899_data, BYTE2);
+ buf_1[5] = GETBYTE(stb0899_data, BYTE3);
+
+ if (unlikely(*state->verbose >= FE_DEBUGREG))
+ printk(KERN_DEBUG "%s Device=[0x%04x], Base Address=[0x%08x], Offset=[0x%04x], Data=[0x%08x]\n",
+ __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, stb0899_data);
+
+ status = i2c_transfer(state->i2c, &msg_0, 1);
+ if (unlikely(status < 1)) {
+ if (status != -ERESTARTSYS)
+ printk(KERN_ERR "%s ERR (1), Device=[0x%04x], Base Address=[0x%08x], Offset=[0x%04x], Data=[0x%08x], status=%d\n",
+ __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, stb0899_data, status);
+ goto err;
+ }
+ status = i2c_transfer(state->i2c, &msg_1, 1);
+ if (unlikely(status < 1)) {
+ if (status != -ERESTARTSYS)
+ printk(KERN_ERR "%s ERR (2), Device=[0x%04x], Base Address=[0x%08x], Offset=[0x%04x], Data=[0x%08x], status=%d\n",
+ __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, stb0899_data, status);
+
+ return status < 0 ? status : -EREMOTEIO;
+ }
+
+ return 0;
+
+err:
+ return status < 0 ? status : -EREMOTEIO;
+}
+
+int stb0899_read_regs(struct stb0899_state *state, unsigned int reg, u8 *buf, u32 count)
+{
+ int status;
+
+ u8 b0[] = { reg >> 8, reg & 0xff };
+
+ struct i2c_msg msg[] = {
+ {
+ .addr = state->config->demod_address,
+ .flags = 0,
+ .buf = b0,
+ .len = 2
+ },{
+ .addr = state->config->demod_address,
+ .flags = I2C_M_RD,
+ .buf = buf,
+ .len = count
+ }
+ };
+
+ status = i2c_transfer(state->i2c, msg, 2);
+ if (status != 2) {
+ if (status != -ERESTARTSYS)
+ printk(KERN_ERR "%s Read error, Reg=[0x%04x], Count=%u, Status=%d\n",
+ __func__, reg, count, status);
+ goto err;
+ }
+ /*
+ * Bug ID 9:
+ * access to 0xf2xx/0xf6xx
+ * must be followed by read from 0xf2ff/0xf6ff.
+ */
+ if ((reg != 0xf2ff) && (reg != 0xf6ff) &&
+ (((reg & 0xff00) == 0xf200) || ((reg & 0xff00) == 0xf600)))
+ _stb0899_read_reg(state, (reg | 0x00ff));
+
+ if (unlikely(*state->verbose >= FE_DEBUGREG)) {
+ int i;
+
+ printk(KERN_DEBUG "%s [0x%04x]:", __func__, reg);
+ for (i = 0; i < count; i++) {
+ printk(" %02x", buf[i]);
+ }
+ printk("\n");
+ }
+
+ return 0;
+err:
+ return status < 0 ? status : -EREMOTEIO;
+}
+
+int stb0899_write_regs(struct stb0899_state *state, unsigned int reg, u8 *data, u32 count)
+{
+ int ret;
+ u8 buf[2 + count];
+ struct i2c_msg i2c_msg = {
+ .addr = state->config->demod_address,
+ .flags = 0,
+ .buf = buf,
+ .len = 2 + count
+ };
+
+ buf[0] = reg >> 8;
+ buf[1] = reg & 0xff;
+ memcpy(&buf[2], data, count);
+
+ if (unlikely(*state->verbose >= FE_DEBUGREG)) {
+ int i;
+
+ printk(KERN_DEBUG "%s [0x%04x]:", __func__, reg);
+ for (i = 0; i < count; i++)
+ printk(" %02x", data[i]);
+ printk("\n");
+ }
+ ret = i2c_transfer(state->i2c, &i2c_msg, 1);
+
+ /*
+ * Bug ID 9:
+ * access to 0xf2xx/0xf6xx
+ * must be followed by read from 0xf2ff/0xf6ff.
+ */
+ if ((((reg & 0xff00) == 0xf200) || ((reg & 0xff00) == 0xf600)))
+ stb0899_read_reg(state, (reg | 0x00ff));
+
+ if (ret != 1) {
+ if (ret != -ERESTARTSYS)
+ dprintk(state->verbose, FE_ERROR, 1, "Reg=[0x%04x], Data=[0x%02x ...], Count=%u, Status=%d",
+ reg, data[0], count, ret);
+ return ret < 0 ? ret : -EREMOTEIO;
+ }
+
+ return 0;
+}
+
+int stb0899_write_reg(struct stb0899_state *state, unsigned int reg, u8 data)
+{
+ return stb0899_write_regs(state, reg, &data, 1);
+}
+
+/*
+ * stb0899_get_mclk
+ * Get STB0899 master clock frequency
+ * ExtClk: external clock frequency (Hz)
+ */
+static u32 stb0899_get_mclk(struct stb0899_state *state)
+{
+ u32 mclk = 0, div = 0;
+
+ div = stb0899_read_reg(state, STB0899_NCOARSE);
+ mclk = (div + 1) * state->config->xtal_freq / 6;
+ dprintk(state->verbose, FE_DEBUG, 1, "div=%d, mclk=%d", div, mclk);
+
+ return mclk;
+}
+
+/*
+ * stb0899_set_mclk
+ * Set STB0899 master Clock frequency
+ * Mclk: demodulator master clock
+ * ExtClk: external clock frequency (Hz)
+ */
+static void stb0899_set_mclk(struct stb0899_state *state, u32 Mclk)
+{
+ struct stb0899_internal *internal = &state->internal;
+ u8 mdiv = 0;
+
+ dprintk(state->verbose, FE_DEBUG, 1, "state->config=%p", state->config);
+ mdiv = ((6 * Mclk) / state->config->xtal_freq) - 1;
+ dprintk(state->verbose, FE_DEBUG, 1, "mdiv=%d", mdiv);
+
+ stb0899_write_reg(state, STB0899_NCOARSE, mdiv);
+ internal->master_clk = stb0899_get_mclk(state);
+
+ dprintk(state->verbose, FE_DEBUG, 1, "MasterCLOCK=%d", internal->master_clk);
+}
+
+static int stb0899_postproc(struct stb0899_state *state, u8 ctl, int enable)
+{
+ struct stb0899_config *config = state->config;
+ const struct stb0899_postproc *postproc = config->postproc;
+
+ /* post process event */
+ if (postproc) {
+ if (enable) {
+ if (postproc[ctl].level == STB0899_GPIOPULLUP)
+ stb0899_write_reg(state, postproc[ctl].gpio, 0x02);
+ else
+ stb0899_write_reg(state, postproc[ctl].gpio, 0x82);
+ } else {
+ if (postproc[ctl].level == STB0899_GPIOPULLUP)
+ stb0899_write_reg(state, postproc[ctl].gpio, 0x82);
+ else
+ stb0899_write_reg(state, postproc[ctl].gpio, 0x02);
+ }
+ }
+ return 0;
+}
+
+static void stb0899_release(struct dvb_frontend *fe)
+{
+ struct stb0899_state *state = fe->demodulator_priv;
+
+ dprintk(state->verbose, FE_DEBUG, 1, "Release Frontend");
+ /* post process event */
+ stb0899_postproc(state, STB0899_POSTPROC_GPIO_POWER, 0);
+ kfree(state);
+}
+
+/*
+ * stb0899_get_alpha
+ * return: rolloff
+ */
+static int stb0899_get_alpha(struct stb0899_state *state)
+{
+ u8 mode_coeff;
+
+ mode_coeff = stb0899_read_reg(state, STB0899_DEMOD);
+
+ if (STB0899_GETFIELD(MODECOEFF, mode_coeff) == 1)
+ return 20;
+ else
+ return 35;
+}
+
+/*
+ * stb0899_init_calc
+ */
+static void stb0899_init_calc(struct stb0899_state *state)
+{
+ struct stb0899_internal *internal = &state->internal;
+ int master_clk;
+ u8 agc[2];
+ u8 agc1cn;
+ u32 reg;
+
+ /* Read registers (in burst mode) */
+ agc1cn = stb0899_read_reg(state, STB0899_AGC1CN);
+ stb0899_read_regs(state, STB0899_AGC1REF, agc, 2); /* AGC1R and AGC2O */
+
+ /* Initial calculations */
+ master_clk = stb0899_get_mclk(state);
+ internal->t_agc1 = 0;
+ internal->t_agc2 = 0;
+ internal->master_clk = master_clk;
+ internal->mclk = master_clk / 65536L;
+ internal->rolloff = stb0899_get_alpha(state);
+
+ /* DVBS2 Initial calculations */
+ /* Set AGC value to the middle */
+ internal->agc_gain = 8154;
+ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_CNTRL);
+ STB0899_SETFIELD_VAL(IF_GAIN_INIT, reg, internal->agc_gain);
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_IF_AGC_CNTRL, STB0899_OFF0_IF_AGC_CNTRL, reg);
+
+ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, RRC_ALPHA);
+ internal->rrc_alpha = STB0899_GETFIELD(RRC_ALPHA, reg);
+
+ internal->center_freq = 0;
+ internal->av_frame_coarse = 10;
+ internal->av_frame_fine = 20;
+ internal->step_size = 2;
+/*
+ if ((pParams->SpectralInv == FE_IQ_NORMAL) || (pParams->SpectralInv == FE_IQ_AUTO))
+ pParams->IQLocked = 0;
+ else
+ pParams->IQLocked = 1;
+*/
+}
+
+static int stb0899_wait_diseqc_fifo_empty(struct stb0899_state *state, int timeout)
+{
+ u8 reg = 0;
+ unsigned long start = jiffies;
+
+ while (1) {
+ reg = stb0899_read_reg(state, STB0899_DISSTATUS);
+ if (!STB0899_GETFIELD(FIFOFULL, reg))
+ break;
+ if ((jiffies - start) > timeout) {
+ dprintk(state->verbose, FE_ERROR, 1, "timed out !!");
+ return -ETIMEDOUT;
+ }
+ }
+
+ return 0;
+}
+
+static int stb0899_send_diseqc_msg(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *cmd)
+{
+ struct stb0899_state *state = fe->demodulator_priv;
+ u8 reg, i;
+
+ if (cmd->msg_len > 8)
+ return -EINVAL;
+
+ /* enable FIFO precharge */
+ reg = stb0899_read_reg(state, STB0899_DISCNTRL1);
+ STB0899_SETFIELD_VAL(DISPRECHARGE, reg, 1);
+ stb0899_write_reg(state, STB0899_DISCNTRL1, reg);
+ for (i = 0; i < cmd->msg_len; i++) {
+ /* wait for FIFO empty */
+ if (stb0899_wait_diseqc_fifo_empty(state, 10) < 0)
+ return -ETIMEDOUT;
+
+ stb0899_write_reg(state, STB0899_DISFIFO, cmd->msg[i]);
+ }
+ reg = stb0899_read_reg(state, STB0899_DISCNTRL1);
+ STB0899_SETFIELD_VAL(DISPRECHARGE, reg, 0);
+ stb0899_write_reg(state, STB0899_DISCNTRL1, reg);
+
+ return 0;
+}
+
+static int stb0899_wait_diseqc_rxidle(struct stb0899_state *state, int timeout)
+{
+ u8 reg = 0;
+ unsigned long start = jiffies;
+
+ while (!STB0899_GETFIELD(RXEND, reg)) {
+ reg = stb0899_read_reg(state, STB0899_DISRX_ST0);
+ if (jiffies - start > timeout) {
+ dprintk(state->verbose, FE_ERROR, 1, "timed out!!");
+ return -ETIMEDOUT;
+ }
+ msleep(10);
+ }
+
+ return 0;
+}
+
+static int stb0899_recv_slave_reply(struct dvb_frontend *fe, struct dvb_diseqc_slave_reply *reply)
+{
+ struct stb0899_state *state = fe->demodulator_priv;
+ u8 reg, length = 0, i;
+ int result;
+
+ if (stb0899_wait_diseqc_rxidle(state, 100) < 0)
+ return -ETIMEDOUT;
+
+ reg = stb0899_read_reg(state, STB0899_DISRX_ST0);
+ if (STB0899_GETFIELD(RXEND, reg)) {
+
+ reg = stb0899_read_reg(state, STB0899_DISRX_ST1);
+ length = STB0899_GETFIELD(FIFOBYTENBR, reg);
+
+ if (length > sizeof (reply->msg)) {
+ result = -EOVERFLOW;
+ goto exit;
+ }
+ reply->msg_len = length;
+
+ /* extract data */
+ for (i = 0; i < length; i++)
+ reply->msg[i] = stb0899_read_reg(state, STB0899_DISFIFO);
+ }
+
+ return 0;
+exit:
+
+ return result;
+}
+
+static int stb0899_wait_diseqc_txidle(struct stb0899_state *state, int timeout)
+{
+ u8 reg = 0;
+ unsigned long start = jiffies;
+
+ while (!STB0899_GETFIELD(TXIDLE, reg)) {
+ reg = stb0899_read_reg(state, STB0899_DISSTATUS);
+ if (jiffies - start > timeout) {
+ dprintk(state->verbose, FE_ERROR, 1, "timed out!!");
+ return -ETIMEDOUT;
+ }
+ msleep(10);
+ }
+ return 0;
+}
+
+static int stb0899_send_diseqc_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst)
+{
+ struct stb0899_state *state = fe->demodulator_priv;
+ u8 reg, old_state;
+
+ /* wait for diseqc idle */
+ if (stb0899_wait_diseqc_txidle(state, 100) < 0)
+ return -ETIMEDOUT;
+
+ reg = stb0899_read_reg(state, STB0899_DISCNTRL1);
+ old_state = reg;
+ /* set to burst mode */
+ STB0899_SETFIELD_VAL(DISEQCMODE, reg, 0x02);
+ STB0899_SETFIELD_VAL(DISPRECHARGE, reg, 0x01);
+ stb0899_write_reg(state, STB0899_DISCNTRL1, reg);
+ switch (burst) {
+ case SEC_MINI_A:
+ /* unmodulated */
+ stb0899_write_reg(state, STB0899_DISFIFO, 0x00);
+ break;
+ case SEC_MINI_B:
+ /* modulated */
+ stb0899_write_reg(state, STB0899_DISFIFO, 0xff);
+ break;
+ }
+ reg = stb0899_read_reg(state, STB0899_DISCNTRL1);
+ STB0899_SETFIELD_VAL(DISPRECHARGE, reg, 0x00);
+ stb0899_write_reg(state, STB0899_DISCNTRL1, reg);
+ /* wait for diseqc idle */
+ if (stb0899_wait_diseqc_txidle(state, 100) < 0)
+ return -ETIMEDOUT;
+
+ /* restore state */
+ stb0899_write_reg(state, STB0899_DISCNTRL1, old_state);
+
+ return 0;
+}
+
+static int stb0899_diseqc_init(struct stb0899_state *state)
+{
+ struct dvb_diseqc_master_cmd tx_data;
+/*
+ struct dvb_diseqc_slave_reply rx_data;
+*/
+ u8 f22_tx, f22_rx, reg;
+
+ u32 mclk, tx_freq = 22000;/* count = 0, i; */
+#if 0
+ u32 trial = 0; /* try max = 2 (try 20khz and 17.5 khz) */
+ u32 ret_1 = 0; /* 20 Khz status */
+ u32 ret_2 = 0; /* 17.5 Khz status */
+#endif
+ tx_data.msg[0] = 0xe2;
+ tx_data.msg_len = 3;
+ reg = stb0899_read_reg(state, STB0899_DISCNTRL2);
+ STB0899_SETFIELD_VAL(ONECHIP_TRX, reg, 0);
+ stb0899_write_reg(state, STB0899_DISCNTRL2, reg);
+
+ /* disable Tx spy */
+ reg = stb0899_read_reg(state, STB0899_DISCNTRL1);
+ STB0899_SETFIELD_VAL(DISEQCRESET, reg, 1);
+ stb0899_write_reg(state, STB0899_DISCNTRL1, reg);
+
+ reg = stb0899_read_reg(state, STB0899_DISCNTRL1);
+ STB0899_SETFIELD_VAL(DISEQCRESET, reg, 0);
+ stb0899_write_reg(state, STB0899_DISCNTRL1, reg);
+
+ mclk = stb0899_get_mclk(state);
+ f22_tx = mclk / (tx_freq * 32);
+ stb0899_write_reg(state, STB0899_DISF22, f22_tx); /* DiSEqC Tx freq */
+ state->rx_freq = 20000;
+ f22_rx = mclk / (state->rx_freq * 32);
+
+#if 0
+ while ((count < 5) && (trial < 2)) {
+ stb0899_write_reg(state, STB0899_DISF22RX, f22_rx); /* 2 possible values 17.5k/20k */
+
+ for (i = 0; i < 5; i++) {
+ msleep(50);
+ stb0899_send_diseqc_msg(&state->frontend, &tx_data);
+ msleep(100);
+ stb0899_recv_slave_reply(&state->frontend, &rx_data);
+ if (rx_data.msg_len >= 1) {
+ if ((rx_data.msg[0] == 0xe4) || (rx_data.msg[0] == 0xe5))
+ count++;
+ }
+ }
+ if (trial == 0)
+ ret_1 = count;
+ else
+ ret_2 = count;
+
+ trial++;
+ state->rx_freq = 17500;
+ f22_rx = mclk / (state->rx_freq * 32);
+ }
+ if (ret_1 > ret_2) {
+ state->rx_freq = 20000;
+ f22_rx = mclk / (state->rx_freq * 32);
+ } else {
+ state->rx_freq = 17500;
+ f22_rx = mclk / (state->rx_freq * 32);
+ }
+
+ stb0899_write_reg(state, STB0899_DISF22RX, f22_rx);
+ if ((ret_1 == 0) && (ret_2 == 0))
+ state->rx_freq = 0; /* no DiSEqC 2.0 slave */
+
+#endif
+ return 0;
+}
+
+static int stb0899_sleep(struct dvb_frontend *fe)
+{
+ struct stb0899_state *state = fe->demodulator_priv;
+/*
+ u8 reg;
+*/
+ dprintk(state->verbose, FE_DEBUG, 1, "Going to Sleep .. (Really tired .. :-))");
+#if 0
+ reg = stb0899_read_reg(state, STB0899_SYNTCTRL);
+ STB0899_SETFIELD_VAL(STANDBY, reg, 1);
+ stb0899_write_reg(state, STB0899_SYNTCTRL, reg);
+#endif
+ /* post process event */
+ stb0899_postproc(state, STB0899_POSTPROC_GPIO_POWER, 0);
+
+ return 0;
+}
+
+static int stb0899_wakeup(struct dvb_frontend *fe)
+{
+ int rc;
+ struct stb0899_state *state = fe->demodulator_priv;
+
+ if ((rc = stb0899_write_reg(state, STB0899_SYNTCTRL, STB0899_SELOSCI)))
+ return rc;
+ /* Activate all clocks; DVB-S2 registers are inaccessible otherwise. */
+ if ((rc = stb0899_write_reg(state, STB0899_STOPCLK1, 0x00)))
+ return rc;
+ if ((rc = stb0899_write_reg(state, STB0899_STOPCLK2, 0x00)))
+ return rc;
+
+ /* post process event */
+ stb0899_postproc(state, STB0899_POSTPROC_GPIO_POWER, 1);
+
+ return 0;
+}
+
+static int stb0899_init(struct dvb_frontend *fe)
+{
+ int i;
+ struct stb0899_state *state = fe->demodulator_priv;
+ struct stb0899_config *config = state->config;
+
+ dprintk(state->verbose, FE_DEBUG, 1, "Initializing STB0899 ... ");
+
+ /* init device */
+ dprintk(state->verbose, FE_DEBUG, 1, "init device");
+ for (i = 0; config->init_dev[i].address != 0xffff; i++)
+ stb0899_write_reg(state, config->init_dev[i].address, config->init_dev[i].data);
+
+ dprintk(state->verbose, FE_DEBUG, 1, "init S2 demod");
+ /* init S2 demod */
+ for (i = 0; config->init_s2_demod[i].offset != 0xffff; i++)
+ stb0899_write_s2reg(state, STB0899_S2DEMOD,
+ config->init_s2_demod[i].base_address,
+ config->init_s2_demod[i].offset,
+ config->init_s2_demod[i].data);
+
+ dprintk(state->verbose, FE_DEBUG, 1, "init S1 demod");
+ /* init S1 demod */
+ for (i = 0; config->init_s1_demod[i].address != 0xffff; i++)
+ stb0899_write_reg(state, config->init_s1_demod[i].address, config->init_s1_demod[i].data);
+
+ dprintk(state->verbose, FE_DEBUG, 1, "init S2 FEC");
+ /* init S2 fec */
+ for (i = 0; config->init_s2_fec[i].offset != 0xffff; i++)
+ stb0899_write_s2reg(state, STB0899_S2FEC,
+ config->init_s2_fec[i].base_address,
+ config->init_s2_fec[i].offset,
+ config->init_s2_fec[i].data);
+
+ dprintk(state->verbose, FE_DEBUG, 1, "init TST");
+ /* init test */
+ for (i = 0; config->init_tst[i].address != 0xffff; i++)
+ stb0899_write_reg(state, config->init_tst[i].address, config->init_tst[i].data);
+
+ stb0899_init_calc(state);
+ stb0899_diseqc_init(state);
+
+ return 0;
+}
+
+static int stb0899_table_lookup(const struct stb0899_tab *tab, int max, int val)
+{
+ int res = 0;
+ int min = 0, med;
+
+ if (val < tab[min].read)
+ res = tab[min].real;
+ else if (val >= tab[max].read)
+ res = tab[max].real;
+ else {
+ while ((max - min) > 1) {
+ med = (max + min) / 2;
+ if (val >= tab[min].read && val < tab[med].read)
+ max = med;
+ else
+ min = med;
+ }
+ res = ((val - tab[min].read) *
+ (tab[max].real - tab[min].real) /
+ (tab[max].read - tab[min].read)) +
+ tab[min].real;
+ }
+
+ return res;
+}
+
+static int stb0899_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+ struct stb0899_state *state = fe->demodulator_priv;
+ struct stb0899_internal *internal = &state->internal;
+
+ int val;
+ u32 reg;
+ switch (state->delsys) {
+ case SYS_DVBS:
+ case SYS_DSS:
+ if (internal->lock) {
+ reg = stb0899_read_reg(state, STB0899_VSTATUS);
+ if (STB0899_GETFIELD(VSTATUS_LOCKEDVIT, reg)) {
+
+ reg = stb0899_read_reg(state, STB0899_AGCIQIN);
+ val = (s32)(s8)STB0899_GETFIELD(AGCIQVALUE, reg);
+
+ *strength = stb0899_table_lookup(stb0899_dvbsrf_tab, ARRAY_SIZE(stb0899_dvbsrf_tab) - 1, val);
+ *strength += 750;
+ dprintk(state->verbose, FE_DEBUG, 1, "AGCIQVALUE = 0x%02x, C = %d * 0.1 dBm",
+ val & 0xff, *strength);
+ }
+ }
+ break;
+ case SYS_DVBS2:
+ if (internal->lock) {
+ reg = STB0899_READ_S2REG(STB0899_DEMOD, IF_AGC_GAIN);
+ val = STB0899_GETFIELD(IF_AGC_GAIN, reg);
+
+ *strength = stb0899_table_lookup(stb0899_dvbs2rf_tab, ARRAY_SIZE(stb0899_dvbs2rf_tab) - 1, val);
+ *strength += 750;
+ dprintk(state->verbose, FE_DEBUG, 1, "IF_AGC_GAIN = 0x%04x, C = %d * 0.1 dBm",
+ val & 0x3fff, *strength);
+ }
+ break;
+ default:
+ dprintk(state->verbose, FE_DEBUG, 1, "Unsupported delivery system");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int stb0899_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+ struct stb0899_state *state = fe->demodulator_priv;
+ struct stb0899_internal *internal = &state->internal;
+
+ unsigned int val, quant, quantn = -1, est, estn = -1;
+ u8 buf[2];
+ u32 reg;
+
+ reg = stb0899_read_reg(state, STB0899_VSTATUS);
+ switch (state->delsys) {
+ case SYS_DVBS:
+ case SYS_DSS:
+ if (internal->lock) {
+ if (STB0899_GETFIELD(VSTATUS_LOCKEDVIT, reg)) {
+
+ stb0899_read_regs(state, STB0899_NIRM, buf, 2);
+ val = MAKEWORD16(buf[0], buf[1]);
+
+ *snr = stb0899_table_lookup(stb0899_cn_tab, ARRAY_SIZE(stb0899_cn_tab) - 1, val);
+ dprintk(state->verbose, FE_DEBUG, 1, "NIR = 0x%02x%02x = %u, C/N = %d * 0.1 dBm\n",
+ buf[0], buf[1], val, *snr);
+ }
+ }
+ break;
+ case SYS_DVBS2:
+ if (internal->lock) {
+ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_CNTRL1);
+ quant = STB0899_GETFIELD(UWP_ESN0_QUANT, reg);
+ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_STAT2);
+ est = STB0899_GETFIELD(ESN0_EST, reg);
+ if (est == 1)
+ val = 301; /* C/N = 30.1 dB */
+ else if (est == 2)
+ val = 270; /* C/N = 27.0 dB */
+ else {
+ /* quantn = 100 * log(quant^2) */
+ quantn = stb0899_table_lookup(stb0899_quant_tab, ARRAY_SIZE(stb0899_quant_tab) - 1, quant * 100);
+ /* estn = 100 * log(est) */
+ estn = stb0899_table_lookup(stb0899_est_tab, ARRAY_SIZE(stb0899_est_tab) - 1, est);
+ /* snr(dBm/10) = -10*(log(est)-log(quant^2)) => snr(dBm/10) = (100*log(quant^2)-100*log(est))/10 */
+ val = (quantn - estn) / 10;
+ }
+ *snr = val;
+ dprintk(state->verbose, FE_DEBUG, 1, "Es/N0 quant = %d (%d) estimate = %u (%d), C/N = %d * 0.1 dBm",
+ quant, quantn, est, estn, val);
+ }
+ break;
+ default:
+ dprintk(state->verbose, FE_DEBUG, 1, "Unsupported delivery system");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int stb0899_read_status(struct dvb_frontend *fe, enum fe_status *status)
+{
+ struct stb0899_state *state = fe->demodulator_priv;
+ struct stb0899_internal *internal = &state->internal;
+ u8 reg;
+ *status = 0;
+
+ switch (state->delsys) {
+ case SYS_DVBS:
+ case SYS_DSS:
+ dprintk(state->verbose, FE_DEBUG, 1, "Delivery system DVB-S/DSS");
+ if (internal->lock) {
+ reg = stb0899_read_reg(state, STB0899_VSTATUS);
+ if (STB0899_GETFIELD(VSTATUS_LOCKEDVIT, reg)) {
+ dprintk(state->verbose, FE_DEBUG, 1, "--------> FE_HAS_CARRIER | FE_HAS_LOCK");
+ *status |= FE_HAS_CARRIER | FE_HAS_LOCK;
+
+ reg = stb0899_read_reg(state, STB0899_PLPARM);
+ if (STB0899_GETFIELD(VITCURPUN, reg)) {
+ dprintk(state->verbose, FE_DEBUG, 1, "--------> FE_HAS_VITERBI | FE_HAS_SYNC");
+ *status |= FE_HAS_VITERBI | FE_HAS_SYNC;
+ /* post process event */
+ stb0899_postproc(state, STB0899_POSTPROC_GPIO_LOCK, 1);
+ }
+ }
+ }
+ break;
+ case SYS_DVBS2:
+ dprintk(state->verbose, FE_DEBUG, 1, "Delivery system DVB-S2");
+ if (internal->lock) {
+ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_STAT2);
+ if (STB0899_GETFIELD(UWP_LOCK, reg) && STB0899_GETFIELD(CSM_LOCK, reg)) {
+ *status |= FE_HAS_CARRIER;
+ dprintk(state->verbose, FE_DEBUG, 1,
+ "UWP & CSM Lock ! ---> DVB-S2 FE_HAS_CARRIER");
+
+ reg = stb0899_read_reg(state, STB0899_CFGPDELSTATUS1);
+ if (STB0899_GETFIELD(CFGPDELSTATUS_LOCK, reg)) {
+ *status |= FE_HAS_LOCK;
+ dprintk(state->verbose, FE_DEBUG, 1,
+ "Packet Delineator Locked ! -----> DVB-S2 FE_HAS_LOCK");
+
+ }
+ if (STB0899_GETFIELD(CONTINUOUS_STREAM, reg)) {
+ *status |= FE_HAS_VITERBI;
+ dprintk(state->verbose, FE_DEBUG, 1,
+ "Packet Delineator found VITERBI ! -----> DVB-S2 FE_HAS_VITERBI");
+ }
+ if (STB0899_GETFIELD(ACCEPTED_STREAM, reg)) {
+ *status |= FE_HAS_SYNC;
+ dprintk(state->verbose, FE_DEBUG, 1,
+ "Packet Delineator found SYNC ! -----> DVB-S2 FE_HAS_SYNC");
+ /* post process event */
+ stb0899_postproc(state, STB0899_POSTPROC_GPIO_LOCK, 1);
+ }
+ }
+ }
+ break;
+ default:
+ dprintk(state->verbose, FE_DEBUG, 1, "Unsupported delivery system");
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/*
+ * stb0899_get_error
+ * viterbi error for DVB-S/DSS
+ * packet error for DVB-S2
+ * Bit Error Rate or Packet Error Rate * 10 ^ 7
+ */
+static int stb0899_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+ struct stb0899_state *state = fe->demodulator_priv;
+ struct stb0899_internal *internal = &state->internal;
+
+ u8 lsb, msb;
+ u32 i;
+
+ *ber = 0;
+
+ switch (state->delsys) {
+ case SYS_DVBS:
+ case SYS_DSS:
+ if (internal->lock) {
+ /* average 5 BER values */
+ for (i = 0; i < 5; i++) {
+ msleep(100);
+ lsb = stb0899_read_reg(state, STB0899_ECNT1L);
+ msb = stb0899_read_reg(state, STB0899_ECNT1M);
+ *ber += MAKEWORD16(msb, lsb);
+ }
+ *ber /= 5;
+ /* Viterbi Check */
+ if (STB0899_GETFIELD(VSTATUS_PRFVIT, internal->v_status)) {
+ /* Error Rate */
+ *ber *= 9766;
+ /* ber = ber * 10 ^ 7 */
+ *ber /= (-1 + (1 << (2 * STB0899_GETFIELD(NOE, internal->err_ctrl))));
+ *ber /= 8;
+ }
+ }
+ break;
+ case SYS_DVBS2:
+ if (internal->lock) {
+ /* Average 5 PER values */
+ for (i = 0; i < 5; i++) {
+ msleep(100);
+ lsb = stb0899_read_reg(state, STB0899_ECNT1L);
+ msb = stb0899_read_reg(state, STB0899_ECNT1M);
+ *ber += MAKEWORD16(msb, lsb);
+ }
+ /* ber = ber * 10 ^ 7 */
+ *ber *= 10000000;
+ *ber /= (-1 + (1 << (4 + 2 * STB0899_GETFIELD(NOE, internal->err_ctrl))));
+ }
+ break;
+ default:
+ dprintk(state->verbose, FE_DEBUG, 1, "Unsupported delivery system");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int stb0899_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+ struct stb0899_state *state = fe->demodulator_priv;
+
+ switch (voltage) {
+ case SEC_VOLTAGE_13:
+ stb0899_write_reg(state, STB0899_GPIO00CFG, 0x82);
+ stb0899_write_reg(state, STB0899_GPIO01CFG, 0x02);
+ stb0899_write_reg(state, STB0899_GPIO02CFG, 0x00);
+ break;
+ case SEC_VOLTAGE_18:
+ stb0899_write_reg(state, STB0899_GPIO00CFG, 0x02);
+ stb0899_write_reg(state, STB0899_GPIO01CFG, 0x02);
+ stb0899_write_reg(state, STB0899_GPIO02CFG, 0x82);
+ break;
+ case SEC_VOLTAGE_OFF:
+ stb0899_write_reg(state, STB0899_GPIO00CFG, 0x82);
+ stb0899_write_reg(state, STB0899_GPIO01CFG, 0x82);
+ stb0899_write_reg(state, STB0899_GPIO02CFG, 0x82);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int stb0899_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+{
+ struct stb0899_state *state = fe->demodulator_priv;
+ struct stb0899_internal *internal = &state->internal;
+
+ u8 div, reg;
+
+ /* wait for diseqc idle */
+ if (stb0899_wait_diseqc_txidle(state, 100) < 0)
+ return -ETIMEDOUT;
+
+ switch (tone) {
+ case SEC_TONE_ON:
+ div = (internal->master_clk / 100) / 5632;
+ div = (div + 5) / 10;
+ stb0899_write_reg(state, STB0899_DISEQCOCFG, 0x66);
+ reg = stb0899_read_reg(state, STB0899_ACRPRESC);
+ STB0899_SETFIELD_VAL(ACRPRESC, reg, 0x03);
+ stb0899_write_reg(state, STB0899_ACRPRESC, reg);
+ stb0899_write_reg(state, STB0899_ACRDIV1, div);
+ break;
+ case SEC_TONE_OFF:
+ stb0899_write_reg(state, STB0899_DISEQCOCFG, 0x20);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+int stb0899_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+ int i2c_stat;
+ struct stb0899_state *state = fe->demodulator_priv;
+
+ i2c_stat = stb0899_read_reg(state, STB0899_I2CRPT);
+ if (i2c_stat < 0)
+ goto err;
+
+ if (enable) {
+ dprintk(state->verbose, FE_DEBUG, 1, "Enabling I2C Repeater ...");
+ i2c_stat |= STB0899_I2CTON;
+ if (stb0899_write_reg(state, STB0899_I2CRPT, i2c_stat) < 0)
+ goto err;
+ } else {
+ dprintk(state->verbose, FE_DEBUG, 1, "Disabling I2C Repeater ...");
+ i2c_stat &= ~STB0899_I2CTON;
+ if (stb0899_write_reg(state, STB0899_I2CRPT, i2c_stat) < 0)
+ goto err;
+ }
+ return 0;
+err:
+ dprintk(state->verbose, FE_ERROR, 1, "I2C Repeater control failed");
+ return -EREMOTEIO;
+}
+
+
+static inline void CONVERT32(u32 x, char *str)
+{
+ *str++ = (x >> 24) & 0xff;
+ *str++ = (x >> 16) & 0xff;
+ *str++ = (x >> 8) & 0xff;
+ *str++ = (x >> 0) & 0xff;
+ *str = '\0';
+}
+
+int stb0899_get_dev_id(struct stb0899_state *state)
+{
+ u8 chip_id, release;
+ u16 id;
+ u32 demod_ver = 0, fec_ver = 0;
+ char demod_str[5] = { 0 };
+ char fec_str[5] = { 0 };
+
+ id = stb0899_read_reg(state, STB0899_DEV_ID);
+ dprintk(state->verbose, FE_DEBUG, 1, "ID reg=[0x%02x]", id);
+ chip_id = STB0899_GETFIELD(CHIP_ID, id);
+ release = STB0899_GETFIELD(CHIP_REL, id);
+
+ dprintk(state->verbose, FE_ERROR, 1, "Device ID=[%d], Release=[%d]",
+ chip_id, release);
+
+ CONVERT32(STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CORE_ID), (char *)&demod_str);
+
+ demod_ver = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_VERSION_ID);
+ dprintk(state->verbose, FE_ERROR, 1, "Demodulator Core ID=[%s], Version=[%d]", (char *) &demod_str, demod_ver);
+ CONVERT32(STB0899_READ_S2REG(STB0899_S2FEC, FEC_CORE_ID_REG), (char *)&fec_str);
+ fec_ver = STB0899_READ_S2REG(STB0899_S2FEC, FEC_VER_ID_REG);
+ if (! (chip_id > 0)) {
+ dprintk(state->verbose, FE_ERROR, 1, "couldn't find a STB 0899");
+
+ return -ENODEV;
+ }
+ dprintk(state->verbose, FE_ERROR, 1, "FEC Core ID=[%s], Version=[%d]", (char*) &fec_str, fec_ver);
+
+ return 0;
+}
+
+static void stb0899_set_delivery(struct stb0899_state *state)
+{
+ u8 reg;
+ u8 stop_clk[2];
+
+ stop_clk[0] = stb0899_read_reg(state, STB0899_STOPCLK1);
+ stop_clk[1] = stb0899_read_reg(state, STB0899_STOPCLK2);
+
+ switch (state->delsys) {
+ case SYS_DVBS:
+ dprintk(state->verbose, FE_DEBUG, 1, "Delivery System -- DVB-S");
+ /* FECM/Viterbi ON */
+ reg = stb0899_read_reg(state, STB0899_FECM);
+ STB0899_SETFIELD_VAL(FECM_RSVD0, reg, 0);
+ STB0899_SETFIELD_VAL(FECM_VITERBI_ON, reg, 1);
+ stb0899_write_reg(state, STB0899_FECM, reg);
+
+ stb0899_write_reg(state, STB0899_RSULC, 0xb1);
+ stb0899_write_reg(state, STB0899_TSULC, 0x40);
+ stb0899_write_reg(state, STB0899_RSLLC, 0x42);
+ stb0899_write_reg(state, STB0899_TSLPL, 0x12);
+
+ reg = stb0899_read_reg(state, STB0899_TSTRES);
+ STB0899_SETFIELD_VAL(FRESLDPC, reg, 1);
+ stb0899_write_reg(state, STB0899_TSTRES, reg);
+
+ STB0899_SETFIELD_VAL(STOP_CHK8PSK, stop_clk[0], 1);
+ STB0899_SETFIELD_VAL(STOP_CKFEC108, stop_clk[0], 1);
+ STB0899_SETFIELD_VAL(STOP_CKFEC216, stop_clk[0], 1);
+
+ STB0899_SETFIELD_VAL(STOP_CKPKDLIN108, stop_clk[1], 1);
+ STB0899_SETFIELD_VAL(STOP_CKPKDLIN216, stop_clk[1], 1);
+
+ STB0899_SETFIELD_VAL(STOP_CKINTBUF216, stop_clk[0], 1);
+ STB0899_SETFIELD_VAL(STOP_CKCORE216, stop_clk[0], 0);
+
+ STB0899_SETFIELD_VAL(STOP_CKS2DMD108, stop_clk[1], 1);
+ break;
+ case SYS_DVBS2:
+ /* FECM/Viterbi OFF */
+ reg = stb0899_read_reg(state, STB0899_FECM);
+ STB0899_SETFIELD_VAL(FECM_RSVD0, reg, 0);
+ STB0899_SETFIELD_VAL(FECM_VITERBI_ON, reg, 0);
+ stb0899_write_reg(state, STB0899_FECM, reg);
+
+ stb0899_write_reg(state, STB0899_RSULC, 0xb1);
+ stb0899_write_reg(state, STB0899_TSULC, 0x42);
+ stb0899_write_reg(state, STB0899_RSLLC, 0x40);
+ stb0899_write_reg(state, STB0899_TSLPL, 0x02);
+
+ reg = stb0899_read_reg(state, STB0899_TSTRES);
+ STB0899_SETFIELD_VAL(FRESLDPC, reg, 0);
+ stb0899_write_reg(state, STB0899_TSTRES, reg);
+
+ STB0899_SETFIELD_VAL(STOP_CHK8PSK, stop_clk[0], 1);
+ STB0899_SETFIELD_VAL(STOP_CKFEC108, stop_clk[0], 0);
+ STB0899_SETFIELD_VAL(STOP_CKFEC216, stop_clk[0], 0);
+
+ STB0899_SETFIELD_VAL(STOP_CKPKDLIN108, stop_clk[1], 0);
+ STB0899_SETFIELD_VAL(STOP_CKPKDLIN216, stop_clk[1], 0);
+
+ STB0899_SETFIELD_VAL(STOP_CKINTBUF216, stop_clk[0], 0);
+ STB0899_SETFIELD_VAL(STOP_CKCORE216, stop_clk[0], 0);
+
+ STB0899_SETFIELD_VAL(STOP_CKS2DMD108, stop_clk[1], 0);
+ break;
+ case SYS_DSS:
+ /* FECM/Viterbi ON */
+ reg = stb0899_read_reg(state, STB0899_FECM);
+ STB0899_SETFIELD_VAL(FECM_RSVD0, reg, 1);
+ STB0899_SETFIELD_VAL(FECM_VITERBI_ON, reg, 1);
+ stb0899_write_reg(state, STB0899_FECM, reg);
+
+ stb0899_write_reg(state, STB0899_RSULC, 0xa1);
+ stb0899_write_reg(state, STB0899_TSULC, 0x61);
+ stb0899_write_reg(state, STB0899_RSLLC, 0x42);
+
+ reg = stb0899_read_reg(state, STB0899_TSTRES);
+ STB0899_SETFIELD_VAL(FRESLDPC, reg, 1);
+ stb0899_write_reg(state, STB0899_TSTRES, reg);
+
+ STB0899_SETFIELD_VAL(STOP_CHK8PSK, stop_clk[0], 1);
+ STB0899_SETFIELD_VAL(STOP_CKFEC108, stop_clk[0], 1);
+ STB0899_SETFIELD_VAL(STOP_CKFEC216, stop_clk[0], 1);
+
+ STB0899_SETFIELD_VAL(STOP_CKPKDLIN108, stop_clk[1], 1);
+ STB0899_SETFIELD_VAL(STOP_CKPKDLIN216, stop_clk[1], 1);
+
+ STB0899_SETFIELD_VAL(STOP_CKCORE216, stop_clk[0], 0);
+
+ STB0899_SETFIELD_VAL(STOP_CKS2DMD108, stop_clk[1], 1);
+ break;
+ default:
+ dprintk(state->verbose, FE_ERROR, 1, "Unsupported delivery system");
+ break;
+ }
+ STB0899_SETFIELD_VAL(STOP_CKADCI108, stop_clk[0], 0);
+ stb0899_write_regs(state, STB0899_STOPCLK1, stop_clk, 2);
+}
+
+/*
+ * stb0899_set_iterations
+ * set the LDPC iteration scale function
+ */
+static void stb0899_set_iterations(struct stb0899_state *state)
+{
+ struct stb0899_internal *internal = &state->internal;
+ struct stb0899_config *config = state->config;
+
+ s32 iter_scale;
+ u32 reg;
+
+ iter_scale = 17 * (internal->master_clk / 1000);
+ iter_scale += 410000;
+ iter_scale /= (internal->srate / 1000000);
+ iter_scale /= 1000;
+
+ if (iter_scale > config->ldpc_max_iter)
+ iter_scale = config->ldpc_max_iter;
+
+ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, MAX_ITER);
+ STB0899_SETFIELD_VAL(MAX_ITERATIONS, reg, iter_scale);
+ stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_MAX_ITER, STB0899_OFF0_MAX_ITER, reg);
+}
+
+static enum dvbfe_search stb0899_search(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+{
+ struct stb0899_state *state = fe->demodulator_priv;
+ struct stb0899_params *i_params = &state->params;
+ struct stb0899_internal *internal = &state->internal;
+ struct stb0899_config *config = state->config;
+ struct dtv_frontend_properties *props = &fe->dtv_property_cache;
+
+ u32 SearchRange, gain;
+
+ i_params->freq = p->frequency;
+ i_params->srate = p->u.qpsk.symbol_rate;
+ state->delsys = props->delivery_system;
+ dprintk(state->verbose, FE_DEBUG, 1, "delivery system=%d", state->delsys);
+
+ SearchRange = 10000000;
+ dprintk(state->verbose, FE_DEBUG, 1, "Frequency=%d, Srate=%d", i_params->freq, i_params->srate);
+ /* checking Search Range is meaningless for a fixed 3 Mhz */
+ if (INRANGE(i_params->srate, 1000000, 45000000)) {
+ dprintk(state->verbose, FE_DEBUG, 1, "Parameters IN RANGE");
+ stb0899_set_delivery(state);
+
+ if (state->config->tuner_set_rfsiggain) {
+ if (internal->srate > 15000000)
+ gain = 8; /* 15Mb < srate < 45Mb, gain = 8dB */
+ else if (internal->srate > 5000000)
+ gain = 12; /* 5Mb < srate < 15Mb, gain = 12dB */
+ else
+ gain = 14; /* 1Mb < srate < 5Mb, gain = 14db */
+ state->config->tuner_set_rfsiggain(fe, gain);
+ }
+
+ if (i_params->srate <= 5000000)
+ stb0899_set_mclk(state, config->lo_clk);
+ else
+ stb0899_set_mclk(state, config->hi_clk);
+
+ switch (state->delsys) {
+ case SYS_DVBS:
+ case SYS_DSS:
+ dprintk(state->verbose, FE_DEBUG, 1, "DVB-S delivery system");
+ internal->freq = i_params->freq;
+ internal->srate = i_params->srate;
+ /*
+ * search = user search range +
+ * 500Khz +
+ * 2 * Tuner_step_size +
+ * 10% of the symbol rate
+ */
+ internal->srch_range = SearchRange + 1500000 + (i_params->srate / 5);
+ internal->derot_percent = 30;
+
+ /* What to do for tuners having no bandwidth setup ? */
+ /* enable tuner I/O */
+ stb0899_i2c_gate_ctrl(&state->frontend, 1);
+
+ if (state->config->tuner_set_bandwidth)
+ state->config->tuner_set_bandwidth(fe, (13 * (stb0899_carr_width(state) + SearchRange)) / 10);
+ if (state->config->tuner_get_bandwidth)
+ state->config->tuner_get_bandwidth(fe, &internal->tuner_bw);
+
+ /* disable tuner I/O */
+ stb0899_i2c_gate_ctrl(&state->frontend, 0);
+
+ /* Set DVB-S1 AGC */
+ stb0899_write_reg(state, STB0899_AGCRFCFG, 0x11);
+
+ /* Run the search algorithm */
+ dprintk(state->verbose, FE_DEBUG, 1, "running DVB-S search algo ..");
+ if (stb0899_dvbs_algo(state) == RANGEOK) {
+ internal->lock = 1;
+ dprintk(state->verbose, FE_DEBUG, 1,
+ "-------------------------------------> DVB-S LOCK !");
+
+// stb0899_write_reg(state, STB0899_ERRCTRL1, 0x3d); /* Viterbi Errors */
+// internal->v_status = stb0899_read_reg(state, STB0899_VSTATUS);
+// internal->err_ctrl = stb0899_read_reg(state, STB0899_ERRCTRL1);
+// dprintk(state->verbose, FE_DEBUG, 1, "VSTATUS=0x%02x", internal->v_status);
+// dprintk(state->verbose, FE_DEBUG, 1, "ERR_CTRL=0x%02x", internal->err_ctrl);
+
+ return DVBFE_ALGO_SEARCH_SUCCESS;
+ } else {
+ internal->lock = 0;
+
+ return DVBFE_ALGO_SEARCH_FAILED;
+ }
+ break;
+ case SYS_DVBS2:
+ internal->freq = i_params->freq;
+ internal->srate = i_params->srate;
+ internal->srch_range = SearchRange;
+
+ /* enable tuner I/O */
+ stb0899_i2c_gate_ctrl(&state->frontend, 1);
+
+ if (state->config->tuner_set_bandwidth)
+ state->config->tuner_set_bandwidth(fe, (stb0899_carr_width(state) + SearchRange));
+ if (state->config->tuner_get_bandwidth)
+ state->config->tuner_get_bandwidth(fe, &internal->tuner_bw);
+
+ /* disable tuner I/O */
+ stb0899_i2c_gate_ctrl(&state->frontend, 0);
+
+// pParams->SpectralInv = pSearch->IQ_Inversion;
+
+ /* Set DVB-S2 AGC */
+ stb0899_write_reg(state, STB0899_AGCRFCFG, 0x1c);
+
+ /* Set IterScale =f(MCLK,SYMB) */
+ stb0899_set_iterations(state);
+
+ /* Run the search algorithm */
+ dprintk(state->verbose, FE_DEBUG, 1, "running DVB-S2 search algo ..");
+ if (stb0899_dvbs2_algo(state) == DVBS2_FEC_LOCK) {
+ internal->lock = 1;
+ dprintk(state->verbose, FE_DEBUG, 1,
+ "-------------------------------------> DVB-S2 LOCK !");
+
+// stb0899_write_reg(state, STB0899_ERRCTRL1, 0xb6); /* Packet Errors */
+// internal->v_status = stb0899_read_reg(state, STB0899_VSTATUS);
+// internal->err_ctrl = stb0899_read_reg(state, STB0899_ERRCTRL1);
+
+ return DVBFE_ALGO_SEARCH_SUCCESS;
+ } else {
+ internal->lock = 0;
+
+ return DVBFE_ALGO_SEARCH_FAILED;
+ }
+ break;
+ default:
+ dprintk(state->verbose, FE_ERROR, 1, "Unsupported delivery system");
+ return DVBFE_ALGO_SEARCH_INVALID;
+ }
+ }
+
+ return DVBFE_ALGO_SEARCH_ERROR;
+}
+#if 0
+static enum stb0899_status stb0899_track_carrier(struct stb0899_state *state)
+{
+ u8 reg;
+
+ reg = stb0899_read_reg(state, STB0899_DSTATUS);
+ dprintk(state->verbose, FE_DEBUG, 1, "--------------------> STB0899_DSTATUS=[0x%02x]", reg);
+ if (STB0899_GETFIELD(CARRIER_FOUND, reg)) {
+ dprintk(state->verbose, FE_DEBUG, 1, "-------------> CARRIEROK !");
+ return CARRIEROK;
+ } else {
+ dprintk(state->verbose, FE_DEBUG, 1, "-------------> NOCARRIER !");
+ return NOCARRIER;
+ }
+
+ return NOCARRIER;
+}
+
+static enum stb0899_status stb0899_get_ifagc(struct stb0899_state *state)
+{
+ u8 reg;
+
+ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_STATUS);
+ dprintk(state->verbose, FE_DEBUG, 1, "DMD_STATUS=[0x%02x]", reg);
+ if (STB0899_GETFIELD(IF_AGC_LOCK, reg)) {
+ dprintk(state->verbose, FE_DEBUG, 1, "------------->IF AGC LOCKED !");
+ return AGC1OK;
+ } else {
+ dprintk(state->verbose, FE_DEBUG, 1, "------------->IF AGC LOCK LOST !");
+ return NOAGC1;
+ }
+
+ return NOAGC1;
+}
+
+static int stb0899_get_s1fec(struct stb0899_internal *internal, enum fe_code_rate *fec)
+{
+ switch (internal->fecrate) {
+ case STB0899_FEC_1_2:
+ *fec = FEC_1_2;
+ break;
+ case STB0899_FEC_2_3:
+ *fec = FEC_2_3;
+ break;
+ case STB0899_FEC_3_4:
+ *fec = FEC_3_4;
+ break;
+ case STB0899_FEC_5_6:
+ *fec = FEC_5_6;
+ break;
+ case STB0899_FEC_6_7:
+ *fec = FEC_6_7;
+ break;
+ case STB0899_FEC_7_8:
+ *fec = FEC_7_8;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int stb0899_get_modcod(struct stb0899_internal *internal, struct dvbs2_params *params)
+{
+ switch (internal->modcod) {
+ case STB0899_DUMMY_PLF:
+ params->modulation = DVBFE_MOD_NONE;
+ params->fec = DVBFE_FEC_NONE;
+ break;
+ case STB0899_QPSK_14:
+ params->modulation = DVBFE_MOD_QPSK;
+ params->fec = DVBFE_FEC_1_4;
+ break;
+ case STB0899_QPSK_13:
+ params->modulation = DVBFE_MOD_QPSK;
+ params->fec = DVBFE_FEC_1_3;
+ break;
+ case STB0899_QPSK_25:
+ params->modulation = DVBFE_MOD_QPSK;
+ params->fec = DVBFE_FEC_2_5;
+ break;
+ case STB0899_QPSK_12:
+ params->modulation = DVBFE_MOD_QPSK;
+ params->fec = DVBFE_FEC_1_2;
+ break;
+ case STB0899_QPSK_35:
+ params->modulation = DVBFE_MOD_QPSK;
+ params->fec = DVBFE_FEC_3_5;
+ break;
+ case STB0899_QPSK_23:
+ params->modulation = DVBFE_MOD_QPSK;
+ params->fec = DVBFE_FEC_2_3;
+ break;
+ case STB0899_QPSK_34:
+ params->modulation = DVBFE_MOD_QPSK;
+ params->fec = DVBFE_FEC_3_4;
+ break;
+ case STB0899_QPSK_45:
+ params->modulation = DVBFE_MOD_QPSK;
+ params->fec = DVBFE_FEC_4_5;
+ break;
+ case STB0899_QPSK_56:
+ params->modulation = DVBFE_MOD_QPSK;
+ params->fec = DVBFE_FEC_5_6;
+ break;
+ case STB0899_QPSK_89:
+ params->modulation = DVBFE_MOD_QPSK;
+ params->fec = DVBFE_FEC_8_9;
+ break;
+ case STB0899_QPSK_910:
+ params->modulation = DVBFE_MOD_QPSK;
+ params->fec = DVBFE_FEC_9_10;
+ break;
+ case STB0899_8PSK_35:
+ params->modulation = DVBFE_MOD_8PSK;
+ params->fec = DVBFE_FEC_3_5;
+ break;
+ case STB0899_8PSK_23:
+ params->modulation = DVBFE_MOD_8PSK;
+ params->fec = DVBFE_FEC_2_3;
+ break;
+ case STB0899_8PSK_34:
+ params->modulation = DVBFE_MOD_8PSK;
+ params->fec = DVBFE_FEC_3_4;
+ break;
+ case STB0899_8PSK_56:
+ params->modulation = DVBFE_MOD_8PSK;
+ params->fec = DVBFE_FEC_5_6;
+ break;
+ case STB0899_8PSK_89:
+ params->modulation = DVBFE_MOD_8PSK;
+ params->fec = DVBFE_FEC_8_9;
+ break;
+ case STB0899_8PSK_910:
+ params->modulation = DVBFE_MOD_8PSK;
+ params->fec = DVBFE_FEC_9_10;
+ break;
+ case STB0899_16APSK_23:
+ params->modulation = DVBFE_MOD_16APSK;
+ params->fec = DVBFE_FEC_2_3;
+ break;
+ case STB0899_16APSK_34:
+ params->modulation = DVBFE_MOD_16APSK;
+ params->fec = DVBFE_FEC_3_4;
+ break;
+ case STB0899_16APSK_45:
+ params->modulation = DVBFE_MOD_16APSK;
+ params->fec = DVBFE_FEC_4_5;
+ break;
+ case STB0899_16APSK_56:
+ params->modulation = DVBFE_MOD_16APSK;
+ params->fec = DVBFE_FEC_5_6;
+ break;
+ case STB0899_16APSK_89:
+ params->modulation = DVBFE_MOD_16APSK;
+ params->fec = DVBFE_FEC_8_9;
+ break;
+ case STB0899_16APSK_910:
+ params->modulation = DVBFE_MOD_16APSK;
+ params->fec = DVBFE_FEC_9_10;
+ break;
+ case STB0899_32APSK_34:
+ params->modulation = DVBFE_MOD_32APSK;
+ params->fec = DVBFE_FEC_3_4;
+ break;
+ case STB0899_32APSK_45:
+ params->modulation = DVBFE_MOD_32APSK;
+ params->fec = DVBFE_FEC_4_5;
+ break;
+ case STB0899_32APSK_56:
+ params->modulation = DVBFE_MOD_32APSK;
+ params->fec = DVBFE_FEC_5_6;
+ break;
+ case STB0899_32APSK_89:
+ params->modulation = DVBFE_MOD_32APSK;
+ params->fec = DVBFE_FEC_8_9;
+ break;
+ case STB0899_32APSK_910:
+ params->modulation = DVBFE_MOD_32APSK;
+ params->fec = DVBFE_FEC_9_10;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+#endif
+/*
+ * stb0899_track
+ * periodically check the signal level against a specified
+ * threshold level and perform derotator centering.
+ * called once we have a lock from a succesful search
+ * event.
+ *
+ * Will be called periodically called to maintain the
+ * lock.
+ *
+ * Will be used to get parameters as well as info from
+ * the decoded baseband header
+ *
+ * Once a new lock has established, the internal state
+ * frequency (internal->freq) is updated
+ */
+static int stb0899_track(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+{
+#if 0
+ u32 lock_lost;
+
+ struct stb0899_state *state = fe->demodulator_priv;
+ struct stb0899_internal *internal = &state->internal;
+
+ switch (state->delsys) {
+ case DVBFE_DELSYS_DVBS:
+ dprintk(state->verbose, FE_DEBUG, 1, "Tracking DVB-S state");
+ if (stb0899_track_carrier(state) == CARRIEROK) {
+ params->frequency = internal->freq;
+ params->inversion = internal->inversion;
+ params->delivery = state->delsys;
+ params->delsys.dvbs.symbol_rate = internal->srate;
+ params->delsys.dvbs.modulation = DVBFE_MOD_QPSK;
+ stb0899_get_s1fec(internal, &params->delsys.dvbs.fec);
+ }
+ break;
+ case DVBFE_DELSYS_DSS:
+ dprintk(state->verbose, FE_DEBUG, 1, "Tracking DSS state");
+ if (stb0899_track_carrier(state) == CARRIEROK) {
+ params->frequency = internal->freq;
+ params->inversion = internal->inversion;
+ params->delivery = state->delsys;
+ params->delsys.dss.symbol_rate = internal->srate;
+ params->delsys.dss.modulation = DVBFE_MOD_QPSK;
+ stb0899_get_s1fec(internal, &params->delsys.dss.fec);
+ }
+ break;
+ case DVBFE_DELSYS_DVBS2:
+ dprintk(state->verbose, FE_DEBUG, 1, "Tracking DVB-S2 state");
+ if (stb0899_get_ifagc(state) == AGC1OK) {
+ params->frequency = internal->freq;
+ params->inversion = internal->inversion;
+ params->delivery = state->delsys;
+ params->delsys.dvbs2.symbol_rate = internal->srate;
+ stb0899_get_modcod(internal, &params->delsys.dvbs2);
+ params->delsys.dvbs2.rolloff = internal->rolloff;
+ params->delsys.dvbs2.matype_1 = stb0899_read_reg(state, STB0899_MATSTRL);
+ params->delsys.dvbs2.matype_2 = stb0899_read_reg(state, STB0899_MATSTRM);
+ params->delsys.dvbs2.upl_1 = stb0899_read_reg(state, STB0899_UPLSTRL);
+ params->delsys.dvbs2.upl_2 = stb0899_read_reg(state, STB0899_UPLSTRM);
+ params->delsys.dvbs2.dfl_1 = stb0899_read_reg(state, STB0899_DFLSTRL);
+ params->delsys.dvbs2.dfl_2 = stb0899_read_reg(state, STB0899_DFLSTRM);
+ params->delsys.dvbs2.sync = stb0899_read_reg(state, STB0899_SYNCSTR);
+ params->delsys.dvbs2.syncd_1 = stb0899_read_reg(state, STB0899_SYNCDSTRL);
+ params->delsys.dvbs2.syncd_2 = stb0899_read_reg(state, STB0899_SYNCDSTRM);
+ }
+ lock_lost = STB0899_READ_S2REG(STB0899_S2DEMOD, LOCK_LOST);
+ dprintk(state->verbose, FE_DEBUG, 1, "Lock Lost=[0x%02x]\n", lock_lost);
+ if (STB0899_GETFIELD(LOCK_LOST, lock_lost))
+ dprintk(state->verbose, FE_ERROR, 1, "Demodulator LOST LOCK !\n");
+ break;
+ default:
+ dprintk(state->verbose, FE_ERROR, 1, "Unsupported delivery system");
+ return -EINVAL;
+ }
+
+// *delay = HZ/10;
+#endif
+ return 0;
+}
+
+static int stb0899_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+{
+ struct stb0899_state *state = fe->demodulator_priv;
+ struct stb0899_internal *internal = &state->internal;
+
+ dprintk(state->verbose, FE_DEBUG, 1, "Get params");
+ p->u.qpsk.symbol_rate = internal->srate;
+
+ return 0;
+}
+
+static enum dvbfe_algo stb0899_frontend_algo(struct dvb_frontend *fe)
+{
+ return DVBFE_ALGO_CUSTOM;
+}
+
+static struct dvb_frontend_ops stb0899_ops = {
+
+ .info = {
+ .name = "STB0899 Multistandard",
+ .type = FE_QPSK,
+ .frequency_min = 950000,
+ .frequency_max = 2150000,
+ .frequency_stepsize = 0,
+ .frequency_tolerance = 0,
+ .symbol_rate_min = 5000000,
+ .symbol_rate_max = 45000000,
+
+ .caps = FE_CAN_INVERSION_AUTO |
+ FE_CAN_FEC_AUTO |
+ FE_CAN_QPSK
+ },
+
+ .release = stb0899_release,
+ .init = stb0899_init,
+ .sleep = stb0899_sleep,
+// .wakeup = stb0899_wakeup,
+
+ .i2c_gate_ctrl = stb0899_i2c_gate_ctrl,
+
+ .get_frontend_algo = stb0899_frontend_algo,
+ .search = stb0899_search,
+ .track = stb0899_track,
+ .get_frontend = stb0899_get_frontend,
+
+
+ .read_status = stb0899_read_status,
+ .read_snr = stb0899_read_snr,
+ .read_signal_strength = stb0899_read_signal_strength,
+ .read_ber = stb0899_read_ber,
+
+ .set_voltage = stb0899_set_voltage,
+ .set_tone = stb0899_set_tone,
+
+ .diseqc_send_master_cmd = stb0899_send_diseqc_msg,
+ .diseqc_recv_slave_reply = stb0899_recv_slave_reply,
+ .diseqc_send_burst = stb0899_send_diseqc_burst,
+};
+
+struct dvb_frontend *stb0899_attach(struct stb0899_config *config, struct i2c_adapter *i2c)
+{
+ struct stb0899_state *state = NULL;
+ enum stb0899_inversion inversion;
+
+ state = kzalloc(sizeof (struct stb0899_state), GFP_KERNEL);
+ if (state == NULL)
+ goto error;
+
+ inversion = config->inversion;
+ state->verbose = &verbose;
+ state->config = config;
+ state->i2c = i2c;
+ state->frontend.ops = stb0899_ops;
+ state->frontend.demodulator_priv = state;
+ state->internal.inversion = inversion;
+
+ stb0899_wakeup(&state->frontend);
+ if (stb0899_get_dev_id(state) == -ENODEV) {
+ printk("%s: Exiting .. !\n", __func__);
+ goto error;
+ }
+
+ printk("%s: Attaching STB0899 \n", __func__);
+ return &state->frontend;
+
+error:
+ kfree(state);
+ return NULL;
+}
+EXPORT_SYMBOL(stb0899_attach);
+MODULE_PARM_DESC(verbose, "Set Verbosity level");
+MODULE_AUTHOR("Manu Abraham");
+MODULE_DESCRIPTION("STB0899 Multi-Std frontend");
+MODULE_LICENSE("GPL");
diff --git a/linux/drivers/media/dvb/frontends/stb0899_drv.h b/linux/drivers/media/dvb/frontends/stb0899_drv.h
new file mode 100644
index 000000000..98b200ce0
--- /dev/null
+++ b/linux/drivers/media/dvb/frontends/stb0899_drv.h
@@ -0,0 +1,162 @@
+/*
+ STB0899 Multistandard Frontend driver
+ Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+ Copyright (C) ST Microelectronics
+
+ 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 __STB0899_DRV_H
+#define __STB0899_DRV_H
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "dvb_frontend.h"
+
+#define STB0899_TSMODE_SERIAL 1
+#define STB0899_CLKPOL_FALLING 2
+#define STB0899_CLKNULL_PARITY 3
+#define STB0899_SYNC_FORCED 4
+#define STB0899_FECMODE_DSS 5
+
+struct stb0899_s1_reg {
+ u16 address;
+ u8 data;
+};
+
+struct stb0899_s2_reg {
+ u16 offset;
+ u32 base_address;
+ u32 data;
+};
+
+enum stb0899_inversion {
+ IQ_SWAP_OFF = 0,
+ IQ_SWAP_ON,
+ IQ_SWAP_AUTO
+};
+
+#define STB0899_GPIO00 0xf140
+#define STB0899_GPIO01 0xf141
+#define STB0899_GPIO02 0xf142
+#define STB0899_GPIO03 0xf143
+#define STB0899_GPIO04 0xf144
+#define STB0899_GPIO05 0xf145
+#define STB0899_GPIO06 0xf146
+#define STB0899_GPIO07 0xf147
+#define STB0899_GPIO08 0xf148
+#define STB0899_GPIO09 0xf149
+#define STB0899_GPIO10 0xf14a
+#define STB0899_GPIO11 0xf14b
+#define STB0899_GPIO12 0xf14c
+#define STB0899_GPIO13 0xf14d
+#define STB0899_GPIO14 0xf14e
+#define STB0899_GPIO15 0xf14f
+#define STB0899_GPIO16 0xf150
+#define STB0899_GPIO17 0xf151
+#define STB0899_GPIO18 0xf152
+#define STB0899_GPIO19 0xf153
+#define STB0899_GPIO20 0xf154
+
+#define STB0899_GPIOPULLUP 0x01 /* Output device is connected to Vdd */
+#define STB0899_GPIOPULLDN 0x00 /* Output device is connected to Vss */
+
+#define STB0899_POSTPROC_GPIO_POWER 0x00
+#define STB0899_POSTPROC_GPIO_LOCK 0x01
+
+/*
+ * Post process output configuration control
+ * 1. POWER ON/OFF (index 0)
+ * 2. FE_HAS_LOCK/LOCK_LOSS (index 1)
+ *
+ * @gpio = one of the above listed GPIO's
+ * @level = output state: pulled up or low
+ */
+struct stb0899_postproc {
+ u16 gpio;
+ u8 level;
+};
+
+struct stb0899_config {
+ const struct stb0899_s1_reg *init_dev;
+ const struct stb0899_s2_reg *init_s2_demod;
+ const struct stb0899_s1_reg *init_s1_demod;
+ const struct stb0899_s2_reg *init_s2_fec;
+ const struct stb0899_s1_reg *init_tst;
+
+ const struct stb0899_postproc *postproc;
+
+ enum stb0899_inversion inversion;
+
+ u32 xtal_freq;
+
+ u8 demod_address;
+ u8 ts_output_mode;
+ u8 block_sync_mode;
+ u8 ts_pfbit_toggle;
+
+ u8 clock_polarity;
+ u8 data_clk_parity;
+ u8 fec_mode;
+ u8 data_output_ctl;
+ u8 data_fifo_mode;
+ u8 out_rate_comp;
+ u8 i2c_repeater;
+// int inversion;
+ int lo_clk;
+ int hi_clk;
+
+ u32 esno_ave;
+ u32 esno_quant;
+ u32 avframes_coarse;
+ u32 avframes_fine;
+ u32 miss_threshold;
+ u32 uwp_threshold_acq;
+ u32 uwp_threshold_track;
+ u32 uwp_threshold_sof;
+ u32 sof_search_timeout;
+
+ u32 btr_nco_bits;
+ u32 btr_gain_shift_offset;
+ u32 crl_nco_bits;
+ u32 ldpc_max_iter;
+
+ int (*tuner_set_frequency)(struct dvb_frontend *fe, u32 frequency);
+ int (*tuner_get_frequency)(struct dvb_frontend *fe, u32 *frequency);
+ int (*tuner_set_bandwidth)(struct dvb_frontend *fe, u32 bandwidth);
+ int (*tuner_get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth);
+ int (*tuner_set_rfsiggain)(struct dvb_frontend *fe, u32 rf_gain);
+};
+
+#if defined(CONFIG_DVB_STB0899) || (defined(CONFIG_DVB_STB0899_MODULE) && defined(MODULE))
+
+extern struct dvb_frontend *stb0899_attach(struct stb0899_config *config,
+ struct i2c_adapter *i2c);
+
+#else
+
+static inline struct dvb_frontend *stb0899_attach(struct stb0899_config *config,
+ struct i2c_adapter *i2c)
+{
+ printk(KERN_WARNING "%s: Driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+
+#endif //CONFIG_DVB_STB0899
+
+
+#endif
diff --git a/linux/drivers/media/dvb/frontends/stb0899_priv.h b/linux/drivers/media/dvb/frontends/stb0899_priv.h
new file mode 100644
index 000000000..e57ff227b
--- /dev/null
+++ b/linux/drivers/media/dvb/frontends/stb0899_priv.h
@@ -0,0 +1,274 @@
+/*
+ STB0899 Multistandard Frontend driver
+ Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+ Copyright (C) ST Microelectronics
+
+ 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 __STB0899_PRIV_H
+#define __STB0899_PRIV_H
+
+#include "dvb_frontend.h"
+#include "stb0899_drv.h"
+
+#define FE_ERROR 0
+#define FE_NOTICE 1
+#define FE_INFO 2
+#define FE_DEBUG 3
+#define FE_DEBUGREG 4
+
+#define dprintk(x, y, z, format, arg...) do { \
+ if (z) { \
+ if ((*x > FE_ERROR) && (*x > y)) \
+ printk(KERN_ERR "%s: " format "\n", __func__ , ##arg); \
+ else if ((*x > FE_NOTICE) && (*x > y)) \
+ printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg); \
+ else if ((*x > FE_INFO) && (*x > y)) \
+ printk(KERN_INFO "%s: " format "\n", __func__ , ##arg); \
+ else if ((*x > FE_DEBUG) && (*x > y)) \
+ printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg); \
+ } else { \
+ if (*x > y) \
+ printk(format, ##arg); \
+ } \
+} while(0)
+
+#define INRANGE(val, x, y) (((x <= val) && (val <= y)) || \
+ ((y <= val) && (val <= x)) ? 1 : 0)
+
+#define BYTE0 0
+#define BYTE1 8
+#define BYTE2 16
+#define BYTE3 24
+
+#define GETBYTE(x, y) (((x) >> (y)) & 0xff)
+#define MAKEWORD32(a, b, c, d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
+#define MAKEWORD16(a, b) (((a) << 8) | (b))
+
+#define MIN(x, y) ((x) <= (y) ? (x) : (y))
+#define MAX(x, y) ((x) >= (y) ? (x) : (y))
+#define ABS(x) ((x) >= 0 ? (x) : -(x))
+
+#define LSB(x) ((x & 0xff))
+#define MSB(y) ((y >> 8) & 0xff)
+
+
+#define STB0899_GETFIELD(bitf, val) ((val >> STB0899_OFFST_##bitf) & ((1 << STB0899_WIDTH_##bitf) - 1))
+
+
+#define STB0899_SETFIELD(mask, val, width, offset) (mask & (~(((1 << width) - 1) << \
+ offset))) | ((val & \
+ ((1 << width) - 1)) << offset)
+
+#define STB0899_SETFIELD_VAL(bitf, mask, val) (mask = (mask & (~(((1 << STB0899_WIDTH_##bitf) - 1) <<\
+ STB0899_OFFST_##bitf))) | \
+ (val << STB0899_OFFST_##bitf))
+
+
+enum stb0899_status {
+ NOAGC1 = 0,
+ AGC1OK,
+ NOTIMING,
+ ANALOGCARRIER,
+ TIMINGOK,
+ NOAGC2,
+ AGC2OK,
+ NOCARRIER,
+ CARRIEROK,
+ NODATA,
+ FALSELOCK,
+ DATAOK,
+ OUTOFRANGE,
+ RANGEOK,
+ DVBS2_DEMOD_LOCK,
+ DVBS2_DEMOD_NOLOCK,
+ DVBS2_FEC_LOCK,
+ DVBS2_FEC_NOLOCK
+};
+
+enum stb0899_modcod {
+ STB0899_DUMMY_PLF,
+ STB0899_QPSK_14,
+ STB0899_QPSK_13,
+ STB0899_QPSK_25,
+ STB0899_QPSK_12,
+ STB0899_QPSK_35,
+ STB0899_QPSK_23,
+ STB0899_QPSK_34,
+ STB0899_QPSK_45,
+ STB0899_QPSK_56,
+ STB0899_QPSK_89,
+ STB0899_QPSK_910,
+ STB0899_8PSK_35,
+ STB0899_8PSK_23,
+ STB0899_8PSK_34,
+ STB0899_8PSK_56,
+ STB0899_8PSK_89,
+ STB0899_8PSK_910,
+ STB0899_16APSK_23,
+ STB0899_16APSK_34,
+ STB0899_16APSK_45,
+ STB0899_16APSK_56,
+ STB0899_16APSK_89,
+ STB0899_16APSK_910,
+ STB0899_32APSK_34,
+ STB0899_32APSK_45,
+ STB0899_32APSK_56,
+ STB0899_32APSK_89,
+ STB0899_32APSK_910
+};
+
+enum stb0899_frame {
+ STB0899_LONG_FRAME,
+ STB0899_SHORT_FRAME
+};
+
+enum stb0899_alpha {
+ RRC_20,
+ RRC_25,
+ RRC_35
+};
+
+struct stb0899_tab {
+ s32 real;
+ s32 read;
+};
+
+enum stb0899_fec {
+ STB0899_FEC_1_2 = 13,
+ STB0899_FEC_2_3 = 18,
+ STB0899_FEC_3_4 = 21,
+ STB0899_FEC_5_6 = 24,
+ STB0899_FEC_6_7 = 25,
+ STB0899_FEC_7_8 = 26
+};
+
+struct stb0899_params {
+ u32 freq; /* Frequency */
+ u32 srate; /* Symbol rate */
+ enum fe_code_rate fecrate;
+};
+
+struct stb0899_internal {
+ u32 master_clk;
+ u32 freq; /* Demod internal Frequency */
+ u32 srate; /* Demod internal Symbol rate */
+ enum stb0899_fec fecrate; /* Demod internal FEC rate */
+ u32 srch_range; /* Demod internal Search Range */
+ u32 sub_range; /* Demod current sub range (Hz) */
+ u32 tuner_step; /* Tuner step (Hz) */
+ u32 tuner_offst; /* Relative offset to carrier (Hz) */
+ u32 tuner_bw; /* Current bandwidth of the tuner (Hz) */
+
+ s32 mclk; /* Masterclock Divider factor (binary) */
+ s32 rolloff; /* Current RollOff of the filter (x100) */
+
+ s16 derot_freq; /* Current derotator frequency (Hz) */
+ s16 derot_percent;
+
+ s16 direction; /* Current derotator search direction */
+ s16 derot_step; /* Derotator step (binary value) */
+ s16 t_derot; /* Derotator time constant (ms) */
+ s16 t_data; /* Data recovery time constant (ms) */
+ s16 sub_dir; /* Direction of the next sub range */
+
+ s16 t_agc1; /* Agc1 time constant (ms) */
+ s16 t_agc2; /* Agc2 time constant (ms) */
+
+ u32 lock; /* Demod internal lock state */
+ enum stb0899_status status; /* Demod internal status */
+
+ /* DVB-S2 */
+ s32 agc_gain; /* RF AGC Gain */
+ s32 center_freq; /* Nominal carrier frequency */
+ s32 av_frame_coarse; /* Coarse carrier freq search frames */
+ s32 av_frame_fine; /* Fine carrier freq search frames */
+
+ s16 step_size; /* Carrier frequency search step size */
+
+ enum stb0899_alpha rrc_alpha;
+ enum stb0899_inversion inversion;
+ enum stb0899_modcod modcod;
+ u8 pilots; /* Pilots found */
+
+ enum stb0899_frame frame_length;
+ u8 v_status; /* VSTATUS */
+ u8 err_ctrl; /* ERRCTRLn */
+};
+
+struct stb0899_state {
+ struct i2c_adapter *i2c;
+ struct stb0899_config *config;
+ struct dvb_frontend frontend;
+
+ u32 *verbose; /* Cached module verbosity level */
+
+ struct stb0899_internal internal; /* Device internal parameters */
+
+ /* cached params from API */
+ enum fe_delivery_system delsys;
+ struct stb0899_params params;
+
+ u32 rx_freq; /* DiSEqC 2.0 receiver freq */
+ struct mutex search_lock;
+};
+/* stb0899.c */
+extern int stb0899_read_reg(struct stb0899_state *state,
+ unsigned int reg);
+
+extern u32 _stb0899_read_s2reg(struct stb0899_state *state,
+ u32 stb0899_i2cdev,
+ u32 stb0899_base_addr,
+ u16 stb0899_reg_offset);
+
+extern int stb0899_read_regs(struct stb0899_state *state,
+ unsigned int reg, u8 *buf,
+ u32 count);
+
+extern int stb0899_write_regs(struct stb0899_state *state,
+ unsigned int reg, u8 *data,
+ u32 count);
+
+extern int stb0899_write_reg(struct stb0899_state *state,
+ unsigned int reg,
+ u8 data);
+
+extern int stb0899_write_s2reg(struct stb0899_state *state,
+ u32 stb0899_i2cdev,
+ u32 stb0899_base_addr,
+ u16 stb0899_reg_offset,
+ u32 stb0899_data);
+
+extern int stb0899_i2c_gate_ctrl(struct dvb_frontend *fe, int enable);
+
+#if 0
+extern int _stb0899_write_s2reg(struct stb0899_state *state,
+ u32 stb0899_i2cdev,
+ u32 stb0899_base_addr,
+ u16 stb0899_reg_offset,
+ u32 stb0899_data);
+#endif
+
+#define STB0899_READ_S2REG(DEVICE, REG) (_stb0899_read_s2reg(state, DEVICE, STB0899_BASE_##REG, STB0899_OFF0_##REG))
+//#define STB0899_WRITE_S2REG(DEVICE, REG, DATA) (_stb0899_write_s2reg(state, DEVICE, STB0899_BASE_##REG, STB0899_OFF0_##REG, DATA))
+
+/* stb0899_algo.c */
+extern enum stb0899_status stb0899_dvbs_algo(struct stb0899_state *state);
+extern enum stb0899_status stb0899_dvbs2_algo(struct stb0899_state *state);
+extern long stb0899_carr_width(struct stb0899_state *state);
+
+#endif //__STB0899_PRIV_H
diff --git a/linux/drivers/media/dvb/frontends/stb0899_reg.h b/linux/drivers/media/dvb/frontends/stb0899_reg.h
new file mode 100644
index 000000000..ba1ed5630
--- /dev/null
+++ b/linux/drivers/media/dvb/frontends/stb0899_reg.h
@@ -0,0 +1,2027 @@
+/*
+ STB0899 Multistandard Frontend driver
+ Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+ Copyright (C) ST Microelectronics
+
+ 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 __STB0899_REG_H
+#define __STB0899_REG_H
+
+/* S1 */
+#define STB0899_DEV_ID 0xf000
+#define STB0899_CHIP_ID (0x0f << 4)
+#define STB0899_OFFST_CHIP_ID 4
+#define STB0899_WIDTH_CHIP_ID 4
+#define STB0899_CHIP_REL (0x0f << 0)
+#define STB0899_OFFST_CHIP_REL 0
+#define STB0899_WIDTH_CHIP_REL 4
+
+#define STB0899_DEMOD 0xf40e
+#define STB0899_MODECOEFF (0x01 << 0)
+#define STB0899_OFFST_MODECOEFF 0
+#define STB0899_WIDTH_MODECOEFF 1
+
+#define STB0899_RCOMPC 0xf410
+#define STB0899_AGC1CN 0xf412
+#define STB0899_AGC1REF 0xf413
+#define STB0899_RTC 0xf417
+#define STB0899_TMGCFG 0xf418
+#define STB0899_AGC2REF 0xf419
+#define STB0899_TLSR 0xf41a
+
+#define STB0899_CFD 0xf41b
+#define STB0899_CFD_ON (0x01 << 7)
+#define STB0899_OFFST_CFD_ON 7
+#define STB0899_WIDTH_CFD_ON 1
+
+#define STB0899_ACLC 0xf41c
+
+#define STB0899_BCLC 0xf41d
+#define STB0899_OFFST_ALGO 6
+#define STB0899_WIDTH_ALGO_QPSK2 2
+#define STB0899_ALGO_QPSK2 (2 << 6)
+#define STB0899_ALGO_QPSK1 (1 << 6)
+#define STB0899_ALGO_BPSK (0 << 6)
+#define STB0899_OFFST_BETA 0
+#define STB0899_WIDTH_BETA 6
+
+#define STB0899_EQON 0xf41e
+#define STB0899_LDT 0xf41f
+#define STB0899_LDT2 0xf420
+#define STB0899_EQUALREF 0xf425
+#define STB0899_TMGRAMP 0xf426
+#define STB0899_TMGTHD 0xf427
+#define STB0899_IDCCOMP 0xf428
+#define STB0899_QDCCOMP 0xf429
+#define STB0899_POWERI 0xf42a
+#define STB0899_POWERQ 0xf42b
+#define STB0899_RCOMP 0xf42c
+
+#define STB0899_AGCIQIN 0xf42e
+#define STB0899_AGCIQVALUE (0xff << 0)
+#define STB0899_OFFST_AGCIQVALUE 0
+#define STB0899_WIDTH_AGCIQVALUE 8
+
+#define STB0899_AGC2I1 0xf436
+#define STB0899_AGC2I2 0xf437
+
+#define STB0899_TLIR 0xf438
+#define STB0899_TLIR_TMG_LOCK_IND (0xff << 0)
+#define STB0899_OFFST_TLIR_TMG_LOCK_IND 0
+#define STB0899_WIDTH_TLIR_TMG_LOCK_IND 8
+
+#define STB0899_RTF 0xf439
+#define STB0899_RTF_TIMING_LOOP_FREQ (0xff << 0)
+#define STB0899_OFFST_RTF_TIMING_LOOP_FREQ 0
+#define STB0899_WIDTH_RTF_TIMING_LOOP_FREQ 8
+
+#define STB0899_DSTATUS 0xf43a
+#define STB0899_CARRIER_FOUND (0x01 << 7)
+#define STB0899_OFFST_CARRIER_FOUND 7
+#define STB0899_WIDTH_CARRIER_FOUND 1
+#define STB0899_TMG_LOCK (0x01 << 6)
+#define STB0899_OFFST_TMG_LOCK 6
+#define STB0899_WIDTH_TMG_LOCK 1
+#define STB0899_DEMOD_LOCK (0x01 << 5)
+#define STB0899_OFFST_DEMOD_LOCK 5
+#define STB0899_WIDTH_DEMOD_LOCK 1
+#define STB0899_TMG_AUTO (0x01 << 4)
+#define STB0899_OFFST_TMG_AUTO 4
+#define STB0899_WIDTH_TMG_AUTO 1
+#define STB0899_END_MAIN (0x01 << 3)
+#define STB0899_OFFST_END_MAIN 3
+#define STB0899_WIDTH_END_MAIN 1
+
+#define STB0899_LDI 0xf43b
+#define STB0899_OFFST_LDI 0
+#define STB0899_WIDTH_LDI 8
+
+#define STB0899_CFRM 0xf43e
+#define STB0899_OFFST_CFRM 0
+#define STB0899_WIDTH_CFRM 8
+
+#define STB0899_CFRL 0xf43f
+#define STB0899_OFFST_CFRL 0
+#define STB0899_WIDTH_CFRL 8
+
+#define STB0899_NIRM 0xf440
+#define STB0899_OFFST_NIRM 0
+#define STB0899_WIDTH_NIRM 8
+
+#define STB0899_NIRL 0xf441
+#define STB0899_OFFST_NIRL 0
+#define STB0899_WIDTH_NIRL 8
+
+#define STB0899_ISYMB 0xf444
+#define STB0899_QSYMB 0xf445
+
+#define STB0899_SFRH 0xf446
+#define STB0899_OFFST_SFRH 0
+#define STB0899_WIDTH_SFRH 8
+
+#define STB0899_SFRM 0xf447
+#define STB0899_OFFST_SFRM 0
+#define STB0899_WIDTH_SFRM 8
+
+#define STB0899_SFRL 0xf448
+#define STB0899_OFFST_SFRL 4
+#define STB0899_WIDTH_SFRL 4
+
+#define STB0899_SFRUPH 0xf44c
+#define STB0899_SFRUPM 0xf44d
+#define STB0899_SFRUPL 0xf44e
+
+#define STB0899_EQUAI1 0xf4e0
+#define STB0899_EQUAQ1 0xf4e1
+#define STB0899_EQUAI2 0xf4e2
+#define STB0899_EQUAQ2 0xf4e3
+#define STB0899_EQUAI3 0xf4e4
+#define STB0899_EQUAQ3 0xf4e5
+#define STB0899_EQUAI4 0xf4e6
+#define STB0899_EQUAQ4 0xf4e7
+#define STB0899_EQUAI5 0xf4e8
+#define STB0899_EQUAQ5 0xf4e9
+
+#define STB0899_DSTATUS2 0xf50c
+#define STB0899_DS2_TMG_AUTOSRCH (0x01 << 7)
+#define STB8999_OFFST_DS2_TMG_AUTOSRCH 7
+#define STB0899_WIDTH_DS2_TMG_AUTOSRCH 1
+#define STB0899_DS2_END_MAINLOOP (0x01 << 6)
+#define STB0899_OFFST_DS2_END_MAINLOOP 6
+#define STB0899_WIDTH_DS2_END_MAINLOOP 1
+#define STB0899_DS2_CFSYNC (0x01 << 5)
+#define STB0899_OFFST_DS2_CFSYNC 5
+#define STB0899_WIDTH_DS2_CFSYNC 1
+#define STB0899_DS2_TMGLOCK (0x01 << 4)
+#define STB0899_OFFST_DS2_TMGLOCK 4
+#define STB0899_WIDTH_DS2_TMGLOCK 1
+#define STB0899_DS2_DEMODWAIT (0x01 << 3)
+#define STB0899_OFFST_DS2_DEMODWAIT 3
+#define STB0899_WIDTH_DS2_DEMODWAIT 1
+#define STB0899_DS2_FECON (0x01 << 1)
+#define STB0899_OFFST_DS2_FECON 1
+#define STB0899_WIDTH_DS2_FECON 1
+
+/* S1 FEC */
+#define STB0899_VSTATUS 0xf50d
+#define STB0899_VSTATUS_VITERBI_ON (0x01 << 7)
+#define STB0899_OFFST_VSTATUS_VITERBI_ON 7
+#define STB0899_WIDTH_VSTATUS_VITERBI_ON 1
+#define STB0899_VSTATUS_END_LOOPVIT (0x01 << 6)
+#define STB0899_OFFST_VSTATUS_END_LOOPVIT 6
+#define STB0899_WIDTH_VSTATUS_END_LOOPVIT 1
+#define STB0899_VSTATUS_PRFVIT (0x01 << 4)
+#define STB0899_OFFST_VSTATUS_PRFVIT 4
+#define STB0899_WIDTH_VSTATUS_PRFVIT 1
+#define STB0899_VSTATUS_LOCKEDVIT (0x01 << 3)
+#define STB0899_OFFST_VSTATUS_LOCKEDVIT 3
+#define STB0899_WIDTH_VSTATUS_LOCKEDVIT 1
+
+#define STB0899_VERROR 0xf50f
+
+#define STB0899_IQSWAP 0xf523
+#define STB0899_SYM (0x01 << 3)
+#define STB0899_OFFST_SYM 3
+#define STB0899_WIDTH_SYM 1
+
+#define STB0899_FECAUTO1 0xf530
+#define STB0899_DSSSRCH (0x01 << 3)
+#define STB0899_OFFST_DSSSRCH 3
+#define STB0899_WIDTH_DSSSRCH 1
+#define STB0899_SYMSRCH (0x01 << 2)
+#define STB0899_OFFST_SYMSRCH 2
+#define STB0899_WIDTH_SYMSRCH 1
+#define STB0899_QPSKSRCH (0x01 << 1)
+#define STB0899_OFFST_QPSKSRCH 1
+#define STB0899_WIDTH_QPSKSRCH 1
+#define STB0899_BPSKSRCH (0x01 << 0)
+#define STB0899_OFFST_BPSKSRCH 0
+#define STB0899_WIDTH_BPSKSRCH 1
+
+#define STB0899_FECM 0xf533
+#define STB0899_FECM_NOT_DVB (0x01 << 7)
+#define STB0899_OFFST_FECM_NOT_DVB 7
+#define STB0899_WIDTH_FECM_NOT_DVB 1
+#define STB0899_FECM_RSVD1 (0x07 << 4)
+#define STB0899_OFFST_FECM_RSVD1 4
+#define STB0899_WIDTH_FECM_RSVD1 3
+#define STB0899_FECM_VITERBI_ON (0x01 << 3)
+#define STB0899_OFFST_FECM_VITERBI_ON 3
+#define STB0899_WIDTH_FECM_VITERBI_ON 1
+#define STB0899_FECM_RSVD0 (0x01 << 2)
+#define STB0899_OFFST_FECM_RSVD0 2
+#define STB0899_WIDTH_FECM_RSVD0 1
+#define STB0899_FECM_SYNCDIS (0x01 << 1)
+#define STB0899_OFFST_FECM_SYNCDIS 1
+#define STB0899_WIDTH_FECM_SYNCDIS 1
+#define STB0899_FECM_SYMI (0x01 << 0)
+#define STB0899_OFFST_FECM_SYMI 0
+#define STB0899_WIDTH_FECM_SYMI 1
+
+#define STB0899_VTH12 0xf534
+#define STB0899_VTH23 0xf535
+#define STB0899_VTH34 0xf536
+#define STB0899_VTH56 0xf537
+#define STB0899_VTH67 0xf538
+#define STB0899_VTH78 0xf539
+
+#define STB0899_PRVIT 0xf53c
+#define STB0899_PR_7_8 (0x01 << 5)
+#define STB0899_OFFST_PR_7_8 5
+#define STB0899_WIDTH_PR_7_8 1
+#define STB0899_PR_6_7 (0x01 << 4)
+#define STB0899_OFFST_PR_6_7 4
+#define STB0899_WIDTH_PR_6_7 1
+#define STB0899_PR_5_6 (0x01 << 3)
+#define STB0899_OFFST_PR_5_6 3
+#define STB0899_WIDTH_PR_5_6 1
+#define STB0899_PR_3_4 (0x01 << 2)
+#define STB0899_OFFST_PR_3_4 2
+#define STB0899_WIDTH_PR_3_4 1
+#define STB0899_PR_2_3 (0x01 << 1)
+#define STB0899_OFFST_PR_2_3 1
+#define STB0899_WIDTH_PR_2_3 1
+#define STB0899_PR_1_2 (0x01 << 0)
+#define STB0899_OFFST_PR_1_2 0
+#define STB0899_WIDTH_PR_1_2 1
+
+#define STB0899_VITSYNC 0xf53d
+#define STB0899_AM (0x01 << 7)
+#define STB0899_OFFST_AM 7
+#define STB0899_WIDTH_AM 1
+#define STB0899_FREEZE (0x01 << 6)
+#define STB0899_OFFST_FREEZE 6
+#define STB0899_WIDTH_FREEZE 1
+#define STB0899_SN_65536 (0x03 << 4)
+#define STB0899_OFFST_SN_65536 4
+#define STB0899_WIDTH_SN_65536 2
+#define STB0899_SN_16384 (0x01 << 5)
+#define STB0899_OFFST_SN_16384 5
+#define STB0899_WIDTH_SN_16384 1
+#define STB0899_SN_4096 (0x01 << 4)
+#define STB0899_OFFST_SN_4096 4
+#define STB0899_WIDTH_SN_4096 1
+#define STB0899_SN_1024 (0x00 << 4)
+#define STB0899_OFFST_SN_1024 4
+#define STB0899_WIDTH_SN_1024 0
+#define STB0899_TO_128 (0x03 << 2)
+#define STB0899_OFFST_TO_128 2
+#define STB0899_WIDTH_TO_128 2
+#define STB0899_TO_64 (0x01 << 3)
+#define STB0899_OFFST_TO_64 3
+#define STB0899_WIDTH_TO_64 1
+#define STB0899_TO_32 (0x01 << 2)
+#define STB0899_OFFST_TO_32 2
+#define STB0899_WIDTH_TO_32 1
+#define STB0899_TO_16 (0x00 << 2)
+#define STB0899_OFFST_TO_16 2
+#define STB0899_WIDTH_TO_16 0
+#define STB0899_HYST_128 (0x03 << 1)
+#define STB0899_OFFST_HYST_128 1
+#define STB0899_WIDTH_HYST_128 2
+#define STB0899_HYST_64 (0x01 << 1)
+#define STB0899_OFFST_HYST_64 1
+#define STB0899_WIDTH_HYST_64 1
+#define STB0899_HYST_32 (0x01 << 0)
+#define STB0899_OFFST_HYST_32 0
+#define STB0899_WIDTH_HYST_32 1
+#define STB0899_HYST_16 (0x00 << 0)
+#define STB0899_OFFST_HYST_16 0
+#define STB0899_WIDTH_HYST_16 0
+
+#define STB0899_RSULC 0xf548
+#define STB0899_ULDIL_ON (0x01 << 7)
+#define STB0899_OFFST_ULDIL_ON 7
+#define STB0899_WIDTH_ULDIL_ON 1
+#define STB0899_ULAUTO_ON (0x01 << 6)
+#define STB0899_OFFST_ULAUTO_ON 6
+#define STB0899_WIDTH_ULAUTO_ON 1
+#define STB0899_ULRS_ON (0x01 << 5)
+#define STB0899_OFFST_ULRS_ON 5
+#define STB0899_WIDTH_ULRS_ON 1
+#define STB0899_ULDESCRAM_ON (0x01 << 4)
+#define STB0899_OFFST_ULDESCRAM_ON 4
+#define STB0899_WIDTH_ULDESCRAM_ON 1
+#define STB0899_UL_DISABLE (0x01 << 2)
+#define STB0899_OFFST_UL_DISABLE 2
+#define STB0899_WIDTH_UL_DISABLE 1
+#define STB0899_NOFTHRESHOLD (0x01 << 0)
+#define STB0899_OFFST_NOFTHRESHOLD 0
+#define STB0899_WIDTH_NOFTHRESHOLD 1
+
+#define STB0899_RSLLC 0xf54a
+#define STB0899_DEMAPVIT 0xf583
+#define STB0899_DEMAPVIT_RSVD (0x01 << 7)
+#define STB0899_OFFST_DEMAPVIT_RSVD 7
+#define STB0899_WIDTH_DEMAPVIT_RSVD 1
+#define STB0899_DEMAPVIT_KDIVIDER (0x7f << 0)
+#define STB0899_OFFST_DEMAPVIT_KDIVIDER 0
+#define STB0899_WIDTH_DEMAPVIT_KDIVIDER 7
+
+#define STB0899_PLPARM 0xf58c
+#define STB0899_VITMAPPING (0x07 << 5)
+#define STB0899_OFFST_VITMAPPING 5
+#define STB0899_WIDTH_VITMAPPING 3
+#define STB0899_VITMAPPING_BPSK (0x01 << 5)
+#define STB0899_OFFST_VITMAPPING_BPSK 5
+#define STB0899_WIDTH_VITMAPPING_BPSK 1
+#define STB0899_VITMAPPING_QPSK (0x00 << 5)
+#define STB0899_OFFST_VITMAPPING_QPSK 5
+#define STB0899_WIDTH_VITMAPPING_QPSK 0
+#define STB0899_VITCURPUN (0x1f << 0)
+#define STB0899_OFFST_VITCURPUN 0
+#define STB0899_WIDTH_VITCURPUN 5
+#define STB0899_VITCURPUN_1_2 (0x0d << 0)
+#define STB0899_VITCURPUN_2_3 (0x12 << 0)
+#define STB0899_VITCURPUN_3_4 (0x15 << 0)
+#define STB0899_VITCURPUN_5_6 (0x18 << 0)
+#define STB0899_VITCURPUN_6_7 (0x19 << 0)
+#define STB0899_VITCURPUN_7_8 (0x1a << 0)
+
+/* S2 DEMOD */
+#define STB0899_OFF0_DMD_STATUS 0xf300
+#define STB0899_BASE_DMD_STATUS 0x00000000
+#define STB0899_IF_AGC_LOCK (0x01 << 8)
+#define STB0899_OFFST_IF_AGC_LOCK 0
+#define STB0899_WIDTH_IF_AGC_LOCK 1
+
+#define STB0899_OFF0_CRL_FREQ 0xf304
+#define STB0899_BASE_CRL_FREQ 0x00000000
+#define STB0899_CARR_FREQ (0x3fffffff << 0)
+#define STB0899_OFFST_CARR_FREQ 0
+#define STB0899_WIDTH_CARR_FREQ 30
+
+#define STB0899_OFF0_BTR_FREQ 0xf308
+#define STB0899_BASE_BTR_FREQ 0x00000000
+#define STB0899_BTR_FREQ (0xfffffff << 0)
+#define STB0899_OFFST_BTR_FREQ 0
+#define STB0899_WIDTH_BTR_FREQ 28
+
+#define STB0899_OFF0_IF_AGC_GAIN 0xf30c
+#define STB0899_BASE_IF_AGC_GAIN 0x00000000
+#define STB0899_IF_AGC_GAIN (0x3fff < 0)
+#define STB0899_OFFST_IF_AGC_GAIN 0
+#define STB0899_WIDTH_IF_AGC_GAIN 14
+
+#define STB0899_OFF0_BB_AGC_GAIN 0xf310
+#define STB0899_BASE_BB_AGC_GAIN 0x00000000
+#define STB0899_BB_AGC_GAIN (0x3fff < 0)
+#define STB0899_OFFST_BB_AGC_GAIN 0
+#define STB0899_WIDTH_BB_AGC_GAIN 14
+
+#define STB0899_OFF0_DC_OFFSET 0xf314
+#define STB0899_BASE_DC_OFFSET 0x00000000
+#define STB0899_I (0xff < 8)
+#define STB0899_OFFST_I 8
+#define STB0899_WIDTH_I 8
+#define STB0899_Q (0xff < 0)
+#define STB0899_OFFST_Q 8
+#define STB0899_WIDTH_Q 8
+
+#define STB0899_OFF0_DMD_CNTRL 0xf31c
+#define STB0899_BASE_DMD_CNTRL 0x00000000
+#define STB0899_ADC0_PINS1IN (0x01 << 6)
+#define STB0899_OFFST_ADC0_PINS1IN 6
+#define STB0899_WIDTH_ADC0_PINS1IN 1
+#define STB0899_IN2COMP1_OFFBIN0 (0x01 << 3)
+#define STB0899_OFFST_IN2COMP1_OFFBIN0 3
+#define STB0899_WIDTH_IN2COMP1_OFFBIN0 1
+#define STB0899_DC_COMP (0x01 << 2)
+#define STB0899_OFFST_DC_COMP 2
+#define STB0899_WIDTH_DC_COMP 1
+#define STB0899_MODMODE (0x03 << 0)
+#define STB0899_OFFST_MODMODE 0
+#define STB0899_WIDTH_MODMODE 2
+
+#define STB0899_OFF0_IF_AGC_CNTRL 0xf320
+#define STB0899_BASE_IF_AGC_CNTRL 0x00000000
+#define STB0899_IF_GAIN_INIT (0x3fff << 13)
+#define STB0899_OFFST_IF_GAIN_INIT 13
+#define STB0899_WIDTH_IF_GAIN_INIT 14
+#define STB0899_IF_GAIN_SENSE (0x01 << 12)
+#define STB0899_OFFST_IF_GAIN_SENSE 12
+#define STB0899_WIDTH_IF_GAIN_SENSE 1
+#define STB0899_IF_LOOP_GAIN (0x0f << 8)
+#define STB0899_OFFST_IF_LOOP_GAIN 8
+#define STB0899_WIDTH_IF_LOOP_GAIN 4
+#define STB0899_IF_LD_GAIN_INIT (0x01 << 7)
+#define STB0899_OFFST_IF_LD_GAIN_INIT 7
+#define STB0899_WIDTH_IF_LD_GAIN_INIT 1
+#define STB0899_IF_AGC_REF (0x7f << 0)
+#define STB0899_OFFST_IF_AGC_REF 0
+#define STB0899_WIDTH_IF_AGC_REF 7
+
+#define STB0899_OFF0_BB_AGC_CNTRL 0xf324
+#define STB0899_BASE_BB_AGC_CNTRL 0x00000000
+#define STB0899_BB_GAIN_INIT (0x3fff << 12)
+#define STB0899_OFFST_BB_GAIN_INIT 12
+#define STB0899_WIDTH_BB_GAIN_INIT 14
+#define STB0899_BB_LOOP_GAIN (0x0f << 8)
+#define STB0899_OFFST_BB_LOOP_GAIN 8
+#define STB0899_WIDTH_BB_LOOP_GAIN 4
+#define STB0899_BB_LD_GAIN_INIT (0x01 << 7)
+#define STB0899_OFFST_BB_LD_GAIN_INIT 7
+#define STB0899_WIDTH_BB_LD_GAIN_INIT 1
+#define STB0899_BB_AGC_REF (0x7f << 0)
+#define STB0899_OFFST_BB_AGC_REF 0
+#define STB0899_WIDTH_BB_AGC_REF 7
+
+#define STB0899_OFF0_CRL_CNTRL 0xf328
+#define STB0899_BASE_CRL_CNTRL 0x00000000
+#define STB0899_CRL_LOCK_CLEAR (0x01 << 5)
+#define STB0899_OFFST_CRL_LOCK_CLEAR 5
+#define STB0899_WIDTH_CRL_LOCK_CLEAR 1
+#define STB0899_CRL_SWPR_CLEAR (0x01 << 4)
+#define STB0899_OFFST_CRL_SWPR_CLEAR 4
+#define STB0899_WIDTH_CRL_SWPR_CLEAR 1
+#define STB0899_CRL_SWP_ENA (0x01 << 3)
+#define STB0899_OFFST_CRL_SWP_ENA 3
+#define STB0899_WIDTH_CRL_SWP_ENA 1
+#define STB0899_CRL_DET_SEL (0x01 << 2)
+#define STB0899_OFFST_CRL_DET_SEL 2
+#define STB0899_WIDTH_CRL_DET_SEL 1
+#define STB0899_CRL_SENSE (0x01 << 1)
+#define STB0899_OFFST_CRL_SENSE 1
+#define STB0899_WIDTH_CRL_SENSE 1
+#define STB0899_CRL_PHSERR_CLEAR (0x01 << 0)
+#define STB0899_OFFST_CRL_PHSERR_CLEAR 0
+#define STB0899_WIDTH_CRL_PHSERR_CLEAR 1
+
+#define STB0899_OFF0_CRL_PHS_INIT 0xf32c
+#define STB0899_BASE_CRL_PHS_INIT 0x00000000
+#define STB0899_CRL_PHS_INIT_31 (0x1 << 30)
+#define STB0899_OFFST_CRL_PHS_INIT_31 30
+#define STB0899_WIDTH_CRL_PHS_INIT_31 1
+#define STB0899_CRL_LD_INIT_PHASE (0x1 << 24)
+#define STB0899_OFFST_CRL_LD_INIT_PHASE 24
+#define STB0899_WIDTH_CRL_LD_INIT_PHASE 1
+#define STB0899_CRL_INIT_PHASE (0xffffff << 0)
+#define STB0899_OFFST_CRL_INIT_PHASE 0
+#define STB0899_WIDTH_CRL_INIT_PHASE 24
+
+#define STB0899_OFF0_CRL_FREQ_INIT 0xf330
+#define STB0899_BASE_CRL_FREQ_INIT 0x00000000
+#define STB0899_CRL_FREQ_INIT_31 (0x1 << 30)
+#define STB0899_OFFST_CRL_FREQ_INIT_31 30
+#define STB0899_WIDTH_CRL_FREQ_INIT_31 1
+#define STB0899_CRL_LD_FREQ_INIT (0x1 << 24)
+#define STB0899_OFFST_CRL_LD_FREQ_INIT 24
+#define STB0899_WIDTH_CRL_LD_FREQ_INIT 1
+#define STB0899_CRL_FREQ_INIT (0xffffff << 0)
+#define STB0899_OFFST_CRL_FREQ_INIT 0
+#define STB0899_WIDTH_CRL_FREQ_INIT 24
+
+#define STB0899_OFF0_CRL_LOOP_GAIN 0xf334
+#define STB0899_BASE_CRL_LOOP_GAIN 0x00000000
+#define STB0899_KCRL2_RSHFT (0xf << 16)
+#define STB0899_OFFST_KCRL2_RSHFT 16
+#define STB0899_WIDTH_KCRL2_RSHFT 4
+#define STB0899_KCRL1 (0xf << 12)
+#define STB0899_OFFST_KCRL1 12
+#define STB0899_WIDTH_KCRL1 4
+#define STB0899_KCRL1_RSHFT (0xf << 8)
+#define STB0899_OFFST_KCRL1_RSHFT 8
+#define STB0899_WIDTH_KCRL1_RSHFT 4
+#define STB0899_KCRL0 (0xf << 4)
+#define STB0899_OFFST_KCRL0 4
+#define STB0899_WIDTH_KCRL0 4
+#define STB0899_KCRL0_RSHFT (0xf << 0)
+#define STB0899_OFFST_KCRL0_RSHFT 0
+#define STB0899_WIDTH_KCRL0_RSHFT 4
+
+#define STB0899_OFF0_CRL_NOM_FREQ 0xf338
+#define STB0899_BASE_CRL_NOM_FREQ 0x00000000
+#define STB0899_CRL_NOM_FREQ (0x3fffffff << 0)
+#define STB0899_OFFST_CRL_NOM_FREQ 0
+#define STB0899_WIDTH_CRL_NOM_FREQ 30
+
+#define STB0899_OFF0_CRL_SWP_RATE 0xf33c
+#define STB0899_BASE_CRL_SWP_RATE 0x00000000
+#define STB0899_CRL_SWP_RATE (0x3fffffff << 0)
+#define STB0899_OFFST_CRL_SWP_RATE 0
+#define STB0899_WIDTH_CRL_SWP_RATE 30
+
+#define STB0899_OFF0_CRL_MAX_SWP 0xf340
+#define STB0899_BASE_CRL_MAX_SWP 0x00000000
+#define STB0899_CRL_MAX_SWP (0x3fffffff << 0)
+#define STB0899_OFFST_CRL_MAX_SWP 0
+#define STB0899_WIDTH_CRL_MAX_SWP 30
+
+#define STB0899_OFF0_CRL_LK_CNTRL 0xf344
+#define STB0899_BASE_CRL_LK_CNTRL 0x00000000
+
+#define STB0899_OFF0_DECIM_CNTRL 0xf348
+#define STB0899_BASE_DECIM_CNTRL 0x00000000
+#define STB0899_BAND_LIMIT_B (0x01 << 5)
+#define STB0899_OFFST_BAND_LIMIT_B 5
+#define STB0899_WIDTH_BAND_LIMIT_B 1
+#define STB0899_WIN_SEL (0x03 << 3)
+#define STB0899_OFFST_WIN_SEL 3
+#define STB0899_WIDTH_WIN_SEL 2
+#define STB0899_DECIM_RATE (0x07 << 0)
+#define STB0899_OFFST_DECIM_RATE 0
+#define STB0899_WIDTH_DECIM_RATE 3
+
+#define STB0899_OFF0_BTR_CNTRL 0xf34c
+#define STB0899_BASE_BTR_CNTRL 0x00000000
+#define STB0899_BTR_FREQ_CORR (0x7ff << 4)
+#define STB0899_OFFST_BTR_FREQ_CORR 4
+#define STB0899_WIDTH_BTR_FREQ_CORR 11
+#define STB0899_BTR_CLR_LOCK (0x01 << 3)
+#define STB0899_OFFST_BTR_CLR_LOCK 3
+#define STB0899_WIDTH_BTR_CLR_LOCK 1
+#define STB0899_BTR_SENSE (0x01 << 2)
+#define STB0899_OFFST_BTR_SENSE 2
+#define STB0899_WIDTH_BTR_SENSE 1
+#define STB0899_BTR_ERR_ENA (0x01 << 1)
+#define STB0899_OFFST_BTR_ERR_ENA 1
+#define STB0899_WIDTH_BTR_ERR_ENA 1
+#define STB0899_INTRP_PHS_SENSE (0x01 << 0)
+#define STB0899_OFFST_INTRP_PHS_SENSE 0
+#define STB0899_WIDTH_INTRP_PHS_SENSE 1
+
+#define STB0899_OFF0_BTR_LOOP_GAIN 0xf350
+#define STB0899_BASE_BTR_LOOP_GAIN 0x00000000
+#define STB0899_KBTR2_RSHFT (0x0f << 16)
+#define STB0899_OFFST_KBTR2_RSHFT 16
+#define STB0899_WIDTH_KBTR2_RSHFT 4
+#define STB0899_KBTR1 (0x0f << 12)
+#define STB0899_OFFST_KBTR1 12
+#define STB0899_WIDTH_KBTR1 4
+#define STB0899_KBTR1_RSHFT (0x0f << 8)
+#define STB0899_OFFST_KBTR1_RSHFT 8
+#define STB0899_WIDTH_KBTR1_RSHFT 4
+#define STB0899_KBTR0 (0x0f << 4)
+#define STB0899_OFFST_KBTR0 4
+#define STB0899_WIDTH_KBTR0 4
+#define STB0899_KBTR0_RSHFT (0x0f << 0)
+#define STB0899_OFFST_KBTR0_RSHFT 0
+#define STB0899_WIDTH_KBTR0_RSHFT 4
+
+#define STB0899_OFF0_BTR_PHS_INIT 0xf354
+#define STB0899_BASE_BTR_PHS_INIT 0x00000000
+#define STB0899_BTR_LD_PHASE_INIT (0x01 << 28)
+#define STB0899_OFFST_BTR_LD_PHASE_INIT 28
+#define STB0899_WIDTH_BTR_LD_PHASE_INIT 1
+#define STB0899_BTR_INIT_PHASE (0xfffffff << 0)
+#define STB0899_OFFST_BTR_INIT_PHASE 0
+#define STB0899_WIDTH_BTR_INIT_PHASE 28
+
+#define STB0899_OFF0_BTR_FREQ_INIT 0xf358
+#define STB0899_BASE_BTR_FREQ_INIT 0x00000000
+#define STB0899_BTR_LD_FREQ_INIT (1 << 28)
+#define STB0899_OFFST_BTR_LD_FREQ_INIT 28
+#define STB0899_WIDTH_BTR_LD_FREQ_INIT 1
+#define STB0899_BTR_FREQ_INIT (0xfffffff << 0)
+#define STB0899_OFFST_BTR_FREQ_INIT 0
+#define STB0899_WIDTH_BTR_FREQ_INIT 28
+
+#define STB0899_OFF0_BTR_NOM_FREQ 0xf35c
+#define STB0899_BASE_BTR_NOM_FREQ 0x00000000
+#define STB0899_BTR_NOM_FREQ (0xfffffff << 0)
+#define STB0899_OFFST_BTR_NOM_FREQ 0
+#define STB0899_WIDTH_BTR_NOM_FREQ 28
+
+#define STB0899_OFF0_BTR_LK_CNTRL 0xf360
+#define STB0899_BASE_BTR_LK_CNTRL 0x00000000
+#define STB0899_BTR_MIN_ENERGY (0x0f << 24)
+#define STB0899_OFFST_BTR_MIN_ENERGY 24
+#define STB0899_WIDTH_BTR_MIN_ENERGY 4
+#define STB0899_BTR_LOCK_TH_LO (0xff << 16)
+#define STB0899_OFFST_BTR_LOCK_TH_LO 16
+#define STB0899_WIDTH_BTR_LOCK_TH_LO 8
+#define STB0899_BTR_LOCK_TH_HI (0xff << 8)
+#define STB0899_OFFST_BTR_LOCK_TH_HI 8
+#define STB0899_WIDTH_BTR_LOCK_TH_HI 8
+#define STB0899_BTR_LOCK_GAIN (0x03 << 6)
+#define STB0899_OFFST_BTR_LOCK_GAIN 6
+#define STB0899_WIDTH_BTR_LOCK_GAIN 2
+#define STB0899_BTR_LOCK_LEAK (0x3f << 0)
+#define STB0899_OFFST_BTR_LOCK_LEAK 0
+#define STB0899_WIDTH_BTR_LOCK_LEAK 6
+
+#define STB0899_OFF0_DECN_CNTRL 0xf364
+#define STB0899_BASE_DECN_CNTRL 0x00000000
+
+#define STB0899_OFF0_TP_CNTRL 0xf368
+#define STB0899_BASE_TP_CNTRL 0x00000000
+
+#define STB0899_OFF0_TP_BUF_STATUS 0xf36c
+#define STB0899_BASE_TP_BUF_STATUS 0x00000000
+#define STB0899_TP_BUFFER_FULL (1 << 0)
+
+#define STB0899_OFF0_DC_ESTIM 0xf37c
+#define STB0899_BASE_DC_ESTIM 0x0000
+#define STB0899_I_DC_ESTIMATE (0xff << 8)
+#define STB0899_OFFST_I_DC_ESTIMATE 8
+#define STB0899_WIDTH_I_DC_ESTIMATE 8
+#define STB0899_Q_DC_ESTIMATE (0xff << 0)
+#define STB0899_OFFST_Q_DC_ESTIMATE 0
+#define STB0899_WIDTH_Q_DC_ESTIMATE 8
+
+#define STB0899_OFF0_FLL_CNTRL 0xf310
+#define STB0899_BASE_FLL_CNTRL 0x00000020
+#define STB0899_CRL_FLL_ACC (0x01 << 4)
+#define STB0899_OFFST_CRL_FLL_ACC 4
+#define STB0899_WIDTH_CRL_FLL_ACC 1
+#define STB0899_FLL_AVG_PERIOD (0x0f << 0)
+#define STB0899_OFFST_FLL_AVG_PERIOD 0
+#define STB0899_WIDTH_FLL_AVG_PERIOD 4
+
+#define STB0899_OFF0_FLL_FREQ_WD 0xf314
+#define STB0899_BASE_FLL_FREQ_WD 0x00000020
+#define STB0899_FLL_FREQ_WD (0xffffffff << 0)
+#define STB0899_OFFST_FLL_FREQ_WD 0
+#define STB0899_WIDTH_FLL_FREQ_WD 32
+
+#define STB0899_OFF0_ANTI_ALIAS_SEL 0xf358
+#define STB0899_BASE_ANTI_ALIAS_SEL 0x00000020
+#define STB0899_ANTI_ALIAS_SELB (0x03 << 0)
+#define STB0899_OFFST_ANTI_ALIAS_SELB 0
+#define STB0899_WIDTH_ANTI_ALIAS_SELB 2
+
+#define STB0899_OFF0_RRC_ALPHA 0xf35c
+#define STB0899_BASE_RRC_ALPHA 0x00000020
+#define STB0899_RRC_ALPHA (0x03 << 0)
+#define STB0899_OFFST_RRC_ALPHA 0
+#define STB0899_WIDTH_RRC_ALPHA 2
+
+#define STB0899_OFF0_DC_ADAPT_LSHFT 0xf360
+#define STB0899_BASE_DC_ADAPT_LSHFT 0x00000020
+#define STB0899_DC_ADAPT_LSHFT (0x077 << 0)
+#define STB0899_OFFST_DC_ADAPT_LSHFT 0
+#define STB0899_WIDTH_DC_ADAPT_LSHFT 3
+
+#define STB0899_OFF0_IMB_OFFSET 0xf364
+#define STB0899_BASE_IMB_OFFSET 0x00000020
+#define STB0899_PHS_IMB_COMP (0xff << 8)
+#define STB0899_OFFST_PHS_IMB_COMP 8
+#define STB0899_WIDTH_PHS_IMB_COMP 8
+#define STB0899_AMPL_IMB_COMP (0xff << 0)
+#define STB0899_OFFST_AMPL_IMB_COMP 0
+#define STB0899_WIDTH_AMPL_IMB_COMP 8
+
+#define STB0899_OFF0_IMB_ESTIMATE 0xf368
+#define STB0899_BASE_IMB_ESTIMATE 0x00000020
+#define STB0899_PHS_IMB_ESTIMATE (0xff << 8)
+#define STB0899_OFFST_PHS_IMB_ESTIMATE 8
+#define STB0899_WIDTH_PHS_IMB_ESTIMATE 8
+#define STB0899_AMPL_IMB_ESTIMATE (0xff << 0)
+#define STB0899_OFFST_AMPL_IMB_ESTIMATE 0
+#define STB0899_WIDTH_AMPL_IMB_ESTIMATE 8
+
+#define STB0899_OFF0_IMB_CNTRL 0xf36c
+#define STB0899_BASE_IMB_CNTRL 0x00000020
+#define STB0899_PHS_ADAPT_LSHFT (0x07 << 4)
+#define STB0899_OFFST_PHS_ADAPT_LSHFT 4
+#define STB0899_WIDTH_PHS_ADAPT_LSHFT 3
+#define STB0899_AMPL_ADAPT_LSHFT (0x07 << 1)
+#define STB0899_OFFST_AMPL_ADAPT_LSHFT 1
+#define STB0899_WIDTH_AMPL_ADAPT_LSHFT 3
+#define STB0899_IMB_COMP (0x01 << 0)
+#define STB0899_OFFST_IMB_COMP 0
+#define STB0899_WIDTH_IMB_COMP 1
+
+#define STB0899_OFF0_IF_AGC_CNTRL2 0xf374
+#define STB0899_BASE_IF_AGC_CNTRL2 0x00000020
+#define STB0899_IF_AGC_LOCK_TH (0xff << 11)
+#define STB0899_OFFST_IF_AGC_LOCK_TH 11
+#define STB0899_WIDTH_IF_AGC_LOCK_TH 8
+#define STB0899_IF_AGC_SD_DIV (0xff << 3)
+#define STB0899_OFFST_IF_AGC_SD_DIV 3
+#define STB0899_WIDTH_IF_AGC_SD_DIV 8
+#define STB0899_IF_AGC_DUMP_PER (0x07 << 0)
+#define STB0899_OFFST_IF_AGC_DUMP_PER 0
+#define STB0899_WIDTH_IF_AGC_DUMP_PER 3
+
+#define STB0899_OFF0_DMD_CNTRL2 0xf378
+#define STB0899_BASE_DMD_CNTRL2 0x00000020
+#define STB0899_SPECTRUM_INVERT (0x01 << 2)
+#define STB0899_OFFST_SPECTRUM_INVERT 2
+#define STB0899_WIDTH_SPECTRUM_INVERT 1
+#define STB0899_AGC_MODE (0x01 << 1)
+#define STB0899_OFFST_AGC_MODE 1
+#define STB0899_WIDTH_AGC_MODE 1
+#define STB0899_CRL_FREQ_ADJ (0x01 << 0)
+#define STB0899_OFFST_CRL_FREQ_ADJ 0
+#define STB0899_WIDTH_CRL_FREQ_ADJ 1
+
+#define STB0899_OFF0_TP_BUFFER 0xf300
+#define STB0899_BASE_TP_BUFFER 0x00000040
+#define STB0899_TP_BUFFER_IN (0xffff << 0)
+#define STB0899_OFFST_TP_BUFFER_IN 0
+#define STB0899_WIDTH_TP_BUFFER_IN 16
+
+#define STB0899_OFF0_TP_BUFFER1 0xf304
+#define STB0899_BASE_TP_BUFFER1 0x00000040
+#define STB0899_OFF0_TP_BUFFER2 0xf308
+#define STB0899_BASE_TP_BUFFER2 0x00000040
+#define STB0899_OFF0_TP_BUFFER3 0xf30c
+#define STB0899_BASE_TP_BUFFER3 0x00000040
+#define STB0899_OFF0_TP_BUFFER4 0xf310
+#define STB0899_BASE_TP_BUFFER4 0x00000040
+#define STB0899_OFF0_TP_BUFFER5 0xf314
+#define STB0899_BASE_TP_BUFFER5 0x00000040
+#define STB0899_OFF0_TP_BUFFER6 0xf318
+#define STB0899_BASE_TP_BUFFER6 0x00000040
+#define STB0899_OFF0_TP_BUFFER7 0xf31c
+#define STB0899_BASE_TP_BUFFER7 0x00000040
+#define STB0899_OFF0_TP_BUFFER8 0xf320
+#define STB0899_BASE_TP_BUFFER8 0x00000040
+#define STB0899_OFF0_TP_BUFFER9 0xf324
+#define STB0899_BASE_TP_BUFFER9 0x00000040
+#define STB0899_OFF0_TP_BUFFER10 0xf328
+#define STB0899_BASE_TP_BUFFER10 0x00000040
+#define STB0899_OFF0_TP_BUFFER11 0xf32c
+#define STB0899_BASE_TP_BUFFER11 0x00000040
+#define STB0899_OFF0_TP_BUFFER12 0xf330
+#define STB0899_BASE_TP_BUFFER12 0x00000040
+#define STB0899_OFF0_TP_BUFFER13 0xf334
+#define STB0899_BASE_TP_BUFFER13 0x00000040
+#define STB0899_OFF0_TP_BUFFER14 0xf338
+#define STB0899_BASE_TP_BUFFER14 0x00000040
+#define STB0899_OFF0_TP_BUFFER15 0xf33c
+#define STB0899_BASE_TP_BUFFER15 0x00000040
+#define STB0899_OFF0_TP_BUFFER16 0xf340
+#define STB0899_BASE_TP_BUFFER16 0x00000040
+#define STB0899_OFF0_TP_BUFFER17 0xf344
+#define STB0899_BASE_TP_BUFFER17 0x00000040
+#define STB0899_OFF0_TP_BUFFER18 0xf348
+#define STB0899_BASE_TP_BUFFER18 0x00000040
+#define STB0899_OFF0_TP_BUFFER19 0xf34c
+#define STB0899_BASE_TP_BUFFER19 0x00000040
+#define STB0899_OFF0_TP_BUFFER20 0xf350
+#define STB0899_BASE_TP_BUFFER20 0x00000040
+#define STB0899_OFF0_TP_BUFFER21 0xf354
+#define STB0899_BASE_TP_BUFFER21 0x00000040
+#define STB0899_OFF0_TP_BUFFER22 0xf358
+#define STB0899_BASE_TP_BUFFER22 0x00000040
+#define STB0899_OFF0_TP_BUFFER23 0xf35c
+#define STB0899_BASE_TP_BUFFER23 0x00000040
+#define STB0899_OFF0_TP_BUFFER24 0xf360
+#define STB0899_BASE_TP_BUFFER24 0x00000040
+#define STB0899_OFF0_TP_BUFFER25 0xf364
+#define STB0899_BASE_TP_BUFFER25 0x00000040
+#define STB0899_OFF0_TP_BUFFER26 0xf368
+#define STB0899_BASE_TP_BUFFER26 0x00000040
+#define STB0899_OFF0_TP_BUFFER27 0xf36c
+#define STB0899_BASE_TP_BUFFER27 0x00000040
+#define STB0899_OFF0_TP_BUFFER28 0xf370
+#define STB0899_BASE_TP_BUFFER28 0x00000040
+#define STB0899_OFF0_TP_BUFFER29 0xf374
+#define STB0899_BASE_TP_BUFFER29 0x00000040
+#define STB0899_OFF0_TP_BUFFER30 0xf378
+#define STB0899_BASE_TP_BUFFER30 0x00000040
+#define STB0899_OFF0_TP_BUFFER31 0xf37c
+#define STB0899_BASE_TP_BUFFER31 0x00000040
+#define STB0899_OFF0_TP_BUFFER32 0xf300
+#define STB0899_BASE_TP_BUFFER32 0x00000060
+#define STB0899_OFF0_TP_BUFFER33 0xf304
+#define STB0899_BASE_TP_BUFFER33 0x00000060
+#define STB0899_OFF0_TP_BUFFER34 0xf308
+#define STB0899_BASE_TP_BUFFER34 0x00000060
+#define STB0899_OFF0_TP_BUFFER35 0xf30c
+#define STB0899_BASE_TP_BUFFER35 0x00000060
+#define STB0899_OFF0_TP_BUFFER36 0xf310
+#define STB0899_BASE_TP_BUFFER36 0x00000060
+#define STB0899_OFF0_TP_BUFFER37 0xf314
+#define STB0899_BASE_TP_BUFFER37 0x00000060
+#define STB0899_OFF0_TP_BUFFER38 0xf318
+#define STB0899_BASE_TP_BUFFER38 0x00000060
+#define STB0899_OFF0_TP_BUFFER39 0xf31c
+#define STB0899_BASE_TP_BUFFER39 0x00000060
+#define STB0899_OFF0_TP_BUFFER40 0xf320
+#define STB0899_BASE_TP_BUFFER40 0x00000060
+#define STB0899_OFF0_TP_BUFFER41 0xf324
+#define STB0899_BASE_TP_BUFFER41 0x00000060
+#define STB0899_OFF0_TP_BUFFER42 0xf328
+#define STB0899_BASE_TP_BUFFER42 0x00000060
+#define STB0899_OFF0_TP_BUFFER43 0xf32c
+#define STB0899_BASE_TP_BUFFER43 0x00000060
+#define STB0899_OFF0_TP_BUFFER44 0xf330
+#define STB0899_BASE_TP_BUFFER44 0x00000060
+#define STB0899_OFF0_TP_BUFFER45 0xf334
+#define STB0899_BASE_TP_BUFFER45 0x00000060
+#define STB0899_OFF0_TP_BUFFER46 0xf338
+#define STB0899_BASE_TP_BUFFER46 0x00000060
+#define STB0899_OFF0_TP_BUFFER47 0xf33c
+#define STB0899_BASE_TP_BUFFER47 0x00000060
+#define STB0899_OFF0_TP_BUFFER48 0xf340
+#define STB0899_BASE_TP_BUFFER48 0x00000060
+#define STB0899_OFF0_TP_BUFFER49 0xf344
+#define STB0899_BASE_TP_BUFFER49 0x00000060
+#define STB0899_OFF0_TP_BUFFER50 0xf348
+#define STB0899_BASE_TP_BUFFER50 0x00000060
+#define STB0899_OFF0_TP_BUFFER51 0xf34c
+#define STB0899_BASE_TP_BUFFER51 0x00000060
+#define STB0899_OFF0_TP_BUFFER52 0xf350
+#define STB0899_BASE_TP_BUFFER52 0x00000060
+#define STB0899_OFF0_TP_BUFFER53 0xf354
+#define STB0899_BASE_TP_BUFFER53 0x00000060
+#define STB0899_OFF0_TP_BUFFER54 0xf358
+#define STB0899_BASE_TP_BUFFER54 0x00000060
+#define STB0899_OFF0_TP_BUFFER55 0xf35c
+#define STB0899_BASE_TP_BUFFER55 0x00000060
+#define STB0899_OFF0_TP_BUFFER56 0xf360
+#define STB0899_BASE_TP_BUFFER56 0x00000060
+#define STB0899_OFF0_TP_BUFFER57 0xf364
+#define STB0899_BASE_TP_BUFFER57 0x00000060
+#define STB0899_OFF0_TP_BUFFER58 0xf368
+#define STB0899_BASE_TP_BUFFER58 0x00000060
+#define STB0899_OFF0_TP_BUFFER59 0xf36c
+#define STB0899_BASE_TP_BUFFER59 0x00000060
+#define STB0899_OFF0_TP_BUFFER60 0xf370
+#define STB0899_BASE_TP_BUFFER60 0x00000060
+#define STB0899_OFF0_TP_BUFFER61 0xf374
+#define STB0899_BASE_TP_BUFFER61 0x00000060
+#define STB0899_OFF0_TP_BUFFER62 0xf378
+#define STB0899_BASE_TP_BUFFER62 0x00000060
+#define STB0899_OFF0_TP_BUFFER63 0xf37c
+#define STB0899_BASE_TP_BUFFER63 0x00000060
+
+#define STB0899_OFF0_RESET_CNTRL 0xf300
+#define STB0899_BASE_RESET_CNTRL 0x00000400
+#define STB0899_DVBS2_RESET (0x01 << 0)
+#define STB0899_OFFST_DVBS2_RESET 0
+#define STB0899_WIDTH_DVBS2_RESET 1
+
+#define STB0899_OFF0_ACM_ENABLE 0xf304
+#define STB0899_BASE_ACM_ENABLE 0x00000400
+#define STB0899_ACM_ENABLE 1
+
+#define STB0899_OFF0_DESCR_CNTRL 0xf30c
+#define STB0899_BASE_DESCR_CNTRL 0x00000400
+#define STB0899_OFFST_DESCR_CNTRL 0
+#define STB0899_WIDTH_DESCR_CNTRL 16
+
+#define STB0899_OFF0_UWP_CNTRL1 0xf320
+#define STB0899_BASE_UWP_CNTRL1 0x00000400
+#define STB0899_UWP_TH_SOF (0x7fff << 11)
+#define STB0899_OFFST_UWP_TH_SOF 11
+#define STB0899_WIDTH_UWP_TH_SOF 15
+#define STB0899_UWP_ESN0_QUANT (0xff << 3)
+#define STB0899_OFFST_UWP_ESN0_QUANT 3
+#define STB0899_WIDTH_UWP_ESN0_QUANT 8
+#define STB0899_UWP_ESN0_AVE (0x03 << 1)
+#define STB0899_OFFST_UWP_ESN0_AVE 1
+#define STB0899_WIDTH_UWP_ESN0_AVE 2
+#define STB0899_UWP_START (0x01 << 0)
+#define STB0899_OFFST_UWP_START 0
+#define STB0899_WIDTH_UWP_START 1
+
+#define STB0899_OFF0_UWP_CNTRL2 0xf324
+#define STB0899_BASE_UWP_CNTRL2 0x00000400
+#define STB0899_UWP_MISS_TH (0xff << 16)
+#define STB0899_OFFST_UWP_MISS_TH 16
+#define STB0899_WIDTH_UWP_MISS_TH 8
+#define STB0899_FE_FINE_TRK (0xff << 8)
+#define STB0899_OFFST_FE_FINE_TRK 8
+#define STB0899_WIDTH_FE_FINE_TRK 8
+#define STB0899_FE_COARSE_TRK (0xff << 0)
+#define STB0899_OFFST_FE_COARSE_TRK 0
+#define STB0899_WIDTH_FE_COARSE_TRK 8
+
+#define STB0899_OFF0_UWP_STAT1 0xf328
+#define STB0899_BASE_UWP_STAT1 0x00000400
+#define STB0899_UWP_STATE (0x03ff << 15)
+#define STB0899_OFFST_UWP_STATE 15
+#define STB0899_WIDTH_UWP_STATE 10
+#define STB0899_UW_MAX_PEAK (0x7fff << 0)
+#define STB0899_OFFST_UW_MAX_PEAK 0
+#define STB0899_WIDTH_UW_MAX_PEAK 15
+
+#define STB0899_OFF0_UWP_STAT2 0xf32c
+#define STB0899_BASE_UWP_STAT2 0x00000400
+#define STB0899_ESNO_EST (0x07ffff << 7)
+#define STB0899_OFFST_ESN0_EST 7
+#define STB0899_WIDTH_ESN0_EST 19
+#define STB0899_UWP_DECODE_MOD (0x7f << 0)
+#define STB0899_OFFST_UWP_DECODE_MOD 0
+#define STB0899_WIDTH_UWP_DECODE_MOD 7
+
+#define STB0899_OFF0_DMD_CORE_ID 0xf334
+#define STB0899_BASE_DMD_CORE_ID 0x00000400
+#define STB0899_CORE_ID (0xffffffff << 0)
+#define STB0899_OFFST_CORE_ID 0
+#define STB0899_WIDTH_CORE_ID 32
+
+#define STB0899_OFF0_DMD_VERSION_ID 0xf33c
+#define STB0899_BASE_DMD_VERSION_ID 0x00000400
+#define STB0899_VERSION_ID (0xff << 0)
+#define STB0899_OFFST_VERSION_ID 0
+#define STB0899_WIDTH_VERSION_ID 8
+
+#define STB0899_OFF0_DMD_STAT2 0xf340
+#define STB0899_BASE_DMD_STAT2 0x00000400
+#define STB0899_CSM_LOCK (0x01 << 1)
+#define STB0899_OFFST_CSM_LOCK 1
+#define STB0899_WIDTH_CSM_LOCK 1
+#define STB0899_UWP_LOCK (0x01 << 0)
+#define STB0899_OFFST_UWP_LOCK 0
+#define STB0899_WIDTH_UWP_LOCK 1
+
+#define STB0899_OFF0_FREQ_ADJ_SCALE 0xf344
+#define STB0899_BASE_FREQ_ADJ_SCALE 0x00000400
+#define STB0899_FREQ_ADJ_SCALE (0x0fff << 0)
+#define STB0899_OFFST_FREQ_ADJ_SCALE 0
+#define STB0899_WIDTH_FREQ_ADJ_SCALE 12
+
+#define STB0899_OFF0_UWP_CNTRL3 0xf34c
+#define STB0899_BASE_UWP_CNTRL3 0x00000400
+#define STB0899_UWP_TH_TRACK (0x7fff << 15)
+#define STB0899_OFFST_UWP_TH_TRACK 15
+#define STB0899_WIDTH_UWP_TH_TRACK 15
+#define STB0899_UWP_TH_ACQ (0x7fff << 0)
+#define STB0899_OFFST_UWP_TH_ACQ 0
+#define STB0899_WIDTH_UWP_TH_ACQ 15
+
+#define STB0899_OFF0_SYM_CLK_SEL 0xf350
+#define STB0899_BASE_SYM_CLK_SEL 0x00000400
+#define STB0899_SYM_CLK_SEL (0x03 << 0)
+#define STB0899_OFFST_SYM_CLK_SEL 0
+#define STB0899_WIDTH_SYM_CLK_SEL 2
+
+#define STB0899_OFF0_SOF_SRCH_TO 0xf354
+#define STB0899_BASE_SOF_SRCH_TO 0x00000400
+#define STB0899_SOF_SEARCH_TIMEOUT (0x3fffff << 0)
+#define STB0899_OFFST_SOF_SEARCH_TIMEOUT 0
+#define STB0899_WIDTH_SOF_SEARCH_TIMEOUT 22
+
+#define STB0899_OFF0_ACQ_CNTRL1 0xf358
+#define STB0899_BASE_ACQ_CNTRL1 0x00000400
+#define STB0899_FE_FINE_ACQ (0xff << 8)
+#define STB0899_OFFST_FE_FINE_ACQ 8
+#define STB0899_WIDTH_FE_FINE_ACQ 8
+#define STB0899_FE_COARSE_ACQ (0xff << 0)
+#define STB0899_OFFST_FE_COARSE_ACQ 0
+#define STB0899_WIDTH_FE_COARSE_ACQ 8
+
+#define STB0899_OFF0_ACQ_CNTRL2 0xf35c
+#define STB0899_BASE_ACQ_CNTRL2 0x00000400
+#define STB0899_ZIGZAG (0x01 << 25)
+#define STB0899_OFFST_ZIGZAG 25
+#define STB0899_WIDTH_ZIGZAG 1
+#define STB0899_NUM_STEPS (0xff << 17)
+#define STB0899_OFFST_NUM_STEPS 17
+#define STB0899_WIDTH_NUM_STEPS 8
+#define STB0899_FREQ_STEPSIZE (0x1ffff << 0)
+#define STB0899_OFFST_FREQ_STEPSIZE 0
+#define STB0899_WIDTH_FREQ_STEPSIZE 17
+
+#define STB0899_OFF0_ACQ_CNTRL3 0xf360
+#define STB0899_BASE_ACQ_CNTRL3 0x00000400
+#define STB0899_THRESHOLD_SCL (0x3f << 23)
+#define STB0899_OFFST_THRESHOLD_SCL 23
+#define STB0899_WIDTH_THRESHOLD_SCL 6
+#define STB0899_UWP_TH_SRCH (0x7fff << 8)
+#define STB0899_OFFST_UWP_TH_SRCH 8
+#define STB0899_WIDTH_UWP_TH_SRCH 15
+#define STB0899_AUTO_REACQUIRE (0x01 << 7)
+#define STB0899_OFFST_AUTO_REACQUIRE 7
+#define STB0899_WIDTH_AUTO_REACQUIRE 1
+#define STB0899_TRACK_LOCK_SEL (0x01 << 6)
+#define STB0899_OFFST_TRACK_LOCK_SEL 6
+#define STB0899_WIDTH_TRACK_LOCK_SEL 1
+#define STB0899_ACQ_SEARCH_MODE (0x03 << 4)
+#define STB0899_OFFST_ACQ_SEARCH_MODE 4
+#define STB0899_WIDTH_ACQ_SEARCH_MODE 2
+#define STB0899_CONFIRM_FRAMES (0x0f << 0)
+#define STB0899_OFFST_CONFIRM_FRAMES 0
+#define STB0899_WIDTH_CONFIRM_FRAMES 4
+
+#define STB0899_OFF0_FE_SETTLE 0xf364
+#define STB0899_BASE_FE_SETTLE 0x00000400
+#define STB0899_SETTLING_TIME (0x3fffff << 0)
+#define STB0899_OFFST_SETTLING_TIME 0
+#define STB0899_WIDTH_SETTLING_TIME 22
+
+#define STB0899_OFF0_AC_DWELL 0xf368
+#define STB0899_BASE_AC_DWELL 0x00000400
+#define STB0899_DWELL_TIME (0x3fffff << 0)
+#define STB0899_OFFST_DWELL_TIME 0
+#define STB0899_WIDTH_DWELL_TIME 22
+
+#define STB0899_OFF0_ACQUIRE_TRIG 0xf36c
+#define STB0899_BASE_ACQUIRE_TRIG 0x00000400
+#define STB0899_ACQUIRE (0x01 << 0)
+#define STB0899_OFFST_ACQUIRE 0
+#define STB0899_WIDTH_ACQUIRE 1
+
+#define STB0899_OFF0_LOCK_LOST 0xf370
+#define STB0899_BASE_LOCK_LOST 0x00000400
+#define STB0899_LOCK_LOST (0x01 << 0)
+#define STB0899_OFFST_LOCK_LOST 0
+#define STB0899_WIDTH_LOCK_LOST 1
+
+#define STB0899_OFF0_ACQ_STAT1 0xf374
+#define STB0899_BASE_ACQ_STAT1 0x00000400
+#define STB0899_STEP_FREQ (0x1fffff << 11)
+#define STB0899_OFFST_STEP_FREQ 11
+#define STB0899_WIDTH_STEP_FREQ 21
+#define STB0899_ACQ_STATE (0x07 << 8)
+#define STB0899_OFFST_ACQ_STATE 8
+#define STB0899_WIDTH_ACQ_STATE 3
+#define STB0899_UW_DETECT_COUNT (0xff << 0)
+#define STB0899_OFFST_UW_DETECT_COUNT 0
+#define STB0899_WIDTH_UW_DETECT_COUNT 8
+
+#define STB0899_OFF0_ACQ_TIMEOUT 0xf378
+#define STB0899_BASE_ACQ_TIMEOUT 0x00000400
+#define STB0899_ACQ_TIMEOUT (0x3fffff << 0)
+#define STB0899_OFFST_ACQ_TIMEOUT 0
+#define STB0899_WIDTH_ACQ_TIMEOUT 22
+
+#define STB0899_OFF0_ACQ_TIME 0xf37c
+#define STB0899_BASE_ACQ_TIME 0x00000400
+#define STB0899_ACQ_TIME_SYM (0xffffff << 0)
+#define STB0899_OFFST_ACQ_TIME_SYM 0
+#define STB0899_WIDTH_ACQ_TIME_SYM 24
+
+#define STB0899_OFF0_FINAL_AGC_CNTRL 0xf308
+#define STB0899_BASE_FINAL_AGC_CNTRL 0x00000440
+#define STB0899_FINAL_GAIN_INIT (0x3fff << 12)
+#define STB0899_OFFST_FINAL_GAIN_INIT 12
+#define STB0899_WIDTH_FINAL_GAIN_INIT 14
+#define STB0899_FINAL_LOOP_GAIN (0x0f << 8)
+#define STB0899_OFFST_FINAL_LOOP_GAIN 8
+#define STB0899_WIDTH_FINAL_LOOP_GAIN 4
+#define STB0899_FINAL_LD_GAIN_INIT (0x01 << 7)
+#define STB0899_OFFST_FINAL_LD_GAIN_INIT 7
+#define STB0899_WIDTH_FINAL_LD_GAIN_INIT 1
+#define STB0899_FINAL_AGC_REF (0x7f << 0)
+#define STB0899_OFFST_FINAL_AGC_REF 0
+#define STB0899_WIDTH_FINAL_AGC_REF 7
+
+#define STB0899_OFF0_FINAL_AGC_GAIN 0xf30c
+#define STB0899_BASE_FINAL_AGC_GAIN 0x00000440
+#define STB0899_FINAL_AGC_GAIN (0x3fff << 0)
+#define STB0899_OFFST_FINAL_AGC_GAIN 0
+#define STB0899_WIDTH_FINAL_AGC_GAIN 14
+
+#define STB0899_OFF0_EQUALIZER_INIT 0xf310
+#define STB0899_BASE_EQUALIZER_INIT 0x00000440
+#define STB0899_EQ_SRST (0x01 << 1)
+#define STB0899_OFFST_EQ_SRST 1
+#define STB0899_WIDTH_EQ_SRST 1
+#define STB0899_EQ_INIT (0x01 << 0)
+#define STB0899_OFFST_EQ_INIT 0
+#define STB0899_WIDTH_EQ_INIT 1
+
+#define STB0899_OFF0_EQ_CNTRL 0xf314
+#define STB0899_BASE_EQ_CNTRL 0x00000440
+#define STB0899_EQ_ADAPT_MODE (0x01 << 18)
+#define STB0899_OFFST_EQ_ADAPT_MODE 18
+#define STB0899_WIDTH_EQ_ADAPT_MODE 1
+#define STB0899_EQ_DELAY (0x0f << 14)
+#define STB0899_OFFST_EQ_DELAY 14
+#define STB0899_WIDTH_EQ_DELAY 4
+#define STB0899_EQ_QUANT_LEVEL (0xff << 6)
+#define STB0899_OFFST_EQ_QUANT_LEVEL 6
+#define STB0899_WIDTH_EQ_QUANT_LEVEL 8
+#define STB0899_EQ_DISABLE_UPDATE (0x01 << 5)
+#define STB0899_OFFST_EQ_DISABLE_UPDATE 5
+#define STB0899_WIDTH_EQ_DISABLE_UPDATE 1
+#define STB0899_EQ_BYPASS (0x01 << 4)
+#define STB0899_OFFST_EQ_BYPASS 4
+#define STB0899_WIDTH_EQ_BYPASS 1
+#define STB0899_EQ_SHIFT (0x0f << 0)
+#define STB0899_OFFST_EQ_SHIFT 0
+#define STB0899_WIDTH_EQ_SHIFT 4
+
+#define STB0899_OFF0_EQ_I_INIT_COEFF_0 0xf320
+#define STB0899_OFF1_EQ_I_INIT_COEFF_1 0xf324
+#define STB0899_OFF2_EQ_I_INIT_COEFF_2 0xf328
+#define STB0899_OFF3_EQ_I_INIT_COEFF_3 0xf32c
+#define STB0899_OFF4_EQ_I_INIT_COEFF_4 0xf330
+#define STB0899_OFF5_EQ_I_INIT_COEFF_5 0xf334
+#define STB0899_OFF6_EQ_I_INIT_COEFF_6 0xf338
+#define STB0899_OFF7_EQ_I_INIT_COEFF_7 0xf33c
+#define STB0899_OFF8_EQ_I_INIT_COEFF_8 0xf340
+#define STB0899_OFF9_EQ_I_INIT_COEFF_9 0xf344
+#define STB0899_OFFa_EQ_I_INIT_COEFF_10 0xf348
+#define STB0899_BASE_EQ_I_INIT_COEFF_N 0x00000440
+#define STB0899_EQ_I_INIT_COEFF_N (0x0fff << 0)
+#define STB0899_OFFST_EQ_I_INIT_COEFF_N 0
+#define STB0899_WIDTH_EQ_I_INIT_COEFF_N 12
+
+#define STB0899_OFF0_EQ_Q_INIT_COEFF_0 0xf350
+#define STB0899_OFF1_EQ_Q_INIT_COEFF_1 0xf354
+#define STB0899_OFF2_EQ_Q_INIT_COEFF_2 0xf358
+#define STB0899_OFF3_EQ_Q_INIT_COEFF_3 0xf35c
+#define STB0899_OFF4_EQ_Q_INIT_COEFF_4 0xf360
+#define STB0899_OFF5_EQ_Q_INIT_COEFF_5 0xf364
+#define STB0899_OFF6_EQ_Q_INIT_COEFF_6 0xf368
+#define STB0899_OFF7_EQ_Q_INIT_COEFF_7 0xf36c
+#define STB0899_OFF8_EQ_Q_INIT_COEFF_8 0xf370
+#define STB0899_OFF9_EQ_Q_INIT_COEFF_9 0xf374
+#define STB0899_OFFa_EQ_Q_INIT_COEFF_10 0xf378
+#define STB0899_BASE_EQ_Q_INIT_COEFF_N 0x00000440
+#define STB0899_EQ_Q_INIT_COEFF_N (0x0fff << 0)
+#define STB0899_OFFST_EQ_Q_INIT_COEFF_N 0
+#define STB0899_WIDTH_EQ_Q_INIT_COEFF_N 12
+
+#define STB0899_OFF0_EQ_I_OUT_COEFF_0 0xf300
+#define STB0899_OFF1_EQ_I_OUT_COEFF_1 0xf304
+#define STB0899_OFF2_EQ_I_OUT_COEFF_2 0xf308
+#define STB0899_OFF3_EQ_I_OUT_COEFF_3 0xf30c
+#define STB0899_OFF4_EQ_I_OUT_COEFF_4 0xf310
+#define STB0899_OFF5_EQ_I_OUT_COEFF_5 0xf314
+#define STB0899_OFF6_EQ_I_OUT_COEFF_6 0xf318
+#define STB0899_OFF7_EQ_I_OUT_COEFF_7 0xf31c
+#define STB0899_OFF8_EQ_I_OUT_COEFF_8 0xf320
+#define STB0899_OFF9_EQ_I_OUT_COEFF_9 0xf324
+#define STB0899_OFFa_EQ_I_OUT_COEFF_10 0xf328
+#define STB0899_BASE_EQ_I_OUT_COEFF_N 0x00000460
+#define STB0899_EQ_I_OUT_COEFF_N (0x0fff << 0)
+#define STB0899_OFFST_EQ_I_OUT_COEFF_N 0
+#define STB0899_WIDTH_EQ_I_OUT_COEFF_N 12
+
+#define STB0899_OFF0_EQ_Q_OUT_COEFF_0 0xf330
+#define STB0899_OFF1_EQ_Q_OUT_COEFF_1 0xf334
+#define STB0899_OFF2_EQ_Q_OUT_COEFF_2 0xf338
+#define STB0899_OFF3_EQ_Q_OUT_COEFF_3 0xf33c
+#define STB0899_OFF4_EQ_Q_OUT_COEFF_4 0xf340
+#define STB0899_OFF5_EQ_Q_OUT_COEFF_5 0xf344
+#define STB0899_OFF6_EQ_Q_OUT_COEFF_6 0xf348
+#define STB0899_OFF7_EQ_Q_OUT_COEFF_7 0xf34c
+#define STB0899_OFF8_EQ_Q_OUT_COEFF_8 0xf350
+#define STB0899_OFF9_EQ_Q_OUT_COEFF_9 0xf354
+#define STB0899_OFFa_EQ_Q_OUT_COEFF_10 0xf358
+#define STB0899_BASE_EQ_Q_OUT_COEFF_N 0x00000460
+#define STB0899_EQ_Q_OUT_COEFF_N (0x0fff << 0)
+#define STB0899_OFFST_EQ_Q_OUT_COEFF_N 0
+#define STB0899_WIDTH_EQ_Q_OUT_COEFF_N 12
+
+/* S2 FEC */
+#define STB0899_OFF0_BLOCK_LNGTH 0xfa04
+#define STB0899_BASE_BLOCK_LNGTH 0x00000000
+#define STB0899_BLOCK_LENGTH (0xff << 0)
+#define STB0899_OFFST_BLOCK_LENGTH 0
+#define STB0899_WIDTH_BLOCK_LENGTH 8
+
+#define STB0899_OFF0_ROW_STR 0xfa08
+#define STB0899_BASE_ROW_STR 0x00000000
+#define STB0899_ROW_STRIDE (0xff << 0)
+#define STB0899_OFFST_ROW_STRIDE 0
+#define STB0899_WIDTH_ROW_STRIDE 8
+
+#define STB0899_OFF0_MAX_ITER 0xfa0c
+#define STB0899_BASE_MAX_ITER 0x00000000
+#define STB0899_MAX_ITERATIONS (0xff << 0)
+#define STB0899_OFFST_MAX_ITERATIONS 0
+#define STB0899_WIDTH_MAX_ITERATIONS 8
+
+#define STB0899_OFF0_BN_END_ADDR 0xfa10
+#define STB0899_BASE_BN_END_ADDR 0x00000000
+#define STB0899_BN_END_ADDR (0x0fff << 0)
+#define STB0899_OFFST_BN_END_ADDR 0
+#define STB0899_WIDTH_BN_END_ADDR 12
+
+#define STB0899_OFF0_CN_END_ADDR 0xfa14
+#define STB0899_BASE_CN_END_ADDR 0x00000000
+#define STB0899_CN_END_ADDR (0x0fff << 0)
+#define STB0899_OFFST_CN_END_ADDR 0
+#define STB0899_WIDTH_CN_END_ADDR 12
+
+#define STB0899_OFF0_INFO_LENGTH 0xfa1c
+#define STB0899_BASE_INFO_LENGTH 0x00000000
+#define STB0899_INFO_LENGTH (0xff << 0)
+#define STB0899_OFFST_INFO_LENGTH 0
+#define STB0899_WIDTH_INFO_LENGTH 8
+
+#define STB0899_OFF0_BOT_ADDR 0xfa20
+#define STB0899_BASE_BOT_ADDR 0x00000000
+#define STB0899_BOTTOM_BASE_ADDR (0x03ff << 0)
+#define STB0899_OFFST_BOTTOM_BASE_ADDR 0
+#define STB0899_WIDTH_BOTTOM_BASE_ADDR 10
+
+#define STB0899_OFF0_BCH_BLK_LN 0xfa24
+#define STB0899_BASE_BCH_BLK_LN 0x00000000
+#define STB0899_BCH_BLOCK_LENGTH (0xffff << 0)
+#define STB0899_OFFST_BCH_BLOCK_LENGTH 0
+#define STB0899_WIDTH_BCH_BLOCK_LENGTH 16
+
+#define STB0899_OFF0_BCH_T 0xfa28
+#define STB0899_BASE_BCH_T 0x00000000
+#define STB0899_BCH_T (0x0f << 0)
+#define STB0899_OFFST_BCH_T 0
+#define STB0899_WIDTH_BCH_T 4
+
+#define STB0899_OFF0_CNFG_MODE 0xfa00
+#define STB0899_BASE_CNFG_MODE 0x00000800
+#define STB0899_MODCOD (0x1f << 2)
+#define STB0899_OFFST_MODCOD 2
+#define STB0899_WIDTH_MODCOD 5
+#define STB0899_MODCOD_SEL (0x01 << 1)
+#define STB0899_OFFST_MODCOD_SEL 1
+#define STB0899_WIDTH_MODCOD_SEL 1
+#define STB0899_CONFIG_MODE (0x01 << 0)
+#define STB0899_OFFST_CONFIG_MODE 0
+#define STB0899_WIDTH_CONFIG_MODE 1
+
+#define STB0899_OFF0_LDPC_STAT 0xfa04
+#define STB0899_BASE_LDPC_STAT 0x00000800
+#define STB0899_ITERATION (0xff << 3)
+#define STB0899_OFFST_ITERATION 3
+#define STB0899_WIDTH_ITERATION 8
+#define STB0899_LDPC_DEC_STATE (0x07 << 0)
+#define STB0899_OFFST_LDPC_DEC_STATE 0
+#define STB0899_WIDTH_LDPC_DEC_STATE 3
+
+#define STB0899_OFF0_ITER_SCALE 0xfa08
+#define STB0899_BASE_ITER_SCALE 0x00000800
+#define STB0899_ITERATION_SCALE (0xff << 0)
+#define STB0899_OFFST_ITERATION_SCALE 0
+#define STB0899_WIDTH_ITERATION_SCALE 8
+
+#define STB0899_OFF0_INPUT_MODE 0xfa0c
+#define STB0899_BASE_INPUT_MODE 0x00000800
+#define STB0899_SD_BLOCK1_STREAM0 (0x01 << 0)
+#define STB0899_OFFST_SD_BLOCK1_STREAM0 0
+#define STB0899_WIDTH_SD_BLOCK1_STREAM0 1
+
+#define STB0899_OFF0_LDPCDECRST 0xfa10
+#define STB0899_BASE_LDPCDECRST 0x00000800
+#define STB0899_LDPC_DEC_RST (0x01 << 0)
+#define STB0899_OFFST_LDPC_DEC_RST 0
+#define STB0899_WIDTH_LDPC_DEC_RST 1
+
+#define STB0899_OFF0_CLK_PER_BYTE_RW 0xfa14
+#define STB0899_BASE_CLK_PER_BYTE_RW 0x00000800
+#define STB0899_CLKS_PER_BYTE (0x0f << 0)
+#define STB0899_OFFST_CLKS_PER_BYTE 0
+#define STB0899_WIDTH_CLKS_PER_BYTE 5
+
+#define STB0899_OFF0_BCH_ERRORS 0xfa18
+#define STB0899_BASE_BCH_ERRORS 0x00000800
+#define STB0899_BCH_ERRORS (0x0f << 0)
+#define STB0899_OFFST_BCH_ERRORS 0
+#define STB0899_WIDTH_BCH_ERRORS 4
+
+#define STB0899_OFF0_LDPC_ERRORS 0xfa1c
+#define STB0899_BASE_LDPC_ERRORS 0x00000800
+#define STB0899_LDPC_ERRORS (0xffff << 0)
+#define STB0899_OFFST_LDPC_ERRORS 0
+#define STB0899_WIDTH_LDPC_ERRORS 16
+
+#define STB0899_OFF0_BCH_MODE 0xfa20
+#define STB0899_BASE_BCH_MODE 0x00000800
+#define STB0899_BCH_CORRECT_N (0x01 << 1)
+#define STB0899_OFFST_BCH_CORRECT_N 1
+#define STB0899_WIDTH_BCH_CORRECT_N 1
+#define STB0899_FULL_BYPASS (0x01 << 0)
+#define STB0899_OFFST_FULL_BYPASS 0
+#define STB0899_WIDTH_FULL_BYPASS 1
+
+#define STB0899_OFF0_ERR_ACC_PER 0xfa24
+#define STB0899_BASE_ERR_ACC_PER 0x00000800
+#define STB0899_BCH_ERR_ACC_PERIOD (0x0f << 0)
+#define STB0899_OFFST_BCH_ERR_ACC_PERIOD 0
+#define STB0899_WIDTH_BCH_ERR_ACC_PERIOD 4
+
+#define STB0899_OFF0_BCH_ERR_ACC 0xfa28
+#define STB0899_BASE_BCH_ERR_ACC 0x00000800
+#define STB0899_BCH_ERR_ACCUM (0xff << 0)
+#define STB0899_OFFST_BCH_ERR_ACCUM 0
+#define STB0899_WIDTH_BCH_ERR_ACCUM 8
+
+#define STB0899_OFF0_FEC_CORE_ID_REG 0xfa2c
+#define STB0899_BASE_FEC_CORE_ID_REG 0x00000800
+#define STB0899_FEC_CORE_ID (0xffffffff << 0)
+#define STB0899_OFFST_FEC_CORE_ID 0
+#define STB0899_WIDTH_FEC_CORE_ID 32
+
+#define STB0899_OFF0_FEC_VER_ID_REG 0xfa34
+#define STB0899_BASE_FEC_VER_ID_REG 0x00000800
+#define STB0899_FEC_VER_ID (0xff << 0)
+#define STB0899_OFFST_FEC_VER_ID 0
+#define STB0899_WIDTH_FEC_VER_ID 8
+
+#define STB0899_OFF0_FEC_TP_SEL 0xfa38
+#define STB0899_BASE_FEC_TP_SEL 0x00000800
+
+#define STB0899_OFF0_CSM_CNTRL1 0xf310
+#define STB0899_BASE_CSM_CNTRL1 0x00000400
+#define STB0899_CSM_FORCE_FREQLOCK (0x01 << 19)
+#define STB0899_OFFST_CSM_FORCE_FREQLOCK 19
+#define STB0899_WIDTH_CSM_FORCE_FREQLOCK 1
+#define STB0899_CSM_FREQ_LOCKSTATE (0x01 << 18)
+#define STB0899_OFFST_CSM_FREQ_LOCKSTATE 18
+#define STB0899_WIDTH_CSM_FREQ_LOCKSTATE 1
+#define STB0899_CSM_AUTO_PARAM (0x01 << 17)
+#define STB0899_OFFST_CSM_AUTO_PARAM 17
+#define STB0899_WIDTH_CSM_AUTO_PARAM 1
+#define STB0899_FE_LOOP_SHIFT (0x07 << 14)
+#define STB0899_OFFST_FE_LOOP_SHIFT 14
+#define STB0899_WIDTH_FE_LOOP_SHIFT 3
+#define STB0899_CSM_AGC_SHIFT (0x07 << 11)
+#define STB0899_OFFST_CSM_AGC_SHIFT 11
+#define STB0899_WIDTH_CSM_AGC_SHIFT 3
+#define STB0899_CSM_AGC_GAIN (0x1ff << 2)
+#define STB0899_OFFST_CSM_AGC_GAIN 2
+#define STB0899_WIDTH_CSM_AGC_GAIN 9
+#define STB0899_CSM_TWO_PASS (0x01 << 1)
+#define STB0899_OFFST_CSM_TWO_PASS 1
+#define STB0899_WIDTH_CSM_TWO_PASS 1
+#define STB0899_CSM_DVT_TABLE (0x01 << 0)
+#define STB0899_OFFST_CSM_DVT_TABLE 0
+#define STB0899_WIDTH_CSM_DVT_TABLE 1
+
+#define STB0899_OFF0_CSM_CNTRL2 0xf314
+#define STB0899_BASE_CSM_CNTRL2 0x00000400
+#define STB0899_CSM_GAMMA_RHO_ACQ (0x1ff << 9)
+#define STB0899_OFFST_CSM_GAMMA_RHOACQ 9
+#define STB0899_WIDTH_CSM_GAMMA_RHOACQ 9
+#define STB0899_CSM_GAMMA_ACQ (0x1ff << 0)
+#define STB0899_OFFST_CSM_GAMMA_ACQ 0
+#define STB0899_WIDTH_CSM_GAMMA_ACQ 9
+
+#define STB0899_OFF0_CSM_CNTRL3 0xf318
+#define STB0899_BASE_CSM_CNTRL3 0x00000400
+#define STB0899_CSM_GAMMA_RHO_TRACK (0x1ff << 9)
+#define STB0899_OFFST_CSM_GAMMA_RHOTRACK 9
+#define STB0899_WIDTH_CSM_GAMMA_RHOTRACK 9
+#define STB0899_CSM_GAMMA_TRACK (0x1ff << 0)
+#define STB0899_OFFST_CSM_GAMMA_TRACK 0
+#define STB0899_WIDTH_CSM_GAMMA_TRACK 9
+
+#define STB0899_OFF0_CSM_CNTRL4 0xf31c
+#define STB0899_BASE_CSM_CNTRL4 0x00000400
+#define STB0899_CSM_PHASEDIFF_THRESH (0x0f << 8)
+#define STB0899_OFFST_CSM_PHASEDIFF_THRESH 8
+#define STB0899_WIDTH_CSM_PHASEDIFF_THRESH 4
+#define STB0899_CSM_LOCKCOUNT_THRESH (0xff << 0)
+#define STB0899_OFFST_CSM_LOCKCOUNT_THRESH 0
+#define STB0899_WIDTH_CSM_LOCKCOUNT_THRESH 8
+
+/* Check on chapter 8 page 42 */
+#define STB0899_ERRCTRL1 0xf574
+#define STB0899_ERRCTRL2 0xf575
+#define STB0899_ERRCTRL3 0xf576
+#define STB0899_ERR_SRC_S1 (0x1f << 3)
+#define STB0899_OFFST_ERR_SRC_S1 3
+#define STB0899_WIDTH_ERR_SRC_S1 5
+#define STB0899_ERR_SRC_S2 (0x0f << 0)
+#define STB0899_OFFST_ERR_SRC_S2 0
+#define STB0899_WIDTH_ERR_SRC_S2 4
+#define STB0899_NOE (0x07 << 0)
+#define STB0899_OFFST_NOE 0
+#define STB0899_WIDTH_NOE 3
+
+#define STB0899_ECNT1M 0xf524
+#define STB0899_ECNT1L 0xf525
+#define STB0899_ECNT2M 0xf526
+#define STB0899_ECNT2L 0xf527
+#define STB0899_ECNT3M 0xf528
+#define STB0899_ECNT3L 0xf529
+
+#define STB0899_DMONMSK1 0xf57b
+#define STB0899_DMONMSK1_WAIT_1STEP (1 << 7)
+#define STB0899_DMONMSK1_FREE_14 (1 << 6)
+#define STB0899_DMONMSK1_AVRGVIT_CALC (1 << 5)
+#define STB0899_DMONMSK1_FREE_12 (1 << 4)
+#define STB0899_DMONMSK1_FREE_11 (1 << 3)
+#define STB0899_DMONMSK1_B0DIV_CALC (1 << 2)
+#define STB0899_DMONMSK1_KDIVB1_CALC (1 << 1)
+#define STB0899_DMONMSK1_KDIVB2_CALC (1 << 0)
+
+#define STB0899_DMONMSK0 0xf57c
+#define STB0899_DMONMSK0_SMOTTH_CALC (1 << 7)
+#define STB0899_DMONMSK0_FREE_6 (1 << 6)
+#define STB0899_DMONMSK0_SIGPOWER_CALC (1 << 5)
+#define STB0899_DMONMSK0_QSEUIL_CALC (1 << 4)
+#define STB0899_DMONMSK0_FREE_3 (1 << 3)
+#define STB0899_DMONMSK0_FREE_2 (1 << 2)
+#define STB0899_DMONMSK0_KVDIVB1_CALC (1 << 1)
+#define STB0899_DMONMSK0_KVDIVB2_CALC (1 << 0)
+
+#define STB0899_TSULC 0xf549
+#define STB0899_ULNOSYNCBYTES (0x01 << 7)
+#define STB0899_OFFST_ULNOSYNCBYTES 7
+#define STB0899_WIDTH_ULNOSYNCBYTES 1
+#define STB0899_ULPARITY_ON (0x01 << 6)
+#define STB0899_OFFST_ULPARITY_ON 6
+#define STB0899_WIDTH_ULPARITY_ON 1
+#define STB0899_ULSYNCOUTRS (0x01 << 5)
+#define STB0899_OFFST_ULSYNCOUTRS 5
+#define STB0899_WIDTH_ULSYNCOUTRS 1
+#define STB0899_ULDSS_PACKETS (0x01 << 0)
+#define STB0899_OFFST_ULDSS_PACKETS 0
+#define STB0899_WIDTH_ULDSS_PACKETS 1
+
+#define STB0899_TSLPL 0xf54b
+#define STB0899_LLDVBS2_MODE (0x01 << 4)
+#define STB0899_OFFST_LLDVBS2_MODE 4
+#define STB0899_WIDTH_LLDVBS2_MODE 1
+#define STB0899_LLISSYI_ON (0x01 << 3)
+#define STB0899_OFFST_LLISSYI_ON 3
+#define STB0899_WIDTH_LLISSYI_ON 1
+#define STB0899_LLNPD_ON (0x01 << 2)
+#define STB0899_OFFST_LLNPD_ON 2
+#define STB0899_WIDTH_LLNPD_ON 1
+#define STB0899_LLCRC8_ON (0x01 << 1)
+#define STB0899_OFFST_LLCRC8_ON 1
+#define STB0899_WIDTH_LLCRC8_ON 1
+
+#define STB0899_TSCFGH 0xf54c
+#define STB0899_OUTRS_PS (0x01 << 6)
+#define STB0899_OFFST_OUTRS_PS 6
+#define STB0899_WIDTH_OUTRS_PS 1
+#define STB0899_SYNCBYTE (0x01 << 5)
+#define STB0899_OFFST_SYNCBYTE 5
+#define STB0899_WIDTH_SYNCBYTE 1
+#define STB0899_PFBIT (0x01 << 4)
+#define STB0899_OFFST_PFBIT 4
+#define STB0899_WIDTH_PFBIT 1
+#define STB0899_ERR_BIT (0x01 << 3)
+#define STB0899_OFFST_ERR_BIT 3
+#define STB0899_WIDTH_ERR_BIT 1
+#define STB0899_MPEG (0x01 << 2)
+#define STB0899_OFFST_MPEG 2
+#define STB0899_WIDTH_MPEG 1
+#define STB0899_CLK_POL (0x01 << 1)
+#define STB0899_OFFST_CLK_POL 1
+#define STB0899_WIDTH_CLK_POL 1
+#define STB0899_FORCE0 (0x01 << 0)
+#define STB0899_OFFST_FORCE0 0
+#define STB0899_WIDTH_FORCE0 1
+
+#define STB0899_TSCFGM 0xf54d
+#define STB0899_LLPRIORITY (0x01 << 3)
+#define STB0899_OFFST_LLPRIORIY 3
+#define STB0899_WIDTH_LLPRIORITY 1
+#define STB0899_EN188 (0x01 << 2)
+#define STB0899_OFFST_EN188 2
+#define STB0899_WIDTH_EN188 1
+
+#define STB0899_TSCFGL 0xf54e
+#define STB0899_DEL_ERRPCK (0x01 << 7)
+#define STB0899_OFFST_DEL_ERRPCK 7
+#define STB0899_WIDTH_DEL_ERRPCK 1
+#define STB0899_ERRFLAGSTD (0x01 << 5)
+#define STB0899_OFFST_ERRFLAGSTD 5
+#define STB0899_WIDTH_ERRFLAGSTD 1
+#define STB0899_MPEGERR (0x01 << 4)
+#define STB0899_OFFST_MPEGERR 4
+#define STB0899_WIDTH_MPEGERR 1
+#define STB0899_BCH_CHK (0x01 << 3)
+#define STB0899_OFFST_BCH_CHK 5
+#define STB0899_WIDTH_BCH_CHK 1
+#define STB0899_CRC8CHK (0x01 << 2)
+#define STB0899_OFFST_CRC8CHK 2
+#define STB0899_WIDTH_CRC8CHK 1
+#define STB0899_SPEC_INFO (0x01 << 1)
+#define STB0899_OFFST_SPEC_INFO 1
+#define STB0899_WIDTH_SPEC_INFO 1
+#define STB0899_LOW_PRIO_CLK (0x01 << 0)
+#define STB0899_OFFST_LOW_PRIO_CLK 0
+#define STB0899_WIDTH_LOW_PRIO_CLK 1
+#define STB0899_ERROR_NORM (0x00 << 0)
+#define STB0899_OFFST_ERROR_NORM 0
+#define STB0899_WIDTH_ERROR_NORM 0
+
+#define STB0899_TSOUT 0xf54f
+#define STB0899_RSSYNCDEL 0xf550
+#define STB0899_TSINHDELH 0xf551
+#define STB0899_TSINHDELM 0xf552
+#define STB0899_TSINHDELL 0xf553
+#define STB0899_TSLLSTKM 0xf55a
+#define STB0899_TSLLSTKL 0xf55b
+#define STB0899_TSULSTKM 0xf55c
+#define STB0899_TSULSTKL 0xf55d
+#define STB0899_TSSTATUS 0xf561
+
+#define STB0899_PDELCTRL 0xf600
+#define STB0899_INVERT_RES (0x01 << 7)
+#define STB0899_OFFST_INVERT_RES 7
+#define STB0899_WIDTH_INVERT_RES 1
+#define STB0899_FORCE_ACCEPTED (0x01 << 6)
+#define STB0899_OFFST_FORCE_ACCEPTED 6
+#define STB0899_WIDTH_FORCE_ACCEPTED 1
+#define STB0899_FILTER_EN (0x01 << 5)
+#define STB0899_OFFST_FILTER_EN 5
+#define STB0899_WIDTH_FILTER_EN 1
+#define STB0899_LOCKFALL_THRESH (0x01 << 4)
+#define STB0899_OFFST_LOCKFALL_THRESH 4
+#define STB0899_WIDTH_LOCKFALL_THRESH 1
+#define STB0899_HYST_EN (0x01 << 3)
+#define STB0899_OFFST_HYST_EN 3
+#define STB0899_WIDTH_HYST_EN 1
+#define STB0899_HYST_SWRST (0x01 << 2)
+#define STB0899_OFFST_HYST_SWRST 2
+#define STB0899_WIDTH_HYST_SWRST 1
+#define STB0899_ALGO_EN (0x01 << 1)
+#define STB0899_OFFST_ALGO_EN 1
+#define STB0899_WIDTH_ALGO_EN 1
+#define STB0899_ALGO_SWRST (0x01 << 0)
+#define STB0899_OFFST_ALGO_SWRST 0
+#define STB0899_WIDTH_ALGO_SWRST 1
+
+#define STB0899_PDELCTRL2 0xf601
+#define STB0899_BBHCTRL1 0xf602
+#define STB0899_BBHCTRL2 0xf603
+#define STB0899_HYSTTHRESH 0xf604
+
+#define STB0899_MATCSTM 0xf605
+#define STB0899_MATCSTL 0xf606
+#define STB0899_UPLCSTM 0xf607
+#define STB0899_UPLCSTL 0xf608
+#define STB0899_DFLCSTM 0xf609
+#define STB0899_DFLCSTL 0xf60a
+#define STB0899_SYNCCST 0xf60b
+#define STB0899_SYNCDCSTM 0xf60c
+#define STB0899_SYNCDCSTL 0xf60d
+#define STB0899_ISI_ENTRY 0xf60e
+#define STB0899_ISI_BIT_EN 0xf60f
+#define STB0899_MATSTRM 0xf610
+#define STB0899_MATSTRL 0xf611
+#define STB0899_UPLSTRM 0xf612
+#define STB0899_UPLSTRL 0xf613
+#define STB0899_DFLSTRM 0xf614
+#define STB0899_DFLSTRL 0xf615
+#define STB0899_SYNCSTR 0xf616
+#define STB0899_SYNCDSTRM 0xf617
+#define STB0899_SYNCDSTRL 0xf618
+
+#define STB0899_CFGPDELSTATUS1 0xf619
+#define STB0899_BADDFL (0x01 << 6)
+#define STB0899_OFFST_BADDFL 6
+#define STB0899_WIDTH_BADDFL 1
+#define STB0899_CONTINUOUS_STREAM (0x01 << 5)
+#define STB0899_OFFST_CONTINUOUS_STREAM 5
+#define STB0899_WIDTH_CONTINUOUS_STREAM 1
+#define STB0899_ACCEPTED_STREAM (0x01 << 4)
+#define STB0899_OFFST_ACCEPTED_STREAM 4
+#define STB0899_WIDTH_ACCEPTED_STREAM 1
+#define STB0899_BCH_ERRFLAG (0x01 << 3)
+#define STB0899_OFFST_BCH_ERRFLAG 3
+#define STB0899_WIDTH_BCH_ERRFLAG 1
+#define STB0899_CRCRES (0x01 << 2)
+#define STB0899_OFFST_CRCRES 2
+#define STB0899_WIDTH_CRCRES 1
+#define STB0899_CFGPDELSTATUS_LOCK (0x01 << 1)
+#define STB0899_OFFST_CFGPDELSTATUS_LOCK 1
+#define STB0899_WIDTH_CFGPDELSTATUS_LOCK 1
+#define STB0899_1STLOCK (0x01 << 0)
+#define STB0899_OFFST_1STLOCK 0
+#define STB0899_WIDTH_1STLOCK 1
+
+#define STB0899_CFGPDELSTATUS2 0xf61a
+#define STB0899_BBFERRORM 0xf61b
+#define STB0899_BBFERRORL 0xf61c
+#define STB0899_UPKTERRORM 0xf61d
+#define STB0899_UPKTERRORL 0xf61e
+
+#define STB0899_TSTCK 0xff10
+
+#define STB0899_TSTRES 0xff11
+#define STB0899_FRESLDPC (0x01 << 7)
+#define STB0899_OFFST_FRESLDPC 7
+#define STB0899_WIDTH_FRESLDPC 1
+#define STB0899_FRESRS (0x01 << 6)
+#define STB0899_OFFST_FRESRS 6
+#define STB0899_WIDTH_FRESRS 1
+#define STB0899_FRESVIT (0x01 << 5)
+#define STB0899_OFFST_FRESVIT 5
+#define STB0899_WIDTH_FRESVIT 1
+#define STB0899_FRESMAS1_2 (0x01 << 4)
+#define STB0899_OFFST_FRESMAS1_2 4
+#define STB0899_WIDTH_FRESMAS1_2 1
+#define STB0899_FRESACS (0x01 << 3)
+#define STB0899_OFFST_FRESACS 3
+#define STB0899_WIDTH_FRESACS 1
+#define STB0899_FRESSYM (0x01 << 2)
+#define STB0899_OFFST_FRESSYM 2
+#define STB0899_WIDTH_FRESSYM 1
+#define STB0899_FRESMAS (0x01 << 1)
+#define STB0899_OFFST_FRESMAS 1
+#define STB0899_WIDTH_FRESMAS 1
+#define STB0899_FRESINT (0x01 << 0)
+#define STB0899_OFFST_FRESINIT 0
+#define STB0899_WIDTH_FRESINIT 1
+
+#define STB0899_TSTOUT 0xff12
+#define STB0899_EN_SIGNATURE (0x01 << 7)
+#define STB0899_OFFST_EN_SIGNATURE 7
+#define STB0899_WIDTH_EN_SIGNATURE 1
+#define STB0899_BCLK_CLK (0x01 << 6)
+#define STB0899_OFFST_BCLK_CLK 6
+#define STB0899_WIDTH_BCLK_CLK 1
+#define STB0899_SGNL_OUT (0x01 << 5)
+#define STB0899_OFFST_SGNL_OUT 5
+#define STB0899_WIDTH_SGNL_OUT 1
+#define STB0899_TS (0x01 << 4)
+#define STB0899_OFFST_TS 4
+#define STB0899_WIDTH_TS 1
+#define STB0899_CTEST (0x01 << 0)
+#define STB0899_OFFST_CTEST 0
+#define STB0899_WIDTH_CTEST 1
+
+#define STB0899_TSTIN 0xff13
+#define STB0899_TEST_IN (0x01 << 7)
+#define STB0899_OFFST_TEST_IN 7
+#define STB0899_WIDTH_TEST_IN 1
+#define STB0899_EN_ADC (0x01 << 6)
+#define STB0899_OFFST_EN_ADC 6
+#define STB0899_WIDTH_ENADC 1
+#define STB0899_SGN_ADC (0x01 << 5)
+#define STB0899_OFFST_SGN_ADC 5
+#define STB0899_WIDTH_SGN_ADC 1
+#define STB0899_BCLK_IN (0x01 << 4)
+#define STB0899_OFFST_BCLK_IN 4
+#define STB0899_WIDTH_BCLK_IN 1
+#define STB0899_JETONIN_MODE (0x01 << 3)
+#define STB0899_OFFST_JETONIN_MODE 3
+#define STB0899_WIDTH_JETONIN_MODE 1
+#define STB0899_BCLK_VALUE (0x01 << 2)
+#define STB0899_OFFST_BCLK_VALUE 2
+#define STB0899_WIDTH_BCLK_VALUE 1
+#define STB0899_SGNRST_T12 (0x01 << 1)
+#define STB0899_OFFST_SGNRST_T12 1
+#define STB0899_WIDTH_SGNRST_T12 1
+#define STB0899_LOWSP_ENAX (0x01 << 0)
+#define STB0899_OFFST_LOWSP_ENAX 0
+#define STB0899_WIDTH_LOWSP_ENAX 1
+
+#define STB0899_TSTSYS 0xff14
+#define STB0899_TSTCHIP 0xff15
+#define STB0899_TSTFREE 0xff16
+#define STB0899_TSTI2C 0xff17
+#define STB0899_BITSPEEDM 0xff1c
+#define STB0899_BITSPEEDL 0xff1d
+#define STB0899_TBUSBIT 0xff1e
+#define STB0899_TSTDIS 0xff24
+#define STB0899_TSTDISRX 0xff25
+#define STB0899_TSTJETON 0xff28
+#define STB0899_TSTDCADJ 0xff40
+#define STB0899_TSTAGC1 0xff41
+#define STB0899_TSTAGC1N 0xff42
+#define STB0899_TSTPOLYPH 0xff48
+#define STB0899_TSTR 0xff49
+#define STB0899_TSTAGC2 0xff4a
+#define STB0899_TSTCTL1 0xff4b
+#define STB0899_TSTCTL2 0xff4c
+#define STB0899_TSTCTL3 0xff4d
+#define STB0899_TSTDEMAP 0xff50
+#define STB0899_TSTDEMAP2 0xff51
+#define STB0899_TSTDEMMON 0xff52
+#define STB0899_TSTRATE 0xff53
+#define STB0899_TSTSELOUT 0xff54
+#define STB0899_TSYNC 0xff55
+#define STB0899_TSTERR 0xff56
+#define STB0899_TSTRAM1 0xff58
+#define STB0899_TSTVSELOUT 0xff59
+#define STB0899_TSTFORCEIN 0xff5a
+#define STB0899_TSTRS1 0xff5c
+#define STB0899_TSTRS2 0xff5d
+#define STB0899_TSTRS3 0xff53
+
+#define STB0899_INTBUFSTATUS 0xf200
+#define STB0899_INTBUFCTRL 0xf201
+#define STB0899_PCKLENUL 0xf55e
+#define STB0899_PCKLENLL 0xf55f
+#define STB0899_RSPCKLEN 0xf560
+
+/* 2 registers */
+#define STB0899_SYNCDCST 0xf60c
+
+/* DiSEqC */
+#define STB0899_DISCNTRL1 0xf0a0
+#define STB0899_TIMOFF (0x01 << 7)
+#define STB0899_OFFST_TIMOFF 7
+#define STB0899_WIDTH_TIMOFF 1
+#define STB0899_DISEQCRESET (0x01 << 6)
+#define STB0899_OFFST_DISEQCRESET 6
+#define STB0899_WIDTH_DISEQCRESET 1
+#define STB0899_TIMCMD (0x03 << 4)
+#define STB0899_OFFST_TIMCMD 4
+#define STB0899_WIDTH_TIMCMD 2
+#define STB0899_DISPRECHARGE (0x01 << 2)
+#define STB0899_OFFST_DISPRECHARGE 2
+#define STB0899_WIDTH_DISPRECHARGE 1
+#define STB0899_DISEQCMODE (0x03 << 0)
+#define STB0899_OFFST_DISEQCMODE 0
+#define STB0899_WIDTH_DISEQCMODE 2
+
+#define STB0899_DISCNTRL2 0xf0a1
+#define STB0899_RECEIVER_ON (0x01 << 7)
+#define STB0899_OFFST_RECEIVER_ON 7
+#define STB0899_WIDTH_RECEIVER_ON 1
+#define STB0899_IGNO_SHORT_22K (0x01 << 6)
+#define STB0899_OFFST_IGNO_SHORT_22K 6
+#define STB0899_WIDTH_IGNO_SHORT_22K 1
+#define STB0899_ONECHIP_TRX (0x01 << 5)
+#define STB0899_OFFST_ONECHIP_TRX 5
+#define STB0899_WIDTH_ONECHIP_TRX 1
+#define STB0899_EXT_ENVELOP (0x01 << 4)
+#define STB0899_OFFST_EXT_ENVELOP 4
+#define STB0899_WIDTH_EXT_ENVELOP 1
+#define STB0899_PIN_SELECT (0x03 << 2)
+#define STB0899_OFFST_PIN_SELCT 2
+#define STB0899_WIDTH_PIN_SELCT 2
+#define STB0899_IRQ_RXEND (0x01 << 1)
+#define STB0899_OFFST_IRQ_RXEND 1
+#define STB0899_WIDTH_IRQ_RXEND 1
+#define STB0899_IRQ_4NBYTES (0x01 << 0)
+#define STB0899_OFFST_IRQ_4NBYTES 0
+#define STB0899_WIDTH_IRQ_4NBYTES 1
+
+#define STB0899_DISRX_ST0 0xf0a4
+#define STB0899_RXEND (0x01 << 7)
+#define STB0899_OFFST_RXEND 7
+#define STB0899_WIDTH_RXEND 1
+#define STB0899_RXACTIVE (0x01 << 6)
+#define STB0899_OFFST_RXACTIVE 6
+#define STB0899_WIDTH_RXACTIVE 1
+#define STB0899_SHORT22K (0x01 << 5)
+#define STB0899_OFFST_SHORT22K 5
+#define STB0899_WIDTH_SHORT22K 1
+#define STB0899_CONTTONE (0x01 << 4)
+#define STB0899_OFFST_CONTTONE 4
+#define STB0899_WIDTH_CONTONE 1
+#define STB0899_4BFIFOREDY (0x01 << 3)
+#define STB0899_OFFST_4BFIFOREDY 3
+#define STB0899_WIDTH_4BFIFOREDY 1
+#define STB0899_FIFOEMPTY (0x01 << 2)
+#define STB0899_OFFST_FIFOEMPTY 2
+#define STB0899_WIDTH_FIFOEMPTY 1
+#define STB0899_ABORTTRX (0x01 << 0)
+#define STB0899_OFFST_ABORTTRX 0
+#define STB0899_WIDTH_ABORTTRX 1
+
+#define STB0899_DISRX_ST1 0xf0a5
+#define STB0899_RXFAIL (0x01 << 7)
+#define STB0899_OFFST_RXFAIL 7
+#define STB0899_WIDTH_RXFAIL 1
+#define STB0899_FIFOPFAIL (0x01 << 6)
+#define STB0899_OFFST_FIFOPFAIL 6
+#define STB0899_WIDTH_FIFOPFAIL 1
+#define STB0899_RXNONBYTES (0x01 << 5)
+#define STB0899_OFFST_RXNONBYTES 5
+#define STB0899_WIDTH_RXNONBYTES 1
+#define STB0899_FIFOOVF (0x01 << 4)
+#define STB0899_OFFST_FIFOOVF 4
+#define STB0899_WIDTH_FIFOOVF 1
+#define STB0899_FIFOBYTENBR (0x0f << 0)
+#define STB0899_OFFST_FIFOBYTENBR 0
+#define STB0899_WIDTH_FIFOBYTENBR 4
+
+#define STB0899_DISPARITY 0xf0a6
+
+#define STB0899_DISFIFO 0xf0a7
+
+#define STB0899_DISSTATUS 0xf0a8
+#define STB0899_FIFOFULL (0x01 << 6)
+#define STB0899_OFFST_FIFOFULL 6
+#define STB0899_WIDTH_FIFOFULL 1
+#define STB0899_TXIDLE (0x01 << 5)
+#define STB0899_OFFST_TXIDLE 5
+#define STB0899_WIDTH_TXIDLE 1
+#define STB0899_GAPBURST (0x01 << 4)
+#define STB0899_OFFST_GAPBURST 4
+#define STB0899_WIDTH_GAPBURST 1
+#define STB0899_TXFIFOBYTES (0x0f << 0)
+#define STB0899_OFFST_TXFIFOBYTES 0
+#define STB0899_WIDTH_TXFIFOBYTES 4
+#define STB0899_DISF22 0xf0a9
+
+#define STB0899_DISF22RX 0xf0aa
+
+/* General Purpose */
+#define STB0899_SYSREG 0xf101
+#define STB0899_ACRPRESC 0xf110
+#define STB0899_OFFST_RSVD2 7
+#define STB0899_WIDTH_RSVD2 1
+#define STB0899_OFFST_ACRPRESC 4
+#define STB0899_WIDTH_ACRPRESC 3
+#define STB0899_OFFST_RSVD1 3
+#define STB0899_WIDTH_RSVD1 1
+#define STB0899_OFFST_ACRPRESC2 0
+#define STB0899_WIDTH_ACRPRESC2 3
+
+#define STB0899_ACRDIV1 0xf111
+#define STB0899_ACRDIV2 0xf112
+#define STB0899_DACR1 0xf113
+#define STB0899_DACR2 0xf114
+#define STB0899_OUTCFG 0xf11c
+#define STB0899_MODECFG 0xf11d
+#define STB0899_NCOARSE 0xf1b3
+
+#define STB0899_SYNTCTRL 0xf1b6
+#define STB0899_STANDBY (0x01 << 7)
+#define STB0899_OFFST_STANDBY 7
+#define STB0899_WIDTH_STANDBY 1
+#define STB0899_BYPASSPLL (0x01 << 6)
+#define STB0899_OFFST_BYPASSPLL 6
+#define STB0899_WIDTH_BYPASSPLL 1
+#define STB0899_SEL1XRATIO (0x01 << 5)
+#define STB0899_OFFST_SEL1XRATIO 5
+#define STB0899_WIDTH_SEL1XRATIO 1
+#define STB0899_SELOSCI (0x01 << 1)
+#define STB0899_OFFST_SELOSCI 1
+#define STB0899_WIDTH_SELOSCI 1
+
+#define STB0899_FILTCTRL 0xf1b7
+#define STB0899_SYSCTRL 0xf1b8
+
+#define STB0899_STOPCLK1 0xf1c2
+#define STB0899_STOP_CKINTBUF108 (0x01 << 7)
+#define STB0899_OFFST_STOP_CKINTBUF108 7
+#define STB0899_WIDTH_STOP_CKINTBUF108 1
+#define STB0899_STOP_CKINTBUF216 (0x01 << 6)
+#define STB0899_OFFST_STOP_CKINTBUF216 6
+#define STB0899_WIDTH_STOP_CKINTBUF216 1
+#define STB0899_STOP_CHK8PSK (0x01 << 5)
+#define STB0899_OFFST_STOP_CHK8PSK 5
+#define STB0899_WIDTH_STOP_CHK8PSK 1
+#define STB0899_STOP_CKFEC108 (0x01 << 4)
+#define STB0899_OFFST_STOP_CKFEC108 4
+#define STB0899_WIDTH_STOP_CKFEC108 1
+#define STB0899_STOP_CKFEC216 (0x01 << 3)
+#define STB0899_OFFST_STOP_CKFEC216 3
+#define STB0899_WIDTH_STOP_CKFEC216 1
+#define STB0899_STOP_CKCORE216 (0x01 << 2)
+#define STB0899_OFFST_STOP_CKCORE216 2
+#define STB0899_WIDTH_STOP_CKCORE216 1
+#define STB0899_STOP_CKADCI108 (0x01 << 1)
+#define STB0899_OFFST_STOP_CKADCI108 1
+#define STB0899_WIDTH_STOP_CKADCI108 1
+#define STB0899_STOP_INVCKADCI108 (0x01 << 0)
+#define STB0899_OFFST_STOP_INVCKADCI108 0
+#define STB0899_WIDTH_STOP_INVCKADCI108 1
+
+#define STB0899_STOPCLK2 0xf1c3
+#define STB0899_STOP_CKS2DMD108 (0x01 << 2)
+#define STB0899_OFFST_STOP_CKS2DMD108 2
+#define STB0899_WIDTH_STOP_CKS2DMD108 1
+#define STB0899_STOP_CKPKDLIN108 (0x01 << 1)
+#define STB0899_OFFST_STOP_CKPKDLIN108 1
+#define STB0899_WIDTH_STOP_CKPKDLIN108 1
+#define STB0899_STOP_CKPKDLIN216 (0x01 << 0)
+#define STB0899_OFFST_STOP_CKPKDLIN216 0
+#define STB0899_WIDTH_STOP_CKPKDLIN216 1
+
+#define STB0899_TSTTNR1 0xf1e0
+#define STB0899_BYPASS_ADC (0x01 << 7)
+#define STB0899_OFFST_BYPASS_ADC 7
+#define STB0899_WIDTH_BYPASS_ADC 1
+#define STB0899_INVADCICKOUT (0x01 << 6)
+#define STB0899_OFFST_INVADCICKOUT 6
+#define STB0899_WIDTH_INVADCICKOUT 1
+#define STB0899_ADCTEST_VOLTAGE (0x03 << 4)
+#define STB0899_OFFST_ADCTEST_VOLTAGE 4
+#define STB0899_WIDTH_ADCTEST_VOLTAGE 1
+#define STB0899_ADC_RESET (0x01 << 3)
+#define STB0899_OFFST_ADC_RESET 3
+#define STB0899_WIDTH_ADC_RESET 1
+#define STB0899_TSTTNR1_2 (0x01 << 2)
+#define STB0899_OFFST_TSTTNR1_2 2
+#define STB0899_WIDTH_TSTTNR1_2 1
+#define STB0899_ADCPON (0x01 << 1)
+#define STB0899_OFFST_ADCPON 1
+#define STB0899_WIDTH_ADCPON 1
+#define STB0899_ADCIN_MODE (0x01 << 0)
+#define STB0899_OFFST_ADCIN_MODE 0
+#define STB0899_WIDTH_ADCIN_MODE 1
+
+#define STB0899_TSTTNR2 0xf1e1
+#define STB0899_TSTTNR2_7 (0x01 << 7)
+#define STB0899_OFFST_TSTTNR2_7 7
+#define STB0899_WIDTH_TSTTNR2_7 1
+#define STB0899_NOT_DISRX_WIRED (0x01 << 6)
+#define STB0899_OFFST_NOT_DISRX_WIRED 6
+#define STB0899_WIDTH_NOT_DISRX_WIRED 1
+#define STB0899_DISEQC_DCURRENT (0x01 << 5)
+#define STB0899_OFFST_DISEQC_DCURRENT 5
+#define STB0899_WIDTH_DISEQC_DCURRENT 1
+#define STB0899_DISEQC_ZCURRENT (0x01 << 4)
+#define STB0899_OFFST_DISEQC_ZCURRENT 4
+#define STB0899_WIDTH_DISEQC_ZCURRENT 1
+#define STB0899_DISEQC_SINC_SOURCE (0x03 << 2)
+#define STB0899_OFFST_DISEQC_SINC_SOURCE 2
+#define STB0899_WIDTH_DISEQC_SINC_SOURCE 2
+#define STB0899_SELIQSRC (0x03 << 0)
+#define STB0899_OFFST_SELIQSRC 0
+#define STB0899_WIDTH_SELIQSRC 2
+
+#define STB0899_TSTTNR3 0xf1e2
+
+#define STB0899_I2CCFG 0xf129
+#define STB0899_I2CCFGRSVD (0x0f << 4)
+#define STB0899_OFFST_I2CCFGRSVD 4
+#define STB0899_WIDTH_I2CCFGRSVD 4
+#define STB0899_I2CFASTMODE (0x01 << 3)
+#define STB0899_OFFST_I2CFASTMODE 3
+#define STB0899_WIDTH_I2CFASTMODE 1
+#define STB0899_STATUSWR (0x01 << 2)
+#define STB0899_OFFST_STATUSWR 2
+#define STB0899_WIDTH_STATUSWR 1
+#define STB0899_I2CADDRINC (0x03 << 0)
+#define STB0899_OFFST_I2CADDRINC 0
+#define STB0899_WIDTH_I2CADDRINC 2
+
+#define STB0899_I2CRPT 0xf12a
+#define STB0899_I2CTON (0x01 << 7)
+#define STB0899_OFFST_I2CTON 7
+#define STB0899_WIDTH_I2CTON 1
+#define STB0899_ENARPTLEVEL (0x01 << 6)
+#define STB0899_OFFST_ENARPTLEVEL 6
+#define STB0899_WIDTH_ENARPTLEVEL 2
+#define STB0899_SCLTDELAY (0x01 << 3)
+#define STB0899_OFFST_SCLTDELAY 3
+#define STB0899_WIDTH_SCLTDELAY 1
+#define STB0899_STOPENA (0x01 << 2)
+#define STB0899_OFFST_STOPENA 2
+#define STB0899_WIDTH_STOPENA 1
+#define STB0899_STOPSDAT2SDA (0x01 << 1)
+#define STB0899_OFFST_STOPSDAT2SDA 1
+#define STB0899_WIDTH_STOPSDAT2SDA 1
+
+#define STB0899_IOPVALUE8 0xf136
+#define STB0899_IOPVALUE7 0xf137
+#define STB0899_IOPVALUE6 0xf138
+#define STB0899_IOPVALUE5 0xf139
+#define STB0899_IOPVALUE4 0xf13a
+#define STB0899_IOPVALUE3 0xf13b
+#define STB0899_IOPVALUE2 0xf13c
+#define STB0899_IOPVALUE1 0xf13d
+#define STB0899_IOPVALUE0 0xf13e
+
+#define STB0899_GPIO00CFG 0xf140
+
+#define STB0899_GPIO01CFG 0xf141
+#define STB0899_GPIO02CFG 0xf142
+#define STB0899_GPIO03CFG 0xf143
+#define STB0899_GPIO04CFG 0xf144
+#define STB0899_GPIO05CFG 0xf145
+#define STB0899_GPIO06CFG 0xf146
+#define STB0899_GPIO07CFG 0xf147
+#define STB0899_GPIO08CFG 0xf148
+#define STB0899_GPIO09CFG 0xf149
+#define STB0899_GPIO10CFG 0xf14a
+#define STB0899_GPIO11CFG 0xf14b
+#define STB0899_GPIO12CFG 0xf14c
+#define STB0899_GPIO13CFG 0xf14d
+#define STB0899_GPIO14CFG 0xf14e
+#define STB0899_GPIO15CFG 0xf14f
+#define STB0899_GPIO16CFG 0xf150
+#define STB0899_GPIO17CFG 0xf151
+#define STB0899_GPIO18CFG 0xf152
+#define STB0899_GPIO19CFG 0xf153
+#define STB0899_GPIO20CFG 0xf154
+
+#define STB0899_SDATCFG 0xf155
+#define STB0899_SCLTCFG 0xf156
+#define STB0899_AGCRFCFG 0xf157
+#define STB0899_GPIO22 0xf158 /* AGCBB2CFG */
+#define STB0899_GPIO21 0xf159 /* AGCBB1CFG */
+#define STB0899_DIRCLKCFG 0xf15a
+#define STB0899_CLKOUT27CFG 0xf15b
+#define STB0899_STDBYCFG 0xf15c
+#define STB0899_CS0CFG 0xf15d
+#define STB0899_CS1CFG 0xf15e
+#define STB0899_DISEQCOCFG 0xf15f
+
+#define STB0899_GPIO32CFG 0xf160
+#define STB0899_GPIO33CFG 0xf161
+#define STB0899_GPIO34CFG 0xf162
+#define STB0899_GPIO35CFG 0xf163
+#define STB0899_GPIO36CFG 0xf164
+#define STB0899_GPIO37CFG 0xf165
+#define STB0899_GPIO38CFG 0xf166
+#define STB0899_GPIO39CFG 0xf167
+
+#define STB0899_IRQSTATUS_3 0xf120
+#define STB0899_IRQSTATUS_2 0xf121
+#define STB0899_IRQSTATUS_1 0xf122
+#define STB0899_IRQSTATUS_0 0xf123
+
+#define STB0899_IRQMSK_3 0xf124
+#define STB0899_IRQMSK_2 0xf125
+#define STB0899_IRQMSK_1 0xf126
+#define STB0899_IRQMSK_0 0xf127
+
+#define STB0899_IRQCFG 0xf128
+
+#define STB0899_GHOSTREG 0xf000
+
+#define STB0899_S2DEMOD 0xf3fc
+#define STB0899_S2FEC 0xfafc
+
+
+#endif
diff --git a/linux/drivers/media/dvb/frontends/stb6100.c b/linux/drivers/media/dvb/frontends/stb6100.c
new file mode 100644
index 000000000..29bc07b86
--- /dev/null
+++ b/linux/drivers/media/dvb/frontends/stb6100.c
@@ -0,0 +1,552 @@
+/*
+ STB6100 Silicon Tuner
+ Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+ Copyright (C) ST Microelectronics
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include "dvb_frontend.h"
+#include "stb6100.h"
+
+static unsigned int verbose;
+module_param(verbose, int, 0644);
+
+
+#define FE_ERROR 0
+#define FE_NOTICE 1
+#define FE_INFO 2
+#define FE_DEBUG 3
+
+#define dprintk(x, y, z, format, arg...) do { \
+ if (z) { \
+ if ((x > FE_ERROR) && (x > y)) \
+ printk(KERN_ERR "%s: " format "\n", __func__ , ##arg); \
+ else if ((x > FE_NOTICE) && (x > y)) \
+ printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg); \
+ else if ((x > FE_INFO) && (x > y)) \
+ printk(KERN_INFO "%s: " format "\n", __func__ , ##arg); \
+ else if ((x > FE_DEBUG) && (x > y)) \
+ printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg); \
+ } else { \
+ if (x > y) \
+ printk(format, ##arg); \
+ } \
+} while(0)
+
+struct stb6100_lkup {
+ u32 val_low;
+ u32 val_high;
+ u8 reg;
+};
+
+static int stb6100_release(struct dvb_frontend *fe);
+
+static const struct stb6100_lkup lkup[] = {
+ { 0, 950000, 0x0a },
+ { 950000, 1000000, 0x0a },
+ { 1000000, 1075000, 0x0c },
+ { 1075000, 1200000, 0x00 },
+ { 1200000, 1300000, 0x01 },
+ { 1300000, 1370000, 0x02 },
+ { 1370000, 1470000, 0x04 },
+ { 1470000, 1530000, 0x05 },
+ { 1530000, 1650000, 0x06 },
+ { 1650000, 1800000, 0x08 },
+ { 1800000, 1950000, 0x0a },
+ { 1950000, 2150000, 0x0c },
+ { 2150000, 9999999, 0x0c },
+ { 0, 0, 0x00 }
+};
+
+/* Register names for easy debugging. */
+static const char *stb6100_regnames[] = {
+ [STB6100_LD] = "LD",
+ [STB6100_VCO] = "VCO",
+ [STB6100_NI] = "NI",
+ [STB6100_NF_LSB] = "NF",
+ [STB6100_K] = "K",
+ [STB6100_G] = "G",
+ [STB6100_F] = "F",
+ [STB6100_DLB] = "DLB",
+ [STB6100_TEST1] = "TEST1",
+ [STB6100_FCCK] = "FCCK",
+ [STB6100_LPEN] = "LPEN",
+ [STB6100_TEST3] = "TEST3",
+};
+
+/* Template for normalisation, i.e. setting unused or undocumented
+ * bits as required according to the documentation.
+ */
+struct stb6100_regmask {
+ u8 mask;
+ u8 set;
+};
+
+static const struct stb6100_regmask stb6100_template[] = {
+ [STB6100_LD] = { 0xff, 0x00 },
+ [STB6100_VCO] = { 0xff, 0x00 },
+ [STB6100_NI] = { 0xff, 0x00 },
+ [STB6100_NF_LSB] = { 0xff, 0x00 },
+ [STB6100_K] = { 0xc7, 0x38 },
+ [STB6100_G] = { 0xef, 0x10 },
+ [STB6100_F] = { 0x1f, 0xc0 },
+ [STB6100_DLB] = { 0x38, 0xc4 },
+ [STB6100_TEST1] = { 0x00, 0x8f },
+ [STB6100_FCCK] = { 0x40, 0x0d },
+ [STB6100_LPEN] = { 0xf0, 0x0b },
+ [STB6100_TEST3] = { 0x00, 0xde },
+};
+
+static void stb6100_normalise_regs(u8 regs[])
+{
+ int i;
+
+ for (i = 0; i < STB6100_NUMREGS; i++)
+ regs[i] = (regs[i] & stb6100_template[i].mask) | stb6100_template[i].set;
+}
+
+static int stb6100_read_regs(struct stb6100_state *state, u8 regs[])
+{
+ int rc;
+ struct i2c_msg msg = {
+ .addr = state->config->tuner_address,
+ .flags = I2C_M_RD,
+ .buf = regs,
+ .len = STB6100_NUMREGS
+ };
+
+ rc = i2c_transfer(state->i2c, &msg, 1);
+ if (unlikely(rc != 1)) {
+ dprintk(verbose, FE_ERROR, 1, "Read (0x%x) err, rc=[%d]",
+ state->config->tuner_address, rc);
+
+ return -EREMOTEIO;
+ }
+ if (unlikely(verbose > FE_DEBUG)) {
+ int i;
+
+ dprintk(verbose, FE_DEBUG, 1, " Read from 0x%02x", state->config->tuner_address);
+ for (i = 0; i < STB6100_NUMREGS; i++)
+ dprintk(verbose, FE_DEBUG, 1, " %s: 0x%02x", stb6100_regnames[i], regs[i]);
+ }
+ return 0;
+}
+
+static int stb6100_read_reg(struct stb6100_state *state, u8 reg)
+{
+ u8 regs[STB6100_NUMREGS];
+ int rc;
+
+ if (unlikely(reg >= STB6100_NUMREGS)) {
+ dprintk(verbose, FE_ERROR, 1, "Invalid register offset 0x%x", reg);
+ return -EINVAL;
+ }
+ if ((rc = stb6100_read_regs(state, regs)) < 0)
+ return rc;
+ return (unsigned int)regs[reg];
+}
+
+static int stb6100_write_reg_range(struct stb6100_state *state, u8 buf[], int start, int len)
+{
+ int rc;
+ u8 cmdbuf[len + 1];
+ struct i2c_msg msg = {
+ .addr = state->config->tuner_address,
+ .flags = 0,
+ .buf = cmdbuf,
+ .len = len + 1
+ };
+
+ if (unlikely(start < 1 || start + len > STB6100_NUMREGS)) {
+ dprintk(verbose, FE_ERROR, 1, "Invalid register range %d:%d",
+ start, len);
+ return -EINVAL;
+ }
+ memcpy(&cmdbuf[1], buf, len);
+ cmdbuf[0] = start;
+
+ if (unlikely(verbose > FE_DEBUG)) {
+ int i;
+
+ dprintk(verbose, FE_DEBUG, 1, " Write @ 0x%02x: [%d:%d]", state->config->tuner_address, start, len);
+ for (i = 0; i < len; i++)
+ dprintk(verbose, FE_DEBUG, 1, " %s: 0x%02x", stb6100_regnames[start + i], buf[i]);
+ }
+ rc = i2c_transfer(state->i2c, &msg, 1);
+ if (unlikely(rc != 1)) {
+ dprintk(verbose, FE_ERROR, 1, "(0x%x) write err [%d:%d], rc=[%d]",
+ (unsigned int)state->config->tuner_address, start, len, rc);
+ return -EREMOTEIO;
+ }
+ return 0;
+}
+
+static int stb6100_write_reg(struct stb6100_state *state, u8 reg, u8 data)
+{
+ if (unlikely(reg >= STB6100_NUMREGS)) {
+ dprintk(verbose, FE_ERROR, 1, "Invalid register offset 0x%x", reg);
+ return -EREMOTEIO;
+ }
+ data = (data & stb6100_template[reg].mask) | stb6100_template[reg].set;
+ return stb6100_write_reg_range(state, &data, reg, 1);
+}
+
+static int stb6100_write_regs(struct stb6100_state *state, u8 regs[])
+{
+ stb6100_normalise_regs(regs);
+ return stb6100_write_reg_range(state, &regs[1], 1, STB6100_NUMREGS - 1);
+}
+
+static int stb6100_get_status(struct dvb_frontend *fe, u32 *status)
+{
+ int rc;
+ struct stb6100_state *state = fe->tuner_priv;
+
+ if ((rc = stb6100_read_reg(state, STB6100_LD)) < 0)
+ return rc;
+
+ return (rc & STB6100_LD_LOCK) ? TUNER_STATUS_LOCKED : 0;
+}
+
+static int stb6100_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+ int rc;
+ u8 f;
+ struct stb6100_state *state = fe->tuner_priv;
+
+ if ((rc = stb6100_read_reg(state, STB6100_F)) < 0)
+ return rc;
+ f = rc & STB6100_F_F;
+
+ state->status.bandwidth = (f + 5) * 2000; /* x2 for ZIF */
+
+ *bandwidth = state->bandwidth = state->status.bandwidth * 1000;
+ dprintk(verbose, FE_DEBUG, 1, "bandwidth = %u Hz", state->bandwidth);
+ return 0;
+}
+
+static int stb6100_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth)
+{
+ u32 tmp;
+ int rc;
+ struct stb6100_state *state = fe->tuner_priv;
+
+ dprintk(verbose, FE_DEBUG, 1, "set bandwidth to %u Hz", bandwidth);
+
+ bandwidth /= 2; /* ZIF */
+
+ if (bandwidth >= 36000000) /* F[4:0] BW/2 max =31+5=36 mhz for F=31 */
+ tmp = 31;
+ else if (bandwidth <= 5000000) /* bw/2 min = 5Mhz for F=0 */
+ tmp = 0;
+ else /* if 5 < bw/2 < 36 */
+ tmp = (bandwidth + 500000) / 1000000 - 5;
+
+ /* Turn on LPF bandwidth setting clock control,
+ * set bandwidth, wait 10ms, turn off.
+ */
+ if ((rc = stb6100_write_reg(state, STB6100_FCCK, 0x0d | STB6100_FCCK_FCCK)) < 0)
+ return rc;
+ if ((rc = stb6100_write_reg(state, STB6100_F, 0xc0 | tmp)) < 0)
+ return rc;
+ msleep(1);
+ if ((rc = stb6100_write_reg(state, STB6100_FCCK, 0x0d)) < 0)
+ return rc;
+
+ return 0;
+}
+
+static int stb6100_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+ int rc;
+ u32 nint, nfrac, fvco;
+ int psd2, odiv;
+ struct stb6100_state *state = fe->tuner_priv;
+ u8 regs[STB6100_NUMREGS];
+
+ if ((rc = stb6100_read_regs(state, regs)) < 0)
+ return rc;
+
+ odiv = (regs[STB6100_VCO] & STB6100_VCO_ODIV) >> STB6100_VCO_ODIV_SHIFT;
+ psd2 = (regs[STB6100_K] & STB6100_K_PSD2) >> STB6100_K_PSD2_SHIFT;
+ nint = regs[STB6100_NI];
+ nfrac = ((regs[STB6100_K] & STB6100_K_NF_MSB) << 8) | regs[STB6100_NF_LSB];
+ fvco = (nfrac * state->reference >> (9 - psd2)) + (nint * state->reference << psd2);
+ *frequency = state->frequency = fvco >> (odiv + 1);
+
+ dprintk(verbose, FE_DEBUG, 1,
+ "frequency = %u kHz, odiv = %u, psd2 = %u, fxtal = %u kHz, fvco = %u kHz, N(I) = %u, N(F) = %u",
+ state->frequency, odiv, psd2, state->reference, fvco, nint, nfrac);
+ return 0;
+}
+
+#if 0
+static int stb6100_set_rfgain(struct dvb_frontend *fe, u32 rfgain)
+{
+
+ return 0;
+}
+#endif
+
+static int stb6100_set_frequency(struct dvb_frontend *fe, u32 frequency)
+{
+ int rc;
+ const struct stb6100_lkup *ptr;
+ struct stb6100_state *state = fe->tuner_priv;
+ struct dvb_frontend_parameters p;
+
+ u32 srate = 0, fvco, nint, nfrac;
+ u8 regs[STB6100_NUMREGS];
+ u8 g, psd2, odiv;
+
+ if ((rc = stb6100_read_regs(state, regs)) < 0)
+ return rc;
+
+ if (fe->ops.get_frontend) {
+ dprintk(verbose, FE_DEBUG, 1, "Get frontend parameters");
+ fe->ops.get_frontend(fe, &p);
+ }
+ srate = p.u.qpsk.symbol_rate;
+
+ regs[STB6100_DLB] = 0xdc;
+ /* Disable LPEN */
+ regs[STB6100_LPEN] &= ~STB6100_LPEN_LPEN; /* PLL Loop disabled */
+
+ if ((rc = stb6100_write_regs(state, regs)) < 0)
+ return rc;
+
+ /* Baseband gain. */
+ if (srate >= 15000000)
+ g = 9; // +4 dB
+ else if (srate >= 5000000)
+ g = 11; // +8 dB
+ else
+ g = 14; // +14 dB
+
+ regs[STB6100_G] = (regs[STB6100_G] & ~STB6100_G_G) | g;
+ regs[STB6100_G] &= ~STB6100_G_GCT; /* mask GCT */
+ regs[STB6100_G] |= (1 << 5); /* 2Vp-p Mode */
+
+ /* VCO divide ratio (LO divide ratio, VCO prescaler enable). */
+ if (frequency <= 1075000)
+ odiv = 1;
+ else
+ odiv = 0;
+ regs[STB6100_VCO] = (regs[STB6100_VCO] & ~STB6100_VCO_ODIV) | (odiv << STB6100_VCO_ODIV_SHIFT);
+
+ if ((frequency > 1075000) && (frequency <= 1325000))
+ psd2 = 0;
+ else
+ psd2 = 1;
+ regs[STB6100_K] = (regs[STB6100_K] & ~STB6100_K_PSD2) | (psd2 << STB6100_K_PSD2_SHIFT);
+
+ /* OSM */
+ for (ptr = lkup;
+ (ptr->val_high != 0) && !CHKRANGE(frequency, ptr->val_low, ptr->val_high);
+ ptr++);
+ if (ptr->val_high == 0) {
+ printk(KERN_ERR "%s: frequency out of range: %u kHz\n", __func__, frequency);
+ return -EINVAL;
+ }
+ regs[STB6100_VCO] = (regs[STB6100_VCO] & ~STB6100_VCO_OSM) | ptr->reg;
+
+ /* F(VCO) = F(LO) * (ODIV == 0 ? 2 : 4) */
+ fvco = frequency << (1 + odiv);
+ /* N(I) = floor(f(VCO) / (f(XTAL) * (PSD2 ? 2 : 1))) */
+ nint = fvco / (state->reference << psd2);
+ /* N(F) = round(f(VCO) / f(XTAL) * (PSD2 ? 2 : 1) - N(I)) * 2 ^ 9 */
+ nfrac = (((fvco - (nint * state->reference << psd2)) << (9 - psd2)) + state->reference / 2) / state->reference;
+ dprintk(verbose, FE_DEBUG, 1,
+ "frequency = %u, srate = %u, g = %u, odiv = %u, psd2 = %u, fxtal = %u, osm = %u, fvco = %u, N(I) = %u, N(F) = %u",
+ frequency, srate, (unsigned int)g, (unsigned int)odiv,
+ (unsigned int)psd2, state->reference,
+ ptr->reg, fvco, nint, nfrac);
+ regs[STB6100_NI] = nint;
+ regs[STB6100_NF_LSB] = nfrac;
+ regs[STB6100_K] = (regs[STB6100_K] & ~STB6100_K_NF_MSB) | ((nfrac >> 8) & STB6100_K_NF_MSB);
+ regs[STB6100_VCO] |= STB6100_VCO_OSCH; /* VCO search enabled */
+ regs[STB6100_VCO] |= STB6100_VCO_OCK; /* VCO search clock off */
+ regs[STB6100_FCCK] |= STB6100_FCCK_FCCK; /* LPF BW setting clock enabled */
+ regs[STB6100_LPEN] &= ~STB6100_LPEN_LPEN; /* PLL loop disabled */
+ /* Power up. */
+ regs[STB6100_LPEN] |= STB6100_LPEN_SYNP | STB6100_LPEN_OSCP | STB6100_LPEN_BEN;
+
+ msleep(2);
+ if ((rc = stb6100_write_regs(state, regs)) < 0)
+ return rc;
+
+ msleep(2);
+ regs[STB6100_LPEN] |= STB6100_LPEN_LPEN; /* PLL loop enabled */
+ if ((rc = stb6100_write_reg(state, STB6100_LPEN, regs[STB6100_LPEN])) < 0)
+ return rc;
+
+ regs[STB6100_VCO] &= ~STB6100_VCO_OCK; /* VCO fast search */
+ if ((rc = stb6100_write_reg(state, STB6100_VCO, regs[STB6100_VCO])) < 0)
+ return rc;
+
+ msleep(10); /* wait for LO to lock */
+ regs[STB6100_VCO] &= ~STB6100_VCO_OSCH; /* vco search disabled */
+ regs[STB6100_VCO] |= STB6100_VCO_OCK; /* search clock off */
+ if ((rc = stb6100_write_reg(state, STB6100_VCO, regs[STB6100_VCO])) < 0)
+ return rc;
+ regs[STB6100_FCCK] &= ~STB6100_FCCK_FCCK; /* LPF BW clock disabled */
+ stb6100_normalise_regs(regs);
+ if ((rc = stb6100_write_reg_range(state, &regs[1], 1, STB6100_NUMREGS - 3)) < 0)
+ return rc;
+
+ msleep(100);
+
+ return 0;
+}
+
+static int stb6100_sleep(struct dvb_frontend *fe)
+{
+ /* TODO: power down */
+ return 0;
+}
+
+static int stb6100_init(struct dvb_frontend *fe)
+{
+ struct stb6100_state *state = fe->tuner_priv;
+ struct tuner_state *status = &state->status;
+
+ status->tunerstep = 125000;
+ status->ifreq = 0;
+ status->refclock = 27000000; /* Hz */
+ status->iqsense = 1;
+ status->bandwidth = 36000; /* kHz */
+ state->bandwidth = status->bandwidth * 1000; /* MHz */
+ state->reference = status->refclock / 1000; /* kHz */
+
+ /* Set default bandwidth. */
+ return stb6100_set_bandwidth(fe, status->bandwidth);
+}
+
+static int stb6100_get_state(struct dvb_frontend *fe,
+ enum tuner_param param,
+ struct tuner_state *state)
+{
+ switch (param) {
+ case DVBFE_TUNER_FREQUENCY:
+ stb6100_get_frequency(fe, &state->frequency);
+ break;
+ case DVBFE_TUNER_TUNERSTEP:
+ break;
+ case DVBFE_TUNER_IFFREQ:
+ break;
+ case DVBFE_TUNER_BANDWIDTH:
+ stb6100_get_bandwidth(fe, &state->bandwidth);
+ break;
+ case DVBFE_TUNER_REFCLOCK:
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int stb6100_set_state(struct dvb_frontend *fe,
+ enum tuner_param param,
+ struct tuner_state *state)
+{
+ struct stb6100_state *tstate = fe->tuner_priv;
+
+ switch (param) {
+ case DVBFE_TUNER_FREQUENCY:
+ stb6100_set_frequency(fe, state->frequency);
+ tstate->frequency = state->frequency;
+ break;
+ case DVBFE_TUNER_TUNERSTEP:
+ break;
+ case DVBFE_TUNER_IFFREQ:
+ break;
+ case DVBFE_TUNER_BANDWIDTH:
+ stb6100_set_bandwidth(fe, state->bandwidth);
+ tstate->bandwidth = state->bandwidth;
+ break;
+ case DVBFE_TUNER_REFCLOCK:
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static struct dvb_tuner_ops stb6100_ops = {
+ .info = {
+ .name = "STB6100 Silicon Tuner",
+ .frequency_min = 950000,
+ .frequency_max = 2150000,
+ .frequency_step = 0,
+ },
+
+ .init = stb6100_init,
+ .sleep = stb6100_sleep,
+ .get_status = stb6100_get_status,
+ .get_state = stb6100_get_state,
+ .set_state = stb6100_set_state,
+ .release = stb6100_release
+};
+
+struct dvb_frontend *stb6100_attach(struct dvb_frontend *fe,
+ struct stb6100_config *config,
+ struct i2c_adapter *i2c)
+{
+ struct stb6100_state *state = NULL;
+
+ state = kzalloc(sizeof (struct stb6100_state), GFP_KERNEL);
+ if (state == NULL)
+ goto error;
+
+ state->config = config;
+ state->i2c = i2c;
+ state->frontend = fe;
+ state->reference = config->refclock / 1000; /* kHz */
+ fe->tuner_priv = state;
+ fe->ops.tuner_ops = stb6100_ops;
+
+ printk("%s: Attaching STB6100 \n", __func__);
+ return fe;
+
+error:
+ kfree(state);
+ return NULL;
+}
+
+static int stb6100_release(struct dvb_frontend *fe)
+{
+ struct stb6100_state *state = fe->tuner_priv;
+
+ fe->tuner_priv = NULL;
+ kfree(state);
+
+ return 0;
+}
+
+EXPORT_SYMBOL(stb6100_attach);
+MODULE_PARM_DESC(verbose, "Set Verbosity level");
+
+MODULE_AUTHOR("Manu Abraham");
+MODULE_DESCRIPTION("STB6100 Silicon tuner");
+MODULE_LICENSE("GPL");
diff --git a/linux/drivers/media/dvb/frontends/stb6100.h b/linux/drivers/media/dvb/frontends/stb6100.h
new file mode 100644
index 000000000..395d05659
--- /dev/null
+++ b/linux/drivers/media/dvb/frontends/stb6100.h
@@ -0,0 +1,115 @@
+/*
+ STB6100 Silicon Tuner
+ Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+ Copyright (C) ST Microelectronics
+
+ 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 __STB_6100_REG_H
+#define __STB_6100_REG_H
+
+#include <linux/dvb/frontend.h>
+#include "dvb_frontend.h"
+
+#define STB6100_LD 0x00
+#define STB6100_LD_LOCK (1 << 0)
+
+#define STB6100_VCO 0x01
+#define STB6100_VCO_OSCH (0x01 << 7)
+#define STB6100_VCO_OSCH_SHIFT 7
+#define STB6100_VCO_OCK (0x03 << 5)
+#define STB6100_VCO_OCK_SHIFT 5
+#define STB6100_VCO_ODIV (0x01 << 4)
+#define STB6100_VCO_ODIV_SHIFT 4
+#define STB6100_VCO_OSM (0x0f << 0)
+
+#define STB6100_NI 0x02
+#define STB6100_NF_LSB 0x03
+
+#define STB6100_K 0x04
+#define STB6100_K_PSD2 (0x01 << 2)
+#define STB6100_K_PSD2_SHIFT 2
+#define STB6100_K_NF_MSB (0x03 << 0)
+
+#define STB6100_G 0x05
+#define STB6100_G_G (0x0f << 0)
+#define STB6100_G_GCT (0x07 << 5)
+
+#define STB6100_F 0x06
+#define STB6100_F_F (0x1f << 0)
+
+#define STB6100_DLB 0x07
+
+#define STB6100_TEST1 0x08
+
+#define STB6100_FCCK 0x09
+#define STB6100_FCCK_FCCK (0x01 << 6)
+
+#define STB6100_LPEN 0x0a
+#define STB6100_LPEN_LPEN (0x01 << 4)
+#define STB6100_LPEN_SYNP (0x01 << 5)
+#define STB6100_LPEN_OSCP (0x01 << 6)
+#define STB6100_LPEN_BEN (0x01 << 7)
+
+#define STB6100_TEST3 0x0b
+
+#define STB6100_NUMREGS 0x0c
+
+
+#define INRANGE(val, x, y) (((x <= val) && (val <= y)) || \
+ ((y <= val) && (val <= x)) ? 1 : 0)
+
+#define CHKRANGE(val, x, y) (((val >= x) && (val < y)) ? 1 : 0)
+
+struct stb6100_config {
+ u8 tuner_address;
+ u32 refclock;
+};
+
+struct stb6100_state {
+ struct i2c_adapter *i2c;
+
+ const struct stb6100_config *config;
+ struct dvb_tuner_ops ops;
+ struct dvb_frontend *frontend;
+ struct tuner_state status;
+
+ u32 frequency;
+ u32 srate;
+ u32 bandwidth;
+ u32 reference;
+};
+
+#if defined(CONFIG_DVB_STB6100) || (defined(CONFIG_DVB_STB6100_MODULE) && defined(MODULE))
+
+extern struct dvb_frontend *stb6100_attach(struct dvb_frontend *fe,
+ struct stb6100_config *config,
+ struct i2c_adapter *i2c);
+
+#else
+
+static inline struct dvb_frontend *stb6100_attach(struct dvb_frontend *fe,
+ struct stb6100_config *config,
+ struct i2c_adapter *i2c)
+{
+ printk(KERN_WARNING "%s: Driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+
+#endif //CONFIG_DVB_STB6100
+
+#endif
diff --git a/linux/drivers/media/dvb/frontends/stb6100_cfg.h b/linux/drivers/media/dvb/frontends/stb6100_cfg.h
new file mode 100644
index 000000000..d3133405d
--- /dev/null
+++ b/linux/drivers/media/dvb/frontends/stb6100_cfg.h
@@ -0,0 +1,108 @@
+/*
+ STB6100 Silicon Tuner
+ Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+ Copyright (C) ST Microelectronics
+
+ 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.
+*/
+
+static int stb6100_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+ struct dvb_frontend_ops *frontend_ops = NULL;
+ struct dvb_tuner_ops *tuner_ops = NULL;
+ struct tuner_state t_state;
+ int err = 0;
+
+ if (&fe->ops)
+ frontend_ops = &fe->ops;
+ if (&frontend_ops->tuner_ops)
+ tuner_ops = &frontend_ops->tuner_ops;
+ if (tuner_ops->get_state) {
+ if ((err = tuner_ops->get_state(fe, DVBFE_TUNER_FREQUENCY, &t_state)) < 0) {
+ printk("%s: Invalid parameter\n", __func__);
+ return err;
+ }
+ *frequency = t_state.frequency;
+ printk("%s: Frequency=%d\n", __func__, t_state.frequency);
+ }
+ return 0;
+}
+
+static int stb6100_set_frequency(struct dvb_frontend *fe, u32 frequency)
+{
+ struct dvb_frontend_ops *frontend_ops = NULL;
+ struct dvb_tuner_ops *tuner_ops = NULL;
+ struct tuner_state t_state;
+ int err = 0;
+
+ t_state.frequency = frequency;
+ if (&fe->ops)
+ frontend_ops = &fe->ops;
+ if (&frontend_ops->tuner_ops)
+ tuner_ops = &frontend_ops->tuner_ops;
+ if (tuner_ops->set_state) {
+ if ((err = tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY, &t_state)) < 0) {
+ printk("%s: Invalid parameter\n", __func__);
+ return err;
+ }
+ }
+ printk("%s: Frequency=%d\n", __func__, t_state.frequency);
+ return 0;
+}
+
+static int stb6100_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+ struct dvb_frontend_ops *frontend_ops = &fe->ops;
+ struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
+ struct tuner_state t_state;
+ int err = 0;
+
+ if (&fe->ops)
+ frontend_ops = &fe->ops;
+ if (&frontend_ops->tuner_ops)
+ tuner_ops = &frontend_ops->tuner_ops;
+ if (tuner_ops->get_state) {
+ if ((err = tuner_ops->get_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state)) < 0) {
+ printk("%s: Invalid parameter\n", __func__);
+ return err;
+ }
+ *bandwidth = t_state.bandwidth;
+ }
+ printk("%s: Bandwidth=%d\n", __func__, t_state.bandwidth);
+ return 0;
+}
+
+static int stb6100_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth)
+{
+ struct dvb_frontend_ops *frontend_ops = NULL;
+ struct dvb_tuner_ops *tuner_ops = NULL;
+ struct tuner_state t_state;
+ int err = 0;
+
+ t_state.bandwidth = bandwidth;
+ if (&fe->ops)
+ frontend_ops = &fe->ops;
+ if (&frontend_ops->tuner_ops)
+ tuner_ops = &frontend_ops->tuner_ops;
+ if (tuner_ops->set_state) {
+ if ((err = tuner_ops->set_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state)) < 0) {
+ printk("%s: Invalid parameter\n", __func__);
+ return err;
+ }
+ }
+ printk("%s: Bandwidth=%d\n", __func__, t_state.bandwidth);
+ return 0;
+}
diff --git a/linux/drivers/media/dvb/frontends/tda10048.c b/linux/drivers/media/dvb/frontends/tda10048.c
index 7a882faf5..cb5b1efd8 100644
--- a/linux/drivers/media/dvb/frontends/tda10048.c
+++ b/linux/drivers/media/dvb/frontends/tda10048.c
@@ -195,7 +195,7 @@ static struct init_tab {
static int tda10048_writereg(struct tda10048_state *state, u8 reg, u8 data)
{
int ret;
- u8 buf [] = { reg, data };
+ u8 buf[] = { reg, data };
struct i2c_msg msg = {
.addr = state->config->demod_address,
.flags = 0, .buf = buf, .len = 2 };
@@ -213,9 +213,9 @@ static int tda10048_writereg(struct tda10048_state *state, u8 reg, u8 data)
static u8 tda10048_readreg(struct tda10048_state *state, u8 reg)
{
int ret;
- u8 b0 [] = { reg };
- u8 b1 [] = { 0 };
- struct i2c_msg msg [] = {
+ u8 b0[] = { reg };
+ u8 b1[] = { 0 };
+ struct i2c_msg msg[] = {
{ .addr = state->config->demod_address,
.flags = 0, .buf = b0, .len = 1 },
{ .addr = state->config->demod_address,
@@ -393,43 +393,89 @@ static int tda10048_get_tps(struct tda10048_state *state,
val = tda10048_readreg(state, TDA10048_OUT_CONF2);
switch ((val & 0x60) >> 5) {
- case 0: p->constellation = QPSK; break;
- case 1: p->constellation = QAM_16; break;
- case 2: p->constellation = QAM_64; break;
+ case 0:
+ p->constellation = QPSK;
+ break;
+ case 1:
+ p->constellation = QAM_16;
+ break;
+ case 2:
+ p->constellation = QAM_64;
+ break;
}
switch ((val & 0x18) >> 3) {
- case 0: p->hierarchy_information = HIERARCHY_NONE; break;
- case 1: p->hierarchy_information = HIERARCHY_1; break;
- case 2: p->hierarchy_information = HIERARCHY_2; break;
- case 3: p->hierarchy_information = HIERARCHY_4; break;
+ case 0:
+ p->hierarchy_information = HIERARCHY_NONE;
+ break;
+ case 1:
+ p->hierarchy_information = HIERARCHY_1;
+ break;
+ case 2:
+ p->hierarchy_information = HIERARCHY_2;
+ break;
+ case 3:
+ p->hierarchy_information = HIERARCHY_4;
+ break;
}
switch (val & 0x07) {
- case 0: p->code_rate_HP = FEC_1_2; break;
- case 1: p->code_rate_HP = FEC_2_3; break;
- case 2: p->code_rate_HP = FEC_3_4; break;
- case 3: p->code_rate_HP = FEC_5_6; break;
- case 4: p->code_rate_HP = FEC_7_8; break;
+ case 0:
+ p->code_rate_HP = FEC_1_2;
+ break;
+ case 1:
+ p->code_rate_HP = FEC_2_3;
+ break;
+ case 2:
+ p->code_rate_HP = FEC_3_4;
+ break;
+ case 3:
+ p->code_rate_HP = FEC_5_6;
+ break;
+ case 4:
+ p->code_rate_HP = FEC_7_8;
+ break;
}
val = tda10048_readreg(state, TDA10048_OUT_CONF3);
switch (val & 0x07) {
- case 0: p->code_rate_LP = FEC_1_2; break;
- case 1: p->code_rate_LP = FEC_2_3; break;
- case 2: p->code_rate_LP = FEC_3_4; break;
- case 3: p->code_rate_LP = FEC_5_6; break;
- case 4: p->code_rate_LP = FEC_7_8; break;
+ case 0:
+ p->code_rate_LP = FEC_1_2;
+ break;
+ case 1:
+ p->code_rate_LP = FEC_2_3;
+ break;
+ case 2:
+ p->code_rate_LP = FEC_3_4;
+ break;
+ case 3:
+ p->code_rate_LP = FEC_5_6;
+ break;
+ case 4:
+ p->code_rate_LP = FEC_7_8;
+ break;
}
val = tda10048_readreg(state, TDA10048_OUT_CONF1);
switch ((val & 0x0c) >> 2) {
- case 0: p->guard_interval = GUARD_INTERVAL_1_32; break;
- case 1: p->guard_interval = GUARD_INTERVAL_1_16; break;
- case 2: p->guard_interval = GUARD_INTERVAL_1_8; break;
- case 3: p->guard_interval = GUARD_INTERVAL_1_4; break;
+ case 0:
+ p->guard_interval = GUARD_INTERVAL_1_32;
+ break;
+ case 1:
+ p->guard_interval = GUARD_INTERVAL_1_16;
+ break;
+ case 2:
+ p->guard_interval = GUARD_INTERVAL_1_8;
+ break;
+ case 3:
+ p->guard_interval = GUARD_INTERVAL_1_4;
+ break;
}
switch (val & 0x02) {
- case 0: p->transmission_mode = TRANSMISSION_MODE_2K; break;
- case 1: p->transmission_mode = TRANSMISSION_MODE_8K; break;
+ case 0:
+ p->transmission_mode = TRANSMISSION_MODE_2K;
+ break;
+ case 1:
+ p->transmission_mode = TRANSMISSION_MODE_8K;
+ break;
}
return 0;
diff --git a/linux/drivers/media/dvb/frontends/tda8261.c b/linux/drivers/media/dvb/frontends/tda8261.c
new file mode 100644
index 000000000..b6d177799
--- /dev/null
+++ b/linux/drivers/media/dvb/frontends/tda8261.c
@@ -0,0 +1,230 @@
+/*
+ TDA8261 8PSK/QPSK tuner driver
+ Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "dvb_frontend.h"
+#include "tda8261.h"
+
+struct tda8261_state {
+ struct dvb_frontend *fe;
+ struct i2c_adapter *i2c;
+ const struct tda8261_config *config;
+
+ /* state cache */
+ u32 frequency;
+ u32 bandwidth;
+};
+
+static int tda8261_read(struct tda8261_state *state, u8 *buf)
+{
+ const struct tda8261_config *config = state->config;
+ int err = 0;
+ struct i2c_msg msg = { .addr = config->addr, .flags = I2C_M_RD,.buf = buf, .len = 2 };
+
+ if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1)
+ printk("%s: read error, err=%d\n", __func__, err);
+
+ return err;
+}
+
+static int tda8261_write(struct tda8261_state *state, u8 *buf)
+{
+ const struct tda8261_config *config = state->config;
+ int err = 0;
+ struct i2c_msg msg = { .addr = config->addr, .flags = 0, .buf = buf, .len = 4 };
+
+ if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1)
+ printk("%s: write error, err=%d\n", __func__, err);
+
+ return err;
+}
+
+static int tda8261_get_status(struct dvb_frontend *fe, u32 *status)
+{
+ struct tda8261_state *state = fe->tuner_priv;
+ u8 result = 0;
+ int err = 0;
+
+ *status = 0;
+
+ if ((err = tda8261_read(state, &result)) < 0) {
+ printk("%s: I/O Error\n", __func__);
+ return err;
+ }
+ if ((result >> 6) & 0x01) {
+ printk("%s: Tuner Phase Locked\n", __func__);
+ *status = 1;
+ }
+
+ return err;
+}
+
+static const u32 div_tab[] = { 2000, 1000, 500, 250, 125 }; /* kHz */
+static const u8 ref_div[] = { 0x00, 0x01, 0x02, 0x05, 0x07 };
+
+static int tda8261_get_state(struct dvb_frontend *fe,
+ enum tuner_param param,
+ struct tuner_state *tstate)
+{
+ struct tda8261_state *state = fe->tuner_priv;
+ int err = 0;
+
+ switch (param) {
+ case DVBFE_TUNER_FREQUENCY:
+ tstate->frequency = state->frequency;
+ break;
+ case DVBFE_TUNER_BANDWIDTH:
+ tstate->bandwidth = 40000000; /* FIXME! need to calculate Bandwidth */
+ break;
+ default:
+ printk("%s: Unknown parameter (param=%d)\n", __func__, param);
+ err = -EINVAL;
+ break;
+ }
+
+ return err;
+}
+
+static int tda8261_set_state(struct dvb_frontend *fe,
+ enum tuner_param param,
+ struct tuner_state *tstate)
+{
+ struct tda8261_state *state = fe->tuner_priv;
+ const struct tda8261_config *config = state->config;
+ u32 frequency, N, status = 0;
+ u8 buf[4];
+ int err = 0;
+
+ if (param & DVBFE_TUNER_FREQUENCY) {
+ /**
+ * N = Max VCO Frequency / Channel Spacing
+ * Max VCO Frequency = VCO frequency + (channel spacing - 1)
+ * (to account for half channel spacing on either side)
+ */
+ frequency = tstate->frequency;
+ if ((frequency < 950000) || (frequency > 2150000)) {
+ printk("%s: Frequency beyond limits, frequency=%d\n", __func__, frequency);
+ return -EINVAL;
+ }
+ N = (frequency + (div_tab[config->step_size] - 1)) / div_tab[config->step_size];
+ printk("%s: Step size=%d, Divider=%d, PG=0x%02x (%d)\n",
+ __func__, config->step_size, div_tab[config->step_size], N, N);
+
+ buf[0] = (N >> 8) & 0xff;
+ buf[1] = N & 0xff;
+ buf[2] = (0x01 << 7) | ((ref_div[config->step_size] & 0x07) << 1);
+
+ if (frequency < 1450000)
+ buf[3] = 0x00;
+ if (frequency < 2000000)
+ buf[3] = 0x40;
+ if (frequency < 2150000)
+ buf[3] = 0x80;
+
+ /* Set params */
+ if ((err = tda8261_write(state, buf)) < 0) {
+ printk("%s: I/O Error\n", __func__);
+ return err;
+ }
+ /* sleep for some time */
+ printk("%s: Waiting to Phase LOCK\n", __func__);
+ msleep(20);
+ /* check status */
+ if ((err = tda8261_get_status(fe, &status)) < 0) {
+ printk("%s: I/O Error\n", __func__);
+ return err;
+ }
+ if (status == 1) {
+ printk("%s: Tuner Phase locked: status=%d\n", __func__, status);
+ state->frequency = frequency; /* cache successful state */
+ } else {
+ printk("%s: No Phase lock: status=%d\n", __func__, status);
+ }
+ } else {
+ printk("%s: Unknown parameter (param=%d)\n", __func__, param);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int tda8261_release(struct dvb_frontend *fe)
+{
+ struct tda8261_state *state = fe->tuner_priv;
+
+ fe->tuner_priv = NULL;
+ kfree(state);
+ return 0;
+}
+
+static struct dvb_tuner_ops tda8261_ops = {
+
+ .info = {
+ .name = "TDA8261",
+// .tuner_name = NULL,
+ .frequency_min = 950000,
+ .frequency_max = 2150000,
+ .frequency_step = 0
+ },
+
+ .set_state = tda8261_set_state,
+ .get_state = tda8261_get_state,
+ .get_status = tda8261_get_status,
+ .release = tda8261_release
+};
+
+struct dvb_frontend *tda8261_attach(struct dvb_frontend *fe,
+ const struct tda8261_config *config,
+ struct i2c_adapter *i2c)
+{
+ struct tda8261_state *state = NULL;
+
+ if ((state = kzalloc(sizeof (struct tda8261_state), GFP_KERNEL)) == NULL)
+ goto exit;
+
+ state->config = config;
+ state->i2c = i2c;
+ state->fe = fe;
+ fe->tuner_priv = state;
+ fe->ops.tuner_ops = tda8261_ops;
+
+ fe->ops.tuner_ops.info.frequency_step = div_tab[config->step_size];
+// fe->ops.tuner_ops.tuner_name = &config->buf;
+
+// printk("%s: Attaching %s TDA8261 8PSK/QPSK tuner\n",
+// __func__, fe->ops.tuner_ops.tuner_name);
+ printk("%s: Attaching TDA8261 8PSK/QPSK tuner\n", __func__);
+
+ return fe;
+
+exit:
+ kfree(state);
+ return NULL;
+}
+
+EXPORT_SYMBOL(tda8261_attach);
+MODULE_PARM_DESC(verbose, "Set verbosity level");
+
+MODULE_AUTHOR("Manu Abraham");
+MODULE_DESCRIPTION("TDA8261 8PSK/QPSK Tuner");
+MODULE_LICENSE("GPL");
diff --git a/linux/drivers/media/dvb/frontends/tda8261.h b/linux/drivers/media/dvb/frontends/tda8261.h
new file mode 100644
index 000000000..006e45351
--- /dev/null
+++ b/linux/drivers/media/dvb/frontends/tda8261.h
@@ -0,0 +1,55 @@
+/*
+ TDA8261 8PSK/QPSK tuner driver
+ Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __TDA8261_H
+#define __TDA8261_H
+
+enum tda8261_step {
+ TDA8261_STEP_2000 = 0, /* 2000 kHz */
+ TDA8261_STEP_1000, /* 1000 kHz */
+ TDA8261_STEP_500, /* 500 kHz */
+ TDA8261_STEP_250, /* 250 kHz */
+ TDA8261_STEP_125 /* 125 kHz */
+};
+
+struct tda8261_config {
+// u8 buf[16];
+ u8 addr;
+ enum tda8261_step step_size;
+};
+
+#if defined(CONFIG_DVB_TDA8261) || (defined(CONFIG_DVB_TDA8261_MODULE) && defined(MODULE))
+
+extern struct dvb_frontend *tda8261_attach(struct dvb_frontend *fe,
+ const struct tda8261_config *config,
+ struct i2c_adapter *i2c);
+
+#else
+
+static inline struct dvb_frontend *tda8261_attach(struct dvb_frontend *fe,
+ const struct tda8261_config *config,
+ struct i2c_adapter *i2c)
+{
+ printk(KERN_WARNING "%s: Driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+
+#endif //CONFIG_DVB_TDA8261
+
+#endif// __TDA8261_H
diff --git a/linux/drivers/media/dvb/frontends/tda8261_cfg.h b/linux/drivers/media/dvb/frontends/tda8261_cfg.h
new file mode 100644
index 000000000..1af1ee49b
--- /dev/null
+++ b/linux/drivers/media/dvb/frontends/tda8261_cfg.h
@@ -0,0 +1,84 @@
+/*
+ TDA8261 8PSK/QPSK tuner driver
+ Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+static int tda8261_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+ struct dvb_frontend_ops *frontend_ops = NULL;
+ struct dvb_tuner_ops *tuner_ops = NULL;
+ struct tuner_state t_state;
+ int err = 0;
+
+ if (&fe->ops)
+ frontend_ops = &fe->ops;
+ if (&frontend_ops->tuner_ops)
+ tuner_ops = &frontend_ops->tuner_ops;
+ if (tuner_ops->get_state) {
+ if ((err = tuner_ops->get_state(fe, DVBFE_TUNER_FREQUENCY, &t_state)) < 0) {
+ printk("%s: Invalid parameter\n", __func__);
+ return err;
+ }
+ *frequency = t_state.frequency;
+ printk("%s: Frequency=%d\n", __func__, t_state.frequency);
+ }
+ return 0;
+}
+
+static int tda8261_set_frequency(struct dvb_frontend *fe, u32 frequency)
+{
+ struct dvb_frontend_ops *frontend_ops = NULL;
+ struct dvb_tuner_ops *tuner_ops = NULL;
+ struct tuner_state t_state;
+ int err = 0;
+
+ t_state.frequency = frequency;
+ if (&fe->ops)
+ frontend_ops = &fe->ops;
+ if (&frontend_ops->tuner_ops)
+ tuner_ops = &frontend_ops->tuner_ops;
+ if (tuner_ops->set_state) {
+ if ((err = tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY, &t_state)) < 0) {
+ printk("%s: Invalid parameter\n", __func__);
+ return err;
+ }
+ }
+ printk("%s: Frequency=%d\n", __func__, t_state.frequency);
+ return 0;
+}
+
+static int tda8261_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+ struct dvb_frontend_ops *frontend_ops = &fe->ops;
+ struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
+ struct tuner_state t_state;
+ int err = 0;
+
+ if (&fe->ops)
+ frontend_ops = &fe->ops;
+ if (&frontend_ops->tuner_ops)
+ tuner_ops = &frontend_ops->tuner_ops;
+ if (tuner_ops->get_state) {
+ if ((err = tuner_ops->get_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state)) < 0) {
+ printk("%s: Invalid parameter\n", __func__);
+ return err;
+ }
+ *bandwidth = t_state.bandwidth;
+ }
+ printk("%s: Bandwidth=%d\n", __func__, t_state.bandwidth);
+ return 0;
+}
diff --git a/linux/drivers/media/dvb/frontends/z0194a.h b/linux/drivers/media/dvb/frontends/z0194a.h
index d2876d2e1..07f3fc099 100644
--- a/linux/drivers/media/dvb/frontends/z0194a.h
+++ b/linux/drivers/media/dvb/frontends/z0194a.h
@@ -12,7 +12,7 @@
#ifndef Z0194A
#define Z0194A
-static int sharp_z0194a__set_symbol_rate(struct dvb_frontend *fe,
+static int sharp_z0194a_set_symbol_rate(struct dvb_frontend *fe,
u32 srate, u32 ratio)
{
u8 aclk = 0;
@@ -40,7 +40,7 @@ static int sharp_z0194a__set_symbol_rate(struct dvb_frontend *fe,
return 0;
}
-static u8 sharp_z0194a__inittab[] = {
+static u8 sharp_z0194a_inittab[] = {
0x01, 0x15,
0x02, 0x00,
0x03, 0x00,
@@ -82,16 +82,4 @@ static u8 sharp_z0194a__inittab[] = {
0xff, 0xff
};
-static struct stv0299_config sharp_z0194a_config = {
- .demod_address = 0x68,
- .inittab = sharp_z0194a__inittab,
- .mclk = 88000000UL,
- .invert = 1,
- .skip_reinit = 0,
- .lock_output = STV0299_LOCKOUTPUT_1,
- .volt13_op0_op1 = STV0299_VOLT13_OP1,
- .min_delay_ms = 100,
- .set_symbol_rate = sharp_z0194a__set_symbol_rate,
-};
-
#endif
diff --git a/linux/drivers/media/dvb/frontends/zl10353.c b/linux/drivers/media/dvb/frontends/zl10353.c
index 11160a3ee..2e449a457 100644
--- a/linux/drivers/media/dvb/frontends/zl10353.c
+++ b/linux/drivers/media/dvb/frontends/zl10353.c
@@ -225,15 +225,18 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
/* These are extrapolated from the 7 and 8MHz values */
zl10353_single_write(fe, MCLK_RATIO, 0x97);
zl10353_single_write(fe, 0x64, 0x34);
+ zl10353_single_write(fe, 0xcc, 0xdd);
break;
case BANDWIDTH_7_MHZ:
zl10353_single_write(fe, MCLK_RATIO, 0x86);
zl10353_single_write(fe, 0x64, 0x35);
+ zl10353_single_write(fe, 0xcc, 0x73);
break;
case BANDWIDTH_8_MHZ:
default:
zl10353_single_write(fe, MCLK_RATIO, 0x75);
zl10353_single_write(fe, 0x64, 0x36);
+ zl10353_single_write(fe, 0xcc, 0x73);
}
zl10353_calc_nominal_rate(fe, op->bandwidth, &nominal_rate);
diff --git a/linux/drivers/media/dvb/siano/sms-cards.c b/linux/drivers/media/dvb/siano/sms-cards.c
index 9da260fe3..6f9b77360 100644
--- a/linux/drivers/media/dvb/siano/sms-cards.c
+++ b/linux/drivers/media/dvb/siano/sms-cards.c
@@ -42,6 +42,10 @@ struct usb_device_id smsusb_id_table[] = {
.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
{ USB_DEVICE(0x2040, 0x5510),
.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+ { USB_DEVICE(0x2040, 0x5520),
+ .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+ { USB_DEVICE(0x2040, 0x5530),
+ .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
{ USB_DEVICE(0x2040, 0x5580),
.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
{ USB_DEVICE(0x2040, 0x5590),
diff --git a/linux/drivers/media/dvb/ttpci/Kconfig b/linux/drivers/media/dvb/ttpci/Kconfig
index 867027cea..9e2ece9e4 100644
--- a/linux/drivers/media/dvb/ttpci/Kconfig
+++ b/linux/drivers/media/dvb/ttpci/Kconfig
@@ -104,6 +104,8 @@ config DVB_BUDGET_CI
select DVB_STV0297 if !DVB_FE_CUSTOMISE
select DVB_STV0299 if !DVB_FE_CUSTOMISE
select DVB_TDA1004X if !DVB_FE_CUSTOMISE
+ select DVB_STB0899 if !DVB_FE_CUSTOMISE
+ select DVB_STB6100 if !DVB_FE_CUSTOMISE
select DVB_LNBP21 if !DVB_FE_CUSTOMISE
select DVB_TDA10023 if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_TDA827X if !DVB_FE_CUSTOMISE
@@ -131,6 +133,8 @@ config DVB_BUDGET_AV
select DVB_TDA1004X if !DVB_FE_CUSTOMISE
select DVB_TDA10021 if !DVB_FE_CUSTOMISE
select DVB_TDA10023 if !DVB_FE_CUSTOMISE
+ select DVB_STB0899 if !DVB_FE_CUSTOMISE
+ select DVB_TDA8261 if !DVB_FE_CUSTOMISE
select DVB_TUA6100 if !DVB_FE_CUSTOMISE
help
Support for simple SAA7146 based DVB cards
diff --git a/linux/drivers/media/dvb/ttpci/av7110.c b/linux/drivers/media/dvb/ttpci/av7110.c
index bb63e2121..b99057a68 100644
--- a/linux/drivers/media/dvb/ttpci/av7110.c
+++ b/linux/drivers/media/dvb/ttpci/av7110.c
@@ -36,7 +36,6 @@
#include <linux/fs.h>
#include <linux/timer.h>
#include <linux/poll.h>
-#include <linux/byteorder/swabb.h>
#include <linux/smp_lock.h>
#include <linux/kernel.h>
@@ -52,6 +51,10 @@
#include <linux/i2c.h>
#include <linux/kthread.h>
#include <asm/unaligned.h>
+#include <asm/byteorder.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28)
+#include <linux/byteorder/swabb.h>
+#endif
#include <asm/system.h>
diff --git a/linux/drivers/media/dvb/ttpci/budget-av.c b/linux/drivers/media/dvb/ttpci/budget-av.c
index 1032ea778..f996cef79 100644
--- a/linux/drivers/media/dvb/ttpci/budget-av.c
+++ b/linux/drivers/media/dvb/ttpci/budget-av.c
@@ -35,6 +35,11 @@
#include "budget.h"
#include "stv0299.h"
+#include "stb0899_drv.h"
+#include "stb0899_reg.h"
+#include "stb0899_cfg.h"
+#include "tda8261.h"
+#include "tda8261_cfg.h"
#include "tda1002x.h"
#include "tda1004x.h"
#include "tua6100.h"
@@ -882,6 +887,281 @@ static struct stv0299_config philips_sd1878_config = {
.set_symbol_rate = philips_sd1878_ci_set_symbol_rate,
};
+/* KNC1 DVB-S (STB0899) Inittab */
+static const struct stb0899_s1_reg knc1_stb0899_s1_init_1[] = {
+
+ { STB0899_DEV_ID , 0x81 },
+ { STB0899_DISCNTRL1 , 0x32 },
+ { STB0899_DISCNTRL2 , 0x80 },
+ { STB0899_DISRX_ST0 , 0x04 },
+ { STB0899_DISRX_ST1 , 0x00 },
+ { STB0899_DISPARITY , 0x00 },
+ { STB0899_DISFIFO , 0x00 },
+ { STB0899_DISSTATUS , 0x20 },
+ { STB0899_DISF22 , 0x8c },
+ { STB0899_DISF22RX , 0x9a },
+ { STB0899_SYSREG , 0x0b },
+ { STB0899_ACRPRESC , 0x11 },
+ { STB0899_ACRDIV1 , 0x0a },
+ { STB0899_ACRDIV2 , 0x05 },
+ { STB0899_DACR1 , 0x00 },
+ { STB0899_DACR2 , 0x00 },
+ { STB0899_OUTCFG , 0x00 },
+ { STB0899_MODECFG , 0x00 },
+ { STB0899_IRQSTATUS_3 , 0x30 },
+ { STB0899_IRQSTATUS_2 , 0x00 },
+ { STB0899_IRQSTATUS_1 , 0x00 },
+ { STB0899_IRQSTATUS_0 , 0x00 },
+ { STB0899_IRQMSK_3 , 0xf3 },
+ { STB0899_IRQMSK_2 , 0xfc },
+ { STB0899_IRQMSK_1 , 0xff },
+ { STB0899_IRQMSK_0 , 0xff },
+ { STB0899_IRQCFG , 0x00 },
+ { STB0899_I2CCFG , 0x88 },
+ { STB0899_I2CRPT , 0x58 }, /* Repeater=8, Stop=disabled */
+ { STB0899_IOPVALUE5 , 0x00 },
+ { STB0899_IOPVALUE4 , 0x20 },
+ { STB0899_IOPVALUE3 , 0xc9 },
+ { STB0899_IOPVALUE2 , 0x90 },
+ { STB0899_IOPVALUE1 , 0x40 },
+ { STB0899_IOPVALUE0 , 0x00 },
+ { STB0899_GPIO00CFG , 0x82 },
+ { STB0899_GPIO01CFG , 0x82 },
+ { STB0899_GPIO02CFG , 0x82 },
+ { STB0899_GPIO03CFG , 0x82 },
+ { STB0899_GPIO04CFG , 0x82 },
+ { STB0899_GPIO05CFG , 0x82 },
+ { STB0899_GPIO06CFG , 0x82 },
+ { STB0899_GPIO07CFG , 0x82 },
+ { STB0899_GPIO08CFG , 0x82 },
+ { STB0899_GPIO09CFG , 0x82 },
+ { STB0899_GPIO10CFG , 0x82 },
+ { STB0899_GPIO11CFG , 0x82 },
+ { STB0899_GPIO12CFG , 0x82 },
+ { STB0899_GPIO13CFG , 0x82 },
+ { STB0899_GPIO14CFG , 0x82 },
+ { STB0899_GPIO15CFG , 0x82 },
+ { STB0899_GPIO16CFG , 0x82 },
+ { STB0899_GPIO17CFG , 0x82 },
+ { STB0899_GPIO18CFG , 0x82 },
+ { STB0899_GPIO19CFG , 0x82 },
+ { STB0899_GPIO20CFG , 0x82 },
+ { STB0899_SDATCFG , 0xb8 },
+ { STB0899_SCLTCFG , 0xba },
+ { STB0899_AGCRFCFG , 0x08 }, /* 0x1c */
+ { STB0899_GPIO22 , 0x82 }, /* AGCBB2CFG */
+ { STB0899_GPIO21 , 0x91 }, /* AGCBB1CFG */
+ { STB0899_DIRCLKCFG , 0x82 },
+ { STB0899_CLKOUT27CFG , 0x7e },
+ { STB0899_STDBYCFG , 0x82 },
+ { STB0899_CS0CFG , 0x82 },
+ { STB0899_CS1CFG , 0x82 },
+ { STB0899_DISEQCOCFG , 0x20 },
+ { STB0899_GPIO32CFG , 0x82 },
+ { STB0899_GPIO33CFG , 0x82 },
+ { STB0899_GPIO34CFG , 0x82 },
+ { STB0899_GPIO35CFG , 0x82 },
+ { STB0899_GPIO36CFG , 0x82 },
+ { STB0899_GPIO37CFG , 0x82 },
+ { STB0899_GPIO38CFG , 0x82 },
+ { STB0899_GPIO39CFG , 0x82 },
+ { STB0899_NCOARSE , 0x15 }, /* 0x15 = 27 Mhz Clock, F/3 = 198MHz, F/6 = 99MHz */
+ { STB0899_SYNTCTRL , 0x02 }, /* 0x00 = CLK from CLKI, 0x02 = CLK from XTALI */
+ { STB0899_FILTCTRL , 0x00 },
+ { STB0899_SYSCTRL , 0x00 },
+ { STB0899_STOPCLK1 , 0x20 },
+ { STB0899_STOPCLK2 , 0x00 },
+ { STB0899_INTBUFSTATUS , 0x00 },
+ { STB0899_INTBUFCTRL , 0x0a },
+ { 0xffff , 0xff },
+};
+
+static const struct stb0899_s1_reg knc1_stb0899_s1_init_3[] = {
+ { STB0899_DEMOD , 0x00 },
+ { STB0899_RCOMPC , 0xc9 },
+ { STB0899_AGC1CN , 0x41 },
+ { STB0899_AGC1REF , 0x08 },
+ { STB0899_RTC , 0x7a },
+ { STB0899_TMGCFG , 0x4e },
+ { STB0899_AGC2REF , 0x33 },
+ { STB0899_TLSR , 0x84 },
+ { STB0899_CFD , 0xee },
+ { STB0899_ACLC , 0x87 },
+ { STB0899_BCLC , 0x94 },
+ { STB0899_EQON , 0x41 },
+ { STB0899_LDT , 0xdd },
+ { STB0899_LDT2 , 0xc9 },
+ { STB0899_EQUALREF , 0xb4 },
+ { STB0899_TMGRAMP , 0x10 },
+ { STB0899_TMGTHD , 0x30 },
+ { STB0899_IDCCOMP , 0xfb },
+ { STB0899_QDCCOMP , 0x03 },
+ { STB0899_POWERI , 0x3b },
+ { STB0899_POWERQ , 0x3d },
+ { STB0899_RCOMP , 0x81 },
+ { STB0899_AGCIQIN , 0x80 },
+ { STB0899_AGC2I1 , 0x04 },
+ { STB0899_AGC2I2 , 0xf5 },
+ { STB0899_TLIR , 0x25 },
+ { STB0899_RTF , 0x80 },
+ { STB0899_DSTATUS , 0x00 },
+ { STB0899_LDI , 0xca },
+ { STB0899_CFRM , 0xf1 },
+ { STB0899_CFRL , 0xf3 },
+ { STB0899_NIRM , 0x2a },
+ { STB0899_NIRL , 0x05 },
+ { STB0899_ISYMB , 0x17 },
+ { STB0899_QSYMB , 0xfa },
+ { STB0899_SFRH , 0x2f },
+ { STB0899_SFRM , 0x68 },
+ { STB0899_SFRL , 0x40 },
+ { STB0899_SFRUPH , 0x2f },
+ { STB0899_SFRUPM , 0x68 },
+ { STB0899_SFRUPL , 0x40 },
+ { STB0899_EQUAI1 , 0xfd },
+ { STB0899_EQUAQ1 , 0x04 },
+ { STB0899_EQUAI2 , 0x0f },
+ { STB0899_EQUAQ2 , 0xff },
+ { STB0899_EQUAI3 , 0xdf },
+ { STB0899_EQUAQ3 , 0xfa },
+ { STB0899_EQUAI4 , 0x37 },
+ { STB0899_EQUAQ4 , 0x0d },
+ { STB0899_EQUAI5 , 0xbd },
+ { STB0899_EQUAQ5 , 0xf7 },
+ { STB0899_DSTATUS2 , 0x00 },
+ { STB0899_VSTATUS , 0x00 },
+ { STB0899_VERROR , 0xff },
+ { STB0899_IQSWAP , 0x2a },
+ { STB0899_ECNT1M , 0x00 },
+ { STB0899_ECNT1L , 0x00 },
+ { STB0899_ECNT2M , 0x00 },
+ { STB0899_ECNT2L , 0x00 },
+ { STB0899_ECNT3M , 0x00 },
+ { STB0899_ECNT3L , 0x00 },
+ { STB0899_FECAUTO1 , 0x06 },
+ { STB0899_FECM , 0x01 },
+ { STB0899_VTH12 , 0xf0 },
+ { STB0899_VTH23 , 0xa0 },
+ { STB0899_VTH34 , 0x78 },
+ { STB0899_VTH56 , 0x4e },
+ { STB0899_VTH67 , 0x48 },
+ { STB0899_VTH78 , 0x38 },
+ { STB0899_PRVIT , 0xff },
+ { STB0899_VITSYNC , 0x19 },
+ { STB0899_RSULC , 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */
+ { STB0899_TSULC , 0x42 },
+ { STB0899_RSLLC , 0x40 },
+ { STB0899_TSLPL , 0x12 },
+ { STB0899_TSCFGH , 0x0c },
+ { STB0899_TSCFGM , 0x00 },
+ { STB0899_TSCFGL , 0x0c },
+ { STB0899_TSOUT , 0x0d }, /* 0x0d for CAM */
+ { STB0899_RSSYNCDEL , 0x00 },
+ { STB0899_TSINHDELH , 0x02 },
+ { STB0899_TSINHDELM , 0x00 },
+ { STB0899_TSINHDELL , 0x00 },
+ { STB0899_TSLLSTKM , 0x00 },
+ { STB0899_TSLLSTKL , 0x00 },
+ { STB0899_TSULSTKM , 0x00 },
+ { STB0899_TSULSTKL , 0xab },
+ { STB0899_PCKLENUL , 0x00 },
+ { STB0899_PCKLENLL , 0xcc },
+ { STB0899_RSPCKLEN , 0xcc },
+ { STB0899_TSSTATUS , 0x80 },
+ { STB0899_ERRCTRL1 , 0xb6 },
+ { STB0899_ERRCTRL2 , 0x96 },
+ { STB0899_ERRCTRL3 , 0x89 },
+ { STB0899_DMONMSK1 , 0x27 },
+ { STB0899_DMONMSK0 , 0x03 },
+ { STB0899_DEMAPVIT , 0x5c },
+ { STB0899_PLPARM , 0x1f },
+ { STB0899_PDELCTRL , 0x48 },
+ { STB0899_PDELCTRL2 , 0x00 },
+ { STB0899_BBHCTRL1 , 0x00 },
+ { STB0899_BBHCTRL2 , 0x00 },
+ { STB0899_HYSTTHRESH , 0x77 },
+ { STB0899_MATCSTM , 0x00 },
+ { STB0899_MATCSTL , 0x00 },
+ { STB0899_UPLCSTM , 0x00 },
+ { STB0899_UPLCSTL , 0x00 },
+ { STB0899_DFLCSTM , 0x00 },
+ { STB0899_DFLCSTL , 0x00 },
+ { STB0899_SYNCCST , 0x00 },
+ { STB0899_SYNCDCSTM , 0x00 },
+ { STB0899_SYNCDCSTL , 0x00 },
+ { STB0899_ISI_ENTRY , 0x00 },
+ { STB0899_ISI_BIT_EN , 0x00 },
+ { STB0899_MATSTRM , 0x00 },
+ { STB0899_MATSTRL , 0x00 },
+ { STB0899_UPLSTRM , 0x00 },
+ { STB0899_UPLSTRL , 0x00 },
+ { STB0899_DFLSTRM , 0x00 },
+ { STB0899_DFLSTRL , 0x00 },
+ { STB0899_SYNCSTR , 0x00 },
+ { STB0899_SYNCDSTRM , 0x00 },
+ { STB0899_SYNCDSTRL , 0x00 },
+ { STB0899_CFGPDELSTATUS1 , 0x10 },
+ { STB0899_CFGPDELSTATUS2 , 0x00 },
+ { STB0899_BBFERRORM , 0x00 },
+ { STB0899_BBFERRORL , 0x00 },
+ { STB0899_UPKTERRORM , 0x00 },
+ { STB0899_UPKTERRORL , 0x00 },
+ { 0xffff , 0xff },
+};
+
+/* STB0899 demodulator config for the KNC1 and clones */
+static struct stb0899_config knc1_dvbs2_config = {
+ .init_dev = knc1_stb0899_s1_init_1,
+ .init_s2_demod = stb0899_s2_init_2,
+ .init_s1_demod = knc1_stb0899_s1_init_3,
+ .init_s2_fec = stb0899_s2_init_4,
+ .init_tst = stb0899_s1_init_5,
+
+ .postproc = NULL,
+
+ .demod_address = 0x68,
+// .ts_output_mode = STB0899_OUT_PARALLEL, /* types = SERIAL/PARALLEL */
+ .block_sync_mode = STB0899_SYNC_FORCED, /* DSS, SYNC_FORCED/UNSYNCED */
+// .ts_pfbit_toggle = STB0899_MPEG_NORMAL, /* DirecTV, MPEG toggling seq */
+
+ .xtal_freq = 27000000,
+ .inversion = IQ_SWAP_OFF, /* 1 */
+
+ .lo_clk = 76500000,
+ .hi_clk = 90000000,
+
+ .esno_ave = STB0899_DVBS2_ESNO_AVE,
+ .esno_quant = STB0899_DVBS2_ESNO_QUANT,
+ .avframes_coarse = STB0899_DVBS2_AVFRAMES_COARSE,
+ .avframes_fine = STB0899_DVBS2_AVFRAMES_FINE,
+ .miss_threshold = STB0899_DVBS2_MISS_THRESHOLD,
+ .uwp_threshold_acq = STB0899_DVBS2_UWP_THRESHOLD_ACQ,
+ .uwp_threshold_track = STB0899_DVBS2_UWP_THRESHOLD_TRACK,
+ .uwp_threshold_sof = STB0899_DVBS2_UWP_THRESHOLD_SOF,
+ .sof_search_timeout = STB0899_DVBS2_SOF_SEARCH_TIMEOUT,
+
+ .btr_nco_bits = STB0899_DVBS2_BTR_NCO_BITS,
+ .btr_gain_shift_offset = STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET,
+ .crl_nco_bits = STB0899_DVBS2_CRL_NCO_BITS,
+ .ldpc_max_iter = STB0899_DVBS2_LDPC_MAX_ITER,
+
+ .tuner_get_frequency = tda8261_get_frequency,
+ .tuner_set_frequency = tda8261_set_frequency,
+ .tuner_set_bandwidth = NULL,
+ .tuner_get_bandwidth = tda8261_get_bandwidth,
+ .tuner_set_rfsiggain = NULL
+};
+
+/*
+ * SD1878/SHA tuner config
+ * 1F, Single I/P, Horizontal mount, High Sensitivity
+ */
+static const struct tda8261_config sd1878c_config = {
+// .name = "SD1878/SHA",
+ .addr = 0x60,
+ .step_size = TDA8261_STEP_1000 /* kHz */
+};
+
static u8 read_pwm(struct budget_av *budget_av)
{
u8 b = 0xff;
@@ -905,8 +1185,11 @@ static u8 read_pwm(struct budget_av *budget_av)
#define SUBID_DVBS_TV_STAR 0x0014
#define SUBID_DVBS_TV_STAR_PLUS_X4 0x0015
#define SUBID_DVBS_TV_STAR_CI 0x0016
+#define SUBID_DVBS2_KNC1 0x0018
+#define SUBID_DVBS2_KNC1_OEM 0x0019
#define SUBID_DVBS_EASYWATCH_1 0x001a
#define SUBID_DVBS_EASYWATCH_2 0x001b
+#define SUBID_DVBS2_EASYWATCH 0x001d
#define SUBID_DVBS_EASYWATCH 0x001e
#define SUBID_DVBC_EASYWATCH 0x002a
@@ -941,6 +1224,9 @@ static void frontend_init(struct budget_av *budget_av)
case SUBID_DVBT_KNC1_PLUS:
case SUBID_DVBC_EASYWATCH:
case SUBID_DVBC_KNC1_PLUS_MK3:
+ case SUBID_DVBS2_KNC1:
+ case SUBID_DVBS2_KNC1_OEM:
+ case SUBID_DVBS2_EASYWATCH:
saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTHI);
break;
}
@@ -993,7 +1279,14 @@ static void frontend_init(struct budget_av *budget_av)
fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;
}
break;
+ case SUBID_DVBS2_KNC1:
+ case SUBID_DVBS2_KNC1_OEM:
+ case SUBID_DVBS2_EASYWATCH:
+ budget_av->reinitialise_demod = 1;
+ if ((fe = dvb_attach(stb0899_attach, &knc1_dvbs2_config, &budget_av->budget.i2c_adap)))
+ dvb_attach(tda8261_attach, fe, &sd1878c_config, &budget_av->budget.i2c_adap);
+ break;
case SUBID_DVBS_CINERGY1200:
fe = dvb_attach(stv0299_attach, &cinergy_1200s_config,
&budget_av->budget.i2c_adap);
@@ -1260,6 +1553,8 @@ static struct saa7146_ext_vv vv_data = {
static struct saa7146_extension budget_extension;
MAKE_BUDGET_INFO(knc1s, "KNC1 DVB-S", BUDGET_KNC1S);
+MAKE_BUDGET_INFO(knc1s2,"KNC1 DVB-S2", BUDGET_KNC1S2);
+MAKE_BUDGET_INFO(sates2,"Satelco EasyWatch DVB-S2", BUDGET_KNC1S2);
MAKE_BUDGET_INFO(knc1c, "KNC1 DVB-C", BUDGET_KNC1C);
MAKE_BUDGET_INFO(knc1t, "KNC1 DVB-T", BUDGET_KNC1T);
MAKE_BUDGET_INFO(kncxs, "KNC TV STAR DVB-S", BUDGET_TVSTAR);
@@ -1290,6 +1585,9 @@ static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0014),
MAKE_EXTENSION_PCI(knc1spx4, 0x1894, 0x0015),
MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0016),
+ MAKE_EXTENSION_PCI(knc1s2, 0x1894, 0x0018),
+ MAKE_EXTENSION_PCI(knc1s2, 0x1894, 0x0019),
+ MAKE_EXTENSION_PCI(sates2, 0x1894, 0x001d),
MAKE_EXTENSION_PCI(satewpls, 0x1894, 0x001e),
MAKE_EXTENSION_PCI(satewpls1, 0x1894, 0x001a),
MAKE_EXTENSION_PCI(satewps, 0x1894, 0x001b),
diff --git a/linux/drivers/media/dvb/ttpci/budget-ci.c b/linux/drivers/media/dvb/ttpci/budget-ci.c
index 969877f58..89797e1bd 100644
--- a/linux/drivers/media/dvb/ttpci/budget-ci.c
+++ b/linux/drivers/media/dvb/ttpci/budget-ci.c
@@ -47,6 +47,11 @@
#include "stv0299.h"
#include "stv0297.h"
#include "tda1004x.h"
+#include "stb0899_drv.h"
+#include "stb0899_reg.h"
+#include "stb0899_cfg.h"
+#include "stb6100.h"
+#include "stb6100_cfg.h"
#include "lnbp21.h"
#include "bsbe1.h"
#include "bsru6.h"
@@ -1079,7 +1084,271 @@ static struct tda10023_config tda10023_config = {
.deltaf = 0xa511,
};
+/* TT S2-3200 DVB-S (STB0899) Inittab */
+static const struct stb0899_s1_reg tt3200_stb0899_s1_init_1[] = {
+
+ { STB0899_DEV_ID , 0x81 },
+ { STB0899_DISCNTRL1 , 0x32 },
+ { STB0899_DISCNTRL2 , 0x80 },
+ { STB0899_DISRX_ST0 , 0x04 },
+ { STB0899_DISRX_ST1 , 0x00 },
+ { STB0899_DISPARITY , 0x00 },
+ { STB0899_DISFIFO , 0x00 },
+ { STB0899_DISSTATUS , 0x20 },
+ { STB0899_DISF22 , 0x8c },
+ { STB0899_DISF22RX , 0x9a },
+ { STB0899_SYSREG , 0x0b },
+ { STB0899_ACRPRESC , 0x11 },
+ { STB0899_ACRDIV1 , 0x0a },
+ { STB0899_ACRDIV2 , 0x05 },
+ { STB0899_DACR1 , 0x00 },
+ { STB0899_DACR2 , 0x00 },
+ { STB0899_OUTCFG , 0x00 },
+ { STB0899_MODECFG , 0x00 },
+ { STB0899_IRQSTATUS_3 , 0x30 },
+ { STB0899_IRQSTATUS_2 , 0x00 },
+ { STB0899_IRQSTATUS_1 , 0x00 },
+ { STB0899_IRQSTATUS_0 , 0x00 },
+ { STB0899_IRQMSK_3 , 0xf3 },
+ { STB0899_IRQMSK_2 , 0xfc },
+ { STB0899_IRQMSK_1 , 0xff },
+ { STB0899_IRQMSK_0 , 0xff },
+ { STB0899_IRQCFG , 0x00 },
+ { STB0899_I2CCFG , 0x88 },
+ { STB0899_I2CRPT , 0x48 }, /* 12k Pullup, Repeater=16, Stop=disabled */
+ { STB0899_IOPVALUE5 , 0x00 },
+ { STB0899_IOPVALUE4 , 0x20 },
+ { STB0899_IOPVALUE3 , 0xc9 },
+ { STB0899_IOPVALUE2 , 0x90 },
+ { STB0899_IOPVALUE1 , 0x40 },
+ { STB0899_IOPVALUE0 , 0x00 },
+ { STB0899_GPIO00CFG , 0x82 },
+ { STB0899_GPIO01CFG , 0x82 },
+ { STB0899_GPIO02CFG , 0x82 },
+ { STB0899_GPIO03CFG , 0x82 },
+ { STB0899_GPIO04CFG , 0x82 },
+ { STB0899_GPIO05CFG , 0x82 },
+ { STB0899_GPIO06CFG , 0x82 },
+ { STB0899_GPIO07CFG , 0x82 },
+ { STB0899_GPIO08CFG , 0x82 },
+ { STB0899_GPIO09CFG , 0x82 },
+ { STB0899_GPIO10CFG , 0x82 },
+ { STB0899_GPIO11CFG , 0x82 },
+ { STB0899_GPIO12CFG , 0x82 },
+ { STB0899_GPIO13CFG , 0x82 },
+ { STB0899_GPIO14CFG , 0x82 },
+ { STB0899_GPIO15CFG , 0x82 },
+ { STB0899_GPIO16CFG , 0x82 },
+ { STB0899_GPIO17CFG , 0x82 },
+ { STB0899_GPIO18CFG , 0x82 },
+ { STB0899_GPIO19CFG , 0x82 },
+ { STB0899_GPIO20CFG , 0x82 },
+ { STB0899_SDATCFG , 0xb8 },
+ { STB0899_SCLTCFG , 0xba },
+ { STB0899_AGCRFCFG , 0x1c }, /* 0x11 */
+ { STB0899_GPIO22 , 0x82 }, /* AGCBB2CFG */
+ { STB0899_GPIO21 , 0x91 }, /* AGCBB1CFG */
+ { STB0899_DIRCLKCFG , 0x82 },
+ { STB0899_CLKOUT27CFG , 0x7e },
+ { STB0899_STDBYCFG , 0x82 },
+ { STB0899_CS0CFG , 0x82 },
+ { STB0899_CS1CFG , 0x82 },
+ { STB0899_DISEQCOCFG , 0x20 },
+ { STB0899_GPIO32CFG , 0x82 },
+ { STB0899_GPIO33CFG , 0x82 },
+ { STB0899_GPIO34CFG , 0x82 },
+ { STB0899_GPIO35CFG , 0x82 },
+ { STB0899_GPIO36CFG , 0x82 },
+ { STB0899_GPIO37CFG , 0x82 },
+ { STB0899_GPIO38CFG , 0x82 },
+ { STB0899_GPIO39CFG , 0x82 },
+ { STB0899_NCOARSE , 0x15 }, /* 0x15 = 27 Mhz Clock, F/3 = 198MHz, F/6 = 99MHz */
+ { STB0899_SYNTCTRL , 0x02 }, /* 0x00 = CLK from CLKI, 0x02 = CLK from XTALI */
+ { STB0899_FILTCTRL , 0x00 },
+ { STB0899_SYSCTRL , 0x00 },
+ { STB0899_STOPCLK1 , 0x20 },
+ { STB0899_STOPCLK2 , 0x00 },
+ { STB0899_INTBUFSTATUS , 0x00 },
+ { STB0899_INTBUFCTRL , 0x0a },
+ { 0xffff , 0xff },
+};
+
+static const struct stb0899_s1_reg tt3200_stb0899_s1_init_3[] = {
+ { STB0899_DEMOD , 0x00 },
+ { STB0899_RCOMPC , 0xc9 },
+ { STB0899_AGC1CN , 0x41 },
+ { STB0899_AGC1REF , 0x10 },
+ { STB0899_RTC , 0x7a },
+ { STB0899_TMGCFG , 0x4e },
+ { STB0899_AGC2REF , 0x34 },
+ { STB0899_TLSR , 0x84 },
+ { STB0899_CFD , 0xc7 },
+ { STB0899_ACLC , 0x87 },
+ { STB0899_BCLC , 0x94 },
+ { STB0899_EQON , 0x41 },
+ { STB0899_LDT , 0xdd },
+ { STB0899_LDT2 , 0xc9 },
+ { STB0899_EQUALREF , 0xb4 },
+ { STB0899_TMGRAMP , 0x10 },
+ { STB0899_TMGTHD , 0x30 },
+ { STB0899_IDCCOMP , 0xfb },
+ { STB0899_QDCCOMP , 0x03 },
+ { STB0899_POWERI , 0x3b },
+ { STB0899_POWERQ , 0x3d },
+ { STB0899_RCOMP , 0x81 },
+ { STB0899_AGCIQIN , 0x80 },
+ { STB0899_AGC2I1 , 0x04 },
+ { STB0899_AGC2I2 , 0xf5 },
+ { STB0899_TLIR , 0x25 },
+ { STB0899_RTF , 0x80 },
+ { STB0899_DSTATUS , 0x00 },
+ { STB0899_LDI , 0xca },
+ { STB0899_CFRM , 0xf1 },
+ { STB0899_CFRL , 0xf3 },
+ { STB0899_NIRM , 0x2a },
+ { STB0899_NIRL , 0x05 },
+ { STB0899_ISYMB , 0x17 },
+ { STB0899_QSYMB , 0xfa },
+ { STB0899_SFRH , 0x2f },
+ { STB0899_SFRM , 0x68 },
+ { STB0899_SFRL , 0x40 },
+ { STB0899_SFRUPH , 0x2f },
+ { STB0899_SFRUPM , 0x68 },
+ { STB0899_SFRUPL , 0x40 },
+ { STB0899_EQUAI1 , 0xfd },
+ { STB0899_EQUAQ1 , 0x04 },
+ { STB0899_EQUAI2 , 0x0f },
+ { STB0899_EQUAQ2 , 0xff },
+ { STB0899_EQUAI3 , 0xdf },
+ { STB0899_EQUAQ3 , 0xfa },
+ { STB0899_EQUAI4 , 0x37 },
+ { STB0899_EQUAQ4 , 0x0d },
+ { STB0899_EQUAI5 , 0xbd },
+ { STB0899_EQUAQ5 , 0xf7 },
+ { STB0899_DSTATUS2 , 0x00 },
+ { STB0899_VSTATUS , 0x00 },
+ { STB0899_VERROR , 0xff },
+ { STB0899_IQSWAP , 0x2a },
+ { STB0899_ECNT1M , 0x00 },
+ { STB0899_ECNT1L , 0x00 },
+ { STB0899_ECNT2M , 0x00 },
+ { STB0899_ECNT2L , 0x00 },
+ { STB0899_ECNT3M , 0x00 },
+ { STB0899_ECNT3L , 0x00 },
+ { STB0899_FECAUTO1 , 0x06 },
+ { STB0899_FECM , 0x01 },
+ { STB0899_VTH12 , 0xf0 },
+ { STB0899_VTH23 , 0xa0 },
+ { STB0899_VTH34 , 0x78 },
+ { STB0899_VTH56 , 0x4e },
+ { STB0899_VTH67 , 0x48 },
+ { STB0899_VTH78 , 0x38 },
+ { STB0899_PRVIT , 0xff },
+ { STB0899_VITSYNC , 0x19 },
+ { STB0899_RSULC , 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */
+ { STB0899_TSULC , 0x42 },
+ { STB0899_RSLLC , 0x40 },
+ { STB0899_TSLPL , 0x12 },
+ { STB0899_TSCFGH , 0x0c },
+ { STB0899_TSCFGM , 0x00 },
+ { STB0899_TSCFGL , 0x0c },
+ { STB0899_TSOUT , 0x0d }, /* 0x0d for CAM */
+ { STB0899_RSSYNCDEL , 0x00 },
+ { STB0899_TSINHDELH , 0x02 },
+ { STB0899_TSINHDELM , 0x00 },
+ { STB0899_TSINHDELL , 0x00 },
+ { STB0899_TSLLSTKM , 0x00 },
+ { STB0899_TSLLSTKL , 0x00 },
+ { STB0899_TSULSTKM , 0x00 },
+ { STB0899_TSULSTKL , 0xab },
+ { STB0899_PCKLENUL , 0x00 },
+ { STB0899_PCKLENLL , 0xcc },
+ { STB0899_RSPCKLEN , 0xcc },
+ { STB0899_TSSTATUS , 0x80 },
+ { STB0899_ERRCTRL1 , 0xb6 },
+ { STB0899_ERRCTRL2 , 0x96 },
+ { STB0899_ERRCTRL3 , 0x89 },
+ { STB0899_DMONMSK1 , 0x27 },
+ { STB0899_DMONMSK0 , 0x03 },
+ { STB0899_DEMAPVIT , 0x5c },
+ { STB0899_PLPARM , 0x1f },
+ { STB0899_PDELCTRL , 0x48 },
+ { STB0899_PDELCTRL2 , 0x00 },
+ { STB0899_BBHCTRL1 , 0x00 },
+ { STB0899_BBHCTRL2 , 0x00 },
+ { STB0899_HYSTTHRESH , 0x77 },
+ { STB0899_MATCSTM , 0x00 },
+ { STB0899_MATCSTL , 0x00 },
+ { STB0899_UPLCSTM , 0x00 },
+ { STB0899_UPLCSTL , 0x00 },
+ { STB0899_DFLCSTM , 0x00 },
+ { STB0899_DFLCSTL , 0x00 },
+ { STB0899_SYNCCST , 0x00 },
+ { STB0899_SYNCDCSTM , 0x00 },
+ { STB0899_SYNCDCSTL , 0x00 },
+ { STB0899_ISI_ENTRY , 0x00 },
+ { STB0899_ISI_BIT_EN , 0x00 },
+ { STB0899_MATSTRM , 0x00 },
+ { STB0899_MATSTRL , 0x00 },
+ { STB0899_UPLSTRM , 0x00 },
+ { STB0899_UPLSTRL , 0x00 },
+ { STB0899_DFLSTRM , 0x00 },
+ { STB0899_DFLSTRL , 0x00 },
+ { STB0899_SYNCSTR , 0x00 },
+ { STB0899_SYNCDSTRM , 0x00 },
+ { STB0899_SYNCDSTRL , 0x00 },
+ { STB0899_CFGPDELSTATUS1 , 0x10 },
+ { STB0899_CFGPDELSTATUS2 , 0x00 },
+ { STB0899_BBFERRORM , 0x00 },
+ { STB0899_BBFERRORL , 0x00 },
+ { STB0899_UPKTERRORM , 0x00 },
+ { STB0899_UPKTERRORL , 0x00 },
+ { 0xffff , 0xff },
+};
+static struct stb0899_config tt3200_config = {
+ .init_dev = tt3200_stb0899_s1_init_1,
+ .init_s2_demod = stb0899_s2_init_2,
+ .init_s1_demod = tt3200_stb0899_s1_init_3,
+ .init_s2_fec = stb0899_s2_init_4,
+ .init_tst = stb0899_s1_init_5,
+
+ .postproc = NULL,
+
+ .demod_address = 0x68,
+
+ .xtal_freq = 27000000,
+ .inversion = IQ_SWAP_ON, /* 1 */
+
+ .lo_clk = 76500000,
+ .hi_clk = 99000000,
+
+ .esno_ave = STB0899_DVBS2_ESNO_AVE,
+ .esno_quant = STB0899_DVBS2_ESNO_QUANT,
+ .avframes_coarse = STB0899_DVBS2_AVFRAMES_COARSE,
+ .avframes_fine = STB0899_DVBS2_AVFRAMES_FINE,
+ .miss_threshold = STB0899_DVBS2_MISS_THRESHOLD,
+ .uwp_threshold_acq = STB0899_DVBS2_UWP_THRESHOLD_ACQ,
+ .uwp_threshold_track = STB0899_DVBS2_UWP_THRESHOLD_TRACK,
+ .uwp_threshold_sof = STB0899_DVBS2_UWP_THRESHOLD_SOF,
+ .sof_search_timeout = STB0899_DVBS2_SOF_SEARCH_TIMEOUT,
+
+ .btr_nco_bits = STB0899_DVBS2_BTR_NCO_BITS,
+ .btr_gain_shift_offset = STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET,
+ .crl_nco_bits = STB0899_DVBS2_CRL_NCO_BITS,
+ .ldpc_max_iter = STB0899_DVBS2_LDPC_MAX_ITER,
+
+ .tuner_get_frequency = stb6100_get_frequency,
+ .tuner_set_frequency = stb6100_set_frequency,
+ .tuner_set_bandwidth = stb6100_set_bandwidth,
+ .tuner_get_bandwidth = stb6100_get_bandwidth,
+ .tuner_set_rfsiggain = NULL
+};
+
+struct stb6100_config tt3200_stb6100_config = {
+ .tuner_address = 0x60,
+ .refclock = 27000000,
+};
static void frontend_init(struct budget_ci *budget_ci)
{
@@ -1160,6 +1429,46 @@ static void frontend_init(struct budget_ci *budget_ci)
}
}
break;
+
+ case 0x1019: // TT S2-3200 PCI
+ /*
+ * NOTE! on some STB0899 versions, the internal PLL takes a longer time
+ * to settle, aka LOCK. On the older revisions of the chip, we don't see
+ * this, as a result on the newer chips the entire clock tree, will not
+ * be stable after a freshly POWER 'ed up situation.
+ * In this case, we should RESET the STB0899 (Active LOW) and wait for
+ * PLL stabilization.
+ *
+ * On the TT S2 3200 and clones, the STB0899 demodulator's RESETB is
+ * connected to the SAA7146 GPIO, GPIO2, Pin 142
+ */
+ /* Reset Demodulator */
+ saa7146_setgpio(budget_ci->budget.dev, 2, SAA7146_GPIO_OUTLO);
+ /* Wait for everything to die */
+ msleep(50);
+ /* Pull it up out of Reset state */
+ saa7146_setgpio(budget_ci->budget.dev, 2, SAA7146_GPIO_OUTHI);
+ /* Wait for PLL to stabilize */
+ msleep(250);
+ /*
+ * PLL state should be stable now. Ideally, we should check
+ * for PLL LOCK status. But well, never mind!
+ */
+ budget_ci->budget.dvb_frontend = dvb_attach(stb0899_attach, &tt3200_config, &budget_ci->budget.i2c_adap);
+ if (budget_ci->budget.dvb_frontend) {
+ if (dvb_attach(stb6100_attach, budget_ci->budget.dvb_frontend, &tt3200_stb6100_config, &budget_ci->budget.i2c_adap)) {
+ if (!dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, 0, 0)) {
+ printk("%s: No LNBP21 found!\n", __FUNCTION__);
+ dvb_frontend_detach(budget_ci->budget.dvb_frontend);
+ budget_ci->budget.dvb_frontend = NULL;
+ }
+ } else {
+ dvb_frontend_detach(budget_ci->budget.dvb_frontend);
+ budget_ci->budget.dvb_frontend = NULL;
+ }
+ }
+ break;
+
}
if (budget_ci->budget.dvb_frontend == NULL) {
@@ -1250,6 +1559,7 @@ MAKE_BUDGET_INFO(ttbt2, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT);
MAKE_BUDGET_INFO(ttbtci, "TT-Budget-T-CI PCI", BUDGET_TT);
MAKE_BUDGET_INFO(ttbcci, "TT-Budget-C-CI PCI", BUDGET_TT);
MAKE_BUDGET_INFO(ttc1501, "TT-Budget C-1501 PCI", BUDGET_TT);
+MAKE_BUDGET_INFO(tt3200, "TT-Budget S2-3200 PCI", BUDGET_TT);
static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c),
@@ -1259,6 +1569,7 @@ static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(ttbtci, 0x13c2, 0x1012),
MAKE_EXTENSION_PCI(ttbs2, 0x13c2, 0x1017),
MAKE_EXTENSION_PCI(ttc1501, 0x13c2, 0x101a),
+ MAKE_EXTENSION_PCI(tt3200, 0x13c2, 0x1019),
{
.vendor = 0,
}
diff --git a/linux/drivers/media/dvb/ttpci/budget.h b/linux/drivers/media/dvb/ttpci/budget.h
index 6129196b8..e1ebf5e8a 100644
--- a/linux/drivers/media/dvb/ttpci/budget.h
+++ b/linux/drivers/media/dvb/ttpci/budget.h
@@ -104,6 +104,7 @@ static struct saa7146_pci_extension_data x_var = { \
#define BUDGET_CIN1200C_MK3 15
#define BUDGET_KNC1C_MK3 16
#define BUDGET_KNC1CP_MK3 17
+#define BUDGET_KNC1S2 18
#define BUDGET_VIDEO_PORTA 0
#define BUDGET_VIDEO_PORTB 1
diff --git a/linux/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/linux/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
index 13085a8e2..8775b78af 100644
--- a/linux/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
+++ b/linux/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
@@ -828,6 +828,12 @@ static int ttusb_alloc_iso_urbs(struct ttusb *ttusb)
ISO_BUF_COUNT,
&ttusb->iso_dma_handle);
+ if (!ttusb->iso_buffer) {
+ dprintk("%s: pci_alloc_consistent - not enough memory\n",
+ __func__);
+ return -ENOMEM;
+ }
+
memset(ttusb->iso_buffer, 0,
ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF * ISO_BUF_COUNT);
@@ -1679,7 +1685,14 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
ttusb_setup_interfaces(ttusb);
- ttusb_alloc_iso_urbs(ttusb);
+ result = ttusb_alloc_iso_urbs(ttusb);
+ if (result < 0) {
+ dprintk("%s: ttusb_alloc_iso_urbs - failed\n", __func__);
+ mutex_unlock(&ttusb->semi2c);
+ kfree(ttusb);
+ return result;
+ }
+
if (ttusb_init_controller(ttusb))
printk("ttusb_init_controller: error\n");
diff --git a/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c
index 5c2885e17..7cfc2e4d0 100644
--- a/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+++ b/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c
@@ -1166,6 +1166,12 @@ static int ttusb_dec_alloc_iso_urbs(struct ttusb_dec *dec)
ISO_BUF_COUNT),
&dec->iso_dma_handle);
+ if (!dec->iso_buffer) {
+ dprintk("%s: pci_alloc_consistent - not enough memory\n",
+ __func__);
+ return -ENOMEM;
+ }
+
memset(dec->iso_buffer, 0,
ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF * ISO_BUF_COUNT));
@@ -1263,6 +1269,7 @@ static int ttusb_dec_init_usb(struct ttusb_dec *dec)
dec->irq_buffer = usb_buffer_alloc(dec->udev,IRQ_PACKET_SIZE,
GFP_ATOMIC, &dec->irq_dma_handle);
if(!dec->irq_buffer) {
+ usb_free_urb(dec->irq_urb);
return -ENOMEM;
}
usb_fill_int_urb(dec->irq_urb, dec->udev,dec->irq_pipe,
diff --git a/linux/drivers/media/radio/Kconfig b/linux/drivers/media/radio/Kconfig
index 04cd7c04b..5189c4eb4 100644
--- a/linux/drivers/media/radio/Kconfig
+++ b/linux/drivers/media/radio/Kconfig
@@ -355,6 +355,20 @@ config USB_SI470X
tristate "Silicon Labs Si470x FM Radio Receiver support"
depends on USB && VIDEO_V4L2
---help---
+ This is a driver for USB devices with the Silicon Labs SI470x
+ chip. Currently these devices are known to work:
+ - 10c4:818a: Silicon Labs USB FM Radio Reference Design
+ - 06e1:a155: ADS/Tech FM Radio Receiver (formerly Instant FM Music)
+ - 1b80:d700: KWorld USB FM Radio SnapMusic Mobile 700 (FM700)
+
+ Sound is provided by the ALSA USB Audio/MIDI driver. Therefore
+ if you don't want to use the device solely for RDS receiving,
+ it is recommended to also select SND_USB_AUDIO.
+
+ Please have a look at the documentation, especially on how
+ to redirect the audio stream from the radio to your sound device:
+ Documentation/video4linux/si470x.txt
+
Say Y here if you want to connect this type of radio to your
computer's USB port.
diff --git a/linux/drivers/media/radio/dsbr100.c b/linux/drivers/media/radio/dsbr100.c
index 7172977c7..d1865b164 100644
--- a/linux/drivers/media/radio/dsbr100.c
+++ b/linux/drivers/media/radio/dsbr100.c
@@ -94,8 +94,8 @@
*/
#include <linux/version.h> /* for KERNEL_VERSION MACRO */
-#define DRIVER_VERSION "v0.41"
-#define RADIO_VERSION KERNEL_VERSION(0,4,1)
+#define DRIVER_VERSION "v0.43"
+#define RADIO_VERSION KERNEL_VERSION(0, 4, 3)
static struct v4l2_queryctrl radio_qctrl[] = {
{
@@ -105,7 +105,27 @@ static struct v4l2_queryctrl radio_qctrl[] = {
.maximum = 1,
.default_value = 1,
.type = V4L2_CTRL_TYPE_BOOLEAN,
- }
+ },
+/* HINT: the disabled controls are only here to satify kradio and such apps */
+ { .id = V4L2_CID_AUDIO_VOLUME,
+ .flags = V4L2_CTRL_FLAG_DISABLED,
+ },
+ {
+ .id = V4L2_CID_AUDIO_BALANCE,
+ .flags = V4L2_CTRL_FLAG_DISABLED,
+ },
+ {
+ .id = V4L2_CID_AUDIO_BASS,
+ .flags = V4L2_CTRL_FLAG_DISABLED,
+ },
+ {
+ .id = V4L2_CID_AUDIO_TREBLE,
+ .flags = V4L2_CTRL_FLAG_DISABLED,
+ },
+ {
+ .id = V4L2_CID_AUDIO_LOUDNESS,
+ .flags = V4L2_CTRL_FLAG_DISABLED,
+ },
};
#define DRIVER_AUTHOR "Markus Demleitner <msdemlei@tucana.harvard.edu>"
@@ -132,6 +152,9 @@ static int usb_dsbr100_probe(struct usb_interface *intf,
static void usb_dsbr100_disconnect(struct usb_interface *intf);
static int usb_dsbr100_open(struct inode *inode, struct file *file);
static int usb_dsbr100_close(struct inode *inode, struct file *file);
+static int usb_dsbr100_suspend(struct usb_interface *intf,
+ pm_message_t message);
+static int usb_dsbr100_resume(struct usb_interface *intf);
static int radio_nr = -1;
module_param(radio_nr, int, 0);
@@ -158,10 +181,16 @@ MODULE_DEVICE_TABLE (usb, usb_dsbr100_device_table);
/* USB subsystem interface */
static struct usb_driver usb_dsbr100_driver = {
- .name = "dsbr100",
- .probe = usb_dsbr100_probe,
- .disconnect = usb_dsbr100_disconnect,
- .id_table = usb_dsbr100_device_table,
+ .name = "dsbr100",
+ .probe = usb_dsbr100_probe,
+ .disconnect = usb_dsbr100_disconnect,
+ .id_table = usb_dsbr100_device_table,
+ .suspend = usb_dsbr100_suspend,
+ .resume = usb_dsbr100_resume,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
+ .reset_resume = usb_dsbr100_resume,
+#endif
+ .supports_autosuspend = 0,
};
/* Low-level device interface begins here */
@@ -172,11 +201,11 @@ static int dsbr100_start(struct dsbr100_device *radio)
if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
USB_REQ_GET_STATUS,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
- 0x00, 0xC7, radio->transfer_buffer, 8, 300)<0 ||
+ 0x00, 0xC7, radio->transfer_buffer, 8, 300) < 0 ||
usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
DSB100_ONOFF,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
- 0x01, 0x00, radio->transfer_buffer, 8, 300)<0)
+ 0x01, 0x00, radio->transfer_buffer, 8, 300) < 0)
return -1;
radio->muted=0;
return (radio->transfer_buffer)[0];
@@ -189,11 +218,11 @@ static int dsbr100_stop(struct dsbr100_device *radio)
if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
USB_REQ_GET_STATUS,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
- 0x16, 0x1C, radio->transfer_buffer, 8, 300)<0 ||
+ 0x16, 0x1C, radio->transfer_buffer, 8, 300) < 0 ||
usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
DSB100_ONOFF,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
- 0x00, 0x00, radio->transfer_buffer, 8, 300)<0)
+ 0x00, 0x00, radio->transfer_buffer, 8, 300) < 0)
return -1;
radio->muted=1;
return (radio->transfer_buffer)[0];
@@ -202,24 +231,24 @@ static int dsbr100_stop(struct dsbr100_device *radio)
/* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
static int dsbr100_setfreq(struct dsbr100_device *radio, int freq)
{
- freq = (freq/16*80)/1000+856;
+ freq = (freq / 16 * 80) / 1000 + 856;
if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
DSB100_TUNE,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
- (freq>>8)&0x00ff, freq&0xff,
- radio->transfer_buffer, 8, 300)<0 ||
+ (freq >> 8) & 0x00ff, freq & 0xff,
+ radio->transfer_buffer, 8, 300) < 0 ||
usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
USB_REQ_GET_STATUS,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
- 0x96, 0xB7, radio->transfer_buffer, 8, 300)<0 ||
+ 0x96, 0xB7, radio->transfer_buffer, 8, 300) < 0 ||
usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
USB_REQ_GET_STATUS,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
- 0x00, 0x24, radio->transfer_buffer, 8, 300)<0) {
+ 0x00, 0x24, radio->transfer_buffer, 8, 300) < 0) {
radio->stereo = -1;
return -1;
}
- radio->stereo = ! ((radio->transfer_buffer)[0]&0x01);
+ radio->stereo = !((radio->transfer_buffer)[0] & 0x01);
return (radio->transfer_buffer)[0];
}
@@ -230,10 +259,10 @@ static void dsbr100_getstat(struct dsbr100_device *radio)
if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
USB_REQ_GET_STATUS,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
- 0x00 , 0x24, radio->transfer_buffer, 8, 300)<0)
+ 0x00 , 0x24, radio->transfer_buffer, 8, 300) < 0)
radio->stereo = -1;
else
- radio->stereo = ! (radio->transfer_buffer[0]&0x01);
+ radio->stereo = !(radio->transfer_buffer[0] & 0x01);
}
@@ -266,7 +295,7 @@ static int vidioc_querycap(struct file *file, void *priv,
{
strlcpy(v->driver, "dsbr100", sizeof(v->driver));
strlcpy(v->card, "D-Link R-100 USB FM Radio", sizeof(v->card));
- sprintf(v->bus_info, "ISA");
+ sprintf(v->bus_info, "USB");
v->version = RADIO_VERSION;
v->capabilities = V4L2_CAP_TUNER;
return 0;
@@ -283,9 +312,9 @@ static int vidioc_g_tuner(struct file *file, void *priv,
dsbr100_getstat(radio);
strcpy(v->name, "FM");
v->type = V4L2_TUNER_RADIO;
- v->rangelow = FREQ_MIN*FREQ_MUL;
- v->rangehigh = FREQ_MAX*FREQ_MUL;
- v->rxsubchans = V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;
+ v->rangelow = FREQ_MIN * FREQ_MUL;
+ v->rangehigh = FREQ_MAX * FREQ_MUL;
+ v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
v->capability = V4L2_TUNER_CAP_LOW;
if(radio->stereo)
v->audmode = V4L2_TUNER_MODE_STEREO;
@@ -310,8 +339,8 @@ static int vidioc_s_frequency(struct file *file, void *priv,
struct dsbr100_device *radio = video_drvdata(file);
radio->curfreq = f->frequency;
- if (dsbr100_setfreq(radio, radio->curfreq)==-1)
- warn("Set frequency failed");
+ if (dsbr100_setfreq(radio, radio->curfreq) == -1)
+ dev_warn(&radio->usbdev->dev, "Set frequency failed\n");
return 0;
}
@@ -332,8 +361,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
if (qc->id && qc->id == radio_qctrl[i].id) {
- memcpy(qc, &(radio_qctrl[i]),
- sizeof(*qc));
+ memcpy(qc, &(radio_qctrl[i]), sizeof(*qc));
return 0;
}
}
@@ -362,12 +390,14 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
case V4L2_CID_AUDIO_MUTE:
if (ctrl->value) {
if (dsbr100_stop(radio) == -1) {
- warn("Radio did not respond properly");
+ dev_warn(&radio->usbdev->dev,
+ "Radio did not respond properly\n");
return -EBUSY;
}
} else {
if (dsbr100_start(radio) == -1) {
- warn("Radio did not respond properly");
+ dev_warn(&radio->usbdev->dev,
+ "Radio did not respond properly\n");
return -EBUSY;
}
}
@@ -411,18 +441,25 @@ static int vidioc_s_audio(struct file *file, void *priv,
static int usb_dsbr100_open(struct inode *inode, struct file *file)
{
struct dsbr100_device *radio = video_drvdata(file);
+ int retval;
lock_kernel();
radio->users = 1;
radio->muted = 1;
- if (dsbr100_start(radio)<0) {
- warn("Radio did not start up properly");
+ if (dsbr100_start(radio) < 0) {
+ dev_warn(&radio->usbdev->dev,
+ "Radio did not start up properly\n");
radio->users = 0;
unlock_kernel();
return -EIO;
}
- dsbr100_setfreq(radio, radio->curfreq);
+
+ retval = dsbr100_setfreq(radio, radio->curfreq);
+
+ if (retval == -1)
+ printk(KERN_WARNING KBUILD_MODNAME ": Set frequency failed\n");
+
unlock_kernel();
return 0;
}
@@ -441,6 +478,36 @@ static int usb_dsbr100_close(struct inode *inode, struct file *file)
return 0;
}
+/* Suspend device - stop device. */
+static int usb_dsbr100_suspend(struct usb_interface *intf, pm_message_t message)
+{
+ struct dsbr100_device *radio = usb_get_intfdata(intf);
+ int retval;
+
+ retval = dsbr100_stop(radio);
+ if (retval == -1)
+ dev_warn(&intf->dev, "dsbr100_stop failed\n");
+
+ dev_info(&intf->dev, "going into suspend..\n");
+
+ return 0;
+}
+
+/* Resume device - start device. */
+static int usb_dsbr100_resume(struct usb_interface *intf)
+{
+ struct dsbr100_device *radio = usb_get_intfdata(intf);
+ int retval;
+
+ retval = dsbr100_start(radio);
+ if (retval == -1)
+ dev_warn(&intf->dev, "dsbr100_start failed\n");
+
+ dev_info(&intf->dev, "coming out of suspend..\n");
+
+ return 0;
+}
+
/* File system interface */
static const struct file_operations usb_dsbr100_fops = {
.owner = THIS_MODULE,
@@ -483,13 +550,20 @@ static int usb_dsbr100_probe(struct usb_interface *intf,
{
struct dsbr100_device *radio;
- if (!(radio = kmalloc(sizeof(struct dsbr100_device), GFP_KERNEL)))
+ radio = kmalloc(sizeof(struct dsbr100_device), GFP_KERNEL);
+
+ if (!radio)
return -ENOMEM;
- if (!(radio->transfer_buffer = kmalloc(TB_LEN, GFP_KERNEL))) {
+
+ radio->transfer_buffer = kmalloc(TB_LEN, GFP_KERNEL);
+
+ if (!(radio->transfer_buffer)) {
kfree(radio);
return -ENOMEM;
}
- if (!(radio->videodev = video_device_alloc())) {
+ radio->videodev = video_device_alloc();
+
+ if (!(radio->videodev)) {
kfree(radio->transfer_buffer);
kfree(radio);
return -ENOMEM;
@@ -499,10 +573,10 @@ static int usb_dsbr100_probe(struct usb_interface *intf,
radio->removed = 0;
radio->users = 0;
radio->usbdev = interface_to_usbdev(intf);
- radio->curfreq = FREQ_MIN*FREQ_MUL;
+ radio->curfreq = FREQ_MIN * FREQ_MUL;
video_set_drvdata(radio->videodev, radio);
if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr) < 0) {
- warn("Could not register video device");
+ dev_warn(&intf->dev, "Could not register video device\n");
video_device_release(radio->videodev);
kfree(radio->transfer_buffer);
kfree(radio);
diff --git a/linux/drivers/media/radio/radio-aimslab.c b/linux/drivers/media/radio/radio-aimslab.c
index 483ada689..4f3886097 100644
--- a/linux/drivers/media/radio/radio-aimslab.c
+++ b/linux/drivers/media/radio/radio-aimslab.c
@@ -1,7 +1,7 @@
/* radiotrack (radioreveal) driver for Linux radio support
* (c) 1997 M. Kirkwood
* Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
- * Converted to new API by Alan Cox <Alan.Cox@linux.org>
+ * Converted to new API by Alan Cox <alan@lxorguk.ukuu.org.uk>
* Various bugfixes and enhancements by Russell Kroll <rkroll@exploits.org>
*
* History:
diff --git a/linux/drivers/media/radio/radio-cadet.c b/linux/drivers/media/radio/radio-cadet.c
index f40c079ea..d05141fd9 100644
--- a/linux/drivers/media/radio/radio-cadet.c
+++ b/linux/drivers/media/radio/radio-cadet.c
@@ -23,7 +23,7 @@
* 2002-01-17 Adam Belay <ambx1@neo.rr.com>
* Updated to latest pnp code
*
- * 2003-01-31 Alan Cox <alan@redhat.com>
+ * 2003-01-31 Alan Cox <alan@lxorguk.ukuu.org.uk>
* Cleaned up locking, delay code, general odds and ends
*
* 2006-07-30 Hans J. Koch <koch@hjk-az.de>
diff --git a/linux/drivers/media/radio/radio-gemtek.c b/linux/drivers/media/radio/radio-gemtek.c
index 003c7b2f7..5dbd342bf 100644
--- a/linux/drivers/media/radio/radio-gemtek.c
+++ b/linux/drivers/media/radio/radio-gemtek.c
@@ -8,7 +8,7 @@
* RadioTrack II driver for Linux radio support (C) 1998 Ben Pfaff
*
* Based on RadioTrack I/RadioReveal (C) 1997 M. Kirkwood
- * Converted to new API by Alan Cox <Alan.Cox@linux.org>
+ * Converted to new API by Alan Cox <alan@lxorguk.ukuu.org.uk>
* Various bugfixes and enhancements by Russell Kroll <rkroll@exploits.org>
*
* TODO: Allow for more than one of these foolish entities :-)
diff --git a/linux/drivers/media/radio/radio-mr800.c b/linux/drivers/media/radio/radio-mr800.c
index 2ae8e1447..208ade5b0 100644
--- a/linux/drivers/media/radio/radio-mr800.c
+++ b/linux/drivers/media/radio/radio-mr800.c
@@ -73,6 +73,11 @@ MODULE_LICENSE("GPL");
#define USB_AMRADIO_VENDOR 0x07ca
#define USB_AMRADIO_PRODUCT 0xb800
+/* dev_warn macro with driver name */
+#define MR800_DRIVER_NAME "radio-mr800"
+#define amradio_dev_warn(dev, fmt, arg...) \
+ dev_warn(dev, MR800_DRIVER_NAME " - " fmt, ##arg)
+
/* Probably USB_TIMEOUT should be modified in module parameter */
#define BUFFER_LENGTH 8
#define USB_TIMEOUT 500
@@ -155,7 +160,7 @@ MODULE_DEVICE_TABLE(usb, usb_amradio_device_table);
/* USB subsystem interface */
static struct usb_driver usb_amradio_driver = {
- .name = "radio-mr800",
+ .name = MR800_DRIVER_NAME,
.probe = usb_amradio_probe,
.disconnect = usb_amradio_disconnect,
.suspend = usb_amradio_suspend,
@@ -362,7 +367,8 @@ static int vidioc_s_frequency(struct file *file, void *priv,
radio->curfreq = f->frequency;
if (amradio_setfreq(radio, radio->curfreq) < 0)
- warn("Set frequency failed");
+ amradio_dev_warn(&radio->videodev->dev,
+ "set frequency failed\n");
return 0;
}
@@ -385,8 +391,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
if (qc->id && qc->id == radio_qctrl[i].id) {
- memcpy(qc, &(radio_qctrl[i]),
- sizeof(*qc));
+ memcpy(qc, &(radio_qctrl[i]), sizeof(*qc));
return 0;
}
}
@@ -417,12 +422,14 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
case V4L2_CID_AUDIO_MUTE:
if (ctrl->value) {
if (amradio_stop(radio) < 0) {
- warn("amradio_stop() failed");
+ amradio_dev_warn(&radio->videodev->dev,
+ "amradio_stop failed\n");
return -1;
}
} else {
if (amradio_start(radio) < 0) {
- warn("amradio_start() failed");
+ amradio_dev_warn(&radio->videodev->dev,
+ "amradio_start failed\n");
return -1;
}
}
@@ -472,16 +479,23 @@ static int usb_amradio_open(struct inode *inode, struct file *file)
{
struct amradio_device *radio = video_get_drvdata(video_devdata(file));
+ lock_kernel();
+
radio->users = 1;
radio->muted = 1;
if (amradio_start(radio) < 0) {
- warn("Radio did not start up properly");
+ amradio_dev_warn(&radio->videodev->dev,
+ "radio did not start up properly\n");
radio->users = 0;
+ unlock_kernel();
return -EIO;
}
if (amradio_setfreq(radio, radio->curfreq) < 0)
- warn("Set frequency failed");
+ amradio_dev_warn(&radio->videodev->dev,
+ "set frequency failed\n");
+
+ unlock_kernel();
return 0;
}
@@ -506,9 +520,9 @@ static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message)
struct amradio_device *radio = usb_get_intfdata(intf);
if (amradio_stop(radio) < 0)
- warn("amradio_stop() failed");
+ dev_warn(&intf->dev, "amradio_stop failed\n");
- info("radio-mr800: Going into suspend..");
+ dev_info(&intf->dev, "going into suspend..\n");
return 0;
}
@@ -519,9 +533,9 @@ static int usb_amradio_resume(struct usb_interface *intf)
struct amradio_device *radio = usb_get_intfdata(intf);
if (amradio_start(radio) < 0)
- warn("amradio_start() failed");
+ dev_warn(&intf->dev, "amradio_start failed\n");
- info("radio-mr800: Coming out of suspend..");
+ dev_info(&intf->dev, "coming out of suspend..\n");
return 0;
}
@@ -600,7 +614,7 @@ static int usb_amradio_probe(struct usb_interface *intf,
video_set_drvdata(radio->videodev, radio);
if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr)) {
- warn("Could not register video device");
+ dev_warn(&intf->dev, "could not register video device\n");
video_device_release(radio->videodev);
kfree(radio->buffer);
kfree(radio);
@@ -615,9 +629,13 @@ static int __init amradio_init(void)
{
int retval = usb_register(&usb_amradio_driver);
- info(DRIVER_VERSION " " DRIVER_DESC);
+ pr_info(KBUILD_MODNAME
+ ": version " DRIVER_VERSION " " DRIVER_DESC "\n");
+
if (retval)
- err("usb_register failed. Error number %d", retval);
+ pr_err(KBUILD_MODNAME
+ ": usb_register failed. Error number %d\n", retval);
+
return retval;
}
diff --git a/linux/drivers/media/radio/radio-rtrack2.c b/linux/drivers/media/radio/radio-rtrack2.c
index 59592bb84..72413df42 100644
--- a/linux/drivers/media/radio/radio-rtrack2.c
+++ b/linux/drivers/media/radio/radio-rtrack2.c
@@ -1,7 +1,7 @@
/* RadioTrack II driver for Linux radio support (C) 1998 Ben Pfaff
*
* Based on RadioTrack I/RadioReveal (C) 1997 M. Kirkwood
- * Converted to new API by Alan Cox <Alan.Cox@linux.org>
+ * Converted to new API by Alan Cox <alan@lxorguk.ukuu.org.uk>
* Various bugfixes and enhancements by Russell Kroll <rkroll@exploits.org>
*
* TODO: Allow for more than one of these foolish entities :-)
diff --git a/linux/drivers/media/radio/radio-sf16fmi.c b/linux/drivers/media/radio/radio-sf16fmi.c
index edf7480bc..20326e7a5 100644
--- a/linux/drivers/media/radio/radio-sf16fmi.c
+++ b/linux/drivers/media/radio/radio-sf16fmi.c
@@ -3,7 +3,7 @@
* (c) 1997 M. Kirkwood
* (c) 1998 Petr Vandrovec, vandrove@vc.cvut.cz
*
- * Fitted to new interface by Alan Cox <alan.cox@linux.org>
+ * Fitted to new interface by Alan Cox <alan@lxorguk.ukuu.org.uk>
* Made working and cleaned up functions <mikael.hedin@irf.se>
* Support for ISAPnP by Ladislav Michl <ladis@psi.cz>
*
diff --git a/linux/drivers/media/radio/radio-si470x.c b/linux/drivers/media/radio/radio-si470x.c
index e332b3de5..5d6237b6d 100644
--- a/linux/drivers/media/radio/radio-si470x.c
+++ b/linux/drivers/media/radio/radio-si470x.c
@@ -4,6 +4,7 @@
* Driver for USB radios for the Silicon Labs Si470x FM Radio Receivers:
* - Silicon Labs USB FM Radio Reference Design
* - ADS/Tech FM Radio Receiver (formerly Instant FM Music) (RDX-155-EF)
+ * - KWorld USB FM Radio SnapMusic Mobile 700 (FM700)
*
* Copyright (c) 2008 Tobias Lorenz <tobias.lorenz@gmx.net>
*
@@ -24,19 +25,6 @@
/*
- * User Notes:
- * - USB Audio is provided by the alsa snd_usb_audio module.
- * For listing you have to redirect the sound, for example using:
- * arecord -D hw:1,0 -r96000 -c2 -f S16_LE | artsdsp aplay -B -
- * - regarding module parameters in /sys/module/radio_si470x/parameters:
- * the contents of read-only files (0444) are not updated, even if
- * space, band and de are changed using private video controls
- * - increase tune_timeout, if you often get -EIO errors
- * - hw_freq_seek returns -EAGAIN, when timed out or band limit is reached
- */
-
-
-/*
* History:
* 2008-01-12 Tobias Lorenz <tobias.lorenz@gmx.net>
* Version 1.0.0
@@ -105,6 +93,9 @@
* - afc indication
* - more safety checks, let si470x_get_freq return errno
* - vidioc behavior corrected according to v4l2 spec
+ * 2008-10-20 Alexey Klimov <klimov.linux@gmail.com>
+ * - add support for KWorld USB FM Radio FM700
+ * - blacklisted KWorld radio in hid-core.c and hid-ids.h
*
* ToDo:
* - add firmware download/update support
@@ -146,6 +137,8 @@ static struct usb_device_id si470x_usb_driver_id_table[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(0x10c4, 0x818a, USB_CLASS_HID, 0, 0) },
/* ADS/Tech FM Radio Receiver (formerly Instant FM Music) */
{ USB_DEVICE_AND_INTERFACE_INFO(0x06e1, 0xa155, USB_CLASS_HID, 0, 0) },
+ /* KWorld USB FM Radio SnapMusic Mobile 700 (FM700) */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x1b80, 0xd700, USB_CLASS_HID, 0, 0) },
/* Terminating entry */
{ }
};
diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig
index 47102c2c8..c4ee10c37 100644
--- a/linux/drivers/media/video/Kconfig
+++ b/linux/drivers/media/video/Kconfig
@@ -184,7 +184,7 @@ config VIDEO_MSP3400
config VIDEO_CS5345
tristate "Cirrus Logic CS5345 audio ADC"
- depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
+ depends on VIDEO_V4L2 && I2C
---help---
Support for the Cirrus Logic CS5345 24-bit, 192 kHz
stereo A/D converter.
@@ -204,7 +204,7 @@ config VIDEO_CS53L32A
config VIDEO_M52790
tristate "Mitsubishi M52790 A/V switch"
- depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
+ depends on VIDEO_V4L2 && I2C
---help---
Support for the Mitsubishi M52790 A/V switch.
@@ -242,7 +242,7 @@ config VIDEO_WM8739
config VIDEO_VP27SMPX
tristate "Panasonic VP27s internal MPX"
- depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
+ depends on VIDEO_V4L2 && I2C
---help---
Support for the internal MPX of the Panasonic VP27s tuner.
@@ -387,7 +387,7 @@ comment "MPEG video encoders"
config VIDEO_CX2341X
tristate "Conexant CX2341x MPEG encoders"
- depends on VIDEO_V4L2 && EXPERIMENTAL && VIDEO_V4L2_COMMON
+ depends on VIDEO_V4L2 && VIDEO_V4L2_COMMON
---help---
Support for the Conexant CX23416 MPEG encoders
and CX23415 MPEG encoder/decoders.
@@ -750,6 +750,12 @@ config SOC_CAMERA_PLATFORM
help
This is a generic SoC camera platform driver, useful for testing
+config SOC_CAMERA_OV772X
+ tristate "ov772x camera support"
+ depends on SOC_CAMERA && I2C
+ help
+ This is a ov772x camera driver
+
config VIDEO_PXA27x
tristate "PXA27x Quick Capture Interface driver"
depends on VIDEO_DEV && PXA27x && SOC_CAMERA
diff --git a/linux/drivers/media/video/Makefile b/linux/drivers/media/video/Makefile
index 745780e1f..53d43f9e0 100644
--- a/linux/drivers/media/video/Makefile
+++ b/linux/drivers/media/video/Makefile
@@ -10,7 +10,7 @@ stkwebcam-objs := stk-webcam.o stk-sensor.o
videodev-objs := v4l2-dev.o v4l2-ioctl.o
-obj-$(CONFIG_VIDEO_DEV) += videodev.o compat_ioctl32.o v4l2-int-device.o
+obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-compat-ioctl32.o v4l2-int-device.o
obj-$(CONFIG_VIDEO_V4L2_COMMON) += v4l2-common.o
@@ -134,6 +134,7 @@ obj-$(CONFIG_SOC_CAMERA) += soc_camera.o
obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o
obj-$(CONFIG_SOC_CAMERA_MT9M111) += mt9m111.o
obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o
+obj-$(CONFIG_SOC_CAMERA_OV772X) += ov772x.o
obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o
obj-$(CONFIG_VIDEO_AU0828) += au0828/
diff --git a/linux/drivers/media/video/arv.c b/linux/drivers/media/video/arv.c
index a6c2ff1b4..c15dfd37c 100644
--- a/linux/drivers/media/video/arv.c
+++ b/linux/drivers/media/video/arv.c
@@ -397,8 +397,7 @@ out_up:
return ret;
}
-static int ar_do_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, void *arg)
+static int ar_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct video_device *dev = video_devdata(file);
struct ar_device *ar = video_get_drvdata(dev);
@@ -544,7 +543,7 @@ static int ar_do_ioctl(struct inode *inode, struct file *file,
static int ar_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg)
{
- return video_usercopy(inode, file, cmd, arg, ar_do_ioctl);
+ return video_usercopy(file, cmd, arg, ar_do_ioctl);
}
#if USE_INT
@@ -871,7 +870,7 @@ static int __init ar_init(void)
}
printk("video%d: Found M64278 VGA (IRQ %d, Freq %dMHz).\n",
- ar->vdev->minor, M32R_IRQ_INT3, freq);
+ ar->vdev->num, M32R_IRQ_INT3, freq);
return 0;
diff --git a/linux/drivers/media/video/au0828/au0828-cards.c b/linux/drivers/media/video/au0828/au0828-cards.c
index 5f07a8a07..d60123b41 100644
--- a/linux/drivers/media/video/au0828/au0828-cards.c
+++ b/linux/drivers/media/video/au0828/au0828-cards.c
@@ -90,6 +90,7 @@ static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data)
case 72221: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and basic analog video */
case 72231: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and basic analog video */
case 72241: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM and basic analog video */
+ case 72251: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and basic analog video */
case 72301: /* WinTV-HVR850 (Retail, IR, ATSC and basic analog video */
case 72500: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM */
break;
@@ -185,7 +186,7 @@ void au0828_gpio_setup(struct au0828_dev *dev)
}
/* table of devices that work with this driver */
-struct usb_device_id au0828_usb_id_table [] = {
+struct usb_device_id au0828_usb_id_table[] = {
{ USB_DEVICE(0x2040, 0x7200),
.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
{ USB_DEVICE(0x2040, 0x7240),
@@ -198,6 +199,8 @@ struct usb_device_id au0828_usb_id_table [] = {
.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
{ USB_DEVICE(0x2040, 0x721b),
.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
+ { USB_DEVICE(0x2040, 0x721e),
+ .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
{ USB_DEVICE(0x2040, 0x721f),
.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
{ USB_DEVICE(0x2040, 0x7280),
diff --git a/linux/drivers/media/video/au0828/au0828-core.c b/linux/drivers/media/video/au0828/au0828-core.c
index 59dcb3255..05e38f41c 100644
--- a/linux/drivers/media/video/au0828/au0828-core.c
+++ b/linux/drivers/media/video/au0828/au0828-core.c
@@ -92,7 +92,8 @@ static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value,
status = usb_control_msg(dev->usbdev,
usb_sndctrlpipe(dev->usbdev, 0),
request,
- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ USB_DIR_OUT | USB_TYPE_VENDOR |
+ USB_RECIP_DEVICE,
value, index,
cp, size, 1000);
diff --git a/linux/drivers/media/video/au0828/au0828-dvb.c b/linux/drivers/media/video/au0828/au0828-dvb.c
index bc76e4079..9966f83d5 100644
--- a/linux/drivers/media/video/au0828/au0828-dvb.c
+++ b/linux/drivers/media/video/au0828/au0828-dvb.c
@@ -178,7 +178,8 @@ static int start_urb_transfer(struct au0828_dev *dev)
purb->status = -EINPROGRESS;
usb_fill_bulk_urb(purb,
dev->usbdev,
- usb_rcvbulkpipe(dev->usbdev, _AU0828_BULKPIPE),
+ usb_rcvbulkpipe(dev->usbdev,
+ _AU0828_BULKPIPE),
purb->transfer_buffer,
URB_BUFSIZE,
urb_completion,
diff --git a/linux/drivers/media/video/bt8xx/bttv-driver.c b/linux/drivers/media/video/bt8xx/bttv-driver.c
index c7bca940a..09188617b 100644
--- a/linux/drivers/media/video/bt8xx/bttv-driver.c
+++ b/linux/drivers/media/video/bt8xx/bttv-driver.c
@@ -4270,7 +4270,7 @@ static int __devinit bttv_register_video(struct bttv *btv)
video_nr[btv->c.nr]) < 0)
goto err;
printk(KERN_INFO "bttv%d: registered device video%d\n",
- btv->c.nr,btv->video_dev->minor & 0x1f);
+ btv->c.nr, btv->video_dev->num);
if (device_create_file(&btv->video_dev->dev,
&dev_attr_card)<0) {
printk(KERN_ERR "bttv%d: device_create_file 'card' "
@@ -4287,7 +4287,7 @@ static int __devinit bttv_register_video(struct bttv *btv)
vbi_nr[btv->c.nr]) < 0)
goto err;
printk(KERN_INFO "bttv%d: registered device vbi%d\n",
- btv->c.nr,btv->vbi_dev->minor & 0x1f);
+ btv->c.nr, btv->vbi_dev->num);
if (!btv->has_radio)
return 0;
@@ -4299,7 +4299,7 @@ static int __devinit bttv_register_video(struct bttv *btv)
radio_nr[btv->c.nr]) < 0)
goto err;
printk(KERN_INFO "bttv%d: registered device radio%d\n",
- btv->c.nr,btv->radio_dev->minor & 0x1f);
+ btv->c.nr, btv->radio_dev->num);
/* all done */
return 0;
diff --git a/linux/drivers/media/video/bt8xx/bttv-gpio.c b/linux/drivers/media/video/bt8xx/bttv-gpio.c
index dce6dae57..74c325e59 100644
--- a/linux/drivers/media/video/bt8xx/bttv-gpio.c
+++ b/linux/drivers/media/video/bt8xx/bttv-gpio.c
@@ -42,7 +42,7 @@ static int bttv_sub_bus_match(struct device *dev, struct device_driver *drv)
struct bttv_sub_driver *sub = to_bttv_sub_drv(drv);
int len = strlen(sub->wanted);
- if (0 == strncmp(dev->bus_id, sub->wanted, len))
+ if (0 == strncmp(dev_name(dev), sub->wanted, len))
return 1;
return 0;
}
@@ -91,15 +91,14 @@ int bttv_sub_add_device(struct bttv_core *core, char *name)
sub->dev.parent = &core->pci->dev;
sub->dev.bus = &bttv_sub_bus_type;
sub->dev.release = release_sub_device;
- snprintf(sub->dev.bus_id,sizeof(sub->dev.bus_id),"%s%d",
- name, core->nr);
+ dev_set_name(&sub->dev, "%s%d", name, core->nr);
err = device_register(&sub->dev);
if (0 != err) {
kfree(sub);
return err;
}
- printk("bttv%d: add subdevice \"%s\"\n", core->nr, sub->dev.bus_id);
+ printk("bttv%d: add subdevice \"%s\"\n", core->nr, dev_name(&sub->dev));
list_add_tail(&sub->list,&core->subs);
return 0;
}
diff --git a/linux/drivers/media/video/bt8xx/bttv.h b/linux/drivers/media/video/bt8xx/bttv.h
index 0f2a33eb3..20f027ee4 100644
--- a/linux/drivers/media/video/bt8xx/bttv.h
+++ b/linux/drivers/media/video/bt8xx/bttv.h
@@ -311,7 +311,7 @@ struct bttv_sub_device {
struct bttv_sub_driver {
struct device_driver drv;
- char wanted[BUS_ID_SIZE];
+ char wanted[20];
int (*probe)(struct bttv_sub_device *sub);
void (*remove)(struct bttv_sub_device *sub);
};
diff --git a/linux/drivers/media/video/bt8xx/bttvp.h b/linux/drivers/media/video/bt8xx/bttvp.h
index 403695f9a..92961e130 100644
--- a/linux/drivers/media/video/bt8xx/bttvp.h
+++ b/linux/drivers/media/video/bt8xx/bttvp.h
@@ -461,7 +461,7 @@ struct bttv {
};
/* our devices */
-#define BTTV_MAX 16
+#define BTTV_MAX 32
extern unsigned int bttv_num;
extern struct bttv bttvs[BTTV_MAX];
diff --git a/linux/drivers/media/video/bw-qcam.c b/linux/drivers/media/video/bw-qcam.c
index ca8fabdf3..e534eaf39 100644
--- a/linux/drivers/media/video/bw-qcam.c
+++ b/linux/drivers/media/video/bw-qcam.c
@@ -707,8 +707,7 @@ static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long l
* Video4linux interfacing
*/
-static int qcam_do_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, void *arg)
+static int qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct video_device *dev = video_devdata(file);
struct qcam_device *qcam=(struct qcam_device *)dev;
@@ -868,7 +867,7 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file,
static int qcam_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- return video_usercopy(inode, file, cmd, arg, qcam_do_ioctl);
+ return video_usercopy(file, cmd, arg, qcam_do_ioctl);
}
static ssize_t qcam_read(struct file *file, char __user *buf,
diff --git a/linux/drivers/media/video/c-qcam.c b/linux/drivers/media/video/c-qcam.c
index ba4d43b90..bdad822a5 100644
--- a/linux/drivers/media/video/c-qcam.c
+++ b/linux/drivers/media/video/c-qcam.c
@@ -501,8 +501,7 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le
* Video4linux interfacing
*/
-static int qcam_do_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, void *arg)
+static int qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct video_device *dev = video_devdata(file);
struct qcam_device *qcam=(struct qcam_device *)dev;
@@ -668,9 +667,9 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file,
}
static int qcam_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
- return video_usercopy(inode, file, cmd, arg, qcam_do_ioctl);
+ return video_usercopy(file, cmd, arg, qcam_do_ioctl);
}
static ssize_t qcam_read(struct file *file, char __user *buf,
@@ -816,7 +815,7 @@ static int init_cqcam(struct parport *port)
}
printk(KERN_INFO "video%d: Colour QuickCam found on %s\n",
- qcam->vdev.minor, qcam->pport->name);
+ qcam->vdev.num, qcam->pport->name);
qcams[num_cams++] = qcam;
diff --git a/linux/drivers/media/video/cafe_ccic.c b/linux/drivers/media/video/cafe_ccic.c
index 26c08f00b..1184b9186 100644
--- a/linux/drivers/media/video/cafe_ccic.c
+++ b/linux/drivers/media/video/cafe_ccic.c
@@ -1483,12 +1483,9 @@ static int cafe_v4l_open(struct inode *inode, struct file *filp)
{
struct cafe_camera *cam;
- lock_kernel();
cam = cafe_find_dev(iminor(inode));
- if (cam == NULL) {
- unlock_kernel();
+ if (cam == NULL)
return -ENODEV;
- }
filp->private_data = cam;
mutex_lock(&cam->s_mutex);
@@ -1500,7 +1497,6 @@ static int cafe_v4l_open(struct inode *inode, struct file *filp)
}
(cam->users)++;
mutex_unlock(&cam->s_mutex);
- unlock_kernel();
return 0;
}
@@ -2066,10 +2062,10 @@ static void cafe_dfs_cam_setup(struct cafe_camera *cam)
if (!cafe_dfs_root)
return;
- sprintf(fname, "regs-%d", cam->v4ldev.minor);
+ sprintf(fname, "regs-%d", cam->v4ldev.num);
cam->dfs_regs = debugfs_create_file(fname, 0444, cafe_dfs_root,
cam, &cafe_dfs_reg_ops);
- sprintf(fname, "cam-%d", cam->v4ldev.minor);
+ sprintf(fname, "cam-%d", cam->v4ldev.num);
cam->dfs_cam_regs = debugfs_create_file(fname, 0444, cafe_dfs_root,
cam, &cafe_dfs_cam_ops);
}
@@ -2103,15 +2099,8 @@ static int cafe_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
int ret;
- u16 classword;
struct cafe_camera *cam;
- /*
- * Make sure we have a camera here - we'll get calls for
- * the other cafe devices as well.
- */
- pci_read_config_word(pdev, PCI_CLASS_DEVICE, &classword);
- if (classword != PCI_CLASS_MULTIMEDIA_VIDEO)
- return -ENODEV;
+
/*
* Start putting together one of our big camera structures.
*/
@@ -2299,8 +2288,8 @@ static int cafe_pci_resume(struct pci_dev *pdev)
static struct pci_device_id cafe_ids[] = {
- { PCI_DEVICE(0x11ab, 0x4100) }, /* Eventual real ID */
- { PCI_DEVICE(0x11ab, 0x4102) }, /* Really eventual real ID */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL,
+ PCI_DEVICE_ID_MARVELL_88ALP01_CCIC) },
{ 0, }
};
diff --git a/linux/drivers/media/video/cpia.c b/linux/drivers/media/video/cpia.c
index 0bee440ab..004f36928 100644
--- a/linux/drivers/media/video/cpia.c
+++ b/linux/drivers/media/video/cpia.c
@@ -39,10 +39,6 @@
#include <asm/io.h>
#include <linux/mutex.h>
-#ifdef CONFIG_KMOD
-#include <linux/kmod.h>
-#endif
-
#include "cpia.h"
#include "compat.h"
@@ -1352,7 +1348,7 @@ static void create_proc_cpia_cam(struct cam_data *cam)
if (!cpia_proc_root || !cam)
return;
- snprintf(name, sizeof(name), "video%d", cam->vdev.minor);
+ snprintf(name, sizeof(name), "video%d", cam->vdev.num);
ent = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, cpia_proc_root);
if (!ent)
@@ -1377,7 +1373,7 @@ static void destroy_proc_cpia_cam(struct cam_data *cam)
if (!cam || !cam->proc_entry)
return;
- snprintf(name, sizeof(name), "video%d", cam->vdev.minor);
+ snprintf(name, sizeof(name), "video%d", cam->vdev.num);
remove_proc_entry(name, cpia_proc_root);
cam->proc_entry = NULL;
}
@@ -3338,8 +3334,7 @@ static ssize_t cpia_read(struct file *file, char __user *buf,
return cam->decompressed_frame.count;
}
-static int cpia_do_ioctl(struct inode *inode, struct file *file,
- unsigned int ioctlnr, void *arg)
+static int cpia_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct video_device *dev = file->private_data;
struct cam_data *cam = video_get_drvdata(dev);
@@ -3352,9 +3347,9 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file,
if (mutex_lock_interruptible(&cam->busy_lock))
return -EINTR;
- //DBG("cpia_ioctl: %u\n", ioctlnr);
+ /* DBG("cpia_ioctl: %u\n", cmd); */
- switch (ioctlnr) {
+ switch (cmd) {
/* query capabilities */
case VIDIOCGCAP:
{
@@ -3729,7 +3724,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file,
static int cpia_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- return video_usercopy(inode, file, cmd, arg, cpia_do_ioctl);
+ return video_usercopy(file, cmd, arg, cpia_do_ioctl);
}
@@ -4010,7 +4005,7 @@ void cpia_unregister_camera(struct cam_data *cam)
}
#ifdef CONFIG_PROC_FS
- DBG("destroying /proc/cpia/video%d\n", cam->vdev.minor);
+ DBG("destroying /proc/cpia/video%d\n", cam->vdev.num);
destroy_proc_cpia_cam(cam);
#endif
if (!cam->open_count) {
diff --git a/linux/drivers/media/video/cpia2/cpia2_core.c b/linux/drivers/media/video/cpia2/cpia2_core.c
index 8e55d3a21..08e98e70a 100644
--- a/linux/drivers/media/video/cpia2/cpia2_core.c
+++ b/linux/drivers/media/video/cpia2/cpia2_core.c
@@ -25,7 +25,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Stripped of 2.4 stuff ready for main kernel submit by
- * Alan Cox <alan@redhat.com>
+ * Alan Cox <alan@lxorguk.ukuu.org.uk>
*
****************************************************************************/
diff --git a/linux/drivers/media/video/cpia2/cpia2_usb.c b/linux/drivers/media/video/cpia2/cpia2_usb.c
index bd9277873..d1b8fb10c 100644
--- a/linux/drivers/media/video/cpia2/cpia2_usb.c
+++ b/linux/drivers/media/video/cpia2/cpia2_usb.c
@@ -25,7 +25,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Stripped of 2.4 stuff ready for main kernel submit by
- * Alan Cox <alan@redhat.com>
+ * Alan Cox <alan@lxorguk.ukuu.org.uk>
****************************************************************************/
#include <linux/kernel.h>
diff --git a/linux/drivers/media/video/cpia2/cpia2_v4l.c b/linux/drivers/media/video/cpia2/cpia2_v4l.c
index 897e8d1a5..3c2d7eac1 100644
--- a/linux/drivers/media/video/cpia2/cpia2_v4l.c
+++ b/linux/drivers/media/video/cpia2/cpia2_v4l.c
@@ -26,7 +26,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Stripped of 2.4 stuff ready for main kernel submit by
- * Alan Cox <alan@redhat.com>
+ * Alan Cox <alan@lxorguk.ukuu.org.uk>
****************************************************************************/
#include <linux/version.h>
@@ -1572,8 +1572,7 @@ static int ioctl_dqbuf(void *arg,struct camera_data *cam, struct file *file)
* cpia2_ioctl
*
*****************************************************************************/
-static int cpia2_do_ioctl(struct inode *inode, struct file *file,
- unsigned int ioctl_nr, void *arg)
+static int cpia2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct camera_data *cam = video_drvdata(file);
int retval = 0;
@@ -1591,7 +1590,7 @@ static int cpia2_do_ioctl(struct inode *inode, struct file *file,
}
/* Priority check */
- switch (ioctl_nr) {
+ switch (cmd) {
case VIDIOCSWIN:
case VIDIOCMCAPTURE:
case VIDIOC_S_FMT:
@@ -1618,7 +1617,7 @@ static int cpia2_do_ioctl(struct inode *inode, struct file *file,
break;
}
- switch (ioctl_nr) {
+ switch (cmd) {
case VIDIOCGCAP: /* query capabilities */
retval = ioctl_cap_query(arg, cam);
break;
@@ -1683,7 +1682,7 @@ static int cpia2_do_ioctl(struct inode *inode, struct file *file,
case VIDIOC_ENUMINPUT:
case VIDIOC_G_INPUT:
case VIDIOC_S_INPUT:
- retval = ioctl_input(ioctl_nr, arg,cam);
+ retval = ioctl_input(cmd, arg, cam);
break;
case VIDIOC_ENUM_FMT:
@@ -1843,9 +1842,9 @@ static int cpia2_do_ioctl(struct inode *inode, struct file *file,
}
static int cpia2_ioctl(struct inode *inode, struct file *file,
- unsigned int ioctl_nr, unsigned long iarg)
+ unsigned int cmd, unsigned long arg)
{
- return video_usercopy(inode, file, ioctl_nr, iarg, cpia2_do_ioctl);
+ return video_usercopy(file, cmd, arg, cpia2_do_ioctl);
}
/******************************************************************************
@@ -1973,7 +1972,7 @@ void cpia2_unregister_camera(struct camera_data *cam)
} else {
LOG("/dev/video%d removed while open, "
"deferring video_unregister_device\n",
- cam->vdev->minor);
+ cam->vdev->num);
}
}
diff --git a/linux/drivers/media/video/cx18/cx18-av-audio.c b/linux/drivers/media/video/cx18/cx18-av-audio.c
index 0b5583788..486cad0c2 100644
--- a/linux/drivers/media/video/cx18/cx18-av-audio.c
+++ b/linux/drivers/media/video/cx18/cx18-av-audio.c
@@ -215,12 +215,15 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
void cx18_av_audio_set_path(struct cx18 *cx)
{
struct cx18_av_state *state = &cx->av_state;
+ u8 v;
/* stop microcontroller */
- cx18_av_and_or(cx, 0x803, ~0x10, 0);
+ v = cx18_av_read(cx, 0x803) & ~0x10;
+ cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
/* assert soft reset */
- cx18_av_and_or(cx, 0x810, ~0x1, 0x01);
+ v = cx18_av_read(cx, 0x810) | 0x01;
+ cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
/* Mute everything to prevent the PFFT! */
cx18_av_write(cx, 0x8d3, 0x1f);
@@ -240,12 +243,14 @@ void cx18_av_audio_set_path(struct cx18 *cx)
set_audclk_freq(cx, state->audclk_freq);
/* deassert soft reset */
- cx18_av_and_or(cx, 0x810, ~0x1, 0x00);
+ v = cx18_av_read(cx, 0x810) & ~0x01;
+ cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
/* When the microcontroller detects the
* audio format, it will unmute the lines */
- cx18_av_and_or(cx, 0x803, ~0x10, 0x10);
+ v = cx18_av_read(cx, 0x803) | 0x10;
+ cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
}
}
@@ -347,19 +352,23 @@ static int get_mute(struct cx18 *cx)
static void set_mute(struct cx18 *cx, int mute)
{
struct cx18_av_state *state = &cx->av_state;
+ u8 v;
if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
/* Must turn off microcontroller in order to mute sound.
* Not sure if this is the best method, but it does work.
* If the microcontroller is running, then it will undo any
* changes to the mute register. */
+ v = cx18_av_read(cx, 0x803);
if (mute) {
/* disable microcontroller */
- cx18_av_and_or(cx, 0x803, ~0x10, 0x00);
+ v &= ~0x10;
+ cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
cx18_av_write(cx, 0x8d3, 0x1f);
} else {
/* enable microcontroller */
- cx18_av_and_or(cx, 0x803, ~0x10, 0x10);
+ v |= 0x10;
+ cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
}
} else {
/* SRC1_MUTE_EN */
@@ -375,16 +384,26 @@ int cx18_av_audio(struct cx18 *cx, unsigned int cmd, void *arg)
switch (cmd) {
case VIDIOC_INT_AUDIO_CLOCK_FREQ:
+ {
+ u8 v;
if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
- cx18_av_and_or(cx, 0x803, ~0x10, 0);
+ v = cx18_av_read(cx, 0x803) & ~0x10;
+ cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
cx18_av_write(cx, 0x8d3, 0x1f);
}
- cx18_av_and_or(cx, 0x810, ~0x1, 1);
+ v = cx18_av_read(cx, 0x810) | 0x1;
+ cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
+
retval = set_audclk_freq(cx, *(u32 *)arg);
- cx18_av_and_or(cx, 0x810, ~0x1, 0);
- if (state->aud_input > CX18_AV_AUDIO_SERIAL2)
- cx18_av_and_or(cx, 0x803, ~0x10, 0x10);
+
+ v = cx18_av_read(cx, 0x810) & ~0x1;
+ cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
+ if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
+ v = cx18_av_read(cx, 0x803) | 0x10;
+ cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
+ }
return retval;
+ }
case VIDIOC_G_CTRL:
switch (ctrl->id) {
diff --git a/linux/drivers/media/video/cx18/cx18-av-core.c b/linux/drivers/media/video/cx18/cx18-av-core.c
index 73f5141a4..518bd701d 100644
--- a/linux/drivers/media/video/cx18/cx18-av-core.c
+++ b/linux/drivers/media/video/cx18/cx18-av-core.c
@@ -36,12 +36,31 @@ int cx18_av_write(struct cx18 *cx, u16 addr, u8 value)
return 0;
}
+int cx18_av_write_expect(struct cx18 *cx, u16 addr, u8 value, u8 eval, u8 mask)
+{
+ u32 reg = 0xc40000 + (addr & ~3);
+ int shift = (addr & 3) * 8;
+ u32 x = cx18_read_reg(cx, reg);
+
+ x = (x & ~((u32)0xff << shift)) | ((u32)value << shift);
+ cx18_write_reg_expect(cx, x, reg,
+ ((u32)eval << shift), ((u32)mask << shift));
+ return 0;
+}
+
int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value)
{
cx18_write_reg(cx, value, 0xc40000 + addr);
return 0;
}
+int
+cx18_av_write4_expect(struct cx18 *cx, u16 addr, u32 value, u32 eval, u32 mask)
+{
+ cx18_write_reg_expect(cx, value, 0xc40000 + addr, eval, mask);
+ return 0;
+}
+
int cx18_av_write4_noretry(struct cx18 *cx, u16 addr, u32 value)
{
cx18_write_reg_noretry(cx, value, 0xc40000 + addr);
@@ -98,14 +117,16 @@ static void cx18_av_initialize(struct cx18 *cx)
cx18_av_loadfw(cx);
/* Stop 8051 code execution */
- cx18_av_write4(cx, CXADEC_DL_CTL, 0x03000000);
+ cx18_av_write4_expect(cx, CXADEC_DL_CTL, 0x03000000,
+ 0x03000000, 0x13000000);
/* initallize the PLL by toggling sleep bit */
v = cx18_av_read4(cx, CXADEC_HOST_REG1);
- /* enable sleep mode */
- cx18_av_write4(cx, CXADEC_HOST_REG1, v | 1);
+ /* enable sleep mode - register appears to be read only... */
+ cx18_av_write4_expect(cx, CXADEC_HOST_REG1, v | 1, v, 0xfffe);
/* disable sleep mode */
- cx18_av_write4(cx, CXADEC_HOST_REG1, v & 0xfffe);
+ cx18_av_write4_expect(cx, CXADEC_HOST_REG1, v & 0xfffe,
+ v & 0xfffe, 0xffff);
/* initialize DLLs */
v = cx18_av_read4(cx, CXADEC_DLL1_DIAG_CTRL) & 0xE1FFFEFF;
@@ -125,9 +146,10 @@ static void cx18_av_initialize(struct cx18 *cx)
v = cx18_av_read4(cx, CXADEC_AFE_DIAG_CTRL3) | 1;
/* enable TUNE_FIL_RST */
- cx18_av_write4(cx, CXADEC_AFE_DIAG_CTRL3, v);
+ cx18_av_write4_expect(cx, CXADEC_AFE_DIAG_CTRL3, v, v, 0x03009F0F);
/* disable TUNE_FIL_RST */
- cx18_av_write4(cx, CXADEC_AFE_DIAG_CTRL3, v & 0xFFFFFFFE);
+ cx18_av_write4_expect(cx, CXADEC_AFE_DIAG_CTRL3,
+ v & 0xFFFFFFFE, v & 0xFFFFFFFE, 0x03009F0F);
/* enable 656 output */
cx18_av_and_or4(cx, CXADEC_PIN_CTRL1, ~0, 0x040C00);
@@ -251,10 +273,9 @@ void cx18_av_std_setup(struct cx18 *cx)
pll_int, pll_frac, pll_post);
if (pll_post) {
- int fin, fsc;
- int pll = 28636363L * ((((u64)pll_int) << 25) + pll_frac);
+ int fin, fsc, pll;
- pll >>= 25;
+ pll = (28636364L * ((((u64)pll_int) << 25) + pll_frac)) >> 25;
pll /= pll_post;
CX18_DEBUG_INFO("PLL = %d.%06d MHz\n",
pll / 1000000, pll % 1000000);
@@ -324,6 +345,7 @@ static void input_change(struct cx18 *cx)
{
struct cx18_av_state *state = &cx->av_state;
v4l2_std_id std = state->std;
+ u8 v;
/* Follow step 8c and 8d of section 3.16 in the cx18_av datasheet */
cx18_av_write(cx, 0x49f, (std & V4L2_STD_NTSC) ? 0x14 : 0x11);
@@ -333,31 +355,34 @@ static void input_change(struct cx18 *cx)
if (std & V4L2_STD_525_60) {
if (std == V4L2_STD_NTSC_M_JP) {
/* Japan uses EIAJ audio standard */
- cx18_av_write(cx, 0x808, 0xf7);
- cx18_av_write(cx, 0x80b, 0x02);
+ cx18_av_write_expect(cx, 0x808, 0xf7, 0xf7, 0xff);
+ cx18_av_write_expect(cx, 0x80b, 0x02, 0x02, 0x3f);
} else if (std == V4L2_STD_NTSC_M_KR) {
/* South Korea uses A2 audio standard */
- cx18_av_write(cx, 0x808, 0xf8);
- cx18_av_write(cx, 0x80b, 0x03);
+ cx18_av_write_expect(cx, 0x808, 0xf8, 0xf8, 0xff);
+ cx18_av_write_expect(cx, 0x80b, 0x03, 0x03, 0x3f);
} else {
/* Others use the BTSC audio standard */
- cx18_av_write(cx, 0x808, 0xf6);
- cx18_av_write(cx, 0x80b, 0x01);
+ cx18_av_write_expect(cx, 0x808, 0xf6, 0xf6, 0xff);
+ cx18_av_write_expect(cx, 0x80b, 0x01, 0x01, 0x3f);
}
} else if (std & V4L2_STD_PAL) {
/* Follow tuner change procedure for PAL */
- cx18_av_write(cx, 0x808, 0xff);
- cx18_av_write(cx, 0x80b, 0x03);
+ cx18_av_write_expect(cx, 0x808, 0xff, 0xff, 0xff);
+ cx18_av_write_expect(cx, 0x80b, 0x03, 0x03, 0x3f);
} else if (std & V4L2_STD_SECAM) {
/* Select autodetect for SECAM */
- cx18_av_write(cx, 0x808, 0xff);
- cx18_av_write(cx, 0x80b, 0x03);
+ cx18_av_write_expect(cx, 0x808, 0xff, 0xff, 0xff);
+ cx18_av_write_expect(cx, 0x80b, 0x03, 0x03, 0x3f);
}
- if (cx18_av_read(cx, 0x803) & 0x10) {
+ v = cx18_av_read(cx, 0x803);
+ if (v & 0x10) {
/* restart audio decoder microcontroller */
- cx18_av_and_or(cx, 0x803, ~0x10, 0x00);
- cx18_av_and_or(cx, 0x803, ~0x10, 0x10);
+ v &= ~0x10;
+ cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
+ v |= 0x10;
+ cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
}
}
@@ -368,6 +393,7 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input,
u8 is_composite = (vid_input >= CX18_AV_COMPOSITE1 &&
vid_input <= CX18_AV_COMPOSITE8);
u8 reg;
+ u8 v;
CX18_DEBUG_INFO("decoder set video input %d, audio input %d\n",
vid_input, aud_input);
@@ -413,16 +439,23 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input,
return -EINVAL;
}
- cx18_av_write(cx, 0x103, reg);
+ cx18_av_write_expect(cx, 0x103, reg, reg, 0xf7);
/* Set INPUT_MODE to Composite (0) or S-Video (1) */
cx18_av_and_or(cx, 0x401, ~0x6, is_composite ? 0 : 0x02);
+
/* Set CH_SEL_ADC2 to 1 if input comes from CH3 */
- cx18_av_and_or(cx, 0x102, ~0x2, (reg & 0x80) == 0 ? 2 : 0);
+ v = cx18_av_read(cx, 0x102);
+ if (reg & 0x80)
+ v &= ~0x2;
+ else
+ v |= 0x2;
/* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2 and CH3 */
if ((reg & 0xc0) != 0xc0 && (reg & 0x30) != 0x30)
- cx18_av_and_or(cx, 0x102, ~0x4, 4);
+ v |= 0x4;
else
- cx18_av_and_or(cx, 0x102, ~0x4, 0);
+ v &= ~0x4;
+ cx18_av_write_expect(cx, 0x102, v, v, 0x17);
+
/*cx18_av_and_or4(cx, 0x104, ~0x001b4180, 0x00004180);*/
state->vid_input = vid_input;
@@ -799,40 +832,47 @@ int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg)
}
case VIDIOC_S_TUNER:
+ {
+ u8 v;
+
if (state->radio)
break;
+ v = cx18_av_read(cx, 0x809);
+ v &= ~0xf;
+
switch (vt->audmode) {
case V4L2_TUNER_MODE_MONO:
/* mono -> mono
stereo -> mono
bilingual -> lang1 */
- cx18_av_and_or(cx, 0x809, ~0xf, 0x00);
break;
case V4L2_TUNER_MODE_STEREO:
case V4L2_TUNER_MODE_LANG1:
/* mono -> mono
stereo -> stereo
bilingual -> lang1 */
- cx18_av_and_or(cx, 0x809, ~0xf, 0x04);
+ v |= 0x4;
break;
case V4L2_TUNER_MODE_LANG1_LANG2:
/* mono -> mono
stereo -> stereo
bilingual -> lang1/lang2 */
- cx18_av_and_or(cx, 0x809, ~0xf, 0x07);
+ v |= 0x7;
break;
case V4L2_TUNER_MODE_LANG2:
/* mono -> mono
stereo -> stereo
bilingual -> lang2 */
- cx18_av_and_or(cx, 0x809, ~0xf, 0x01);
+ v |= 0x1;
break;
default:
return -EINVAL;
}
+ cx18_av_write_expect(cx, 0x809, v, v, 0xff);
state->audmode = vt->audmode;
break;
+ }
case VIDIOC_G_FMT:
return get_v4lfmt(cx, (struct v4l2_format *)arg);
diff --git a/linux/drivers/media/video/cx18/cx18-av-core.h b/linux/drivers/media/video/cx18/cx18-av-core.h
index b67d8df20..a07988c6f 100644
--- a/linux/drivers/media/video/cx18/cx18-av-core.h
+++ b/linux/drivers/media/video/cx18/cx18-av-core.h
@@ -302,6 +302,9 @@ struct cx18_av_state {
int cx18_av_write(struct cx18 *cx, u16 addr, u8 value);
int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value);
int cx18_av_write4_noretry(struct cx18 *cx, u16 addr, u32 value);
+int cx18_av_write_expect(struct cx18 *cx, u16 addr, u8 value, u8 eval, u8 mask);
+int cx18_av_write4_expect(struct cx18 *cx, u16 addr, u32 value, u32 eval,
+ u32 mask);
u8 cx18_av_read(struct cx18 *cx, u16 addr);
u32 cx18_av_read4(struct cx18 *cx, u16 addr);
u32 cx18_av_read4_noretry(struct cx18 *cx, u16 addr);
diff --git a/linux/drivers/media/video/cx18/cx18-av-firmware.c b/linux/drivers/media/video/cx18/cx18-av-firmware.c
index 522a035b2..924691dca 100644
--- a/linux/drivers/media/video/cx18/cx18-av-firmware.c
+++ b/linux/drivers/media/video/cx18/cx18-av-firmware.c
@@ -43,11 +43,13 @@ int cx18_av_loadfw(struct cx18 *cx)
/* The firmware load often has byte errors, so allow for several
retries, both at byte level and at the firmware load level. */
while (retries1 < 5) {
- cx18_av_write4(cx, CXADEC_CHIP_CTRL, 0x00010000);
- cx18_av_write(cx, CXADEC_STD_DET_CTL, 0xf6);
+ cx18_av_write4_expect(cx, CXADEC_CHIP_CTRL, 0x00010000,
+ 0x00008430, 0xffffffff); /* cx25843 */
+ cx18_av_write_expect(cx, CXADEC_STD_DET_CTL, 0xf6, 0xf6, 0xff);
- /* Reset the Mako core (Register is undocumented.) */
- cx18_av_write4(cx, 0x8100, 0x00010000);
+ /* Reset the Mako core, Register is alias of CXADEC_CHIP_CTRL */
+ cx18_av_write4_expect(cx, 0x8100, 0x00010000,
+ 0x00008430, 0xffffffff); /* cx25843 */
/* Put the 8051 in reset and enable firmware upload */
cx18_av_write4_noretry(cx, CXADEC_DL_CTL, 0x0F000000);
@@ -61,7 +63,7 @@ int cx18_av_loadfw(struct cx18 *cx)
int retries2;
int unrec_err = 0;
- for (retries2 = 0; retries2 < CX18_MAX_MMIO_RETRIES;
+ for (retries2 = 0; retries2 < CX18_MAX_MMIO_WR_RETRIES;
retries2++) {
cx18_av_write4_noretry(cx, CXADEC_DL_CTL,
dl_control);
@@ -80,7 +82,7 @@ int cx18_av_loadfw(struct cx18 *cx)
}
cx18_log_write_retries(cx, retries2,
cx->reg_mem + 0xc40000 + CXADEC_DL_CTL);
- if (unrec_err || retries2 >= CX18_MAX_MMIO_RETRIES)
+ if (unrec_err || retries2 >= CX18_MAX_MMIO_WR_RETRIES)
break;
}
if (i == size)
@@ -93,7 +95,8 @@ int cx18_av_loadfw(struct cx18 *cx)
return -EIO;
}
- cx18_av_write4(cx, CXADEC_DL_CTL, 0x13000000 | fw->size);
+ cx18_av_write4_expect(cx, CXADEC_DL_CTL,
+ 0x13000000 | fw->size, 0x13000000, 0x13000000);
/* Output to the 416 */
cx18_av_and_or4(cx, CXADEC_PIN_CTRL1, ~0, 0x78000);
@@ -118,7 +121,8 @@ int cx18_av_loadfw(struct cx18 *cx)
passthrough */
cx18_av_write4(cx, CXADEC_PIN_CFG3, 0x5000B687);
- cx18_av_write4(cx, CXADEC_STD_DET_CTL, 0x000000F6);
+ cx18_av_write4_expect(cx, CXADEC_STD_DET_CTL, 0x000000F6, 0x000000F6,
+ 0x3F00FFFF);
/* CxDevWrReg(CXADEC_STD_DET_CTL, 0x000000FF); */
/* Set bit 0 in register 0x9CC to signify that this is MiniMe. */
@@ -136,7 +140,7 @@ int cx18_av_loadfw(struct cx18 *cx)
v |= 0xFF; /* Auto by default */
v |= 0x400; /* Stereo by default */
v |= 0x14000000;
- cx18_av_write4(cx, CXADEC_STD_DET_CTL, v);
+ cx18_av_write4_expect(cx, CXADEC_STD_DET_CTL, v, v, 0x3F00FFFF);
release_firmware(fw);
diff --git a/linux/drivers/media/video/cx18/cx18-driver.c b/linux/drivers/media/video/cx18/cx18-driver.c
index 085121c2b..54f0fde42 100644
--- a/linux/drivers/media/video/cx18/cx18-driver.c
+++ b/linux/drivers/media/video/cx18/cx18-driver.c
@@ -187,7 +187,7 @@ MODULE_VERSION(CX18_VERSION);
/* Generic utility functions */
int cx18_msleep_timeout(unsigned int msecs, int intr)
{
- int timeout = msecs_to_jiffies(msecs);
+ long int timeout = msecs_to_jiffies(msecs);
int sig;
do {
@@ -446,9 +446,16 @@ static int __devinit cx18_init_struct1(struct cx18 *cx)
mutex_init(&cx->i2c_bus_lock[0]);
mutex_init(&cx->i2c_bus_lock[1]);
mutex_init(&cx->gpio_lock);
+ mutex_init(&cx->epu2apu_mb_lock);
+ mutex_init(&cx->epu2cpu_mb_lock);
spin_lock_init(&cx->lock);
- spin_lock_init(&cx->dma_reg_lock);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
+ INIT_WORK(&cx->work, cx18_work_handler);
+#else
+ INIT_WORK(&cx->work, cx18_work_handler, cx);
+#endif
/* start counting open_id at 1 */
cx->open_id = 1;
@@ -465,8 +472,6 @@ static int __devinit cx18_init_struct1(struct cx18 *cx)
init_waitqueue_head(&cx->cap_w);
init_waitqueue_head(&cx->mb_apu_waitq);
init_waitqueue_head(&cx->mb_cpu_waitq);
- init_waitqueue_head(&cx->mb_epu_waitq);
- init_waitqueue_head(&cx->mb_hpu_waitq);
init_waitqueue_head(&cx->dma_waitq);
/* VBI */
@@ -581,10 +586,10 @@ static void cx18_load_and_init_modules(struct cx18 *cx)
#ifdef MODULE
/* load modules */
-#ifndef CONFIG_MEDIA_TUNER
+#ifdef CONFIG_MEDIA_TUNER_MODULE
hw = cx18_request_module(cx, hw, "tuner", CX18_HW_TUNER);
#endif
-#ifndef CONFIG_VIDEO_CS5345
+#ifdef CONFIG_VIDEO_CS5345_MODULE
hw = cx18_request_module(cx, hw, "cs5345", CX18_HW_CS5345);
#endif
#endif
@@ -613,6 +618,7 @@ static int __devinit cx18_probe(struct pci_dev *dev,
const struct pci_device_id *pci_id)
{
int retval = 0;
+ int i;
int vbi_buf_size;
u32 devtype;
struct cx18 *cx;
@@ -698,7 +704,8 @@ static int __devinit cx18_probe(struct pci_dev *dev,
/* active i2c */
CX18_DEBUG_INFO("activating i2c...\n");
- if (init_cx18_i2c(cx)) {
+ retval = init_cx18_i2c(cx);
+ if (retval) {
CX18_ERR("Could not initialize i2c\n");
goto free_map;
}
@@ -730,8 +737,6 @@ static int __devinit cx18_probe(struct pci_dev *dev,
cx->std = V4L2_STD_NTSC_M;
if (cx->options.tuner == -1) {
- int i;
-
for (i = 0; i < CX18_CARD_MAX_TUNERS; i++) {
if ((cx->std & cx->card->tuners[i].std) == 0)
continue;
@@ -836,8 +841,11 @@ err:
CX18_ERR("Error %d on initialization\n", retval);
cx18_log_statistics(cx);
- kfree(cx18_cards[cx18_cards_active]);
- cx18_cards[cx18_cards_active] = NULL;
+ i = cx->num;
+ spin_lock(&cx18_cards_lock);
+ kfree(cx18_cards[i]);
+ cx18_cards[i] = NULL;
+ spin_unlock(&cx18_cards_lock);
return retval;
}
@@ -927,6 +935,8 @@ static void cx18_remove(struct pci_dev *pci_dev)
cx18_halt_firmware(cx);
+ flush_scheduled_work();
+
cx18_streams_cleanup(cx, 1);
exit_cx18_i2c(cx);
diff --git a/linux/drivers/media/video/cx18/cx18-driver.h b/linux/drivers/media/video/cx18/cx18-driver.h
index fa8be0731..ce7680675 100644
--- a/linux/drivers/media/video/cx18/cx18-driver.h
+++ b/linux/drivers/media/video/cx18/cx18-driver.h
@@ -41,6 +41,7 @@
#include <linux/pagemap.h>
#include <linux/workqueue.h>
#include <linux/mutex.h>
+#include <asm/byteorder.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
@@ -198,12 +199,14 @@ struct cx18_options {
#define CX18_F_S_APPL_IO 8 /* this stream is used read/written by an application */
/* per-cx18, i_flags */
-#define CX18_F_I_LOADED_FW 0 /* Loaded the firmware the first time */
-#define CX18_F_I_EOS 4 /* End of encoder stream reached */
-#define CX18_F_I_RADIO_USER 5 /* The radio tuner is selected */
-#define CX18_F_I_ENC_PAUSED 13 /* the encoder is paused */
-#define CX18_F_I_INITED 21 /* set after first open */
-#define CX18_F_I_FAILED 22 /* set if first open failed */
+#define CX18_F_I_LOADED_FW 0 /* Loaded firmware 1st time */
+#define CX18_F_I_EOS 4 /* End of encoder stream */
+#define CX18_F_I_RADIO_USER 5 /* radio tuner is selected */
+#define CX18_F_I_ENC_PAUSED 13 /* the encoder is paused */
+#define CX18_F_I_HAVE_WORK 15 /* there is work to be done */
+#define CX18_F_I_WORK_HANDLER_DVB 18 /* work to be done for DVB */
+#define CX18_F_I_INITED 21 /* set after first open */
+#define CX18_F_I_FAILED 22 /* set if first open failed */
/* These are the VBI types as they appear in the embedded VBI private packets. */
#define CX18_SLICED_TYPE_TELETEXT_B (1)
@@ -349,11 +352,18 @@ struct cx18_i2c_algo_callback_data {
int bus_index; /* 0 or 1 for the cx23418's 1st or 2nd I2C bus */
};
-#define CX18_MAX_MMIO_RETRIES 10
+#define CX18_MAX_MMIO_WR_RETRIES 10
+#define CX18_MAX_MMIO_RD_RETRIES 2
struct cx18_mmio_stats {
- atomic_t retried_write[CX18_MAX_MMIO_RETRIES+1];
- atomic_t retried_read[CX18_MAX_MMIO_RETRIES+1];
+ atomic_t retried_write[CX18_MAX_MMIO_WR_RETRIES+1];
+ atomic_t retried_read[CX18_MAX_MMIO_RD_RETRIES+1];
+};
+
+#define CX18_MAX_MB_ACK_DELAY 100
+
+struct cx18_mbox_stats {
+ atomic_t mb_ack_delay[CX18_MAX_MB_ACK_DELAY+1];
};
/* Struct to hold info about cx18 cards */
@@ -374,7 +384,10 @@ struct cx18 {
u32 v4l2_cap; /* V4L2 capabilities of card */
u32 hw_flags; /* Hardware description of the board */
unsigned mdl_offset;
- struct cx18_scb __iomem *scb; /* pointer to SCB */
+ struct cx18_scb __iomem *scb; /* pointer to SCB */
+ struct mutex epu2apu_mb_lock; /* protect driver to chip mailbox in SCB*/
+ struct mutex epu2cpu_mb_lock; /* protect driver to chip mailbox in SCB*/
+
struct cx18_av_state av_state;
@@ -401,8 +414,6 @@ struct cx18 {
spinlock_t lock; /* lock access to this struct */
int search_pack_header;
- spinlock_t dma_reg_lock; /* lock access to DMA engine registers */
-
int open_id; /* incremented each time an open occurs, used as
unique ID. Starts at 1, so 0 can be used as
uninitialized value in the stream->id. */
@@ -426,12 +437,12 @@ struct cx18 {
wait_queue_head_t mb_apu_waitq;
wait_queue_head_t mb_cpu_waitq;
- wait_queue_head_t mb_epu_waitq;
- wait_queue_head_t mb_hpu_waitq;
wait_queue_head_t cap_w;
/* when the current DMA is finished this queue is woken up */
wait_queue_head_t dma_waitq;
+ struct work_struct work;
+
/* i2c */
struct i2c_adapter i2c_adap[2];
struct i2c_algo_bit_data i2c_algo[2];
@@ -447,6 +458,7 @@ struct cx18 {
/* Statistics */
struct cx18_mmio_stats mmio_stats;
+ struct cx18_mbox_stats mbox_stats;
/* v4l2 and User settings */
diff --git a/linux/drivers/media/video/cx18/cx18-dvb.c b/linux/drivers/media/video/cx18/cx18-dvb.c
index afc694e7b..4845f732e 100644
--- a/linux/drivers/media/video/cx18/cx18-dvb.c
+++ b/linux/drivers/media/video/cx18/cx18-dvb.c
@@ -23,6 +23,8 @@
#include "cx18-dvb.h"
#include "cx18-io.h"
#include "cx18-streams.h"
+#include "cx18-queue.h"
+#include "cx18-scb.h"
#include "cx18-cards.h"
#include "s5h1409.h"
#include "mxl5005s.h"
@@ -107,20 +109,23 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed)
if (!demux->dmx.frontend)
return -EINVAL;
- if (stream) {
- mutex_lock(&stream->dvb.feedlock);
- if (stream->dvb.feeding++ == 0) {
- CX18_DEBUG_INFO("Starting Transport DMA\n");
- ret = cx18_start_v4l2_encode_stream(stream);
- if (ret < 0) {
- CX18_DEBUG_INFO(
- "Failed to start Transport DMA\n");
- stream->dvb.feeding--;
- }
- } else
- ret = 0;
- mutex_unlock(&stream->dvb.feedlock);
- }
+ if (!stream)
+ return -EINVAL;
+
+ mutex_lock(&stream->dvb.feedlock);
+ if (stream->dvb.feeding++ == 0) {
+ CX18_DEBUG_INFO("Starting Transport DMA\n");
+ set_bit(CX18_F_S_STREAMING, &stream->s_flags);
+ ret = cx18_start_v4l2_encode_stream(stream);
+ if (ret < 0) {
+ CX18_DEBUG_INFO("Failed to start Transport DMA\n");
+ stream->dvb.feeding--;
+ if (stream->dvb.feeding == 0)
+ clear_bit(CX18_F_S_STREAMING, &stream->s_flags);
+ }
+ } else
+ ret = 0;
+ mutex_unlock(&stream->dvb.feedlock);
return ret;
}
@@ -300,3 +305,26 @@ static int dvb_register(struct cx18_stream *stream)
return ret;
}
+
+void cx18_dvb_work_handler(struct cx18 *cx)
+{
+ struct cx18_buffer *buf;
+ struct cx18_stream *s = &cx->streams[CX18_ENC_STREAM_TYPE_TS];
+
+ while ((buf = cx18_dequeue(s, &s->q_full)) != NULL) {
+ if (s->dvb.enabled)
+ dvb_dmx_swfilter(&s->dvb.demux, buf->buf,
+ buf->bytesused);
+
+ cx18_buf_sync_for_device(s, buf);
+ cx18_enqueue(s, buf, &s->q_free);
+
+ if (s->handle == CX18_INVALID_TASK_HANDLE ||
+ !test_bit(CX18_F_S_STREAMING, &s->s_flags))
+ continue;
+
+ cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle,
+ (void __iomem *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem,
+ 1, buf->id, s->buf_size);
+ }
+}
diff --git a/linux/drivers/media/video/cx18/cx18-dvb.h b/linux/drivers/media/video/cx18/cx18-dvb.h
index bf8d8f6f5..bbdcefc87 100644
--- a/linux/drivers/media/video/cx18/cx18-dvb.h
+++ b/linux/drivers/media/video/cx18/cx18-dvb.h
@@ -23,3 +23,4 @@
int cx18_dvb_register(struct cx18_stream *stream);
void cx18_dvb_unregister(struct cx18_stream *stream);
+void cx18_dvb_work_handler(struct cx18 *cx);
diff --git a/linux/drivers/media/video/cx18/cx18-firmware.c b/linux/drivers/media/video/cx18/cx18-firmware.c
index 51534428c..d9c5f55ab 100644
--- a/linux/drivers/media/video/cx18/cx18-firmware.c
+++ b/linux/drivers/media/video/cx18/cx18-firmware.c
@@ -134,7 +134,8 @@ static int load_cpu_fw_direct(const char *fn, u8 __iomem *mem, struct cx18 *cx)
return size;
}
-static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx)
+static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx,
+ u32 *entry_addr)
{
const struct firmware *fw = NULL;
int i, j;
@@ -152,6 +153,7 @@ static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx)
return -ENOMEM;
}
+ *entry_addr = 0;
src = (const u32 *)fw->data;
vers = fw->data + sizeof(seghdr);
sz = fw->size;
@@ -168,10 +170,12 @@ static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx)
}
CX18_DEBUG_INFO("load segment %x-%x\n", seghdr.addr,
seghdr.addr + seghdr.size - 1);
+ if (*entry_addr == 0)
+ *entry_addr = seghdr.addr;
if (offset + seghdr.size > sz)
break;
for (i = 0; i < seghdr.size; i += 4096) {
- cx18_setup_page(cx, offset + i);
+ cx18_setup_page(cx, seghdr.addr + i);
for (j = i; j < seghdr.size && j < i + 4096; j += 4) {
/* no need for endianness conversion on the ppc */
cx18_raw_writel(cx, src[(offset + j) / 4],
@@ -192,16 +196,16 @@ static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx)
fn, apu_version, fw->size);
size = fw->size;
release_firmware(fw);
- /* Clear bit0 for APU to start from 0 */
- cx18_write_reg(cx, cx18_read_reg(cx, 0xc72030) & ~1, 0xc72030);
return size;
}
void cx18_halt_firmware(struct cx18 *cx)
{
CX18_DEBUG_INFO("Preparing for firmware halt.\n");
- cx18_write_reg(cx, 0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */
- cx18_write_reg(cx, 0x00020002, CX18_ADEC_CONTROL);
+ cx18_write_reg_expect(cx, 0x000F000F, CX18_PROC_SOFT_RESET,
+ 0x0000000F, 0x000F000F);
+ cx18_write_reg_expect(cx, 0x00020002, CX18_ADEC_CONTROL,
+ 0x00000002, 0x00020002);
}
void cx18_init_power(struct cx18 *cx, int lowpwr)
@@ -211,7 +215,8 @@ void cx18_init_power(struct cx18 *cx, int lowpwr)
cx18_write_reg(cx, 0x00000008, CX18_PLL_POWER_DOWN);
/* ADEC out of sleep */
- cx18_write_reg(cx, 0x00020000, CX18_ADEC_CONTROL);
+ cx18_write_reg_expect(cx, 0x00020000, CX18_ADEC_CONTROL,
+ 0x00000000, 0x00020002);
/* The fast clock is at 200/245 MHz */
cx18_write_reg(cx, lowpwr ? 0xD : 0x11, CX18_FAST_CLOCK_PLL_INT);
@@ -248,22 +253,34 @@ void cx18_init_power(struct cx18 *cx, int lowpwr)
/* VFC = disabled */
/* USB = disabled */
- cx18_write_reg(cx, lowpwr ? 0xFFFF0020 : 0x00060004,
- CX18_CLOCK_SELECT1);
- cx18_write_reg(cx, lowpwr ? 0xFFFF0004 : 0x00060006,
- CX18_CLOCK_SELECT2);
-
- cx18_write_reg(cx, 0xFFFF0002, CX18_HALF_CLOCK_SELECT1);
- cx18_write_reg(cx, 0xFFFF0104, CX18_HALF_CLOCK_SELECT2);
+ if (lowpwr) {
+ cx18_write_reg_expect(cx, 0xFFFF0020, CX18_CLOCK_SELECT1,
+ 0x00000020, 0xFFFFFFFF);
+ cx18_write_reg_expect(cx, 0xFFFF0004, CX18_CLOCK_SELECT2,
+ 0x00000004, 0xFFFFFFFF);
+ } else {
+ /* This doesn't explicitly set every clock select */
+ cx18_write_reg_expect(cx, 0x00060004, CX18_CLOCK_SELECT1,
+ 0x00000004, 0x00060006);
+ cx18_write_reg_expect(cx, 0x00060006, CX18_CLOCK_SELECT2,
+ 0x00000006, 0x00060006);
+ }
- cx18_write_reg(cx, 0xFFFF9026, CX18_CLOCK_ENABLE1);
- cx18_write_reg(cx, 0xFFFF3105, CX18_CLOCK_ENABLE2);
+ cx18_write_reg_expect(cx, 0xFFFF0002, CX18_HALF_CLOCK_SELECT1,
+ 0x00000002, 0xFFFFFFFF);
+ cx18_write_reg_expect(cx, 0xFFFF0104, CX18_HALF_CLOCK_SELECT2,
+ 0x00000104, 0xFFFFFFFF);
+ cx18_write_reg_expect(cx, 0xFFFF9026, CX18_CLOCK_ENABLE1,
+ 0x00009026, 0xFFFFFFFF);
+ cx18_write_reg_expect(cx, 0xFFFF3105, CX18_CLOCK_ENABLE2,
+ 0x00003105, 0xFFFFFFFF);
}
void cx18_init_memory(struct cx18 *cx)
{
cx18_msleep_timeout(10, 0);
- cx18_write_reg(cx, 0x10000, CX18_DDR_SOFT_RESET);
+ cx18_write_reg_expect(cx, 0x00010000, CX18_DDR_SOFT_RESET,
+ 0x00000000, 0x00010001);
cx18_msleep_timeout(10, 0);
cx18_write_reg(cx, cx->card->ddr.chip_config, CX18_DDR_CHIP_CONFIG);
@@ -282,13 +299,15 @@ void cx18_init_memory(struct cx18 *cx)
cx18_msleep_timeout(10, 0);
- cx18_write_reg(cx, 0x20000, CX18_DDR_SOFT_RESET);
+ cx18_write_reg_expect(cx, 0x00020000, CX18_DDR_SOFT_RESET,
+ 0x00000000, 0x00020002);
cx18_msleep_timeout(10, 0);
/* use power-down mode when idle */
cx18_write_reg(cx, 0x00000010, CX18_DDR_POWER_REG);
- cx18_write_reg(cx, 0x10001, CX18_REG_BUS_TIMEOUT_EN);
+ cx18_write_reg_expect(cx, 0x00010001, CX18_REG_BUS_TIMEOUT_EN,
+ 0x00000001, 0x00010001);
cx18_write_reg(cx, 0x48, CX18_DDR_MB_PER_ROW_7);
cx18_write_reg(cx, 0xE0000, CX18_DDR_BASE_63_ADDR);
@@ -310,7 +329,9 @@ int cx18_firmware_init(struct cx18 *cx)
/* Allow chip to control CLKRUN */
cx18_write_reg(cx, 0x5, CX18_DSP0_INTERRUPT_MASK);
- cx18_write_reg(cx, 0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */
+ /* Stop the firmware */
+ cx18_write_reg_expect(cx, 0x000F000F, CX18_PROC_SOFT_RESET,
+ 0x0000000F, 0x000F000F);
cx18_msleep_timeout(1, 0);
@@ -319,13 +340,22 @@ int cx18_firmware_init(struct cx18 *cx)
/* Only if the processor is not running */
if (cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 8) {
+ u32 fw_entry_addr = 0;
int sz = load_apu_fw_direct("v4l-cx23418-apu.fw",
- cx->enc_mem, cx);
+ cx->enc_mem, cx, &fw_entry_addr);
+
+ if (sz <= 0)
+ return sz;
+
+ /* Clear bit0 for APU to start from 0 */
+ cx18_write_reg(cx, cx18_read_reg(cx, 0xc72030) & ~1, 0xc72030);
+
+ cx18_write_enc(cx, 0xE51FF004, 0); /* ldr pc, [pc, #-4] */
+ cx18_write_enc(cx, fw_entry_addr, 4);
- cx18_write_enc(cx, 0xE51FF004, 0);
- cx18_write_enc(cx, 0xa00000, 4); /* todo: not hardcoded */
/* Start APU */
- cx18_write_reg(cx, 0x00010000, CX18_PROC_SOFT_RESET);
+ cx18_write_reg_expect(cx, 0x00010000, CX18_PROC_SOFT_RESET,
+ 0x00000000, 0x00010001);
cx18_msleep_timeout(500, 0);
sz = sz <= 0 ? sz : load_cpu_fw_direct("v4l-cx23418-cpu.fw",
@@ -335,7 +365,9 @@ int cx18_firmware_init(struct cx18 *cx)
int retries = 0;
/* start the CPU */
- cx18_write_reg(cx, 0x00080000, CX18_PROC_SOFT_RESET);
+ cx18_write_reg_expect(cx,
+ 0x00080000, CX18_PROC_SOFT_RESET,
+ 0x00000000, 0x00080008);
while (retries++ < 50) { /* Loop for max 500mS */
if ((cx18_read_reg(cx, CX18_PROC_SOFT_RESET)
& 1) == 0)
@@ -351,7 +383,18 @@ int cx18_firmware_init(struct cx18 *cx)
if (sz <= 0)
return -EIO;
}
+
+ /*
+ * The CPU firmware apparently sets up to receive an interrupt for it's
+ * outgoing IRQ_CPU_TO_EPU_ACK to us (*boggle*). We get an interrupt
+ * when it sends us an ack, but by the time we process it, that flag in
+ * the SW2 status register has been cleared by the CPU firmware.
+ * We'll prevent that not so useful behavior by clearing the CPU's
+ * interrupt enables for Ack IRQ's we want to process.
+ */
+ cx18_sw2_irq_disable_cpu(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
+
/* initialize GPIO */
- cx18_write_reg(cx, 0x14001400, 0xC78110);
+ cx18_write_reg_expect(cx, 0x14001400, 0xc78110, 0x00001400, 0x14001400);
return 0;
}
diff --git a/linux/drivers/media/video/cx18/cx18-gpio.c b/linux/drivers/media/video/cx18/cx18-gpio.c
index 0e5604219..17b7a32fc 100644
--- a/linux/drivers/media/video/cx18/cx18-gpio.c
+++ b/linux/drivers/media/video/cx18/cx18-gpio.c
@@ -47,15 +47,21 @@
static void gpio_write(struct cx18 *cx)
{
- u32 dir = cx->gpio_dir;
- u32 val = cx->gpio_val;
-
- cx18_write_reg(cx, (dir & 0xffff) << 16, CX18_REG_GPIO_DIR1);
- cx18_write_reg(cx, ((dir & 0xffff) << 16) | (val & 0xffff),
- CX18_REG_GPIO_OUT1);
- cx18_write_reg(cx, dir & 0xffff0000, CX18_REG_GPIO_DIR2);
- cx18_write_reg_sync(cx, (dir & 0xffff0000) | ((val & 0xffff0000) >> 16),
- CX18_REG_GPIO_OUT2);
+ u32 dir_lo = cx->gpio_dir & 0xffff;
+ u32 val_lo = cx->gpio_val & 0xffff;
+ u32 dir_hi = cx->gpio_dir >> 16;
+ u32 val_hi = cx->gpio_val >> 16;
+
+ cx18_write_reg_expect(cx, dir_lo << 16,
+ CX18_REG_GPIO_DIR1, ~dir_lo, dir_lo);
+ cx18_write_reg_expect(cx, (dir_lo << 16) | val_lo,
+ CX18_REG_GPIO_OUT1, val_lo, dir_lo);
+ cx18_write_reg_expect(cx, dir_hi << 16,
+ CX18_REG_GPIO_DIR2, ~dir_hi, dir_hi);
+ cx18_write_reg_expect(cx, (dir_hi << 16) | val_hi,
+ CX18_REG_GPIO_OUT2, val_hi, dir_hi);
+ if (!cx18_retry_mmio)
+ (void) cx18_read_reg(cx, CX18_REG_GPIO_OUT2); /* sync */
}
void cx18_reset_i2c_slaves_gpio(struct cx18 *cx)
diff --git a/linux/drivers/media/video/cx18/cx18-i2c.c b/linux/drivers/media/video/cx18/cx18-i2c.c
index f28a1ff2e..1af9ea149 100644
--- a/linux/drivers/media/video/cx18/cx18-i2c.c
+++ b/linux/drivers/media/video/cx18/cx18-i2c.c
@@ -27,6 +27,7 @@
#include "cx18-gpio.h"
#include "cx18-av-core.h"
#include "cx18-i2c.h"
+#include "cx18-irq.h"
#define CX18_REG_I2C_1_WR 0xf15000
#define CX18_REG_I2C_1_RD 0xf15008
@@ -424,22 +425,31 @@ int init_cx18_i2c(struct cx18 *cx)
if (cx18_read_reg(cx, CX18_REG_I2C_2_WR) != 0x0003c02f) {
/* Reset/Unreset I2C hardware block */
/* Clock select 220MHz */
- cx18_write_reg(cx, 0x10000000, 0xc71004);
+ cx18_write_reg_expect(cx, 0x10000000, 0xc71004,
+ 0x00000000, 0x10001000);
/* Clock Enable */
- cx18_write_reg_sync(cx, 0x10001000, 0xc71024);
+ cx18_write_reg_expect(cx, 0x10001000, 0xc71024,
+ 0x00001000, 0x10001000);
}
/* courtesy of Steven Toth <stoth@hauppauge.com> */
- cx18_write_reg_sync(cx, 0x00c00000, 0xc7001c);
+ cx18_write_reg_expect(cx, 0x00c00000, 0xc7001c, 0x00000000, 0x00c000c0);
+ if (!cx18_retry_mmio)
+ (void) cx18_read_reg(cx, 0xc7001c); /* sync */
mdelay(10);
- cx18_write_reg_sync(cx, 0x00c000c0, 0xc7001c);
+ cx18_write_reg_expect(cx, 0x00c000c0, 0xc7001c, 0x000000c0, 0x00c000c0);
+ if (!cx18_retry_mmio)
+ (void) cx18_read_reg(cx, 0xc7001c); /* sync */
mdelay(10);
- cx18_write_reg_sync(cx, 0x00c00000, 0xc7001c);
+ cx18_write_reg_expect(cx, 0x00c00000, 0xc7001c, 0x00000000, 0x00c000c0);
+ if (!cx18_retry_mmio)
+ (void) cx18_read_reg(cx, 0xc7001c); /* sync */
mdelay(10);
/* Set to edge-triggered intrs. */
- cx18_write_reg_sync(cx, 0x00c00000, 0xc730c8);
+ cx18_write_reg(cx, 0x00c00000, 0xc730c8);
/* Clear any stale intrs */
- cx18_write_reg_sync(cx, 0x00c00000, 0xc730c4);
+ cx18_write_reg_expect(cx, HW2_I2C1_INT|HW2_I2C2_INT, HW2_INT_CLR_STATUS,
+ ~(HW2_I2C1_INT|HW2_I2C2_INT), HW2_I2C1_INT|HW2_I2C2_INT);
/* Hw I2C1 Clock Freq ~100kHz */
cx18_write_reg_sync(cx, 0x00021c0f & ~4, CX18_REG_I2C_1_WR);
diff --git a/linux/drivers/media/video/cx18/cx18-io.c b/linux/drivers/media/video/cx18/cx18-io.c
index 700ab9439..3c6485fce 100644
--- a/linux/drivers/media/video/cx18/cx18-io.c
+++ b/linux/drivers/media/video/cx18/cx18-io.c
@@ -31,19 +31,23 @@ void cx18_log_statistics(struct cx18 *cx)
if (!(cx18_debug & CX18_DBGFLG_INFO))
return;
- for (i = 0; i <= CX18_MAX_MMIO_RETRIES; i++)
+ for (i = 0; i <= CX18_MAX_MMIO_WR_RETRIES; i++)
CX18_DEBUG_INFO("retried_write[%d] = %d\n", i,
atomic_read(&cx->mmio_stats.retried_write[i]));
- for (i = 0; i <= CX18_MAX_MMIO_RETRIES; i++)
+ for (i = 0; i <= CX18_MAX_MMIO_RD_RETRIES; i++)
CX18_DEBUG_INFO("retried_read[%d] = %d\n", i,
atomic_read(&cx->mmio_stats.retried_read[i]));
+ for (i = 0; i <= CX18_MAX_MB_ACK_DELAY; i++)
+ if (atomic_read(&cx->mbox_stats.mb_ack_delay[i]))
+ CX18_DEBUG_INFO("mb_ack_delay[%d] = %d\n", i,
+ atomic_read(&cx->mbox_stats.mb_ack_delay[i]));
return;
}
void cx18_raw_writel_retry(struct cx18 *cx, u32 val, void __iomem *addr)
{
int i;
- for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
+ for (i = 0; i < CX18_MAX_MMIO_WR_RETRIES; i++) {
cx18_raw_writel_noretry(cx, val, addr);
if (val == cx18_raw_readl_noretry(cx, addr))
break;
@@ -55,7 +59,7 @@ u32 cx18_raw_readl_retry(struct cx18 *cx, const void __iomem *addr)
{
int i;
u32 val;
- for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
+ for (i = 0; i < CX18_MAX_MMIO_RD_RETRIES; i++) {
val = cx18_raw_readl_noretry(cx, addr);
if (val != 0xffffffff) /* PCI bus read error */
break;
@@ -68,7 +72,7 @@ u16 cx18_raw_readw_retry(struct cx18 *cx, const void __iomem *addr)
{
int i;
u16 val;
- for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
+ for (i = 0; i < CX18_MAX_MMIO_RD_RETRIES; i++) {
val = cx18_raw_readw_noretry(cx, addr);
if (val != 0xffff) /* PCI bus read error */
break;
@@ -80,7 +84,7 @@ u16 cx18_raw_readw_retry(struct cx18 *cx, const void __iomem *addr)
void cx18_writel_retry(struct cx18 *cx, u32 val, void __iomem *addr)
{
int i;
- for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
+ for (i = 0; i < CX18_MAX_MMIO_WR_RETRIES; i++) {
cx18_writel_noretry(cx, val, addr);
if (val == cx18_readl_noretry(cx, addr))
break;
@@ -88,10 +92,23 @@ void cx18_writel_retry(struct cx18 *cx, u32 val, void __iomem *addr)
cx18_log_write_retries(cx, i, addr);
}
+void _cx18_writel_expect(struct cx18 *cx, u32 val, void __iomem *addr,
+ u32 eval, u32 mask)
+{
+ int i;
+ eval &= mask;
+ for (i = 0; i < CX18_MAX_MMIO_WR_RETRIES; i++) {
+ cx18_writel_noretry(cx, val, addr);
+ if (eval == (cx18_readl_noretry(cx, addr) & mask))
+ break;
+ }
+ cx18_log_write_retries(cx, i, addr);
+}
+
void cx18_writew_retry(struct cx18 *cx, u16 val, void __iomem *addr)
{
int i;
- for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
+ for (i = 0; i < CX18_MAX_MMIO_WR_RETRIES; i++) {
cx18_writew_noretry(cx, val, addr);
if (val == cx18_readw_noretry(cx, addr))
break;
@@ -102,7 +119,7 @@ void cx18_writew_retry(struct cx18 *cx, u16 val, void __iomem *addr)
void cx18_writeb_retry(struct cx18 *cx, u8 val, void __iomem *addr)
{
int i;
- for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
+ for (i = 0; i < CX18_MAX_MMIO_WR_RETRIES; i++) {
cx18_writeb_noretry(cx, val, addr);
if (val == cx18_readb_noretry(cx, addr))
break;
@@ -114,7 +131,7 @@ u32 cx18_readl_retry(struct cx18 *cx, const void __iomem *addr)
{
int i;
u32 val;
- for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
+ for (i = 0; i < CX18_MAX_MMIO_RD_RETRIES; i++) {
val = cx18_readl_noretry(cx, addr);
if (val != 0xffffffff) /* PCI bus read error */
break;
@@ -127,7 +144,7 @@ u16 cx18_readw_retry(struct cx18 *cx, const void __iomem *addr)
{
int i;
u16 val;
- for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
+ for (i = 0; i < CX18_MAX_MMIO_RD_RETRIES; i++) {
val = cx18_readw_noretry(cx, addr);
if (val != 0xffff) /* PCI bus read error */
break;
@@ -140,7 +157,7 @@ u8 cx18_readb_retry(struct cx18 *cx, const void __iomem *addr)
{
int i;
u8 val;
- for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
+ for (i = 0; i < CX18_MAX_MMIO_RD_RETRIES; i++) {
val = cx18_readb_noretry(cx, addr);
if (val != 0xff) /* PCI bus read error */
break;
@@ -218,7 +235,7 @@ void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count)
void cx18_sw1_irq_enable(struct cx18 *cx, u32 val)
{
u32 r;
- cx18_write_reg(cx, val, SW1_INT_STATUS);
+ cx18_write_reg_expect(cx, val, SW1_INT_STATUS, ~val, val);
r = cx18_read_reg(cx, SW1_INT_ENABLE_PCI);
cx18_write_reg(cx, r | val, SW1_INT_ENABLE_PCI);
}
@@ -233,7 +250,7 @@ void cx18_sw1_irq_disable(struct cx18 *cx, u32 val)
void cx18_sw2_irq_enable(struct cx18 *cx, u32 val)
{
u32 r;
- cx18_write_reg(cx, val, SW2_INT_STATUS);
+ cx18_write_reg_expect(cx, val, SW2_INT_STATUS, ~val, val);
r = cx18_read_reg(cx, SW2_INT_ENABLE_PCI);
cx18_write_reg(cx, r | val, SW2_INT_ENABLE_PCI);
}
@@ -245,6 +262,13 @@ void cx18_sw2_irq_disable(struct cx18 *cx, u32 val)
cx18_write_reg(cx, r & ~val, SW2_INT_ENABLE_PCI);
}
+void cx18_sw2_irq_disable_cpu(struct cx18 *cx, u32 val)
+{
+ u32 r;
+ r = cx18_read_reg(cx, SW2_INT_ENABLE_CPU);
+ cx18_write_reg(cx, r & ~val, SW2_INT_ENABLE_CPU);
+}
+
void cx18_setup_page(struct cx18 *cx, u32 addr)
{
u32 val;
diff --git a/linux/drivers/media/video/cx18/cx18-io.h b/linux/drivers/media/video/cx18/cx18-io.h
index 197d4fbd9..4486b73fa 100644
--- a/linux/drivers/media/video/cx18/cx18-io.h
+++ b/linux/drivers/media/video/cx18/cx18-io.h
@@ -39,19 +39,19 @@ static inline void cx18_io_delay(struct cx18 *cx)
/* Statistics gathering */
static inline
-void cx18_log_write_retries(struct cx18 *cx, int i, const void *addr)
+void cx18_log_write_retries(struct cx18 *cx, int i, const void __iomem *addr)
{
- if (i > CX18_MAX_MMIO_RETRIES)
- i = CX18_MAX_MMIO_RETRIES;
+ if (i > CX18_MAX_MMIO_WR_RETRIES)
+ i = CX18_MAX_MMIO_WR_RETRIES;
atomic_inc(&cx->mmio_stats.retried_write[i]);
return;
}
static inline
-void cx18_log_read_retries(struct cx18 *cx, int i, const void *addr)
+void cx18_log_read_retries(struct cx18 *cx, int i, const void __iomem *addr)
{
- if (i > CX18_MAX_MMIO_RETRIES)
- i = CX18_MAX_MMIO_RETRIES;
+ if (i > CX18_MAX_MMIO_RD_RETRIES)
+ i = CX18_MAX_MMIO_RD_RETRIES;
atomic_inc(&cx->mmio_stats.retried_read[i]);
return;
}
@@ -133,6 +133,8 @@ static inline void cx18_writel(struct cx18 *cx, u32 val, void __iomem *addr)
cx18_writel_noretry(cx, val, addr);
}
+void _cx18_writel_expect(struct cx18 *cx, u32 val, void __iomem *addr,
+ u32 eval, u32 mask);
static inline
void cx18_writew_noretry(struct cx18 *cx, u16 val, void __iomem *addr)
@@ -271,6 +273,21 @@ static inline void cx18_write_reg(struct cx18 *cx, u32 val, u32 reg)
cx18_write_reg_noretry(cx, val, reg);
}
+static inline void _cx18_write_reg_expect(struct cx18 *cx, u32 val, u32 reg,
+ u32 eval, u32 mask)
+{
+ _cx18_writel_expect(cx, val, cx->reg_mem + reg, eval, mask);
+}
+
+static inline void cx18_write_reg_expect(struct cx18 *cx, u32 val, u32 reg,
+ u32 eval, u32 mask)
+{
+ if (cx18_retry_mmio)
+ _cx18_write_reg_expect(cx, val, reg, eval, mask);
+ else
+ cx18_write_reg_noretry(cx, val, reg);
+}
+
static inline u32 cx18_read_reg_noretry(struct cx18 *cx, u32 reg)
{
@@ -373,6 +390,7 @@ void cx18_sw1_irq_enable(struct cx18 *cx, u32 val);
void cx18_sw1_irq_disable(struct cx18 *cx, u32 val);
void cx18_sw2_irq_enable(struct cx18 *cx, u32 val);
void cx18_sw2_irq_disable(struct cx18 *cx, u32 val);
+void cx18_sw2_irq_disable_cpu(struct cx18 *cx, u32 val);
void cx18_setup_page(struct cx18 *cx, u32 addr);
#endif /* CX18_IO_H */
diff --git a/linux/drivers/media/video/cx18/cx18-irq.c b/linux/drivers/media/video/cx18/cx18-irq.c
index 85a56974b..3e23fc350 100644
--- a/linux/drivers/media/video/cx18/cx18-irq.c
+++ b/linux/drivers/media/video/cx18/cx18-irq.c
@@ -29,10 +29,22 @@
#include "cx18-mailbox.h"
#include "cx18-vbi.h"
#include "cx18-scb.h"
+#include "cx18-dvb.h"
-#define DMA_MAGIC_COOKIE 0x000001fe
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
+void cx18_work_handler(struct work_struct *work)
+{
+ struct cx18 *cx = container_of(work, struct cx18, work);
+#else
+void cx18_work_handler(void *arg)
+{
+ struct cx18 *cx = arg;
+#endif
+ if (test_and_clear_bit(CX18_F_I_WORK_HANDLER_DVB, &cx->i_flags))
+ cx18_dvb_work_handler(cx);
+}
-static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb)
+static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb, int rpu)
{
u32 handle = mb->args[0];
struct cx18_stream *s = NULL;
@@ -53,7 +65,7 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb)
" handle %d\n", handle);
mb->error = CXERR_NOT_OPEN;
mb->cmd = 0;
- cx18_mb_ack(cx, mb);
+ cx18_mb_ack(cx, mb, rpu);
return;
}
@@ -67,17 +79,11 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb)
if (buf) {
cx18_buf_sync_for_cpu(s, buf);
if (s->type == CX18_ENC_STREAM_TYPE_TS && s->dvb.enabled) {
- /* process the buffer here */
- CX18_DEBUG_HI_DMA("TS recv and sent bytesused=%d\n",
+ CX18_DEBUG_HI_DMA("TS recv bytesused = %d\n",
buf->bytesused);
- dvb_dmx_swfilter(&s->dvb.demux, buf->buf,
- buf->bytesused);
-
- cx18_buf_sync_for_device(s, buf);
- cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle,
- (void __iomem *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem,
- 1, buf->id, s->buf_size);
+ set_bit(CX18_F_I_WORK_HANDLER_DVB, &cx->i_flags);
+ set_bit(CX18_F_I_HAVE_WORK, &cx->i_flags);
} else
set_bit(CX18_F_B_NEED_BUF_SWAP, &buf->b_flags);
} else {
@@ -86,13 +92,13 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb)
}
mb->error = 0;
mb->cmd = 0;
- cx18_mb_ack(cx, mb);
+ cx18_mb_ack(cx, mb, rpu);
wake_up(&cx->dma_waitq);
if (s->id != -1)
wake_up(&s->waitq);
}
-static void epu_debug(struct cx18 *cx, struct cx18_mailbox *mb)
+static void epu_debug(struct cx18 *cx, struct cx18_mailbox *mb, int rpu)
{
char str[256] = { 0 };
char *p;
@@ -102,14 +108,14 @@ static void epu_debug(struct cx18 *cx, struct cx18_mailbox *mb)
cx18_memcpy_fromio(cx, str, cx->enc_mem + mb->args[1], 252);
str[252] = 0;
}
- cx18_mb_ack(cx, mb);
+ cx18_mb_ack(cx, mb, rpu);
CX18_DEBUG_INFO("%x %s\n", mb->args[0], str);
p = strchr(str, '.');
if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags) && p && p > str)
CX18_INFO("FW version: %s\n", p - 1);
}
-static void hpu_cmd(struct cx18 *cx, u32 sw1)
+static void epu_cmd(struct cx18 *cx, u32 sw1)
{
struct cx18_mailbox mb;
@@ -119,18 +125,30 @@ static void hpu_cmd(struct cx18 *cx, u32 sw1)
switch (mb.cmd) {
case CX18_EPU_DMA_DONE:
- epu_dma_done(cx, &mb);
+ epu_dma_done(cx, &mb, CPU);
break;
case CX18_EPU_DEBUG:
- epu_debug(cx, &mb);
+ epu_debug(cx, &mb, CPU);
break;
default:
- CX18_WARN("Unexpected mailbox command %08x\n", mb.cmd);
+ CX18_WARN("Unknown CPU_TO_EPU mailbox command %#08x\n",
+ mb.cmd);
break;
}
}
- if (sw1 & (IRQ_APU_TO_EPU | IRQ_HPU_TO_EPU))
- CX18_WARN("Unexpected interrupt %08x\n", sw1);
+
+ if (sw1 & IRQ_APU_TO_EPU) {
+ cx18_memcpy_fromio(cx, &mb, &cx->scb->apu2epu_mb, sizeof(mb));
+ CX18_WARN("Unknown APU_TO_EPU mailbox command %#08x\n", mb.cmd);
+ }
+}
+
+static void xpu_ack(struct cx18 *cx, u32 sw2)
+{
+ if (sw2 & IRQ_CPU_TO_EPU_ACK)
+ wake_up(&cx->mb_cpu_waitq);
+ if (sw2 & IRQ_APU_TO_EPU_ACK)
+ wake_up(&cx->mb_apu_waitq);
}
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
@@ -144,43 +162,37 @@ irqreturn_t cx18_irq_handler(int irq, void *dev_id)
u32 sw2, sw2_mask;
u32 hw2, hw2_mask;
- spin_lock(&cx->dma_reg_lock);
-
+ sw1_mask = cx18_read_reg(cx, SW1_INT_ENABLE_PCI);
+ sw1 = cx18_read_reg(cx, SW1_INT_STATUS) & sw1_mask;
+ sw2_mask = cx18_read_reg(cx, SW2_INT_ENABLE_PCI);
+ sw2 = cx18_read_reg(cx, SW2_INT_STATUS) & sw2_mask;
hw2_mask = cx18_read_reg(cx, HW2_INT_MASK5_PCI);
hw2 = cx18_read_reg(cx, HW2_INT_CLR_STATUS) & hw2_mask;
- sw2_mask = cx18_read_reg(cx, SW2_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU_ACK;
- sw2 = cx18_read_reg(cx, SW2_INT_STATUS) & sw2_mask;
- sw1_mask = cx18_read_reg(cx, SW1_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU;
- sw1 = cx18_read_reg(cx, SW1_INT_STATUS) & sw1_mask;
- cx18_write_reg(cx, sw2&sw2_mask, SW2_INT_STATUS);
- cx18_write_reg(cx, sw1&sw1_mask, SW1_INT_STATUS);
- cx18_write_reg(cx, hw2&hw2_mask, HW2_INT_CLR_STATUS);
+ if (sw1)
+ cx18_write_reg_expect(cx, sw1, SW1_INT_STATUS, ~sw1, sw1);
+ if (sw2)
+ cx18_write_reg_expect(cx, sw2, SW2_INT_STATUS, ~sw2, sw2);
+ if (hw2)
+ cx18_write_reg_expect(cx, hw2, HW2_INT_CLR_STATUS, ~hw2, hw2);
if (sw1 || sw2 || hw2)
- CX18_DEBUG_HI_IRQ("SW1: %x SW2: %x HW2: %x\n", sw1, sw2, hw2);
+ CX18_DEBUG_HI_IRQ("received interrupts "
+ "SW1: %x SW2: %x HW2: %x\n", sw1, sw2, hw2);
/* To do: interrupt-based I2C handling
- if (hw2 & 0x00c00000) {
+ if (hw2 & (HW2_I2C1_INT|HW2_I2C2_INT)) {
}
*/
- if (sw2) {
- if (sw2 & (cx18_readl(cx, &cx->scb->cpu2hpu_irq_ack) |
- cx18_readl(cx, &cx->scb->cpu2epu_irq_ack)))
- wake_up(&cx->mb_cpu_waitq);
- if (sw2 & (cx18_readl(cx, &cx->scb->apu2hpu_irq_ack) |
- cx18_readl(cx, &cx->scb->apu2epu_irq_ack)))
- wake_up(&cx->mb_apu_waitq);
- if (sw2 & cx18_readl(cx, &cx->scb->epu2hpu_irq_ack))
- wake_up(&cx->mb_epu_waitq);
- if (sw2 & cx18_readl(cx, &cx->scb->hpu2epu_irq_ack))
- wake_up(&cx->mb_hpu_waitq);
- }
+ if (sw2)
+ xpu_ack(cx, sw2);
if (sw1)
- hpu_cmd(cx, sw1);
- spin_unlock(&cx->dma_reg_lock);
+ epu_cmd(cx, sw1);
+
+ if (test_and_clear_bit(CX18_F_I_HAVE_WORK, &cx->i_flags))
+ schedule_work(&cx->work);
- return (hw2 | sw1 | sw2) ? IRQ_HANDLED : IRQ_NONE;
+ return (sw1 || sw2 || hw2) ? IRQ_HANDLED : IRQ_NONE;
}
diff --git a/linux/drivers/media/video/cx18/cx18-irq.h b/linux/drivers/media/video/cx18/cx18-irq.h
index cbcd2022f..6472e42c6 100644
--- a/linux/drivers/media/video/cx18/cx18-irq.h
+++ b/linux/drivers/media/video/cx18/cx18-irq.h
@@ -28,6 +28,7 @@
#define SW1_INT_ENABLE_PCI 0xc7311c
#define SW2_INT_SET 0xc73140
#define SW2_INT_STATUS 0xc73144
+#define SW2_INT_ENABLE_CPU 0xc73158
#define SW2_INT_ENABLE_PCI 0xc7315c
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
@@ -36,6 +37,8 @@ irqreturn_t cx18_irq_handler(int irq, void *dev_id, struct pt_regs *regs);
irqreturn_t cx18_irq_handler(int irq, void *dev_id);
#endif
-void cx18_irq_work_handler(struct work_struct *work);
-void cx18_dma_stream_dec_prepare(struct cx18_stream *s, u32 offset, int lock);
-void cx18_unfinished_dma(unsigned long arg);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
+void cx18_work_handler(struct work_struct *work);
+#else
+void cx18_work_handler(void *arg);
+#endif
diff --git a/linux/drivers/media/video/cx18/cx18-mailbox.c b/linux/drivers/media/video/cx18/cx18-mailbox.c
index 9d18dd22d..35f7188d4 100644
--- a/linux/drivers/media/video/cx18/cx18-mailbox.c
+++ b/linux/drivers/media/video/cx18/cx18-mailbox.c
@@ -30,11 +30,6 @@
#define API_FAST (1 << 2) /* Short timeout */
#define API_SLOW (1 << 3) /* Additional 300ms timeout */
-#define APU 0
-#define CPU 1
-#define EPU 2
-#define HPU 3
-
struct cx18_api_info {
u32 cmd;
u8 flags; /* Flags, see above */
@@ -83,7 +78,7 @@ static const struct cx18_api_info api_info[] = {
API_ENTRY(CPU, CX18_CPU_DE_SET_MDL_ACK, 0),
API_ENTRY(CPU, CX18_CPU_DE_SET_MDL, API_FAST),
API_ENTRY(CPU, CX18_APU_RESETAI, API_FAST),
- API_ENTRY(CPU, CX18_CPU_DE_RELEASE_MDL, 0),
+ API_ENTRY(CPU, CX18_CPU_DE_RELEASE_MDL, API_SLOW),
API_ENTRY(0, 0, 0),
};
@@ -97,70 +92,12 @@ static const struct cx18_api_info *find_api_info(u32 cmd)
return NULL;
}
-static struct cx18_mailbox __iomem *cx18_mb_is_complete(struct cx18 *cx, int rpu,
- u32 *state, u32 *irq, u32 *req)
+long cx18_mb_ack(struct cx18 *cx, const struct cx18_mailbox *mb, int rpu)
{
- struct cx18_mailbox __iomem *mb = NULL;
- int wait_count = 0;
- u32 ack;
-
- switch (rpu) {
- case APU:
- mb = &cx->scb->epu2apu_mb;
- *state = cx18_readl(cx, &cx->scb->apu_state);
- *irq = cx18_readl(cx, &cx->scb->epu2apu_irq);
- break;
-
- case CPU:
- mb = &cx->scb->epu2cpu_mb;
- *state = cx18_readl(cx, &cx->scb->cpu_state);
- *irq = cx18_readl(cx, &cx->scb->epu2cpu_irq);
- break;
-
- case HPU:
- mb = &cx->scb->epu2hpu_mb;
- *state = cx18_readl(cx, &cx->scb->hpu_state);
- *irq = cx18_readl(cx, &cx->scb->epu2hpu_irq);
- break;
- }
-
- if (mb == NULL)
- return mb;
-
- do {
- *req = cx18_readl(cx, &mb->request);
- ack = cx18_readl(cx, &mb->ack);
- wait_count++;
- } while (*req != ack && wait_count < 600);
-
- if (*req == ack) {
- (*req)++;
- if (*req == 0 || *req == 0xffffffff)
- *req = 1;
- return mb;
- }
- return NULL;
-}
-
-long cx18_mb_ack(struct cx18 *cx, const struct cx18_mailbox *mb)
-{
- const struct cx18_api_info *info = find_api_info(mb->cmd);
struct cx18_mailbox __iomem *ack_mb;
u32 ack_irq;
- u8 rpu = CPU;
-
- if (info == NULL && mb->cmd) {
- CX18_WARN("Cannot ack unknown command %x\n", mb->cmd);
- return -EINVAL;
- }
- if (info)
- rpu = info->rpu;
switch (rpu) {
- case HPU:
- ack_irq = IRQ_EPU_TO_HPU_ACK;
- ack_mb = &cx->scb->hpu2epu_mb;
- break;
case APU:
ack_irq = IRQ_EPU_TO_APU_ACK;
ack_mb = &cx->scb->apu2epu_mb;
@@ -170,26 +107,33 @@ long cx18_mb_ack(struct cx18 *cx, const struct cx18_mailbox *mb)
ack_mb = &cx->scb->cpu2epu_mb;
break;
default:
- CX18_WARN("Unknown RPU for command %x\n", mb->cmd);
+ CX18_WARN("Unhandled RPU (%d) for command %x ack\n",
+ rpu, mb->cmd);
return -EINVAL;
}
cx18_setup_page(cx, SCB_OFFSET);
cx18_write_sync(cx, mb->request, &ack_mb->ack);
- cx18_write_reg(cx, ack_irq, SW2_INT_SET);
+ cx18_write_reg_expect(cx, ack_irq, SW2_INT_SET, ack_irq, ack_irq);
return 0;
}
+static void cx18_api_log_ack_delay(struct cx18 *cx, int msecs)
+{
+ if (msecs > CX18_MAX_MB_ACK_DELAY)
+ msecs = CX18_MAX_MB_ACK_DELAY;
+ atomic_inc(&cx->mbox_stats.mb_ack_delay[msecs]);
+}
static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[])
{
const struct cx18_api_info *info = find_api_info(cmd);
- u32 state = 0, irq = 0, req, oldreq, err;
+ u32 state, irq, req, ack, err;
struct cx18_mailbox __iomem *mb;
+ u32 __iomem *xpu_state;
wait_queue_head_t *waitq;
- int timeout = 100;
- int cnt = 0;
- int sig = 0;
+ struct mutex *mb_lock;
+ long int timeout, ret;
int i;
if (info == NULL) {
@@ -201,50 +145,116 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[])
CX18_DEBUG_HI_API("%s\n", info->name);
else
CX18_DEBUG_API("%s\n", info->name);
- cx18_setup_page(cx, SCB_OFFSET);
- mb = cx18_mb_is_complete(cx, info->rpu, &state, &irq, &req);
- if (mb == NULL) {
- CX18_ERR("mb %s busy\n", info->name);
- return -EBUSY;
+ switch (info->rpu) {
+ case APU:
+ waitq = &cx->mb_apu_waitq;
+ mb_lock = &cx->epu2apu_mb_lock;
+ irq = IRQ_EPU_TO_APU;
+ mb = &cx->scb->epu2apu_mb;
+ xpu_state = &cx->scb->apu_state;
+ break;
+ case CPU:
+ waitq = &cx->mb_cpu_waitq;
+ mb_lock = &cx->epu2cpu_mb_lock;
+ irq = IRQ_EPU_TO_CPU;
+ mb = &cx->scb->epu2cpu_mb;
+ xpu_state = &cx->scb->cpu_state;
+ break;
+ default:
+ CX18_WARN("Unknown RPU (%d) for API call\n", info->rpu);
+ return -EINVAL;
}
- oldreq = req - 1;
+ mutex_lock(mb_lock);
+ cx18_setup_page(cx, SCB_OFFSET);
+
+ /*
+ * Wait for an in-use mailbox to complete
+ *
+ * If the XPU is responding with Ack's, the mailbox shouldn't be in
+ * a busy state, since we serialize access to it on our end.
+ *
+ * If the wait for ack after sending a previous command was interrupted
+ * by a signal, we may get here and find a busy mailbox. After waiting,
+ * mark it "not busy" from our end, if the XPU hasn't ack'ed it still.
+ */
+ state = cx18_readl(cx, xpu_state);
+ req = cx18_readl(cx, &mb->request);
+ timeout = msecs_to_jiffies(20); /* 1 field at 50 Hz vertical refresh */
+ ret = wait_event_timeout(*waitq,
+ (ack = cx18_readl(cx, &mb->ack)) == req,
+ timeout);
+ if (req != ack) {
+ /* waited long enough, make the mbox "not busy" from our end */
+ cx18_writel(cx, req, &mb->ack);
+ CX18_ERR("mbox was found stuck busy when setting up for %s; "
+ "clearing busy and trying to proceed\n", info->name);
+ } else if (ret != timeout)
+ CX18_DEBUG_API("waited %u usecs for busy mbox to be acked\n",
+ jiffies_to_usecs(timeout-ret));
+
+ /* Build the outgoing mailbox */
+ req = ((req & 0xfffffffe) == 0xfffffffe) ? 1 : req + 1;
+
cx18_writel(cx, cmd, &mb->cmd);
for (i = 0; i < args; i++)
cx18_writel(cx, data[i], &mb->args[i]);
cx18_writel(cx, 0, &mb->error);
cx18_writel(cx, req, &mb->request);
-
- switch (info->rpu) {
- case APU: waitq = &cx->mb_apu_waitq; break;
- case CPU: waitq = &cx->mb_cpu_waitq; break;
- case EPU: waitq = &cx->mb_epu_waitq; break;
- case HPU: waitq = &cx->mb_hpu_waitq; break;
- default: return -EINVAL;
- }
- if (info->flags & API_FAST)
- timeout /= 2;
- cx18_write_reg(cx, irq, SW1_INT_SET);
-
- while (!sig && cx18_readl(cx, &mb->ack) != cx18_readl(cx, &mb->request)
- && cnt < 660) {
- if (cnt > 200 && !in_atomic())
- sig = cx18_msleep_timeout(10, 1);
- cnt++;
- }
- if (sig)
- return -EINTR;
- if (cnt == 660) {
- cx18_writel(cx, oldreq, &mb->request);
- CX18_ERR("mb %s failed\n", info->name);
+ cx18_writel(cx, req - 1, &mb->ack); /* ensure ack & req are distinct */
+
+ /*
+ * Notify the XPU and wait for it to send an Ack back
+ * 21 ms = ~ 0.5 frames at a frame rate of 24 fps
+ * 42 ms = ~ 1 frame at a frame rate of 24 fps
+ */
+ timeout = msecs_to_jiffies((info->flags & API_FAST) ? 21 : 42);
+
+ CX18_DEBUG_HI_IRQ("sending interrupt SW1: %x to send %s\n",
+ irq, info->name);
+ cx18_write_reg_expect(cx, irq, SW1_INT_SET, irq, irq);
+
+ ret = wait_event_timeout(
+ *waitq,
+ cx18_readl(cx, &mb->ack) == cx18_readl(cx, &mb->request),
+ timeout);
+ if (ret == 0) {
+ /* Timed out */
+ mutex_unlock(mb_lock);
+ i = jiffies_to_msecs(timeout);
+ cx18_api_log_ack_delay(cx, i);
+ CX18_WARN("sending %s timed out waiting %d msecs for RPU "
+ "acknowledgement\n", info->name, i);
return -EINVAL;
+ } else if (ret < 0) {
+ /* Interrupted */
+ mutex_unlock(mb_lock);
+ CX18_WARN("sending %s was interrupted waiting for RPU"
+ "acknowledgement\n", info->name);
+ return -EINTR;
}
+
+ i = jiffies_to_msecs(timeout-ret);
+ cx18_api_log_ack_delay(cx, i);
+ if (ret != timeout)
+ CX18_DEBUG_HI_API("waited %u msecs for %s to be acked\n",
+ i, info->name);
+
+ /* Collect data returned by the XPU */
for (i = 0; i < MAX_MB_ARGUMENTS; i++)
data[i] = cx18_readl(cx, &mb->args[i]);
err = cx18_readl(cx, &mb->error);
- if (!in_atomic() && (info->flags & API_SLOW))
+ mutex_unlock(mb_lock);
+
+ /*
+ * Wait for XPU to perform extra actions for the caller in some cases.
+ * e.g. CX18_CPU_DE_RELEASE_MDL will cause the CPU to send all buffers
+ * back in a burst shortly thereafter
+ */
+ if (info->flags & API_SLOW)
cx18_msleep_timeout(300, 0);
+
if (err)
CX18_DEBUG_API("mailbox error %08x for command %s\n", err,
info->name);
@@ -253,12 +263,7 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[])
int cx18_api(struct cx18 *cx, u32 cmd, int args, u32 data[])
{
- int res = cx18_api_call(cx, cmd, args, data);
-
- /* Allow a single retry, probably already too late though.
- If there is no free mailbox then that is usually an indication
- of a more serious problem. */
- return (res == -EBUSY) ? cx18_api_call(cx, cmd, args, data) : res;
+ return cx18_api_call(cx, cmd, args, data);
}
static int cx18_set_filter_param(struct cx18_stream *s)
diff --git a/linux/drivers/media/video/cx18/cx18-mailbox.h b/linux/drivers/media/video/cx18/cx18-mailbox.h
index d99564153..54758f32d 100644
--- a/linux/drivers/media/video/cx18/cx18-mailbox.h
+++ b/linux/drivers/media/video/cx18/cx18-mailbox.h
@@ -30,6 +30,11 @@
#define MB_RESERVED_HANDLE_0 0
#define MB_RESERVED_HANDLE_1 0xFFFFFFFF
+#define APU 0
+#define CPU 1
+#define EPU 2
+#define HPU 3
+
struct cx18;
/* The cx18_mailbox struct is the mailbox structure which is used for passing
@@ -68,6 +73,6 @@ int cx18_vapi_result(struct cx18 *cx, u32 data[MAX_MB_ARGUMENTS], u32 cmd,
int cx18_vapi(struct cx18 *cx, u32 cmd, int args, ...);
int cx18_api_func(void *priv, u32 cmd, int in, int out,
u32 data[CX2341X_MBOX_MAX_DATA]);
-long cx18_mb_ack(struct cx18 *cx, const struct cx18_mailbox *mb);
+long cx18_mb_ack(struct cx18 *cx, const struct cx18_mailbox *mb, int rpu);
#endif
diff --git a/linux/drivers/media/video/cx18/cx18-queue.c b/linux/drivers/media/video/cx18/cx18-queue.c
index a33ba04a2..174682c25 100644
--- a/linux/drivers/media/video/cx18/cx18-queue.c
+++ b/linux/drivers/media/video/cx18/cx18-queue.c
@@ -88,15 +88,13 @@ struct cx18_buffer *cx18_queue_get_buf_irq(struct cx18_stream *s, u32 id,
if (buf->id != id)
continue;
+
buf->bytesused = bytesused;
- /* the transport buffers are handled differently,
- they are not moved to the full queue */
- if (s->type != CX18_ENC_STREAM_TYPE_TS) {
- atomic_dec(&s->q_free.buffers);
- atomic_inc(&s->q_full.buffers);
- s->q_full.bytesused += buf->bytesused;
- list_move_tail(&buf->list, &s->q_full.list);
- }
+ atomic_dec(&s->q_free.buffers);
+ atomic_inc(&s->q_full.buffers);
+ s->q_full.bytesused += buf->bytesused;
+ list_move_tail(&buf->list, &s->q_full.list);
+
spin_unlock(&s->qlock);
return buf;
}
diff --git a/linux/drivers/media/video/cx18/cx18-scb.h b/linux/drivers/media/video/cx18/cx18-scb.h
index 86b4cb15d..594713bbe 100644
--- a/linux/drivers/media/video/cx18/cx18-scb.h
+++ b/linux/drivers/media/video/cx18/cx18-scb.h
@@ -128,22 +128,22 @@ struct cx18_scb {
u32 apu2cpu_irq;
/* Value to write to register SW2 register set (0xC7003140) after the
command is cleared */
- u32 apu2cpu_irq_ack;
+ u32 cpu2apu_irq_ack;
u32 reserved2[13];
u32 hpu2cpu_mb_offset;
u32 hpu2cpu_irq;
- u32 hpu2cpu_irq_ack;
+ u32 cpu2hpu_irq_ack;
u32 reserved3[13];
u32 ppu2cpu_mb_offset;
u32 ppu2cpu_irq;
- u32 ppu2cpu_irq_ack;
+ u32 cpu2ppu_irq_ack;
u32 reserved4[13];
u32 epu2cpu_mb_offset;
u32 epu2cpu_irq;
- u32 epu2cpu_irq_ack;
+ u32 cpu2epu_irq_ack;
u32 reserved5[13];
u32 reserved6[8];
@@ -153,22 +153,22 @@ struct cx18_scb {
u32 reserved11[7];
u32 cpu2apu_mb_offset;
u32 cpu2apu_irq;
- u32 cpu2apu_irq_ack;
+ u32 apu2cpu_irq_ack;
u32 reserved12[13];
u32 hpu2apu_mb_offset;
u32 hpu2apu_irq;
- u32 hpu2apu_irq_ack;
+ u32 apu2hpu_irq_ack;
u32 reserved13[13];
u32 ppu2apu_mb_offset;
u32 ppu2apu_irq;
- u32 ppu2apu_irq_ack;
+ u32 apu2ppu_irq_ack;
u32 reserved14[13];
u32 epu2apu_mb_offset;
u32 epu2apu_irq;
- u32 epu2apu_irq_ack;
+ u32 apu2epu_irq_ack;
u32 reserved15[13];
u32 reserved16[8];
@@ -178,22 +178,22 @@ struct cx18_scb {
u32 reserved21[7];
u32 cpu2hpu_mb_offset;
u32 cpu2hpu_irq;
- u32 cpu2hpu_irq_ack;
+ u32 hpu2cpu_irq_ack;
u32 reserved22[13];
u32 apu2hpu_mb_offset;
u32 apu2hpu_irq;
- u32 apu2hpu_irq_ack;
+ u32 hpu2apu_irq_ack;
u32 reserved23[13];
u32 ppu2hpu_mb_offset;
u32 ppu2hpu_irq;
- u32 ppu2hpu_irq_ack;
+ u32 hpu2ppu_irq_ack;
u32 reserved24[13];
u32 epu2hpu_mb_offset;
u32 epu2hpu_irq;
- u32 epu2hpu_irq_ack;
+ u32 hpu2epu_irq_ack;
u32 reserved25[13];
u32 reserved26[8];
@@ -203,22 +203,22 @@ struct cx18_scb {
u32 reserved31[7];
u32 cpu2ppu_mb_offset;
u32 cpu2ppu_irq;
- u32 cpu2ppu_irq_ack;
+ u32 ppu2cpu_irq_ack;
u32 reserved32[13];
u32 apu2ppu_mb_offset;
u32 apu2ppu_irq;
- u32 apu2ppu_irq_ack;
+ u32 ppu2apu_irq_ack;
u32 reserved33[13];
u32 hpu2ppu_mb_offset;
u32 hpu2ppu_irq;
- u32 hpu2ppu_irq_ack;
+ u32 ppu2hpu_irq_ack;
u32 reserved34[13];
u32 epu2ppu_mb_offset;
u32 epu2ppu_irq;
- u32 epu2ppu_irq_ack;
+ u32 ppu2epu_irq_ack;
u32 reserved35[13];
u32 reserved36[8];
@@ -228,22 +228,22 @@ struct cx18_scb {
u32 reserved41[7];
u32 cpu2epu_mb_offset;
u32 cpu2epu_irq;
- u32 cpu2epu_irq_ack;
+ u32 epu2cpu_irq_ack;
u32 reserved42[13];
u32 apu2epu_mb_offset;
u32 apu2epu_irq;
- u32 apu2epu_irq_ack;
+ u32 epu2apu_irq_ack;
u32 reserved43[13];
u32 hpu2epu_mb_offset;
u32 hpu2epu_irq;
- u32 hpu2epu_irq_ack;
+ u32 epu2hpu_irq_ack;
u32 reserved44[13];
u32 ppu2epu_mb_offset;
u32 ppu2epu_irq;
- u32 ppu2epu_irq_ack;
+ u32 epu2ppu_irq_ack;
u32 reserved45[13];
u32 reserved46[8];
diff --git a/linux/drivers/media/video/cx18/cx18-streams.c b/linux/drivers/media/video/cx18/cx18-streams.c
index f85f4a2cd..d29a0b61b 100644
--- a/linux/drivers/media/video/cx18/cx18-streams.c
+++ b/linux/drivers/media/video/cx18/cx18-streams.c
@@ -200,16 +200,18 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
/* Initialize v4l2 variables and register v4l2 devices */
int cx18_streams_setup(struct cx18 *cx)
{
- int type;
+ int type, ret;
/* Setup V4L2 Devices */
for (type = 0; type < CX18_MAX_STREAMS; type++) {
/* Prepare device */
- if (cx18_prep_dev(cx, type))
+ ret = cx18_prep_dev(cx, type);
+ if (ret < 0)
break;
/* Allocate Stream */
- if (cx18_stream_alloc(&cx->streams[type]))
+ ret = cx18_stream_alloc(&cx->streams[type]);
+ if (ret < 0)
break;
}
if (type == CX18_MAX_STREAMS)
@@ -217,14 +219,14 @@ int cx18_streams_setup(struct cx18 *cx)
/* One or more streams could not be initialized. Clean 'em all up. */
cx18_streams_cleanup(cx, 0);
- return -ENOMEM;
+ return ret;
}
static int cx18_reg_dev(struct cx18 *cx, int type)
{
struct cx18_stream *s = &cx->streams[type];
int vfl_type = cx18_stream_info[type].vfl_type;
- int num;
+ int num, ret;
/* TODO: Shouldn't this be a VFL_TYPE_TRANSPORT or something?
* We need a VFL_TYPE_TS defined.
@@ -233,9 +235,10 @@ static int cx18_reg_dev(struct cx18 *cx, int type)
/* just return if no DVB is supported */
if ((cx->card->hw_all & CX18_HW_DVB) == 0)
return 0;
- if (cx18_dvb_register(s) < 0) {
+ ret = cx18_dvb_register(s);
+ if (ret < 0) {
CX18_ERR("DVB failed to register\n");
- return -EINVAL;
+ return ret;
}
}
@@ -252,12 +255,13 @@ static int cx18_reg_dev(struct cx18 *cx, int type)
}
/* Register device. First try the desired minor, then any free one. */
- if (video_register_device(s->v4l2dev, vfl_type, num)) {
+ ret = video_register_device(s->v4l2dev, vfl_type, num);
+ if (ret < 0) {
CX18_ERR("Couldn't register v4l2 device for %s kernel number %d\n",
s->name, num);
video_device_release(s->v4l2dev);
s->v4l2dev = NULL;
- return -ENOMEM;
+ return ret;
}
num = s->v4l2dev->num;
@@ -290,18 +294,22 @@ static int cx18_reg_dev(struct cx18 *cx, int type)
int cx18_streams_register(struct cx18 *cx)
{
int type;
- int err = 0;
+ int err;
+ int ret = 0;
/* Register V4L2 devices */
- for (type = 0; type < CX18_MAX_STREAMS; type++)
- err |= cx18_reg_dev(cx, type);
+ for (type = 0; type < CX18_MAX_STREAMS; type++) {
+ err = cx18_reg_dev(cx, type);
+ if (err && ret == 0)
+ ret = err;
+ }
- if (err == 0)
+ if (ret == 0)
return 0;
/* One or more streams could not be initialized. Clean 'em all up. */
cx18_streams_cleanup(cx, 1);
- return -ENOMEM;
+ return ret;
}
/* Unregister v4l2 devices */
@@ -579,9 +587,6 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end)
#endif
}
- /* Tell the CX23418 it can't use our buffers anymore */
- cx18_vapi(cx, CX18_CPU_DE_RELEASE_MDL, 1, s->handle);
-
if (s->type != CX18_ENC_STREAM_TYPE_TS)
atomic_dec(&cx->ana_capturing);
atomic_dec(&cx->tot_capturing);
@@ -589,6 +594,9 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end)
/* Clear capture and no-read bits */
clear_bit(CX18_F_S_STREAMING, &s->s_flags);
+ /* Tell the CX23418 it can't use our buffers anymore */
+ cx18_vapi(cx, CX18_CPU_DE_RELEASE_MDL, 1, s->handle);
+
cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle);
s->handle = CX18_INVALID_TASK_HANDLE;
diff --git a/linux/drivers/media/video/cx18/cx18-version.h b/linux/drivers/media/video/cx18/cx18-version.h
index 9f6be2d45..366cc1472 100644
--- a/linux/drivers/media/video/cx18/cx18-version.h
+++ b/linux/drivers/media/video/cx18/cx18-version.h
@@ -25,7 +25,7 @@
#define CX18_DRIVER_NAME "cx18"
#define CX18_DRIVER_VERSION_MAJOR 1
#define CX18_DRIVER_VERSION_MINOR 0
-#define CX18_DRIVER_VERSION_PATCHLEVEL 1
+#define CX18_DRIVER_VERSION_PATCHLEVEL 2
#define CX18_VERSION __stringify(CX18_DRIVER_VERSION_MAJOR) "." __stringify(CX18_DRIVER_VERSION_MINOR) "." __stringify(CX18_DRIVER_VERSION_PATCHLEVEL)
#define CX18_DRIVER_VERSION KERNEL_VERSION(CX18_DRIVER_VERSION_MAJOR, \
diff --git a/linux/drivers/media/video/cx23885/cx23885-417.c b/linux/drivers/media/video/cx23885/cx23885-417.c
index ae914cdc5..d98e64545 100644
--- a/linux/drivers/media/video/cx23885/cx23885-417.c
+++ b/linux/drivers/media/video/cx23885/cx23885-417.c
@@ -1823,7 +1823,7 @@ int cx23885_417_register(struct cx23885_dev *dev)
cx23885_mc417_init(dev);
printk(KERN_INFO "%s: registered device video%d [mpeg]\n",
- dev->name, dev->v4l_device->minor & 0x1f);
+ dev->name, dev->v4l_device->num);
return 0;
}
diff --git a/linux/drivers/media/video/cx23885/cx23885-cards.c b/linux/drivers/media/video/cx23885/cx23885-cards.c
index 2b497b28b..dc3f79638 100644
--- a/linux/drivers/media/video/cx23885/cx23885-cards.c
+++ b/linux/drivers/media/video/cx23885/cx23885-cards.c
@@ -40,16 +40,16 @@ struct cx23885_board cx23885_boards[] = {
.input = {{
.type = CX23885_VMUX_COMPOSITE1,
.vmux = 0,
- },{
+ }, {
.type = CX23885_VMUX_COMPOSITE2,
.vmux = 1,
- },{
+ }, {
.type = CX23885_VMUX_COMPOSITE3,
.vmux = 2,
- },{
+ }, {
.type = CX23885_VMUX_COMPOSITE4,
.vmux = 3,
- }},
+ } },
},
[CX23885_BOARD_HAUPPAUGE_HVR1800lp] = {
.name = "Hauppauge WinTV-HVR1800lp",
@@ -58,19 +58,19 @@ struct cx23885_board cx23885_boards[] = {
.type = CX23885_VMUX_TELEVISION,
.vmux = 0,
.gpio0 = 0xff00,
- },{
+ }, {
.type = CX23885_VMUX_DEBUG,
.vmux = 0,
.gpio0 = 0xff01,
- },{
+ }, {
.type = CX23885_VMUX_COMPOSITE1,
.vmux = 1,
.gpio0 = 0xff02,
- },{
+ }, {
.type = CX23885_VMUX_SVIDEO,
.vmux = 2,
.gpio0 = 0xff02,
- }},
+ } },
},
[CX23885_BOARD_HAUPPAUGE_HVR1800] = {
.name = "Hauppauge WinTV-HVR1800",
@@ -85,20 +85,20 @@ struct cx23885_board cx23885_boards[] = {
CX25840_VIN5_CH2 |
CX25840_VIN2_CH1,
.gpio0 = 0,
- },{
+ }, {
.type = CX23885_VMUX_COMPOSITE1,
.vmux = CX25840_VIN7_CH3 |
CX25840_VIN4_CH2 |
CX25840_VIN6_CH1,
.gpio0 = 0,
- },{
+ }, {
.type = CX23885_VMUX_SVIDEO,
.vmux = CX25840_VIN7_CH3 |
CX25840_VIN4_CH2 |
CX25840_VIN8_CH1 |
CX25840_SVIDEO_ON,
.gpio0 = 0,
- }},
+ } },
},
[CX23885_BOARD_HAUPPAUGE_HVR1250] = {
.name = "Hauppauge WinTV-HVR1250",
@@ -107,19 +107,19 @@ struct cx23885_board cx23885_boards[] = {
.type = CX23885_VMUX_TELEVISION,
.vmux = 0,
.gpio0 = 0xff00,
- },{
+ }, {
.type = CX23885_VMUX_DEBUG,
.vmux = 0,
.gpio0 = 0xff01,
- },{
+ }, {
.type = CX23885_VMUX_COMPOSITE1,
.vmux = 1,
.gpio0 = 0xff02,
- },{
+ }, {
.type = CX23885_VMUX_SVIDEO,
.vmux = 2,
.gpio0 = 0xff02,
- }},
+ } },
},
[CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP] = {
.name = "DViCO FusionHDTV5 Express",
@@ -170,43 +170,43 @@ struct cx23885_subid cx23885_subids[] = {
.subvendor = 0x0070,
.subdevice = 0x3400,
.card = CX23885_BOARD_UNKNOWN,
- },{
+ }, {
.subvendor = 0x0070,
.subdevice = 0x7600,
.card = CX23885_BOARD_HAUPPAUGE_HVR1800lp,
- },{
+ }, {
.subvendor = 0x0070,
.subdevice = 0x7800,
.card = CX23885_BOARD_HAUPPAUGE_HVR1800,
- },{
+ }, {
.subvendor = 0x0070,
.subdevice = 0x7801,
.card = CX23885_BOARD_HAUPPAUGE_HVR1800,
- },{
+ }, {
.subvendor = 0x0070,
.subdevice = 0x7809,
.card = CX23885_BOARD_HAUPPAUGE_HVR1800,
- },{
+ }, {
.subvendor = 0x0070,
.subdevice = 0x7911,
.card = CX23885_BOARD_HAUPPAUGE_HVR1250,
- },{
+ }, {
.subvendor = 0x18ac,
.subdevice = 0xd500,
.card = CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP,
- },{
+ }, {
.subvendor = 0x0070,
.subdevice = 0x7790,
.card = CX23885_BOARD_HAUPPAUGE_HVR1500Q,
- },{
+ }, {
.subvendor = 0x0070,
.subdevice = 0x7797,
.card = CX23885_BOARD_HAUPPAUGE_HVR1500Q,
- },{
+ }, {
.subvendor = 0x0070,
.subdevice = 0x7710,
.card = CX23885_BOARD_HAUPPAUGE_HVR1500,
- },{
+ }, {
.subvendor = 0x0070,
.subdevice = 0x7717,
.card = CX23885_BOARD_HAUPPAUGE_HVR1500,
@@ -226,11 +226,11 @@ struct cx23885_subid cx23885_subids[] = {
.subvendor = 0x0070,
.subdevice = 0x8010,
.card = CX23885_BOARD_HAUPPAUGE_HVR1400,
- },{
+ }, {
.subvendor = 0x18ac,
.subdevice = 0xd618,
.card = CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP,
- },{
+ }, {
.subvendor = 0x18ac,
.subdevice = 0xdb78,
.card = CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP,
@@ -248,23 +248,25 @@ void cx23885_card_list(struct cx23885_dev *dev)
if (0 == dev->pci->subsystem_vendor &&
0 == dev->pci->subsystem_device) {
- printk("%s: Your board has no valid PCIe Subsystem ID and thus can't\n"
- "%s: be autodetected. Please pass card=<n> insmod option to\n"
- "%s: workaround that. Redirect complaints to the vendor of\n"
- "%s: the TV card. Best regards,\n"
+ printk(KERN_INFO
+ "%s: Board has no valid PCIe Subsystem ID and can't\n"
+ "%s: be autodetected. Pass card=<n> insmod option\n"
+ "%s: to workaround that. Redirect complaints to the\n"
+ "%s: vendor of the TV card. Best regards,\n"
"%s: -- tux\n",
dev->name, dev->name, dev->name, dev->name, dev->name);
} else {
- printk("%s: Your board isn't known (yet) to the driver. You can\n"
- "%s: try to pick one of the existing card configs via\n"
+ printk(KERN_INFO
+ "%s: Your board isn't known (yet) to the driver.\n"
+ "%s: Try to pick one of the existing card configs via\n"
"%s: card=<n> insmod option. Updating to the latest\n"
"%s: version might help as well.\n",
dev->name, dev->name, dev->name, dev->name);
}
- printk("%s: Here is a list of valid choices for the card=<n> insmod option:\n",
+ printk(KERN_INFO "%s: Here is a list of valid choices for the card=<n> insmod option:\n",
dev->name);
for (i = 0; i < cx23885_bcount; i++)
- printk("%s: card=%d -> %s\n",
+ printk(KERN_INFO "%s: card=%d -> %s\n",
dev->name, i, cx23885_boards[i].name);
}
@@ -272,11 +274,11 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data)
{
struct tveeprom tv;
- tveeprom_hauppauge_analog(&dev->i2c_bus[0].i2c_client, &tv, eeprom_data);
+ tveeprom_hauppauge_analog(&dev->i2c_bus[0].i2c_client, &tv,
+ eeprom_data);
/* Make sure we support the board model */
- switch (tv.model)
- {
+ switch (tv.model) {
case 71009:
/* WinTV-HVR1200 (PCIe, Retail, full height)
* DVB-T and basic analog */
@@ -304,21 +306,51 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data)
case 71999:
/* WinTV-HVR1200 (PCIe, OEM, full height)
* DVB-T and basic analog */
- case 76601: /* WinTV-HVR1800lp (PCIe, Retail, No IR, Dual channel ATSC and MPEG2 HW Encoder */
- case 77001: /* WinTV-HVR1500 (Express Card, OEM, No IR, ATSC and Basic analog */
- case 77011: /* WinTV-HVR1500 (Express Card, Retail, No IR, ATSC and Basic analog */
- case 77041: /* WinTV-HVR1500Q (Express Card, OEM, No IR, ATSC/QAM and Basic analog */
- case 77051: /* WinTV-HVR1500Q (Express Card, Retail, No IR, ATSC/QAM and Basic analog */
- case 78011: /* WinTV-HVR1800 (PCIe, Retail, 3.5mm in, IR, No FM, Dual channel ATSC and MPEG2 HW Encoder */
- case 78501: /* WinTV-HVR1800 (PCIe, OEM, RCA in, No IR, FM, Dual channel ATSC and MPEG2 HW Encoder */
- case 78521: /* WinTV-HVR1800 (PCIe, OEM, RCA in, No IR, FM, Dual channel ATSC and MPEG2 HW Encoder */
- case 78531: /* WinTV-HVR1800 (PCIe, OEM, RCA in, No IR, No FM, Dual channel ATSC and MPEG2 HW Encoder */
- case 78631: /* WinTV-HVR1800 (PCIe, OEM, No IR, No FM, Dual channel ATSC and MPEG2 HW Encoder */
- case 79001: /* WinTV-HVR1250 (PCIe, Retail, IR, full height, ATSC and Basic analog */
- case 79101: /* WinTV-HVR1250 (PCIe, Retail, IR, half height, ATSC and Basic analog */
- case 79561: /* WinTV-HVR1250 (PCIe, OEM, No IR, half height, ATSC and Basic analog */
- case 79571: /* WinTV-HVR1250 (PCIe, OEM, No IR, full height, ATSC and Basic analog */
- case 79671: /* WinTV-HVR1250 (PCIe, OEM, No IR, half height, ATSC and Basic analog */
+ case 76601:
+ /* WinTV-HVR1800lp (PCIe, Retail, No IR, Dual
+ channel ATSC and MPEG2 HW Encoder */
+ case 77001:
+ /* WinTV-HVR1500 (Express Card, OEM, No IR, ATSC
+ and Basic analog */
+ case 77011:
+ /* WinTV-HVR1500 (Express Card, Retail, No IR, ATSC
+ and Basic analog */
+ case 77041:
+ /* WinTV-HVR1500Q (Express Card, OEM, No IR, ATSC/QAM
+ and Basic analog */
+ case 77051:
+ /* WinTV-HVR1500Q (Express Card, Retail, No IR, ATSC/QAM
+ and Basic analog */
+ case 78011:
+ /* WinTV-HVR1800 (PCIe, Retail, 3.5mm in, IR, No FM,
+ Dual channel ATSC and MPEG2 HW Encoder */
+ case 78501:
+ /* WinTV-HVR1800 (PCIe, OEM, RCA in, No IR, FM,
+ Dual channel ATSC and MPEG2 HW Encoder */
+ case 78521:
+ /* WinTV-HVR1800 (PCIe, OEM, RCA in, No IR, FM,
+ Dual channel ATSC and MPEG2 HW Encoder */
+ case 78531:
+ /* WinTV-HVR1800 (PCIe, OEM, RCA in, No IR, No FM,
+ Dual channel ATSC and MPEG2 HW Encoder */
+ case 78631:
+ /* WinTV-HVR1800 (PCIe, OEM, No IR, No FM,
+ Dual channel ATSC and MPEG2 HW Encoder */
+ case 79001:
+ /* WinTV-HVR1250 (PCIe, Retail, IR, full height,
+ ATSC and Basic analog */
+ case 79101:
+ /* WinTV-HVR1250 (PCIe, Retail, IR, half height,
+ ATSC and Basic analog */
+ case 79561:
+ /* WinTV-HVR1250 (PCIe, OEM, No IR, half height,
+ ATSC and Basic analog */
+ case 79571:
+ /* WinTV-HVR1250 (PCIe, OEM, No IR, full height,
+ ATSC and Basic analog */
+ case 79671:
+ /* WinTV-HVR1250 (PCIe, OEM, No IR, half height,
+ ATSC and Basic analog */
case 80019:
/* WinTV-HVR1400 (Express Card, Retail, IR,
* DVB-T and Basic analog */
@@ -330,7 +362,8 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data)
* DVB-T and MPEG2 HW Encoder */
break;
default:
- printk("%s: warning: unknown hauppauge model #%d\n", dev->name, tv.model);
+ printk(KERN_WARNING "%s: warning: unknown hauppauge model #%d\n",
+ dev->name, tv.model);
break;
}
@@ -353,7 +386,7 @@ int cx23885_tuner_callback(void *priv, int component, int command, int arg)
return -EINVAL;
}
- switch(dev->board) {
+ switch (dev->board) {
case CX23885_BOARD_HAUPPAUGE_HVR1400:
case CX23885_BOARD_HAUPPAUGE_HVR1500:
case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
@@ -384,7 +417,7 @@ int cx23885_tuner_callback(void *priv, int component, int command, int arg)
void cx23885_gpio_setup(struct cx23885_dev *dev)
{
- switch(dev->board) {
+ switch (dev->board) {
case CX23885_BOARD_HAUPPAUGE_HVR1250:
/* GPIO-0 cx24227 demodulator reset */
cx_set(GP0_IO, 0x00010001); /* Bring the part out of reset */
@@ -618,10 +651,3 @@ void cx23885_card_setup(struct cx23885_dev *dev)
}
/* ------------------------------------------------------------------ */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
- */
diff --git a/linux/drivers/media/video/cx23885/cx23885-core.c b/linux/drivers/media/video/cx23885/cx23885-core.c
index 6fc69988a..4f68156d2 100644
--- a/linux/drivers/media/video/cx23885/cx23885-core.c
+++ b/linux/drivers/media/video/cx23885/cx23885-core.c
@@ -38,12 +38,12 @@ MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
MODULE_LICENSE("GPL");
static unsigned int debug;
-module_param(debug,int,0644);
-MODULE_PARM_DESC(debug,"enable debug messages");
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages");
static unsigned int card[] = {[0 ... (CX23885_MAXBOARDS - 1)] = UNSET };
module_param_array(card, int, NULL, 0444);
-MODULE_PARM_DESC(card,"card type");
+MODULE_PARM_DESC(card, "card type");
#define dprintk(level, fmt, arg...)\
do { if (debug >= level)\
@@ -365,13 +365,12 @@ void cx23885_wakeup(struct cx23885_tsport *port,
list_del(&buf->vb.queue);
wake_up(&buf->vb.done);
}
- if (list_empty(&q->active)) {
+ if (list_empty(&q->active))
del_timer(&q->timeout);
- } else {
+ else
mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
- }
if (bc != 1)
- printk("%s: %d buffers handled (should be 1)\n",
+ printk(KERN_WARNING "%s: %d buffers handled (should be 1)\n",
__func__, bc);
}
@@ -382,8 +381,7 @@ int cx23885_sram_channel_setup(struct cx23885_dev *dev,
unsigned int i, lines;
u32 cdt;
- if (ch->cmds_start == 0)
- {
+ if (ch->cmds_start == 0) {
dprintk(1, "%s() Erasing channel [%s]\n", __func__,
ch->name);
cx_write(ch->ptr1_reg, 0);
@@ -419,15 +417,15 @@ int cx23885_sram_channel_setup(struct cx23885_dev *dev,
/* write CMDS */
if (ch->jumponly)
- cx_write(ch->cmds_start + 0, 8);
+ cx_write(ch->cmds_start + 0, 8);
else
- cx_write(ch->cmds_start + 0, risc);
+ cx_write(ch->cmds_start + 0, risc);
cx_write(ch->cmds_start + 4, 0); /* 64 bits 63-32 */
cx_write(ch->cmds_start + 8, cdt);
cx_write(ch->cmds_start + 12, (lines*16) >> 3);
cx_write(ch->cmds_start + 16, ch->ctrl_start);
if (ch->jumponly)
- cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2) );
+ cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2));
else
cx_write(ch->cmds_start + 20, 64 >> 2);
for (i = 24; i < 80; i += 4)
@@ -437,9 +435,9 @@ int cx23885_sram_channel_setup(struct cx23885_dev *dev,
cx_write(ch->ptr1_reg, ch->fifo_start);
cx_write(ch->ptr2_reg, cdt);
cx_write(ch->cnt2_reg, (lines*16) >> 3);
- cx_write(ch->cnt1_reg, (bpl >> 3) -1);
+ cx_write(ch->cnt1_reg, (bpl >> 3) - 1);
- dprintk(2,"[bridge %d] sram setup %s: bpl=%d lines=%d\n",
+ dprintk(2, "[bridge %d] sram setup %s: bpl=%d lines=%d\n",
dev->bridge,
ch->name,
bpl,
@@ -470,43 +468,43 @@ void cx23885_sram_channel_dump(struct cx23885_dev *dev,
u32 risc;
unsigned int i, j, n;
- printk("%s: %s - dma channel status dump\n",
+ printk(KERN_WARNING "%s: %s - dma channel status dump\n",
dev->name, ch->name);
for (i = 0; i < ARRAY_SIZE(name); i++)
- printk("%s: cmds: %-15s: 0x%08x\n",
+ printk(KERN_WARNING "%s: cmds: %-15s: 0x%08x\n",
dev->name, name[i],
cx_read(ch->cmds_start + 4*i));
for (i = 0; i < 4; i++) {
risc = cx_read(ch->cmds_start + 4 * (i + 14));
- printk("%s: risc%d: ", dev->name, i);
+ printk(KERN_WARNING "%s: risc%d: ", dev->name, i);
cx23885_risc_decode(risc);
}
for (i = 0; i < (64 >> 2); i += n) {
risc = cx_read(ch->ctrl_start + 4 * i);
/* No consideration for bits 63-32 */
- printk("%s: (0x%08x) iq %x: ", dev->name,
+ printk(KERN_WARNING "%s: (0x%08x) iq %x: ", dev->name,
ch->ctrl_start + 4 * i, i);
n = cx23885_risc_decode(risc);
for (j = 1; j < n; j++) {
risc = cx_read(ch->ctrl_start + 4 * (i + j));
- printk("%s: iq %x: 0x%08x [ arg #%d ]\n",
+ printk(KERN_WARNING "%s: iq %x: 0x%08x [ arg #%d ]\n",
dev->name, i+j, risc, j);
}
}
- printk("%s: fifo: 0x%08x -> 0x%x\n",
+ printk(KERN_WARNING "%s: fifo: 0x%08x -> 0x%x\n",
dev->name, ch->fifo_start, ch->fifo_start+ch->fifo_size);
- printk("%s: ctrl: 0x%08x -> 0x%x\n",
+ printk(KERN_WARNING "%s: ctrl: 0x%08x -> 0x%x\n",
dev->name, ch->ctrl_start, ch->ctrl_start + 6*16);
- printk("%s: ptr1_reg: 0x%08x\n",
+ printk(KERN_WARNING "%s: ptr1_reg: 0x%08x\n",
dev->name, cx_read(ch->ptr1_reg));
- printk("%s: ptr2_reg: 0x%08x\n",
+ printk(KERN_WARNING "%s: ptr2_reg: 0x%08x\n",
dev->name, cx_read(ch->ptr2_reg));
- printk("%s: cnt1_reg: 0x%08x\n",
+ printk(KERN_WARNING "%s: cnt1_reg: 0x%08x\n",
dev->name, cx_read(ch->cnt1_reg));
- printk("%s: cnt2_reg: 0x%08x\n",
+ printk(KERN_WARNING "%s: cnt2_reg: 0x%08x\n",
dev->name, cx_read(ch->cnt2_reg));
}
@@ -516,13 +514,13 @@ static void cx23885_risc_disasm(struct cx23885_tsport *port,
struct cx23885_dev *dev = port->dev;
unsigned int i, j, n;
- printk("%s: risc disasm: %p [dma=0x%08lx]\n",
+ printk(KERN_INFO "%s: risc disasm: %p [dma=0x%08lx]\n",
dev->name, risc->cpu, (unsigned long)risc->dma);
for (i = 0; i < (risc->size >> 2); i += n) {
- printk("%s: %04d: ", dev->name, i);
+ printk(KERN_INFO "%s: %04d: ", dev->name, i);
n = cx23885_risc_decode(le32_to_cpu(risc->cpu[i]));
for (j = 1; j < n; j++)
- printk("%s: %04d: 0x%08x [ arg #%d ]\n",
+ printk(KERN_INFO "%s: %04d: 0x%08x [ arg #%d ]\n",
dev->name, i + j, risc->cpu[i + j], j);
if (risc->cpu[i] == cpu_to_le32(RISC_JUMP))
break;
@@ -601,7 +599,7 @@ static int cx23885_pci_quirks(struct cx23885_dev *dev)
* when DMA begins if RDR_TLCTL0 bit4 is not cleared. It does not
* occur on the cx23887 bridge.
*/
- if(dev->bridge == CX23885_BRIDGE_885)
+ if (dev->bridge == CX23885_BRIDGE_885)
cx_clear(RDR_TLCTL0, 1 << 4);
return 0;
@@ -609,13 +607,13 @@ static int cx23885_pci_quirks(struct cx23885_dev *dev)
static int get_resources(struct cx23885_dev *dev)
{
- if (request_mem_region(pci_resource_start(dev->pci,0),
- pci_resource_len(dev->pci,0),
+ if (request_mem_region(pci_resource_start(dev->pci, 0),
+ pci_resource_len(dev->pci, 0),
dev->name))
return 0;
printk(KERN_ERR "%s: can't get MMIO memory @ 0x%llx\n",
- dev->name, (unsigned long long)pci_resource_start(dev->pci,0));
+ dev->name, (unsigned long long)pci_resource_start(dev->pci, 0));
return -EBUSY;
}
@@ -624,7 +622,8 @@ static void cx23885_timeout(unsigned long data);
int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
u32 reg, u32 mask, u32 value);
-static int cx23885_init_tsport(struct cx23885_dev *dev, struct cx23885_tsport *port, int portno)
+static int cx23885_init_tsport(struct cx23885_dev *dev,
+ struct cx23885_tsport *port, int portno)
{
dprintk(1, "%s(portno=%d)\n", __func__, portno);
@@ -645,17 +644,17 @@ static int cx23885_init_tsport(struct cx23885_dev *dev, struct cx23885_tsport *p
init_timer(&port->mpegq.timeout);
mutex_init(&port->frontends.lock);
- INIT_LIST_HEAD(&port->frontends.frontend.felist);
+ INIT_LIST_HEAD(&port->frontends.felist);
port->frontends.active_fe_id = 0;
/* This should be hardcoded allow a single frontend
* attachment to this tsport, keeping the -dvb.c
* code clean and safe.
*/
- if(!port->num_frontends)
+ if (!port->num_frontends)
port->num_frontends = 1;
- switch(portno) {
+ switch (portno) {
case 1:
port->reg_gpcnt = VID_B_GPCNT;
port->reg_gpcnt_ctl = VID_B_GPCNT_CTL;
@@ -756,13 +755,13 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
mutex_unlock(&devlist);
/* Configure the internal memory */
- if(dev->pci->device == 0x8880) {
+ if (dev->pci->device == 0x8880) {
dev->bridge = CX23885_BRIDGE_887;
/* Apply a sensible clock frequency for the PCIe bridge */
dev->clk_freq = 25000000;
dev->sram_channels = cx23887_sram_channels;
} else
- if(dev->pci->device == 0x8852) {
+ if (dev->pci->device == 0x8852) {
dev->bridge = CX23885_BRIDGE_885;
/* Apply a sensible clock frequency for the PCIe bridge */
dev->clk_freq = 28000000;
@@ -843,8 +842,8 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
}
/* PCIe stuff */
- dev->lmmio = ioremap(pci_resource_start(dev->pci,0),
- pci_resource_len(dev->pci,0));
+ dev->lmmio = ioremap(pci_resource_start(dev->pci, 0),
+ pci_resource_len(dev->pci, 0));
dev->bmmio = (u8 __iomem *)dev->lmmio;
@@ -874,7 +873,7 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
cx23885_i2c_register(&dev->i2c_bus[1]);
cx23885_i2c_register(&dev->i2c_bus[2]);
cx23885_card_setup(dev);
- cx23885_call_i2c_clients (&dev->i2c_bus[0], TUNER_SET_STANDBY, NULL);
+ cx23885_call_i2c_clients(&dev->i2c_bus[0], TUNER_SET_STANDBY, NULL);
cx23885_ir_init(dev);
if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO) {
@@ -920,8 +919,8 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
static void cx23885_dev_unregister(struct cx23885_dev *dev)
{
- release_mem_region(pci_resource_start(dev->pci,0),
- pci_resource_len(dev->pci,0));
+ release_mem_region(pci_resource_start(dev->pci, 0),
+ pci_resource_len(dev->pci, 0));
if (!atomic_dec_and_test(&dev->refcount))
return;
@@ -948,7 +947,7 @@ static void cx23885_dev_unregister(struct cx23885_dev *dev)
iounmap(dev->lmmio);
}
-static __le32* cx23885_risc_field(__le32 *rp, struct scatterlist *sglist,
+static __le32 *cx23885_risc_field(__le32 *rp, struct scatterlist *sglist,
unsigned int offset, u32 sync_line,
unsigned int bpl, unsigned int padding,
unsigned int lines)
@@ -969,31 +968,31 @@ static __le32* cx23885_risc_field(__le32 *rp, struct scatterlist *sglist,
}
if (bpl <= sg_dma_len(sg)-offset) {
/* fits into current chunk */
- *(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL|RISC_EOL|bpl);
- *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
- *(rp++)=cpu_to_le32(0); /* bits 63-32 */
- offset+=bpl;
+ *(rp++) = cpu_to_le32(RISC_WRITE|RISC_SOL|RISC_EOL|bpl);
+ *(rp++) = cpu_to_le32(sg_dma_address(sg)+offset);
+ *(rp++) = cpu_to_le32(0); /* bits 63-32 */
+ offset += bpl;
} else {
/* scanline needs to be split */
todo = bpl;
- *(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL|
+ *(rp++) = cpu_to_le32(RISC_WRITE|RISC_SOL|
(sg_dma_len(sg)-offset));
- *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
- *(rp++)=cpu_to_le32(0); /* bits 63-32 */
+ *(rp++) = cpu_to_le32(sg_dma_address(sg)+offset);
+ *(rp++) = cpu_to_le32(0); /* bits 63-32 */
todo -= (sg_dma_len(sg)-offset);
offset = 0;
sg++;
while (todo > sg_dma_len(sg)) {
- *(rp++)=cpu_to_le32(RISC_WRITE|
+ *(rp++) = cpu_to_le32(RISC_WRITE|
sg_dma_len(sg));
- *(rp++)=cpu_to_le32(sg_dma_address(sg));
- *(rp++)=cpu_to_le32(0); /* bits 63-32 */
+ *(rp++) = cpu_to_le32(sg_dma_address(sg));
+ *(rp++) = cpu_to_le32(0); /* bits 63-32 */
todo -= sg_dma_len(sg);
sg++;
}
- *(rp++)=cpu_to_le32(RISC_WRITE|RISC_EOL|todo);
- *(rp++)=cpu_to_le32(sg_dma_address(sg));
- *(rp++)=cpu_to_le32(0); /* bits 63-32 */
+ *(rp++) = cpu_to_le32(RISC_WRITE|RISC_EOL|todo);
+ *(rp++) = cpu_to_le32(sg_dma_address(sg));
+ *(rp++) = cpu_to_le32(0); /* bits 63-32 */
offset += todo;
}
offset += padding;
@@ -1022,9 +1021,11 @@ int cx23885_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
can cause next bpl to start close to a page border. First DMA
region may be smaller than PAGE_SIZE */
/* write and jump need and extra dword */
- instructions = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines);
+ instructions = fields * (1 + ((bpl + padding) * lines)
+ / PAGE_SIZE + lines);
instructions += 2;
- if ((rc = btcx_riscmem_alloc(pci,risc,instructions*12)) < 0)
+ rc = btcx_riscmem_alloc(pci, risc, instructions*12);
+ if (rc < 0)
return rc;
/* write risc instructions */
@@ -1038,7 +1039,7 @@ int cx23885_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
/* save pointer to jmp instruction address */
risc->jmp = rp;
- BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size);
+ BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
return 0;
}
@@ -1060,7 +1061,8 @@ static int cx23885_risc_databuffer(struct pci_dev *pci,
instructions = 1 + (bpl * lines) / PAGE_SIZE + lines;
instructions += 1;
- if ((rc = btcx_riscmem_alloc(pci,risc,instructions*12)) < 0)
+ rc = btcx_riscmem_alloc(pci, risc, instructions*12);
+ if (rc < 0)
return rc;
/* write risc instructions */
@@ -1069,7 +1071,7 @@ static int cx23885_risc_databuffer(struct pci_dev *pci,
/* save pointer to jmp instruction address */
risc->jmp = rp;
- BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size);
+ BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
return 0;
}
@@ -1079,7 +1081,8 @@ int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
__le32 *rp;
int rc;
- if ((rc = btcx_riscmem_alloc(pci, risc, 4*16)) < 0)
+ rc = btcx_riscmem_alloc(pci, risc, 4*16);
+ if (rc < 0)
return rc;
/* write risc instructions */
@@ -1173,22 +1176,23 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
/* setup fifo + format */
cx23885_sram_channel_setup(dev,
- &dev->sram_channels[ port->sram_chno ],
+ &dev->sram_channels[port->sram_chno],
port->ts_packet_size, buf->risc.dma);
- if(debug > 5) {
- cx23885_sram_channel_dump(dev, &dev->sram_channels[ port->sram_chno ] );
+ if (debug > 5) {
+ cx23885_sram_channel_dump(dev,
+ &dev->sram_channels[port->sram_chno]);
cx23885_risc_disasm(port, &buf->risc);
}
/* write TS length to chip */
cx_write(port->reg_lngth, buf->vb.width);
- if ( (!(cx23885_boards[dev->board].portb & CX23885_MPEG_DVB)) &&
- (!(cx23885_boards[dev->board].portc & CX23885_MPEG_DVB)) ) {
- printk( "%s() Failed. Unsupported value in .portb/c (0x%08x)/(0x%08x)\n",
+ if ((!(cx23885_boards[dev->board].portb & CX23885_MPEG_DVB)) &&
+ (!(cx23885_boards[dev->board].portc & CX23885_MPEG_DVB))) {
+ printk("%s() Unsupported .portb/c (0x%08x)/(0x%08x)\n",
__func__,
cx23885_boards[dev->board].portb,
- cx23885_boards[dev->board].portc );
+ cx23885_boards[dev->board].portc);
return -EINVAL;
}
@@ -1198,7 +1202,7 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
udelay(100);
/* If the port supports SRC SELECT, configure it */
- if(port->reg_src_sel)
+ if (port->reg_src_sel)
cx_write(port->reg_src_sel, port->src_sel_val);
cx_write(port->reg_hw_sop_ctrl, port->hw_sop_ctrl_val);
@@ -1207,7 +1211,7 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
cx_write(port->reg_gen_ctrl, port->gen_ctrl_val);
udelay(100);
- // NOTE: this is 2 (reserved) for portb, does it matter?
+ /* NOTE: this is 2 (reserved) for portb, does it matter? */
/* reset counter to zero */
cx_write(port->reg_gpcnt_ctl, 3);
q->count = 1;
@@ -1241,11 +1245,11 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
cx_write(ALT_PIN_OUT_SEL, 0x10100045);
}
- switch(dev->bridge) {
+ switch (dev->bridge) {
case CX23885_BRIDGE_885:
case CX23885_BRIDGE_887:
/* enable irqs */
- dprintk(1, "%s() enabling TS int's and DMA\n", __func__ );
+ dprintk(1, "%s() enabling TS int's and DMA\n", __func__);
cx_set(port->reg_ts_int_msk, port->ts_int_msk_val);
cx_set(port->reg_dma_ctl, port->dma_ctl_val);
cx_set(PCI_INT_MSK, dev->pci_irqmask | port->pci_irqmask);
@@ -1310,8 +1314,7 @@ int cx23885_restart_queue(struct cx23885_tsport *port,
struct cx23885_buffer *buf;
dprintk(5, "%s()\n", __func__);
- if (list_empty(&q->active))
- {
+ if (list_empty(&q->active)) {
struct cx23885_buffer *prev;
prev = NULL;
@@ -1329,7 +1332,7 @@ int cx23885_restart_queue(struct cx23885_tsport *port,
buf->vb.state = VIDEOBUF_ACTIVE;
buf->count = q->count++;
mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
- dprintk(5, "[%p/%d] restart_queue - first active\n",
+ dprintk(5, "[%p/%d] restart_queue - f/active\n",
buf, buf->vb.i);
} else if (prev->vb.width == buf->vb.width &&
@@ -1340,8 +1343,9 @@ int cx23885_restart_queue(struct cx23885_tsport *port,
buf->vb.state = VIDEOBUF_ACTIVE;
buf->count = q->count++;
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
- prev->risc.jmp[2] = cpu_to_le32(0); /* 64 bit bits 63-32 */
- dprintk(5,"[%p/%d] restart_queue - move to active\n",
+ /* 64 bit bits 63-32 */
+ prev->risc.jmp[2] = cpu_to_le32(0);
+ dprintk(5, "[%p/%d] restart_queue - m/active\n",
buf, buf->vb.i);
} else {
return 0;
@@ -1380,7 +1384,8 @@ int cx23885_buf_prepare(struct videobuf_queue *q, struct cx23885_tsport *port,
buf->vb.size = size;
buf->vb.field = field /*V4L2_FIELD_TOP*/;
- if (0 != (rc = videobuf_iolock(q, &buf->vb, NULL)))
+ rc = videobuf_iolock(q, &buf->vb, NULL);
+ if (0 != rc)
goto fail;
cx23885_risc_databuffer(dev->pci, &buf->risc,
videobuf_to_dma(&buf->vb)->sglist,
@@ -1406,7 +1411,7 @@ void cx23885_buf_queue(struct cx23885_tsport *port, struct cx23885_buffer *buf)
buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
if (list_empty(&cx88q->active)) {
- dprintk( 1, "queue is empty - first active\n" );
+ dprintk(1, "queue is empty - first active\n");
list_add_tail(&buf->vb.queue, &cx88q->active);
cx23885_start_dma(port, cx88q, buf);
buf->vb.state = VIDEOBUF_ACTIVE;
@@ -1415,7 +1420,7 @@ void cx23885_buf_queue(struct cx23885_tsport *port, struct cx23885_buffer *buf)
dprintk(1, "[%p/%d] %s - first active\n",
buf, buf->vb.i, __func__);
} else {
- dprintk( 1, "queue is not empty - append to active\n" );
+ dprintk(1, "queue is not empty - append to active\n");
prev = list_entry(cx88q->active.prev, struct cx23885_buffer,
vb.queue);
list_add_tail(&buf->vb.queue, &cx88q->active);
@@ -1423,7 +1428,7 @@ void cx23885_buf_queue(struct cx23885_tsport *port, struct cx23885_buffer *buf)
buf->count = cx88q->count++;
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
prev->risc.jmp[2] = cpu_to_le32(0); /* 64 bit bits 63-32 */
- dprintk( 1, "[%p/%d] %s - append to active\n",
+ dprintk(1, "[%p/%d] %s - append to active\n",
buf, buf->vb.i, __func__);
}
}
@@ -1449,7 +1454,7 @@ static void do_cancel_buffers(struct cx23885_tsport *port, char *reason,
buf, buf->vb.i, reason, (unsigned long)buf->risc.dma);
}
if (restart) {
- dprintk(1, "restarting queue\n" );
+ dprintk(1, "restarting queue\n");
cx23885_restart_queue(port, q);
}
spin_unlock_irqrestore(&port->slock, flags);
@@ -1471,10 +1476,11 @@ static void cx23885_timeout(unsigned long data)
struct cx23885_tsport *port = (struct cx23885_tsport *)data;
struct cx23885_dev *dev = port->dev;
- dprintk(1, "%s()\n",__func__);
+ dprintk(1, "%s()\n", __func__);
if (debug > 5)
- cx23885_sram_channel_dump(dev, &dev->sram_channels[ port->sram_chno ]);
+ cx23885_sram_channel_dump(dev,
+ &dev->sram_channels[port->sram_chno]);
cx23885_stop_dma(port);
do_cancel_buffers(port, "timeout", 1);
@@ -1550,16 +1556,23 @@ static int cx23885_irq_ts(struct cx23885_tsport *port, u32 status)
if ((status & VID_BC_MSK_OPC_ERR) ||
(status & VID_BC_MSK_BAD_PKT) ||
(status & VID_BC_MSK_SYNC) ||
- (status & VID_BC_MSK_OF))
- {
+ (status & VID_BC_MSK_OF)) {
+
if (status & VID_BC_MSK_OPC_ERR)
- dprintk(7, " (VID_BC_MSK_OPC_ERR 0x%08x)\n", VID_BC_MSK_OPC_ERR);
+ dprintk(7, " (VID_BC_MSK_OPC_ERR 0x%08x)\n",
+ VID_BC_MSK_OPC_ERR);
+
if (status & VID_BC_MSK_BAD_PKT)
- dprintk(7, " (VID_BC_MSK_BAD_PKT 0x%08x)\n", VID_BC_MSK_BAD_PKT);
+ dprintk(7, " (VID_BC_MSK_BAD_PKT 0x%08x)\n",
+ VID_BC_MSK_BAD_PKT);
+
if (status & VID_BC_MSK_SYNC)
- dprintk(7, " (VID_BC_MSK_SYNC 0x%08x)\n", VID_BC_MSK_SYNC);
+ dprintk(7, " (VID_BC_MSK_SYNC 0x%08x)\n",
+ VID_BC_MSK_SYNC);
+
if (status & VID_BC_MSK_OF)
- dprintk(7, " (VID_BC_MSK_OF 0x%08x)\n", VID_BC_MSK_OF);
+ dprintk(7, " (VID_BC_MSK_OF 0x%08x)\n",
+ VID_BC_MSK_OF);
printk(KERN_ERR "%s: mpeg risc op code error\n", dev->name);
@@ -1593,7 +1606,7 @@ static int cx23885_irq_ts(struct cx23885_tsport *port, u32 status)
return handled;
}
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
static irqreturn_t cx23885_irq(int irq, void *dev_id, struct pt_regs *regs)
#else
static irqreturn_t cx23885_irq(int irq, void *dev_id)
@@ -1617,7 +1630,7 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
ts2_status = cx_read(VID_C_INT_STAT);
ts2_mask = cx_read(VID_C_INT_MSK);
- if ( (pci_status == 0) && (ts2_status == 0) && (ts1_status == 0) )
+ if ((pci_status == 0) && (ts2_status == 0) && (ts1_status == 0))
goto out;
vida_count = cx_read(VID_A_GPCNT);
@@ -1632,38 +1645,56 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
dprintk(7, "ts2_status: 0x%08x ts2_mask: 0x%08x count: 0x%x\n",
ts2_status, ts2_mask, ts2_count);
- if ( (pci_status & PCI_MSK_RISC_RD) ||
- (pci_status & PCI_MSK_RISC_WR) ||
- (pci_status & PCI_MSK_AL_RD) ||
- (pci_status & PCI_MSK_AL_WR) ||
- (pci_status & PCI_MSK_APB_DMA) ||
- (pci_status & PCI_MSK_VID_C) ||
- (pci_status & PCI_MSK_VID_B) ||
- (pci_status & PCI_MSK_VID_A) ||
- (pci_status & PCI_MSK_AUD_INT) ||
- (pci_status & PCI_MSK_AUD_EXT) )
- {
+ if ((pci_status & PCI_MSK_RISC_RD) ||
+ (pci_status & PCI_MSK_RISC_WR) ||
+ (pci_status & PCI_MSK_AL_RD) ||
+ (pci_status & PCI_MSK_AL_WR) ||
+ (pci_status & PCI_MSK_APB_DMA) ||
+ (pci_status & PCI_MSK_VID_C) ||
+ (pci_status & PCI_MSK_VID_B) ||
+ (pci_status & PCI_MSK_VID_A) ||
+ (pci_status & PCI_MSK_AUD_INT) ||
+ (pci_status & PCI_MSK_AUD_EXT)) {
if (pci_status & PCI_MSK_RISC_RD)
- dprintk(7, " (PCI_MSK_RISC_RD 0x%08x)\n", PCI_MSK_RISC_RD);
+ dprintk(7, " (PCI_MSK_RISC_RD 0x%08x)\n",
+ PCI_MSK_RISC_RD);
+
if (pci_status & PCI_MSK_RISC_WR)
- dprintk(7, " (PCI_MSK_RISC_WR 0x%08x)\n", PCI_MSK_RISC_WR);
+ dprintk(7, " (PCI_MSK_RISC_WR 0x%08x)\n",
+ PCI_MSK_RISC_WR);
+
if (pci_status & PCI_MSK_AL_RD)
- dprintk(7, " (PCI_MSK_AL_RD 0x%08x)\n", PCI_MSK_AL_RD);
+ dprintk(7, " (PCI_MSK_AL_RD 0x%08x)\n",
+ PCI_MSK_AL_RD);
+
if (pci_status & PCI_MSK_AL_WR)
- dprintk(7, " (PCI_MSK_AL_WR 0x%08x)\n", PCI_MSK_AL_WR);
+ dprintk(7, " (PCI_MSK_AL_WR 0x%08x)\n",
+ PCI_MSK_AL_WR);
+
if (pci_status & PCI_MSK_APB_DMA)
- dprintk(7, " (PCI_MSK_APB_DMA 0x%08x)\n", PCI_MSK_APB_DMA);
+ dprintk(7, " (PCI_MSK_APB_DMA 0x%08x)\n",
+ PCI_MSK_APB_DMA);
+
if (pci_status & PCI_MSK_VID_C)
- dprintk(7, " (PCI_MSK_VID_C 0x%08x)\n", PCI_MSK_VID_C);
+ dprintk(7, " (PCI_MSK_VID_C 0x%08x)\n",
+ PCI_MSK_VID_C);
+
if (pci_status & PCI_MSK_VID_B)
- dprintk(7, " (PCI_MSK_VID_B 0x%08x)\n", PCI_MSK_VID_B);
+ dprintk(7, " (PCI_MSK_VID_B 0x%08x)\n",
+ PCI_MSK_VID_B);
+
if (pci_status & PCI_MSK_VID_A)
- dprintk(7, " (PCI_MSK_VID_A 0x%08x)\n", PCI_MSK_VID_A);
+ dprintk(7, " (PCI_MSK_VID_A 0x%08x)\n",
+ PCI_MSK_VID_A);
+
if (pci_status & PCI_MSK_AUD_INT)
- dprintk(7, " (PCI_MSK_AUD_INT 0x%08x)\n", PCI_MSK_AUD_INT);
+ dprintk(7, " (PCI_MSK_AUD_INT 0x%08x)\n",
+ PCI_MSK_AUD_INT);
+
if (pci_status & PCI_MSK_AUD_EXT)
- dprintk(7, " (PCI_MSK_AUD_EXT 0x%08x)\n", PCI_MSK_AUD_EXT);
+ dprintk(7, " (PCI_MSK_AUD_EXT 0x%08x)\n",
+ PCI_MSK_AUD_EXT);
}
@@ -1775,13 +1806,13 @@ static struct pci_device_id cx23885_pci_tbl[] = {
.device = 0x8852,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
- },{
+ }, {
/* CX23887 Rev 2 */
.vendor = 0x14f1,
.device = 0x8880,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
- },{
+ }, {
/* --- end of list --- */
}
};
@@ -1819,9 +1850,3 @@ module_init(cx23885_init);
module_exit(cx23885_fini);
/* ----------------------------------------------------------- */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
- */
diff --git a/linux/drivers/media/video/cx23885/cx23885-dvb.c b/linux/drivers/media/video/cx23885/cx23885-dvb.c
index 9b96b0600..a11fdbfb5 100644
--- a/linux/drivers/media/video/cx23885/cx23885-dvb.c
+++ b/linux/drivers/media/video/cx23885/cx23885-dvb.c
@@ -79,19 +79,19 @@ static int dvb_buf_prepare(struct videobuf_queue *q,
struct videobuf_buffer *vb, enum v4l2_field field)
{
struct cx23885_tsport *port = q->priv_data;
- return cx23885_buf_prepare(q, port, (struct cx23885_buffer*)vb, field);
+ return cx23885_buf_prepare(q, port, (struct cx23885_buffer *)vb, field);
}
static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
{
struct cx23885_tsport *port = q->priv_data;
- cx23885_buf_queue(port, (struct cx23885_buffer*)vb);
+ cx23885_buf_queue(port, (struct cx23885_buffer *)vb);
}
static void dvb_buf_release(struct videobuf_queue *q,
struct videobuf_buffer *vb)
{
- cx23885_free_buffer(q, (struct cx23885_buffer*)vb);
+ cx23885_free_buffer(q, (struct cx23885_buffer *)vb);
}
static struct videobuf_queue_ops dvb_qops = {
@@ -451,7 +451,8 @@ static int dvb_register(struct cx23885_tsport *port)
.fname = XC3028L_DEFAULT_FIRMWARE,
.max_len = 64,
.demod = 5000,
- /* This is true for all demods with v36 firmware? */
+ /* This is true for all demods with
+ v36 firmware? */
.type = XC2028_D2633,
};
@@ -526,12 +527,14 @@ static int dvb_register(struct cx23885_tsport *port)
}
break;
default:
- printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n",
+ printk(KERN_INFO "%s: The frontend of your DVB/ATSC card "
+ " isn't supported yet\n",
dev->name);
break;
}
if (NULL == fe0->dvb.frontend) {
- printk("%s: frontend initialization failed\n", dev->name);
+ printk(KERN_ERR "%s: frontend initialization failed\n",
+ dev->name);
return -1;
}
/* define general-purpose callback pointer */
@@ -569,7 +572,8 @@ int cx23885_dvb_register(struct cx23885_tsport *port)
port->num_frontends);
for (i = 1; i <= port->num_frontends; i++) {
- if (videobuf_dvb_alloc_frontend(dev, &port->frontends, i) == NULL) {
+ if (videobuf_dvb_alloc_frontend(
+ &port->frontends, i) == NULL) {
printk(KERN_ERR "%s() failed to alloc\n", __func__);
return -ENOMEM;
}
@@ -579,7 +583,7 @@ int cx23885_dvb_register(struct cx23885_tsport *port)
err = -EINVAL;
dprintk(1, "%s\n", __func__);
- dprintk(1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
+ dprintk(1, " ->probed by Card=%d Name=%s, PCI %02x:%02x\n",
dev->board,
dev->name,
dev->pci_bus,
@@ -589,14 +593,16 @@ int cx23885_dvb_register(struct cx23885_tsport *port)
/* dvb stuff */
/* We have to init the queue for each frontend on a port. */
- printk("%s: cx23885 based dvb card\n", dev->name);
- videobuf_queue_sg_init(&fe0->dvb.dvbq, &dvb_qops, &dev->pci->dev, &port->slock,
+ printk(KERN_INFO "%s: cx23885 based dvb card\n", dev->name);
+ videobuf_queue_sg_init(&fe0->dvb.dvbq, &dvb_qops,
+ &dev->pci->dev, &port->slock,
V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP,
sizeof(struct cx23885_buffer), port);
}
err = dvb_register(port);
if (err != 0)
- printk("%s() dvb_register failed err = %d\n", __func__, err);
+ printk(KERN_ERR "%s() dvb_register failed err = %d\n",
+ __func__, err);
return err;
}
@@ -613,15 +619,9 @@ int cx23885_dvb_unregister(struct cx23885_tsport *port)
* implement MFE support.
*/
fe0 = videobuf_dvb_get_frontend(&port->frontends, 1);
- if(fe0->dvb.frontend)
+ if (fe0->dvb.frontend)
videobuf_dvb_unregister_bus(&port->frontends);
return 0;
}
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
-*/
diff --git a/linux/drivers/media/video/cx23885/cx23885-i2c.c b/linux/drivers/media/video/cx23885/cx23885-i2c.c
index 6f3a43607..ced5648d8 100644
--- a/linux/drivers/media/video/cx23885/cx23885-i2c.c
+++ b/linux/drivers/media/video/cx23885/cx23885-i2c.c
@@ -132,7 +132,7 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
printk(" >\n");
}
- for (cnt = 1; cnt < msg->len; cnt++ ) {
+ for (cnt = 1; cnt < msg->len; cnt++) {
/* following bytes */
wdata = msg->buf[cnt];
ctrl = bus->i2c_period | (1 << 12) | (1 << 2);
@@ -152,9 +152,9 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
if (retval == 0)
goto eio;
if (i2c_debug) {
- printk(" %02x", msg->buf[cnt]);
+ dprintk(1, " %02x", msg->buf[cnt]);
if (!(ctrl & I2C_NOSTOP))
- printk(" >\n");
+ dprintk(1, " >\n");
}
}
return msg->len;
@@ -163,7 +163,7 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
retval = -EIO;
err:
if (i2c_debug)
- printk(" ERR: %d\n", retval);
+ printk(KERN_ERR " ERR: %d\n", retval);
return retval;
}
@@ -195,12 +195,12 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap,
if (i2c_debug) {
if (joined)
- printk(" R");
+ dprintk(1, " R");
else
- printk(" <R %02x", (msg->addr << 1) + 1);
+ dprintk(1, " <R %02x", (msg->addr << 1) + 1);
}
- for(cnt = 0; cnt < msg->len; cnt++) {
+ for (cnt = 0; cnt < msg->len; cnt++) {
ctrl = bus->i2c_period | (1 << 12) | (1 << 2) | 1;
@@ -217,9 +217,9 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap,
goto eio;
msg->buf[cnt] = cx_read(bus->reg_rdata) & 0xff;
if (i2c_debug) {
- printk(" %02x", msg->buf[cnt]);
+ dprintk(1, " %02x", msg->buf[cnt]);
if (!(ctrl & I2C_NOSTOP))
- printk(" >\n");
+ dprintk(1, " >\n");
}
}
return msg->len;
@@ -228,7 +228,7 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap,
retval = -EIO;
err:
if (i2c_debug)
- printk(" ERR: %d\n", retval);
+ printk(KERN_ERR " ERR: %d\n", retval);
return retval;
}
@@ -372,17 +372,17 @@ static struct i2c_client cx23885_i2c_client_template = {
};
static char *i2c_devs[128] = {
- [0x10 >> 1] = "tda10048",
- [0x12 >> 1] = "dib7000pc",
- [ 0x1c >> 1 ] = "lgdt3303",
- [ 0x86 >> 1 ] = "tda9887",
- [ 0x32 >> 1 ] = "cx24227",
- [ 0x88 >> 1 ] = "cx25837",
- [ 0x84 >> 1 ] = "tda8295",
- [ 0xa0 >> 1 ] = "eeprom",
- [ 0xc0 >> 1 ] = "tuner/mt2131/tda8275",
+ [0x10 >> 1] = "tda10048",
+ [0x12 >> 1] = "dib7000pc",
+ [0x1c >> 1] = "lgdt3303",
+ [0x86 >> 1] = "tda9887",
+ [0x32 >> 1] = "cx24227",
+ [0x88 >> 1] = "cx25837",
+ [0x84 >> 1] = "tda8295",
+ [0xa0 >> 1] = "eeprom",
+ [0xc0 >> 1] = "tuner/mt2131/tda8275",
[0xc2 >> 1] = "tuner/mt2131/tda8275/xc5000/xc3028",
- [0xc8 >> 1] = "tuner/xc3028L",
+ [0xc8 >> 1] = "tuner/xc3028L",
};
static void do_i2c_scan(char *name, struct i2c_client *c)
@@ -395,7 +395,7 @@ static void do_i2c_scan(char *name, struct i2c_client *c)
rc = i2c_master_recv(c, &buf, 0);
if (rc < 0)
continue;
- printk("%s: i2c scan: found device @ 0x%x [%s]\n",
+ printk(KERN_INFO "%s: i2c scan: found device @ 0x%x [%s]\n",
name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
}
}
@@ -427,11 +427,12 @@ int cx23885_i2c_register(struct cx23885_i2c *bus)
bus->i2c_client.adapter = &bus->i2c_adap;
if (0 == bus->i2c_rc) {
- printk("%s: i2c bus %d registered\n", dev->name, bus->nr);
+ dprintk(1, "%s: i2c bus %d registered\n", dev->name, bus->nr);
if (i2c_scan)
do_i2c_scan(dev->name, &bus->i2c_client);
} else
- printk("%s: i2c bus %d register FAILED\n", dev->name, bus->nr);
+ printk(KERN_WARNING "%s: i2c bus %d register FAILED\n",
+ dev->name, bus->nr);
return bus->i2c_rc;
}
diff --git a/linux/drivers/media/video/cx23885/cx23885-video.c b/linux/drivers/media/video/cx23885/cx23885-video.c
index 70333ee2b..0b5d20481 100644
--- a/linux/drivers/media/video/cx23885/cx23885-video.c
+++ b/linux/drivers/media/video/cx23885/cx23885-video.c
@@ -320,11 +320,10 @@ static void cx23885_video_wakeup(struct cx23885_dev *dev,
list_del(&buf->vb.queue);
wake_up(&buf->vb.done);
}
- if (list_empty(&q->active)) {
+ if (list_empty(&q->active))
del_timer(&q->timeout);
- } else {
+ else
mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
- }
if (bc != 1)
printk(KERN_ERR "%s: %d buffers handled (should be 1)\n",
__func__, bc);
@@ -414,12 +413,12 @@ static int res_get(struct cx23885_dev *dev, struct cx23885_fh *fh,
static int res_check(struct cx23885_fh *fh, unsigned int bit)
{
- return (fh->resources & bit);
+ return fh->resources & bit;
}
static int res_locked(struct cx23885_dev *dev, unsigned int bit)
{
- return (dev->resources & bit);
+ return dev->resources & bit;
}
static void res_free(struct cx23885_dev *dev, struct cx23885_fh *fh,
@@ -964,14 +963,16 @@ static int video_mmap(struct file *file, struct vm_area_struct *vma)
/* ------------------------------------------------------------------ */
/* VIDEO CTRL IOCTLS */
-static int cx23885_get_control(struct cx23885_dev *dev, struct v4l2_control *ctl)
+static int cx23885_get_control(struct cx23885_dev *dev,
+ struct v4l2_control *ctl)
{
dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __func__);
cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_CTRL, ctl);
return 0;
}
-static int cx23885_set_control(struct cx23885_dev *dev, struct v4l2_control *ctl)
+static int cx23885_set_control(struct cx23885_dev *dev,
+ struct v4l2_control *ctl)
{
dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)"
" (disabled - no action)\n", __func__);
@@ -1156,29 +1157,29 @@ static int vidioc_reqbufs(struct file *file, void *priv,
struct v4l2_requestbuffers *p)
{
struct cx23885_fh *fh = priv;
- return (videobuf_reqbufs(get_queue(fh), p));
+ return videobuf_reqbufs(get_queue(fh), p);
}
static int vidioc_querybuf(struct file *file, void *priv,
struct v4l2_buffer *p)
{
struct cx23885_fh *fh = priv;
- return (videobuf_querybuf(get_queue(fh), p));
+ return videobuf_querybuf(get_queue(fh), p);
}
static int vidioc_qbuf(struct file *file, void *priv,
struct v4l2_buffer *p)
{
struct cx23885_fh *fh = priv;
- return (videobuf_qbuf(get_queue(fh), p));
+ return videobuf_qbuf(get_queue(fh), p);
}
static int vidioc_dqbuf(struct file *file, void *priv,
struct v4l2_buffer *p)
{
struct cx23885_fh *fh = priv;
- return (videobuf_dqbuf(get_queue(fh), p,
- file->f_flags & O_NONBLOCK));
+ return videobuf_dqbuf(get_queue(fh), p,
+ file->f_flags & O_NONBLOCK);
}
static int vidioc_streamon(struct file *file, void *priv,
@@ -1809,7 +1810,7 @@ int cx23885_video_register(struct cx23885_dev *dev)
goto fail_unreg;
}
printk(KERN_INFO "%s/0: registered device video%d [v4l2]\n",
- dev->name, dev->video_dev->minor & 0x1f);
+ dev->name, dev->video_dev->num);
#if 0
dev->vbi_dev = cx23885_vdev_init(dev, dev->pci,
&cx23885_vbi_template, "vbi");
@@ -1821,7 +1822,7 @@ int cx23885_video_register(struct cx23885_dev *dev)
goto fail_unreg;
}
printk(KERN_INFO "%s/0: registered device vbi%d\n",
- dev->name, dev->vbi_dev->minor & 0x1f);
+ dev->name, dev->vbi_dev->num);
if (dev->has_radio) {
dev->radio_dev = cx23885_vdev_init(dev, dev->pci,
@@ -1834,7 +1835,7 @@ int cx23885_video_register(struct cx23885_dev *dev)
goto fail_unreg;
}
printk(KERN_INFO "%s/0: registered device radio%d\n",
- dev->name, dev->radio_dev->minor & 0x1f);
+ dev->name, dev->radio_dev->num);
}
#endif
/* initial device configuration */
diff --git a/linux/drivers/media/video/cx23885/cx23885.h b/linux/drivers/media/video/cx23885/cx23885.h
index 2dde9e01a..26f755354 100644
--- a/linux/drivers/media/video/cx23885/cx23885.h
+++ b/linux/drivers/media/video/cx23885/cx23885.h
@@ -38,7 +38,7 @@
#include <linux/version.h>
#include <linux/mutex.h>
-#define CX23885_VERSION_CODE KERNEL_VERSION(0,0,1)
+#define CX23885_VERSION_CODE KERNEL_VERSION(0, 0, 1)
#define UNSET (-1U)
@@ -371,14 +371,14 @@ struct sram_channel {
/* ----------------------------------------------------------- */
#define cx_read(reg) readl(dev->lmmio + ((reg)>>2))
-#define cx_write(reg,value) writel((value), dev->lmmio + ((reg)>>2))
+#define cx_write(reg, value) writel((value), dev->lmmio + ((reg)>>2))
-#define cx_andor(reg,mask,value) \
+#define cx_andor(reg, mask, value) \
writel((readl(dev->lmmio+((reg)>>2)) & ~(mask)) |\
((value) & (mask)), dev->lmmio+((reg)>>2))
-#define cx_set(reg,bit) cx_andor((reg),(bit),(bit))
-#define cx_clear(reg,bit) cx_andor((reg),(bit),0)
+#define cx_set(reg, bit) cx_andor((reg), (bit), (bit))
+#define cx_clear(reg, bit) cx_andor((reg), (bit), 0)
/* ----------------------------------------------------------- */
/* cx23885-core.c */
@@ -415,7 +415,8 @@ extern const unsigned int cx23885_bcount;
extern struct cx23885_subid cx23885_subids[];
extern const unsigned int cx23885_idcount;
-extern int cx23885_tuner_callback(void *priv, int component, int command, int arg);
+extern int cx23885_tuner_callback(void *priv, int component,
+ int command, int arg);
extern void cx23885_card_list(struct cx23885_dev *dev);
extern int cx23885_ir_init(struct cx23885_dev *dev);
extern void cx23885_gpio_setup(struct cx23885_dev *dev);
@@ -483,11 +484,3 @@ static inline unsigned int norm_swidth(v4l2_std_id norm)
{
return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 754 : 922;
}
-
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
- */
diff --git a/linux/drivers/media/video/cx25840/Kconfig b/linux/drivers/media/video/cx25840/Kconfig
index de515dada..451133ad4 100644
--- a/linux/drivers/media/video/cx25840/Kconfig
+++ b/linux/drivers/media/video/cx25840/Kconfig
@@ -1,6 +1,6 @@
config VIDEO_CX25840
tristate "Conexant CX2584x audio/video decoders"
- depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
+ depends on VIDEO_V4L2 && I2C
---help---
Support for the Conexant CX2584x audio/video decoders.
diff --git a/linux/drivers/media/video/cx88/cx88-alsa.c b/linux/drivers/media/video/cx88/cx88-alsa.c
index c675cbeae..3dd2f6629 100644
--- a/linux/drivers/media/video/cx88/cx88-alsa.c
+++ b/linux/drivers/media/video/cx88/cx88-alsa.c
@@ -60,7 +60,7 @@
#define timestamp() if(debug>=2) { u64 time; u32 rem; rdtscll(time); \
time = (time - chip->starttime)<<12; \
rem = do_div(time, INT); \
- dprintk(2, "%s - called at %u.%03u us\n", __FUNCTION__, \
+ dprintk(2, "%s - called at %u.%03u us\n", __func__, \
(unsigned int)time, (rem << 9) / FRAC); }
#endif
/****************************************************************************
diff --git a/linux/drivers/media/video/cx88/cx88-blackbird.c b/linux/drivers/media/video/cx88/cx88-blackbird.c
index 5f44368f6..3d2afe195 100644
--- a/linux/drivers/media/video/cx88/cx88-blackbird.c
+++ b/linux/drivers/media/video/cx88/cx88-blackbird.c
@@ -1097,7 +1097,7 @@ static int mpeg_open(struct inode *inode, struct file *file)
}
}
- if (blackbird_initialize_codec(dev) < 0) {
+ if (!atomic_read(&dev->core->mpeg_users) && blackbird_initialize_codec(dev) < 0) {
if (drv)
drv->request_release(drv);
unlock_kernel();
@@ -1128,6 +1128,8 @@ static int mpeg_open(struct inode *inode, struct file *file)
fh->mpegq.field);
unlock_kernel();
+ atomic_inc(&dev->core->mpeg_users);
+
return 0;
}
@@ -1137,7 +1139,7 @@ static int mpeg_release(struct inode *inode, struct file *file)
struct cx8802_dev *dev = fh->dev;
struct cx8802_driver *drv = NULL;
- if (dev->mpeg_active)
+ if (dev->mpeg_active && atomic_read(&dev->core->mpeg_users) == 1)
blackbird_stop_codec(dev);
cx8802_cancel_buffers(fh->dev);
@@ -1157,6 +1159,8 @@ static int mpeg_release(struct inode *inode, struct file *file)
if (drv)
drv->request_release(drv);
+ atomic_dec(&dev->core->mpeg_users);
+
return 0;
}
@@ -1177,6 +1181,10 @@ static unsigned int
mpeg_poll(struct file *file, struct poll_table_struct *wait)
{
struct cx8802_fh *fh = file->private_data;
+ struct cx8802_dev *dev = fh->dev;
+
+ if (!dev->mpeg_active)
+ blackbird_start_codec(file, fh);
return videobuf_poll_stream(file, &fh->mpegq, wait);
}
@@ -1307,7 +1315,7 @@ static int blackbird_register_video(struct cx8802_dev *dev)
return err;
}
printk(KERN_INFO "%s/2: registered device video%d [mpeg]\n",
- dev->core->name,dev->mpeg_dev->minor & 0x1f);
+ dev->core->name, dev->mpeg_dev->num);
return 0;
}
diff --git a/linux/drivers/media/video/cx88/cx88-cards.c b/linux/drivers/media/video/cx88/cx88-cards.c
index eac3508d6..f9b5a9c09 100644
--- a/linux/drivers/media/video/cx88/cx88-cards.c
+++ b/linux/drivers/media/video/cx88/cx88-cards.c
@@ -1270,7 +1270,6 @@ static const struct cx88_board cx88_boards[] = {
},
},
[CX88_BOARD_WINFAST_DTV2000H] = {
- /* video inputs and radio still in testing */
.name = "WinFast DTV2000 H",
.tuner_type = TUNER_PHILIPS_FMD1216ME_MK3,
.radio_type = UNSET,
@@ -1284,7 +1283,35 @@ static const struct cx88_board cx88_boards[] = {
.gpio1 = 0x00008203,
.gpio2 = 0x00017304,
.gpio3 = 0x02000000,
+ }, {
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ .gpio0 = 0x0001d701,
+ .gpio1 = 0x0000b207,
+ .gpio2 = 0x0001d701,
+ .gpio3 = 0x02000000,
+ }, {
+ .type = CX88_VMUX_COMPOSITE2,
+ .vmux = 2,
+ .gpio0 = 0x0001d503,
+ .gpio1 = 0x0000b207,
+ .gpio2 = 0x0001d503,
+ .gpio3 = 0x02000000,
+ }, {
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 3,
+ .gpio0 = 0x0001d701,
+ .gpio1 = 0x0000b207,
+ .gpio2 = 0x0001d701,
+ .gpio3 = 0x02000000,
}},
+ .radio = {
+ .type = CX88_RADIO,
+ .gpio0 = 0x00015702,
+ .gpio1 = 0x0000f207,
+ .gpio2 = 0x00015702,
+ .gpio3 = 0x02000000,
+ },
.mpeg = CX88_MPEG_DVB,
},
[CX88_BOARD_GENIATECH_DVBS] = {
@@ -1314,22 +1341,26 @@ static const struct cx88_board cx88_boards[] = {
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
.gpio0 = 0x84bf,
+ /* 1: TV Audio / FM Mono */
.audioroute = 1,
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
.gpio0 = 0x84bf,
+ /* 2: Line-In */
.audioroute = 2,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
.gpio0 = 0x84bf,
+ /* 2: Line-In */
.audioroute = 2,
}},
- /* FIXME Radio tunes but only noise is heard */
.radio = {
.type = CX88_RADIO,
.gpio0 = 0x84bf,
+ /* 4: FM Stereo (untested) */
+ .audioroute = 8,
},
.mpeg = CX88_MPEG_DVB,
.num_frontends = 2,
@@ -1398,23 +1429,27 @@ static const struct cx88_board cx88_boards[] = {
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
.gpio0 = 0xef88,
+ /* 1: TV Audio / FM Mono */
.audioroute = 1,
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
.gpio0 = 0xef88,
+ /* 2: Line-In */
.audioroute = 2,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
.gpio0 = 0xef88,
+ /* 2: Line-In */
.audioroute = 2,
}},
- /* fixme: Add radio support */
.mpeg = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD,
.radio = {
.type = CX88_RADIO,
.gpio0 = 0xef88,
+ /* 4: FM Stereo (untested) */
+ .audioroute = 8,
},
},
[CX88_BOARD_ADSTECH_PTV_390] = {
@@ -1788,27 +1823,38 @@ static const struct cx88_board cx88_boards[] = {
* d 0 I
* e 1 O
* f 1 O
+ *
+ * WM8775 ADC
+ *
+ * 1: TV Audio / FM Mono
+ * 2: Line-In
+ * 3: Line-In Expansion
+ * 4: FM Stereo
*/
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
.gpio0 = 0xc4bf,
+ /* 1: TV Audio / FM Mono */
.audioroute = 1,
}, {
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
.gpio0 = 0xc4bf,
+ /* 2: Line-In */
.audioroute = 2,
}, {
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
.gpio0 = 0xc4bf,
+ /* 2: Line-In */
.audioroute = 2,
} },
- /* FIXME Radio tunes but only noise is heard */
.radio = {
.type = CX88_RADIO,
.gpio0 = 0xc4bf,
+ /* 4: FM Stereo */
+ .audioroute = 8,
},
.mpeg = CX88_MPEG_DVB,
.num_frontends = 2,
@@ -1861,6 +1907,18 @@ static const struct cx88_board cx88_boards[] = {
} },
.mpeg = CX88_MPEG_DVB,
},
+ [CX88_BOARD_TBS_8910] = {
+ .name = "TBS 8910 DVB-S",
+ .tuner_type = UNSET,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .input = {{
+ .type = CX88_VMUX_DVB,
+ .vmux = 0,
+ } },
+ .mpeg = CX88_MPEG_DVB,
+ },
[CX88_BOARD_TBS_8920] = {
.name = "TBS 8920 DVB-S/S2",
.tuner_type = TUNER_ABSENT,
@@ -1873,6 +1931,18 @@ static const struct cx88_board cx88_boards[] = {
} },
.mpeg = CX88_MPEG_DVB,
},
+ [CX88_BOARD_PROF_6200] = {
+ .name = "Prof 6200 DVB-S",
+ .tuner_type = UNSET,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .input = {{
+ .type = CX88_VMUX_DVB,
+ .vmux = 0,
+ } },
+ .mpeg = CX88_MPEG_DVB,
+ },
[CX88_BOARD_PROF_7300] = {
.name = "PROF 7300 DVB-S/S2",
.tuner_type = UNSET,
@@ -1885,6 +1955,18 @@ static const struct cx88_board cx88_boards[] = {
} },
.mpeg = CX88_MPEG_DVB,
},
+ [CX88_BOARD_SATTRADE_ST4200] = {
+ .name = "SATTRADE ST4200 DVB-S/S2",
+ .tuner_type = UNSET,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .input = {{
+ .type = CX88_VMUX_DVB,
+ .vmux = 0,
+ } },
+ .mpeg = CX88_MPEG_DVB,
+ },
};
/* ------------------------------------------------------------------ */
@@ -1911,7 +1993,11 @@ static const struct cx88_subid cx88_subids[] = {
.subvendor = PCI_VENDOR_ID_ATI,
.subdevice = 0x00f8,
.card = CX88_BOARD_ATI_WONDER_PRO,
- },{
+ }, {
+ .subvendor = PCI_VENDOR_ID_ATI,
+ .subdevice = 0x00f9,
+ .card = CX88_BOARD_ATI_WONDER_PRO,
+ }, {
.subvendor = 0x107d,
.subdevice = 0x6611,
.card = CX88_BOARD_WINFAST2000XP_EXPERT,
@@ -2271,13 +2357,25 @@ static const struct cx88_subid cx88_subids[] = {
.subdevice = 0x2011,
.card = CX88_BOARD_OMICOM_SS4_PCI,
}, {
+ .subvendor = 0x8910,
+ .subdevice = 0x8888,
+ .card = CX88_BOARD_TBS_8910,
+ }, {
.subvendor = 0x8920,
.subdevice = 0x8888,
.card = CX88_BOARD_TBS_8920,
}, {
+ .subvendor = 0xb022,
+ .subdevice = 0x3022,
+ .card = CX88_BOARD_PROF_6200,
+ }, {
.subvendor = 0xB033,
.subdevice = 0x3033,
.card = CX88_BOARD_PROF_7300,
+ }, {
+ .subvendor = 0xb200,
+ .subdevice = 0x4200,
+ .card = CX88_BOARD_SATTRADE_ST4200,
},
};
@@ -2888,8 +2986,11 @@ static void cx88_card_setup(struct cx88_core *core)
case CX88_BOARD_TEVII_S420:
case CX88_BOARD_TEVII_S460:
case CX88_BOARD_OMICOM_SS4_PCI:
+ case CX88_BOARD_TBS_8910:
case CX88_BOARD_TBS_8920:
+ case CX88_BOARD_PROF_6200:
case CX88_BOARD_PROF_7300:
+ case CX88_BOARD_SATTRADE_ST4200:
cx_write(MO_SRST_IO, 0);
msleep(100);
cx_write(MO_SRST_IO, 1);
@@ -3058,8 +3159,8 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
memcpy(&core->board, &cx88_boards[core->boardnr], sizeof(core->board));
- if (!core->board.num_frontends)
- core->board.num_frontends=1;
+ if (!core->board.num_frontends && (core->board.mpeg & CX88_MPEG_DVB))
+ core->board.num_frontends = 1;
info_printk(core, "subsystem: %04x:%04x, board: %s [card=%d,%s], frontend(s): %d\n",
pci->subsystem_vendor, pci->subsystem_device, core->board.name,
diff --git a/linux/drivers/media/video/cx88/cx88-core.c b/linux/drivers/media/video/cx88/cx88-core.c
index 4ce5f7589..c9de13b56 100644
--- a/linux/drivers/media/video/cx88/cx88-core.c
+++ b/linux/drivers/media/video/cx88/cx88-core.c
@@ -574,7 +574,8 @@ void cx88_wakeup(struct cx88_core *core,
mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
}
if (bc != 1)
- printk("%s: %d buffers handled (should be 1)\n",__func__,bc);
+ dprintk(2, "%s: %d buffers handled (should be 1)\n",
+ __func__, bc);
}
void cx88_shutdown(struct cx88_core *core)
@@ -868,6 +869,9 @@ static int set_tvaudio(struct cx88_core *core)
} else if (V4L2_STD_SECAM_L & norm) {
core->tvaudio = WW_L;
+ } else if ((V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H) & norm) {
+ core->tvaudio = WW_BG;
+
} else if (V4L2_STD_SECAM_DK & norm) {
core->tvaudio = WW_DK;
diff --git a/linux/drivers/media/video/cx88/cx88-dvb.c b/linux/drivers/media/video/cx88/cx88-dvb.c
index 1a0f971c6..5a9fafd25 100644
--- a/linux/drivers/media/video/cx88/cx88-dvb.c
+++ b/linux/drivers/media/video/cx88/cx88-dvb.c
@@ -121,7 +121,7 @@ static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, int acquire)
fe_id = videobuf_dvb_find_frontend(&dev->frontends, fe);
if (!fe_id) {
- printk(KERN_ERR "%s() No frontend found\n", __FUNCTION__);
+ printk(KERN_ERR "%s() No frontend found\n", __func__);
return -EINVAL;
}
@@ -582,14 +582,14 @@ static struct cx24116_config tevii_s460_config = {
static struct stv0299_config tevii_tuner_sharp_config = {
.demod_address = 0x68,
- .inittab = sharp_z0194a__inittab,
+ .inittab = sharp_z0194a_inittab,
.mclk = 88000000UL,
.invert = 1,
.skip_reinit = 0,
.lock_output = 1,
.volt13_op0_op1 = STV0299_VOLT13_OP1,
.min_delay_ms = 100,
- .set_symbol_rate = sharp_z0194a__set_symbol_rate,
+ .set_symbol_rate = sharp_z0194a_set_symbol_rate,
.set_ts_params = cx24116_set_ts_param,
};
@@ -605,10 +605,15 @@ static int dvb_register(struct cx8802_dev *dev)
struct videobuf_dvb_frontend *fe0, *fe1 = NULL;
int mfe_shared = 0; /* bus not shared by default */
+ if (0 != core->i2c_rc) {
+ printk(KERN_ERR "%s/2: no i2c-bus available, cannot attach dvb drivers\n", core->name);
+ goto frontend_detach;
+ }
+
/* Get the first frontend */
fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
if (!fe0)
- return -EINVAL;
+ goto frontend_detach;
/* multi-frontend gate control is undefined or defaults to fe0 */
dev->frontends.gate = 0;
@@ -655,38 +660,35 @@ static int dvb_register(struct cx8802_dev *dev)
}
break;
case CX88_BOARD_HAUPPAUGE_HVR3000:
+ /* MFE frontend 1 */
+ mfe_shared = 1;
+ dev->frontends.gate = 2;
/* DVB-S init */
fe0->dvb.frontend = dvb_attach(cx24123_attach,
- &hauppauge_novas_config,
- &dev->core->i2c_adap);
+ &hauppauge_novas_config,
+ &dev->core->i2c_adap);
if (fe0->dvb.frontend) {
- if (!dvb_attach(isl6421_attach, fe0->dvb.frontend,
- &dev->core->i2c_adap, 0x08, ISL6421_DCL, 0x00)) {
- dprintk( 1, "%s(): HVR3000 - DVB-S LNB Init: failed\n", __FUNCTION__);
- }
- } else {
- dprintk( 1, "%s(): HVR3000 - DVB-S Init: failed\n", __FUNCTION__);
+ if (!dvb_attach(isl6421_attach,
+ fe0->dvb.frontend,
+ &dev->core->i2c_adap,
+ 0x08, ISL6421_DCL, 0x00))
+ goto frontend_detach;
}
- /* DVB-T init */
+ /* MFE frontend 2 */
fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2);
- if (fe1) {
- dev->frontends.gate = 2;
- mfe_shared = 1;
- fe1->dvb.frontend = dvb_attach(cx22702_attach,
- &hauppauge_hvr_config,
- &dev->core->i2c_adap);
- if (fe1->dvb.frontend) {
- fe1->dvb.frontend->id = 1;
- if(!dvb_attach(simple_tuner_attach, fe1->dvb.frontend,
- &dev->core->i2c_adap, 0x61,
- TUNER_PHILIPS_FMD1216ME_MK3)) {
- dprintk( 1, "%s(): HVR3000 - DVB-T misc Init: failed\n", __FUNCTION__);
- }
- } else {
- dprintk( 1, "%s(): HVR3000 - DVB-T Init: failed\n", __FUNCTION__);
- }
- } else {
- dprintk( 1, "%s(): HVR3000 - DVB-T Init: can't find frontend 2.\n", __FUNCTION__);
+ if (!fe1)
+ goto frontend_detach;
+ /* DVB-T init */
+ fe1->dvb.frontend = dvb_attach(cx22702_attach,
+ &hauppauge_hvr_config,
+ &dev->core->i2c_adap);
+ if (fe1->dvb.frontend) {
+ fe1->dvb.frontend->id = 1;
+ if (!dvb_attach(simple_tuner_attach,
+ fe1->dvb.frontend,
+ &dev->core->i2c_adap,
+ 0x61, TUNER_PHILIPS_FMD1216ME_MK3))
+ goto frontend_detach;
}
break;
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
@@ -796,7 +798,7 @@ static int dvb_register(struct cx8802_dev *dev)
if (fe0->dvb.frontend)
fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
if (attach_xc3028(0x61, dev) < 0)
- return -EINVAL;
+ goto frontend_detach;
break;
case CX88_BOARD_PCHDTV_HD3000:
fe0->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000,
@@ -1000,50 +1002,51 @@ static int dvb_register(struct cx8802_dev *dev)
}
break;
case CX88_BOARD_HAUPPAUGE_HVR4000:
+ /* MFE frontend 1 */
+ mfe_shared = 1;
+ dev->frontends.gate = 2;
/* DVB-S/S2 Init */
fe0->dvb.frontend = dvb_attach(cx24116_attach,
- &hauppauge_hvr4000_config,
- &dev->core->i2c_adap);
+ &hauppauge_hvr4000_config,
+ &dev->core->i2c_adap);
if (fe0->dvb.frontend) {
- if(!dvb_attach(isl6421_attach, fe0->dvb.frontend,
- &dev->core->i2c_adap, 0x08, ISL6421_DCL, 0x00)) {
- dprintk( 1, "%s(): HVR4000 - DVB-S LNB Init: failed\n", __FUNCTION__);
- }
- } else {
- dprintk( 1, "%s(): HVR4000 - DVB-S Init: failed\n", __FUNCTION__);
+ if (!dvb_attach(isl6421_attach,
+ fe0->dvb.frontend,
+ &dev->core->i2c_adap,
+ 0x08, ISL6421_DCL, 0x00))
+ goto frontend_detach;
}
- /* DVB-T Init */
+ /* MFE frontend 2 */
fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2);
- if (fe1) {
- dev->frontends.gate = 2;
- mfe_shared = 1;
- fe1->dvb.frontend = dvb_attach(cx22702_attach,
- &hauppauge_hvr_config,
- &dev->core->i2c_adap);
- if (fe1->dvb.frontend) {
- fe1->dvb.frontend->id = 1;
- if(!dvb_attach(simple_tuner_attach, fe1->dvb.frontend,
- &dev->core->i2c_adap, 0x61,
- TUNER_PHILIPS_FMD1216ME_MK3)) {
- dprintk( 1, "%s(): HVR4000 - DVB-T misc Init: failed\n", __FUNCTION__);
- }
- } else {
- dprintk( 1, "%s(): HVR4000 - DVB-T Init: failed\n", __FUNCTION__);
- }
- } else {
- dprintk( 1, "%s(): HVR4000 - DVB-T Init: can't find frontend 2.\n", __FUNCTION__);
+ if (!fe1)
+ goto frontend_detach;
+ /* DVB-T Init */
+ fe1->dvb.frontend = dvb_attach(cx22702_attach,
+ &hauppauge_hvr_config,
+ &dev->core->i2c_adap);
+ if (fe1->dvb.frontend) {
+ fe1->dvb.frontend->id = 1;
+ if (!dvb_attach(simple_tuner_attach,
+ fe1->dvb.frontend,
+ &dev->core->i2c_adap,
+ 0x61, TUNER_PHILIPS_FMD1216ME_MK3))
+ goto frontend_detach;
}
break;
case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
fe0->dvb.frontend = dvb_attach(cx24116_attach,
- &hauppauge_hvr4000_config,
- &dev->core->i2c_adap);
+ &hauppauge_hvr4000_config,
+ &dev->core->i2c_adap);
if (fe0->dvb.frontend) {
- dvb_attach(isl6421_attach, fe0->dvb.frontend,
- &dev->core->i2c_adap,
- 0x08, ISL6421_DCL, 0x00);
+ if (!dvb_attach(isl6421_attach,
+ fe0->dvb.frontend,
+ &dev->core->i2c_adap,
+ 0x08, ISL6421_DCL, 0x00))
+ goto frontend_detach;
}
break;
+ case CX88_BOARD_PROF_6200:
+ case CX88_BOARD_TBS_8910:
case CX88_BOARD_TEVII_S420:
fe0->dvb.frontend = dvb_attach(stv0299_attach,
&tevii_tuner_sharp_config,
@@ -1065,7 +1068,6 @@ static int dvb_register(struct cx8802_dev *dev)
goto frontend_detach;
core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
-
}
}
break;
@@ -1073,21 +1075,18 @@ static int dvb_register(struct cx8802_dev *dev)
fe0->dvb.frontend = dvb_attach(cx24116_attach,
&tevii_s460_config,
&core->i2c_adap);
- if (fe0->dvb.frontend != NULL) {
- core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
+ if (fe0->dvb.frontend != NULL)
fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
- }
break;
case CX88_BOARD_OMICOM_SS4_PCI:
case CX88_BOARD_TBS_8920:
case CX88_BOARD_PROF_7300:
+ case CX88_BOARD_SATTRADE_ST4200:
fe0->dvb.frontend = dvb_attach(cx24116_attach,
&hauppauge_hvr4000_config,
&core->i2c_adap);
- if (fe0->dvb.frontend != NULL) {
- core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
+ if (fe0->dvb.frontend != NULL)
fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
- }
break;
default:
printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n",
@@ -1099,7 +1098,7 @@ static int dvb_register(struct cx8802_dev *dev)
printk(KERN_ERR
"%s/2: frontend initialization failed\n",
core->name);
- return -EINVAL;
+ goto frontend_detach;
}
/* define general-purpose callback pointer */
fe0->dvb.frontend->callback = cx88_tuner_callback;
@@ -1117,10 +1116,7 @@ static int dvb_register(struct cx8802_dev *dev)
&dev->pci->dev, adapter_nr, mfe_shared);
frontend_detach:
- if (fe0->dvb.frontend) {
- dvb_frontend_detach(fe0->dvb.frontend);
- fe0->dvb.frontend = NULL;
- }
+ videobuf_dvb_dealloc_frontends(&dev->frontends);
return -EINVAL;
}
@@ -1208,8 +1204,7 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv)
{
struct cx88_core *core = drv->core;
struct cx8802_dev *dev = drv->core->dvbdev;
- int err, i;
- struct videobuf_dvb_frontend *fe;
+ int err;
dprintk( 1, "%s\n", __func__);
dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
@@ -1225,39 +1220,58 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv)
/* If vp3054 isn't enabled, a stub will just return 0 */
err = vp3054_i2c_probe(dev);
if (0 != err)
- goto fail_core;
+ goto fail_probe;
/* dvb stuff */
printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name);
dev->ts_gen_cntrl = 0x0c;
- for (i = 1; i <= core->board.num_frontends; i++) {
- fe = videobuf_dvb_get_frontend(&core->dvbdev->frontends, i);
- if (!fe) {
- printk(KERN_ERR "%s() failed to get frontend(%d)\n", __FUNCTION__, i);
- continue;
+ err = -ENODEV;
+ if (core->board.num_frontends) {
+ struct videobuf_dvb_frontend *fe;
+ int i;
+
+ for (i = 1; i <= core->board.num_frontends; i++) {
+ fe = videobuf_dvb_get_frontend(&core->dvbdev->frontends, i);
+ if (fe == NULL) {
+ printk(KERN_ERR "%s() failed to get frontend(%d)\n",
+ __func__, i);
+ goto fail_probe;
+ }
+ videobuf_queue_sg_init(&fe->dvb.dvbq, &dvb_qops,
+ &dev->pci->dev, &dev->slock,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ V4L2_FIELD_TOP,
+ sizeof(struct cx88_buffer),
+ dev);
+ /* init struct videobuf_dvb */
+ fe->dvb.name = dev->core->name;
}
- videobuf_queue_sg_init(&fe->dvb.dvbq, &dvb_qops,
- &dev->pci->dev, &dev->slock,
- V4L2_BUF_TYPE_VIDEO_CAPTURE,
- V4L2_FIELD_TOP,
- sizeof(struct cx88_buffer),
- dev);
- /* init struct videobuf_dvb */
- fe->dvb.name = dev->core->name;
+ } else {
+ /* no frontends allocated */
+ printk(KERN_ERR "%s/2 .num_frontends should be non-zero\n",
+ core->name);
+ goto fail_core;
}
err = dvb_register(dev);
- if (err != 0)
+ if (err)
+ /* frontends/adapter de-allocated in dvb_register */
printk(KERN_ERR "%s/2: dvb_register failed (err = %d)\n",
core->name, err);
+ return err;
+fail_probe:
+ videobuf_dvb_dealloc_frontends(&core->dvbdev->frontends);
fail_core:
return err;
}
static int cx8802_dvb_remove(struct cx8802_driver *drv)
{
+ struct cx88_core *core = drv->core;
struct cx8802_dev *dev = drv->core->dvbdev;
+ dprintk( 1, "%s\n", __func__);
+
videobuf_dvb_unregister_bus(&dev->frontends);
vp3054_i2c_remove(dev);
diff --git a/linux/drivers/media/video/cx88/cx88-i2c.c b/linux/drivers/media/video/cx88/cx88-i2c.c
index 01de23007..1ab691d20 100644
--- a/linux/drivers/media/video/cx88/cx88-i2c.c
+++ b/linux/drivers/media/video/cx88/cx88-i2c.c
@@ -116,8 +116,10 @@ static int detach_inform(struct i2c_client *client)
void cx88_call_i2c_clients(struct cx88_core *core, unsigned int cmd, void *arg)
{
+#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)
struct videobuf_dvb_frontends *f = &core->dvbdev->frontends;
struct videobuf_dvb_frontend *fe = NULL;
+#endif
if (0 != core->i2c_rc)
return;
diff --git a/linux/drivers/media/video/cx88/cx88-mpeg.c b/linux/drivers/media/video/cx88/cx88-mpeg.c
index 88c237790..dbad45a35 100644
--- a/linux/drivers/media/video/cx88/cx88-mpeg.c
+++ b/linux/drivers/media/video/cx88/cx88-mpeg.c
@@ -808,8 +808,7 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev,
{
struct cx8802_dev *dev;
struct cx88_core *core;
- struct videobuf_dvb_frontend *demod;
- int err,i;
+ int err;
/* general setup */
core = cx88_core_get(pci_dev);
@@ -822,11 +821,6 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev,
if (!core->board.mpeg)
goto fail_core;
- if (!core->board.num_frontends) {
- printk(KERN_ERR "%s() .num_frontends should be non-zero, err = %d\n", __FUNCTION__, err);
- goto fail_core;
- }
-
err = -ENOMEM;
dev = kzalloc(sizeof(*dev),GFP_KERNEL);
if (NULL == dev)
@@ -841,19 +835,28 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev,
INIT_LIST_HEAD(&dev->drvlist);
list_add_tail(&dev->devlist,&cx8802_devlist);
+#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)
mutex_init(&dev->frontends.lock);
- INIT_LIST_HEAD(&dev->frontends.frontend.felist);
-
- printk(KERN_INFO "%s() allocating %d frontend(s)\n", __FUNCTION__, core->board.num_frontends);
-
- for (i = 1; i <= core->board.num_frontends; i++) {
- demod = videobuf_dvb_alloc_frontend(dev, &dev->frontends, i);
- if(demod == NULL) {
- printk(KERN_ERR "%s() failed to alloc\n", __FUNCTION__);
- err = -ENOMEM;
- goto fail_free;
+ INIT_LIST_HEAD(&dev->frontends.felist);
+
+ if (core->board.num_frontends) {
+ struct videobuf_dvb_frontend *fe;
+ int i;
+
+ printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__,
+ core->board.num_frontends);
+ for (i = 1; i <= core->board.num_frontends; i++) {
+ fe = videobuf_dvb_alloc_frontend(&dev->frontends, i);
+ if(fe == NULL) {
+ printk(KERN_ERR "%s() failed to alloc\n",
+ __func__);
+ videobuf_dvb_dealloc_frontends(&dev->frontends);
+ err = -ENOMEM;
+ goto fail_free;
+ }
}
}
+#endif
/* Maintain a reference so cx88-video can query the 8802 device. */
core->dvbdev = dev;
diff --git a/linux/drivers/media/video/cx88/cx88-tvaudio.c b/linux/drivers/media/video/cx88/cx88-tvaudio.c
index 5eb95dbbe..0039354cf 100644
--- a/linux/drivers/media/video/cx88/cx88-tvaudio.c
+++ b/linux/drivers/media/video/cx88/cx88-tvaudio.c
@@ -771,6 +771,14 @@ void cx88_set_tvaudio(struct cx88_core *core)
case WW_FM:
set_audio_standard_FM(core, radio_deemphasis);
break;
+ case WW_I2SADC:
+ set_audio_start(core, 0x01);
+ /* Slave/Philips/Autobaud */
+ cx_write(AUD_I2SINPUTCNTL, 0);
+ /* Switch to "I2S ADC mode" */
+ cx_write(AUD_I2SCNTL, 0x1);
+ set_audio_finish(core, EN_I2SIN_ENABLE);
+ break;
case WW_NONE:
default:
printk("%s/0: unknown tv audio mode [%d]\n",
@@ -948,6 +956,9 @@ void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual)
break;
}
break;
+ case WW_I2SADC:
+ /* DO NOTHING */
+ break;
}
if (UNSET != ctl) {
diff --git a/linux/drivers/media/video/cx88/cx88-video.c b/linux/drivers/media/video/cx88/cx88-video.c
index c4fdb6da2..40136a431 100644
--- a/linux/drivers/media/video/cx88/cx88-video.c
+++ b/linux/drivers/media/video/cx88/cx88-video.c
@@ -427,24 +427,7 @@ int cx88_video_mux(struct cx88_core *core, unsigned int input)
/* if there are audioroutes defined, we have an external
ADC to deal with audio */
-
if (INPUT(input).audioroute) {
-
- /* cx2388's C-ADC is connected to the tuner only.
- When used with S-Video, that ADC is busy dealing with
- chroma, so an external must be used for baseband audio */
-
- if (INPUT(input).type != CX88_VMUX_TELEVISION &&
- INPUT(input).type != CX88_RADIO) {
- /* "ADC mode" */
- cx_write(AUD_I2SCNTL, 0x1);
- cx_set(AUD_CTL, EN_I2SIN_ENABLE);
- } else {
- /* Normal mode */
- cx_write(AUD_I2SCNTL, 0x0);
- cx_clear(AUD_CTL, EN_I2SIN_ENABLE);
- }
-
/* The wm8775 module has the "2" route hardwired into
the initialization. Some boards may use different
routes for different inputs. HVR-1300 surely does */
@@ -455,9 +438,19 @@ int cx88_video_mux(struct cx88_core *core, unsigned int input)
route.input = INPUT(input).audioroute;
cx88_call_i2c_clients(core,
VIDIOC_INT_S_AUDIO_ROUTING, &route);
-
}
-
+ /* cx2388's C-ADC is connected to the tuner only.
+ When used with S-Video, that ADC is busy dealing with
+ chroma, so an external must be used for baseband audio */
+ if (INPUT(input).type != CX88_VMUX_TELEVISION ) {
+ /* "I2S ADC mode" */
+ core->tvaudio = WW_I2SADC;
+ cx88_set_tvaudio(core);
+ } else {
+ /* Normal mode */
+ cx_write(AUD_I2SCNTL, 0x0);
+ cx_clear(AUD_CTL, EN_I2SIN_ENABLE);
+ }
}
return 0;
@@ -1058,9 +1051,24 @@ static int video_open(struct inode *inode, struct file *file)
cx_write(MO_GP0_IO, core->board.radio.gpio0);
cx_write(MO_GP1_IO, core->board.radio.gpio1);
cx_write(MO_GP2_IO, core->board.radio.gpio2);
- core->tvaudio = WW_FM;
- cx88_set_tvaudio(core);
- cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1);
+ if (core->board.radio.audioroute) {
+ if(core->board.audio_chip &&
+ core->board.audio_chip == V4L2_IDENT_WM8775) {
+ struct v4l2_routing route;
+
+ route.input = core->board.radio.audioroute;
+ cx88_call_i2c_clients(core,
+ VIDIOC_INT_S_AUDIO_ROUTING, &route);
+ }
+ /* "I2S ADC mode" */
+ core->tvaudio = WW_I2SADC;
+ cx88_set_tvaudio(core);
+ } else {
+ /* FM Mode */
+ core->tvaudio = WW_FM;
+ cx88_set_tvaudio(core);
+ cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1);
+ }
cx88_call_i2c_clients(core,AUDC_SET_RADIO,NULL);
}
unlock_kernel();
@@ -1445,8 +1453,12 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
struct cx8800_fh *fh = priv;
struct cx8800_dev *dev = fh->dev;
- if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE))
+ /* We should remember that this driver also supports teletext, */
+ /* so we have to test if the v4l2_buf_type is VBI capture data. */
+ if (unlikely((fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+ (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE)))
return -EINVAL;
+
if (unlikely(i != fh->type))
return -EINVAL;
@@ -1461,8 +1473,10 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
struct cx8800_dev *dev = fh->dev;
int err, res;
- if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ if ((fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+ (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE))
return -EINVAL;
+
if (i != fh->type)
return -EINVAL;
@@ -2177,7 +2191,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
goto fail_unreg;
}
printk(KERN_INFO "%s/0: registered device video%d [v4l2]\n",
- core->name,dev->video_dev->minor & 0x1f);
+ core->name, dev->video_dev->num);
dev->vbi_dev = cx88_vdev_init(core,dev->pci,&cx8800_vbi_template,"vbi");
err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI,
@@ -2188,7 +2202,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
goto fail_unreg;
}
printk(KERN_INFO "%s/0: registered device vbi%d\n",
- core->name,dev->vbi_dev->minor & 0x1f);
+ core->name, dev->vbi_dev->num);
if (core->board.radio.type == CX88_RADIO) {
dev->radio_dev = cx88_vdev_init(core,dev->pci,
@@ -2201,7 +2215,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
goto fail_unreg;
}
printk(KERN_INFO "%s/0: registered device radio%d\n",
- core->name,dev->radio_dev->minor & 0x1f);
+ core->name, dev->radio_dev->num);
}
/* everything worked */
diff --git a/linux/drivers/media/video/cx88/cx88.h b/linux/drivers/media/video/cx88/cx88.h
index 774c0b9b1..6f8e575a3 100644
--- a/linux/drivers/media/video/cx88/cx88.h
+++ b/linux/drivers/media/video/cx88/cx88.h
@@ -54,12 +54,11 @@
/* ----------------------------------------------------------- */
/* defines and enums */
-/* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */
-#define CX88_NORMS (\
- V4L2_STD_NTSC_M| V4L2_STD_NTSC_M_JP| V4L2_STD_NTSC_443 | \
- V4L2_STD_PAL_BG| V4L2_STD_PAL_DK | V4L2_STD_PAL_I | \
- V4L2_STD_PAL_M | V4L2_STD_PAL_N | V4L2_STD_PAL_Nc | \
- V4L2_STD_PAL_60| V4L2_STD_SECAM_L | V4L2_STD_SECAM_DK )
+/* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM/LC */
+#define CX88_NORMS (V4L2_STD_ALL \
+ & ~V4L2_STD_PAL_H \
+ & ~V4L2_STD_NTSC_M_KR \
+ & ~V4L2_STD_SECAM_LC)
#define FORMAT_FLAGS_PACKED 0x01
#define FORMAT_FLAGS_PLANAR 0x02
@@ -230,6 +229,9 @@ extern struct sram_channel cx88_sram_channels[];
#define CX88_BOARD_TEVII_S420 73
#define CX88_BOARD_PROLINK_PV_GLOBAL_XTREME 74
#define CX88_BOARD_PROF_7300 75
+#define CX88_BOARD_SATTRADE_ST4200 76
+#define CX88_BOARD_TBS_8910 77
+#define CX88_BOARD_PROF_6200 78
enum cx88_itype {
CX88_VMUX_COMPOSITE1 = 1,
@@ -356,6 +358,7 @@ struct cx88_core {
/* various v4l controls */
u32 freq;
atomic_t users;
+ atomic_t mpeg_users;
/* cx88-video needs to access cx8802 for hybrid tuner pll access. */
struct cx8802_dev *dvbdev;
@@ -651,6 +654,7 @@ extern void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl);
#define WW_EIAJ 7
#define WW_I2SPT 8
#define WW_FM 9
+#define WW_I2SADC 10
void cx88_set_tvaudio(struct cx88_core *core);
void cx88_newstation(struct cx88_core *core);
diff --git a/linux/drivers/media/video/dabusb.c b/linux/drivers/media/video/dabusb.c
index 21280dbc3..7ba206b34 100644
--- a/linux/drivers/media/video/dabusb.c
+++ b/linux/drivers/media/video/dabusb.c
@@ -202,7 +202,7 @@ static void dabusb_iso_complete (struct urb *purb)
err("dabusb_iso_complete: invalid len %d", len);
}
else
- warn("dabusb_iso_complete: corrupted packet status: %d", purb->iso_frame_desc[i].status);
+ dev_warn(&purb->dev->dev, "dabusb_iso_complete: corrupted packet status: %d\n", purb->iso_frame_desc[i].status);
if (dst != purb->actual_length)
err("dst!=purb->actual_length:%d!=%d", dst, purb->actual_length);
}
@@ -299,7 +299,7 @@ static int dabusb_bulk (pdabusb_t s, pbulk_transfer_t pb)
}
if( ret == -EPIPE ) {
- warn("CLEAR_FEATURE request to remove STALL condition.");
+ dev_warn(&s->usbdev->dev, "CLEAR_FEATURE request to remove STALL condition.\n");
if(usb_clear_halt(s->usbdev, usb_pipeendpoint(pipe)))
err("request failed");
}
diff --git a/linux/drivers/media/video/em28xx/em28xx-audio.c b/linux/drivers/media/video/em28xx/em28xx-audio.c
index d6856b331..b86b0870d 100644
--- a/linux/drivers/media/video/em28xx/em28xx-audio.c
+++ b/linux/drivers/media/video/em28xx/em28xx-audio.c
@@ -496,11 +496,12 @@ static int em28xx_audio_init(struct em28xx *dev)
struct snd_card *card;
#endif
static int devnr;
- int ret, err;
+ int err;
- if (dev->has_audio_class) {
+ if (dev->has_alsa_audio != 1) {
/* This device does not support the extension (in this case
- the device is expecting the snd-usb-audio module */
+ the device is expecting the snd-usb-audio module or
+ doesn't have analog audio support at all) */
return 0;
}
@@ -521,7 +522,12 @@ static int em28xx_audio_init(struct em28xx *dev)
}
spin_lock_init(&adev->slock);
- ret = snd_pcm_new(card, "Em28xx Audio", 0, 0, 1, &pcm);
+ err = snd_pcm_new(card, "Em28xx Audio", 0, 0, 1, &pcm);
+ if (err < 0) {
+ snd_card_free(card);
+ return err;
+ }
+
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_em28xx_pcm_capture);
pcm->info_flags = 0;
pcm->private_data = dev;
@@ -533,7 +539,7 @@ static int em28xx_audio_init(struct em28xx *dev)
err = snd_card_register(card);
if (err < 0) {
snd_card_free(card);
- return -ENOMEM;
+ return err;
}
adev->sndcard = card;
adev->udev = dev->udev;
@@ -547,9 +553,10 @@ static int em28xx_audio_fini(struct em28xx *dev)
if (dev == NULL)
return 0;
- if (dev->has_audio_class) {
+ if (dev->has_alsa_audio != 1) {
/* This device does not support the extension (in this case
- the device is expecting the snd-usb-audio module */
+ the device is expecting the snd-usb-audio module or
+ doesn't have analog audio support at all) */
return 0;
}
diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c
index 4f078da31..57c91838e 100644
--- a/linux/drivers/media/video/em28xx/em28xx-cards.c
+++ b/linux/drivers/media/video/em28xx/em28xx-cards.c
@@ -593,6 +593,7 @@ struct em28xx_board em28xx_boards[] = {
.mts_firmware = 1,
.has_12mhz_i2s = 1,
.has_dvb = 1,
+ .ir_codes = ir_codes_hauppauge_new,
.decoder = EM28XX_TVP5150,
.input = { {
.type = EM28XX_VMUX_TELEVISION,
@@ -616,6 +617,7 @@ struct em28xx_board em28xx_boards[] = {
.mts_firmware = 1,
.has_12mhz_i2s = 1,
.has_dvb = 1,
+ .ir_codes = ir_codes_pinnacle_pctv_hd,
.decoder = EM28XX_TVP5150,
.input = { {
.type = EM28XX_VMUX_TELEVISION,
@@ -639,6 +641,7 @@ struct em28xx_board em28xx_boards[] = {
.mts_firmware = 1,
.has_12mhz_i2s = 1,
.has_dvb = 1,
+ .ir_codes = ir_codes_ati_tv_wonder_hd_600,
.decoder = EM28XX_TVP5150,
.input = { {
.type = EM28XX_VMUX_TELEVISION,
@@ -1088,6 +1091,21 @@ struct em28xx_board em28xx_boards[] = {
.amux = EM28XX_AMUX_LINE_IN,
} },
},
+ [EM2874_BOARD_PINNACLE_PCTV_80E] = {
+ .name = "Pinnacle PCTV HD Mini",
+ .vchannels = 0,
+ .tuner_type = TUNER_ABSENT,
+ .has_dvb = 1,
+ .ir_codes = ir_codes_pinnacle_pctv_hd,
+ .decoder = EM28XX_NODECODER,
+#ifdef DJH_DEBUG
+ .input = { {
+ .type = EM28XX_VMUX_TELEVISION,
+ .vmux = TVP5150_COMPOSITE0,
+ .amux = EM28XX_AMUX_LINE_IN,
+ } },
+#endif
+ },
};
const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards);
@@ -1185,6 +1203,8 @@ struct usb_device_id em28xx_id_table [] = {
.driver_info = EM2882_BOARD_PINNACLE_HYBRID_PRO },
{ USB_DEVICE(0x2304, 0x0227),
.driver_info = EM2880_BOARD_PINNACLE_PCTV_HD_PRO },
+ { USB_DEVICE(0x2304, 0x023f),
+ .driver_info = EM2874_BOARD_PINNACLE_PCTV_80E },
{ USB_DEVICE(0x0413, 0x6023),
.driver_info = EM2800_BOARD_LEADTEK_WINFAST_USBII },
{ USB_DEVICE(0x093b, 0xa005),
@@ -1260,6 +1280,17 @@ static struct em28xx_reg_seq em2882_terratec_hybrid_xs_digital[] = {
{ -1, -1, -1, -1},
};
+/* Pinnacle PCTV HD Mini (80e) GPIOs
+ 0-5: not used
+ 6: demod reset, active low
+ 7: LED on, active high */
+static struct em28xx_reg_seq em2874_pinnacle_80e_digital[] = {
+ {EM28XX_R06_I2C_CLK, 0x45, 0xff, 10}, /*400 KHz*/
+ {EM2874_R80_GPIO, 0x80, 0xff, 100},/*Demod reset*/
+ {EM2874_R80_GPIO, 0xc0, 0xff, 10},
+ { -1, -1, -1, -1},
+};
+
/*
* EEPROM hash table for devices with generic USB IDs
*/
@@ -1307,6 +1338,7 @@ static void em28xx_set_model(struct em28xx *dev)
dev->max_range_640_480 = em28xx_boards[dev->model].max_range_640_480;
dev->has_dvb = em28xx_boards[dev->model].has_dvb;
dev->has_snapshot_button = em28xx_boards[dev->model].has_snapshot_button;
+ dev->ir_codes = em28xx_boards[dev->model].ir_codes;
dev->valid = em28xx_boards[dev->model].valid;
}
@@ -1317,17 +1349,34 @@ void em28xx_pre_card_setup(struct em28xx *dev)
{
int rc;
- rc = em28xx_read_reg(dev, EM2880_R04_GPO);
- if (rc >= 0)
- dev->reg_gpo = rc;
+ /* Set the default GPO/GPIO for legacy devices */
+ dev->reg_gpo_num = EM2880_R04_GPO;
+ dev->reg_gpio_num = EM28XX_R08_GPIO;
dev->wait_after_write = 5;
+
+ /* Based on the Chip ID, set the device configuration */
rc = em28xx_read_reg(dev, EM28XX_R0A_CHIPID);
if (rc > 0) {
+ dev->chip_id = rc;
switch (rc) {
+ case CHIP_ID_EM2750:
+ em28xx_info("chip ID is em2750\n");
+ break;
+ case CHIP_ID_EM2820:
+ em28xx_info("chip ID is em2820\n");
+ break;
+ case CHIP_ID_EM2840:
+ em28xx_info("chip ID is em2840\n");
+ break;
case CHIP_ID_EM2860:
em28xx_info("chip ID is em2860\n");
break;
+ case CHIP_ID_EM2874:
+ em28xx_info("chip ID is em2874\n");
+ dev->reg_gpio_num = EM2874_R80_GPIO;
+ dev->wait_after_write = 0;
+ break;
case CHIP_ID_EM2883:
em28xx_info("chip ID is em2882/em2883\n");
dev->wait_after_write = 0;
@@ -1336,6 +1385,12 @@ void em28xx_pre_card_setup(struct em28xx *dev)
em28xx_info("em28xx chip ID = %d\n", rc);
}
}
+
+ /* Prepopulate cached GPO register content */
+ rc = em28xx_read_reg(dev, dev->reg_gpo_num);
+ if (rc >= 0)
+ dev->reg_gpo = rc;
+
em28xx_set_model(dev);
/* request some modules */
@@ -1509,6 +1564,13 @@ void em28xx_pre_card_setup(struct em28xx *dev)
/* enables audio for that device */
em28xx_write_regs_req(dev, 0x00, 0x08, "\xfd", 1);
break;
+
+ case EM2874_BOARD_PINNACLE_PCTV_80E:
+ /* Set 400 KHz clock */
+ em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x45", 1);
+
+ dev->digital_gpio = em2874_pinnacle_80e_digital;
+ break;
}
em28xx_gpio_set(dev, dev->tun_analog_gpio);
@@ -1717,6 +1779,7 @@ void em28xx_card_setup(struct em28xx *dev)
em28xx_set_model(dev);
dev->tuner_type = em28xx_boards[dev->model].tuner_type;
+ dev->tuner_addr = em28xx_boards[dev->model].tuner_addr;
/* request some modules */
switch (dev->model) {
@@ -1800,4 +1863,6 @@ void em28xx_card_setup(struct em28xx *dev)
#endif
em28xx_config_tuner(dev);
+
+ em28xx_ir_init(dev);
}
diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c
index 1a30e361c..ef6830cd5 100644
--- a/linux/drivers/media/video/em28xx/em28xx-core.c
+++ b/linux/drivers/media/video/em28xx/em28xx-core.c
@@ -69,19 +69,29 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg,
int ret, byte;
if (dev->state & DEV_DISCONNECTED)
- return(-ENODEV);
+ return -ENODEV;
+
+ if (len > URB_MAX_CTRL_SIZE)
+ return -EINVAL;
em28xx_regdbg("req=%02x, reg=%02x ", req, reg);
ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 0x0000, reg, buf, len, HZ);
+ 0x0000, reg, dev->urb_buf, len, HZ);
+ if (ret < 0) {
+ if (reg_debug)
+ printk(" failed!\n");
+ return ret;
+ }
+
+ if (len)
+ memcpy(buf, dev->urb_buf, len);
if (reg_debug) {
- printk(ret < 0 ? " failed!\n" : "%02x values: ", ret);
+ printk("%02x values: ", ret);
for (byte = 0; byte < len; byte++)
printk(" %02x", (unsigned char)buf[byte]);
-
printk("\n");
}
@@ -104,14 +114,16 @@ int em28xx_read_reg_req(struct em28xx *dev, u8 req, u16 reg)
ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 0x0000, reg, &val, 1, HZ);
+ 0x0000, reg, dev->urb_buf, 1, HZ);
+ if (ret < 0) {
+ printk(" failed!\n");
+ return ret;
+ }
- if (reg_debug)
- printk(ret < 0 ? " failed!\n" :
- "%02x\n", (unsigned char) val);
+ val = dev->urb_buf[0];
- if (ret < 0)
- return ret;
+ if (reg_debug)
+ printk("%02x\n", (unsigned char) val);
return val;
}
@@ -130,19 +142,13 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
{
int ret;
- /*usb_control_msg seems to expect a kmalloced buffer */
- unsigned char *bufs;
-
if (dev->state & DEV_DISCONNECTED)
return -ENODEV;
- if (len < 1)
+ if ((len < 1) || (len > URB_MAX_CTRL_SIZE))
return -EINVAL;
- bufs = kmalloc(len, GFP_KERNEL);
-
em28xx_regdbg("req=%02x reg=%02x:", req, reg);
-
if (reg_debug) {
int i;
for (i = 0; i < len; ++i)
@@ -150,16 +156,14 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
printk("\n");
}
- if (!bufs)
- return -ENOMEM;
- memcpy(bufs, buf, len);
+ memcpy(dev->urb_buf, buf, len);
ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), req,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 0x0000, reg, bufs, len, HZ);
+ 0x0000, reg, dev->urb_buf, len, HZ);
+
if (dev->wait_after_write)
msleep(dev->wait_after_write);
- kfree(bufs);
return ret;
}
@@ -175,9 +179,9 @@ int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len)
Not sure what happens on reading GPO register.
*/
if (rc >= 0) {
- if (reg == EM2880_R04_GPO)
+ if (reg == dev->reg_gpo_num)
dev->reg_gpo = buf[0];
- else if (reg == EM28XX_R08_GPIO)
+ else if (reg == dev->reg_gpio_num)
dev->reg_gpio = buf[0];
}
@@ -196,9 +200,9 @@ static int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val,
u8 newval;
/* Uses cache for gpo/gpio registers */
- if (reg == EM2880_R04_GPO)
+ if (reg == dev->reg_gpo_num)
oldval = dev->reg_gpo;
- else if (reg == EM28XX_R08_GPIO)
+ else if (reg == dev->reg_gpio_num)
oldval = dev->reg_gpio;
else
oldval = em28xx_read_reg(dev, reg);
@@ -270,6 +274,8 @@ static int em28xx_set_audio_source(struct em28xx *dev)
break;
case EM28XX_AMUX_LINE_IN:
input = EM28XX_AUDIO_SRC_LINE;
+ video = disable;
+ line = enable;
break;
case EM28XX_AMUX_AC97_VIDEO:
input = EM28XX_AUDIO_SRC_LINE;
@@ -290,11 +296,11 @@ static int em28xx_set_audio_source(struct em28xx *dev)
/* Sets AC97 mixer registers
This is seems to be needed, even for non-ac97 configs
*/
- ret = em28xx_write_ac97(dev, EM28XX_R14_VIDEO_AC97, video);
+ ret = em28xx_write_ac97(dev, AC97_VIDEO_VOL, video);
if (ret < 0)
return ret;
- ret = em28xx_write_ac97(dev, EM28XX_R10_LINE_IN_AC97, line);
+ ret = em28xx_write_ac97(dev, AC97_LINEIN_VOL, line);
return ret;
}
@@ -310,7 +316,7 @@ int em28xx_audio_analog_set(struct em28xx *dev)
/* Mute */
s[1] |= 0x80;
- ret = em28xx_write_ac97(dev, EM28XX_R02_MASTER_AC97, s);
+ ret = em28xx_write_ac97(dev, AC97_MASTER_VOL, s);
if (ret < 0)
return ret;
@@ -332,7 +338,7 @@ int em28xx_audio_analog_set(struct em28xx *dev)
/* Unmute device */
if (!dev->mute)
s[1] &= ~0x80;
- ret = em28xx_write_ac97(dev, EM28XX_R02_MASTER_AC97, s);
+ ret = em28xx_write_ac97(dev, AC97_MASTER_VOL, s);
return ret;
}
@@ -359,6 +365,24 @@ int em28xx_colorlevels_set_default(struct em28xx *dev)
int em28xx_capture_start(struct em28xx *dev, int start)
{
int rc;
+
+ if (dev->chip_id == CHIP_ID_EM2874) {
+ /* The Transport Stream Enable Register moved in em2874 */
+ if (!start) {
+ rc = em28xx_write_reg_bits(dev, EM2874_R5F_TS_ENABLE,
+ 0x00,
+ EM2874_TS1_CAPTURE_ENABLE);
+ return rc;
+ }
+
+ /* Enable Transport Stream */
+ rc = em28xx_write_reg_bits(dev, EM2874_R5F_TS_ENABLE,
+ EM2874_TS1_CAPTURE_ENABLE,
+ EM2874_TS1_CAPTURE_ENABLE);
+ return rc;
+ }
+
+
/* FIXME: which is the best order? */
/* video registers are sampled by VREF */
rc = em28xx_write_reg_bits(dev, EM28XX_R0C_USBSUSP,
diff --git a/linux/drivers/media/video/em28xx/em28xx-i2c.c b/linux/drivers/media/video/em28xx/em28xx-i2c.c
index 3bab56b99..ec3e3b157 100644
--- a/linux/drivers/media/video/em28xx/em28xx-i2c.c
+++ b/linux/drivers/media/video/em28xx/em28xx-i2c.c
@@ -332,14 +332,25 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
struct em28xx_eeprom *em_eeprom = (void *)eedata;
int i, err, size = len, block;
+ if (dev->chip_id == CHIP_ID_EM2874) {
+ /* Empia switched to a 16-bit addressable eeprom in newer
+ devices. While we could certainly write a routine to read
+ the eeprom, there is nothing of use in there that cannot be
+ accessed through registers, and there is the risk that we
+ could corrupt the eeprom (since a 16-bit read call is
+ interpreted as a write call by 8-bit eeproms).
+ */
+ return 0;
+ }
+
dev->i2c_client.addr = 0xa0 >> 1;
/* Check if board has eeprom */
err = i2c_master_recv(&dev->i2c_client, &buf, 0);
if (err < 0) {
- em28xx_errdev("%s: i2c_master_recv failed! err [%d]\n",
- __func__, err);
- return err;
+ em28xx_errdev("board has no eeprom\n");
+ memset(eedata, 0, len);
+ return -ENODEV;
}
buf = 0;
@@ -609,14 +620,16 @@ int em28xx_i2c_register(struct em28xx *dev)
dev->i2c_client.adapter = &dev->i2c_adap;
retval = em28xx_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata));
- if (retval < 0) {
+ if ((retval < 0) && (retval != -ENODEV)) {
em28xx_errdev("%s: em28xx_i2_eeprom failed! retval [%d]\n",
__func__, retval);
+
return retval;
}
if (i2c_scan)
em28xx_do_i2c_scan(dev);
+
return 0;
}
diff --git a/linux/drivers/media/video/em28xx/em28xx-input.c b/linux/drivers/media/video/em28xx/em28xx-input.c
index 8d21eaad9..29900920d 100644
--- a/linux/drivers/media/video/em28xx/em28xx-input.c
+++ b/linux/drivers/media/video/em28xx/em28xx-input.c
@@ -39,12 +39,48 @@ static unsigned int ir_debug;
module_param(ir_debug, int, 0644);
MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
-#define dprintk(fmt, arg...) \
+#define i2cdprintk(fmt, arg...) \
if (ir_debug) { \
printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg); \
}
-/* ----------------------------------------------------------------------- */
+#define dprintk(fmt, arg...) \
+ if (ir_debug) { \
+ printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \
+ }
+
+/**********************************************************
+ Polling structure used by em28xx IR's
+ **********************************************************/
+
+struct em28xx_ir_poll_result {
+ unsigned int toggle_bit:1;
+ unsigned int read_count:7;
+ u8 rc_address;
+ u8 rc_data[4]; /* 1 byte on em2860/2880, 4 on em2874 */
+};
+
+struct em28xx_IR {
+ struct em28xx *dev;
+ struct input_dev *input;
+ struct ir_input_state ir;
+ char name[32];
+ char phys[32];
+
+ /* poll external decoder */
+ int polling;
+ struct work_struct work;
+ struct timer_list timer;
+ unsigned int last_toggle:1;
+ unsigned int last_readcount;
+ unsigned int repeat_interval;
+
+ int (*get_key)(struct em28xx_IR *, struct em28xx_ir_poll_result *);
+};
+
+/**********************************************************
+ I2C IR based get keycodes - should be used with ir-kbd-i2c
+ **********************************************************/
int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
{
@@ -52,7 +88,7 @@ int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
/* poll IR chip */
if (1 != i2c_master_recv(&ir->c, &b, 1)) {
- dprintk("read error\n");
+ i2cdprintk("read error\n");
return -EIO;
}
@@ -60,7 +96,7 @@ int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
down, while 0xff indicates that no button is hold
down. 0xfe sequences are sometimes interrupted by 0xFF */
- dprintk("key %02x\n", b);
+ i2cdprintk("key %02x\n", b);
if (b == 0xff)
return 0;
@@ -74,7 +110,6 @@ int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
return 1;
}
-
int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
{
unsigned char buf[2];
@@ -103,7 +138,7 @@ int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
((buf[0]&0x10)>>3) | /* 0000 0010 */
((buf[0]&0x20)>>5); /* 0000 0001 */
- dprintk("ir hauppauge (em2840): code=0x%02x (rcv=0x%02x)\n",
+ i2cdprintk("ir hauppauge (em2840): code=0x%02x (rcv=0x%02x)\n",
code, buf[0]);
/* return key */
@@ -120,11 +155,11 @@ int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key,
/* poll IR chip */
if (3 != i2c_master_recv(&ir->c, buf, 3)) {
- dprintk("read error\n");
+ i2cdprintk("read error\n");
return -EIO;
}
- dprintk("key %02x\n", buf[2]&0x3f);
+ i2cdprintk("key %02x\n", buf[2]&0x3f);
if (buf[0] != 0x00)
return 0;
@@ -134,6 +169,276 @@ int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key,
return 1;
}
+/**********************************************************
+ Poll based get keycode functions
+ **********************************************************/
+
+/* This is for the em2860/em2880 */
+static int default_polling_getkey(struct em28xx_IR *ir,
+ struct em28xx_ir_poll_result *poll_result)
+{
+ struct em28xx *dev = ir->dev;
+ int rc;
+ u8 msg[3] = { 0, 0, 0 };
+
+ /* Read key toggle, brand, and key code
+ on registers 0x45, 0x46 and 0x47
+ */
+ rc = dev->em28xx_read_reg_req_len(dev, 0, EM28XX_R45_IR,
+ msg, sizeof(msg));
+ if (rc < 0)
+ return rc;
+
+ /* Infrared toggle (Reg 0x45[7]) */
+ poll_result->toggle_bit = (msg[0] >> 7);
+
+ /* Infrared read count (Reg 0x45[6:0] */
+ poll_result->read_count = (msg[0] & 0x7f);
+
+ /* Remote Control Address (Reg 0x46) */
+ poll_result->rc_address = msg[1];
+
+ /* Remote Control Data (Reg 0x47) */
+ poll_result->rc_data[0] = msg[2];
+
+ return 0;
+}
+
+static int em2874_polling_getkey(struct em28xx_IR *ir,
+ struct em28xx_ir_poll_result *poll_result)
+{
+ struct em28xx *dev = ir->dev;
+ int rc;
+ u8 msg[5] = { 0, 0, 0, 0, 0 };
+
+ /* Read key toggle, brand, and key code
+ on registers 0x51-55
+ */
+ rc = dev->em28xx_read_reg_req_len(dev, 0, EM2874_R51_IR,
+ msg, sizeof(msg));
+ if (rc < 0)
+ return rc;
+
+ /* Infrared toggle (Reg 0x51[7]) */
+ poll_result->toggle_bit = (msg[0] >> 7);
+
+ /* Infrared read count (Reg 0x51[6:0] */
+ poll_result->read_count = (msg[0] & 0x7f);
+
+ /* Remote Control Address (Reg 0x52) */
+ poll_result->rc_address = msg[1];
+
+ /* Remote Control Data (Reg 0x53-55) */
+ poll_result->rc_data[0] = msg[2];
+ poll_result->rc_data[1] = msg[3];
+ poll_result->rc_data[2] = msg[4];
+
+ return 0;
+}
+
+/**********************************************************
+ Polling code for em28xx
+ **********************************************************/
+
+static void em28xx_ir_handle_key(struct em28xx_IR *ir)
+{
+ int result;
+ int do_sendkey = 0;
+ struct em28xx_ir_poll_result poll_result;
+
+ /* read the registers containing the IR status */
+ result = ir->get_key(ir, &poll_result);
+ if (result < 0) {
+ dprintk("ir->get_key() failed %d\n", result);
+ return;
+ }
+
+ dprintk("ir->get_key result tb=%02x rc=%02x lr=%02x data=%02x\n",
+ poll_result.toggle_bit, poll_result.read_count,
+ ir->last_readcount, poll_result.rc_data[0]);
+
+ if (ir->dev->chip_id == CHIP_ID_EM2874) {
+ /* The em2874 clears the readcount field every time the
+ register is read. The em2860/2880 datasheet says that it
+ is supposed to clear the readcount, but it doesn't. So with
+ the em2874, we are looking for a non-zero read count as
+ opposed to a readcount that is incrementing */
+ ir->last_readcount = 0;
+ }
+
+ if (poll_result.read_count == 0) {
+ /* The button has not been pressed since the last read */
+ } else if (ir->last_toggle != poll_result.toggle_bit) {
+ /* A button has been pressed */
+ dprintk("button has been pressed\n");
+ ir->last_toggle = poll_result.toggle_bit;
+ ir->repeat_interval = 0;
+ do_sendkey = 1;
+ } else if (poll_result.toggle_bit == ir->last_toggle &&
+ poll_result.read_count > 0 &&
+ poll_result.read_count != ir->last_readcount) {
+ /* The button is still being held down */
+ dprintk("button being held down\n");
+
+ /* Debouncer for first keypress */
+ if (ir->repeat_interval++ > 9) {
+ /* Start repeating after 1 second */
+ do_sendkey = 1;
+ }
+ }
+
+ if (do_sendkey) {
+ dprintk("sending keypress\n");
+ ir_input_keydown(ir->input, &ir->ir, poll_result.rc_data[0],
+ poll_result.rc_data[0]);
+ ir_input_nokey(ir->input, &ir->ir);
+ }
+
+ ir->last_readcount = poll_result.read_count;
+ return;
+}
+
+static void ir_timer(unsigned long data)
+{
+ struct em28xx_IR *ir = (struct em28xx_IR *)data;
+
+ schedule_work(&ir->work);
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
+static void em28xx_ir_work(void *data)
+#else
+static void em28xx_ir_work(struct work_struct *work)
+#endif
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
+ struct em28xx_IR *ir = data;
+#else
+ struct em28xx_IR *ir = container_of(work, struct em28xx_IR, work);
+#endif
+
+ em28xx_ir_handle_key(ir);
+ mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling));
+}
+
+void em28xx_ir_start(struct em28xx_IR *ir)
+{
+ setup_timer(&ir->timer, ir_timer, (unsigned long)ir);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
+ INIT_WORK(&ir->work, em28xx_ir_work, ir);
+#else
+ INIT_WORK(&ir->work, em28xx_ir_work);
+#endif
+ schedule_work(&ir->work);
+}
+
+static void em28xx_ir_stop(struct em28xx_IR *ir)
+{
+ del_timer_sync(&ir->timer);
+ flush_scheduled_work();
+}
+
+int em28xx_ir_init(struct em28xx *dev)
+{
+ struct em28xx_IR *ir;
+ struct input_dev *input_dev;
+ u8 ir_config;
+ int err = -ENOMEM;
+
+ if (dev->ir_codes == NULL) {
+ /* No remote control support */
+ return 0;
+ }
+
+ ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!ir || !input_dev)
+ goto err_out_free;
+
+ ir->input = input_dev;
+
+ /* Setup the proper handler based on the chip */
+ switch (dev->chip_id) {
+ case CHIP_ID_EM2860:
+ case CHIP_ID_EM2883:
+ ir->get_key = default_polling_getkey;
+ break;
+ case CHIP_ID_EM2874:
+ ir->get_key = em2874_polling_getkey;
+ /* For now we only support RC5, so enable it */
+ ir_config = EM2874_IR_RC5;
+ em28xx_write_regs(dev, EM2874_R50_IR_CONFIG, &ir_config, 1);
+ break;
+ default:
+ printk("Unrecognized em28xx chip id: IR not supported\n");
+ goto err_out_free;
+ }
+
+ /* This is how often we ask the chip for IR information */
+ ir->polling = 100; /* ms */
+
+ /* init input device */
+ snprintf(ir->name, sizeof(ir->name), "em28xx IR (%s)",
+ dev->name);
+
+ usb_make_path(dev->udev, ir->phys, sizeof(ir->phys));
+ strlcat(ir->phys, "/input0", sizeof(ir->phys));
+
+ ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER, dev->ir_codes);
+ input_dev->name = ir->name;
+ input_dev->phys = ir->phys;
+ input_dev->id.bustype = BUS_USB;
+ input_dev->id.version = 1;
+ input_dev->id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
+ input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
+ input_dev->dev.parent = &dev->udev->dev;
+#else
+ input_dev->cdev.dev = &dev->udev->dev;
+#endif
+ /* record handles to ourself */
+ ir->dev = dev;
+ dev->ir = ir;
+
+ em28xx_ir_start(ir);
+
+ /* all done */
+ err = input_register_device(ir->input);
+ if (err)
+ goto err_out_stop;
+
+ return 0;
+ err_out_stop:
+ em28xx_ir_stop(ir);
+ dev->ir = NULL;
+ err_out_free:
+ input_free_device(input_dev);
+ kfree(ir);
+ return err;
+}
+
+int em28xx_ir_fini(struct em28xx *dev)
+{
+ struct em28xx_IR *ir = dev->ir;
+
+ /* skip detach on non attached boards */
+ if (!ir)
+ return 0;
+
+ em28xx_ir_stop(ir);
+ input_unregister_device(ir->input);
+ kfree(ir);
+
+ /* done */
+ dev->ir = NULL;
+ return 0;
+}
+
+/**********************************************************
+ Handle Webcam snapshot button
+ **********************************************************/
+
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
static void em28xx_query_sbutton(void *data)
#else
@@ -232,9 +537,3 @@ void em28xx_deregister_snapshot_button(struct em28xx *dev)
}
return;
}
-
-/* ----------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/linux/drivers/media/video/em28xx/em28xx-reg.h b/linux/drivers/media/video/em28xx/em28xx-reg.h
index fac1ab23f..491d66abe 100644
--- a/linux/drivers/media/video/em28xx/em28xx-reg.h
+++ b/linux/drivers/media/video/em28xx/em28xx-reg.h
@@ -71,10 +71,32 @@
#define EM28XX_R42_AC97ADDR 0x42
#define EM28XX_R43_AC97BUSY 0x43
-/* em202 registers */
-#define EM28XX_R02_MASTER_AC97 0x02
-#define EM28XX_R10_LINE_IN_AC97 0x10
-#define EM28XX_R14_VIDEO_AC97 0x14
+#define EM28XX_R45_IR 0x45
+ /* 0x45 bit 7 - parity bit
+ bits 6-0 - count
+ 0x46 IR brand
+ 0x47 IR data
+ */
+
+/* em2874 registers */
+#define EM2874_R50_IR_CONFIG 0x50
+#define EM2874_R51_IR 0x51
+#define EM2874_R5F_TS_ENABLE 0x5f
+#define EM2874_R80_GPIO 0x80
+
+/* em2874 IR config register (0x50) */
+#define EM2874_IR_NEC 0x00
+#define EM2874_IR_RC5 0x04
+#define EM2874_IR_RC5_MODE_0 0x08
+#define EM2874_IR_RC5_MODE_6A 0x0b
+
+/* em2874 Transport Stream Enable Register (0x5f) */
+#define EM2874_TS1_CAPTURE_ENABLE (1 << 0)
+#define EM2874_TS1_FILTER_ENABLE (1 << 1)
+#define EM2874_TS1_NULL_DISCARD (1 << 2)
+#define EM2874_TS2_CAPTURE_ENABLE (1 << 4)
+#define EM2874_TS2_FILTER_ENABLE (1 << 5)
+#define EM2874_TS2_NULL_DISCARD (1 << 6)
/* register settings */
#define EM2800_AUDIO_SRC_TUNER 0x0d
@@ -84,6 +106,62 @@
/* FIXME: Need to be populated with the other chip ID's */
enum em28xx_chip_id {
+ CHIP_ID_EM2820 = 18,
+ CHIP_ID_EM2840 = 20,
+ CHIP_ID_EM2750 = 33,
CHIP_ID_EM2860 = 34,
CHIP_ID_EM2883 = 36,
+ CHIP_ID_EM2874 = 65,
};
+
+/*
+ * Registers used by em202 and other AC97 chips
+ */
+
+/* Standard AC97 registers */
+#define AC97_RESET 0x00
+#define AC97_MASTER_VOL 0x02
+#define AC97_LINE_LEVEL_VOL 0x04
+#define AC97_MASTER_MONO_VOL 0x06
+
+#define AC97_PC_BEEP_VOL 0x0a
+#define AC97_PHONE_VOL 0x0c
+#define AC97_MIC_VOL 0x0e
+#define AC97_LINEIN_VOL 0x10
+#define AC97_CD_VOL 0x12
+#define AC97_VIDEO_VOL 0x14
+#define AC97_AUX_VOL 0x16
+#define AC97_PCM_OUT_VOL 0x18
+#define AC97_RECORD_SELECT 0x1a
+#define AC97_RECORD_GAIN 0x1c
+#define AC97_GENERAL_PURPOSE 0x20
+#define AC97_3D_CTRL 0x22
+#define AC97_AUD_INT_AND_PAG 0x24
+#define AC97_POWER_DOWN_CTRL 0x26
+#define AC97_EXT_AUD_ID 0x28
+#define AC97_EXT_AUD_CTRL 0x2a
+
+/* Supported rate varies for each AC97 device
+ if write an unsupported value, it will return the closest one
+ */
+#define AC97_PCM_OUT_FRONT_SRATE 0x2c
+#define AC97_PCM_OUT_SURR_SRATE 0x2e
+#define AC97_PCM_OUT_LFE_SRATE 0x30
+#define AC97_PCM_IN_SRATE 0x32
+#define AC97_LFE_MASTER_VOL 0x36
+#define AC97_SURR_MASTER_VOL 0x38
+#define AC97_SPDIF_OUT_CTRL 0x3a
+
+#define AC97_VENDOR_ID1 0x7c
+#define AC97_VENDOR_ID2 0x7e
+
+/* EMP202 vendor registers */
+#define EM202_EXT_MODEM_CTRL 0x3e
+#define EM202_GPIO_CONF 0x4c
+#define EM202_GPIO_POLARITY 0x4e
+#define EM202_GPIO_STICKY 0x50
+#define EM202_GPIO_MASK 0x52
+#define EM202_GPIO_STATUS 0x54
+#define EM202_SPDIF_OUT_SEL 0x6a
+#define EM202_ANTIPOP 0x72
+#define EM202_EAPD_GPIO_ACCESS 0x74
diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c
index 2d0cd4abc..625c9dea1 100644
--- a/linux/drivers/media/video/em28xx/em28xx-video.c
+++ b/linux/drivers/media/video/em28xx/em28xx-video.c
@@ -1275,7 +1275,7 @@ static int vidioc_querycap(struct file *file, void *priv,
strlcpy(cap->driver, "em28xx", sizeof(cap->driver));
strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card));
- strlcpy(cap->bus_info, dev->udev->dev.bus_id, sizeof(cap->bus_info));
+ strlcpy(cap->bus_info, dev_name(&dev->udev->dev), sizeof(cap->bus_info));
cap->version = EM28XX_VERSION_CODE;
@@ -1465,7 +1465,7 @@ static int radio_querycap(struct file *file, void *priv,
strlcpy(cap->driver, "em28xx", sizeof(cap->driver));
strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card));
- strlcpy(cap->bus_info, dev->udev->dev.bus_id, sizeof(cap->bus_info));
+ strlcpy(cap->bus_info, dev_name(&dev->udev->dev), sizeof(cap->bus_info));
cap->version = EM28XX_VERSION_CODE;
cap->capabilities = V4L2_CAP_TUNER;
@@ -1656,11 +1656,13 @@ static void em28xx_release_resources(struct em28xx *dev)
/*FIXME: I2C IR should be disconnected */
- em28xx_info("V4L2 devices /dev/video%d and /dev/vbi%d deregistered\n",
- dev->vdev->num, dev->vbi_dev->num);
list_del(&dev->devlist);
if (dev->sbutton_input_dev)
em28xx_deregister_snapshot_button(dev);
+
+ if (dev->ir)
+ em28xx_ir_fini(dev);
+
if (dev->radio_dev) {
if (-1 != dev->radio_dev->minor)
video_unregister_device(dev->radio_dev);
@@ -1669,6 +1671,8 @@ static void em28xx_release_resources(struct em28xx *dev)
dev->radio_dev = NULL;
}
if (dev->vbi_dev) {
+ em28xx_info("V4L2 device /dev/vbi%d deregistered\n",
+ dev->vbi_dev->num);
if (-1 != dev->vbi_dev->minor)
video_unregister_device(dev->vbi_dev);
else
@@ -1676,6 +1680,8 @@ static void em28xx_release_resources(struct em28xx *dev)
dev->vbi_dev = NULL;
}
if (dev->vdev) {
+ em28xx_info("V4L2 device /dev/video%d deregistered\n",
+ dev->vdev->num);
if (-1 != dev->vdev->minor)
video_unregister_device(dev->vdev);
else
@@ -1982,6 +1988,19 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev,
return vfd;
}
+int em28xx_supports_audio_extension(struct em28xx *dev)
+{
+ /* The chip dictates whether we support the Empia analog audio
+ extension */
+ switch (dev->chip_id) {
+ case CHIP_ID_EM2874:
+ /* Either a digital-only device or provides AC97 audio */
+ return 0;
+ case CHIP_ID_EM2883:
+ default:
+ return 1;
+ }
+}
/*
* em28xx_init_dev()
@@ -2015,8 +2034,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
errCode = em28xx_config(dev);
if (errCode) {
em28xx_errdev("error configuring device\n");
- em28xx_devused &= ~(1<<dev->devno);
- kfree(dev);
return -ENOMEM;
}
@@ -2104,7 +2121,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
goto fail_unreg;
}
em28xx_info("Registered radio device as /dev/radio%d\n",
- dev->radio_dev->minor & 0x1f);
+ dev->radio_dev->num);
}
/* init video dma queues */
@@ -2153,7 +2170,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
fail_unreg:
em28xx_release_resources(dev);
mutex_unlock(&dev->lock);
- kfree(dev);
return retval;
}
@@ -2171,7 +2187,7 @@ static void request_module_async(struct work_struct *work)
if (dev->has_audio_class)
request_module("snd-usb-audio");
- else
+ else if (dev->has_alsa_audio)
request_module("em28xx-alsa");
if (dev->has_dvb)
@@ -2204,7 +2220,7 @@ static int em28xx_usb_probe(struct usb_interface *interface,
struct usb_interface *uif;
struct em28xx *dev = NULL;
int retval = -ENODEV;
- int i, nr, ifnum;
+ int i, nr, ifnum, isoc_pipe;
udev = usb_get_dev(interface_to_usbdev(interface));
ifnum = interface->altsetting[0].desc.bInterfaceNumber;
@@ -2231,19 +2247,29 @@ static int em28xx_usb_probe(struct usb_interface *interface,
ifnum,
interface->altsetting[0].desc.bInterfaceClass);
- endpoint = &interface->cur_altsetting->endpoint[1].desc;
+ endpoint = &interface->cur_altsetting->endpoint[0].desc;
/* check if the device has the iso in endpoint at the correct place */
- if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
- USB_ENDPOINT_XFER_ISOC) {
- em28xx_err(DRIVER_NAME " probing error: endpoint is non-ISO endpoint!\n");
- em28xx_devused &= ~(1<<nr);
- return -ENODEV;
- }
- if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) {
- em28xx_err(DRIVER_NAME " probing error: endpoint is ISO OUT endpoint!\n");
- em28xx_devused &= ~(1<<nr);
- return -ENODEV;
+ if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+ USB_ENDPOINT_XFER_ISOC &&
+ (interface->altsetting[1].endpoint[0].desc.wMaxPacketSize == 940))
+ {
+ /* It's a newer em2874/em2875 device */
+ isoc_pipe = 0;
+ } else {
+ isoc_pipe = 1;
+ endpoint = &interface->cur_altsetting->endpoint[1].desc;
+ if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
+ USB_ENDPOINT_XFER_ISOC) {
+ em28xx_err(DRIVER_NAME " probing error: endpoint is non-ISO endpoint!\n");
+ em28xx_devused &= ~(1<<nr);
+ return -ENODEV;
+ }
+ if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) {
+ em28xx_err(DRIVER_NAME " probing error: endpoint is ISO OUT endpoint!\n");
+ em28xx_devused &= ~(1<<nr);
+ return -ENODEV;
+ }
}
if (nr >= EM28XX_MAXBOARDS) {
@@ -2275,9 +2301,6 @@ static int em28xx_usb_probe(struct usb_interface *interface,
}
}
- printk(KERN_INFO DRIVER_NAME " %s usb audio class\n",
- dev->has_audio_class ? "Has" : "Doesn't have");
-
/* compute alternate max packet sizes */
uif = udev->actconfig->interface[0];
@@ -2294,7 +2317,7 @@ static int em28xx_usb_probe(struct usb_interface *interface,
}
for (i = 0; i < dev->num_alt ; i++) {
- u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[1].desc.
+ u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc.
wMaxPacketSize);
dev->alt_max_pkt_size[i] =
(tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
@@ -2307,11 +2330,26 @@ static int em28xx_usb_probe(struct usb_interface *interface,
/* allocate device struct */
retval = em28xx_init_dev(&dev, udev, nr);
- if (retval)
+ if (retval) {
+ em28xx_devused &= ~(1<<dev->devno);
+ kfree(dev);
+
return retval;
+ }
em28xx_info("Found %s\n", em28xx_boards[dev->model].name);
+ if (dev->has_audio_class == 0) {
+ /* We don't have a USB audio class, let's see if we support
+ ALSA Audio */
+ dev->has_alsa_audio = em28xx_supports_audio_extension(dev);
+ if (dev->has_alsa_audio)
+ printk(KERN_INFO DRIVER_NAME " supports alsa audio\n");
+ } else {
+ printk(KERN_INFO DRIVER_NAME " has usb audio class\n");
+ }
+
+
/* save our data pointer in this interface device */
usb_set_intfdata(interface, dev);
diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h
index d73b8c983..2e108be19 100644
--- a/linux/drivers/media/video/em28xx/em28xx.h
+++ b/linux/drivers/media/video/em28xx/em28xx.h
@@ -98,11 +98,15 @@
#define EM2882_BOARD_PINNACLE_HYBRID_PRO 56
#define EM2883_BOARD_KWORLD_HYBRID_A316 57
#define EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU 58
+#define EM2874_BOARD_PINNACLE_PCTV_80E 59
/* Limits minimum and default number of buffers */
#define EM28XX_MIN_BUF 4
#define EM28XX_DEF_BUF 8
+/*Limits the max URB message size */
+#define URB_MAX_CTRL_SIZE 80
+
/* Params for validated field */
#define EM28XX_BOARD_NOT_VALIDATED 1
#define EM28XX_BOARD_VALIDATED 0
@@ -269,6 +273,7 @@ struct em28xx_input {
#define INPUT(nr) (&em28xx_boards[dev->model].input[nr])
enum em28xx_decoder {
+ EM28XX_NODECODER,
EM28XX_TVP5150,
EM28XX_SAA7113,
EM28XX_SAA7114
@@ -284,6 +289,7 @@ struct em28xx_board {
char *name;
int vchannels;
int tuner_type;
+ int tuner_addr;
/* i2c flags */
unsigned int tda9887_conf;
@@ -301,6 +307,7 @@ struct em28xx_board {
struct em28xx_input input[MAX_EM28XX_INPUT];
struct em28xx_input radio;
+ IR_KEYTAB_TYPE *ir_codes;
};
struct em28xx_eeprom {
@@ -375,17 +382,21 @@ struct em28xx {
char name[30]; /* name (including minor) of the device */
int model; /* index in the device_data struct */
int devno; /* marks the number of this device */
+ enum em28xx_chip_id chip_id;
unsigned int is_em2800:1;
unsigned int has_msp34xx:1;
unsigned int has_tda9887:1;
unsigned int stream_on:1; /* Locks streams */
unsigned int has_audio_class:1;
+ unsigned int has_alsa_audio:1;
unsigned int has_12mhz_i2s:1;
unsigned int max_range_640_480:1;
unsigned int has_dvb:1;
unsigned int has_snapshot_button:1;
unsigned int valid:1; /* report for validated boards */
+ struct em28xx_IR *ir;
+
/* Some older em28xx chips needs a waiting time after writing */
unsigned int wait_after_write;
@@ -460,6 +471,8 @@ struct em28xx {
unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */
struct urb *urb[EM28XX_NUM_BUFS]; /* urb for isoc transfers */
char *transfer_buffer[EM28XX_NUM_BUFS]; /* transfer buffers for isoc transfer */
+ char urb_buf[URB_MAX_CTRL_SIZE]; /* urb control msg buffer */
+
/* helper funcs that call usb_control_msg */
int (*em28xx_write_regs) (struct em28xx *dev, u16 reg,
char *buf, int len);
@@ -472,9 +485,15 @@ struct em28xx {
enum em28xx_mode mode;
+ /* register numbers for GPO/GPIO registers */
+ u16 reg_gpo_num, reg_gpio_num;
+
/* Caches GPO and GPIO registers */
unsigned char reg_gpo, reg_gpio;
+ /* Infrared remote control support */
+ IR_KEYTAB_TYPE *ir_codes;
+
/* Snapshot button */
char snapshot_button_path[30]; /* path of the input dev */
struct input_dev *sbutton_input_dev;
@@ -544,7 +563,6 @@ void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir);
int em28xx_tuner_callback(void *ptr, int component, int command, int arg);
/* Provided by em28xx-input.c */
-/* TODO: Check if the standard get_key handlers on ir-common can be used */
int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw);
int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw);
int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key,
@@ -552,6 +570,9 @@ int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key,
void em28xx_register_snapshot_button(struct em28xx *dev);
void em28xx_deregister_snapshot_button(struct em28xx *dev);
+int em28xx_ir_init(struct em28xx *dev);
+int em28xx_ir_fini(struct em28xx *dev);
+
/* printk macros */
#define em28xx_err(fmt, arg...) do {\
diff --git a/linux/drivers/media/video/et61x251/et61x251_core.c b/linux/drivers/media/video/et61x251/et61x251_core.c
index f58aee5aa..52e0f2710 100644
--- a/linux/drivers/media/video/et61x251/et61x251_core.c
+++ b/linux/drivers/media/video/et61x251/et61x251_core.c
@@ -592,7 +592,7 @@ static int et61x251_stream_interrupt(struct et61x251_device* cam)
cam->state |= DEV_MISCONFIGURED;
DBG(1, "URB timeout reached. The camera is misconfigured. To "
"use it, close and open /dev/video%d again.",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
return -EIO;
}
@@ -1199,7 +1199,7 @@ static void et61x251_release_resources(struct kref *kref)
cam = container_of(kref, struct et61x251_device, kref);
- DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor);
+ DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->num);
video_set_drvdata(cam->v4ldev, NULL);
video_unregister_device(cam->v4ldev);
usb_put_dev(cam->usbdev);
@@ -1241,7 +1241,7 @@ static int et61x251_open(struct inode* inode, struct file* filp)
if (cam->users) {
DBG(2, "Device /dev/video%d is already in use",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
DBG(3, "Simultaneous opens are not supported");
if ((filp->f_flags & O_NONBLOCK) ||
(filp->f_flags & O_NDELAY)) {
@@ -1284,7 +1284,7 @@ static int et61x251_open(struct inode* inode, struct file* filp)
cam->frame_count = 0;
et61x251_empty_framequeues(cam);
- DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor);
+ DBG(3, "Video device /dev/video%d is open", cam->v4ldev->num);
out:
mutex_unlock(&cam->open_mutex);
@@ -1308,7 +1308,7 @@ static int et61x251_release(struct inode* inode, struct file* filp)
cam->users--;
wake_up_interruptible_nr(&cam->wait_open, 1);
- DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor);
+ DBG(3, "Video device /dev/video%d closed", cam->v4ldev->num);
kref_put(&cam->kref, et61x251_release_resources);
@@ -1585,7 +1585,7 @@ et61x251_vidioc_querycap(struct et61x251_device* cam, void __user * arg)
strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card));
if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0)
- strlcpy(cap.bus_info, cam->usbdev->dev.bus_id,
+ strlcpy(cap.bus_info, dev_name(&cam->usbdev->dev),
sizeof(cap.bus_info));
if (copy_to_user(arg, &cap, sizeof(cap)))
@@ -1849,7 +1849,7 @@ et61x251_vidioc_s_crop(struct et61x251_device* cam, void __user * arg)
cam->state |= DEV_MISCONFIGURED;
DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To "
"use the camera, close and open /dev/video%d again.",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
return -EIO;
}
@@ -1862,7 +1862,7 @@ et61x251_vidioc_s_crop(struct et61x251_device* cam, void __user * arg)
cam->state |= DEV_MISCONFIGURED;
DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To "
"use the camera, close and open /dev/video%d again.",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
return -ENOMEM;
}
@@ -2072,7 +2072,7 @@ et61x251_vidioc_try_s_fmt(struct et61x251_device* cam, unsigned int cmd,
cam->state |= DEV_MISCONFIGURED;
DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To "
"use the camera, close and open /dev/video%d again.",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
return -EIO;
}
@@ -2084,7 +2084,7 @@ et61x251_vidioc_try_s_fmt(struct et61x251_device* cam, unsigned int cmd,
cam->state |= DEV_MISCONFIGURED;
DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To "
"use the camera, close and open /dev/video%d again.",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
return -ENOMEM;
}
@@ -2132,7 +2132,7 @@ et61x251_vidioc_s_jpegcomp(struct et61x251_device* cam, void __user * arg)
cam->state |= DEV_MISCONFIGURED;
DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware "
"problems. To use the camera, close and open "
- "/dev/video%d again.", cam->v4ldev->minor);
+ "/dev/video%d again.", cam->v4ldev->num);
return -EIO;
}
@@ -2609,7 +2609,7 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
goto fail;
}
- DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor);
+ DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->num);
cam->module_param.force_munmap = force_munmap[dev_nr];
cam->module_param.frame_timeout = frame_timeout[dev_nr];
@@ -2662,7 +2662,7 @@ static void et61x251_usb_disconnect(struct usb_interface* intf)
if (cam->users) {
DBG(2, "Device /dev/video%d is open! Deregistration and "
"memory deallocation are deferred.",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
cam->state |= DEV_MISCONFIGURED;
et61x251_stop_transfer(cam);
cam->state |= DEV_DISCONNECTED;
diff --git a/linux/drivers/media/video/gspca/Kconfig b/linux/drivers/media/video/gspca/Kconfig
index 4d0817471..6b557c057 100644
--- a/linux/drivers/media/video/gspca/Kconfig
+++ b/linux/drivers/media/video/gspca/Kconfig
@@ -3,16 +3,16 @@ menuconfig USB_GSPCA
depends on VIDEO_V4L2
default m
---help---
- Say Y here if you want to enable selecting webcams based
- on the GSPCA framework.
+ Say Y here if you want to enable selecting webcams based
+ on the GSPCA framework.
- See <file:Documentation/video4linux/gspca.txt> for more info.
+ See <file:Documentation/video4linux/gspca.txt> for more info.
- This driver uses the Video For Linux API. You must say Y or M to
- "Video For Linux" to use this driver.
+ This driver uses the Video For Linux API. You must say Y or M to
+ "Video For Linux" to use this driver.
- To compile this driver as modules, choose M here: the
- modules will be called gspca_main.
+ To compile this driver as modules, choose M here: the
+ modules will be called gspca_main.
if USB_GSPCA && VIDEO_V4L2
@@ -23,190 +23,190 @@ config USB_GSPCA_CONEX
tristate "Conexant Camera Driver"
depends on VIDEO_V4L2 && USB_GSPCA
help
- Say Y here if you want support for cameras based on the Conexant chip.
+ Say Y here if you want support for cameras based on the Conexant chip.
- To compile this driver as a module, choose M here: the
- module will be called gspca_conex.
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_conex.
config USB_GSPCA_ETOMS
tristate "Etoms USB Camera Driver"
depends on VIDEO_V4L2 && USB_GSPCA
help
- Say Y here if you want support for cameras based on the Etoms chip.
+ Say Y here if you want support for cameras based on the Etoms chip.
- To compile this driver as a module, choose M here: the
- module will be called gspca_etoms.
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_etoms.
config USB_GSPCA_FINEPIX
tristate "Fujifilm FinePix USB V4L2 driver"
depends on VIDEO_V4L2 && USB_GSPCA
help
- Say Y here if you want support for cameras based on the FinePix chip.
+ Say Y here if you want support for cameras based on the FinePix chip.
- To compile this driver as a module, choose M here: the
- module will be called gspca_finepix.
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_finepix.
config USB_GSPCA_MARS
tristate "Mars USB Camera Driver"
depends on VIDEO_V4L2 && USB_GSPCA
help
- Say Y here if you want support for cameras based on the Mars chip.
+ Say Y here if you want support for cameras based on the Mars chip.
- To compile this driver as a module, choose M here: the
- module will be called gspca_mars.
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_mars.
config USB_GSPCA_OV519
tristate "OV519 USB Camera Driver"
depends on VIDEO_V4L2 && USB_GSPCA
help
- Say Y here if you want support for cameras based on the OV519 chip.
+ Say Y here if you want support for cameras based on the OV519 chip.
- To compile this driver as a module, choose M here: the
- module will be called gspca_ov519.
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_ov519.
config USB_GSPCA_PAC207
tristate "Pixart PAC207 USB Camera Driver"
depends on VIDEO_V4L2 && USB_GSPCA
help
- Say Y here if you want support for cameras based on the PAC207 chip.
+ Say Y here if you want support for cameras based on the PAC207 chip.
- To compile this driver as a module, choose M here: the
- module will be called gspca_pac207.
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_pac207.
config USB_GSPCA_PAC7311
tristate "Pixart PAC7311 USB Camera Driver"
depends on VIDEO_V4L2 && USB_GSPCA
help
- Say Y here if you want support for cameras based on the PAC7311 chip.
+ Say Y here if you want support for cameras based on the PAC7311 chip.
- To compile this driver as a module, choose M here: the
- module will be called gspca_pac7311.
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_pac7311.
config USB_GSPCA_SONIXB
tristate "SN9C102 USB Camera Driver"
depends on VIDEO_V4L2 && USB_GSPCA
help
- Say Y here if you want support for cameras based on the SONIXB chip.
+ Say Y here if you want support for cameras based on the SONIXB chip.
- To compile this driver as a module, choose M here: the
- module will be called gspca_sonixb.
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_sonixb.
config USB_GSPCA_SONIXJ
tristate "SONIX JPEG USB Camera Driver"
depends on VIDEO_V4L2 && USB_GSPCA
help
- Say Y here if you want support for cameras based on the SONIXJ chip.
+ Say Y here if you want support for cameras based on the SONIXJ chip.
- To compile this driver as a module, choose M here: the
- module will be called gspca_sonixj
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_sonixj
config USB_GSPCA_SPCA500
tristate "SPCA500 USB Camera Driver"
depends on VIDEO_V4L2 && USB_GSPCA
help
- Say Y here if you want support for cameras based on the SPCA500 chip.
+ Say Y here if you want support for cameras based on the SPCA500 chip.
- To compile this driver as a module, choose M here: the
- module will be called gspca_spca500.
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_spca500.
config USB_GSPCA_SPCA501
tristate "SPCA501 USB Camera Driver"
depends on VIDEO_V4L2 && USB_GSPCA
help
- Say Y here if you want support for cameras based on the SPCA501 chip.
+ Say Y here if you want support for cameras based on the SPCA501 chip.
- To compile this driver as a module, choose M here: the
- module will be called gspca_spca501.
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_spca501.
config USB_GSPCA_SPCA505
tristate "SPCA505 USB Camera Driver"
depends on VIDEO_V4L2 && USB_GSPCA
help
- Say Y here if you want support for cameras based on the SPCA505 chip.
+ Say Y here if you want support for cameras based on the SPCA505 chip.
- To compile this driver as a module, choose M here: the
- module will be called gspca_spca505.
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_spca505.
config USB_GSPCA_SPCA506
tristate "SPCA506 USB Camera Driver"
depends on VIDEO_V4L2 && USB_GSPCA
help
- Say Y here if you want support for cameras based on the SPCA506 chip.
+ Say Y here if you want support for cameras based on the SPCA506 chip.
- To compile this driver as a module, choose M here: the
- module will be called gspca_spca506.
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_spca506.
config USB_GSPCA_SPCA508
tristate "SPCA508 USB Camera Driver"
depends on VIDEO_V4L2 && USB_GSPCA
help
- Say Y here if you want support for cameras based on the SPCA508 chip.
+ Say Y here if you want support for cameras based on the SPCA508 chip.
- To compile this driver as a module, choose M here: the
- module will be called gspca_spca508.
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_spca508.
config USB_GSPCA_SPCA561
tristate "SPCA561 USB Camera Driver"
depends on VIDEO_V4L2 && USB_GSPCA
help
- Say Y here if you want support for cameras based on the SPCA561 chip.
+ Say Y here if you want support for cameras based on the SPCA561 chip.
- To compile this driver as a module, choose M here: the
- module will be called gspca_spca561.
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_spca561.
config USB_GSPCA_STK014
tristate "Syntek DV4000 (STK014) USB Camera Driver"
depends on VIDEO_V4L2 && USB_GSPCA
help
- Say Y here if you want support for cameras based on the STK014 chip.
+ Say Y here if you want support for cameras based on the STK014 chip.
- To compile this driver as a module, choose M here: the
- module will be called gspca_stk014.
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_stk014.
config USB_GSPCA_SUNPLUS
tristate "SUNPLUS USB Camera Driver"
depends on VIDEO_V4L2 && USB_GSPCA
help
- Say Y here if you want support for cameras based on the Sunplus
- SPCA504(abc) SPCA533 SPCA536 chips.
+ Say Y here if you want support for cameras based on the Sunplus
+ SPCA504(abc) SPCA533 SPCA536 chips.
- To compile this driver as a module, choose M here: the
- module will be called gspca_spca5xx.
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_spca5xx.
config USB_GSPCA_T613
tristate "T613 (JPEG Compliance) USB Camera Driver"
depends on VIDEO_V4L2 && USB_GSPCA
help
- Say Y here if you want support for cameras based on the T613 chip.
+ Say Y here if you want support for cameras based on the T613 chip.
- To compile this driver as a module, choose M here: the
- module will be called gspca_t613.
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_t613.
config USB_GSPCA_TV8532
tristate "TV8532 USB Camera Driver"
depends on VIDEO_V4L2 && USB_GSPCA
help
- Say Y here if you want support for cameras based on the TV8531 chip.
+ Say Y here if you want support for cameras based on the TV8531 chip.
- To compile this driver as a module, choose M here: the
- module will be called gspca_tv8532.
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_tv8532.
config USB_GSPCA_VC032X
tristate "VC032X USB Camera Driver"
depends on VIDEO_V4L2 && USB_GSPCA
help
- Say Y here if you want support for cameras based on the VC032X chip.
+ Say Y here if you want support for cameras based on the VC032X chip.
- To compile this driver as a module, choose M here: the
- module will be called gspca_vc032x.
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_vc032x.
config USB_GSPCA_ZC3XX
- tristate "VC3xx USB Camera Driver"
+ tristate "ZC3XX USB Camera Driver"
depends on VIDEO_V4L2 && USB_GSPCA
help
- Say Y here if you want support for cameras based on the ZC3XX chip.
+ Say Y here if you want support for cameras based on the ZC3XX chip.
- To compile this driver as a module, choose M here: the
- module will be called gspca_zc3xx.
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_zc3xx.
endif
diff --git a/linux/drivers/media/video/gspca/conex.c b/linux/drivers/media/video/gspca/conex.c
index a9d51ba7c..de28354ea 100644
--- a/linux/drivers/media/video/gspca/conex.c
+++ b/linux/drivers/media/video/gspca/conex.c
@@ -846,10 +846,13 @@ static int sd_start(struct gspca_dev *gspca_dev)
return 0;
}
+/* called on streamoff with alt 0 and on disconnect */
static void sd_stop0(struct gspca_dev *gspca_dev)
{
int retry = 50;
+ if (!gspca_dev->present)
+ return;
reg_w_val(gspca_dev, 0x0000, 0x00);
reg_r(gspca_dev, 0x0002, 1);
reg_w_val(gspca_dev, 0x0053, 0x00);
diff --git a/linux/drivers/media/video/gspca/finepix.c b/linux/drivers/media/video/gspca/finepix.c
index 65d3cbfe6..03cb94466 100644
--- a/linux/drivers/media/video/gspca/finepix.c
+++ b/linux/drivers/media/video/gspca/finepix.c
@@ -276,6 +276,12 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
/* Stop the state machine */
if (dev->state != FPIX_NOP)
wait_for_completion(&dev->can_close);
+}
+
+/* called on streamoff with alt 0 and disconnect */
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+ struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
usb_free_urb(dev->control_urb);
dev->control_urb = NULL;
@@ -308,9 +314,6 @@ static int sd_start(struct gspca_dev *gspca_dev)
int ret;
int size_ret;
- /* Reset bulk in endpoint */
- usb_clear_halt(gspca_dev->dev, gspca_dev->cam.epaddr);
-
/* Init the device */
memset(gspca_dev->usb_buf, 0, 12);
gspca_dev->usb_buf[0] = 0xc6;
@@ -385,6 +388,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
error:
/* Free the ressources */
sd_stopN(gspca_dev);
+ sd_stop0(gspca_dev);
return ret;
}
@@ -425,6 +429,7 @@ static const struct sd_desc sd_desc = {
.init = sd_init,
.start = sd_start,
.stopN = sd_stopN,
+ .stop0 = sd_stop0,
};
/* -- device connect -- */
diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c
index 4e0e7a32a..35f504440 100644
--- a/linux/drivers/media/video/gspca/gspca.c
+++ b/linux/drivers/media/video/gspca/gspca.c
@@ -49,7 +49,7 @@ MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
MODULE_DESCRIPTION("GSPCA USB Camera Driver");
MODULE_LICENSE("GPL");
-#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 3, 0)
+#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 4, 0)
static int video_nr = -1;
@@ -154,8 +154,11 @@ static void fill_frame(struct gspca_dev *gspca_dev,
/* check the packet status and length */
len = urb->iso_frame_desc[i].actual_length;
- if (len == 0)
+ if (len == 0) {
+ if (gspca_dev->empty_packet == 0)
+ gspca_dev->empty_packet = 1;
continue;
+ }
st = urb->iso_frame_desc[i].status;
if (st) {
PDEBUG(D_ERR,
@@ -174,7 +177,6 @@ static void fill_frame(struct gspca_dev *gspca_dev,
}
/* resubmit the URB */
- urb->status = 0;
st = usb_submit_urb(urb, GFP_ATOMIC);
if (st < 0)
PDEBUG(D_ERR|D_PACK, "usb_submit_urb() ret %d", st);
@@ -210,11 +212,18 @@ static void bulk_irq(struct urb *urb
{
struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
struct gspca_frame *frame;
+ int st;
PDEBUG(D_PACK, "bulk irq");
if (!gspca_dev->streaming)
return;
- if (urb->status != 0 && urb->status != -ECONNRESET) {
+ switch (urb->status) {
+ case 0:
+ break;
+ case -ECONNRESET:
+ urb->status = 0;
+ break;
+ default:
#ifdef CONFIG_PM
if (!gspca_dev->frozen)
#endif
@@ -233,6 +242,13 @@ static void bulk_irq(struct urb *urb
urb->transfer_buffer,
urb->actual_length);
}
+
+ /* resubmit the URB */
+ if (gspca_dev->cam.bulk_nurbs != 0) {
+ st = usb_submit_urb(urb, GFP_ATOMIC);
+ if (st < 0)
+ PDEBUG(D_ERR|D_PACK, "usb_submit_urb() ret %d", st);
+ }
}
/*
@@ -530,11 +546,14 @@ static int create_urbs(struct gspca_dev *gspca_dev,
nurbs = DEF_NURBS;
} else { /* bulk */
npkt = 0;
- bsize = gspca_dev->cam. bulk_size;
+ bsize = gspca_dev->cam.bulk_size;
if (bsize == 0)
bsize = psize;
PDEBUG(D_STREAM, "bulk bsize:%d", bsize);
- nurbs = 1;
+ if (gspca_dev->cam.bulk_nurbs != 0)
+ nurbs = gspca_dev->cam.bulk_nurbs;
+ else
+ nurbs = 1;
}
gspca_dev->nurbs = nurbs;
@@ -607,6 +626,12 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
if (ret < 0)
goto out;
+ /* clear the bulk endpoint */
+ if (gspca_dev->alt == 0) /* if bulk transfer */
+ usb_clear_halt(gspca_dev->dev,
+ usb_rcvintpipe(gspca_dev->dev,
+ gspca_dev->cam.epaddr));
+
/* start the cam */
ret = gspca_dev->sd_desc->start(gspca_dev);
if (ret < 0) {
@@ -616,8 +641,8 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
gspca_dev->streaming = 1;
atomic_set(&gspca_dev->nevent, 0);
- /* bulk transfers are started by the subdriver */
- if (gspca_dev->alt == 0)
+ /* some bulk transfers are started by the subdriver */
+ if (gspca_dev->alt == 0 && gspca_dev->cam.bulk_nurbs == 0)
break;
/* submit the URBs */
@@ -656,15 +681,14 @@ static void gspca_stream_off(struct gspca_dev *gspca_dev)
{
gspca_dev->streaming = 0;
atomic_set(&gspca_dev->nevent, 0);
- if (gspca_dev->present) {
- if (gspca_dev->sd_desc->stopN)
- gspca_dev->sd_desc->stopN(gspca_dev);
- destroy_urbs(gspca_dev);
- gspca_set_alt0(gspca_dev);
- if (gspca_dev->sd_desc->stop0)
- gspca_dev->sd_desc->stop0(gspca_dev);
- PDEBUG(D_STREAM, "stream off OK");
- }
+ if (gspca_dev->present
+ && gspca_dev->sd_desc->stopN)
+ gspca_dev->sd_desc->stopN(gspca_dev);
+ destroy_urbs(gspca_dev);
+ gspca_set_alt0(gspca_dev);
+ if (gspca_dev->sd_desc->stop0)
+ gspca_dev->sd_desc->stop0(gspca_dev);
+ PDEBUG(D_STREAM, "stream off OK");
}
static void gspca_set_default_mode(struct gspca_dev *gspca_dev)
@@ -738,7 +762,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
if (fmtdesc->index == index)
break; /* new format */
index++;
- if (index >= sizeof fmt_tb / sizeof fmt_tb[0])
+ if (index >= ARRAY_SIZE(fmt_tb))
return -EINVAL;
}
}
@@ -873,7 +897,7 @@ static int dev_open(struct inode *inode, struct file *file)
int ret;
PDEBUG(D_STREAM, "%s open", current->comm);
- gspca_dev = (struct gspca_dev *) video_devdata(file);
+ gspca_dev = video_drvdata(file);
if (mutex_lock_interruptible(&gspca_dev->queue_lock))
return -ERESTARTSYS;
if (!gspca_dev->present) {
@@ -885,6 +909,13 @@ static int dev_open(struct inode *inode, struct file *file)
ret = -EBUSY;
goto out;
}
+
+ /* protect the subdriver against rmmod */
+ if (!try_module_get(gspca_dev->module)) {
+ ret = -ENODEV;
+ goto out;
+ }
+
gspca_dev->users++;
/* one more user */
@@ -894,10 +925,10 @@ static int dev_open(struct inode *inode, struct file *file)
#ifdef GSPCA_DEBUG
/* activate the v4l2 debug */
if (gspca_debug & D_V4L2)
- gspca_dev->vdev.debug |= V4L2_DEBUG_IOCTL
+ gspca_dev->vdev->debug |= V4L2_DEBUG_IOCTL
| V4L2_DEBUG_IOCTL_ARG;
else
- gspca_dev->vdev.debug &= ~(V4L2_DEBUG_IOCTL
+ gspca_dev->vdev->debug &= ~(V4L2_DEBUG_IOCTL
| V4L2_DEBUG_IOCTL_ARG);
#endif
ret = 0;
@@ -931,6 +962,7 @@ static int dev_close(struct inode *inode, struct file *file)
gspca_dev->memory = GSPCA_MEMORY_NO;
}
file->private_data = NULL;
+ module_put(gspca_dev->module);
mutex_unlock(&gspca_dev->queue_lock);
PDEBUG(D_STREAM, "close done");
@@ -1758,11 +1790,6 @@ out:
return ret;
}
-static void dev_release(struct video_device *vfd)
-{
- /* nothing */
-}
-
static struct file_operations dev_fops = {
.owner = THIS_MODULE,
.open = dev_open,
@@ -1810,7 +1837,7 @@ static struct video_device gspca_template = {
.name = "gspca main driver",
.fops = &dev_fops,
.ioctl_ops = &dev_ioctl_ops,
- .release = dev_release, /* mandatory */
+ .release = video_device_release,
.minor = -1,
};
@@ -1860,6 +1887,7 @@ int gspca_dev_probe(struct usb_interface *intf,
gspca_dev->nbalt = intf->num_altsetting;
gspca_dev->sd_desc = sd_desc;
gspca_dev->nbufread = 2;
+ gspca_dev->empty_packet = -1; /* don't check the empty packets */
/* configure the subdriver and initialize the USB device */
ret = gspca_dev->sd_desc->config(gspca_dev, id);
@@ -1879,17 +1907,18 @@ int gspca_dev_probe(struct usb_interface *intf,
init_waitqueue_head(&gspca_dev->wq);
/* init video stuff */
- memcpy(&gspca_dev->vdev, &gspca_template, sizeof gspca_template);
- gspca_dev->vdev.parent = &dev->dev;
- memcpy(&gspca_dev->fops, &dev_fops, sizeof gspca_dev->fops);
- gspca_dev->vdev.fops = &gspca_dev->fops;
- gspca_dev->fops.owner = module; /* module protection */
+ gspca_dev->vdev = video_device_alloc();
+ memcpy(gspca_dev->vdev, &gspca_template, sizeof gspca_template);
+ gspca_dev->vdev->parent = &dev->dev;
+ gspca_dev->module = module;
gspca_dev->present = 1;
- ret = video_register_device(&gspca_dev->vdev,
+ video_set_drvdata(gspca_dev->vdev, gspca_dev);
+ ret = video_register_device(gspca_dev->vdev,
VFL_TYPE_GRABBER,
video_nr);
if (ret < 0) {
err("video_register_device err %d", ret);
+ video_device_release(gspca_dev->vdev);
goto out;
}
@@ -1897,7 +1926,8 @@ int gspca_dev_probe(struct usb_interface *intf,
PDEBUG(D_PROBE, "probe ok");
return 0;
out:
- kref_put(&gspca_dev->kref, gspca_delete);
+ kfree(gspca_dev->usb_buf);
+ kfree(gspca_dev);
return ret;
}
EXPORT_SYMBOL(gspca_dev_probe);
@@ -1915,7 +1945,7 @@ void gspca_disconnect(struct usb_interface *intf)
usb_set_intfdata(intf, NULL);
/* We don't want people trying to open up the device */
- video_unregister_device(&gspca_dev->vdev);
+ video_unregister_device(gspca_dev->vdev);
gspca_dev->present = 0;
gspca_dev->streaming = 0;
@@ -1998,7 +2028,7 @@ int gspca_auto_gain_n_exposure(struct gspca_dev *gspca_dev, int avg_lum,
desired lumination fast (with the risc of a slight overshoot) */
steps = abs(desired_avg_lum - avg_lum) / deadzone;
- PDEBUG(D_FRAM, "autogain: lum: %d, desired: %d, steps: %d\n",
+ PDEBUG(D_FRAM, "autogain: lum: %d, desired: %d, steps: %d",
avg_lum, desired_avg_lum, steps);
for (i = 0; i < steps; i++) {
diff --git a/linux/drivers/media/video/gspca/gspca.h b/linux/drivers/media/video/gspca/gspca.h
index 1d9dc90b4..a557738e8 100644
--- a/linux/drivers/media/video/gspca/gspca.h
+++ b/linux/drivers/media/video/gspca/gspca.h
@@ -58,6 +58,10 @@ struct cam {
int bulk_size; /* buffer size when image transfer by bulk */
struct v4l2_pix_format *cam_mode; /* size nmodes */
char nmodes;
+ __u8 bulk_nurbs; /* number of URBs in bulk mode
+ * - cannot be > MAX_NURBS
+ * - when 0 and bulk_size != 0 means
+ * 1 URB and submit done by subdriver */
__u8 epaddr;
};
@@ -97,7 +101,7 @@ struct sd_desc {
cam_pkt_op pkt_scan;
/* optional operations */
cam_v_op stopN; /* called on stream off - main alt */
- cam_v_op stop0; /* called on stream off - alt 0 */
+ cam_v_op stop0; /* called on stream off & disconnect - alt 0 */
cam_v_op dq_callback; /* called when a frame has been dequeued */
cam_jpg_op get_jcomp;
cam_jpg_op set_jcomp;
@@ -120,8 +124,8 @@ struct gspca_frame {
};
struct gspca_dev {
- struct video_device vdev; /* !! must be the first item */
- struct file_operations fops;
+ struct video_device *vdev;
+ struct module *module; /* subdriver handling the device */
struct usb_device *dev;
struct kref kref;
struct file *capt_file; /* file doing video capture */
@@ -142,22 +146,21 @@ struct gspca_dev {
char fr_q; /* next frame to queue */
char fr_o; /* next frame to dequeue */
signed char fr_queue[GSPCA_MAX_FRAMES]; /* frame queue */
- char last_packet_type;
+ __u8 last_packet_type;
+ __s8 empty_packet; /* if (-1) don't check empty packets */
+ __u8 streaming;
- __u8 iface; /* USB interface number */
- __u8 alt; /* USB alternate setting */
__u8 curr_mode; /* current camera mode */
__u32 pixfmt; /* current mode parameters */
__u16 width;
__u16 height;
+ __u32 sequence; /* frame sequence number */
atomic_t nevent; /* number of frames done */
wait_queue_head_t wq; /* wait queue */
struct mutex usb_lock; /* usb exchange protection */
struct mutex read_lock; /* read protection */
struct mutex queue_lock; /* ISOC queue protection */
- __u32 sequence; /* frame sequence number */
- char streaming;
#ifdef CONFIG_PM
char frozen; /* suspend - resume */
#endif
@@ -166,6 +169,8 @@ struct gspca_dev {
char nbufread; /* number of buffers for read() */
char nurbs; /* number of allocated URBs */
char memory; /* memory type (V4L2_MEMORY_xxx) */
+ __u8 iface; /* USB interface number */
+ __u8 alt; /* USB alternate setting */
__u8 nbalt; /* number of USB alternate settings */
};
diff --git a/linux/drivers/media/video/gspca/mars.c b/linux/drivers/media/video/gspca/mars.c
index 277ca34a8..492cdd3b5 100644
--- a/linux/drivers/media/video/gspca/mars.c
+++ b/linux/drivers/media/video/gspca/mars.c
@@ -123,7 +123,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
cam = &gspca_dev->cam;
cam->epaddr = 0x01;
cam->cam_mode = vga_mode;
- cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
+ cam->nmodes = ARRAY_SIZE(vga_mode);
sd->qindex = 1; /* set the quantization table */
return 0;
}
diff --git a/linux/drivers/media/video/gspca/ov519.c b/linux/drivers/media/video/gspca/ov519.c
index 895bcf082..b18d98191 100644
--- a/linux/drivers/media/video/gspca/ov519.c
+++ b/linux/drivers/media/video/gspca/ov519.c
@@ -40,22 +40,18 @@ struct sd {
struct gspca_dev gspca_dev; /* !! must be the first item */
/* Determined by sensor type */
- char sif;
+ __u8 sif;
- unsigned char primary_i2c_slave; /* I2C write id of sensor */
-
- unsigned char brightness;
- unsigned char contrast;
- unsigned char colors;
+ __u8 brightness;
+ __u8 contrast;
+ __u8 colors;
__u8 hflip;
__u8 vflip;
- char compress; /* Should the next frame be compressed? */
- char compress_inited; /* Are compression params uploaded? */
- char stopped; /* Streaming is temporarily paused */
+ __u8 stopped; /* Streaming is temporarily paused */
- char frame_rate; /* current Framerate (OV519 only) */
- char clockdiv; /* clockdiv override for OV519 only */
+ __u8 frame_rate; /* current Framerate (OV519 only) */
+ __u8 clockdiv; /* clockdiv override for OV519 only */
char sensor; /* Type of image sensor chip (SEN_*) */
#define SEN_UNKNOWN 0
@@ -67,7 +63,6 @@ struct sd {
#define SEN_OV7670 6
#define SEN_OV76BE 7
#define SEN_OV8610 8
-
};
/* V4L2 controls supported by the driver */
@@ -184,15 +179,15 @@ static struct v4l2_pix_format sif_mode[] = {
};
/* OV519 Camera interface register numbers */
-#define OV519_CAM_H_SIZE 0x10
-#define OV519_CAM_V_SIZE 0x11
-#define OV519_CAM_X_OFFSETL 0x12
-#define OV519_CAM_X_OFFSETH 0x13
-#define OV519_CAM_Y_OFFSETL 0x14
-#define OV519_CAM_Y_OFFSETH 0x15
-#define OV519_CAM_DIVIDER 0x16
-#define OV519_CAM_DFR 0x20
-#define OV519_CAM_FORMAT 0x25
+#define OV519_R10_H_SIZE 0x10
+#define OV519_R11_V_SIZE 0x11
+#define OV519_R12_X_OFFSETL 0x12
+#define OV519_R13_X_OFFSETH 0x13
+#define OV519_R14_Y_OFFSETL 0x14
+#define OV519_R15_Y_OFFSETH 0x15
+#define OV519_R16_DIVIDER 0x16
+#define OV519_R20_DFR 0x20
+#define OV519_R25_FORMAT 0x25
/* OV519 System Controller register numbers */
#define OV519_SYS_RESET1 0x51
@@ -562,8 +557,8 @@ static const struct ov_i2c_regvals norm_7670[] = {
{ OV7670_REG_VSTOP, 0x7a },
{ OV7670_REG_VREF, 0x0a },
- { OV7670_REG_COM3, 0 },
- { OV7670_REG_COM14, 0 },
+ { OV7670_REG_COM3, 0x00 },
+ { OV7670_REG_COM14, 0x00 },
/* Mystery scaling numbers */
{ 0x70, 0x3a },
{ 0x71, 0x35 },
@@ -595,8 +590,8 @@ static const struct ov_i2c_regvals norm_7670[] = {
{ OV7670_REG_COM8, OV7670_COM8_FASTAEC
| OV7670_COM8_AECSTEP
| OV7670_COM8_BFILT },
- { OV7670_REG_GAIN, 0 },
- { OV7670_REG_AECH, 0 },
+ { OV7670_REG_GAIN, 0x00 },
+ { OV7670_REG_AECH, 0x00 },
{ OV7670_REG_COM4, 0x40 }, /* magic reserved bit */
{ OV7670_REG_COM9, 0x18 }, /* 4x gain + magic rsvd bit */
{ OV7670_REG_BD50MAX, 0x05 },
@@ -634,16 +629,16 @@ static const struct ov_i2c_regvals norm_7670[] = {
{ OV7670_REG_COM12, 0x78 },
{ 0x4d, 0x40 },
{ 0x4e, 0x20 },
- { OV7670_REG_GFIX, 0 },
+ { OV7670_REG_GFIX, 0x00 },
{ 0x6b, 0x4a },
{ 0x74, 0x10 },
{ 0x8d, 0x4f },
- { 0x8e, 0 },
- { 0x8f, 0 },
- { 0x90, 0 },
- { 0x91, 0 },
- { 0x96, 0 },
- { 0x9a, 0 },
+ { 0x8e, 0x00 },
+ { 0x8f, 0x00 },
+ { 0x90, 0x00 },
+ { 0x91, 0x00 },
+ { 0x96, 0x00 },
+ { 0x9a, 0x00 },
{ 0xb0, 0x84 },
{ 0xb1, 0x0c },
{ 0xb2, 0x0e },
@@ -681,17 +676,17 @@ static const struct ov_i2c_regvals norm_7670[] = {
/* Matrix coefficients */
{ 0x4f, 0x80 },
{ 0x50, 0x80 },
- { 0x51, 0 },
+ { 0x51, 0x00 },
{ 0x52, 0x22 },
{ 0x53, 0x5e },
{ 0x54, 0x80 },
{ 0x58, 0x9e },
{ OV7670_REG_COM16, OV7670_COM16_AWBGAIN },
- { OV7670_REG_EDGE, 0 },
+ { OV7670_REG_EDGE, 0x00 },
{ 0x75, 0x05 },
{ 0x76, 0xe1 },
- { 0x4c, 0 },
+ { 0x4c, 0x00 },
{ 0x77, 0x01 },
{ OV7670_REG_COM13, OV7670_COM13_GAMMA
| OV7670_COM13_UVSAT
@@ -704,7 +699,7 @@ static const struct ov_i2c_regvals norm_7670[] = {
{ 0x34, 0x11 },
{ OV7670_REG_COM11, OV7670_COM11_EXP|OV7670_COM11_HZAUTO },
{ 0xa4, 0x88 },
- { 0x96, 0 },
+ { 0x96, 0x00 },
{ 0x97, 0x30 },
{ 0x98, 0x20 },
{ 0x99, 0x30 },
@@ -942,11 +937,11 @@ static int i2c_w(struct sd *sd,
/* Initiate 3-byte write cycle */
rc = reg_w(sd, R518_I2C_CTL, 0x01);
+ if (rc < 0)
+ return rc;
/* wait for write complete */
msleep(4);
- if (rc < 0)
- return rc;
return reg_r8(sd, R518_I2C_CTL);
}
@@ -1029,7 +1024,7 @@ static inline int ov51x_restart(struct sd *sd)
*/
static int init_ov_sensor(struct sd *sd)
{
- int i, success;
+ int i;
/* Reset the sensor */
if (i2c_w(sd, 0x12, 0x80) < 0)
@@ -1038,11 +1033,11 @@ static int init_ov_sensor(struct sd *sd)
/* Wait for it to initialize */
msleep(150);
- for (i = 0, success = 0; i < i2c_detect_tries && !success; i++) {
+ for (i = 0; i < i2c_detect_tries; i++) {
if (i2c_r(sd, OV7610_REG_ID_HIGH) == 0x7f &&
i2c_r(sd, OV7610_REG_ID_LOW) == 0xa2) {
- success = 1;
- continue;
+ PDEBUG(D_PROBE, "I2C synced in %d attempt(s)", i);
+ return 0;
}
/* Reset the sensor */
@@ -1054,10 +1049,7 @@ static int init_ov_sensor(struct sd *sd)
if (i2c_r(sd, 0x00) < 0)
return -EIO;
}
- if (!success)
- return -EIO;
- PDEBUG(D_PROBE, "I2C synced in %d attempt(s)", i);
- return 0;
+ return -EIO;
}
/* Set the read and write slave IDs. The "slave" argument is the write slave,
@@ -1073,7 +1065,6 @@ static int ov51x_set_slave_ids(struct sd *sd,
rc = reg_w(sd, R51x_I2C_W_SID, slave);
if (rc < 0)
return rc;
- sd->primary_i2c_slave = slave;
return reg_w(sd, R51x_I2C_R_SID, slave + 1);
}
@@ -1285,7 +1276,6 @@ static int ov6xx0_configure(struct sd *sd)
/* Turns on or off the LED. Only has an effect with OV511+/OV518(+)/OV519 */
static void ov51x_led_control(struct sd *sd, int on)
{
-/* PDEBUG(D_STREAM, "LED (%s)", on ? "on" : "off"); */
reg_w_mask(sd, OV519_GPIO_DATA_OUT0, !on, 1); /* 0 / 1 */
}
@@ -1352,7 +1342,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
}
if (ov8xx0_configure(sd) < 0) {
PDEBUG(D_ERR,
- "Failed to configure OV8xx0 sensor");
+ "Failed to configure OV8xx0 sensor");
goto error;
}
}
@@ -1482,7 +1472,7 @@ static int ov519_mode_init_regs(struct sd *sd)
return -EIO;
if (sd->sensor == SEN_OV7640) {
/* Select 8-bit input mode */
- reg_w_mask(sd, OV519_CAM_DFR, 0x10, 0x10);
+ reg_w_mask(sd, OV519_R20_DFR, 0x10, 0x10);
}
} else {
if (write_regvals(sd, mode_init_519_ov7670,
@@ -1490,14 +1480,14 @@ static int ov519_mode_init_regs(struct sd *sd)
return -EIO;
}
- reg_w(sd, OV519_CAM_H_SIZE, sd->gspca_dev.width >> 4);
- reg_w(sd, OV519_CAM_V_SIZE, sd->gspca_dev.height >> 3);
- reg_w(sd, OV519_CAM_X_OFFSETL, 0x00);
- reg_w(sd, OV519_CAM_X_OFFSETH, 0x00);
- reg_w(sd, OV519_CAM_Y_OFFSETL, 0x00);
- reg_w(sd, OV519_CAM_Y_OFFSETH, 0x00);
- reg_w(sd, OV519_CAM_DIVIDER, 0x00);
- reg_w(sd, OV519_CAM_FORMAT, 0x03); /* YUV422 */
+ reg_w(sd, OV519_R10_H_SIZE, sd->gspca_dev.width >> 4);
+ reg_w(sd, OV519_R11_V_SIZE, sd->gspca_dev.height >> 3);
+ reg_w(sd, OV519_R12_X_OFFSETL, 0x00);
+ reg_w(sd, OV519_R13_X_OFFSETH, 0x00);
+ reg_w(sd, OV519_R14_Y_OFFSETL, 0x00);
+ reg_w(sd, OV519_R15_Y_OFFSETH, 0x00);
+ reg_w(sd, OV519_R16_DIVIDER, 0x00);
+ reg_w(sd, OV519_R25_FORMAT, 0x03); /* YUV422 */
reg_w(sd, 0x26, 0x00); /* Undocumented */
/******** Set the framerate ********/
@@ -1509,8 +1499,8 @@ static int ov519_mode_init_regs(struct sd *sd)
switch (sd->sensor) {
case SEN_OV7640:
switch (sd->frame_rate) {
-/*fixme: default was 30 fps */
- case 30:
+ default:
+/* case 30: */
reg_w(sd, 0xa4, 0x0c);
reg_w(sd, 0x23, 0xff);
break;
@@ -1522,8 +1512,7 @@ static int ov519_mode_init_regs(struct sd *sd)
reg_w(sd, 0xa4, 0x0c);
reg_w(sd, 0x23, 0x1b);
break;
- default:
-/* case 15: */
+ case 15:
reg_w(sd, 0xa4, 0x04);
reg_w(sd, 0x23, 0xff);
sd->clockdiv = 1;
@@ -1576,7 +1565,6 @@ static int ov519_mode_init_regs(struct sd *sd)
}
break;
}
-
return 0;
}
@@ -1692,7 +1680,7 @@ static int mode_init_ov_sensor_regs(struct sd *sd)
* the gain or the contrast. The "reserved" bits seem
* to have some effect in this case. */
i2c_w(sd, 0x2d, 0x85);
- } else if (sd->clockdiv >= 0) {
+ } else {
i2c_w(sd, 0x11, sd->clockdiv);
}
@@ -1894,7 +1882,6 @@ static int sd_start(struct gspca_dev *gspca_dev)
ret = ov51x_restart(sd);
if (ret < 0)
goto out;
- PDEBUG(D_STREAM, "camera started alt: 0x%02x", gspca_dev->alt);
ov51x_led_control(sd, 1);
return 0;
out:
@@ -1904,8 +1891,10 @@ out:
static void sd_stopN(struct gspca_dev *gspca_dev)
{
- ov51x_stop((struct sd *) gspca_dev);
- ov51x_led_control((struct sd *) gspca_dev, 0);
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ ov51x_stop(sd);
+ ov51x_led_control(sd, 0);
}
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
@@ -1960,9 +1949,6 @@ static void setbrightness(struct gspca_dev *gspca_dev)
int val;
val = sd->brightness;
- PDEBUG(D_CONF, "brightness:%d", val);
-/* if (gspca_dev->streaming)
- * ov51x_stop(sd); */
switch (sd->sensor) {
case SEN_OV8610:
case SEN_OV7610:
@@ -1984,8 +1970,6 @@ static void setbrightness(struct gspca_dev *gspca_dev)
i2c_w(sd, OV7670_REG_BRIGHT, ov7670_abs_to_sm(val));
break;
}
-/* if (gspca_dev->streaming)
- * ov51x_restart(sd); */
}
static void setcontrast(struct gspca_dev *gspca_dev)
@@ -1994,9 +1978,6 @@ static void setcontrast(struct gspca_dev *gspca_dev)
int val;
val = sd->contrast;
- PDEBUG(D_CONF, "contrast:%d", val);
-/* if (gspca_dev->streaming)
- ov51x_stop(sd); */
switch (sd->sensor) {
case SEN_OV7610:
case SEN_OV6620:
@@ -2032,8 +2013,6 @@ static void setcontrast(struct gspca_dev *gspca_dev)
i2c_w(sd, OV7670_REG_CONTRAS, val >> 1);
break;
}
-/* if (gspca_dev->streaming)
- ov51x_restart(sd); */
}
static void setcolors(struct gspca_dev *gspca_dev)
@@ -2042,9 +2021,6 @@ static void setcolors(struct gspca_dev *gspca_dev)
int val;
val = sd->colors;
- PDEBUG(D_CONF, "saturation:%d", val);
-/* if (gspca_dev->streaming)
- ov51x_stop(sd); */
switch (sd->sensor) {
case SEN_OV8610:
case SEN_OV7610:
@@ -2069,8 +2045,6 @@ static void setcolors(struct gspca_dev *gspca_dev)
/* set REG_COM13 values for UV sat auto mode */
break;
}
-/* if (gspca_dev->streaming)
- ov51x_restart(sd); */
}
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
@@ -2078,7 +2052,8 @@ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
struct sd *sd = (struct sd *) gspca_dev;
sd->brightness = val;
- setbrightness(gspca_dev);
+ if (gspca_dev->streaming)
+ setbrightness(gspca_dev);
return 0;
}
@@ -2095,7 +2070,8 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
struct sd *sd = (struct sd *) gspca_dev;
sd->contrast = val;
- setcontrast(gspca_dev);
+ if (gspca_dev->streaming)
+ setcontrast(gspca_dev);
return 0;
}
@@ -2112,7 +2088,8 @@ static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
struct sd *sd = (struct sd *) gspca_dev;
sd->colors = val;
- setcolors(gspca_dev);
+ if (gspca_dev->streaming)
+ setcolors(gspca_dev);
return 0;
}
@@ -2129,7 +2106,8 @@ static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
struct sd *sd = (struct sd *) gspca_dev;
sd->hflip = val;
- sethvflip(sd);
+ if (gspca_dev->streaming)
+ sethvflip(sd);
return 0;
}
@@ -2146,7 +2124,8 @@ static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
struct sd *sd = (struct sd *) gspca_dev;
sd->vflip = val;
- sethvflip(sd);
+ if (gspca_dev->streaming)
+ sethvflip(sd);
return 0;
}
@@ -2187,7 +2166,7 @@ static const __devinitdata struct usb_device_id device_table[] = {
{USB_DEVICE(0x05a9, 0x8519)},
{}
};
-#undef DVNAME
+
MODULE_DEVICE_TABLE(usb, device_table);
/* -- device connect -- */
diff --git a/linux/drivers/media/video/gspca/pac207.c b/linux/drivers/media/video/gspca/pac207.c
index 0b0c573d0..39473e6b9 100644
--- a/linux/drivers/media/video/gspca/pac207.c
+++ b/linux/drivers/media/video/gspca/pac207.c
@@ -536,6 +536,7 @@ static const __devinitdata struct usb_device_id device_table[] = {
{USB_DEVICE(0x093a, 0x2471)},
{USB_DEVICE(0x093a, 0x2472)},
{USB_DEVICE(0x093a, 0x2476)},
+ {USB_DEVICE(0x145f, 0x013a)},
{USB_DEVICE(0x2001, 0xf115)},
{}
};
diff --git a/linux/drivers/media/video/gspca/pac7311.c b/linux/drivers/media/video/gspca/pac7311.c
index a122634e0..f443df77e 100644
--- a/linux/drivers/media/video/gspca/pac7311.c
+++ b/linux/drivers/media/video/gspca/pac7311.c
@@ -763,10 +763,13 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
}
+/* called on streamoff with alt 0 and on disconnect */
static void sd_stop0(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
+ if (!gspca_dev->present)
+ return;
if (sd->sensor == SENSOR_PAC7302) {
reg_w(gspca_dev, 0xff, 0x01);
reg_w(gspca_dev, 0x78, 0x40);
diff --git a/linux/drivers/media/video/gspca/sonixb.c b/linux/drivers/media/video/gspca/sonixb.c
index 4bae911da..5ca8ab780 100644
--- a/linux/drivers/media/video/gspca/sonixb.c
+++ b/linux/drivers/media/video/gspca/sonixb.c
@@ -132,8 +132,6 @@ struct sensor_data {
ignore atleast the 2 next frames for the new settings to come into effect
before doing any other adjustments */
#define AUTOGAIN_IGNORE_FRAMES 3
-#define AUTOGAIN_DEADZONE 1000
-#define DESIRED_AVG_LUM 7000
/* V4L2 controls supported by the driver */
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
@@ -857,18 +855,29 @@ static void setfreq(struct gspca_dev *gspca_dev)
static void do_autogain(struct gspca_dev *gspca_dev)
{
+ int deadzone, desired_avg_lum;
struct sd *sd = (struct sd *) gspca_dev;
int avg_lum = atomic_read(&sd->avg_lum);
if (avg_lum == -1)
return;
+ /* SIF / VGA sensors have a different autoexposure area and thus
+ different avg_lum values for the same picture brightness */
+ if (sensor_data[sd->sensor].flags & F_SIF) {
+ deadzone = 1000;
+ desired_avg_lum = 7000;
+ } else {
+ deadzone = 3000;
+ desired_avg_lum = 23000;
+ }
+
if (sd->autogain_ignore_frames > 0)
sd->autogain_ignore_frames--;
else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
- sd->brightness * DESIRED_AVG_LUM / 127,
- AUTOGAIN_DEADZONE, GAIN_KNEE, EXPOSURE_KNEE)) {
- PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d\n",
+ sd->brightness * desired_avg_lum / 127,
+ deadzone, GAIN_KNEE, EXPOSURE_KNEE)) {
+ PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d",
(int)sd->gain, (int)sd->exposure);
sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
}
@@ -1256,8 +1265,8 @@ static __devinitdata struct usb_device_id device_table[] = {
{USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX, 102)},
{USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)},
{USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)},
- {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)},
#endif
+ {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)},
{USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)},
#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
{USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)},
diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c
index aa11df134..93cc65b5f 100644
--- a/linux/drivers/media/video/gspca/sonixj.c
+++ b/linux/drivers/media/video/gspca/sonixj.c
@@ -24,6 +24,8 @@
#include "gspca.h"
#include "jpeg.h"
+#define V4L2_CID_INFRARED (V4L2_CID_PRIVATE_BASE + 0)
+
MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
MODULE_DESCRIPTION("GSPCA/SONIX JPEG USB Camera Driver");
MODULE_LICENSE("GPL");
@@ -40,6 +42,7 @@ struct sd {
unsigned char colors;
unsigned char autogain;
__u8 vflip; /* ov7630 only */
+ __u8 infrared; /* mi0360 only */
signed char ag_cnt;
#define AG_CNT_START 13
@@ -73,6 +76,8 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setinfrared(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getinfrared(struct gspca_dev *gspca_dev, __s32 *val);
static struct ctrl sd_ctrls[] = {
{
@@ -150,6 +155,22 @@ static struct ctrl sd_ctrls[] = {
.set = sd_setvflip,
.get = sd_getvflip,
},
+/* mi0360 only */
+#define INFRARED_IDX 5
+ {
+ {
+ .id = V4L2_CID_INFRARED,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Infrared",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+#define INFRARED_DEF 0
+ .default_value = INFRARED_DEF,
+ },
+ .set = sd_setinfrared,
+ .get = sd_getinfrared,
+ },
};
static struct v4l2_pix_format vga_mode[] = {
@@ -231,13 +252,13 @@ static const __u8 sn_ov7630[] = {
static const __u8 sn_ov7648[] = {
/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
- 0x00, 0x21, 0x62, 0x00, 0x1a, 0x20, 0x20, 0x20,
+ 0x00, 0x63, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20,
/* reg8 reg9 rega regb regc regd rege regf */
- 0xa1, 0x6e, 0x18, 0x65, 0x00, 0x00, 0x00, 0x10,
+ 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
- 0x03, 0x00, 0x00, 0x06, 0x06, 0x28, 0x1e, 0x82,
+ 0x03, 0x00, 0x00, 0x01, 0x00, 0x28, 0x1e, 0x00,
/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
- 0x07, 0x00, 0x00, 0x00, 0x00, 0x00
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00
};
static const __u8 sn_ov7660[] = {
@@ -469,6 +490,53 @@ static const __u8 ov7630_sensor_init[][8] = {
/* {0xb1, 0x21, 0x01, 0x88, 0x70, 0x00, 0x00, 0x10}, */
{}
};
+
+static const __u8 ov7648_sensor_init[][8] = {
+ {0xa1, 0x21, 0x76, 0x00, 0x00, 0x00, 0x00, 0x10},
+ {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset */
+ {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
+ {0xd1, 0x21, 0x03, 0xa4, 0x30, 0x88, 0x00, 0x10},
+ {0xb1, 0x21, 0x11, 0x80, 0x08, 0x00, 0x00, 0x10},
+ {0xc1, 0x21, 0x13, 0xa0, 0x04, 0x84, 0x00, 0x10},
+ {0xd1, 0x21, 0x17, 0x1a, 0x02, 0xba, 0xf4, 0x10},
+ {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
+ {0xd1, 0x21, 0x1f, 0x41, 0xc0, 0x80, 0x80, 0x10},
+ {0xd1, 0x21, 0x23, 0xde, 0xa0, 0x80, 0x32, 0x10},
+ {0xd1, 0x21, 0x27, 0xfe, 0xa0, 0x00, 0x91, 0x10},
+ {0xd1, 0x21, 0x2b, 0x00, 0x88, 0x85, 0x80, 0x10},
+ {0xc1, 0x21, 0x2f, 0x9c, 0x00, 0xc4, 0x00, 0x10},
+ {0xd1, 0x21, 0x60, 0xa6, 0x60, 0x88, 0x12, 0x10},
+ {0xd1, 0x21, 0x64, 0x88, 0x00, 0x00, 0x94, 0x10},
+ {0xd1, 0x21, 0x68, 0x7a, 0x0c, 0x00, 0x00, 0x10},
+ {0xd1, 0x21, 0x6c, 0x11, 0x33, 0x22, 0x00, 0x10},
+ {0xd1, 0x21, 0x70, 0x11, 0x00, 0x10, 0x50, 0x10},
+ {0xd1, 0x21, 0x74, 0x20, 0x06, 0x00, 0xb5, 0x10},
+ {0xd1, 0x21, 0x78, 0x8a, 0x00, 0x00, 0x00, 0x10},
+ {0xb1, 0x21, 0x7c, 0x00, 0x43, 0x00, 0x00, 0x10},
+
+ {0xd1, 0x21, 0x21, 0x86, 0x00, 0xde, 0xa0, 0x10},
+/* {0xd1, 0x21, 0x25, 0x80, 0x32, 0xfe, 0xa0, 0x10}, jfm done */
+/* {0xd1, 0x21, 0x29, 0x00, 0x91, 0x00, 0x88, 0x10}, jfm done */
+ {0xb1, 0x21, 0x2d, 0x85, 0x00, 0x00, 0x00, 0x10},
+/*...*/
+/* {0xa1, 0x21, 0x12, 0x08, 0x00, 0x00, 0x00, 0x10}, jfm done */
+/* {0xa1, 0x21, 0x75, 0x06, 0x00, 0x00, 0x00, 0x10}, jfm done */
+ {0xa1, 0x21, 0x19, 0x02, 0x00, 0x00, 0x00, 0x10},
+ {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
+/* {0xa1, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
+/* {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, * GAIN - def */
+/* {0xb1, 0x21, 0x01, 0x6c, 0x6c, 0x00, 0x00, 0x10}, * B R - def: 80 */
+/*...*/
+ {0xa1, 0x21, 0x11, 0x81, 0x00, 0x00, 0x00, 0x10}, /* CLKRC */
+/* {0xa1, 0x21, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
+/* {0xa1, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
+/* {0xa1, 0x21, 0x2a, 0x91, 0x00, 0x00, 0x00, 0x10}, jfm done */
+/* {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
+/* {0xb1, 0x21, 0x01, 0x64, 0x84, 0x00, 0x00, 0x10}, * B R - def: 80 */
+
+ {}
+};
+
static const __u8 ov7660_sensor_init[][8] = {
{0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
/* (delay 20ms) */
@@ -557,64 +625,6 @@ static const __u8 ov7660_sensor_init[][8] = {
{0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
{}
};
-/* reg 0x04 reg 0x07 reg 0x10 */
-/* expo = (COM1 & 0x02) | ((AECHH & 0x2f) << 10) | (AECh << 2) */
-
-static const __u8 ov7648_sensor_init[][8] = {
- {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
- {0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00},
- {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
- {0xA1, 0x6E, 0x3F, 0x20, 0x00, 0x00, 0x00, 0x10},
- {0xA1, 0x6E, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x10},
- {0xA1, 0x6E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x10},
- {0xD1, 0x6E, 0x04, 0x02, 0xB1, 0x02, 0x39, 0x10},
- {0xD1, 0x6E, 0x08, 0x00, 0x01, 0x00, 0x00, 0x10},
- {0xD1, 0x6E, 0x0C, 0x02, 0x7F, 0x01, 0xE0, 0x10},
- {0xD1, 0x6E, 0x12, 0x03, 0x02, 0x00, 0x03, 0x10},
- {0xD1, 0x6E, 0x16, 0x85, 0x40, 0x4A, 0x40, 0x10},
- {0xC1, 0x6E, 0x1A, 0x00, 0x80, 0x00, 0x00, 0x10},
- {0xD1, 0x6E, 0x1D, 0x08, 0x03, 0x00, 0x00, 0x10},
- {0xD1, 0x6E, 0x23, 0x00, 0xB0, 0x00, 0x94, 0x10},
- {0xD1, 0x6E, 0x27, 0x58, 0x00, 0x00, 0x00, 0x10},
- {0xD1, 0x6E, 0x2D, 0x14, 0x35, 0x61, 0x84, 0x10},
- {0xD1, 0x6E, 0x31, 0xA2, 0xBD, 0xD8, 0xFF, 0x10},
- {0xD1, 0x6E, 0x35, 0x06, 0x1E, 0x12, 0x02, 0x10},
- {0xD1, 0x6E, 0x39, 0xAA, 0x53, 0x37, 0xD5, 0x10},
- {0xA1, 0x6E, 0x3D, 0xF2, 0x00, 0x00, 0x00, 0x10},
- {0xD1, 0x6E, 0x3E, 0x00, 0x00, 0x80, 0x03, 0x10},
- {0xD1, 0x6E, 0x42, 0x03, 0x00, 0x00, 0x00, 0x10},
- {0xC1, 0x6E, 0x46, 0x00, 0x80, 0x80, 0x00, 0x10},
- {0xD1, 0x6E, 0x4B, 0x02, 0xEF, 0x08, 0xCD, 0x10},
- {0xD1, 0x6E, 0x4F, 0x00, 0xD0, 0x00, 0xA0, 0x10},
- {0xD1, 0x6E, 0x53, 0x01, 0xAA, 0x01, 0x40, 0x10},
- {0xD1, 0x6E, 0x5A, 0x50, 0x04, 0x30, 0x03, 0x10},
- {0xA1, 0x6E, 0x5E, 0x00, 0x00, 0x00, 0x00, 0x10},
- {0xD1, 0x6E, 0x5F, 0x10, 0x40, 0xFF, 0x00, 0x10},
- /* {0xD1, 0x6E, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10},
- {0xD1, 0x6E, 0x67, 0x00, 0x00, 0x00, 0x00, 0x10},
- * This is currently setting a
- * blue tint, and some things more , i leave it here for future test if
- * somene is having problems with color on this sensor
- {0xD1, 0x6E, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x10},
- {0xD1, 0x6E, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x10},
- {0xC1, 0x6E, 0x73, 0x10, 0x80, 0xEB, 0x00, 0x10},
- {0xA1, 0x6E, 0x1E, 0x03, 0x00, 0x00, 0x00, 0x10},
- {0xA1, 0x6E, 0x15, 0x01, 0x00, 0x00, 0x00, 0x10},
- {0xC1, 0x6E, 0x16, 0x40, 0x40, 0x40, 0x00, 0x10},
- {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
- {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
- {0xA1, 0x6E, 0x07, 0xB5, 0x00, 0x00, 0x00, 0x10},
- {0xA1, 0x6E, 0x18, 0x6B, 0x00, 0x00, 0x00, 0x10},
- {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
- {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
- {0xA1, 0x6E, 0x07, 0xB8, 0x00, 0x00, 0x00, 0x10}, */
- {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
- {0xA1, 0x6E, 0x06, 0x03, 0x00, 0x00, 0x00, 0x10}, /* Bright... */
- {0xA1, 0x6E, 0x07, 0x66, 0x00, 0x00, 0x00, 0x10}, /* B.. */
- {0xC1, 0x6E, 0x1A, 0x03, 0x65, 0x90, 0x00, 0x10}, /* Bright/Witen....*/
-/* {0xC1, 0x6E, 0x16, 0x45, 0x40, 0x60, 0x00, 0x10}, * Bright/Witene */
- {}
-};
static const __u8 qtable4[] = {
0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x08, 0x06,
@@ -833,8 +843,8 @@ static int configure_gpio(struct gspca_dev *gspca_dev,
break;
#endif
case SENSOR_OV7648:
- reg_w1(gspca_dev, 0x01, 0x43);
- reg_w1(gspca_dev, 0x17, 0xae);
+ reg_w1(gspca_dev, 0x01, 0x63);
+ reg_w1(gspca_dev, 0x17, 0x20);
reg_w1(gspca_dev, 0x01, 0x42);
break;
#if 1
@@ -930,6 +940,13 @@ static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
{
int i = 0;
+ i2c_w8(gspca_dev, ov7648_sensor_init[i]);
+ i++;
+/* win: dble reset */
+ i2c_w8(gspca_dev, ov7648_sensor_init[i]); /* reset */
+ i++;
+ msleep(20);
+/* win: i2c reg read 00..7f */
while (ov7648_sensor_init[i][0]) {
i2c_w8(gspca_dev, ov7648_sensor_init[i]);
i++;
@@ -971,6 +988,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
sd->colors = COLOR_DEF;
sd->autogain = AUTOGAIN_DEF;
sd->ag_cnt = -1;
+ sd->vflip = VFLIP_DEF;
+ sd->infrared = INFRARED_DEF;
switch (sd->sensor) {
case SENSOR_OV7630:
@@ -981,7 +1000,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
}
if (sd->sensor != SENSOR_OV7630)
gspca_dev->ctrl_dis |= (1 << VFLIP_IDX);
-
+ if (sd->sensor != SENSOR_MI0360)
+ gspca_dev->ctrl_dis |= (1 << INFRARED_IDX);
return 0;
}
@@ -1208,12 +1228,24 @@ static void setautogain(struct gspca_dev *gspca_dev)
static void setvflip(struct sd *sd)
{
- if (sd->sensor != SENSOR_OV7630)
- return;
i2c_w1(&sd->gspca_dev, 0x75, /* COMN */
sd->vflip ? 0x82 : 0x02);
}
+static void setinfrared(struct sd *sd)
+{
+/*fixme: different sequence for StarCam Clip and StarCam 370i */
+#if 1
+/* Clip */
+ i2c_w1(&sd->gspca_dev, 0x02, /* gpio */
+ sd->infrared ? 0x66 : 0x64);
+#else
+/* 370i */
+ i2c_w1(&sd->gspca_dev, 0x02, /* gpio */
+ sd->infrared ? 0x55 : 0x54);
+#endif
+}
+
/* -- start the camera -- */
static int sd_start(struct gspca_dev *gspca_dev)
{
@@ -1248,7 +1280,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
reg17 = 0xe2;
break;
case SENSOR_OV7648:
- reg17 = 0xae;
+ reg17 = 0x20;
break;
#if 1
/*jfm: from win trace */
@@ -1269,6 +1301,10 @@ static int sd_start(struct gspca_dev *gspca_dev)
for (i = 0; i < 8; i++)
reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
switch (sd->sensor) {
+ case SENSOR_OV7648:
+ reg_w1(gspca_dev, 0x9a, 0x0a);
+ reg_w1(gspca_dev, 0x99, 0x60);
+ break;
case SENSOR_OV7660:
reg_w1(gspca_dev, 0x9a, 0x05);
break;
@@ -1313,8 +1349,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
break;
case SENSOR_OV7648:
ov7648_InitSensor(gspca_dev);
- reg17 = 0xa2;
- reg1 = 0x44;
+ reg17 = 0x21;
+/* reg1 = 0x42; * 42 - 46? */
/* if (mode)
; * 320x2...
else
@@ -1358,8 +1394,10 @@ static int sd_start(struct gspca_dev *gspca_dev)
reg_w1(gspca_dev, 0x17, reg17);
switch (sd->sensor) {
- case SENSOR_HV7131R:
case SENSOR_MI0360:
+ setinfrared(sd);
+ /* fall thru */
+ case SENSOR_HV7131R:
case SENSOR_MO4000:
case SENSOR_OM6802:
setbrightness(gspca_dev);
@@ -1384,6 +1422,8 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
{ 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
static const __u8 stopmi0360[] =
{ 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
+ static const __u8 stopov7648[] =
+ { 0xa1, 0x21, 0x76, 0x20, 0x00, 0x00, 0x00, 0x10 };
__u8 data;
const __u8 *sn9c1xx;
@@ -1397,8 +1437,10 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
i2c_w8(gspca_dev, stopmi0360);
data = 0x29;
break;
- case SENSOR_OV7630:
case SENSOR_OV7648:
+ i2c_w8(gspca_dev, stopov7648);
+ /* fall thru */
+ case SENSOR_OV7630:
data = 0x29;
break;
default:
@@ -1613,6 +1655,24 @@ static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
return 0;
}
+static int sd_setinfrared(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ sd->infrared = val;
+ if (gspca_dev->streaming)
+ setinfrared(sd);
+ return 0;
+}
+
+static int sd_getinfrared(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ *val = sd->infrared;
+ return 0;
+}
+
/* sub-driver description */
static const struct sd_desc sd_desc = {
.name = MODULE_NAME,
@@ -1638,8 +1698,8 @@ static const __devinitdata struct usb_device_id device_table[] = {
{USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)},
{USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)},
{USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)},
- {USB_DEVICE(0x0471, 0x0328), BSI(SN9C105, MI0360, 0x5d)},
#endif
+ {USB_DEVICE(0x0471, 0x0328), BSI(SN9C105, MI0360, 0x5d)},
{USB_DEVICE(0x0471, 0x0330), BSI(SN9C105, MI0360, 0x5d)},
{USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, HV7131R, 0x11)},
/* bw600.inf:
@@ -1664,7 +1724,7 @@ static const __devinitdata struct usb_device_id device_table[] = {
/* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */
{USB_DEVICE(0x0c45, 0x6128), BSI(SN9C110, OM6802, 0x21)}, /*sn9c325?*/
/*bw600.inf:*/
- {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C110, OV7648, 0x21)}, /*sn9c325?*/
+ {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C120, OV7648, 0x21)}, /*sn9c110?*/
{USB_DEVICE(0x0c45, 0x612c), BSI(SN9C110, MO4000, 0x21)},
{USB_DEVICE(0x0c45, 0x612e), BSI(SN9C110, OV7630, 0x21)},
/* {USB_DEVICE(0x0c45, 0x612f), BSI(SN9C110, ICM105C, 0x??)}, */
@@ -1672,8 +1732,8 @@ static const __devinitdata struct usb_device_id device_table[] = {
{USB_DEVICE(0x0c45, 0x6130), BSI(SN9C120, MI0360, 0x5d)},
#endif
{USB_DEVICE(0x0c45, 0x6138), BSI(SN9C120, MO4000, 0x21)},
+ {USB_DEVICE(0x0c45, 0x613a), BSI(SN9C120, OV7648, 0x21)},
#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
-/* {USB_DEVICE(0x0c45, 0x613a), BSI(SN9C120, OV7648, 0x??)}, */
{USB_DEVICE(0x0c45, 0x613b), BSI(SN9C120, OV7660, 0x21)},
{USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)},
/* {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x??)}, */
diff --git a/linux/drivers/media/video/gspca/spca500.c b/linux/drivers/media/video/gspca/spca500.c
index a3f616709..2e1c5e50e 100644
--- a/linux/drivers/media/video/gspca/spca500.c
+++ b/linux/drivers/media/video/gspca/spca500.c
@@ -650,10 +650,10 @@ static int sd_config(struct gspca_dev *gspca_dev,
sd->subtype = id->driver_info;
if (sd->subtype != LogitechClickSmart310) {
cam->cam_mode = vga_mode;
- cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
+ cam->nmodes = ARRAY_SIZE(vga_mode);
} else {
cam->cam_mode = sif_mode;
- cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
+ cam->nmodes = ARRAY_SIZE(sif_mode);
}
sd->qindex = 5;
sd->brightness = BRIGHTNESS_DEF;
diff --git a/linux/drivers/media/video/gspca/spca501.c b/linux/drivers/media/video/gspca/spca501.c
index 979344907..17dab9859 100644
--- a/linux/drivers/media/video/gspca/spca501.c
+++ b/linux/drivers/media/video/gspca/spca501.c
@@ -34,6 +34,8 @@ struct sd {
unsigned short contrast;
__u8 brightness;
__u8 colors;
+ __u8 blue_balance;
+ __u8 red_balance;
char subtype;
#define Arowana300KCMOSCamera 0
@@ -52,6 +54,10 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val);
static struct ctrl sd_ctrls[] = {
#define MY_BRIGHTNESS 0
@@ -63,7 +69,7 @@ static struct ctrl sd_ctrls[] = {
.minimum = 0,
.maximum = 127,
.step = 1,
- .default_value = 63,
+ .default_value = 0,
},
.set = sd_setbrightness,
.get = sd_getbrightness,
@@ -75,9 +81,9 @@ static struct ctrl sd_ctrls[] = {
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Contrast",
.minimum = 0,
- .maximum = 0xffff,
+ .maximum = 64725,
.step = 1,
- .default_value = 0xaa00,
+ .default_value = 64725,
},
.set = sd_setcontrast,
.get = sd_getcontrast,
@@ -91,11 +97,39 @@ static struct ctrl sd_ctrls[] = {
.minimum = 0,
.maximum = 63,
.step = 1,
- .default_value = 31,
+ .default_value = 20,
},
.set = sd_setcolors,
.get = sd_getcolors,
},
+#define MY_BLUE_BALANCE 3
+ {
+ {
+ .id = V4L2_CID_BLUE_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Blue Balance",
+ .minimum = 0,
+ .maximum = 127,
+ .step = 1,
+ .default_value = 0,
+ },
+ .set = sd_setblue_balance,
+ .get = sd_getblue_balance,
+ },
+#define MY_RED_BALANCE 4
+ {
+ {
+ .id = V4L2_CID_RED_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Red Balance",
+ .minimum = 0,
+ .maximum = 127,
+ .step = 1,
+ .default_value = 0,
+ },
+ .set = sd_setred_balance,
+ .get = sd_getred_balance,
+ },
};
static struct v4l2_pix_format vga_mode[] = {
@@ -1822,6 +1856,7 @@ static int reg_write(struct usb_device *dev,
return ret;
}
+#if 0
/* returns: negative is error, pos or zero is data */
static int reg_read(struct gspca_dev *gspca_dev,
__u16 req, /* bRequest */
@@ -1845,6 +1880,7 @@ static int reg_read(struct gspca_dev *gspca_dev,
}
return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
}
+#endif
static int write_vector(struct gspca_dev *gspca_dev,
const __u16 data[][3])
@@ -1869,18 +1905,18 @@ static void setbrightness(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
- reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x11, sd->brightness);
reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x12, sd->brightness);
- reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x13, sd->brightness);
}
static void getbrightness(struct gspca_dev *gspca_dev)
{
+#if 0
struct sd *sd = (struct sd *) gspca_dev;
__u16 brightness;
- brightness = reg_read(gspca_dev, SPCA501_REG_CCDSP, 0x11, 2);
- sd->brightness = brightness << 1;
+ brightness = reg_read(gspca_dev, SPCA501_REG_CCDSP, 0x12, 2);
+ sd->brightness = brightness;
+#endif
}
static void setcontrast(struct gspca_dev *gspca_dev)
@@ -1906,7 +1942,6 @@ static void getcontrast(struct gspca_dev *gspca_dev)
0x01,
1) & 0xff);
#endif
-/* spca50x->contrast = 0xaa01; */
}
static void setcolors(struct gspca_dev *gspca_dev)
@@ -1918,11 +1953,25 @@ static void setcolors(struct gspca_dev *gspca_dev)
static void getcolors(struct gspca_dev *gspca_dev)
{
+#if 0
struct sd *sd = (struct sd *) gspca_dev;
sd->colors = reg_read(gspca_dev, SPCA501_REG_CCDSP, 0x0c, 2);
-/* sd->hue = (reg_read(gspca_dev, SPCA501_REG_CCDSP, 0x13, */
-/* 2) & 0xFF) << 8; */
+#endif
+}
+
+static void setblue_balance(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x11, sd->blue_balance);
+}
+
+static void setred_balance(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x13, sd->red_balance);
}
/* this function is called at probe time */
@@ -1941,6 +1990,14 @@ static int sd_config(struct gspca_dev *gspca_dev,
sd->contrast = sd_ctrls[MY_CONTRAST].qctrl.default_value;
sd->colors = sd_ctrls[MY_COLOR].qctrl.default_value;
+ return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
switch (sd->subtype) {
case Arowana300KCMOSCamera:
case SmileIntlCamera:
@@ -1959,15 +2016,17 @@ static int sd_config(struct gspca_dev *gspca_dev,
goto error;
break;
}
+ PDEBUG(D_STREAM, "Initializing SPCA501 finished");
return 0;
error:
return -EINVAL;
}
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
+ struct usb_device *dev = gspca_dev->dev;
+ int mode;
switch (sd->subtype) {
case ThreeComHomeConnectLite:
@@ -1987,14 +2046,6 @@ static int sd_init(struct gspca_dev *gspca_dev)
/* Generic 501 open data */
write_vector(gspca_dev, spca501_open_data);
}
- PDEBUG(D_STREAM, "Initializing SPCA501 finished");
- return 0;
-}
-
-static int sd_start(struct gspca_dev *gspca_dev)
-{
- struct usb_device *dev = gspca_dev->dev;
- int mode;
/* memorize the wanted pixel format */
mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
@@ -2033,8 +2084,11 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x01, 0x00);
}
+/* called on streamoff with alt 0 and on disconnect */
static void sd_stop0(struct gspca_dev *gspca_dev)
{
+ if (!gspca_dev->present)
+ return;
reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x05, 0x00);
}
@@ -2121,6 +2175,42 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
return 0;
}
+static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ sd->blue_balance = val;
+ if (gspca_dev->streaming)
+ setblue_balance(gspca_dev);
+ return 0;
+}
+
+static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ *val = sd->blue_balance;
+ return 0;
+}
+
+static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ sd->red_balance = val;
+ if (gspca_dev->streaming)
+ setred_balance(gspca_dev);
+ return 0;
+}
+
+static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ *val = sd->red_balance;
+ return 0;
+}
+
/* sub-driver description */
static const struct sd_desc sd_desc = {
.name = MODULE_NAME,
diff --git a/linux/drivers/media/video/gspca/spca505.c b/linux/drivers/media/video/gspca/spca505.c
index 62bab3cc1..c52598e94 100644
--- a/linux/drivers/media/video/gspca/spca505.c
+++ b/linux/drivers/media/video/gspca/spca505.c
@@ -811,8 +811,12 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
reg_write(gspca_dev->dev, 0x02, 0x00, 0x00);
}
+/* called on streamoff with alt 0 and on disconnect */
static void sd_stop0(struct gspca_dev *gspca_dev)
{
+ if (!gspca_dev->present)
+ return;
+
/* This maybe reset or power control */
reg_write(gspca_dev->dev, 0x03, 0x03, 0x20);
reg_write(gspca_dev->dev, 0x03, 0x01, 0x0);
diff --git a/linux/drivers/media/video/gspca/spca561.c b/linux/drivers/media/video/gspca/spca561.c
index 5b65dd66b..4c0046cc7 100644
--- a/linux/drivers/media/video/gspca/spca561.c
+++ b/linux/drivers/media/video/gspca/spca561.c
@@ -780,10 +780,13 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
}
}
+/* called on streamoff with alt 0 and on disconnect */
static void sd_stop0(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
+ if (!gspca_dev->present)
+ return;
if (sd->chip_revision == Rev012A) {
reg_w_val(gspca_dev->dev, 0x8118, 0x29);
reg_w_val(gspca_dev->dev, 0x8114, 0x08);
diff --git a/linux/drivers/media/video/gspca/tv8532.c b/linux/drivers/media/video/gspca/tv8532.c
index 8204dabb1..4e18f90ba 100644
--- a/linux/drivers/media/video/gspca/tv8532.c
+++ b/linux/drivers/media/video/gspca/tv8532.c
@@ -30,15 +30,10 @@ MODULE_LICENSE("GPL");
struct sd {
struct gspca_dev gspca_dev; /* !! must be the first item */
- int buflen; /* current length of tmpbuf */
- __u8 tmpbuf[352 * 288 + 10 * 288]; /* no protection... */
- __u8 tmpbuf2[352 * 288]; /* no protection... */
+ __u16 brightness;
+ __u16 contrast;
- unsigned short brightness;
- unsigned short contrast;
-
- char packet;
- char synchro;
+ __u8 packet;
};
/* V4L2 controls supported by the driver */
@@ -392,6 +387,8 @@ static void setbrightness(struct gspca_dev *gspca_dev)
/* -- start the camera -- */
static int sd_start(struct gspca_dev *gspca_dev)
{
+ struct sd *sd = (struct sd *) gspca_dev;
+
reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x32);
reg_w_1(gspca_dev, TV8532_AD_BITCTRL, 0x00);
tv_8532ReadRegisters(gspca_dev);
@@ -443,6 +440,10 @@ static int sd_start(struct gspca_dev *gspca_dev)
/************************************************/
tv_8532_PollReg(gspca_dev);
reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x00); /* 0x31 */
+
+ gspca_dev->empty_packet = 0; /* check the empty packets */
+ sd->packet = 0; /* ignore the first packets */
+
return 0;
}
@@ -451,111 +452,36 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0b);
}
-static void tv8532_preprocess(struct gspca_dev *gspca_dev)
-{
- struct sd *sd = (struct sd *) gspca_dev;
-/* we should received a whole frame with header and EOL marker
- * in gspca_dev->tmpbuf and return a GBRG pattern in gspca_dev->tmpbuf2
- * sequence 2bytes header the Alternate pixels bayer GB 4 bytes
- * Alternate pixels bayer RG 4 bytes EOL */
- int width = gspca_dev->width;
- int height = gspca_dev->height;
- unsigned char *dst = sd->tmpbuf2;
- unsigned char *data = sd->tmpbuf;
- int i;
-
- /* precompute where is the good bayer line */
- if (((data[3] + data[width + 7]) >> 1)
- + (data[4] >> 2)
- + (data[width + 6] >> 1) >= ((data[2] + data[width + 6]) >> 1)
- + (data[3] >> 2)
- + (data[width + 5] >> 1))
- data += 3;
- else
- data += 2;
- for (i = 0; i < height / 2; i++) {
- memcpy(dst, data, width);
- data += width + 3;
- dst += width;
- memcpy(dst, data, width);
- data += width + 7;
- dst += width;
- }
-}
-
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
struct gspca_frame *frame, /* target */
__u8 *data, /* isoc packet */
int len) /* iso packet length */
{
struct sd *sd = (struct sd *) gspca_dev;
-
- if (data[0] != 0x80) {
- sd->packet++;
- if (sd->buflen + len > sizeof sd->tmpbuf) {
- if (gspca_dev->last_packet_type != DISCARD_PACKET) {
- PDEBUG(D_PACK, "buffer overflow");
- gspca_dev->last_packet_type = DISCARD_PACKET;
- }
- return;
- }
- memcpy(&sd->tmpbuf[sd->buflen], data, len);
- sd->buflen += len;
- return;
- }
-
- /* here we detect 0x80 */
- /* counter is limited so we need few header for a frame :) */
-
- /* header 0x80 0x80 0x80 0x80 0x80 */
- /* packet 00 63 127 145 00 */
- /* sof 0 1 1 0 0 */
-
- /* update sequence */
- if (sd->packet == 63 || sd->packet == 127)
- sd->synchro = 1;
-
- /* is there a frame start ? */
- if (sd->packet >= (gspca_dev->height >> 1) - 1) {
- PDEBUG(D_PACK, "SOF > %d packet %d", sd->synchro,
- sd->packet);
- if (!sd->synchro) { /* start of frame */
- if (gspca_dev->last_packet_type == FIRST_PACKET) {
- tv8532_preprocess(gspca_dev);
- frame = gspca_frame_add(gspca_dev,
- LAST_PACKET,
- frame, sd->tmpbuf2,
- gspca_dev->width *
- gspca_dev->width);
- }
- gspca_frame_add(gspca_dev, FIRST_PACKET,
- frame, data, 0);
- memcpy(sd->tmpbuf, data, len);
- sd->buflen = len;
- sd->packet = 0;
- return;
- }
- if (gspca_dev->last_packet_type != DISCARD_PACKET) {
- PDEBUG(D_PACK,
- "Warning wrong TV8532 frame detection %d",
- sd->packet);
- gspca_dev->last_packet_type = DISCARD_PACKET;
- }
- return;
- }
-
- if (!sd->synchro) {
- /* Drop packet frame corrupt */
- PDEBUG(D_PACK, "DROP SOF %d packet %d",
- sd->synchro, sd->packet);
- sd->packet = 0;
- gspca_dev->last_packet_type = DISCARD_PACKET;
- return;
- }
- sd->synchro = 1;
- sd->packet++;
- memcpy(&sd->tmpbuf[sd->buflen], data, len);
- sd->buflen += len;
+ int packet_type0, packet_type1;
+
+ packet_type0 = packet_type1 = INTER_PACKET;
+ if (gspca_dev->empty_packet) {
+ gspca_dev->empty_packet = 0;
+ sd->packet = gspca_dev->height / 2;
+ packet_type0 = FIRST_PACKET;
+ } else if (sd->packet == 0)
+ return; /* 2 more lines in 352x288 ! */
+ sd->packet--;
+ if (sd->packet == 0)
+ packet_type1 = LAST_PACKET;
+
+ /* each packet contains:
+ * - header 2 bytes
+ * - RG line
+ * - 4 bytes
+ * - GB line
+ * - 4 bytes
+ */
+ gspca_frame_add(gspca_dev, packet_type0,
+ frame, data + 2, gspca_dev->width);
+ gspca_frame_add(gspca_dev, packet_type1,
+ frame, data + gspca_dev->width + 6, gspca_dev->width);
}
static void setcontrast(struct gspca_dev *gspca_dev)
diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c
index 95531138e..f6fae60ae 100644
--- a/linux/drivers/media/video/gspca/vc032x.c
+++ b/linux/drivers/media/video/gspca/vc032x.c
@@ -1830,10 +1830,13 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
reg_w(dev, 0xa0, 0x09, 0xb003);
}
+/* called on streamoff with alt 0 and on disconnect */
static void sd_stop0(struct gspca_dev *gspca_dev)
{
struct usb_device *dev = gspca_dev->dev;
+ if (!gspca_dev->present)
+ return;
reg_w(dev, 0x89, 0xffff, 0xffff);
}
diff --git a/linux/drivers/media/video/gspca/zc3xx.c b/linux/drivers/media/video/gspca/zc3xx.c
index 0b1871cec..adbca6a9d 100644
--- a/linux/drivers/media/video/gspca/zc3xx.c
+++ b/linux/drivers/media/video/gspca/zc3xx.c
@@ -2266,7 +2266,7 @@ static const struct usb_action hdcs2020b_NoFliker[] = {
{}
};
-static const struct usb_action hv7131bxx_Initial[] = {
+static const struct usb_action hv7131bxx_Initial[] = { /* 320x240 */
{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
{0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
{0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT},
@@ -2290,7 +2290,7 @@ static const struct usb_action hv7131bxx_Initial[] = {
{0xaa, 0x14, 0x0001},
{0xaa, 0x15, 0x00e8},
{0xaa, 0x16, 0x0002},
- {0xaa, 0x17, 0x0086},
+ {0xaa, 0x17, 0x0086}, /* 00,17,88,aa */
{0xaa, 0x31, 0x0038},
{0xaa, 0x32, 0x0038},
{0xaa, 0x33, 0x0038},
@@ -2309,72 +2309,11 @@ static const struct usb_action hv7131bxx_Initial[] = {
{0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
{0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
{0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
- {0xaa, 0x02, 0x0080}, /* {0xaa, 0x02, 0x0090}; */
- {0xa1, 0x01, 0x0002},
- {0xa0, 0x00, ZC3XX_R092_I2CADDRESSSELECT},
- {0xa0, 0x02, ZC3XX_R090_I2CCOMMAND},
- {0xa1, 0x01, 0x0091},
- {0xa1, 0x01, 0x0095},
- {0xa1, 0x01, 0x0096},
-
- {0xa1, 0x01, 0x0008},
- {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
- {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
- {0xa1, 0x01, 0x01c8},
- {0xa1, 0x01, 0x01c9},
- {0xa1, 0x01, 0x01ca},
- {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
-
- {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */
- {0xa0, 0xf8, ZC3XX_R10B_RGB01},
- {0xa0, 0xf8, ZC3XX_R10C_RGB02},
- {0xa0, 0xf8, ZC3XX_R10D_RGB10},
- {0xa0, 0x50, ZC3XX_R10E_RGB11},
- {0xa0, 0xf8, ZC3XX_R10F_RGB12},
- {0xa0, 0xf8, ZC3XX_R110_RGB20},
- {0xa0, 0xf8, ZC3XX_R111_RGB21},
- {0xa0, 0x50, ZC3XX_R112_RGB22},
- {0xa1, 0x01, 0x0180},
- {0xa0, 0x10, ZC3XX_R180_AUTOCORRECTENABLE},
- {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
- {0xaa, 0x25, 0x0007},
- {0xaa, 0x26, 0x00a1},
- {0xaa, 0x27, 0x0020},
- {0xaa, 0x20, 0x0000},
- {0xaa, 0x21, 0x00a0},
- {0xaa, 0x22, 0x0016},
- {0xaa, 0x23, 0x0040},
-
- {0xa0, 0x10, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 2F */
- {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 4d */
- {0xa0, 0x60, ZC3XX_R192_EXPOSURELIMITLOW},
- {0xa0, 0x01, ZC3XX_R195_ANTIFLICKERHIGH},
- {0xa0, 0x86, ZC3XX_R196_ANTIFLICKERMID},
- {0xa0, 0xa0, ZC3XX_R197_ANTIFLICKERLOW},
- {0xa0, 0x07, ZC3XX_R18C_AEFREEZE},
- {0xa0, 0x0f, ZC3XX_R18F_AEUNFREEZE},
- {0xa0, 0x18, ZC3XX_R1A9_DIGITALLIMITDIFF},
- {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
- {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},
- {0xa0, 0xa0, ZC3XX_R01E_HSYNC_1},
- {0xa0, 0x16, ZC3XX_R01F_HSYNC_2},
- {0xa0, 0x40, ZC3XX_R020_HSYNC_3},
- {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
- {0xa1, 0x01, 0x001d},
- {0xa1, 0x01, 0x001e},
- {0xa1, 0x01, 0x001f},
- {0xa1, 0x01, 0x0020},
- {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
- {0xa1, 0x01, 0x0180},
- {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
- {0xa0, 0x40, ZC3XX_R116_RGAIN},
- {0xa0, 0x40, ZC3XX_R117_GGAIN},
- {0xa0, 0x40, ZC3XX_R118_BGAIN},
-/* {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, */
+ {0xaa, 0x02, 0x0090}, /* 00,02,80,aa */
{}
};
-static const struct usb_action hv7131bxx_InitialScale[] = {
+static const struct usb_action hv7131bxx_InitialScale[] = { /* 640x480*/
{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
{0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
{0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT},
@@ -2418,65 +2357,156 @@ static const struct usb_action hv7131bxx_InitialScale[] = {
{0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
{0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
{0xaa, 0x02, 0x0090}, /* {0xaa, 0x02, 0x0080}, */
- {0xa1, 0x01, 0x0002},
- {0xa0, 0x00, ZC3XX_R092_I2CADDRESSSELECT},
- {0xa0, 0x02, ZC3XX_R090_I2CCOMMAND},
- {0xa1, 0x01, 0x0091},
- {0xa1, 0x01, 0x0095},
- {0xa1, 0x01, 0x0096},
- {0xa1, 0x01, 0x0008},
- {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
- {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
- {0xa1, 0x01, 0x01c8},
- {0xa1, 0x01, 0x01c9},
- {0xa1, 0x01, 0x01ca},
- {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
-
- {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */
- {0xa0, 0xf8, ZC3XX_R10B_RGB01},
- {0xa0, 0xf8, ZC3XX_R10C_RGB02},
- {0xa0, 0xf8, ZC3XX_R10D_RGB10},
- {0xa0, 0x50, ZC3XX_R10E_RGB11},
- {0xa0, 0xf8, ZC3XX_R10F_RGB12},
- {0xa0, 0xf8, ZC3XX_R110_RGB20},
- {0xa0, 0xf8, ZC3XX_R111_RGB21},
- {0xa0, 0x50, ZC3XX_R112_RGB22},
- {0xa1, 0x01, 0x0180},
- {0xa0, 0x10, ZC3XX_R180_AUTOCORRECTENABLE},
- {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
- {0xaa, 0x25, 0x0007},
- {0xaa, 0x26, 0x00a1},
- {0xaa, 0x27, 0x0020},
- {0xaa, 0x20, 0x0000},
- {0xaa, 0x21, 0x0040},
- {0xaa, 0x22, 0x0013},
- {0xaa, 0x23, 0x004c},
- {0xa0, 0x10, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 2f */
- {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 4d */
- {0xa0, 0x60, ZC3XX_R192_EXPOSURELIMITLOW}, /* 60 */
- {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
- {0xa0, 0xc3, ZC3XX_R196_ANTIFLICKERMID},
- {0xa0, 0x50, ZC3XX_R197_ANTIFLICKERLOW},
- {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
- {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
- {0xa0, 0x18, ZC3XX_R1A9_DIGITALLIMITDIFF},
- {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
- {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},
- {0xa0, 0x40, ZC3XX_R01E_HSYNC_1},
- {0xa0, 0x13, ZC3XX_R01F_HSYNC_2},
- {0xa0, 0x4c, ZC3XX_R020_HSYNC_3},
- {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
- {0xa1, 0x01, 0x001d},
- {0xa1, 0x01, 0x001e},
- {0xa1, 0x01, 0x001f},
- {0xa1, 0x01, 0x0020},
- {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
- {0xa1, 0x01, 0x0180},
- {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
- {0xa0, 0x40, ZC3XX_R116_RGAIN},
- {0xa0, 0x40, ZC3XX_R117_GGAIN},
- {0xa0, 0x40, ZC3XX_R118_BGAIN},
-/* {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, */
+ {}
+};
+static const struct usb_action hv7131b_50HZ[] = { /* 640x480*/
+ {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
+ {0xaa, 0x25, 0x0007}, /* 00,25,07,aa */
+ {0xaa, 0x26, 0x0053}, /* 00,26,53,aa */
+ {0xaa, 0x27, 0x0000}, /* 00,27,00,aa */
+ {0xaa, 0x20, 0x0000}, /* 00,20,00,aa */
+ {0xaa, 0x21, 0x0050}, /* 00,21,50,aa */
+ {0xaa, 0x22, 0x001b}, /* 00,22,1b,aa */
+ {0xaa, 0x23, 0x00fc}, /* 00,23,fc,aa */
+ {0xa0, 0x2f, ZC3XX_R190_SYNC00LOW}, /* 01,90,2f,cc */
+ {0xa0, 0x9b, ZC3XX_R191_SYNC00MID}, /* 01,91,9b,cc */
+ {0xa0, 0x80, ZC3XX_R192_SYNC00HIGH}, /* 01,92,80,cc */
+ {0xa0, 0x00, ZC3XX_R195_SYNC01LOW}, /* 01,95,00,cc */
+ {0xa0, 0xea, ZC3XX_R196_SYNC01MID}, /* 01,96,ea,cc */
+ {0xa0, 0x60, ZC3XX_R197_SYNC01HIGH}, /* 01,97,60,cc */
+ {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0c,cc */
+ {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,18,cc */
+ {0xa0, 0x18, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,18,cc */
+ {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
+ {0xa0, 0x00, ZC3XX_R01D_HSYNC_0}, /* 00,1d,00,cc */
+ {0xa0, 0x50, ZC3XX_R01E_HSYNC_1}, /* 00,1e,50,cc */
+ {0xa0, 0x1b, ZC3XX_R01F_HSYNC_2}, /* 00,1f,1b,cc */
+ {0xa0, 0xfc, ZC3XX_R020_HSYNC_3}, /* 00,20,fc,cc */
+ {}
+};
+static const struct usb_action hv7131b_50HZScale[] = { /* 320x240 */
+ {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
+ {0xaa, 0x25, 0x0007}, /* 00,25,07,aa */
+ {0xaa, 0x26, 0x0053}, /* 00,26,53,aa */
+ {0xaa, 0x27, 0x0000}, /* 00,27,00,aa */
+ {0xaa, 0x20, 0x0000}, /* 00,20,00,aa */
+ {0xaa, 0x21, 0x0050}, /* 00,21,50,aa */
+ {0xaa, 0x22, 0x0012}, /* 00,22,12,aa */
+ {0xaa, 0x23, 0x0080}, /* 00,23,80,aa */
+ {0xa0, 0x2f, ZC3XX_R190_SYNC00LOW}, /* 01,90,2f,cc */
+ {0xa0, 0x9b, ZC3XX_R191_SYNC00MID}, /* 01,91,9b,cc */
+ {0xa0, 0x80, ZC3XX_R192_SYNC00HIGH}, /* 01,92,80,cc */
+ {0xa0, 0x01, ZC3XX_R195_SYNC01LOW}, /* 01,95,01,cc */
+ {0xa0, 0xd4, ZC3XX_R196_SYNC01MID}, /* 01,96,d4,cc */
+ {0xa0, 0xc0, ZC3XX_R197_SYNC01HIGH}, /* 01,97,c0,cc */
+ {0xa0, 0x07, ZC3XX_R18C_AEFREEZE}, /* 01,8c,07,cc */
+ {0xa0, 0x0f, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,0f,cc */
+ {0xa0, 0x18, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,18,cc */
+ {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
+ {0xa0, 0x00, ZC3XX_R01D_HSYNC_0}, /* 00,1d,00,cc */
+ {0xa0, 0x50, ZC3XX_R01E_HSYNC_1}, /* 00,1e,50,cc */
+ {0xa0, 0x12, ZC3XX_R01F_HSYNC_2}, /* 00,1f,12,cc */
+ {0xa0, 0x80, ZC3XX_R020_HSYNC_3}, /* 00,20,80,cc */
+ {}
+};
+static const struct usb_action hv7131b_60HZ[] = { /* 640x480*/
+ {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
+ {0xaa, 0x25, 0x0007}, /* 00,25,07,aa */
+ {0xaa, 0x26, 0x00a1}, /* 00,26,a1,aa */
+ {0xaa, 0x27, 0x0020}, /* 00,27,20,aa */
+ {0xaa, 0x20, 0x0000}, /* 00,20,00,aa */
+ {0xaa, 0x21, 0x0040}, /* 00,21,40,aa */
+ {0xaa, 0x22, 0x0013}, /* 00,22,13,aa */
+ {0xaa, 0x23, 0x004c}, /* 00,23,4c,aa */
+ {0xa0, 0x2f, ZC3XX_R190_SYNC00LOW}, /* 01,90,2f,cc */
+ {0xa0, 0x4d, ZC3XX_R191_SYNC00MID}, /* 01,91,4d,cc */
+ {0xa0, 0x60, ZC3XX_R192_SYNC00HIGH}, /* 01,92,60,cc */
+ {0xa0, 0x00, ZC3XX_R195_SYNC01LOW}, /* 01,95,00,cc */
+ {0xa0, 0xc3, ZC3XX_R196_SYNC01MID}, /* 01,96,c3,cc */
+ {0xa0, 0x50, ZC3XX_R197_SYNC01HIGH}, /* 01,97,50,cc */
+ {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0c,cc */
+ {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,18,cc */
+ {0xa0, 0x18, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,18,cc */
+ {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
+ {0xa0, 0x00, ZC3XX_R01D_HSYNC_0}, /* 00,1d,00,cc */
+ {0xa0, 0x40, ZC3XX_R01E_HSYNC_1}, /* 00,1e,40,cc */
+ {0xa0, 0x13, ZC3XX_R01F_HSYNC_2}, /* 00,1f,13,cc */
+ {0xa0, 0x4c, ZC3XX_R020_HSYNC_3}, /* 00,20,4c,cc */
+ {}
+};
+static const struct usb_action hv7131b_60HZScale[] = { /* 320x240 */
+ {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
+ {0xaa, 0x25, 0x0007}, /* 00,25,07,aa */
+ {0xaa, 0x26, 0x00a1}, /* 00,26,a1,aa */
+ {0xaa, 0x27, 0x0020}, /* 00,27,20,aa */
+ {0xaa, 0x20, 0x0000}, /* 00,20,00,aa */
+ {0xaa, 0x21, 0x00a0}, /* 00,21,a0,aa */
+ {0xaa, 0x22, 0x0016}, /* 00,22,16,aa */
+ {0xaa, 0x23, 0x0040}, /* 00,23,40,aa */
+ {0xa0, 0x2f, ZC3XX_R190_SYNC00LOW}, /* 01,90,2f,cc */
+ {0xa0, 0x4d, ZC3XX_R191_SYNC00MID}, /* 01,91,4d,cc */
+ {0xa0, 0x60, ZC3XX_R192_SYNC00HIGH}, /* 01,92,60,cc */
+ {0xa0, 0x01, ZC3XX_R195_SYNC01LOW}, /* 01,95,01,cc */
+ {0xa0, 0x86, ZC3XX_R196_SYNC01MID}, /* 01,96,86,cc */
+ {0xa0, 0xa0, ZC3XX_R197_SYNC01HIGH}, /* 01,97,a0,cc */
+ {0xa0, 0x07, ZC3XX_R18C_AEFREEZE}, /* 01,8c,07,cc */
+ {0xa0, 0x0f, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,0f,cc */
+ {0xa0, 0x18, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,18,cc */
+ {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
+ {0xa0, 0x00, ZC3XX_R01D_HSYNC_0}, /* 00,1d,00,cc */
+ {0xa0, 0xa0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,a0,cc */
+ {0xa0, 0x16, ZC3XX_R01F_HSYNC_2}, /* 00,1f,16,cc */
+ {0xa0, 0x40, ZC3XX_R020_HSYNC_3}, /* 00,20,40,cc */
+ {}
+};
+static const struct usb_action hv7131b_NoFliker[] = { /* 640x480*/
+ {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
+ {0xaa, 0x25, 0x0003}, /* 00,25,03,aa */
+ {0xaa, 0x26, 0x0000}, /* 00,26,00,aa */
+ {0xaa, 0x27, 0x0000}, /* 00,27,00,aa */
+ {0xaa, 0x20, 0x0000}, /* 00,20,00,aa */
+ {0xaa, 0x21, 0x0010}, /* 00,21,10,aa */
+ {0xaa, 0x22, 0x0000}, /* 00,22,00,aa */
+ {0xaa, 0x23, 0x0003}, /* 00,23,03,aa */
+ {0xa0, 0x2f, ZC3XX_R190_SYNC00LOW}, /* 01,90,2f,cc */
+ {0xa0, 0xf8, ZC3XX_R191_SYNC00MID}, /* 01,91,f8,cc */
+ {0xa0, 0x00, ZC3XX_R192_SYNC00HIGH}, /* 01,92,00,cc */
+ {0xa0, 0x00, ZC3XX_R195_SYNC01LOW}, /* 01,95,00,cc */
+ {0xa0, 0x02, ZC3XX_R196_SYNC01MID}, /* 01,96,02,cc */
+ {0xa0, 0x00, ZC3XX_R197_SYNC01HIGH}, /* 01,97,00,cc */
+ {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
+ {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
+ {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
+ {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
+ {0xa0, 0x00, ZC3XX_R01D_HSYNC_0}, /* 00,1d,00,cc */
+ {0xa0, 0x10, ZC3XX_R01E_HSYNC_1}, /* 00,1e,10,cc */
+ {0xa0, 0x00, ZC3XX_R01F_HSYNC_2}, /* 00,1f,00,cc */
+ {0xa0, 0x03, ZC3XX_R020_HSYNC_3}, /* 00,20,03,cc */
+ {}
+};
+static const struct usb_action hv7131b_NoFlikerScale[] = { /* 320x240 */
+ {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
+ {0xaa, 0x25, 0x0003}, /* 00,25,03,aa */
+ {0xaa, 0x26, 0x0000}, /* 00,26,00,aa */
+ {0xaa, 0x27, 0x0000}, /* 00,27,00,aa */
+ {0xaa, 0x20, 0x0000}, /* 00,20,00,aa */
+ {0xaa, 0x21, 0x00a0}, /* 00,21,a0,aa */
+ {0xaa, 0x22, 0x0016}, /* 00,22,16,aa */
+ {0xaa, 0x23, 0x0040}, /* 00,23,40,aa */
+ {0xa0, 0x2f, ZC3XX_R190_SYNC00LOW}, /* 01,90,2f,cc */
+ {0xa0, 0xf8, ZC3XX_R191_SYNC00MID}, /* 01,91,f8,cc */
+ {0xa0, 0x00, ZC3XX_R192_SYNC00HIGH}, /* 01,92,00,cc */
+ {0xa0, 0x00, ZC3XX_R195_SYNC01LOW}, /* 01,95,00,cc */
+ {0xa0, 0x02, ZC3XX_R196_SYNC01MID}, /* 01,96,02,cc */
+ {0xa0, 0x00, ZC3XX_R197_SYNC01HIGH}, /* 01,97,00,cc */
+ {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
+ {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
+ {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
+ {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
+ {0xa0, 0x00, ZC3XX_R01D_HSYNC_0}, /* 00,1d,00,cc */
+ {0xa0, 0xa0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,a0,cc */
+ {0xa0, 0x16, ZC3XX_R01F_HSYNC_2}, /* 00,1f,16,cc */
+ {0xa0, 0x40, ZC3XX_R020_HSYNC_3}, /* 00,20,40,cc */
{}
};
@@ -6358,6 +6388,7 @@ static void setmatrix(struct gspca_dev *gspca_dev)
switch (sd->sensor) {
case SENSOR_GC0305:
+ case SENSOR_HV7131B:
matrix = gc0305_matrix;
break;
case SENSOR_MC501CB:
@@ -6393,6 +6424,8 @@ static void setbrightness(struct gspca_dev *gspca_dev)
/*fixme: is it really write to 011d and 018d for all other sensors? */
brightness = sd->brightness;
reg_w(gspca_dev->dev, brightness, 0x011d);
+ if (sd->sensor == SENSOR_HV7131B)
+ return;
if (brightness < 0x70)
brightness += 0x10;
else
@@ -6534,6 +6567,7 @@ static void setquality(struct gspca_dev *gspca_dev)
switch (sd->sensor) {
case SENSOR_GC0305:
+ case SENSOR_HV7131B:
case SENSOR_OV7620:
case SENSOR_PO2030:
return;
@@ -6596,9 +6630,9 @@ static int setlightfreq(struct gspca_dev *gspca_dev)
hdcs2020b_50HZ, hdcs2020b_50HZ,
hdcs2020b_60HZ, hdcs2020b_60HZ},
/* SENSOR_HV7131B 5 */
- {NULL, NULL,
- NULL, NULL,
- NULL, NULL},
+ {hv7131b_NoFlikerScale, hv7131b_NoFliker,
+ hv7131b_50HZScale, hv7131b_50HZ,
+ hv7131b_60HZScale, hv7131b_60HZ},
/* SENSOR_HV7131C 6 */
{NULL, NULL,
NULL, NULL,
@@ -7155,7 +7189,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
sd->gamma = gamma[(int) sd->sensor];
sd->autogain = sd_ctrls[SD_AUTOGAIN].qctrl.default_value;
sd->lightfreq = sd_ctrls[SD_FREQ].qctrl.default_value;
- sd->sharpness = sd_ctrls[SD_SHARPNESS].qctrl.default_value;
switch (sd->sensor) {
case SENSOR_GC0305:
@@ -7214,7 +7247,6 @@ static int sd_start(struct gspca_dev *gspca_dev)
mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
zc3_init = init_tb[(int) sd->sensor][mode];
switch (sd->sensor) {
- case SENSOR_HV7131B:
case SENSOR_HV7131C:
zcxx_probeSensor(gspca_dev);
break;
@@ -7339,10 +7371,13 @@ static int sd_start(struct gspca_dev *gspca_dev)
return 0;
}
+/* called on streamoff with alt 0 and on disconnect */
static void sd_stop0(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
+ if (!gspca_dev->present)
+ return;
send_unknown(gspca_dev->dev, sd->sensor);
}
diff --git a/linux/drivers/media/video/ir-kbd-i2c.c b/linux/drivers/media/video/ir-kbd-i2c.c
index 5f0fa6e90..a67bed7d7 100644
--- a/linux/drivers/media/video/ir-kbd-i2c.c
+++ b/linux/drivers/media/video/ir-kbd-i2c.c
@@ -394,10 +394,10 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
goto err_out_detach;
}
- /* Phys addr can only be set after attaching (for ir->c.dev.bus_id) */
+ /* Phys addr can only be set after attaching (for ir->c.dev) */
snprintf(ir->phys, sizeof(ir->phys), "%s/%s/ir0",
- ir->c.adapter->dev.bus_id,
- ir->c.dev.bus_id);
+ dev_name(&ir->c.adapter->dev),
+ dev_name(&ir->c.dev));
/* init + register input device */
ir_input_init(input_dev, &ir->ir, ir_type, ir->ir_codes);
diff --git a/linux/drivers/media/video/ivtv/Kconfig b/linux/drivers/media/video/ivtv/Kconfig
index 0069898bd..c46bfb156 100644
--- a/linux/drivers/media/video/ivtv/Kconfig
+++ b/linux/drivers/media/video/ivtv/Kconfig
@@ -1,6 +1,6 @@
config VIDEO_IVTV
tristate "Conexant cx23416/cx23415 MPEG encoder/decoder support"
- depends on VIDEO_V4L1 && VIDEO_V4L2 && PCI && I2C && EXPERIMENTAL
+ depends on VIDEO_V4L2 && PCI && I2C
depends on INPUT # due to VIDEO_IR
select I2C_ALGOBIT
select VIDEO_IR
@@ -12,7 +12,6 @@ config VIDEO_IVTV
select VIDEO_SAA711X
select VIDEO_SAA717X
select VIDEO_SAA7127
- select VIDEO_TVAUDIO
select VIDEO_CS53L32A
select VIDEO_M52790
select VIDEO_WM8775
@@ -32,7 +31,7 @@ config VIDEO_IVTV
config VIDEO_FB_IVTV
tristate "Conexant cx23415 framebuffer support"
- depends on VIDEO_IVTV && FB && EXPERIMENTAL
+ depends on VIDEO_IVTV && FB
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
diff --git a/linux/drivers/media/video/ivtv/ivtv-cards.c b/linux/drivers/media/video/ivtv/ivtv-cards.c
index c52371f9e..2883c8780 100644
--- a/linux/drivers/media/video/ivtv/ivtv-cards.c
+++ b/linux/drivers/media/video/ivtv/ivtv-cards.c
@@ -877,15 +877,13 @@ static const struct ivtv_card_pci_info ivtv_pci_pg600v2[] = {
static const struct ivtv_card ivtv_card_pg600v2 = {
.type = IVTV_CARD_PG600V2,
.name = "Yuan PG600-2, GotView PCI DVD Lite",
- .comment = "only Composite and S-Video inputs are supported, not the tuner\n",
.v4l2_capabilities = IVTV_CAP_ENCODER,
.hw_video = IVTV_HW_CX25840,
.hw_audio = IVTV_HW_CX25840,
.hw_audio_ctrl = IVTV_HW_CX25840,
-#if 0
.hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER,
- /* XC2028 support has not yet been tested on this card, until
- that's done support for this tuner is disabled. */
+ /* XC2028 support apparently works for the Yuan, it's still
+ uncertain whether it also works with the GotView. */
.video_inputs = {
{ IVTV_CARD_INPUT_VID_TUNER, 0, CX25840_COMPOSITE2 },
{ IVTV_CARD_INPUT_SVIDEO1, 1,
@@ -901,17 +899,6 @@ static const struct ivtv_card ivtv_card_pg600v2 = {
.tuners = {
{ .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
},
-#else
- .hw_all = IVTV_HW_CX25840,
- .video_inputs = {
- { IVTV_CARD_INPUT_SVIDEO1, 0,
- CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 },
- { IVTV_CARD_INPUT_COMPOSITE1, 0, CX25840_COMPOSITE1 },
- },
- .audio_inputs = {
- { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL },
- },
-#endif
.pci_list = ivtv_pci_pg600v2,
.i2c = &ivtv_i2c_std,
};
diff --git a/linux/drivers/media/video/ivtv/ivtv-driver.c b/linux/drivers/media/video/ivtv/ivtv-driver.c
index c9750a058..db866d912 100644
--- a/linux/drivers/media/video/ivtv/ivtv-driver.c
+++ b/linux/drivers/media/video/ivtv/ivtv-driver.c
@@ -879,43 +879,43 @@ static void ivtv_load_and_init_modules(struct ivtv *itv)
#ifdef MODULE
/* load modules */
-#ifndef CONFIG_MEDIA_TUNER
+#ifdef CONFIG_MEDIA_TUNER_MODULE
hw = ivtv_request_module(itv, hw, "tuner", IVTV_HW_TUNER);
#endif
-#ifndef CONFIG_VIDEO_CX25840
+#ifdef CONFIG_VIDEO_CX25840_MODULE
hw = ivtv_request_module(itv, hw, "cx25840", IVTV_HW_CX25840);
#endif
-#ifndef CONFIG_VIDEO_SAA711X
+#ifdef CONFIG_VIDEO_SAA711X_MODULE
hw = ivtv_request_module(itv, hw, "saa7115", IVTV_HW_SAA711X);
#endif
-#ifndef CONFIG_VIDEO_SAA7127
+#ifdef CONFIG_VIDEO_SAA7127_MODULE
hw = ivtv_request_module(itv, hw, "saa7127", IVTV_HW_SAA7127);
#endif
-#ifndef CONFIG_VIDEO_SAA717X
+#ifdef CONFIG_VIDEO_SAA717X_MODULE
hw = ivtv_request_module(itv, hw, "saa717x", IVTV_HW_SAA717X);
#endif
-#ifndef CONFIG_VIDEO_UPD64031A
+#ifdef CONFIG_VIDEO_UPD64031A_MODULE
hw = ivtv_request_module(itv, hw, "upd64031a", IVTV_HW_UPD64031A);
#endif
-#ifndef CONFIG_VIDEO_UPD64083
+#ifdef CONFIG_VIDEO_UPD64083_MODULE
hw = ivtv_request_module(itv, hw, "upd64083", IVTV_HW_UPD6408X);
#endif
-#ifndef CONFIG_VIDEO_MSP3400
+#ifdef CONFIG_VIDEO_MSP3400_MODULE
hw = ivtv_request_module(itv, hw, "msp3400", IVTV_HW_MSP34XX);
#endif
-#ifndef CONFIG_VIDEO_VP27SMPX
+#ifdef CONFIG_VIDEO_VP27SMPX_MODULE
hw = ivtv_request_module(itv, hw, "vp27smpx", IVTV_HW_VP27SMPX);
#endif
-#ifndef CONFIG_VIDEO_WM8775
+#ifdef CONFIG_VIDEO_WM8775_MODULE
hw = ivtv_request_module(itv, hw, "wm8775", IVTV_HW_WM8775);
#endif
-#ifndef CONFIG_VIDEO_WM8739
+#ifdef CONFIG_VIDEO_WM8739_MODULE
hw = ivtv_request_module(itv, hw, "wm8739", IVTV_HW_WM8739);
#endif
-#ifndef CONFIG_VIDEO_CS53L32A
+#ifdef CONFIG_VIDEO_CS53L32A_MODULE
hw = ivtv_request_module(itv, hw, "cs53l32a", IVTV_HW_CS53L32A);
#endif
-#ifndef CONFIG_VIDEO_M52790
+#ifdef CONFIG_VIDEO_M52790_MODULE
hw = ivtv_request_module(itv, hw, "m52790", IVTV_HW_M52790);
#endif
#endif
@@ -1215,6 +1215,10 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
ivtv_call_i2c_clients(itv, VIDIOC_INT_S_STD_OUTPUT, &itv->std);
+ /* Turn off the output signal. The mpeg decoder is not yet
+ active so without this you would get a green image until the
+ mpeg decoder becomes active. */
+ ivtv_saa7127(itv, VIDIOC_STREAMOFF, NULL);
}
/* clear interrupt mask, effectively disabling interrupts */
@@ -1334,6 +1338,10 @@ int ivtv_init_on_first_open(struct ivtv *itv)
ivtv_s_frequency(NULL, &fh, &vf);
if (itv->card->v4l2_capabilities & V4L2_CAP_VIDEO_OUTPUT) {
+ /* Turn on the TV-out: ivtv_init_mpeg_decoder() initializes
+ the mpeg decoder so now the saa7127 receives a proper
+ signal. */
+ ivtv_saa7127(itv, VIDIOC_STREAMON, NULL);
ivtv_init_mpeg_decoder(itv);
}
ivtv_s_std(NULL, &fh, &itv->tuner_std);
@@ -1370,6 +1378,10 @@ static void ivtv_remove(struct pci_dev *pci_dev)
/* Stop all decoding */
IVTV_DEBUG_INFO("Stopping decoding\n");
+
+ /* Turn off the TV-out */
+ if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)
+ ivtv_saa7127(itv, VIDIOC_STREAMOFF, NULL);
if (atomic_read(&itv->decoding) > 0) {
int type;
diff --git a/linux/drivers/media/video/ivtv/ivtv-driver.h b/linux/drivers/media/video/ivtv/ivtv-driver.h
index 5c401fae5..9128df0f3 100644
--- a/linux/drivers/media/video/ivtv/ivtv-driver.h
+++ b/linux/drivers/media/video/ivtv/ivtv-driver.h
@@ -55,6 +55,7 @@
#include <linux/mutex.h>
#include <asm/uaccess.h>
#include <asm/system.h>
+#include <asm/byteorder.h>
#include "compat.h"
#include <linux/dvb/video.h>
diff --git a/linux/drivers/media/video/ivtv/ivtv-i2c.c b/linux/drivers/media/video/ivtv/ivtv-i2c.c
index 6c37203db..c251ddb2f 100644
--- a/linux/drivers/media/video/ivtv/ivtv-i2c.c
+++ b/linux/drivers/media/video/ivtv/ivtv-i2c.c
@@ -760,6 +760,7 @@ int ivtv_saa7127(struct ivtv *itv, unsigned int cmd, void *arg)
{
return ivtv_call_i2c_client(itv, IVTV_SAA7127_I2C_ADDR, cmd, arg);
}
+EXPORT_SYMBOL(ivtv_saa7127);
int ivtv_saa717x(struct ivtv *itv, unsigned int cmd, void *arg)
{
diff --git a/linux/drivers/media/video/ivtv/ivtv-ioctl.c b/linux/drivers/media/video/ivtv/ivtv-ioctl.c
index 208fb5484..4bae38d21 100644
--- a/linux/drivers/media/video/ivtv/ivtv-ioctl.c
+++ b/linux/drivers/media/video/ivtv/ivtv-ioctl.c
@@ -1756,12 +1756,12 @@ static int ivtv_default(struct file *file, void *fh, int cmd, void *arg)
return 0;
}
-static int ivtv_serialized_ioctl(struct ivtv *itv, struct inode *inode, struct file *filp,
+static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp,
unsigned int cmd, unsigned long arg)
{
struct video_device *vfd = video_devdata(filp);
struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
- int ret;
+ long ret;
/* Filter dvb ioctls that cannot be handled by the v4l ioctl framework */
switch (cmd) {
@@ -1830,20 +1830,19 @@ static int ivtv_serialized_ioctl(struct ivtv *itv, struct inode *inode, struct f
if (ivtv_debug & IVTV_DBGFLG_IOCTL)
vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
- ret = video_ioctl2(inode, filp, cmd, arg);
+ ret = __video_ioctl2(filp, cmd, arg);
vfd->debug = 0;
return ret;
}
-int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
+long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
struct ivtv *itv = id->itv;
- int res;
+ long res;
mutex_lock(&itv->serialize_lock);
- res = ivtv_serialized_ioctl(itv, inode, filp, cmd, arg);
+ res = ivtv_serialized_ioctl(itv, filp, cmd, arg);
mutex_unlock(&itv->serialize_lock);
return res;
}
diff --git a/linux/drivers/media/video/ivtv/ivtv-ioctl.h b/linux/drivers/media/video/ivtv/ivtv-ioctl.h
index 70188588b..58f003412 100644
--- a/linux/drivers/media/video/ivtv/ivtv-ioctl.h
+++ b/linux/drivers/media/video/ivtv/ivtv-ioctl.h
@@ -30,7 +30,6 @@ void ivtv_set_funcs(struct video_device *vdev);
int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std);
int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf);
int ivtv_s_input(struct file *file, void *fh, unsigned int inp);
-int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg);
+long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
#endif
diff --git a/linux/drivers/media/video/ivtv/ivtv-streams.c b/linux/drivers/media/video/ivtv/ivtv-streams.c
index 5bbf31e39..9b7aa79eb 100644
--- a/linux/drivers/media/video/ivtv/ivtv-streams.c
+++ b/linux/drivers/media/video/ivtv/ivtv-streams.c
@@ -48,7 +48,7 @@ static const struct file_operations ivtv_v4l2_enc_fops = {
.read = ivtv_v4l2_read,
.write = ivtv_v4l2_write,
.open = ivtv_v4l2_open,
- .ioctl = ivtv_v4l2_ioctl,
+ .unlocked_ioctl = ivtv_v4l2_ioctl,
.compat_ioctl = v4l_compat_ioctl32,
.release = ivtv_v4l2_close,
.poll = ivtv_v4l2_enc_poll,
@@ -59,7 +59,7 @@ static const struct file_operations ivtv_v4l2_dec_fops = {
.read = ivtv_v4l2_read,
.write = ivtv_v4l2_write,
.open = ivtv_v4l2_open,
- .ioctl = ivtv_v4l2_ioctl,
+ .unlocked_ioctl = ivtv_v4l2_ioctl,
.compat_ioctl = v4l_compat_ioctl32,
.release = ivtv_v4l2_close,
.poll = ivtv_v4l2_dec_poll,
diff --git a/linux/drivers/media/video/ivtv/ivtvfb.c b/linux/drivers/media/video/ivtv/ivtvfb.c
index 1ac3af3fc..5e3613d86 100644
--- a/linux/drivers/media/video/ivtv/ivtvfb.c
+++ b/linux/drivers/media/video/ivtv/ivtvfb.c
@@ -48,6 +48,7 @@
#endif
#include "ivtv-driver.h"
+#include "ivtv-i2c.h"
#include "ivtv-udma.h"
#include "ivtv-mailbox.h"
@@ -903,11 +904,16 @@ static int ivtvfb_blank(int blank_mode, struct fb_info *info)
switch (blank_mode) {
case FB_BLANK_UNBLANK:
ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 1);
+ ivtv_saa7127(itv, VIDIOC_STREAMON, NULL);
break;
case FB_BLANK_NORMAL:
case FB_BLANK_HSYNC_SUSPEND:
case FB_BLANK_VSYNC_SUSPEND:
+ ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0);
+ ivtv_saa7127(itv, VIDIOC_STREAMON, NULL);
+ break;
case FB_BLANK_POWERDOWN:
+ ivtv_saa7127(itv, VIDIOC_STREAMOFF, NULL);
ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0);
break;
}
diff --git a/linux/drivers/media/video/ov511.c b/linux/drivers/media/video/ov511.c
index 9a5662024..ca3a89616 100644
--- a/linux/drivers/media/video/ov511.c
+++ b/linux/drivers/media/video/ov511.c
@@ -1098,9 +1098,10 @@ ov51x_clear_snapshot(struct usb_ov511 *ov)
reg_w(ov, R51x_SYS_SNAP, 0x02);
reg_w(ov, R51x_SYS_SNAP, 0x00);
} else if (ov->bclass == BCL_OV518) {
- warn("snapshot reset not supported yet on OV518(+)");
+ dev_warn(&ov->dev->dev,
+ "snapshot reset not supported yet on OV518(+)\n");
} else {
- err("clear snap: invalid bridge type");
+ dev_err(&ov->dev->dev, "clear snap: invalid bridge type\n");
}
}
@@ -1115,14 +1116,16 @@ ov51x_check_snapshot(struct usb_ov511 *ov)
if (ov->bclass == BCL_OV511) {
ret = reg_r(ov, R51x_SYS_SNAP);
if (ret < 0) {
- err("Error checking snspshot status (%d)", ret);
+ dev_err(&ov->dev->dev,
+ "Error checking snspshot status (%d)\n", ret);
} else if (ret & 0x08) {
status = 1;
}
} else if (ov->bclass == BCL_OV518) {
- warn("snapshot check not supported yet on OV518(+)");
+ dev_warn(&ov->dev->dev,
+ "snapshot check not supported yet on OV518(+)\n");
} else {
- err("check snap: invalid bridge type");
+ dev_err(&ov->dev->dev, "clear snap: invalid bridge type\n");
}
return status;
@@ -4012,8 +4015,7 @@ ov51x_v4l1_close(struct inode *inode, struct file *file)
/* Do not call this function directly! */
static int
-ov51x_v4l1_ioctl_internal(struct inode *inode, struct file *file,
- unsigned int cmd, void *arg)
+ov51x_v4l1_ioctl_internal(struct file *file, unsigned int cmd, void *arg)
{
struct video_device *vdev = file->private_data;
struct usb_ov511 *ov = video_get_drvdata(vdev);
@@ -4462,7 +4464,7 @@ ov51x_v4l1_ioctl(struct inode *inode, struct file *file,
if (mutex_lock_interruptible(&ov->lock))
return -EINTR;
- rc = video_usercopy(inode, file, cmd, arg, ov51x_v4l1_ioctl_internal);
+ rc = video_usercopy(file, cmd, arg, ov51x_v4l1_ioctl_internal);
mutex_unlock(&ov->lock);
return rc;
@@ -5221,7 +5223,8 @@ saa7111a_configure(struct usb_ov511 *ov)
if (ov->bclass == BCL_OV511)
reg_w(ov, 0x11, 0x00);
else
- warn("SAA7111A not yet supported with OV518/OV518+");
+ dev_warn(&ov->dev->dev,
+ "SAA7111A not yet supported with OV518/OV518+\n");
return 0;
}
@@ -5460,7 +5463,8 @@ ov518_configure(struct usb_ov511 *ov)
* required. OV518 has no uncompressed mode, to save RAM. */
if (!dumppix && !ov->compress) {
ov->compress = 1;
- warn("Compression required with OV518...enabling");
+ dev_warn(&ov->dev->dev,
+ "Compression required with OV518...enabling\n");
}
if (ov->bridge == BRG_OV518) {
diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c
new file mode 100644
index 000000000..2ddc2ab70
--- /dev/null
+++ b/linux/drivers/media/video/ov772x.c
@@ -0,0 +1,972 @@
+/*
+ * ov772x Camera Driver
+ *
+ * Copyright (C) 2008 Renesas Solutions Corp.
+ * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ *
+ * Based on ov7670 and soc_camera_platform driver,
+ *
+ * Copyright 2006-7 Jonathan Corbet <corbet@lwn.net>
+ * Copyright (C) 2008 Magnus Damm
+ * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-common.h>
+#include <media/soc_camera.h>
+#include <media/ov772x.h>
+
+/*
+ * register offset
+ */
+#define GAIN 0x00 /* AGC - Gain control gain setting */
+#define BLUE 0x01 /* AWB - Blue channel gain setting */
+#define RED 0x02 /* AWB - Red channel gain setting */
+#define GREEN 0x03 /* AWB - Green channel gain setting */
+#define COM1 0x04 /* Common control 1 */
+#define BAVG 0x05 /* U/B Average Level */
+#define GAVG 0x06 /* Y/Gb Average Level */
+#define RAVG 0x07 /* V/R Average Level */
+#define AECH 0x08 /* Exposure Value - AEC MSBs */
+#define COM2 0x09 /* Common control 2 */
+#define PID 0x0A /* Product ID Number MSB */
+#define VER 0x0B /* Product ID Number LSB */
+#define COM3 0x0C /* Common control 3 */
+#define COM4 0x0D /* Common control 4 */
+#define COM5 0x0E /* Common control 5 */
+#define COM6 0x0F /* Common control 6 */
+#define AEC 0x10 /* Exposure Value */
+#define CLKRC 0x11 /* Internal clock */
+#define COM7 0x12 /* Common control 7 */
+#define COM8 0x13 /* Common control 8 */
+#define COM9 0x14 /* Common control 9 */
+#define COM10 0x15 /* Common control 10 */
+#define HSTART 0x17 /* Horizontal sensor size */
+#define HSIZE 0x18 /* Horizontal frame (HREF column) end high 8-bit */
+#define VSTART 0x19 /* Vertical frame (row) start high 8-bit */
+#define VSIZE 0x1A /* Vertical sensor size */
+#define PSHFT 0x1B /* Data format - pixel delay select */
+#define MIDH 0x1C /* Manufacturer ID byte - high */
+#define MIDL 0x1D /* Manufacturer ID byte - low */
+#define LAEC 0x1F /* Fine AEC value */
+#define COM11 0x20 /* Common control 11 */
+#define BDBASE 0x22 /* Banding filter Minimum AEC value */
+#define DBSTEP 0x23 /* Banding filter Maximum Setp */
+#define AEW 0x24 /* AGC/AEC - Stable operating region (upper limit) */
+#define AEB 0x25 /* AGC/AEC - Stable operating region (lower limit) */
+#define VPT 0x26 /* AGC/AEC Fast mode operating region */
+#define HOUTSIZE 0x29 /* Horizontal data output size MSBs */
+#define EXHCH 0x2A /* Dummy pixel insert MSB */
+#define EXHCL 0x2B /* Dummy pixel insert LSB */
+#define VOUTSIZE 0x2C /* Vertical data output size MSBs */
+#define ADVFL 0x2D /* LSB of insert dummy lines in Vertical direction */
+#define ADVFH 0x2E /* MSG of insert dummy lines in Vertical direction */
+#define YAVE 0x2F /* Y/G Channel Average value */
+#define LUMHTH 0x30 /* Histogram AEC/AGC Luminance high level threshold */
+#define LUMLTH 0x31 /* Histogram AEC/AGC Luminance low level threshold */
+#define HREF 0x32 /* Image start and size control */
+#define DM_LNL 0x33 /* Dummy line low 8 bits */
+#define DM_LNH 0x34 /* Dummy line high 8 bits */
+#define ADOFF_B 0x35 /* AD offset compensation value for B channel */
+#define ADOFF_R 0x36 /* AD offset compensation value for R channel */
+#define ADOFF_GB 0x37 /* AD offset compensation value for Gb channel */
+#define ADOFF_GR 0x38 /* AD offset compensation value for Gr channel */
+#define OFF_B 0x39 /* Analog process B channel offset value */
+#define OFF_R 0x3A /* Analog process R channel offset value */
+#define OFF_GB 0x3B /* Analog process Gb channel offset value */
+#define OFF_GR 0x3C /* Analog process Gr channel offset value */
+#define COM12 0x3D /* Common control 12 */
+#define COM13 0x3E /* Common control 13 */
+#define COM14 0x3F /* Common control 14 */
+#define COM15 0x40 /* Common control 15*/
+#define COM16 0x41 /* Common control 16 */
+#define TGT_B 0x42 /* BLC blue channel target value */
+#define TGT_R 0x43 /* BLC red channel target value */
+#define TGT_GB 0x44 /* BLC Gb channel target value */
+#define TGT_GR 0x45 /* BLC Gr channel target value */
+#define LCC0 0x46 /* Lens correction control 0 */
+#define LCC1 0x47 /* Lens correction option 1 - X coordinate */
+#define LCC2 0x48 /* Lens correction option 2 - Y coordinate */
+#define LCC3 0x49 /* Lens correction option 3 */
+#define LCC4 0x4A /* Lens correction option 4 - radius of the circular */
+#define LCC5 0x4B /* Lens correction option 5 */
+#define LCC6 0x4C /* Lens correction option 6 */
+#define FIXGAIN 0x4D /* Analog fix gain amplifer */
+#define AREF0 0x4E /* Sensor reference control */
+#define AREF1 0x4F /* Sensor reference current control */
+#define AREF2 0x50 /* Analog reference control */
+#define AREF3 0x51 /* ADC reference control */
+#define AREF4 0x52 /* ADC reference control */
+#define AREF5 0x53 /* ADC reference control */
+#define AREF6 0x54 /* Analog reference control */
+#define AREF7 0x55 /* Analog reference control */
+#define UFIX 0x60 /* U channel fixed value output */
+#define VFIX 0x61 /* V channel fixed value output */
+#define AW_BB_BLK 0x62 /* AWB option for advanced AWB */
+#define AW_B_CTRL0 0x63 /* AWB control byte 0 */
+#define DSP_CTRL1 0x64 /* DSP control byte 1 */
+#define DSP_CTRL2 0x65 /* DSP control byte 2 */
+#define DSP_CTRL3 0x66 /* DSP control byte 3 */
+#define DSP_CTRL4 0x67 /* DSP control byte 4 */
+#define AW_B_BIAS 0x68 /* AWB BLC level clip */
+#define AW_BCTRL1 0x69 /* AWB control 1 */
+#define AW_BCTRL2 0x6A /* AWB control 2 */
+#define AW_BCTRL3 0x6B /* AWB control 3 */
+#define AW_BCTRL4 0x6C /* AWB control 4 */
+#define AW_BCTRL5 0x6D /* AWB control 5 */
+#define AW_BCTRL6 0x6E /* AWB control 6 */
+#define AW_BCTRL7 0x6F /* AWB control 7 */
+#define AW_BCTRL8 0x70 /* AWB control 8 */
+#define AW_BCTRL9 0x71 /* AWB control 9 */
+#define AW_BCTRL10 0x72 /* AWB control 10 */
+#define AW_BCTRL11 0x73 /* AWB control 11 */
+#define AW_BCTRL12 0x74 /* AWB control 12 */
+#define AW_BCTRL13 0x75 /* AWB control 13 */
+#define AW_BCTRL14 0x76 /* AWB control 14 */
+#define AW_BCTRL15 0x77 /* AWB control 15 */
+#define AW_BCTRL16 0x78 /* AWB control 16 */
+#define AW_BCTRL17 0x79 /* AWB control 17 */
+#define AW_BCTRL18 0x7A /* AWB control 18 */
+#define AW_BCTRL19 0x7B /* AWB control 19 */
+#define AW_BCTRL20 0x7C /* AWB control 20 */
+#define AW_BCTRL21 0x7D /* AWB control 21 */
+#define GAM1 0x7E /* Gamma Curve 1st segment input end point */
+#define GAM2 0x7F /* Gamma Curve 2nd segment input end point */
+#define GAM3 0x80 /* Gamma Curve 3rd segment input end point */
+#define GAM4 0x81 /* Gamma Curve 4th segment input end point */
+#define GAM5 0x82 /* Gamma Curve 5th segment input end point */
+#define GAM6 0x83 /* Gamma Curve 6th segment input end point */
+#define GAM7 0x84 /* Gamma Curve 7th segment input end point */
+#define GAM8 0x85 /* Gamma Curve 8th segment input end point */
+#define GAM9 0x86 /* Gamma Curve 9th segment input end point */
+#define GAM10 0x87 /* Gamma Curve 10th segment input end point */
+#define GAM11 0x88 /* Gamma Curve 11th segment input end point */
+#define GAM12 0x89 /* Gamma Curve 12th segment input end point */
+#define GAM13 0x8A /* Gamma Curve 13th segment input end point */
+#define GAM14 0x8B /* Gamma Curve 14th segment input end point */
+#define GAM15 0x8C /* Gamma Curve 15th segment input end point */
+#define SLOP 0x8D /* Gamma curve highest segment slope */
+#define DNSTH 0x8E /* De-noise threshold */
+#define EDGE0 0x8F /* Edge enhancement control 0 */
+#define EDGE1 0x90 /* Edge enhancement control 1 */
+#define DNSOFF 0x91 /* Auto De-noise threshold control */
+#define EDGE2 0x92 /* Edge enhancement strength low point control */
+#define EDGE3 0x93 /* Edge enhancement strength high point control */
+#define MTX1 0x94 /* Matrix coefficient 1 */
+#define MTX2 0x95 /* Matrix coefficient 2 */
+#define MTX3 0x96 /* Matrix coefficient 3 */
+#define MTX4 0x97 /* Matrix coefficient 4 */
+#define MTX5 0x98 /* Matrix coefficient 5 */
+#define MTX6 0x99 /* Matrix coefficient 6 */
+#define MTX_CTRL 0x9A /* Matrix control */
+#define BRIGHT 0x9B /* Brightness control */
+#define CNTRST 0x9C /* Contrast contrast */
+#define CNTRST_CTRL 0x9D /* Contrast contrast center */
+#define UVAD_J0 0x9E /* Auto UV adjust contrast 0 */
+#define UVAD_J1 0x9F /* Auto UV adjust contrast 1 */
+#define SCAL0 0xA0 /* Scaling control 0 */
+#define SCAL1 0xA1 /* Scaling control 1 */
+#define SCAL2 0xA2 /* Scaling control 2 */
+#define FIFODLYM 0xA3 /* FIFO manual mode delay control */
+#define FIFODLYA 0xA4 /* FIFO auto mode delay control */
+#define SDE 0xA6 /* Special digital effect control */
+#define USAT 0xA7 /* U component saturation control */
+#define VSAT 0xA8 /* V component saturation control */
+#define HUE0 0xA9 /* Hue control 0 */
+#define HUE1 0xAA /* Hue control 1 */
+#define SIGN 0xAB /* Sign bit for Hue and contrast */
+#define DSPAUTO 0xAC /* DSP auto function ON/OFF control */
+
+/*
+ * register detail
+ */
+
+/* COM2 */
+#define SOFT_SLEEP_MODE 0x10 /* Soft sleep mode */
+ /* Output drive capability */
+#define OCAP_1x 0x00 /* 1x */
+#define OCAP_2x 0x01 /* 2x */
+#define OCAP_3x 0x02 /* 3x */
+#define OCAP_4x 0x03 /* 4x */
+
+/* COM3 */
+#define SWAP_MASK 0x38
+
+#define VFIMG_ON_OFF 0x80 /* Vertical flip image ON/OFF selection */
+#define HMIMG_ON_OFF 0x40 /* Horizontal mirror image ON/OFF selection */
+#define SWAP_RGB 0x20 /* Swap B/R output sequence in RGB mode */
+#define SWAP_YUV 0x10 /* Swap Y/UV output sequence in YUV mode */
+#define SWAP_ML 0x08 /* Swap output MSB/LSB */
+ /* Tri-state option for output clock */
+#define NOTRI_CLOCK 0x04 /* 0: Tri-state at this period */
+ /* 1: No tri-state at this period */
+ /* Tri-state option for output data */
+#define NOTRI_DATA 0x02 /* 0: Tri-state at this period */
+ /* 1: No tri-state at this period */
+#define SCOLOR_TEST 0x01 /* Sensor color bar test pattern */
+
+/* COM4 */
+ /* PLL frequency control */
+#define PLL_BYPASS 0x00 /* 00: Bypass PLL */
+#define PLL_4x 0x40 /* 01: PLL 4x */
+#define PLL_6x 0x80 /* 10: PLL 6x */
+#define PLL_8x 0xc0 /* 11: PLL 8x */
+ /* AEC evaluate window */
+#define AEC_FULL 0x00 /* 00: Full window */
+#define AEC_1p2 0x10 /* 01: 1/2 window */
+#define AEC_1p4 0x20 /* 10: 1/4 window */
+#define AEC_2p3 0x30 /* 11: Low 2/3 window */
+
+/* COM5 */
+#define AFR_ON_OFF 0x80 /* Auto frame rate control ON/OFF selection */
+#define AFR_SPPED 0x40 /* Auto frame rate control speed slection */
+ /* Auto frame rate max rate control */
+#define AFR_NO_RATE 0x00 /* No reduction of frame rate */
+#define AFR_1p2 0x10 /* Max reduction to 1/2 frame rate */
+#define AFR_1p4 0x20 /* Max reduction to 1/4 frame rate */
+#define AFR_1p8 0x30 /* Max reduction to 1/8 frame rate */
+ /* Auto frame rate active point control */
+#define AF_2x 0x00 /* Add frame when AGC reaches 2x gain */
+#define AF_4x 0x04 /* Add frame when AGC reaches 4x gain */
+#define AF_8x 0x08 /* Add frame when AGC reaches 8x gain */
+#define AF_16x 0x0c /* Add frame when AGC reaches 16x gain */
+ /* AEC max step control */
+#define AEC_NO_LIMIT 0x01 /* 0 : AEC incease step has limit */
+ /* 1 : No limit to AEC increase step */
+
+/* COM7 */
+ /* SCCB Register Reset */
+#define SCCB_RESET 0x80 /* 0 : No change */
+ /* 1 : Resets all registers to default */
+ /* Resolution selection */
+#define SLCT_MASK 0x40 /* Mask of VGA or QVGA */
+#define SLCT_VGA 0x00 /* 0 : VGA */
+#define SLCT_QVGA 0x40 /* 1 : QVGA */
+#define ITU656_ON_OFF 0x20 /* ITU656 protocol ON/OFF selection */
+ /* RGB output format control */
+#define FMT_GBR422 0x00 /* 00 : GBR 4:2:2 */
+#define FMT_RGB565 0x04 /* 01 : RGB 565 */
+#define FMT_RGB555 0x08 /* 10 : RGB 555 */
+#define FMT_RGB444 0x0c /* 11 : RGB 444 */
+ /* Output format control */
+#define OFMT_YUV 0x00 /* 00 : YUV */
+#define OFMT_P_BRAW 0x01 /* 01 : Processed Bayer RAW */
+#define OFMT_RGB 0x02 /* 10 : RGB */
+#define OFMT_BRAW 0x03 /* 11 : Bayer RAW */
+
+/* COM8 */
+#define FAST_ALGO 0x80 /* Enable fast AGC/AEC algorithm */
+ /* AEC Setp size limit */
+#define UNLMT_STEP 0x40 /* 0 : Step size is limited */
+ /* 1 : Unlimited step size */
+#define BNDF_ON_OFF 0x20 /* Banding filter ON/OFF */
+#define AEC_BND 0x10 /* Enable AEC below banding value */
+#define AEC_ON_OFF 0x08 /* Fine AEC ON/OFF control */
+#define AGC_ON 0x04 /* AGC Enable */
+#define AWB_ON 0x02 /* AWB Enable */
+#define AEC_ON 0x01 /* AEC Enable */
+
+/* COM9 */
+#define BASE_AECAGC 0x80 /* Histogram or average based AEC/AGC */
+ /* Automatic gain ceiling - maximum AGC value */
+#define GAIN_2x 0x00 /* 000 : 2x */
+#define GAIN_4x 0x10 /* 001 : 4x */
+#define GAIN_8x 0x20 /* 010 : 8x */
+#define GAIN_16x 0x30 /* 011 : 16x */
+#define GAIN_32x 0x40 /* 100 : 32x */
+#define GAIN_64x 0x50 /* 101 : 64x */
+#define GAIN_128x 0x60 /* 110 : 128x */
+#define DROP_VSYNC 0x04 /* Drop VSYNC output of corrupt frame */
+#define DROP_HREF 0x02 /* Drop HREF output of corrupt frame */
+
+/* COM11 */
+#define SGLF_ON_OFF 0x02 /* Single frame ON/OFF selection */
+#define SGLF_TRIG 0x01 /* Single frame transfer trigger */
+
+/* EXHCH */
+#define VSIZE_LSB 0x04 /* Vertical data output size LSB */
+
+/* DSP_CTRL1 */
+#define FIFO_ON 0x80 /* FIFO enable/disable selection */
+#define UV_ON_OFF 0x40 /* UV adjust function ON/OFF selection */
+#define YUV444_2_422 0x20 /* YUV444 to 422 UV channel option selection */
+#define CLR_MTRX_ON_OFF 0x10 /* Color matrix ON/OFF selection */
+#define INTPLT_ON_OFF 0x08 /* Interpolation ON/OFF selection */
+#define GMM_ON_OFF 0x04 /* Gamma function ON/OFF selection */
+#define AUTO_BLK_ON_OFF 0x02 /* Black defect auto correction ON/OFF */
+#define AUTO_WHT_ON_OFF 0x01 /* White define auto correction ON/OFF */
+
+/* DSP_CTRL3 */
+#define UV_MASK 0x80 /* UV output sequence option */
+#define UV_ON 0x80 /* ON */
+#define UV_OFF 0x00 /* OFF */
+#define CBAR_MASK 0x20 /* DSP Color bar mask */
+#define CBAR_ON 0x20 /* ON */
+#define CBAR_OFF 0x00 /* OFF */
+
+/* HSTART */
+#define HST_VGA 0x23
+#define HST_QVGA 0x3F
+
+/* HSIZE */
+#define HSZ_VGA 0xA0
+#define HSZ_QVGA 0x50
+
+/* VSTART */
+#define VST_VGA 0x07
+#define VST_QVGA 0x03
+
+/* VSIZE */
+#define VSZ_VGA 0xF0
+#define VSZ_QVGA 0x78
+
+/* HOUTSIZE */
+#define HOSZ_VGA 0xA0
+#define HOSZ_QVGA 0x50
+
+/* VOUTSIZE */
+#define VOSZ_VGA 0xF0
+#define VOSZ_QVGA 0x78
+
+/*
+ * bit configure (32 bit)
+ * this is used in struct ov772x_color_format :: option
+ */
+#define OP_UV 0x00000001
+#define OP_SWAP_RGB 0x00000002
+
+/*
+ * struct
+ */
+struct regval_list {
+ unsigned char reg_num;
+ unsigned char value;
+};
+
+struct ov772x_color_format {
+ char *name;
+ __u32 fourcc;
+ const struct regval_list *regs;
+ unsigned int option;
+};
+
+struct ov772x_win_size {
+ char *name;
+ __u32 width;
+ __u32 height;
+ unsigned char com7_bit;
+ const struct regval_list *regs;
+};
+
+struct ov772x_priv {
+ struct ov772x_camera_info *info;
+ struct i2c_client *client;
+ struct soc_camera_device icd;
+ const struct ov772x_color_format *fmt;
+ const struct ov772x_win_size *win;
+};
+
+#define ENDMARKER { 0xff, 0xff }
+
+static const struct regval_list ov772x_default_regs[] =
+{
+ { COM3, 0x00 },
+ { COM4, PLL_4x | 0x01 },
+ { 0x16, 0x00 }, /* Mystery */
+ { COM11, 0x10 }, /* Mystery */
+ { 0x28, 0x00 }, /* Mystery */
+ { HREF, 0x00 },
+ { COM13, 0xe2 }, /* Mystery */
+ { AREF0, 0xef },
+ { AREF2, 0x60 },
+ { AREF6, 0x7a },
+ ENDMARKER,
+};
+
+/*
+ * register setting for color format
+ */
+static const struct regval_list ov772x_RGB555_regs[] = {
+ { COM7, FMT_RGB555 | OFMT_RGB },
+ ENDMARKER,
+};
+
+static const struct regval_list ov772x_RGB565_regs[] = {
+ { COM7, FMT_RGB565 | OFMT_RGB },
+ ENDMARKER,
+};
+
+static const struct regval_list ov772x_YYUV_regs[] = {
+ { COM3, SWAP_YUV },
+ { COM7, OFMT_YUV },
+ ENDMARKER,
+};
+
+static const struct regval_list ov772x_UVYY_regs[] = {
+ { COM7, OFMT_YUV },
+ ENDMARKER,
+};
+
+
+/*
+ * register setting for window size
+ */
+static const struct regval_list ov772x_qvga_regs[] = {
+ { HSTART, HST_QVGA },
+ { HSIZE, HSZ_QVGA },
+ { VSTART, VST_QVGA },
+ { VSIZE, VSZ_QVGA },
+ { HOUTSIZE, HOSZ_QVGA },
+ { VOUTSIZE, VOSZ_QVGA },
+ ENDMARKER,
+};
+
+static const struct regval_list ov772x_vga_regs[] = {
+ { HSTART, HST_VGA },
+ { HSIZE, HSZ_VGA },
+ { VSTART, VST_VGA },
+ { VSIZE, VSZ_VGA },
+ { HOUTSIZE, HOSZ_VGA },
+ { VOUTSIZE, VOSZ_VGA },
+ ENDMARKER,
+};
+
+/*
+ * supported format list
+ */
+
+#define SETFOURCC(type) .name = (#type), .fourcc = (V4L2_PIX_FMT_ ## type)
+static const struct soc_camera_data_format ov772x_fmt_lists[] = {
+ {
+ SETFOURCC(YUYV),
+ .depth = 16,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ },
+ {
+ SETFOURCC(YVYU),
+ .depth = 16,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ },
+ {
+ SETFOURCC(UYVY),
+ .depth = 16,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ },
+ {
+ SETFOURCC(RGB555),
+ .depth = 16,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ },
+ {
+ SETFOURCC(RGB555X),
+ .depth = 16,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ },
+ {
+ SETFOURCC(RGB565),
+ .depth = 16,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ },
+ {
+ SETFOURCC(RGB565X),
+ .depth = 16,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ },
+};
+
+/*
+ * color format list
+ */
+#define T_YUYV 0
+static const struct ov772x_color_format ov772x_cfmts[] = {
+ [T_YUYV] = {
+ SETFOURCC(YUYV),
+ .regs = ov772x_YYUV_regs,
+ },
+ {
+ SETFOURCC(YVYU),
+ .regs = ov772x_YYUV_regs,
+ .option = OP_UV,
+ },
+ {
+ SETFOURCC(UYVY),
+ .regs = ov772x_UVYY_regs,
+ },
+ {
+ SETFOURCC(RGB555),
+ .regs = ov772x_RGB555_regs,
+ .option = OP_SWAP_RGB,
+ },
+ {
+ SETFOURCC(RGB555X),
+ .regs = ov772x_RGB555_regs,
+ },
+ {
+ SETFOURCC(RGB565),
+ .regs = ov772x_RGB565_regs,
+ .option = OP_SWAP_RGB,
+ },
+ {
+ SETFOURCC(RGB565X),
+ .regs = ov772x_RGB565_regs,
+ },
+};
+
+
+/*
+ * window size list
+ */
+#define VGA_WIDTH 640
+#define VGA_HEIGHT 480
+#define QVGA_WIDTH 320
+#define QVGA_HEIGHT 240
+#define MAX_WIDTH VGA_WIDTH
+#define MAX_HEIGHT VGA_HEIGHT
+
+static const struct ov772x_win_size ov772x_win_vga = {
+ .name = "VGA",
+ .width = VGA_WIDTH,
+ .height = VGA_HEIGHT,
+ .com7_bit = SLCT_VGA,
+ .regs = ov772x_vga_regs,
+};
+
+static const struct ov772x_win_size ov772x_win_qvga = {
+ .name = "QVGA",
+ .width = QVGA_WIDTH,
+ .height = QVGA_HEIGHT,
+ .com7_bit = SLCT_QVGA,
+ .regs = ov772x_qvga_regs,
+};
+
+
+/*
+ * general function
+ */
+
+static int ov772x_write_array(struct i2c_client *client,
+ const struct regval_list *vals)
+{
+ while (vals->reg_num != 0xff) {
+ int ret = i2c_smbus_write_byte_data(client,
+ vals->reg_num,
+ vals->value);
+ if (ret < 0)
+ return ret;
+ vals++;
+ }
+ return 0;
+}
+
+static int ov772x_mask_set(struct i2c_client *client,
+ u8 command,
+ u8 mask,
+ u8 set)
+{
+ s32 val = i2c_smbus_read_byte_data(client, command);
+ val &= ~mask;
+ val |= set;
+
+ return i2c_smbus_write_byte_data(client, command, val);
+}
+
+static int ov772x_reset(struct i2c_client *client)
+{
+ int ret = i2c_smbus_write_byte_data(client, COM7, SCCB_RESET);
+ msleep(1);
+ return ret;
+}
+
+/*
+ * soc_camera_ops function
+ */
+
+static int ov772x_init(struct soc_camera_device *icd)
+{
+ return 0;
+}
+
+static int ov772x_release(struct soc_camera_device *icd)
+{
+ return 0;
+}
+
+static int ov772x_start_capture(struct soc_camera_device *icd)
+{
+ struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
+ int ret;
+
+
+ if (!priv->win)
+ priv->win = &ov772x_win_vga;
+ if (!priv->fmt)
+ priv->fmt = &ov772x_cfmts[T_YUYV];
+
+ /*
+ * reset hardware
+ */
+ ov772x_reset(priv->client);
+ ret = ov772x_write_array(priv->client, ov772x_default_regs);
+ if (ret < 0)
+ goto start_end;
+
+ /*
+ * set color format
+ */
+ ret = ov772x_write_array(priv->client, priv->fmt->regs);
+ if (ret < 0)
+ goto start_end;
+
+ /*
+ * set size format
+ */
+ ret = ov772x_write_array(priv->client, priv->win->regs);
+ if (ret < 0)
+ goto start_end;
+
+ /*
+ * set COM7 bit ( QVGA or VGA )
+ */
+ ret = ov772x_mask_set(priv->client,
+ COM7, SLCT_MASK, priv->win->com7_bit);
+ if (ret < 0)
+ goto start_end;
+
+ /*
+ * set UV setting
+ */
+ if (priv->fmt->option & OP_UV) {
+ ret = ov772x_mask_set(priv->client,
+ DSP_CTRL3, UV_MASK, UV_ON);
+ if (ret < 0)
+ goto start_end;
+ }
+
+ /*
+ * set SWAP setting
+ */
+ if (priv->fmt->option & OP_SWAP_RGB) {
+ ret = ov772x_mask_set(priv->client,
+ COM3, SWAP_MASK, SWAP_RGB);
+ if (ret < 0)
+ goto start_end;
+ }
+
+ dev_info(&icd->dev,
+ "format %s, win %s\n", priv->fmt->name, priv->win->name);
+
+start_end:
+ priv->fmt = NULL;
+ priv->win = NULL;
+
+ return ret;
+}
+
+static int ov772x_stop_capture(struct soc_camera_device *icd)
+{
+ struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
+ ov772x_reset(priv->client);
+ return 0;
+}
+
+static int ov772x_set_bus_param(struct soc_camera_device *icd,
+ unsigned long flags)
+{
+ return 0;
+}
+
+static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd)
+{
+ struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
+
+ return SOCAM_PCLK_SAMPLE_RISING |
+ SOCAM_HSYNC_ACTIVE_HIGH |
+ SOCAM_VSYNC_ACTIVE_HIGH |
+ SOCAM_MASTER |
+ priv->info->buswidth;
+}
+
+static int ov772x_get_chip_id(struct soc_camera_device *icd,
+ struct v4l2_chip_ident *id)
+{
+ id->ident = V4L2_IDENT_OV772X;
+ id->revision = 0;
+
+ return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int ov772x_get_register(struct soc_camera_device *icd,
+ struct v4l2_register *reg)
+{
+ struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
+ int ret;
+
+ if (reg->reg > 0xff)
+ return -EINVAL;
+
+ ret = i2c_smbus_read_byte_data(priv->client, reg->reg);
+ if (ret < 0)
+ return ret;
+
+ reg->val = (__u64)ret;
+
+ return 0;
+}
+
+static int ov772x_set_register(struct soc_camera_device *icd,
+ struct v4l2_register *reg)
+{
+ struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
+
+ if (reg->reg > 0xff ||
+ reg->val > 0xff)
+ return -EINVAL;
+
+ return i2c_smbus_write_byte_data(priv->client, reg->reg, reg->val);
+}
+#endif
+
+static int ov772x_set_fmt_cap(struct soc_camera_device *icd,
+ __u32 pixfmt,
+ struct v4l2_rect *rect)
+{
+ struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
+ int ret = -EINVAL;
+ int i;
+
+ /*
+ * select format
+ */
+ priv->fmt = NULL;
+ for (i = 0; i < ARRAY_SIZE(ov772x_cfmts); i++) {
+ if (pixfmt == ov772x_cfmts[i].fourcc) {
+ priv->fmt = ov772x_cfmts + i;
+ ret = 0;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int ov772x_try_fmt_cap(struct soc_camera_device *icd,
+ struct v4l2_format *f)
+{
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+ struct ov772x_priv *priv;
+
+ priv = container_of(icd, struct ov772x_priv, icd);
+
+ /* QVGA */
+ if (pix->width <= ov772x_win_qvga.width ||
+ pix->height <= ov772x_win_qvga.height) {
+ priv->win = &ov772x_win_qvga;
+ pix->width = ov772x_win_qvga.width;
+ pix->height = ov772x_win_qvga.height;
+ }
+
+ /* VGA */
+ else if (pix->width <= ov772x_win_vga.width ||
+ pix->height <= ov772x_win_vga.height) {
+ priv->win = &ov772x_win_vga;
+ pix->width = ov772x_win_vga.width;
+ pix->height = ov772x_win_vga.height;
+ }
+
+ pix->field = V4L2_FIELD_NONE;
+
+ return 0;
+}
+
+static int ov772x_video_probe(struct soc_camera_device *icd)
+{
+ struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
+ u8 pid, ver;
+
+ /*
+ * We must have a parent by now. And it cannot be a wrong one.
+ * So this entire test is completely redundant.
+ */
+ if (!icd->dev.parent ||
+ to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
+ return -ENODEV;
+
+ /*
+ * ov772x only use 8 or 10 bit bus width
+ */
+ if (SOCAM_DATAWIDTH_10 != priv->info->buswidth &&
+ SOCAM_DATAWIDTH_8 != priv->info->buswidth) {
+ dev_err(&icd->dev, "bus width error\n");
+ return -ENODEV;
+ }
+
+ icd->formats = ov772x_fmt_lists;
+ icd->num_formats = ARRAY_SIZE(ov772x_fmt_lists);
+
+ if (priv->info->link.power)
+ priv->info->link.power(&priv->client->dev, 1);
+
+ /*
+ * check and show product ID and manufacturer ID
+ */
+ pid = i2c_smbus_read_byte_data(priv->client, PID);
+ ver = i2c_smbus_read_byte_data(priv->client, VER);
+ if (pid != 0x77 ||
+ ver != 0x21) {
+ if (priv->info->link.power)
+ priv->info->link.power(&priv->client->dev, 0);
+ return -ENODEV;
+ }
+
+ dev_info(&icd->dev,
+ "ov772x Product ID %0x:%0x Manufacturer ID %x:%x\n",
+ pid,
+ ver,
+ i2c_smbus_read_byte_data(priv->client, MIDH),
+ i2c_smbus_read_byte_data(priv->client, MIDL));
+
+
+ return soc_camera_video_start(icd);
+}
+
+static void ov772x_video_remove(struct soc_camera_device *icd)
+{
+ struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
+
+ soc_camera_video_stop(icd);
+
+ if (priv->info->link.power)
+ priv->info->link.power(&priv->client->dev, 0);
+
+}
+
+static struct soc_camera_ops ov772x_ops = {
+ .owner = THIS_MODULE,
+ .probe = ov772x_video_probe,
+ .remove = ov772x_video_remove,
+ .init = ov772x_init,
+ .release = ov772x_release,
+ .start_capture = ov772x_start_capture,
+ .stop_capture = ov772x_stop_capture,
+ .set_fmt_cap = ov772x_set_fmt_cap,
+ .try_fmt_cap = ov772x_try_fmt_cap,
+ .set_bus_param = ov772x_set_bus_param,
+ .query_bus_param = ov772x_query_bus_param,
+ .get_chip_id = ov772x_get_chip_id,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ .get_register = ov772x_get_register,
+ .set_register = ov772x_set_register,
+#endif
+};
+
+/*
+ * i2c_driver function
+ */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
+static int ov772x_probe(struct i2c_client *client)
+#else
+static int ov772x_probe(struct i2c_client *client,
+ const struct i2c_device_id *did)
+#endif
+{
+ struct ov772x_priv *priv;
+ struct ov772x_camera_info *info;
+ struct soc_camera_device *icd;
+ struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+ int ret;
+
+ info = client->dev.platform_data;
+ if (!info)
+ return -EINVAL;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+ dev_err(&adapter->dev,
+ "I2C-Adapter doesn't support "
+ "I2C_FUNC_SMBUS_BYTE_DATA\n");
+ return -EIO;
+ }
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->info = info;
+ priv->client = client;
+ i2c_set_clientdata(client, priv);
+
+ icd = &priv->icd;
+ icd->ops = &ov772x_ops;
+ icd->control = &client->dev;
+ icd->width_max = MAX_WIDTH;
+ icd->height_max = MAX_HEIGHT;
+ icd->iface = priv->info->link.bus_id;
+
+ ret = soc_camera_device_register(icd);
+
+ if (ret)
+ kfree(priv);
+
+ return ret;
+}
+
+static int ov772x_remove(struct i2c_client *client)
+{
+ struct ov772x_priv *priv = i2c_get_clientdata(client);
+
+ soc_camera_device_unregister(&priv->icd);
+ kfree(priv);
+ return 0;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+static const struct i2c_device_id ov772x_id[] = {
+ {"ov772x", 0},
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, ov772x_id);
+#endif
+
+static struct i2c_driver ov772x_i2c_driver = {
+ .driver = {
+ .name = "ov772x",
+ },
+ .probe = ov772x_probe,
+ .remove = ov772x_remove,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+ .id_table = ov772x_id,
+#endif
+};
+
+/*
+ * module function
+ */
+
+static int __init ov772x_module_init(void)
+{
+ printk(KERN_INFO "ov772x driver\n");
+ return i2c_add_driver(&ov772x_i2c_driver);
+}
+
+static void __exit ov772x_module_exit(void)
+{
+ i2c_del_driver(&ov772x_i2c_driver);
+}
+
+module_init(ov772x_module_init);
+module_exit(ov772x_module_exit);
+
+MODULE_DESCRIPTION("SoC Camera driver for ov772x");
+MODULE_AUTHOR("Kuninori Morimoto");
+MODULE_LICENSE("GPL v2");
diff --git a/linux/drivers/media/video/pms.c b/linux/drivers/media/video/pms.c
index 00b623e00..522f75def 100644
--- a/linux/drivers/media/video/pms.c
+++ b/linux/drivers/media/video/pms.c
@@ -10,8 +10,8 @@
* 14478 Potsdam, Germany
*
* Most of this code is directly derived from his userspace driver.
- * His driver works so send any reports to alan@redhat.com unless the
- * userspace driver also doesn't work for you...
+ * His driver works so send any reports to alan@lxorguk.ukuu.org.uk
+ * unless the userspace driver also doesn't work for you...
*
* Changes:
* 08/07/2003 Daniele Bellucci <bellucda@tiscali.it>
@@ -681,8 +681,7 @@ static int pms_capture(struct pms_device *dev, char __user *buf, int rgb555, int
* Video4linux interfacing
*/
-static int pms_do_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, void *arg)
+static int pms_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct video_device *dev = video_devdata(file);
struct pms_device *pd=(struct pms_device *)dev;
@@ -867,7 +866,7 @@ static int pms_do_ioctl(struct inode *inode, struct file *file,
static int pms_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- return video_usercopy(inode, file, cmd, arg, pms_do_ioctl);
+ return video_usercopy(file, cmd, arg, pms_do_ioctl);
}
static ssize_t pms_read(struct file *file, char __user *buf,
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c
index da5b5a7e9..744bc192c 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c
@@ -435,6 +435,10 @@ static int pvr2_encoder_prep_config(struct pvr2_hdw *hdw)
ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 0,3,0,0);
ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4,15,0,0,0);
+ /* prevent the PTSs from slowly drifting away in the generated
+ MPEG stream */
+ ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC, 2, 4, 1);
+
return ret;
}
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c
index b79829f8a..447fcede8 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -61,7 +61,6 @@ static struct pvr2_hdw *unit_pointers[PVR_NUM] = {[ 0 ... PVR_NUM-1 ] = NULL};
static DEFINE_MUTEX(pvr2_unit_mtx);
static int ctlchg;
-static int initusbreset = 1;
static int procreload;
static int tuner[PVR_NUM] = { [0 ... PVR_NUM-1] = -1 };
static int tolerance[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 };
@@ -72,8 +71,6 @@ module_param(ctlchg, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ctlchg, "0=optimize ctl change 1=always accept new ctl value");
module_param(init_pause_msec, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(init_pause_msec, "hardware initialization settling delay");
-module_param(initusbreset, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(initusbreset, "Do USB reset device on probe");
module_param(procreload, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(procreload,
"Attempt init failure recovery with firmware reload");
@@ -1984,9 +1981,6 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
}
hdw->fw1_state = FW1_STATE_OK;
- if (initusbreset) {
- pvr2_hdw_device_reset(hdw);
- }
if (!pvr2_hdw_dev_ok(hdw)) return;
for (idx = 0; idx < hdw->hdw_desc->client_modules.cnt; idx++) {
@@ -2425,7 +2419,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
scnprintf(hdw->bus_info,sizeof(hdw->bus_info),
"usb %s address %d",
- hdw->usb_dev->dev.bus_id,
+ dev_name(&hdw->usb_dev->dev),
hdw->usb_dev->devnum);
ifnum = hdw->usb_intf->cur_altsetting->desc.bInterfaceNumber;
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
index 16461dd92..770f31e60 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
@@ -637,10 +637,10 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
class_dev->class = &class_ptr->class;
if (pvr2_hdw_get_sn(sfp->channel.hdw)) {
- snprintf(class_dev->bus_id, BUS_ID_SIZE, "sn-%lu",
+ dev_set_name(class_dev, "sn-%lu",
pvr2_hdw_get_sn(sfp->channel.hdw));
} else if (pvr2_hdw_get_unit_number(sfp->channel.hdw) >= 0) {
- snprintf(class_dev->bus_id, BUS_ID_SIZE, "unit-%c",
+ dev_set_name(class_dev, "unit-%c",
pvr2_hdw_get_unit_number(sfp->channel.hdw) + 'a');
} else {
kfree(class_dev);
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
index 429c96d4f..09fabfd2f 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
@@ -169,8 +169,7 @@ static const char *get_v4l_name(int v4l_type)
* This is part of Video 4 Linux API. The procedure handles ioctl() calls.
*
*/
-static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, void *arg)
+static int pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct pvr2_v4l2_fh *fh = file->private_data;
struct pvr2_v4l2 *vp = fh->vhead;
@@ -864,8 +863,8 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
#endif
default :
- ret = v4l_compat_translate_ioctl(inode,file,cmd,
- arg,pvr2_v4l2_do_ioctl);
+ ret = v4l_compat_translate_ioctl(file, cmd,
+ arg, pvr2_v4l2_do_ioctl);
}
pvr2_hdw_commit_ctl(hdw);
@@ -891,10 +890,9 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
return ret;
}
-
static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
{
- int minor_id = dip->devbase.minor;
+ int num = dip->devbase.num;
struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw;
enum pvr2_config cfg = dip->config;
int v4l_type = dip->v4l_type;
@@ -910,7 +908,7 @@ static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
video_unregister_device(&dip->devbase);
printk(KERN_INFO "pvrusb2: unregistered device %s%u [%s]\n",
- get_v4l_name(v4l_type),minor_id & 0x1f,
+ get_v4l_name(v4l_type), num,
pvr2_config_get_name(cfg));
}
@@ -959,7 +957,7 @@ static int pvr2_v4l2_ioctl(struct inode *inode, struct file *file,
#define IVTV_IOC_G_CODEC 0xFFEE7703
#define IVTV_IOC_S_CODEC 0xFFEE7704
if (cmd == IVTV_IOC_G_CODEC || cmd == IVTV_IOC_S_CODEC) return 0;
- return video_usercopy(inode, file, cmd, arg, pvr2_v4l2_do_ioctl);
+ return video_usercopy(file, cmd, arg, pvr2_v4l2_do_ioctl);
}
@@ -1317,7 +1315,7 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
}
printk(KERN_INFO "pvrusb2: registered device %s%u [%s]\n",
- get_v4l_name(dip->v4l_type),dip->devbase.minor & 0x1f,
+ get_v4l_name(dip->v4l_type), dip->devbase.num,
pvr2_config_get_name(dip->config));
pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,
diff --git a/linux/drivers/media/video/pwc/pwc-if.c b/linux/drivers/media/video/pwc/pwc-if.c
index 69917b2f9..d657e6f8d 100644
--- a/linux/drivers/media/video/pwc/pwc-if.c
+++ b/linux/drivers/media/video/pwc/pwc-if.c
@@ -1416,7 +1416,7 @@ static int pwc_video_ioctl(struct inode *inode, struct file *file,
mutex_lock(&pdev->modlock);
if (!pdev->unplugged)
- r = video_usercopy(inode, file, cmd, arg, pwc_video_do_ioctl);
+ r = video_usercopy(file, cmd, arg, pwc_video_do_ioctl);
mutex_unlock(&pdev->modlock);
out:
return r;
@@ -1799,7 +1799,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
goto err;
}
else {
- PWC_INFO("Registered as /dev/video%d.\n", pdev->vdev->minor & 0x3F);
+ PWC_INFO("Registered as /dev/video%d.\n", pdev->vdev->num);
}
/* occupy slot */
diff --git a/linux/drivers/media/video/pwc/pwc-v4l.c b/linux/drivers/media/video/pwc/pwc-v4l.c
index 76a1376c9..d7c147328 100644
--- a/linux/drivers/media/video/pwc/pwc-v4l.c
+++ b/linux/drivers/media/video/pwc/pwc-v4l.c
@@ -337,8 +337,7 @@ static int pwc_vidioc_set_fmt(struct pwc_device *pdev, struct v4l2_format *f)
}
-int pwc_video_do_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, void *arg)
+int pwc_video_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct video_device *vdev = video_devdata(file);
struct pwc_device *pdev;
diff --git a/linux/drivers/media/video/pwc/pwc.h b/linux/drivers/media/video/pwc/pwc.h
index 926defb11..ade796037 100644
--- a/linux/drivers/media/video/pwc/pwc.h
+++ b/linux/drivers/media/video/pwc/pwc.h
@@ -341,8 +341,7 @@ extern int pwc_camera_power(struct pwc_device *pdev, int power);
extern int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg);
/** Functions in pwc-v4l.c */
-extern int pwc_video_do_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, void *arg);
+extern int pwc_video_do_ioctl(struct file *file, unsigned int cmd, void *arg);
/** pwc-uncompress.c */
/* Expand frame to image, possibly including decompression. Uses read_frame and fill_image */
diff --git a/linux/drivers/media/video/s2255drv.c b/linux/drivers/media/video/s2255drv.c
index 5a872787e..ab9814144 100644
--- a/linux/drivers/media/video/s2255drv.c
+++ b/linux/drivers/media/video/s2255drv.c
@@ -193,7 +193,7 @@ struct s2255_dmaqueue {
#define S2255_FW_FAILED 3
#define S2255_FW_DISCONNECTING 4
-#define S2255_FW_MARKER 0x22552f2f
+#define S2255_FW_MARKER cpu_to_le32(0x22552f2f)
/* 2255 read states */
#define S2255_READ_IDLE 0
#define S2255_READ_FRAME 1
diff --git a/linux/drivers/media/video/saa5246a.c b/linux/drivers/media/video/saa5246a.c
index 355490467..086fc807a 100644
--- a/linux/drivers/media/video/saa5246a.c
+++ b/linux/drivers/media/video/saa5246a.c
@@ -15,7 +15,7 @@
* <richard.guenther@student.uni-tuebingen.de>
*
* with changes by
- * Alan Cox <Alan.Cox@linux.org>
+ * Alan Cox <alan@lxorguk.ukuu.org.uk>
*
* and
*
@@ -805,8 +805,7 @@ static inline int saa5246a_stop_dau(struct saa5246a_device *t,
*
* Returns 0 if successful
*/
-static int do_saa5246a_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, void *arg)
+static int do_saa5246a_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct saa5246a_device *t = video_drvdata(file);
@@ -954,7 +953,7 @@ static int saa5246a_ioctl(struct inode *inode, struct file *file,
cmd = vtx_fix_command(cmd);
mutex_lock(&t->lock);
- err = video_usercopy(inode, file, cmd, arg, do_saa5246a_ioctl);
+ err = video_usercopy(file, cmd, arg, do_saa5246a_ioctl);
mutex_unlock(&t->lock);
return err;
}
diff --git a/linux/drivers/media/video/saa5249.c b/linux/drivers/media/video/saa5249.c
index 2f63455d3..86352dbe7 100644
--- a/linux/drivers/media/video/saa5249.c
+++ b/linux/drivers/media/video/saa5249.c
@@ -8,7 +8,7 @@
* you can add arbitary multiple teletext devices to Linux video4linux
* now (well 32 anyway).
*
- * Alan Cox <Alan.Cox@linux.org>
+ * Alan Cox <alan@lxorguk.ukuu.org.uk>
*
* The original driver was heavily modified to match the i2c interface
* It was truncated to use the WinTV boards, too.
@@ -191,8 +191,7 @@ static int i2c_getdata(struct saa5249_device *t, int count, u8 *buf)
* Standard character-device-driver functions
*/
-static int do_saa5249_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, void *arg)
+static int do_saa5249_ioctl(struct file *file, unsigned int cmd, void *arg)
{
static int virtual_mode = false;
struct saa5249_device *t = video_drvdata(file);
@@ -489,7 +488,7 @@ static int saa5249_ioctl(struct inode *inode, struct file *file,
cmd = vtx_fix_command(cmd);
mutex_lock(&t->lock);
- err = video_usercopy(inode,file,cmd,arg,do_saa5249_ioctl);
+ err = video_usercopy(file, cmd, arg, do_saa5249_ioctl);
mutex_unlock(&t->lock);
return err;
}
diff --git a/linux/drivers/media/video/saa7110.c b/linux/drivers/media/video/saa7110.c
index 15eb8bd7a..b7afe3124 100644
--- a/linux/drivers/media/video/saa7110.c
+++ b/linux/drivers/media/video/saa7110.c
@@ -48,7 +48,7 @@ module_param(debug, int, 0);
MODULE_PARM_DESC(debug, "Debug level (0-1)");
#define SAA7110_MAX_INPUT 9 /* 6 CVBS, 3 SVHS */
-#define SAA7110_MAX_OUTPUT 0 /* its a decoder only */
+#define SAA7110_MAX_OUTPUT 1 /* 1 YUV */
#define SAA7110_NR_REG 0x35
@@ -328,7 +328,7 @@ saa7110_command (struct i2c_client *client,
case DECODER_SET_INPUT:
v = *(int *) arg;
- if (v < 0 || v > SAA7110_MAX_INPUT) {
+ if (v < 0 || v >= SAA7110_MAX_INPUT) {
v4l_dbg(1, debug, client, "input=%d not available\n", v);
return -EINVAL;
}
diff --git a/linux/drivers/media/video/saa7127.c b/linux/drivers/media/video/saa7127.c
index 0b126a849..fd7d15305 100644
--- a/linux/drivers/media/video/saa7127.c
+++ b/linux/drivers/media/video/saa7127.c
@@ -29,7 +29,7 @@
* Note: the saa7126 is identical to the saa7127, and the saa7128 is
* identical to the saa7129, except that the saa7126 and saa7128 have
* macrovision anti-taping support. This driver will almost certainly
- * work find for those chips, except of course for the missing anti-taping
+ * work fine for those chips, except of course for the missing anti-taping
* support.
*
* This program is free software; you can redistribute it and/or modify
diff --git a/linux/drivers/media/video/saa7134/saa7134-core.c b/linux/drivers/media/video/saa7134/saa7134-core.c
index c839114a0..2e9a015e9 100644
--- a/linux/drivers/media/video/saa7134/saa7134-core.c
+++ b/linux/drivers/media/video/saa7134/saa7134-core.c
@@ -1002,7 +1002,8 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
dev->name,(unsigned long long)pci_resource_start(pci_dev,0));
goto fail1;
}
- dev->lmmio = ioremap(pci_resource_start(pci_dev,0), 0x1000);
+ dev->lmmio = ioremap(pci_resource_start(pci_dev, 0),
+ pci_resource_len(pci_dev, 0));
dev->bmmio = (__u8 __iomem *)dev->lmmio;
if (NULL == dev->lmmio) {
err = -EIO;
@@ -1057,7 +1058,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
goto fail4;
}
printk(KERN_INFO "%s: registered device video%d [v4l2]\n",
- dev->name,dev->video_dev->minor & 0x1f);
+ dev->name, dev->video_dev->num);
dev->vbi_dev = vdev_init(dev, &saa7134_video_template, "vbi");
@@ -1066,7 +1067,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
if (err < 0)
goto fail4;
printk(KERN_INFO "%s: registered device vbi%d\n",
- dev->name,dev->vbi_dev->minor & 0x1f);
+ dev->name, dev->vbi_dev->num);
if (card_has_radio(dev)) {
dev->radio_dev = vdev_init(dev,&saa7134_radio_template,"radio");
@@ -1075,7 +1076,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
if (err < 0)
goto fail4;
printk(KERN_INFO "%s: registered device radio%d\n",
- dev->name,dev->radio_dev->minor & 0x1f);
+ dev->name, dev->radio_dev->num);
}
/* everything worked */
diff --git a/linux/drivers/media/video/saa7134/saa7134-dvb.c b/linux/drivers/media/video/saa7134/saa7134-dvb.c
index 11a7c76bc..704442f55 100644
--- a/linux/drivers/media/video/saa7134/saa7134-dvb.c
+++ b/linux/drivers/media/video/saa7134/saa7134-dvb.c
@@ -953,21 +953,15 @@ static int dvb_init(struct saa7134_dev *dev)
/* FIXME: add support for multi-frontend */
mutex_init(&dev->frontends.lock);
- INIT_LIST_HEAD(&dev->frontends.frontend.felist);
- dev->frontends.active_fe_id = 0;
+ INIT_LIST_HEAD(&dev->frontends.felist);
printk(KERN_INFO "%s() allocating 1 frontend\n", __func__);
-
- if (videobuf_dvb_alloc_frontend(dev, &dev->frontends, 1) == NULL) {
+ fe0 = videobuf_dvb_alloc_frontend(&dev->frontends, 1);
+ if (!fe0) {
printk(KERN_ERR "%s() failed to alloc\n", __func__);
return -ENOMEM;
}
- /* Get the first frontend */
- fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
- if (!fe0)
- return -EINVAL;
-
/* init struct videobuf_dvb */
dev->ts.nr_bufs = 32;
dev->ts.nr_packets = 32*4;
@@ -1380,7 +1374,7 @@ static int dvb_init(struct saa7134_dev *dev)
};
if (!fe0->dvb.frontend)
- return -1;
+ goto dettach_frontend;
fe = dvb_attach(xc2028_attach, fe0->dvb.frontend, &cfg);
if (!fe) {
@@ -1392,7 +1386,7 @@ static int dvb_init(struct saa7134_dev *dev)
if (NULL == fe0->dvb.frontend) {
printk(KERN_ERR "%s/dvb: frontend initialization failed\n", dev->name);
- return -1;
+ goto dettach_frontend;
}
/* define general-purpose callback pointer */
fe0->dvb.frontend->callback = saa7134_tuner_callback;
@@ -1415,11 +1409,8 @@ static int dvb_init(struct saa7134_dev *dev)
return ret;
dettach_frontend:
- if (fe0->dvb.frontend)
- dvb_frontend_detach(fe0->dvb.frontend);
- fe0->dvb.frontend = NULL;
-
- return -1;
+ videobuf_dvb_dealloc_frontends(&dev->frontends);
+ return -EINVAL;
}
static int dvb_fini(struct saa7134_dev *dev)
@@ -1458,8 +1449,7 @@ static int dvb_fini(struct saa7134_dev *dev)
}
}
}
- if (fe0->dvb.frontend)
- videobuf_dvb_unregister_bus(&dev->frontends);
+ videobuf_dvb_unregister_bus(&dev->frontends);
return 0;
}
diff --git a/linux/drivers/media/video/saa7134/saa7134-empress.c b/linux/drivers/media/video/saa7134/saa7134-empress.c
index 9ebe166cc..53de5545c 100644
--- a/linux/drivers/media/video/saa7134/saa7134-empress.c
+++ b/linux/drivers/media/video/saa7134/saa7134-empress.c
@@ -546,7 +546,7 @@ static int empress_init(struct saa7134_dev *dev)
return err;
}
printk(KERN_INFO "%s: registered device video%d [mpeg]\n",
- dev->name,dev->empress_dev->minor & 0x1f);
+ dev->name, dev->empress_dev->num);
videobuf_queue_sg_init(&dev->empress_tsq, &saa7134_ts_qops,
&dev->pci->dev, &dev->slock,
diff --git a/linux/drivers/media/video/saa7134/saa7134-tvaudio.c b/linux/drivers/media/video/saa7134/saa7134-tvaudio.c
index f7a3f1d0a..477d9e091 100644
--- a/linux/drivers/media/video/saa7134/saa7134-tvaudio.c
+++ b/linux/drivers/media/video/saa7134/saa7134-tvaudio.c
@@ -161,7 +161,7 @@ static struct saa7134_tvaudio tvaudio[] = {
.mode = TVAUDIO_FM_MONO,
}
};
-#define TVAUDIO (sizeof(tvaudio)/sizeof(struct saa7134_tvaudio))
+#define TVAUDIO ARRAY_SIZE(tvaudio)
/* ------------------------------------------------------------------ */
diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h
index 837fc5424..82f9a889a 100644
--- a/linux/drivers/media/video/saa7134/saa7134.h
+++ b/linux/drivers/media/video/saa7134/saa7134.h
@@ -277,7 +277,7 @@ struct saa7134_format {
#define SAA7134_BOARD_ADS_INSTANT_HDTV_PCI 151
#define SAA7134_BOARD_ASUSTeK_TIGER 152
-#define SAA7134_MAXBOARDS 8
+#define SAA7134_MAXBOARDS 32
#define SAA7134_INPUT_MAX 8
/* ----------------------------------------------------------- */
diff --git a/linux/drivers/media/video/se401.c b/linux/drivers/media/video/se401.c
index 5a346d0c5..8935c1632 100644
--- a/linux/drivers/media/video/se401.c
+++ b/linux/drivers/media/video/se401.c
@@ -983,8 +983,7 @@ static int se401_close(struct inode *inode, struct file *file)
return 0;
}
-static int se401_do_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, void *arg)
+static int se401_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct video_device *vdev = file->private_data;
struct usb_se401 *se401 = (struct usb_se401 *)vdev;
@@ -1150,7 +1149,7 @@ static int se401_do_ioctl(struct inode *inode, struct file *file,
static int se401_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- return video_usercopy(inode, file, cmd, arg, se401_do_ioctl);
+ return video_usercopy(file, cmd, arg, se401_do_ioctl);
}
static ssize_t se401_read(struct file *file, char __user *buf,
@@ -1420,7 +1419,7 @@ static int se401_probe(struct usb_interface *intf,
return -EIO;
}
dev_info(&intf->dev, "registered new video device: video%d\n",
- se401->vdev.minor);
+ se401->vdev.num);
usb_set_intfdata (intf, se401);
return 0;
diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c
index 76838091d..2fb8bee0b 100644
--- a/linux/drivers/media/video/sh_mobile_ceu_camera.c
+++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c
@@ -37,42 +37,43 @@
#include <media/soc_camera.h>
#include <media/sh_mobile_ceu.h>
#include <media/videobuf-dma-contig.h>
+#include "compat.h"
/* register offsets for sh7722 / sh7723 */
-#define CAPSR 0x00
-#define CAPCR 0x04
-#define CAMCR 0x08
-#define CMCYR 0x0c
-#define CAMOR 0x10
-#define CAPWR 0x14
-#define CAIFR 0x18
-#define CSTCR 0x20 /* not on sh7723 */
-#define CSECR 0x24 /* not on sh7723 */
-#define CRCNTR 0x28
-#define CRCMPR 0x2c
-#define CFLCR 0x30
-#define CFSZR 0x34
-#define CDWDR 0x38
-#define CDAYR 0x3c
-#define CDACR 0x40
-#define CDBYR 0x44
-#define CDBCR 0x48
-#define CBDSR 0x4c
-#define CFWCR 0x5c
-#define CLFCR 0x60
-#define CDOCR 0x64
-#define CDDCR 0x68
-#define CDDAR 0x6c
-#define CEIER 0x70
-#define CETCR 0x74
-#define CSTSR 0x7c
-#define CSRTR 0x80
-#define CDSSR 0x84
-#define CDAYR2 0x90
-#define CDACR2 0x94
-#define CDBYR2 0x98
-#define CDBCR2 0x9c
+#define CAPSR 0x00 /* Capture start register */
+#define CAPCR 0x04 /* Capture control register */
+#define CAMCR 0x08 /* Capture interface control register */
+#define CMCYR 0x0c /* Capture interface cycle register */
+#define CAMOR 0x10 /* Capture interface offset register */
+#define CAPWR 0x14 /* Capture interface width register */
+#define CAIFR 0x18 /* Capture interface input format register */
+#define CSTCR 0x20 /* Camera strobe control register (<= sh7722) */
+#define CSECR 0x24 /* Camera strobe emission count register (<= sh7722) */
+#define CRCNTR 0x28 /* CEU register control register */
+#define CRCMPR 0x2c /* CEU register forcible control register */
+#define CFLCR 0x30 /* Capture filter control register */
+#define CFSZR 0x34 /* Capture filter size clip register */
+#define CDWDR 0x38 /* Capture destination width register */
+#define CDAYR 0x3c /* Capture data address Y register */
+#define CDACR 0x40 /* Capture data address C register */
+#define CDBYR 0x44 /* Capture data bottom-field address Y register */
+#define CDBCR 0x48 /* Capture data bottom-field address C register */
+#define CBDSR 0x4c /* Capture bundle destination size register */
+#define CFWCR 0x5c /* Firewall operation control register */
+#define CLFCR 0x60 /* Capture low-pass filter control register */
+#define CDOCR 0x64 /* Capture data output control register */
+#define CDDCR 0x68 /* Capture data complexity level register */
+#define CDDAR 0x6c /* Capture data complexity level address register */
+#define CEIER 0x70 /* Capture event interrupt enable register */
+#define CETCR 0x74 /* Capture event flag clear register */
+#define CSTSR 0x7c /* Capture status register */
+#define CSRTR 0x80 /* Capture software reset register */
+#define CDSSR 0x84 /* Capture data size register */
+#define CDAYR2 0x90 /* Capture data address Y register 2 */
+#define CDACR2 0x94 /* Capture data address C register 2 */
+#define CDBYR2 0x98 /* Capture data bottom-field address Y register 2 */
+#define CDBCR2 0x9c /* Capture data bottom-field address C register 2 */
static DEFINE_MUTEX(camera_lock);
@@ -165,6 +166,7 @@ static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev)
ceu_write(pcdev, CETCR, 0x0317f313 ^ 0x10);
if (pcdev->active) {
+ pcdev->active->state = VIDEOBUF_ACTIVE;
ceu_write(pcdev, CDAYR, videobuf_to_dma_contig(pcdev->active));
ceu_write(pcdev, CAPSR, 0x1); /* start capture */
}
@@ -236,7 +238,7 @@ static void sh_mobile_ceu_videobuf_queue(struct videobuf_queue *vq,
dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
vb, vb->baddr, vb->bsize);
- vb->state = VIDEOBUF_ACTIVE;
+ vb->state = VIDEOBUF_QUEUED;
spin_lock_irqsave(&pcdev->lock, flags);
list_add_tail(&vb->queue, &pcdev->capture);
@@ -323,12 +325,24 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd)
{
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
struct sh_mobile_ceu_dev *pcdev = ici->priv;
+ unsigned long flags;
BUG_ON(icd != pcdev->icd);
/* disable capture, disable interrupts */
ceu_write(pcdev, CEIER, 0);
ceu_write(pcdev, CAPSR, 1 << 16); /* reset */
+
+ /* make sure active buffer is canceled */
+ spin_lock_irqsave(&pcdev->lock, flags);
+ if (pcdev->active) {
+ list_del(&pcdev->active->queue);
+ pcdev->active->state = VIDEOBUF_ERROR;
+ wake_up_all(&pcdev->active->done);
+ pcdev->active = NULL;
+ }
+ spin_unlock_irqrestore(&pcdev->lock, flags);
+
icd->ops->release(icd);
dev_info(&icd->dev,
@@ -391,7 +405,20 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
ceu_write(pcdev, CFLCR, 0); /* data fetch mode - no scaling */
ceu_write(pcdev, CFSZR, (icd->height << 16) | cfszr_width);
ceu_write(pcdev, CLFCR, 0); /* data fetch mode - no lowpass filter */
- ceu_write(pcdev, CDOCR, 0x00000016);
+
+ /* A few words about byte order (observed in Big Endian mode)
+ *
+ * In data fetch mode bytes are received in chunks of 8 bytes.
+ * D0, D1, D2, D3, D4, D5, D6, D7 (D0 received first)
+ *
+ * The data is however by default written to memory in reverse order:
+ * D7, D6, D5, D4, D3, D2, D1, D0 (D7 written to lowest byte)
+ *
+ * The lowest three bits of CDOCR allows us to do swapping,
+ * using 7 we swap the data bytes to match the incoming order:
+ * D0, D1, D2, D3, D4, D5, D6, D7
+ */
+ ceu_write(pcdev, CDOCR, 0x00000017);
ceu_write(pcdev, CDWDR, cdwdr_width);
ceu_write(pcdev, CFWCR, 0); /* keep "datafetch firewall" disabled */
@@ -583,7 +610,7 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev)
/* request irq */
err = request_irq(pcdev->irq, sh_mobile_ceu_irq, IRQF_DISABLED,
- pdev->dev.bus_id, pcdev);
+ dev_name(&pdev->dev), pcdev);
if (err) {
dev_err(&pdev->dev, "Unable to register CEU interrupt.\n");
goto exit_release_mem;
@@ -592,8 +619,8 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev)
pcdev->ici.priv = pcdev;
pcdev->ici.dev.parent = &pdev->dev;
pcdev->ici.nr = pdev->id;
- pcdev->ici.drv_name = pdev->dev.bus_id,
- pcdev->ici.ops = &sh_mobile_ceu_host_ops,
+ pcdev->ici.drv_name = dev_name(&pdev->dev);
+ pcdev->ici.ops = &sh_mobile_ceu_host_ops;
err = soc_camera_host_register(&pcdev->ici);
if (err)
diff --git a/linux/drivers/media/video/sn9c102/sn9c102_core.c b/linux/drivers/media/video/sn9c102/sn9c102_core.c
index fd867dadf..3ce12faf5 100644
--- a/linux/drivers/media/video/sn9c102/sn9c102_core.c
+++ b/linux/drivers/media/video/sn9c102/sn9c102_core.c
@@ -1012,7 +1012,7 @@ static int sn9c102_stream_interrupt(struct sn9c102_device* cam)
cam->state |= DEV_MISCONFIGURED;
DBG(1, "URB timeout reached. The camera is misconfigured. "
"To use it, close and open /dev/video%d again.",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
return -EIO;
}
@@ -1738,7 +1738,7 @@ static void sn9c102_release_resources(struct kref *kref)
cam = container_of(kref, struct sn9c102_device, kref);
- DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor);
+ DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->num);
video_set_drvdata(cam->v4ldev, NULL);
video_unregister_device(cam->v4ldev);
usb_put_dev(cam->usbdev);
@@ -1796,7 +1796,7 @@ static int sn9c102_open(struct inode* inode, struct file* filp)
if (cam->users) {
DBG(2, "Device /dev/video%d is already in use",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
DBG(3, "Simultaneous opens are not supported");
/*
open() must follow the open flags and should block
@@ -1849,7 +1849,7 @@ static int sn9c102_open(struct inode* inode, struct file* filp)
cam->frame_count = 0;
sn9c102_empty_framequeues(cam);
- DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor);
+ DBG(3, "Video device /dev/video%d is open", cam->v4ldev->num);
out:
mutex_unlock(&cam->open_mutex);
@@ -1874,7 +1874,7 @@ static int sn9c102_release(struct inode* inode, struct file* filp)
cam->users--;
wake_up_interruptible_nr(&cam->wait_open, 1);
- DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor);
+ DBG(3, "Video device /dev/video%d closed", cam->v4ldev->num);
kref_put(&cam->kref, sn9c102_release_resources);
@@ -2166,7 +2166,7 @@ sn9c102_vidioc_querycap(struct sn9c102_device* cam, void __user * arg)
strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card));
if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0)
- strlcpy(cap.bus_info, cam->usbdev->dev.bus_id,
+ strlcpy(cap.bus_info, dev_name(&cam->usbdev->dev),
sizeof(cap.bus_info));
if (copy_to_user(arg, &cap, sizeof(cap)))
@@ -2436,7 +2436,7 @@ sn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg)
cam->state |= DEV_MISCONFIGURED;
DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To "
"use the camera, close and open /dev/video%d again.",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
return -EIO;
}
@@ -2449,7 +2449,7 @@ sn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg)
cam->state |= DEV_MISCONFIGURED;
DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To "
"use the camera, close and open /dev/video%d again.",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
return -ENOMEM;
}
@@ -2693,7 +2693,7 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd,
cam->state |= DEV_MISCONFIGURED;
DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To "
"use the camera, close and open /dev/video%d again.",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
return -EIO;
}
@@ -2705,7 +2705,7 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd,
cam->state |= DEV_MISCONFIGURED;
DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To "
"use the camera, close and open /dev/video%d again.",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
return -ENOMEM;
}
@@ -2752,7 +2752,7 @@ sn9c102_vidioc_s_jpegcomp(struct sn9c102_device* cam, void __user * arg)
cam->state |= DEV_MISCONFIGURED;
DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware "
"problems. To use the camera, close and open "
- "/dev/video%d again.", cam->v4ldev->minor);
+ "/dev/video%d again.", cam->v4ldev->num);
return -EIO;
}
@@ -3352,7 +3352,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
goto fail;
}
- DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor);
+ DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->num);
video_set_drvdata(cam->v4ldev, cam);
cam->module_param.force_munmap = force_munmap[dev_nr];
@@ -3406,7 +3406,7 @@ static void sn9c102_usb_disconnect(struct usb_interface* intf)
if (cam->users) {
DBG(2, "Device /dev/video%d is open! Deregistration and "
"memory deallocation are deferred.",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
cam->state |= DEV_MISCONFIGURED;
sn9c102_stop_transfer(cam);
cam->state |= DEV_DISCONNECTED;
diff --git a/linux/drivers/media/video/sn9c102/sn9c102_devtable.h b/linux/drivers/media/video/sn9c102/sn9c102_devtable.h
index e23734f6d..b0d9d9589 100644
--- a/linux/drivers/media/video/sn9c102/sn9c102_devtable.h
+++ b/linux/drivers/media/video/sn9c102/sn9c102_devtable.h
@@ -55,7 +55,9 @@ static const struct usb_device_id sn9c102_id_table[] = {
{ SN9C102_USB_DEVICE(0x0c45, 0x6029, BRIDGE_SN9C102), },
{ SN9C102_USB_DEVICE(0x0c45, 0x602a, BRIDGE_SN9C102), },
{ SN9C102_USB_DEVICE(0x0c45, 0x602b, BRIDGE_SN9C102), },
+#if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE
{ SN9C102_USB_DEVICE(0x0c45, 0x602c, BRIDGE_SN9C102), },
+#endif
/* { SN9C102_USB_DEVICE(0x0c45, 0x602d, BRIDGE_SN9C102), }, HV7131R */
{ SN9C102_USB_DEVICE(0x0c45, 0x602e, BRIDGE_SN9C102), },
{ SN9C102_USB_DEVICE(0x0c45, 0x6030, BRIDGE_SN9C102), },
@@ -94,7 +96,9 @@ static const struct usb_device_id sn9c102_id_table[] = {
{ SN9C102_USB_DEVICE(0x045e, 0x00f5, BRIDGE_SN9C105), },
{ SN9C102_USB_DEVICE(0x045e, 0x00f7, BRIDGE_SN9C105), },
{ SN9C102_USB_DEVICE(0x0471, 0x0327, BRIDGE_SN9C105), },
+#if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE
{ SN9C102_USB_DEVICE(0x0471, 0x0328, BRIDGE_SN9C105), },
+#endif
{ SN9C102_USB_DEVICE(0x0c45, 0x60c0, BRIDGE_SN9C105), },
{ SN9C102_USB_DEVICE(0x0c45, 0x60c2, BRIDGE_SN9C105), },
{ SN9C102_USB_DEVICE(0x0c45, 0x60c8, BRIDGE_SN9C105), },
@@ -113,7 +117,9 @@ static const struct usb_device_id sn9c102_id_table[] = {
{ SN9C102_USB_DEVICE(0x0c45, 0x610f, BRIDGE_SN9C120), },
{ SN9C102_USB_DEVICE(0x0c45, 0x6130, BRIDGE_SN9C120), },
/* { SN9C102_USB_DEVICE(0x0c45, 0x6138, BRIDGE_SN9C120), }, MO8000 */
+#if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE
{ SN9C102_USB_DEVICE(0x0c45, 0x613a, BRIDGE_SN9C120), },
+#endif
{ SN9C102_USB_DEVICE(0x0c45, 0x613b, BRIDGE_SN9C120), },
{ SN9C102_USB_DEVICE(0x0c45, 0x613c, BRIDGE_SN9C120), },
{ SN9C102_USB_DEVICE(0x0c45, 0x613e, BRIDGE_SN9C120), },
diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c
index 66ebe5956..7a46697c4 100644
--- a/linux/drivers/media/video/soc_camera.c
+++ b/linux/drivers/media/video/soc_camera.c
@@ -29,6 +29,7 @@
#include <media/v4l2-dev.h>
#include <media/videobuf-core.h>
#include <media/soc_camera.h>
+#include "compat.h"
static LIST_HEAD(hosts);
static LIST_HEAD(devices);
@@ -783,7 +784,7 @@ int soc_camera_host_register(struct soc_camera_host *ici)
return -EINVAL;
/* Number might be equal to the platform device ID */
- sprintf(ici->dev.bus_id, "camera_host%d", ici->nr);
+ dev_set_name(&ici->dev, "camera_host%d", ici->nr);
mutex_lock(&list_lock);
list_for_each_entry(ix, &hosts, list) {
@@ -867,8 +868,7 @@ int soc_camera_device_register(struct soc_camera_device *icd)
icd->devnum = num;
icd->dev.bus = &soc_camera_bus_type;
- snprintf(icd->dev.bus_id, sizeof(icd->dev.bus_id),
- "%u-%u", icd->iface, icd->devnum);
+ dev_set_name(&icd->dev, "%u-%u", icd->iface, icd->devnum);
icd->dev.release = dummy_release;
diff --git a/linux/drivers/media/video/soc_camera_platform.c b/linux/drivers/media/video/soc_camera_platform.c
index 1adc257eb..bb7a9d480 100644
--- a/linux/drivers/media/video/soc_camera_platform.c
+++ b/linux/drivers/media/video/soc_camera_platform.c
@@ -18,15 +18,7 @@
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
#include <media/soc_camera.h>
-
-struct soc_camera_platform_info {
- int iface;
- char *format_name;
- unsigned long format_depth;
- struct v4l2_pix_format format;
- unsigned long bus_param;
- int (*set_capture)(struct soc_camera_platform_info *info, int enable);
-};
+#include <media/soc_camera_platform.h>
struct soc_camera_platform_priv {
struct soc_camera_platform_info *info;
@@ -44,11 +36,21 @@ soc_camera_platform_get_info(struct soc_camera_device *icd)
static int soc_camera_platform_init(struct soc_camera_device *icd)
{
+ struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd);
+
+ if (p->power)
+ p->power(1);
+
return 0;
}
static int soc_camera_platform_release(struct soc_camera_device *icd)
{
+ struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd);
+
+ if (p->power)
+ p->power(0);
+
return 0;
}
diff --git a/linux/drivers/media/video/stk-webcam.c b/linux/drivers/media/video/stk-webcam.c
index f606300e8..9615b7678 100644
--- a/linux/drivers/media/video/stk-webcam.c
+++ b/linux/drivers/media/video/stk-webcam.c
@@ -1332,7 +1332,7 @@ static int stk_register_video_device(struct stk_camera *dev)
STK_ERROR("v4l registration failed\n");
else
STK_INFO("Syntek USB2.0 Camera is now controlling video device"
- " /dev/video%d\n", dev->vdev.minor);
+ " /dev/video%d\n", dev->vdev.num);
return err;
}
@@ -1427,7 +1427,7 @@ static void stk_camera_disconnect(struct usb_interface *interface)
stk_remove_sysfs_files(&dev->vdev);
STK_INFO("Syntek USB2.0 Camera release resources "
- "video device /dev/video%d\n", dev->vdev.minor);
+ "video device /dev/video%d\n", dev->vdev.num);
video_unregister_device(&dev->vdev);
}
diff --git a/linux/drivers/media/video/stv680.c b/linux/drivers/media/video/stv680.c
index f74c08b41..be5ed5940 100644
--- a/linux/drivers/media/video/stv680.c
+++ b/linux/drivers/media/video/stv680.c
@@ -1137,8 +1137,7 @@ static int stv_close (struct inode *inode, struct file *file)
return 0;
}
-static int stv680_do_ioctl (struct inode *inode, struct file *file,
- unsigned int cmd, void *arg)
+static int stv680_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct video_device *vdev = file->private_data;
struct usb_stv *stv680 = video_get_drvdata(vdev);
@@ -1308,7 +1307,7 @@ static int stv680_do_ioctl (struct inode *inode, struct file *file,
static int stv680_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- return video_usercopy(inode, file, cmd, arg, stv680_do_ioctl);
+ return video_usercopy(file, cmd, arg, stv680_do_ioctl);
}
static int stv680_mmap (struct file *file, struct vm_area_struct *vma)
@@ -1475,7 +1474,8 @@ static int stv680_probe (struct usb_interface *intf, const struct usb_device_id
retval = -EIO;
goto error_vdev;
}
- PDEBUG (0, "STV(i): registered new video device: video%d", stv680->vdev->minor);
+ PDEBUG(0, "STV(i): registered new video device: video%d",
+ stv680->vdev->num);
usb_set_intfdata (intf, stv680);
retval = stv680_create_sysfs_files(stv680->vdev);
diff --git a/linux/drivers/media/video/tvaudio.c b/linux/drivers/media/video/tvaudio.c
index 7e670f2bc..0a86c80a2 100644
--- a/linux/drivers/media/video/tvaudio.c
+++ b/linux/drivers/media/video/tvaudio.c
@@ -1,5 +1,5 @@
/*
- * experimental driver for simple i2c audio chips.
+ * Driver for simple i2c audio chips.
*
* Copyright (c) 2000 Gerd Knorr
* based on code by:
@@ -7,6 +7,10 @@
* Steve VanDeBogart (vandebo@uclink.berkeley.edu)
* Greg Alexander (galexand@acm.org)
*
+ * Copyright(c) 2005-2008 Mauro Carvalho Chehab
+ * - Some cleanups, code fixes, etc
+ * - Convert it to V4L2 API
+ *
* This code is placed under the terms of the GNU General Public License
*
* OPTIONS:
@@ -33,6 +37,7 @@
#include <media/tvaudio.h>
#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
#include <media/v4l2-chip-ident.h>
#include <media/v4l2-i2c-drv-legacy.h>
@@ -61,7 +66,6 @@ typedef int (*checkit)(struct CHIPSTATE*);
typedef int (*initialize)(struct CHIPSTATE*);
typedef int (*getmode)(struct CHIPSTATE*);
typedef void (*setmode)(struct CHIPSTATE*, int mode);
-typedef void (*checkmode)(struct CHIPSTATE*);
/* i2c command */
typedef struct AUDIOCMD {
@@ -82,6 +86,7 @@ struct CHIPDESC {
#define CHIP_HAS_VOLUME 1
#define CHIP_HAS_BASSTREBLE 2
#define CHIP_HAS_INPUTSEL 4
+#define CHIP_NEED_CHECKMODE 8
/* various i2c command sequences */
audiocmd init;
@@ -99,23 +104,20 @@ struct CHIPDESC {
getmode getmode;
setmode setmode;
- /* check / autoswitch audio after channel switches */
- checkmode checkmode;
-
/* input switch register + values for v4l inputs */
int inputreg;
int inputmap[4];
int inputmute;
int inputmask;
};
-static struct CHIPDESC chiplist[];
/* current state of the chip */
struct CHIPSTATE {
struct i2c_client *c;
- /* index into CHIPDESC array */
- int type;
+ /* chip-specific description - should point to
+ an entry at CHIPDESC table */
+ struct CHIPDESC *desc;
/* shadow register set */
audiocmd shadow;
@@ -155,7 +157,7 @@ static int chip_write(struct CHIPSTATE *chip, int subaddr, int val)
{
unsigned char buffer[2];
- if (-1 == subaddr) {
+ if (subaddr < 0) {
v4l_dbg(1, debug, chip->c, "%s: chip_write: 0x%x\n",
chip->c->name, val);
chip->shadow.bytes[1] = val;
@@ -166,6 +168,13 @@ static int chip_write(struct CHIPSTATE *chip, int subaddr, int val)
return -1;
}
} else {
+ if (subaddr + 1 >= ARRAY_SIZE(chip->shadow.bytes)) {
+ v4l_info(chip->c,
+ "Tried to access a non-existent register: %d\n",
+ subaddr);
+ return -EINVAL;
+ }
+
v4l_dbg(1, debug, chip->c, "%s: chip_write: reg%d=0x%x\n",
chip->c->name, subaddr, val);
chip->shadow.bytes[subaddr+1] = val;
@@ -180,12 +189,20 @@ static int chip_write(struct CHIPSTATE *chip, int subaddr, int val)
return 0;
}
-static int chip_write_masked(struct CHIPSTATE *chip, int subaddr, int val, int mask)
+static int chip_write_masked(struct CHIPSTATE *chip,
+ int subaddr, int val, int mask)
{
if (mask != 0) {
- if (-1 == subaddr) {
+ if (subaddr < 0) {
val = (chip->shadow.bytes[1] & ~mask) | (val & mask);
} else {
+ if (subaddr + 1 >= ARRAY_SIZE(chip->shadow.bytes)) {
+ v4l_info(chip->c,
+ "Tried to access a non-existent register: %d\n",
+ subaddr);
+ return -EINVAL;
+ }
+
val = (chip->shadow.bytes[subaddr+1] & ~mask) | (val & mask);
}
}
@@ -231,6 +248,15 @@ static int chip_cmd(struct CHIPSTATE *chip, char *name, audiocmd *cmd)
if (0 == cmd->count)
return 0;
+ if (cmd->count + cmd->bytes[0] - 1 >= ARRAY_SIZE(chip->shadow.bytes)) {
+ v4l_info(chip->c,
+ "Tried to access a non-existent register range: %d to %d\n",
+ cmd->bytes[0] + 1, cmd->bytes[0] + cmd->count - 1);
+ return -EINVAL;
+ }
+
+ /* FIXME: it seems that the shadow bytes are wrong bellow !*/
+
/* update our shadow register set; print bytes if (debug > 0) */
v4l_dbg(1, debug, chip->c, "%s: chip_cmd(%s): reg=%d, data:",
chip->c->name, name,cmd->bytes[0]);
@@ -266,7 +292,8 @@ static void chip_thread_wake(unsigned long data)
static int chip_thread(void *data)
{
struct CHIPSTATE *chip = data;
- struct CHIPDESC *desc = chiplist + chip->type;
+ struct CHIPDESC *desc = chip->desc;
+ int mode;
v4l_dbg(1, debug, chip->c, "%s: thread started\n", chip->c->name);
set_freezable();
@@ -285,7 +312,26 @@ static int chip_thread(void *data)
continue;
/* have a look what's going on */
- desc->checkmode(chip);
+ mode = desc->getmode(chip);
+ if (mode == chip->prevmode)
+ continue;
+
+ /* chip detected a new audio mode - set it */
+ v4l_dbg(1, debug, chip->c, "%s: thread checkmode\n",
+ chip->c->name);
+
+ chip->prevmode = mode;
+
+ if (mode & V4L2_TUNER_MODE_STEREO)
+ desc->setmode(chip, V4L2_TUNER_MODE_STEREO);
+ if (mode & V4L2_TUNER_MODE_LANG1_LANG2)
+ desc->setmode(chip, V4L2_TUNER_MODE_STEREO);
+ else if (mode & V4L2_TUNER_MODE_LANG1)
+ desc->setmode(chip, V4L2_TUNER_MODE_LANG1);
+ else if (mode & V4L2_TUNER_MODE_LANG2)
+ desc->setmode(chip, V4L2_TUNER_MODE_LANG2);
+ else
+ desc->setmode(chip, V4L2_TUNER_MODE_MONO);
/* schedule next check */
mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000));
@@ -295,29 +341,6 @@ static int chip_thread(void *data)
return 0;
}
-static void generic_checkmode(struct CHIPSTATE *chip)
-{
- struct CHIPDESC *desc = chiplist + chip->type;
- int mode = desc->getmode(chip);
-
- if (mode == chip->prevmode)
- return;
-
- v4l_dbg(1, debug, chip->c, "%s: thread checkmode\n", chip->c->name);
- chip->prevmode = mode;
-
- if (mode & V4L2_TUNER_MODE_STEREO)
- desc->setmode(chip,V4L2_TUNER_MODE_STEREO);
- if (mode & V4L2_TUNER_MODE_LANG1_LANG2)
- desc->setmode(chip,V4L2_TUNER_MODE_STEREO);
- else if (mode & V4L2_TUNER_MODE_LANG1)
- desc->setmode(chip,V4L2_TUNER_MODE_LANG1);
- else if (mode & V4L2_TUNER_MODE_LANG2)
- desc->setmode(chip,V4L2_TUNER_MODE_LANG2);
- else
- desc->setmode(chip,V4L2_TUNER_MODE_MONO);
-}
-
/* ---------------------------------------------------------------------- */
/* audio chip descriptions - defines+functions for tda9840 */
@@ -780,7 +803,7 @@ static struct tda9874a_MODES {
char *name;
audiocmd cmd;
} tda9874a_modelist[9] = {
- { "A2, B/G",
+ { "A2, B/G", /* default */
{ 9, { TDA9874A_C1FRA, 0x72,0x95,0x55, 0x77,0xA0,0x00, 0x00,0x00 }} },
{ "A2, M (Korea)",
{ 9, { TDA9874A_C1FRA, 0x5D,0xC0,0x00, 0x62,0x6A,0xAA, 0x20,0x22 }} },
@@ -794,7 +817,7 @@ static struct tda9874a_MODES {
{ 9, { TDA9874A_C1FRA, 0x7D,0x00,0x00, 0x88,0x8A,0xAA, 0x08,0x33 }} },
{ "NICAM, B/G",
{ 9, { TDA9874A_C1FRA, 0x72,0x95,0x55, 0x79,0xEA,0xAA, 0x08,0x33 }} },
- { "NICAM, D/K", /* default */
+ { "NICAM, D/K",
{ 9, { TDA9874A_C1FRA, 0x87,0x6A,0xAA, 0x79,0xEA,0xAA, 0x08,0x33 }} },
{ "NICAM, L",
{ 9, { TDA9874A_C1FRA, 0x87,0x6A,0xAA, 0x79,0xEA,0xAA, 0x09,0x33 }} }
@@ -989,7 +1012,7 @@ static int tda9874a_initialize(struct CHIPSTATE *chip)
{
if (tda9874a_SIF > 2)
tda9874a_SIF = 1;
- if (tda9874a_STD > 8)
+ if (tda9874a_STD >= ARRAY_SIZE(tda9874a_modelist))
tda9874a_STD = 0;
if(tda9874a_AMSEL > 1)
tda9874a_AMSEL = 0;
@@ -1097,7 +1120,7 @@ static int tda8425_shift12(int val) { return (val >> 12) | 0xf0; }
static int tda8425_initialize(struct CHIPSTATE *chip)
{
- struct CHIPDESC *desc = chiplist + chip->type;
+ struct CHIPDESC *desc = chip->desc;
int inputmap[4] = { /* tuner */ TDA8425_S1_CH2, /* radio */ TDA8425_S1_CH1,
/* extern */ TDA8425_S1_CH1, /* intern */ TDA8425_S1_OFF};
@@ -1267,27 +1290,28 @@ static struct CHIPDESC chiplist[] = {
.addr_lo = I2C_ADDR_TDA9840 >> 1,
.addr_hi = I2C_ADDR_TDA9840 >> 1,
.registers = 5,
+ .flags = CHIP_NEED_CHECKMODE,
+ /* callbacks */
.checkit = tda9840_checkit,
.getmode = tda9840_getmode,
.setmode = tda9840_setmode,
- .checkmode = generic_checkmode,
.init = { 2, { TDA9840_TEST, TDA9840_TEST_INT1SN
/* ,TDA9840_SW, TDA9840_MONO */} }
},
{
.name = "tda9873h",
- .checkit = tda9873_checkit,
.insmodopt = &tda9873,
.addr_lo = I2C_ADDR_TDA985x_L >> 1,
.addr_hi = I2C_ADDR_TDA985x_H >> 1,
.registers = 3,
- .flags = CHIP_HAS_INPUTSEL,
+ .flags = CHIP_HAS_INPUTSEL | CHIP_NEED_CHECKMODE,
+ /* callbacks */
+ .checkit = tda9873_checkit,
.getmode = tda9873_getmode,
.setmode = tda9873_setmode,
- .checkmode = generic_checkmode,
.init = { 4, { TDA9873_SW, 0xa4, 0x06, 0x03 } },
.inputreg = TDA9873_SW,
@@ -1298,15 +1322,16 @@ static struct CHIPDESC chiplist[] = {
},
{
.name = "tda9874h/a",
- .checkit = tda9874a_checkit,
- .initialize = tda9874a_initialize,
.insmodopt = &tda9874a,
.addr_lo = I2C_ADDR_TDA9874 >> 1,
.addr_hi = I2C_ADDR_TDA9874 >> 1,
+ .flags = CHIP_NEED_CHECKMODE,
+ /* callbacks */
+ .initialize = tda9874a_initialize,
+ .checkit = tda9874a_checkit,
.getmode = tda9874a_getmode,
.setmode = tda9874a_setmode,
- .checkmode = generic_checkmode,
},
{
.name = "tda9850",
@@ -1332,10 +1357,11 @@ static struct CHIPDESC chiplist[] = {
.rightreg = TDA9855_VR,
.bassreg = TDA9855_BA,
.treblereg = TDA9855_TR,
+
+ /* callbacks */
.volfunc = tda9855_volume,
.bassfunc = tda9855_bass,
.treblefunc = tda9855_treble,
-
.getmode = tda985x_getmode,
.setmode = tda985x_setmode,
@@ -1356,6 +1382,8 @@ static struct CHIPDESC chiplist[] = {
.rightreg = TEA6300_VL,
.bassreg = TEA6300_BA,
.treblereg = TEA6300_TR,
+
+ /* callbacks */
.volfunc = tea6300_shift10,
.bassfunc = tea6300_shift12,
.treblefunc = tea6300_shift12,
@@ -1366,7 +1394,6 @@ static struct CHIPDESC chiplist[] = {
},
{
.name = "tea6320",
- .initialize = tea6320_initialize,
.insmodopt = &tea6320,
.addr_lo = I2C_ADDR_TEA6300 >> 1,
.addr_hi = I2C_ADDR_TEA6300 >> 1,
@@ -1377,6 +1404,9 @@ static struct CHIPDESC chiplist[] = {
.rightreg = TEA6320_V,
.bassreg = TEA6320_BA,
.treblereg = TEA6320_TR,
+
+ /* callbacks */
+ .initialize = tea6320_initialize,
.volfunc = tea6320_volume,
.bassfunc = tea6320_shift11,
.treblefunc = tea6320_shift11,
@@ -1409,16 +1439,18 @@ static struct CHIPDESC chiplist[] = {
.rightreg = TDA8425_VR,
.bassreg = TDA8425_BA,
.treblereg = TDA8425_TR,
+
+ /* callbacks */
+ .initialize = tda8425_initialize,
.volfunc = tda8425_shift10,
.bassfunc = tda8425_shift12,
.treblefunc = tda8425_shift12,
+ .setmode = tda8425_setmode,
.inputreg = TDA8425_S1,
.inputmap = { TDA8425_S1_CH1, TDA8425_S1_CH1, TDA8425_S1_CH1 },
.inputmute = TDA8425_S1_OFF,
- .setmode = tda8425_setmode,
- .initialize = tda8425_initialize,
},
{
.name = "pic16c54 (PV951)",
@@ -1442,10 +1474,11 @@ static struct CHIPDESC chiplist[] = {
.addr_lo = I2C_ADDR_TDA9840 >> 1,
.addr_hi = I2C_ADDR_TDA9840 >> 1,
.registers = 2,
+ .flags = CHIP_NEED_CHECKMODE,
+ /* callbacks */
.getmode = ta8874z_getmode,
.setmode = ta8874z_setmode,
- .checkmode = generic_checkmode,
.init = {2, { TA8874Z_MONO_SET, TA8874Z_SEPARATION_DEFAULT}},
},
@@ -1489,6 +1522,7 @@ static int chip_probe(struct i2c_client *client, const struct i2c_device_id *id)
}
if (desc->name == NULL) {
v4l_dbg(1, debug, client, "no matching chip description found\n");
+ kfree(chip);
return -EIO;
}
v4l_info(client, "%s found @ 0x%x (%s)\n", desc->name, client->addr<<1, client->adapter->name);
@@ -1501,12 +1535,12 @@ static int chip_probe(struct i2c_client *client, const struct i2c_device_id *id)
/* fill required data structures */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
- strcpy(client->name, desc->name);
+ strlcpy(client->name, desc->name, I2C_NAME_SIZE);
#else
if (!id)
strlcpy(client->name, desc->name, I2C_NAME_SIZE);
#endif
- chip->type = desc-chiplist;
+ chip->desc = desc;
chip->shadow.count = desc->registers+1;
chip->prevmode = -1;
chip->audmode = V4L2_TUNER_MODE_LANG1;
@@ -1518,20 +1552,49 @@ static int chip_probe(struct i2c_client *client, const struct i2c_device_id *id)
chip_cmd(chip,"init",&desc->init);
if (desc->flags & CHIP_HAS_VOLUME) {
- chip->left = desc->leftinit ? desc->leftinit : 65535;
- chip->right = desc->rightinit ? desc->rightinit : 65535;
- chip_write(chip,desc->leftreg,desc->volfunc(chip->left));
- chip_write(chip,desc->rightreg,desc->volfunc(chip->right));
+ if (!desc->volfunc) {
+ /* This shouldn't be happen. Warn user, but keep working
+ without volume controls
+ */
+ v4l_info(chip->c, "volume callback undefined!\n");
+ desc->flags &= ~CHIP_HAS_VOLUME;
+ } else {
+ chip->left = desc->leftinit ? desc->leftinit : 65535;
+ chip->right = desc->rightinit ? desc->rightinit : 65535;
+ chip_write(chip, desc->leftreg,
+ desc->volfunc(chip->left));
+ chip_write(chip, desc->rightreg,
+ desc->volfunc(chip->right));
+ }
}
if (desc->flags & CHIP_HAS_BASSTREBLE) {
- chip->treble = desc->trebleinit ? desc->trebleinit : 32768;
- chip->bass = desc->bassinit ? desc->bassinit : 32768;
- chip_write(chip,desc->bassreg,desc->bassfunc(chip->bass));
- chip_write(chip,desc->treblereg,desc->treblefunc(chip->treble));
+ if (!desc->bassfunc || !desc->treblefunc) {
+ /* This shouldn't be happen. Warn user, but keep working
+ without bass/treble controls
+ */
+ v4l_info(chip->c, "bass/treble callbacks undefined!\n");
+ desc->flags &= ~CHIP_HAS_BASSTREBLE;
+ } else {
+ chip->treble = desc->trebleinit ?
+ desc->trebleinit : 32768;
+ chip->bass = desc->bassinit ?
+ desc->bassinit : 32768;
+ chip_write(chip, desc->bassreg,
+ desc->bassfunc(chip->bass));
+ chip_write(chip, desc->treblereg,
+ desc->treblefunc(chip->treble));
+ }
}
chip->thread = NULL;
- if (desc->checkmode) {
+ if (desc->flags & CHIP_NEED_CHECKMODE) {
+ if (!desc->getmode || !desc->setmode) {
+ /* This shouldn't be happen. Warn user, but keep working
+ without kthread
+ */
+ v4l_info(chip->c, "set/get mode callbacks undefined!\n");
+ return 0;
+ }
/* start async thread */
init_timer(&chip->wt);
chip->wt.function = chip_thread_wake;
@@ -1564,7 +1627,7 @@ static int chip_remove(struct i2c_client *client)
static int tvaudio_get_ctrl(struct CHIPSTATE *chip,
struct v4l2_control *ctrl)
{
- struct CHIPDESC *desc = chiplist + chip->type;
+ struct CHIPDESC *desc = chip->desc;
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -1588,13 +1651,13 @@ static int tvaudio_get_ctrl(struct CHIPSTATE *chip,
return 0;
}
case V4L2_CID_AUDIO_BASS:
- if (desc->flags & CHIP_HAS_BASSTREBLE)
+ if (!(desc->flags & CHIP_HAS_BASSTREBLE))
break;
ctrl->value = chip->bass;
return 0;
case V4L2_CID_AUDIO_TREBLE:
- if (desc->flags & CHIP_HAS_BASSTREBLE)
- return -EINVAL;
+ if (!(desc->flags & CHIP_HAS_BASSTREBLE))
+ break;
ctrl->value = chip->treble;
return 0;
}
@@ -1604,7 +1667,7 @@ static int tvaudio_get_ctrl(struct CHIPSTATE *chip,
static int tvaudio_set_ctrl(struct CHIPSTATE *chip,
struct v4l2_control *ctrl)
{
- struct CHIPDESC *desc = chiplist + chip->type;
+ struct CHIPDESC *desc = chip->desc;
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -1654,16 +1717,15 @@ static int tvaudio_set_ctrl(struct CHIPSTATE *chip,
return 0;
}
case V4L2_CID_AUDIO_BASS:
- if (desc->flags & CHIP_HAS_BASSTREBLE)
+ if (!(desc->flags & CHIP_HAS_BASSTREBLE))
break;
chip->bass = ctrl->value;
chip_write(chip,desc->bassreg,desc->bassfunc(chip->bass));
return 0;
case V4L2_CID_AUDIO_TREBLE:
- if (desc->flags & CHIP_HAS_BASSTREBLE)
- return -EINVAL;
-
+ if (!(desc->flags & CHIP_HAS_BASSTREBLE))
+ break;
chip->treble = ctrl->value;
chip_write(chip,desc->treblereg,desc->treblefunc(chip->treble));
@@ -1680,9 +1742,12 @@ static int chip_command(struct i2c_client *client,
unsigned int cmd, void *arg)
{
struct CHIPSTATE *chip = i2c_get_clientdata(client);
- struct CHIPDESC *desc = chiplist + chip->type;
+ struct CHIPDESC *desc = chip->desc;
- v4l_dbg(1, debug, chip->c, "%s: chip_command 0x%x\n", chip->c->name, cmd);
+ if (debug > 0) {
+ v4l_i2c_print_ioctl(chip->c, cmd);
+ printk("\n");
+ }
switch (cmd) {
case AUDC_SET_RADIO:
@@ -1707,7 +1772,7 @@ static int chip_command(struct i2c_client *client,
break;
case V4L2_CID_AUDIO_BASS:
case V4L2_CID_AUDIO_TREBLE:
- if (desc->flags & CHIP_HAS_BASSTREBLE)
+ if (!(desc->flags & CHIP_HAS_BASSTREBLE))
return -EINVAL;
break;
default:
@@ -1804,12 +1869,20 @@ static int chip_command(struct i2c_client *client,
break;
case VIDIOC_S_FREQUENCY:
chip->mode = 0; /* automatic */
- if (desc->checkmode && desc->setmode) {
+
+ /* For chips that provide getmode and setmode, and doesn't
+ automatically follows the stereo carrier, a kthread is
+ created to set the audio standard. In this case, when then
+ the video channel is changed, tvaudio starts on MONO mode.
+ After waiting for 2 seconds, the kernel thread is called,
+ to follow whatever audio standard is pointed by the
+ audio carrier.
+ */
+ if (chip->thread) {
desc->setmode(chip,V4L2_TUNER_MODE_MONO);
if (chip->prevmode != V4L2_TUNER_MODE_MONO)
chip->prevmode = -1; /* reset previous mode */
mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000));
- /* the thread will call checkmode() later */
}
break;
@@ -1852,9 +1925,3 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = {
.id_table = chip_id,
#endif
};
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/linux/drivers/media/video/tveeprom.c b/linux/drivers/media/video/tveeprom.c
index 5f088e669..c1809a56b 100644
--- a/linux/drivers/media/video/tveeprom.c
+++ b/linux/drivers/media/video/tveeprom.c
@@ -243,7 +243,7 @@ hauppauge_tuner[] =
{ TUNER_ABSENT, "TCL M2523_3DBH_E"},
{ TUNER_ABSENT, "TCL M2523_3DIH_E"},
{ TUNER_ABSENT, "TCL MFPE05_2_U"},
- { TUNER_PHILIPS_FMD1216ME_MK3, "Philips FMD1216MEX"},
+ { TUNER_PHILIPS_FMD1216MEX_MK3, "Philips FMD1216MEX"},
{ TUNER_ABSENT, "Philips FRH2036B"},
{ TUNER_ABSENT, "Panasonic ENGF75_01GF"},
{ TUNER_ABSENT, "MaxLinear MXL5005"},
diff --git a/linux/drivers/media/video/tvp5150.c b/linux/drivers/media/video/tvp5150.c
index 28c5c6761..ac8205d87 100644
--- a/linux/drivers/media/video/tvp5150.c
+++ b/linux/drivers/media/video/tvp5150.c
@@ -935,6 +935,21 @@ static int tvp5150_command(struct i2c_client *c,
int i;
fmt = arg;
+ /* raw vbi */
+ if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
+ /* this is for capturing 36 raw vbi lines
+ if there's a way to cut off the beginning 2 vbi lines
+ with the tvp5150 then the vbi line count could be lowered
+ to 17 lines/field again, although I couldn't find a register
+ which could do that cropping */
+ if (fmt->fmt.vbi.sample_format == V4L2_PIX_FMT_GREY)
+ tvp5150_write(c, TVP5150_LUMA_PROC_CTL_1, 0x70);
+ if (fmt->fmt.vbi.count[0] == 18 && fmt->fmt.vbi.count[1] == 18) {
+ tvp5150_write(c, TVP5150_VERT_BLANKING_START, 0x00);
+ tvp5150_write(c, TVP5150_VERT_BLANKING_STOP, 0x01);
+ }
+ break;
+ }
if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
return -EINVAL;
svbi = &fmt->fmt.sliced;
diff --git a/linux/drivers/media/video/usbvideo/ibmcam.c b/linux/drivers/media/video/usbvideo/ibmcam.c
index d202feac0..1119bcf58 100644
--- a/linux/drivers/media/video/usbvideo/ibmcam.c
+++ b/linux/drivers/media/video/usbvideo/ibmcam.c
@@ -3695,7 +3695,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id *
unsigned char video_ep = 0;
if (debug >= 1)
- dev_info(&uvd->dev->dev, "ibmcam_probe(%p,%u.)\n", intf, ifnum);
+ dev_info(&dev->dev, "ibmcam_probe(%p,%u.)\n", intf, ifnum);
/* We don't handle multi-config cameras */
if (dev->descriptor.bNumConfigurations != 1)
@@ -3746,7 +3746,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id *
brand = "IBM PC Camera"; /* a.k.a. Xirlink C-It */
break;
}
- dev_info(&uvd->dev->dev,
+ dev_info(&dev->dev,
"%s USB camera found (model %d, rev. 0x%04x)\n",
brand, model, le16_to_cpu(dev->descriptor.bcdDevice));
} while (0);
@@ -3754,7 +3754,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id *
/* Validate found interface: must have one ISO endpoint */
nas = intf->num_altsetting;
if (debug > 0)
- dev_info(&uvd->dev->dev, "Number of alternate settings=%d.\n",
+ dev_info(&dev->dev, "Number of alternate settings=%d.\n",
nas);
if (nas < 2) {
err("Too few alternate settings for this camera!");
@@ -3799,7 +3799,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id *
actInterface = i;
maxPS = le16_to_cpu(endpoint->wMaxPacketSize);
if (debug > 0)
- dev_info(&uvd->dev->dev,
+ dev_info(&dev->dev,
"Active setting=%d. "
"maxPS=%d.\n", i, maxPS);
} else
@@ -3840,7 +3840,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id *
RESTRICT_TO_RANGE(framerate, 0, 5);
break;
default:
- dev_info(&uvd->dev->dev, "IBM camera: using 320x240\n");
+ dev_info(&dev->dev, "IBM camera: using 320x240\n");
size = SIZE_320x240;
/* No break here */
case SIZE_320x240:
@@ -3869,7 +3869,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id *
canvasY = 120;
break;
default:
- dev_info(&uvd->dev->dev, "IBM NetCamera: using 176x144\n");
+ dev_info(&dev->dev, "IBM NetCamera: using 176x144\n");
size = SIZE_176x144;
/* No break here */
case SIZE_176x144:
diff --git a/linux/drivers/media/video/usbvideo/konicawc.c b/linux/drivers/media/video/usbvideo/konicawc.c
index 5c11ea64c..73abbb3f4 100644
--- a/linux/drivers/media/video/usbvideo/konicawc.c
+++ b/linux/drivers/media/video/usbvideo/konicawc.c
@@ -234,7 +234,8 @@ static void konicawc_register_input(struct konicawc *cam, struct usb_device *dev
cam->input = input_dev = input_allocate_device();
if (!input_dev) {
- warn("Not enough memory for camera's input device\n");
+ dev_warn(&dev->dev,
+ "Not enough memory for camera's input device\n");
return;
}
@@ -252,8 +253,9 @@ static void konicawc_register_input(struct konicawc *cam, struct usb_device *dev
error = input_register_device(cam->input);
if (error) {
- warn("Failed to register camera's input device, err: %d\n",
- error);
+ dev_warn(&dev->dev,
+ "Failed to register camera's input device, err: %d\n",
+ error);
input_free_device(cam->input);
cam->input = NULL;
}
diff --git a/linux/drivers/media/video/usbvideo/quickcam_messenger.c b/linux/drivers/media/video/usbvideo/quickcam_messenger.c
index 2f7274aba..d363e3d64 100644
--- a/linux/drivers/media/video/usbvideo/quickcam_messenger.c
+++ b/linux/drivers/media/video/usbvideo/quickcam_messenger.c
@@ -98,7 +98,7 @@ static void qcm_register_input(struct qcm *cam, struct usb_device *dev)
cam->input = input_dev = input_allocate_device();
if (!input_dev) {
- warn("insufficient mem for cam input device");
+ dev_warn(&dev->dev, "insufficient mem for cam input device\n");
return;
}
@@ -116,8 +116,9 @@ static void qcm_register_input(struct qcm *cam, struct usb_device *dev)
error = input_register_device(cam->input);
if (error) {
- warn("Failed to register camera's input device, err: %d\n",
- error);
+ dev_warn(&dev->dev,
+ "Failed to register camera's input device, err: %d\n",
+ error);
input_free_device(cam->input);
cam->input = NULL;
}
@@ -600,8 +601,9 @@ static int qcm_compress_iso(struct uvd *uvd, struct urb *dataurb)
dataurb->iso_frame_desc[i].offset;
if (st < 0) {
- warn("Data error: packet=%d. len=%d. status=%d.",
- i, n, st);
+ dev_warn(&uvd->dev->dev,
+ "Data error: packet=%d. len=%d. status=%d.\n",
+ i, n, st);
uvd->stats.iso_err_count++;
continue;
}
@@ -716,7 +718,7 @@ static void qcm_stop_data(struct uvd *uvd)
ret = qcm_camera_off(uvd);
if (ret)
- warn("couldn't turn the cam off.");
+ dev_warn(&uvd->dev->dev, "couldn't turn the cam off.\n");
uvd->streaming = 0;
diff --git a/linux/drivers/media/video/usbvideo/usbvideo.c b/linux/drivers/media/video/usbvideo/usbvideo.c
index c6d1e7dca..332929bb2 100644
--- a/linux/drivers/media/video/usbvideo/usbvideo.c
+++ b/linux/drivers/media/video/usbvideo/usbvideo.c
@@ -1059,7 +1059,7 @@ int usbvideo_RegisterVideoDevice(struct uvd *uvd)
dev_info(&uvd->dev->dev, "%s on /dev/video%d: canvas=%s videosize=%s\n",
(uvd->handle != NULL) ? uvd->handle->drvName : "???",
- uvd->vdev.minor, tmp2, tmp1);
+ uvd->vdev.num, tmp2, tmp1);
usb_get_dev(uvd->dev);
return 0;
@@ -1281,8 +1281,7 @@ static int usbvideo_v4l_close(struct inode *inode, struct file *file)
* History:
* 22-Jan-2000 Corrected VIDIOCSPICT to reject unsupported settings.
*/
-static int usbvideo_v4l_do_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, void *arg)
+static int usbvideo_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct uvd *uvd = file->private_data;
@@ -1505,7 +1504,7 @@ static int usbvideo_v4l_do_ioctl(struct inode *inode, struct file *file,
static int usbvideo_v4l_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- return video_usercopy(inode, file, cmd, arg, usbvideo_v4l_do_ioctl);
+ return video_usercopy(file, cmd, arg, usbvideo_v4l_do_ioctl);
}
/*
diff --git a/linux/drivers/media/video/usbvideo/vicam.c b/linux/drivers/media/video/usbvideo/vicam.c
index bad26ccf8..77032eaa7 100644
--- a/linux/drivers/media/video/usbvideo/vicam.c
+++ b/linux/drivers/media/video/usbvideo/vicam.c
@@ -1187,7 +1187,8 @@ vicam_probe( struct usb_interface *intf, const struct usb_device_id *id)
return -EIO;
}
- printk(KERN_INFO "ViCam webcam driver now controlling video device %d\n",cam->vdev.minor);
+ printk(KERN_INFO "ViCam webcam driver now controlling video device %d\n",
+ cam->vdev.num);
usb_set_intfdata (intf, cam);
diff --git a/linux/drivers/media/video/usbvision/usbvision-core.c b/linux/drivers/media/video/usbvision/usbvision-core.c
index d66cce1a5..33f37ac46 100644
--- a/linux/drivers/media/video/usbvision/usbvision-core.c
+++ b/linux/drivers/media/video/usbvision/usbvision-core.c
@@ -45,10 +45,6 @@
#include <linux/workqueue.h>
-#ifdef CONFIG_KMOD
-#include <linux/kmod.h>
-#endif
-
#include "usbvision.h"
static unsigned int core_debug;
diff --git a/linux/drivers/media/video/usbvision/usbvision-i2c.c b/linux/drivers/media/video/usbvision/usbvision-i2c.c
index d98eb913e..888051b80 100644
--- a/linux/drivers/media/video/usbvision/usbvision-i2c.c
+++ b/linux/drivers/media/video/usbvision/usbvision-i2c.c
@@ -237,7 +237,7 @@ int usbvision_i2c_register(struct usb_usbvision *usbvision)
sizeof(struct i2c_client));
sprintf(usbvision->i2c_adap.name + strlen(usbvision->i2c_adap.name),
- " #%d", usbvision->vdev->minor & 0x1f);
+ " #%d", usbvision->vdev->num);
PDEBUG(DBG_I2C,"Adaptername: %s", usbvision->i2c_adap.name);
usbvision->i2c_adap.dev.parent = &usbvision->dev->dev;
diff --git a/linux/drivers/media/video/usbvision/usbvision-video.c b/linux/drivers/media/video/usbvision/usbvision-video.c
index e10b256ae..48c8c4399 100644
--- a/linux/drivers/media/video/usbvision/usbvision-video.c
+++ b/linux/drivers/media/video/usbvision/usbvision-video.c
@@ -69,10 +69,6 @@
#include <linux/workqueue.h>
-#ifdef CONFIG_KMOD
-#include <linux/kmod.h>
-#endif
-
#include "usbvision.h"
#include "usbvision-cards.h"
@@ -527,7 +523,7 @@ static int vidioc_querycap (struct file *file, void *priv,
strlcpy(vc->card,
usbvision_device_data[usbvision->DevModel].ModelString,
sizeof(vc->card));
- strlcpy(vc->bus_info, usbvision->dev->dev.bus_id,
+ strlcpy(vc->bus_info, dev_name(&usbvision->dev->dev),
sizeof(vc->bus_info));
vc->version = USBVISION_DRIVER_VERSION;
vc->capabilities = V4L2_CAP_VIDEO_CAPTURE |
@@ -1282,7 +1278,7 @@ static int usbvision_vbi_close(struct inode *inode, struct file *file)
return -ENODEV;
}
-static int usbvision_do_vbi_ioctl(struct inode *inode, struct file *file,
+static int usbvision_do_vbi_ioctl(struct file *file,
unsigned int cmd, void *arg)
{
/* TODO */
@@ -1292,7 +1288,7 @@ static int usbvision_do_vbi_ioctl(struct inode *inode, struct file *file,
static int usbvision_vbi_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- return video_usercopy(inode, file, cmd, arg, usbvision_do_vbi_ioctl);
+ return video_usercopy(file, cmd, arg, usbvision_do_vbi_ioctl);
}
@@ -1444,7 +1440,7 @@ static void usbvision_unregister_video(struct usb_usbvision *usbvision)
// vbi Device:
if (usbvision->vbi) {
PDEBUG(DBG_PROBE, "unregister /dev/vbi%d [v4l2]",
- usbvision->vbi->minor & 0x1f);
+ usbvision->vbi->num);
if (usbvision->vbi->minor != -1) {
video_unregister_device(usbvision->vbi);
} else {
@@ -1456,7 +1452,7 @@ static void usbvision_unregister_video(struct usb_usbvision *usbvision)
// Radio Device:
if (usbvision->rdev) {
PDEBUG(DBG_PROBE, "unregister /dev/radio%d [v4l2]",
- usbvision->rdev->minor & 0x1f);
+ usbvision->rdev->num);
if (usbvision->rdev->minor != -1) {
video_unregister_device(usbvision->rdev);
} else {
@@ -1468,7 +1464,7 @@ static void usbvision_unregister_video(struct usb_usbvision *usbvision)
// Video Device:
if (usbvision->vdev) {
PDEBUG(DBG_PROBE, "unregister /dev/video%d [v4l2]",
- usbvision->vdev->minor & 0x1f);
+ usbvision->vdev->num);
if (usbvision->vdev->minor != -1) {
video_unregister_device(usbvision->vdev);
} else {
@@ -1494,7 +1490,7 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision)
goto err_exit;
}
printk(KERN_INFO "USBVision[%d]: registered USBVision Video device /dev/video%d [v4l2]\n",
- usbvision->nr,usbvision->vdev->minor & 0x1f);
+ usbvision->nr, usbvision->vdev->num);
// Radio Device:
if (usbvision_device_data[usbvision->DevModel].Radio) {
@@ -1511,7 +1507,7 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision)
goto err_exit;
}
printk(KERN_INFO "USBVision[%d]: registered USBVision Radio device /dev/radio%d [v4l2]\n",
- usbvision->nr, usbvision->rdev->minor & 0x1f);
+ usbvision->nr, usbvision->rdev->num);
}
// vbi Device:
if (usbvision_device_data[usbvision->DevModel].vbi) {
@@ -1527,7 +1523,7 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision)
goto err_exit;
}
printk(KERN_INFO "USBVision[%d]: registered USBVision VBI device /dev/vbi%d [v4l2] (Not Working Yet!)\n",
- usbvision->nr,usbvision->vbi->minor & 0x1f);
+ usbvision->nr, usbvision->vbi->num);
}
// all done
return 0;
diff --git a/linux/drivers/media/video/uvc/uvc_ctrl.c b/linux/drivers/media/video/uvc/uvc_ctrl.c
index f16aafe9c..9de8a1db5 100644
--- a/linux/drivers/media/video/uvc/uvc_ctrl.c
+++ b/linux/drivers/media/video/uvc/uvc_ctrl.c
@@ -15,7 +15,9 @@
#include <linux/version.h>
#include <linux/list.h>
#include <linux/module.h>
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)
#include <linux/uaccess.h>
+#endif
#include <linux/usb.h>
#include <linux/videodev2.h>
#include <linux/vmalloc.h>
diff --git a/linux/drivers/media/video/uvc/uvc_driver.c b/linux/drivers/media/video/uvc/uvc_driver.c
index cbe9d0452..046b98871 100644
--- a/linux/drivers/media/video/uvc/uvc_driver.c
+++ b/linux/drivers/media/video/uvc/uvc_driver.c
@@ -288,8 +288,10 @@ static int uvc_parse_format(struct uvc_device *dev,
struct uvc_format_desc *fmtdesc;
struct uvc_frame *frame;
const unsigned char *start = buffer;
+ unsigned char *_buffer;
unsigned int interval;
unsigned int i, n;
+ int _buflen;
__u8 ftype;
format->type = buffer[2];
@@ -410,12 +412,20 @@ static int uvc_parse_format(struct uvc_device *dev,
buflen -= buffer[0];
buffer += buffer[0];
+ /* Count the number of frame descriptors to test the bFrameIndex
+ * field when parsing the descriptors. We can't rely on the
+ * bNumFrameDescriptors field as some cameras don't initialize it
+ * properly.
+ */
+ for (_buflen = buflen, _buffer = buffer;
+ _buflen > 2 && _buffer[2] == ftype;
+ _buflen -= _buffer[0], _buffer += _buffer[0])
+ format->nframes++;
+
/* Parse the frame descriptors. Only uncompressed, MJPEG and frame
* based formats have frame descriptors.
*/
while (buflen > 2 && buffer[2] == ftype) {
- frame = &format->frame[format->nframes];
-
if (ftype != VS_FRAME_FRAME_BASED)
n = buflen > 25 ? buffer[25] : 0;
else
@@ -430,6 +440,16 @@ static int uvc_parse_format(struct uvc_device *dev,
return -EINVAL;
}
+ if (buffer[3] - 1 >= format->nframes) {
+ uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming"
+ "interface %d frame index %u out of range\n",
+ dev->udev->devnum, alts->desc.bInterfaceNumber,
+ buffer[3]);
+ return -EINVAL;
+ }
+
+ frame = &format->frame[buffer[3] - 1];
+
frame->bFrameIndex = buffer[3];
frame->bmCapabilities = buffer[4];
frame->wWidth = le16_to_cpup((__le16 *)&buffer[5]);
@@ -486,7 +506,6 @@ static int uvc_parse_format(struct uvc_device *dev,
10000000/frame->dwDefaultFrameInterval,
(100000000/frame->dwDefaultFrameInterval)%10);
- format->nframes++;
buflen -= buffer[0];
buffer += buffer[0];
}
@@ -1709,24 +1728,6 @@ static int uvc_reset_resume(struct usb_interface *intf)
* though they are compliant.
*/
static struct usb_device_id uvc_ids[] = {
- /* ALi M5606 (Clevo M540SR) */
- { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
- | USB_DEVICE_ID_MATCH_INT_INFO,
- .idVendor = 0x0402,
- .idProduct = 0x5606,
- .bInterfaceClass = USB_CLASS_VIDEO,
- .bInterfaceSubClass = 1,
- .bInterfaceProtocol = 0,
- .driver_info = UVC_QUIRK_PROBE_MINMAX },
- /* Creative Live! Optia */
- { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
- | USB_DEVICE_ID_MATCH_INT_INFO,
- .idVendor = 0x041e,
- .idProduct = 0x4057,
- .bInterfaceClass = USB_CLASS_VIDEO,
- .bInterfaceSubClass = 1,
- .bInterfaceProtocol = 0,
- .driver_info = UVC_QUIRK_PROBE_MINMAX },
/* Microsoft Lifecam NX-6000 */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
@@ -1812,15 +1813,6 @@ static struct usb_device_id uvc_ids[] = {
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
.driver_info = UVC_QUIRK_STREAM_NO_FID },
- /* Silicon Motion SM371 */
- { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
- | USB_DEVICE_ID_MATCH_INT_INFO,
- .idVendor = 0x090c,
- .idProduct = 0xb371,
- .bInterfaceClass = USB_CLASS_VIDEO,
- .bInterfaceSubClass = 1,
- .bInterfaceProtocol = 0,
- .driver_info = UVC_QUIRK_PROBE_MINMAX },
/* MT6227 */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
@@ -1839,6 +1831,15 @@ static struct usb_device_id uvc_ids[] = {
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
.driver_info = UVC_QUIRK_STREAM_NO_FID },
+ /* Syntek (Samsung Q310) */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x174f,
+ .idProduct = 0x5931,
+ .bInterfaceClass = USB_CLASS_VIDEO,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 0,
+ .driver_info = UVC_QUIRK_STREAM_NO_FID },
/* Asus F9SG */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
@@ -1857,6 +1858,15 @@ static struct usb_device_id uvc_ids[] = {
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
.driver_info = UVC_QUIRK_STREAM_NO_FID },
+ /* Lenovo Thinkpad SL500 */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x17ef,
+ .idProduct = 0x480b,
+ .bInterfaceClass = USB_CLASS_VIDEO,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 0,
+ .driver_info = UVC_QUIRK_STREAM_NO_FID },
/* Ecamm Pico iMage */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
@@ -1887,105 +1897,6 @@ static struct usb_device_id uvc_ids[] = {
.bInterfaceProtocol = 0,
.driver_info = UVC_QUIRK_PROBE_MINMAX
| UVC_QUIRK_IGNORE_SELECTOR_UNIT},
- /* Acer OEM Webcam - Unknown vendor */
- { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
- | USB_DEVICE_ID_MATCH_INT_INFO,
- .idVendor = 0x5986,
- .idProduct = 0x0100,
- .bInterfaceClass = USB_CLASS_VIDEO,
- .bInterfaceSubClass = 1,
- .bInterfaceProtocol = 0,
- .driver_info = UVC_QUIRK_PROBE_MINMAX },
- /* Packard Bell OEM Webcam - Bison Electronics */
- { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
- | USB_DEVICE_ID_MATCH_INT_INFO,
- .idVendor = 0x5986,
- .idProduct = 0x0101,
- .bInterfaceClass = USB_CLASS_VIDEO,
- .bInterfaceSubClass = 1,
- .bInterfaceProtocol = 0,
- .driver_info = UVC_QUIRK_PROBE_MINMAX },
- /* Acer Crystal Eye webcam - Bison Electronics */
- { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
- | USB_DEVICE_ID_MATCH_INT_INFO,
- .idVendor = 0x5986,
- .idProduct = 0x0102,
- .bInterfaceClass = USB_CLASS_VIDEO,
- .bInterfaceSubClass = 1,
- .bInterfaceProtocol = 0,
- .driver_info = UVC_QUIRK_PROBE_MINMAX },
- /* Compaq Presario B1200 - Bison Electronics */
- { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
- | USB_DEVICE_ID_MATCH_INT_INFO,
- .idVendor = 0x5986,
- .idProduct = 0x0104,
- .bInterfaceClass = USB_CLASS_VIDEO,
- .bInterfaceSubClass = 1,
- .bInterfaceProtocol = 0,
- .driver_info = UVC_QUIRK_PROBE_MINMAX },
- /* Acer Travelmate 7720 - Bison Electronics */
- { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
- | USB_DEVICE_ID_MATCH_INT_INFO,
- .idVendor = 0x5986,
- .idProduct = 0x0105,
- .bInterfaceClass = USB_CLASS_VIDEO,
- .bInterfaceSubClass = 1,
- .bInterfaceProtocol = 0,
- .driver_info = UVC_QUIRK_PROBE_MINMAX },
- /* Medion Akoya Mini E1210 - Bison Electronics */
- { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
- | USB_DEVICE_ID_MATCH_INT_INFO,
- .idVendor = 0x5986,
- .idProduct = 0x0141,
- .bInterfaceClass = USB_CLASS_VIDEO,
- .bInterfaceSubClass = 1,
- .bInterfaceProtocol = 0,
- .driver_info = UVC_QUIRK_PROBE_MINMAX },
- /* Acer OrbiCam - Bison Electronics */
- { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
- | USB_DEVICE_ID_MATCH_INT_INFO,
- .idVendor = 0x5986,
- .idProduct = 0x0200,
- .bInterfaceClass = USB_CLASS_VIDEO,
- .bInterfaceSubClass = 1,
- .bInterfaceProtocol = 0,
- .driver_info = UVC_QUIRK_PROBE_MINMAX },
- /* Fujitsu Amilo SI2636 - Bison Electronics */
- { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
- | USB_DEVICE_ID_MATCH_INT_INFO,
- .idVendor = 0x5986,
- .idProduct = 0x0202,
- .bInterfaceClass = USB_CLASS_VIDEO,
- .bInterfaceSubClass = 1,
- .bInterfaceProtocol = 0,
- .driver_info = UVC_QUIRK_PROBE_MINMAX },
- /* Advent 4211 - Bison Electronics */
- { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
- | USB_DEVICE_ID_MATCH_INT_INFO,
- .idVendor = 0x5986,
- .idProduct = 0x0203,
- .bInterfaceClass = USB_CLASS_VIDEO,
- .bInterfaceSubClass = 1,
- .bInterfaceProtocol = 0,
- .driver_info = UVC_QUIRK_PROBE_MINMAX },
- /* Bison Electronics */
- { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
- | USB_DEVICE_ID_MATCH_INT_INFO,
- .idVendor = 0x5986,
- .idProduct = 0x0300,
- .bInterfaceClass = USB_CLASS_VIDEO,
- .bInterfaceSubClass = 1,
- .bInterfaceProtocol = 0,
- .driver_info = UVC_QUIRK_PROBE_MINMAX },
- /* Clevo M570TU - Bison Electronics */
- { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
- | USB_DEVICE_ID_MATCH_INT_INFO,
- .idVendor = 0x5986,
- .idProduct = 0x0303,
- .bInterfaceClass = USB_CLASS_VIDEO,
- .bInterfaceSubClass = 1,
- .bInterfaceProtocol = 0,
- .driver_info = UVC_QUIRK_PROBE_MINMAX },
/* Generic USB Video Class */
{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) },
{}
@@ -2004,7 +1915,9 @@ struct uvc_driver uvc_driver = {
.reset_resume = uvc_reset_resume,
#endif
.id_table = uvc_ids,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
.supports_autosuspend = 1,
+#endif
},
};
diff --git a/linux/drivers/media/video/uvc/uvc_status.c b/linux/drivers/media/video/uvc/uvc_status.c
index 5d60b264d..ab62d7bf9 100644
--- a/linux/drivers/media/video/uvc/uvc_status.c
+++ b/linux/drivers/media/video/uvc/uvc_status.c
@@ -15,7 +15,11 @@
#include <linux/version.h>
#include <linux/input.h>
#include <linux/usb.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
+#include <linux/usb_input.h>
+#else
#include <linux/usb/input.h>
+#endif
#include "uvcvideo.h"
@@ -45,7 +49,11 @@ static int uvc_input_init(struct uvc_device *dev)
input->name = dev->name;
input->phys = phys;
usb_to_input_id(udev, &input->id);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
input->dev.parent = &dev->intf->dev;
+#else
+ input->cdev.dev = &dev->intf->dev;
+#endif
set_bit(EV_KEY, input->evbit);
set_bit(BTN_0, input->keybit);
@@ -118,7 +126,11 @@ static void uvc_event_control(struct uvc_device *dev, __u8 *data, int len)
data[1], data[3], attrs[data[4]], len);
}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+static void uvc_status_complete(struct urb *urb, struct pt_regs *regs)
+#else
static void uvc_status_complete(struct urb *urb)
+#endif
{
struct uvc_device *dev = urb->context;
int len, ret;
diff --git a/linux/drivers/media/video/uvc/uvc_v4l2.c b/linux/drivers/media/video/uvc/uvc_v4l2.c
index 78e4c4e09..5588698e2 100644
--- a/linux/drivers/media/video/uvc/uvc_v4l2.c
+++ b/linux/drivers/media/video/uvc/uvc_v4l2.c
@@ -252,7 +252,7 @@ static int uvc_v4l2_set_format(struct uvc_video_device *video,
if (ret < 0)
return ret;
- if ((ret = uvc_set_video_ctrl(video, &probe, 0)) < 0)
+ if ((ret = uvc_commit_video(video, &probe)) < 0)
return ret;
memcpy(&video->streaming->ctrl, &probe, sizeof probe);
@@ -316,7 +316,7 @@ static int uvc_v4l2_set_streamparm(struct uvc_video_device *video,
return ret;
/* Commit the new settings. */
- if ((ret = uvc_set_video_ctrl(video, &probe, 0)) < 0)
+ if ((ret = uvc_commit_video(video, &probe)) < 0)
return ret;
memcpy(&video->streaming->ctrl, &probe, sizeof probe);
@@ -413,14 +413,18 @@ static int uvc_v4l2_open(struct inode *inode, struct file *file)
goto done;
}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
ret = usb_autopm_get_interface(video->dev->intf);
if (ret < 0)
goto done;
+#endif
/* Create the device handle. */
handle = kzalloc(sizeof *handle, GFP_KERNEL);
if (handle == NULL) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
usb_autopm_put_interface(video->dev->intf);
+#endif
ret = -ENOMEM;
goto done;
}
@@ -459,13 +463,14 @@ static int uvc_v4l2_release(struct inode *inode, struct file *file)
kfree(handle);
file->private_data = NULL;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
usb_autopm_put_interface(video->dev->intf);
+#endif
kref_put(&video->dev->kref, uvc_delete);
return 0;
}
-static int uvc_v4l2_do_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, void *arg)
+static int uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct video_device *vdev = video_devdata(file);
struct uvc_video_device *video = video_get_drvdata(vdev);
@@ -978,7 +983,7 @@ static int uvc_v4l2_do_ioctl(struct inode *inode, struct file *file,
return uvc_xu_ctrl_query(video, arg, 1);
default:
- if ((ret = v4l_compat_translate_ioctl(inode, file, cmd, arg,
+ if ((ret = v4l_compat_translate_ioctl(file, cmd, arg,
uvc_v4l2_do_ioctl)) == -ENOIOCTLCMD)
uvc_trace(UVC_TRACE_IOCTL, "Unknown ioctl 0x%08x\n",
cmd);
@@ -992,7 +997,7 @@ static int uvc_v4l2_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_ioctl\n");
- return video_usercopy(inode, file, cmd, arg, uvc_v4l2_do_ioctl);
+ return video_usercopy(file, cmd, arg, uvc_v4l2_do_ioctl);
}
static ssize_t uvc_v4l2_read(struct file *file, char __user *data,
diff --git a/linux/drivers/media/video/uvc/uvc_video.c b/linux/drivers/media/video/uvc/uvc_video.c
index b7bb23820..987e110fe 100644
--- a/linux/drivers/media/video/uvc/uvc_video.c
+++ b/linux/drivers/media/video/uvc/uvc_video.c
@@ -36,15 +36,22 @@ static int __uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit,
{
__u8 type = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
unsigned int pipe;
- int ret;
pipe = (query & 0x80) ? usb_rcvctrlpipe(dev->udev, 0)
: usb_sndctrlpipe(dev->udev, 0);
type |= (query & 0x80) ? USB_DIR_IN : USB_DIR_OUT;
- ret = usb_control_msg(dev->udev, pipe, query, type, cs << 8,
+ return usb_control_msg(dev->udev, pipe, query, type, cs << 8,
unit << 8 | intfnum, data, size, timeout);
+}
+
+int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit,
+ __u8 intfnum, __u8 cs, void *data, __u16 size)
+{
+ int ret;
+ ret = __uvc_query_ctrl(dev, query, unit, intfnum, cs, data, size,
+ UVC_CTRL_CONTROL_TIMEOUT);
if (ret != size) {
uvc_printk(KERN_ERR, "Failed to query (%u) UVC control %u "
"(unit %u) : %d (exp. %u).\n", query, cs, unit, ret,
@@ -55,13 +62,6 @@ static int __uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit,
return 0;
}
-int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit,
- __u8 intfnum, __u8 cs, void *data, __u16 size)
-{
- return __uvc_query_ctrl(dev, query, unit, intfnum, cs, data, size,
- UVC_CTRL_CONTROL_TIMEOUT);
-}
-
static void uvc_fixup_buffer_size(struct uvc_video_device *video,
struct uvc_streaming_control *ctrl)
{
@@ -102,8 +102,36 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video,
ret = __uvc_query_ctrl(video->dev, query, 0, video->streaming->intfnum,
probe ? VS_PROBE_CONTROL : VS_COMMIT_CONTROL, data, size,
UVC_CTRL_STREAMING_TIMEOUT);
- if (ret < 0)
+
+ if ((query == GET_MIN || query == GET_MAX) && ret == 2) {
+ /* Some cameras, mostly based on Bison Electronics chipsets,
+ * answer a GET_MIN or GET_MAX request with the wCompQuality
+ * field only.
+ */
+ uvc_warn_once(video->dev, UVC_WARN_MINMAX, "UVC non "
+ "compliance - GET_MIN/MAX(PROBE) incorrectly "
+ "supported. Enabling workaround.\n");
+ memset(ctrl, 0, sizeof ctrl);
+ ctrl->wCompQuality = le16_to_cpup((__le16 *)data);
+ ret = 0;
goto out;
+ } else if (query == GET_DEF && probe == 1) {
+ /* Many cameras don't support the GET_DEF request on their
+ * video probe control. Warn once and return, the caller will
+ * fall back to GET_CUR.
+ */
+ uvc_warn_once(video->dev, UVC_WARN_PROBE_DEF, "UVC non "
+ "compliance - GET_DEF(PROBE) not supported. "
+ "Enabling workaround.\n");
+ ret = -EIO;
+ goto out;
+ } else if (ret != size) {
+ uvc_printk(KERN_ERR, "Failed to query (%u) UVC %s control : "
+ "%d (exp. %u).\n", query, probe ? "probe" : "commit",
+ ret, size);
+ ret = -EIO;
+ goto out;
+ }
ctrl->bmHint = le16_to_cpup((__le16 *)&data[0]);
ctrl->bFormatIndex = data[2];
@@ -138,13 +166,14 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video,
* Try to get the value from the format and frame descriptor.
*/
uvc_fixup_buffer_size(video, ctrl);
+ ret = 0;
out:
kfree(data);
return ret;
}
-int uvc_set_video_ctrl(struct uvc_video_device *video,
+static int uvc_set_video_ctrl(struct uvc_video_device *video,
struct uvc_streaming_control *ctrl, int probe)
{
__u8 *data;
@@ -186,6 +215,12 @@ int uvc_set_video_ctrl(struct uvc_video_device *video,
video->streaming->intfnum,
probe ? VS_PROBE_CONTROL : VS_COMMIT_CONTROL, data, size,
UVC_CTRL_STREAMING_TIMEOUT);
+ if (ret != size) {
+ uvc_printk(KERN_ERR, "Failed to set UVC %s control : "
+ "%d (exp. %u).\n", probe ? "probe" : "commit",
+ ret, size);
+ ret = -EIO;
+ }
kfree(data);
return ret;
@@ -252,6 +287,12 @@ done:
return ret;
}
+int uvc_commit_video(struct uvc_video_device *video,
+ struct uvc_streaming_control *probe)
+{
+ return uvc_set_video_ctrl(video, probe, 0);
+}
+
/* ------------------------------------------------------------------------
* Video codecs
*/
@@ -525,7 +566,11 @@ static void uvc_video_decode_bulk(struct urb *urb,
}
}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+static void uvc_video_complete(struct urb *urb, struct pt_regs *regs)
+#else
static void uvc_video_complete(struct urb *urb)
+#endif
{
struct uvc_video_device *video = urb->context;
struct uvc_video_queue *queue = &video->queue;
diff --git a/linux/drivers/media/video/uvc/uvcvideo.h b/linux/drivers/media/video/uvc/uvcvideo.h
index 9a6bc1aaf..f95040380 100644
--- a/linux/drivers/media/video/uvc/uvcvideo.h
+++ b/linux/drivers/media/video/uvc/uvcvideo.h
@@ -4,6 +4,7 @@
#include <linux/kernel.h>
#include <linux/videodev2.h>
+#include "compat.h"
/*
* Dynamic controls
@@ -617,6 +618,7 @@ enum uvc_device_state {
struct uvc_device {
struct usb_device *udev;
struct usb_interface *intf;
+ unsigned long warnings;
__u32 quirks;
int intfnum;
char name[32];
@@ -679,6 +681,9 @@ struct uvc_driver {
#define UVC_TRACE_SUSPEND (1 << 8)
#define UVC_TRACE_STATUS (1 << 9)
+#define UVC_WARN_MINMAX 0
+#define UVC_WARN_PROBE_DEF 1
+
extern unsigned int uvc_trace_param;
#define uvc_trace(flag, msg...) \
@@ -687,6 +692,12 @@ extern unsigned int uvc_trace_param;
printk(KERN_DEBUG "uvcvideo: " msg); \
} while (0)
+#define uvc_warn_once(dev, warn, msg...) \
+ do { \
+ if (!test_and_set_bit(warn, &dev->warnings)) \
+ printk(KERN_INFO "uvcvideo: " msg); \
+ } while (0)
+
#define uvc_printk(level, msg...) \
printk(level "uvcvideo: " msg)
@@ -740,10 +751,10 @@ extern int uvc_video_resume(struct uvc_video_device *video);
extern int uvc_video_enable(struct uvc_video_device *video, int enable);
extern int uvc_probe_video(struct uvc_video_device *video,
struct uvc_streaming_control *probe);
+extern int uvc_commit_video(struct uvc_video_device *video,
+ struct uvc_streaming_control *ctrl);
extern int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit,
__u8 intfnum, __u8 cs, void *data, __u16 size);
-extern int uvc_set_video_ctrl(struct uvc_video_device *video,
- struct uvc_streaming_control *ctrl, int probe);
/* Status */
extern int uvc_status_init(struct uvc_device *dev);
diff --git a/linux/drivers/media/video/v4l1-compat.c b/linux/drivers/media/video/v4l1-compat.c
index 5d8a65aa5..ff1d3eb68 100644
--- a/linux/drivers/media/video/v4l1-compat.c
+++ b/linux/drivers/media/video/v4l1-compat.c
@@ -35,10 +35,6 @@
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/pgtable.h>
-
-#ifdef CONFIG_KMOD
-#include <linux/kmod.h>
-#endif
#include "compat.h"
static unsigned int debug;
@@ -62,8 +58,7 @@ MODULE_LICENSE("GPL");
*/
static int
-get_v4l_control(struct inode *inode,
- struct file *file,
+get_v4l_control(struct file *file,
int cid,
v4l2_kioctl drv)
{
@@ -72,12 +67,12 @@ get_v4l_control(struct inode *inode,
int err;
qctrl2.id = cid;
- err = drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2);
+ err = drv(file, VIDIOC_QUERYCTRL, &qctrl2);
if (err < 0)
dprintk("VIDIOC_QUERYCTRL: %d\n", err);
if (err == 0 && !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED)) {
ctrl2.id = qctrl2.id;
- err = drv(inode, file, VIDIOC_G_CTRL, &ctrl2);
+ err = drv(file, VIDIOC_G_CTRL, &ctrl2);
if (err < 0) {
dprintk("VIDIOC_G_CTRL: %d\n", err);
return 0;
@@ -90,8 +85,7 @@ get_v4l_control(struct inode *inode,
}
static int
-set_v4l_control(struct inode *inode,
- struct file *file,
+set_v4l_control(struct file *file,
int cid,
int value,
v4l2_kioctl drv)
@@ -101,7 +95,7 @@ set_v4l_control(struct inode *inode,
int err;
qctrl2.id = cid;
- err = drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2);
+ err = drv(file, VIDIOC_QUERYCTRL, &qctrl2);
if (err < 0)
dprintk("VIDIOC_QUERYCTRL: %d\n", err);
if (err == 0 &&
@@ -119,7 +113,7 @@ set_v4l_control(struct inode *inode,
+ 32767)
/ 65535;
ctrl2.value += qctrl2.minimum;
- err = drv(inode, file, VIDIOC_S_CTRL, &ctrl2);
+ err = drv(file, VIDIOC_S_CTRL, &ctrl2);
if (err < 0)
dprintk("VIDIOC_S_CTRL: %d\n", err);
}
@@ -227,7 +221,6 @@ static int poll_one(struct file *file, struct poll_wqueues *pwq)
}
static int count_inputs(
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -237,14 +230,13 @@ static int count_inputs(
for (i = 0;; i++) {
memset(&input2, 0, sizeof(input2));
input2.index = i;
- if (0 != drv(inode, file, VIDIOC_ENUMINPUT, &input2))
+ if (0 != drv(file, VIDIOC_ENUMINPUT, &input2))
break;
}
return i;
}
static int check_size(
- struct inode *inode,
struct file *file,
v4l2_kioctl drv,
int *maxw,
@@ -257,14 +249,14 @@ static int check_size(
memset(&fmt2, 0, sizeof(fmt2));
desc2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- if (0 != drv(inode, file, VIDIOC_ENUM_FMT, &desc2))
+ if (0 != drv(file, VIDIOC_ENUM_FMT, &desc2))
goto done;
fmt2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt2.fmt.pix.width = 10000;
fmt2.fmt.pix.height = 10000;
fmt2.fmt.pix.pixelformat = desc2.pixelformat;
- if (0 != drv(inode, file, VIDIOC_TRY_FMT, &fmt2))
+ if (0 != drv(file, VIDIOC_TRY_FMT, &fmt2))
goto done;
*maxw = fmt2.fmt.pix.width;
@@ -278,7 +270,6 @@ done:
static noinline int v4l1_compat_get_capabilities(
struct video_capability *cap,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -294,13 +285,13 @@ static noinline int v4l1_compat_get_capabilities(
memset(cap, 0, sizeof(*cap));
memset(&fbuf, 0, sizeof(fbuf));
- err = drv(inode, file, VIDIOC_QUERYCAP, cap2);
+ err = drv(file, VIDIOC_QUERYCAP, cap2);
if (err < 0) {
dprintk("VIDIOCGCAP / VIDIOC_QUERYCAP: %d\n", err);
goto done;
}
if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY) {
- err = drv(inode, file, VIDIOC_G_FBUF, &fbuf);
+ err = drv(file, VIDIOC_G_FBUF, &fbuf);
if (err < 0) {
dprintk("VIDIOCGCAP / VIDIOC_G_FBUF: %d\n", err);
memset(&fbuf, 0, sizeof(fbuf));
@@ -322,8 +313,8 @@ static noinline int v4l1_compat_get_capabilities(
if (fbuf.capability & V4L2_FBUF_CAP_LIST_CLIPPING)
cap->type |= VID_TYPE_CLIPPING;
- cap->channels = count_inputs(inode, file, drv);
- check_size(inode, file, drv,
+ cap->channels = count_inputs(file, drv);
+ check_size(file, drv,
&cap->maxwidth, &cap->maxheight);
cap->audios = 0; /* FIXME */
cap->minwidth = 48; /* FIXME */
@@ -336,7 +327,6 @@ done:
static noinline int v4l1_compat_get_frame_buffer(
struct video_buffer *buffer,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -346,7 +336,7 @@ static noinline int v4l1_compat_get_frame_buffer(
memset(buffer, 0, sizeof(*buffer));
memset(&fbuf, 0, sizeof(fbuf));
- err = drv(inode, file, VIDIOC_G_FBUF, &fbuf);
+ err = drv(file, VIDIOC_G_FBUF, &fbuf);
if (err < 0) {
dprintk("VIDIOCGFBUF / VIDIOC_G_FBUF: %d\n", err);
goto done;
@@ -391,7 +381,6 @@ done:
static noinline int v4l1_compat_set_frame_buffer(
struct video_buffer *buffer,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -420,7 +409,7 @@ static noinline int v4l1_compat_set_frame_buffer(
break;
}
fbuf.fmt.bytesperline = buffer->bytesperline;
- err = drv(inode, file, VIDIOC_S_FBUF, &fbuf);
+ err = drv(file, VIDIOC_S_FBUF, &fbuf);
if (err < 0)
dprintk("VIDIOCSFBUF / VIDIOC_S_FBUF: %d\n", err);
return err;
@@ -428,7 +417,6 @@ static noinline int v4l1_compat_set_frame_buffer(
static noinline int v4l1_compat_get_win_cap_dimensions(
struct video_window *win,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -443,7 +431,7 @@ static noinline int v4l1_compat_get_win_cap_dimensions(
memset(win, 0, sizeof(*win));
fmt->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
- err = drv(inode, file, VIDIOC_G_FMT, fmt);
+ err = drv(file, VIDIOC_G_FMT, fmt);
if (err < 0)
dprintk("VIDIOCGWIN / VIDIOC_G_WIN: %d\n", err);
if (err == 0) {
@@ -458,7 +446,7 @@ static noinline int v4l1_compat_get_win_cap_dimensions(
}
fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- err = drv(inode, file, VIDIOC_G_FMT, fmt);
+ err = drv(file, VIDIOC_G_FMT, fmt);
if (err < 0) {
dprintk("VIDIOCGWIN / VIDIOC_G_FMT: %d\n", err);
goto done;
@@ -477,7 +465,6 @@ done:
static noinline int v4l1_compat_set_win_cap_dimensions(
struct video_window *win,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -490,8 +477,8 @@ static noinline int v4l1_compat_set_win_cap_dimensions(
return err;
}
fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- drv(inode, file, VIDIOC_STREAMOFF, &fmt->type);
- err1 = drv(inode, file, VIDIOC_G_FMT, fmt);
+ drv(file, VIDIOC_STREAMOFF, &fmt->type);
+ err1 = drv(file, VIDIOC_G_FMT, fmt);
if (err1 < 0)
dprintk("VIDIOCSWIN / VIDIOC_G_FMT: %d\n", err1);
if (err1 == 0) {
@@ -499,7 +486,7 @@ static noinline int v4l1_compat_set_win_cap_dimensions(
fmt->fmt.pix.height = win->height;
fmt->fmt.pix.field = V4L2_FIELD_ANY;
fmt->fmt.pix.bytesperline = 0;
- err = drv(inode, file, VIDIOC_S_FMT, fmt);
+ err = drv(file, VIDIOC_S_FMT, fmt);
if (err < 0)
dprintk("VIDIOCSWIN / VIDIOC_S_FMT #1: %d\n",
err);
@@ -516,7 +503,7 @@ static noinline int v4l1_compat_set_win_cap_dimensions(
fmt->fmt.win.chromakey = win->chromakey;
fmt->fmt.win.clips = (void __user *)win->clips;
fmt->fmt.win.clipcount = win->clipcount;
- err2 = drv(inode, file, VIDIOC_S_FMT, fmt);
+ err2 = drv(file, VIDIOC_S_FMT, fmt);
if (err2 < 0)
dprintk("VIDIOCSWIN / VIDIOC_S_FMT #2: %d\n", err2);
@@ -530,7 +517,6 @@ static noinline int v4l1_compat_set_win_cap_dimensions(
static noinline int v4l1_compat_turn_preview_on_off(
int *on,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -541,9 +527,9 @@ static noinline int v4l1_compat_turn_preview_on_off(
/* dirty hack time. But v4l1 has no STREAMOFF
* equivalent in the API, and this one at
* least comes close ... */
- drv(inode, file, VIDIOC_STREAMOFF, &captype);
+ drv(file, VIDIOC_STREAMOFF, &captype);
}
- err = drv(inode, file, VIDIOC_OVERLAY, on);
+ err = drv(file, VIDIOC_OVERLAY, on);
if (err < 0)
dprintk("VIDIOCCAPTURE / VIDIOC_PREVIEW: %d\n", err);
return err;
@@ -551,7 +537,6 @@ static noinline int v4l1_compat_turn_preview_on_off(
static noinline int v4l1_compat_get_input_info(
struct video_channel *chan,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -561,7 +546,7 @@ static noinline int v4l1_compat_get_input_info(
memset(&input2, 0, sizeof(input2));
input2.index = chan->channel;
- err = drv(inode, file, VIDIOC_ENUMINPUT, &input2);
+ err = drv(file, VIDIOC_ENUMINPUT, &input2);
if (err < 0) {
dprintk("VIDIOCGCHAN / VIDIOC_ENUMINPUT: "
"channel=%d err=%d\n", chan->channel, err);
@@ -583,7 +568,7 @@ static noinline int v4l1_compat_get_input_info(
break;
}
chan->norm = 0;
- err = drv(inode, file, VIDIOC_G_STD, &sid);
+ err = drv(file, VIDIOC_G_STD, &sid);
if (err < 0)
dprintk("VIDIOCGCHAN / VIDIOC_G_STD: %d\n", err);
if (err == 0) {
@@ -600,14 +585,13 @@ done:
static noinline int v4l1_compat_set_input(
struct video_channel *chan,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
int err;
v4l2_std_id sid = 0;
- err = drv(inode, file, VIDIOC_S_INPUT, &chan->channel);
+ err = drv(file, VIDIOC_S_INPUT, &chan->channel);
if (err < 0)
dprintk("VIDIOCSCHAN / VIDIOC_S_INPUT: %d\n", err);
switch (chan->norm) {
@@ -622,7 +606,7 @@ static noinline int v4l1_compat_set_input(
break;
}
if (0 != sid) {
- err = drv(inode, file, VIDIOC_S_STD, &sid);
+ err = drv(file, VIDIOC_S_STD, &sid);
if (err < 0)
dprintk("VIDIOCSCHAN / VIDIOC_S_STD: %d\n", err);
}
@@ -631,7 +615,6 @@ static noinline int v4l1_compat_set_input(
static noinline int v4l1_compat_get_picture(
struct video_picture *pict,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -644,19 +627,19 @@ static noinline int v4l1_compat_get_picture(
return err;
}
- pict->brightness = get_v4l_control(inode, file,
+ pict->brightness = get_v4l_control(file,
V4L2_CID_BRIGHTNESS, drv);
- pict->hue = get_v4l_control(inode, file,
+ pict->hue = get_v4l_control(file,
V4L2_CID_HUE, drv);
- pict->contrast = get_v4l_control(inode, file,
+ pict->contrast = get_v4l_control(file,
V4L2_CID_CONTRAST, drv);
- pict->colour = get_v4l_control(inode, file,
+ pict->colour = get_v4l_control(file,
V4L2_CID_SATURATION, drv);
- pict->whiteness = get_v4l_control(inode, file,
+ pict->whiteness = get_v4l_control(file,
V4L2_CID_WHITENESS, drv);
fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- err = drv(inode, file, VIDIOC_G_FMT, fmt);
+ err = drv(file, VIDIOC_G_FMT, fmt);
if (err < 0) {
dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %d\n", err);
goto done;
@@ -674,7 +657,6 @@ done:
static noinline int v4l1_compat_set_picture(
struct video_picture *pict,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -690,15 +672,15 @@ static noinline int v4l1_compat_set_picture(
}
memset(&fbuf, 0, sizeof(fbuf));
- set_v4l_control(inode, file,
+ set_v4l_control(file,
V4L2_CID_BRIGHTNESS, pict->brightness, drv);
- set_v4l_control(inode, file,
+ set_v4l_control(file,
V4L2_CID_HUE, pict->hue, drv);
- set_v4l_control(inode, file,
+ set_v4l_control(file,
V4L2_CID_CONTRAST, pict->contrast, drv);
- set_v4l_control(inode, file,
+ set_v4l_control(file,
V4L2_CID_SATURATION, pict->colour, drv);
- set_v4l_control(inode, file,
+ set_v4l_control(file,
V4L2_CID_WHITENESS, pict->whiteness, drv);
/*
* V4L1 uses this ioctl to set both memory capture and overlay
@@ -708,7 +690,7 @@ static noinline int v4l1_compat_set_picture(
*/
fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- err = drv(inode, file, VIDIOC_G_FMT, fmt);
+ err = drv(file, VIDIOC_G_FMT, fmt);
/* If VIDIOC_G_FMT failed, then the driver likely doesn't
support memory capture. Trying to set the memory capture
parameters would be pointless. */
@@ -719,13 +701,13 @@ static noinline int v4l1_compat_set_picture(
palette_to_pixelformat(pict->palette)) {
fmt->fmt.pix.pixelformat = palette_to_pixelformat(
pict->palette);
- mem_err = drv(inode, file, VIDIOC_S_FMT, fmt);
+ mem_err = drv(file, VIDIOC_S_FMT, fmt);
if (mem_err < 0)
dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n",
mem_err);
}
- err = drv(inode, file, VIDIOC_G_FBUF, &fbuf);
+ err = drv(file, VIDIOC_G_FBUF, &fbuf);
/* If VIDIOC_G_FBUF failed, then the driver likely doesn't
support overlay. Trying to set the overlay parameters
would be quite pointless. */
@@ -736,7 +718,7 @@ static noinline int v4l1_compat_set_picture(
palette_to_pixelformat(pict->palette)) {
fbuf.fmt.pixelformat = palette_to_pixelformat(
pict->palette);
- ovl_err = drv(inode, file, VIDIOC_S_FBUF, &fbuf);
+ ovl_err = drv(file, VIDIOC_S_FBUF, &fbuf);
if (ovl_err < 0)
dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n",
ovl_err);
@@ -757,7 +739,6 @@ static noinline int v4l1_compat_set_picture(
static noinline int v4l1_compat_get_tuner(
struct video_tuner *tun,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -767,7 +748,7 @@ static noinline int v4l1_compat_get_tuner(
v4l2_std_id sid;
memset(&tun2, 0, sizeof(tun2));
- err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
+ err = drv(file, VIDIOC_G_TUNER, &tun2);
if (err < 0) {
dprintk("VIDIOCGTUNER / VIDIOC_G_TUNER: %d\n", err);
goto done;
@@ -783,7 +764,7 @@ static noinline int v4l1_compat_get_tuner(
for (i = 0; i < 64; i++) {
memset(&std2, 0, sizeof(std2));
std2.index = i;
- if (0 != drv(inode, file, VIDIOC_ENUMSTD, &std2))
+ if (0 != drv(file, VIDIOC_ENUMSTD, &std2))
break;
if (std2.id & V4L2_STD_PAL)
tun->flags |= VIDEO_TUNER_PAL;
@@ -793,7 +774,7 @@ static noinline int v4l1_compat_get_tuner(
tun->flags |= VIDEO_TUNER_SECAM;
}
- err = drv(inode, file, VIDIOC_G_STD, &sid);
+ err = drv(file, VIDIOC_G_STD, &sid);
if (err < 0)
dprintk("VIDIOCGTUNER / VIDIOC_G_STD: %d\n", err);
if (err == 0) {
@@ -816,7 +797,6 @@ done:
static noinline int v4l1_compat_select_tuner(
struct video_tuner *tun,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -826,7 +806,7 @@ static noinline int v4l1_compat_select_tuner(
t.index = tun->tuner;
- err = drv(inode, file, VIDIOC_S_INPUT, &t);
+ err = drv(file, VIDIOC_S_INPUT, &t);
if (err < 0)
dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n", err);
return err;
@@ -834,7 +814,6 @@ static noinline int v4l1_compat_select_tuner(
static noinline int v4l1_compat_get_frequency(
unsigned long *freq,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -843,7 +822,7 @@ static noinline int v4l1_compat_get_frequency(
memset(&freq2, 0, sizeof(freq2));
freq2.tuner = 0;
- err = drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
+ err = drv(file, VIDIOC_G_FREQUENCY, &freq2);
if (err < 0)
dprintk("VIDIOCGFREQ / VIDIOC_G_FREQUENCY: %d\n", err);
if (0 == err)
@@ -853,7 +832,6 @@ static noinline int v4l1_compat_get_frequency(
static noinline int v4l1_compat_set_frequency(
unsigned long *freq,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -861,9 +839,9 @@ static noinline int v4l1_compat_set_frequency(
struct v4l2_frequency freq2;
memset(&freq2, 0, sizeof(freq2));
- drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
+ drv(file, VIDIOC_G_FREQUENCY, &freq2);
freq2.frequency = *freq;
- err = drv(inode, file, VIDIOC_S_FREQUENCY, &freq2);
+ err = drv(file, VIDIOC_S_FREQUENCY, &freq2);
if (err < 0)
dprintk("VIDIOCSFREQ / VIDIOC_S_FREQUENCY: %d\n", err);
return err;
@@ -871,7 +849,6 @@ static noinline int v4l1_compat_set_frequency(
static noinline int v4l1_compat_get_audio(
struct video_audio *aud,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -881,7 +858,7 @@ static noinline int v4l1_compat_get_audio(
struct v4l2_tuner tun2;
memset(&aud2, 0, sizeof(aud2));
- err = drv(inode, file, VIDIOC_G_AUDIO, &aud2);
+ err = drv(file, VIDIOC_G_AUDIO, &aud2);
if (err < 0) {
dprintk("VIDIOCGAUDIO / VIDIOC_G_AUDIO: %d\n", err);
goto done;
@@ -891,27 +868,27 @@ static noinline int v4l1_compat_get_audio(
aud->name[sizeof(aud->name) - 1] = 0;
aud->audio = aud2.index;
aud->flags = 0;
- i = get_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME, drv);
+ i = get_v4l_control(file, V4L2_CID_AUDIO_VOLUME, drv);
if (i >= 0) {
aud->volume = i;
aud->flags |= VIDEO_AUDIO_VOLUME;
}
- i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BASS, drv);
+ i = get_v4l_control(file, V4L2_CID_AUDIO_BASS, drv);
if (i >= 0) {
aud->bass = i;
aud->flags |= VIDEO_AUDIO_BASS;
}
- i = get_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE, drv);
+ i = get_v4l_control(file, V4L2_CID_AUDIO_TREBLE, drv);
if (i >= 0) {
aud->treble = i;
aud->flags |= VIDEO_AUDIO_TREBLE;
}
- i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE, drv);
+ i = get_v4l_control(file, V4L2_CID_AUDIO_BALANCE, drv);
if (i >= 0) {
aud->balance = i;
aud->flags |= VIDEO_AUDIO_BALANCE;
}
- i = get_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE, drv);
+ i = get_v4l_control(file, V4L2_CID_AUDIO_MUTE, drv);
if (i >= 0) {
if (i)
aud->flags |= VIDEO_AUDIO_MUTE;
@@ -919,13 +896,13 @@ static noinline int v4l1_compat_get_audio(
}
aud->step = 1;
qctrl2.id = V4L2_CID_AUDIO_VOLUME;
- if (drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2) == 0 &&
+ if (drv(file, VIDIOC_QUERYCTRL, &qctrl2) == 0 &&
!(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED))
aud->step = qctrl2.step;
aud->mode = 0;
memset(&tun2, 0, sizeof(tun2));
- err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
+ err = drv(file, VIDIOC_G_TUNER, &tun2);
if (err < 0) {
dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %d\n", err);
err = 0;
@@ -944,7 +921,6 @@ done:
static noinline int v4l1_compat_set_audio(
struct video_audio *aud,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -956,24 +932,24 @@ static noinline int v4l1_compat_set_audio(
memset(&tun2, 0, sizeof(tun2));
aud2.index = aud->audio;
- err = drv(inode, file, VIDIOC_S_AUDIO, &aud2);
+ err = drv(file, VIDIOC_S_AUDIO, &aud2);
if (err < 0) {
dprintk("VIDIOCSAUDIO / VIDIOC_S_AUDIO: %d\n", err);
goto done;
}
- set_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME,
+ set_v4l_control(file, V4L2_CID_AUDIO_VOLUME,
aud->volume, drv);
- set_v4l_control(inode, file, V4L2_CID_AUDIO_BASS,
+ set_v4l_control(file, V4L2_CID_AUDIO_BASS,
aud->bass, drv);
- set_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE,
+ set_v4l_control(file, V4L2_CID_AUDIO_TREBLE,
aud->treble, drv);
- set_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE,
+ set_v4l_control(file, V4L2_CID_AUDIO_BALANCE,
aud->balance, drv);
- set_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE,
+ set_v4l_control(file, V4L2_CID_AUDIO_MUTE,
!!(aud->flags & VIDEO_AUDIO_MUTE), drv);
- err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
+ err = drv(file, VIDIOC_G_TUNER, &tun2);
if (err < 0)
dprintk("VIDIOCSAUDIO / VIDIOC_G_TUNER: %d\n", err);
if (err == 0) {
@@ -990,7 +966,7 @@ static noinline int v4l1_compat_set_audio(
tun2.audmode = V4L2_TUNER_MODE_LANG2;
break;
}
- err = drv(inode, file, VIDIOC_S_TUNER, &tun2);
+ err = drv(file, VIDIOC_S_TUNER, &tun2);
if (err < 0)
dprintk("VIDIOCSAUDIO / VIDIOC_S_TUNER: %d\n", err);
}
@@ -1001,7 +977,6 @@ done:
static noinline int v4l1_compat_capture_frame(
struct video_mmap *mm,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -1018,7 +993,7 @@ static noinline int v4l1_compat_capture_frame(
memset(&buf, 0, sizeof(buf));
fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- err = drv(inode, file, VIDIOC_G_FMT, fmt);
+ err = drv(file, VIDIOC_G_FMT, fmt);
if (err < 0) {
dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %d\n", err);
goto done;
@@ -1034,7 +1009,7 @@ static noinline int v4l1_compat_capture_frame(
palette_to_pixelformat(mm->format);
fmt->fmt.pix.field = V4L2_FIELD_ANY;
fmt->fmt.pix.bytesperline = 0;
- err = drv(inode, file, VIDIOC_S_FMT, fmt);
+ err = drv(file, VIDIOC_S_FMT, fmt);
if (err < 0) {
dprintk("VIDIOCMCAPTURE / VIDIOC_S_FMT: %d\n", err);
goto done;
@@ -1042,17 +1017,17 @@ static noinline int v4l1_compat_capture_frame(
}
buf.index = mm->frame;
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- err = drv(inode, file, VIDIOC_QUERYBUF, &buf);
+ err = drv(file, VIDIOC_QUERYBUF, &buf);
if (err < 0) {
dprintk("VIDIOCMCAPTURE / VIDIOC_QUERYBUF: %d\n", err);
goto done;
}
- err = drv(inode, file, VIDIOC_QBUF, &buf);
+ err = drv(file, VIDIOC_QBUF, &buf);
if (err < 0) {
dprintk("VIDIOCMCAPTURE / VIDIOC_QBUF: %d\n", err);
goto done;
}
- err = drv(inode, file, VIDIOC_STREAMON, &captype);
+ err = drv(file, VIDIOC_STREAMON, &captype);
if (err < 0)
dprintk("VIDIOCMCAPTURE / VIDIOC_STREAMON: %d\n", err);
done:
@@ -1062,7 +1037,6 @@ done:
static noinline int v4l1_compat_sync(
int *i,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -1074,7 +1048,7 @@ static noinline int v4l1_compat_sync(
memset(&buf, 0, sizeof(buf));
buf.index = *i;
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- err = drv(inode, file, VIDIOC_QUERYBUF, &buf);
+ err = drv(file, VIDIOC_QUERYBUF, &buf);
if (err < 0) {
/* No such buffer */
dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n", err);
@@ -1087,7 +1061,7 @@ static noinline int v4l1_compat_sync(
}
/* make sure capture actually runs so we don't block forever */
- err = drv(inode, file, VIDIOC_STREAMON, &captype);
+ err = drv(file, VIDIOC_STREAMON, &captype);
if (err < 0) {
dprintk("VIDIOCSYNC / VIDIOC_STREAMON: %d\n", err);
goto done;
@@ -1101,7 +1075,7 @@ static noinline int v4l1_compat_sync(
if (err < 0 || /* error or sleep was interrupted */
err == 0) /* timeout? Shouldn't occur. */
break;
- err = drv(inode, file, VIDIOC_QUERYBUF, &buf);
+ err = drv(file, VIDIOC_QUERYBUF, &buf);
if (err < 0)
dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n", err);
}
@@ -1109,7 +1083,7 @@ static noinline int v4l1_compat_sync(
if (!(buf.flags & V4L2_BUF_FLAG_DONE)) /* not done */
goto done;
do {
- err = drv(inode, file, VIDIOC_DQBUF, &buf);
+ err = drv(file, VIDIOC_DQBUF, &buf);
if (err < 0)
dprintk("VIDIOCSYNC / VIDIOC_DQBUF: %d\n", err);
} while (err == 0 && buf.index != *i);
@@ -1119,7 +1093,6 @@ done:
static noinline int v4l1_compat_get_vbi_format(
struct vbi_format *fmt,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -1133,7 +1106,7 @@ static noinline int v4l1_compat_get_vbi_format(
}
fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
- err = drv(inode, file, VIDIOC_G_FMT, fmt2);
+ err = drv(file, VIDIOC_G_FMT, fmt2);
if (err < 0) {
dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %d\n", err);
goto done;
@@ -1158,7 +1131,6 @@ done:
static noinline int v4l1_compat_set_vbi_format(
struct vbi_format *fmt,
- struct inode *inode,
struct file *file,
v4l2_kioctl drv)
{
@@ -1184,7 +1156,7 @@ static noinline int v4l1_compat_set_vbi_format(
fmt2->fmt.vbi.start[1] = fmt->start[1];
fmt2->fmt.vbi.count[1] = fmt->count[1];
fmt2->fmt.vbi.flags = fmt->flags;
- err = drv(inode, file, VIDIOC_TRY_FMT, fmt2);
+ err = drv(file, VIDIOC_TRY_FMT, fmt2);
if (err < 0) {
dprintk("VIDIOCSVBIFMT / VIDIOC_TRY_FMT: %d\n", err);
goto done;
@@ -1201,7 +1173,7 @@ static noinline int v4l1_compat_set_vbi_format(
err = -EINVAL;
goto done;
}
- err = drv(inode, file, VIDIOC_S_FMT, fmt2);
+ err = drv(file, VIDIOC_S_FMT, fmt2);
if (err < 0)
dprintk("VIDIOCSVBIFMT / VIDIOC_S_FMT: %d\n", err);
done:
@@ -1213,8 +1185,7 @@ done:
* This function is exported.
*/
int
-v4l_compat_translate_ioctl(struct inode *inode,
- struct file *file,
+v4l_compat_translate_ioctl(struct file *file,
int cmd,
void *arg,
v4l2_kioctl drv)
@@ -1223,52 +1194,52 @@ v4l_compat_translate_ioctl(struct inode *inode,
switch (cmd) {
case VIDIOCGCAP: /* capability */
- err = v4l1_compat_get_capabilities(arg, inode, file, drv);
+ err = v4l1_compat_get_capabilities(arg, file, drv);
break;
case VIDIOCGFBUF: /* get frame buffer */
- err = v4l1_compat_get_frame_buffer(arg, inode, file, drv);
+ err = v4l1_compat_get_frame_buffer(arg, file, drv);
break;
case VIDIOCSFBUF: /* set frame buffer */
- err = v4l1_compat_set_frame_buffer(arg, inode, file, drv);
+ err = v4l1_compat_set_frame_buffer(arg, file, drv);
break;
case VIDIOCGWIN: /* get window or capture dimensions */
- err = v4l1_compat_get_win_cap_dimensions(arg, inode, file, drv);
+ err = v4l1_compat_get_win_cap_dimensions(arg, file, drv);
break;
case VIDIOCSWIN: /* set window and/or capture dimensions */
- err = v4l1_compat_set_win_cap_dimensions(arg, inode, file, drv);
+ err = v4l1_compat_set_win_cap_dimensions(arg, file, drv);
break;
case VIDIOCCAPTURE: /* turn on/off preview */
- err = v4l1_compat_turn_preview_on_off(arg, inode, file, drv);
+ err = v4l1_compat_turn_preview_on_off(arg, file, drv);
break;
case VIDIOCGCHAN: /* get input information */
- err = v4l1_compat_get_input_info(arg, inode, file, drv);
+ err = v4l1_compat_get_input_info(arg, file, drv);
break;
case VIDIOCSCHAN: /* set input */
- err = v4l1_compat_set_input(arg, inode, file, drv);
+ err = v4l1_compat_set_input(arg, file, drv);
break;
case VIDIOCGPICT: /* get tone controls & partial capture format */
- err = v4l1_compat_get_picture(arg, inode, file, drv);
+ err = v4l1_compat_get_picture(arg, file, drv);
break;
case VIDIOCSPICT: /* set tone controls & partial capture format */
- err = v4l1_compat_set_picture(arg, inode, file, drv);
+ err = v4l1_compat_set_picture(arg, file, drv);
break;
case VIDIOCGTUNER: /* get tuner information */
- err = v4l1_compat_get_tuner(arg, inode, file, drv);
+ err = v4l1_compat_get_tuner(arg, file, drv);
break;
case VIDIOCSTUNER: /* select a tuner input */
- err = v4l1_compat_select_tuner(arg, inode, file, drv);
+ err = v4l1_compat_select_tuner(arg, file, drv);
break;
case VIDIOCGFREQ: /* get frequency */
- err = v4l1_compat_get_frequency(arg, inode, file, drv);
+ err = v4l1_compat_get_frequency(arg, file, drv);
break;
case VIDIOCSFREQ: /* set frequency */
- err = v4l1_compat_set_frequency(arg, inode, file, drv);
+ err = v4l1_compat_set_frequency(arg, file, drv);
break;
case VIDIOCGAUDIO: /* get audio properties/controls */
- err = v4l1_compat_get_audio(arg, inode, file, drv);
+ err = v4l1_compat_get_audio(arg, file, drv);
break;
case VIDIOCSAUDIO: /* set audio controls */
- err = v4l1_compat_set_audio(arg, inode, file, drv);
+ err = v4l1_compat_set_audio(arg, file, drv);
break;
#if 0
case VIDIOCGMBUF:
@@ -1277,16 +1248,16 @@ v4l_compat_translate_ioctl(struct inode *inode,
transparent, thus there is no point to try that */
#endif
case VIDIOCMCAPTURE: /* capture a frame */
- err = v4l1_compat_capture_frame(arg, inode, file, drv);
+ err = v4l1_compat_capture_frame(arg, file, drv);
break;
case VIDIOCSYNC: /* wait for a frame */
- err = v4l1_compat_sync(arg, inode, file, drv);
+ err = v4l1_compat_sync(arg, file, drv);
break;
case VIDIOCGVBIFMT: /* query VBI data capture format */
- err = v4l1_compat_get_vbi_format(arg, inode, file, drv);
+ err = v4l1_compat_get_vbi_format(arg, file, drv);
break;
case VIDIOCSVBIFMT:
- err = v4l1_compat_set_vbi_format(arg, inode, file, drv);
+ err = v4l1_compat_set_vbi_format(arg, file, drv);
break;
default:
err = -ENOIOCTLCMD;
diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c
index b5baf8f7e..e87a04a60 100644
--- a/linux/drivers/media/video/v4l2-common.c
+++ b/linux/drivers/media/video/v4l2-common.c
@@ -28,7 +28,7 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
- * Author: Alan Cox, <alan@redhat.com>
+ * Author: Alan Cox, <alan@lxorguk.ukuu.org.uk>
*
* Fixes:
*/
@@ -60,10 +60,6 @@
#include <media/v4l2-common.h>
#include <media/v4l2-chip-ident.h>
-#ifdef CONFIG_KMOD
-#include <linux/kmod.h>
-#endif
-
#include <linux/videodev2.h>
#include "compat.h"
diff --git a/linux/drivers/media/video/compat_ioctl32.c b/linux/drivers/media/video/v4l2-compat-ioctl32.c
index a37f3a64e..09d5c5693 100644
--- a/linux/drivers/media/video/compat_ioctl32.c
+++ b/linux/drivers/media/video/v4l2-compat-ioctl32.c
@@ -33,7 +33,7 @@ struct video_tuner32 {
static int get_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up)
{
- if(!access_ok(VERIFY_READ, up, sizeof(struct video_tuner32)) ||
+ if (!access_ok(VERIFY_READ, up, sizeof(struct video_tuner32)) ||
get_user(kp->tuner, &up->tuner) ||
copy_from_user(kp->name, up->name, 32) ||
get_user(kp->rangelow, &up->rangelow) ||
@@ -47,7 +47,7 @@ static int get_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user
static int put_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up)
{
- if(!access_ok(VERIFY_WRITE, up, sizeof(struct video_tuner32)) ||
+ if (!access_ok(VERIFY_WRITE, up, sizeof(struct video_tuner32)) ||
put_user(kp->tuner, &up->tuner) ||
copy_to_user(up->name, kp->name, 32) ||
put_user(kp->rangelow, &up->rangelow) ||
@@ -66,7 +66,6 @@ struct video_audio32 {
__u16 bass, treble;
__u32 flags;
__u8 name[16];
-// char name[16];
__u16 mode;
__u16 balance;
__u16 step;
@@ -138,7 +137,7 @@ static int put_video_buffer32(struct video_buffer *kp, struct video_buffer32 __u
{
u32 tmp = (u32)((unsigned long)kp->base);
- if(!access_ok(VERIFY_WRITE, up, sizeof(struct video_buffer32)) ||
+ if (!access_ok(VERIFY_WRITE, up, sizeof(struct video_buffer32)) ||
put_user(tmp, &up->base) ||
put_user(kp->height, &up->height) ||
put_user(kp->width, &up->width) ||
@@ -168,7 +167,7 @@ static int native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
ret = file->f_op->unlocked_ioctl(file, cmd, arg);
else if (file->f_op->ioctl) {
lock_kernel();
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
ret = file->f_op->ioctl(file->f_dentry->d_inode, file, cmd, arg);
#else
ret = file->f_op->ioctl(file->f_path.dentry->d_inode, file, cmd, arg);
@@ -184,7 +183,7 @@ static int native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
/* You get back everything except the clips... */
static int put_video_window32(struct video_window *kp, struct video_window32 __user *up)
{
- if(!access_ok(VERIFY_WRITE, up, sizeof(struct video_window32)) ||
+ if (!access_ok(VERIFY_WRITE, up, sizeof(struct video_window32)) ||
put_user(kp->x, &up->x) ||
put_user(kp->y, &up->y) ||
put_user(kp->width, &up->width) ||
@@ -197,14 +196,12 @@ static int put_video_window32(struct video_window *kp, struct video_window32 __u
}
#endif
-struct v4l2_clip32
-{
+struct v4l2_clip32 {
struct v4l2_rect c;
compat_caddr_t next;
};
-struct v4l2_window32
-{
+struct v4l2_window32 {
struct v4l2_rect w;
enum v4l2_field field;
__u32 chromakey;
@@ -285,15 +282,13 @@ static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vb
return 0;
}
-struct v4l2_format32
-{
+struct v4l2_format32 {
enum v4l2_buf_type type;
- union
- {
- struct v4l2_pix_format pix; // V4L2_BUF_TYPE_VIDEO_CAPTURE
- struct v4l2_window32 win; // V4L2_BUF_TYPE_VIDEO_OVERLAY
- struct v4l2_vbi_format vbi; // V4L2_BUF_TYPE_VBI_CAPTURE
- __u8 raw_data[200]; // user-defined
+ union {
+ struct v4l2_pix_format pix; /* V4L2_BUF_TYPE_VIDEO_CAPTURE */
+ struct v4l2_window32 win; /* V4L2_BUF_TYPE_VIDEO_OVERLAY */
+ struct v4l2_vbi_format vbi; /* V4L2_BUF_TYPE_VBI_CAPTURE */
+ __u8 raw_data[200]; /* user-defined */
} fmt;
};
@@ -310,7 +305,7 @@ static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user
case V4L2_BUF_TYPE_VBI_CAPTURE:
return get_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi);
default:
- printk("compat_ioctl : unexpected VIDIOC_FMT type %d\n",
+ printk(KERN_INFO "compat_ioctl: unexpected VIDIOC_FMT type %d\n",
kp->type);
return -ENXIO;
}
@@ -318,7 +313,7 @@ static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user
static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
{
- if(!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) ||
+ if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) ||
put_user(kp->type, &up->type))
return -EFAULT;
switch (kp->type) {
@@ -348,8 +343,7 @@ static inline int put_v4l2_standard(struct v4l2_standard *kp, struct v4l2_standa
return 0;
}
-struct v4l2_standard32
-{
+struct v4l2_standard32 {
__u32 index;
__u32 id[2]; /* __u64 would get the alignment wrong */
__u8 name[24];
@@ -369,7 +363,7 @@ static int get_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32
static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up)
{
- if(!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) ||
+ if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) ||
put_user(kp->index, &up->index) ||
copy_to_user(up->id, &kp->id, sizeof(__u64)) ||
copy_to_user(up->name, kp->name, 24) ||
@@ -395,8 +389,7 @@ static inline int put_v4l2_tuner(struct v4l2_tuner *kp, struct v4l2_tuner __user
return 0;
}
-struct v4l2_buffer32
-{
+struct v4l2_buffer32 {
__u32 index;
enum v4l2_buf_type type;
__u32 bytesused;
@@ -427,7 +420,7 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user
get_user(kp->memory, &up->memory) ||
get_user(kp->input, &up->input))
return -EFAULT;
- switch(kp->memory) {
+ switch (kp->memory) {
case V4L2_MEMORY_MMAP:
break;
case V4L2_MEMORY_USERPTR:
@@ -442,7 +435,7 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user
}
break;
case V4L2_MEMORY_OVERLAY:
- if(get_user(kp->m.offset, &up->m.offset))
+ if (get_user(kp->m.offset, &up->m.offset))
return -EFAULT;
break;
}
@@ -458,7 +451,7 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user
put_user(kp->memory, &up->memory) ||
put_user(kp->input, &up->input))
return -EFAULT;
- switch(kp->memory) {
+ switch (kp->memory) {
case V4L2_MEMORY_MMAP:
if (put_user(kp->length, &up->length) ||
put_user(kp->m.offset, &up->m.offset))
@@ -485,8 +478,7 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user
return 0;
}
-struct v4l2_framebuffer32
-{
+struct v4l2_framebuffer32 {
__u32 capability;
__u32 flags;
compat_caddr_t base;
@@ -511,7 +503,7 @@ static int put_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_frame
{
u32 tmp = (u32)((unsigned long)kp->base);
- if(!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_framebuffer32)) ||
+ if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_framebuffer32)) ||
put_user(tmp, &up->base) ||
put_user(kp->capability, &up->capability) ||
put_user(kp->flags, &up->flags))
@@ -549,8 +541,7 @@ static inline int put_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user
}
#ifdef CONFIG_VIDEO_V4L1_COMPAT
-struct video_code32
-{
+struct video_code32 {
char loadwhat[16]; /* name or tag of file being passed */
compat_int_t datasize;
unsigned char *data;
@@ -558,28 +549,28 @@ struct video_code32
static inline int microcode32(struct video_code *kp, struct video_code32 __user *up)
{
- if(!access_ok(VERIFY_READ, up, sizeof(struct video_code32)) ||
- copy_from_user(kp->loadwhat, up->loadwhat, sizeof (up->loadwhat)) ||
+ if (!access_ok(VERIFY_READ, up, sizeof(struct video_code32)) ||
+ copy_from_user(kp->loadwhat, up->loadwhat, sizeof(up->loadwhat)) ||
get_user(kp->datasize, &up->datasize) ||
copy_from_user(kp->data, up->data, up->datasize))
return -EFAULT;
return 0;
}
-#define VIDIOCGTUNER32 _IOWR('v',4, struct video_tuner32)
-#define VIDIOCSTUNER32 _IOW('v',5, struct video_tuner32)
-#define VIDIOCGWIN32 _IOR('v',9, struct video_window32)
-#define VIDIOCSWIN32 _IOW('v',10, struct video_window32)
-#define VIDIOCGFBUF32 _IOR('v',11, struct video_buffer32)
-#define VIDIOCSFBUF32 _IOW('v',12, struct video_buffer32)
-#define VIDIOCGFREQ32 _IOR('v',14, u32)
-#define VIDIOCSFREQ32 _IOW('v',15, u32)
-#define VIDIOCSMICROCODE32 _IOW('v',27, struct video_code32)
+#define VIDIOCGTUNER32 _IOWR('v', 4, struct video_tuner32)
+#define VIDIOCSTUNER32 _IOW('v', 5, struct video_tuner32)
+#define VIDIOCGWIN32 _IOR('v', 9, struct video_window32)
+#define VIDIOCSWIN32 _IOW('v', 10, struct video_window32)
+#define VIDIOCGFBUF32 _IOR('v', 11, struct video_buffer32)
+#define VIDIOCSFBUF32 _IOW('v', 12, struct video_buffer32)
+#define VIDIOCGFREQ32 _IOR('v', 14, u32)
+#define VIDIOCSFREQ32 _IOW('v', 15, u32)
+#define VIDIOCSMICROCODE32 _IOW('v', 27, struct video_code32)
#endif
/* VIDIOC_ENUMINPUT32 is VIDIOC_ENUMINPUT minus 4 bytes of padding alignement */
-#define VIDIOC_ENUMINPUT32 VIDIOC_ENUMINPUT - _IOC(0, 0, 0, 4)
+#define VIDIOC_ENUMINPUT32 (VIDIOC_ENUMINPUT - _IOC(0, 0, 0, 4))
#define VIDIOC_G_FMT32 _IOWR ('V', 4, struct v4l2_format32)
#define VIDIOC_S_FMT32 _IOWR ('V', 5, struct v4l2_format32)
#define VIDIOC_QUERYBUF32 _IOWR ('V', 9, struct v4l2_buffer32)
@@ -689,7 +680,7 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
int realcmd = cmd;
/* First, convert the command. */
- switch(cmd) {
+ switch (cmd) {
#ifdef CONFIG_VIDEO_V4L1_COMPAT
case VIDIOCGTUNER32: realcmd = cmd = VIDIOCGTUNER; break;
case VIDIOCSTUNER32: realcmd = cmd = VIDIOCSTUNER; break;
@@ -718,7 +709,7 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
case VIDIOC_TRY_FMT32: realcmd = cmd = VIDIOC_TRY_FMT; break;
};
- switch(cmd) {
+ switch (cmd) {
#ifdef CONFIG_VIDEO_V4L1_COMPAT
case VIDIOCSTUNER:
case VIDIOCGTUNER:
@@ -810,20 +801,20 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
break;
#endif
};
- if(err)
+ if (err)
goto out;
- if(compatible_arg)
+ if (compatible_arg)
err = native_ioctl(file, realcmd, (unsigned long)up);
else {
mm_segment_t old_fs = get_fs();
set_fs(KERNEL_DS);
- err = native_ioctl(file, realcmd, (unsigned long) &karg);
+ err = native_ioctl(file, realcmd, (unsigned long)&karg);
set_fs(old_fs);
}
- if(err == 0) {
- switch(cmd) {
+ if (err == 0) {
+ switch (cmd) {
#ifdef CONFIG_VIDEO_V4L1_COMPAT
case VIDIOCGTUNER:
err = put_video_tuner32(&karg.vt, up);
@@ -932,6 +923,7 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
case VIDIOC_STREAMON32:
case VIDIOC_STREAMOFF32:
case VIDIOC_G_PARM:
+ case VIDIOC_S_PARM:
case VIDIOC_G_STD:
case VIDIOC_S_STD:
case VIDIOC_G_TUNER:
@@ -950,6 +942,8 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
case VIDIOC_S_INPUT32:
case VIDIOC_TRY_FMT32:
case VIDIOC_S_HW_FREQ_SEEK:
+ case VIDIOC_ENUM_FRAMESIZES:
+ case VIDIOC_ENUM_FRAMEINTERVALS:
ret = do_video_ioctl(file, cmd, arg);
break;
diff --git a/linux/drivers/media/video/v4l2-dev.c b/linux/drivers/media/video/v4l2-dev.c
index 70f852c37..3b8f33c8d 100644
--- a/linux/drivers/media/video/v4l2-dev.c
+++ b/linux/drivers/media/video/v4l2-dev.c
@@ -9,7 +9,7 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
- * Authors: Alan Cox, <alan@redhat.com> (version 1)
+ * Authors: Alan Cox, <alan@lxorguk.ukuu.org.uk> (version 1)
* Mauro Carvalho Chehab <mchehab@infradead.org> (version 2)
*
* Fixes: 20000516 Claudio Matsuoka <claudio@conectiva.com>
@@ -381,7 +381,7 @@ int video_register_device_index(struct video_device *vfd, int type, int nr,
#else
if (vfd->parent)
vfd->dev.parent = vfd->parent;
- sprintf(vfd->dev.bus_id, "%s%d", name_base, nr);
+ dev_set_name(&vfd->dev, "%s%d", name_base, nr);
ret = device_register(&vfd->dev);
#endif
if (ret < 0) {
diff --git a/linux/drivers/media/video/v4l2-int-device.c b/linux/drivers/media/video/v4l2-int-device.c
index 4434a9e9e..00c9bb7d6 100644
--- a/linux/drivers/media/video/v4l2-int-device.c
+++ b/linux/drivers/media/video/v4l2-int-device.c
@@ -33,7 +33,7 @@
static DEFINE_MUTEX(mutex);
static LIST_HEAD(int_list);
-static void v4l2_int_device_try_attach_all(void)
+void v4l2_int_device_try_attach_all(void)
{
struct v4l2_int_device *m, *s;
@@ -67,6 +67,7 @@ static void v4l2_int_device_try_attach_all(void)
}
}
}
+EXPORT_SYMBOL_GPL(v4l2_int_device_try_attach_all);
static int ioctl_sort_cmp(const void *a, const void *b)
{
@@ -145,6 +146,7 @@ int v4l2_int_ioctl_0(struct v4l2_int_device *d, int cmd)
find_ioctl(d->u.slave, cmd,
(v4l2_int_ioctl_func *)no_such_ioctl_0))(d);
}
+EXPORT_SYMBOL_GPL(v4l2_int_ioctl_0);
static int no_such_ioctl_1(struct v4l2_int_device *d, void *arg)
{
@@ -157,5 +159,6 @@ int v4l2_int_ioctl_1(struct v4l2_int_device *d, int cmd, void *arg)
find_ioctl(d->u.slave, cmd,
(v4l2_int_ioctl_func *)no_such_ioctl_1))(d, arg);
}
+EXPORT_SYMBOL_GPL(v4l2_int_ioctl_1);
MODULE_LICENSE("GPL");
diff --git a/linux/drivers/media/video/v4l2-ioctl.c b/linux/drivers/media/video/v4l2-ioctl.c
index 3a68d6e35..86dd04026 100644
--- a/linux/drivers/media/video/v4l2-ioctl.c
+++ b/linux/drivers/media/video/v4l2-ioctl.c
@@ -8,7 +8,7 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
- * Authors: Alan Cox, <alan@redhat.com> (version 1)
+ * Authors: Alan Cox, <alan@lxorguk.ukuu.org.uk> (version 1)
* Mauro Carvalho Chehab <mchehab@infradead.org> (version 2)
*/
@@ -394,10 +394,8 @@ video_fix_command(unsigned int cmd)
* Obsolete usercopy function - Should be removed soon
*/
int
-video_usercopy(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg,
- int (*func)(struct inode *inode, struct file *file,
- unsigned int cmd, void *arg))
+video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
+ v4l2_kioctl func)
{
char sbuf[128];
void *mbuf = NULL;
@@ -459,7 +457,7 @@ video_usercopy(struct inode *inode, struct file *file,
}
/* call driver */
- err = func(inode, file, cmd, parg);
+ err = func(file, cmd, parg);
if (err == -ENOIOCTLCMD)
err = -EINVAL;
if (is_ext_ctrl) {
@@ -626,13 +624,13 @@ static int check_fmt(const struct v4l2_ioctl_ops *ops, enum v4l2_buf_type type)
return -EINVAL;
}
-static int __video_do_ioctl(struct inode *inode, struct file *file,
+static int __video_do_ioctl(struct file *file,
unsigned int cmd, void *arg)
{
struct video_device *vfd = video_devdata(file);
const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
- void *fh = file->private_data;
- int ret = -EINVAL;
+ void *fh = file->private_data;
+ int ret = -EINVAL;
if ((vfd->debug & V4L2_DEBUG_IOCTL) &&
!(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) {
@@ -676,7 +674,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
V4L2 ioctls.
********************************************************/
if (_IOC_TYPE(cmd) == 'v' && _IOC_NR(cmd) < BASE_VIDIOCPRIVATE)
- return v4l_compat_translate_ioctl(inode, file, cmd, arg,
+ return v4l_compat_translate_ioctl(file, cmd, arg,
__video_do_ioctl);
#endif
@@ -1482,9 +1480,15 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
case VIDIOC_G_CROP:
{
struct v4l2_crop *p = arg;
+ __u32 type;
if (!ops->vidioc_g_crop)
break;
+
+ type = p->type;
+ memset(p, 0, sizeof(*p));
+ p->type = type;
+
dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
ret = ops->vidioc_g_crop(file, fh, p);
if (!ret)
@@ -1505,10 +1509,16 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
case VIDIOC_CROPCAP:
{
struct v4l2_cropcap *p = arg;
+ __u32 type;
/*FIXME: Should also show v4l2_fract pixelaspect */
if (!ops->vidioc_cropcap)
break;
+
+ type = p->type;
+ memset(p, 0, sizeof(*p));
+ p->type = type;
+
dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
ret = ops->vidioc_cropcap(file, fh, p);
if (!ret) {
@@ -1523,6 +1533,9 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
if (!ops->vidioc_g_jpegcomp)
break;
+
+ memset(p, 0, sizeof(*p));
+
ret = ops->vidioc_g_jpegcomp(file, fh, p);
if (!ret)
dbgarg(cmd, "quality=%d, APPn=%d, "
@@ -1750,6 +1763,77 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
ret = ops->vidioc_s_hw_freq_seek(file, fh, p);
break;
}
+ case VIDIOC_ENUM_FRAMESIZES:
+ {
+ struct v4l2_frmsizeenum *p = arg;
+
+ if (!ops->vidioc_enum_framesizes)
+ break;
+
+ memset(p, 0, sizeof(*p));
+
+ ret = ops->vidioc_enum_framesizes(file, fh, p);
+ dbgarg(cmd,
+ "index=%d, pixelformat=%d, type=%d ",
+ p->index, p->pixel_format, p->type);
+ switch (p->type) {
+ case V4L2_FRMSIZE_TYPE_DISCRETE:
+ dbgarg2("width = %d, height=%d\n",
+ p->discrete.width, p->discrete.height);
+ break;
+ case V4L2_FRMSIZE_TYPE_STEPWISE:
+ dbgarg2("min %dx%d, max %dx%d, step %dx%d\n",
+ p->stepwise.min_width, p->stepwise.min_height,
+ p->stepwise.step_width, p->stepwise.step_height,
+ p->stepwise.max_width, p->stepwise.max_height);
+ break;
+ case V4L2_FRMSIZE_TYPE_CONTINUOUS:
+ dbgarg2("continuous\n");
+ break;
+ default:
+ dbgarg2("- Unknown type!\n");
+ }
+
+ break;
+ }
+ case VIDIOC_ENUM_FRAMEINTERVALS:
+ {
+ struct v4l2_frmivalenum *p = arg;
+
+ if (!ops->vidioc_enum_frameintervals)
+ break;
+
+ memset(p, 0, sizeof(*p));
+
+ ret = ops->vidioc_enum_frameintervals(file, fh, p);
+ dbgarg(cmd,
+ "index=%d, pixelformat=%d, width=%d, height=%d, type=%d ",
+ p->index, p->pixel_format,
+ p->width, p->height, p->type);
+ switch (p->type) {
+ case V4L2_FRMIVAL_TYPE_DISCRETE:
+ dbgarg2("fps=%d/%d\n",
+ p->discrete.numerator,
+ p->discrete.denominator);
+ break;
+ case V4L2_FRMIVAL_TYPE_STEPWISE:
+ dbgarg2("min=%d/%d, max=%d/%d, step=%d/%d\n",
+ p->stepwise.min.numerator,
+ p->stepwise.min.denominator,
+ p->stepwise.max.numerator,
+ p->stepwise.max.denominator,
+ p->stepwise.step.numerator,
+ p->stepwise.step.denominator);
+ break;
+ case V4L2_FRMIVAL_TYPE_CONTINUOUS:
+ dbgarg2("continuous\n");
+ break;
+ default:
+ dbgarg2("- Unknown type!\n");
+ }
+ break;
+ }
+
default:
{
if (!ops->vidioc_default)
@@ -1769,7 +1853,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
return ret;
}
-int video_ioctl2(struct inode *inode, struct file *file,
+int __video_ioctl2(struct file *file,
unsigned int cmd, unsigned long arg)
{
char sbuf[128];
@@ -1833,7 +1917,7 @@ int video_ioctl2(struct inode *inode, struct file *file,
}
/* Handles IOCTL */
- err = __video_do_ioctl(inode, file, cmd, parg);
+ err = __video_do_ioctl(file, cmd, parg);
if (err == -ENOIOCTLCMD)
err = -EINVAL;
if (is_ext_ctrl) {
@@ -1861,4 +1945,11 @@ out:
kfree(mbuf);
return err;
}
+EXPORT_SYMBOL(__video_ioctl2);
+
+int video_ioctl2(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ return __video_ioctl2(file, cmd, arg);
+}
EXPORT_SYMBOL(video_ioctl2);
diff --git a/linux/drivers/media/video/videobuf-dvb.c b/linux/drivers/media/video/videobuf-dvb.c
index 33e2f2b2b..2d382373b 100644
--- a/linux/drivers/media/video/videobuf-dvb.c
+++ b/linux/drivers/media/video/videobuf-dvb.c
@@ -131,7 +131,6 @@ static int videobuf_dvb_stop_feed(struct dvb_demux_feed *feed)
mutex_lock(&dvb->lock);
dvb->nfeeds--;
if (0 == dvb->nfeeds && NULL != dvb->thread) {
- // FIXME: cx8802_cancel_buffers(dev);
err = kthread_stop(dvb->thread);
dvb->thread = NULL;
}
@@ -139,50 +138,7 @@ static int videobuf_dvb_stop_feed(struct dvb_demux_feed *feed)
return err;
}
-/* ------------------------------------------------------------------ */
-/* Register a single adapter and one or more frontends */
-int videobuf_dvb_register_bus(struct videobuf_dvb_frontends *f,
- struct module *module,
- void *adapter_priv,
- struct device *device,
- short *adapter_nr,
- int mfe_shared)
-{
- struct list_head *list, *q;
- struct videobuf_dvb_frontend *fe;
- int res = -EINVAL;
-
- fe = videobuf_dvb_get_frontend(f, 1);
- if (!fe) {
- printk(KERN_WARNING "Unable to register the adapter which has no frontends\n");
- goto err;
- }
-
- /* Bring up the adapter */
- res = videobuf_dvb_register_adapter(f, module, adapter_priv, device, fe->dvb.name, adapter_nr, mfe_shared);
- if (res < 0) {
- printk(KERN_WARNING "videobuf_dvb_register_adapter failed (errno = %d)\n", res);
- goto err;
- }
-
- /* Attach all of the frontends to the adapter */
- mutex_lock(&f->lock);
- list_for_each_safe(list, q, &f->frontend.felist) {
- fe = list_entry(list, struct videobuf_dvb_frontend, felist);
-
- res = videobuf_dvb_register_frontend(&f->adapter, &fe->dvb);
- if (res < 0) {
- printk(KERN_WARNING "%s: videobuf_dvb_register_frontend failed (errno = %d)\n",
- fe->dvb.name, res);
- }
- }
- mutex_unlock(&f->lock);
-
-err:
- return res;
-}
-
-int videobuf_dvb_register_adapter(struct videobuf_dvb_frontends *fe,
+static int videobuf_dvb_register_adapter(struct videobuf_dvb_frontends *fe,
struct module *module,
void *adapter_priv,
struct device *device,
@@ -195,7 +151,8 @@ int videobuf_dvb_register_adapter(struct videobuf_dvb_frontends *fe,
mutex_init(&fe->lock);
/* register adapter */
- result = dvb_register_adapter(&fe->adapter, adapter_name, module, device, adapter_nr);
+ result = dvb_register_adapter(&fe->adapter, adapter_name, module,
+ device, adapter_nr);
if (result < 0) {
printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n",
adapter_name, result);
@@ -206,7 +163,8 @@ int videobuf_dvb_register_adapter(struct videobuf_dvb_frontends *fe,
return result;
}
-int videobuf_dvb_register_frontend(struct dvb_adapter *adapter, struct videobuf_dvb *dvb)
+static int videobuf_dvb_register_frontend(struct dvb_adapter *adapter,
+ struct videobuf_dvb *dvb)
{
int result;
@@ -270,6 +228,10 @@ int videobuf_dvb_register_frontend(struct dvb_adapter *adapter, struct videobuf_
/* register network adapter */
dvb_net_init(adapter, &dvb->net, &dvb->demux.dmx);
+ if (dvb->net.dvbdev == NULL) {
+ result = -ENOMEM;
+ goto fail_fe_conn;
+ }
return 0;
fail_fe_conn:
@@ -284,44 +246,76 @@ fail_dmx:
dvb_unregister_frontend(dvb->frontend);
fail_frontend:
dvb_frontend_detach(dvb->frontend);
- dvb_unregister_adapter(adapter);
+ dvb->frontend = NULL;
return result;
}
-void videobuf_dvb_unregister_bus(struct videobuf_dvb_frontends *f)
+/* ------------------------------------------------------------------ */
+/* Register a single adapter and one or more frontends */
+int videobuf_dvb_register_bus(struct videobuf_dvb_frontends *f,
+ struct module *module,
+ void *adapter_priv,
+ struct device *device,
+ short *adapter_nr,
+ int mfe_shared)
{
struct list_head *list, *q;
struct videobuf_dvb_frontend *fe;
+ int res;
- mutex_lock(&f->lock);
- list_for_each_safe(list, q, &f->frontend.felist) {
- fe = list_entry(list, struct videobuf_dvb_frontend, felist);
+ fe = videobuf_dvb_get_frontend(f, 1);
+ if (!fe) {
+ printk(KERN_WARNING "Unable to register the adapter which has no frontends\n");
+ return -EINVAL;
+ }
- dvb_net_release(&fe->dvb.net);
- fe->dvb.demux.dmx.remove_frontend(&fe->dvb.demux.dmx, &fe->dvb.fe_mem);
- fe->dvb.demux.dmx.remove_frontend(&fe->dvb.demux.dmx, &fe->dvb.fe_hw);
- dvb_dmxdev_release(&fe->dvb.dmxdev);
- dvb_dmx_release(&fe->dvb.demux);
- dvb_unregister_frontend(fe->dvb.frontend);
- dvb_frontend_detach(fe->dvb.frontend);
+ /* Bring up the adapter */
+ res = videobuf_dvb_register_adapter(f, module, adapter_priv, device,
+ fe->dvb.name, adapter_nr, mfe_shared);
+ if (res < 0) {
+ printk(KERN_WARNING "videobuf_dvb_register_adapter failed (errno = %d)\n", res);
+ return res;
+ }
- list_del(list);
- kfree(fe);
+ /* Attach all of the frontends to the adapter */
+ mutex_lock(&f->lock);
+ list_for_each_safe(list, q, &f->felist) {
+ fe = list_entry(list, struct videobuf_dvb_frontend, felist);
+ res = videobuf_dvb_register_frontend(&f->adapter, &fe->dvb);
+ if (res < 0) {
+ printk(KERN_WARNING "%s: videobuf_dvb_register_frontend failed (errno = %d)\n",
+ fe->dvb.name, res);
+ goto err;
+ }
}
mutex_unlock(&f->lock);
+ return 0;
+
+err:
+ mutex_unlock(&f->lock);
+ videobuf_dvb_unregister_bus(f);
+ return res;
+}
+EXPORT_SYMBOL(videobuf_dvb_register_bus);
+
+void videobuf_dvb_unregister_bus(struct videobuf_dvb_frontends *f)
+{
+ videobuf_dvb_dealloc_frontends(f);
dvb_unregister_adapter(&f->adapter);
}
+EXPORT_SYMBOL(videobuf_dvb_unregister_bus);
-struct videobuf_dvb_frontend * videobuf_dvb_get_frontend(struct videobuf_dvb_frontends *f, int id)
+struct videobuf_dvb_frontend *videobuf_dvb_get_frontend(
+ struct videobuf_dvb_frontends *f, int id)
{
struct list_head *list, *q;
struct videobuf_dvb_frontend *fe, *ret = NULL;
mutex_lock(&f->lock);
- list_for_each_safe(list, q, &f->frontend.felist) {
+ list_for_each_safe(list, q, &f->felist) {
fe = list_entry(list, struct videobuf_dvb_frontend, felist);
if (fe->id == id) {
ret = fe;
@@ -333,8 +327,10 @@ struct videobuf_dvb_frontend * videobuf_dvb_get_frontend(struct videobuf_dvb_fro
return ret;
}
+EXPORT_SYMBOL(videobuf_dvb_get_frontend);
-int videobuf_dvb_find_frontend(struct videobuf_dvb_frontends *f, struct dvb_frontend *p)
+int videobuf_dvb_find_frontend(struct videobuf_dvb_frontends *f,
+ struct dvb_frontend *p)
{
struct list_head *list, *q;
struct videobuf_dvb_frontend *fe = NULL;
@@ -342,7 +338,7 @@ int videobuf_dvb_find_frontend(struct videobuf_dvb_frontends *f, struct dvb_fron
mutex_lock(&f->lock);
- list_for_each_safe(list, q, &f->frontend.felist) {
+ list_for_each_safe(list, q, &f->felist) {
fe = list_entry(list, struct videobuf_dvb_frontend, felist);
if (fe->dvb.frontend == p) {
ret = fe->id;
@@ -354,37 +350,53 @@ int videobuf_dvb_find_frontend(struct videobuf_dvb_frontends *f, struct dvb_fron
return ret;
}
+EXPORT_SYMBOL(videobuf_dvb_find_frontend);
-struct videobuf_dvb_frontend * videobuf_dvb_alloc_frontend(void *private, struct videobuf_dvb_frontends *f, int id)
+struct videobuf_dvb_frontend *videobuf_dvb_alloc_frontend(
+ struct videobuf_dvb_frontends *f, int id)
{
struct videobuf_dvb_frontend *fe;
- fe = kzalloc(sizeof(struct videobuf_dvb_frontend),GFP_KERNEL);
+ fe = kzalloc(sizeof(struct videobuf_dvb_frontend), GFP_KERNEL);
if (fe == NULL)
goto fail_alloc;
- fe->dev = private;
fe->id = id;
mutex_init(&fe->dvb.lock);
mutex_lock(&f->lock);
- list_add_tail(&fe->felist,&f->frontend.felist);
+ list_add_tail(&fe->felist, &f->felist);
mutex_unlock(&f->lock);
fail_alloc:
return fe;
}
-
-EXPORT_SYMBOL(videobuf_dvb_register_bus);
-EXPORT_SYMBOL(videobuf_dvb_unregister_bus);
EXPORT_SYMBOL(videobuf_dvb_alloc_frontend);
-EXPORT_SYMBOL(videobuf_dvb_get_frontend);
-EXPORT_SYMBOL(videobuf_dvb_find_frontend);
-/* ------------------------------------------------------------------ */
-/*
- * Local variables:
- * c-basic-offset: 8
- * compile-command: "make DVB=1"
- * End:
- */
+void videobuf_dvb_dealloc_frontends(struct videobuf_dvb_frontends *f)
+{
+ struct list_head *list, *q;
+ struct videobuf_dvb_frontend *fe;
+
+ mutex_lock(&f->lock);
+ list_for_each_safe(list, q, &f->felist) {
+ fe = list_entry(list, struct videobuf_dvb_frontend, felist);
+ if (fe->dvb.net.dvbdev) {
+ dvb_net_release(&fe->dvb.net);
+ fe->dvb.demux.dmx.remove_frontend(&fe->dvb.demux.dmx,
+ &fe->dvb.fe_mem);
+ fe->dvb.demux.dmx.remove_frontend(&fe->dvb.demux.dmx,
+ &fe->dvb.fe_hw);
+ dvb_dmxdev_release(&fe->dvb.dmxdev);
+ dvb_dmx_release(&fe->dvb.demux);
+ dvb_unregister_frontend(fe->dvb.frontend);
+ }
+ if (fe->dvb.frontend)
+ /* always allocated, may have been reset */
+ dvb_frontend_detach(fe->dvb.frontend);
+ list_del(list); /* remove list entry */
+ kfree(fe); /* free frontend allocation */
+ }
+ mutex_unlock(&f->lock);
+}
+EXPORT_SYMBOL(videobuf_dvb_dealloc_frontends);
diff --git a/linux/drivers/media/video/vino.c b/linux/drivers/media/video/vino.c
index 08eb57818..50f685fae 100644
--- a/linux/drivers/media/video/vino.c
+++ b/linux/drivers/media/video/vino.c
@@ -30,10 +30,7 @@
#include <linux/mm.h>
#include <linux/time.h>
#include <linux/version.h>
-
-#ifdef CONFIG_KMOD
#include <linux/kmod.h>
-#endif
#include <linux/i2c.h>
#include <linux/i2c-algo-sgi.h>
@@ -4244,8 +4241,7 @@ error:
return ret;
}
-static int vino_do_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, void *arg)
+static int vino_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct vino_channel_settings *vcs = video_drvdata(file);
@@ -4360,7 +4356,7 @@ static int vino_ioctl(struct inode *inode, struct file *file,
if (mutex_lock_interruptible(&vcs->mutex))
return -EINTR;
- ret = video_usercopy(inode, file, cmd, arg, vino_do_ioctl);
+ ret = video_usercopy(file, cmd, arg, vino_do_ioctl);
mutex_unlock(&vcs->mutex);
@@ -4638,7 +4634,7 @@ static int __init vino_module_init(void)
}
vino_init_stage++;
-#if defined(CONFIG_KMOD) && defined(MODULE)
+#ifdef MODULE
request_module("saa7191");
request_module("indycam");
#endif
diff --git a/linux/drivers/media/video/vivi.c b/linux/drivers/media/video/vivi.c
index f6a12b184..692a90c35 100644
--- a/linux/drivers/media/video/vivi.c
+++ b/linux/drivers/media/video/vivi.c
@@ -131,12 +131,56 @@ struct vivi_fmt {
int depth;
};
-static struct vivi_fmt format = {
- .name = "4:2:2, packed, YUYV",
- .fourcc = V4L2_PIX_FMT_YUYV,
- .depth = 16,
+static struct vivi_fmt formats[] = {
+ {
+ .name = "4:2:2, packed, YUYV",
+ .fourcc = V4L2_PIX_FMT_YUYV,
+ .depth = 16,
+ },
+ {
+ .name = "4:2:2, packed, UYVY",
+ .fourcc = V4L2_PIX_FMT_UYVY,
+ .depth = 16,
+ },
+ {
+ .name = "RGB565 (LE)",
+ .fourcc = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
+ .depth = 16,
+ },
+ {
+ .name = "RGB565 (BE)",
+ .fourcc = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
+ .depth = 16,
+ },
+ {
+ .name = "RGB555 (LE)",
+ .fourcc = V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */
+ .depth = 16,
+ },
+ {
+ .name = "RGB555 (BE)",
+ .fourcc = V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */
+ .depth = 16,
+ },
};
+static struct vivi_fmt *get_format(struct v4l2_format *f)
+{
+ struct vivi_fmt *fmt;
+ unsigned int k;
+
+ for (k = 0; k < ARRAY_SIZE(formats); k++) {
+ fmt = &formats[k];
+ if (fmt->fourcc == f->fmt.pix.pixelformat)
+ break;
+ }
+
+ if (k == ARRAY_SIZE(formats))
+ return NULL;
+
+ return &formats[k];
+}
+
struct sg_to_addr {
int pos;
struct scatterlist *sg;
@@ -193,6 +237,7 @@ struct vivi_fh {
struct videobuf_queue vb_vidq;
enum v4l2_buf_type type;
+ unsigned char bars[8][3];
};
/* ------------------------------------------------------------------
@@ -237,42 +282,118 @@ static u8 bars[8][3] = {
#define TSTAMP_MAX_Y TSTAMP_MIN_Y+15
#define TSTAMP_MIN_X 64
-static void gen_line(char *basep, int inipos, int wmax,
- int hmax, int line, int count, char *timestr)
+static void gen_twopix(struct vivi_fh *fh, unsigned char *buf, int colorpos)
{
- int w, i, j, y;
- int pos = inipos;
- char *p, *s;
- u8 chr, r, g, b, color;
+ unsigned char r_y, g_u, b_v;
+ unsigned char *p;
+ int color;
- /* We will just duplicate the second pixel at the packet */
- wmax /= 2;
+ r_y = fh->bars[colorpos][0]; /* R or precalculated Y */
+ g_u = fh->bars[colorpos][1]; /* G or precalculated U */
+ b_v = fh->bars[colorpos][2]; /* B or precalculated V */
- /* Generate a standard color bar pattern */
- for (w = 0; w < wmax; w++) {
- int colorpos = ((w + count) * 8/(wmax + 1)) % 8;
- r = bars[colorpos][0];
- g = bars[colorpos][1];
- b = bars[colorpos][2];
-
- for (color = 0; color < 4; color++) {
- p = basep + pos;
+ for (color = 0; color < 4; color++) {
+ p = buf + color;
+ switch (fh->fmt->fourcc) {
+ case V4L2_PIX_FMT_YUYV:
switch (color) {
case 0:
case 2:
- *p = TO_Y(r, g, b); /* Luma */
+ *p = r_y;
break;
case 1:
- *p = TO_U(r, g, b); /* Cb */
+ *p = g_u;
break;
case 3:
- *p = TO_V(r, g, b); /* Cr */
+ *p = b_v;
+ break;
+ }
+ break;
+ case V4L2_PIX_FMT_UYVY:
+ switch (color) {
+ case 1:
+ case 3:
+ *p = r_y;
+ break;
+ case 0:
+ *p = g_u;
+ break;
+ case 2:
+ *p = b_v;
+ break;
+ }
+ break;
+ case V4L2_PIX_FMT_RGB565:
+ switch (color) {
+ case 0:
+ case 2:
+ *p = (g_u << 5) | b_v;
+ break;
+ case 1:
+ case 3:
+ *p = (r_y << 3) | (g_u >> 3);
+ break;
+ }
+ break;
+ case V4L2_PIX_FMT_RGB565X:
+ switch (color) {
+ case 0:
+ case 2:
+ *p = (r_y << 3) | (g_u >> 3);
+ break;
+ case 1:
+ case 3:
+ *p = (g_u << 5) | b_v;
break;
}
- pos++;
+ break;
+ case V4L2_PIX_FMT_RGB555:
+ switch (color) {
+ case 0:
+ case 2:
+ *p = (g_u << 5) | b_v;
+ break;
+ case 1:
+ case 3:
+ *p = (r_y << 2) | (g_u >> 3);
+ break;
+ }
+ break;
+ case V4L2_PIX_FMT_RGB555X:
+ switch (color) {
+ case 0:
+ case 2:
+ *p = (r_y << 2) | (g_u >> 3);
+ break;
+ case 1:
+ case 3:
+ *p = (g_u << 5) | b_v;
+ break;
+ }
+ break;
}
}
+}
+
+static void gen_line(struct vivi_fh *fh, char *basep, int inipos, int wmax,
+ int hmax, int line, int count, char *timestr)
+{
+ int w, i, j;
+ int pos = inipos;
+ char *s;
+ u8 chr;
+
+ /* We will just duplicate the second pixel at the packet */
+ wmax /= 2;
+
+ /* Generate a standard color bar pattern */
+ for (w = 0; w < wmax; w++) {
+ int colorpos = ((w + count) * 8/(wmax + 1)) % 8;
+
+ gen_twopix(fh, basep + pos, colorpos);
+ pos += 4; /* only 16 bpp supported for now */
+ }
/* Checks if it is possible to show timestamp */
if (TSTAMP_MAX_Y >= hmax)
@@ -286,38 +407,12 @@ static void gen_line(char *basep, int inipos, int wmax,
for (s = timestr; *s; s++) {
chr = rom8x16_bits[(*s-0x30)*16+line-TSTAMP_MIN_Y];
for (i = 0; i < 7; i++) {
- if (chr & 1 << (7 - i)) {
- /* Font color*/
- r = 0;
- g = 198;
- b = 0;
- } else {
- /* Background color */
- r = bars[BLACK][0];
- g = bars[BLACK][1];
- b = bars[BLACK][2];
- }
-
pos = inipos + j * 2;
- for (color = 0; color < 4; color++) {
- p = basep + pos;
-
- y = TO_Y(r, g, b);
-
- switch (color) {
- case 0:
- case 2:
- *p = TO_Y(r, g, b); /* Luma */
- break;
- case 1:
- *p = TO_U(r, g, b); /* Cb */
- break;
- case 3:
- *p = TO_V(r, g, b); /* Cr */
- break;
- }
- pos++;
- }
+ /* Draw white font on black background */
+ if (chr & 1 << (7 - i))
+ gen_twopix(fh, basep + pos, WHITE);
+ else
+ gen_twopix(fh, basep + pos, BLACK);
j++;
}
}
@@ -327,8 +422,9 @@ end:
return;
}
-static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf)
+static void vivi_fillbuff(struct vivi_fh *fh, struct vivi_buffer *buf)
{
+ struct vivi_dev *dev = fh->dev;
int h , pos = 0;
int hmax = buf->vb.height;
int wmax = buf->vb.width;
@@ -344,7 +440,7 @@ static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf)
return;
for (h = 0; h < hmax; h++) {
- gen_line(tmpbuf, 0, wmax, hmax, h, dev->mv_count,
+ gen_line(fh, tmpbuf, 0, wmax, hmax, h, dev->mv_count,
dev->timestr);
memcpy(vbuf + pos, tmpbuf, wmax * 2);
pos += wmax*2;
@@ -413,7 +509,7 @@ static void vivi_thread_tick(struct vivi_fh *fh)
do_gettimeofday(&buf->vb.ts);
/* Fill buffer */
- vivi_fillbuff(dev, buf);
+ vivi_fillbuff(fh, buf);
dprintk(dev, 1, "filled buffer %p\n", buf);
wake_up(&buf->vb.done);
@@ -639,11 +735,15 @@ static int vidioc_querycap(struct file *file, void *priv,
static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
- if (f->index > 0)
+ struct vivi_fmt *fmt;
+
+ if (f->index >= ARRAY_SIZE(formats))
return -EINVAL;
- strlcpy(f->description, format.name, sizeof(f->description));
- f->pixelformat = format.fourcc;
+ fmt = &formats[f->index];
+
+ strlcpy(f->description, fmt->name, sizeof(f->description));
+ f->pixelformat = fmt->fourcc;
return 0;
}
@@ -673,13 +773,12 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
enum v4l2_field field;
unsigned int maxw, maxh;
- if (format.fourcc != f->fmt.pix.pixelformat) {
- dprintk(dev, 1, "Fourcc format (0x%08x) invalid. "
- "Driver accepts only 0x%08x\n",
- f->fmt.pix.pixelformat, format.fourcc);
+ fmt = get_format(f);
+ if (!fmt) {
+ dprintk(dev, 1, "Fourcc format (0x%08x) invalid.\n",
+ f->fmt.pix.pixelformat);
return -EINVAL;
}
- fmt = &format;
field = f->fmt.pix.field;
@@ -717,6 +816,8 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
{
struct vivi_fh *fh = priv;
struct videobuf_queue *q = &fh->vb_vidq;
+ unsigned char r, g, b;
+ int k, is_yuv;
int ret = vidioc_try_fmt_vid_cap(file, fh, f);
if (ret < 0)
@@ -730,12 +831,49 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
goto out;
}
- fh->fmt = &format;
+ fh->fmt = get_format(f);
fh->width = f->fmt.pix.width;
fh->height = f->fmt.pix.height;
fh->vb_vidq.field = f->fmt.pix.field;
fh->type = f->type;
+ /* precalculate color bar values to speed up rendering */
+ for (k = 0; k < 8; k++) {
+ r = bars[k][0];
+ g = bars[k][1];
+ b = bars[k][2];
+ is_yuv = 0;
+
+ switch (fh->fmt->fourcc) {
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_UYVY:
+ is_yuv = 1;
+ break;
+ case V4L2_PIX_FMT_RGB565:
+ case V4L2_PIX_FMT_RGB565X:
+ r >>= 3;
+ g >>= 2;
+ b >>= 3;
+ break;
+ case V4L2_PIX_FMT_RGB555:
+ case V4L2_PIX_FMT_RGB555X:
+ r >>= 3;
+ g >>= 3;
+ b >>= 3;
+ break;
+ }
+
+ if (is_yuv) {
+ fh->bars[k][0] = TO_Y(r, g, b); /* Luma */
+ fh->bars[k][1] = TO_U(r, g, b); /* Cb */
+ fh->bars[k][2] = TO_V(r, g, b); /* Cr */
+ } else {
+ fh->bars[k][0] = r;
+ fh->bars[k][1] = g;
+ fh->bars[k][2] = b;
+ }
+ }
+
ret = 0;
out:
mutex_unlock(&q->vb_lock);
@@ -889,8 +1027,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
File operations for the device
------------------------------------------------------------------*/
-#define line_buf_size(norm) (norm_maxw(norm)*(format.depth+7)/8)
-
static int vivi_open(struct inode *inode, struct file *file)
{
int minor = iminor(inode);
@@ -939,7 +1075,7 @@ unlock:
fh->dev = dev;
fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- fh->fmt = &format;
+ fh->fmt = &formats[0];
fh->width = 640;
fh->height = 480;
@@ -1030,11 +1166,11 @@ static int vivi_release(void)
if (-1 != dev->vfd->minor) {
printk(KERN_INFO "%s: unregistering /dev/video%d\n",
- VIVI_MODULE_NAME, dev->vfd->minor);
+ VIVI_MODULE_NAME, dev->vfd->num);
video_unregister_device(dev->vfd);
} else {
printk(KERN_INFO "%s: releasing /dev/video%d\n",
- VIVI_MODULE_NAME, dev->vfd->minor);
+ VIVI_MODULE_NAME, dev->vfd->num);
video_device_release(dev->vfd);
}
@@ -1174,7 +1310,7 @@ static int __init vivi_init(void)
dev->vfd = vfd;
printk(KERN_INFO "%s: V4L2 device registered as /dev/video%d\n",
- VIVI_MODULE_NAME, vfd->minor);
+ VIVI_MODULE_NAME, vfd->num);
}
if (ret < 0) {
diff --git a/linux/drivers/media/video/w9966.c b/linux/drivers/media/video/w9966.c
index f3f28c232..53f317dcd 100644
--- a/linux/drivers/media/video/w9966.c
+++ b/linux/drivers/media/video/w9966.c
@@ -728,8 +728,7 @@ static int w9966_wReg_i2c(struct w9966_dev* cam, int reg, int data)
* Video4linux interfacing
*/
-static int w9966_v4l_do_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, void *arg)
+static int w9966_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct w9966_dev *cam = video_drvdata(file);
@@ -882,7 +881,7 @@ static int w9966_v4l_do_ioctl(struct inode *inode, struct file *file,
static int w9966_v4l_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- return video_usercopy(inode, file, cmd, arg, w9966_v4l_do_ioctl);
+ return video_usercopy(file, cmd, arg, w9966_v4l_do_ioctl);
}
// Capture data
diff --git a/linux/drivers/media/video/w9968cf.c b/linux/drivers/media/video/w9968cf.c
index 4e7a8400b..ab3c054c4 100644
--- a/linux/drivers/media/video/w9968cf.c
+++ b/linux/drivers/media/video/w9968cf.c
@@ -111,7 +111,7 @@ static int specific_debug = W9968CF_SPECIFIC_DEBUG;
static unsigned int param_nv[24]; /* number of values per parameter */
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
module_param(ovmod_load, bool, 0644);
#endif
module_param(simcams, ushort, 0644);
@@ -144,7 +144,7 @@ module_param(debug, ushort, 0644);
module_param(specific_debug, bool, 0644);
#endif
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
MODULE_PARM_DESC(ovmod_load,
"\n<0|1> Automatic 'ovcamchip' module loading."
"\n0 disabled, 1 enabled."
@@ -2406,7 +2406,7 @@ error:
cam->sensor = CC_UNKNOWN;
DBG(1, "Image sensor initialization failed for %s (/dev/video%d). "
"Try to detach and attach this device again",
- symbolic(camlist, cam->id), cam->v4ldev->minor)
+ symbolic(camlist, cam->id), cam->v4ldev->num)
return err;
}
@@ -2652,7 +2652,7 @@ static void w9968cf_release_resources(struct w9968cf_device* cam)
{
mutex_lock(&w9968cf_devlist_mutex);
- DBG(2, "V4L device deregistered: /dev/video%d", cam->v4ldev->minor)
+ DBG(2, "V4L device deregistered: /dev/video%d", cam->v4ldev->num)
video_unregister_device(cam->v4ldev);
list_del(&cam->v4llist);
@@ -2687,7 +2687,7 @@ static int w9968cf_open(struct inode* inode, struct file* filp)
DBG(2, "No supported image sensor has been detected by the "
"'ovcamchip' module for the %s (/dev/video%d). Make "
"sure it is loaded *before* (re)connecting the camera.",
- symbolic(camlist, cam->id), cam->v4ldev->minor)
+ symbolic(camlist, cam->id), cam->v4ldev->num)
mutex_unlock(&cam->dev_mutex);
up_read(&w9968cf_disconnect);
return -ENODEV;
@@ -2695,7 +2695,7 @@ static int w9968cf_open(struct inode* inode, struct file* filp)
if (cam->users) {
DBG(2, "%s (/dev/video%d) has been already occupied by '%s'",
- symbolic(camlist, cam->id),cam->v4ldev->minor,cam->command)
+ symbolic(camlist, cam->id), cam->v4ldev->num, cam->command)
if ((filp->f_flags & O_NONBLOCK)||(filp->f_flags & O_NDELAY)) {
mutex_unlock(&cam->dev_mutex);
up_read(&w9968cf_disconnect);
@@ -2717,7 +2717,7 @@ static int w9968cf_open(struct inode* inode, struct file* filp)
}
DBG(5, "Opening '%s', /dev/video%d ...",
- symbolic(camlist, cam->id), cam->v4ldev->minor)
+ symbolic(camlist, cam->id), cam->v4ldev->num)
cam->streaming = 0;
cam->misconfigured = 0;
@@ -2955,7 +2955,7 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp,
.minheight = cam->minheight,
};
sprintf(cap.name, "W996[87]CF USB Camera #%d",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
cap.maxwidth = (cam->upscaling && w9968cf_vpp)
? max((u16)W9968CF_MAX_WIDTH, cam->maxwidth)
: cam->maxwidth;
@@ -3575,7 +3575,7 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
goto fail;
}
- DBG(2, "V4L device registered as /dev/video%d", cam->v4ldev->minor)
+ DBG(2, "V4L device registered as /dev/video%d", cam->v4ldev->num)
/* Set some basic constants */
w9968cf_configure_camera(cam, udev, mod_id, dev_nr);
@@ -3626,7 +3626,7 @@ static void w9968cf_usb_disconnect(struct usb_interface* intf)
DBG(2, "The device is open (/dev/video%d)! "
"Process name: %s. Deregistration and memory "
"deallocation are deferred on close.",
- cam->v4ldev->minor, cam->command)
+ cam->v4ldev->num, cam->command)
cam->misconfigured = 1;
w9968cf_stop_transfer(cam);
wake_up_interruptible(&cam->wait_queue);
diff --git a/linux/drivers/media/video/zc0301/zc0301_core.c b/linux/drivers/media/video/zc0301/zc0301_core.c
index 0be0f095e..a8c1f6730 100644
--- a/linux/drivers/media/video/zc0301/zc0301_core.c
+++ b/linux/drivers/media/video/zc0301/zc0301_core.c
@@ -543,7 +543,7 @@ static int zc0301_stream_interrupt(struct zc0301_device* cam)
cam->state |= DEV_MISCONFIGURED;
DBG(1, "URB timeout reached. The camera is misconfigured. To "
"use it, close and open /dev/video%d again.",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
return -EIO;
}
@@ -644,7 +644,7 @@ static void zc0301_release_resources(struct kref *kref)
{
struct zc0301_device *cam = container_of(kref, struct zc0301_device,
kref);
- DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor);
+ DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->num);
video_set_drvdata(cam->v4ldev, NULL);
video_unregister_device(cam->v4ldev);
usb_put_dev(cam->usbdev);
@@ -683,7 +683,7 @@ static int zc0301_open(struct inode* inode, struct file* filp)
}
if (cam->users) {
- DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor);
+ DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->num);
DBG(3, "Simultaneous opens are not supported");
if ((filp->f_flags & O_NONBLOCK) ||
(filp->f_flags & O_NDELAY)) {
@@ -726,7 +726,7 @@ static int zc0301_open(struct inode* inode, struct file* filp)
cam->frame_count = 0;
zc0301_empty_framequeues(cam);
- DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor);
+ DBG(3, "Video device /dev/video%d is open", cam->v4ldev->num);
out:
mutex_unlock(&cam->open_mutex);
@@ -750,7 +750,7 @@ static int zc0301_release(struct inode* inode, struct file* filp)
cam->users--;
wake_up_interruptible_nr(&cam->wait_open, 1);
- DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor);
+ DBG(3, "Video device /dev/video%d closed", cam->v4ldev->num);
kref_put(&cam->kref, zc0301_release_resources);
@@ -1024,7 +1024,7 @@ zc0301_vidioc_querycap(struct zc0301_device* cam, void __user * arg)
strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card));
if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0)
- strlcpy(cap.bus_info, cam->usbdev->dev.bus_id,
+ strlcpy(cap.bus_info, dev_name(&cam->usbdev->dev),
sizeof(cap.bus_info));
if (copy_to_user(arg, &cap, sizeof(cap)))
@@ -1279,7 +1279,7 @@ zc0301_vidioc_s_crop(struct zc0301_device* cam, void __user * arg)
cam->state |= DEV_MISCONFIGURED;
DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To "
"use the camera, close and open /dev/video%d again.",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
return -EIO;
}
@@ -1292,7 +1292,7 @@ zc0301_vidioc_s_crop(struct zc0301_device* cam, void __user * arg)
cam->state |= DEV_MISCONFIGURED;
DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To "
"use the camera, close and open /dev/video%d again.",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
return -ENOMEM;
}
@@ -1474,7 +1474,7 @@ zc0301_vidioc_try_s_fmt(struct zc0301_device* cam, unsigned int cmd,
cam->state |= DEV_MISCONFIGURED;
DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To "
"use the camera, close and open /dev/video%d again.",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
return -EIO;
}
@@ -1486,7 +1486,7 @@ zc0301_vidioc_try_s_fmt(struct zc0301_device* cam, unsigned int cmd,
cam->state |= DEV_MISCONFIGURED;
DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To "
"use the camera, close and open /dev/video%d again.",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
return -ENOMEM;
}
@@ -1533,7 +1533,7 @@ zc0301_vidioc_s_jpegcomp(struct zc0301_device* cam, void __user * arg)
cam->state |= DEV_MISCONFIGURED;
DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware "
"problems. To use the camera, close and open "
- "/dev/video%d again.", cam->v4ldev->minor);
+ "/dev/video%d again.", cam->v4ldev->num);
return -EIO;
}
@@ -2009,7 +2009,7 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
goto fail;
}
- DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor);
+ DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->num);
cam->module_param.force_munmap = force_munmap[dev_nr];
cam->module_param.frame_timeout = frame_timeout[dev_nr];
@@ -2048,7 +2048,7 @@ static void zc0301_usb_disconnect(struct usb_interface* intf)
if (cam->users) {
DBG(2, "Device /dev/video%d is open! Deregistration and "
"memory deallocation are deferred.",
- cam->v4ldev->minor);
+ cam->v4ldev->num);
cam->state |= DEV_MISCONFIGURED;
zc0301_stop_transfer(cam);
cam->state |= DEV_DISCONNECTED;
diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c
index 9d57a630c..605195a82 100644
--- a/linux/drivers/media/video/zoran/zoran_driver.c
+++ b/linux/drivers/media/video/zoran/zoran_driver.c
@@ -2005,11 +2005,7 @@ zoran_set_input (struct zoran *zr,
* ioctl routine
*/
-static int
-zoran_do_ioctl (struct inode *inode,
- struct file *file,
- unsigned int cmd,
- void *arg)
+static int zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct zoran_fh *fh = file->private_data;
struct zoran *zr = fh->zr;
@@ -3061,7 +3057,6 @@ zoran_do_ioctl (struct inode *inode,
break;
default:
- dprintk(3, "unsupported\n");
dprintk(1,
KERN_ERR
"%s: VIDIOC_S_FMT - unsupported type %d\n",
@@ -4267,7 +4262,7 @@ zoran_ioctl (struct inode *inode,
unsigned int cmd,
unsigned long arg)
{
- return video_usercopy(inode, file, cmd, arg, zoran_do_ioctl);
+ return video_usercopy(file, cmd, arg, zoran_do_ioctl);
}
static unsigned int
diff --git a/linux/drivers/media/video/zr364xx.c b/linux/drivers/media/video/zr364xx.c
index b0da282a5..1f43328a5 100644
--- a/linux/drivers/media/video/zr364xx.c
+++ b/linux/drivers/media/video/zr364xx.c
@@ -886,7 +886,7 @@ static int zr364xx_probe(struct usb_interface *intf,
usb_set_intfdata(intf, cam);
dev_info(&udev->dev, DRIVER_DESC " controlling video device %d\n",
- cam->vdev->minor);
+ cam->vdev->num);
return 0;
}