aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/pci
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-06-25 17:55:48 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2015-06-25 17:55:48 -0700
commit5b4ca4447757019f11a601b0009534ef84bed801 (patch)
tree09bc8445e61aea621580d7587c21ac3f2b0cafb4 /drivers/media/pci
parentMerge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux (diff)
parent[media] lmedm04: fix the range for relative measurements (diff)
downloadlinux-dev-5b4ca4447757019f11a601b0009534ef84bed801.tar.xz
linux-dev-5b4ca4447757019f11a601b0009534ef84bed801.zip
Merge tag 'media/v4.2-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab: - Lots of improvements at the DVB API DocBook documentation. Now, the frontend and the network APIs are fully in sync with the Kernel and looks more like the rest of the media documentation; - New frontend driver: cx24120 - New driver for a PCI device: cobalt. This driver is actually not sold in the market, but it is a good example of a multi-HDMI input device; - The dt3155 driver were promoted from staging; - The mantis driver got remote controller support; - New V4L2 driver for ST bdisp SoC chipsets; - Make sparse and smatch happier: several bugs were solved by fixing the issues reported by those static code analyzers. - Lots of new device additions, new features, improvements and cleanups at the existing drivers. * tag 'media/v4.2-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (553 commits) [media] lmedm04: fix the range for relative measurements [media] lmedm04: use u32 instead of u64 for relative stats [media] omap3isp: remove unused var [media] saa7134: fix page size on some archs [media] use CONFIG_PM_SLEEP for suspend/resume [media] tuner-i2c: be consistent with I2C declaration [media] si470x: cleanup define namespace [media] bdisp: prevent compiling on random arch [media] vb2: Don't WARN when v4l2_buffer.bytesused is 0 for multiplanar buffers [media] MAINTAINERS: Add entry for the Renesas VSP1 driver [media] videodev2.h: fix copy-and-paste error in V4L2_MAP_XFER_FUNC_DEFAULT [media] Revert "[media] vb2: Push mmap_sem down to memops" [media] mantis: cleanup a warning [media] bdisp-debug: don't try to divide by s64 [media] cx88: don't declare restart_video_queue if not used [media] au0828: move dev->boards atribuition to happen earlier [media] lmedm04: implement dvb v5 statistics [media] bdisp: remove unused var [media] bdisp: remove needless check ts2020: fix compilation on i386 ...
Diffstat (limited to 'drivers/media/pci')
-rw-r--r--drivers/media/pci/Kconfig2
-rw-r--r--drivers/media/pci/Makefile2
-rw-r--r--drivers/media/pci/bt8xx/bttv-audio-hook.c443
-rw-r--r--drivers/media/pci/bt8xx/bttv-driver.c5
-rw-r--r--drivers/media/pci/bt8xx/dst.c25
-rw-r--r--drivers/media/pci/bt8xx/dst_ca.c138
-rw-r--r--drivers/media/pci/bt8xx/dst_common.h12
-rw-r--r--drivers/media/pci/cobalt/Kconfig18
-rw-r--r--drivers/media/pci/cobalt/Makefile5
-rw-r--r--drivers/media/pci/cobalt/cobalt-alsa-main.c162
-rw-r--r--drivers/media/pci/cobalt/cobalt-alsa-pcm.c603
-rw-r--r--drivers/media/pci/cobalt/cobalt-alsa-pcm.h22
-rw-r--r--drivers/media/pci/cobalt/cobalt-alsa.h41
-rw-r--r--drivers/media/pci/cobalt/cobalt-cpld.c341
-rw-r--r--drivers/media/pci/cobalt/cobalt-cpld.h29
-rw-r--r--drivers/media/pci/cobalt/cobalt-driver.c832
-rw-r--r--drivers/media/pci/cobalt/cobalt-driver.h380
-rw-r--r--drivers/media/pci/cobalt/cobalt-flash.c128
-rw-r--r--drivers/media/pci/cobalt/cobalt-flash.h29
-rw-r--r--drivers/media/pci/cobalt/cobalt-i2c.c396
-rw-r--r--drivers/media/pci/cobalt/cobalt-i2c.h25
-rw-r--r--drivers/media/pci/cobalt/cobalt-irq.c258
-rw-r--r--drivers/media/pci/cobalt/cobalt-irq.h25
-rw-r--r--drivers/media/pci/cobalt/cobalt-omnitek.c341
-rw-r--r--drivers/media/pci/cobalt/cobalt-omnitek.h62
-rw-r--r--drivers/media/pci/cobalt/cobalt-v4l2.c1272
-rw-r--r--drivers/media/pci/cobalt/cobalt-v4l2.h22
-rw-r--r--drivers/media/pci/cobalt/m00233_video_measure_memmap_package.h115
-rw-r--r--drivers/media/pci/cobalt/m00235_fdma_packer_memmap_package.h44
-rw-r--r--drivers/media/pci/cobalt/m00389_cvi_memmap_package.h59
-rw-r--r--drivers/media/pci/cobalt/m00460_evcnt_memmap_package.h44
-rw-r--r--drivers/media/pci/cobalt/m00473_freewheel_memmap_package.h57
-rw-r--r--drivers/media/pci/cobalt/m00479_clk_loss_detector_memmap_package.h53
-rw-r--r--drivers/media/pci/cobalt/m00514_syncgen_flow_evcnt_memmap_package.h88
-rw-r--r--drivers/media/pci/cx18/cx18-av-core.c16
-rw-r--r--drivers/media/pci/cx18/cx18-controls.c13
-rw-r--r--drivers/media/pci/cx18/cx18-driver.c4
-rw-r--r--drivers/media/pci/cx18/cx18-ioctl.c12
-rw-r--r--drivers/media/pci/cx18/cx18-streams.c1
-rw-r--r--drivers/media/pci/cx23885/altera-ci.c2
-rw-r--r--drivers/media/pci/cx23885/cx23885-dvb.c150
-rw-r--r--drivers/media/pci/cx23885/cx23885-f300.c2
-rw-r--r--drivers/media/pci/cx23885/cx23885-f300.h2
-rw-r--r--drivers/media/pci/cx23885/cx23885-video.c12
-rw-r--r--drivers/media/pci/cx23885/cx23885.h3
-rw-r--r--drivers/media/pci/cx88/cx88-core.c2
-rw-r--r--drivers/media/pci/cx88/cx88-dvb.c12
-rw-r--r--drivers/media/pci/cx88/cx88-mpeg.c6
-rw-r--r--drivers/media/pci/cx88/cx88-vbi.c6
-rw-r--r--drivers/media/pci/cx88/cx88-video.c9
-rw-r--r--drivers/media/pci/cx88/cx88.h6
-rw-r--r--drivers/media/pci/ddbridge/ddbridge-core.c3
-rw-r--r--drivers/media/pci/dm1105/dm1105.c3
-rw-r--r--drivers/media/pci/dt3155/Kconfig13
-rw-r--r--drivers/media/pci/dt3155/Makefile1
-rw-r--r--drivers/media/pci/dt3155/dt3155.c632
-rw-r--r--drivers/media/pci/dt3155/dt3155.h196
-rw-r--r--drivers/media/pci/ivtv/ivtv-controls.c12
-rw-r--r--drivers/media/pci/ivtv/ivtv-driver.c4
-rw-r--r--drivers/media/pci/ivtv/ivtv-driver.h3
-rw-r--r--drivers/media/pci/ivtv/ivtv-ioctl.c15
-rw-r--r--drivers/media/pci/mantis/hopper_cards.c14
-rw-r--r--drivers/media/pci/mantis/mantis_cards.c94
-rw-r--r--drivers/media/pci/mantis/mantis_common.h33
-rw-r--r--drivers/media/pci/mantis/mantis_dma.c5
-rw-r--r--drivers/media/pci/mantis/mantis_i2c.c12
-rw-r--r--drivers/media/pci/mantis/mantis_input.c110
-rw-r--r--drivers/media/pci/mantis/mantis_input.h24
-rw-r--r--drivers/media/pci/mantis/mantis_pcmcia.c4
-rw-r--r--drivers/media/pci/mantis/mantis_uart.c61
-rw-r--r--drivers/media/pci/mantis/mantis_vp1034.c2
-rw-r--r--drivers/media/pci/mantis/mantis_vp1034.h3
-rw-r--r--drivers/media/pci/ngene/ngene-core.c10
-rw-r--r--drivers/media/pci/ngene/ngene.h2
-rw-r--r--drivers/media/pci/pt1/pt1.c6
-rw-r--r--drivers/media/pci/pt1/va1j5jf8007s.c4
-rw-r--r--drivers/media/pci/pt1/va1j5jf8007t.c4
-rw-r--r--drivers/media/pci/pt3/pt3.c2
-rw-r--r--drivers/media/pci/saa7134/saa7134-alsa.c55
-rw-r--r--drivers/media/pci/saa7134/saa7134-cards.c150
-rw-r--r--drivers/media/pci/saa7134/saa7134-core.c161
-rw-r--r--drivers/media/pci/saa7134/saa7134-dvb.c122
-rw-r--r--drivers/media/pci/saa7134/saa7134-empress.c55
-rw-r--r--drivers/media/pci/saa7134/saa7134-go7007.c11
-rw-r--r--drivers/media/pci/saa7134/saa7134-i2c.c87
-rw-r--r--drivers/media/pci/saa7134/saa7134-input.c59
-rw-r--r--drivers/media/pci/saa7134/saa7134-ts.c24
-rw-r--r--drivers/media/pci/saa7134/saa7134-tvaudio.c168
-rw-r--r--drivers/media/pci/saa7134/saa7134-vbi.c14
-rw-r--r--drivers/media/pci/saa7134/saa7134-video.c43
-rw-r--r--drivers/media/pci/saa7134/saa7134.h6
-rw-r--r--drivers/media/pci/saa7164/saa7164-api.c11
-rw-r--r--drivers/media/pci/saa7164/saa7164-buffer.c2
-rw-r--r--drivers/media/pci/saa7164/saa7164-bus.c2
-rw-r--r--drivers/media/pci/saa7164/saa7164-cards.c188
-rw-r--r--drivers/media/pci/saa7164/saa7164-cmd.c2
-rw-r--r--drivers/media/pci/saa7164/saa7164-core.c82
-rw-r--r--drivers/media/pci/saa7164/saa7164-dvb.c241
-rw-r--r--drivers/media/pci/saa7164/saa7164-encoder.c13
-rw-r--r--drivers/media/pci/saa7164/saa7164-fw.c2
-rw-r--r--drivers/media/pci/saa7164/saa7164-i2c.c9
-rw-r--r--drivers/media/pci/saa7164/saa7164-reg.h2
-rw-r--r--drivers/media/pci/saa7164/saa7164-types.h2
-rw-r--r--drivers/media/pci/saa7164/saa7164-vbi.c13
-rw-r--r--drivers/media/pci/saa7164/saa7164.h8
-rw-r--r--drivers/media/pci/smipcie/smipcie.c1
-rw-r--r--drivers/media/pci/sta2x11/sta2x11_vip.c3
-rw-r--r--drivers/media/pci/ttpci/av7110.c18
-rw-r--r--drivers/media/pci/ttpci/av7110.h27
-rw-r--r--drivers/media/pci/ttpci/budget-core.c3
-rw-r--r--drivers/media/pci/ttpci/budget-patch.c15
-rw-r--r--drivers/media/pci/ttpci/budget.c12
-rw-r--r--drivers/media/pci/ttpci/budget.h2
-rw-r--r--drivers/media/pci/zoran/zoran_device.c13
114 files changed, 8148 insertions, 1086 deletions
diff --git a/drivers/media/pci/Kconfig b/drivers/media/pci/Kconfig
index 218144a99016..f318ae9bb57a 100644
--- a/drivers/media/pci/Kconfig
+++ b/drivers/media/pci/Kconfig
@@ -21,6 +21,7 @@ source "drivers/media/pci/zoran/Kconfig"
source "drivers/media/pci/saa7146/Kconfig"
source "drivers/media/pci/solo6x10/Kconfig"
source "drivers/media/pci/tw68/Kconfig"
+source "drivers/media/pci/dt3155/Kconfig"
endif
if MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT
@@ -32,6 +33,7 @@ source "drivers/media/pci/cx88/Kconfig"
source "drivers/media/pci/bt8xx/Kconfig"
source "drivers/media/pci/saa7134/Kconfig"
source "drivers/media/pci/saa7164/Kconfig"
+source "drivers/media/pci/cobalt/Kconfig"
endif
diff --git a/drivers/media/pci/Makefile b/drivers/media/pci/Makefile
index 0baf0d2967ee..23ce53bd47c3 100644
--- a/drivers/media/pci/Makefile
+++ b/drivers/media/pci/Makefile
@@ -24,6 +24,8 @@ obj-$(CONFIG_VIDEO_BT848) += bt8xx/
obj-$(CONFIG_VIDEO_SAA7134) += saa7134/
obj-$(CONFIG_VIDEO_SAA7164) += saa7164/
obj-$(CONFIG_VIDEO_TW68) += tw68/
+obj-$(CONFIG_VIDEO_DT3155) += dt3155/
obj-$(CONFIG_VIDEO_MEYE) += meye/
obj-$(CONFIG_STA2X11_VIP) += sta2x11/
obj-$(CONFIG_VIDEO_SOLO6X10) += solo6x10/
+obj-$(CONFIG_VIDEO_COBALT) += cobalt/
diff --git a/drivers/media/pci/bt8xx/bttv-audio-hook.c b/drivers/media/pci/bt8xx/bttv-audio-hook.c
index 2364d16586b3..9f1f9169fb5b 100644
--- a/drivers/media/pci/bt8xx/bttv-audio-hook.c
+++ b/drivers/media/pci/bt8xx/bttv-audio-hook.c
@@ -54,23 +54,33 @@ void winview_volume(struct bttv *btv, __u16 volume)
void gvbctv3pci_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
{
- unsigned int con = 0;
+ unsigned int con;
- if (set) {
- gpio_inout(0x300, 0x300);
- if (t->audmode & V4L2_TUNER_MODE_LANG1)
- con = 0x000;
- if (t->audmode & V4L2_TUNER_MODE_LANG2)
- con = 0x300;
- if (t->audmode & V4L2_TUNER_MODE_STEREO)
- con = 0x200;
-/* if (t->audmode & V4L2_TUNER_MODE_MONO)
- * con = 0x100; */
- gpio_bits(0x300, con);
- } else {
- t->audmode = V4L2_TUNER_MODE_STEREO |
- V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
+ if (!set) {
+ /* Not much to do here */
+ t->audmode = V4L2_TUNER_MODE_LANG1;
+ t->rxsubchans = V4L2_TUNER_SUB_MONO |
+ V4L2_TUNER_SUB_STEREO |
+ V4L2_TUNER_SUB_LANG1 |
+ V4L2_TUNER_SUB_LANG2;
+
+ return;
+ }
+
+ gpio_inout(0x300, 0x300);
+ switch (t->audmode) {
+ case V4L2_TUNER_MODE_LANG1:
+ default:
+ con = 0x000;
+ break;
+ case V4L2_TUNER_MODE_LANG2:
+ con = 0x300;
+ break;
+ case V4L2_TUNER_MODE_STEREO:
+ con = 0x200;
+ break;
}
+ gpio_bits(0x300, con);
}
void gvbctv5pci_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
@@ -82,47 +92,51 @@ void gvbctv5pci_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
val = gpio_read();
if (set) {
- con = 0x000;
- if (t->audmode & V4L2_TUNER_MODE_LANG2) {
- if (t->audmode & V4L2_TUNER_MODE_LANG1) {
- /* LANG1 + LANG2 */
- con = 0x100;
- }
- else {
- /* LANG2 */
- con = 0x300;
- }
+ switch (t->audmode) {
+ case V4L2_TUNER_MODE_LANG2:
+ con = 0x300;
+ break;
+ case V4L2_TUNER_MODE_LANG1_LANG2:
+ con = 0x100;
+ break;
+ default:
+ con = 0x000;
+ break;
}
if (con != (val & 0x300)) {
gpio_bits(0x300, con);
if (bttv_gpio)
- bttv_gpio_tracking(btv,"gvbctv5pci");
+ bttv_gpio_tracking(btv, "gvbctv5pci");
}
} else {
switch (val & 0x70) {
case 0x10:
t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+ t->audmode = V4L2_TUNER_MODE_LANG1_LANG2;
break;
case 0x30:
t->rxsubchans = V4L2_TUNER_SUB_LANG2;
+ t->audmode = V4L2_TUNER_MODE_LANG1_LANG2;
break;
case 0x50:
t->rxsubchans = V4L2_TUNER_SUB_LANG1;
+ t->audmode = V4L2_TUNER_MODE_LANG1_LANG2;
break;
case 0x60:
t->rxsubchans = V4L2_TUNER_SUB_STEREO;
+ t->audmode = V4L2_TUNER_MODE_STEREO;
break;
case 0x70:
t->rxsubchans = V4L2_TUNER_SUB_MONO;
+ t->audmode = V4L2_TUNER_MODE_MONO;
break;
default:
t->rxsubchans = V4L2_TUNER_SUB_MONO |
V4L2_TUNER_SUB_STEREO |
V4L2_TUNER_SUB_LANG1 |
V4L2_TUNER_SUB_LANG2;
+ t->audmode = V4L2_TUNER_MODE_LANG1;
}
- t->audmode = V4L2_TUNER_MODE_STEREO |
- V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
}
}
@@ -142,23 +156,32 @@ void gvbctv5pci_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
void avermedia_tvphone_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
{
- int val = 0;
+ int val;
- if (set) {
- if (t->audmode & V4L2_TUNER_MODE_LANG2) /* SAP */
- val = 0x02;
- if (t->audmode & V4L2_TUNER_MODE_STEREO)
- val = 0x01;
- if (val) {
- gpio_bits(0x03,val);
- if (bttv_gpio)
- bttv_gpio_tracking(btv,"avermedia");
- }
- } else {
- t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
- V4L2_TUNER_MODE_LANG1;
+ if (!set) {
+ /* Not much to do here */
+ t->audmode = V4L2_TUNER_MODE_LANG1;
+ t->rxsubchans = V4L2_TUNER_SUB_MONO |
+ V4L2_TUNER_SUB_STEREO |
+ V4L2_TUNER_SUB_LANG1 |
+ V4L2_TUNER_SUB_LANG2;
+
+ return;
+ }
+
+ switch (t->audmode) {
+ case V4L2_TUNER_MODE_LANG2: /* SAP */
+ val = 0x02;
+ break;
+ case V4L2_TUNER_MODE_STEREO:
+ val = 0x01;
+ break;
+ default:
return;
}
+ gpio_bits(0x03, val);
+ if (bttv_gpio)
+ bttv_gpio_tracking(btv, "avermedia");
}
@@ -166,19 +189,31 @@ void avermedia_tv_stereo_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
{
int val = 0;
- if (set) {
- if (t->audmode & V4L2_TUNER_MODE_LANG2) /* SAP */
- val = 0x01;
- if (t->audmode & V4L2_TUNER_MODE_STEREO) /* STEREO */
- val = 0x02;
- btaor(val, ~0x03, BT848_GPIO_DATA);
- if (bttv_gpio)
- bttv_gpio_tracking(btv,"avermedia");
- } else {
- t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
- V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
+ if (!set) {
+ /* Not much to do here */
+ t->audmode = V4L2_TUNER_MODE_LANG1;
+ t->rxsubchans = V4L2_TUNER_SUB_MONO |
+ V4L2_TUNER_SUB_STEREO |
+ V4L2_TUNER_SUB_LANG1 |
+ V4L2_TUNER_SUB_LANG2;
+
return;
}
+
+ switch (t->audmode) {
+ case V4L2_TUNER_MODE_LANG2: /* SAP */
+ val = 0x01;
+ break;
+ case V4L2_TUNER_MODE_STEREO:
+ val = 0x02;
+ break;
+ default:
+ val = 0;
+ break;
+ }
+ btaor(val, ~0x03, BT848_GPIO_DATA);
+ if (bttv_gpio)
+ bttv_gpio_tracking(btv, "avermedia");
}
/* Lifetec 9415 handling */
@@ -192,23 +227,32 @@ void lt9415_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
return;
}
- if (set) {
- if (t->audmode & V4L2_TUNER_MODE_LANG2) /* A2 SAP */
- val = 0x0080;
- if (t->audmode & V4L2_TUNER_MODE_STEREO) /* A2 stereo */
- val = 0x0880;
- if ((t->audmode & V4L2_TUNER_MODE_LANG1) ||
- (t->audmode & V4L2_TUNER_MODE_MONO))
- val = 0;
- gpio_bits(0x0880, val);
- if (bttv_gpio)
- bttv_gpio_tracking(btv,"lt9415");
- } else {
- /* autodetect doesn't work with this card :-( */
- t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
- V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
+ if (!set) {
+ /* Not much to do here */
+ t->audmode = V4L2_TUNER_MODE_LANG1;
+ t->rxsubchans = V4L2_TUNER_SUB_MONO |
+ V4L2_TUNER_SUB_STEREO |
+ V4L2_TUNER_SUB_LANG1 |
+ V4L2_TUNER_SUB_LANG2;
+
return;
}
+
+ switch (t->audmode) {
+ case V4L2_TUNER_MODE_LANG2: /* A2 SAP */
+ val = 0x0080;
+ break;
+ case V4L2_TUNER_MODE_STEREO: /* A2 stereo */
+ val = 0x0880;
+ break;
+ default:
+ val = 0;
+ break;
+ }
+
+ gpio_bits(0x0880, val);
+ if (bttv_gpio)
+ bttv_gpio_tracking(btv, "lt9415");
}
/* TDA9821 on TerraTV+ Bt848, Bt878 */
@@ -216,45 +260,69 @@ void terratv_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
{
unsigned int con = 0;
- if (set) {
- gpio_inout(0x180000,0x180000);
- if (t->audmode & V4L2_TUNER_MODE_LANG2)
- con = 0x080000;
- if (t->audmode & V4L2_TUNER_MODE_STEREO)
- con = 0x180000;
- gpio_bits(0x180000, con);
- if (bttv_gpio)
- bttv_gpio_tracking(btv,"terratv");
- } else {
- t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
- V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
+ if (!set) {
+ /* Not much to do here */
+ t->audmode = V4L2_TUNER_MODE_LANG1;
+ t->rxsubchans = V4L2_TUNER_SUB_MONO |
+ V4L2_TUNER_SUB_STEREO |
+ V4L2_TUNER_SUB_LANG1 |
+ V4L2_TUNER_SUB_LANG2;
+
+ return;
+ }
+
+ gpio_inout(0x180000, 0x180000);
+ switch (t->audmode) {
+ case V4L2_TUNER_MODE_LANG2:
+ con = 0x080000;
+ break;
+ case V4L2_TUNER_MODE_STEREO:
+ con = 0x180000;
+ break;
+ default:
+ con = 0;
+ break;
}
+ gpio_bits(0x180000, con);
+ if (bttv_gpio)
+ bttv_gpio_tracking(btv, "terratv");
}
void winfast2000_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
{
- unsigned long val = 0;
+ unsigned long val;
- if (set) {
- /*btor (0xc32000, BT848_GPIO_OUT_EN);*/
- if (t->audmode & V4L2_TUNER_MODE_MONO) /* Mono */
- val = 0x420000;
- if (t->audmode & V4L2_TUNER_MODE_LANG1) /* Mono */
- val = 0x420000;
- if (t->audmode & V4L2_TUNER_MODE_LANG2) /* SAP */
- val = 0x410000;
- if (t->audmode & V4L2_TUNER_MODE_STEREO) /* Stereo */
- val = 0x020000;
- if (val) {
- gpio_bits(0x430000, val);
- if (bttv_gpio)
- bttv_gpio_tracking(btv,"winfast2000");
- }
- } else {
- t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
- V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
+ if (!set) {
+ /* Not much to do here */
+ t->audmode = V4L2_TUNER_MODE_LANG1;
+ t->rxsubchans = V4L2_TUNER_SUB_MONO |
+ V4L2_TUNER_SUB_STEREO |
+ V4L2_TUNER_SUB_LANG1 |
+ V4L2_TUNER_SUB_LANG2;
+
+ return;
}
+
+ /*btor (0xc32000, BT848_GPIO_OUT_EN);*/
+ switch (t->audmode) {
+ case V4L2_TUNER_MODE_MONO:
+ case V4L2_TUNER_MODE_LANG1:
+ val = 0x420000;
+ break;
+ case V4L2_TUNER_MODE_LANG2: /* SAP */
+ val = 0x410000;
+ break;
+ case V4L2_TUNER_MODE_STEREO:
+ val = 0x020000;
+ break;
+ default:
+ return;
+ }
+
+ gpio_bits(0x430000, val);
+ if (bttv_gpio)
+ bttv_gpio_tracking(btv, "winfast2000");
}
/*
@@ -272,23 +340,33 @@ void pvbt878p9b_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
if (btv->radio_user)
return;
- if (set) {
- if (t->audmode & V4L2_TUNER_MODE_MONO) {
- val = 0x01;
- }
- if ((t->audmode & (V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2))
- || (t->audmode & V4L2_TUNER_MODE_STEREO)) {
- val = 0x02;
- }
- if (val) {
- gpio_bits(0x03,val);
- if (bttv_gpio)
- bttv_gpio_tracking(btv,"pvbt878p9b");
- }
- } else {
- t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
- V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
+ if (!set) {
+ /* Not much to do here */
+ t->audmode = V4L2_TUNER_MODE_LANG1;
+ t->rxsubchans = V4L2_TUNER_SUB_MONO |
+ V4L2_TUNER_SUB_STEREO |
+ V4L2_TUNER_SUB_LANG1 |
+ V4L2_TUNER_SUB_LANG2;
+
+ return;
}
+
+ switch (t->audmode) {
+ case V4L2_TUNER_MODE_MONO:
+ val = 0x01;
+ break;
+ case V4L2_TUNER_MODE_LANG1:
+ case V4L2_TUNER_MODE_LANG2:
+ case V4L2_TUNER_MODE_STEREO:
+ val = 0x02;
+ break;
+ default:
+ return;
+ }
+
+ gpio_bits(0x03, val);
+ if (bttv_gpio)
+ bttv_gpio_tracking(btv, "pvbt878p9b");
}
/*
@@ -298,28 +376,37 @@ void pvbt878p9b_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
*/
void fv2000s_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
{
- unsigned int val = 0xffff;
+ unsigned int val;
if (btv->radio_user)
return;
- if (set) {
- if (t->audmode & V4L2_TUNER_MODE_MONO) {
- val = 0x0000;
- }
- if ((t->audmode & (V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2))
- || (t->audmode & V4L2_TUNER_MODE_STEREO)) {
- val = 0x1080; /*-dk-???: 0x0880, 0x0080, 0x1800 ... */
- }
- if (val != 0xffff) {
- gpio_bits(0x1800, val);
- if (bttv_gpio)
- bttv_gpio_tracking(btv,"fv2000s");
- }
- } else {
- t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
- V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
+ if (!set) {
+ /* Not much to do here */
+ t->audmode = V4L2_TUNER_MODE_LANG1;
+ t->rxsubchans = V4L2_TUNER_SUB_MONO |
+ V4L2_TUNER_SUB_STEREO |
+ V4L2_TUNER_SUB_LANG1 |
+ V4L2_TUNER_SUB_LANG2;
+
+ return;
}
+
+ switch (t->audmode) {
+ case V4L2_TUNER_MODE_MONO:
+ val = 0x0000;
+ break;
+ case V4L2_TUNER_MODE_LANG1:
+ case V4L2_TUNER_MODE_LANG2:
+ case V4L2_TUNER_MODE_STEREO:
+ val = 0x1080; /*-dk-???: 0x0880, 0x0080, 0x1800 ... */
+ break;
+ default:
+ return;
+ }
+ gpio_bits(0x1800, val);
+ if (bttv_gpio)
+ bttv_gpio_tracking(btv, "fv2000s");
}
/*
@@ -328,26 +415,33 @@ void fv2000s_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
*/
void windvr_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
{
- unsigned long val = 0;
+ unsigned long val;
- if (set) {
- if (t->audmode & V4L2_TUNER_MODE_MONO)
- val = 0x040000;
- if (t->audmode & V4L2_TUNER_MODE_LANG1)
- val = 0;
- if (t->audmode & V4L2_TUNER_MODE_LANG2)
- val = 0x100000;
- if (t->audmode & V4L2_TUNER_MODE_STEREO)
- val = 0;
- if (val) {
- gpio_bits(0x140000, val);
- if (bttv_gpio)
- bttv_gpio_tracking(btv,"windvr");
- }
- } else {
- t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
- V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
+ if (!set) {
+ /* Not much to do here */
+ t->audmode = V4L2_TUNER_MODE_LANG1;
+ t->rxsubchans = V4L2_TUNER_SUB_MONO |
+ V4L2_TUNER_SUB_STEREO |
+ V4L2_TUNER_SUB_LANG1 |
+ V4L2_TUNER_SUB_LANG2;
+
+ return;
+ }
+
+ switch (t->audmode) {
+ case V4L2_TUNER_MODE_MONO:
+ val = 0x040000;
+ break;
+ case V4L2_TUNER_MODE_LANG2:
+ val = 0x100000;
+ break;
+ default:
+ return;
}
+
+ gpio_bits(0x140000, val);
+ if (bttv_gpio)
+ bttv_gpio_tracking(btv, "windvr");
}
/*
@@ -360,23 +454,36 @@ void adtvk503_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
/* btaor(0x1e0000, ~0x1e0000, BT848_GPIO_OUT_EN); */
- if (set) {
- /* btor(***, BT848_GPIO_OUT_EN); */
- if (t->audmode & V4L2_TUNER_MODE_LANG1)
- con = 0x00000000;
- if (t->audmode & V4L2_TUNER_MODE_LANG2)
- con = 0x00180000;
- if (t->audmode & V4L2_TUNER_MODE_STEREO)
- con = 0x00000000;
- if (t->audmode & V4L2_TUNER_MODE_MONO)
- con = 0x00060000;
- if (con != 0xffffff) {
- gpio_bits(0x1e0000,con);
- if (bttv_gpio)
- bttv_gpio_tracking(btv, "adtvk503");
- }
- } else {
- t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
- V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
+ if (!set) {
+ /* Not much to do here */
+ t->audmode = V4L2_TUNER_MODE_LANG1;
+ t->rxsubchans = V4L2_TUNER_SUB_MONO |
+ V4L2_TUNER_SUB_STEREO |
+ V4L2_TUNER_SUB_LANG1 |
+ V4L2_TUNER_SUB_LANG2;
+
+ return;
}
+
+ /* btor(***, BT848_GPIO_OUT_EN); */
+ switch (t->audmode) {
+ case V4L2_TUNER_MODE_LANG1:
+ con = 0x00000000;
+ break;
+ case V4L2_TUNER_MODE_LANG2:
+ con = 0x00180000;
+ break;
+ case V4L2_TUNER_MODE_STEREO:
+ con = 0x00000000;
+ break;
+ case V4L2_TUNER_MODE_MONO:
+ con = 0x00060000;
+ break;
+ default:
+ return;
+ }
+
+ gpio_bits(0x1e0000, con);
+ if (bttv_gpio)
+ bttv_gpio_tracking(btv, "adtvk503");
}
diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c
index bc12060e0882..3632958f2158 100644
--- a/drivers/media/pci/bt8xx/bttv-driver.c
+++ b/drivers/media/pci/bt8xx/bttv-driver.c
@@ -2676,7 +2676,8 @@ static int bttv_s_fbuf(struct file *file, void *f,
fh->ov.w.height = fb->fmt.height;
btv->init.ov.w.width = fb->fmt.width;
btv->init.ov.w.height = fb->fmt.height;
- kfree(fh->ov.clips);
+
+ kfree(fh->ov.clips);
fh->ov.clips = NULL;
fh->ov.nclips = 0;
@@ -4238,6 +4239,7 @@ fail0:
iounmap(btv->bt848_mmio);
release_mem_region(pci_resource_start(btv->c.pci,0),
pci_resource_len(btv->c.pci,0));
+ pci_disable_device(btv->c.pci);
return result;
}
@@ -4281,6 +4283,7 @@ static void bttv_remove(struct pci_dev *pci_dev)
iounmap(btv->bt848_mmio);
release_mem_region(pci_resource_start(btv->c.pci,0),
pci_resource_len(btv->c.pci,0));
+ pci_disable_device(btv->c.pci);
v4l2_device_unregister(&btv->c.v4l2_dev);
bttvs[btv->c.nr] = NULL;
diff --git a/drivers/media/pci/bt8xx/dst.c b/drivers/media/pci/bt8xx/dst.c
index f2261dfe5d1a..4a90eee5e3bb 100644
--- a/drivers/media/pci/bt8xx/dst.c
+++ b/drivers/media/pci/bt8xx/dst.c
@@ -425,7 +425,8 @@ static int dst_set_bandwidth(struct dst_state *state, u32 bandwidth)
return 0;
}
-static int dst_set_inversion(struct dst_state *state, fe_spectral_inversion_t inversion)
+static int dst_set_inversion(struct dst_state *state,
+ enum fe_spectral_inversion inversion)
{
state->inversion = inversion;
switch (inversion) {
@@ -442,13 +443,13 @@ static int dst_set_inversion(struct dst_state *state, fe_spectral_inversion_t in
return 0;
}
-static int dst_set_fec(struct dst_state *state, fe_code_rate_t fec)
+static int dst_set_fec(struct dst_state *state, enum fe_code_rate fec)
{
state->fec = fec;
return 0;
}
-static fe_code_rate_t dst_get_fec(struct dst_state *state)
+static enum fe_code_rate dst_get_fec(struct dst_state *state)
{
return state->fec;
}
@@ -499,7 +500,8 @@ static int dst_set_symbolrate(struct dst_state *state, u32 srate)
return 0;
}
-static int dst_set_modulation(struct dst_state *state, fe_modulation_t modulation)
+static int dst_set_modulation(struct dst_state *state,
+ enum fe_modulation modulation)
{
if (state->dst_type != DST_TYPE_IS_CABLE)
return -EOPNOTSUPP;
@@ -536,7 +538,7 @@ static int dst_set_modulation(struct dst_state *state, fe_modulation_t modulatio
return 0;
}
-static fe_modulation_t dst_get_modulation(struct dst_state *state)
+static enum fe_modulation dst_get_modulation(struct dst_state *state)
{
return state->modulation;
}
@@ -1376,7 +1378,8 @@ static int dst_get_tuna(struct dst_state *state)
return 1;
}
-static int dst_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
+static int dst_set_voltage(struct dvb_frontend *fe,
+ enum fe_sec_voltage voltage);
static int dst_write_tuna(struct dvb_frontend *fe)
{
@@ -1466,7 +1469,7 @@ static int dst_set_diseqc(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd
return dst_command(state, paket, 8);
}
-static int dst_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+static int dst_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage)
{
int need_cmd, retval = 0;
struct dst_state *state = fe->demodulator_priv;
@@ -1500,7 +1503,7 @@ static int dst_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
return retval;
}
-static int dst_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+static int dst_set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone)
{
struct dst_state *state = fe->demodulator_priv;
@@ -1525,7 +1528,7 @@ static int dst_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
return dst_tone_power_cmd(state);
}
-static int dst_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t minicmd)
+static int dst_send_burst(struct dvb_frontend *fe, enum fe_sec_mini_cmd minicmd)
{
struct dst_state *state = fe->demodulator_priv;
@@ -1575,7 +1578,7 @@ static int bt8xx_dst_init(struct dvb_frontend *fe)
return 0;
}
-static int dst_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int dst_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct dst_state *state = fe->demodulator_priv;
@@ -1646,7 +1649,7 @@ static int dst_tune_frontend(struct dvb_frontend* fe,
bool re_tune,
unsigned int mode_flags,
unsigned int *delay,
- fe_status_t *status)
+ enum fe_status *status)
{
struct dst_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
diff --git a/drivers/media/pci/bt8xx/dst_ca.c b/drivers/media/pci/bt8xx/dst_ca.c
index c22c4ae06844..c5cc14ef8347 100644
--- a/drivers/media/pci/bt8xx/dst_ca.c
+++ b/drivers/media/pci/bt8xx/dst_ca.c
@@ -320,29 +320,27 @@ static int ca_get_message(struct dst_state *state, struct ca_msg *p_ca_message,
if (copy_from_user(p_ca_message, arg, sizeof (struct ca_msg)))
return -EFAULT;
- if (p_ca_message->msg) {
- dprintk(verbose, DST_CA_NOTICE, 1, " Message = [%*ph]",
- 3, p_ca_message->msg);
-
- for (i = 0; i < 3; i++) {
- command = command | p_ca_message->msg[i];
- if (i < 2)
- command = command << 8;
- }
- dprintk(verbose, DST_CA_NOTICE, 1, " Command=[0x%x]", command);
+ dprintk(verbose, DST_CA_NOTICE, 1, " Message = [%*ph]",
+ 3, p_ca_message->msg);
- switch (command) {
- case CA_APP_INFO:
- memcpy(p_ca_message->msg, state->messages, 128);
- if (copy_to_user(arg, p_ca_message, sizeof (struct ca_msg)) )
- return -EFAULT;
- break;
- case CA_INFO:
- memcpy(p_ca_message->msg, state->messages, 128);
- if (copy_to_user(arg, p_ca_message, sizeof (struct ca_msg)) )
- return -EFAULT;
- break;
- }
+ for (i = 0; i < 3; i++) {
+ command = command | p_ca_message->msg[i];
+ if (i < 2)
+ command = command << 8;
+ }
+ dprintk(verbose, DST_CA_NOTICE, 1, " Command=[0x%x]", command);
+
+ switch (command) {
+ case CA_APP_INFO:
+ memcpy(p_ca_message->msg, state->messages, 128);
+ if (copy_to_user(arg, p_ca_message, sizeof (struct ca_msg)) )
+ return -EFAULT;
+ break;
+ case CA_INFO:
+ memcpy(p_ca_message->msg, state->messages, 128);
+ if (copy_to_user(arg, p_ca_message, sizeof (struct ca_msg)) )
+ return -EFAULT;
+ break;
}
return 0;
@@ -494,60 +492,58 @@ static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message,
goto free_mem_and_exit;
}
+ /* EN50221 tag */
+ command = 0;
- if (p_ca_message->msg) {
- /* EN50221 tag */
- command = 0;
+ for (i = 0; i < 3; i++) {
+ command = command | p_ca_message->msg[i];
+ if (i < 2)
+ command = command << 8;
+ }
+ dprintk(verbose, DST_CA_DEBUG, 1, " Command=[0x%x]\n", command);
- for (i = 0; i < 3; i++) {
- command = command | p_ca_message->msg[i];
- if (i < 2)
- command = command << 8;
+ switch (command) {
+ case CA_PMT:
+ dprintk(verbose, DST_CA_DEBUG, 1, "Command = SEND_CA_PMT");
+ if ((ca_set_pmt(state, p_ca_message, hw_buffer, 0, 0)) < 0) { // code simplification started
+ dprintk(verbose, DST_CA_ERROR, 1, " -->CA_PMT Failed !");
+ result = -1;
+ goto free_mem_and_exit;
}
- dprintk(verbose, DST_CA_DEBUG, 1, " Command=[0x%x]\n", command);
-
- switch (command) {
- case CA_PMT:
- dprintk(verbose, DST_CA_DEBUG, 1, "Command = SEND_CA_PMT");
- if ((ca_set_pmt(state, p_ca_message, hw_buffer, 0, 0)) < 0) { // code simplification started
- dprintk(verbose, DST_CA_ERROR, 1, " -->CA_PMT Failed !");
- result = -1;
- goto free_mem_and_exit;
- }
- dprintk(verbose, DST_CA_INFO, 1, " -->CA_PMT Success !");
- break;
- case CA_PMT_REPLY:
- dprintk(verbose, DST_CA_INFO, 1, "Command = CA_PMT_REPLY");
- /* Have to handle the 2 basic types of cards here */
- if ((dst_check_ca_pmt(state, p_ca_message, hw_buffer)) < 0) {
- dprintk(verbose, DST_CA_ERROR, 1, " -->CA_PMT_REPLY Failed !");
- result = -1;
- goto free_mem_and_exit;
- }
- dprintk(verbose, DST_CA_INFO, 1, " -->CA_PMT_REPLY Success !");
- break;
- case CA_APP_INFO_ENQUIRY: // only for debugging
- dprintk(verbose, DST_CA_INFO, 1, " Getting Cam Application information");
-
- if ((ca_get_app_info(state)) < 0) {
- dprintk(verbose, DST_CA_ERROR, 1, " -->CA_APP_INFO_ENQUIRY Failed !");
- result = -1;
- goto free_mem_and_exit;
- }
- dprintk(verbose, DST_CA_INFO, 1, " -->CA_APP_INFO_ENQUIRY Success !");
- break;
- case CA_INFO_ENQUIRY:
- dprintk(verbose, DST_CA_INFO, 1, " Getting CA Information");
-
- if ((ca_get_ca_info(state)) < 0) {
- dprintk(verbose, DST_CA_ERROR, 1, " -->CA_INFO_ENQUIRY Failed !");
- result = -1;
- goto free_mem_and_exit;
- }
- dprintk(verbose, DST_CA_INFO, 1, " -->CA_INFO_ENQUIRY Success !");
- break;
+ dprintk(verbose, DST_CA_INFO, 1, " -->CA_PMT Success !");
+ break;
+ case CA_PMT_REPLY:
+ dprintk(verbose, DST_CA_INFO, 1, "Command = CA_PMT_REPLY");
+ /* Have to handle the 2 basic types of cards here */
+ if ((dst_check_ca_pmt(state, p_ca_message, hw_buffer)) < 0) {
+ dprintk(verbose, DST_CA_ERROR, 1, " -->CA_PMT_REPLY Failed !");
+ result = -1;
+ goto free_mem_and_exit;
+ }
+ dprintk(verbose, DST_CA_INFO, 1, " -->CA_PMT_REPLY Success !");
+ break;
+ case CA_APP_INFO_ENQUIRY: // only for debugging
+ dprintk(verbose, DST_CA_INFO, 1, " Getting Cam Application information");
+
+ if ((ca_get_app_info(state)) < 0) {
+ dprintk(verbose, DST_CA_ERROR, 1, " -->CA_APP_INFO_ENQUIRY Failed !");
+ result = -1;
+ goto free_mem_and_exit;
}
+ dprintk(verbose, DST_CA_INFO, 1, " -->CA_APP_INFO_ENQUIRY Success !");
+ break;
+ case CA_INFO_ENQUIRY:
+ dprintk(verbose, DST_CA_INFO, 1, " Getting CA Information");
+
+ if ((ca_get_ca_info(state)) < 0) {
+ dprintk(verbose, DST_CA_ERROR, 1, " -->CA_INFO_ENQUIRY Failed !");
+ result = -1;
+ goto free_mem_and_exit;
+ }
+ dprintk(verbose, DST_CA_INFO, 1, " -->CA_INFO_ENQUIRY Success !");
+ break;
}
+
free_mem_and_exit:
kfree (hw_buffer);
diff --git a/drivers/media/pci/bt8xx/dst_common.h b/drivers/media/pci/bt8xx/dst_common.h
index d70d98f1a571..6a2cfdd44e3e 100644
--- a/drivers/media/pci/bt8xx/dst_common.h
+++ b/drivers/media/pci/bt8xx/dst_common.h
@@ -113,11 +113,11 @@ struct dst_state {
u8 dst_type;
u32 type_flags;
u32 frequency; /* intermediate frequency in kHz for QPSK */
- fe_spectral_inversion_t inversion;
+ enum fe_spectral_inversion inversion;
u32 symbol_rate; /* symbol rate in Symbols per second */
- fe_code_rate_t fec;
- fe_sec_voltage_t voltage;
- fe_sec_tone_mode_t tone;
+ enum fe_code_rate fec;
+ enum fe_sec_voltage voltage;
+ enum fe_sec_tone_mode tone;
u32 decode_freq;
u8 decode_lock;
u16 decode_strength;
@@ -127,8 +127,8 @@ struct dst_state {
u32 bandwidth;
u32 dst_hw_cap;
u8 dst_fw_version;
- fe_sec_mini_cmd_t minicmd;
- fe_modulation_t modulation;
+ enum fe_sec_mini_cmd minicmd;
+ enum fe_modulation modulation;
u8 messages[256];
u8 mac_address[8];
u8 fw_version[8];
diff --git a/drivers/media/pci/cobalt/Kconfig b/drivers/media/pci/cobalt/Kconfig
new file mode 100644
index 000000000000..3be1b2c3c386
--- /dev/null
+++ b/drivers/media/pci/cobalt/Kconfig
@@ -0,0 +1,18 @@
+config VIDEO_COBALT
+ tristate "Cisco Cobalt support"
+ depends on VIDEO_V4L2 && I2C && MEDIA_CONTROLLER
+ depends on PCI_MSI && MTD_COMPLEX_MAPPINGS && GPIOLIB
+ select I2C_ALGOBIT
+ select VIDEO_ADV7604
+ select VIDEO_ADV7511
+ select VIDEO_ADV7842
+ select VIDEOBUF2_DMA_SG
+ ---help---
+ This is a video4linux driver for the Cisco PCIe Cobalt card.
+
+ This board is sadly not available outside of Cisco, but it is
+ very useful as an example of a real driver that uses all the
+ latest frameworks and APIs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called cobalt.
diff --git a/drivers/media/pci/cobalt/Makefile b/drivers/media/pci/cobalt/Makefile
new file mode 100644
index 000000000000..b328955abbd2
--- /dev/null
+++ b/drivers/media/pci/cobalt/Makefile
@@ -0,0 +1,5 @@
+cobalt-objs := cobalt-driver.o cobalt-irq.o cobalt-v4l2.o \
+ cobalt-i2c.o cobalt-omnitek.o cobalt-flash.o cobalt-cpld.o \
+ cobalt-alsa-main.o cobalt-alsa-pcm.o
+
+obj-$(CONFIG_VIDEO_COBALT) += cobalt.o
diff --git a/drivers/media/pci/cobalt/cobalt-alsa-main.c b/drivers/media/pci/cobalt/cobalt-alsa-main.c
new file mode 100644
index 000000000000..720e3ad93a9e
--- /dev/null
+++ b/drivers/media/pci/cobalt/cobalt-alsa-main.c
@@ -0,0 +1,162 @@
+/*
+ * ALSA interface to cobalt PCM capture streams
+ *
+ * Copyright 2014-2015 Cisco Systems, Inc. and/or its affiliates.
+ * All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/spinlock.h>
+
+#include <media/v4l2-device.h>
+
+#include <sound/core.h>
+#include <sound/initval.h>
+
+#include "cobalt-driver.h"
+#include "cobalt-alsa.h"
+#include "cobalt-alsa-pcm.h"
+
+static void snd_cobalt_card_free(struct snd_cobalt_card *cobsc)
+{
+ if (cobsc == NULL)
+ return;
+
+ cobsc->s->alsa = NULL;
+
+ kfree(cobsc);
+}
+
+static void snd_cobalt_card_private_free(struct snd_card *sc)
+{
+ if (sc == NULL)
+ return;
+ snd_cobalt_card_free(sc->private_data);
+ sc->private_data = NULL;
+ sc->private_free = NULL;
+}
+
+static int snd_cobalt_card_create(struct cobalt_stream *s,
+ struct snd_card *sc,
+ struct snd_cobalt_card **cobsc)
+{
+ *cobsc = kzalloc(sizeof(struct snd_cobalt_card), GFP_KERNEL);
+ if (*cobsc == NULL)
+ return -ENOMEM;
+
+ (*cobsc)->s = s;
+ (*cobsc)->sc = sc;
+
+ sc->private_data = *cobsc;
+ sc->private_free = snd_cobalt_card_private_free;
+
+ return 0;
+}
+
+static int snd_cobalt_card_set_names(struct snd_cobalt_card *cobsc)
+{
+ struct cobalt_stream *s = cobsc->s;
+ struct cobalt *cobalt = s->cobalt;
+ struct snd_card *sc = cobsc->sc;
+
+ /* sc->driver is used by alsa-lib's configurator: simple, unique */
+ strlcpy(sc->driver, "cobalt", sizeof(sc->driver));
+
+ /* sc->shortname is a symlink in /proc/asound: COBALT-M -> cardN */
+ snprintf(sc->shortname, sizeof(sc->shortname), "cobalt-%d-%d",
+ cobalt->instance, s->video_channel);
+
+ /* sc->longname is read from /proc/asound/cards */
+ snprintf(sc->longname, sizeof(sc->longname),
+ "Cobalt %d HDMI %d",
+ cobalt->instance, s->video_channel);
+
+ return 0;
+}
+
+int cobalt_alsa_init(struct cobalt_stream *s)
+{
+ struct cobalt *cobalt = s->cobalt;
+ struct snd_card *sc = NULL;
+ struct snd_cobalt_card *cobsc;
+ int ret;
+
+ /* Numbrs steps from "Writing an ALSA Driver" by Takashi Iwai */
+
+ /* (1) Check and increment the device index */
+ /* This is a no-op for us. We'll use the cobalt->instance */
+
+ /* (2) Create a card instance */
+ ret = snd_card_new(&cobalt->pci_dev->dev, SNDRV_DEFAULT_IDX1,
+ SNDRV_DEFAULT_STR1, THIS_MODULE, 0, &sc);
+ if (ret) {
+ cobalt_err("snd_card_new() failed with err %d\n", ret);
+ goto err_exit;
+ }
+
+ /* (3) Create a main component */
+ ret = snd_cobalt_card_create(s, sc, &cobsc);
+ if (ret) {
+ cobalt_err("snd_cobalt_card_create() failed with err %d\n",
+ ret);
+ goto err_exit_free;
+ }
+
+ /* (4) Set the driver ID and name strings */
+ snd_cobalt_card_set_names(cobsc);
+
+ ret = snd_cobalt_pcm_create(cobsc);
+ if (ret) {
+ cobalt_err("snd_cobalt_pcm_create() failed with err %d\n",
+ ret);
+ goto err_exit_free;
+ }
+ /* FIXME - proc files */
+
+ /* (7) Set the driver data and return 0 */
+ /* We do this out of normal order for PCI drivers to avoid races */
+ s->alsa = cobsc;
+
+ /* (6) Register the card instance */
+ ret = snd_card_register(sc);
+ if (ret) {
+ s->alsa = NULL;
+ cobalt_err("snd_card_register() failed with err %d\n", ret);
+ goto err_exit_free;
+ }
+
+ return 0;
+
+err_exit_free:
+ if (sc != NULL)
+ snd_card_free(sc);
+ kfree(cobsc);
+err_exit:
+ return ret;
+}
+
+void cobalt_alsa_exit(struct cobalt_stream *s)
+{
+ struct snd_cobalt_card *cobsc = s->alsa;
+
+ if (cobsc)
+ snd_card_free(cobsc->sc);
+ s->alsa = NULL;
+}
diff --git a/drivers/media/pci/cobalt/cobalt-alsa-pcm.c b/drivers/media/pci/cobalt/cobalt-alsa-pcm.c
new file mode 100644
index 000000000000..f0bdf10cfd57
--- /dev/null
+++ b/drivers/media/pci/cobalt/cobalt-alsa-pcm.c
@@ -0,0 +1,603 @@
+/*
+ * ALSA PCM device for the
+ * ALSA interface to cobalt PCM capture streams
+ *
+ * Copyright 2014-2015 Cisco Systems, Inc. and/or its affiliates.
+ * All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+
+#include <media/v4l2-device.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+
+#include "cobalt-driver.h"
+#include "cobalt-alsa.h"
+#include "cobalt-alsa-pcm.h"
+
+static unsigned int pcm_debug;
+module_param(pcm_debug, int, 0644);
+MODULE_PARM_DESC(pcm_debug, "enable debug messages for pcm");
+
+#define dprintk(fmt, arg...) \
+ do { \
+ if (pcm_debug) \
+ pr_info("cobalt-alsa-pcm %s: " fmt, __func__, ##arg); \
+ } while (0)
+
+static struct snd_pcm_hardware snd_cobalt_hdmi_capture = {
+ .info = SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_MMAP_VALID,
+
+ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
+
+ .rates = SNDRV_PCM_RATE_48000,
+
+ .rate_min = 48000,
+ .rate_max = 48000,
+ .channels_min = 1,
+ .channels_max = 8,
+ .buffer_bytes_max = 4 * 240 * 8 * 4, /* 5 ms of data */
+ .period_bytes_min = 1920, /* 1 sample = 8 * 4 bytes */
+ .period_bytes_max = 240 * 8 * 4, /* 5 ms of 8 channel data */
+ .periods_min = 1,
+ .periods_max = 4,
+};
+
+static struct snd_pcm_hardware snd_cobalt_playback = {
+ .info = SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_MMAP_VALID,
+
+ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
+
+ .rates = SNDRV_PCM_RATE_48000,
+
+ .rate_min = 48000,
+ .rate_max = 48000,
+ .channels_min = 1,
+ .channels_max = 8,
+ .buffer_bytes_max = 4 * 240 * 8 * 4, /* 5 ms of data */
+ .period_bytes_min = 1920, /* 1 sample = 8 * 4 bytes */
+ .period_bytes_max = 240 * 8 * 4, /* 5 ms of 8 channel data */
+ .periods_min = 1,
+ .periods_max = 4,
+};
+
+static void sample_cpy(u8 *dst, const u8 *src, u32 len, bool is_s32)
+{
+ static const unsigned map[8] = { 0, 1, 5, 4, 2, 3, 6, 7 };
+ unsigned idx = 0;
+
+ while (len >= (is_s32 ? 4 : 2)) {
+ unsigned offset = map[idx] * 4;
+ u32 val = src[offset + 1] + (src[offset + 2] << 8) +
+ (src[offset + 3] << 16);
+
+ if (is_s32) {
+ *dst++ = 0;
+ *dst++ = val & 0xff;
+ }
+ *dst++ = (val >> 8) & 0xff;
+ *dst++ = (val >> 16) & 0xff;
+ len -= is_s32 ? 4 : 2;
+ idx++;
+ }
+}
+
+static void cobalt_alsa_announce_pcm_data(struct snd_cobalt_card *cobsc,
+ u8 *pcm_data,
+ size_t skip,
+ size_t samples)
+{
+ struct snd_pcm_substream *substream;
+ struct snd_pcm_runtime *runtime;
+ unsigned long flags;
+ unsigned int oldptr;
+ unsigned int stride;
+ int length = samples;
+ int period_elapsed = 0;
+ bool is_s32;
+
+ dprintk("cobalt alsa announce ptr=%p data=%p num_bytes=%zd\n", cobsc,
+ pcm_data, samples);
+
+ substream = cobsc->capture_pcm_substream;
+ if (substream == NULL) {
+ dprintk("substream was NULL\n");
+ return;
+ }
+
+ runtime = substream->runtime;
+ if (runtime == NULL) {
+ dprintk("runtime was NULL\n");
+ return;
+ }
+ is_s32 = runtime->format == SNDRV_PCM_FORMAT_S32_LE;
+
+ stride = runtime->frame_bits >> 3;
+ if (stride == 0) {
+ dprintk("stride is zero\n");
+ return;
+ }
+
+ if (length == 0) {
+ dprintk("%s: length was zero\n", __func__);
+ return;
+ }
+
+ if (runtime->dma_area == NULL) {
+ dprintk("dma area was NULL - ignoring\n");
+ return;
+ }
+
+ oldptr = cobsc->hwptr_done_capture;
+ if (oldptr + length >= runtime->buffer_size) {
+ unsigned int cnt = runtime->buffer_size - oldptr;
+ unsigned i;
+
+ for (i = 0; i < cnt; i++)
+ sample_cpy(runtime->dma_area + (oldptr + i) * stride,
+ pcm_data + i * skip,
+ stride, is_s32);
+ for (i = cnt; i < length; i++)
+ sample_cpy(runtime->dma_area + (i - cnt) * stride,
+ pcm_data + i * skip, stride, is_s32);
+ } else {
+ unsigned i;
+
+ for (i = 0; i < length; i++)
+ sample_cpy(runtime->dma_area + (oldptr + i) * stride,
+ pcm_data + i * skip,
+ stride, is_s32);
+ }
+ snd_pcm_stream_lock_irqsave(substream, flags);
+
+ cobsc->hwptr_done_capture += length;
+ if (cobsc->hwptr_done_capture >=
+ runtime->buffer_size)
+ cobsc->hwptr_done_capture -=
+ runtime->buffer_size;
+
+ cobsc->capture_transfer_done += length;
+ if (cobsc->capture_transfer_done >=
+ runtime->period_size) {
+ cobsc->capture_transfer_done -=
+ runtime->period_size;
+ period_elapsed = 1;
+ }
+
+ snd_pcm_stream_unlock_irqrestore(substream, flags);
+
+ if (period_elapsed)
+ snd_pcm_period_elapsed(substream);
+}
+
+static int alsa_fnc(struct vb2_buffer *vb, void *priv)
+{
+ struct cobalt_stream *s = priv;
+ unsigned char *p = vb2_plane_vaddr(vb, 0);
+ int i;
+
+ if (pcm_debug) {
+ pr_info("alsa: ");
+ for (i = 0; i < 8 * 4; i++) {
+ if (!(i & 3))
+ pr_cont(" ");
+ pr_cont("%02x", p[i]);
+ }
+ pr_cont("\n");
+ }
+ cobalt_alsa_announce_pcm_data(s->alsa,
+ vb2_plane_vaddr(vb, 0),
+ 8 * 4,
+ vb2_get_plane_payload(vb, 0) / (8 * 4));
+ return 0;
+}
+
+static int snd_cobalt_pcm_capture_open(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_cobalt_card *cobsc = snd_pcm_substream_chip(substream);
+ struct cobalt_stream *s = cobsc->s;
+
+ runtime->hw = snd_cobalt_hdmi_capture;
+ snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+ cobsc->capture_pcm_substream = substream;
+ runtime->private_data = s;
+ cobsc->alsa_record_cnt++;
+ if (cobsc->alsa_record_cnt == 1) {
+ int rc;
+
+ rc = vb2_thread_start(&s->q, alsa_fnc, s, s->vdev.name);
+ if (rc) {
+ cobsc->alsa_record_cnt--;
+ return rc;
+ }
+ }
+ return 0;
+}
+
+static int snd_cobalt_pcm_capture_close(struct snd_pcm_substream *substream)
+{
+ struct snd_cobalt_card *cobsc = snd_pcm_substream_chip(substream);
+ struct cobalt_stream *s = cobsc->s;
+
+ cobsc->alsa_record_cnt--;
+ if (cobsc->alsa_record_cnt == 0)
+ vb2_thread_stop(&s->q);
+ return 0;
+}
+
+static int snd_cobalt_pcm_ioctl(struct snd_pcm_substream *substream,
+ unsigned int cmd, void *arg)
+{
+ return snd_pcm_lib_ioctl(substream, cmd, arg);
+}
+
+
+static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs,
+ size_t size)
+{
+ struct snd_pcm_runtime *runtime = subs->runtime;
+
+ dprintk("Allocating vbuffer\n");
+ if (runtime->dma_area) {
+ if (runtime->dma_bytes > size)
+ return 0;
+
+ vfree(runtime->dma_area);
+ }
+ runtime->dma_area = vmalloc(size);
+ if (!runtime->dma_area)
+ return -ENOMEM;
+
+ runtime->dma_bytes = size;
+
+ return 0;
+}
+
+static int snd_cobalt_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ dprintk("%s called\n", __func__);
+
+ return snd_pcm_alloc_vmalloc_buffer(substream,
+ params_buffer_bytes(params));
+}
+
+static int snd_cobalt_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+ if (substream->runtime->dma_area) {
+ dprintk("freeing pcm capture region\n");
+ vfree(substream->runtime->dma_area);
+ substream->runtime->dma_area = NULL;
+ }
+
+ return 0;
+}
+
+static int snd_cobalt_pcm_prepare(struct snd_pcm_substream *substream)
+{
+ struct snd_cobalt_card *cobsc = snd_pcm_substream_chip(substream);
+
+ cobsc->hwptr_done_capture = 0;
+ cobsc->capture_transfer_done = 0;
+
+ return 0;
+}
+
+static int snd_cobalt_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_STOP:
+ return 0;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static
+snd_pcm_uframes_t snd_cobalt_pcm_pointer(struct snd_pcm_substream *substream)
+{
+ snd_pcm_uframes_t hwptr_done;
+ struct snd_cobalt_card *cobsc = snd_pcm_substream_chip(substream);
+
+ hwptr_done = cobsc->hwptr_done_capture;
+
+ return hwptr_done;
+}
+
+static void pb_sample_cpy(u8 *dst, const u8 *src, u32 len, bool is_s32)
+{
+ static const unsigned map[8] = { 0, 1, 5, 4, 2, 3, 6, 7 };
+ unsigned idx = 0;
+
+ while (len >= (is_s32 ? 4 : 2)) {
+ unsigned offset = map[idx] * 4;
+ u8 *out = dst + offset;
+
+ *out++ = 0;
+ if (is_s32) {
+ src++;
+ *out++ = *src++;
+ } else {
+ *out++ = 0;
+ }
+ *out++ = *src++;
+ *out = *src++;
+ len -= is_s32 ? 4 : 2;
+ idx++;
+ }
+}
+
+static void cobalt_alsa_pb_pcm_data(struct snd_cobalt_card *cobsc,
+ u8 *pcm_data,
+ size_t skip,
+ size_t samples)
+{
+ struct snd_pcm_substream *substream;
+ struct snd_pcm_runtime *runtime;
+ unsigned long flags;
+ unsigned int pos;
+ unsigned int stride;
+ bool is_s32;
+ unsigned i;
+
+ dprintk("cobalt alsa pb ptr=%p data=%p samples=%zd\n", cobsc,
+ pcm_data, samples);
+
+ substream = cobsc->playback_pcm_substream;
+ if (substream == NULL) {
+ dprintk("substream was NULL\n");
+ return;
+ }
+
+ runtime = substream->runtime;
+ if (runtime == NULL) {
+ dprintk("runtime was NULL\n");
+ return;
+ }
+
+ is_s32 = runtime->format == SNDRV_PCM_FORMAT_S32_LE;
+ stride = runtime->frame_bits >> 3;
+ if (stride == 0) {
+ dprintk("stride is zero\n");
+ return;
+ }
+
+ if (samples == 0) {
+ dprintk("%s: samples was zero\n", __func__);
+ return;
+ }
+
+ if (runtime->dma_area == NULL) {
+ dprintk("dma area was NULL - ignoring\n");
+ return;
+ }
+
+ pos = cobsc->pb_pos % cobsc->pb_size;
+ for (i = 0; i < cobsc->pb_count / (8 * 4); i++)
+ pb_sample_cpy(pcm_data + i * skip,
+ runtime->dma_area + pos + i * stride,
+ stride, is_s32);
+ snd_pcm_stream_lock_irqsave(substream, flags);
+
+ cobsc->pb_pos += i * stride;
+
+ snd_pcm_stream_unlock_irqrestore(substream, flags);
+ if (cobsc->pb_pos % cobsc->pb_count == 0)
+ snd_pcm_period_elapsed(substream);
+}
+
+static int alsa_pb_fnc(struct vb2_buffer *vb, void *priv)
+{
+ struct cobalt_stream *s = priv;
+
+ if (s->alsa->alsa_pb_channel)
+ cobalt_alsa_pb_pcm_data(s->alsa,
+ vb2_plane_vaddr(vb, 0),
+ 8 * 4,
+ vb2_get_plane_payload(vb, 0) / (8 * 4));
+ return 0;
+}
+
+static int snd_cobalt_pcm_playback_open(struct snd_pcm_substream *substream)
+{
+ struct snd_cobalt_card *cobsc = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct cobalt_stream *s = cobsc->s;
+
+ runtime->hw = snd_cobalt_playback;
+ snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+ cobsc->playback_pcm_substream = substream;
+ runtime->private_data = s;
+ cobsc->alsa_playback_cnt++;
+ if (cobsc->alsa_playback_cnt == 1) {
+ int rc;
+
+ rc = vb2_thread_start(&s->q, alsa_pb_fnc, s, s->vdev.name);
+ if (rc) {
+ cobsc->alsa_playback_cnt--;
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+static int snd_cobalt_pcm_playback_close(struct snd_pcm_substream *substream)
+{
+ struct snd_cobalt_card *cobsc = snd_pcm_substream_chip(substream);
+ struct cobalt_stream *s = cobsc->s;
+
+ cobsc->alsa_playback_cnt--;
+ if (cobsc->alsa_playback_cnt == 0)
+ vb2_thread_stop(&s->q);
+ return 0;
+}
+
+static int snd_cobalt_pcm_pb_prepare(struct snd_pcm_substream *substream)
+{
+ struct snd_cobalt_card *cobsc = snd_pcm_substream_chip(substream);
+
+ cobsc->pb_size = snd_pcm_lib_buffer_bytes(substream);
+ cobsc->pb_count = snd_pcm_lib_period_bytes(substream);
+ cobsc->pb_pos = 0;
+
+ return 0;
+}
+
+static int snd_cobalt_pcm_pb_trigger(struct snd_pcm_substream *substream,
+ int cmd)
+{
+ struct snd_cobalt_card *cobsc = snd_pcm_substream_chip(substream);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ if (cobsc->alsa_pb_channel)
+ return -EBUSY;
+ cobsc->alsa_pb_channel = true;
+ return 0;
+ case SNDRV_PCM_TRIGGER_STOP:
+ cobsc->alsa_pb_channel = false;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+static
+snd_pcm_uframes_t snd_cobalt_pcm_pb_pointer(struct snd_pcm_substream *substream)
+{
+ struct snd_cobalt_card *cobsc = snd_pcm_substream_chip(substream);
+ size_t ptr;
+
+ ptr = cobsc->pb_pos;
+
+ return bytes_to_frames(substream->runtime, ptr) %
+ substream->runtime->buffer_size;
+}
+
+static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs,
+ unsigned long offset)
+{
+ void *pageptr = subs->runtime->dma_area + offset;
+
+ return vmalloc_to_page(pageptr);
+}
+
+static struct snd_pcm_ops snd_cobalt_pcm_capture_ops = {
+ .open = snd_cobalt_pcm_capture_open,
+ .close = snd_cobalt_pcm_capture_close,
+ .ioctl = snd_cobalt_pcm_ioctl,
+ .hw_params = snd_cobalt_pcm_hw_params,
+ .hw_free = snd_cobalt_pcm_hw_free,
+ .prepare = snd_cobalt_pcm_prepare,
+ .trigger = snd_cobalt_pcm_trigger,
+ .pointer = snd_cobalt_pcm_pointer,
+ .page = snd_pcm_get_vmalloc_page,
+};
+
+static struct snd_pcm_ops snd_cobalt_pcm_playback_ops = {
+ .open = snd_cobalt_pcm_playback_open,
+ .close = snd_cobalt_pcm_playback_close,
+ .ioctl = snd_cobalt_pcm_ioctl,
+ .hw_params = snd_cobalt_pcm_hw_params,
+ .hw_free = snd_cobalt_pcm_hw_free,
+ .prepare = snd_cobalt_pcm_pb_prepare,
+ .trigger = snd_cobalt_pcm_pb_trigger,
+ .pointer = snd_cobalt_pcm_pb_pointer,
+ .page = snd_pcm_get_vmalloc_page,
+};
+
+int snd_cobalt_pcm_create(struct snd_cobalt_card *cobsc)
+{
+ struct snd_pcm *sp;
+ struct snd_card *sc = cobsc->sc;
+ struct cobalt_stream *s = cobsc->s;
+ struct cobalt *cobalt = s->cobalt;
+ int ret;
+
+ s->q.gfp_flags |= __GFP_ZERO;
+
+ if (!s->is_output) {
+ cobalt_s_bit_sysctrl(cobalt,
+ COBALT_SYS_CTRL_AUDIO_IPP_RESETN_BIT(s->video_channel),
+ 0);
+ mdelay(2);
+ cobalt_s_bit_sysctrl(cobalt,
+ COBALT_SYS_CTRL_AUDIO_IPP_RESETN_BIT(s->video_channel),
+ 1);
+ mdelay(1);
+
+ ret = snd_pcm_new(sc, "Cobalt PCM-In HDMI",
+ 0, /* PCM device 0, the only one for this card */
+ 0, /* 0 playback substreams */
+ 1, /* 1 capture substream */
+ &sp);
+ if (ret) {
+ cobalt_err("snd_cobalt_pcm_create() failed for input with err %d\n",
+ ret);
+ goto err_exit;
+ }
+
+ snd_pcm_set_ops(sp, SNDRV_PCM_STREAM_CAPTURE,
+ &snd_cobalt_pcm_capture_ops);
+ sp->info_flags = 0;
+ sp->private_data = cobsc;
+ strlcpy(sp->name, "cobalt", sizeof(sp->name));
+ } else {
+ cobalt_s_bit_sysctrl(cobalt,
+ COBALT_SYS_CTRL_AUDIO_OPP_RESETN_BIT, 0);
+ mdelay(2);
+ cobalt_s_bit_sysctrl(cobalt,
+ COBALT_SYS_CTRL_AUDIO_OPP_RESETN_BIT, 1);
+ mdelay(1);
+
+ ret = snd_pcm_new(sc, "Cobalt PCM-Out HDMI",
+ 0, /* PCM device 0, the only one for this card */
+ 1, /* 0 playback substreams */
+ 0, /* 1 capture substream */
+ &sp);
+ if (ret) {
+ cobalt_err("snd_cobalt_pcm_create() failed for output with err %d\n",
+ ret);
+ goto err_exit;
+ }
+
+ snd_pcm_set_ops(sp, SNDRV_PCM_STREAM_PLAYBACK,
+ &snd_cobalt_pcm_playback_ops);
+ sp->info_flags = 0;
+ sp->private_data = cobsc;
+ strlcpy(sp->name, "cobalt", sizeof(sp->name));
+ }
+
+ return 0;
+
+err_exit:
+ return ret;
+}
diff --git a/drivers/media/pci/cobalt/cobalt-alsa-pcm.h b/drivers/media/pci/cobalt/cobalt-alsa-pcm.h
new file mode 100644
index 000000000000..513fb1f71794
--- /dev/null
+++ b/drivers/media/pci/cobalt/cobalt-alsa-pcm.h
@@ -0,0 +1,22 @@
+/*
+ * ALSA PCM device for the
+ * ALSA interface to cobalt PCM capture streams
+ *
+ * Copyright 2014-2015 Cisco Systems, Inc. and/or its affiliates.
+ * All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+int snd_cobalt_pcm_create(struct snd_cobalt_card *cobsc);
diff --git a/drivers/media/pci/cobalt/cobalt-alsa.h b/drivers/media/pci/cobalt/cobalt-alsa.h
new file mode 100644
index 000000000000..08db699ced37
--- /dev/null
+++ b/drivers/media/pci/cobalt/cobalt-alsa.h
@@ -0,0 +1,41 @@
+/*
+ * ALSA interface to cobalt PCM capture streams
+ *
+ * Copyright 2014-2015 Cisco Systems, Inc. and/or its affiliates.
+ * All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+struct snd_card;
+
+struct snd_cobalt_card {
+ struct cobalt_stream *s;
+ struct snd_card *sc;
+ unsigned int capture_transfer_done;
+ unsigned int hwptr_done_capture;
+ unsigned alsa_record_cnt;
+ struct snd_pcm_substream *capture_pcm_substream;
+
+ unsigned int pb_size;
+ unsigned int pb_count;
+ unsigned int pb_pos;
+ unsigned pb_filled;
+ bool alsa_pb_channel;
+ unsigned alsa_playback_cnt;
+ struct snd_pcm_substream *playback_pcm_substream;
+};
+
+int cobalt_alsa_init(struct cobalt_stream *s);
+void cobalt_alsa_exit(struct cobalt_stream *s);
diff --git a/drivers/media/pci/cobalt/cobalt-cpld.c b/drivers/media/pci/cobalt/cobalt-cpld.c
new file mode 100644
index 000000000000..e83f5c9f7e7d
--- /dev/null
+++ b/drivers/media/pci/cobalt/cobalt-cpld.c
@@ -0,0 +1,341 @@
+/*
+ * Cobalt CPLD functions
+ *
+ * Copyright 2012-2015 Cisco Systems, Inc. and/or its affiliates.
+ * All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/delay.h>
+
+#include "cobalt-cpld.h"
+
+#define ADRS(offset) (COBALT_BUS_CPLD_BASE + offset)
+
+static u16 cpld_read(struct cobalt *cobalt, u32 offset)
+{
+ return cobalt_bus_read32(cobalt->bar1, ADRS(offset));
+}
+
+static void cpld_write(struct cobalt *cobalt, u32 offset, u16 val)
+{
+ return cobalt_bus_write32(cobalt->bar1, ADRS(offset), val);
+}
+
+static void cpld_info_ver3(struct cobalt *cobalt)
+{
+ u32 rd;
+ u32 tmp;
+
+ cobalt_info("CPLD System control register (read/write)\n");
+ cobalt_info("\t\tSystem control: 0x%04x (0x0f00)\n",
+ cpld_read(cobalt, 0));
+ cobalt_info("CPLD Clock control register (read/write)\n");
+ cobalt_info("\t\tClock control: 0x%04x (0x0000)\n",
+ cpld_read(cobalt, 0x04));
+ cobalt_info("CPLD HSMA Clk Osc register (read/write) - Must set wr trigger to load default values\n");
+ cobalt_info("\t\tRegister #7:\t0x%04x (0x0022)\n",
+ cpld_read(cobalt, 0x08));
+ cobalt_info("\t\tRegister #8:\t0x%04x (0x0047)\n",
+ cpld_read(cobalt, 0x0c));
+ cobalt_info("\t\tRegister #9:\t0x%04x (0x00fa)\n",
+ cpld_read(cobalt, 0x10));
+ cobalt_info("\t\tRegister #10:\t0x%04x (0x0061)\n",
+ cpld_read(cobalt, 0x14));
+ cobalt_info("\t\tRegister #11:\t0x%04x (0x001e)\n",
+ cpld_read(cobalt, 0x18));
+ cobalt_info("\t\tRegister #12:\t0x%04x (0x0045)\n",
+ cpld_read(cobalt, 0x1c));
+ cobalt_info("\t\tRegister #135:\t0x%04x\n",
+ cpld_read(cobalt, 0x20));
+ cobalt_info("\t\tRegister #137:\t0x%04x\n",
+ cpld_read(cobalt, 0x24));
+ cobalt_info("CPLD System status register (read only)\n");
+ cobalt_info("\t\tSystem status: 0x%04x\n",
+ cpld_read(cobalt, 0x28));
+ cobalt_info("CPLD MAXII info register (read only)\n");
+ cobalt_info("\t\tBoard serial number: 0x%04x\n",
+ cpld_read(cobalt, 0x2c));
+ cobalt_info("\t\tMAXII program revision: 0x%04x\n",
+ cpld_read(cobalt, 0x30));
+ cobalt_info("CPLD temp and voltage ADT7411 registers (read only)\n");
+ cobalt_info("\t\tBoard temperature: %u Celcius\n",
+ cpld_read(cobalt, 0x34) / 4);
+ cobalt_info("\t\tFPGA temperature: %u Celcius\n",
+ cpld_read(cobalt, 0x38) / 4);
+ rd = cpld_read(cobalt, 0x3c);
+ tmp = (rd * 33 * 1000) / (483 * 10);
+ cobalt_info("\t\tVDD 3V3: %u,%03uV\n", tmp / 1000, tmp % 1000);
+ rd = cpld_read(cobalt, 0x40);
+ tmp = (rd * 74 * 2197) / (27 * 1000);
+ cobalt_info("\t\tADC ch3 5V: %u,%03uV\n", tmp / 1000, tmp % 1000);
+ rd = cpld_read(cobalt, 0x44);
+ tmp = (rd * 74 * 2197) / (47 * 1000);
+ cobalt_info("\t\tADC ch4 3V: %u,%03uV\n", tmp / 1000, tmp % 1000);
+ rd = cpld_read(cobalt, 0x48);
+ tmp = (rd * 57 * 2197) / (47 * 1000);
+ cobalt_info("\t\tADC ch5 2V5: %u,%03uV\n", tmp / 1000, tmp % 1000);
+ rd = cpld_read(cobalt, 0x4c);
+ tmp = (rd * 2197) / 1000;
+ cobalt_info("\t\tADC ch6 1V8: %u,%03uV\n", tmp / 1000, tmp % 1000);
+ rd = cpld_read(cobalt, 0x50);
+ tmp = (rd * 2197) / 1000;
+ cobalt_info("\t\tADC ch7 1V5: %u,%03uV\n", tmp / 1000, tmp % 1000);
+ rd = cpld_read(cobalt, 0x54);
+ tmp = (rd * 2197) / 1000;
+ cobalt_info("\t\tADC ch8 0V9: %u,%03uV\n", tmp / 1000, tmp % 1000);
+}
+
+void cobalt_cpld_status(struct cobalt *cobalt)
+{
+ u32 rev = cpld_read(cobalt, 0x30);
+
+ switch (rev) {
+ case 3:
+ case 4:
+ case 5:
+ cpld_info_ver3(cobalt);
+ break;
+ default:
+ cobalt_info("CPLD revision %u is not supported!\n", rev);
+ break;
+ }
+}
+
+#define DCO_MIN 4850000000ULL
+#define DCO_MAX 5670000000ULL
+
+#define SI570_CLOCK_CTRL 0x04
+#define S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_WR_TRIGGER 0x200
+#define S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_RST_TRIGGER 0x100
+#define S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_FPGA_CTRL 0x80
+#define S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_EN 0x40
+
+#define SI570_REG7 0x08
+#define SI570_REG8 0x0c
+#define SI570_REG9 0x10
+#define SI570_REG10 0x14
+#define SI570_REG11 0x18
+#define SI570_REG12 0x1c
+#define SI570_REG135 0x20
+#define SI570_REG137 0x24
+
+struct multiplier {
+ unsigned mult, hsdiv, n1;
+};
+
+/* List all possible multipliers (= hsdiv * n1). There are lots of duplicates,
+ which are all removed in this list to keep the list as short as possible.
+ The values for hsdiv and n1 are the actual values, not the register values.
+ */
+static const struct multiplier multipliers[] = {
+ { 4, 4, 1 }, { 5, 5, 1 }, { 6, 6, 1 },
+ { 7, 7, 1 }, { 8, 4, 2 }, { 9, 9, 1 },
+ { 10, 5, 2 }, { 11, 11, 1 }, { 12, 6, 2 },
+ { 14, 7, 2 }, { 16, 4, 4 }, { 18, 9, 2 },
+ { 20, 5, 4 }, { 22, 11, 2 }, { 24, 4, 6 },
+ { 28, 7, 4 }, { 30, 5, 6 }, { 32, 4, 8 },
+ { 36, 6, 6 }, { 40, 4, 10 }, { 42, 7, 6 },
+ { 44, 11, 4 }, { 48, 4, 12 }, { 50, 5, 10 },
+ { 54, 9, 6 }, { 56, 4, 14 }, { 60, 5, 12 },
+ { 64, 4, 16 }, { 66, 11, 6 }, { 70, 5, 14 },
+ { 72, 4, 18 }, { 80, 4, 20 }, { 84, 6, 14 },
+ { 88, 11, 8 }, { 90, 5, 18 }, { 96, 4, 24 },
+ { 98, 7, 14 }, { 100, 5, 20 }, { 104, 4, 26 },
+ { 108, 6, 18 }, { 110, 11, 10 }, { 112, 4, 28 },
+ { 120, 4, 30 }, { 126, 7, 18 }, { 128, 4, 32 },
+ { 130, 5, 26 }, { 132, 11, 12 }, { 136, 4, 34 },
+ { 140, 5, 28 }, { 144, 4, 36 }, { 150, 5, 30 },
+ { 152, 4, 38 }, { 154, 11, 14 }, { 156, 6, 26 },
+ { 160, 4, 40 }, { 162, 9, 18 }, { 168, 4, 42 },
+ { 170, 5, 34 }, { 176, 11, 16 }, { 180, 5, 36 },
+ { 182, 7, 26 }, { 184, 4, 46 }, { 190, 5, 38 },
+ { 192, 4, 48 }, { 196, 7, 28 }, { 198, 11, 18 },
+ { 198, 9, 22 }, { 200, 4, 50 }, { 204, 6, 34 },
+ { 208, 4, 52 }, { 210, 5, 42 }, { 216, 4, 54 },
+ { 220, 11, 20 }, { 224, 4, 56 }, { 228, 6, 38 },
+ { 230, 5, 46 }, { 232, 4, 58 }, { 234, 9, 26 },
+ { 238, 7, 34 }, { 240, 4, 60 }, { 242, 11, 22 },
+ { 248, 4, 62 }, { 250, 5, 50 }, { 252, 6, 42 },
+ { 256, 4, 64 }, { 260, 5, 52 }, { 264, 11, 24 },
+ { 266, 7, 38 }, { 270, 5, 54 }, { 272, 4, 68 },
+ { 276, 6, 46 }, { 280, 4, 70 }, { 286, 11, 26 },
+ { 288, 4, 72 }, { 290, 5, 58 }, { 294, 7, 42 },
+ { 296, 4, 74 }, { 300, 5, 60 }, { 304, 4, 76 },
+ { 306, 9, 34 }, { 308, 11, 28 }, { 310, 5, 62 },
+ { 312, 4, 78 }, { 320, 4, 80 }, { 322, 7, 46 },
+ { 324, 6, 54 }, { 328, 4, 82 }, { 330, 11, 30 },
+ { 336, 4, 84 }, { 340, 5, 68 }, { 342, 9, 38 },
+ { 344, 4, 86 }, { 348, 6, 58 }, { 350, 5, 70 },
+ { 352, 11, 32 }, { 360, 4, 90 }, { 364, 7, 52 },
+ { 368, 4, 92 }, { 370, 5, 74 }, { 372, 6, 62 },
+ { 374, 11, 34 }, { 376, 4, 94 }, { 378, 7, 54 },
+ { 380, 5, 76 }, { 384, 4, 96 }, { 390, 5, 78 },
+ { 392, 4, 98 }, { 396, 11, 36 }, { 400, 4, 100 },
+ { 406, 7, 58 }, { 408, 4, 102 }, { 410, 5, 82 },
+ { 414, 9, 46 }, { 416, 4, 104 }, { 418, 11, 38 },
+ { 420, 5, 84 }, { 424, 4, 106 }, { 430, 5, 86 },
+ { 432, 4, 108 }, { 434, 7, 62 }, { 440, 11, 40 },
+ { 444, 6, 74 }, { 448, 4, 112 }, { 450, 5, 90 },
+ { 456, 4, 114 }, { 460, 5, 92 }, { 462, 11, 42 },
+ { 464, 4, 116 }, { 468, 6, 78 }, { 470, 5, 94 },
+ { 472, 4, 118 }, { 476, 7, 68 }, { 480, 4, 120 },
+ { 484, 11, 44 }, { 486, 9, 54 }, { 488, 4, 122 },
+ { 490, 5, 98 }, { 492, 6, 82 }, { 496, 4, 124 },
+ { 500, 5, 100 }, { 504, 4, 126 }, { 506, 11, 46 },
+ { 510, 5, 102 }, { 512, 4, 128 }, { 516, 6, 86 },
+ { 518, 7, 74 }, { 520, 5, 104 }, { 522, 9, 58 },
+ { 528, 11, 48 }, { 530, 5, 106 }, { 532, 7, 76 },
+ { 540, 5, 108 }, { 546, 7, 78 }, { 550, 11, 50 },
+ { 552, 6, 92 }, { 558, 9, 62 }, { 560, 5, 112 },
+ { 564, 6, 94 }, { 570, 5, 114 }, { 572, 11, 52 },
+ { 574, 7, 82 }, { 576, 6, 96 }, { 580, 5, 116 },
+ { 588, 6, 98 }, { 590, 5, 118 }, { 594, 11, 54 },
+ { 600, 5, 120 }, { 602, 7, 86 }, { 610, 5, 122 },
+ { 612, 6, 102 }, { 616, 11, 56 }, { 620, 5, 124 },
+ { 624, 6, 104 }, { 630, 5, 126 }, { 636, 6, 106 },
+ { 638, 11, 58 }, { 640, 5, 128 }, { 644, 7, 92 },
+ { 648, 6, 108 }, { 658, 7, 94 }, { 660, 11, 60 },
+ { 666, 9, 74 }, { 672, 6, 112 }, { 682, 11, 62 },
+ { 684, 6, 114 }, { 686, 7, 98 }, { 696, 6, 116 },
+ { 700, 7, 100 }, { 702, 9, 78 }, { 704, 11, 64 },
+ { 708, 6, 118 }, { 714, 7, 102 }, { 720, 6, 120 },
+ { 726, 11, 66 }, { 728, 7, 104 }, { 732, 6, 122 },
+ { 738, 9, 82 }, { 742, 7, 106 }, { 744, 6, 124 },
+ { 748, 11, 68 }, { 756, 6, 126 }, { 768, 6, 128 },
+ { 770, 11, 70 }, { 774, 9, 86 }, { 784, 7, 112 },
+ { 792, 11, 72 }, { 798, 7, 114 }, { 810, 9, 90 },
+ { 812, 7, 116 }, { 814, 11, 74 }, { 826, 7, 118 },
+ { 828, 9, 92 }, { 836, 11, 76 }, { 840, 7, 120 },
+ { 846, 9, 94 }, { 854, 7, 122 }, { 858, 11, 78 },
+ { 864, 9, 96 }, { 868, 7, 124 }, { 880, 11, 80 },
+ { 882, 7, 126 }, { 896, 7, 128 }, { 900, 9, 100 },
+ { 902, 11, 82 }, { 918, 9, 102 }, { 924, 11, 84 },
+ { 936, 9, 104 }, { 946, 11, 86 }, { 954, 9, 106 },
+ { 968, 11, 88 }, { 972, 9, 108 }, { 990, 11, 90 },
+ { 1008, 9, 112 }, { 1012, 11, 92 }, { 1026, 9, 114 },
+ { 1034, 11, 94 }, { 1044, 9, 116 }, { 1056, 11, 96 },
+ { 1062, 9, 118 }, { 1078, 11, 98 }, { 1080, 9, 120 },
+ { 1098, 9, 122 }, { 1100, 11, 100 }, { 1116, 9, 124 },
+ { 1122, 11, 102 }, { 1134, 9, 126 }, { 1144, 11, 104 },
+ { 1152, 9, 128 }, { 1166, 11, 106 }, { 1188, 11, 108 },
+ { 1210, 11, 110 }, { 1232, 11, 112 }, { 1254, 11, 114 },
+ { 1276, 11, 116 }, { 1298, 11, 118 }, { 1320, 11, 120 },
+ { 1342, 11, 122 }, { 1364, 11, 124 }, { 1386, 11, 126 },
+ { 1408, 11, 128 },
+};
+
+bool cobalt_cpld_set_freq(struct cobalt *cobalt, unsigned f_out)
+{
+ const unsigned f_xtal = 39170000; /* xtal for si598 */
+ u64 dco;
+ u64 rfreq;
+ unsigned delta = 0xffffffff;
+ unsigned i_best = 0;
+ unsigned i;
+ u8 n1, hsdiv;
+ u8 regs[6];
+ int found = 0;
+ u16 clock_ctrl;
+ int retries = 3;
+
+ for (i = 0; i < ARRAY_SIZE(multipliers); i++) {
+ unsigned mult = multipliers[i].mult;
+ u32 d;
+
+ dco = (u64)f_out * mult;
+ if (dco < DCO_MIN || dco > DCO_MAX)
+ continue;
+ div_u64_rem((dco << 28) + f_xtal / 2, f_xtal, &d);
+ if (d < delta) {
+ found = 1;
+ i_best = i;
+ delta = d;
+ }
+ }
+ if (!found)
+ return false;
+ dco = (u64)f_out * multipliers[i_best].mult;
+ n1 = multipliers[i_best].n1 - 1;
+ hsdiv = multipliers[i_best].hsdiv - 4;
+ rfreq = div_u64(dco << 28, f_xtal);
+
+ clock_ctrl = cpld_read(cobalt, SI570_CLOCK_CTRL);
+ clock_ctrl |= S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_FPGA_CTRL;
+ clock_ctrl |= S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_EN;
+
+ regs[0] = (hsdiv << 5) | (n1 >> 2);
+ regs[1] = ((n1 & 0x3) << 6) | (rfreq >> 32);
+ regs[2] = (rfreq >> 24) & 0xff;
+ regs[3] = (rfreq >> 16) & 0xff;
+ regs[4] = (rfreq >> 8) & 0xff;
+ regs[5] = rfreq & 0xff;
+
+ /* The sequence of clock_ctrl flags to set is very weird. It looks
+ like I have to reset it, then set the new frequency and reset it
+ again. It shouldn't be necessary to do a reset, but if I don't,
+ then a strange frequency is set (156.412034 MHz, or register values
+ 0x01, 0xc7, 0xfc, 0x7f, 0x53, 0x62).
+ */
+
+ cobalt_dbg(1, "%u: %02x %02x %02x %02x %02x %02x\n", f_out,
+ regs[0], regs[1], regs[2], regs[3], regs[4], regs[5]);
+ while (retries--) {
+ u8 read_regs[6];
+
+ cpld_write(cobalt, SI570_CLOCK_CTRL,
+ S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_EN |
+ S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_FPGA_CTRL);
+ usleep_range(10000, 15000);
+ cpld_write(cobalt, SI570_REG7, regs[0]);
+ cpld_write(cobalt, SI570_REG8, regs[1]);
+ cpld_write(cobalt, SI570_REG9, regs[2]);
+ cpld_write(cobalt, SI570_REG10, regs[3]);
+ cpld_write(cobalt, SI570_REG11, regs[4]);
+ cpld_write(cobalt, SI570_REG12, regs[5]);
+ cpld_write(cobalt, SI570_CLOCK_CTRL,
+ S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_EN |
+ S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_WR_TRIGGER);
+ usleep_range(10000, 15000);
+ cpld_write(cobalt, SI570_CLOCK_CTRL,
+ S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_EN |
+ S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_FPGA_CTRL);
+ usleep_range(10000, 15000);
+ read_regs[0] = cpld_read(cobalt, SI570_REG7);
+ read_regs[1] = cpld_read(cobalt, SI570_REG8);
+ read_regs[2] = cpld_read(cobalt, SI570_REG9);
+ read_regs[3] = cpld_read(cobalt, SI570_REG10);
+ read_regs[4] = cpld_read(cobalt, SI570_REG11);
+ read_regs[5] = cpld_read(cobalt, SI570_REG12);
+ cpld_write(cobalt, SI570_CLOCK_CTRL,
+ S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_EN |
+ S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_FPGA_CTRL |
+ S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_RST_TRIGGER);
+ usleep_range(10000, 15000);
+ cpld_write(cobalt, SI570_CLOCK_CTRL,
+ S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_EN);
+ usleep_range(10000, 15000);
+
+ if (!memcmp(read_regs, regs, sizeof(read_regs)))
+ break;
+ cobalt_dbg(1, "retry: %02x %02x %02x %02x %02x %02x\n",
+ read_regs[0], read_regs[1], read_regs[2],
+ read_regs[3], read_regs[4], read_regs[5]);
+ }
+ if (2 - retries)
+ cobalt_info("Needed %d retries\n", 2 - retries);
+
+ return true;
+}
diff --git a/drivers/media/pci/cobalt/cobalt-cpld.h b/drivers/media/pci/cobalt/cobalt-cpld.h
new file mode 100644
index 000000000000..0fc88fd5fa7b
--- /dev/null
+++ b/drivers/media/pci/cobalt/cobalt-cpld.h
@@ -0,0 +1,29 @@
+/*
+ * Cobalt CPLD functions
+ *
+ * Copyright 2012-2015 Cisco Systems, Inc. and/or its affiliates.
+ * All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef COBALT_CPLD_H
+#define COBALT_CPLD_H
+
+#include "cobalt-driver.h"
+
+void cobalt_cpld_status(struct cobalt *cobalt);
+bool cobalt_cpld_set_freq(struct cobalt *cobalt, unsigned freq);
+
+#endif
diff --git a/drivers/media/pci/cobalt/cobalt-driver.c b/drivers/media/pci/cobalt/cobalt-driver.c
new file mode 100644
index 000000000000..b994b8efdc99
--- /dev/null
+++ b/drivers/media/pci/cobalt/cobalt-driver.c
@@ -0,0 +1,832 @@
+/*
+ * cobalt driver initialization and card probing
+ *
+ * Derived from cx18-driver.c
+ *
+ * Copyright 2012-2015 Cisco Systems, Inc. and/or its affiliates.
+ * All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/delay.h>
+#include <media/adv7604.h>
+#include <media/adv7842.h>
+#include <media/adv7511.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-ctrls.h>
+
+#include "cobalt-driver.h"
+#include "cobalt-irq.h"
+#include "cobalt-i2c.h"
+#include "cobalt-v4l2.h"
+#include "cobalt-flash.h"
+#include "cobalt-alsa.h"
+#include "cobalt-omnitek.h"
+
+/* add your revision and whatnot here */
+static struct pci_device_id cobalt_pci_tbl[] = {
+ {PCI_VENDOR_ID_CISCO, PCI_DEVICE_ID_COBALT,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0,}
+};
+
+MODULE_DEVICE_TABLE(pci, cobalt_pci_tbl);
+
+static atomic_t cobalt_instance = ATOMIC_INIT(0);
+
+int cobalt_debug;
+module_param_named(debug, cobalt_debug, int, 0644);
+MODULE_PARM_DESC(debug, "Debug level. Default: 0\n");
+
+int cobalt_ignore_err;
+module_param_named(ignore_err, cobalt_ignore_err, int, 0644);
+MODULE_PARM_DESC(ignore_err,
+ "If set then ignore missing i2c adapters/receivers. Default: 0\n");
+
+MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com> & Morten Hestnes");
+MODULE_DESCRIPTION("cobalt driver");
+MODULE_LICENSE("GPL");
+
+static u8 edid[256] = {
+ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
+ 0x50, 0x21, 0x9C, 0x27, 0x00, 0x00, 0x00, 0x00,
+ 0x19, 0x12, 0x01, 0x03, 0x80, 0x00, 0x00, 0x78,
+ 0x0E, 0x00, 0xB2, 0xA0, 0x57, 0x49, 0x9B, 0x26,
+ 0x10, 0x48, 0x4F, 0x2F, 0xCF, 0x00, 0x31, 0x59,
+ 0x45, 0x59, 0x61, 0x59, 0x81, 0x99, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3A,
+ 0x80, 0x18, 0x71, 0x38, 0x2D, 0x40, 0x58, 0x2C,
+ 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E,
+ 0x00, 0x00, 0x00, 0xFD, 0x00, 0x31, 0x55, 0x18,
+ 0x5E, 0x11, 0x00, 0x0A, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x43,
+ 0x20, 0x39, 0x30, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
+ 0x0A, 0x0A, 0x0A, 0x0A, 0x00, 0x00, 0x00, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x68,
+ 0x02, 0x03, 0x1a, 0xc0, 0x48, 0xa2, 0x10, 0x04,
+ 0x02, 0x01, 0x21, 0x14, 0x13, 0x23, 0x09, 0x07,
+ 0x07, 0x65, 0x03, 0x0c, 0x00, 0x10, 0x00, 0xe2,
+ 0x00, 0x2a, 0x01, 0x1d, 0x00, 0x80, 0x51, 0xd0,
+ 0x1c, 0x20, 0x40, 0x80, 0x35, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x1e, 0x8c, 0x0a, 0xd0, 0x8a,
+ 0x20, 0xe0, 0x2d, 0x10, 0x10, 0x3e, 0x96, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd7
+};
+
+static void cobalt_set_interrupt(struct cobalt *cobalt, bool enable)
+{
+ if (enable) {
+ unsigned irqs = COBALT_SYSSTAT_VI0_INT1_MSK |
+ COBALT_SYSSTAT_VI1_INT1_MSK |
+ COBALT_SYSSTAT_VI2_INT1_MSK |
+ COBALT_SYSSTAT_VI3_INT1_MSK |
+ COBALT_SYSSTAT_VI0_INT2_MSK |
+ COBALT_SYSSTAT_VI1_INT2_MSK |
+ COBALT_SYSSTAT_VI2_INT2_MSK |
+ COBALT_SYSSTAT_VI3_INT2_MSK |
+ COBALT_SYSSTAT_VI0_LOST_DATA_MSK |
+ COBALT_SYSSTAT_VI1_LOST_DATA_MSK |
+ COBALT_SYSSTAT_VI2_LOST_DATA_MSK |
+ COBALT_SYSSTAT_VI3_LOST_DATA_MSK |
+ COBALT_SYSSTAT_AUD_IN_LOST_DATA_MSK;
+
+ if (cobalt->have_hsma_rx)
+ irqs |= COBALT_SYSSTAT_VIHSMA_INT1_MSK |
+ COBALT_SYSSTAT_VIHSMA_INT2_MSK |
+ COBALT_SYSSTAT_VIHSMA_LOST_DATA_MSK;
+
+ if (cobalt->have_hsma_tx)
+ irqs |= COBALT_SYSSTAT_VOHSMA_INT1_MSK |
+ COBALT_SYSSTAT_VOHSMA_LOST_DATA_MSK |
+ COBALT_SYSSTAT_AUD_OUT_LOST_DATA_MSK;
+ /* Clear any existing interrupts */
+ cobalt_write_bar1(cobalt, COBALT_SYS_STAT_EDGE, 0xffffffff);
+ /* PIO Core interrupt mask register.
+ Enable ADV7604 INT1 interrupts */
+ cobalt_write_bar1(cobalt, COBALT_SYS_STAT_MASK, irqs);
+ } else {
+ /* Disable all ADV7604 interrupts */
+ cobalt_write_bar1(cobalt, COBALT_SYS_STAT_MASK, 0);
+ }
+}
+
+static unsigned cobalt_get_sd_nr(struct v4l2_subdev *sd)
+{
+ struct cobalt *cobalt = to_cobalt(sd->v4l2_dev);
+ unsigned i;
+
+ for (i = 0; i < COBALT_NUM_NODES; i++)
+ if (sd == cobalt->streams[i].sd)
+ return i;
+ cobalt_err("Invalid adv7604 subdev pointer!\n");
+ return 0;
+}
+
+static void cobalt_notify(struct v4l2_subdev *sd,
+ unsigned int notification, void *arg)
+{
+ struct cobalt *cobalt = to_cobalt(sd->v4l2_dev);
+ unsigned sd_nr = cobalt_get_sd_nr(sd);
+ struct cobalt_stream *s = &cobalt->streams[sd_nr];
+ bool hotplug = arg ? *((int *)arg) : false;
+
+ if (s->is_output)
+ return;
+
+ switch (notification) {
+ case ADV76XX_HOTPLUG:
+ cobalt_s_bit_sysctrl(cobalt,
+ COBALT_SYS_CTRL_HPD_TO_CONNECTOR_BIT(sd_nr), hotplug);
+ cobalt_dbg(1, "Set hotplug for adv %d to %d\n", sd_nr, hotplug);
+ break;
+ case V4L2_DEVICE_NOTIFY_EVENT:
+ cobalt_dbg(1, "Format changed for adv %d\n", sd_nr);
+ v4l2_event_queue(&s->vdev, arg);
+ break;
+ default:
+ break;
+ }
+}
+
+static int get_payload_size(u16 code)
+{
+ switch (code) {
+ case 0: return 128;
+ case 1: return 256;
+ case 2: return 512;
+ case 3: return 1024;
+ case 4: return 2048;
+ case 5: return 4096;
+ default: return 0;
+ }
+ return 0;
+}
+
+static const char *get_link_speed(u16 stat)
+{
+ switch (stat & PCI_EXP_LNKSTA_CLS) {
+ case 1: return "2.5 Gbit/s";
+ case 2: return "5 Gbit/s";
+ case 3: return "10 Gbit/s";
+ }
+ return "Unknown speed";
+}
+
+void cobalt_pcie_status_show(struct cobalt *cobalt)
+{
+ struct pci_dev *pci_dev = cobalt->pci_dev;
+ struct pci_dev *pci_bus_dev = cobalt->pci_dev->bus->self;
+ int offset;
+ int bus_offset;
+ u32 capa;
+ u16 stat, ctrl;
+
+ offset = pci_find_capability(pci_dev, PCI_CAP_ID_EXP);
+ bus_offset = pci_find_capability(pci_bus_dev, PCI_CAP_ID_EXP);
+
+ /* Device */
+ pci_read_config_dword(pci_dev, offset + PCI_EXP_DEVCAP, &capa);
+ pci_read_config_word(pci_dev, offset + PCI_EXP_DEVCTL, &ctrl);
+ pci_read_config_word(pci_dev, offset + PCI_EXP_DEVSTA, &stat);
+ cobalt_info("PCIe device capability 0x%08x: Max payload %d\n",
+ capa, get_payload_size(capa & PCI_EXP_DEVCAP_PAYLOAD));
+ cobalt_info("PCIe device control 0x%04x: Max payload %d. Max read request %d\n",
+ ctrl,
+ get_payload_size((ctrl & PCI_EXP_DEVCTL_PAYLOAD) >> 5),
+ get_payload_size((ctrl & PCI_EXP_DEVCTL_READRQ) >> 12));
+ cobalt_info("PCIe device status 0x%04x\n", stat);
+
+ /* Link */
+ pci_read_config_dword(pci_dev, offset + PCI_EXP_LNKCAP, &capa);
+ pci_read_config_word(pci_dev, offset + PCI_EXP_LNKCTL, &ctrl);
+ pci_read_config_word(pci_dev, offset + PCI_EXP_LNKSTA, &stat);
+ cobalt_info("PCIe link capability 0x%08x: %s per lane and %u lanes\n",
+ capa, get_link_speed(capa),
+ (capa & PCI_EXP_LNKCAP_MLW) >> 4);
+ cobalt_info("PCIe link control 0x%04x\n", ctrl);
+ cobalt_info("PCIe link status 0x%04x: %s per lane and %u lanes\n",
+ stat, get_link_speed(stat),
+ (stat & PCI_EXP_LNKSTA_NLW) >> 4);
+
+ /* Bus */
+ pci_read_config_dword(pci_bus_dev, bus_offset + PCI_EXP_LNKCAP, &capa);
+ cobalt_info("PCIe bus link capability 0x%08x: %s per lane and %u lanes\n",
+ capa, get_link_speed(capa),
+ (capa & PCI_EXP_LNKCAP_MLW) >> 4);
+
+ /* Slot */
+ pci_read_config_dword(pci_dev, offset + PCI_EXP_SLTCAP, &capa);
+ pci_read_config_word(pci_dev, offset + PCI_EXP_SLTCTL, &ctrl);
+ pci_read_config_word(pci_dev, offset + PCI_EXP_SLTSTA, &stat);
+ cobalt_info("PCIe slot capability 0x%08x\n", capa);
+ cobalt_info("PCIe slot control 0x%04x\n", ctrl);
+ cobalt_info("PCIe slot status 0x%04x\n", stat);
+}
+
+static unsigned pcie_link_get_lanes(struct cobalt *cobalt)
+{
+ struct pci_dev *pci_dev = cobalt->pci_dev;
+ unsigned offset;
+ u16 link;
+
+ offset = pci_find_capability(pci_dev, PCI_CAP_ID_EXP);
+ if (!offset)
+ return 0;
+ pci_read_config_word(pci_dev, offset + PCI_EXP_LNKSTA, &link);
+ return (link & PCI_EXP_LNKSTA_NLW) >> 4;
+}
+
+static unsigned pcie_bus_link_get_lanes(struct cobalt *cobalt)
+{
+ struct pci_dev *pci_dev = cobalt->pci_dev->bus->self;
+ unsigned offset;
+ u32 link;
+
+ offset = pci_find_capability(pci_dev, PCI_CAP_ID_EXP);
+ if (!offset)
+ return 0;
+ pci_read_config_dword(pci_dev, offset + PCI_EXP_LNKCAP, &link);
+ return (link & PCI_EXP_LNKCAP_MLW) >> 4;
+}
+
+static void msi_config_show(struct cobalt *cobalt, struct pci_dev *pci_dev)
+{
+ u16 ctrl, data;
+ u32 adrs_l, adrs_h;
+
+ pci_read_config_word(pci_dev, 0x52, &ctrl);
+ cobalt_info("MSI %s\n", ctrl & 1 ? "enable" : "disable");
+ cobalt_info("MSI multiple message: Capable %u. Enable %u\n",
+ (1 << ((ctrl >> 1) & 7)), (1 << ((ctrl >> 4) & 7)));
+ if (ctrl & 0x80)
+ cobalt_info("MSI: 64-bit address capable\n");
+ pci_read_config_dword(pci_dev, 0x54, &adrs_l);
+ pci_read_config_dword(pci_dev, 0x58, &adrs_h);
+ pci_read_config_word(pci_dev, 0x5c, &data);
+ if (ctrl & 0x80)
+ cobalt_info("MSI: Address 0x%08x%08x. Data 0x%04x\n",
+ adrs_h, adrs_l, data);
+ else
+ cobalt_info("MSI: Address 0x%08x. Data 0x%04x\n",
+ adrs_l, data);
+}
+
+static void cobalt_pci_iounmap(struct cobalt *cobalt, struct pci_dev *pci_dev)
+{
+ if (cobalt->bar0) {
+ pci_iounmap(pci_dev, cobalt->bar0);
+ cobalt->bar0 = NULL;
+ }
+ if (cobalt->bar1) {
+ pci_iounmap(pci_dev, cobalt->bar1);
+ cobalt->bar1 = NULL;
+ }
+}
+
+static void cobalt_free_msi(struct cobalt *cobalt, struct pci_dev *pci_dev)
+{
+ free_irq(pci_dev->irq, (void *)cobalt);
+
+ if (cobalt->msi_enabled)
+ pci_disable_msi(pci_dev);
+}
+
+static int cobalt_setup_pci(struct cobalt *cobalt, struct pci_dev *pci_dev,
+ const struct pci_device_id *pci_id)
+{
+ u32 ctrl;
+ int ret;
+
+ cobalt_dbg(1, "enabling pci device\n");
+
+ ret = pci_enable_device(pci_dev);
+ if (ret) {
+ cobalt_err("can't enable device\n");
+ return ret;
+ }
+ pci_set_master(pci_dev);
+ pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &cobalt->card_rev);
+ pci_read_config_word(pci_dev, PCI_DEVICE_ID, &cobalt->device_id);
+
+ switch (cobalt->device_id) {
+ case PCI_DEVICE_ID_COBALT:
+ cobalt_info("PCI Express interface from Omnitek\n");
+ break;
+ default:
+ cobalt_info("PCI Express interface provider is unknown!\n");
+ break;
+ }
+
+ if (pcie_link_get_lanes(cobalt) != 8) {
+ cobalt_err("PCI Express link width is not 8 lanes (%d)\n",
+ pcie_link_get_lanes(cobalt));
+ if (pcie_bus_link_get_lanes(cobalt) < 8)
+ cobalt_err("The current slot only supports %d lanes, at least 8 are needed\n",
+ pcie_bus_link_get_lanes(cobalt));
+ else
+ cobalt_err("The card is most likely not seated correctly in the PCIe slot\n");
+ ret = -EIO;
+ goto err_disable;
+ }
+
+ if (pci_set_dma_mask(pci_dev, DMA_BIT_MASK(64))) {
+ ret = pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32));
+ if (ret) {
+ cobalt_err("no suitable DMA available\n");
+ goto err_disable;
+ }
+ }
+
+ ret = pci_request_regions(pci_dev, "cobalt");
+ if (ret) {
+ cobalt_err("error requesting regions\n");
+ goto err_disable;
+ }
+
+ cobalt_pcie_status_show(cobalt);
+
+ cobalt->bar0 = pci_iomap(pci_dev, 0, 0);
+ cobalt->bar1 = pci_iomap(pci_dev, 1, 0);
+ if (cobalt->bar1 == NULL) {
+ cobalt->bar1 = pci_iomap(pci_dev, 2, 0);
+ cobalt_info("64-bit BAR\n");
+ }
+ if (!cobalt->bar0 || !cobalt->bar1) {
+ ret = -EIO;
+ goto err_release;
+ }
+
+ /* Reset the video inputs before enabling any interrupts */
+ ctrl = cobalt_read_bar1(cobalt, COBALT_SYS_CTRL_BASE);
+ cobalt_write_bar1(cobalt, COBALT_SYS_CTRL_BASE, ctrl & ~0xf00);
+
+ /* Disable interrupts to prevent any spurious interrupts
+ from being generated. */
+ cobalt_set_interrupt(cobalt, false);
+
+ if (pci_enable_msi_range(pci_dev, 1, 1) < 1) {
+ cobalt_err("Could not enable MSI\n");
+ cobalt->msi_enabled = false;
+ ret = -EIO;
+ goto err_release;
+ }
+ msi_config_show(cobalt, pci_dev);
+ cobalt->msi_enabled = true;
+
+ /* Register IRQ */
+ if (request_irq(pci_dev->irq, cobalt_irq_handler, IRQF_SHARED,
+ cobalt->v4l2_dev.name, (void *)cobalt)) {
+ cobalt_err("Failed to register irq %d\n", pci_dev->irq);
+ ret = -EIO;
+ goto err_msi;
+ }
+
+ omni_sg_dma_init(cobalt);
+ return 0;
+
+err_msi:
+ pci_disable_msi(pci_dev);
+
+err_release:
+ cobalt_pci_iounmap(cobalt, pci_dev);
+ pci_release_regions(pci_dev);
+
+err_disable:
+ pci_disable_device(cobalt->pci_dev);
+ return ret;
+}
+
+static int cobalt_hdl_info_get(struct cobalt *cobalt)
+{
+ int i;
+
+ for (i = 0; i < COBALT_HDL_INFO_SIZE; i++)
+ cobalt->hdl_info[i] =
+ ioread8(cobalt->bar1 + COBALT_HDL_INFO_BASE + i);
+ cobalt->hdl_info[COBALT_HDL_INFO_SIZE - 1] = '\0';
+ if (strstr(cobalt->hdl_info, COBALT_HDL_SEARCH_STR))
+ return 0;
+
+ return 1;
+}
+
+static void cobalt_stream_struct_init(struct cobalt *cobalt)
+{
+ int i;
+
+ for (i = 0; i < COBALT_NUM_STREAMS; i++) {
+ struct cobalt_stream *s = &cobalt->streams[i];
+
+ s->cobalt = cobalt;
+ s->flags = 0;
+ s->is_audio = false;
+ s->is_output = false;
+ s->is_dummy = true;
+
+ /* The Memory DMA channels will always get a lower channel
+ * number than the FIFO DMA. Video input should map to the
+ * stream 0-3. The other can use stream struct from 4 and
+ * higher */
+ if (i <= COBALT_HSMA_IN_NODE) {
+ s->dma_channel = i + cobalt->first_fifo_channel;
+ s->video_channel = i;
+ s->dma_fifo_mask =
+ COBALT_SYSSTAT_VI0_LOST_DATA_MSK << (4 * i);
+ s->adv_irq_mask =
+ COBALT_SYSSTAT_VI0_INT1_MSK << (4 * i);
+ } else if (i >= COBALT_AUDIO_IN_STREAM &&
+ i <= COBALT_AUDIO_IN_STREAM + 4) {
+ unsigned idx = i - COBALT_AUDIO_IN_STREAM;
+
+ s->dma_channel = 6 + idx;
+ s->is_audio = true;
+ s->video_channel = idx;
+ s->dma_fifo_mask = COBALT_SYSSTAT_AUD_IN_LOST_DATA_MSK;
+ } else if (i == COBALT_HSMA_OUT_NODE) {
+ s->dma_channel = 11;
+ s->is_output = true;
+ s->video_channel = 5;
+ s->dma_fifo_mask = COBALT_SYSSTAT_VOHSMA_LOST_DATA_MSK;
+ s->adv_irq_mask = COBALT_SYSSTAT_VOHSMA_INT1_MSK;
+ } else if (i == COBALT_AUDIO_OUT_STREAM) {
+ s->dma_channel = 12;
+ s->is_audio = true;
+ s->is_output = true;
+ s->video_channel = 5;
+ s->dma_fifo_mask = COBALT_SYSSTAT_AUD_OUT_LOST_DATA_MSK;
+ } else {
+ /* FIXME: Memory DMA for debug purpose */
+ s->dma_channel = i - COBALT_NUM_NODES;
+ }
+ cobalt_info("stream #%d -> dma channel #%d <- video channel %d\n",
+ i, s->dma_channel, s->video_channel);
+ }
+}
+
+static int cobalt_subdevs_init(struct cobalt *cobalt)
+{
+ static struct adv76xx_platform_data adv7604_pdata = {
+ .disable_pwrdnb = 1,
+ .ain_sel = ADV7604_AIN7_8_9_NC_SYNC_3_1,
+ .bus_order = ADV7604_BUS_ORDER_BRG,
+ .blank_data = 1,
+ .op_656_range = 1,
+ .op_format_mode_sel = ADV7604_OP_FORMAT_MODE0,
+ .int1_config = ADV76XX_INT1_CONFIG_ACTIVE_HIGH,
+ .dr_str_data = ADV76XX_DR_STR_HIGH,
+ .dr_str_clk = ADV76XX_DR_STR_HIGH,
+ .dr_str_sync = ADV76XX_DR_STR_HIGH,
+ .hdmi_free_run_mode = 1,
+ .inv_vs_pol = 1,
+ .inv_hs_pol = 1,
+ };
+ static struct i2c_board_info adv7604_info = {
+ .type = "adv7604",
+ .addr = 0x20,
+ .platform_data = &adv7604_pdata,
+ };
+
+ struct cobalt_stream *s = cobalt->streams;
+ int i;
+
+ for (i = 0; i < COBALT_NUM_INPUTS; i++) {
+ struct v4l2_subdev_format sd_fmt = {
+ .pad = ADV7604_PAD_SOURCE,
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ .format.code = MEDIA_BUS_FMT_YUYV8_1X16,
+ };
+ struct v4l2_subdev_edid cobalt_edid = {
+ .pad = ADV76XX_PAD_HDMI_PORT_A,
+ .start_block = 0,
+ .blocks = 2,
+ .edid = edid,
+ };
+ int err;
+
+ s[i].pad_source = ADV7604_PAD_SOURCE;
+ s[i].i2c_adap = &cobalt->i2c_adap[i];
+ if (s[i].i2c_adap->dev.parent == NULL)
+ continue;
+ cobalt_s_bit_sysctrl(cobalt,
+ COBALT_SYS_CTRL_NRESET_TO_HDMI_BIT(i), 1);
+ s[i].sd = v4l2_i2c_new_subdev_board(&cobalt->v4l2_dev,
+ s[i].i2c_adap, &adv7604_info, NULL);
+ if (!s[i].sd) {
+ if (cobalt_ignore_err)
+ continue;
+ return -ENODEV;
+ }
+ err = v4l2_subdev_call(s[i].sd, video, s_routing,
+ ADV76XX_PAD_HDMI_PORT_A, 0, 0);
+ if (err)
+ return err;
+ err = v4l2_subdev_call(s[i].sd, pad, set_edid,
+ &cobalt_edid);
+ if (err)
+ return err;
+ err = v4l2_subdev_call(s[i].sd, pad, set_fmt, NULL,
+ &sd_fmt);
+ if (err)
+ return err;
+ /* Reset channel video module */
+ cobalt_s_bit_sysctrl(cobalt,
+ COBALT_SYS_CTRL_VIDEO_RX_RESETN_BIT(i), 0);
+ mdelay(2);
+ cobalt_s_bit_sysctrl(cobalt,
+ COBALT_SYS_CTRL_VIDEO_RX_RESETN_BIT(i), 1);
+ mdelay(1);
+ s[i].is_dummy = false;
+ cobalt->streams[i + COBALT_AUDIO_IN_STREAM].is_dummy = false;
+ }
+ return 0;
+}
+
+static int cobalt_subdevs_hsma_init(struct cobalt *cobalt)
+{
+ static struct adv7842_platform_data adv7842_pdata = {
+ .disable_pwrdnb = 1,
+ .ain_sel = ADV7842_AIN1_2_3_NC_SYNC_1_2,
+ .bus_order = ADV7842_BUS_ORDER_RBG,
+ .op_format_mode_sel = ADV7842_OP_FORMAT_MODE0,
+ .blank_data = 1,
+ .op_656_range = 1,
+ .dr_str_data = 3,
+ .dr_str_clk = 3,
+ .dr_str_sync = 3,
+ .mode = ADV7842_MODE_HDMI,
+ .hdmi_free_run_enable = 1,
+ .vid_std_select = ADV7842_HDMI_COMP_VID_STD_HD_1250P,
+ .i2c_sdp_io = 0x4a,
+ .i2c_sdp = 0x48,
+ .i2c_cp = 0x22,
+ .i2c_vdp = 0x24,
+ .i2c_afe = 0x26,
+ .i2c_hdmi = 0x34,
+ .i2c_repeater = 0x32,
+ .i2c_edid = 0x36,
+ .i2c_infoframe = 0x3e,
+ .i2c_cec = 0x40,
+ .i2c_avlink = 0x42,
+ };
+ static struct i2c_board_info adv7842_info = {
+ .type = "adv7842",
+ .addr = 0x20,
+ .platform_data = &adv7842_pdata,
+ };
+ static struct v4l2_subdev_format sd_fmt = {
+ .pad = ADV7842_PAD_SOURCE,
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ .format.code = MEDIA_BUS_FMT_YUYV8_1X16,
+ };
+ static struct adv7511_platform_data adv7511_pdata = {
+ .i2c_edid = 0x7e >> 1,
+ .i2c_cec = 0x7c >> 1,
+ .i2c_pktmem = 0x70 >> 1,
+ .cec_clk = 12000000,
+ };
+ static struct i2c_board_info adv7511_info = {
+ .type = "adv7511",
+ .addr = 0x39, /* 0x39 or 0x3d */
+ .platform_data = &adv7511_pdata,
+ };
+ struct v4l2_subdev_edid cobalt_edid = {
+ .pad = ADV7842_EDID_PORT_A,
+ .start_block = 0,
+ .blocks = 2,
+ .edid = edid,
+ };
+ struct cobalt_stream *s = &cobalt->streams[COBALT_HSMA_IN_NODE];
+
+ s->i2c_adap = &cobalt->i2c_adap[COBALT_NUM_ADAPTERS - 1];
+ if (s->i2c_adap->dev.parent == NULL)
+ return 0;
+ cobalt_s_bit_sysctrl(cobalt, COBALT_SYS_CTRL_NRESET_TO_HDMI_BIT(4), 1);
+
+ s->sd = v4l2_i2c_new_subdev_board(&cobalt->v4l2_dev,
+ s->i2c_adap, &adv7842_info, NULL);
+ if (s->sd) {
+ int err = v4l2_subdev_call(s->sd, pad, set_edid, &cobalt_edid);
+
+ if (err)
+ return err;
+ err = v4l2_subdev_call(s->sd, pad, set_fmt, NULL,
+ &sd_fmt);
+ if (err)
+ return err;
+ cobalt->have_hsma_rx = true;
+ s->pad_source = ADV7842_PAD_SOURCE;
+ s->is_dummy = false;
+ cobalt->streams[4 + COBALT_AUDIO_IN_STREAM].is_dummy = false;
+ /* Reset channel video module */
+ cobalt_s_bit_sysctrl(cobalt,
+ COBALT_SYS_CTRL_VIDEO_RX_RESETN_BIT(4), 0);
+ mdelay(2);
+ cobalt_s_bit_sysctrl(cobalt,
+ COBALT_SYS_CTRL_VIDEO_RX_RESETN_BIT(4), 1);
+ mdelay(1);
+ return err;
+ }
+ cobalt_s_bit_sysctrl(cobalt, COBALT_SYS_CTRL_NRESET_TO_HDMI_BIT(4), 0);
+ cobalt_s_bit_sysctrl(cobalt, COBALT_SYS_CTRL_PWRDN0_TO_HSMA_TX_BIT, 0);
+ s++;
+ s->i2c_adap = &cobalt->i2c_adap[COBALT_NUM_ADAPTERS - 1];
+ s->sd = v4l2_i2c_new_subdev_board(&cobalt->v4l2_dev,
+ s->i2c_adap, &adv7511_info, NULL);
+ if (s->sd) {
+ /* A transmitter is hooked up, so we can set this bit */
+ cobalt_s_bit_sysctrl(cobalt,
+ COBALT_SYS_CTRL_HSMA_TX_ENABLE_BIT, 1);
+ cobalt_s_bit_sysctrl(cobalt,
+ COBALT_SYS_CTRL_VIDEO_RX_RESETN_BIT(4), 0);
+ cobalt_s_bit_sysctrl(cobalt,
+ COBALT_SYS_CTRL_VIDEO_TX_RESETN_BIT, 1);
+ cobalt->have_hsma_tx = true;
+ v4l2_subdev_call(s->sd, core, s_power, 1);
+ v4l2_subdev_call(s->sd, video, s_stream, 1);
+ v4l2_subdev_call(s->sd, audio, s_stream, 1);
+ v4l2_ctrl_s_ctrl(v4l2_ctrl_find(s->sd->ctrl_handler,
+ V4L2_CID_DV_TX_MODE), V4L2_DV_TX_MODE_HDMI);
+ s->is_dummy = false;
+ cobalt->streams[COBALT_AUDIO_OUT_STREAM].is_dummy = false;
+ return 0;
+ }
+ return -ENODEV;
+}
+
+static int cobalt_probe(struct pci_dev *pci_dev,
+ const struct pci_device_id *pci_id)
+{
+ struct cobalt *cobalt;
+ int retval = 0;
+ int i;
+
+ /* FIXME - module parameter arrays constrain max instances */
+ i = atomic_inc_return(&cobalt_instance) - 1;
+
+ cobalt = kzalloc(sizeof(struct cobalt), GFP_ATOMIC);
+ if (cobalt == NULL)
+ return -ENOMEM;
+ cobalt->pci_dev = pci_dev;
+ cobalt->instance = i;
+
+ cobalt->alloc_ctx = vb2_dma_sg_init_ctx(&pci_dev->dev);
+ if (IS_ERR(cobalt->alloc_ctx)) {
+ kfree(cobalt);
+ return -ENOMEM;
+ }
+
+ retval = v4l2_device_register(&pci_dev->dev, &cobalt->v4l2_dev);
+ if (retval) {
+ pr_err("cobalt: v4l2_device_register of card %d failed\n",
+ cobalt->instance);
+ vb2_dma_sg_cleanup_ctx(cobalt->alloc_ctx);
+ kfree(cobalt);
+ return retval;
+ }
+ snprintf(cobalt->v4l2_dev.name, sizeof(cobalt->v4l2_dev.name),
+ "cobalt-%d", cobalt->instance);
+ cobalt->v4l2_dev.notify = cobalt_notify;
+ cobalt_info("Initializing card %d\n", cobalt->instance);
+
+ cobalt->irq_work_queues =
+ create_singlethread_workqueue(cobalt->v4l2_dev.name);
+ if (cobalt->irq_work_queues == NULL) {
+ cobalt_err("Could not create workqueue\n");
+ retval = -ENOMEM;
+ goto err;
+ }
+
+ INIT_WORK(&cobalt->irq_work_queue, cobalt_irq_work_handler);
+
+ /* PCI Device Setup */
+ retval = cobalt_setup_pci(cobalt, pci_dev, pci_id);
+ if (retval != 0)
+ goto err_wq;
+
+ /* Show HDL version info */
+ if (cobalt_hdl_info_get(cobalt))
+ cobalt_info("Not able to read the HDL info\n");
+ else
+ cobalt_info("%s", cobalt->hdl_info);
+
+ retval = cobalt_i2c_init(cobalt);
+ if (retval)
+ goto err_pci;
+
+ cobalt_stream_struct_init(cobalt);
+
+ retval = cobalt_subdevs_init(cobalt);
+ if (retval)
+ goto err_i2c;
+
+ if (!(cobalt_read_bar1(cobalt, COBALT_SYS_STAT_BASE) &
+ COBALT_SYSSTAT_HSMA_PRSNTN_MSK)) {
+ retval = cobalt_subdevs_hsma_init(cobalt);
+ if (retval)
+ goto err_i2c;
+ }
+
+ retval = v4l2_device_register_subdev_nodes(&cobalt->v4l2_dev);
+ if (retval)
+ goto err_i2c;
+ retval = cobalt_nodes_register(cobalt);
+ if (retval) {
+ cobalt_err("Error %d registering device nodes\n", retval);
+ goto err_i2c;
+ }
+ cobalt_set_interrupt(cobalt, true);
+ v4l2_device_call_all(&cobalt->v4l2_dev, 0, core,
+ interrupt_service_routine, 0, NULL);
+
+ cobalt_info("Initialized cobalt card\n");
+
+ cobalt_flash_probe(cobalt);
+
+ return 0;
+
+err_i2c:
+ cobalt_i2c_exit(cobalt);
+ cobalt_s_bit_sysctrl(cobalt, COBALT_SYS_CTRL_HSMA_TX_ENABLE_BIT, 0);
+err_pci:
+ cobalt_free_msi(cobalt, pci_dev);
+ cobalt_pci_iounmap(cobalt, pci_dev);
+ pci_release_regions(cobalt->pci_dev);
+ pci_disable_device(cobalt->pci_dev);
+err_wq:
+ destroy_workqueue(cobalt->irq_work_queues);
+err:
+ if (retval == 0)
+ retval = -ENODEV;
+ cobalt_err("error %d on initialization\n", retval);
+
+ v4l2_device_unregister(&cobalt->v4l2_dev);
+ vb2_dma_sg_cleanup_ctx(cobalt->alloc_ctx);
+ kfree(cobalt);
+ return retval;
+}
+
+static void cobalt_remove(struct pci_dev *pci_dev)
+{
+ struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
+ struct cobalt *cobalt = to_cobalt(v4l2_dev);
+ int i;
+
+ cobalt_flash_remove(cobalt);
+ cobalt_set_interrupt(cobalt, false);
+ flush_workqueue(cobalt->irq_work_queues);
+ cobalt_nodes_unregister(cobalt);
+ for (i = 0; i < COBALT_NUM_ADAPTERS; i++) {
+ struct v4l2_subdev *sd = cobalt->streams[i].sd;
+ struct i2c_client *client;
+
+ if (sd == NULL)
+ continue;
+ client = v4l2_get_subdevdata(sd);
+ v4l2_device_unregister_subdev(sd);
+ i2c_unregister_device(client);
+ }
+ cobalt_i2c_exit(cobalt);
+ cobalt_free_msi(cobalt, pci_dev);
+ cobalt_s_bit_sysctrl(cobalt, COBALT_SYS_CTRL_HSMA_TX_ENABLE_BIT, 0);
+ cobalt_pci_iounmap(cobalt, pci_dev);
+ pci_release_regions(cobalt->pci_dev);
+ pci_disable_device(cobalt->pci_dev);
+ destroy_workqueue(cobalt->irq_work_queues);
+
+ cobalt_info("removed cobalt card\n");
+
+ v4l2_device_unregister(v4l2_dev);
+ vb2_dma_sg_cleanup_ctx(cobalt->alloc_ctx);
+ kfree(cobalt);
+}
+
+/* define a pci_driver for card detection */
+static struct pci_driver cobalt_pci_driver = {
+ .name = "cobalt",
+ .id_table = cobalt_pci_tbl,
+ .probe = cobalt_probe,
+ .remove = cobalt_remove,
+};
+
+module_pci_driver(cobalt_pci_driver);
diff --git a/drivers/media/pci/cobalt/cobalt-driver.h b/drivers/media/pci/cobalt/cobalt-driver.h
new file mode 100644
index 000000000000..c206df930669
--- /dev/null
+++ b/drivers/media/pci/cobalt/cobalt-driver.h
@@ -0,0 +1,380 @@
+/*
+ * cobalt driver internal defines and structures
+ *
+ * Derived from cx18-driver.h
+ *
+ * Copyright 2012-2015 Cisco Systems, Inc. and/or its affiliates.
+ * All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef COBALT_DRIVER_H
+#define COBALT_DRIVER_H
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/i2c.h>
+#include <linux/list.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-fh.h>
+#include <media/videobuf2-dma-sg.h>
+
+#include "m00233_video_measure_memmap_package.h"
+#include "m00235_fdma_packer_memmap_package.h"
+#include "m00389_cvi_memmap_package.h"
+#include "m00460_evcnt_memmap_package.h"
+#include "m00473_freewheel_memmap_package.h"
+#include "m00479_clk_loss_detector_memmap_package.h"
+#include "m00514_syncgen_flow_evcnt_memmap_package.h"
+
+/* System device ID */
+#define PCI_DEVICE_ID_COBALT 0x2732
+
+/* Number of cobalt device nodes. */
+#define COBALT_NUM_INPUTS 4
+#define COBALT_NUM_NODES 6
+
+/* Number of cobalt device streams. */
+#define COBALT_NUM_STREAMS 12
+
+#define COBALT_HSMA_IN_NODE 4
+#define COBALT_HSMA_OUT_NODE 5
+
+/* Cobalt audio streams */
+#define COBALT_AUDIO_IN_STREAM 6
+#define COBALT_AUDIO_OUT_STREAM 11
+
+/* DMA stuff */
+#define DMA_CHANNELS_MAX 16
+
+/* i2c stuff */
+#define I2C_CLIENTS_MAX 16
+#define COBALT_NUM_ADAPTERS 5
+
+#define COBALT_CLK 50000000
+
+/* System status register */
+#define COBALT_SYSSTAT_DIP0_MSK (1 << 0)
+#define COBALT_SYSSTAT_DIP1_MSK (1 << 1)
+#define COBALT_SYSSTAT_HSMA_PRSNTN_MSK (1 << 2)
+#define COBALT_SYSSTAT_FLASH_RDYBSYN_MSK (1 << 3)
+#define COBALT_SYSSTAT_VI0_5V_MSK (1 << 4)
+#define COBALT_SYSSTAT_VI0_INT1_MSK (1 << 5)
+#define COBALT_SYSSTAT_VI0_INT2_MSK (1 << 6)
+#define COBALT_SYSSTAT_VI0_LOST_DATA_MSK (1 << 7)
+#define COBALT_SYSSTAT_VI1_5V_MSK (1 << 8)
+#define COBALT_SYSSTAT_VI1_INT1_MSK (1 << 9)
+#define COBALT_SYSSTAT_VI1_INT2_MSK (1 << 10)
+#define COBALT_SYSSTAT_VI1_LOST_DATA_MSK (1 << 11)
+#define COBALT_SYSSTAT_VI2_5V_MSK (1 << 12)
+#define COBALT_SYSSTAT_VI2_INT1_MSK (1 << 13)
+#define COBALT_SYSSTAT_VI2_INT2_MSK (1 << 14)
+#define COBALT_SYSSTAT_VI2_LOST_DATA_MSK (1 << 15)
+#define COBALT_SYSSTAT_VI3_5V_MSK (1 << 16)
+#define COBALT_SYSSTAT_VI3_INT1_MSK (1 << 17)
+#define COBALT_SYSSTAT_VI3_INT2_MSK (1 << 18)
+#define COBALT_SYSSTAT_VI3_LOST_DATA_MSK (1 << 19)
+#define COBALT_SYSSTAT_VIHSMA_5V_MSK (1 << 20)
+#define COBALT_SYSSTAT_VIHSMA_INT1_MSK (1 << 21)
+#define COBALT_SYSSTAT_VIHSMA_INT2_MSK (1 << 22)
+#define COBALT_SYSSTAT_VIHSMA_LOST_DATA_MSK (1 << 23)
+#define COBALT_SYSSTAT_VOHSMA_INT1_MSK (1 << 24)
+#define COBALT_SYSSTAT_VOHSMA_PLL_LOCKED_MSK (1 << 25)
+#define COBALT_SYSSTAT_VOHSMA_LOST_DATA_MSK (1 << 26)
+#define COBALT_SYSSTAT_AUD_PLL_LOCKED_MSK (1 << 28)
+#define COBALT_SYSSTAT_AUD_IN_LOST_DATA_MSK (1 << 29)
+#define COBALT_SYSSTAT_AUD_OUT_LOST_DATA_MSK (1 << 30)
+#define COBALT_SYSSTAT_PCIE_SMBCLK_MSK (1 << 31)
+
+/* Cobalt memory map */
+#define COBALT_I2C_0_BASE 0x0
+#define COBALT_I2C_1_BASE 0x080
+#define COBALT_I2C_2_BASE 0x100
+#define COBALT_I2C_3_BASE 0x180
+#define COBALT_I2C_HSMA_BASE 0x200
+
+#define COBALT_SYS_CTRL_BASE 0x400
+#define COBALT_SYS_CTRL_HSMA_TX_ENABLE_BIT 1
+#define COBALT_SYS_CTRL_VIDEO_RX_RESETN_BIT(n) (4 + 4 * (n))
+#define COBALT_SYS_CTRL_NRESET_TO_HDMI_BIT(n) (5 + 4 * (n))
+#define COBALT_SYS_CTRL_HPD_TO_CONNECTOR_BIT(n) (6 + 4 * (n))
+#define COBALT_SYS_CTRL_AUDIO_IPP_RESETN_BIT(n) (7 + 4 * (n))
+#define COBALT_SYS_CTRL_PWRDN0_TO_HSMA_TX_BIT 24
+#define COBALT_SYS_CTRL_VIDEO_TX_RESETN_BIT 25
+#define COBALT_SYS_CTRL_AUDIO_OPP_RESETN_BIT 27
+
+#define COBALT_SYS_STAT_BASE 0x500
+#define COBALT_SYS_STAT_MASK (COBALT_SYS_STAT_BASE + 0x08)
+#define COBALT_SYS_STAT_EDGE (COBALT_SYS_STAT_BASE + 0x0c)
+
+#define COBALT_HDL_INFO_BASE 0x4800
+#define COBALT_HDL_INFO_SIZE 0x200
+
+#define COBALT_VID_BASE 0x10000
+#define COBALT_VID_SIZE 0x1000
+
+#define COBALT_CVI(cobalt, c) \
+ (cobalt->bar1 + COBALT_VID_BASE + (c) * COBALT_VID_SIZE)
+#define COBALT_CVI_VMR(cobalt, c) \
+ (cobalt->bar1 + COBALT_VID_BASE + (c) * COBALT_VID_SIZE + 0x100)
+#define COBALT_CVI_EVCNT(cobalt, c) \
+ (cobalt->bar1 + COBALT_VID_BASE + (c) * COBALT_VID_SIZE + 0x200)
+#define COBALT_CVI_FREEWHEEL(cobalt, c) \
+ (cobalt->bar1 + COBALT_VID_BASE + (c) * COBALT_VID_SIZE + 0x300)
+#define COBALT_CVI_CLK_LOSS(cobalt, c) \
+ (cobalt->bar1 + COBALT_VID_BASE + (c) * COBALT_VID_SIZE + 0x400)
+#define COBALT_CVI_PACKER(cobalt, c) \
+ (cobalt->bar1 + COBALT_VID_BASE + (c) * COBALT_VID_SIZE + 0x500)
+
+#define COBALT_TX_BASE(cobalt) (cobalt->bar1 + COBALT_VID_BASE + 0x5000)
+
+#define DMA_INTERRUPT_STATUS_REG 0x08
+
+#define COBALT_HDL_SEARCH_STR "** HDL version info **"
+
+/* Cobalt CPU bus interface */
+#define COBALT_BUS_BAR1_BASE 0x600
+#define COBALT_BUS_SRAM_BASE 0x0
+#define COBALT_BUS_CPLD_BASE 0x00600000
+#define COBALT_BUS_FLASH_BASE 0x08000000
+
+/* FDMA to PCIe packing */
+#define COBALT_BYTES_PER_PIXEL_YUYV 2
+#define COBALT_BYTES_PER_PIXEL_RGB24 3
+#define COBALT_BYTES_PER_PIXEL_RGB32 4
+
+/* debugging */
+extern int cobalt_debug;
+extern int cobalt_ignore_err;
+
+#define cobalt_err(fmt, arg...) v4l2_err(&cobalt->v4l2_dev, fmt, ## arg)
+#define cobalt_warn(fmt, arg...) v4l2_warn(&cobalt->v4l2_dev, fmt, ## arg)
+#define cobalt_info(fmt, arg...) v4l2_info(&cobalt->v4l2_dev, fmt, ## arg)
+#define cobalt_dbg(level, fmt, arg...) \
+ v4l2_dbg(level, cobalt_debug, &cobalt->v4l2_dev, fmt, ## arg)
+
+struct cobalt;
+struct cobalt_i2c_regs;
+
+/* Per I2C bus private algo callback data */
+struct cobalt_i2c_data {
+ struct cobalt *cobalt;
+ struct cobalt_i2c_regs __iomem *regs;
+};
+
+struct pci_consistent_buffer {
+ void *virt;
+ dma_addr_t bus;
+ size_t bytes;
+};
+
+struct sg_dma_desc_info {
+ void *virt;
+ dma_addr_t bus;
+ unsigned size;
+ void *last_desc_virt;
+ struct device *dev;
+};
+
+#define COBALT_MAX_WIDTH 1920
+#define COBALT_MAX_HEIGHT 1200
+#define COBALT_MAX_BPP 3
+#define COBALT_MAX_FRAMESZ \
+ (COBALT_MAX_WIDTH * COBALT_MAX_HEIGHT * COBALT_MAX_BPP)
+
+#define NR_BUFS VIDEO_MAX_FRAME
+
+#define COBALT_STREAM_FL_DMA_IRQ 0
+#define COBALT_STREAM_FL_ADV_IRQ 1
+
+struct cobalt_buffer {
+ struct vb2_buffer vb;
+ struct list_head list;
+};
+
+static inline struct cobalt_buffer *to_cobalt_buffer(struct vb2_buffer *vb2)
+{
+ return container_of(vb2, struct cobalt_buffer, vb);
+}
+
+struct cobalt_stream {
+ struct video_device vdev;
+ struct vb2_queue q;
+ struct list_head bufs;
+ struct i2c_adapter *i2c_adap;
+ struct v4l2_subdev *sd;
+ struct mutex lock;
+ spinlock_t irqlock;
+ struct v4l2_dv_timings timings;
+ u32 input;
+ u32 pad_source;
+ u32 width, height, bpp;
+ u32 stride;
+ u32 pixfmt;
+ u32 sequence;
+ u32 colorspace;
+ u32 xfer_func;
+ u32 ycbcr_enc;
+ u32 quantization;
+
+ u8 dma_channel;
+ int video_channel;
+ unsigned dma_fifo_mask;
+ unsigned adv_irq_mask;
+ struct sg_dma_desc_info dma_desc_info[NR_BUFS];
+ unsigned long flags;
+ bool unstable_frame;
+ bool enable_cvi;
+ bool enable_freewheel;
+ unsigned skip_first_frames;
+ bool is_output;
+ bool is_audio;
+ bool is_dummy;
+
+ struct cobalt *cobalt;
+ struct snd_cobalt_card *alsa;
+};
+
+struct snd_cobalt_card;
+
+/* Struct to hold info about cobalt cards */
+struct cobalt {
+ int instance;
+ struct pci_dev *pci_dev;
+ struct v4l2_device v4l2_dev;
+ void *alloc_ctx;
+
+ void __iomem *bar0, *bar1;
+
+ u8 card_rev;
+ u16 device_id;
+
+ /* device nodes */
+ struct cobalt_stream streams[DMA_CHANNELS_MAX];
+ struct i2c_adapter i2c_adap[COBALT_NUM_ADAPTERS];
+ struct cobalt_i2c_data i2c_data[COBALT_NUM_ADAPTERS];
+ bool have_hsma_rx;
+ bool have_hsma_tx;
+
+ /* irq */
+ struct workqueue_struct *irq_work_queues;
+ struct work_struct irq_work_queue; /* work entry */
+ /* irq counters */
+ u32 irq_adv1;
+ u32 irq_adv2;
+ u32 irq_advout;
+ u32 irq_dma_tot;
+ u32 irq_dma[COBALT_NUM_STREAMS];
+ u32 irq_none;
+ u32 irq_full_fifo;
+
+ bool msi_enabled;
+
+ /* omnitek dma */
+ int dma_channels;
+ int first_fifo_channel;
+ bool pci_32_bit;
+
+ char hdl_info[COBALT_HDL_INFO_SIZE];
+
+ /* NOR flash */
+ struct mtd_info *mtd;
+};
+
+static inline struct cobalt *to_cobalt(struct v4l2_device *v4l2_dev)
+{
+ return container_of(v4l2_dev, struct cobalt, v4l2_dev);
+}
+
+static inline void cobalt_write_bar0(struct cobalt *cobalt, u32 reg, u32 val)
+{
+ iowrite32(val, cobalt->bar0 + reg);
+}
+
+static inline u32 cobalt_read_bar0(struct cobalt *cobalt, u32 reg)
+{
+ return ioread32(cobalt->bar0 + reg);
+}
+
+static inline void cobalt_write_bar1(struct cobalt *cobalt, u32 reg, u32 val)
+{
+ iowrite32(val, cobalt->bar1 + reg);
+}
+
+static inline u32 cobalt_read_bar1(struct cobalt *cobalt, u32 reg)
+{
+ return ioread32(cobalt->bar1 + reg);
+}
+
+static inline u32 cobalt_g_sysctrl(struct cobalt *cobalt)
+{
+ return cobalt_read_bar1(cobalt, COBALT_SYS_CTRL_BASE);
+}
+
+static inline void cobalt_s_bit_sysctrl(struct cobalt *cobalt,
+ int bit, int val)
+{
+ u32 ctrl = cobalt_read_bar1(cobalt, COBALT_SYS_CTRL_BASE);
+
+ cobalt_write_bar1(cobalt, COBALT_SYS_CTRL_BASE,
+ (ctrl & ~(1UL << bit)) | (val << bit));
+}
+
+static inline u32 cobalt_g_sysstat(struct cobalt *cobalt)
+{
+ return cobalt_read_bar1(cobalt, COBALT_SYS_STAT_BASE);
+}
+
+#define ADRS_REG (bar1 + COBALT_BUS_BAR1_BASE + 0)
+#define LOWER_DATA (bar1 + COBALT_BUS_BAR1_BASE + 4)
+#define UPPER_DATA (bar1 + COBALT_BUS_BAR1_BASE + 6)
+
+static inline u32 cobalt_bus_read32(void __iomem *bar1, u32 bus_adrs)
+{
+ iowrite32(bus_adrs, ADRS_REG);
+ return ioread32(LOWER_DATA);
+}
+
+static inline void cobalt_bus_write16(void __iomem *bar1,
+ u32 bus_adrs, u16 data)
+{
+ iowrite32(bus_adrs, ADRS_REG);
+ if (bus_adrs & 2)
+ iowrite16(data, UPPER_DATA);
+ else
+ iowrite16(data, LOWER_DATA);
+}
+
+static inline void cobalt_bus_write32(void __iomem *bar1,
+ u32 bus_adrs, u16 data)
+{
+ iowrite32(bus_adrs, ADRS_REG);
+ if (bus_adrs & 2)
+ iowrite32(data, UPPER_DATA);
+ else
+ iowrite32(data, LOWER_DATA);
+}
+
+/*==============Prototypes==================*/
+
+void cobalt_pcie_status_show(struct cobalt *cobalt);
+
+#endif
diff --git a/drivers/media/pci/cobalt/cobalt-flash.c b/drivers/media/pci/cobalt/cobalt-flash.c
new file mode 100644
index 000000000000..04dcaf9198d2
--- /dev/null
+++ b/drivers/media/pci/cobalt/cobalt-flash.c
@@ -0,0 +1,128 @@
+/*
+ * Cobalt NOR flash functions
+ *
+ * Copyright 2012-2015 Cisco Systems, Inc. and/or its affiliates.
+ * All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/cfi.h>
+#include <linux/time.h>
+
+#include "cobalt-flash.h"
+
+#define ADRS(offset) (COBALT_BUS_FLASH_BASE + offset)
+
+static struct map_info cobalt_flash_map = {
+ .name = "cobalt-flash",
+ .bankwidth = 2, /* 16 bits */
+ .size = 0x4000000, /* 64MB */
+ .phys = 0, /* offset */
+};
+
+static map_word flash_read16(struct map_info *map, unsigned long offset)
+{
+ map_word r;
+
+ r.x[0] = cobalt_bus_read32(map->virt, ADRS(offset));
+ if (offset & 0x2)
+ r.x[0] >>= 16;
+ else
+ r.x[0] &= 0x0000ffff;
+
+ return r;
+}
+
+static void flash_write16(struct map_info *map, const map_word datum,
+ unsigned long offset)
+{
+ u16 data = (u16)datum.x[0];
+
+ cobalt_bus_write16(map->virt, ADRS(offset), data);
+}
+
+static void flash_copy_from(struct map_info *map, void *to,
+ unsigned long from, ssize_t len)
+{
+ u32 src = from;
+ u8 *dest = to;
+ u32 data;
+
+ while (len) {
+ data = cobalt_bus_read32(map->virt, ADRS(src));
+ do {
+ *dest = data >> (8 * (src & 3));
+ src++;
+ dest++;
+ len--;
+ } while (len && (src % 4));
+ }
+}
+
+static void flash_copy_to(struct map_info *map, unsigned long to,
+ const void *from, ssize_t len)
+{
+ const u8 *src = from;
+ u32 dest = to;
+
+ pr_info("%s: offset 0x%x: length %zu\n", __func__, dest, len);
+ while (len) {
+ u16 data = 0xffff;
+
+ do {
+ data = *src << (8 * (dest & 1));
+ src++;
+ dest++;
+ len--;
+ } while (len && (dest % 2));
+
+ cobalt_bus_write16(map->virt, ADRS(dest - 2), data);
+ }
+}
+
+int cobalt_flash_probe(struct cobalt *cobalt)
+{
+ struct map_info *map = &cobalt_flash_map;
+ struct mtd_info *mtd;
+
+ BUG_ON(!map_bankwidth_supported(map->bankwidth));
+ map->virt = cobalt->bar1;
+ map->read = flash_read16;
+ map->write = flash_write16;
+ map->copy_from = flash_copy_from;
+ map->copy_to = flash_copy_to;
+
+ mtd = do_map_probe("cfi_probe", map);
+ cobalt->mtd = mtd;
+ if (!mtd) {
+ cobalt_err("Probe CFI flash failed!\n");
+ return -1;
+ }
+
+ mtd->owner = THIS_MODULE;
+ mtd->dev.parent = &cobalt->pci_dev->dev;
+ mtd_device_register(mtd, NULL, 0);
+ return 0;
+}
+
+void cobalt_flash_remove(struct cobalt *cobalt)
+{
+ if (cobalt->mtd) {
+ mtd_device_unregister(cobalt->mtd);
+ map_destroy(cobalt->mtd);
+ }
+}
diff --git a/drivers/media/pci/cobalt/cobalt-flash.h b/drivers/media/pci/cobalt/cobalt-flash.h
new file mode 100644
index 000000000000..8077daea51cd
--- /dev/null
+++ b/drivers/media/pci/cobalt/cobalt-flash.h
@@ -0,0 +1,29 @@
+/*
+ * Cobalt NOR flash functions
+ *
+ * Copyright 2012-2015 Cisco Systems, Inc. and/or its affiliates.
+ * All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef COBALT_FLASH_H
+#define COBALT_FLASH_H
+
+#include "cobalt-driver.h"
+
+int cobalt_flash_probe(struct cobalt *cobalt);
+void cobalt_flash_remove(struct cobalt *cobalt);
+
+#endif
diff --git a/drivers/media/pci/cobalt/cobalt-i2c.c b/drivers/media/pci/cobalt/cobalt-i2c.c
new file mode 100644
index 000000000000..ad16b89b8d0c
--- /dev/null
+++ b/drivers/media/pci/cobalt/cobalt-i2c.c
@@ -0,0 +1,396 @@
+/*
+ * cobalt I2C functions
+ *
+ * Derived from cx18-i2c.c
+ *
+ * Copyright 2012-2015 Cisco Systems, Inc. and/or its affiliates.
+ * All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "cobalt-driver.h"
+#include "cobalt-i2c.h"
+
+struct cobalt_i2c_regs {
+ /* Clock prescaler register lo-byte */
+ u8 prerlo;
+ u8 dummy0[3];
+ /* Clock prescaler register high-byte */
+ u8 prerhi;
+ u8 dummy1[3];
+ /* Control register */
+ u8 ctr;
+ u8 dummy2[3];
+ /* Transmit/Receive register */
+ u8 txr_rxr;
+ u8 dummy3[3];
+ /* Command and Status register */
+ u8 cr_sr;
+ u8 dummy4[3];
+};
+
+/* CTR[7:0] - Control register */
+
+/* I2C Core enable bit */
+#define M00018_CTR_BITMAP_EN_MSK (1 << 7)
+
+/* I2C Core interrupt enable bit */
+#define M00018_CTR_BITMAP_IEN_MSK (1 << 6)
+
+/* CR[7:0] - Command register */
+
+/* I2C start condition */
+#define M00018_CR_BITMAP_STA_MSK (1 << 7)
+
+/* I2C stop condition */
+#define M00018_CR_BITMAP_STO_MSK (1 << 6)
+
+/* I2C read from slave */
+#define M00018_CR_BITMAP_RD_MSK (1 << 5)
+
+/* I2C write to slave */
+#define M00018_CR_BITMAP_WR_MSK (1 << 4)
+
+/* I2C ack */
+#define M00018_CR_BITMAP_ACK_MSK (1 << 3)
+
+/* I2C Interrupt ack */
+#define M00018_CR_BITMAP_IACK_MSK (1 << 0)
+
+/* SR[7:0] - Status register */
+
+/* Receive acknowledge from slave */
+#define M00018_SR_BITMAP_RXACK_MSK (1 << 7)
+
+/* Busy, I2C bus busy (as defined by start / stop bits) */
+#define M00018_SR_BITMAP_BUSY_MSK (1 << 6)
+
+/* Arbitration lost - core lost arbitration */
+#define M00018_SR_BITMAP_AL_MSK (1 << 5)
+
+/* Transfer in progress */
+#define M00018_SR_BITMAP_TIP_MSK (1 << 1)
+
+/* Interrupt flag */
+#define M00018_SR_BITMAP_IF_MSK (1 << 0)
+
+/* Frequency, in Hz */
+#define I2C_FREQUENCY 400000
+#define ALT_CPU_FREQ 83333333
+
+static struct cobalt_i2c_regs __iomem *
+cobalt_i2c_regs(struct cobalt *cobalt, unsigned idx)
+{
+ switch (idx) {
+ case 0:
+ default:
+ return (struct cobalt_i2c_regs __iomem *)
+ (cobalt->bar1 + COBALT_I2C_0_BASE);
+ case 1:
+ return (struct cobalt_i2c_regs __iomem *)
+ (cobalt->bar1 + COBALT_I2C_1_BASE);
+ case 2:
+ return (struct cobalt_i2c_regs __iomem *)
+ (cobalt->bar1 + COBALT_I2C_2_BASE);
+ case 3:
+ return (struct cobalt_i2c_regs __iomem *)
+ (cobalt->bar1 + COBALT_I2C_3_BASE);
+ case 4:
+ return (struct cobalt_i2c_regs __iomem *)
+ (cobalt->bar1 + COBALT_I2C_HSMA_BASE);
+ }
+}
+
+/* Do low-level i2c byte transfer.
+ * Returns -1 in case of an error or 0 otherwise.
+ */
+static int cobalt_tx_bytes(struct cobalt_i2c_regs __iomem *regs,
+ struct i2c_adapter *adap, bool start, bool stop,
+ u8 *data, u16 len)
+{
+ unsigned long start_time;
+ int status;
+ int cmd;
+ int i;
+
+ for (i = 0; i < len; i++) {
+ /* Setup data */
+ iowrite8(data[i], &regs->txr_rxr);
+
+ /* Setup command */
+ if (i == 0 && start != 0) {
+ /* Write + Start */
+ cmd = M00018_CR_BITMAP_WR_MSK |
+ M00018_CR_BITMAP_STA_MSK;
+ } else if (i == len - 1 && stop != 0) {
+ /* Write + Stop */
+ cmd = M00018_CR_BITMAP_WR_MSK |
+ M00018_CR_BITMAP_STO_MSK;
+ } else {
+ /* Write only */
+ cmd = M00018_CR_BITMAP_WR_MSK;
+ }
+
+ /* Execute command */
+ iowrite8(cmd, &regs->cr_sr);
+
+ /* Wait for transfer to complete (TIP = 0) */
+ start_time = jiffies;
+ status = ioread8(&regs->cr_sr);
+ while (status & M00018_SR_BITMAP_TIP_MSK) {
+ if (time_after(jiffies, start_time + adap->timeout))
+ return -ETIMEDOUT;
+ cond_resched();
+ status = ioread8(&regs->cr_sr);
+ }
+
+ /* Verify ACK */
+ if (status & M00018_SR_BITMAP_RXACK_MSK) {
+ /* NO ACK! */
+ return -EIO;
+ }
+
+ /* Verify arbitration */
+ if (status & M00018_SR_BITMAP_AL_MSK) {
+ /* Arbitration lost! */
+ return -EIO;
+ }
+ }
+ return 0;
+}
+
+/* Do low-level i2c byte read.
+ * Returns -1 in case of an error or 0 otherwise.
+ */
+static int cobalt_rx_bytes(struct cobalt_i2c_regs __iomem *regs,
+ struct i2c_adapter *adap, bool start, bool stop,
+ u8 *data, u16 len)
+{
+ unsigned long start_time;
+ int status;
+ int cmd;
+ int i;
+
+ for (i = 0; i < len; i++) {
+ /* Setup command */
+ if (i == 0 && start != 0) {
+ /* Read + Start */
+ cmd = M00018_CR_BITMAP_RD_MSK |
+ M00018_CR_BITMAP_STA_MSK;
+ } else if (i == len - 1 && stop != 0) {
+ /* Read + Stop */
+ cmd = M00018_CR_BITMAP_RD_MSK |
+ M00018_CR_BITMAP_STO_MSK;
+ } else {
+ /* Read only */
+ cmd = M00018_CR_BITMAP_RD_MSK;
+ }
+
+ /* Last byte to read, no ACK */
+ if (i == len - 1)
+ cmd |= M00018_CR_BITMAP_ACK_MSK;
+
+ /* Execute command */
+ iowrite8(cmd, &regs->cr_sr);
+
+ /* Wait for transfer to complete (TIP = 0) */
+ start_time = jiffies;
+ status = ioread8(&regs->cr_sr);
+ while (status & M00018_SR_BITMAP_TIP_MSK) {
+ if (time_after(jiffies, start_time + adap->timeout))
+ return -ETIMEDOUT;
+ cond_resched();
+ status = ioread8(&regs->cr_sr);
+ }
+
+ /* Verify arbitration */
+ if (status & M00018_SR_BITMAP_AL_MSK) {
+ /* Arbitration lost! */
+ return -EIO;
+ }
+
+ /* Store data */
+ data[i] = ioread8(&regs->txr_rxr);
+ }
+ return 0;
+}
+
+/* Generate stop condition on i2c bus.
+ * The m00018 stop isn't doing the right thing (wrong timing).
+ * So instead send a start condition, 8 zeroes and a stop condition.
+ */
+static int cobalt_stop(struct cobalt_i2c_regs __iomem *regs,
+ struct i2c_adapter *adap)
+{
+ u8 data = 0;
+
+ return cobalt_tx_bytes(regs, adap, true, true, &data, 1);
+}
+
+static int cobalt_xfer(struct i2c_adapter *adap,
+ struct i2c_msg msgs[], int num)
+{
+ struct cobalt_i2c_data *data = adap->algo_data;
+ struct cobalt_i2c_regs __iomem *regs = data->regs;
+ struct i2c_msg *pmsg;
+ unsigned short flags;
+ int ret = 0;
+ int i, j;
+
+ for (i = 0; i < num; i++) {
+ int stop = (i == num - 1);
+
+ pmsg = &msgs[i];
+ flags = pmsg->flags;
+
+ if (!(pmsg->flags & I2C_M_NOSTART)) {
+ u8 addr = pmsg->addr << 1;
+
+ if (flags & I2C_M_RD)
+ addr |= 1;
+ if (flags & I2C_M_REV_DIR_ADDR)
+ addr ^= 1;
+ for (j = 0; j < adap->retries; j++) {
+ ret = cobalt_tx_bytes(regs, adap, true, false,
+ &addr, 1);
+ if (!ret)
+ break;
+ cobalt_stop(regs, adap);
+ }
+ if (ret < 0)
+ return ret;
+ ret = 0;
+ }
+ if (pmsg->flags & I2C_M_RD) {
+ /* read bytes into buffer */
+ ret = cobalt_rx_bytes(regs, adap, false, stop,
+ pmsg->buf, pmsg->len);
+ if (ret < 0)
+ goto bailout;
+ } else {
+ /* write bytes from buffer */
+ ret = cobalt_tx_bytes(regs, adap, false, stop,
+ pmsg->buf, pmsg->len);
+ if (ret < 0)
+ goto bailout;
+ }
+ }
+ ret = i;
+
+bailout:
+ if (ret < 0)
+ cobalt_stop(regs, adap);
+ return ret;
+}
+
+static u32 cobalt_func(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+/* template for i2c-bit-algo */
+static struct i2c_adapter cobalt_i2c_adap_template = {
+ .name = "cobalt i2c driver",
+ .algo = NULL, /* set by i2c-algo-bit */
+ .algo_data = NULL, /* filled from template */
+ .owner = THIS_MODULE,
+};
+
+static const struct i2c_algorithm cobalt_algo = {
+ .master_xfer = cobalt_xfer,
+ .functionality = cobalt_func,
+};
+
+/* init + register i2c algo-bit adapter */
+int cobalt_i2c_init(struct cobalt *cobalt)
+{
+ int i, err;
+ int status;
+ int prescale;
+ unsigned long start_time;
+
+ cobalt_dbg(1, "i2c init\n");
+
+ /* Define I2C clock prescaler */
+ prescale = ((ALT_CPU_FREQ) / (5 * I2C_FREQUENCY)) - 1;
+
+ for (i = 0; i < COBALT_NUM_ADAPTERS; i++) {
+ struct cobalt_i2c_regs __iomem *regs =
+ cobalt_i2c_regs(cobalt, i);
+ struct i2c_adapter *adap = &cobalt->i2c_adap[i];
+
+ /* Disable I2C */
+ iowrite8(M00018_CTR_BITMAP_EN_MSK, &regs->cr_sr);
+ iowrite8(0, &regs->ctr);
+ iowrite8(0, &regs->cr_sr);
+
+ start_time = jiffies;
+ do {
+ if (time_after(jiffies, start_time + HZ)) {
+ if (cobalt_ignore_err) {
+ adap->dev.parent = NULL;
+ return 0;
+ }
+ return -ETIMEDOUT;
+ }
+ status = ioread8(&regs->cr_sr);
+ } while (status & M00018_SR_BITMAP_TIP_MSK);
+
+ /* Disable I2C */
+ iowrite8(0, &regs->ctr);
+ iowrite8(0, &regs->cr_sr);
+
+ /* Calculate i2c prescaler */
+ iowrite8(prescale & 0xff, &regs->prerlo);
+ iowrite8((prescale >> 8) & 0xff, &regs->prerhi);
+ /* Enable I2C, interrupts disabled */
+ iowrite8(M00018_CTR_BITMAP_EN_MSK, &regs->ctr);
+ /* Setup algorithm for adapter */
+ cobalt->i2c_data[i].cobalt = cobalt;
+ cobalt->i2c_data[i].regs = regs;
+ *adap = cobalt_i2c_adap_template;
+ adap->algo = &cobalt_algo;
+ adap->algo_data = &cobalt->i2c_data[i];
+ adap->retries = 3;
+ sprintf(adap->name + strlen(adap->name),
+ " #%d-%d", cobalt->instance, i);
+ i2c_set_adapdata(adap, &cobalt->v4l2_dev);
+ adap->dev.parent = &cobalt->pci_dev->dev;
+ err = i2c_add_adapter(adap);
+ if (err) {
+ if (cobalt_ignore_err) {
+ adap->dev.parent = NULL;
+ return 0;
+ }
+ while (i--)
+ i2c_del_adapter(&cobalt->i2c_adap[i]);
+ return err;
+ }
+ cobalt_info("registered bus %s\n", adap->name);
+ }
+ return 0;
+}
+
+void cobalt_i2c_exit(struct cobalt *cobalt)
+{
+ int i;
+
+ cobalt_dbg(1, "i2c exit\n");
+
+ for (i = 0; i < COBALT_NUM_ADAPTERS; i++) {
+ cobalt_err("unregistered bus %s\n", cobalt->i2c_adap[i].name);
+ i2c_del_adapter(&cobalt->i2c_adap[i]);
+ }
+}
diff --git a/drivers/media/pci/cobalt/cobalt-i2c.h b/drivers/media/pci/cobalt/cobalt-i2c.h
new file mode 100644
index 000000000000..a4c1cfaacf95
--- /dev/null
+++ b/drivers/media/pci/cobalt/cobalt-i2c.h
@@ -0,0 +1,25 @@
+/*
+ * cobalt I2C functions
+ *
+ * Derived from cx18-i2c.h
+ *
+ * Copyright 2012-2015 Cisco Systems, Inc. and/or its affiliates.
+ * All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* init + register i2c algo-bit adapter */
+int cobalt_i2c_init(struct cobalt *cobalt);
+void cobalt_i2c_exit(struct cobalt *cobalt);
diff --git a/drivers/media/pci/cobalt/cobalt-irq.c b/drivers/media/pci/cobalt/cobalt-irq.c
new file mode 100644
index 000000000000..dd4bff9cf339
--- /dev/null
+++ b/drivers/media/pci/cobalt/cobalt-irq.c
@@ -0,0 +1,258 @@
+/*
+ * cobalt interrupt handling
+ *
+ * Copyright 2012-2015 Cisco Systems, Inc. and/or its affiliates.
+ * All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <media/adv7604.h>
+
+#include "cobalt-driver.h"
+#include "cobalt-irq.h"
+#include "cobalt-omnitek.h"
+
+static void cobalt_dma_stream_queue_handler(struct cobalt_stream *s)
+{
+ struct cobalt *cobalt = s->cobalt;
+ int rx = s->video_channel;
+ struct m00473_freewheel_regmap __iomem *fw =
+ COBALT_CVI_FREEWHEEL(s->cobalt, rx);
+ struct m00233_video_measure_regmap __iomem *vmr =
+ COBALT_CVI_VMR(s->cobalt, rx);
+ struct m00389_cvi_regmap __iomem *cvi =
+ COBALT_CVI(s->cobalt, rx);
+ struct m00479_clk_loss_detector_regmap __iomem *clkloss =
+ COBALT_CVI_CLK_LOSS(s->cobalt, rx);
+ struct cobalt_buffer *cb;
+ bool skip = false;
+
+ spin_lock(&s->irqlock);
+
+ if (list_empty(&s->bufs)) {
+ pr_err("no buffers!\n");
+ spin_unlock(&s->irqlock);
+ return;
+ }
+
+ /* Give the fresh filled up buffer to the user.
+ * Note that the interrupt is only sent if the DMA can continue
+ * with a new buffer, so it is always safe to return this buffer
+ * to userspace. */
+ cb = list_first_entry(&s->bufs, struct cobalt_buffer, list);
+ list_del(&cb->list);
+ spin_unlock(&s->irqlock);
+
+ if (s->is_audio || s->is_output)
+ goto done;
+
+ if (s->unstable_frame) {
+ uint32_t stat = ioread32(&vmr->irq_status);
+
+ iowrite32(stat, &vmr->irq_status);
+ if (!(ioread32(&vmr->status) &
+ M00233_STATUS_BITMAP_INIT_DONE_MSK)) {
+ cobalt_dbg(1, "!init_done\n");
+ if (s->enable_freewheel)
+ goto restart_fw;
+ goto done;
+ }
+
+ if (ioread32(&clkloss->status) &
+ M00479_STATUS_BITMAP_CLOCK_MISSING_MSK) {
+ iowrite32(0, &clkloss->ctrl);
+ iowrite32(M00479_CTRL_BITMAP_ENABLE_MSK, &clkloss->ctrl);
+ cobalt_dbg(1, "no clock\n");
+ if (s->enable_freewheel)
+ goto restart_fw;
+ goto done;
+ }
+ if ((stat & (M00233_IRQ_STATUS_BITMAP_VACTIVE_AREA_MSK |
+ M00233_IRQ_STATUS_BITMAP_HACTIVE_AREA_MSK)) ||
+ ioread32(&vmr->vactive_area) != s->timings.bt.height ||
+ ioread32(&vmr->hactive_area) != s->timings.bt.width) {
+ cobalt_dbg(1, "unstable\n");
+ if (s->enable_freewheel)
+ goto restart_fw;
+ goto done;
+ }
+ if (!s->enable_cvi) {
+ s->enable_cvi = true;
+ iowrite32(M00389_CONTROL_BITMAP_ENABLE_MSK, &cvi->control);
+ goto done;
+ }
+ if (!(ioread32(&cvi->status) & M00389_STATUS_BITMAP_LOCK_MSK)) {
+ cobalt_dbg(1, "cvi no lock\n");
+ if (s->enable_freewheel)
+ goto restart_fw;
+ goto done;
+ }
+ if (!s->enable_freewheel) {
+ cobalt_dbg(1, "stable\n");
+ s->enable_freewheel = true;
+ iowrite32(0, &fw->ctrl);
+ goto done;
+ }
+ cobalt_dbg(1, "enabled fw\n");
+ iowrite32(M00233_CONTROL_BITMAP_ENABLE_MEASURE_MSK |
+ M00233_CONTROL_BITMAP_ENABLE_INTERRUPT_MSK,
+ &vmr->control);
+ iowrite32(M00473_CTRL_BITMAP_ENABLE_MSK, &fw->ctrl);
+ s->enable_freewheel = false;
+ s->unstable_frame = false;
+ s->skip_first_frames = 2;
+ skip = true;
+ goto done;
+ }
+ if (ioread32(&fw->status) & M00473_STATUS_BITMAP_FREEWHEEL_MODE_MSK) {
+restart_fw:
+ cobalt_dbg(1, "lost lock\n");
+ iowrite32(M00233_CONTROL_BITMAP_ENABLE_MEASURE_MSK,
+ &vmr->control);
+ iowrite32(M00473_CTRL_BITMAP_ENABLE_MSK |
+ M00473_CTRL_BITMAP_FORCE_FREEWHEEL_MODE_MSK,
+ &fw->ctrl);
+ iowrite32(0, &cvi->control);
+ s->unstable_frame = true;
+ s->enable_freewheel = false;
+ s->enable_cvi = false;
+ }
+done:
+ if (s->skip_first_frames) {
+ skip = true;
+ s->skip_first_frames--;
+ }
+ v4l2_get_timestamp(&cb->vb.v4l2_buf.timestamp);
+ /* TODO: the sequence number should be read from the FPGA so we
+ also know about dropped frames. */
+ cb->vb.v4l2_buf.sequence = s->sequence++;
+ vb2_buffer_done(&cb->vb, (skip || s->unstable_frame) ?
+ VB2_BUF_STATE_QUEUED : VB2_BUF_STATE_DONE);
+}
+
+irqreturn_t cobalt_irq_handler(int irq, void *dev_id)
+{
+ struct cobalt *cobalt = (struct cobalt *)dev_id;
+ u32 dma_interrupt =
+ cobalt_read_bar0(cobalt, DMA_INTERRUPT_STATUS_REG) & 0xffff;
+ u32 mask = cobalt_read_bar1(cobalt, COBALT_SYS_STAT_MASK);
+ u32 edge = cobalt_read_bar1(cobalt, COBALT_SYS_STAT_EDGE);
+ int i;
+
+ /* Clear DMA interrupt */
+ cobalt_write_bar0(cobalt, DMA_INTERRUPT_STATUS_REG, dma_interrupt);
+ cobalt_write_bar1(cobalt, COBALT_SYS_STAT_MASK, mask & ~edge);
+ cobalt_write_bar1(cobalt, COBALT_SYS_STAT_EDGE, edge);
+
+ for (i = 0; i < COBALT_NUM_STREAMS; i++) {
+ struct cobalt_stream *s = &cobalt->streams[i];
+ unsigned dma_fifo_mask = s->dma_fifo_mask;
+
+ if (dma_interrupt & (1 << s->dma_channel)) {
+ cobalt->irq_dma[i]++;
+ /* Give fresh buffer to user and chain newly
+ * queued buffers */
+ cobalt_dma_stream_queue_handler(s);
+ if (!s->is_audio) {
+ edge &= ~dma_fifo_mask;
+ cobalt_write_bar1(cobalt, COBALT_SYS_STAT_MASK,
+ mask & ~edge);
+ }
+ }
+ if (s->is_audio)
+ continue;
+ if (edge & s->adv_irq_mask)
+ set_bit(COBALT_STREAM_FL_ADV_IRQ, &s->flags);
+ if ((edge & mask & dma_fifo_mask) && vb2_is_streaming(&s->q)) {
+ cobalt_info("full rx FIFO %d\n", i);
+ cobalt->irq_full_fifo++;
+ }
+ }
+
+ queue_work(cobalt->irq_work_queues, &cobalt->irq_work_queue);
+
+ if (edge & mask & (COBALT_SYSSTAT_VI0_INT1_MSK |
+ COBALT_SYSSTAT_VI1_INT1_MSK |
+ COBALT_SYSSTAT_VI2_INT1_MSK |
+ COBALT_SYSSTAT_VI3_INT1_MSK |
+ COBALT_SYSSTAT_VIHSMA_INT1_MSK |
+ COBALT_SYSSTAT_VOHSMA_INT1_MSK))
+ cobalt->irq_adv1++;
+ if (edge & mask & (COBALT_SYSSTAT_VI0_INT2_MSK |
+ COBALT_SYSSTAT_VI1_INT2_MSK |
+ COBALT_SYSSTAT_VI2_INT2_MSK |
+ COBALT_SYSSTAT_VI3_INT2_MSK |
+ COBALT_SYSSTAT_VIHSMA_INT2_MSK))
+ cobalt->irq_adv2++;
+ if (edge & mask & COBALT_SYSSTAT_VOHSMA_INT1_MSK)
+ cobalt->irq_advout++;
+ if (dma_interrupt)
+ cobalt->irq_dma_tot++;
+ if (!(edge & mask) && !dma_interrupt)
+ cobalt->irq_none++;
+ dma_interrupt = cobalt_read_bar0(cobalt, DMA_INTERRUPT_STATUS_REG);
+
+ return IRQ_HANDLED;
+}
+
+void cobalt_irq_work_handler(struct work_struct *work)
+{
+ struct cobalt *cobalt =
+ container_of(work, struct cobalt, irq_work_queue);
+ int i;
+
+ for (i = 0; i < COBALT_NUM_NODES; i++) {
+ struct cobalt_stream *s = &cobalt->streams[i];
+
+ if (test_and_clear_bit(COBALT_STREAM_FL_ADV_IRQ, &s->flags)) {
+ u32 mask;
+
+ v4l2_subdev_call(cobalt->streams[i].sd, core,
+ interrupt_service_routine, 0, NULL);
+ mask = cobalt_read_bar1(cobalt, COBALT_SYS_STAT_MASK);
+ cobalt_write_bar1(cobalt, COBALT_SYS_STAT_MASK,
+ mask | s->adv_irq_mask);
+ }
+ }
+}
+
+void cobalt_irq_log_status(struct cobalt *cobalt)
+{
+ u32 mask;
+ int i;
+
+ cobalt_info("irq: adv1=%u adv2=%u advout=%u none=%u full=%u\n",
+ cobalt->irq_adv1, cobalt->irq_adv2, cobalt->irq_advout,
+ cobalt->irq_none, cobalt->irq_full_fifo);
+ cobalt_info("irq: dma_tot=%u (", cobalt->irq_dma_tot);
+ for (i = 0; i < COBALT_NUM_STREAMS; i++)
+ pr_cont("%s%u", i ? "/" : "", cobalt->irq_dma[i]);
+ pr_cont(")\n");
+ cobalt->irq_dma_tot = cobalt->irq_adv1 = cobalt->irq_adv2 = 0;
+ cobalt->irq_advout = cobalt->irq_none = cobalt->irq_full_fifo = 0;
+ memset(cobalt->irq_dma, 0, sizeof(cobalt->irq_dma));
+
+ mask = cobalt_read_bar1(cobalt, COBALT_SYS_STAT_MASK);
+ cobalt_write_bar1(cobalt, COBALT_SYS_STAT_MASK,
+ mask |
+ COBALT_SYSSTAT_VI0_LOST_DATA_MSK |
+ COBALT_SYSSTAT_VI1_LOST_DATA_MSK |
+ COBALT_SYSSTAT_VI2_LOST_DATA_MSK |
+ COBALT_SYSSTAT_VI3_LOST_DATA_MSK |
+ COBALT_SYSSTAT_VIHSMA_LOST_DATA_MSK |
+ COBALT_SYSSTAT_VOHSMA_LOST_DATA_MSK |
+ COBALT_SYSSTAT_AUD_IN_LOST_DATA_MSK |
+ COBALT_SYSSTAT_AUD_OUT_LOST_DATA_MSK);
+}
diff --git a/drivers/media/pci/cobalt/cobalt-irq.h b/drivers/media/pci/cobalt/cobalt-irq.h
new file mode 100644
index 000000000000..5119484a24d9
--- /dev/null
+++ b/drivers/media/pci/cobalt/cobalt-irq.h
@@ -0,0 +1,25 @@
+/*
+ * cobalt interrupt handling
+ *
+ * Copyright 2012-2015 Cisco Systems, Inc. and/or its affiliates.
+ * All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/interrupt.h>
+
+irqreturn_t cobalt_irq_handler(int irq, void *dev_id);
+void cobalt_irq_work_handler(struct work_struct *work);
+void cobalt_irq_log_status(struct cobalt *cobalt);
diff --git a/drivers/media/pci/cobalt/cobalt-omnitek.c b/drivers/media/pci/cobalt/cobalt-omnitek.c
new file mode 100644
index 000000000000..a28a8482c1d4
--- /dev/null
+++ b/drivers/media/pci/cobalt/cobalt-omnitek.c
@@ -0,0 +1,341 @@
+/*
+ * Omnitek Scatter-Gather DMA Controller
+ *
+ * Copyright 2012-2015 Cisco Systems, Inc. and/or its affiliates.
+ * All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/string.h>
+#include <linux/io.h>
+#include <linux/pci_regs.h>
+#include <linux/spinlock.h>
+
+#include "cobalt-driver.h"
+#include "cobalt-omnitek.h"
+
+/* descriptor */
+#define END_OF_CHAIN (1 << 1)
+#define INTERRUPT_ENABLE (1 << 2)
+#define WRITE_TO_PCI (1 << 3)
+#define READ_FROM_PCI (0 << 3)
+#define DESCRIPTOR_FLAG_MSK (END_OF_CHAIN | INTERRUPT_ENABLE | WRITE_TO_PCI)
+#define NEXT_ADRS_MSK 0xffffffe0
+
+/* control/status register */
+#define ENABLE (1 << 0)
+#define START (1 << 1)
+#define ABORT (1 << 2)
+#define DONE (1 << 4)
+#define SG_INTERRUPT (1 << 5)
+#define EVENT_INTERRUPT (1 << 6)
+#define SCATTER_GATHER_MODE (1 << 8)
+#define DISABLE_VIDEO_RESYNC (1 << 9)
+#define EVENT_INTERRUPT_ENABLE (1 << 10)
+#define DIRECTIONAL_MSK (3 << 16)
+#define INPUT_ONLY (0 << 16)
+#define OUTPUT_ONLY (1 << 16)
+#define BIDIRECTIONAL (2 << 16)
+#define DMA_TYPE_MEMORY (0 << 18)
+#define DMA_TYPE_FIFO (1 << 18)
+
+#define BASE (cobalt->bar0)
+#define CAPABILITY_HEADER (BASE)
+#define CAPABILITY_REGISTER (BASE + 0x04)
+#define PCI_64BIT (1 << 8)
+#define LOCAL_64BIT (1 << 9)
+#define INTERRUPT_STATUS (BASE + 0x08)
+#define PCI(c) (BASE + 0x40 + ((c) * 0x40))
+#define SIZE(c) (BASE + 0x58 + ((c) * 0x40))
+#define DESCRIPTOR(c) (BASE + 0x50 + ((c) * 0x40))
+#define CS_REG(c) (BASE + 0x60 + ((c) * 0x40))
+#define BYTES_TRANSFERRED(c) (BASE + 0x64 + ((c) * 0x40))
+
+
+static char *get_dma_direction(u32 status)
+{
+ switch (status & DIRECTIONAL_MSK) {
+ case INPUT_ONLY: return "Input";
+ case OUTPUT_ONLY: return "Output";
+ case BIDIRECTIONAL: return "Bidirectional";
+ }
+ return "";
+}
+
+static void show_dma_capability(struct cobalt *cobalt)
+{
+ u32 header = ioread32(CAPABILITY_HEADER);
+ u32 capa = ioread32(CAPABILITY_REGISTER);
+ u32 i;
+
+ cobalt_info("Omnitek DMA capability: ID 0x%02x Version 0x%02x Next 0x%x Size 0x%x\n",
+ header & 0xff, (header >> 8) & 0xff,
+ (header >> 16) & 0xffff, (capa >> 24) & 0xff);
+
+ switch ((capa >> 8) & 0x3) {
+ case 0:
+ cobalt_info("Omnitek DMA: 32 bits PCIe and Local\n");
+ break;
+ case 1:
+ cobalt_info("Omnitek DMA: 64 bits PCIe, 32 bits Local\n");
+ break;
+ case 3:
+ cobalt_info("Omnitek DMA: 64 bits PCIe and Local\n");
+ break;
+ }
+
+ for (i = 0; i < (capa & 0xf); i++) {
+ u32 status = ioread32(CS_REG(i));
+
+ cobalt_info("Omnitek DMA channel #%d: %s %s\n", i,
+ status & DMA_TYPE_FIFO ? "FIFO" : "MEMORY",
+ get_dma_direction(status));
+ }
+}
+
+void omni_sg_dma_start(struct cobalt_stream *s, struct sg_dma_desc_info *desc)
+{
+ struct cobalt *cobalt = s->cobalt;
+
+ iowrite32((u32)((u64)desc->bus >> 32), DESCRIPTOR(s->dma_channel) + 4);
+ iowrite32((u32)desc->bus & NEXT_ADRS_MSK, DESCRIPTOR(s->dma_channel));
+ iowrite32(ENABLE | SCATTER_GATHER_MODE | START, CS_REG(s->dma_channel));
+}
+
+bool is_dma_done(struct cobalt_stream *s)
+{
+ struct cobalt *cobalt = s->cobalt;
+
+ if (ioread32(CS_REG(s->dma_channel)) & DONE)
+ return true;
+
+ return false;
+}
+
+void omni_sg_dma_abort_channel(struct cobalt_stream *s)
+{
+ struct cobalt *cobalt = s->cobalt;
+
+ if (is_dma_done(s) == false)
+ iowrite32(ABORT, CS_REG(s->dma_channel));
+}
+
+int omni_sg_dma_init(struct cobalt *cobalt)
+{
+ u32 capa = ioread32(CAPABILITY_REGISTER);
+ int i;
+
+ cobalt->first_fifo_channel = 0;
+ cobalt->dma_channels = capa & 0xf;
+ if (capa & PCI_64BIT)
+ cobalt->pci_32_bit = false;
+ else
+ cobalt->pci_32_bit = true;
+
+ for (i = 0; i < cobalt->dma_channels; i++) {
+ u32 status = ioread32(CS_REG(i));
+ u32 ctrl = ioread32(CS_REG(i));
+
+ if (!(ctrl & DONE))
+ iowrite32(ABORT, CS_REG(i));
+
+ if (!(status & DMA_TYPE_FIFO))
+ cobalt->first_fifo_channel++;
+ }
+ show_dma_capability(cobalt);
+ return 0;
+}
+
+int descriptor_list_create(struct cobalt *cobalt,
+ struct scatterlist *scatter_list, bool to_pci, unsigned sglen,
+ unsigned size, unsigned width, unsigned stride,
+ struct sg_dma_desc_info *desc)
+{
+ struct sg_dma_descriptor *d = (struct sg_dma_descriptor *)desc->virt;
+ dma_addr_t next = desc->bus;
+ unsigned offset = 0;
+ unsigned copy_bytes = width;
+ unsigned copied = 0;
+ bool first = true;
+
+ /* Must be 4-byte aligned */
+ WARN_ON(sg_dma_address(scatter_list) & 3);
+ WARN_ON(size & 3);
+ WARN_ON(next & 3);
+ WARN_ON(stride & 3);
+ WARN_ON(stride < width);
+ if (width >= stride)
+ copy_bytes = stride = size;
+
+ while (size) {
+ dma_addr_t addr = sg_dma_address(scatter_list) + offset;
+ unsigned bytes;
+
+ if (addr == 0)
+ return -EFAULT;
+ if (cobalt->pci_32_bit) {
+ WARN_ON((u64)addr >> 32);
+ if ((u64)addr >> 32)
+ return -EFAULT;
+ }
+
+ /* PCIe address */
+ d->pci_l = addr & 0xffffffff;
+ /* If dma_addr_t is 32 bits, then addr >> 32 is actually the
+ equivalent of addr >> 0 in gcc. So must cast to u64. */
+ d->pci_h = (u64)addr >> 32;
+
+ /* Sync to start of streaming frame */
+ d->local = 0;
+ d->reserved0 = 0;
+
+ /* Transfer bytes */
+ bytes = min(sg_dma_len(scatter_list) - offset,
+ copy_bytes - copied);
+
+ if (first) {
+ if (to_pci)
+ d->local = 0x11111111;
+ first = false;
+ if (sglen == 1) {
+ /* Make sure there are always at least two
+ * descriptors */
+ d->bytes = (bytes / 2) & ~3;
+ d->reserved1 = 0;
+ size -= d->bytes;
+ copied += d->bytes;
+ offset += d->bytes;
+ addr += d->bytes;
+ next += sizeof(struct sg_dma_descriptor);
+ d->next_h = (u32)((u64)next >> 32);
+ d->next_l = (u32)next |
+ (to_pci ? WRITE_TO_PCI : 0);
+ bytes -= d->bytes;
+ d++;
+ /* PCIe address */
+ d->pci_l = addr & 0xffffffff;
+ /* If dma_addr_t is 32 bits, then addr >> 32
+ * is actually the equivalent of addr >> 0 in
+ * gcc. So must cast to u64. */
+ d->pci_h = (u64)addr >> 32;
+
+ /* Sync to start of streaming frame */
+ d->local = 0;
+ d->reserved0 = 0;
+ }
+ }
+
+ d->bytes = bytes;
+ d->reserved1 = 0;
+ size -= bytes;
+ copied += bytes;
+ offset += bytes;
+
+ if (copied == copy_bytes) {
+ while (copied < stride) {
+ bytes = min(sg_dma_len(scatter_list) - offset,
+ stride - copied);
+ copied += bytes;
+ offset += bytes;
+ size -= bytes;
+ if (sg_dma_len(scatter_list) == offset) {
+ offset = 0;
+ scatter_list = sg_next(scatter_list);
+ }
+ }
+ copied = 0;
+ } else {
+ offset = 0;
+ scatter_list = sg_next(scatter_list);
+ }
+
+ /* Next descriptor + control bits */
+ next += sizeof(struct sg_dma_descriptor);
+ if (size == 0) {
+ /* Loopback to the first descriptor */
+ d->next_h = (u32)((u64)desc->bus >> 32);
+ d->next_l = (u32)desc->bus |
+ (to_pci ? WRITE_TO_PCI : 0) | INTERRUPT_ENABLE;
+ if (!to_pci)
+ d->local = 0x22222222;
+ desc->last_desc_virt = d;
+ } else {
+ d->next_h = (u32)((u64)next >> 32);
+ d->next_l = (u32)next | (to_pci ? WRITE_TO_PCI : 0);
+ }
+ d++;
+ }
+ return 0;
+}
+
+void descriptor_list_chain(struct sg_dma_desc_info *this,
+ struct sg_dma_desc_info *next)
+{
+ struct sg_dma_descriptor *d = this->last_desc_virt;
+ u32 direction = d->next_l & WRITE_TO_PCI;
+
+ if (next == NULL) {
+ d->next_h = 0;
+ d->next_l = direction | INTERRUPT_ENABLE | END_OF_CHAIN;
+ } else {
+ d->next_h = (u32)((u64)next->bus >> 32);
+ d->next_l = (u32)next->bus | direction | INTERRUPT_ENABLE;
+ }
+}
+
+void *descriptor_list_allocate(struct sg_dma_desc_info *desc, size_t bytes)
+{
+ desc->size = bytes;
+ desc->virt = dma_alloc_coherent(desc->dev, bytes,
+ &desc->bus, GFP_KERNEL);
+ return desc->virt;
+}
+
+void descriptor_list_free(struct sg_dma_desc_info *desc)
+{
+ if (desc->virt)
+ dma_free_coherent(desc->dev, desc->size,
+ desc->virt, desc->bus);
+ desc->virt = NULL;
+}
+
+void descriptor_list_interrupt_enable(struct sg_dma_desc_info *desc)
+{
+ struct sg_dma_descriptor *d = desc->last_desc_virt;
+
+ d->next_l |= INTERRUPT_ENABLE;
+}
+
+void descriptor_list_interrupt_disable(struct sg_dma_desc_info *desc)
+{
+ struct sg_dma_descriptor *d = desc->last_desc_virt;
+
+ d->next_l &= ~INTERRUPT_ENABLE;
+}
+
+void descriptor_list_loopback(struct sg_dma_desc_info *desc)
+{
+ struct sg_dma_descriptor *d = desc->last_desc_virt;
+
+ d->next_h = (u32)((u64)desc->bus >> 32);
+ d->next_l = (u32)desc->bus | (d->next_l & DESCRIPTOR_FLAG_MSK);
+}
+
+void descriptor_list_end_of_chain(struct sg_dma_desc_info *desc)
+{
+ struct sg_dma_descriptor *d = desc->last_desc_virt;
+
+ d->next_l |= END_OF_CHAIN;
+}
diff --git a/drivers/media/pci/cobalt/cobalt-omnitek.h b/drivers/media/pci/cobalt/cobalt-omnitek.h
new file mode 100644
index 000000000000..e5c6d032c6f2
--- /dev/null
+++ b/drivers/media/pci/cobalt/cobalt-omnitek.h
@@ -0,0 +1,62 @@
+/*
+ * Omnitek Scatter-Gather DMA Controller
+ *
+ * Copyright 2012-2015 Cisco Systems, Inc. and/or its affiliates.
+ * All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef COBALT_OMNITEK_H
+#define COBALT_OMNITEK_H
+
+#include <linux/scatterlist.h>
+#include "cobalt-driver.h"
+
+struct sg_dma_descriptor {
+ u32 pci_l;
+ u32 pci_h;
+
+ u32 local;
+ u32 reserved0;
+
+ u32 next_l;
+ u32 next_h;
+
+ u32 bytes;
+ u32 reserved1;
+};
+
+int omni_sg_dma_init(struct cobalt *cobalt);
+void omni_sg_dma_abort_channel(struct cobalt_stream *s);
+void omni_sg_dma_start(struct cobalt_stream *s, struct sg_dma_desc_info *desc);
+bool is_dma_done(struct cobalt_stream *s);
+
+int descriptor_list_create(struct cobalt *cobalt,
+ struct scatterlist *scatter_list, bool to_pci, unsigned sglen,
+ unsigned size, unsigned width, unsigned stride,
+ struct sg_dma_desc_info *desc);
+
+void descriptor_list_chain(struct sg_dma_desc_info *this,
+ struct sg_dma_desc_info *next);
+void descriptor_list_loopback(struct sg_dma_desc_info *desc);
+void descriptor_list_end_of_chain(struct sg_dma_desc_info *desc);
+
+void *descriptor_list_allocate(struct sg_dma_desc_info *desc, size_t bytes);
+void descriptor_list_free(struct sg_dma_desc_info *desc);
+
+void descriptor_list_interrupt_enable(struct sg_dma_desc_info *desc);
+void descriptor_list_interrupt_disable(struct sg_dma_desc_info *desc);
+
+#endif
diff --git a/drivers/media/pci/cobalt/cobalt-v4l2.c b/drivers/media/pci/cobalt/cobalt-v4l2.c
new file mode 100644
index 000000000000..b40c2d141b58
--- /dev/null
+++ b/drivers/media/pci/cobalt/cobalt-v4l2.c
@@ -0,0 +1,1272 @@
+/*
+ * cobalt V4L2 API
+ *
+ * Derived from ivtv-ioctl.c and cx18-fileops.c
+ *
+ * Copyright 2012-2015 Cisco Systems, Inc. and/or its affiliates.
+ * All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/math64.h>
+#include <linux/pci.h>
+#include <linux/v4l2-dv-timings.h>
+
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
+#include <media/adv7604.h>
+#include <media/adv7842.h>
+
+#include "cobalt-alsa.h"
+#include "cobalt-cpld.h"
+#include "cobalt-driver.h"
+#include "cobalt-v4l2.h"
+#include "cobalt-irq.h"
+#include "cobalt-omnitek.h"
+
+static const struct v4l2_dv_timings cea1080p60 = V4L2_DV_BT_CEA_1920X1080P60;
+
+/* vb2 DMA streaming ops */
+
+static int cobalt_queue_setup(struct vb2_queue *q,
+ const struct v4l2_format *fmt,
+ unsigned int *num_buffers, unsigned int *num_planes,
+ unsigned int sizes[], void *alloc_ctxs[])
+{
+ struct cobalt_stream *s = q->drv_priv;
+ unsigned size = s->stride * s->height;
+
+ if (*num_buffers < 3)
+ *num_buffers = 3;
+ if (*num_buffers > NR_BUFS)
+ *num_buffers = NR_BUFS;
+ *num_planes = 1;
+ if (fmt) {
+ if (fmt->fmt.pix.sizeimage < size)
+ return -EINVAL;
+ size = fmt->fmt.pix.sizeimage;
+ }
+ sizes[0] = size;
+ alloc_ctxs[0] = s->cobalt->alloc_ctx;
+ return 0;
+}
+
+static int cobalt_buf_init(struct vb2_buffer *vb)
+{
+ struct cobalt_stream *s = vb->vb2_queue->drv_priv;
+ struct cobalt *cobalt = s->cobalt;
+ const size_t max_pages_per_line =
+ (COBALT_MAX_WIDTH * COBALT_MAX_BPP) / PAGE_SIZE + 2;
+ const size_t bytes =
+ COBALT_MAX_HEIGHT * max_pages_per_line * 0x20;
+ const size_t audio_bytes = ((1920 * 4) / PAGE_SIZE + 1) * 0x20;
+ struct sg_dma_desc_info *desc = &s->dma_desc_info[vb->v4l2_buf.index];
+ struct sg_table *sg_desc = vb2_dma_sg_plane_desc(vb, 0);
+ unsigned size;
+ int ret;
+
+ size = s->stride * s->height;
+ if (vb2_plane_size(vb, 0) < size) {
+ cobalt_info("data will not fit into plane (%lu < %u)\n",
+ vb2_plane_size(vb, 0), size);
+ return -EINVAL;
+ }
+
+ if (desc->virt == NULL) {
+ desc->dev = &cobalt->pci_dev->dev;
+ descriptor_list_allocate(desc,
+ s->is_audio ? audio_bytes : bytes);
+ if (desc->virt == NULL)
+ return -ENOMEM;
+ }
+ ret = descriptor_list_create(cobalt, sg_desc->sgl,
+ !s->is_output, sg_desc->nents, size,
+ s->width * s->bpp, s->stride, desc);
+ if (ret)
+ descriptor_list_free(desc);
+ return ret;
+}
+
+static void cobalt_buf_cleanup(struct vb2_buffer *vb)
+{
+ struct cobalt_stream *s = vb->vb2_queue->drv_priv;
+ struct sg_dma_desc_info *desc = &s->dma_desc_info[vb->v4l2_buf.index];
+
+ descriptor_list_free(desc);
+}
+
+static int cobalt_buf_prepare(struct vb2_buffer *vb)
+{
+ struct cobalt_stream *s = vb->vb2_queue->drv_priv;
+
+ vb2_set_plane_payload(vb, 0, s->stride * s->height);
+ vb->v4l2_buf.field = V4L2_FIELD_NONE;
+ return 0;
+}
+
+static void chain_all_buffers(struct cobalt_stream *s)
+{
+ struct sg_dma_desc_info *desc[NR_BUFS];
+ struct cobalt_buffer *cb;
+ struct list_head *p;
+ int i = 0;
+
+ list_for_each(p, &s->bufs) {
+ cb = list_entry(p, struct cobalt_buffer, list);
+ desc[i] = &s->dma_desc_info[cb->vb.v4l2_buf.index];
+ if (i > 0)
+ descriptor_list_chain(desc[i-1], desc[i]);
+ i++;
+ }
+}
+
+static void cobalt_buf_queue(struct vb2_buffer *vb)
+{
+ struct vb2_queue *q = vb->vb2_queue;
+ struct cobalt_stream *s = q->drv_priv;
+ struct cobalt_buffer *cb = to_cobalt_buffer(vb);
+ struct sg_dma_desc_info *desc = &s->dma_desc_info[vb->v4l2_buf.index];
+ unsigned long flags;
+
+ /* Prepare new buffer */
+ descriptor_list_loopback(desc);
+ descriptor_list_interrupt_disable(desc);
+
+ spin_lock_irqsave(&s->irqlock, flags);
+ list_add_tail(&cb->list, &s->bufs);
+ chain_all_buffers(s);
+ spin_unlock_irqrestore(&s->irqlock, flags);
+}
+
+static void cobalt_enable_output(struct cobalt_stream *s)
+{
+ struct cobalt *cobalt = s->cobalt;
+ struct v4l2_bt_timings *bt = &s->timings.bt;
+ struct m00514_syncgen_flow_evcnt_regmap __iomem *vo =
+ COBALT_TX_BASE(cobalt);
+ unsigned fmt = s->pixfmt != V4L2_PIX_FMT_BGR32 ?
+ M00514_CONTROL_BITMAP_FORMAT_16_BPP_MSK : 0;
+ struct v4l2_subdev_format sd_fmt = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
+
+ if (!cobalt_cpld_set_freq(cobalt, bt->pixelclock)) {
+ cobalt_err("pixelclock out of range\n");
+ return;
+ }
+
+ sd_fmt.format.colorspace = s->colorspace;
+ sd_fmt.format.xfer_func = s->xfer_func;
+ sd_fmt.format.ycbcr_enc = s->ycbcr_enc;
+ sd_fmt.format.quantization = s->quantization;
+ sd_fmt.format.width = bt->width;
+ sd_fmt.format.height = bt->height;
+
+ /* Set up FDMA packer */
+ switch (s->pixfmt) {
+ case V4L2_PIX_FMT_YUYV:
+ sd_fmt.format.code = MEDIA_BUS_FMT_UYVY8_1X16;
+ break;
+ case V4L2_PIX_FMT_BGR32:
+ sd_fmt.format.code = MEDIA_BUS_FMT_RGB888_1X24;
+ break;
+ }
+ v4l2_subdev_call(s->sd, pad, set_fmt, NULL, &sd_fmt);
+
+ iowrite32(0, &vo->control);
+ /* 1080p60 */
+ iowrite32(bt->hsync, &vo->sync_generator_h_sync_length);
+ iowrite32(bt->hbackporch, &vo->sync_generator_h_backporch_length);
+ iowrite32(bt->width, &vo->sync_generator_h_active_length);
+ iowrite32(bt->hfrontporch, &vo->sync_generator_h_frontporch_length);
+ iowrite32(bt->vsync, &vo->sync_generator_v_sync_length);
+ iowrite32(bt->vbackporch, &vo->sync_generator_v_backporch_length);
+ iowrite32(bt->height, &vo->sync_generator_v_active_length);
+ iowrite32(bt->vfrontporch, &vo->sync_generator_v_frontporch_length);
+ iowrite32(0x9900c1, &vo->error_color);
+
+ iowrite32(M00514_CONTROL_BITMAP_SYNC_GENERATOR_LOAD_PARAM_MSK | fmt,
+ &vo->control);
+ iowrite32(M00514_CONTROL_BITMAP_EVCNT_CLEAR_MSK | fmt, &vo->control);
+ iowrite32(M00514_CONTROL_BITMAP_SYNC_GENERATOR_ENABLE_MSK |
+ M00514_CONTROL_BITMAP_FLOW_CTRL_OUTPUT_ENABLE_MSK |
+ fmt, &vo->control);
+}
+
+static void cobalt_enable_input(struct cobalt_stream *s)
+{
+ struct cobalt *cobalt = s->cobalt;
+ int ch = (int)s->video_channel;
+ struct m00235_fdma_packer_regmap __iomem *packer;
+ struct v4l2_subdev_format sd_fmt_yuyv = {
+ .pad = s->pad_source,
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ .format.code = MEDIA_BUS_FMT_YUYV8_1X16,
+ };
+ struct v4l2_subdev_format sd_fmt_rgb = {
+ .pad = s->pad_source,
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ .format.code = MEDIA_BUS_FMT_RGB888_1X24,
+ };
+
+ cobalt_dbg(1, "video_channel %d (%s, %s)\n",
+ s->video_channel,
+ s->input == 0 ? "hdmi" : "generator",
+ "YUYV");
+
+ packer = COBALT_CVI_PACKER(cobalt, ch);
+
+ /* Set up FDMA packer */
+ switch (s->pixfmt) {
+ case V4L2_PIX_FMT_YUYV:
+ iowrite32(M00235_CONTROL_BITMAP_ENABLE_MSK |
+ (1 << M00235_CONTROL_BITMAP_PACK_FORMAT_OFST),
+ &packer->control);
+ v4l2_subdev_call(s->sd, pad, set_fmt, NULL,
+ &sd_fmt_yuyv);
+ break;
+ case V4L2_PIX_FMT_RGB24:
+ iowrite32(M00235_CONTROL_BITMAP_ENABLE_MSK |
+ (2 << M00235_CONTROL_BITMAP_PACK_FORMAT_OFST),
+ &packer->control);
+ v4l2_subdev_call(s->sd, pad, set_fmt, NULL,
+ &sd_fmt_rgb);
+ break;
+ case V4L2_PIX_FMT_BGR32:
+ iowrite32(M00235_CONTROL_BITMAP_ENABLE_MSK |
+ M00235_CONTROL_BITMAP_ENDIAN_FORMAT_MSK |
+ (3 << M00235_CONTROL_BITMAP_PACK_FORMAT_OFST),
+ &packer->control);
+ v4l2_subdev_call(s->sd, pad, set_fmt, NULL,
+ &sd_fmt_rgb);
+ break;
+ }
+}
+
+static void cobalt_dma_start_streaming(struct cobalt_stream *s)
+{
+ struct cobalt *cobalt = s->cobalt;
+ int rx = s->video_channel;
+ struct m00460_evcnt_regmap __iomem *evcnt =
+ COBALT_CVI_EVCNT(cobalt, rx);
+ struct cobalt_buffer *cb;
+ unsigned long flags;
+
+ spin_lock_irqsave(&s->irqlock, flags);
+ if (!s->is_output) {
+ iowrite32(M00460_CONTROL_BITMAP_CLEAR_MSK, &evcnt->control);
+ iowrite32(M00460_CONTROL_BITMAP_ENABLE_MSK, &evcnt->control);
+ } else {
+ struct m00514_syncgen_flow_evcnt_regmap __iomem *vo =
+ COBALT_TX_BASE(cobalt);
+ u32 ctrl = ioread32(&vo->control);
+
+ ctrl &= ~(M00514_CONTROL_BITMAP_EVCNT_ENABLE_MSK |
+ M00514_CONTROL_BITMAP_EVCNT_CLEAR_MSK);
+ iowrite32(ctrl | M00514_CONTROL_BITMAP_EVCNT_CLEAR_MSK,
+ &vo->control);
+ iowrite32(ctrl | M00514_CONTROL_BITMAP_EVCNT_ENABLE_MSK,
+ &vo->control);
+ }
+ cb = list_first_entry(&s->bufs, struct cobalt_buffer, list);
+ omni_sg_dma_start(s, &s->dma_desc_info[cb->vb.v4l2_buf.index]);
+ spin_unlock_irqrestore(&s->irqlock, flags);
+}
+
+static int cobalt_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+ struct cobalt_stream *s = q->drv_priv;
+ struct cobalt *cobalt = s->cobalt;
+ struct m00233_video_measure_regmap __iomem *vmr;
+ struct m00473_freewheel_regmap __iomem *fw;
+ struct m00479_clk_loss_detector_regmap __iomem *clkloss;
+ int rx = s->video_channel;
+ struct m00389_cvi_regmap __iomem *cvi = COBALT_CVI(cobalt, rx);
+ struct m00460_evcnt_regmap __iomem *evcnt = COBALT_CVI_EVCNT(cobalt, rx);
+ struct v4l2_bt_timings *bt = &s->timings.bt;
+ u64 tot_size;
+ u32 clk_freq;
+
+ if (s->is_audio)
+ goto done;
+ if (s->is_output) {
+ s->unstable_frame = false;
+ cobalt_enable_output(s);
+ goto done;
+ }
+
+ cobalt_enable_input(s);
+
+ fw = COBALT_CVI_FREEWHEEL(cobalt, rx);
+ vmr = COBALT_CVI_VMR(cobalt, rx);
+ clkloss = COBALT_CVI_CLK_LOSS(cobalt, rx);
+
+ iowrite32(M00460_CONTROL_BITMAP_CLEAR_MSK, &evcnt->control);
+ iowrite32(M00460_CONTROL_BITMAP_ENABLE_MSK, &evcnt->control);
+ iowrite32(bt->width, &cvi->frame_width);
+ iowrite32(bt->height, &cvi->frame_height);
+ tot_size = V4L2_DV_BT_FRAME_WIDTH(bt) * V4L2_DV_BT_FRAME_HEIGHT(bt);
+ iowrite32(div_u64((u64)V4L2_DV_BT_FRAME_WIDTH(bt) * COBALT_CLK * 4,
+ bt->pixelclock), &vmr->hsync_timeout_val);
+ iowrite32(M00233_CONTROL_BITMAP_ENABLE_MEASURE_MSK, &vmr->control);
+ clk_freq = ioread32(&fw->clk_freq);
+ iowrite32(clk_freq / 1000000, &clkloss->ref_clk_cnt_val);
+ /* The lower bound for the clock frequency is 0.5% lower as is
+ * allowed by the spec */
+ iowrite32(div_u64(bt->pixelclock * 995, 1000000000),
+ &clkloss->test_clk_cnt_val);
+ /* will be enabled after the first frame has been received */
+ iowrite32(bt->width * bt->height, &fw->active_length);
+ iowrite32(div_u64((u64)clk_freq * tot_size, bt->pixelclock),
+ &fw->total_length);
+ iowrite32(M00233_IRQ_TRIGGERS_BITMAP_VACTIVE_AREA_MSK |
+ M00233_IRQ_TRIGGERS_BITMAP_HACTIVE_AREA_MSK,
+ &vmr->irq_triggers);
+ iowrite32(0, &cvi->control);
+ iowrite32(M00233_CONTROL_BITMAP_ENABLE_MEASURE_MSK, &vmr->control);
+
+ iowrite32(0xff, &fw->output_color);
+ iowrite32(M00479_CTRL_BITMAP_ENABLE_MSK, &clkloss->ctrl);
+ iowrite32(M00473_CTRL_BITMAP_ENABLE_MSK |
+ M00473_CTRL_BITMAP_FORCE_FREEWHEEL_MODE_MSK, &fw->ctrl);
+ s->unstable_frame = true;
+ s->enable_freewheel = false;
+ s->enable_cvi = false;
+ s->skip_first_frames = 0;
+
+done:
+ s->sequence = 0;
+ cobalt_dma_start_streaming(s);
+ return 0;
+}
+
+static void cobalt_dma_stop_streaming(struct cobalt_stream *s)
+{
+ struct cobalt *cobalt = s->cobalt;
+ struct sg_dma_desc_info *desc;
+ struct cobalt_buffer *cb;
+ struct list_head *p;
+ unsigned long flags;
+ int timeout_msec = 100;
+ int rx = s->video_channel;
+ struct m00460_evcnt_regmap __iomem *evcnt =
+ COBALT_CVI_EVCNT(cobalt, rx);
+
+ if (!s->is_output) {
+ iowrite32(0, &evcnt->control);
+ } else if (!s->is_audio) {
+ struct m00514_syncgen_flow_evcnt_regmap __iomem *vo =
+ COBALT_TX_BASE(cobalt);
+
+ iowrite32(M00514_CONTROL_BITMAP_EVCNT_CLEAR_MSK, &vo->control);
+ iowrite32(0, &vo->control);
+ }
+
+ /* Try to stop the DMA engine gracefully */
+ spin_lock_irqsave(&s->irqlock, flags);
+ list_for_each(p, &s->bufs) {
+ cb = list_entry(p, struct cobalt_buffer, list);
+ desc = &s->dma_desc_info[cb->vb.v4l2_buf.index];
+ /* Stop DMA after this descriptor chain */
+ descriptor_list_end_of_chain(desc);
+ }
+ spin_unlock_irqrestore(&s->irqlock, flags);
+
+ /* Wait 100 milisecond for DMA to finish, abort on timeout. */
+ if (!wait_event_timeout(s->q.done_wq, is_dma_done(s),
+ msecs_to_jiffies(timeout_msec))) {
+ omni_sg_dma_abort_channel(s);
+ pr_warn("aborted\n");
+ }
+ cobalt_write_bar0(cobalt, DMA_INTERRUPT_STATUS_REG,
+ 1 << s->dma_channel);
+}
+
+static void cobalt_stop_streaming(struct vb2_queue *q)
+{
+ struct cobalt_stream *s = q->drv_priv;
+ struct cobalt *cobalt = s->cobalt;
+ int rx = s->video_channel;
+ struct m00233_video_measure_regmap __iomem *vmr;
+ struct m00473_freewheel_regmap __iomem *fw;
+ struct m00479_clk_loss_detector_regmap __iomem *clkloss;
+ struct cobalt_buffer *cb;
+ struct list_head *p, *safe;
+ unsigned long flags;
+
+ cobalt_dma_stop_streaming(s);
+
+ /* Return all buffers to user space */
+ spin_lock_irqsave(&s->irqlock, flags);
+ list_for_each_safe(p, safe, &s->bufs) {
+ cb = list_entry(p, struct cobalt_buffer, list);
+ list_del(&cb->list);
+ vb2_buffer_done(&cb->vb, VB2_BUF_STATE_ERROR);
+ }
+ spin_unlock_irqrestore(&s->irqlock, flags);
+
+ if (s->is_audio || s->is_output)
+ return;
+
+ fw = COBALT_CVI_FREEWHEEL(cobalt, rx);
+ vmr = COBALT_CVI_VMR(cobalt, rx);
+ clkloss = COBALT_CVI_CLK_LOSS(cobalt, rx);
+ iowrite32(0, &vmr->control);
+ iowrite32(M00233_CONTROL_BITMAP_ENABLE_MEASURE_MSK, &vmr->control);
+ iowrite32(0, &fw->ctrl);
+ iowrite32(0, &clkloss->ctrl);
+}
+
+static const struct vb2_ops cobalt_qops = {
+ .queue_setup = cobalt_queue_setup,
+ .buf_init = cobalt_buf_init,
+ .buf_cleanup = cobalt_buf_cleanup,
+ .buf_prepare = cobalt_buf_prepare,
+ .buf_queue = cobalt_buf_queue,
+ .start_streaming = cobalt_start_streaming,
+ .stop_streaming = cobalt_stop_streaming,
+ .wait_prepare = vb2_ops_wait_prepare,
+ .wait_finish = vb2_ops_wait_finish,
+};
+
+/* V4L2 ioctls */
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int cobalt_cobaltc(struct cobalt *cobalt, unsigned int cmd, void *arg)
+{
+ struct v4l2_dbg_register *regs = arg;
+ void __iomem *adrs = cobalt->bar1 + regs->reg;
+
+ cobalt_info("cobalt_cobaltc: adrs = %p\n", adrs);
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ regs->size = 4;
+ if (cmd == VIDIOC_DBG_S_REGISTER)
+ iowrite32(regs->val, adrs);
+ else
+ regs->val = ioread32(adrs);
+ return 0;
+}
+
+static int cobalt_g_register(struct file *file, void *priv_fh,
+ struct v4l2_dbg_register *reg)
+{
+ struct cobalt_stream *s = video_drvdata(file);
+ struct cobalt *cobalt = s->cobalt;
+
+ return cobalt_cobaltc(cobalt, VIDIOC_DBG_G_REGISTER, reg);
+}
+
+static int cobalt_s_register(struct file *file, void *priv_fh,
+ const struct v4l2_dbg_register *reg)
+{
+ struct cobalt_stream *s = video_drvdata(file);
+ struct cobalt *cobalt = s->cobalt;
+
+ return cobalt_cobaltc(cobalt, VIDIOC_DBG_S_REGISTER,
+ (struct v4l2_dbg_register *)reg);
+}
+#endif
+
+static int cobalt_querycap(struct file *file, void *priv_fh,
+ struct v4l2_capability *vcap)
+{
+ struct cobalt_stream *s = video_drvdata(file);
+ struct cobalt *cobalt = s->cobalt;
+
+ strlcpy(vcap->driver, "cobalt", sizeof(vcap->driver));
+ strlcpy(vcap->card, "cobalt", sizeof(vcap->card));
+ snprintf(vcap->bus_info, sizeof(vcap->bus_info),
+ "PCIe:%s", pci_name(cobalt->pci_dev));
+ vcap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
+ if (s->is_output)
+ vcap->device_caps |= V4L2_CAP_VIDEO_OUTPUT;
+ else
+ vcap->device_caps |= V4L2_CAP_VIDEO_CAPTURE;
+ vcap->capabilities = vcap->device_caps | V4L2_CAP_DEVICE_CAPS |
+ V4L2_CAP_VIDEO_CAPTURE;
+ if (cobalt->have_hsma_tx)
+ vcap->capabilities |= V4L2_CAP_VIDEO_OUTPUT;
+ return 0;
+}
+
+static void cobalt_video_input_status_show(struct cobalt_stream *s)
+{
+ struct m00389_cvi_regmap __iomem *cvi;
+ struct m00233_video_measure_regmap __iomem *vmr;
+ struct m00473_freewheel_regmap __iomem *fw;
+ struct m00479_clk_loss_detector_regmap __iomem *clkloss;
+ struct m00235_fdma_packer_regmap __iomem *packer;
+ int rx = s->video_channel;
+ struct cobalt *cobalt = s->cobalt;
+ u32 cvi_ctrl, cvi_stat;
+ u32 vmr_ctrl, vmr_stat;
+
+ cvi = COBALT_CVI(cobalt, rx);
+ vmr = COBALT_CVI_VMR(cobalt, rx);
+ fw = COBALT_CVI_FREEWHEEL(cobalt, rx);
+ clkloss = COBALT_CVI_CLK_LOSS(cobalt, rx);
+ packer = COBALT_CVI_PACKER(cobalt, rx);
+ cvi_ctrl = ioread32(&cvi->control);
+ cvi_stat = ioread32(&cvi->status);
+ vmr_ctrl = ioread32(&vmr->control);
+ vmr_stat = ioread32(&vmr->control);
+ cobalt_info("rx%d: cvi resolution: %dx%d\n", rx,
+ ioread32(&cvi->frame_width), ioread32(&cvi->frame_height));
+ cobalt_info("rx%d: cvi control: %s%s%s\n", rx,
+ (cvi_ctrl & M00389_CONTROL_BITMAP_ENABLE_MSK) ?
+ "enable " : "disable ",
+ (cvi_ctrl & M00389_CONTROL_BITMAP_HSYNC_POLARITY_LOW_MSK) ?
+ "HSync- " : "HSync+ ",
+ (cvi_ctrl & M00389_CONTROL_BITMAP_VSYNC_POLARITY_LOW_MSK) ?
+ "VSync- " : "VSync+ ");
+ cobalt_info("rx%d: cvi status: %s%s\n", rx,
+ (cvi_stat & M00389_STATUS_BITMAP_LOCK_MSK) ?
+ "lock " : "no-lock ",
+ (cvi_stat & M00389_STATUS_BITMAP_ERROR_MSK) ?
+ "error " : "no-error ");
+
+ cobalt_info("rx%d: Measurements: %s%s%s%s%s%s%s\n", rx,
+ (vmr_ctrl & M00233_CONTROL_BITMAP_HSYNC_POLARITY_LOW_MSK) ?
+ "HSync- " : "HSync+ ",
+ (vmr_ctrl & M00233_CONTROL_BITMAP_VSYNC_POLARITY_LOW_MSK) ?
+ "VSync- " : "VSync+ ",
+ (vmr_ctrl & M00233_CONTROL_BITMAP_ENABLE_MEASURE_MSK) ?
+ "enabled " : "disabled ",
+ (vmr_ctrl & M00233_CONTROL_BITMAP_ENABLE_INTERRUPT_MSK) ?
+ "irq-enabled " : "irq-disabled ",
+ (vmr_ctrl & M00233_CONTROL_BITMAP_UPDATE_ON_HSYNC_MSK) ?
+ "update-on-hsync " : "",
+ (vmr_stat & M00233_STATUS_BITMAP_HSYNC_TIMEOUT_MSK) ?
+ "hsync-timeout " : "",
+ (vmr_stat & M00233_STATUS_BITMAP_INIT_DONE_MSK) ?
+ "init-done" : "");
+ cobalt_info("rx%d: irq_status: 0x%02x irq_triggers: 0x%02x\n", rx,
+ ioread32(&vmr->irq_status) & 0xff,
+ ioread32(&vmr->irq_triggers) & 0xff);
+ cobalt_info("rx%d: vsync: %d\n", rx, ioread32(&vmr->vsync_time));
+ cobalt_info("rx%d: vbp: %d\n", rx, ioread32(&vmr->vback_porch));
+ cobalt_info("rx%d: vact: %d\n", rx, ioread32(&vmr->vactive_area));
+ cobalt_info("rx%d: vfb: %d\n", rx, ioread32(&vmr->vfront_porch));
+ cobalt_info("rx%d: hsync: %d\n", rx, ioread32(&vmr->hsync_time));
+ cobalt_info("rx%d: hbp: %d\n", rx, ioread32(&vmr->hback_porch));
+ cobalt_info("rx%d: hact: %d\n", rx, ioread32(&vmr->hactive_area));
+ cobalt_info("rx%d: hfb: %d\n", rx, ioread32(&vmr->hfront_porch));
+ cobalt_info("rx%d: Freewheeling: %s%s%s\n", rx,
+ (ioread32(&fw->ctrl) & M00473_CTRL_BITMAP_ENABLE_MSK) ?
+ "enabled " : "disabled ",
+ (ioread32(&fw->ctrl) & M00473_CTRL_BITMAP_FORCE_FREEWHEEL_MODE_MSK) ?
+ "forced " : "",
+ (ioread32(&fw->status) & M00473_STATUS_BITMAP_FREEWHEEL_MODE_MSK) ?
+ "freewheeling " : "video-passthrough ");
+ iowrite32(0xff, &vmr->irq_status);
+ cobalt_info("rx%d: Clock Loss Detection: %s%s\n", rx,
+ (ioread32(&clkloss->ctrl) & M00479_CTRL_BITMAP_ENABLE_MSK) ?
+ "enabled " : "disabled ",
+ (ioread32(&clkloss->status) & M00479_STATUS_BITMAP_CLOCK_MISSING_MSK) ?
+ "clock-missing " : "found-clock ");
+ cobalt_info("rx%d: Packer: %x\n", rx, ioread32(&packer->control));
+}
+
+static int cobalt_log_status(struct file *file, void *priv_fh)
+{
+ struct cobalt_stream *s = video_drvdata(file);
+ struct cobalt *cobalt = s->cobalt;
+ struct m00514_syncgen_flow_evcnt_regmap __iomem *vo =
+ COBALT_TX_BASE(cobalt);
+ u8 stat;
+
+ cobalt_info("%s", cobalt->hdl_info);
+ cobalt_info("sysctrl: %08x, sysstat: %08x\n",
+ cobalt_g_sysctrl(cobalt),
+ cobalt_g_sysstat(cobalt));
+ cobalt_info("dma channel: %d, video channel: %d\n",
+ s->dma_channel, s->video_channel);
+ cobalt_pcie_status_show(cobalt);
+ cobalt_cpld_status(cobalt);
+ cobalt_irq_log_status(cobalt);
+ v4l2_subdev_call(s->sd, core, log_status);
+ if (!s->is_output) {
+ cobalt_video_input_status_show(s);
+ return 0;
+ }
+
+ stat = ioread32(&vo->rd_status);
+
+ cobalt_info("tx: status: %s%s\n",
+ (stat & M00514_RD_STATUS_BITMAP_FLOW_CTRL_NO_DATA_ERROR_MSK) ?
+ "no_data " : "",
+ (stat & M00514_RD_STATUS_BITMAP_READY_BUFFER_FULL_MSK) ?
+ "ready_buffer_full " : "");
+ cobalt_info("tx: evcnt: %d\n", ioread32(&vo->rd_evcnt_count));
+ return 0;
+}
+
+static int cobalt_enum_dv_timings(struct file *file, void *priv_fh,
+ struct v4l2_enum_dv_timings *timings)
+{
+ struct cobalt_stream *s = video_drvdata(file);
+
+ if (s->input == 1) {
+ if (timings->index)
+ return -EINVAL;
+ memset(timings->reserved, 0, sizeof(timings->reserved));
+ timings->timings = cea1080p60;
+ return 0;
+ }
+ timings->pad = 0;
+ return v4l2_subdev_call(s->sd,
+ pad, enum_dv_timings, timings);
+}
+
+static int cobalt_s_dv_timings(struct file *file, void *priv_fh,
+ struct v4l2_dv_timings *timings)
+{
+ struct cobalt_stream *s = video_drvdata(file);
+ int err;
+
+ if (vb2_is_busy(&s->q))
+ return -EBUSY;
+
+ if (s->input == 1) {
+ *timings = cea1080p60;
+ return 0;
+ }
+ err = v4l2_subdev_call(s->sd,
+ video, s_dv_timings, timings);
+ if (!err) {
+ s->timings = *timings;
+ s->width = timings->bt.width;
+ s->height = timings->bt.height;
+ s->stride = timings->bt.width * s->bpp;
+ }
+ return err;
+}
+
+static int cobalt_g_dv_timings(struct file *file, void *priv_fh,
+ struct v4l2_dv_timings *timings)
+{
+ struct cobalt_stream *s = video_drvdata(file);
+
+ if (s->input == 1) {
+ *timings = cea1080p60;
+ return 0;
+ }
+ return v4l2_subdev_call(s->sd,
+ video, g_dv_timings, timings);
+}
+
+static int cobalt_query_dv_timings(struct file *file, void *priv_fh,
+ struct v4l2_dv_timings *timings)
+{
+ struct cobalt_stream *s = video_drvdata(file);
+
+ if (s->input == 1) {
+ *timings = cea1080p60;
+ return 0;
+ }
+ return v4l2_subdev_call(s->sd,
+ video, query_dv_timings, timings);
+}
+
+static int cobalt_dv_timings_cap(struct file *file, void *priv_fh,
+ struct v4l2_dv_timings_cap *cap)
+{
+ struct cobalt_stream *s = video_drvdata(file);
+
+ cap->pad = 0;
+ return v4l2_subdev_call(s->sd,
+ pad, dv_timings_cap, cap);
+}
+
+static int cobalt_enum_fmt_vid_cap(struct file *file, void *priv_fh,
+ struct v4l2_fmtdesc *f)
+{
+ switch (f->index) {
+ case 0:
+ strlcpy(f->description, "YUV 4:2:2", sizeof(f->description));
+ f->pixelformat = V4L2_PIX_FMT_YUYV;
+ break;
+ case 1:
+ strlcpy(f->description, "RGB24", sizeof(f->description));
+ f->pixelformat = V4L2_PIX_FMT_RGB24;
+ break;
+ case 2:
+ strlcpy(f->description, "RGB32", sizeof(f->description));
+ f->pixelformat = V4L2_PIX_FMT_BGR32;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int cobalt_g_fmt_vid_cap(struct file *file, void *priv_fh,
+ struct v4l2_format *f)
+{
+ struct cobalt_stream *s = video_drvdata(file);
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+ struct v4l2_subdev_format sd_fmt;
+
+ pix->width = s->width;
+ pix->height = s->height;
+ pix->bytesperline = s->stride;
+ pix->field = V4L2_FIELD_NONE;
+
+ if (s->input == 1) {
+ pix->colorspace = V4L2_COLORSPACE_SRGB;
+ } else {
+ sd_fmt.pad = s->pad_source;
+ sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+ v4l2_subdev_call(s->sd, pad, get_fmt, NULL, &sd_fmt);
+ v4l2_fill_pix_format(pix, &sd_fmt.format);
+ }
+
+ pix->pixelformat = s->pixfmt;
+ pix->sizeimage = pix->bytesperline * pix->height;
+
+ return 0;
+}
+
+static int cobalt_try_fmt_vid_cap(struct file *file, void *priv_fh,
+ struct v4l2_format *f)
+{
+ struct cobalt_stream *s = video_drvdata(file);
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+ struct v4l2_subdev_format sd_fmt;
+
+ /* Check for min (QCIF) and max (Full HD) size */
+ if ((pix->width < 176) || (pix->height < 144)) {
+ pix->width = 176;
+ pix->height = 144;
+ }
+
+ if ((pix->width > 1920) || (pix->height > 1080)) {
+ pix->width = 1920;
+ pix->height = 1080;
+ }
+
+ /* Make width multiple of 4 */
+ pix->width &= ~0x3;
+
+ /* Make height multiple of 2 */
+ pix->height &= ~0x1;
+
+ if (s->input == 1) {
+ /* Generator => fixed format only */
+ pix->width = 1920;
+ pix->height = 1080;
+ pix->colorspace = V4L2_COLORSPACE_SRGB;
+ } else {
+ sd_fmt.pad = s->pad_source;
+ sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+ v4l2_subdev_call(s->sd, pad, get_fmt, NULL, &sd_fmt);
+ v4l2_fill_pix_format(pix, &sd_fmt.format);
+ }
+
+ switch (pix->pixelformat) {
+ case V4L2_PIX_FMT_YUYV:
+ default:
+ pix->bytesperline = max(pix->bytesperline & ~0x3,
+ pix->width * COBALT_BYTES_PER_PIXEL_YUYV);
+ pix->pixelformat = V4L2_PIX_FMT_YUYV;
+ break;
+ case V4L2_PIX_FMT_RGB24:
+ pix->bytesperline = max(pix->bytesperline & ~0x3,
+ pix->width * COBALT_BYTES_PER_PIXEL_RGB24);
+ break;
+ case V4L2_PIX_FMT_BGR32:
+ pix->bytesperline = max(pix->bytesperline & ~0x3,
+ pix->width * COBALT_BYTES_PER_PIXEL_RGB32);
+ break;
+ }
+
+ pix->sizeimage = pix->bytesperline * pix->height;
+ pix->field = V4L2_FIELD_NONE;
+ pix->priv = 0;
+
+ return 0;
+}
+
+static int cobalt_s_fmt_vid_cap(struct file *file, void *priv_fh,
+ struct v4l2_format *f)
+{
+ struct cobalt_stream *s = video_drvdata(file);
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+
+ if (vb2_is_busy(&s->q))
+ return -EBUSY;
+
+ if (cobalt_try_fmt_vid_cap(file, priv_fh, f))
+ return -EINVAL;
+
+ s->width = pix->width;
+ s->height = pix->height;
+ s->stride = pix->bytesperline;
+ switch (pix->pixelformat) {
+ case V4L2_PIX_FMT_YUYV:
+ s->bpp = COBALT_BYTES_PER_PIXEL_YUYV;
+ break;
+ case V4L2_PIX_FMT_RGB24:
+ s->bpp = COBALT_BYTES_PER_PIXEL_RGB24;
+ break;
+ case V4L2_PIX_FMT_BGR32:
+ s->bpp = COBALT_BYTES_PER_PIXEL_RGB32;
+ break;
+ default:
+ return -EINVAL;
+ }
+ s->pixfmt = pix->pixelformat;
+ cobalt_enable_input(s);
+
+ return 0;
+}
+
+static int cobalt_try_fmt_vid_out(struct file *file, void *priv_fh,
+ struct v4l2_format *f)
+{
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+
+ /* Check for min (QCIF) and max (Full HD) size */
+ if ((pix->width < 176) || (pix->height < 144)) {
+ pix->width = 176;
+ pix->height = 144;
+ }
+
+ if ((pix->width > 1920) || (pix->height > 1080)) {
+ pix->width = 1920;
+ pix->height = 1080;
+ }
+
+ /* Make width multiple of 4 */
+ pix->width &= ~0x3;
+
+ /* Make height multiple of 2 */
+ pix->height &= ~0x1;
+
+ switch (pix->pixelformat) {
+ case V4L2_PIX_FMT_YUYV:
+ default:
+ pix->bytesperline = max(pix->bytesperline & ~0x3,
+ pix->width * COBALT_BYTES_PER_PIXEL_YUYV);
+ pix->pixelformat = V4L2_PIX_FMT_YUYV;
+ break;
+ case V4L2_PIX_FMT_BGR32:
+ pix->bytesperline = max(pix->bytesperline & ~0x3,
+ pix->width * COBALT_BYTES_PER_PIXEL_RGB32);
+ break;
+ }
+
+ pix->sizeimage = pix->bytesperline * pix->height;
+ pix->field = V4L2_FIELD_NONE;
+
+ return 0;
+}
+
+static int cobalt_g_fmt_vid_out(struct file *file, void *priv_fh,
+ struct v4l2_format *f)
+{
+ struct cobalt_stream *s = video_drvdata(file);
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+
+ pix->width = s->width;
+ pix->height = s->height;
+ pix->bytesperline = s->stride;
+ pix->field = V4L2_FIELD_NONE;
+ pix->pixelformat = s->pixfmt;
+ pix->colorspace = s->colorspace;
+ pix->xfer_func = s->xfer_func;
+ pix->ycbcr_enc = s->ycbcr_enc;
+ pix->quantization = s->quantization;
+ pix->sizeimage = pix->bytesperline * pix->height;
+
+ return 0;
+}
+
+static int cobalt_enum_fmt_vid_out(struct file *file, void *priv_fh,
+ struct v4l2_fmtdesc *f)
+{
+ switch (f->index) {
+ case 0:
+ strlcpy(f->description, "YUV 4:2:2", sizeof(f->description));
+ f->pixelformat = V4L2_PIX_FMT_YUYV;
+ break;
+ case 1:
+ strlcpy(f->description, "RGB32", sizeof(f->description));
+ f->pixelformat = V4L2_PIX_FMT_BGR32;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int cobalt_s_fmt_vid_out(struct file *file, void *priv_fh,
+ struct v4l2_format *f)
+{
+ struct cobalt_stream *s = video_drvdata(file);
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+ struct v4l2_subdev_format sd_fmt = { 0 };
+ u32 code;
+
+ if (cobalt_try_fmt_vid_out(file, priv_fh, f))
+ return -EINVAL;
+
+ if (vb2_is_busy(&s->q) && (pix->pixelformat != s->pixfmt ||
+ pix->width != s->width || pix->height != s->height ||
+ pix->bytesperline != s->stride))
+ return -EBUSY;
+
+ switch (pix->pixelformat) {
+ case V4L2_PIX_FMT_YUYV:
+ s->bpp = COBALT_BYTES_PER_PIXEL_YUYV;
+ code = MEDIA_BUS_FMT_UYVY8_1X16;
+ break;
+ case V4L2_PIX_FMT_BGR32:
+ s->bpp = COBALT_BYTES_PER_PIXEL_RGB32;
+ code = MEDIA_BUS_FMT_RGB888_1X24;
+ break;
+ default:
+ return -EINVAL;
+ }
+ s->width = pix->width;
+ s->height = pix->height;
+ s->stride = pix->bytesperline;
+ s->pixfmt = pix->pixelformat;
+ s->colorspace = pix->colorspace;
+ s->xfer_func = pix->xfer_func;
+ s->ycbcr_enc = pix->ycbcr_enc;
+ s->quantization = pix->quantization;
+ sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+ v4l2_fill_mbus_format(&sd_fmt.format, pix, code);
+ v4l2_subdev_call(s->sd, pad, set_fmt, NULL, &sd_fmt);
+ return 0;
+}
+
+static int cobalt_enum_input(struct file *file, void *priv_fh,
+ struct v4l2_input *inp)
+{
+ struct cobalt_stream *s = video_drvdata(file);
+
+ if (inp->index > 1)
+ return -EINVAL;
+ if (inp->index == 0)
+ snprintf(inp->name, sizeof(inp->name),
+ "HDMI-%d", s->video_channel);
+ else
+ snprintf(inp->name, sizeof(inp->name),
+ "Generator-%d", s->video_channel);
+ inp->type = V4L2_INPUT_TYPE_CAMERA;
+ inp->capabilities = V4L2_IN_CAP_DV_TIMINGS;
+ if (inp->index == 1)
+ return 0;
+ return v4l2_subdev_call(s->sd,
+ video, g_input_status, &inp->status);
+}
+
+static int cobalt_g_input(struct file *file, void *priv_fh, unsigned int *i)
+{
+ struct cobalt_stream *s = video_drvdata(file);
+
+ *i = s->input;
+ return 0;
+}
+
+static int cobalt_s_input(struct file *file, void *priv_fh, unsigned int i)
+{
+ struct cobalt_stream *s = video_drvdata(file);
+
+ if (i >= 2)
+ return -EINVAL;
+ if (vb2_is_busy(&s->q))
+ return -EBUSY;
+ s->input = i;
+
+ cobalt_enable_input(s);
+
+ if (s->input == 1) /* Test Pattern Generator */
+ return 0;
+
+ return v4l2_subdev_call(s->sd, video, s_routing,
+ ADV76XX_PAD_HDMI_PORT_A, 0, 0);
+}
+
+static int cobalt_enum_output(struct file *file, void *priv_fh,
+ struct v4l2_output *out)
+{
+ if (out->index)
+ return -EINVAL;
+ snprintf(out->name, sizeof(out->name), "HDMI-%d", out->index);
+ out->type = V4L2_OUTPUT_TYPE_ANALOG;
+ out->capabilities = V4L2_OUT_CAP_DV_TIMINGS;
+ return 0;
+}
+
+static int cobalt_g_output(struct file *file, void *priv_fh, unsigned int *i)
+{
+ *i = 0;
+ return 0;
+}
+
+static int cobalt_s_output(struct file *file, void *priv_fh, unsigned int i)
+{
+ return i ? -EINVAL : 0;
+}
+
+static int cobalt_g_edid(struct file *file, void *fh, struct v4l2_edid *edid)
+{
+ struct cobalt_stream *s = video_drvdata(file);
+ u32 pad = edid->pad;
+ int ret;
+
+ if (edid->pad >= (s->is_output ? 1 : 2))
+ return -EINVAL;
+ edid->pad = 0;
+ ret = v4l2_subdev_call(s->sd, pad, get_edid, edid);
+ edid->pad = pad;
+ return ret;
+}
+
+static int cobalt_s_edid(struct file *file, void *fh, struct v4l2_edid *edid)
+{
+ struct cobalt_stream *s = video_drvdata(file);
+ u32 pad = edid->pad;
+ int ret;
+
+ if (edid->pad >= 2)
+ return -EINVAL;
+ edid->pad = 0;
+ ret = v4l2_subdev_call(s->sd, pad, set_edid, edid);
+ edid->pad = pad;
+ return ret;
+}
+
+static int cobalt_subscribe_event(struct v4l2_fh *fh,
+ const struct v4l2_event_subscription *sub)
+{
+ switch (sub->type) {
+ case V4L2_EVENT_SOURCE_CHANGE:
+ return v4l2_event_subscribe(fh, sub, 4, NULL);
+ }
+ return v4l2_ctrl_subscribe_event(fh, sub);
+}
+
+static int cobalt_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
+{
+ if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ a->parm.capture.timeperframe.numerator = 1;
+ a->parm.capture.timeperframe.denominator = 60;
+ a->parm.capture.readbuffers = 3;
+ return 0;
+}
+
+static const struct v4l2_ioctl_ops cobalt_ioctl_ops = {
+ .vidioc_querycap = cobalt_querycap,
+ .vidioc_g_parm = cobalt_g_parm,
+ .vidioc_log_status = cobalt_log_status,
+ .vidioc_streamon = vb2_ioctl_streamon,
+ .vidioc_streamoff = vb2_ioctl_streamoff,
+ .vidioc_enum_input = cobalt_enum_input,
+ .vidioc_g_input = cobalt_g_input,
+ .vidioc_s_input = cobalt_s_input,
+ .vidioc_enum_fmt_vid_cap = cobalt_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = cobalt_g_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = cobalt_s_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = cobalt_try_fmt_vid_cap,
+ .vidioc_enum_output = cobalt_enum_output,
+ .vidioc_g_output = cobalt_g_output,
+ .vidioc_s_output = cobalt_s_output,
+ .vidioc_enum_fmt_vid_out = cobalt_enum_fmt_vid_out,
+ .vidioc_g_fmt_vid_out = cobalt_g_fmt_vid_out,
+ .vidioc_s_fmt_vid_out = cobalt_s_fmt_vid_out,
+ .vidioc_try_fmt_vid_out = cobalt_try_fmt_vid_out,
+ .vidioc_s_dv_timings = cobalt_s_dv_timings,
+ .vidioc_g_dv_timings = cobalt_g_dv_timings,
+ .vidioc_query_dv_timings = cobalt_query_dv_timings,
+ .vidioc_enum_dv_timings = cobalt_enum_dv_timings,
+ .vidioc_dv_timings_cap = cobalt_dv_timings_cap,
+ .vidioc_g_edid = cobalt_g_edid,
+ .vidioc_s_edid = cobalt_s_edid,
+ .vidioc_subscribe_event = cobalt_subscribe_event,
+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+ .vidioc_reqbufs = vb2_ioctl_reqbufs,
+ .vidioc_create_bufs = vb2_ioctl_create_bufs,
+ .vidioc_querybuf = vb2_ioctl_querybuf,
+ .vidioc_qbuf = vb2_ioctl_qbuf,
+ .vidioc_dqbuf = vb2_ioctl_dqbuf,
+ .vidioc_expbuf = vb2_ioctl_expbuf,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ .vidioc_g_register = cobalt_g_register,
+ .vidioc_s_register = cobalt_s_register,
+#endif
+};
+
+static const struct v4l2_ioctl_ops cobalt_ioctl_empty_ops = {
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ .vidioc_g_register = cobalt_g_register,
+ .vidioc_s_register = cobalt_s_register,
+#endif
+};
+
+/* Register device nodes */
+
+static const struct v4l2_file_operations cobalt_fops = {
+ .owner = THIS_MODULE,
+ .open = v4l2_fh_open,
+ .unlocked_ioctl = video_ioctl2,
+ .release = vb2_fop_release,
+ .poll = vb2_fop_poll,
+ .mmap = vb2_fop_mmap,
+ .read = vb2_fop_read,
+};
+
+static const struct v4l2_file_operations cobalt_out_fops = {
+ .owner = THIS_MODULE,
+ .open = v4l2_fh_open,
+ .unlocked_ioctl = video_ioctl2,
+ .release = vb2_fop_release,
+ .poll = vb2_fop_poll,
+ .mmap = vb2_fop_mmap,
+ .write = vb2_fop_write,
+};
+
+static const struct v4l2_file_operations cobalt_empty_fops = {
+ .owner = THIS_MODULE,
+ .open = v4l2_fh_open,
+ .unlocked_ioctl = video_ioctl2,
+ .release = v4l2_fh_release,
+};
+
+static int cobalt_node_register(struct cobalt *cobalt, int node)
+{
+ static const struct v4l2_dv_timings dv1080p60 =
+ V4L2_DV_BT_CEA_1920X1080P60;
+ struct cobalt_stream *s = cobalt->streams + node;
+ struct video_device *vdev = &s->vdev;
+ struct vb2_queue *q = &s->q;
+ int ret;
+
+ mutex_init(&s->lock);
+ spin_lock_init(&s->irqlock);
+
+ snprintf(vdev->name, sizeof(vdev->name),
+ "%s-%d", cobalt->v4l2_dev.name, node);
+ s->width = 1920;
+ /* Audio frames are just 4 lines of 1920 bytes */
+ s->height = s->is_audio ? 4 : 1080;
+
+ if (s->is_audio) {
+ s->bpp = 1;
+ s->pixfmt = V4L2_PIX_FMT_GREY;
+ } else if (s->is_output) {
+ s->bpp = COBALT_BYTES_PER_PIXEL_RGB32;
+ s->pixfmt = V4L2_PIX_FMT_BGR32;
+ } else {
+ s->bpp = COBALT_BYTES_PER_PIXEL_YUYV;
+ s->pixfmt = V4L2_PIX_FMT_YUYV;
+ }
+ s->colorspace = V4L2_COLORSPACE_SRGB;
+ s->stride = s->width * s->bpp;
+
+ if (!s->is_audio) {
+ if (s->is_dummy)
+ cobalt_warn("Setting up dummy video node %d\n", node);
+ vdev->v4l2_dev = &cobalt->v4l2_dev;
+ if (s->is_dummy)
+ vdev->fops = &cobalt_empty_fops;
+ else
+ vdev->fops = s->is_output ? &cobalt_out_fops :
+ &cobalt_fops;
+ vdev->release = video_device_release_empty;
+ vdev->vfl_dir = s->is_output ? VFL_DIR_TX : VFL_DIR_RX;
+ vdev->lock = &s->lock;
+ if (s->sd)
+ vdev->ctrl_handler = s->sd->ctrl_handler;
+ s->timings = dv1080p60;
+ v4l2_subdev_call(s->sd, video, s_dv_timings, &s->timings);
+ if (!s->is_output && s->sd)
+ cobalt_enable_input(s);
+ vdev->ioctl_ops = s->is_dummy ? &cobalt_ioctl_empty_ops :
+ &cobalt_ioctl_ops;
+ }
+
+ INIT_LIST_HEAD(&s->bufs);
+ q->type = s->is_output ? V4L2_BUF_TYPE_VIDEO_OUTPUT :
+ V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
+ q->io_modes |= s->is_output ? VB2_WRITE : VB2_READ;
+ q->drv_priv = s;
+ q->buf_struct_size = sizeof(struct cobalt_buffer);
+ q->ops = &cobalt_qops;
+ q->mem_ops = &vb2_dma_sg_memops;
+ q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+ q->min_buffers_needed = 2;
+ q->lock = &s->lock;
+ vdev->queue = q;
+
+ video_set_drvdata(vdev, s);
+ ret = vb2_queue_init(q);
+ if (!s->is_audio && ret == 0)
+ ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
+ else if (!s->is_dummy)
+ ret = cobalt_alsa_init(s);
+
+ if (ret < 0) {
+ if (!s->is_audio)
+ cobalt_err("couldn't register v4l2 device node %d\n",
+ node);
+ return ret;
+ }
+ cobalt_info("registered node %d\n", node);
+ return 0;
+}
+
+/* Initialize v4l2 variables and register v4l2 devices */
+int cobalt_nodes_register(struct cobalt *cobalt)
+{
+ int node, ret;
+
+ /* Setup V4L2 Devices */
+ for (node = 0; node < COBALT_NUM_STREAMS; node++) {
+ ret = cobalt_node_register(cobalt, node);
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+/* Unregister v4l2 devices */
+void cobalt_nodes_unregister(struct cobalt *cobalt)
+{
+ int node;
+
+ /* Teardown all streams */
+ for (node = 0; node < COBALT_NUM_STREAMS; node++) {
+ struct cobalt_stream *s = cobalt->streams + node;
+ struct video_device *vdev = &s->vdev;
+
+ if (!s->is_audio)
+ video_unregister_device(vdev);
+ else if (!s->is_dummy)
+ cobalt_alsa_exit(s);
+ }
+}
diff --git a/drivers/media/pci/cobalt/cobalt-v4l2.h b/drivers/media/pci/cobalt/cobalt-v4l2.h
new file mode 100644
index 000000000000..62be553cd8e2
--- /dev/null
+++ b/drivers/media/pci/cobalt/cobalt-v4l2.h
@@ -0,0 +1,22 @@
+/*
+ * cobalt V4L2 API
+ *
+ * Copyright 2012-2015 Cisco Systems, Inc. and/or its affiliates.
+ * All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+int cobalt_nodes_register(struct cobalt *cobalt);
+void cobalt_nodes_unregister(struct cobalt *cobalt);
diff --git a/drivers/media/pci/cobalt/m00233_video_measure_memmap_package.h b/drivers/media/pci/cobalt/m00233_video_measure_memmap_package.h
new file mode 100644
index 000000000000..9bc9ef1fd3a8
--- /dev/null
+++ b/drivers/media/pci/cobalt/m00233_video_measure_memmap_package.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2014-2015 Cisco Systems, Inc. and/or its affiliates.
+ * All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef M00233_VIDEO_MEASURE_MEMMAP_PACKAGE_H
+#define M00233_VIDEO_MEASURE_MEMMAP_PACKAGE_H
+
+/*******************************************************************
+ * Register Block
+ * M00233_VIDEO_MEASURE_MEMMAP_PACKAGE_VHD_REGMAP
+ *******************************************************************/
+struct m00233_video_measure_regmap {
+ uint32_t irq_status; /* Reg 0x0000 */
+ /* The vertical counter starts on rising edge of vsync */
+ uint32_t vsync_time; /* Reg 0x0004 */
+ uint32_t vback_porch; /* Reg 0x0008 */
+ uint32_t vactive_area; /* Reg 0x000c */
+ uint32_t vfront_porch; /* Reg 0x0010 */
+ /* The horizontal counter starts on rising edge of hsync. */
+ uint32_t hsync_time; /* Reg 0x0014 */
+ uint32_t hback_porch; /* Reg 0x0018 */
+ uint32_t hactive_area; /* Reg 0x001c */
+ uint32_t hfront_porch; /* Reg 0x0020 */
+ uint32_t control; /* Reg 0x0024, Default=0x0 */
+ uint32_t irq_triggers; /* Reg 0x0028, Default=0xff */
+ /* Value is given in number of register bus clock periods between */
+ /* falling and rising edge of hsync. Must be non-zero. */
+ uint32_t hsync_timeout_val; /* Reg 0x002c, Default=0x1fff */
+ uint32_t status; /* Reg 0x0030 */
+};
+
+#define M00233_VIDEO_MEASURE_REG_IRQ_STATUS_OFST 0
+#define M00233_VIDEO_MEASURE_REG_VSYNC_TIME_OFST 4
+#define M00233_VIDEO_MEASURE_REG_VBACK_PORCH_OFST 8
+#define M00233_VIDEO_MEASURE_REG_VACTIVE_AREA_OFST 12
+#define M00233_VIDEO_MEASURE_REG_VFRONT_PORCH_OFST 16
+#define M00233_VIDEO_MEASURE_REG_HSYNC_TIME_OFST 20
+#define M00233_VIDEO_MEASURE_REG_HBACK_PORCH_OFST 24
+#define M00233_VIDEO_MEASURE_REG_HACTIVE_AREA_OFST 28
+#define M00233_VIDEO_MEASURE_REG_HFRONT_PORCH_OFST 32
+#define M00233_VIDEO_MEASURE_REG_CONTROL_OFST 36
+#define M00233_VIDEO_MEASURE_REG_IRQ_TRIGGERS_OFST 40
+#define M00233_VIDEO_MEASURE_REG_HSYNC_TIMEOUT_VAL_OFST 44
+#define M00233_VIDEO_MEASURE_REG_STATUS_OFST 48
+
+/*******************************************************************
+ * Bit Mask for register
+ * M00233_VIDEO_MEASURE_MEMMAP_PACKAGE_VHD_BITMAP
+ *******************************************************************/
+/* irq_status [7:0] */
+#define M00233_IRQ_STATUS_BITMAP_VSYNC_TIME_OFST (0)
+#define M00233_IRQ_STATUS_BITMAP_VSYNC_TIME_MSK (0x1 << M00233_IRQ_STATUS_BITMAP_VSYNC_TIME_OFST)
+#define M00233_IRQ_STATUS_BITMAP_VBACK_PORCH_OFST (1)
+#define M00233_IRQ_STATUS_BITMAP_VBACK_PORCH_MSK (0x1 << M00233_IRQ_STATUS_BITMAP_VBACK_PORCH_OFST)
+#define M00233_IRQ_STATUS_BITMAP_VACTIVE_AREA_OFST (2)
+#define M00233_IRQ_STATUS_BITMAP_VACTIVE_AREA_MSK (0x1 << M00233_IRQ_STATUS_BITMAP_VACTIVE_AREA_OFST)
+#define M00233_IRQ_STATUS_BITMAP_VFRONT_PORCH_OFST (3)
+#define M00233_IRQ_STATUS_BITMAP_VFRONT_PORCH_MSK (0x1 << M00233_IRQ_STATUS_BITMAP_VFRONT_PORCH_OFST)
+#define M00233_IRQ_STATUS_BITMAP_HSYNC_TIME_OFST (4)
+#define M00233_IRQ_STATUS_BITMAP_HSYNC_TIME_MSK (0x1 << M00233_IRQ_STATUS_BITMAP_HSYNC_TIME_OFST)
+#define M00233_IRQ_STATUS_BITMAP_HBACK_PORCH_OFST (5)
+#define M00233_IRQ_STATUS_BITMAP_HBACK_PORCH_MSK (0x1 << M00233_IRQ_STATUS_BITMAP_HBACK_PORCH_OFST)
+#define M00233_IRQ_STATUS_BITMAP_HACTIVE_AREA_OFST (6)
+#define M00233_IRQ_STATUS_BITMAP_HACTIVE_AREA_MSK (0x1 << M00233_IRQ_STATUS_BITMAP_HACTIVE_AREA_OFST)
+#define M00233_IRQ_STATUS_BITMAP_HFRONT_PORCH_OFST (7)
+#define M00233_IRQ_STATUS_BITMAP_HFRONT_PORCH_MSK (0x1 << M00233_IRQ_STATUS_BITMAP_HFRONT_PORCH_OFST)
+/* control [4:0] */
+#define M00233_CONTROL_BITMAP_HSYNC_POLARITY_LOW_OFST (0)
+#define M00233_CONTROL_BITMAP_HSYNC_POLARITY_LOW_MSK (0x1 << M00233_CONTROL_BITMAP_HSYNC_POLARITY_LOW_OFST)
+#define M00233_CONTROL_BITMAP_VSYNC_POLARITY_LOW_OFST (1)
+#define M00233_CONTROL_BITMAP_VSYNC_POLARITY_LOW_MSK (0x1 << M00233_CONTROL_BITMAP_VSYNC_POLARITY_LOW_OFST)
+#define M00233_CONTROL_BITMAP_ENABLE_MEASURE_OFST (2)
+#define M00233_CONTROL_BITMAP_ENABLE_MEASURE_MSK (0x1 << M00233_CONTROL_BITMAP_ENABLE_MEASURE_OFST)
+#define M00233_CONTROL_BITMAP_ENABLE_INTERRUPT_OFST (3)
+#define M00233_CONTROL_BITMAP_ENABLE_INTERRUPT_MSK (0x1 << M00233_CONTROL_BITMAP_ENABLE_INTERRUPT_OFST)
+#define M00233_CONTROL_BITMAP_UPDATE_ON_HSYNC_OFST (4)
+#define M00233_CONTROL_BITMAP_UPDATE_ON_HSYNC_MSK (0x1 << M00233_CONTROL_BITMAP_UPDATE_ON_HSYNC_OFST)
+/* irq_triggers [7:0] */
+#define M00233_IRQ_TRIGGERS_BITMAP_VSYNC_TIME_OFST (0)
+#define M00233_IRQ_TRIGGERS_BITMAP_VSYNC_TIME_MSK (0x1 << M00233_IRQ_TRIGGERS_BITMAP_VSYNC_TIME_OFST)
+#define M00233_IRQ_TRIGGERS_BITMAP_VBACK_PORCH_OFST (1)
+#define M00233_IRQ_TRIGGERS_BITMAP_VBACK_PORCH_MSK (0x1 << M00233_IRQ_TRIGGERS_BITMAP_VBACK_PORCH_OFST)
+#define M00233_IRQ_TRIGGERS_BITMAP_VACTIVE_AREA_OFST (2)
+#define M00233_IRQ_TRIGGERS_BITMAP_VACTIVE_AREA_MSK (0x1 << M00233_IRQ_TRIGGERS_BITMAP_VACTIVE_AREA_OFST)
+#define M00233_IRQ_TRIGGERS_BITMAP_VFRONT_PORCH_OFST (3)
+#define M00233_IRQ_TRIGGERS_BITMAP_VFRONT_PORCH_MSK (0x1 << M00233_IRQ_TRIGGERS_BITMAP_VFRONT_PORCH_OFST)
+#define M00233_IRQ_TRIGGERS_BITMAP_HSYNC_TIME_OFST (4)
+#define M00233_IRQ_TRIGGERS_BITMAP_HSYNC_TIME_MSK (0x1 << M00233_IRQ_TRIGGERS_BITMAP_HSYNC_TIME_OFST)
+#define M00233_IRQ_TRIGGERS_BITMAP_HBACK_PORCH_OFST (5)
+#define M00233_IRQ_TRIGGERS_BITMAP_HBACK_PORCH_MSK (0x1 << M00233_IRQ_TRIGGERS_BITMAP_HBACK_PORCH_OFST)
+#define M00233_IRQ_TRIGGERS_BITMAP_HACTIVE_AREA_OFST (6)
+#define M00233_IRQ_TRIGGERS_BITMAP_HACTIVE_AREA_MSK (0x1 << M00233_IRQ_TRIGGERS_BITMAP_HACTIVE_AREA_OFST)
+#define M00233_IRQ_TRIGGERS_BITMAP_HFRONT_PORCH_OFST (7)
+#define M00233_IRQ_TRIGGERS_BITMAP_HFRONT_PORCH_MSK (0x1 << M00233_IRQ_TRIGGERS_BITMAP_HFRONT_PORCH_OFST)
+/* status [1:0] */
+#define M00233_STATUS_BITMAP_HSYNC_TIMEOUT_OFST (0)
+#define M00233_STATUS_BITMAP_HSYNC_TIMEOUT_MSK (0x1 << M00233_STATUS_BITMAP_HSYNC_TIMEOUT_OFST)
+#define M00233_STATUS_BITMAP_INIT_DONE_OFST (1)
+#define M00233_STATUS_BITMAP_INIT_DONE_MSK (0x1 << M00233_STATUS_BITMAP_INIT_DONE_OFST)
+
+#endif /*M00233_VIDEO_MEASURE_MEMMAP_PACKAGE_H*/
diff --git a/drivers/media/pci/cobalt/m00235_fdma_packer_memmap_package.h b/drivers/media/pci/cobalt/m00235_fdma_packer_memmap_package.h
new file mode 100644
index 000000000000..a480529f561e
--- /dev/null
+++ b/drivers/media/pci/cobalt/m00235_fdma_packer_memmap_package.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2014-2015 Cisco Systems, Inc. and/or its affiliates.
+ * All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef M00235_FDMA_PACKER_MEMMAP_PACKAGE_H
+#define M00235_FDMA_PACKER_MEMMAP_PACKAGE_H
+
+/*******************************************************************
+ * Register Block
+ * M00235_FDMA_PACKER_MEMMAP_PACKAGE_VHD_REGMAP
+ *******************************************************************/
+struct m00235_fdma_packer_regmap {
+ uint32_t control; /* Reg 0x0000, Default=0x0 */
+};
+
+#define M00235_FDMA_PACKER_REG_CONTROL_OFST 0
+
+/*******************************************************************
+ * Bit Mask for register
+ * M00235_FDMA_PACKER_MEMMAP_PACKAGE_VHD_BITMAP
+ *******************************************************************/
+/* control [3:0] */
+#define M00235_CONTROL_BITMAP_ENABLE_OFST (0)
+#define M00235_CONTROL_BITMAP_ENABLE_MSK (0x1 << M00235_CONTROL_BITMAP_ENABLE_OFST)
+#define M00235_CONTROL_BITMAP_PACK_FORMAT_OFST (1)
+#define M00235_CONTROL_BITMAP_PACK_FORMAT_MSK (0x3 << M00235_CONTROL_BITMAP_PACK_FORMAT_OFST)
+#define M00235_CONTROL_BITMAP_ENDIAN_FORMAT_OFST (3)
+#define M00235_CONTROL_BITMAP_ENDIAN_FORMAT_MSK (0x1 << M00235_CONTROL_BITMAP_ENDIAN_FORMAT_OFST)
+
+#endif /*M00235_FDMA_PACKER_MEMMAP_PACKAGE_H*/
diff --git a/drivers/media/pci/cobalt/m00389_cvi_memmap_package.h b/drivers/media/pci/cobalt/m00389_cvi_memmap_package.h
new file mode 100644
index 000000000000..602419e589d3
--- /dev/null
+++ b/drivers/media/pci/cobalt/m00389_cvi_memmap_package.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2014-2015 Cisco Systems, Inc. and/or its affiliates.
+ * All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef M00389_CVI_MEMMAP_PACKAGE_H
+#define M00389_CVI_MEMMAP_PACKAGE_H
+
+/*******************************************************************
+ * Register Block
+ * M00389_CVI_MEMMAP_PACKAGE_VHD_REGMAP
+ *******************************************************************/
+struct m00389_cvi_regmap {
+ uint32_t control; /* Reg 0x0000, Default=0x0 */
+ uint32_t frame_width; /* Reg 0x0004, Default=0x10 */
+ uint32_t frame_height; /* Reg 0x0008, Default=0xc */
+ uint32_t freewheel_period; /* Reg 0x000c, Default=0x0 */
+ uint32_t error_color; /* Reg 0x0010, Default=0x0 */
+ uint32_t status; /* Reg 0x0014 */
+};
+
+#define M00389_CVI_REG_CONTROL_OFST 0
+#define M00389_CVI_REG_FRAME_WIDTH_OFST 4
+#define M00389_CVI_REG_FRAME_HEIGHT_OFST 8
+#define M00389_CVI_REG_FREEWHEEL_PERIOD_OFST 12
+#define M00389_CVI_REG_ERROR_COLOR_OFST 16
+#define M00389_CVI_REG_STATUS_OFST 20
+
+/*******************************************************************
+ * Bit Mask for register
+ * M00389_CVI_MEMMAP_PACKAGE_VHD_BITMAP
+ *******************************************************************/
+/* control [2:0] */
+#define M00389_CONTROL_BITMAP_ENABLE_OFST (0)
+#define M00389_CONTROL_BITMAP_ENABLE_MSK (0x1 << M00389_CONTROL_BITMAP_ENABLE_OFST)
+#define M00389_CONTROL_BITMAP_HSYNC_POLARITY_LOW_OFST (1)
+#define M00389_CONTROL_BITMAP_HSYNC_POLARITY_LOW_MSK (0x1 << M00389_CONTROL_BITMAP_HSYNC_POLARITY_LOW_OFST)
+#define M00389_CONTROL_BITMAP_VSYNC_POLARITY_LOW_OFST (2)
+#define M00389_CONTROL_BITMAP_VSYNC_POLARITY_LOW_MSK (0x1 << M00389_CONTROL_BITMAP_VSYNC_POLARITY_LOW_OFST)
+/* status [1:0] */
+#define M00389_STATUS_BITMAP_LOCK_OFST (0)
+#define M00389_STATUS_BITMAP_LOCK_MSK (0x1 << M00389_STATUS_BITMAP_LOCK_OFST)
+#define M00389_STATUS_BITMAP_ERROR_OFST (1)
+#define M00389_STATUS_BITMAP_ERROR_MSK (0x1 << M00389_STATUS_BITMAP_ERROR_OFST)
+
+#endif /*M00389_CVI_MEMMAP_PACKAGE_H*/
diff --git a/drivers/media/pci/cobalt/m00460_evcnt_memmap_package.h b/drivers/media/pci/cobalt/m00460_evcnt_memmap_package.h
new file mode 100644
index 000000000000..95471c995067
--- /dev/null
+++ b/drivers/media/pci/cobalt/m00460_evcnt_memmap_package.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2014-2015 Cisco Systems, Inc. and/or its affiliates.
+ * All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef M00460_EVCNT_MEMMAP_PACKAGE_H
+#define M00460_EVCNT_MEMMAP_PACKAGE_H
+
+/*******************************************************************
+ * Register Block
+ * M00460_EVCNT_MEMMAP_PACKAGE_VHD_REGMAP
+ *******************************************************************/
+struct m00460_evcnt_regmap {
+ uint32_t control; /* Reg 0x0000, Default=0x0 */
+ uint32_t count; /* Reg 0x0004 */
+};
+
+#define M00460_EVCNT_REG_CONTROL_OFST 0
+#define M00460_EVCNT_REG_COUNT_OFST 4
+
+/*******************************************************************
+ * Bit Mask for register
+ * M00460_EVCNT_MEMMAP_PACKAGE_VHD_BITMAP
+ *******************************************************************/
+/* control [1:0] */
+#define M00460_CONTROL_BITMAP_ENABLE_OFST (0)
+#define M00460_CONTROL_BITMAP_ENABLE_MSK (0x1 << M00460_CONTROL_BITMAP_ENABLE_OFST)
+#define M00460_CONTROL_BITMAP_CLEAR_OFST (1)
+#define M00460_CONTROL_BITMAP_CLEAR_MSK (0x1 << M00460_CONTROL_BITMAP_CLEAR_OFST)
+
+#endif /*M00460_EVCNT_MEMMAP_PACKAGE_H*/
diff --git a/drivers/media/pci/cobalt/m00473_freewheel_memmap_package.h b/drivers/media/pci/cobalt/m00473_freewheel_memmap_package.h
new file mode 100644
index 000000000000..384a3e156301
--- /dev/null
+++ b/drivers/media/pci/cobalt/m00473_freewheel_memmap_package.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2014-2015 Cisco Systems, Inc. and/or its affiliates.
+ * All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef M00473_FREEWHEEL_MEMMAP_PACKAGE_H
+#define M00473_FREEWHEEL_MEMMAP_PACKAGE_H
+
+/*******************************************************************
+ * Register Block
+ * M00473_FREEWHEEL_MEMMAP_PACKAGE_VHD_REGMAP
+ *******************************************************************/
+struct m00473_freewheel_regmap {
+ uint32_t ctrl; /* Reg 0x0000, Default=0x0 */
+ uint32_t status; /* Reg 0x0004 */
+ uint32_t active_length; /* Reg 0x0008, Default=0x1fa400 */
+ uint32_t total_length; /* Reg 0x000c, Default=0x31151b */
+ uint32_t data_width; /* Reg 0x0010 */
+ uint32_t output_color; /* Reg 0x0014, Default=0xffff */
+ uint32_t clk_freq; /* Reg 0x0018 */
+};
+
+#define M00473_FREEWHEEL_REG_CTRL_OFST 0
+#define M00473_FREEWHEEL_REG_STATUS_OFST 4
+#define M00473_FREEWHEEL_REG_ACTIVE_LENGTH_OFST 8
+#define M00473_FREEWHEEL_REG_TOTAL_LENGTH_OFST 12
+#define M00473_FREEWHEEL_REG_DATA_WIDTH_OFST 16
+#define M00473_FREEWHEEL_REG_OUTPUT_COLOR_OFST 20
+#define M00473_FREEWHEEL_REG_CLK_FREQ_OFST 24
+
+/*******************************************************************
+ * Bit Mask for register
+ * M00473_FREEWHEEL_MEMMAP_PACKAGE_VHD_BITMAP
+ *******************************************************************/
+/* ctrl [1:0] */
+#define M00473_CTRL_BITMAP_ENABLE_OFST (0)
+#define M00473_CTRL_BITMAP_ENABLE_MSK (0x1 << M00473_CTRL_BITMAP_ENABLE_OFST)
+#define M00473_CTRL_BITMAP_FORCE_FREEWHEEL_MODE_OFST (1)
+#define M00473_CTRL_BITMAP_FORCE_FREEWHEEL_MODE_MSK (0x1 << M00473_CTRL_BITMAP_FORCE_FREEWHEEL_MODE_OFST)
+/* status [0:0] */
+#define M00473_STATUS_BITMAP_FREEWHEEL_MODE_OFST (0)
+#define M00473_STATUS_BITMAP_FREEWHEEL_MODE_MSK (0x1 << M00473_STATUS_BITMAP_FREEWHEEL_MODE_OFST)
+
+#endif /*M00473_FREEWHEEL_MEMMAP_PACKAGE_H*/
diff --git a/drivers/media/pci/cobalt/m00479_clk_loss_detector_memmap_package.h b/drivers/media/pci/cobalt/m00479_clk_loss_detector_memmap_package.h
new file mode 100644
index 000000000000..2a029026bf82
--- /dev/null
+++ b/drivers/media/pci/cobalt/m00479_clk_loss_detector_memmap_package.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2014-2015 Cisco Systems, Inc. and/or its affiliates.
+ * All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef M00479_CLK_LOSS_DETECTOR_MEMMAP_PACKAGE_H
+#define M00479_CLK_LOSS_DETECTOR_MEMMAP_PACKAGE_H
+
+/*******************************************************************
+ * Register Block
+ * M00479_CLK_LOSS_DETECTOR_MEMMAP_PACKAGE_VHD_REGMAP
+ *******************************************************************/
+struct m00479_clk_loss_detector_regmap {
+ /* Control module */
+ uint32_t ctrl; /* Reg 0x0000, Default=0x0 */
+ uint32_t status; /* Reg 0x0004 */
+ /* Number of ref clk cycles before checking the clock under test */
+ uint32_t ref_clk_cnt_val; /* Reg 0x0008, Default=0xc4 */
+ /* Number of test clk cycles required in the ref_clk_cnt_val period
+ * to ensure that the test clock is performing as expected */
+ uint32_t test_clk_cnt_val; /* Reg 0x000c, Default=0xa */
+};
+
+#define M00479_CLK_LOSS_DETECTOR_REG_CTRL_OFST 0
+#define M00479_CLK_LOSS_DETECTOR_REG_STATUS_OFST 4
+#define M00479_CLK_LOSS_DETECTOR_REG_REF_CLK_CNT_VAL_OFST 8
+#define M00479_CLK_LOSS_DETECTOR_REG_TEST_CLK_CNT_VAL_OFST 12
+
+/*******************************************************************
+ * Bit Mask for register
+ * M00479_CLK_LOSS_DETECTOR_MEMMAP_PACKAGE_VHD_BITMAP
+ *******************************************************************/
+/* ctrl [0:0] */
+#define M00479_CTRL_BITMAP_ENABLE_OFST (0)
+#define M00479_CTRL_BITMAP_ENABLE_MSK (0x1 << M00479_CTRL_BITMAP_ENABLE_OFST)
+/* status [0:0] */
+#define M00479_STATUS_BITMAP_CLOCK_MISSING_OFST (0)
+#define M00479_STATUS_BITMAP_CLOCK_MISSING_MSK (0x1 << M00479_STATUS_BITMAP_CLOCK_MISSING_OFST)
+
+#endif /*M00479_CLK_LOSS_DETECTOR_MEMMAP_PACKAGE_H*/
diff --git a/drivers/media/pci/cobalt/m00514_syncgen_flow_evcnt_memmap_package.h b/drivers/media/pci/cobalt/m00514_syncgen_flow_evcnt_memmap_package.h
new file mode 100644
index 000000000000..bdef2df5d689
--- /dev/null
+++ b/drivers/media/pci/cobalt/m00514_syncgen_flow_evcnt_memmap_package.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2014-2015 Cisco Systems, Inc. and/or its affiliates.
+ * All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef M00514_SYNCGEN_FLOW_EVCNT_MEMMAP_PACKAGE_H
+#define M00514_SYNCGEN_FLOW_EVCNT_MEMMAP_PACKAGE_H
+
+/*******************************************************************
+ * Register Block
+ * M00514_SYNCGEN_FLOW_EVCNT_MEMMAP_PACKAGE_VHD_REGMAP
+ *******************************************************************/
+struct m00514_syncgen_flow_evcnt_regmap {
+ uint32_t control; /* Reg 0x0000, Default=0x0 */
+ uint32_t sync_generator_h_sync_length; /* Reg 0x0004, Default=0x0 */
+ uint32_t sync_generator_h_backporch_length; /* Reg 0x0008, Default=0x0 */
+ uint32_t sync_generator_h_active_length; /* Reg 0x000c, Default=0x0 */
+ uint32_t sync_generator_h_frontporch_length; /* Reg 0x0010, Default=0x0 */
+ uint32_t sync_generator_v_sync_length; /* Reg 0x0014, Default=0x0 */
+ uint32_t sync_generator_v_backporch_length; /* Reg 0x0018, Default=0x0 */
+ uint32_t sync_generator_v_active_length; /* Reg 0x001c, Default=0x0 */
+ uint32_t sync_generator_v_frontporch_length; /* Reg 0x0020, Default=0x0 */
+ uint32_t error_color; /* Reg 0x0024, Default=0x0 */
+ uint32_t rd_status; /* Reg 0x0028 */
+ uint32_t rd_evcnt_count; /* Reg 0x002c */
+};
+
+#define M00514_SYNCGEN_FLOW_EVCNT_REG_CONTROL_OFST 0
+#define M00514_SYNCGEN_FLOW_EVCNT_REG_SYNC_GENERATOR_H_SYNC_LENGTH_OFST 4
+#define M00514_SYNCGEN_FLOW_EVCNT_REG_SYNC_GENERATOR_H_BACKPORCH_LENGTH_OFST 8
+#define M00514_SYNCGEN_FLOW_EVCNT_REG_SYNC_GENERATOR_H_ACTIVE_LENGTH_OFST 12
+#define M00514_SYNCGEN_FLOW_EVCNT_REG_SYNC_GENERATOR_H_FRONTPORCH_LENGTH_OFST 16
+#define M00514_SYNCGEN_FLOW_EVCNT_REG_SYNC_GENERATOR_V_SYNC_LENGTH_OFST 20
+#define M00514_SYNCGEN_FLOW_EVCNT_REG_SYNC_GENERATOR_V_BACKPORCH_LENGTH_OFST 24
+#define M00514_SYNCGEN_FLOW_EVCNT_REG_SYNC_GENERATOR_V_ACTIVE_LENGTH_OFST 28
+#define M00514_SYNCGEN_FLOW_EVCNT_REG_SYNC_GENERATOR_V_FRONTPORCH_LENGTH_OFST 32
+#define M00514_SYNCGEN_FLOW_EVCNT_REG_ERROR_COLOR_OFST 36
+#define M00514_SYNCGEN_FLOW_EVCNT_REG_RD_STATUS_OFST 40
+#define M00514_SYNCGEN_FLOW_EVCNT_REG_RD_EVCNT_COUNT_OFST 44
+
+/*******************************************************************
+ * Bit Mask for register
+ * M00514_SYNCGEN_FLOW_EVCNT_MEMMAP_PACKAGE_VHD_BITMAP
+ *******************************************************************/
+/* control [7:0] */
+#define M00514_CONTROL_BITMAP_SYNC_GENERATOR_LOAD_PARAM_OFST (0)
+#define M00514_CONTROL_BITMAP_SYNC_GENERATOR_LOAD_PARAM_MSK (0x1 << M00514_CONTROL_BITMAP_SYNC_GENERATOR_LOAD_PARAM_OFST)
+#define M00514_CONTROL_BITMAP_SYNC_GENERATOR_ENABLE_OFST (1)
+#define M00514_CONTROL_BITMAP_SYNC_GENERATOR_ENABLE_MSK (0x1 << M00514_CONTROL_BITMAP_SYNC_GENERATOR_ENABLE_OFST)
+#define M00514_CONTROL_BITMAP_FLOW_CTRL_OUTPUT_ENABLE_OFST (2)
+#define M00514_CONTROL_BITMAP_FLOW_CTRL_OUTPUT_ENABLE_MSK (0x1 << M00514_CONTROL_BITMAP_FLOW_CTRL_OUTPUT_ENABLE_OFST)
+#define M00514_CONTROL_BITMAP_HSYNC_POLARITY_LOW_OFST (3)
+#define M00514_CONTROL_BITMAP_HSYNC_POLARITY_LOW_MSK (0x1 << M00514_CONTROL_BITMAP_HSYNC_POLARITY_LOW_OFST)
+#define M00514_CONTROL_BITMAP_VSYNC_POLARITY_LOW_OFST (4)
+#define M00514_CONTROL_BITMAP_VSYNC_POLARITY_LOW_MSK (0x1 << M00514_CONTROL_BITMAP_VSYNC_POLARITY_LOW_OFST)
+#define M00514_CONTROL_BITMAP_EVCNT_ENABLE_OFST (5)
+#define M00514_CONTROL_BITMAP_EVCNT_ENABLE_MSK (0x1 << M00514_CONTROL_BITMAP_EVCNT_ENABLE_OFST)
+#define M00514_CONTROL_BITMAP_EVCNT_CLEAR_OFST (6)
+#define M00514_CONTROL_BITMAP_EVCNT_CLEAR_MSK (0x1 << M00514_CONTROL_BITMAP_EVCNT_CLEAR_OFST)
+#define M00514_CONTROL_BITMAP_FORMAT_16_BPP_OFST (7)
+#define M00514_CONTROL_BITMAP_FORMAT_16_BPP_MSK (0x1 << M00514_CONTROL_BITMAP_FORMAT_16_BPP_OFST)
+/* error_color [23:0] */
+#define M00514_ERROR_COLOR_BITMAP_BLUE_OFST (0)
+#define M00514_ERROR_COLOR_BITMAP_BLUE_MSK (0xff << M00514_ERROR_COLOR_BITMAP_BLUE_OFST)
+#define M00514_ERROR_COLOR_BITMAP_GREEN_OFST (8)
+#define M00514_ERROR_COLOR_BITMAP_GREEN_MSK (0xff << M00514_ERROR_COLOR_BITMAP_GREEN_OFST)
+#define M00514_ERROR_COLOR_BITMAP_RED_OFST (16)
+#define M00514_ERROR_COLOR_BITMAP_RED_MSK (0xff << M00514_ERROR_COLOR_BITMAP_RED_OFST)
+/* rd_status [1:0] */
+#define M00514_RD_STATUS_BITMAP_FLOW_CTRL_NO_DATA_ERROR_OFST (0)
+#define M00514_RD_STATUS_BITMAP_FLOW_CTRL_NO_DATA_ERROR_MSK (0x1 << M00514_RD_STATUS_BITMAP_FLOW_CTRL_NO_DATA_ERROR_OFST)
+#define M00514_RD_STATUS_BITMAP_READY_BUFFER_FULL_OFST (1)
+#define M00514_RD_STATUS_BITMAP_READY_BUFFER_FULL_MSK (0x1 << M00514_RD_STATUS_BITMAP_READY_BUFFER_FULL_OFST)
+
+#endif /*M00514_SYNCGEN_FLOW_EVCNT_MEMMAP_PACKAGE_H*/
diff --git a/drivers/media/pci/cx18/cx18-av-core.c b/drivers/media/pci/cx18/cx18-av-core.c
index 5a55630d09db..30bbe8d1ea55 100644
--- a/drivers/media/pci/cx18/cx18-av-core.c
+++ b/drivers/media/pci/cx18/cx18-av-core.c
@@ -945,14 +945,17 @@ static int cx18_av_s_ctrl(struct v4l2_ctrl *ctrl)
return 0;
}
-static int cx18_av_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
+static int cx18_av_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *fmt = &format->format;
struct cx18_av_state *state = to_cx18_av_state(sd);
struct cx18 *cx = v4l2_get_subdevdata(sd);
int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
int is_50Hz = !(state->std & V4L2_STD_525_60);
- if (fmt->code != MEDIA_BUS_FMT_FIXED)
+ if (format->pad || fmt->code != MEDIA_BUS_FMT_FIXED)
return -EINVAL;
fmt->field = V4L2_FIELD_INTERLACED;
@@ -987,6 +990,9 @@ static int cx18_av_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt
return -ERANGE;
}
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY)
+ return 0;
+
HSC = (Hsrc * (1 << 20)) / fmt->width - (1 << 20);
VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9));
VSC &= 0x1fff;
@@ -1285,7 +1291,6 @@ static const struct v4l2_subdev_video_ops cx18_av_video_ops = {
.s_std = cx18_av_s_std,
.s_routing = cx18_av_s_video_routing,
.s_stream = cx18_av_s_stream,
- .s_mbus_fmt = cx18_av_s_mbus_fmt,
};
static const struct v4l2_subdev_vbi_ops cx18_av_vbi_ops = {
@@ -1295,12 +1300,17 @@ static const struct v4l2_subdev_vbi_ops cx18_av_vbi_ops = {
.s_raw_fmt = cx18_av_s_raw_fmt,
};
+static const struct v4l2_subdev_pad_ops cx18_av_pad_ops = {
+ .set_fmt = cx18_av_set_fmt,
+};
+
static const struct v4l2_subdev_ops cx18_av_ops = {
.core = &cx18_av_general_ops,
.tuner = &cx18_av_tuner_ops,
.audio = &cx18_av_audio_ops,
.video = &cx18_av_video_ops,
.vbi = &cx18_av_vbi_ops,
+ .pad = &cx18_av_pad_ops,
};
int cx18_av_probe(struct cx18 *cx)
diff --git a/drivers/media/pci/cx18/cx18-controls.c b/drivers/media/pci/cx18/cx18-controls.c
index 4aeb7c6b8ce1..71227a155cba 100644
--- a/drivers/media/pci/cx18/cx18-controls.c
+++ b/drivers/media/pci/cx18/cx18-controls.c
@@ -93,13 +93,16 @@ static int cx18_s_video_encoding(struct cx2341x_handler *cxhdl, u32 val)
{
struct cx18 *cx = container_of(cxhdl, struct cx18, cxhdl);
int is_mpeg1 = val == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
- struct v4l2_mbus_framefmt fmt;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
+ struct v4l2_mbus_framefmt *fmt = &format.format;
/* fix videodecoder resolution */
- fmt.width = cxhdl->width / (is_mpeg1 ? 2 : 1);
- fmt.height = cxhdl->height;
- fmt.code = MEDIA_BUS_FMT_FIXED;
- v4l2_subdev_call(cx->sd_av, video, s_mbus_fmt, &fmt);
+ fmt->width = cxhdl->width / (is_mpeg1 ? 2 : 1);
+ fmt->height = cxhdl->height;
+ fmt->code = MEDIA_BUS_FMT_FIXED;
+ v4l2_subdev_call(cx->sd_av, pad, set_fmt, NULL, &format);
return 0;
}
diff --git a/drivers/media/pci/cx18/cx18-driver.c b/drivers/media/pci/cx18/cx18-driver.c
index 83f5074706f9..260e462d91b4 100644
--- a/drivers/media/pci/cx18/cx18-driver.c
+++ b/drivers/media/pci/cx18/cx18-driver.c
@@ -786,11 +786,11 @@ static void cx18_init_struct2(struct cx18 *cx)
{
int i;
- for (i = 0; i < CX18_CARD_MAX_VIDEO_INPUTS; i++)
+ for (i = 0; i < CX18_CARD_MAX_VIDEO_INPUTS - 1; i++)
if (cx->card->video_inputs[i].video_type == 0)
break;
cx->nof_inputs = i;
- for (i = 0; i < CX18_CARD_MAX_AUDIO_INPUTS; i++)
+ for (i = 0; i < CX18_CARD_MAX_AUDIO_INPUTS - 1; i++)
if (cx->card->audio_inputs[i].audio_type == 0)
break;
cx->nof_audio_inputs = i;
diff --git a/drivers/media/pci/cx18/cx18-ioctl.c b/drivers/media/pci/cx18/cx18-ioctl.c
index 79aee30d5fd8..55525af1f482 100644
--- a/drivers/media/pci/cx18/cx18-ioctl.c
+++ b/drivers/media/pci/cx18/cx18-ioctl.c
@@ -267,7 +267,9 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh,
{
struct cx18_open_id *id = fh2id(fh);
struct cx18 *cx = id->cx;
- struct v4l2_mbus_framefmt mbus_fmt;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
struct cx18_stream *s = &cx->streams[id->type];
int ret;
int w, h;
@@ -296,10 +298,10 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh,
s->vb_bytes_per_line = 1440; /* Packed */
}
- mbus_fmt.width = cx->cxhdl.width = w;
- mbus_fmt.height = cx->cxhdl.height = h;
- mbus_fmt.code = MEDIA_BUS_FMT_FIXED;
- v4l2_subdev_call(cx->sd_av, video, s_mbus_fmt, &mbus_fmt);
+ format.format.width = cx->cxhdl.width = w;
+ format.format.height = cx->cxhdl.height = h;
+ format.format.code = MEDIA_BUS_FMT_FIXED;
+ v4l2_subdev_call(cx->sd_av, pad, set_fmt, NULL, &format);
return cx18_g_fmt_vid_cap(file, fh, fmt);
}
diff --git a/drivers/media/pci/cx18/cx18-streams.c b/drivers/media/pci/cx18/cx18-streams.c
index c82d25d53341..c9860845264f 100644
--- a/drivers/media/pci/cx18/cx18-streams.c
+++ b/drivers/media/pci/cx18/cx18-streams.c
@@ -90,6 +90,7 @@ static struct {
"encoder PCM audio",
VFL_TYPE_GRABBER, CX18_V4L2_ENC_PCM_OFFSET,
PCI_DMA_FROMDEVICE,
+ V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
},
{ /* CX18_ENC_STREAM_TYPE_IDX */
"encoder IDX",
diff --git a/drivers/media/pci/cx23885/altera-ci.c b/drivers/media/pci/cx23885/altera-ci.c
index 0a91df2c9f08..aaf4e46ff3e9 100644
--- a/drivers/media/pci/cx23885/altera-ci.c
+++ b/drivers/media/pci/cx23885/altera-ci.c
@@ -759,7 +759,7 @@ int altera_ci_init(struct altera_ci_config *config, int ci_nr)
if (0 != ret)
goto err;
- inter->state[ci_nr - 1] = state;
+ inter->state[ci_nr - 1] = state;
altera_hw_filt_init(config, ci_nr);
diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c
index 745caabe3397..6e8c24cdb2cd 100644
--- a/drivers/media/pci/cx23885/cx23885-dvb.c
+++ b/drivers/media/pci/cx23885/cx23885-dvb.c
@@ -572,7 +572,8 @@ static struct stb6100_config prof_8000_stb6100_config = {
.refclock = 27000000,
};
-static int p8000_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+static int p8000_set_voltage(struct dvb_frontend *fe,
+ enum fe_sec_voltage voltage)
{
struct cx23885_tsport *port = fe->dvb->priv;
struct cx23885_dev *dev = port->dev;
@@ -587,7 +588,7 @@ static int p8000_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
}
static int dvbsky_t9580_set_voltage(struct dvb_frontend *fe,
- fe_sec_voltage_t voltage)
+ enum fe_sec_voltage voltage)
{
struct cx23885_tsport *port = fe->dvb->priv;
struct cx23885_dev *dev = port->dev;
@@ -616,7 +617,7 @@ static int dvbsky_t9580_set_voltage(struct dvb_frontend *fe,
}
static int dvbsky_s952_portc_set_voltage(struct dvb_frontend *fe,
- fe_sec_voltage_t voltage)
+ enum fe_sec_voltage voltage)
{
struct cx23885_tsport *port = fe->dvb->priv;
struct cx23885_dev *dev = port->dev;
@@ -856,18 +857,12 @@ static struct mt2063_config terratec_mt2063_config[] = {
},
};
-static const struct tda10071_config hauppauge_tda10071_config = {
- .demod_i2c_addr = 0x05,
- .tuner_i2c_addr = 0x54,
+static const struct tda10071_platform_data hauppauge_tda10071_pdata = {
+ .clk = 40444000, /* 40.444 MHz */
.i2c_wr_max = 64,
.ts_mode = TDA10071_TS_SERIAL,
- .spec_inv = 0,
- .xtal = 40444000, /* 40.444 MHz */
.pll_multiplier = 20,
-};
-
-static const struct a8293_config hauppauge_a8293_config = {
- .i2c_addr = 0x0b,
+ .tuner_i2c_addr = 0x54,
};
static const struct si2165_config hauppauge_hvr4400_si2165_config = {
@@ -1190,8 +1185,10 @@ static int dvb_register(struct cx23885_tsport *port)
struct i2c_board_info info;
struct i2c_adapter *adapter;
struct i2c_client *client_demod = NULL, *client_tuner = NULL;
+ struct i2c_client *client_sec = NULL;
const struct m88ds3103_config *p_m88ds3103_config = NULL;
- int (*p_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage) = NULL;
+ int (*p_set_voltage)(struct dvb_frontend *fe,
+ enum fe_sec_voltage voltage) = NULL;
int mfe_shared = 0; /* bus not shared by default */
int ret;
@@ -1797,21 +1794,46 @@ static int dvb_register(struct cx23885_tsport *port)
fe0->dvb.frontend->ops.set_voltage = p8000_set_voltage;
break;
- case CX23885_BOARD_HAUPPAUGE_HVR4400:
+ case CX23885_BOARD_HAUPPAUGE_HVR4400: {
+ struct tda10071_platform_data tda10071_pdata = hauppauge_tda10071_pdata;
+ struct a8293_platform_data a8293_pdata = {};
+
i2c_bus = &dev->i2c_bus[0];
i2c_bus2 = &dev->i2c_bus[1];
switch (port->nr) {
/* port b */
case 1:
- fe0->dvb.frontend = dvb_attach(tda10071_attach,
- &hauppauge_tda10071_config,
- &i2c_bus->i2c_adap);
- if (fe0->dvb.frontend == NULL)
- break;
- if (!dvb_attach(a8293_attach, fe0->dvb.frontend,
- &i2c_bus->i2c_adap,
- &hauppauge_a8293_config))
+ /* attach demod + tuner combo */
+ memset(&info, 0, sizeof(info));
+ strlcpy(info.type, "tda10071_cx24118", I2C_NAME_SIZE);
+ info.addr = 0x05;
+ info.platform_data = &tda10071_pdata;
+ request_module("tda10071");
+ client_demod = i2c_new_device(&i2c_bus->i2c_adap, &info);
+ if (!client_demod || !client_demod->dev.driver)
+ goto frontend_detach;
+ if (!try_module_get(client_demod->dev.driver->owner)) {
+ i2c_unregister_device(client_demod);
+ goto frontend_detach;
+ }
+ fe0->dvb.frontend = tda10071_pdata.get_dvb_frontend(client_demod);
+ port->i2c_client_demod = client_demod;
+
+ /* attach SEC */
+ a8293_pdata.dvb_frontend = fe0->dvb.frontend;
+ memset(&info, 0, sizeof(info));
+ strlcpy(info.type, "a8293", I2C_NAME_SIZE);
+ info.addr = 0x0b;
+ info.platform_data = &a8293_pdata;
+ request_module("a8293");
+ client_sec = i2c_new_device(&i2c_bus->i2c_adap, &info);
+ if (!client_sec || !client_sec->dev.driver)
+ goto frontend_detach;
+ if (!try_module_get(client_sec->dev.driver->owner)) {
+ i2c_unregister_device(client_sec);
goto frontend_detach;
+ }
+ port->i2c_client_sec = client_sec;
break;
/* port c */
case 2:
@@ -1829,17 +1851,46 @@ static int dvb_register(struct cx23885_tsport *port)
break;
}
break;
- case CX23885_BOARD_HAUPPAUGE_STARBURST:
+ }
+ case CX23885_BOARD_HAUPPAUGE_STARBURST: {
+ struct tda10071_platform_data tda10071_pdata = hauppauge_tda10071_pdata;
+ struct a8293_platform_data a8293_pdata = {};
+
i2c_bus = &dev->i2c_bus[0];
- fe0->dvb.frontend = dvb_attach(tda10071_attach,
- &hauppauge_tda10071_config,
- &i2c_bus->i2c_adap);
- if (fe0->dvb.frontend != NULL) {
- dvb_attach(a8293_attach, fe0->dvb.frontend,
- &i2c_bus->i2c_adap,
- &hauppauge_a8293_config);
+
+ /* attach demod + tuner combo */
+ memset(&info, 0, sizeof(info));
+ strlcpy(info.type, "tda10071_cx24118", I2C_NAME_SIZE);
+ info.addr = 0x05;
+ info.platform_data = &tda10071_pdata;
+ request_module("tda10071");
+ client_demod = i2c_new_device(&i2c_bus->i2c_adap, &info);
+ if (!client_demod || !client_demod->dev.driver)
+ goto frontend_detach;
+ if (!try_module_get(client_demod->dev.driver->owner)) {
+ i2c_unregister_device(client_demod);
+ goto frontend_detach;
}
+ fe0->dvb.frontend = tda10071_pdata.get_dvb_frontend(client_demod);
+ port->i2c_client_demod = client_demod;
+
+ /* attach SEC */
+ a8293_pdata.dvb_frontend = fe0->dvb.frontend;
+ memset(&info, 0, sizeof(info));
+ strlcpy(info.type, "a8293", I2C_NAME_SIZE);
+ info.addr = 0x0b;
+ info.platform_data = &a8293_pdata;
+ request_module("a8293");
+ client_sec = i2c_new_device(&i2c_bus->i2c_adap, &info);
+ if (!client_sec || !client_sec->dev.driver)
+ goto frontend_detach;
+ if (!try_module_get(client_sec->dev.driver->owner)) {
+ i2c_unregister_device(client_sec);
+ goto frontend_detach;
+ }
+ port->i2c_client_sec = client_sec;
break;
+ }
case CX23885_BOARD_DVBSKY_T9580:
case CX23885_BOARD_DVBSKY_S950:
i2c_bus = &dev->i2c_bus[0];
@@ -1857,6 +1908,7 @@ static int dvb_register(struct cx23885_tsport *port)
/* attach tuner */
memset(&ts2020_config, 0, sizeof(ts2020_config));
ts2020_config.fe = fe0->dvb.frontend;
+ ts2020_config.get_agc_pwm = m88ds3103_get_agc_pwm;
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "ts2020", I2C_NAME_SIZE);
info.addr = 0x60;
@@ -1912,6 +1964,7 @@ static int dvb_register(struct cx23885_tsport *port)
/* attach tuner */
memset(&si2157_config, 0, sizeof(si2157_config));
si2157_config.fe = fe0->dvb.frontend;
+ si2157_config.if_port = 1;
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "si2157", I2C_NAME_SIZE);
info.addr = 0x60;
@@ -1957,6 +2010,7 @@ static int dvb_register(struct cx23885_tsport *port)
/* attach tuner */
memset(&si2157_config, 0, sizeof(si2157_config));
si2157_config.fe = fe0->dvb.frontend;
+ si2157_config.if_port = 1;
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "si2157", I2C_NAME_SIZE);
info.addr = 0x60;
@@ -1986,6 +2040,7 @@ static int dvb_register(struct cx23885_tsport *port)
/* attach tuner */
memset(&ts2020_config, 0, sizeof(ts2020_config));
ts2020_config.fe = fe0->dvb.frontend;
+ ts2020_config.get_agc_pwm = m88ds3103_get_agc_pwm;
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "ts2020", I2C_NAME_SIZE);
info.addr = 0x60;
@@ -2031,6 +2086,7 @@ static int dvb_register(struct cx23885_tsport *port)
/* attach tuner */
memset(&ts2020_config, 0, sizeof(ts2020_config));
ts2020_config.fe = fe0->dvb.frontend;
+ ts2020_config.get_agc_pwm = m88ds3103_get_agc_pwm;
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "ts2020", I2C_NAME_SIZE);
info.addr = 0x60;
@@ -2093,6 +2149,7 @@ static int dvb_register(struct cx23885_tsport *port)
/* attach tuner */
memset(&si2157_config, 0, sizeof(si2157_config));
si2157_config.fe = fe0->dvb.frontend;
+ si2157_config.if_port = 1;
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "si2157", I2C_NAME_SIZE);
info.addr = 0x60;
@@ -2111,6 +2168,7 @@ static int dvb_register(struct cx23885_tsport *port)
case CX23885_BOARD_HAUPPAUGE_HVR5525:
switch (port->nr) {
struct m88rs6000t_config m88rs6000t_config;
+ struct a8293_platform_data a8293_pdata = {};
/* port b - satellite */
case 1:
@@ -2122,10 +2180,20 @@ static int dvb_register(struct cx23885_tsport *port)
break;
/* attach SEC */
- if (!dvb_attach(a8293_attach, fe0->dvb.frontend,
- &dev->i2c_bus[0].i2c_adap,
- &hauppauge_a8293_config))
+ a8293_pdata.dvb_frontend = fe0->dvb.frontend;
+ memset(&info, 0, sizeof(info));
+ strlcpy(info.type, "a8293", I2C_NAME_SIZE);
+ info.addr = 0x0b;
+ info.platform_data = &a8293_pdata;
+ request_module("a8293");
+ client_sec = i2c_new_device(&dev->i2c_bus[0].i2c_adap, &info);
+ if (!client_sec || !client_sec->dev.driver)
+ goto frontend_detach;
+ if (!try_module_get(client_sec->dev.driver->owner)) {
+ i2c_unregister_device(client_sec);
goto frontend_detach;
+ }
+ port->i2c_client_sec = client_sec;
/* attach tuner */
memset(&m88rs6000t_config, 0, sizeof(m88rs6000t_config));
@@ -2172,6 +2240,7 @@ static int dvb_register(struct cx23885_tsport *port)
/* attach tuner */
memset(&si2157_config, 0, sizeof(si2157_config));
si2157_config.fe = fe0->dvb.frontend;
+ si2157_config.if_port = 1;
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "si2157", I2C_NAME_SIZE);
info.addr = 0x60;
@@ -2238,6 +2307,14 @@ static int dvb_register(struct cx23885_tsport *port)
return 0;
frontend_detach:
+ /* remove I2C client for SEC */
+ client_sec = port->i2c_client_sec;
+ if (client_sec) {
+ module_put(client_sec->dev.driver->owner);
+ i2c_unregister_device(client_sec);
+ port->i2c_client_sec = NULL;
+ }
+
/* remove I2C client for tuner */
client_tuner = port->i2c_client_tuner;
if (client_tuner) {
@@ -2339,6 +2416,13 @@ int cx23885_dvb_unregister(struct cx23885_tsport *port)
i2c_unregister_device(client);
}
+ /* remove I2C client for SEC */
+ client = port->i2c_client_sec;
+ if (client) {
+ module_put(client->dev.driver->owner);
+ i2c_unregister_device(client);
+ }
+
/* remove I2C client for tuner */
client = port->i2c_client_tuner;
if (client) {
diff --git a/drivers/media/pci/cx23885/cx23885-f300.c b/drivers/media/pci/cx23885/cx23885-f300.c
index 6f817d8732da..a6c45eb0a105 100644
--- a/drivers/media/pci/cx23885/cx23885-f300.c
+++ b/drivers/media/pci/cx23885/cx23885-f300.c
@@ -144,7 +144,7 @@ static u8 f300_xfer(struct dvb_frontend *fe, u8 *buf)
return ret;
}
-int f300_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+int f300_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage)
{
u8 buf[16];
diff --git a/drivers/media/pci/cx23885/cx23885-f300.h b/drivers/media/pci/cx23885/cx23885-f300.h
index e73344c94963..be14d7de7cd8 100644
--- a/drivers/media/pci/cx23885/cx23885-f300.h
+++ b/drivers/media/pci/cx23885/cx23885-f300.h
@@ -1,2 +1,2 @@
extern int f300_set_voltage(struct dvb_frontend *fe,
- fe_sec_voltage_t voltage);
+ enum fe_sec_voltage voltage);
diff --git a/drivers/media/pci/cx23885/cx23885-video.c b/drivers/media/pci/cx23885/cx23885-video.c
index 2232b389c441..ec76470d12a4 100644
--- a/drivers/media/pci/cx23885/cx23885-video.c
+++ b/drivers/media/pci/cx23885/cx23885-video.c
@@ -581,7 +581,9 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct cx23885_dev *dev = video_drvdata(file);
- struct v4l2_mbus_framefmt mbus_fmt;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
int err;
dprintk(2, "%s()\n", __func__);
@@ -600,10 +602,10 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
dev->field = f->fmt.pix.field;
dprintk(2, "%s() width=%d height=%d field=%d\n", __func__,
dev->width, dev->height, dev->field);
- v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, MEDIA_BUS_FMT_FIXED);
- call_all(dev, video, s_mbus_fmt, &mbus_fmt);
- v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
- /* s_mbus_fmt overwrites f->fmt.pix.field, restore it */
+ v4l2_fill_mbus_format(&format.format, &f->fmt.pix, MEDIA_BUS_FMT_FIXED);
+ call_all(dev, pad, set_fmt, NULL, &format);
+ v4l2_fill_pix_format(&f->fmt.pix, &format.format);
+ /* set_fmt overwrites f->fmt.pix.field, restore it */
f->fmt.pix.field = dev->field;
return 0;
}
diff --git a/drivers/media/pci/cx23885/cx23885.h b/drivers/media/pci/cx23885/cx23885.h
index aeda8d3990ae..027ead438194 100644
--- a/drivers/media/pci/cx23885/cx23885.h
+++ b/drivers/media/pci/cx23885/cx23885.h
@@ -304,11 +304,12 @@ struct cx23885_tsport {
struct i2c_client *i2c_client_demod;
struct i2c_client *i2c_client_tuner;
+ struct i2c_client *i2c_client_sec;
struct i2c_client *i2c_client_ci;
int (*set_frontend)(struct dvb_frontend *fe);
int (*fe_set_voltage)(struct dvb_frontend *fe,
- fe_sec_voltage_t voltage);
+ enum fe_sec_voltage voltage);
};
struct cx23885_kernel_ir {
diff --git a/drivers/media/pci/cx88/cx88-core.c b/drivers/media/pci/cx88/cx88-core.c
index 3501be9f19d8..aab7cf4c9825 100644
--- a/drivers/media/pci/cx88/cx88-core.c
+++ b/drivers/media/pci/cx88/cx88-core.c
@@ -519,6 +519,8 @@ void cx88_wakeup(struct cx88_core *core,
buf = list_entry(q->active.next,
struct cx88_buffer, list);
v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
+ buf->vb.v4l2_buf.field = core->field;
+ buf->vb.v4l2_buf.sequence = q->count++;
list_del(&buf->list);
vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
}
diff --git a/drivers/media/pci/cx88/cx88-dvb.c b/drivers/media/pci/cx88/cx88-dvb.c
index 1b2ed238cdb6..9dfa5ee32a8f 100644
--- a/drivers/media/pci/cx88/cx88-dvb.c
+++ b/drivers/media/pci/cx88/cx88-dvb.c
@@ -449,7 +449,7 @@ static int cx24123_set_ts_param(struct dvb_frontend* fe,
}
static int kworld_dvbs_100_set_voltage(struct dvb_frontend* fe,
- fe_sec_voltage_t voltage)
+ enum fe_sec_voltage voltage)
{
struct cx8802_dev *dev= fe->dvb->priv;
struct cx88_core *core = dev->core;
@@ -465,7 +465,7 @@ static int kworld_dvbs_100_set_voltage(struct dvb_frontend* fe,
}
static int geniatech_dvbs_set_voltage(struct dvb_frontend *fe,
- fe_sec_voltage_t voltage)
+ enum fe_sec_voltage voltage)
{
struct cx8802_dev *dev= fe->dvb->priv;
struct cx88_core *core = dev->core;
@@ -481,7 +481,7 @@ static int geniatech_dvbs_set_voltage(struct dvb_frontend *fe,
}
static int tevii_dvbs_set_voltage(struct dvb_frontend *fe,
- fe_sec_voltage_t voltage)
+ enum fe_sec_voltage voltage)
{
struct cx8802_dev *dev= fe->dvb->priv;
struct cx88_core *core = dev->core;
@@ -505,7 +505,7 @@ static int tevii_dvbs_set_voltage(struct dvb_frontend *fe,
}
static int vp1027_set_voltage(struct dvb_frontend *fe,
- fe_sec_voltage_t voltage)
+ enum fe_sec_voltage voltage)
{
struct cx8802_dev *dev = fe->dvb->priv;
struct cx88_core *core = dev->core;
@@ -897,7 +897,7 @@ static int samsung_smt_7020_tuner_set_params(struct dvb_frontend *fe)
}
static int samsung_smt_7020_set_tone(struct dvb_frontend *fe,
- fe_sec_tone_mode_t tone)
+ enum fe_sec_tone_mode tone)
{
struct cx8802_dev *dev = fe->dvb->priv;
struct cx88_core *core = dev->core;
@@ -919,7 +919,7 @@ static int samsung_smt_7020_set_tone(struct dvb_frontend *fe,
}
static int samsung_smt_7020_set_voltage(struct dvb_frontend *fe,
- fe_sec_voltage_t voltage)
+ enum fe_sec_voltage voltage)
{
struct cx8802_dev *dev = fe->dvb->priv;
struct cx88_core *core = dev->core;
diff --git a/drivers/media/pci/cx88/cx88-mpeg.c b/drivers/media/pci/cx88/cx88-mpeg.c
index 98344540c51f..34f505744477 100644
--- a/drivers/media/pci/cx88/cx88-mpeg.c
+++ b/drivers/media/pci/cx88/cx88-mpeg.c
@@ -173,7 +173,7 @@ int cx8802_start_dma(struct cx8802_dev *dev,
/* reset counter */
cx_write(MO_TS_GPCNTRL, GP_COUNT_CONTROL_RESET);
- q->count = 1;
+ q->count = 0;
/* enable irqs */
dprintk( 1, "setting the interrupt mask\n" );
@@ -216,8 +216,6 @@ static int cx8802_restart_queue(struct cx8802_dev *dev,
dprintk(2,"restart_queue [%p/%d]: restart dma\n",
buf, buf->vb.v4l2_buf.index);
cx8802_start_dma(dev, q, buf);
- list_for_each_entry(buf, &q->active, list)
- buf->count = q->count++;
return 0;
}
@@ -260,7 +258,6 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
if (list_empty(&cx88q->active)) {
dprintk( 1, "queue is empty - first active\n" );
list_add_tail(&buf->list, &cx88q->active);
- buf->count = cx88q->count++;
dprintk(1,"[%p/%d] %s - first active\n",
buf, buf->vb.v4l2_buf.index, __func__);
@@ -269,7 +266,6 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
dprintk( 1, "queue is not empty - append to active\n" );
prev = list_entry(cx88q->active.prev, struct cx88_buffer, list);
list_add_tail(&buf->list, &cx88q->active);
- buf->count = cx88q->count++;
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
dprintk( 1, "[%p/%d] %s - append to active\n",
buf, buf->vb.v4l2_buf.index, __func__);
diff --git a/drivers/media/pci/cx88/cx88-vbi.c b/drivers/media/pci/cx88/cx88-vbi.c
index 32eb7fdb875e..7510e80eb2ff 100644
--- a/drivers/media/pci/cx88/cx88-vbi.c
+++ b/drivers/media/pci/cx88/cx88-vbi.c
@@ -59,7 +59,7 @@ static int cx8800_start_vbi_dma(struct cx8800_dev *dev,
/* reset counter */
cx_write(MO_VBI_GPCNTRL, GP_COUNT_CONTROL_RESET);
- q->count = 1;
+ q->count = 0;
/* enable irqs */
cx_set(MO_PCI_INTMSK, core->pci_irqmask | PCI_INT_VIDINT);
@@ -102,8 +102,6 @@ int cx8800_restart_vbi_queue(struct cx8800_dev *dev,
dprintk(2,"restart_queue [%p/%d]: restart dma\n",
buf, buf->vb.v4l2_buf.index);
cx8800_start_vbi_dma(dev, q, buf);
- list_for_each_entry(buf, &q->active, list)
- buf->count = q->count++;
return 0;
}
@@ -175,7 +173,6 @@ static void buffer_queue(struct vb2_buffer *vb)
if (list_empty(&q->active)) {
list_add_tail(&buf->list, &q->active);
cx8800_start_vbi_dma(dev, q, buf);
- buf->count = q->count++;
dprintk(2,"[%p/%d] vbi_queue - first active\n",
buf, buf->vb.v4l2_buf.index);
@@ -183,7 +180,6 @@ static void buffer_queue(struct vb2_buffer *vb)
buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1);
prev = list_entry(q->active.prev, struct cx88_buffer, list);
list_add_tail(&buf->list, &q->active);
- buf->count = q->count++;
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
dprintk(2,"[%p/%d] buffer_queue - append to active\n",
buf, buf->vb.v4l2_buf.index);
diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c
index c9decd80bf61..400e5caefd58 100644
--- a/drivers/media/pci/cx88/cx88-video.c
+++ b/drivers/media/pci/cx88/cx88-video.c
@@ -370,7 +370,7 @@ static int start_video_dma(struct cx8800_dev *dev,
/* reset counter */
cx_write(MO_VIDY_GPCNTRL,GP_COUNT_CONTROL_RESET);
- q->count = 1;
+ q->count = 0;
/* enable irqs */
cx_set(MO_PCI_INTMSK, core->pci_irqmask | PCI_INT_VIDINT);
@@ -410,7 +410,6 @@ static int stop_video_dma(struct cx8800_dev *dev)
cx_clear(MO_VID_INTMSK, 0x0f0011);
return 0;
}
-#endif
static int restart_video_queue(struct cx8800_dev *dev,
struct cx88_dmaqueue *q)
@@ -423,11 +422,10 @@ static int restart_video_queue(struct cx8800_dev *dev,
dprintk(2,"restart_queue [%p/%d]: restart dma\n",
buf, buf->vb.v4l2_buf.index);
start_video_dma(dev, q, buf);
- list_for_each_entry(buf, &q->active, list)
- buf->count = q->count++;
}
return 0;
}
+#endif
/* ------------------------------------------------------------------ */
@@ -523,7 +521,6 @@ static void buffer_queue(struct vb2_buffer *vb)
if (list_empty(&q->active)) {
list_add_tail(&buf->list, &q->active);
- buf->count = q->count++;
dprintk(2,"[%p/%d] buffer_queue - first active\n",
buf, buf->vb.v4l2_buf.index);
@@ -531,7 +528,6 @@ static void buffer_queue(struct vb2_buffer *vb)
buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1);
prev = list_entry(q->active.prev, struct cx88_buffer, list);
list_add_tail(&buf->list, &q->active);
- buf->count = q->count++;
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
dprintk(2, "[%p/%d] buffer_queue - append to active\n",
buf, buf->vb.v4l2_buf.index);
@@ -771,6 +767,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
(f->fmt.pix.width * fmt->depth) >> 3;
f->fmt.pix.sizeimage =
f->fmt.pix.height * f->fmt.pix.bytesperline;
+ f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
return 0;
}
diff --git a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h
index b9fe1ac24803..785fe2e0d702 100644
--- a/drivers/media/pci/cx88/cx88.h
+++ b/drivers/media/pci/cx88/cx88.h
@@ -327,7 +327,6 @@ struct cx88_buffer {
/* cx88 specific */
unsigned int bpl;
struct cx88_riscmem risc;
- u32 count;
};
struct cx88_dmaqueue {
@@ -376,9 +375,10 @@ struct cx88_core {
/* config info -- dvb */
#if IS_ENABLED(CONFIG_VIDEO_CX88_DVB)
- int (*prev_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
+ int (*prev_set_voltage)(struct dvb_frontend *fe,
+ enum fe_sec_voltage voltage);
#endif
- void (*gate_ctrl)(struct cx88_core *core, int open);
+ void (*gate_ctrl)(struct cx88_core *core, int open);
/* state info */
struct task_struct *kthread;
diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c
index 9e3492e20766..0ac2dd35fe50 100644
--- a/drivers/media/pci/ddbridge/ddbridge-core.c
+++ b/drivers/media/pci/ddbridge/ddbridge-core.c
@@ -1630,7 +1630,8 @@ fail1:
printk(KERN_ERR "fail1\n");
if (dev->msi)
pci_disable_msi(dev->pdev);
- free_irq(dev->pdev->irq, dev);
+ if (stat == 0)
+ free_irq(dev->pdev->irq, dev);
fail:
printk(KERN_ERR "fail\n");
ddb_unmap(dev);
diff --git a/drivers/media/pci/dm1105/dm1105.c b/drivers/media/pci/dm1105/dm1105.c
index ed11716731e9..88915fb87e80 100644
--- a/drivers/media/pci/dm1105/dm1105.c
+++ b/drivers/media/pci/dm1105/dm1105.c
@@ -591,7 +591,8 @@ static inline struct dm1105_dev *frontend_to_dm1105_dev(struct dvb_frontend *fe)
return container_of(fe->dvb, struct dm1105_dev, dvb_adapter);
}
-static int dm1105_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+static int dm1105_set_voltage(struct dvb_frontend *fe,
+ enum fe_sec_voltage voltage)
{
struct dm1105_dev *dev = frontend_to_dm1105_dev(fe);
diff --git a/drivers/media/pci/dt3155/Kconfig b/drivers/media/pci/dt3155/Kconfig
new file mode 100644
index 000000000000..5145e0dfa2aa
--- /dev/null
+++ b/drivers/media/pci/dt3155/Kconfig
@@ -0,0 +1,13 @@
+config VIDEO_DT3155
+ tristate "DT3155 frame grabber"
+ depends on PCI && VIDEO_DEV && VIDEO_V4L2
+ depends on HAS_DMA
+ select VIDEOBUF2_DMA_CONTIG
+ default n
+ ---help---
+ Enables dt3155 device driver for the DataTranslation DT3155 frame grabber.
+ Say Y here if you have this hardware.
+ In doubt, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called dt3155.
diff --git a/drivers/media/pci/dt3155/Makefile b/drivers/media/pci/dt3155/Makefile
new file mode 100644
index 000000000000..89fa637ec54c
--- /dev/null
+++ b/drivers/media/pci/dt3155/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_VIDEO_DT3155) += dt3155.o
diff --git a/drivers/media/pci/dt3155/dt3155.c b/drivers/media/pci/dt3155/dt3155.c
new file mode 100644
index 000000000000..89d0dc705e4a
--- /dev/null
+++ b/drivers/media/pci/dt3155/dt3155.c
@@ -0,0 +1,632 @@
+/***************************************************************************
+ * Copyright (C) 2006-2010 by Marin Mitov *
+ * mitov@issp.bas.bg *
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/stringify.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/slab.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-common.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "dt3155.h"
+
+#define DT3155_DEVICE_ID 0x1223
+
+/**
+ * read_i2c_reg - reads an internal i2c register
+ *
+ * @addr: dt3155 mmio base address
+ * @index: index (internal address) of register to read
+ * @data: pointer to byte the read data will be placed in
+ *
+ * returns: zero on success or error code
+ *
+ * This function starts reading the specified (by index) register
+ * and busy waits for the process to finish. The result is placed
+ * in a byte pointed by data.
+ */
+static int read_i2c_reg(void __iomem *addr, u8 index, u8 *data)
+{
+ u32 tmp = index;
+
+ iowrite32((tmp << 17) | IIC_READ, addr + IIC_CSR2);
+ mmiowb();
+ udelay(45); /* wait at least 43 usec for NEW_CYCLE to clear */
+ if (ioread32(addr + IIC_CSR2) & NEW_CYCLE)
+ return -EIO; /* error: NEW_CYCLE not cleared */
+ tmp = ioread32(addr + IIC_CSR1);
+ if (tmp & DIRECT_ABORT) {
+ /* reset DIRECT_ABORT bit */
+ iowrite32(DIRECT_ABORT, addr + IIC_CSR1);
+ return -EIO; /* error: DIRECT_ABORT set */
+ }
+ *data = tmp >> 24;
+ return 0;
+}
+
+/**
+ * write_i2c_reg - writes to an internal i2c register
+ *
+ * @addr: dt3155 mmio base address
+ * @index: index (internal address) of register to read
+ * @data: data to be written
+ *
+ * returns: zero on success or error code
+ *
+ * This function starts writing the specified (by index) register
+ * and busy waits for the process to finish.
+ */
+static int write_i2c_reg(void __iomem *addr, u8 index, u8 data)
+{
+ u32 tmp = index;
+
+ iowrite32((tmp << 17) | IIC_WRITE | data, addr + IIC_CSR2);
+ mmiowb();
+ udelay(65); /* wait at least 63 usec for NEW_CYCLE to clear */
+ if (ioread32(addr + IIC_CSR2) & NEW_CYCLE)
+ return -EIO; /* error: NEW_CYCLE not cleared */
+ if (ioread32(addr + IIC_CSR1) & DIRECT_ABORT) {
+ /* reset DIRECT_ABORT bit */
+ iowrite32(DIRECT_ABORT, addr + IIC_CSR1);
+ return -EIO; /* error: DIRECT_ABORT set */
+ }
+ return 0;
+}
+
+/**
+ * write_i2c_reg_nowait - writes to an internal i2c register
+ *
+ * @addr: dt3155 mmio base address
+ * @index: index (internal address) of register to read
+ * @data: data to be written
+ *
+ * This function starts writing the specified (by index) register
+ * and then returns.
+ */
+static void write_i2c_reg_nowait(void __iomem *addr, u8 index, u8 data)
+{
+ u32 tmp = index;
+
+ iowrite32((tmp << 17) | IIC_WRITE | data, addr + IIC_CSR2);
+ mmiowb();
+}
+
+/**
+ * wait_i2c_reg - waits the read/write to finish
+ *
+ * @addr: dt3155 mmio base address
+ *
+ * returns: zero on success or error code
+ *
+ * This function waits reading/writing to finish.
+ */
+static int wait_i2c_reg(void __iomem *addr)
+{
+ if (ioread32(addr + IIC_CSR2) & NEW_CYCLE)
+ udelay(65); /* wait at least 63 usec for NEW_CYCLE to clear */
+ if (ioread32(addr + IIC_CSR2) & NEW_CYCLE)
+ return -EIO; /* error: NEW_CYCLE not cleared */
+ if (ioread32(addr + IIC_CSR1) & DIRECT_ABORT) {
+ /* reset DIRECT_ABORT bit */
+ iowrite32(DIRECT_ABORT, addr + IIC_CSR1);
+ return -EIO; /* error: DIRECT_ABORT set */
+ }
+ return 0;
+}
+
+static int
+dt3155_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+ unsigned int *nbuffers, unsigned int *num_planes,
+ unsigned int sizes[], void *alloc_ctxs[])
+
+{
+ struct dt3155_priv *pd = vb2_get_drv_priv(vq);
+ unsigned size = pd->width * pd->height;
+
+ if (vq->num_buffers + *nbuffers < 2)
+ *nbuffers = 2 - vq->num_buffers;
+ if (fmt && fmt->fmt.pix.sizeimage < size)
+ return -EINVAL;
+ *num_planes = 1;
+ sizes[0] = fmt ? fmt->fmt.pix.sizeimage : size;
+ alloc_ctxs[0] = pd->alloc_ctx;
+ return 0;
+}
+
+static int dt3155_buf_prepare(struct vb2_buffer *vb)
+{
+ struct dt3155_priv *pd = vb2_get_drv_priv(vb->vb2_queue);
+
+ vb2_set_plane_payload(vb, 0, pd->width * pd->height);
+ return 0;
+}
+
+static int dt3155_start_streaming(struct vb2_queue *q, unsigned count)
+{
+ struct dt3155_priv *pd = vb2_get_drv_priv(q);
+ struct vb2_buffer *vb = pd->curr_buf;
+ dma_addr_t dma_addr;
+
+ pd->sequence = 0;
+ dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
+ iowrite32(dma_addr, pd->regs + EVEN_DMA_START);
+ iowrite32(dma_addr + pd->width, pd->regs + ODD_DMA_START);
+ iowrite32(pd->width, pd->regs + EVEN_DMA_STRIDE);
+ iowrite32(pd->width, pd->regs + ODD_DMA_STRIDE);
+ /* enable interrupts, clear all irq flags */
+ iowrite32(FLD_START_EN | FLD_END_ODD_EN | FLD_START |
+ FLD_END_EVEN | FLD_END_ODD, pd->regs + INT_CSR);
+ iowrite32(FIFO_EN | SRST | FLD_CRPT_ODD | FLD_CRPT_EVEN |
+ FLD_DN_ODD | FLD_DN_EVEN | CAP_CONT_EVEN | CAP_CONT_ODD,
+ pd->regs + CSR1);
+ wait_i2c_reg(pd->regs);
+ write_i2c_reg(pd->regs, CONFIG, pd->config);
+ write_i2c_reg(pd->regs, EVEN_CSR, CSR_ERROR | CSR_DONE);
+ write_i2c_reg(pd->regs, ODD_CSR, CSR_ERROR | CSR_DONE);
+
+ /* start the board */
+ write_i2c_reg(pd->regs, CSR2, pd->csr2 | BUSY_EVEN | BUSY_ODD);
+ return 0;
+}
+
+static void dt3155_stop_streaming(struct vb2_queue *q)
+{
+ struct dt3155_priv *pd = vb2_get_drv_priv(q);
+ struct vb2_buffer *vb;
+
+ spin_lock_irq(&pd->lock);
+ /* stop the board */
+ write_i2c_reg_nowait(pd->regs, CSR2, pd->csr2);
+ iowrite32(FIFO_EN | SRST | FLD_CRPT_ODD | FLD_CRPT_EVEN |
+ FLD_DN_ODD | FLD_DN_EVEN, pd->regs + CSR1);
+ /* disable interrupts, clear all irq flags */
+ iowrite32(FLD_START | FLD_END_EVEN | FLD_END_ODD, pd->regs + INT_CSR);
+ spin_unlock_irq(&pd->lock);
+
+ /*
+ * It is not clear whether the DMA stops at once or whether it
+ * will finish the current frame or field first. To be on the
+ * safe side we wait a bit.
+ */
+ msleep(45);
+
+ spin_lock_irq(&pd->lock);
+ if (pd->curr_buf) {
+ vb2_buffer_done(pd->curr_buf, VB2_BUF_STATE_ERROR);
+ pd->curr_buf = NULL;
+ }
+
+ while (!list_empty(&pd->dmaq)) {
+ vb = list_first_entry(&pd->dmaq, typeof(*vb), done_entry);
+ list_del(&vb->done_entry);
+ vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
+ }
+ spin_unlock_irq(&pd->lock);
+}
+
+static void dt3155_buf_queue(struct vb2_buffer *vb)
+{
+ struct dt3155_priv *pd = vb2_get_drv_priv(vb->vb2_queue);
+
+ /* pd->vidq.streaming = 1 when dt3155_buf_queue() is invoked */
+ spin_lock_irq(&pd->lock);
+ if (pd->curr_buf)
+ list_add_tail(&vb->done_entry, &pd->dmaq);
+ else
+ pd->curr_buf = vb;
+ spin_unlock_irq(&pd->lock);
+}
+
+static const struct vb2_ops q_ops = {
+ .queue_setup = dt3155_queue_setup,
+ .wait_prepare = vb2_ops_wait_prepare,
+ .wait_finish = vb2_ops_wait_finish,
+ .buf_prepare = dt3155_buf_prepare,
+ .start_streaming = dt3155_start_streaming,
+ .stop_streaming = dt3155_stop_streaming,
+ .buf_queue = dt3155_buf_queue,
+};
+
+static irqreturn_t dt3155_irq_handler_even(int irq, void *dev_id)
+{
+ struct dt3155_priv *ipd = dev_id;
+ struct vb2_buffer *ivb;
+ dma_addr_t dma_addr;
+ u32 tmp;
+
+ tmp = ioread32(ipd->regs + INT_CSR) & (FLD_START | FLD_END_ODD);
+ if (!tmp)
+ return IRQ_NONE; /* not our irq */
+ if ((tmp & FLD_START) && !(tmp & FLD_END_ODD)) {
+ iowrite32(FLD_START_EN | FLD_END_ODD_EN | FLD_START,
+ ipd->regs + INT_CSR);
+ return IRQ_HANDLED; /* start of field irq */
+ }
+ tmp = ioread32(ipd->regs + CSR1) & (FLD_CRPT_EVEN | FLD_CRPT_ODD);
+ if (tmp) {
+ iowrite32(FIFO_EN | SRST | FLD_CRPT_ODD | FLD_CRPT_EVEN |
+ FLD_DN_ODD | FLD_DN_EVEN |
+ CAP_CONT_EVEN | CAP_CONT_ODD,
+ ipd->regs + CSR1);
+ mmiowb();
+ }
+
+ spin_lock(&ipd->lock);
+ if (ipd->curr_buf && !list_empty(&ipd->dmaq)) {
+ v4l2_get_timestamp(&ipd->curr_buf->v4l2_buf.timestamp);
+ ipd->curr_buf->v4l2_buf.sequence = ipd->sequence++;
+ ipd->curr_buf->v4l2_buf.field = V4L2_FIELD_NONE;
+ vb2_buffer_done(ipd->curr_buf, VB2_BUF_STATE_DONE);
+
+ ivb = list_first_entry(&ipd->dmaq, typeof(*ivb), done_entry);
+ list_del(&ivb->done_entry);
+ ipd->curr_buf = ivb;
+ dma_addr = vb2_dma_contig_plane_dma_addr(ivb, 0);
+ iowrite32(dma_addr, ipd->regs + EVEN_DMA_START);
+ iowrite32(dma_addr + ipd->width, ipd->regs + ODD_DMA_START);
+ iowrite32(ipd->width, ipd->regs + EVEN_DMA_STRIDE);
+ iowrite32(ipd->width, ipd->regs + ODD_DMA_STRIDE);
+ mmiowb();
+ }
+
+ /* enable interrupts, clear all irq flags */
+ iowrite32(FLD_START_EN | FLD_END_ODD_EN | FLD_START |
+ FLD_END_EVEN | FLD_END_ODD, ipd->regs + INT_CSR);
+ spin_unlock(&ipd->lock);
+ return IRQ_HANDLED;
+}
+
+static const struct v4l2_file_operations dt3155_fops = {
+ .owner = THIS_MODULE,
+ .open = v4l2_fh_open,
+ .release = vb2_fop_release,
+ .unlocked_ioctl = video_ioctl2,
+ .read = vb2_fop_read,
+ .mmap = vb2_fop_mmap,
+ .poll = vb2_fop_poll
+};
+
+static int dt3155_querycap(struct file *filp, void *p,
+ struct v4l2_capability *cap)
+{
+ struct dt3155_priv *pd = video_drvdata(filp);
+
+ strcpy(cap->driver, DT3155_NAME);
+ strcpy(cap->card, DT3155_NAME " frame grabber");
+ sprintf(cap->bus_info, "PCI:%s", pci_name(pd->pdev));
+ cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
+ V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
+ cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+ return 0;
+}
+
+static int dt3155_enum_fmt_vid_cap(struct file *filp,
+ void *p, struct v4l2_fmtdesc *f)
+{
+ if (f->index)
+ return -EINVAL;
+ f->pixelformat = V4L2_PIX_FMT_GREY;
+ strcpy(f->description, "8-bit Greyscale");
+ return 0;
+}
+
+static int dt3155_fmt_vid_cap(struct file *filp, void *p, struct v4l2_format *f)
+{
+ struct dt3155_priv *pd = video_drvdata(filp);
+
+ f->fmt.pix.width = pd->width;
+ f->fmt.pix.height = pd->height;
+ f->fmt.pix.pixelformat = V4L2_PIX_FMT_GREY;
+ f->fmt.pix.field = V4L2_FIELD_NONE;
+ f->fmt.pix.bytesperline = f->fmt.pix.width;
+ f->fmt.pix.sizeimage = f->fmt.pix.width * f->fmt.pix.height;
+ f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+ return 0;
+}
+
+static int dt3155_g_std(struct file *filp, void *p, v4l2_std_id *norm)
+{
+ struct dt3155_priv *pd = video_drvdata(filp);
+
+ *norm = pd->std;
+ return 0;
+}
+
+static int dt3155_s_std(struct file *filp, void *p, v4l2_std_id norm)
+{
+ struct dt3155_priv *pd = video_drvdata(filp);
+
+ if (pd->std == norm)
+ return 0;
+ if (vb2_is_busy(&pd->vidq))
+ return -EBUSY;
+ pd->std = norm;
+ if (pd->std & V4L2_STD_525_60) {
+ pd->csr2 = VT_60HZ;
+ pd->width = 640;
+ pd->height = 480;
+ } else {
+ pd->csr2 = VT_50HZ;
+ pd->width = 768;
+ pd->height = 576;
+ }
+ return 0;
+}
+
+static int dt3155_enum_input(struct file *filp, void *p,
+ struct v4l2_input *input)
+{
+ if (input->index > 3)
+ return -EINVAL;
+ if (input->index)
+ snprintf(input->name, sizeof(input->name), "VID%d",
+ input->index);
+ else
+ strlcpy(input->name, "J2/VID0", sizeof(input->name));
+ input->type = V4L2_INPUT_TYPE_CAMERA;
+ input->std = V4L2_STD_ALL;
+ input->status = 0;
+ return 0;
+}
+
+static int dt3155_g_input(struct file *filp, void *p, unsigned int *i)
+{
+ struct dt3155_priv *pd = video_drvdata(filp);
+
+ *i = pd->input;
+ return 0;
+}
+
+static int dt3155_s_input(struct file *filp, void *p, unsigned int i)
+{
+ struct dt3155_priv *pd = video_drvdata(filp);
+
+ if (i > 3)
+ return -EINVAL;
+ pd->input = i;
+ write_i2c_reg(pd->regs, AD_ADDR, AD_CMD_REG);
+ write_i2c_reg(pd->regs, AD_CMD, (i << 6) | (i << 4) | SYNC_LVL_3);
+ return 0;
+}
+
+static const struct v4l2_ioctl_ops dt3155_ioctl_ops = {
+ .vidioc_querycap = dt3155_querycap,
+ .vidioc_enum_fmt_vid_cap = dt3155_enum_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = dt3155_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = dt3155_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = dt3155_fmt_vid_cap,
+ .vidioc_reqbufs = vb2_ioctl_reqbufs,
+ .vidioc_create_bufs = vb2_ioctl_create_bufs,
+ .vidioc_querybuf = vb2_ioctl_querybuf,
+ .vidioc_expbuf = vb2_ioctl_expbuf,
+ .vidioc_qbuf = vb2_ioctl_qbuf,
+ .vidioc_dqbuf = vb2_ioctl_dqbuf,
+ .vidioc_streamon = vb2_ioctl_streamon,
+ .vidioc_streamoff = vb2_ioctl_streamoff,
+ .vidioc_g_std = dt3155_g_std,
+ .vidioc_s_std = dt3155_s_std,
+ .vidioc_enum_input = dt3155_enum_input,
+ .vidioc_g_input = dt3155_g_input,
+ .vidioc_s_input = dt3155_s_input,
+};
+
+static int dt3155_init_board(struct dt3155_priv *pd)
+{
+ struct pci_dev *pdev = pd->pdev;
+ int i;
+ u8 tmp = 0;
+
+ pci_set_master(pdev); /* dt3155 needs it */
+
+ /* resetting the adapter */
+ iowrite32(ADDR_ERR_ODD | ADDR_ERR_EVEN | FLD_CRPT_ODD | FLD_CRPT_EVEN |
+ FLD_DN_ODD | FLD_DN_EVEN, pd->regs + CSR1);
+ mmiowb();
+ msleep(20);
+
+ /* initializing adapter registers */
+ iowrite32(FIFO_EN | SRST, pd->regs + CSR1);
+ mmiowb();
+ iowrite32(0xEEEEEE01, pd->regs + EVEN_PIXEL_FMT);
+ iowrite32(0xEEEEEE01, pd->regs + ODD_PIXEL_FMT);
+ iowrite32(0x00000020, pd->regs + FIFO_TRIGER);
+ iowrite32(0x00000103, pd->regs + XFER_MODE);
+ iowrite32(0, pd->regs + RETRY_WAIT_CNT);
+ iowrite32(0, pd->regs + INT_CSR);
+ iowrite32(1, pd->regs + EVEN_FLD_MASK);
+ iowrite32(1, pd->regs + ODD_FLD_MASK);
+ iowrite32(0, pd->regs + MASK_LENGTH);
+ iowrite32(0x0005007C, pd->regs + FIFO_FLAG_CNT);
+ iowrite32(0x01010101, pd->regs + IIC_CLK_DUR);
+ mmiowb();
+
+ /* verifying that we have a DT3155 board (not just a SAA7116 chip) */
+ read_i2c_reg(pd->regs, DT_ID, &tmp);
+ if (tmp != DT3155_ID)
+ return -ENODEV;
+
+ /* initialize AD LUT */
+ write_i2c_reg(pd->regs, AD_ADDR, 0);
+ for (i = 0; i < 256; i++)
+ write_i2c_reg(pd->regs, AD_LUT, i);
+
+ /* initialize ADC references */
+ /* FIXME: pos_ref & neg_ref depend on VT_50HZ */
+ write_i2c_reg(pd->regs, AD_ADDR, AD_CMD_REG);
+ write_i2c_reg(pd->regs, AD_CMD, VIDEO_CNL_1 | SYNC_CNL_1 | SYNC_LVL_3);
+ write_i2c_reg(pd->regs, AD_ADDR, AD_POS_REF);
+ write_i2c_reg(pd->regs, AD_CMD, 34);
+ write_i2c_reg(pd->regs, AD_ADDR, AD_NEG_REF);
+ write_i2c_reg(pd->regs, AD_CMD, 0);
+
+ /* initialize PM LUT */
+ write_i2c_reg(pd->regs, CONFIG, pd->config | PM_LUT_PGM);
+ for (i = 0; i < 256; i++) {
+ write_i2c_reg(pd->regs, PM_LUT_ADDR, i);
+ write_i2c_reg(pd->regs, PM_LUT_DATA, i);
+ }
+ write_i2c_reg(pd->regs, CONFIG, pd->config | PM_LUT_PGM | PM_LUT_SEL);
+ for (i = 0; i < 256; i++) {
+ write_i2c_reg(pd->regs, PM_LUT_ADDR, i);
+ write_i2c_reg(pd->regs, PM_LUT_DATA, i);
+ }
+ write_i2c_reg(pd->regs, CONFIG, pd->config); /* ACQ_MODE_EVEN */
+
+ /* select channel 1 for input and set sync level */
+ write_i2c_reg(pd->regs, AD_ADDR, AD_CMD_REG);
+ write_i2c_reg(pd->regs, AD_CMD, VIDEO_CNL_1 | SYNC_CNL_1 | SYNC_LVL_3);
+
+ /* disable all irqs, clear all irq flags */
+ iowrite32(FLD_START | FLD_END_EVEN | FLD_END_ODD,
+ pd->regs + INT_CSR);
+
+ return 0;
+}
+
+static struct video_device dt3155_vdev = {
+ .name = DT3155_NAME,
+ .fops = &dt3155_fops,
+ .ioctl_ops = &dt3155_ioctl_ops,
+ .minor = -1,
+ .release = video_device_release_empty,
+ .tvnorms = V4L2_STD_ALL,
+};
+
+static int dt3155_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ int err;
+ struct dt3155_priv *pd;
+
+ err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+ if (err)
+ return -ENODEV;
+ pd = devm_kzalloc(&pdev->dev, sizeof(*pd), GFP_KERNEL);
+ if (!pd)
+ return -ENOMEM;
+
+ err = v4l2_device_register(&pdev->dev, &pd->v4l2_dev);
+ if (err)
+ return err;
+ pd->vdev = dt3155_vdev;
+ pd->vdev.v4l2_dev = &pd->v4l2_dev;
+ video_set_drvdata(&pd->vdev, pd); /* for use in video_fops */
+ pd->pdev = pdev;
+ pd->std = V4L2_STD_625_50;
+ pd->csr2 = VT_50HZ;
+ pd->width = 768;
+ pd->height = 576;
+ INIT_LIST_HEAD(&pd->dmaq);
+ mutex_init(&pd->mux);
+ pd->vdev.lock = &pd->mux; /* for locking v4l2_file_operations */
+ pd->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ pd->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+ pd->vidq.io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ;
+ pd->vidq.ops = &q_ops;
+ pd->vidq.mem_ops = &vb2_dma_contig_memops;
+ pd->vidq.drv_priv = pd;
+ pd->vidq.min_buffers_needed = 2;
+ pd->vidq.gfp_flags = GFP_DMA32;
+ pd->vidq.lock = &pd->mux; /* for locking v4l2_file_operations */
+ pd->vdev.queue = &pd->vidq;
+ err = vb2_queue_init(&pd->vidq);
+ if (err < 0)
+ goto err_v4l2_dev_unreg;
+ pd->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
+ if (IS_ERR(pd->alloc_ctx)) {
+ dev_err(&pdev->dev, "Can't allocate buffer context");
+ err = PTR_ERR(pd->alloc_ctx);
+ goto err_v4l2_dev_unreg;
+ }
+ spin_lock_init(&pd->lock);
+ pd->config = ACQ_MODE_EVEN;
+ err = pci_enable_device(pdev);
+ if (err)
+ goto err_free_ctx;
+ err = pci_request_region(pdev, 0, pci_name(pdev));
+ if (err)
+ goto err_pci_disable;
+ pd->regs = pci_iomap(pdev, 0, pci_resource_len(pd->pdev, 0));
+ if (!pd->regs) {
+ err = -ENOMEM;
+ goto err_free_reg;
+ }
+ err = dt3155_init_board(pd);
+ if (err)
+ goto err_iounmap;
+ err = request_irq(pd->pdev->irq, dt3155_irq_handler_even,
+ IRQF_SHARED, DT3155_NAME, pd);
+ if (err)
+ goto err_iounmap;
+ err = video_register_device(&pd->vdev, VFL_TYPE_GRABBER, -1);
+ if (err)
+ goto err_free_irq;
+ dev_info(&pdev->dev, "/dev/video%i is ready\n", pd->vdev.minor);
+ return 0; /* success */
+
+err_free_irq:
+ free_irq(pd->pdev->irq, pd);
+err_iounmap:
+ pci_iounmap(pdev, pd->regs);
+err_free_reg:
+ pci_release_region(pdev, 0);
+err_pci_disable:
+ pci_disable_device(pdev);
+err_free_ctx:
+ vb2_dma_contig_cleanup_ctx(pd->alloc_ctx);
+err_v4l2_dev_unreg:
+ v4l2_device_unregister(&pd->v4l2_dev);
+ return err;
+}
+
+static void dt3155_remove(struct pci_dev *pdev)
+{
+ struct v4l2_device *v4l2_dev = pci_get_drvdata(pdev);
+ struct dt3155_priv *pd = container_of(v4l2_dev, struct dt3155_priv,
+ v4l2_dev);
+
+ video_unregister_device(&pd->vdev);
+ free_irq(pd->pdev->irq, pd);
+ vb2_queue_release(&pd->vidq);
+ v4l2_device_unregister(&pd->v4l2_dev);
+ pci_iounmap(pdev, pd->regs);
+ pci_release_region(pdev, 0);
+ pci_disable_device(pdev);
+ vb2_dma_contig_cleanup_ctx(pd->alloc_ctx);
+}
+
+static const struct pci_device_id pci_ids[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, DT3155_DEVICE_ID) },
+ { 0, /* zero marks the end */ },
+};
+MODULE_DEVICE_TABLE(pci, pci_ids);
+
+static struct pci_driver pci_driver = {
+ .name = DT3155_NAME,
+ .id_table = pci_ids,
+ .probe = dt3155_probe,
+ .remove = dt3155_remove,
+};
+
+module_pci_driver(pci_driver);
+
+MODULE_DESCRIPTION("video4linux pci-driver for dt3155 frame grabber");
+MODULE_AUTHOR("Marin Mitov <mitov@issp.bas.bg>");
+MODULE_VERSION(DT3155_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/pci/dt3155/dt3155.h b/drivers/media/pci/dt3155/dt3155.h
new file mode 100644
index 000000000000..4e1f4d598d57
--- /dev/null
+++ b/drivers/media/pci/dt3155/dt3155.h
@@ -0,0 +1,196 @@
+/***************************************************************************
+ * Copyright (C) 2006-2010 by Marin Mitov *
+ * mitov@issp.bas.bg *
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+/* DT3155 header file */
+#ifndef _DT3155_H_
+#define _DT3155_H_
+
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-dev.h>
+
+#define DT3155_NAME "dt3155"
+#define DT3155_VER_MAJ 2
+#define DT3155_VER_MIN 0
+#define DT3155_VER_EXT 0
+#define DT3155_VERSION __stringify(DT3155_VER_MAJ) "." \
+ __stringify(DT3155_VER_MIN) "." \
+ __stringify(DT3155_VER_EXT)
+
+/* DT3155 Base Register offsets (memory mapped) */
+#define EVEN_DMA_START 0x00
+#define ODD_DMA_START 0x0C
+#define EVEN_DMA_STRIDE 0x18
+#define ODD_DMA_STRIDE 0x24
+#define EVEN_PIXEL_FMT 0x30
+#define ODD_PIXEL_FMT 0x34
+#define FIFO_TRIGER 0x38
+#define XFER_MODE 0x3C
+#define CSR1 0x40
+#define RETRY_WAIT_CNT 0x44
+#define INT_CSR 0x48
+#define EVEN_FLD_MASK 0x4C
+#define ODD_FLD_MASK 0x50
+#define MASK_LENGTH 0x54
+#define FIFO_FLAG_CNT 0x58
+#define IIC_CLK_DUR 0x5C
+#define IIC_CSR1 0x60
+#define IIC_CSR2 0x64
+
+/* DT3155 Internal Registers indexes (i2c/IIC mapped) */
+#define CSR2 0x10
+#define EVEN_CSR 0x11
+#define ODD_CSR 0x12
+#define CONFIG 0x13
+#define DT_ID 0x1F
+#define X_CLIP_START 0x20
+#define Y_CLIP_START 0x22
+#define X_CLIP_END 0x24
+#define Y_CLIP_END 0x26
+#define AD_ADDR 0x30
+#define AD_LUT 0x31
+#define AD_CMD 0x32
+#define DIG_OUT 0x40
+#define PM_LUT_ADDR 0x50
+#define PM_LUT_DATA 0x51
+
+/* AD command register values */
+#define AD_CMD_REG 0x00
+#define AD_POS_REF 0x01
+#define AD_NEG_REF 0x02
+
+/* CSR1 bit masks */
+#define RANGE_EN 0x00008000
+#define CRPT_DIS 0x00004000
+#define ADDR_ERR_ODD 0x00000800
+#define ADDR_ERR_EVEN 0x00000400
+#define FLD_CRPT_ODD 0x00000200
+#define FLD_CRPT_EVEN 0x00000100
+#define FIFO_EN 0x00000080
+#define SRST 0x00000040
+#define FLD_DN_ODD 0x00000020
+#define FLD_DN_EVEN 0x00000010
+/* These should not be used.
+ * Use CAP_CONT_ODD/EVEN instead
+#define CAP_SNGL_ODD 0x00000008
+#define CAP_SNGL_EVEN 0x00000004
+*/
+#define CAP_CONT_ODD 0x00000002
+#define CAP_CONT_EVEN 0x00000001
+
+/* INT_CSR bit masks */
+#define FLD_START_EN 0x00000400
+#define FLD_END_ODD_EN 0x00000200
+#define FLD_END_EVEN_EN 0x00000100
+#define FLD_START 0x00000004
+#define FLD_END_ODD 0x00000002
+#define FLD_END_EVEN 0x00000001
+
+/* IIC_CSR1 bit masks */
+#define DIRECT_ABORT 0x00000200
+
+/* IIC_CSR2 bit masks */
+#define NEW_CYCLE 0x01000000
+#define DIR_RD 0x00010000
+#define IIC_READ 0x01010000
+#define IIC_WRITE 0x01000000
+
+/* CSR2 bit masks */
+#define DISP_PASS 0x40
+#define BUSY_ODD 0x20
+#define BUSY_EVEN 0x10
+#define SYNC_PRESENT 0x08
+#define VT_50HZ 0x04
+#define SYNC_SNTL 0x02
+#define CHROM_FILT 0x01
+#define VT_60HZ 0x00
+
+/* CSR_EVEN/ODD bit masks */
+#define CSR_ERROR 0x04
+#define CSR_SNGL 0x02
+#define CSR_DONE 0x01
+
+/* CONFIG bit masks */
+#define PM_LUT_PGM 0x80
+#define PM_LUT_SEL 0x40
+#define CLIP_EN 0x20
+#define HSCALE_EN 0x10
+#define EXT_TRIG_UP 0x0C
+#define EXT_TRIG_DOWN 0x04
+#define ACQ_MODE_NEXT 0x02
+#define ACQ_MODE_ODD 0x01
+#define ACQ_MODE_EVEN 0x00
+
+/* AD_CMD bit masks */
+#define VIDEO_CNL_1 0x00
+#define VIDEO_CNL_2 0x40
+#define VIDEO_CNL_3 0x80
+#define VIDEO_CNL_4 0xC0
+#define SYNC_CNL_1 0x00
+#define SYNC_CNL_2 0x10
+#define SYNC_CNL_3 0x20
+#define SYNC_CNL_4 0x30
+#define SYNC_LVL_1 0x00
+#define SYNC_LVL_2 0x04
+#define SYNC_LVL_3 0x08
+#define SYNC_LVL_4 0x0C
+
+/* DT3155 identificator */
+#define DT3155_ID 0x20
+
+/* per board private data structure */
+/**
+ * struct dt3155_priv - private data structure
+ *
+ * @v4l2_dev: v4l2_device structure
+ * @vdev: video_device structure
+ * @pdev: pointer to pci_dev structure
+ * @vidq: vb2_queue structure
+ * @alloc_ctx: dma_contig allocation context
+ * @curr_buf: pointer to curren buffer
+ * @mux: mutex to protect the instance
+ * @dmaq: queue for dma buffers
+ * @lock: spinlock for dma queue
+ * @std: input standard
+ * @width: frame width
+ * @height: frame height
+ * @input: current input
+ * @sequence: frame counter
+ * @stats: statistics structure
+ * @regs: local copy of mmio base register
+ * @csr2: local copy of csr2 register
+ * @config: local copy of config register
+ */
+struct dt3155_priv {
+ struct v4l2_device v4l2_dev;
+ struct video_device vdev;
+ struct pci_dev *pdev;
+ struct vb2_queue vidq;
+ struct vb2_alloc_ctx *alloc_ctx;
+ struct vb2_buffer *curr_buf;
+ struct mutex mux;
+ struct list_head dmaq;
+ spinlock_t lock;
+ v4l2_std_id std;
+ unsigned width, height;
+ unsigned input;
+ unsigned int sequence;
+ void __iomem *regs;
+ u8 csr2, config;
+};
+
+#endif /* _DT3155_H_ */
diff --git a/drivers/media/pci/ivtv/ivtv-controls.c b/drivers/media/pci/ivtv/ivtv-controls.c
index ccf548c255f1..8a55ccb8f0c9 100644
--- a/drivers/media/pci/ivtv/ivtv-controls.c
+++ b/drivers/media/pci/ivtv/ivtv-controls.c
@@ -64,13 +64,15 @@ static int ivtv_s_video_encoding(struct cx2341x_handler *cxhdl, u32 val)
{
struct ivtv *itv = container_of(cxhdl, struct ivtv, cxhdl);
int is_mpeg1 = val == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
- struct v4l2_mbus_framefmt fmt;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
/* fix videodecoder resolution */
- fmt.width = cxhdl->width / (is_mpeg1 ? 2 : 1);
- fmt.height = cxhdl->height;
- fmt.code = MEDIA_BUS_FMT_FIXED;
- v4l2_subdev_call(itv->sd_video, video, s_mbus_fmt, &fmt);
+ format.format.width = cxhdl->width / (is_mpeg1 ? 2 : 1);
+ format.format.height = cxhdl->height;
+ format.format.code = MEDIA_BUS_FMT_FIXED;
+ v4l2_subdev_call(itv->sd_video, pad, set_fmt, NULL, &format);
return 0;
}
diff --git a/drivers/media/pci/ivtv/ivtv-driver.c b/drivers/media/pci/ivtv/ivtv-driver.c
index c2e60b4f292d..8616fa8193bc 100644
--- a/drivers/media/pci/ivtv/ivtv-driver.c
+++ b/drivers/media/pci/ivtv/ivtv-driver.c
@@ -805,11 +805,11 @@ static void ivtv_init_struct2(struct ivtv *itv)
{
int i;
- for (i = 0; i < IVTV_CARD_MAX_VIDEO_INPUTS; i++)
+ for (i = 0; i < IVTV_CARD_MAX_VIDEO_INPUTS - 1; i++)
if (itv->card->video_inputs[i].video_type == 0)
break;
itv->nof_inputs = i;
- for (i = 0; i < IVTV_CARD_MAX_AUDIO_INPUTS; i++)
+ for (i = 0; i < IVTV_CARD_MAX_AUDIO_INPUTS - 1; i++)
if (itv->card->audio_inputs[i].audio_type == 0)
break;
itv->nof_audio_inputs = i;
diff --git a/drivers/media/pci/ivtv/ivtv-driver.h b/drivers/media/pci/ivtv/ivtv-driver.h
index e8b6c7ad2ba9..ee0ef6e48c7d 100644
--- a/drivers/media/pci/ivtv/ivtv-driver.h
+++ b/drivers/media/pci/ivtv/ivtv-driver.h
@@ -830,7 +830,8 @@ static inline int ivtv_raw_vbi(const struct ivtv *itv)
do { \
struct v4l2_subdev *__sd; \
__v4l2_device_call_subdevs_p(&(itv)->v4l2_dev, __sd, \
- !(hw) || (__sd->grp_id & (hw)), o, f , ##args); \
+ !(hw) ? true : (__sd->grp_id & (hw)), \
+ o, f, ##args); \
} while (0)
#define ivtv_call_all(itv, o, f, args...) ivtv_call_hw(itv, 0, o, f , ##args)
diff --git a/drivers/media/pci/ivtv/ivtv-ioctl.c b/drivers/media/pci/ivtv/ivtv-ioctl.c
index 6fe6c4a0e858..9a21c17fc376 100644
--- a/drivers/media/pci/ivtv/ivtv-ioctl.c
+++ b/drivers/media/pci/ivtv/ivtv-ioctl.c
@@ -581,7 +581,9 @@ static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f
{
struct ivtv_open_id *id = fh2id(fh);
struct ivtv *itv = id->itv;
- struct v4l2_mbus_framefmt mbus_fmt;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
int ret = ivtv_try_fmt_vid_cap(file, fh, fmt);
int w = fmt->fmt.pix.width;
int h = fmt->fmt.pix.height;
@@ -599,10 +601,10 @@ static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f
itv->cxhdl.height = h;
if (v4l2_ctrl_g_ctrl(itv->cxhdl.video_encoding) == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
fmt->fmt.pix.width /= 2;
- mbus_fmt.width = fmt->fmt.pix.width;
- mbus_fmt.height = h;
- mbus_fmt.code = MEDIA_BUS_FMT_FIXED;
- v4l2_subdev_call(itv->sd_video, video, s_mbus_fmt, &mbus_fmt);
+ format.format.width = fmt->fmt.pix.width;
+ format.format.height = h;
+ format.format.code = MEDIA_BUS_FMT_FIXED;
+ v4l2_subdev_call(itv->sd_video, pad, set_fmt, NULL, &format);
return ivtv_g_fmt_vid_cap(file, fh, fmt);
}
@@ -1529,7 +1531,8 @@ static int ivtv_log_status(struct file *file, void *fh)
ivtv_get_audio_input(itv, itv->audio_input, &audin);
IVTV_INFO("Video Input: %s\n", vidin.name);
IVTV_INFO("Audio Input: %s%s\n", audin.name,
- (itv->dualwatch_stereo_mode & ~0x300) == 0x200 ? " (Bilingual)" : "");
+ itv->dualwatch_stereo_mode == V4L2_MPEG_AUDIO_MODE_DUAL ?
+ " (Bilingual)" : "");
if (has_output) {
struct v4l2_output vidout;
struct v4l2_audioout audout;
diff --git a/drivers/media/pci/mantis/hopper_cards.c b/drivers/media/pci/mantis/hopper_cards.c
index 104914a5bf06..68b5800030b7 100644
--- a/drivers/media/pci/mantis/hopper_cards.c
+++ b/drivers/media/pci/mantis/hopper_cards.c
@@ -106,6 +106,10 @@ static irqreturn_t hopper_irq_handler(int irq, void *dev_id)
}
if (stat & MANTIS_INT_IRQ1) {
dprintk(MANTIS_DEBUG, 0, "<%s>", label[2]);
+ spin_lock(&mantis->intmask_lock);
+ mmwrite(mmread(MANTIS_INT_MASK) & ~MANTIS_INT_IRQ1,
+ MANTIS_INT_MASK);
+ spin_unlock(&mantis->intmask_lock);
schedule_work(&mantis->uart_work);
}
if (stat & MANTIS_INT_OCERR) {
@@ -154,6 +158,7 @@ static irqreturn_t hopper_irq_handler(int irq, void *dev_id)
static int hopper_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *pci_id)
{
+ struct mantis_pci_drvdata *drvdata;
struct mantis_pci *mantis;
struct mantis_hwconfig *config;
int err = 0;
@@ -165,12 +170,16 @@ static int hopper_pci_probe(struct pci_dev *pdev,
goto fail0;
}
+ drvdata = (void *)pci_id->driver_data;
mantis->num = devs;
mantis->verbose = verbose;
mantis->pdev = pdev;
- config = (struct mantis_hwconfig *) pci_id->driver_data;
+ config = drvdata->hwconfig;
config->irq_handler = &hopper_irq_handler;
mantis->hwconfig = config;
+ mantis->rc_map_name = drvdata->rc_map_name;
+
+ spin_lock_init(&mantis->intmask_lock);
err = mantis_pci_init(mantis);
if (err) {
@@ -247,7 +256,8 @@ static void hopper_pci_remove(struct pci_dev *pdev)
}
static struct pci_device_id hopper_pci_table[] = {
- MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_3028_DVB_T, &vp3028_config),
+ MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_3028_DVB_T, &vp3028_config,
+ NULL),
{ }
};
diff --git a/drivers/media/pci/mantis/mantis_cards.c b/drivers/media/pci/mantis/mantis_cards.c
index 801fc55b6167..cdefffc16d9e 100644
--- a/drivers/media/pci/mantis/mantis_cards.c
+++ b/drivers/media/pci/mantis/mantis_cards.c
@@ -25,6 +25,7 @@
#include <linux/slab.h>
#include <asm/irq.h>
#include <linux/interrupt.h>
+#include <media/rc-map.h>
#include "dmxdev.h"
#include "dvbdev.h"
@@ -49,6 +50,7 @@
#include "mantis_pci.h"
#include "mantis_i2c.h"
#include "mantis_reg.h"
+#include "mantis_input.h"
static unsigned int verbose;
module_param(verbose, int, 0644);
@@ -114,6 +116,10 @@ static irqreturn_t mantis_irq_handler(int irq, void *dev_id)
}
if (stat & MANTIS_INT_IRQ1) {
dprintk(MANTIS_DEBUG, 0, "<%s>", label[2]);
+ spin_lock(&mantis->intmask_lock);
+ mmwrite(mmread(MANTIS_INT_MASK) & ~MANTIS_INT_IRQ1,
+ MANTIS_INT_MASK);
+ spin_unlock(&mantis->intmask_lock);
schedule_work(&mantis->uart_work);
}
if (stat & MANTIS_INT_OCERR) {
@@ -162,6 +168,7 @@ static irqreturn_t mantis_irq_handler(int irq, void *dev_id)
static int mantis_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *pci_id)
{
+ struct mantis_pci_drvdata *drvdata;
struct mantis_pci *mantis;
struct mantis_hwconfig *config;
int err = 0;
@@ -169,84 +176,91 @@ static int mantis_pci_probe(struct pci_dev *pdev,
mantis = kzalloc(sizeof(struct mantis_pci), GFP_KERNEL);
if (mantis == NULL) {
printk(KERN_ERR "%s ERROR: Out of memory\n", __func__);
- err = -ENOMEM;
- goto fail0;
+ return -ENOMEM;
}
+ drvdata = (void *)pci_id->driver_data;
mantis->num = devs;
mantis->verbose = verbose;
mantis->pdev = pdev;
- config = (struct mantis_hwconfig *) pci_id->driver_data;
+ config = drvdata->hwconfig;
config->irq_handler = &mantis_irq_handler;
mantis->hwconfig = config;
+ mantis->rc_map_name = drvdata->rc_map_name;
+
+ spin_lock_init(&mantis->intmask_lock);
err = mantis_pci_init(mantis);
if (err) {
dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI initialization failed <%d>", err);
- goto fail1;
+ goto err_free_mantis;
}
err = mantis_stream_control(mantis, STREAM_TO_HIF);
if (err < 0) {
dprintk(MANTIS_ERROR, 1, "ERROR: Mantis stream control failed <%d>", err);
- goto fail1;
+ goto err_pci_exit;
}
err = mantis_i2c_init(mantis);
if (err < 0) {
dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C initialization failed <%d>", err);
- goto fail2;
+ goto err_pci_exit;
}
err = mantis_get_mac(mantis);
if (err < 0) {
dprintk(MANTIS_ERROR, 1, "ERROR: Mantis MAC address read failed <%d>", err);
- goto fail2;
+ goto err_i2c_exit;
}
err = mantis_dma_init(mantis);
if (err < 0) {
dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA initialization failed <%d>", err);
- goto fail3;
+ goto err_i2c_exit;
}
err = mantis_dvb_init(mantis);
if (err < 0) {
dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DVB initialization failed <%d>", err);
- goto fail4;
+ goto err_dma_exit;
+ }
+
+ err = mantis_input_init(mantis);
+ if (err < 0) {
+ dprintk(MANTIS_ERROR, 1,
+ "ERROR: Mantis DVB initialization failed <%d>", err);
+ goto err_dvb_exit;
}
+
err = mantis_uart_init(mantis);
if (err < 0) {
dprintk(MANTIS_ERROR, 1, "ERROR: Mantis UART initialization failed <%d>", err);
- goto fail6;
+ goto err_input_exit;
}
devs++;
- return err;
+ return 0;
+err_input_exit:
+ mantis_input_exit(mantis);
- dprintk(MANTIS_ERROR, 1, "ERROR: Mantis UART exit! <%d>", err);
- mantis_uart_exit(mantis);
+err_dvb_exit:
+ mantis_dvb_exit(mantis);
-fail6:
-fail4:
- dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA exit! <%d>", err);
+err_dma_exit:
mantis_dma_exit(mantis);
-fail3:
- dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C exit! <%d>", err);
+err_i2c_exit:
mantis_i2c_exit(mantis);
-fail2:
- dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI exit! <%d>", err);
+err_pci_exit:
mantis_pci_exit(mantis);
-fail1:
- dprintk(MANTIS_ERROR, 1, "ERROR: Mantis free! <%d>", err);
+err_free_mantis:
kfree(mantis);
-fail0:
return err;
}
@@ -257,6 +271,7 @@ static void mantis_pci_remove(struct pci_dev *pdev)
if (mantis) {
mantis_uart_exit(mantis);
+ mantis_input_exit(mantis);
mantis_dvb_exit(mantis);
mantis_dma_exit(mantis);
mantis_i2c_exit(mantis);
@@ -267,17 +282,28 @@ static void mantis_pci_remove(struct pci_dev *pdev)
}
static struct pci_device_id mantis_pci_table[] = {
- MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_1033_DVB_S, &vp1033_config),
- MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_1034_DVB_S, &vp1034_config),
- MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_1041_DVB_S2, &vp1041_config),
- MAKE_ENTRY(TECHNISAT, SKYSTAR_HD2_10, &vp1041_config),
- MAKE_ENTRY(TECHNISAT, SKYSTAR_HD2_20, &vp1041_config),
- MAKE_ENTRY(TERRATEC, CINERGY_S2_PCI_HD, &vp1041_config),
- MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_2033_DVB_C, &vp2033_config),
- MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_2040_DVB_C, &vp2040_config),
- MAKE_ENTRY(TECHNISAT, CABLESTAR_HD2, &vp2040_config),
- MAKE_ENTRY(TERRATEC, CINERGY_C, &vp2040_config),
- MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_3030_DVB_T, &vp3030_config),
+ MAKE_ENTRY(TECHNISAT, CABLESTAR_HD2, &vp2040_config,
+ RC_MAP_TECHNISAT_TS35),
+ MAKE_ENTRY(TECHNISAT, SKYSTAR_HD2_10, &vp1041_config,
+ NULL),
+ MAKE_ENTRY(TECHNISAT, SKYSTAR_HD2_20, &vp1041_config,
+ NULL),
+ MAKE_ENTRY(TERRATEC, CINERGY_C, &vp2040_config,
+ RC_MAP_TERRATEC_CINERGY_C_PCI),
+ MAKE_ENTRY(TERRATEC, CINERGY_S2_PCI_HD, &vp1041_config,
+ RC_MAP_TERRATEC_CINERGY_S2_HD),
+ MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_1033_DVB_S, &vp1033_config,
+ NULL),
+ MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_1034_DVB_S, &vp1034_config,
+ NULL),
+ MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_1041_DVB_S2, &vp1041_config,
+ RC_MAP_TWINHAN_DTV_CAB_CI),
+ MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_2033_DVB_C, &vp2033_config,
+ RC_MAP_TWINHAN_DTV_CAB_CI),
+ MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_2040_DVB_C, &vp2040_config,
+ NULL),
+ MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_3030_DVB_T, &vp3030_config,
+ NULL),
{ }
};
diff --git a/drivers/media/pci/mantis/mantis_common.h b/drivers/media/pci/mantis/mantis_common.h
index 8ff448bb792d..d48778a366a9 100644
--- a/drivers/media/pci/mantis/mantis_common.h
+++ b/drivers/media/pci/mantis/mantis_common.h
@@ -25,6 +25,7 @@
#include <linux/mutex.h>
#include <linux/workqueue.h>
+#include "mantis_reg.h"
#include "mantis_uart.h"
#include "mantis_link.h"
@@ -68,12 +69,13 @@
#define TECHNISAT 0x1ae4
#define TERRATEC 0x153b
-#define MAKE_ENTRY(__subven, __subdev, __configptr) { \
+#define MAKE_ENTRY(__subven, __subdev, __configptr, __rc) { \
.vendor = TWINHAN_TECHNOLOGIES, \
.device = MANTIS, \
.subvendor = (__subven), \
.subdevice = (__subdev), \
- .driver_data = (unsigned long) (__configptr) \
+ .driver_data = (unsigned long) \
+ &(struct mantis_pci_drvdata){__configptr, __rc} \
}
enum mantis_i2c_mode {
@@ -101,6 +103,11 @@ struct mantis_hwconfig {
enum mantis_i2c_mode i2c_mode;
};
+struct mantis_pci_drvdata {
+ struct mantis_hwconfig *hwconfig;
+ char *rc_map_name;
+};
+
struct mantis_pci {
unsigned int verbose;
@@ -131,6 +138,7 @@ struct mantis_pci {
dma_addr_t risc_dma;
struct tasklet_struct tasklet;
+ spinlock_t intmask_lock;
struct i2c_adapter adapter;
int i2c_rc;
@@ -165,15 +173,32 @@ struct mantis_pci {
struct mantis_ca *mantis_ca;
- wait_queue_head_t uart_wq;
struct work_struct uart_work;
- spinlock_t uart_lock;
struct rc_dev *rc;
char input_name[80];
char input_phys[80];
+ char *rc_map_name;
};
#define MANTIS_HIF_STATUS (mantis->gpio_status)
+static inline void mantis_mask_ints(struct mantis_pci *mantis, u32 mask)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&mantis->intmask_lock, flags);
+ mmwrite(mmread(MANTIS_INT_MASK) & ~mask, MANTIS_INT_MASK);
+ spin_unlock_irqrestore(&mantis->intmask_lock, flags);
+}
+
+static inline void mantis_unmask_ints(struct mantis_pci *mantis, u32 mask)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&mantis->intmask_lock, flags);
+ mmwrite(mmread(MANTIS_INT_MASK) | mask, MANTIS_INT_MASK);
+ spin_unlock_irqrestore(&mantis->intmask_lock, flags);
+}
+
#endif /* __MANTIS_COMMON_H */
diff --git a/drivers/media/pci/mantis/mantis_dma.c b/drivers/media/pci/mantis/mantis_dma.c
index 566c407175a4..1d59c7e039f7 100644
--- a/drivers/media/pci/mantis/mantis_dma.c
+++ b/drivers/media/pci/mantis/mantis_dma.c
@@ -190,7 +190,7 @@ void mantis_dma_start(struct mantis_pci *mantis)
mmwrite(0, MANTIS_DMA_CTL);
mantis->last_block = mantis->busy_block = 0;
- mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_RISCI, MANTIS_INT_MASK);
+ mantis_unmask_ints(mantis, MANTIS_INT_RISCI);
mmwrite(MANTIS_FIFO_EN | MANTIS_DCAP_EN
| MANTIS_RISC_EN, MANTIS_DMA_CTL);
@@ -209,8 +209,7 @@ void mantis_dma_stop(struct mantis_pci *mantis)
mmwrite(mmread(MANTIS_INT_STAT), MANTIS_INT_STAT);
- mmwrite(mmread(MANTIS_INT_MASK) & ~(MANTIS_INT_RISCI |
- MANTIS_INT_RISCEN), MANTIS_INT_MASK);
+ mantis_mask_ints(mantis, MANTIS_INT_RISCI | MANTIS_INT_RISCEN);
}
diff --git a/drivers/media/pci/mantis/mantis_i2c.c b/drivers/media/pci/mantis/mantis_i2c.c
index 895ddba3c0fb..d72ee47dc6e4 100644
--- a/drivers/media/pci/mantis/mantis_i2c.c
+++ b/drivers/media/pci/mantis/mantis_i2c.c
@@ -219,7 +219,7 @@ static struct i2c_algorithm mantis_algo = {
int mantis_i2c_init(struct mantis_pci *mantis)
{
- u32 intstat, intmask;
+ u32 intstat;
struct i2c_adapter *i2c_adapter = &mantis->adapter;
struct pci_dev *pdev = mantis->pdev;
@@ -242,11 +242,10 @@ int mantis_i2c_init(struct mantis_pci *mantis)
dprintk(MANTIS_DEBUG, 1, "Initializing I2C ..");
intstat = mmread(MANTIS_INT_STAT);
- intmask = mmread(MANTIS_INT_MASK);
+ mmread(MANTIS_INT_MASK);
mmwrite(intstat, MANTIS_INT_STAT);
dprintk(MANTIS_DEBUG, 1, "Disabling I2C interrupt");
- intmask = mmread(MANTIS_INT_MASK);
- mmwrite((intmask & ~MANTIS_INT_I2CDONE), MANTIS_INT_MASK);
+ mantis_mask_ints(mantis, MANTIS_INT_I2CDONE);
return 0;
}
@@ -254,11 +253,8 @@ EXPORT_SYMBOL_GPL(mantis_i2c_init);
int mantis_i2c_exit(struct mantis_pci *mantis)
{
- u32 intmask;
-
dprintk(MANTIS_DEBUG, 1, "Disabling I2C interrupt");
- intmask = mmread(MANTIS_INT_MASK);
- mmwrite((intmask & ~MANTIS_INT_I2CDONE), MANTIS_INT_MASK);
+ mantis_mask_ints(mantis, MANTIS_INT_I2CDONE);
dprintk(MANTIS_DEBUG, 1, "Removing I2C adapter");
i2c_del_adapter(&mantis->adapter);
diff --git a/drivers/media/pci/mantis/mantis_input.c b/drivers/media/pci/mantis/mantis_input.c
index 0e5252e5c0ef..7f7f1d4d7bb1 100644
--- a/drivers/media/pci/mantis/mantis_input.c
+++ b/drivers/media/pci/mantis/mantis_input.c
@@ -12,14 +12,8 @@
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#if 0 /* Currently unused */
-
#include <media/rc-core.h>
#include <linux/pci.h>
@@ -30,100 +24,32 @@
#include "dvb_net.h"
#include "mantis_common.h"
-#include "mantis_reg.h"
-#include "mantis_uart.h"
+#include "mantis_input.h"
#define MODULE_NAME "mantis_core"
-#define RC_MAP_MANTIS "rc-mantis"
-
-static struct rc_map_table mantis_ir_table[] = {
- { 0x29, KEY_POWER },
- { 0x28, KEY_FAVORITES },
- { 0x30, KEY_TEXT },
- { 0x17, KEY_INFO }, /* Preview */
- { 0x23, KEY_EPG },
- { 0x3b, KEY_F22 }, /* Record List */
- { 0x3c, KEY_1 },
- { 0x3e, KEY_2 },
- { 0x39, KEY_3 },
- { 0x36, KEY_4 },
- { 0x22, KEY_5 },
- { 0x20, KEY_6 },
- { 0x32, KEY_7 },
- { 0x26, KEY_8 },
- { 0x24, KEY_9 },
- { 0x2a, KEY_0 },
-
- { 0x33, KEY_CANCEL },
- { 0x2c, KEY_BACK },
- { 0x15, KEY_CLEAR },
- { 0x3f, KEY_TAB },
- { 0x10, KEY_ENTER },
- { 0x14, KEY_UP },
- { 0x0d, KEY_RIGHT },
- { 0x0e, KEY_DOWN },
- { 0x11, KEY_LEFT },
-
- { 0x21, KEY_VOLUMEUP },
- { 0x35, KEY_VOLUMEDOWN },
- { 0x3d, KEY_CHANNELDOWN },
- { 0x3a, KEY_CHANNELUP },
- { 0x2e, KEY_RECORD },
- { 0x2b, KEY_PLAY },
- { 0x13, KEY_PAUSE },
- { 0x25, KEY_STOP },
-
- { 0x1f, KEY_REWIND },
- { 0x2d, KEY_FASTFORWARD },
- { 0x1e, KEY_PREVIOUS }, /* Replay |< */
- { 0x1d, KEY_NEXT }, /* Skip >| */
-
- { 0x0b, KEY_CAMERA }, /* Capture */
- { 0x0f, KEY_LANGUAGE }, /* SAP */
- { 0x18, KEY_MODE }, /* PIP */
- { 0x12, KEY_ZOOM }, /* Full screen */
- { 0x1c, KEY_SUBTITLE },
- { 0x2f, KEY_MUTE },
- { 0x16, KEY_F20 }, /* L/R */
- { 0x38, KEY_F21 }, /* Hibernate */
-
- { 0x37, KEY_SWITCHVIDEOMODE }, /* A/V */
- { 0x31, KEY_AGAIN }, /* Recall */
- { 0x1a, KEY_KPPLUS }, /* Zoom+ */
- { 0x19, KEY_KPMINUS }, /* Zoom- */
- { 0x27, KEY_RED },
- { 0x0C, KEY_GREEN },
- { 0x01, KEY_YELLOW },
- { 0x00, KEY_BLUE },
-};
-
-static struct rc_map_list ir_mantis_map = {
- .map = {
- .scan = mantis_ir_table,
- .size = ARRAY_SIZE(mantis_ir_table),
- .rc_type = RC_TYPE_UNKNOWN,
- .name = RC_MAP_MANTIS,
- }
-};
+
+void mantis_input_process(struct mantis_pci *mantis, int scancode)
+{
+ if (mantis->rc)
+ rc_keydown(mantis->rc, RC_TYPE_UNKNOWN, scancode, 0);
+}
int mantis_input_init(struct mantis_pci *mantis)
{
struct rc_dev *dev;
int err;
- err = rc_map_register(&ir_mantis_map);
- if (err)
- goto out;
-
dev = rc_allocate_device();
if (!dev) {
dprintk(MANTIS_ERROR, 1, "Remote device allocation failed");
err = -ENOMEM;
- goto out_map;
+ goto out;
}
- sprintf(mantis->input_name, "Mantis %s IR receiver", mantis->hwconfig->model_name);
- sprintf(mantis->input_phys, "pci-%s/ir0", pci_name(mantis->pdev));
+ snprintf(mantis->input_name, sizeof(mantis->input_name),
+ "Mantis %s IR receiver", mantis->hwconfig->model_name);
+ snprintf(mantis->input_phys, sizeof(mantis->input_phys),
+ "pci-%s/ir0", pci_name(mantis->pdev));
dev->input_name = mantis->input_name;
dev->input_phys = mantis->input_phys;
@@ -132,7 +58,7 @@ int mantis_input_init(struct mantis_pci *mantis)
dev->input_id.product = mantis->device_id;
dev->input_id.version = 1;
dev->driver_name = MODULE_NAME;
- dev->map_name = RC_MAP_MANTIS;
+ dev->map_name = mantis->rc_map_name ? : RC_MAP_EMPTY;
dev->dev.parent = &mantis->pdev->dev;
err = rc_register_device(dev);
@@ -146,17 +72,13 @@ int mantis_input_init(struct mantis_pci *mantis)
out_dev:
rc_free_device(dev);
-out_map:
- rc_map_unregister(&ir_mantis_map);
out:
return err;
}
+EXPORT_SYMBOL_GPL(mantis_input_init);
-int mantis_init_exit(struct mantis_pci *mantis)
+void mantis_input_exit(struct mantis_pci *mantis)
{
rc_unregister_device(mantis->rc);
- rc_map_unregister(&ir_mantis_map);
- return 0;
}
-
-#endif
+EXPORT_SYMBOL_GPL(mantis_input_exit);
diff --git a/drivers/media/pci/mantis/mantis_input.h b/drivers/media/pci/mantis/mantis_input.h
new file mode 100644
index 000000000000..0fbd92987c02
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_input.h
@@ -0,0 +1,24 @@
+/*
+ Mantis PCI bridge 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.
+*/
+
+#ifndef __MANTIS_INPUT_H
+#define __MANTIS_INPUT_H
+
+int mantis_input_init(struct mantis_pci *mantis);
+void mantis_input_exit(struct mantis_pci *mantis);
+void mantis_input_process(struct mantis_pci *mantis, int scancode);
+
+#endif /* __MANTIS_UART_H */
diff --git a/drivers/media/pci/mantis/mantis_pcmcia.c b/drivers/media/pci/mantis/mantis_pcmcia.c
index 2f188c089666..b2dbc7b2e0f6 100644
--- a/drivers/media/pci/mantis/mantis_pcmcia.c
+++ b/drivers/media/pci/mantis/mantis_pcmcia.c
@@ -89,7 +89,7 @@ int mantis_pcmcia_init(struct mantis_ca *ca)
u32 gpif_stat, card_stat;
- mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_IRQ0, MANTIS_INT_MASK);
+ mantis_unmask_ints(mantis, MANTIS_INT_IRQ0);
gpif_stat = mmread(MANTIS_GPIF_STATUS);
card_stat = mmread(MANTIS_GPIF_IRQCFG);
@@ -117,5 +117,5 @@ void mantis_pcmcia_exit(struct mantis_ca *ca)
struct mantis_pci *mantis = ca->ca_priv;
mmwrite(mmread(MANTIS_GPIF_STATUS) & (~MANTIS_CARD_PLUGOUT | ~MANTIS_CARD_PLUGIN), MANTIS_GPIF_STATUS);
- mmwrite(mmread(MANTIS_INT_MASK) & ~MANTIS_INT_IRQ0, MANTIS_INT_MASK);
+ mantis_mask_ints(mantis, MANTIS_INT_IRQ0);
}
diff --git a/drivers/media/pci/mantis/mantis_uart.c b/drivers/media/pci/mantis/mantis_uart.c
index a70719218631..f1c96aec8c7b 100644
--- a/drivers/media/pci/mantis/mantis_uart.c
+++ b/drivers/media/pci/mantis/mantis_uart.c
@@ -25,6 +25,7 @@
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
+#include <linux/pci.h>
#include "dmxdev.h"
#include "dvbdev.h"
@@ -35,6 +36,7 @@
#include "mantis_common.h"
#include "mantis_reg.h"
#include "mantis_uart.h"
+#include "mantis_input.h"
struct mantis_uart_params {
enum mantis_baud baud_rate;
@@ -59,51 +61,54 @@ static struct {
{ "EVEN" }
};
-#define UART_MAX_BUF 16
-
-static int mantis_uart_read(struct mantis_pci *mantis, u8 *data)
+static void mantis_uart_read(struct mantis_pci *mantis)
{
struct mantis_hwconfig *config = mantis->hwconfig;
- u32 stat = 0, i;
+ int i, scancode = 0, err = 0;
/* get data */
+ dprintk(MANTIS_DEBUG, 1, "UART Reading ...");
for (i = 0; i < (config->bytes + 1); i++) {
+ int data = mmread(MANTIS_UART_RXD);
- stat = mmread(MANTIS_UART_STAT);
-
- if (stat & MANTIS_UART_RXFIFO_FULL) {
- dprintk(MANTIS_ERROR, 1, "RX Fifo FULL");
- }
- data[i] = mmread(MANTIS_UART_RXD) & 0x3f;
+ dprintk(MANTIS_DEBUG, 0, " <%02x>", data);
- dprintk(MANTIS_DEBUG, 1, "Reading ... <%02x>", data[i] & 0x3f);
+ scancode = (scancode << 8) | (data & 0x3f);
+ err |= data;
- if (data[i] & (1 << 7)) {
+ if (data & (1 << 7))
dprintk(MANTIS_ERROR, 1, "UART framing error");
- return -EINVAL;
- }
- if (data[i] & (1 << 6)) {
+
+ if (data & (1 << 6))
dprintk(MANTIS_ERROR, 1, "UART parity error");
- return -EINVAL;
- }
}
+ dprintk(MANTIS_DEBUG, 0, "\n");
- return 0;
+ if ((err & 0xC0) == 0)
+ mantis_input_process(mantis, scancode);
}
static void mantis_uart_work(struct work_struct *work)
{
struct mantis_pci *mantis = container_of(work, struct mantis_pci, uart_work);
- struct mantis_hwconfig *config = mantis->hwconfig;
- u8 buf[16];
- int i;
+ u32 stat;
- mantis_uart_read(mantis, buf);
+ stat = mmread(MANTIS_UART_STAT);
- for (i = 0; i < (config->bytes + 1); i++)
- dprintk(MANTIS_INFO, 1, "UART BUF:%d <%02x> ", i, buf[i]);
+ if (stat & MANTIS_UART_RXFIFO_FULL)
+ dprintk(MANTIS_ERROR, 1, "RX Fifo FULL");
- dprintk(MANTIS_DEBUG, 0, "\n");
+ /*
+ * MANTIS_UART_RXFIFO_DATA is only set if at least
+ * config->bytes + 1 bytes are in the FIFO.
+ */
+ while (stat & MANTIS_UART_RXFIFO_DATA) {
+ mantis_uart_read(mantis);
+ stat = mmread(MANTIS_UART_STAT);
+ }
+
+ /* re-enable UART (RX) interrupt */
+ mantis_unmask_ints(mantis, MANTIS_INT_IRQ1);
}
static int mantis_uart_setup(struct mantis_pci *mantis,
@@ -152,9 +157,6 @@ int mantis_uart_init(struct mantis_pci *mantis)
rates[params.baud_rate].string,
parity[params.parity].string);
- init_waitqueue_head(&mantis->uart_wq);
- spin_lock_init(&mantis->uart_lock);
-
INIT_WORK(&mantis->uart_work, mantis_uart_work);
/* disable interrupt */
@@ -169,8 +171,8 @@ int mantis_uart_init(struct mantis_pci *mantis)
mmwrite((mmread(MANTIS_UART_CTL) | MANTIS_UART_RXFLUSH), MANTIS_UART_CTL);
/* enable interrupt */
- mmwrite(mmread(MANTIS_INT_MASK) | 0x800, MANTIS_INT_MASK);
mmwrite(mmread(MANTIS_UART_CTL) | MANTIS_UART_RXINT, MANTIS_UART_CTL);
+ mantis_unmask_ints(mantis, MANTIS_INT_IRQ1);
schedule_work(&mantis->uart_work);
dprintk(MANTIS_DEBUG, 1, "UART successfully initialized");
@@ -182,6 +184,7 @@ EXPORT_SYMBOL_GPL(mantis_uart_init);
void mantis_uart_exit(struct mantis_pci *mantis)
{
/* disable interrupt */
+ mantis_mask_ints(mantis, MANTIS_INT_IRQ1);
mmwrite(mmread(MANTIS_UART_CTL) & 0xffef, MANTIS_UART_CTL);
flush_work(&mantis->uart_work);
}
diff --git a/drivers/media/pci/mantis/mantis_vp1034.c b/drivers/media/pci/mantis/mantis_vp1034.c
index 7c1bd167225c..3b1928594b12 100644
--- a/drivers/media/pci/mantis/mantis_vp1034.c
+++ b/drivers/media/pci/mantis/mantis_vp1034.c
@@ -44,7 +44,7 @@ static struct mb86a16_config vp1034_mb86a16_config = {
#define MANTIS_MODEL_NAME "VP-1034"
#define MANTIS_DEV_TYPE "DVB-S/DSS"
-int vp1034_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+int vp1034_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage)
{
struct mantis_pci *mantis = fe->dvb->priv;
diff --git a/drivers/media/pci/mantis/mantis_vp1034.h b/drivers/media/pci/mantis/mantis_vp1034.h
index 323f38ef8e3d..764b1c66ea1b 100644
--- a/drivers/media/pci/mantis/mantis_vp1034.h
+++ b/drivers/media/pci/mantis/mantis_vp1034.h
@@ -28,6 +28,7 @@
#define MANTIS_VP_1034_DVB_S 0x0014
extern struct mantis_hwconfig vp1034_config;
-extern int vp1034_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
+extern int vp1034_set_voltage(struct dvb_frontend *fe,
+ enum fe_sec_voltage voltage);
#endif /* __MANTIS_VP1034_H */
diff --git a/drivers/media/pci/ngene/ngene-core.c b/drivers/media/pci/ngene/ngene-core.c
index e29bc3af4baf..1b92d836a564 100644
--- a/drivers/media/pci/ngene/ngene-core.c
+++ b/drivers/media/pci/ngene/ngene-core.c
@@ -1526,10 +1526,12 @@ static int init_channel(struct ngene_channel *chan)
if (chan->fe2) {
if (dvb_register_frontend(adapter, chan->fe2) < 0)
goto err;
- chan->fe2->tuner_priv = chan->fe->tuner_priv;
- memcpy(&chan->fe2->ops.tuner_ops,
- &chan->fe->ops.tuner_ops,
- sizeof(struct dvb_tuner_ops));
+ if (chan->fe) {
+ chan->fe2->tuner_priv = chan->fe->tuner_priv;
+ memcpy(&chan->fe2->ops.tuner_ops,
+ &chan->fe->ops.tuner_ops,
+ sizeof(struct dvb_tuner_ops));
+ }
}
if (chan->has_demux) {
diff --git a/drivers/media/pci/ngene/ngene.h b/drivers/media/pci/ngene/ngene.h
index 51e2fbd18b1b..fa30930d7047 100644
--- a/drivers/media/pci/ngene/ngene.h
+++ b/drivers/media/pci/ngene/ngene.h
@@ -682,7 +682,7 @@ struct ngene_channel {
int AudioDTOUpdated;
u32 AudioDTOValue;
- int (*set_tone)(struct dvb_frontend *, fe_sec_tone_mode_t);
+ int (*set_tone)(struct dvb_frontend *, enum fe_sec_tone_mode);
u8 lnbh;
/* stuff from analog driver */
diff --git a/drivers/media/pci/pt1/pt1.c b/drivers/media/pci/pt1/pt1.c
index acc35b42e53c..e7e4428109c3 100644
--- a/drivers/media/pci/pt1/pt1.c
+++ b/drivers/media/pci/pt1/pt1.c
@@ -101,11 +101,11 @@ struct pt1_adapter {
struct dmxdev dmxdev;
struct dvb_frontend *fe;
int (*orig_set_voltage)(struct dvb_frontend *fe,
- fe_sec_voltage_t voltage);
+ enum fe_sec_voltage voltage);
int (*orig_sleep)(struct dvb_frontend *fe);
int (*orig_init)(struct dvb_frontend *fe);
- fe_sec_voltage_t voltage;
+ enum fe_sec_voltage voltage;
int sleep;
};
@@ -575,7 +575,7 @@ pt1_update_power(struct pt1 *pt1)
mutex_unlock(&pt1->lock);
}
-static int pt1_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+static int pt1_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage)
{
struct pt1_adapter *adap;
diff --git a/drivers/media/pci/pt1/va1j5jf8007s.c b/drivers/media/pci/pt1/va1j5jf8007s.c
index 1b637b74ef58..d0e70dc0e16f 100644
--- a/drivers/media/pci/pt1/va1j5jf8007s.c
+++ b/drivers/media/pci/pt1/va1j5jf8007s.c
@@ -108,7 +108,7 @@ static int va1j5jf8007s_get_frontend_algo(struct dvb_frontend *fe)
}
static int
-va1j5jf8007s_read_status(struct dvb_frontend *fe, fe_status_t *status)
+va1j5jf8007s_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct va1j5jf8007s_state *state;
@@ -387,7 +387,7 @@ static int
va1j5jf8007s_tune(struct dvb_frontend *fe,
bool re_tune,
unsigned int mode_flags, unsigned int *delay,
- fe_status_t *status)
+ enum fe_status *status)
{
struct va1j5jf8007s_state *state;
int ret;
diff --git a/drivers/media/pci/pt1/va1j5jf8007t.c b/drivers/media/pci/pt1/va1j5jf8007t.c
index 2db15159d514..0268f20b8097 100644
--- a/drivers/media/pci/pt1/va1j5jf8007t.c
+++ b/drivers/media/pci/pt1/va1j5jf8007t.c
@@ -98,7 +98,7 @@ static int va1j5jf8007t_get_frontend_algo(struct dvb_frontend *fe)
}
static int
-va1j5jf8007t_read_status(struct dvb_frontend *fe, fe_status_t *status)
+va1j5jf8007t_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
struct va1j5jf8007t_state *state;
@@ -266,7 +266,7 @@ static int
va1j5jf8007t_tune(struct dvb_frontend *fe,
bool re_tune,
unsigned int mode_flags, unsigned int *delay,
- fe_status_t *status)
+ enum fe_status *status)
{
struct va1j5jf8007t_state *state;
int ret;
diff --git a/drivers/media/pci/pt3/pt3.c b/drivers/media/pci/pt3/pt3.c
index 7a37e8fe2ee2..0d2e2b217121 100644
--- a/drivers/media/pci/pt3/pt3.c
+++ b/drivers/media/pci/pt3/pt3.c
@@ -188,7 +188,7 @@ static int pt3_set_lna(struct dvb_frontend *fe)
return ret;
}
-static int pt3_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt)
+static int pt3_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage volt)
{
struct pt3_adapter *adap;
struct pt3_board *pt3;
diff --git a/drivers/media/pci/saa7134/saa7134-alsa.c b/drivers/media/pci/saa7134/saa7134-alsa.c
index ac3cd74e824e..1d2c310ce838 100644
--- a/drivers/media/pci/saa7134/saa7134-alsa.c
+++ b/drivers/media/pci/saa7134/saa7134-alsa.c
@@ -16,6 +16,9 @@
*
*/
+#include "saa7134.h"
+#include "saa7134-reg.h"
+
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/time.h>
@@ -29,13 +32,6 @@
#include <linux/interrupt.h>
#include <linux/vmalloc.h>
-#include "saa7134.h"
-#include "saa7134-reg.h"
-
-static unsigned int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug,"enable debug messages [alsa]");
-
/*
* Configuration macros
*/
@@ -57,11 +53,6 @@ module_param_array(enable, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for SAA7134 capture interface(s).");
MODULE_PARM_DESC(enable, "Enable (or not) the SAA7134 capture interface(s).");
-#define dprintk(fmt, arg...) if (debug) \
- printk(KERN_DEBUG "%s/alsa: " fmt, dev->name , ##arg)
-
-
-
/*
* Main chip structure
*/
@@ -149,11 +140,11 @@ static void saa7134_irq_alsa_done(struct saa7134_dev *dev,
spin_lock(&dev->slock);
if (UNSET == dev->dmasound.dma_blk) {
- dprintk("irq: recording stopped\n");
+ pr_debug("irq: recording stopped\n");
goto done;
}
if (0 != (status & 0x0f000000))
- dprintk("irq: lost %ld\n", (status >> 24) & 0x0f);
+ pr_debug("irq: lost %ld\n", (status >> 24) & 0x0f);
if (0 == (status & 0x10000000)) {
/* odd */
if (0 == (dev->dmasound.dma_blk & 0x01))
@@ -164,13 +155,14 @@ static void saa7134_irq_alsa_done(struct saa7134_dev *dev,
reg = SAA7134_RS_BA2(6);
}
if (0 == reg) {
- dprintk("irq: field oops [%s]\n",
+ pr_debug("irq: field oops [%s]\n",
(status & 0x10000000) ? "even" : "odd");
goto done;
}
if (dev->dmasound.read_count >= dev->dmasound.blksize * (dev->dmasound.blocks-2)) {
- dprintk("irq: overrun [full=%d/%d] - Blocks in %d\n",dev->dmasound.read_count,
+ pr_debug("irq: overrun [full=%d/%d] - Blocks in %d\n",
+ dev->dmasound.read_count,
dev->dmasound.bufsize, dev->dmasound.blocks);
spin_unlock(&dev->slock);
snd_pcm_stop_xrun(dev->dmasound.substream);
@@ -180,10 +172,10 @@ static void saa7134_irq_alsa_done(struct saa7134_dev *dev,
/* next block addr */
next_blk = (dev->dmasound.dma_blk + 2) % dev->dmasound.blocks;
saa_writel(reg,next_blk * dev->dmasound.blksize);
- if (debug > 2)
- dprintk("irq: ok, %s, next_blk=%d, addr=%x, blocks=%u, size=%u, read=%u\n",
- (status & 0x10000000) ? "even" : "odd ", next_blk,
- next_blk * dev->dmasound.blksize, dev->dmasound.blocks, dev->dmasound.blksize, dev->dmasound.read_count);
+ pr_debug("irq: ok, %s, next_blk=%d, addr=%x, blocks=%u, size=%u, read=%u\n",
+ (status & 0x10000000) ? "even" : "odd ", next_blk,
+ next_blk * dev->dmasound.blksize, dev->dmasound.blocks,
+ dev->dmasound.blksize, dev->dmasound.read_count);
/* update status & wake waiting readers */
dev->dmasound.dma_blk = (dev->dmasound.dma_blk + 1) % dev->dmasound.blocks;
@@ -233,7 +225,7 @@ static irqreturn_t saa7134_alsa_irq(int irq, void *dev_id)
}
if (loop == 10) {
- dprintk("error! looping IRQ!");
+ pr_debug("error! looping IRQ!");
}
out:
@@ -281,11 +273,11 @@ static int saa7134_alsa_dma_init(struct saa7134_dev *dev, int nr_pages)
dma->vaddr = vmalloc_32(nr_pages << PAGE_SHIFT);
if (NULL == dma->vaddr) {
- dprintk("vmalloc_32(%d pages) failed\n", nr_pages);
+ pr_debug("vmalloc_32(%d pages) failed\n", nr_pages);
return -ENOMEM;
}
- dprintk("vmalloc is at addr 0x%08lx, size=%d\n",
+ pr_debug("vmalloc is at addr 0x%08lx, size=%d\n",
(unsigned long)dma->vaddr,
nr_pages << PAGE_SHIFT);
@@ -572,7 +564,7 @@ static int snd_card_saa7134_capture_prepare(struct snd_pcm_substream * substream
break;
}
- dprintk("rec_start: afmt=%d ch=%d => fmt=0x%x swap=%c\n",
+ pr_debug("rec_start: afmt=%d ch=%d => fmt=0x%x swap=%c\n",
runtime->format, runtime->channels, fmt,
bswap ? 'b' : '-');
/* dma: setup channel 6 (= AUDIO) */
@@ -821,7 +813,7 @@ static int snd_card_saa7134_capture_open(struct snd_pcm_substream * substream)
int amux, err;
if (!saa7134) {
- printk(KERN_ERR "BUG: saa7134 can't find device struct."
+ pr_err("BUG: saa7134 can't find device struct."
" Can't proceed with open\n");
return -ENODEV;
}
@@ -1175,7 +1167,7 @@ static int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum)
(void*) &dev->dmasound);
if (err < 0) {
- printk(KERN_ERR "%s: can't get IRQ %d for ALSA\n",
+ pr_err("%s: can't get IRQ %d for ALSA\n",
dev->name, dev->pci->irq);
goto __nodev;
}
@@ -1196,7 +1188,8 @@ static int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum)
sprintf(card->longname, "%s at 0x%lx irq %d",
chip->dev->name, chip->iobase, chip->irq);
- printk(KERN_INFO "%s/alsa: %s registered as card %d\n",dev->name,card->longname,index[devnum]);
+ pr_info("%s/alsa: %s registered as card %d\n",
+ dev->name, card->longname, index[devnum]);
if ((err = snd_card_register(card)) == 0) {
snd_saa7134_cards[devnum] = card;
@@ -1240,19 +1233,19 @@ static int saa7134_alsa_init(void)
saa7134_dmasound_init = alsa_device_init;
saa7134_dmasound_exit = alsa_device_exit;
- printk(KERN_INFO "saa7134 ALSA driver for DMA sound loaded\n");
+ pr_info("saa7134 ALSA driver for DMA sound loaded\n");
list_for_each(list,&saa7134_devlist) {
dev = list_entry(list, struct saa7134_dev, devlist);
if (dev->pci->device == PCI_DEVICE_ID_PHILIPS_SAA7130)
- printk(KERN_INFO "%s/alsa: %s doesn't support digital audio\n",
+ pr_info("%s/alsa: %s doesn't support digital audio\n",
dev->name, saa7134_boards[dev->board].name);
else
alsa_device_init(dev);
}
if (dev == NULL)
- printk(KERN_INFO "saa7134 ALSA: no saa7134 cards found\n");
+ pr_info("saa7134 ALSA: no saa7134 cards found\n");
return 0;
@@ -1272,7 +1265,7 @@ static void saa7134_alsa_exit(void)
saa7134_dmasound_init = NULL;
saa7134_dmasound_exit = NULL;
- printk(KERN_INFO "saa7134 ALSA driver for DMA sound unloaded\n");
+ pr_info("saa7134 ALSA driver for DMA sound unloaded\n");
return;
}
diff --git a/drivers/media/pci/saa7134/saa7134-cards.c b/drivers/media/pci/saa7134/saa7134-cards.c
index 3ca078057755..c7405766609c 100644
--- a/drivers/media/pci/saa7134/saa7134-cards.c
+++ b/drivers/media/pci/saa7134/saa7134-cards.c
@@ -20,13 +20,14 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include "saa7134.h"
+#include "saa7134-reg.h"
+
#include <linux/init.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
-#include "saa7134-reg.h"
-#include "saa7134.h"
#include "tuner-xc2028.h"
#include <media/v4l2-common.h>
#include <media/tveeprom.h>
@@ -5850,6 +5851,39 @@ struct saa7134_board saa7134_boards[] = {
.amux = LINE1,
} },
},
+ [SAA7134_BOARD_AVERMEDIA_505] = {
+ /* much like the "studio" version but without radio
+ * and another tuner (dbaryshkov@gmail.com) */
+ .name = "AverMedia AverTV/505",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_FQ1216ME,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tda9887_conf = TDA9887_PRESENT,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = LINE2,
+ .tv = 1,
+ }, {
+ .name = name_comp1,
+ .vmux = 0,
+ .amux = LINE2,
+ }, {
+ .name = name_comp2,
+ .vmux = 3,
+ .amux = LINE2,
+ }, {
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE2,
+ } },
+ .mute = {
+ .name = name_mute,
+ .amux = LINE1,
+ },
+ },
};
@@ -7109,6 +7143,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
.subdevice = 0x7007,
.driver_data = SAA7134_BOARD_WIS_VOYAGER,
}, {
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7130,
+ .subvendor = 0x1461, /* Avermedia Technologies Inc */
+ .subdevice = 0xa10a,
+ .driver_data = SAA7134_BOARD_AVERMEDIA_505,
+ }, {
/* --- boards without eeprom + subsystem ID --- */
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
@@ -7158,10 +7198,10 @@ MODULE_DEVICE_TABLE(pci, saa7134_pci_tbl);
static void board_flyvideo(struct saa7134_dev *dev)
{
- printk("%s: there are different flyvideo cards with different tuners\n"
- "%s: out there, you might have to use the tuner=<nr> insmod\n"
- "%s: option to override the default value.\n",
- dev->name, dev->name, dev->name);
+ pr_warn("%s: there are different flyvideo cards with different tuners\n"
+ "%s: out there, you might have to use the tuner=<nr> insmod\n"
+ "%s: option to override the default value.\n",
+ dev->name, dev->name, dev->name);
}
static int saa7134_xc2028_callback(struct saa7134_dev *dev,
@@ -7194,7 +7234,7 @@ static int saa7134_xc2028_callback(struct saa7134_dev *dev,
saa7134_set_gpio(dev, 20, 1);
break;
}
- return 0;
+ return 0;
}
return -EINVAL;
}
@@ -7380,7 +7420,7 @@ int saa7134_tuner_callback(void *priv, int component, int command, int arg)
return saa7134_xc5000_callback(dev, command, arg);
}
} else {
- printk(KERN_ERR "saa7134: Error - device struct undefined.\n");
+ pr_err("saa7134: Error - device struct undefined.\n");
return -EINVAL;
}
return -EINVAL;
@@ -7411,12 +7451,12 @@ static void hauppauge_eeprom(struct saa7134_dev *dev, u8 *eeprom_data)
case 67659: /* WinTV-HVR1110 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */
break;
default:
- printk(KERN_WARNING "%s: warning: "
+ pr_warn("%s: warning: "
"unknown hauppauge model #%d\n", dev->name, tv.model);
break;
}
- printk(KERN_INFO "%s: hauppauge eeprom: model=%d\n",
+ pr_info("%s: hauppauge eeprom: model=%d\n",
dev->name, tv.model);
}
@@ -7427,7 +7467,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
/* Always print gpio, often manufacturers encode tuner type and other info. */
saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0);
dev->gpio_value = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2);
- printk(KERN_INFO "%s: board init: gpio is %x\n", dev->name, dev->gpio_value);
+ pr_info("%s: board init: gpio is %x\n", dev->name, dev->gpio_value);
switch (dev->board) {
case SAA7134_BOARD_FLYVIDEO2000:
@@ -7448,8 +7488,9 @@ int saa7134_board_init1(struct saa7134_dev *dev)
case SAA7134_BOARD_KWORLD_VSTREAM_XPERT:
case SAA7134_BOARD_KWORLD_XPERT:
case SAA7134_BOARD_AVERMEDIA_STUDIO_305:
- case SAA7134_BOARD_AVERMEDIA_STUDIO_505:
case SAA7134_BOARD_AVERMEDIA_305:
+ case SAA7134_BOARD_AVERMEDIA_STUDIO_505:
+ case SAA7134_BOARD_AVERMEDIA_505:
case SAA7134_BOARD_AVERMEDIA_STUDIO_307:
case SAA7134_BOARD_AVERMEDIA_307:
case SAA7134_BOARD_AVERMEDIA_STUDIO_507:
@@ -7512,10 +7553,10 @@ int saa7134_board_init1(struct saa7134_dev *dev)
dev->has_remote = SAA7134_REMOTE_GPIO;
break;
case SAA7134_BOARD_MD5044:
- printk("%s: seems there are two different versions of the MD5044\n"
- "%s: (with the same ID) out there. If sound doesn't work for\n"
- "%s: you try the audio_clock_override=0x200000 insmod option.\n",
- dev->name,dev->name,dev->name);
+ pr_warn("%s: seems there are two different versions of the MD5044\n"
+ "%s: (with the same ID) out there. If sound doesn't work for\n"
+ "%s: you try the audio_clock_override=0x200000 insmod option.\n",
+ dev->name, dev->name, dev->name);
break;
case SAA7134_BOARD_CINERGY400_CARDBUS:
/* power-up tuner chip */
@@ -7640,10 +7681,10 @@ int saa7134_board_init1(struct saa7134_dev *dev)
dev->has_remote = SAA7134_REMOTE_I2C;
break;
case SAA7134_BOARD_AVERMEDIA_A169_B:
- printk("%s: %s: dual saa713x broadcast decoders\n"
- "%s: Sorry, none of the inputs to this chip are supported yet.\n"
- "%s: Dual decoder functionality is disabled for now, use the other chip.\n",
- dev->name,card(dev).name,dev->name,dev->name);
+ pr_warn("%s: %s: dual saa713x broadcast decoders\n"
+ "%s: Sorry, none of the inputs to this chip are supported yet.\n"
+ "%s: Dual decoder functionality is disabled for now, use the other chip.\n",
+ dev->name, card(dev).name, dev->name, dev->name);
break;
case SAA7134_BOARD_AVERMEDIA_M102:
/* enable tuner */
@@ -7789,7 +7830,7 @@ int saa7134_board_init2(struct saa7134_dev *dev)
if (board == dev->board)
break;
dev->board = board;
- printk("%s: board type fixup: %s\n", dev->name,
+ pr_warn("%s: board type fixup: %s\n", dev->name,
saa7134_boards[dev->board].name);
dev->tuner_type = saa7134_boards[dev->board].tuner_type;
@@ -7797,10 +7838,11 @@ int saa7134_board_init2(struct saa7134_dev *dev)
case SAA7134_BOARD_MD7134:
{
u8 subaddr;
- u8 data[3];
+ u8 data[3], data1[] = { 0x09, 0x9f, 0x86, 0x11};
int ret, tuner_t;
- struct i2c_msg msg[] = {{.addr=0x50, .flags=0, .buf=&subaddr, .len = 1},
- {.addr=0x50, .flags=I2C_M_RD, .buf=data, .len = 3}};
+ struct i2c_msg msg[] = {{.addr = 0x50, .flags = 0, .buf = &subaddr, .len = 1},
+ {.addr = 0x50, .flags = I2C_M_RD, .buf = data, .len = 3}},
+ msg1 = {.addr = 0x61, .flags = 0, .buf = data1, .len = sizeof(data1)};
subaddr= 0x14;
tuner_t = 0;
@@ -7810,7 +7852,7 @@ int saa7134_board_init2(struct saa7134_dev *dev)
*/
ret = i2c_transfer(&dev->i2c_adap, msg, 2);
if (ret != 2) {
- printk(KERN_ERR "EEPROM read failure\n");
+ pr_err("EEPROM read failure\n");
} else if ((data[0] != 0) && (data[0] != 0xff)) {
/* old config structure */
subaddr = data[0] + 2;
@@ -7825,7 +7867,8 @@ int saa7134_board_init2(struct saa7134_dev *dev)
dev->tuner_type = TUNER_PHILIPS_FM1216ME_MK3;
break;
default:
- printk(KERN_ERR "%s Can't determine tuner type %x from EEPROM\n", dev->name, tuner_t);
+ pr_err("%s Can't determine tuner type %x from EEPROM\n",
+ dev->name, tuner_t);
}
} else if ((data[1] != 0) && (data[1] != 0xff)) {
/* new config structure */
@@ -7842,16 +7885,28 @@ int saa7134_board_init2(struct saa7134_dev *dev)
break;
case 0x001d:
dev->tuner_type = TUNER_PHILIPS_FMD1216ME_MK3;
- printk(KERN_INFO "%s Board has DVB-T\n", dev->name);
+ pr_info("%s Board has DVB-T\n",
+ dev->name);
break;
default:
- printk(KERN_ERR "%s Can't determine tuner type %x from EEPROM\n", dev->name, tuner_t);
+ pr_err("%s Can't determine tuner type %x from EEPROM\n",
+ dev->name, tuner_t);
}
} else {
- printk(KERN_ERR "%s unexpected config structure\n", dev->name);
+ pr_err("%s unexpected config structure\n", dev->name);
}
- printk(KERN_INFO "%s Tuner type is %d\n", dev->name, dev->tuner_type);
+ pr_info("%s Tuner type is %d\n", dev->name, dev->tuner_type);
+
+ /* The tuner TUNER_PHILIPS_FMD1216ME_MK3 after hardware */
+ /* start has disabled IF and enabled DVB-T. When saa7134 */
+ /* scan I2C devices it will not detect IF tda9887 and can`t*/
+ /* watch TV without software reboot. To solve this problem */
+ /* switch the tuner to analog TV mode manually. */
+ if (dev->tuner_type == TUNER_PHILIPS_FMD1216ME_MK3) {
+ if (i2c_transfer(&dev->i2c_adap, &msg1, 1) != 1)
+ printk(KERN_WARNING "%s: Unable to enable IF of the tuner.\n", dev->name);
+ }
break;
}
case SAA7134_BOARD_PHILIPS_EUROPA:
@@ -7859,7 +7914,7 @@ int saa7134_board_init2(struct saa7134_dev *dev)
/* Reconfigure board as Snake reference design */
dev->board = SAA7134_BOARD_PHILIPS_SNAKE;
dev->tuner_type = saa7134_boards[dev->board].tuner_type;
- printk(KERN_INFO "%s: Reconfigured board as %s\n",
+ pr_info("%s: Reconfigured board as %s\n",
dev->name, saa7134_boards[dev->board].name);
break;
}
@@ -7887,7 +7942,7 @@ int saa7134_board_init2(struct saa7134_dev *dev)
struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
if (dev->autodetected && (dev->eedata[0x49] == 0x50)) {
dev->board = SAA7134_BOARD_PHILIPS_TIGER_S;
- printk(KERN_INFO "%s: Reconfigured board as %s\n",
+ pr_info("%s: Reconfigured board as %s\n",
dev->name, saa7134_boards[dev->board].name);
}
if (dev->board == SAA7134_BOARD_PHILIPS_TIGER_S) {
@@ -7903,13 +7958,14 @@ int saa7134_board_init2(struct saa7134_dev *dev)
case SAA7134_BOARD_ASUSTeK_TVFM7135:
/* The card below is detected as card=53, but is different */
if (dev->autodetected && (dev->eedata[0x27] == 0x03)) {
- dev->board = SAA7134_BOARD_ASUSTeK_P7131_ANALOG;
- printk(KERN_INFO "%s: P7131 analog only, using "
- "entry of %s\n",
- dev->name, saa7134_boards[dev->board].name);
+ dev->board = SAA7134_BOARD_ASUSTeK_P7131_ANALOG;
+ pr_info("%s: P7131 analog only, using entry of %s\n",
+ dev->name, saa7134_boards[dev->board].name);
- /* IR init has already happened for other cards, so
- * we have to catch up. */
+ /*
+ * IR init has already happened for other cards, so
+ * we have to catch up.
+ */
dev->has_remote = SAA7134_REMOTE_GPIO;
saa7134_input_init1(dev);
}
@@ -7972,12 +8028,12 @@ int saa7134_board_init2(struct saa7134_dev *dev)
msg.addr = 0x0b;
msg.len = 1;
if (1 != i2c_transfer(&dev->i2c_adap, &msg, 1)) {
- printk(KERN_WARNING "%s: send wake up byte to pic16C505"
+ pr_warn("%s: send wake up byte to pic16C505"
"(IR chip) failed\n", dev->name);
} else {
msg.flags = I2C_M_RD;
rc = i2c_transfer(&dev->i2c_adap, &msg, 1);
- printk(KERN_INFO "%s: probe IR chip @ i2c 0x%02x: %s\n",
+ pr_info("%s: probe IR chip @ i2c 0x%02x: %s\n",
dev->name, msg.addr,
(1 == rc) ? "yes" : "no");
if (rc == 1)
@@ -8018,10 +8074,10 @@ int saa7134_board_init2(struct saa7134_dev *dev)
dev->board = SAA7134_BOARD_VIDEOMATE_DVBT_200A;
dev->tuner_type = saa7134_boards[dev->board].tuner_type;
dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf;
- printk(KERN_INFO "%s: Reconfigured board as %s\n",
+ pr_info("%s: Reconfigured board as %s\n",
dev->name, saa7134_boards[dev->board].name);
} else {
- printk(KERN_WARNING "%s: Unexpected tuner type info: %x in eeprom\n",
+ pr_warn("%s: Unexpected tuner type info: %x in eeprom\n",
dev->name, dev->eedata[0x41]);
break;
}
@@ -8043,9 +8099,8 @@ int saa7134_board_init2(struct saa7134_dev *dev)
msg.buf = &buffer[i][0];
msg.len = ARRAY_SIZE(buffer[0]);
if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1)
- printk(KERN_WARNING
- "%s: Unable to enable tuner(%i).\n",
- dev->name, i);
+ pr_warn("%s: Unable to enable tuner(%i).\n",
+ dev->name, i);
}
break;
}
@@ -8061,9 +8116,8 @@ int saa7134_board_init2(struct saa7134_dev *dev)
/* watch TV without software reboot. For solve this problem */
/* switch the tuner to analog TV mode manually. */
if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1)
- printk(KERN_WARNING
- "%s: Unable to enable IF of the tuner.\n",
- dev->name);
+ pr_warn("%s: Unable to enable IF of the tuner.\n",
+ dev->name);
break;
}
case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG:
diff --git a/drivers/media/pci/saa7134/saa7134-core.c b/drivers/media/pci/saa7134/saa7134-core.c
index a349e964e0bc..72d7f992375e 100644
--- a/drivers/media/pci/saa7134/saa7134-core.c
+++ b/drivers/media/pci/saa7134/saa7134-core.c
@@ -20,6 +20,9 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include "saa7134.h"
+#include "saa7134-reg.h"
+
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
@@ -33,9 +36,6 @@
#include <linux/dma-mapping.h>
#include <linux/pm.h>
-#include "saa7134-reg.h"
-#include "saa7134.h"
-
MODULE_DESCRIPTION("v4l2 driver module for saa7130/34 based TV cards");
MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
MODULE_LICENSE("GPL");
@@ -102,8 +102,15 @@ static unsigned int saa7134_devcount;
int (*saa7134_dmasound_init)(struct saa7134_dev *dev);
int (*saa7134_dmasound_exit)(struct saa7134_dev *dev);
-#define dprintk(fmt, arg...) if (core_debug) \
- printk(KERN_DEBUG "%s/core: " fmt, dev->name , ## arg)
+#define core_dbg(fmt, arg...) do { \
+ if (core_debug) \
+ printk(KERN_DEBUG pr_fmt("core: " fmt), ## arg); \
+ } while (0)
+
+#define irq_dbg(level, fmt, arg...) do {\
+ if (irq_debug > level) \
+ printk(KERN_DEBUG pr_fmt("irq: " fmt), ## arg); \
+ } while (0)
void saa7134_track_gpio(struct saa7134_dev *dev, char *msg)
{
@@ -116,8 +123,7 @@ void saa7134_track_gpio(struct saa7134_dev *dev, char *msg)
saa_andorb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN,SAA7134_GPIO_GPRESCAN);
mode = saa_readl(SAA7134_GPIO_GPMODE0 >> 2) & 0xfffffff;
status = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & 0xfffffff;
- printk(KERN_DEBUG
- "%s: gpio: mode=0x%07lx in=0x%07lx out=0x%07lx [%s]\n",
+ core_dbg("%s: gpio: mode=0x%07lx in=0x%07lx out=0x%07lx [%s]\n",
dev->name, mode, (~mode) & status, mode & status, msg);
}
@@ -128,7 +134,8 @@ void saa7134_set_gpio(struct saa7134_dev *dev, int bit_no, int value)
index = 1 << bit_no;
switch (value) {
case 0: /* static value */
- case 1: dprintk("setting GPIO%d to static %d\n", bit_no, value);
+ case 1:
+ core_dbg("setting GPIO%d to static %d\n", bit_no, value);
/* turn sync mode off if necessary */
if (index & 0x00c00000)
saa_andorb(SAA7134_VIDEO_PORT_CTRL6, 0x0f, 0x00);
@@ -140,7 +147,7 @@ void saa7134_set_gpio(struct saa7134_dev *dev, int bit_no, int value)
saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, index, bitval);
break;
case 3: /* tristate */
- dprintk("setting GPIO%d to tristate\n", bit_no);
+ core_dbg("setting GPIO%d to tristate\n", bit_no);
saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, index, 0);
break;
}
@@ -274,7 +281,7 @@ int saa7134_buffer_queue(struct saa7134_dev *dev,
unsigned long flags;
spin_lock_irqsave(&dev->slock, flags);
- dprintk("buffer_queue %p\n", buf);
+ core_dbg("buffer_queue %p\n", buf);
if (NULL == q->curr) {
if (!q->need_two) {
q->curr = buf;
@@ -298,7 +305,7 @@ void saa7134_buffer_finish(struct saa7134_dev *dev,
struct saa7134_dmaqueue *q,
unsigned int state)
{
- dprintk("buffer_finish %p\n", q->curr);
+ core_dbg("buffer_finish %p\n", q->curr);
/* finish current buffer */
v4l2_get_timestamp(&q->curr->vb2.v4l2_buf.timestamp);
@@ -318,18 +325,18 @@ void saa7134_buffer_next(struct saa7134_dev *dev,
if (!list_empty(&q->queue)) {
/* activate next one from queue */
buf = list_entry(q->queue.next, struct saa7134_buf, entry);
- dprintk("buffer_next %p [prev=%p/next=%p]\n",
+ core_dbg("buffer_next %p [prev=%p/next=%p]\n",
buf, q->queue.prev, q->queue.next);
list_del(&buf->entry);
if (!list_empty(&q->queue))
next = list_entry(q->queue.next, struct saa7134_buf, entry);
q->curr = buf;
buf->activate(dev, buf, next);
- dprintk("buffer_next #2 prev=%p/next=%p\n",
+ core_dbg("buffer_next #2 prev=%p/next=%p\n",
q->queue.prev, q->queue.next);
} else {
/* nothing to do -- just stop DMA */
- dprintk("buffer_next %p\n", NULL);
+ core_dbg("buffer_next %p\n", NULL);
saa7134_set_dmabits(dev);
del_timer(&q->timeout);
}
@@ -351,7 +358,7 @@ void saa7134_buffer_timeout(unsigned long data)
/* flag current buffer as failed,
try to start over with the next one. */
if (q->curr) {
- dprintk("timeout on %p\n", q->curr);
+ core_dbg("timeout on %p\n", q->curr);
saa7134_buffer_finish(dev, q, VB2_BUF_STATE_ERROR);
}
saa7134_buffer_next(dev, q);
@@ -474,7 +481,7 @@ int saa7134_set_dmabits(struct saa7134_dev *dev)
SAA7134_MAIN_CTRL_TE5 |
SAA7134_MAIN_CTRL_TE6,
ctrl);
- dprintk("dmabits: task=0x%02x ctrl=0x%02x irq=0x%x split=%s\n",
+ core_dbg("dmabits: task=0x%02x ctrl=0x%02x irq=0x%x split=%s\n",
task, ctrl, irq, split ? "no" : "yes");
return 0;
@@ -496,21 +503,21 @@ static void print_irqstatus(struct saa7134_dev *dev, int loop,
{
unsigned int i;
- printk(KERN_DEBUG "%s/irq[%d,%ld]: r=0x%lx s=0x%02lx",
- dev->name,loop,jiffies,report,status);
+ irq_dbg(1, "[%d,%ld]: r=0x%lx s=0x%02lx",
+ loop, jiffies, report, status);
for (i = 0; i < IRQBITS; i++) {
if (!(report & (1 << i)))
continue;
- printk(" %s",irqbits[i]);
+ pr_cont(" %s", irqbits[i]);
}
if (report & SAA7134_IRQ_REPORT_DONE_RA0) {
- printk(" | RA0=%s,%s,%s,%ld",
- (status & 0x40) ? "vbi" : "video",
- (status & 0x20) ? "b" : "a",
- (status & 0x10) ? "odd" : "even",
- (status & 0x0f));
+ pr_cont(" | RA0=%s,%s,%s,%ld",
+ (status & 0x40) ? "vbi" : "video",
+ (status & 0x20) ? "b" : "a",
+ (status & 0x10) ? "odd" : "even",
+ (status & 0x0f));
}
- printk("\n");
+ pr_cont("\n");
}
static irqreturn_t saa7134_irq(int irq, void *dev_id)
@@ -532,16 +539,12 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id)
if ((report & SAA7134_IRQ_REPORT_DONE_RA3) &&
(dev->dmasound.priv_data != NULL) )
{
- if (irq_debug > 1)
- printk(KERN_DEBUG "%s/irq: preserving DMA sound interrupt\n",
- dev->name);
+ irq_dbg(2, "preserving DMA sound interrupt\n");
report &= ~SAA7134_IRQ_REPORT_DONE_RA3;
}
if (0 == report) {
- if (irq_debug > 1)
- printk(KERN_DEBUG "%s/irq: no (more) work\n",
- dev->name);
+ irq_dbg(2, "no (more) work\n");
goto out;
}
@@ -614,24 +617,24 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id)
print_irqstatus(dev,loop,report,status);
if (report & SAA7134_IRQ_REPORT_PE) {
/* disable all parity error */
- printk(KERN_WARNING "%s/irq: looping -- "
+ pr_warn("%s/irq: looping -- "
"clearing PE (parity error!) enable bit\n",dev->name);
saa_clearl(SAA7134_IRQ2,SAA7134_IRQ2_INTE_PE);
} else if (report & SAA7134_IRQ_REPORT_GPIO16) {
/* disable gpio16 IRQ */
- printk(KERN_WARNING "%s/irq: looping -- "
+ pr_warn("%s/irq: looping -- "
"clearing GPIO16 enable bit\n",dev->name);
saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO16_P);
saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO16_N);
} else if (report & SAA7134_IRQ_REPORT_GPIO18) {
/* disable gpio18 IRQs */
- printk(KERN_WARNING "%s/irq: looping -- "
+ pr_warn("%s/irq: looping -- "
"clearing GPIO18 enable bit\n",dev->name);
saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18_P);
saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18_N);
} else {
/* disable all irqs */
- printk(KERN_WARNING "%s/irq: looping -- "
+ pr_warn("%s/irq: looping -- "
"clearing all enable bits\n",dev->name);
saa_writel(SAA7134_IRQ1,0);
saa_writel(SAA7134_IRQ2,0);
@@ -680,7 +683,7 @@ static int saa7134_hw_enable1(struct saa7134_dev *dev)
static int saa7134_hwinit1(struct saa7134_dev *dev)
{
- dprintk("hwinit1\n");
+ core_dbg("hwinit1\n");
saa_writel(SAA7134_IRQ1, 0);
saa_writel(SAA7134_IRQ2, 0);
@@ -742,7 +745,7 @@ static int saa7134_hw_enable2(struct saa7134_dev *dev)
static int saa7134_hwinit2(struct saa7134_dev *dev)
{
- dprintk("hwinit2\n");
+ core_dbg("hwinit2\n");
saa7134_video_init2(dev);
saa7134_tvaudio_init2(dev);
@@ -756,7 +759,7 @@ static int saa7134_hwinit2(struct saa7134_dev *dev)
/* shutdown */
static int saa7134_hwfini(struct saa7134_dev *dev)
{
- dprintk("hwfini\n");
+ core_dbg("hwfini\n");
if (card_has_mpeg(dev))
saa7134_ts_fini(dev);
@@ -772,34 +775,32 @@ static void must_configure_manually(int has_eeprom)
unsigned int i,p;
if (!has_eeprom)
- printk(KERN_WARNING
- "saa7134: <rant>\n"
- "saa7134: Congratulations! Your TV card vendor saved a few\n"
- "saa7134: cents for a eeprom, thus your pci board has no\n"
- "saa7134: subsystem ID and I can't identify it automatically\n"
- "saa7134: </rant>\n"
- "saa7134: I feel better now. Ok, here are the good news:\n"
- "saa7134: You can use the card=<nr> insmod option to specify\n"
- "saa7134: which board do you have. The list:\n");
+ pr_warn("saa7134: <rant>\n"
+ "saa7134: Congratulations! Your TV card vendor saved a few\n"
+ "saa7134: cents for a eeprom, thus your pci board has no\n"
+ "saa7134: subsystem ID and I can't identify it automatically\n"
+ "saa7134: </rant>\n"
+ "saa7134: I feel better now. Ok, here are the good news:\n"
+ "saa7134: You can use the card=<nr> insmod option to specify\n"
+ "saa7134: which board do you have. The list:\n");
else
- printk(KERN_WARNING
- "saa7134: Board is currently unknown. You might try to use the card=<nr>\n"
- "saa7134: insmod option to specify which board do you have, but this is\n"
- "saa7134: somewhat risky, as might damage your card. It is better to ask\n"
- "saa7134: for support at linux-media@vger.kernel.org.\n"
- "saa7134: The supported cards are:\n");
+ pr_warn("saa7134: Board is currently unknown. You might try to use the card=<nr>\n"
+ "saa7134: insmod option to specify which board do you have, but this is\n"
+ "saa7134: somewhat risky, as might damage your card. It is better to ask\n"
+ "saa7134: for support at linux-media@vger.kernel.org.\n"
+ "saa7134: The supported cards are:\n");
for (i = 0; i < saa7134_bcount; i++) {
- printk(KERN_WARNING "saa7134: card=%d -> %-40.40s",
+ pr_warn("saa7134: card=%d -> %-40.40s",
i,saa7134_boards[i].name);
for (p = 0; saa7134_pci_tbl[p].driver_data; p++) {
if (saa7134_pci_tbl[p].driver_data != i)
continue;
- printk(" %04x:%04x",
+ pr_cont(" %04x:%04x",
saa7134_pci_tbl[p].subvendor,
saa7134_pci_tbl[p].subdevice);
}
- printk("\n");
+ pr_cont("\n");
}
}
@@ -903,31 +904,31 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
/* pci quirks */
if (pci_pci_problems) {
if (pci_pci_problems & PCIPCI_TRITON)
- printk(KERN_INFO "%s: quirk: PCIPCI_TRITON\n", dev->name);
+ pr_info("%s: quirk: PCIPCI_TRITON\n", dev->name);
if (pci_pci_problems & PCIPCI_NATOMA)
- printk(KERN_INFO "%s: quirk: PCIPCI_NATOMA\n", dev->name);
+ pr_info("%s: quirk: PCIPCI_NATOMA\n", dev->name);
if (pci_pci_problems & PCIPCI_VIAETBF)
- printk(KERN_INFO "%s: quirk: PCIPCI_VIAETBF\n", dev->name);
+ pr_info("%s: quirk: PCIPCI_VIAETBF\n", dev->name);
if (pci_pci_problems & PCIPCI_VSFX)
- printk(KERN_INFO "%s: quirk: PCIPCI_VSFX\n",dev->name);
+ pr_info("%s: quirk: PCIPCI_VSFX\n", dev->name);
#ifdef PCIPCI_ALIMAGIK
if (pci_pci_problems & PCIPCI_ALIMAGIK) {
- printk(KERN_INFO "%s: quirk: PCIPCI_ALIMAGIK -- latency fixup\n",
+ pr_info("%s: quirk: PCIPCI_ALIMAGIK -- latency fixup\n",
dev->name);
latency = 0x0A;
}
#endif
if (pci_pci_problems & (PCIPCI_FAIL|PCIAGP_FAIL)) {
- printk(KERN_INFO "%s: quirk: this driver and your "
+ pr_info("%s: quirk: this driver and your "
"chipset may not work together"
" in overlay mode.\n",dev->name);
if (!saa7134_no_overlay) {
- printk(KERN_INFO "%s: quirk: overlay "
+ pr_info("%s: quirk: overlay "
"mode will be disabled.\n",
dev->name);
saa7134_no_overlay = 1;
} else {
- printk(KERN_INFO "%s: quirk: overlay "
+ pr_info("%s: quirk: overlay "
"mode will be forced. Use this"
" option at your own risk.\n",
dev->name);
@@ -935,7 +936,7 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
}
}
if (UNSET != latency) {
- printk(KERN_INFO "%s: setting pci latency timer to %d\n",
+ pr_info("%s: setting pci latency timer to %d\n",
dev->name,latency);
pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, latency);
}
@@ -943,13 +944,13 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
/* print pci info */
dev->pci_rev = pci_dev->revision;
pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat);
- printk(KERN_INFO "%s: found at %s, rev: %d, irq: %d, "
+ pr_info("%s: found at %s, rev: %d, irq: %d, "
"latency: %d, mmio: 0x%llx\n", dev->name,
pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
dev->pci_lat,(unsigned long long)pci_resource_start(pci_dev,0));
pci_set_master(pci_dev);
if (!pci_dma_supported(pci_dev, DMA_BIT_MASK(32))) {
- printk("%s: Oops: no 32bit PCI DMA ???\n",dev->name);
+ pr_warn("%s: Oops: no 32bit PCI DMA ???\n", dev->name);
err = -EIO;
goto fail1;
}
@@ -972,7 +973,7 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf;
if (UNSET != tuner[dev->nr])
dev->tuner_type = tuner[dev->nr];
- printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
+ pr_info("%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
dev->name,pci_dev->subsystem_vendor,
pci_dev->subsystem_device,saa7134_boards[dev->board].name,
dev->board, dev->autodetected ?
@@ -983,7 +984,7 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
pci_resource_len(pci_dev,0),
dev->name)) {
err = -EBUSY;
- printk(KERN_ERR "%s: can't get MMIO memory @ 0x%llx\n",
+ pr_err("%s: can't get MMIO memory @ 0x%llx\n",
dev->name,(unsigned long long)pci_resource_start(pci_dev,0));
goto fail1;
}
@@ -992,7 +993,7 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
dev->bmmio = (__u8 __iomem *)dev->lmmio;
if (NULL == dev->lmmio) {
err = -EIO;
- printk(KERN_ERR "%s: can't ioremap() MMIO memory\n",
+ pr_err("%s: can't ioremap() MMIO memory\n",
dev->name);
goto fail2;
}
@@ -1010,7 +1011,7 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
err = request_irq(pci_dev->irq, saa7134_irq,
IRQF_SHARED, dev->name, dev);
if (err < 0) {
- printk(KERN_ERR "%s: can't get IRQ %d\n",
+ pr_err("%s: can't get IRQ %d\n",
dev->name,pci_dev->irq);
goto fail4;
}
@@ -1040,7 +1041,7 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
&dev->i2c_adap, "saa6588",
0, I2C_ADDRS(saa7134_boards[dev->board].rds_addr));
if (sd) {
- printk(KERN_INFO "%s: found RDS decoder\n", dev->name);
+ pr_info("%s: found RDS decoder\n", dev->name);
dev->has_rds = 1;
}
}
@@ -1059,7 +1060,7 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
/* register v4l devices */
if (saa7134_no_overlay > 0)
- printk(KERN_INFO "%s: Overlay support disabled.\n", dev->name);
+ pr_info("%s: Overlay support disabled.\n", dev->name);
dev->video_dev = vdev_init(dev,&saa7134_video_template,"video");
dev->video_dev->ctrl_handler = &dev->ctrl_handler;
@@ -1068,11 +1069,11 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER,
video_nr[dev->nr]);
if (err < 0) {
- printk(KERN_INFO "%s: can't register video device\n",
+ pr_info("%s: can't register video device\n",
dev->name);
goto fail5;
}
- printk(KERN_INFO "%s: registered device %s [v4l2]\n",
+ pr_info("%s: registered device %s [v4l2]\n",
dev->name, video_device_node_name(dev->video_dev));
dev->vbi_dev = vdev_init(dev, &saa7134_video_template, "vbi");
@@ -1084,7 +1085,7 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
vbi_nr[dev->nr]);
if (err < 0)
goto fail5;
- printk(KERN_INFO "%s: registered device %s\n",
+ pr_info("%s: registered device %s\n",
dev->name, video_device_node_name(dev->vbi_dev));
if (card_has_radio(dev)) {
@@ -1095,7 +1096,7 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
radio_nr[dev->nr]);
if (err < 0)
goto fail5;
- printk(KERN_INFO "%s: registered device %s\n",
+ pr_info("%s: registered device %s\n",
dev->name, video_device_node_name(dev->radio_dev));
}
@@ -1204,12 +1205,12 @@ static int saa7134_buffer_requeue(struct saa7134_dev *dev,
buf = q->curr;
next = buf;
- dprintk("buffer_requeue\n");
+ core_dbg("buffer_requeue\n");
if (!buf)
return 0;
- dprintk("buffer_requeue : resending active buffers \n");
+ core_dbg("buffer_requeue : resending active buffer\n");
if (!list_empty(&q->queue))
next = list_entry(q->queue.next, struct saa7134_buf,
@@ -1358,7 +1359,7 @@ static struct pci_driver saa7134_pci_driver = {
static int __init saa7134_init(void)
{
INIT_LIST_HEAD(&saa7134_devlist);
- printk(KERN_INFO "saa7130/34: v4l2 driver version %s loaded\n",
+ pr_info("saa7130/34: v4l2 driver version %s loaded\n",
SAA7134_VERSION);
return pci_register_driver(&saa7134_pci_driver);
}
diff --git a/drivers/media/pci/saa7134/saa7134-dvb.c b/drivers/media/pci/saa7134/saa7134-dvb.c
index 73ffbabf831c..101ba8729416 100644
--- a/drivers/media/pci/saa7134/saa7134-dvb.c
+++ b/drivers/media/pci/saa7134/saa7134-dvb.c
@@ -20,6 +20,9 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include "saa7134.h"
+#include "saa7134-reg.h"
+
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
@@ -28,8 +31,6 @@
#include <linux/kthread.h>
#include <linux/suspend.h>
-#include "saa7134-reg.h"
-#include "saa7134.h"
#include <media/v4l2-common.h>
#include "dvb-pll.h"
#include <dvb_frontend.h>
@@ -75,19 +76,8 @@ static int use_frontend;
module_param(use_frontend, int, 0644);
MODULE_PARM_DESC(use_frontend,"for cards with multiple frontends (0: terrestrial, 1: satellite)");
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off module debugging (default:off).");
-
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-#define dprintk(fmt, arg...) do { if (debug) \
- printk(KERN_DEBUG "%s/dvb: " fmt, dev->name , ## arg); } while(0)
-
-/* Print a warning */
-#define wprintk(fmt, arg...) \
- printk(KERN_WARNING "%s/dvb: " fmt, dev->name, ## arg)
-
/* ------------------------------------------------------------------
* mt352 based DVB-T cards
*/
@@ -112,7 +102,7 @@ static int pinnacle_antenna_pwr(struct saa7134_dev *dev, int on)
saa_setl(SAA7134_GPIO_GPSTATUS0 >> 2, (1 << 28));
udelay(10);
ok = saa_readl(SAA7134_GPIO_GPSTATUS0) & (1 << 27);
- dprintk("%s %s\n", __func__, ok ? "on" : "off");
+ pr_debug("%s %s\n", __func__, ok ? "on" : "off");
if (!ok)
saa_clearl(SAA7134_GPIO_GPSTATUS0 >> 2, (1 << 26));
@@ -130,9 +120,8 @@ static int mt352_pinnacle_init(struct dvb_frontend* fe)
static u8 gpp_ctl_cfg [] = { GPP_CTL, 0x0f };
static u8 scan_ctl_cfg [] = { SCAN_CTL, 0x0d };
static u8 irq_cfg [] = { INTERRUPT_EN_0, 0x00, 0x00, 0x00, 0x00 };
- struct saa7134_dev *dev= fe->dvb->priv;
- dprintk("%s called\n", __func__);
+ pr_debug("%s called\n", __func__);
mt352_write(fe, clock_config, sizeof(clock_config));
udelay(200);
@@ -258,7 +247,7 @@ static int kworld_sbtvd_gate_ctrl(struct dvb_frontend* fe, int enable)
struct i2c_msg msg = {.addr = 0x4b, .flags = 0, .buf = initmsg, .len = 2};
if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) {
- wprintk("could not access the I2C gate\n");
+ pr_warn("could not access the I2C gate\n");
return -EIO;
}
if (enable)
@@ -266,7 +255,7 @@ static int kworld_sbtvd_gate_ctrl(struct dvb_frontend* fe, int enable)
else
msg.buf = msg_disable;
if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) {
- wprintk("could not access the I2C gate\n");
+ pr_warn("could not access the I2C gate\n");
return -EIO;
}
msleep(20);
@@ -369,7 +358,7 @@ static int philips_tda6651_pll_set(struct dvb_frontend *fe)
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1) {
- wprintk("could not write to tuner at addr: 0x%02x\n",
+ pr_warn("could not write to tuner at addr: 0x%02x\n",
addr << 1);
return -EIO;
}
@@ -556,8 +545,7 @@ static int tda8290_i2c_gate_ctrl( struct dvb_frontend* fe, int enable)
tda8290_msg.buf = tda8290_open;
}
if (i2c_transfer(state->i2c, &tda8290_msg, 1) != 1) {
- struct saa7134_dev *dev = fe->dvb->priv;
- wprintk("could not access tda8290 I2C gate\n");
+ pr_warn("could not access tda8290 I2C gate\n");
return -EIO;
}
msleep(20);
@@ -570,11 +558,14 @@ static int philips_tda827x_tuner_init(struct dvb_frontend *fe)
struct tda1004x_state *state = fe->demodulator_priv;
switch (state->config->antenna_switch) {
- case 0: break;
- case 1: dprintk("setting GPIO21 to 0 (TV antenna?)\n");
+ case 0:
+ break;
+ case 1:
+ pr_debug("setting GPIO21 to 0 (TV antenna?)\n");
saa7134_set_gpio(dev, 21, 0);
break;
- case 2: dprintk("setting GPIO21 to 1 (Radio antenna?)\n");
+ case 2:
+ pr_debug("setting GPIO21 to 1 (Radio antenna?)\n");
saa7134_set_gpio(dev, 21, 1);
break;
}
@@ -587,11 +578,14 @@ static int philips_tda827x_tuner_sleep(struct dvb_frontend *fe)
struct tda1004x_state *state = fe->demodulator_priv;
switch (state->config->antenna_switch) {
- case 0: break;
- case 1: dprintk("setting GPIO21 to 1 (Radio antenna?)\n");
+ case 0:
+ break;
+ case 1:
+ pr_debug("setting GPIO21 to 1 (Radio antenna?)\n");
saa7134_set_gpio(dev, 21, 1);
break;
- case 2: dprintk("setting GPIO21 to 0 (TV antenna?)\n");
+ case 2:
+ pr_debug("setting GPIO21 to 0 (TV antenna?)\n");
saa7134_set_gpio(dev, 21, 0);
break;
}
@@ -619,7 +613,7 @@ static int configure_tda827x_fe(struct saa7134_dev *dev,
&dev->i2c_adap, tuner_conf))
return 0;
- wprintk("no tda827x tuner found at addr: %02x\n",
+ pr_warn("no tda827x tuner found at addr: %02x\n",
cdec_conf->tuner_address);
}
return -EINVAL;
@@ -993,7 +987,8 @@ static struct tda10086_config sd1878_4m = {
* special case: lnb supply is connected to the gated i2c
*/
-static int md8800_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+static int md8800_set_voltage(struct dvb_frontend *fe,
+ enum fe_sec_voltage voltage)
{
int res = -EIO;
struct saa7134_dev *dev = fe->dvb->priv;
@@ -1019,7 +1014,8 @@ static int md8800_set_high_voltage(struct dvb_frontend *fe, long arg)
return res;
};
-static int md8800_set_voltage2(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+static int md8800_set_voltage2(struct dvb_frontend *fe,
+ enum fe_sec_voltage voltage)
{
struct saa7134_dev *dev = fe->dvb->priv;
u8 wbuf[2] = { 0x1f, 00 };
@@ -1041,8 +1037,8 @@ static int md8800_set_voltage2(struct dvb_frontend *fe, fe_sec_voltage_t voltage
static int md8800_set_high_voltage2(struct dvb_frontend *fe, long arg)
{
- struct saa7134_dev *dev = fe->dvb->priv;
- wprintk("%s: sorry can't set high LNB supply voltage from here\n", __func__);
+ pr_warn("%s: sorry can't set high LNB supply voltage from here\n",
+ __func__);
return -EIO;
}
@@ -1222,10 +1218,10 @@ static int dvb_init(struct saa7134_dev *dev)
mutex_init(&dev->frontends.lock);
INIT_LIST_HEAD(&dev->frontends.felist);
- printk(KERN_INFO "%s() allocating 1 frontend\n", __func__);
+ pr_info("%s() allocating 1 frontend\n", __func__);
fe0 = vb2_dvb_alloc_frontend(&dev->frontends, 1);
if (!fe0) {
- printk(KERN_ERR "%s() failed to alloc\n", __func__);
+ pr_err("%s() failed to alloc\n", __func__);
return -ENOMEM;
}
@@ -1250,7 +1246,7 @@ static int dvb_init(struct saa7134_dev *dev)
switch (dev->board) {
case SAA7134_BOARD_PINNACLE_300I_DVBT_PAL:
- dprintk("pinnacle 300i dvb setup\n");
+ pr_debug("pinnacle 300i dvb setup\n");
fe0->dvb.frontend = dvb_attach(mt352_attach, &pinnacle_300i,
&dev->i2c_adap);
if (fe0->dvb.frontend) {
@@ -1259,7 +1255,7 @@ static int dvb_init(struct saa7134_dev *dev)
break;
case SAA7134_BOARD_AVERMEDIA_777:
case SAA7134_BOARD_AVERMEDIA_A16AR:
- dprintk("avertv 777 dvb setup\n");
+ pr_debug("avertv 777 dvb setup\n");
fe0->dvb.frontend = dvb_attach(mt352_attach, &avermedia_777,
&dev->i2c_adap);
if (fe0->dvb.frontend) {
@@ -1269,7 +1265,7 @@ static int dvb_init(struct saa7134_dev *dev)
}
break;
case SAA7134_BOARD_AVERMEDIA_A16D:
- dprintk("AverMedia A16D dvb setup\n");
+ pr_debug("AverMedia A16D dvb setup\n");
fe0->dvb.frontend = dvb_attach(mt352_attach,
&avermedia_xc3028_mt352_dev,
&dev->i2c_adap);
@@ -1401,13 +1397,15 @@ static int dvb_init(struct saa7134_dev *dev)
if (fe0->dvb.frontend) {
if (dvb_attach(tda826x_attach, fe0->dvb.frontend, 0x63,
&dev->i2c_adap, 0) == NULL) {
- wprintk("%s: Lifeview Trio, No tda826x found!\n", __func__);
+ pr_warn("%s: Lifeview Trio, No tda826x found!\n",
+ __func__);
goto detach_frontend;
}
if (dvb_attach(isl6421_attach, fe0->dvb.frontend,
&dev->i2c_adap,
0x08, 0, 0, false) == NULL) {
- wprintk("%s: Lifeview Trio, No ISL6421 found!\n", __func__);
+ pr_warn("%s: Lifeview Trio, No ISL6421 found!\n",
+ __func__);
goto detach_frontend;
}
}
@@ -1422,12 +1420,12 @@ static int dvb_init(struct saa7134_dev *dev)
if (dvb_attach(tda827x_attach,fe0->dvb.frontend,
ads_tech_duo_config.tuner_address, &dev->i2c_adap,
&ads_duo_cfg) == NULL) {
- wprintk("no tda827x tuner found at addr: %02x\n",
+ pr_warn("no tda827x tuner found at addr: %02x\n",
ads_tech_duo_config.tuner_address);
goto detach_frontend;
}
} else
- wprintk("failed to attach tda10046\n");
+ pr_warn("failed to attach tda10046\n");
break;
case SAA7134_BOARD_TEVION_DVBT_220RF:
if (configure_tda827x_fe(dev, &tevion_dvbt220rf_config,
@@ -1450,7 +1448,7 @@ static int dvb_init(struct saa7134_dev *dev)
if (dvb_attach(tda826x_attach, fe0->dvb.frontend,
0x60, &dev->i2c_adap, 0) == NULL) {
- wprintk("%s: Medion Quadro, no tda826x "
+ pr_warn("%s: Medion Quadro, no tda826x "
"found !\n", __func__);
goto detach_frontend;
}
@@ -1459,7 +1457,7 @@ static int dvb_init(struct saa7134_dev *dev)
fe->ops.i2c_gate_ctrl(fe, 1);
if (dvb_attach(isl6405_attach, fe,
&dev->i2c_adap, 0x08, 0, 0) == NULL) {
- wprintk("%s: Medion Quadro, no ISL6405 "
+ pr_warn("%s: Medion Quadro, no ISL6405 "
"found !\n", __func__);
goto detach_frontend;
}
@@ -1519,13 +1517,13 @@ static int dvb_init(struct saa7134_dev *dev)
if (fe0->dvb.frontend) {
if (dvb_attach(tda826x_attach, fe0->dvb.frontend, 0x60,
&dev->i2c_adap, 0) == NULL) {
- wprintk("%s: No tda826x found!\n", __func__);
+ pr_warn("%s: No tda826x found!\n", __func__);
goto detach_frontend;
}
if (dvb_attach(isl6421_attach, fe0->dvb.frontend,
&dev->i2c_adap,
0x08, 0, 0, false) == NULL) {
- wprintk("%s: No ISL6421 found!\n", __func__);
+ pr_warn("%s: No ISL6421 found!\n", __func__);
goto detach_frontend;
}
}
@@ -1593,12 +1591,12 @@ static int dvb_init(struct saa7134_dev *dev)
if (fe0->dvb.frontend) {
if (dvb_attach(tda826x_attach, fe0->dvb.frontend, 0x60,
&dev->i2c_adap, 0) == NULL) {
- wprintk("%s: No tda826x found!\n", __func__);
+ pr_warn("%s: No tda826x found!\n", __func__);
goto detach_frontend;
}
if (dvb_attach(lnbp21_attach, fe0->dvb.frontend,
&dev->i2c_adap, 0, 0) == NULL) {
- wprintk("%s: No lnbp21 found!\n", __func__);
+ pr_warn("%s: No lnbp21 found!\n", __func__);
goto detach_frontend;
}
}
@@ -1614,7 +1612,7 @@ static int dvb_init(struct saa7134_dev *dev)
goto detach_frontend;
break;
case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
- dprintk("AverMedia E506R dvb setup\n");
+ pr_debug("AverMedia E506R dvb setup\n");
saa7134_set_gpio(dev, 25, 0);
msleep(10);
saa7134_set_gpio(dev, 25, 1);
@@ -1630,7 +1628,7 @@ static int dvb_init(struct saa7134_dev *dev)
struct dvb_frontend *fe;
if (dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x60,
&dev->i2c_adap, DVB_PLL_PHILIPS_SD1878_TDA8261) == NULL) {
- wprintk("%s: MD7134 DVB-S, no SD1878 "
+ pr_warn("%s: MD7134 DVB-S, no SD1878 "
"found !\n", __func__);
goto detach_frontend;
}
@@ -1639,7 +1637,7 @@ static int dvb_init(struct saa7134_dev *dev)
fe->ops.i2c_gate_ctrl(fe, 1);
if (dvb_attach(isl6405_attach, fe,
&dev->i2c_adap, 0x08, 0, 0) == NULL) {
- wprintk("%s: MD7134 DVB-S, no ISL6405 "
+ pr_warn("%s: MD7134 DVB-S, no ISL6405 "
"found !\n", __func__);
goto detach_frontend;
}
@@ -1671,15 +1669,15 @@ static int dvb_init(struct saa7134_dev *dev)
if (dvb_attach(tda826x_attach,
fe0->dvb.frontend, 0x60,
&dev->i2c_adap, 0) == NULL) {
- wprintk("%s: Asus Tiger 3in1, no "
+ pr_warn("%s: Asus Tiger 3in1, no "
"tda826x found!\n", __func__);
goto detach_frontend;
}
if (dvb_attach(lnbp21_attach, fe0->dvb.frontend,
&dev->i2c_adap, 0, 0) == NULL) {
- wprintk("%s: Asus Tiger 3in1, no lnbp21"
+ pr_warn("%s: Asus Tiger 3in1, no lnbp21"
" found!\n", __func__);
- goto detach_frontend;
+ goto detach_frontend;
}
}
}
@@ -1696,13 +1694,13 @@ static int dvb_init(struct saa7134_dev *dev)
if (dvb_attach(tda826x_attach,
fe0->dvb.frontend, 0x60,
&dev->i2c_adap, 0) == NULL) {
- wprintk("%s: Asus My Cinema PS3-100, no "
+ pr_warn("%s: Asus My Cinema PS3-100, no "
"tda826x found!\n", __func__);
goto detach_frontend;
}
if (dvb_attach(lnbp21_attach, fe0->dvb.frontend,
&dev->i2c_adap, 0, 0) == NULL) {
- wprintk("%s: Asus My Cinema PS3-100, no lnbp21"
+ pr_warn("%s: Asus My Cinema PS3-100, no lnbp21"
" found!\n", __func__);
goto detach_frontend;
}
@@ -1750,7 +1748,7 @@ static int dvb_init(struct saa7134_dev *dev)
if (fe0->dvb.frontend) {
if (dvb_attach(zl10036_attach, fe0->dvb.frontend,
&avertv_a700_tuner, &dev->i2c_adap) == NULL) {
- wprintk("%s: No zl10036 found!\n",
+ pr_warn("%s: No zl10036 found!\n",
__func__);
}
}
@@ -1761,7 +1759,7 @@ static int dvb_init(struct saa7134_dev *dev)
if (fe0->dvb.frontend)
if (dvb_attach(zl10039_attach, fe0->dvb.frontend,
0x60, &dev->i2c_adap) == NULL)
- wprintk("%s: No zl10039 found!\n",
+ pr_warn("%s: No zl10039 found!\n",
__func__);
break;
@@ -1774,7 +1772,7 @@ static int dvb_init(struct saa7134_dev *dev)
fe0->dvb.frontend,
&dev->i2c_adap,
&videomate_t750_qt1010_config) == NULL)
- wprintk("error attaching QT1010\n");
+ pr_warn("error attaching QT1010\n");
}
break;
case SAA7134_BOARD_ZOLID_HYBRID_PCI:
@@ -1850,12 +1848,12 @@ static int dvb_init(struct saa7134_dev *dev)
fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
if (dvb_attach(zl10039_attach, fe0->dvb.frontend,
0x60, &dev->i2c_adap) == NULL)
- wprintk("%s: No zl10039 found!\n",
+ pr_warn("%s: No zl10039 found!\n",
__func__);
}
break;
default:
- wprintk("Huh? unknown DVB card?\n");
+ pr_warn("Huh? unknown DVB card?\n");
break;
}
@@ -1871,14 +1869,14 @@ static int dvb_init(struct saa7134_dev *dev)
fe = dvb_attach(xc2028_attach, fe0->dvb.frontend, &cfg);
if (!fe) {
- printk(KERN_ERR "%s/2: xc3028 attach failed\n",
+ pr_err("%s/2: xc3028 attach failed\n",
dev->name);
goto detach_frontend;
}
}
if (NULL == fe0->dvb.frontend) {
- printk(KERN_ERR "%s/dvb: frontend initialization failed\n", dev->name);
+ pr_err("%s/dvb: frontend initialization failed\n", dev->name);
goto detach_frontend;
}
/* define general-purpose callback pointer */
diff --git a/drivers/media/pci/saa7134/saa7134-empress.c b/drivers/media/pci/saa7134/saa7134-empress.c
index 594dc3ad4750..56b932c97196 100644
--- a/drivers/media/pci/saa7134/saa7134-empress.c
+++ b/drivers/media/pci/saa7134/saa7134-empress.c
@@ -17,6 +17,9 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include "saa7134.h"
+#include "saa7134-reg.h"
+
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
@@ -26,9 +29,6 @@
#include <media/v4l2-common.h>
#include <media/v4l2-event.h>
-#include "saa7134-reg.h"
-#include "saa7134.h"
-
/* ------------------------------------------------------------------ */
MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
@@ -39,13 +39,6 @@ static unsigned int empress_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
module_param_array(empress_nr, int, NULL, 0444);
MODULE_PARM_DESC(empress_nr,"ts device number");
-static unsigned int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug,"enable debug messages");
-
-#define dprintk(fmt, arg...) if (debug) \
- printk(KERN_DEBUG "%s/empress: " fmt, dev->name , ## arg)
-
/* ------------------------------------------------------------------ */
static int start_streaming(struct vb2_queue *vq, unsigned int count)
@@ -121,11 +114,14 @@ static int empress_g_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct saa7134_dev *dev = video_drvdata(file);
- struct v4l2_mbus_framefmt mbus_fmt;
+ struct v4l2_subdev_format fmt = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
+ struct v4l2_mbus_framefmt *mbus_fmt = &fmt.format;
- saa_call_all(dev, video, g_mbus_fmt, &mbus_fmt);
+ saa_call_all(dev, pad, get_fmt, NULL, &fmt);
- v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
+ v4l2_fill_pix_format(&f->fmt.pix, mbus_fmt);
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets;
f->fmt.pix.bytesperline = 0;
@@ -137,11 +133,13 @@ static int empress_s_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct saa7134_dev *dev = video_drvdata(file);
- struct v4l2_mbus_framefmt mbus_fmt;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
- v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, MEDIA_BUS_FMT_FIXED);
- saa_call_all(dev, video, s_mbus_fmt, &mbus_fmt);
- v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
+ v4l2_fill_mbus_format(&format.format, &f->fmt.pix, MEDIA_BUS_FMT_FIXED);
+ saa_call_all(dev, pad, set_fmt, NULL, &format);
+ v4l2_fill_pix_format(&f->fmt.pix, &format.format);
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets;
@@ -154,11 +152,14 @@ static int empress_try_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct saa7134_dev *dev = video_drvdata(file);
- struct v4l2_mbus_framefmt mbus_fmt;
+ struct v4l2_subdev_pad_config pad_cfg;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_TRY,
+ };
- v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, MEDIA_BUS_FMT_FIXED);
- saa_call_all(dev, video, try_mbus_fmt, &mbus_fmt);
- v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
+ v4l2_fill_mbus_format(&format.format, &f->fmt.pix, MEDIA_BUS_FMT_FIXED);
+ saa_call_all(dev, pad, set_fmt, &pad_cfg, &format);
+ v4l2_fill_pix_format(&f->fmt.pix, &format.format);
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets;
@@ -221,9 +222,9 @@ static void empress_signal_update(struct work_struct *work)
container_of(work, struct saa7134_dev, empress_workqueue);
if (dev->nosignal) {
- dprintk("no video signal\n");
+ pr_debug("no video signal\n");
} else {
- dprintk("video signal acquired\n");
+ pr_debug("video signal acquired\n");
}
}
@@ -255,7 +256,7 @@ static int empress_init(struct saa7134_dev *dev)
struct vb2_queue *q;
int err;
- dprintk("%s: %s\n",dev->name,__func__);
+ pr_debug("%s: %s\n", dev->name, __func__);
dev->empress_dev = video_device_alloc();
if (NULL == dev->empress_dev)
return -ENOMEM;
@@ -302,13 +303,13 @@ static int empress_init(struct saa7134_dev *dev)
err = video_register_device(dev->empress_dev,VFL_TYPE_GRABBER,
empress_nr[dev->nr]);
if (err < 0) {
- printk(KERN_INFO "%s: can't register video device\n",
+ pr_info("%s: can't register video device\n",
dev->name);
video_device_release(dev->empress_dev);
dev->empress_dev = NULL;
return err;
}
- printk(KERN_INFO "%s: registered device %s [mpeg]\n",
+ pr_info("%s: registered device %s [mpeg]\n",
dev->name, video_device_node_name(dev->empress_dev));
empress_signal_update(&dev->empress_workqueue);
@@ -317,7 +318,7 @@ static int empress_init(struct saa7134_dev *dev)
static int empress_fini(struct saa7134_dev *dev)
{
- dprintk("%s: %s\n",dev->name,__func__);
+ pr_debug("%s: %s\n", dev->name, __func__);
if (NULL == dev->empress_dev)
return 0;
diff --git a/drivers/media/pci/saa7134/saa7134-go7007.c b/drivers/media/pci/saa7134/saa7134-go7007.c
index 54e650b4dff1..8a2abb34186b 100644
--- a/drivers/media/pci/saa7134/saa7134-go7007.c
+++ b/drivers/media/pci/saa7134/saa7134-go7007.c
@@ -11,6 +11,9 @@
* GNU General Public License for more details.
*/
+#include "saa7134.h"
+#include "saa7134-reg.h"
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -27,8 +30,6 @@
#include <media/v4l2-device.h>
#include <media/v4l2-subdev.h>
-#include "saa7134.h"
-#include "saa7134-reg.h"
#include "go7007-priv.h"
/*#define GO7007_HPI_DEBUG*/
@@ -288,9 +289,9 @@ static int saa7134_go7007_stream_start(struct go7007 *go)
/* Set up transfer block size */
saa_writeb(SAA7134_TS_PARALLEL_SERIAL, 128 - 1);
- saa_writeb(SAA7134_TS_DMA0, (PAGE_SIZE >> 7) - 1);
- saa_writeb(SAA7134_TS_DMA1, 0);
- saa_writeb(SAA7134_TS_DMA2, 0);
+ saa_writeb(SAA7134_TS_DMA0, ((PAGE_SIZE >> 7) - 1) & 0xff);
+ saa_writeb(SAA7134_TS_DMA1, (PAGE_SIZE >> 15) & 0xff);
+ saa_writeb(SAA7134_TS_DMA2, (PAGE_SIZE >> 31) & 0x3f);
/* Enable video streaming mode */
saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_VIDEO);
diff --git a/drivers/media/pci/saa7134/saa7134-i2c.c b/drivers/media/pci/saa7134/saa7134-i2c.c
index f4da674e7f26..8ef6399d794f 100644
--- a/drivers/media/pci/saa7134/saa7134-i2c.c
+++ b/drivers/media/pci/saa7134/saa7134-i2c.c
@@ -20,14 +20,15 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include "saa7134.h"
+#include "saa7134-reg.h"
+
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/delay.h>
-#include "saa7134-reg.h"
-#include "saa7134.h"
#include <media/v4l2-common.h>
/* ----------------------------------------------------------- */
@@ -40,8 +41,15 @@ static unsigned int i2c_scan;
module_param(i2c_scan, int, 0444);
MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
-#define d1printk if (1 == i2c_debug) printk
-#define d2printk if (2 == i2c_debug) printk
+#define i2c_dbg(level, fmt, arg...) do { \
+ if (i2c_debug == level) \
+ printk(KERN_DEBUG pr_fmt("i2c: " fmt), ## arg); \
+ } while (0)
+
+#define i2c_cont(level, fmt, arg...) do { \
+ if (i2c_debug == level) \
+ pr_cont(fmt, ## arg); \
+ } while (0)
#define I2C_WAIT_DELAY 32
#define I2C_WAIT_RETRY 16
@@ -89,23 +97,20 @@ static inline enum i2c_status i2c_get_status(struct saa7134_dev *dev)
enum i2c_status status;
status = saa_readb(SAA7134_I2C_ATTR_STATUS) & 0x0f;
- d2printk(KERN_DEBUG "%s: i2c stat <= %s\n",dev->name,
- str_i2c_status[status]);
+ i2c_dbg(2, "i2c stat <= %s\n", str_i2c_status[status]);
return status;
}
static inline void i2c_set_status(struct saa7134_dev *dev,
enum i2c_status status)
{
- d2printk(KERN_DEBUG "%s: i2c stat => %s\n",dev->name,
- str_i2c_status[status]);
+ i2c_dbg(2, "i2c stat => %s\n", str_i2c_status[status]);
saa_andorb(SAA7134_I2C_ATTR_STATUS,0x0f,status);
}
static inline void i2c_set_attr(struct saa7134_dev *dev, enum i2c_attr attr)
{
- d2printk(KERN_DEBUG "%s: i2c attr => %s\n",dev->name,
- str_i2c_attr[attr]);
+ i2c_dbg(2, "i2c attr => %s\n", str_i2c_attr[attr]);
saa_andorb(SAA7134_I2C_ATTR_STATUS,0xc0,attr << 6);
}
@@ -168,7 +173,7 @@ static int i2c_reset(struct saa7134_dev *dev)
enum i2c_status status;
int count;
- d2printk(KERN_DEBUG "%s: i2c reset\n",dev->name);
+ i2c_dbg(2, "i2c reset\n");
status = i2c_get_status(dev);
if (!i2c_is_error(status))
return true;
@@ -206,7 +211,7 @@ static inline int i2c_send_byte(struct saa7134_dev *dev,
// dword |= 0x40 << 16; /* 400 kHz */
dword |= 0xf0 << 24;
saa_writel(SAA7134_I2C_ATTR_STATUS >> 2, dword);
- d2printk(KERN_DEBUG "%s: i2c data => 0x%x\n",dev->name,data);
+ i2c_dbg(2, "i2c data => 0x%x\n", data);
if (!i2c_is_busy_wait(dev))
return -EIO;
@@ -228,7 +233,7 @@ static inline int i2c_recv_byte(struct saa7134_dev *dev)
if (i2c_is_error(status))
return -EIO;
data = saa_readb(SAA7134_I2C_DATA);
- d2printk(KERN_DEBUG "%s: i2c data <= 0x%x\n",dev->name,data);
+ i2c_dbg(2, "i2c data <= 0x%x\n", data);
return data;
}
@@ -245,12 +250,12 @@ static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap,
if (!i2c_reset(dev))
return -EIO;
- d2printk("start xfer\n");
- d1printk(KERN_DEBUG "%s: i2c xfer:",dev->name);
+ i2c_dbg(2, "start xfer\n");
+ i2c_dbg(1, "i2c xfer:");
for (i = 0; i < num; i++) {
if (!(msgs[i].flags & I2C_M_NOSTART) || 0 == i) {
/* send address */
- d2printk("send address\n");
+ i2c_dbg(2, "send address\n");
addr = msgs[i].addr << 1;
if (msgs[i].flags & I2C_M_RD)
addr |= 1;
@@ -262,50 +267,50 @@ static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap,
* needed to talk to the mt352 demux
* thanks to pinnacle for the hint */
int quirk = 0xfe;
- d1printk(" [%02x quirk]",quirk);
+ i2c_cont(1, " [%02x quirk]", quirk);
i2c_send_byte(dev,START,quirk);
i2c_recv_byte(dev);
}
- d1printk(" < %02x", addr);
+ i2c_cont(1, " < %02x", addr);
rc = i2c_send_byte(dev,START,addr);
if (rc < 0)
goto err;
}
if (msgs[i].flags & I2C_M_RD) {
/* read bytes */
- d2printk("read bytes\n");
+ i2c_dbg(2, "read bytes\n");
for (byte = 0; byte < msgs[i].len; byte++) {
- d1printk(" =");
+ i2c_cont(1, " =");
rc = i2c_recv_byte(dev);
if (rc < 0)
goto err;
- d1printk("%02x", rc);
+ i2c_cont(1, "%02x", rc);
msgs[i].buf[byte] = rc;
}
/* discard mysterious extra byte when reading
from Samsung S5H1411. i2c bus gets error
if we do not. */
if (0x19 == msgs[i].addr) {
- d1printk(" ?");
+ i2c_cont(1, " ?");
rc = i2c_recv_byte(dev);
if (rc < 0)
goto err;
- d1printk("%02x", rc);
+ i2c_cont(1, "%02x", rc);
}
} else {
/* write bytes */
- d2printk("write bytes\n");
+ i2c_dbg(2, "write bytes\n");
for (byte = 0; byte < msgs[i].len; byte++) {
data = msgs[i].buf[byte];
- d1printk(" %02x", data);
+ i2c_cont(1, " %02x", data);
rc = i2c_send_byte(dev,CONTINUE,data);
if (rc < 0)
goto err;
}
}
}
- d2printk("xfer done\n");
- d1printk(" >");
+ i2c_dbg(2, "xfer done\n");
+ i2c_cont(1, " >");
i2c_set_attr(dev,STOP);
rc = -EIO;
if (!i2c_is_busy_wait(dev))
@@ -316,12 +321,12 @@ static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap,
/* ensure that the bus is idle for at least one bit slot */
msleep(1);
- d1printk("\n");
+ i2c_cont(1, "\n");
return num;
err:
if (1 == i2c_debug) {
status = i2c_get_status(dev);
- printk(" ERROR: %s\n",str_i2c_status[status]);
+ i2c_cont(1, " ERROR: %s\n", str_i2c_status[status]);
}
return rc;
}
@@ -359,22 +364,22 @@ saa7134_i2c_eeprom(struct saa7134_dev *dev, unsigned char *eedata, int len)
dev->i2c_client.addr = 0xa0 >> 1;
buf = 0;
if (1 != (err = i2c_master_send(&dev->i2c_client,&buf,1))) {
- printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n",
+ pr_info("%s: Huh, no eeprom present (err=%d)?\n",
dev->name,err);
return -1;
}
if (len != (err = i2c_master_recv(&dev->i2c_client,eedata,len))) {
- printk(KERN_WARNING "%s: i2c eeprom read error (err=%d)\n",
+ pr_warn("%s: i2c eeprom read error (err=%d)\n",
dev->name,err);
return -1;
}
- for (i = 0; i < len; i++) {
- if (0 == (i % 16))
- printk(KERN_INFO "%s: i2c eeprom %02x:",dev->name,i);
- printk(" %02x",eedata[i]);
- if (15 == (i % 16))
- printk("\n");
+
+ for (i = 0; i < len; i += 16) {
+ int size = (len - i) > 16 ? 16 : len - i;
+
+ pr_info("i2c eeprom %02x: %*ph\n", i, size, &eedata[i]);
}
+
return 0;
}
@@ -386,7 +391,7 @@ static char *i2c_devs[128] = {
[ 0x5a >> 1 ] = "remote control",
};
-static void do_i2c_scan(char *name, struct i2c_client *c)
+static void do_i2c_scan(struct i2c_client *c)
{
unsigned char buf;
int i,rc;
@@ -396,8 +401,8 @@ 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",
- name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
+ pr_info("i2c scan: found device @ 0x%x [%s]\n",
+ i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
}
}
@@ -415,7 +420,7 @@ int saa7134_i2c_register(struct saa7134_dev *dev)
saa7134_i2c_eeprom(dev,dev->eedata,sizeof(dev->eedata));
if (i2c_scan)
- do_i2c_scan(dev->name,&dev->i2c_client);
+ do_i2c_scan(&dev->i2c_client);
/* Instantiate the IR receiver device, if present */
saa7134_probe_i2c_ir(dev);
diff --git a/drivers/media/pci/saa7134/saa7134-input.c b/drivers/media/pci/saa7134/saa7134-input.c
index dc3d6516edf7..11a172000291 100644
--- a/drivers/media/pci/saa7134/saa7134-input.c
+++ b/drivers/media/pci/saa7134/saa7134-input.c
@@ -18,15 +18,15 @@
*
*/
+#include "saa7134.h"
+#include "saa7134-reg.h"
+
#include <linux/module.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
-#include "saa7134-reg.h"
-#include "saa7134.h"
-
#define MODULE_NAME "saa7134"
static unsigned int disable_ir;
@@ -41,10 +41,14 @@ static int pinnacle_remote;
module_param(pinnacle_remote, int, 0644); /* Choose Pinnacle PCTV remote */
MODULE_PARM_DESC(pinnacle_remote, "Specify Pinnacle PCTV remote: 0=coloured, 1=grey (defaults to 0)");
-#define dprintk(fmt, arg...) if (ir_debug) \
- printk(KERN_DEBUG "%s/ir: " fmt, dev->name , ## arg)
-#define i2cdprintk(fmt, arg...) if (ir_debug) \
- printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg)
+#define input_dbg(fmt, arg...) do { \
+ if (ir_debug) \
+ printk(KERN_DEBUG pr_fmt("input: " fmt), ## arg); \
+ } while (0)
+#define ir_dbg(ir, fmt, arg...) do { \
+ if (ir_debug) \
+ printk(KERN_DEBUG pr_fmt("ir %s: " fmt), ir->name, ## arg); \
+ } while (0)
/* Helper function for raw decoding at GPIO16 or GPIO18 */
static int saa7134_raw_decode_irq(struct saa7134_dev *dev);
@@ -75,7 +79,7 @@ static int build_key(struct saa7134_dev *dev)
}
data = ir_extract_bits(gpio, ir->mask_keycode);
- dprintk("build_key gpio=0x%x mask=0x%x data=%d\n",
+ input_dbg("build_key gpio=0x%x mask=0x%x data=%d\n",
gpio, ir->mask_keycode, data);
switch (dev->board) {
@@ -119,7 +123,7 @@ static int get_key_flydvb_trio(struct IR_i2c *ir, enum rc_type *protocol,
struct saa7134_dev *dev = ir->c->adapter->algo_data;
if (dev == NULL) {
- i2cdprintk("get_key_flydvb_trio: "
+ ir_dbg(ir, "get_key_flydvb_trio: "
"ir->c->adapter->algo_data is NULL!\n");
return -EIO;
}
@@ -146,12 +150,12 @@ static int get_key_flydvb_trio(struct IR_i2c *ir, enum rc_type *protocol,
msleep(10);
continue;
}
- i2cdprintk("send wake up byte to pic16C505 (IR chip)"
+ ir_dbg(ir, "send wake up byte to pic16C505 (IR chip)"
"failed %dx\n", attempt);
return -EIO;
}
if (1 != i2c_master_recv(ir->c, &b, 1)) {
- i2cdprintk("read error\n");
+ ir_dbg(ir, "read error\n");
return -EIO;
}
@@ -170,7 +174,7 @@ static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, enum rc_type *protocol
/* <dev> is needed to access GPIO. Used by the saa_readl macro. */
struct saa7134_dev *dev = ir->c->adapter->algo_data;
if (dev == NULL) {
- i2cdprintk("get_key_msi_tvanywhere_plus: "
+ ir_dbg(ir, "get_key_msi_tvanywhere_plus: "
"ir->c->adapter->algo_data is NULL!\n");
return -EIO;
}
@@ -191,7 +195,7 @@ static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, enum rc_type *protocol
/* GPIO says there is a button press. Get it. */
if (1 != i2c_master_recv(ir->c, &b, 1)) {
- i2cdprintk("read error\n");
+ ir_dbg(ir, "read error\n");
return -EIO;
}
@@ -202,7 +206,7 @@ static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, enum rc_type *protocol
/* Button pressed */
- dprintk("get_key_msi_tvanywhere_plus: Key = 0x%02X\n", b);
+ input_dbg("get_key_msi_tvanywhere_plus: Key = 0x%02X\n", b);
*protocol = RC_TYPE_UNKNOWN;
*scancode = b;
*toggle = 0;
@@ -219,7 +223,7 @@ static int get_key_kworld_pc150u(struct IR_i2c *ir, enum rc_type *protocol,
/* <dev> is needed to access GPIO. Used by the saa_readl macro. */
struct saa7134_dev *dev = ir->c->adapter->algo_data;
if (dev == NULL) {
- i2cdprintk("get_key_kworld_pc150u: "
+ ir_dbg(ir, "get_key_kworld_pc150u: "
"ir->c->adapter->algo_data is NULL!\n");
return -EIO;
}
@@ -240,7 +244,7 @@ static int get_key_kworld_pc150u(struct IR_i2c *ir, enum rc_type *protocol,
/* GPIO says there is a button press. Get it. */
if (1 != i2c_master_recv(ir->c, &b, 1)) {
- i2cdprintk("read error\n");
+ ir_dbg(ir, "read error\n");
return -EIO;
}
@@ -251,7 +255,7 @@ static int get_key_kworld_pc150u(struct IR_i2c *ir, enum rc_type *protocol,
/* Button pressed */
- dprintk("get_key_kworld_pc150u: Key = 0x%02X\n", b);
+ input_dbg("get_key_kworld_pc150u: Key = 0x%02X\n", b);
*protocol = RC_TYPE_UNKNOWN;
*scancode = b;
*toggle = 0;
@@ -265,7 +269,7 @@ static int get_key_purpletv(struct IR_i2c *ir, enum rc_type *protocol,
/* poll IR chip */
if (1 != i2c_master_recv(ir->c, &b, 1)) {
- i2cdprintk("read error\n");
+ ir_dbg(ir, "read error\n");
return -EIO;
}
@@ -334,7 +338,7 @@ static int get_key_beholdm6xx(struct IR_i2c *ir, enum rc_type *protocol,
ir->c->addr = 0x5a >> 1;
if (12 != i2c_master_recv(ir->c, data, 12)) {
- i2cdprintk("read error\n");
+ ir_dbg(ir, "read error\n");
return -EIO;
}
@@ -359,7 +363,7 @@ static int get_key_pinnacle(struct IR_i2c *ir, enum rc_type *protocol,
/* poll IR chip */
if (4 != i2c_master_recv(ir->c, b, 4)) {
- i2cdprintk("read error\n");
+ ir_dbg(ir, "read error\n");
return -EIO;
}
@@ -391,7 +395,7 @@ static int get_key_pinnacle(struct IR_i2c *ir, enum rc_type *protocol,
*scancode = code;
*toggle = 0;
- i2cdprintk("Pinnacle PCTV key %02x\n", code);
+ ir_dbg(ir, "Pinnacle PCTV key %02x\n", code);
return 1;
}
@@ -481,6 +485,7 @@ static int __saa7134_ir_start(void *priv)
case SAA7134_BOARD_KWORLD_VSTREAM_XPERT:
case SAA7134_BOARD_AVERMEDIA_305:
case SAA7134_BOARD_AVERMEDIA_307:
+ case SAA7134_BOARD_AVERMEDIA_505:
case SAA7134_BOARD_AVERMEDIA_STUDIO_305:
case SAA7134_BOARD_AVERMEDIA_STUDIO_505:
case SAA7134_BOARD_AVERMEDIA_STUDIO_307:
@@ -629,6 +634,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
case SAA7134_BOARD_KWORLD_VSTREAM_XPERT:
case SAA7134_BOARD_AVERMEDIA_305:
case SAA7134_BOARD_AVERMEDIA_307:
+ case SAA7134_BOARD_AVERMEDIA_505:
case SAA7134_BOARD_AVERMEDIA_STUDIO_305:
case SAA7134_BOARD_AVERMEDIA_STUDIO_505:
case SAA7134_BOARD_AVERMEDIA_STUDIO_307:
@@ -831,8 +837,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
break;
}
if (NULL == ir_codes) {
- printk("%s: Oops: IR config error [card=%d]\n",
- dev->name, dev->board);
+ pr_err("Oops: IR config error [card=%d]\n", dev->board);
return -ENODEV;
}
@@ -916,7 +921,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev)
int rc;
if (disable_ir) {
- dprintk("IR has been disabled, not probing for i2c remote\n");
+ input_dbg("IR has been disabled, not probing for i2c remote\n");
return;
}
@@ -959,7 +964,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev)
an existing device. Weird...
REVISIT: might no longer be needed */
rc = i2c_transfer(&dev->i2c_adap, &msg_msi, 1);
- dprintk("probe 0x%02x @ %s: %s\n",
+ input_dbg("probe 0x%02x @ %s: %s\n",
msg_msi.addr, dev->i2c_adap.name,
(1 == rc) ? "yes" : "no");
break;
@@ -974,7 +979,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev)
an existing device. Weird...
REVISIT: might no longer be needed */
rc = i2c_transfer(&dev->i2c_adap, &msg_msi, 1);
- dprintk("probe 0x%02x @ %s: %s\n",
+ input_dbg("probe 0x%02x @ %s: %s\n",
msg_msi.addr, dev->i2c_adap.name,
(1 == rc) ? "yes" : "no");
break;
@@ -1019,7 +1024,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev)
info.addr = 0x0b;
break;
default:
- dprintk("No I2C IR support for board %x\n", dev->board);
+ input_dbg("No I2C IR support for board %x\n", dev->board);
return;
}
diff --git a/drivers/media/pci/saa7134/saa7134-ts.c b/drivers/media/pci/saa7134/saa7134-ts.c
index 2709b83d57b1..4b202fa5fbc4 100644
--- a/drivers/media/pci/saa7134/saa7134-ts.c
+++ b/drivers/media/pci/saa7134/saa7134-ts.c
@@ -20,23 +20,25 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include "saa7134.h"
+#include "saa7134-reg.h"
+
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/delay.h>
-#include "saa7134-reg.h"
-#include "saa7134.h"
-
/* ------------------------------------------------------------------ */
static unsigned int ts_debug;
module_param(ts_debug, int, 0644);
MODULE_PARM_DESC(ts_debug,"enable debug messages [ts]");
-#define dprintk(fmt, arg...) if (ts_debug) \
- printk(KERN_DEBUG "%s/ts: " fmt, dev->name , ## arg)
+#define ts_dbg(fmt, arg...) do { \
+ if (ts_debug) \
+ printk(KERN_DEBUG pr_fmt("ts: " fmt), ## arg); \
+ } while (0)
/* ------------------------------------------------------------------ */
static int buffer_activate(struct saa7134_dev *dev,
@@ -44,7 +46,7 @@ static int buffer_activate(struct saa7134_dev *dev,
struct saa7134_buf *next)
{
- dprintk("buffer_activate [%p]",buf);
+ ts_dbg("buffer_activate [%p]", buf);
buf->top_seen = 0;
if (!dev->ts_started)
@@ -53,12 +55,12 @@ static int buffer_activate(struct saa7134_dev *dev,
if (NULL == next)
next = buf;
if (V4L2_FIELD_TOP == dev->ts_field) {
- dprintk("- [top] buf=%p next=%p\n",buf,next);
+ ts_dbg("- [top] buf=%p next=%p\n", buf, next);
saa_writel(SAA7134_RS_BA1(5),saa7134_buffer_base(buf));
saa_writel(SAA7134_RS_BA2(5),saa7134_buffer_base(next));
dev->ts_field = V4L2_FIELD_BOTTOM;
} else {
- dprintk("- [bottom] buf=%p next=%p\n",buf,next);
+ ts_dbg("- [bottom] buf=%p next=%p\n", buf, next);
saa_writel(SAA7134_RS_BA1(5),saa7134_buffer_base(next));
saa_writel(SAA7134_RS_BA2(5),saa7134_buffer_base(buf));
dev->ts_field = V4L2_FIELD_TOP;
@@ -95,7 +97,7 @@ int saa7134_ts_buffer_prepare(struct vb2_buffer *vb2)
struct sg_table *dma = vb2_dma_sg_plane_desc(vb2, 0);
unsigned int lines, llength, size;
- dprintk("buffer_prepare [%p]\n", buf);
+ ts_dbg("buffer_prepare [%p]\n", buf);
llength = TS_PACKET_SIZE;
lines = dev->ts.nr_packets;
@@ -239,7 +241,7 @@ int saa7134_ts_init1(struct saa7134_dev *dev)
/* Function for stop TS */
int saa7134_ts_stop(struct saa7134_dev *dev)
{
- dprintk("TS stop\n");
+ ts_dbg("TS stop\n");
if (!dev->ts_started)
return 0;
@@ -261,7 +263,7 @@ int saa7134_ts_stop(struct saa7134_dev *dev)
/* Function for start TS */
int saa7134_ts_start(struct saa7134_dev *dev)
{
- dprintk("TS start\n");
+ ts_dbg("TS start\n");
if (WARN_ON(dev->ts_started))
return 0;
diff --git a/drivers/media/pci/saa7134/saa7134-tvaudio.c b/drivers/media/pci/saa7134/saa7134-tvaudio.c
index 3afbcb70b518..21a579309575 100644
--- a/drivers/media/pci/saa7134/saa7134-tvaudio.c
+++ b/drivers/media/pci/saa7134/saa7134-tvaudio.c
@@ -20,6 +20,9 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include "saa7134.h"
+#include "saa7134-reg.h"
+
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
@@ -29,9 +32,6 @@
#include <linux/freezer.h>
#include <asm/div64.h>
-#include "saa7134-reg.h"
-#include "saa7134.h"
-
/* ------------------------------------------------------------------ */
static unsigned int audio_debug;
@@ -49,13 +49,10 @@ static int audio_clock_tweak;
module_param(audio_clock_tweak, int, 0644);
MODULE_PARM_DESC(audio_clock_tweak, "Audio clock tick fine tuning for cards with audio crystal that's slightly off (range [-1024 .. 1024])");
-#define dprintk(fmt, arg...) if (audio_debug) \
- printk(KERN_DEBUG "%s/audio: " fmt, dev->name , ## arg)
-#define d2printk(fmt, arg...) if (audio_debug > 1) \
- printk(KERN_DEBUG "%s/audio: " fmt, dev->name, ## arg)
-
-#define print_regb(reg) printk("%s: reg 0x%03x [%-16s]: 0x%02x\n", \
- dev->name,(SAA7134_##reg),(#reg),saa_readb((SAA7134_##reg)))
+#define audio_dbg(level, fmt, arg...) do { \
+ if (audio_debug >= level) \
+ printk(KERN_DEBUG pr_fmt("audio: " fmt), ## arg); \
+ } while (0)
/* msecs */
#define SCAN_INITIAL_DELAY 1000
@@ -206,13 +203,14 @@ static void mute_input_7134(struct saa7134_dev *dev)
if (dev->hw_mute == mute &&
dev->hw_input == in && !dev->insuspend) {
- dprintk("mute/input: nothing to do [mute=%d,input=%s]\n",
- mute,in->name);
+ audio_dbg(1, "mute/input: nothing to do [mute=%d,input=%s]\n",
+ mute, in->name);
return;
}
- dprintk("ctl_mute=%d automute=%d input=%s => mute=%d input=%s\n",
- dev->ctl_mute,dev->automute,dev->input->name,mute,in->name);
+ audio_dbg(1, "ctl_mute=%d automute=%d input=%s => mute=%d input=%s\n",
+ dev->ctl_mute, dev->automute,
+ dev->input->name, mute, in->name);
dev->hw_mute = mute;
dev->hw_input = in;
@@ -265,8 +263,8 @@ static void tvaudio_setmode(struct saa7134_dev *dev,
tweak = audio_clock_tweak;
if (note)
- dprintk("tvaudio_setmode: %s %s [%d.%03d/%d.%03d MHz] acpf=%d%+d\n",
- note,audio->name,
+ audio_dbg(1, "tvaudio_setmode: %s %s [%d.%03d/%d.%03d MHz] acpf=%d%+d\n",
+ note, audio->name,
audio->carr1 / 1000, audio->carr1 % 1000,
audio->carr2 / 1000, audio->carr2 % 1000,
acpf, tweak);
@@ -334,14 +332,14 @@ static int tvaudio_checkcarrier(struct saa7134_dev *dev, struct mainscan *scan)
if (!(dev->tvnorm->id & scan->std)) {
value = 0;
- dprintk("skipping %d.%03d MHz [%4s]\n",
- scan->carr / 1000, scan->carr % 1000, scan->name);
+ audio_dbg(1, "skipping %d.%03d MHz [%4s]\n",
+ scan->carr / 1000, scan->carr % 1000, scan->name);
return 0;
}
if (audio_debug > 1) {
int i;
- dprintk("debug %d:",scan->carr);
+ audio_dbg(1, "debug %d:", scan->carr);
for (i = -150; i <= 150; i += 30) {
tvaudio_setcarrier(dev,scan->carr+i,scan->carr+i);
saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
@@ -349,11 +347,11 @@ static int tvaudio_checkcarrier(struct saa7134_dev *dev, struct mainscan *scan)
return -1;
value = saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
if (0 == i)
- printk(" # %6d # ",value >> 16);
+ pr_cont(" # %6d # ", value >> 16);
else
- printk(" %6d",value >> 16);
+ pr_cont(" %6d", value >> 16);
}
- printk("\n");
+ pr_cont("\n");
}
tvaudio_setcarrier(dev,scan->carr-90,scan->carr-90);
@@ -371,9 +369,9 @@ static int tvaudio_checkcarrier(struct saa7134_dev *dev, struct mainscan *scan)
left >>= 16;
right >>= 16;
value = left > right ? left - right : right - left;
- dprintk("scanning %d.%03d MHz [%4s] => dc is %5d [%d/%d]\n",
- scan->carr / 1000, scan->carr % 1000,
- scan->name, value, left, right);
+ audio_dbg(1, "scanning %d.%03d MHz [%4s] => dc is %5d [%d/%d]\n",
+ scan->carr / 1000, scan->carr % 1000,
+ scan->name, value, left, right);
return value;
}
@@ -389,7 +387,7 @@ static int tvaudio_getstereo(struct saa7134_dev *dev, struct saa7134_tvaudio *au
case TVAUDIO_FM_K_STEREO:
case TVAUDIO_FM_BG_STEREO:
idp = (saa_readb(SAA7134_IDENT_SIF) & 0xe0) >> 5;
- dprintk("getstereo: fm/stereo: idp=0x%x\n",idp);
+ audio_dbg(1, "getstereo: fm/stereo: idp=0x%x\n", idp);
if (0x03 == (idp & 0x03))
retval = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
else if (0x05 == (idp & 0x05))
@@ -403,10 +401,11 @@ static int tvaudio_getstereo(struct saa7134_dev *dev, struct saa7134_tvaudio *au
case TVAUDIO_NICAM_FM:
case TVAUDIO_NICAM_AM:
nicam = saa_readb(SAA7134_AUDIO_STATUS);
- dprintk("getstereo: nicam=0x%x\n",nicam);
+ audio_dbg(1, "getstereo: nicam=0x%x\n", nicam);
if (nicam & 0x1) {
nicam_status = saa_readb(SAA7134_NICAM_STATUS);
- dprintk("getstereo: nicam_status=0x%x\n", nicam_status);
+ audio_dbg(1, "getstereo: nicam_status=0x%x\n",
+ nicam_status);
switch (nicam_status & 0x03) {
case 0x01:
@@ -424,7 +423,7 @@ static int tvaudio_getstereo(struct saa7134_dev *dev, struct saa7134_tvaudio *au
break;
}
if (retval != -1)
- dprintk("found audio subchannels:%s%s%s%s\n",
+ audio_dbg(1, "found audio subchannels:%s%s%s%s\n",
(retval & V4L2_TUNER_SUB_MONO) ? " mono" : "",
(retval & V4L2_TUNER_SUB_STEREO) ? " stereo" : "",
(retval & V4L2_TUNER_SUB_LANG1) ? " lang1" : "",
@@ -459,8 +458,8 @@ static int tvaudio_setstereo(struct saa7134_dev *dev, struct saa7134_tvaudio *au
case TVAUDIO_FM_BG_STEREO:
case TVAUDIO_NICAM_AM:
case TVAUDIO_NICAM_FM:
- dprintk("setstereo [fm] => %s\n",
- name[ mode % ARRAY_SIZE(name) ]);
+ audio_dbg(1, "setstereo [fm] => %s\n",
+ name[mode % ARRAY_SIZE(name)]);
reg = fm[ mode % ARRAY_SIZE(fm) ];
saa_writeb(SAA7134_FM_DEMATRIX, reg);
break;
@@ -489,7 +488,8 @@ static int tvaudio_thread(void *data)
try_to_freeze();
dev->thread.scan1 = dev->thread.scan2;
- dprintk("tvaudio thread scan start [%d]\n",dev->thread.scan1);
+ audio_dbg(1, "tvaudio thread scan start [%d]\n",
+ dev->thread.scan1);
dev->tvaudio = NULL;
saa_writeb(SAA7134_MONITOR_SELECT, 0xa0);
@@ -519,7 +519,7 @@ static int tvaudio_thread(void *data)
if (1 == nscan) {
/* only one candidate -- skip scan ;) */
- dprintk("only one main carrier candidate - skipping scan\n");
+ audio_dbg(1, "only one main carrier candidate - skipping scan\n");
max1 = 12345;
carrier = default_carrier;
} else {
@@ -544,26 +544,24 @@ static int tvaudio_thread(void *data)
if (0 != carrier && max1 > 2000 && max1 > max2*3) {
/* found good carrier */
- dprintk("found %s main sound carrier @ %d.%03d MHz [%d/%d]\n",
- dev->tvnorm->name, carrier/1000, carrier%1000,
- max1, max2);
+ audio_dbg(1, "found %s main sound carrier @ %d.%03d MHz [%d/%d]\n",
+ dev->tvnorm->name, carrier/1000, carrier%1000,
+ max1, max2);
dev->last_carrier = carrier;
dev->automute = 0;
} else if (0 != dev->last_carrier) {
/* no carrier -- try last detected one as fallback */
carrier = dev->last_carrier;
- dprintk("audio carrier scan failed, "
- "using %d.%03d MHz [last detected]\n",
- carrier/1000, carrier%1000);
+ audio_dbg(1, "audio carrier scan failed, using %d.%03d MHz [last detected]\n",
+ carrier/1000, carrier%1000);
dev->automute = 1;
} else {
/* no carrier + no fallback -- use default */
carrier = default_carrier;
- dprintk("audio carrier scan failed, "
- "using %d.%03d MHz [default]\n",
- carrier/1000, carrier%1000);
+ audio_dbg(1, "audio carrier scan failed, using %d.%03d MHz [default]\n",
+ carrier/1000, carrier%1000);
dev->automute = 1;
}
tvaudio_setcarrier(dev,carrier,carrier);
@@ -661,7 +659,7 @@ static inline int saa_dsp_reset_error_bit(struct saa7134_dev *dev)
{
int state = saa_readb(SAA7135_DSP_RWSTATE);
if (unlikely(state & SAA7135_DSP_RWSTATE_ERR)) {
- d2printk("%s: resetting error bit\n", dev->name);
+ audio_dbg(2, "%s: resetting error bit\n", dev->name);
saa_writeb(SAA7135_DSP_RWCLEAR, SAA7135_DSP_RWCLEAR_RERR);
}
return 0;
@@ -673,18 +671,17 @@ static inline int saa_dsp_wait_bit(struct saa7134_dev *dev, int bit)
state = saa_readb(SAA7135_DSP_RWSTATE);
if (unlikely(state & SAA7135_DSP_RWSTATE_ERR)) {
- printk(KERN_WARNING "%s: dsp access error\n", dev->name);
+ pr_warn("%s: dsp access error\n", dev->name);
saa_dsp_reset_error_bit(dev);
return -EIO;
}
while (0 == (state & bit)) {
if (unlikely(0 == count)) {
- printk("%s: dsp access wait timeout [bit=%s]\n",
- dev->name,
- (bit & SAA7135_DSP_RWSTATE_WRR) ? "WRR" :
- (bit & SAA7135_DSP_RWSTATE_RDB) ? "RDB" :
- (bit & SAA7135_DSP_RWSTATE_IDA) ? "IDA" :
- "???");
+ pr_err("dsp access wait timeout [bit=%s]\n",
+ (bit & SAA7135_DSP_RWSTATE_WRR) ? "WRR" :
+ (bit & SAA7135_DSP_RWSTATE_RDB) ? "RDB" :
+ (bit & SAA7135_DSP_RWSTATE_IDA) ? "IDA" :
+ "???");
return -EIO;
}
saa_wait(DSP_DELAY);
@@ -699,7 +696,7 @@ int saa_dsp_writel(struct saa7134_dev *dev, int reg, u32 value)
{
int err;
- d2printk("dsp write reg 0x%x = 0x%06x\n",reg<<2,value);
+ audio_dbg(2, "dsp write reg 0x%x = 0x%06x\n", reg << 2, value);
err = saa_dsp_wait_bit(dev,SAA7135_DSP_RWSTATE_WRR);
if (err < 0)
return err;
@@ -786,14 +783,16 @@ static int tvaudio_thread_ddep(void *data)
try_to_freeze();
dev->thread.scan1 = dev->thread.scan2;
- dprintk("tvaudio thread scan start [%d]\n",dev->thread.scan1);
+ audio_dbg(1, "tvaudio thread scan start [%d]\n",
+ dev->thread.scan1);
if (audio_ddep >= 0x04 && audio_ddep <= 0x0e) {
/* insmod option override */
norms = (audio_ddep << 2) | 0x01;
- dprintk("ddep override: %s\n",stdres[audio_ddep]);
+ audio_dbg(1, "ddep override: %s\n",
+ stdres[audio_ddep]);
} else if (&card(dev).radio == dev->input) {
- dprintk("FM Radio\n");
+ audio_dbg(1, "FM Radio\n");
if (dev->tuner_type == TUNER_PHILIPS_TDA8290) {
norms = (0x11 << 2) | 0x01;
/* set IF frequency to 5.5 MHz */
@@ -816,12 +815,12 @@ static int tvaudio_thread_ddep(void *data)
norms |= 0x10;
if (0 == norms)
norms = 0x7c; /* all */
- dprintk("scanning:%s%s%s%s%s\n",
- (norms & 0x04) ? " B/G" : "",
- (norms & 0x08) ? " D/K" : "",
- (norms & 0x10) ? " L/L'" : "",
- (norms & 0x20) ? " I" : "",
- (norms & 0x40) ? " M" : "");
+ audio_dbg(1, "scanning:%s%s%s%s%s\n",
+ (norms & 0x04) ? " B/G" : "",
+ (norms & 0x08) ? " D/K" : "",
+ (norms & 0x10) ? " L/L'" : "",
+ (norms & 0x20) ? " I" : "",
+ (norms & 0x40) ? " M" : "");
}
/* kick automatic standard detection */
@@ -836,29 +835,28 @@ static int tvaudio_thread_ddep(void *data)
goto restart;
value = saa_readl(0x528 >> 2) & 0xffffff;
- dprintk("tvaudio thread status: 0x%x [%s%s%s]\n",
- value, stdres[value & 0x1f],
- (value & 0x000020) ? ",stereo" : "",
- (value & 0x000040) ? ",dual" : "");
- dprintk("detailed status: "
- "%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s\n",
- (value & 0x000080) ? " A2/EIAJ pilot tone " : "",
- (value & 0x000100) ? " A2/EIAJ dual " : "",
- (value & 0x000200) ? " A2/EIAJ stereo " : "",
- (value & 0x000400) ? " A2/EIAJ noise mute " : "",
-
- (value & 0x000800) ? " BTSC/FM radio pilot " : "",
- (value & 0x001000) ? " SAP carrier " : "",
- (value & 0x002000) ? " BTSC stereo noise mute " : "",
- (value & 0x004000) ? " SAP noise mute " : "",
- (value & 0x008000) ? " VDSP " : "",
-
- (value & 0x010000) ? " NICST " : "",
- (value & 0x020000) ? " NICDU " : "",
- (value & 0x040000) ? " NICAM muted " : "",
- (value & 0x080000) ? " NICAM reserve sound " : "",
-
- (value & 0x100000) ? " init done " : "");
+ audio_dbg(1, "tvaudio thread status: 0x%x [%s%s%s]\n",
+ value, stdres[value & 0x1f],
+ (value & 0x000020) ? ",stereo" : "",
+ (value & 0x000040) ? ",dual" : "");
+ audio_dbg(1, "detailed status: %s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s\n",
+ (value & 0x000080) ? " A2/EIAJ pilot tone " : "",
+ (value & 0x000100) ? " A2/EIAJ dual " : "",
+ (value & 0x000200) ? " A2/EIAJ stereo " : "",
+ (value & 0x000400) ? " A2/EIAJ noise mute " : "",
+
+ (value & 0x000800) ? " BTSC/FM radio pilot " : "",
+ (value & 0x001000) ? " SAP carrier " : "",
+ (value & 0x002000) ? " BTSC stereo noise mute " : "",
+ (value & 0x004000) ? " SAP noise mute " : "",
+ (value & 0x008000) ? " VDSP " : "",
+
+ (value & 0x010000) ? " NICST " : "",
+ (value & 0x020000) ? " NICDU " : "",
+ (value & 0x040000) ? " NICAM muted " : "",
+ (value & 0x080000) ? " NICAM reserve sound " : "",
+
+ (value & 0x100000) ? " init done " : "");
}
done:
@@ -1031,7 +1029,7 @@ int saa7134_tvaudio_init2(struct saa7134_dev *dev)
/* start tvaudio thread */
dev->thread.thread = kthread_run(my_thread, dev, "%s", dev->name);
if (IS_ERR(dev->thread.thread)) {
- printk(KERN_WARNING "%s: kernel_thread() failed\n",
+ pr_warn("%s: kernel_thread() failed\n",
dev->name);
/* XXX: missing error handling here */
}
@@ -1061,7 +1059,7 @@ int saa7134_tvaudio_fini(struct saa7134_dev *dev)
int saa7134_tvaudio_do_scan(struct saa7134_dev *dev)
{
if (dev->input->amux != TV) {
- dprintk("sound IF not in use, skipping scan\n");
+ audio_dbg(1, "sound IF not in use, skipping scan\n");
dev->automute = 0;
saa7134_tvaudio_setmute(dev);
} else if (dev->thread.thread) {
diff --git a/drivers/media/pci/saa7134/saa7134-vbi.c b/drivers/media/pci/saa7134/saa7134-vbi.c
index 5306e549e526..4d36586ad752 100644
--- a/drivers/media/pci/saa7134/saa7134-vbi.c
+++ b/drivers/media/pci/saa7134/saa7134-vbi.c
@@ -20,14 +20,14 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include "saa7134.h"
+#include "saa7134-reg.h"
+
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/kernel.h>
-#include "saa7134-reg.h"
-#include "saa7134.h"
-
/* ------------------------------------------------------------------ */
static unsigned int vbi_debug;
@@ -38,8 +38,10 @@ static unsigned int vbibufs = 4;
module_param(vbibufs, int, 0444);
MODULE_PARM_DESC(vbibufs,"number of vbi buffers, range 2-32");
-#define dprintk(fmt, arg...) if (vbi_debug) \
- printk(KERN_DEBUG "%s/vbi: " fmt, dev->name , ## arg)
+#define vbi_dbg(fmt, arg...) do { \
+ if (vbi_debug) \
+ printk(KERN_DEBUG pr_fmt("vbi: " fmt), ## arg); \
+ } while (0)
/* ------------------------------------------------------------------ */
@@ -84,7 +86,7 @@ static int buffer_activate(struct saa7134_dev *dev,
struct saa7134_dmaqueue *dmaq = buf->vb2.vb2_queue->drv_priv;
unsigned long control, base;
- dprintk("buffer_activate [%p]\n", buf);
+ vbi_dbg("buffer_activate [%p]\n", buf);
buf->top_seen = 0;
task_init(dev, buf, TASK_A);
diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c
index 99d09a7566d3..035039cfae6d 100644
--- a/drivers/media/pci/saa7134/saa7134-video.c
+++ b/drivers/media/pci/saa7134/saa7134-video.c
@@ -20,6 +20,9 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include "saa7134.h"
+#include "saa7134-reg.h"
+
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
@@ -31,9 +34,6 @@
#include <media/v4l2-event.h>
#include <media/saa6588.h>
-#include "saa7134-reg.h"
-#include "saa7134.h"
-
/* ------------------------------------------------------------------ */
unsigned int video_debug;
@@ -52,8 +52,10 @@ module_param_string(secam, secam, sizeof(secam), 0644);
MODULE_PARM_DESC(secam, "force SECAM variant, either DK,L or Lc");
-#define dprintk(fmt, arg...) if (video_debug&0x04) \
- printk(KERN_DEBUG "%s/video: " fmt, dev->name , ## arg)
+#define video_dbg(fmt, arg...) do { \
+ if (video_debug & 0x04) \
+ printk(KERN_DEBUG pr_fmt("video: " fmt), ## arg); \
+ } while (0)
/* ------------------------------------------------------------------ */
/* Defines for Video Output Port Register at address 0x191 */
@@ -385,7 +387,7 @@ static struct saa7134_format* format_by_fourcc(unsigned int fourcc)
static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm)
{
- dprintk("set tv norm = %s\n",norm->name);
+ video_dbg("set tv norm = %s\n", norm->name);
dev->tvnorm = norm;
/* setup cropping */
@@ -407,7 +409,7 @@ static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm)
static void video_mux(struct saa7134_dev *dev, int input)
{
- dprintk("video input = %d [%s]\n", input, card_in(dev, input).name);
+ video_dbg("video input = %d [%s]\n", input, card_in(dev, input).name);
dev->ctl_input = input;
set_tvnorm(dev, dev->tvnorm);
saa7134_tvaudio_setinput(dev, &card_in(dev, input));
@@ -531,14 +533,14 @@ static void set_v_scale(struct saa7134_dev *dev, int task, int yscale)
mirror = (dev->ctl_mirror) ? 0x02 : 0x00;
if (yscale < 2048) {
/* LPI */
- dprintk("yscale LPI yscale=%d\n",yscale);
+ video_dbg("yscale LPI yscale=%d\n", yscale);
saa_writeb(SAA7134_V_FILTER(task), 0x00 | mirror);
saa_writeb(SAA7134_LUMA_CONTRAST(task), 0x40);
saa_writeb(SAA7134_CHROMA_SATURATION(task), 0x40);
} else {
/* ACM */
val = 0x40 * 1024 / yscale;
- dprintk("yscale ACM yscale=%d val=0x%x\n",yscale,val);
+ video_dbg("yscale ACM yscale=%d val=0x%x\n", yscale, val);
saa_writeb(SAA7134_V_FILTER(task), 0x01 | mirror);
saa_writeb(SAA7134_LUMA_CONTRAST(task), val);
saa_writeb(SAA7134_CHROMA_SATURATION(task), val);
@@ -573,7 +575,8 @@ static void set_size(struct saa7134_dev *dev, int task,
prescale = 1;
xscale = 1024 * dev->crop_current.width / prescale / width;
yscale = 512 * div * dev->crop_current.height / height;
- dprintk("prescale=%d xscale=%d yscale=%d\n",prescale,xscale,yscale);
+ video_dbg("prescale=%d xscale=%d yscale=%d\n",
+ prescale, xscale, yscale);
set_h_prescale(dev,task,prescale);
saa_writeb(SAA7134_H_SCALE_INC1(task), xscale & 0xff);
saa_writeb(SAA7134_H_SCALE_INC2(task), xscale >> 8);
@@ -615,7 +618,7 @@ static void set_cliplist(struct saa7134_dev *dev, int reg,
saa_writeb(reg + 0, winbits);
saa_writeb(reg + 2, cl[i].position & 0xff);
saa_writeb(reg + 3, cl[i].position >> 8);
- dprintk("clip: %s winbits=%02x pos=%d\n",
+ video_dbg("clip: %s winbits=%02x pos=%d\n",
name,winbits,cl[i].position);
reg += 8;
}
@@ -730,7 +733,7 @@ static int start_preview(struct saa7134_dev *dev)
return err;
dev->ovfield = dev->win.field;
- dprintk("start_preview %dx%d+%d+%d %s field=%s\n",
+ video_dbg("start_preview %dx%d+%d+%d %s field=%s\n",
dev->win.w.width, dev->win.w.height,
dev->win.w.left, dev->win.w.top,
dev->ovfmt->name, v4l2_field_names[dev->ovfield]);
@@ -792,7 +795,7 @@ static int buffer_activate(struct saa7134_dev *dev,
unsigned long base,control,bpl;
unsigned long bpl_uv,lines_uv,base2,base3,tmp; /* planar */
- dprintk("buffer_activate buf=%p\n",buf);
+ video_dbg("buffer_activate buf=%p\n", buf);
buf->top_seen = 0;
set_size(dev, TASK_A, dev->width, dev->height,
@@ -837,7 +840,7 @@ static int buffer_activate(struct saa7134_dev *dev,
base3 = base2 + bpl_uv * lines_uv;
if (dev->fmt->uvswap)
tmp = base2, base2 = base3, base3 = tmp;
- dprintk("uv: bpl=%ld lines=%ld base2/3=%ld/%ld\n",
+ video_dbg("uv: bpl=%ld lines=%ld base2/3=%ld/%ld\n",
bpl_uv,lines_uv,base2,base3);
if (V4L2_FIELD_HAS_BOTH(dev->field)) {
/* interlaced */
@@ -1229,7 +1232,7 @@ static int saa7134_g_fmt_vid_overlay(struct file *file, void *priv,
int i;
if (saa7134_no_overlay > 0) {
- printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
+ pr_err("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
return -EINVAL;
}
f->fmt.win = dev->win;
@@ -1305,7 +1308,7 @@ static int saa7134_try_fmt_vid_overlay(struct file *file, void *priv,
struct saa7134_dev *dev = video_drvdata(file);
if (saa7134_no_overlay > 0) {
- printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
+ pr_err("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
return -EINVAL;
}
@@ -1339,7 +1342,7 @@ static int saa7134_s_fmt_vid_overlay(struct file *file, void *priv,
unsigned long flags;
if (saa7134_no_overlay > 0) {
- printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
+ pr_err("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
return -EINVAL;
}
if (f->fmt.win.clips == NULL)
@@ -1738,7 +1741,7 @@ static int saa7134_enum_fmt_vid_overlay(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
if (saa7134_no_overlay > 0) {
- printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
+ pr_err("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
return -EINVAL;
}
@@ -1795,7 +1798,7 @@ static int saa7134_overlay(struct file *file, void *priv, unsigned int on)
if (on) {
if (saa7134_no_overlay > 0) {
- dprintk("no_overlay\n");
+ video_dbg("no_overlay\n");
return -EINVAL;
}
@@ -2184,7 +2187,7 @@ void saa7134_irq_video_signalchange(struct saa7134_dev *dev)
st1 = saa_readb(SAA7134_STATUS_VIDEO1);
st2 = saa_readb(SAA7134_STATUS_VIDEO2);
- dprintk("DCSDT: pll: %s, sync: %s, norm: %s\n",
+ video_dbg("DCSDT: pll: %s, sync: %s, norm: %s\n",
(st1 & 0x40) ? "not locked" : "locked",
(st2 & 0x40) ? "no" : "yes",
st[st1 & 0x03]);
diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h
index 8bf0553b8d2f..6b5f6f45d285 100644
--- a/drivers/media/pci/saa7134/saa7134.h
+++ b/drivers/media/pci/saa7134/saa7134.h
@@ -21,6 +21,8 @@
#define SAA7134_VERSION "0, 2, 17"
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/pci.h>
#include <linux/i2c.h>
#include <linux/videodev2.h>
@@ -339,6 +341,7 @@ struct saa7134_card_ir {
#define SAA7134_BOARD_HAWELL_HW_9004V1 191
#define SAA7134_BOARD_AVERMEDIA_A706 192
#define SAA7134_BOARD_WIS_VOYAGER 193
+#define SAA7134_BOARD_AVERMEDIA_505 194
#define SAA7134_MAXBOARDS 32
#define SAA7134_INPUT_MAX 8
@@ -654,7 +657,8 @@ struct saa7134_dev {
/* SAA7134_MPEG_DVB only */
struct vb2_dvb_frontends frontends;
int (*original_demod_sleep)(struct dvb_frontend *fe);
- int (*original_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
+ int (*original_set_voltage)(struct dvb_frontend *fe,
+ enum fe_sec_voltage voltage);
int (*original_set_high_voltage)(struct dvb_frontend *fe, long arg);
#endif
void (*gate_ctrl)(struct saa7134_dev *dev, int open);
diff --git a/drivers/media/pci/saa7164/saa7164-api.c b/drivers/media/pci/saa7164/saa7164-api.c
index 4f3b1dd18ba4..e7e586c1ba53 100644
--- a/drivers/media/pci/saa7164/saa7164-api.c
+++ b/drivers/media/pci/saa7164/saa7164-api.c
@@ -1,7 +1,7 @@
/*
* Driver for the NXP SAA7164 PCIe bridge
*
- * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ * Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.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
@@ -1373,7 +1373,8 @@ int saa7164_api_i2c_read(struct saa7164_i2c *bus, u8 addr, u32 reglen, u8 *reg,
u8 buf[256];
int ret;
- dprintk(DBGLVL_API, "%s()\n", __func__);
+ dprintk(DBGLVL_API, "%s() addr=%x reglen=%d datalen=%d\n",
+ __func__, addr, reglen, datalen);
if (reglen > 4)
return -EIO;
@@ -1434,7 +1435,8 @@ int saa7164_api_i2c_write(struct saa7164_i2c *bus, u8 addr, u32 datalen,
u8 buf[256];
int ret;
- dprintk(DBGLVL_API, "%s()\n", __func__);
+ dprintk(DBGLVL_API, "%s() addr=0x%2x len=0x%x\n",
+ __func__, addr, datalen);
if ((datalen == 0) || (datalen > 232))
return -EIO;
@@ -1464,7 +1466,8 @@ int saa7164_api_i2c_write(struct saa7164_i2c *bus, u8 addr, u32 datalen,
return -EIO;
}
- dprintk(DBGLVL_API, "%s() len = %d bytes\n", __func__, len);
+ dprintk(DBGLVL_API, "%s() len = %d bytes unitid=0x%x\n", __func__,
+ len, unitid);
/* Prepare the send buffer */
/* Bytes 00-03 dest register length
diff --git a/drivers/media/pci/saa7164/saa7164-buffer.c b/drivers/media/pci/saa7164/saa7164-buffer.c
index 9bd1f73f82da..f30758e24f5d 100644
--- a/drivers/media/pci/saa7164/saa7164-buffer.c
+++ b/drivers/media/pci/saa7164/saa7164-buffer.c
@@ -1,7 +1,7 @@
/*
* Driver for the NXP SAA7164 PCIe bridge
*
- * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ * Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.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
diff --git a/drivers/media/pci/saa7164/saa7164-bus.c b/drivers/media/pci/saa7164/saa7164-bus.c
index 6c73f5b155f6..a18fe5d47238 100644
--- a/drivers/media/pci/saa7164/saa7164-bus.c
+++ b/drivers/media/pci/saa7164/saa7164-bus.c
@@ -1,7 +1,7 @@
/*
* Driver for the NXP SAA7164 PCIe bridge
*
- * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ * Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.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
diff --git a/drivers/media/pci/saa7164/saa7164-cards.c b/drivers/media/pci/saa7164/saa7164-cards.c
index 5b72da5ce418..c2b738227f58 100644
--- a/drivers/media/pci/saa7164/saa7164-cards.c
+++ b/drivers/media/pci/saa7164/saa7164-cards.c
@@ -1,7 +1,7 @@
/*
* Driver for the NXP SAA7164 PCIe bridge
*
- * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ * Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.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
@@ -30,6 +30,7 @@
* attached I2C devices, so we can simplify the virtual i2c mechansms
* and keep the -i2c.c implementation clean.
*/
+#define REGLEN_0bit 0
#define REGLEN_8bit 1
#define REGLEN_16bit 2
@@ -499,6 +500,144 @@ struct saa7164_board saa7164_boards[] = {
.i2c_reg_len = REGLEN_8bit,
} },
},
+ [SAA7164_BOARD_HAUPPAUGE_HVR2255proto] = {
+ .name = "Hauppauge WinTV-HVR2255(proto)",
+ .porta = SAA7164_MPEG_DVB,
+ .portb = SAA7164_MPEG_DVB,
+ .portc = SAA7164_MPEG_ENCODER,
+ .portd = SAA7164_MPEG_ENCODER,
+ .porte = SAA7164_MPEG_VBI,
+ .portf = SAA7164_MPEG_VBI,
+ .chiprev = SAA7164_CHIP_REV3,
+ .unit = {{
+ .id = 0x27,
+ .type = SAA7164_UNIT_EEPROM,
+ .name = "4K EEPROM",
+ .i2c_bus_nr = SAA7164_I2C_BUS_0,
+ .i2c_bus_addr = 0xa0 >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ }, {
+ .id = 0x04,
+ .type = SAA7164_UNIT_TUNER,
+ .name = "SI2157-1",
+ .i2c_bus_nr = SAA7164_I2C_BUS_0,
+ .i2c_bus_addr = 0xc0 >> 1,
+ .i2c_reg_len = REGLEN_0bit,
+ }, {
+ .id = 0x06,
+ .type = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+ .name = "LGDT3306",
+ .i2c_bus_nr = SAA7164_I2C_BUS_2,
+ .i2c_bus_addr = 0xb2 >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ }, {
+ .id = 0x24,
+ .type = SAA7164_UNIT_TUNER,
+ .name = "SI2157-2",
+ .i2c_bus_nr = SAA7164_I2C_BUS_1,
+ .i2c_bus_addr = 0xc0 >> 1,
+ .i2c_reg_len = REGLEN_0bit,
+ }, {
+ .id = 0x26,
+ .type = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+ .name = "LGDT3306-2",
+ .i2c_bus_nr = SAA7164_I2C_BUS_2,
+ .i2c_bus_addr = 0x1c >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ } },
+ },
+ [SAA7164_BOARD_HAUPPAUGE_HVR2255] = {
+ .name = "Hauppauge WinTV-HVR2255",
+ .porta = SAA7164_MPEG_DVB,
+ .portb = SAA7164_MPEG_DVB,
+ .portc = SAA7164_MPEG_ENCODER,
+ .portd = SAA7164_MPEG_ENCODER,
+ .porte = SAA7164_MPEG_VBI,
+ .portf = SAA7164_MPEG_VBI,
+ .chiprev = SAA7164_CHIP_REV3,
+ .unit = {{
+ .id = 0x28,
+ .type = SAA7164_UNIT_EEPROM,
+ .name = "4K EEPROM",
+ .i2c_bus_nr = SAA7164_I2C_BUS_0,
+ .i2c_bus_addr = 0xa0 >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ }, {
+ .id = 0x04,
+ .type = SAA7164_UNIT_TUNER,
+ .name = "SI2157-1",
+ .i2c_bus_nr = SAA7164_I2C_BUS_0,
+ .i2c_bus_addr = 0xc0 >> 1,
+ .i2c_reg_len = REGLEN_0bit,
+ }, {
+ .id = 0x06,
+ .type = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+ .name = "LGDT3306-1",
+ .i2c_bus_nr = SAA7164_I2C_BUS_2,
+ .i2c_bus_addr = 0xb2 >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ }, {
+ .id = 0x25,
+ .type = SAA7164_UNIT_TUNER,
+ .name = "SI2157-2",
+ .i2c_bus_nr = SAA7164_I2C_BUS_1,
+ .i2c_bus_addr = 0xc0 >> 1,
+ .i2c_reg_len = REGLEN_0bit,
+ }, {
+ .id = 0x27,
+ .type = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+ .name = "LGDT3306-2",
+ .i2c_bus_nr = SAA7164_I2C_BUS_2,
+ .i2c_bus_addr = 0x1c >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ } },
+ },
+ [SAA7164_BOARD_HAUPPAUGE_HVR2205] = {
+ .name = "Hauppauge WinTV-HVR2205",
+ .porta = SAA7164_MPEG_DVB,
+ .portb = SAA7164_MPEG_DVB,
+ .portc = SAA7164_MPEG_ENCODER,
+ .portd = SAA7164_MPEG_ENCODER,
+ .porte = SAA7164_MPEG_VBI,
+ .portf = SAA7164_MPEG_VBI,
+ .chiprev = SAA7164_CHIP_REV3,
+ .unit = {{
+ .id = 0x28,
+ .type = SAA7164_UNIT_EEPROM,
+ .name = "4K EEPROM",
+ .i2c_bus_nr = SAA7164_I2C_BUS_0,
+ .i2c_bus_addr = 0xa0 >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ }, {
+ .id = 0x04,
+ .type = SAA7164_UNIT_TUNER,
+ .name = "SI2157-1",
+ .i2c_bus_nr = SAA7164_I2C_BUS_0,
+ .i2c_bus_addr = 0xc0 >> 1,
+ .i2c_reg_len = REGLEN_0bit,
+ }, {
+ .id = 0x06,
+ .type = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+ .name = "SI2168-1",
+ .i2c_bus_nr = SAA7164_I2C_BUS_2,
+ .i2c_bus_addr = 0xc8 >> 1,
+ .i2c_reg_len = REGLEN_0bit,
+ }, {
+ .id = 0x25,
+ .type = SAA7164_UNIT_TUNER,
+ .name = "SI2157-2",
+ .i2c_bus_nr = SAA7164_I2C_BUS_1,
+ .i2c_bus_addr = 0xc0 >> 1,
+ .i2c_reg_len = REGLEN_0bit,
+ }, {
+ .id = 0x27,
+ .type = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+ .name = "SI2168-2",
+ .i2c_bus_nr = SAA7164_I2C_BUS_2,
+ .i2c_bus_addr = 0xcc >> 1,
+ .i2c_reg_len = REGLEN_0bit,
+ } },
+ },
};
const unsigned int saa7164_bcount = ARRAY_SIZE(saa7164_boards);
@@ -546,6 +685,21 @@ struct saa7164_subid saa7164_subids[] = {
.subvendor = 0x0070,
.subdevice = 0x8953,
.card = SAA7164_BOARD_HAUPPAUGE_HVR2200_5,
+ }, {
+ .subvendor = 0x0070,
+ .subdevice = 0xf111,
+ .card = SAA7164_BOARD_HAUPPAUGE_HVR2255,
+ /* Prototype card left here for documenation purposes.
+ .card = SAA7164_BOARD_HAUPPAUGE_HVR2255proto,
+ */
+ }, {
+ .subvendor = 0x0070,
+ .subdevice = 0xf123,
+ .card = SAA7164_BOARD_HAUPPAUGE_HVR2205,
+ }, {
+ .subvendor = 0x0070,
+ .subdevice = 0xf120,
+ .card = SAA7164_BOARD_HAUPPAUGE_HVR2205,
},
};
const unsigned int saa7164_idcount = ARRAY_SIZE(saa7164_subids);
@@ -594,12 +748,26 @@ void saa7164_gpio_setup(struct saa7164_dev *dev)
case SAA7164_BOARD_HAUPPAUGE_HVR2250:
case SAA7164_BOARD_HAUPPAUGE_HVR2250_2:
case SAA7164_BOARD_HAUPPAUGE_HVR2250_3:
+ case SAA7164_BOARD_HAUPPAUGE_HVR2255proto:
+ case SAA7164_BOARD_HAUPPAUGE_HVR2255:
+ case SAA7164_BOARD_HAUPPAUGE_HVR2205:
/*
+ HVR2200 / HVR2250
GPIO 2: s5h1411 / tda10048-1 demod reset
GPIO 3: s5h1411 / tda10048-2 demod reset
GPIO 7: IRBlaster Zilog reset
*/
+ /* HVR2255
+ * GPIO 2: lgdg3306-1 demod reset
+ * GPIO 3: lgdt3306-2 demod reset
+ */
+
+ /* HVR2205
+ * GPIO 2: si2168-1 demod reset
+ * GPIO 3: si2168-2 demod reset
+ */
+
/* Reset parts by going in and out of reset */
saa7164_api_clear_gpiobit(dev, PCIEBRIDGE_UNITID, 2);
saa7164_api_clear_gpiobit(dev, PCIEBRIDGE_UNITID, 3);
@@ -647,6 +815,21 @@ static void hauppauge_eeprom(struct saa7164_dev *dev, u8 *eeprom_data)
/* WinTV-HVR2200 (PCIe, Retail, half-height)
* DVB-T (TDA18271/TDA10048) and basic analog, no IR */
break;
+ case 151009:
+ /* First production board rev B2I6 */
+ /* WinTV-HVR2205 (PCIe, Retail, full-height bracket)
+ * DVB-T/T2/C (SI2157/SI2168) and basic analog, FM */
+ break;
+ case 151609:
+ /* First production board rev B2I6 */
+ /* WinTV-HVR2205 (PCIe, Retail, half-height bracket)
+ * DVB-T/T2/C (SI2157/SI2168) and basic analog, FM */
+ break;
+ case 151061:
+ /* First production board rev B1I6 */
+ /* WinTV-HVR2255 (PCIe, Retail, full-height bracket)
+ * ATSC/QAM (SI2157/LGDT3306) and basic analog, FM */
+ break;
default:
printk(KERN_ERR "%s: Warning: Unknown Hauppauge model #%d\n",
dev->name, tv.model);
@@ -676,6 +859,9 @@ void saa7164_card_setup(struct saa7164_dev *dev)
case SAA7164_BOARD_HAUPPAUGE_HVR2250:
case SAA7164_BOARD_HAUPPAUGE_HVR2250_2:
case SAA7164_BOARD_HAUPPAUGE_HVR2250_3:
+ case SAA7164_BOARD_HAUPPAUGE_HVR2255proto:
+ case SAA7164_BOARD_HAUPPAUGE_HVR2255:
+ case SAA7164_BOARD_HAUPPAUGE_HVR2205:
hauppauge_eeprom(dev, &eeprom[0]);
break;
}
diff --git a/drivers/media/pci/saa7164/saa7164-cmd.c b/drivers/media/pci/saa7164/saa7164-cmd.c
index cfabcbacc33d..3285c37b4583 100644
--- a/drivers/media/pci/saa7164/saa7164-cmd.c
+++ b/drivers/media/pci/saa7164/saa7164-cmd.c
@@ -1,7 +1,7 @@
/*
* Driver for the NXP SAA7164 PCIe bridge
*
- * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ * Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.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
diff --git a/drivers/media/pci/saa7164/saa7164-core.c b/drivers/media/pci/saa7164/saa7164-core.c
index 9cf3c6cba498..3206a826b80d 100644
--- a/drivers/media/pci/saa7164/saa7164-core.c
+++ b/drivers/media/pci/saa7164/saa7164-core.c
@@ -1,7 +1,7 @@
/*
* Driver for the NXP SAA7164 PCIe bridge
*
- * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ * Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.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
@@ -85,6 +85,11 @@ module_param(guard_checking, int, 0644);
MODULE_PARM_DESC(guard_checking,
"enable dma sanity checking for buffer overruns");
+static bool enable_msi = true;
+module_param(enable_msi, bool, 0444);
+MODULE_PARM_DESC(enable_msi,
+ "enable the use of an msi interrupt if available");
+
static unsigned int saa7164_devcount;
static DEFINE_MUTEX(devlist);
@@ -618,12 +623,7 @@ static irqreturn_t saa7164_irq_ts(struct saa7164_port *port)
static irqreturn_t saa7164_irq(int irq, void *dev_id)
{
struct saa7164_dev *dev = dev_id;
- struct saa7164_port *porta = &dev->ports[SAA7164_PORT_TS1];
- struct saa7164_port *portb = &dev->ports[SAA7164_PORT_TS2];
- struct saa7164_port *portc = &dev->ports[SAA7164_PORT_ENC1];
- struct saa7164_port *portd = &dev->ports[SAA7164_PORT_ENC2];
- struct saa7164_port *porte = &dev->ports[SAA7164_PORT_VBI1];
- struct saa7164_port *portf = &dev->ports[SAA7164_PORT_VBI2];
+ struct saa7164_port *porta, *portb, *portc, *portd, *porte, *portf;
u32 intid, intstat[INT_SIZE/4];
int i, handled = 0, bit;
@@ -634,6 +634,13 @@ static irqreturn_t saa7164_irq(int irq, void *dev_id)
goto out;
}
+ porta = &dev->ports[SAA7164_PORT_TS1];
+ portb = &dev->ports[SAA7164_PORT_TS2];
+ portc = &dev->ports[SAA7164_PORT_ENC1];
+ portd = &dev->ports[SAA7164_PORT_ENC2];
+ porte = &dev->ports[SAA7164_PORT_VBI1];
+ portf = &dev->ports[SAA7164_PORT_VBI2];
+
/* Check that the hardware is accessible. If the status bytes are
* 0xFF then the device is not accessible, the the IRQ belongs
* to another driver.
@@ -1184,6 +1191,39 @@ static int saa7164_thread_function(void *data)
return 0;
}
+static bool saa7164_enable_msi(struct pci_dev *pci_dev, struct saa7164_dev *dev)
+{
+ int err;
+
+ if (!enable_msi) {
+ printk(KERN_WARNING "%s() MSI disabled by module parameter 'enable_msi'"
+ , __func__);
+ return false;
+ }
+
+ err = pci_enable_msi(pci_dev);
+
+ if (err) {
+ printk(KERN_ERR "%s() Failed to enable MSI interrupt."
+ " Falling back to a shared IRQ\n", __func__);
+ return false;
+ }
+
+ /* no error - so request an msi interrupt */
+ err = request_irq(pci_dev->irq, saa7164_irq, 0,
+ dev->name, dev);
+
+ if (err) {
+ /* fall back to legacy interrupt */
+ printk(KERN_ERR "%s() Failed to get an MSI interrupt."
+ " Falling back to a shared IRQ\n", __func__);
+ pci_disable_msi(pci_dev);
+ return false;
+ }
+
+ return true;
+}
+
static int saa7164_initdev(struct pci_dev *pci_dev,
const struct pci_device_id *pci_id)
{
@@ -1230,13 +1270,22 @@ static int saa7164_initdev(struct pci_dev *pci_dev,
goto fail_irq;
}
- err = request_irq(pci_dev->irq, saa7164_irq,
- IRQF_SHARED, dev->name, dev);
- if (err < 0) {
- printk(KERN_ERR "%s: can't get IRQ %d\n", dev->name,
- pci_dev->irq);
- err = -EIO;
- goto fail_irq;
+ /* irq bit */
+ if (saa7164_enable_msi(pci_dev, dev)) {
+ dev->msi = true;
+ } else {
+ /* if we have an error (i.e. we don't have an interrupt)
+ or msi is not enabled - fallback to shared interrupt */
+
+ err = request_irq(pci_dev->irq, saa7164_irq,
+ IRQF_SHARED, dev->name, dev);
+
+ if (err < 0) {
+ printk(KERN_ERR "%s: can't get IRQ %d\n", dev->name,
+ pci_dev->irq);
+ err = -EIO;
+ goto fail_irq;
+ }
}
pci_set_drvdata(pci_dev, dev);
@@ -1439,6 +1488,11 @@ static void saa7164_finidev(struct pci_dev *pci_dev)
/* unregister stuff */
free_irq(pci_dev->irq, dev);
+ if (dev->msi) {
+ pci_disable_msi(pci_dev);
+ dev->msi = false;
+ }
+
pci_disable_device(pci_dev);
mutex_lock(&devlist);
diff --git a/drivers/media/pci/saa7164/saa7164-dvb.c b/drivers/media/pci/saa7164/saa7164-dvb.c
index 16ae71592e8c..e9a783b71b45 100644
--- a/drivers/media/pci/saa7164/saa7164-dvb.c
+++ b/drivers/media/pci/saa7164/saa7164-dvb.c
@@ -1,7 +1,7 @@
/*
* Driver for the NXP SAA7164 PCIe bridge
*
- * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ * Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.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
@@ -24,6 +24,9 @@
#include "tda10048.h"
#include "tda18271.h"
#include "s5h1411.h"
+#include "si2157.h"
+#include "si2168.h"
+#include "lgdt3306a.h"
#define DRIVER_NAME "saa7164"
@@ -82,6 +85,65 @@ static struct s5h1411_config hauppauge_s5h1411_config = {
.mpeg_timing = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
};
+static struct lgdt3306a_config hauppauge_hvr2255a_config = {
+ .i2c_addr = 0xb2 >> 1,
+ .qam_if_khz = 4000,
+ .vsb_if_khz = 3250,
+ .deny_i2c_rptr = 1, /* Disabled */
+ .spectral_inversion = 0, /* Disabled */
+ .mpeg_mode = LGDT3306A_MPEG_SERIAL,
+ .tpclk_edge = LGDT3306A_TPCLK_RISING_EDGE,
+ .tpvalid_polarity = LGDT3306A_TP_VALID_HIGH,
+ .xtalMHz = 25, /* 24 or 25 */
+};
+
+static struct lgdt3306a_config hauppauge_hvr2255b_config = {
+ .i2c_addr = 0x1c >> 1,
+ .qam_if_khz = 4000,
+ .vsb_if_khz = 3250,
+ .deny_i2c_rptr = 1, /* Disabled */
+ .spectral_inversion = 0, /* Disabled */
+ .mpeg_mode = LGDT3306A_MPEG_SERIAL,
+ .tpclk_edge = LGDT3306A_TPCLK_RISING_EDGE,
+ .tpvalid_polarity = LGDT3306A_TP_VALID_HIGH,
+ .xtalMHz = 25, /* 24 or 25 */
+};
+
+static struct si2157_config hauppauge_hvr2255_tuner_config = {
+ .inversion = 1,
+ .if_port = 1,
+};
+
+static int si2157_attach(struct saa7164_port *port, struct i2c_adapter *adapter,
+ struct dvb_frontend *fe, u8 addr8bit, struct si2157_config *cfg)
+{
+ struct i2c_board_info bi;
+ struct i2c_client *tuner;
+
+ cfg->fe = fe;
+
+ memset(&bi, 0, sizeof(bi));
+
+ strlcpy(bi.type, "si2157", I2C_NAME_SIZE);
+ bi.platform_data = cfg;
+ bi.addr = addr8bit >> 1;
+
+ request_module(bi.type);
+
+ tuner = i2c_new_device(adapter, &bi);
+ if (tuner == NULL || tuner->dev.driver == NULL)
+ return -ENODEV;
+
+ if (!try_module_get(tuner->dev.driver->owner)) {
+ i2c_unregister_device(tuner);
+ return -ENODEV;
+ }
+
+ port->i2c_client_tuner = tuner;
+
+ return 0;
+}
+
static int saa7164_dvb_stop_port(struct saa7164_port *port)
{
struct saa7164_dev *dev = port->dev;
@@ -242,14 +304,16 @@ static int saa7164_dvb_start_feed(struct dvb_demux_feed *feed)
if (!demux->dmx.frontend)
return -EINVAL;
- mutex_lock(&dvb->lock);
- if (dvb->feeding++ == 0) {
- /* Start transport */
- ret = saa7164_dvb_start_port(port);
+ if (dvb) {
+ mutex_lock(&dvb->lock);
+ if (dvb->feeding++ == 0) {
+ /* Start transport */
+ ret = saa7164_dvb_start_port(port);
+ }
+ mutex_unlock(&dvb->lock);
+ dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
+ __func__, port->nr, dvb->feeding);
}
- mutex_unlock(&dvb->lock);
- dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
- __func__, port->nr, dvb->feeding);
return ret;
}
@@ -264,14 +328,16 @@ static int saa7164_dvb_stop_feed(struct dvb_demux_feed *feed)
dprintk(DBGLVL_DVB, "%s(port=%d)\n", __func__, port->nr);
- mutex_lock(&dvb->lock);
- if (--dvb->feeding == 0) {
- /* Stop transport */
- ret = saa7164_dvb_stop_streaming(port);
+ if (dvb) {
+ mutex_lock(&dvb->lock);
+ if (--dvb->feeding == 0) {
+ /* Stop transport */
+ ret = saa7164_dvb_stop_streaming(port);
+ }
+ mutex_unlock(&dvb->lock);
+ dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
+ __func__, port->nr, dvb->feeding);
}
- mutex_unlock(&dvb->lock);
- dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
- __func__, port->nr, dvb->feeding);
return ret;
}
@@ -425,6 +491,7 @@ int saa7164_dvb_unregister(struct saa7164_port *port)
struct saa7164_dev *dev = port->dev;
struct saa7164_buffer *b;
struct list_head *c, *n;
+ struct i2c_client *client;
dprintk(DBGLVL_DVB, "%s()\n", __func__);
@@ -443,6 +510,20 @@ int saa7164_dvb_unregister(struct saa7164_port *port)
if (dvb->frontend == NULL)
return 0;
+ /* remove I2C client for tuner */
+ client = port->i2c_client_tuner;
+ if (client) {
+ module_put(client->dev.driver->owner);
+ i2c_unregister_device(client);
+ }
+
+ /* remove I2C client for demodulator */
+ client = port->i2c_client_demod;
+ if (client) {
+ module_put(client->dev.driver->owner);
+ i2c_unregister_device(client);
+ }
+
dvb_net_release(&dvb->net);
dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
@@ -462,6 +543,12 @@ int saa7164_dvb_register(struct saa7164_port *port)
struct saa7164_dev *dev = port->dev;
struct saa7164_dvb *dvb = &port->dvb;
struct saa7164_i2c *i2c_bus = NULL;
+ struct si2168_config si2168_config;
+ struct si2157_config si2157_config;
+ struct i2c_adapter *adapter;
+ struct i2c_board_info info;
+ struct i2c_client *client_demod;
+ struct i2c_client *client_tuner;
int ret;
dprintk(DBGLVL_DVB, "%s()\n", __func__);
@@ -528,6 +615,126 @@ int saa7164_dvb_register(struct saa7164_port *port)
}
break;
+ case SAA7164_BOARD_HAUPPAUGE_HVR2255proto:
+ case SAA7164_BOARD_HAUPPAUGE_HVR2255:
+ i2c_bus = &dev->i2c_bus[2];
+
+ if (port->nr == 0) {
+ port->dvb.frontend = dvb_attach(lgdt3306a_attach,
+ &hauppauge_hvr2255a_config, &i2c_bus->i2c_adap);
+ } else {
+ port->dvb.frontend = dvb_attach(lgdt3306a_attach,
+ &hauppauge_hvr2255b_config, &i2c_bus->i2c_adap);
+ }
+
+ if (port->dvb.frontend != NULL) {
+
+ if (port->nr == 0) {
+ si2157_attach(port, &dev->i2c_bus[0].i2c_adap,
+ port->dvb.frontend, 0xc0,
+ &hauppauge_hvr2255_tuner_config);
+ } else {
+ si2157_attach(port, &dev->i2c_bus[1].i2c_adap,
+ port->dvb.frontend, 0xc0,
+ &hauppauge_hvr2255_tuner_config);
+ }
+ }
+ break;
+ case SAA7164_BOARD_HAUPPAUGE_HVR2205:
+
+ if (port->nr == 0) {
+ /* attach frontend */
+ memset(&si2168_config, 0, sizeof(si2168_config));
+ si2168_config.i2c_adapter = &adapter;
+ si2168_config.fe = &port->dvb.frontend;
+ si2168_config.ts_mode = SI2168_TS_SERIAL;
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ strlcpy(info.type, "si2168", I2C_NAME_SIZE);
+ info.addr = 0xc8 >> 1;
+ info.platform_data = &si2168_config;
+ request_module(info.type);
+ client_demod = i2c_new_device(&dev->i2c_bus[2].i2c_adap,
+ &info);
+ if (!client_demod || !client_demod->dev.driver)
+ goto frontend_detach;
+
+ if (!try_module_get(client_demod->dev.driver->owner)) {
+ i2c_unregister_device(client_demod);
+ goto frontend_detach;
+ }
+ port->i2c_client_demod = client_demod;
+
+ /* attach tuner */
+ memset(&si2157_config, 0, sizeof(si2157_config));
+ si2157_config.if_port = 1;
+ si2157_config.fe = port->dvb.frontend;
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ strlcpy(info.type, "si2157", I2C_NAME_SIZE);
+ info.addr = 0xc0 >> 1;
+ info.platform_data = &si2157_config;
+ request_module(info.type);
+ client_tuner = i2c_new_device(&dev->i2c_bus[0].i2c_adap,
+ &info);
+ if (!client_tuner || !client_tuner->dev.driver) {
+ module_put(client_demod->dev.driver->owner);
+ i2c_unregister_device(client_demod);
+ goto frontend_detach;
+ }
+ if (!try_module_get(client_tuner->dev.driver->owner)) {
+ i2c_unregister_device(client_tuner);
+ module_put(client_demod->dev.driver->owner);
+ i2c_unregister_device(client_demod);
+ goto frontend_detach;
+ }
+ port->i2c_client_tuner = client_tuner;
+ } else {
+ /* attach frontend */
+ memset(&si2168_config, 0, sizeof(si2168_config));
+ si2168_config.i2c_adapter = &adapter;
+ si2168_config.fe = &port->dvb.frontend;
+ si2168_config.ts_mode = SI2168_TS_SERIAL;
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ strlcpy(info.type, "si2168", I2C_NAME_SIZE);
+ info.addr = 0xcc >> 1;
+ info.platform_data = &si2168_config;
+ request_module(info.type);
+ client_demod = i2c_new_device(&dev->i2c_bus[2].i2c_adap,
+ &info);
+ if (!client_demod || !client_demod->dev.driver)
+ goto frontend_detach;
+
+ if (!try_module_get(client_demod->dev.driver->owner)) {
+ i2c_unregister_device(client_demod);
+ goto frontend_detach;
+ }
+ port->i2c_client_demod = client_demod;
+
+ /* attach tuner */
+ memset(&si2157_config, 0, sizeof(si2157_config));
+ si2157_config.fe = port->dvb.frontend;
+ si2157_config.if_port = 1;
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ strlcpy(info.type, "si2157", I2C_NAME_SIZE);
+ info.addr = 0xc0 >> 1;
+ info.platform_data = &si2157_config;
+ request_module(info.type);
+ client_tuner = i2c_new_device(&dev->i2c_bus[1].i2c_adap,
+ &info);
+ if (!client_tuner || !client_tuner->dev.driver) {
+ module_put(client_demod->dev.driver->owner);
+ i2c_unregister_device(client_demod);
+ goto frontend_detach;
+ }
+ if (!try_module_get(client_tuner->dev.driver->owner)) {
+ i2c_unregister_device(client_tuner);
+ module_put(client_demod->dev.driver->owner);
+ i2c_unregister_device(client_demod);
+ goto frontend_detach;
+ }
+ port->i2c_client_tuner = client_tuner;
+ }
+
+ break;
default:
printk(KERN_ERR "%s: The frontend isn't supported\n",
dev->name);
@@ -548,5 +755,9 @@ int saa7164_dvb_register(struct saa7164_port *port)
}
return 0;
+
+frontend_detach:
+ printk(KERN_ERR "%s() Frontend/I2C initialization failed\n", __func__);
+ return -1;
}
diff --git a/drivers/media/pci/saa7164/saa7164-encoder.c b/drivers/media/pci/saa7164/saa7164-encoder.c
index 9266965412c3..4434e0f28c26 100644
--- a/drivers/media/pci/saa7164/saa7164-encoder.c
+++ b/drivers/media/pci/saa7164/saa7164-encoder.c
@@ -1,7 +1,7 @@
/*
* Driver for the NXP SAA7164 PCIe bridge
*
- * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ * Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.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
@@ -721,13 +721,14 @@ static int vidioc_querycap(struct file *file, void *priv,
sizeof(cap->card));
sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
- cap->capabilities =
+ cap->device_caps =
V4L2_CAP_VIDEO_CAPTURE |
- V4L2_CAP_READWRITE |
- 0;
+ V4L2_CAP_READWRITE |
+ V4L2_CAP_TUNER;
- cap->capabilities |= V4L2_CAP_TUNER;
- cap->version = 0;
+ cap->capabilities = cap->device_caps |
+ V4L2_CAP_VBI_CAPTURE |
+ V4L2_CAP_DEVICE_CAPS;
return 0;
}
diff --git a/drivers/media/pci/saa7164/saa7164-fw.c b/drivers/media/pci/saa7164/saa7164-fw.c
index add06ab5124d..269e0782c7b6 100644
--- a/drivers/media/pci/saa7164/saa7164-fw.c
+++ b/drivers/media/pci/saa7164/saa7164-fw.c
@@ -1,7 +1,7 @@
/*
* Driver for the NXP SAA7164 PCIe bridge
*
- * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ * Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.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
diff --git a/drivers/media/pci/saa7164/saa7164-i2c.c b/drivers/media/pci/saa7164/saa7164-i2c.c
index 4f7e3b42263f..0342d84913b8 100644
--- a/drivers/media/pci/saa7164/saa7164-i2c.c
+++ b/drivers/media/pci/saa7164/saa7164-i2c.c
@@ -1,7 +1,7 @@
/*
* Driver for the NXP SAA7164 PCIe bridge
*
- * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ * Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.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
@@ -39,9 +39,10 @@ static int i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
dprintk(DBGLVL_I2C, "%s(num = %d) addr = 0x%02x len = 0x%x\n",
__func__, num, msgs[i].addr, msgs[i].len);
if (msgs[i].flags & I2C_M_RD) {
- /* Unsupported - Yet*/
- printk(KERN_ERR "%s() Unsupported - Yet\n", __func__);
- continue;
+ retval = saa7164_api_i2c_read(bus,
+ msgs[i].addr,
+ 0 /* reglen */,
+ NULL /* reg */, msgs[i].len, msgs[i].buf);
} else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) &&
msgs[i].addr == msgs[i + 1].addr) {
/* write then read from same address */
diff --git a/drivers/media/pci/saa7164/saa7164-reg.h b/drivers/media/pci/saa7164/saa7164-reg.h
index 2bbf81583d33..37521a2ee504 100644
--- a/drivers/media/pci/saa7164/saa7164-reg.h
+++ b/drivers/media/pci/saa7164/saa7164-reg.h
@@ -1,7 +1,7 @@
/*
* Driver for the NXP SAA7164 PCIe bridge
*
- * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ * Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.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
diff --git a/drivers/media/pci/saa7164/saa7164-types.h b/drivers/media/pci/saa7164/saa7164-types.h
index f48ba978f835..1efba6c64ebf 100644
--- a/drivers/media/pci/saa7164/saa7164-types.h
+++ b/drivers/media/pci/saa7164/saa7164-types.h
@@ -1,7 +1,7 @@
/*
* Driver for the NXP SAA7164 PCIe bridge
*
- * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ * Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.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
diff --git a/drivers/media/pci/saa7164/saa7164-vbi.c b/drivers/media/pci/saa7164/saa7164-vbi.c
index 6e025fea2542..859fd03d82f9 100644
--- a/drivers/media/pci/saa7164/saa7164-vbi.c
+++ b/drivers/media/pci/saa7164/saa7164-vbi.c
@@ -1,7 +1,7 @@
/*
* Driver for the NXP SAA7164 PCIe bridge
*
- * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ * Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.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
@@ -660,13 +660,14 @@ static int vidioc_querycap(struct file *file, void *priv,
sizeof(cap->card));
sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
- cap->capabilities =
+ cap->device_caps =
V4L2_CAP_VBI_CAPTURE |
- V4L2_CAP_READWRITE |
- 0;
+ V4L2_CAP_READWRITE |
+ V4L2_CAP_TUNER;
- cap->capabilities |= V4L2_CAP_TUNER;
- cap->version = 0;
+ cap->capabilities = cap->device_caps |
+ V4L2_CAP_VIDEO_CAPTURE |
+ V4L2_CAP_DEVICE_CAPS;
return 0;
}
diff --git a/drivers/media/pci/saa7164/saa7164.h b/drivers/media/pci/saa7164/saa7164.h
index cd1a07ce27cb..18906e0c80e1 100644
--- a/drivers/media/pci/saa7164/saa7164.h
+++ b/drivers/media/pci/saa7164/saa7164.h
@@ -1,7 +1,7 @@
/*
* Driver for the NXP SAA7164 PCIe bridge
*
- * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ * Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.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
@@ -83,6 +83,9 @@
#define SAA7164_BOARD_HAUPPAUGE_HVR2250_3 8
#define SAA7164_BOARD_HAUPPAUGE_HVR2200_4 9
#define SAA7164_BOARD_HAUPPAUGE_HVR2200_5 10
+#define SAA7164_BOARD_HAUPPAUGE_HVR2255proto 11
+#define SAA7164_BOARD_HAUPPAUGE_HVR2255 12
+#define SAA7164_BOARD_HAUPPAUGE_HVR2205 13
#define SAA7164_MAX_UNITS 8
#define SAA7164_TS_NUMBER_OF_LINES 312
@@ -371,6 +374,8 @@ struct saa7164_port {
/* --- DVB Transport Specific --- */
struct saa7164_dvb dvb;
+ struct i2c_client *i2c_client_demod;
+ struct i2c_client *i2c_client_tuner;
/* --- Encoder/V4L related attributes --- */
/* Encoder */
@@ -459,6 +464,7 @@ struct saa7164_dev {
/* Interrupt status and ack registers */
u32 int_status;
u32 int_ack;
+ bool msi;
struct cmd cmds[SAA_CMD_MAX_MSG_UNITS];
struct mutex lock;
diff --git a/drivers/media/pci/smipcie/smipcie.c b/drivers/media/pci/smipcie/smipcie.c
index 411592524c63..143fd7899ecd 100644
--- a/drivers/media/pci/smipcie/smipcie.c
+++ b/drivers/media/pci/smipcie/smipcie.c
@@ -657,6 +657,7 @@ static int smi_dvbsky_sit2_fe_attach(struct smi_port *port)
/* attach tuner */
memset(&si2157_config, 0, sizeof(si2157_config));
si2157_config.fe = port->fe;
+ si2157_config.if_port = 1;
memset(&client_info, 0, sizeof(struct i2c_board_info));
strlcpy(client_info.type, "si2157", I2C_NAME_SIZE);
diff --git a/drivers/media/pci/sta2x11/sta2x11_vip.c b/drivers/media/pci/sta2x11/sta2x11_vip.c
index d384a6b0b09f..59b3a36a3639 100644
--- a/drivers/media/pci/sta2x11/sta2x11_vip.c
+++ b/drivers/media/pci/sta2x11/sta2x11_vip.c
@@ -813,7 +813,7 @@ static irqreturn_t vip_irq(int irq, struct sta2x11_vip *vip)
/* Disable acquisition */
reg_write(vip, DVP_CTL, reg_read(vip, DVP_CTL) & ~DVP_CTL_ENA);
/* Remove the active buffer from the list */
- do_gettimeofday(&vip->active->vb.v4l2_buf.timestamp);
+ v4l2_get_timestamp(&vip->active->vb.v4l2_buf.timestamp);
vip->active->vb.v4l2_buf.sequence = vip->sequence++;
vb2_buffer_done(&vip->active->vb, VB2_BUF_STATE_DONE);
}
@@ -864,6 +864,7 @@ static int sta2x11_vip_init_buffer(struct sta2x11_vip *vip)
vip->vb_vidq.buf_struct_size = sizeof(struct vip_buffer);
vip->vb_vidq.ops = &vip_video_qops;
vip->vb_vidq.mem_ops = &vb2_dma_contig_memops;
+ vip->vb_vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
err = vb2_queue_init(&vip->vb_vidq);
if (err)
return err;
diff --git a/drivers/media/pci/ttpci/av7110.c b/drivers/media/pci/ttpci/av7110.c
index 45199a12b9d9..3f24fce74fc1 100644
--- a/drivers/media/pci/ttpci/av7110.c
+++ b/drivers/media/pci/ttpci/av7110.c
@@ -1172,7 +1172,7 @@ static int dvb_get_stc(struct dmx_demux *demux, unsigned int num,
******************************************************************************/
-static int av7110_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+static int av7110_set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone)
{
struct av7110* av7110 = fe->dvb->priv;
@@ -1197,7 +1197,7 @@ static int av7110_diseqc_send_master_cmd(struct dvb_frontend* fe,
}
static int av7110_diseqc_send_burst(struct dvb_frontend* fe,
- fe_sec_mini_cmd_t minicmd)
+ enum fe_sec_mini_cmd minicmd)
{
struct av7110* av7110 = fe->dvb->priv;
@@ -1946,7 +1946,7 @@ static struct l64781_config grundig_29504_401_config = {
-static int av7110_fe_lock_fix(struct av7110* av7110, fe_status_t status)
+static int av7110_fe_lock_fix(struct av7110 *av7110, enum fe_status status)
{
int ret = 0;
int synced = (status & FE_HAS_LOCK) ? 1 : 0;
@@ -2008,7 +2008,8 @@ static int av7110_fe_init(struct dvb_frontend* fe)
return ret;
}
-static int av7110_fe_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int av7110_fe_read_status(struct dvb_frontend *fe,
+ enum fe_status *status)
{
struct av7110* av7110 = fe->dvb->priv;
@@ -2043,7 +2044,8 @@ static int av7110_fe_diseqc_send_master_cmd(struct dvb_frontend* fe,
return ret;
}
-static int av7110_fe_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
+static int av7110_fe_diseqc_send_burst(struct dvb_frontend *fe,
+ enum fe_sec_mini_cmd minicmd)
{
struct av7110* av7110 = fe->dvb->priv;
@@ -2055,7 +2057,8 @@ static int av7110_fe_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_
return ret;
}
-static int av7110_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+static int av7110_fe_set_tone(struct dvb_frontend *fe,
+ enum fe_sec_tone_mode tone)
{
struct av7110* av7110 = fe->dvb->priv;
@@ -2067,7 +2070,8 @@ static int av7110_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
return ret;
}
-static int av7110_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+static int av7110_fe_set_voltage(struct dvb_frontend *fe,
+ enum fe_sec_voltage voltage)
{
struct av7110* av7110 = fe->dvb->priv;
diff --git a/drivers/media/pci/ttpci/av7110.h b/drivers/media/pci/ttpci/av7110.h
index 835635b0c712..3a55927edb95 100644
--- a/drivers/media/pci/ttpci/av7110.h
+++ b/drivers/media/pci/ttpci/av7110.h
@@ -269,25 +269,30 @@ struct av7110 {
unsigned long size_root;
struct dvb_frontend* fe;
- fe_status_t fe_status;
+ enum fe_status fe_status;
struct mutex ioctl_mutex;
/* crash recovery */
void (*recover)(struct av7110* av7110);
- fe_sec_voltage_t saved_voltage;
- fe_sec_tone_mode_t saved_tone;
+ enum fe_sec_voltage saved_voltage;
+ enum fe_sec_tone_mode saved_tone;
struct dvb_diseqc_master_cmd saved_master_cmd;
- fe_sec_mini_cmd_t saved_minicmd;
+ enum fe_sec_mini_cmd saved_minicmd;
int (*fe_init)(struct dvb_frontend* fe);
- int (*fe_read_status)(struct dvb_frontend* fe, fe_status_t* status);
- int (*fe_diseqc_reset_overload)(struct dvb_frontend* fe);
- int (*fe_diseqc_send_master_cmd)(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd);
- int (*fe_diseqc_send_burst)(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd);
- int (*fe_set_tone)(struct dvb_frontend* fe, fe_sec_tone_mode_t tone);
- int (*fe_set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage);
- int (*fe_dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd);
+ int (*fe_read_status)(struct dvb_frontend *fe, enum fe_status *status);
+ int (*fe_diseqc_reset_overload)(struct dvb_frontend *fe);
+ int (*fe_diseqc_send_master_cmd)(struct dvb_frontend *fe,
+ struct dvb_diseqc_master_cmd *cmd);
+ int (*fe_diseqc_send_burst)(struct dvb_frontend *fe,
+ enum fe_sec_mini_cmd minicmd);
+ int (*fe_set_tone)(struct dvb_frontend *fe,
+ enum fe_sec_tone_mode tone);
+ int (*fe_set_voltage)(struct dvb_frontend *fe,
+ enum fe_sec_voltage voltage);
+ int (*fe_dishnetwork_send_legacy_command)(struct dvb_frontend *fe,
+ unsigned long cmd);
int (*fe_set_frontend)(struct dvb_frontend *fe);
};
diff --git a/drivers/media/pci/ttpci/budget-core.c b/drivers/media/pci/ttpci/budget-core.c
index 23e05499b509..e9674b40007c 100644
--- a/drivers/media/pci/ttpci/budget-core.c
+++ b/drivers/media/pci/ttpci/budget-core.c
@@ -161,7 +161,8 @@ static int start_ts_capture(struct budget *budget)
return 0;
}
-static int budget_read_fe_status(struct dvb_frontend *fe, fe_status_t *status)
+static int budget_read_fe_status(struct dvb_frontend *fe,
+ enum fe_status *status)
{
struct budget *budget = (struct budget *) fe->dvb->priv;
int synced;
diff --git a/drivers/media/pci/ttpci/budget-patch.c b/drivers/media/pci/ttpci/budget-patch.c
index a4d8867e1d7b..b5b65962ce8f 100644
--- a/drivers/media/pci/ttpci/budget-patch.c
+++ b/drivers/media/pci/ttpci/budget-patch.c
@@ -128,9 +128,9 @@ static int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long
return 0;
}
-/* shamelessly copy/pasted from budget.c
-*/
-static int budget_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+/* shamelessly copy/pasted from budget.c */
+static int budget_set_tone(struct dvb_frontend *fe,
+ enum fe_sec_tone_mode tone)
{
struct budget* budget = (struct budget*) fe->dvb->priv;
@@ -159,7 +159,8 @@ static int budget_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_dis
return 0;
}
-static int budget_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
+static int budget_diseqc_send_burst(struct dvb_frontend *fe,
+ enum fe_sec_mini_cmd minicmd)
{
struct budget* budget = (struct budget*) fe->dvb->priv;
@@ -223,7 +224,8 @@ static int av7110_send_diseqc_msg(struct budget_patch *budget, int len, u8 *msg,
return 0;
}
-static int budget_patch_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+static int budget_patch_set_tone(struct dvb_frontend *fe,
+ enum fe_sec_tone_mode tone)
{
struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
@@ -252,7 +254,8 @@ static int budget_patch_diseqc_send_master_cmd(struct dvb_frontend* fe, struct d
return 0;
}
-static int budget_patch_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
+static int budget_patch_diseqc_send_burst(struct dvb_frontend *fe,
+ enum fe_sec_mini_cmd minicmd)
{
struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
diff --git a/drivers/media/pci/ttpci/budget.c b/drivers/media/pci/ttpci/budget.c
index 6ccc48833fd8..99972beca262 100644
--- a/drivers/media/pci/ttpci/budget.c
+++ b/drivers/media/pci/ttpci/budget.c
@@ -132,7 +132,8 @@ static int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long
* Voltage must be set here.
* GPIO 1: LNBP EN, GPIO 2: LNBP VSEL
*/
-static int SetVoltage_Activy (struct budget *budget, fe_sec_voltage_t voltage)
+static int SetVoltage_Activy(struct budget *budget,
+ enum fe_sec_voltage voltage)
{
struct saa7146_dev *dev=budget->dev;
@@ -157,14 +158,16 @@ static int SetVoltage_Activy (struct budget *budget, fe_sec_voltage_t voltage)
return 0;
}
-static int siemens_budget_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+static int siemens_budget_set_voltage(struct dvb_frontend *fe,
+ enum fe_sec_voltage voltage)
{
struct budget* budget = (struct budget*) fe->dvb->priv;
return SetVoltage_Activy (budget, voltage);
}
-static int budget_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+static int budget_set_tone(struct dvb_frontend *fe,
+ enum fe_sec_tone_mode tone)
{
struct budget* budget = (struct budget*) fe->dvb->priv;
@@ -193,7 +196,8 @@ static int budget_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_dis
return 0;
}
-static int budget_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
+static int budget_diseqc_send_burst(struct dvb_frontend *fe,
+ enum fe_sec_mini_cmd minicmd)
{
struct budget* budget = (struct budget*) fe->dvb->priv;
diff --git a/drivers/media/pci/ttpci/budget.h b/drivers/media/pci/ttpci/budget.h
index 3d8a806c20bb..1ccbe1a49a4b 100644
--- a/drivers/media/pci/ttpci/budget.h
+++ b/drivers/media/pci/ttpci/budget.h
@@ -72,7 +72,7 @@ struct budget {
struct dvb_adapter dvb_adapter;
struct dvb_frontend *dvb_frontend;
- int (*read_fe_status)(struct dvb_frontend *fe, fe_status_t *status);
+ int (*read_fe_status)(struct dvb_frontend *fe, enum fe_status *status);
int fe_synced;
void *priv;
diff --git a/drivers/media/pci/zoran/zoran_device.c b/drivers/media/pci/zoran/zoran_device.c
index b6801e035ea4..40119b3c52c1 100644
--- a/drivers/media/pci/zoran/zoran_device.c
+++ b/drivers/media/pci/zoran/zoran_device.c
@@ -1584,14 +1584,11 @@ zoran_init_hardware (struct zoran *zr)
jpeg_codec_sleep(zr, 1);
jpeg_codec_sleep(zr, 0);
- /* set individual interrupt enables (without GIRQ1)
- * but don't global enable until zoran_open() */
-
- //btwrite(IRQ_MASK & ~ZR36057_ISR_GIRQ1, ZR36057_ICR); // SW
- // It looks like using only JPEGRepIRQEn is not always reliable,
- // may be when JPEG codec crashes it won't generate IRQ? So,
- /*CP*/ // btwrite(IRQ_MASK, ZR36057_ICR); // Enable Vsync interrupts too. SM WHY ? LP
- zr36057_init_vfe(zr);
+ /*
+ * set individual interrupt enables (without GIRQ1)
+ * but don't global enable until zoran_open()
+ */
+ zr36057_init_vfe(zr);
zr36057_enable_jpg(zr, BUZ_MODE_IDLE);