summaryrefslogtreecommitdiffstats
path: root/kernel/drivers/media/pci
diff options
context:
space:
mode:
authorJosé Pekkarinen <jose.pekkarinen@nokia.com>2016-04-11 10:41:07 +0300
committerJosé Pekkarinen <jose.pekkarinen@nokia.com>2016-04-13 08:17:18 +0300
commite09b41010ba33a20a87472ee821fa407a5b8da36 (patch)
treed10dc367189862e7ca5c592f033dc3726e1df4e3 /kernel/drivers/media/pci
parentf93b97fd65072de626c074dbe099a1fff05ce060 (diff)
These changes are the raw update to linux-4.4.6-rt14. Kernel sources
are taken from kernel.org, and rt patch from the rt wiki download page. During the rebasing, the following patch collided: Force tick interrupt and get rid of softirq magic(I70131fb85). Collisions have been removed because its logic was found on the source already. Change-Id: I7f57a4081d9deaa0d9ccfc41a6c8daccdee3b769 Signed-off-by: José Pekkarinen <jose.pekkarinen@nokia.com>
Diffstat (limited to 'kernel/drivers/media/pci')
-rw-r--r--kernel/drivers/media/pci/Kconfig9
-rw-r--r--kernel/drivers/media/pci/Makefile5
-rw-r--r--kernel/drivers/media/pci/bt8xx/btcx-risc.c5
-rw-r--r--kernel/drivers/media/pci/bt8xx/bttv-audio-hook.c443
-rw-r--r--kernel/drivers/media/pci/bt8xx/bttv-driver.c10
-rw-r--r--kernel/drivers/media/pci/bt8xx/bttv-input.c21
-rw-r--r--kernel/drivers/media/pci/bt8xx/bttvp.h2
-rw-r--r--kernel/drivers/media/pci/bt8xx/dst.c25
-rw-r--r--kernel/drivers/media/pci/bt8xx/dst_ca.c138
-rw-r--r--kernel/drivers/media/pci/bt8xx/dst_common.h12
-rw-r--r--kernel/drivers/media/pci/cobalt/Kconfig20
-rw-r--r--kernel/drivers/media/pci/cobalt/Makefile5
-rw-r--r--kernel/drivers/media/pci/cobalt/cobalt-alsa-main.c162
-rw-r--r--kernel/drivers/media/pci/cobalt/cobalt-alsa-pcm.c603
-rw-r--r--kernel/drivers/media/pci/cobalt/cobalt-alsa-pcm.h22
-rw-r--r--kernel/drivers/media/pci/cobalt/cobalt-alsa.h41
-rw-r--r--kernel/drivers/media/pci/cobalt/cobalt-cpld.c339
-rw-r--r--kernel/drivers/media/pci/cobalt/cobalt-cpld.h29
-rw-r--r--kernel/drivers/media/pci/cobalt/cobalt-driver.c833
-rw-r--r--kernel/drivers/media/pci/cobalt/cobalt-driver.h382
-rw-r--r--kernel/drivers/media/pci/cobalt/cobalt-flash.c128
-rw-r--r--kernel/drivers/media/pci/cobalt/cobalt-flash.h29
-rw-r--r--kernel/drivers/media/pci/cobalt/cobalt-i2c.c396
-rw-r--r--kernel/drivers/media/pci/cobalt/cobalt-i2c.h25
-rw-r--r--kernel/drivers/media/pci/cobalt/cobalt-irq.c259
-rw-r--r--kernel/drivers/media/pci/cobalt/cobalt-irq.h25
-rw-r--r--kernel/drivers/media/pci/cobalt/cobalt-omnitek.c341
-rw-r--r--kernel/drivers/media/pci/cobalt/cobalt-omnitek.h62
-rw-r--r--kernel/drivers/media/pci/cobalt/cobalt-v4l2.c1279
-rw-r--r--kernel/drivers/media/pci/cobalt/cobalt-v4l2.h22
-rw-r--r--kernel/drivers/media/pci/cobalt/m00233_video_measure_memmap_package.h115
-rw-r--r--kernel/drivers/media/pci/cobalt/m00235_fdma_packer_memmap_package.h44
-rw-r--r--kernel/drivers/media/pci/cobalt/m00389_cvi_memmap_package.h59
-rw-r--r--kernel/drivers/media/pci/cobalt/m00460_evcnt_memmap_package.h44
-rw-r--r--kernel/drivers/media/pci/cobalt/m00473_freewheel_memmap_package.h57
-rw-r--r--kernel/drivers/media/pci/cobalt/m00479_clk_loss_detector_memmap_package.h53
-rw-r--r--kernel/drivers/media/pci/cobalt/m00514_syncgen_flow_evcnt_memmap_package.h88
-rw-r--r--kernel/drivers/media/pci/cx18/cx18-av-core.c16
-rw-r--r--kernel/drivers/media/pci/cx18/cx18-controls.c13
-rw-r--r--kernel/drivers/media/pci/cx18/cx18-driver.c4
-rw-r--r--kernel/drivers/media/pci/cx18/cx18-ioctl.c12
-rw-r--r--kernel/drivers/media/pci/cx18/cx18-mailbox.c2
-rw-r--r--kernel/drivers/media/pci/cx23885/altera-ci.c2
-rw-r--r--kernel/drivers/media/pci/cx23885/cx23885-417.c13
-rw-r--r--kernel/drivers/media/pci/cx23885/cx23885-core.c28
-rw-r--r--kernel/drivers/media/pci/cx23885/cx23885-dvb.c161
-rw-r--r--kernel/drivers/media/pci/cx23885/cx23885-f300.c2
-rw-r--r--kernel/drivers/media/pci/cx23885/cx23885-f300.h2
-rw-r--r--kernel/drivers/media/pci/cx23885/cx23885-vbi.c18
-rw-r--r--kernel/drivers/media/pci/cx23885/cx23885-video.c41
-rw-r--r--kernel/drivers/media/pci/cx23885/cx23885.h5
-rw-r--r--kernel/drivers/media/pci/cx25821/cx25821-alsa.c2
-rw-r--r--kernel/drivers/media/pci/cx25821/cx25821-core.c3
-rw-r--r--kernel/drivers/media/pci/cx25821/cx25821-medusa-reg.h6
-rw-r--r--kernel/drivers/media/pci/cx25821/cx25821-video.c24
-rw-r--r--kernel/drivers/media/pci/cx25821/cx25821.h3
-rw-r--r--kernel/drivers/media/pci/cx88/cx88-alsa.c6
-rw-r--r--kernel/drivers/media/pci/cx88/cx88-blackbird.c15
-rw-r--r--kernel/drivers/media/pci/cx88/cx88-core.c6
-rw-r--r--kernel/drivers/media/pci/cx88/cx88-dvb.c25
-rw-r--r--kernel/drivers/media/pci/cx88/cx88-mpeg.c23
-rw-r--r--kernel/drivers/media/pci/cx88/cx88-vbi.c25
-rw-r--r--kernel/drivers/media/pci/cx88/cx88-video.c34
-rw-r--r--kernel/drivers/media/pci/cx88/cx88.h8
-rw-r--r--kernel/drivers/media/pci/ddbridge/ddbridge-core.c3
-rw-r--r--kernel/drivers/media/pci/dm1105/dm1105.c3
-rw-r--r--kernel/drivers/media/pci/dt3155/Kconfig13
-rw-r--r--kernel/drivers/media/pci/dt3155/Makefile1
-rw-r--r--kernel/drivers/media/pci/dt3155/dt3155.c633
-rw-r--r--kernel/drivers/media/pci/dt3155/dt3155.h197
-rw-r--r--kernel/drivers/media/pci/ivtv/Kconfig3
-rw-r--r--kernel/drivers/media/pci/ivtv/ivtv-alsa-main.c14
-rw-r--r--kernel/drivers/media/pci/ivtv/ivtv-controls.c12
-rw-r--r--kernel/drivers/media/pci/ivtv/ivtv-driver.h3
-rw-r--r--kernel/drivers/media/pci/ivtv/ivtv-gpio.c7
-rw-r--r--kernel/drivers/media/pci/ivtv/ivtv-ioctl.c15
-rw-r--r--kernel/drivers/media/pci/ivtv/ivtv-yuv.c12
-rw-r--r--kernel/drivers/media/pci/ivtv/ivtvfb.c61
-rw-r--r--kernel/drivers/media/pci/mantis/hopper_cards.c14
-rw-r--r--kernel/drivers/media/pci/mantis/mantis_cards.c94
-rw-r--r--kernel/drivers/media/pci/mantis/mantis_common.h33
-rw-r--r--kernel/drivers/media/pci/mantis/mantis_dma.c14
-rw-r--r--kernel/drivers/media/pci/mantis/mantis_i2c.c12
-rw-r--r--kernel/drivers/media/pci/mantis/mantis_input.c110
-rw-r--r--kernel/drivers/media/pci/mantis/mantis_input.h24
-rw-r--r--kernel/drivers/media/pci/mantis/mantis_pcmcia.c4
-rw-r--r--kernel/drivers/media/pci/mantis/mantis_uart.c61
-rw-r--r--kernel/drivers/media/pci/mantis/mantis_vp1034.c2
-rw-r--r--kernel/drivers/media/pci/mantis/mantis_vp1034.h3
-rw-r--r--kernel/drivers/media/pci/netup_unidvb/Kconfig12
-rw-r--r--kernel/drivers/media/pci/netup_unidvb/Makefile9
-rw-r--r--kernel/drivers/media/pci/netup_unidvb/netup_unidvb.h133
-rw-r--r--kernel/drivers/media/pci/netup_unidvb/netup_unidvb_ci.c248
-rw-r--r--kernel/drivers/media/pci/netup_unidvb/netup_unidvb_core.c1002
-rw-r--r--kernel/drivers/media/pci/netup_unidvb/netup_unidvb_i2c.c381
-rw-r--r--kernel/drivers/media/pci/netup_unidvb/netup_unidvb_spi.c248
-rw-r--r--kernel/drivers/media/pci/ngene/ngene-core.c10
-rw-r--r--kernel/drivers/media/pci/ngene/ngene.h2
-rw-r--r--kernel/drivers/media/pci/pt1/pt1.c6
-rw-r--r--kernel/drivers/media/pci/pt1/va1j5jf8007s.c4
-rw-r--r--kernel/drivers/media/pci/pt1/va1j5jf8007t.c4
-rw-r--r--kernel/drivers/media/pci/pt3/pt3.c2
-rw-r--r--kernel/drivers/media/pci/saa7134/saa7134-alsa.c60
-rw-r--r--kernel/drivers/media/pci/saa7134/saa7134-cards.c193
-rw-r--r--kernel/drivers/media/pci/saa7134/saa7134-core.c179
-rw-r--r--kernel/drivers/media/pci/saa7134/saa7134-dvb.c122
-rw-r--r--kernel/drivers/media/pci/saa7134/saa7134-empress.c55
-rw-r--r--kernel/drivers/media/pci/saa7134/saa7134-go7007.c11
-rw-r--r--kernel/drivers/media/pci/saa7134/saa7134-i2c.c87
-rw-r--r--kernel/drivers/media/pci/saa7134/saa7134-input.c66
-rw-r--r--kernel/drivers/media/pci/saa7134/saa7134-ts.c40
-rw-r--r--kernel/drivers/media/pci/saa7134/saa7134-tvaudio.c168
-rw-r--r--kernel/drivers/media/pci/saa7134/saa7134-vbi.c26
-rw-r--r--kernel/drivers/media/pci/saa7134/saa7134-video.c66
-rw-r--r--kernel/drivers/media/pci/saa7134/saa7134.h11
-rw-r--r--kernel/drivers/media/pci/saa7164/Kconfig1
-rw-r--r--kernel/drivers/media/pci/saa7164/saa7164-api.c11
-rw-r--r--kernel/drivers/media/pci/saa7164/saa7164-buffer.c2
-rw-r--r--kernel/drivers/media/pci/saa7164/saa7164-bus.c2
-rw-r--r--kernel/drivers/media/pci/saa7164/saa7164-cards.c188
-rw-r--r--kernel/drivers/media/pci/saa7164/saa7164-cmd.c2
-rw-r--r--kernel/drivers/media/pci/saa7164/saa7164-core.c86
-rw-r--r--kernel/drivers/media/pci/saa7164/saa7164-dvb.c241
-rw-r--r--kernel/drivers/media/pci/saa7164/saa7164-encoder.c655
-rw-r--r--kernel/drivers/media/pci/saa7164/saa7164-fw.c2
-rw-r--r--kernel/drivers/media/pci/saa7164/saa7164-i2c.c9
-rw-r--r--kernel/drivers/media/pci/saa7164/saa7164-reg.h2
-rw-r--r--kernel/drivers/media/pci/saa7164/saa7164-types.h2
-rw-r--r--kernel/drivers/media/pci/saa7164/saa7164-vbi.c631
-rw-r--r--kernel/drivers/media/pci/saa7164/saa7164.h34
-rw-r--r--kernel/drivers/media/pci/smipcie/Kconfig1
-rw-r--r--kernel/drivers/media/pci/smipcie/Makefile3
-rw-r--r--kernel/drivers/media/pci/smipcie/smipcie-ir.c232
-rw-r--r--kernel/drivers/media/pci/smipcie/smipcie-main.c (renamed from kernel/drivers/media/pci/smipcie/smipcie.c)15
-rw-r--r--kernel/drivers/media/pci/smipcie/smipcie.h19
-rw-r--r--kernel/drivers/media/pci/solo6x10/solo6x10-core.c18
-rw-r--r--kernel/drivers/media/pci/solo6x10/solo6x10-g723.c13
-rw-r--r--kernel/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c50
-rw-r--r--kernel/drivers/media/pci/solo6x10/solo6x10-v4l2.c23
-rw-r--r--kernel/drivers/media/pci/solo6x10/solo6x10.h30
-rw-r--r--kernel/drivers/media/pci/sta2x11/sta2x11_vip.c29
-rw-r--r--kernel/drivers/media/pci/ttpci/av7110.c27
-rw-r--r--kernel/drivers/media/pci/ttpci/av7110.h27
-rw-r--r--kernel/drivers/media/pci/ttpci/av7110_av.c6
-rw-r--r--kernel/drivers/media/pci/ttpci/budget-av.c2
-rw-r--r--kernel/drivers/media/pci/ttpci/budget-core.c3
-rw-r--r--kernel/drivers/media/pci/ttpci/budget-patch.c15
-rw-r--r--kernel/drivers/media/pci/ttpci/budget.c12
-rw-r--r--kernel/drivers/media/pci/ttpci/budget.h2
-rw-r--r--kernel/drivers/media/pci/ttpci/ttpci-eeprom.c9
-rw-r--r--kernel/drivers/media/pci/tw68/tw68-core.c25
-rw-r--r--kernel/drivers/media/pci/tw68/tw68-video.c24
-rw-r--r--kernel/drivers/media/pci/tw68/tw68.h19
-rw-r--r--kernel/drivers/media/pci/zoran/zoran.h7
-rw-r--r--kernel/drivers/media/pci/zoran/zoran_card.c11
-rw-r--r--kernel/drivers/media/pci/zoran/zoran_device.c31
-rw-r--r--kernel/drivers/media/pci/zoran/zoran_driver.c344
157 files changed, 11165 insertions, 2824 deletions
diff --git a/kernel/drivers/media/pci/Kconfig b/kernel/drivers/media/pci/Kconfig
index 218144a99..48a611bc3 100644
--- a/kernel/drivers/media/pci/Kconfig
+++ b/kernel/drivers/media/pci/Kconfig
@@ -11,16 +11,17 @@ if MEDIA_PCI_SUPPORT
if MEDIA_CAMERA_SUPPORT
comment "Media capture support"
source "drivers/media/pci/meye/Kconfig"
+source "drivers/media/pci/solo6x10/Kconfig"
source "drivers/media/pci/sta2x11/Kconfig"
+source "drivers/media/pci/tw68/Kconfig"
+source "drivers/media/pci/zoran/Kconfig"
endif
if MEDIA_ANALOG_TV_SUPPORT
comment "Media capture/analog TV support"
source "drivers/media/pci/ivtv/Kconfig"
-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
@@ -47,6 +49,7 @@ source "drivers/media/pci/mantis/Kconfig"
source "drivers/media/pci/ngene/Kconfig"
source "drivers/media/pci/ddbridge/Kconfig"
source "drivers/media/pci/smipcie/Kconfig"
+source "drivers/media/pci/netup_unidvb/Kconfig"
endif
endif #MEDIA_PCI_SUPPORT
diff --git a/kernel/drivers/media/pci/Makefile b/kernel/drivers/media/pci/Makefile
index 0baf0d296..5f8aacb8b 100644
--- a/kernel/drivers/media/pci/Makefile
+++ b/kernel/drivers/media/pci/Makefile
@@ -12,7 +12,8 @@ obj-y += ttpci/ \
ngene/ \
ddbridge/ \
saa7146/ \
- smipcie/
+ smipcie/ \
+ netup_unidvb/
obj-$(CONFIG_VIDEO_IVTV) += ivtv/
obj-$(CONFIG_VIDEO_ZORAN) += zoran/
@@ -24,6 +25,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/kernel/drivers/media/pci/bt8xx/btcx-risc.c b/kernel/drivers/media/pci/bt8xx/btcx-risc.c
index 00f0880b6..57c7f58c3 100644
--- a/kernel/drivers/media/pci/bt8xx/btcx-risc.c
+++ b/kernel/drivers/media/pci/bt8xx/btcx-risc.c
@@ -160,7 +160,6 @@ btcx_align(struct v4l2_rect *win, struct v4l2_clip *clips, unsigned int n, int m
void
btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips)
{
- struct v4l2_clip swap;
int i,j,n;
if (nclips < 2)
@@ -168,9 +167,7 @@ btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips)
for (i = nclips-2; i >= 0; i--) {
for (n = 0, j = 0; j <= i; j++) {
if (clips[j].c.left > clips[j+1].c.left) {
- swap = clips[j];
- clips[j] = clips[j+1];
- clips[j+1] = swap;
+ swap(clips[j], clips[j + 1]);
n++;
}
}
diff --git a/kernel/drivers/media/pci/bt8xx/bttv-audio-hook.c b/kernel/drivers/media/pci/bt8xx/bttv-audio-hook.c
index 2364d1658..9f1f9169f 100644
--- a/kernel/drivers/media/pci/bt8xx/bttv-audio-hook.c
+++ b/kernel/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/kernel/drivers/media/pci/bt8xx/bttv-driver.c b/kernel/drivers/media/pci/bt8xx/bttv-driver.c
index bc12060e0..15a4ebc28 100644
--- a/kernel/drivers/media/pci/bt8xx/bttv-driver.c
+++ b/kernel/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;
@@ -3624,13 +3625,10 @@ static void
bttv_irq_wakeup_vbi(struct bttv *btv, struct bttv_buffer *wakeup,
unsigned int state)
{
- struct timeval ts;
-
if (NULL == wakeup)
return;
- v4l2_get_timestamp(&ts);
- wakeup->vb.ts = ts;
+ v4l2_get_timestamp(&wakeup->vb.ts);
wakeup->vb.field_count = btv->field_count;
wakeup->vb.state = state;
wake_up(&wakeup->vb.done);
@@ -4238,6 +4236,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 +4280,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/kernel/drivers/media/pci/bt8xx/bttv-input.c b/kernel/drivers/media/pci/bt8xx/bttv-input.c
index 67c8d6b2c..a75c53da2 100644
--- a/kernel/drivers/media/pci/bt8xx/bttv-input.c
+++ b/kernel/drivers/media/pci/bt8xx/bttv-input.c
@@ -194,21 +194,18 @@ static u32 bttv_rc5_decode(unsigned int code)
static void bttv_rc5_timer_end(unsigned long data)
{
struct bttv_ir *ir = (struct bttv_ir *)data;
- struct timeval tv;
+ ktime_t tv;
u32 gap, rc5, scancode;
u8 toggle, command, system;
/* get time */
- do_gettimeofday(&tv);
+ tv = ktime_get();
+ gap = ktime_to_us(ktime_sub(tv, ir->base_time));
/* avoid overflow with gap >1s */
- if (tv.tv_sec - ir->base_time.tv_sec > 1) {
+ if (gap > USEC_PER_SEC) {
gap = 200000;
- } else {
- gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) +
- tv.tv_usec - ir->base_time.tv_usec;
}
-
/* signal we're ready to start a new code */
ir->active = false;
@@ -249,7 +246,7 @@ static void bttv_rc5_timer_end(unsigned long data)
static int bttv_rc5_irq(struct bttv *btv)
{
struct bttv_ir *ir = btv->remote;
- struct timeval tv;
+ ktime_t tv;
u32 gpio;
u32 gap;
unsigned long current_jiffies;
@@ -259,14 +256,12 @@ static int bttv_rc5_irq(struct bttv *btv)
/* get time of bit */
current_jiffies = jiffies;
- do_gettimeofday(&tv);
+ tv = ktime_get();
+ gap = ktime_to_us(ktime_sub(tv, ir->base_time));
/* avoid overflow with gap >1s */
- if (tv.tv_sec - ir->base_time.tv_sec > 1) {
+ if (gap > USEC_PER_SEC) {
gap = 200000;
- } else {
- gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) +
- tv.tv_usec - ir->base_time.tv_usec;
}
dprintk("RC5 IRQ: gap %d us for %s\n",
diff --git a/kernel/drivers/media/pci/bt8xx/bttvp.h b/kernel/drivers/media/pci/bt8xx/bttvp.h
index a444cfb35..31bf79d3b 100644
--- a/kernel/drivers/media/pci/bt8xx/bttvp.h
+++ b/kernel/drivers/media/pci/bt8xx/bttvp.h
@@ -140,7 +140,7 @@ struct bttv_ir {
bool rc5_gpio; /* Is RC5 legacy GPIO enabled? */
u32 last_bit; /* last raw bit seen */
u32 code; /* raw code under construction */
- struct timeval base_time; /* time of last seen code */
+ ktime_t base_time; /* time of last seen code */
bool active; /* building raw code */
};
diff --git a/kernel/drivers/media/pci/bt8xx/dst.c b/kernel/drivers/media/pci/bt8xx/dst.c
index f2261dfe5..4a90eee5e 100644
--- a/kernel/drivers/media/pci/bt8xx/dst.c
+++ b/kernel/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/kernel/drivers/media/pci/bt8xx/dst_ca.c b/kernel/drivers/media/pci/bt8xx/dst_ca.c
index c22c4ae06..c5cc14ef8 100644
--- a/kernel/drivers/media/pci/bt8xx/dst_ca.c
+++ b/kernel/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/kernel/drivers/media/pci/bt8xx/dst_common.h b/kernel/drivers/media/pci/bt8xx/dst_common.h
index d70d98f1a..6a2cfdd44 100644
--- a/kernel/drivers/media/pci/bt8xx/dst_common.h
+++ b/kernel/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/kernel/drivers/media/pci/cobalt/Kconfig b/kernel/drivers/media/pci/cobalt/Kconfig
new file mode 100644
index 000000000..a01f0cc74
--- /dev/null
+++ b/kernel/drivers/media/pci/cobalt/Kconfig
@@ -0,0 +1,20 @@
+config VIDEO_COBALT
+ tristate "Cisco Cobalt support"
+ depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
+ depends on PCI_MSI && MTD_COMPLEX_MAPPINGS
+ depends on GPIOLIB || COMPILE_TEST
+ depends on SND
+ 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/kernel/drivers/media/pci/cobalt/Makefile b/kernel/drivers/media/pci/cobalt/Makefile
new file mode 100644
index 000000000..b328955ab
--- /dev/null
+++ b/kernel/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/kernel/drivers/media/pci/cobalt/cobalt-alsa-main.c b/kernel/drivers/media/pci/cobalt/cobalt-alsa-main.c
new file mode 100644
index 000000000..720e3ad93
--- /dev/null
+++ b/kernel/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/kernel/drivers/media/pci/cobalt/cobalt-alsa-pcm.c b/kernel/drivers/media/pci/cobalt/cobalt-alsa-pcm.c
new file mode 100644
index 000000000..f0bdf10cf
--- /dev/null
+++ b/kernel/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/kernel/drivers/media/pci/cobalt/cobalt-alsa-pcm.h b/kernel/drivers/media/pci/cobalt/cobalt-alsa-pcm.h
new file mode 100644
index 000000000..513fb1f71
--- /dev/null
+++ b/kernel/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/kernel/drivers/media/pci/cobalt/cobalt-alsa.h b/kernel/drivers/media/pci/cobalt/cobalt-alsa.h
new file mode 100644
index 000000000..08db699ce
--- /dev/null
+++ b/kernel/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/kernel/drivers/media/pci/cobalt/cobalt-cpld.c b/kernel/drivers/media/pci/cobalt/cobalt-cpld.c
new file mode 100644
index 000000000..23c875fc1
--- /dev/null
+++ b/kernel/drivers/media/pci/cobalt/cobalt-cpld.c
@@ -0,0 +1,339 @@
+/*
+ * 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: %6ph\n", f_out, regs);
+
+ 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: %6ph\n", read_regs);
+ }
+ if (2 - retries)
+ cobalt_info("Needed %d retries\n", 2 - retries);
+
+ return true;
+}
diff --git a/kernel/drivers/media/pci/cobalt/cobalt-cpld.h b/kernel/drivers/media/pci/cobalt/cobalt-cpld.h
new file mode 100644
index 000000000..0fc88fd5f
--- /dev/null
+++ b/kernel/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/kernel/drivers/media/pci/cobalt/cobalt-driver.c b/kernel/drivers/media/pci/cobalt/cobalt-driver.c
new file mode 100644
index 000000000..8fed61ec7
--- /dev/null
+++ b/kernel/drivers/media/pci/cobalt/cobalt-driver.c
@@ -0,0 +1,833 @@
+/*
+ * 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_warn("PCI Express link width is %d lanes.\n",
+ pcie_link_get_lanes(cobalt));
+ if (pcie_bus_link_get_lanes(cobalt) < 8)
+ cobalt_warn("The current slot only supports %d lanes, for best performance 8 are needed\n",
+ pcie_bus_link_get_lanes(cobalt));
+ if (pcie_link_get_lanes(cobalt) != pcie_bus_link_get_lanes(cobalt)) {
+ 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/kernel/drivers/media/pci/cobalt/cobalt-driver.h b/kernel/drivers/media/pci/cobalt/cobalt-driver.h
new file mode 100644
index 000000000..b2f08e4a6
--- /dev/null
+++ b/kernel/drivers/media/pci/cobalt/cobalt-driver.h
@@ -0,0 +1,382 @@
+/*
+ * 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-v4l2.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_v4l2_buffer vb;
+ struct list_head list;
+};
+
+static inline
+struct cobalt_buffer *to_cobalt_buffer(struct vb2_v4l2_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/kernel/drivers/media/pci/cobalt/cobalt-flash.c b/kernel/drivers/media/pci/cobalt/cobalt-flash.c
new file mode 100644
index 000000000..04dcaf919
--- /dev/null
+++ b/kernel/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/kernel/drivers/media/pci/cobalt/cobalt-flash.h b/kernel/drivers/media/pci/cobalt/cobalt-flash.h
new file mode 100644
index 000000000..8077daea5
--- /dev/null
+++ b/kernel/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/kernel/drivers/media/pci/cobalt/cobalt-i2c.c b/kernel/drivers/media/pci/cobalt/cobalt-i2c.c
new file mode 100644
index 000000000..ad16b89b8
--- /dev/null
+++ b/kernel/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/kernel/drivers/media/pci/cobalt/cobalt-i2c.h b/kernel/drivers/media/pci/cobalt/cobalt-i2c.h
new file mode 100644
index 000000000..a4c1cfaac
--- /dev/null
+++ b/kernel/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/kernel/drivers/media/pci/cobalt/cobalt-irq.c b/kernel/drivers/media/pci/cobalt/cobalt-irq.c
new file mode 100644
index 000000000..3de26d071
--- /dev/null
+++ b/kernel/drivers/media/pci/cobalt/cobalt-irq.c
@@ -0,0 +1,259 @@
+/*
+ * 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.timestamp);
+ /* TODO: the sequence number should be read from the FPGA so we
+ also know about dropped frames. */
+ cb->vb.sequence = s->sequence++;
+ vb2_buffer_done(&cb->vb.vb2_buf,
+ (skip || s->unstable_frame) ?
+ VB2_BUF_STATE_REQUEUEING : 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/kernel/drivers/media/pci/cobalt/cobalt-irq.h b/kernel/drivers/media/pci/cobalt/cobalt-irq.h
new file mode 100644
index 000000000..5119484a2
--- /dev/null
+++ b/kernel/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/kernel/drivers/media/pci/cobalt/cobalt-omnitek.c b/kernel/drivers/media/pci/cobalt/cobalt-omnitek.c
new file mode 100644
index 000000000..a28a8482c
--- /dev/null
+++ b/kernel/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/kernel/drivers/media/pci/cobalt/cobalt-omnitek.h b/kernel/drivers/media/pci/cobalt/cobalt-omnitek.h
new file mode 100644
index 000000000..e5c6d032c
--- /dev/null
+++ b/kernel/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/kernel/drivers/media/pci/cobalt/cobalt-v4l2.c b/kernel/drivers/media/pci/cobalt/cobalt-v4l2.c
new file mode 100644
index 000000000..ff46e4242
--- /dev/null
+++ b/kernel/drivers/media/pci/cobalt/cobalt-v4l2.c
@@ -0,0 +1,1279 @@
+/*
+ * 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/v4l2-dv-timings.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 void *parg,
+ unsigned int *num_buffers, unsigned int *num_planes,
+ unsigned int sizes[], void *alloc_ctxs[])
+{
+ const struct v4l2_format *fmt = parg;
+ 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->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->index];
+
+ descriptor_list_free(desc);
+}
+
+static int cobalt_buf_prepare(struct vb2_buffer *vb)
+{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct cobalt_stream *s = vb->vb2_queue->drv_priv;
+
+ vb2_set_plane_payload(vb, 0, s->stride * s->height);
+ vbuf->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.vb2_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_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct vb2_queue *q = vb->vb2_queue;
+ struct cobalt_stream *s = q->drv_priv;
+ struct cobalt_buffer *cb = to_cobalt_buffer(vbuf);
+ struct sg_dma_desc_info *desc = &s->dma_desc_info[vb->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.vb2_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.vb2_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, 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 (s->input == 1) {
+ *timings = cea1080p60;
+ return 0;
+ }
+
+ if (v4l2_match_dv_timings(timings, &s->timings, 0))
+ return 0;
+
+ if (vb2_is_busy(&s->q))
+ return -EBUSY;
+
+ 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/kernel/drivers/media/pci/cobalt/cobalt-v4l2.h b/kernel/drivers/media/pci/cobalt/cobalt-v4l2.h
new file mode 100644
index 000000000..62be553cd
--- /dev/null
+++ b/kernel/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/kernel/drivers/media/pci/cobalt/m00233_video_measure_memmap_package.h b/kernel/drivers/media/pci/cobalt/m00233_video_measure_memmap_package.h
new file mode 100644
index 000000000..9bc9ef1fd
--- /dev/null
+++ b/kernel/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/kernel/drivers/media/pci/cobalt/m00235_fdma_packer_memmap_package.h b/kernel/drivers/media/pci/cobalt/m00235_fdma_packer_memmap_package.h
new file mode 100644
index 000000000..a480529f5
--- /dev/null
+++ b/kernel/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/kernel/drivers/media/pci/cobalt/m00389_cvi_memmap_package.h b/kernel/drivers/media/pci/cobalt/m00389_cvi_memmap_package.h
new file mode 100644
index 000000000..602419e58
--- /dev/null
+++ b/kernel/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/kernel/drivers/media/pci/cobalt/m00460_evcnt_memmap_package.h b/kernel/drivers/media/pci/cobalt/m00460_evcnt_memmap_package.h
new file mode 100644
index 000000000..95471c995
--- /dev/null
+++ b/kernel/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/kernel/drivers/media/pci/cobalt/m00473_freewheel_memmap_package.h b/kernel/drivers/media/pci/cobalt/m00473_freewheel_memmap_package.h
new file mode 100644
index 000000000..384a3e156
--- /dev/null
+++ b/kernel/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/kernel/drivers/media/pci/cobalt/m00479_clk_loss_detector_memmap_package.h b/kernel/drivers/media/pci/cobalt/m00479_clk_loss_detector_memmap_package.h
new file mode 100644
index 000000000..2a029026b
--- /dev/null
+++ b/kernel/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/kernel/drivers/media/pci/cobalt/m00514_syncgen_flow_evcnt_memmap_package.h b/kernel/drivers/media/pci/cobalt/m00514_syncgen_flow_evcnt_memmap_package.h
new file mode 100644
index 000000000..bdef2df5d
--- /dev/null
+++ b/kernel/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/kernel/drivers/media/pci/cx18/cx18-av-core.c b/kernel/drivers/media/pci/cx18/cx18-av-core.c
index 5a55630d0..30bbe8d1e 100644
--- a/kernel/drivers/media/pci/cx18/cx18-av-core.c
+++ b/kernel/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/kernel/drivers/media/pci/cx18/cx18-controls.c b/kernel/drivers/media/pci/cx18/cx18-controls.c
index 4aeb7c6b8..71227a155 100644
--- a/kernel/drivers/media/pci/cx18/cx18-controls.c
+++ b/kernel/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/kernel/drivers/media/pci/cx18/cx18-driver.c b/kernel/drivers/media/pci/cx18/cx18-driver.c
index 83f507470..260e462d9 100644
--- a/kernel/drivers/media/pci/cx18/cx18-driver.c
+++ b/kernel/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/kernel/drivers/media/pci/cx18/cx18-ioctl.c b/kernel/drivers/media/pci/cx18/cx18-ioctl.c
index 79aee30d5..55525af1f 100644
--- a/kernel/drivers/media/pci/cx18/cx18-ioctl.c
+++ b/kernel/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/kernel/drivers/media/pci/cx18/cx18-mailbox.c b/kernel/drivers/media/pci/cx18/cx18-mailbox.c
index eabf00c63..1f8aa9a74 100644
--- a/kernel/drivers/media/pci/cx18/cx18-mailbox.c
+++ b/kernel/drivers/media/pci/cx18/cx18-mailbox.c
@@ -202,7 +202,7 @@ static void cx18_mdl_send_to_videobuf(struct cx18_stream *s,
}
if (dispatch) {
- vb_buf->vb.ts = ktime_to_timeval(ktime_get());
+ v4l2_get_timestamp(&vb_buf->vb.ts);
list_del(&vb_buf->vb.queue);
vb_buf->vb.state = VIDEOBUF_DONE;
wake_up(&vb_buf->vb.done);
diff --git a/kernel/drivers/media/pci/cx23885/altera-ci.c b/kernel/drivers/media/pci/cx23885/altera-ci.c
index 0a91df2c9..aaf4e46ff 100644
--- a/kernel/drivers/media/pci/cx23885/altera-ci.c
+++ b/kernel/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/kernel/drivers/media/pci/cx23885/cx23885-417.c b/kernel/drivers/media/pci/cx23885/cx23885-417.c
index 63c0ee5d0..88a3afb66 100644
--- a/kernel/drivers/media/pci/cx23885/cx23885-417.c
+++ b/kernel/drivers/media/pci/cx23885/cx23885-417.c
@@ -1138,7 +1138,7 @@ static int cx23885_initialize_codec(struct cx23885_dev *dev, int startencoder)
/* ------------------------------------------------------------------ */
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
unsigned int *num_buffers, unsigned int *num_planes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -1155,17 +1155,19 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
static int buffer_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
struct cx23885_buffer *buf =
- container_of(vb, struct cx23885_buffer, vb);
+ container_of(vbuf, struct cx23885_buffer, vb);
return cx23885_buf_prepare(buf, &dev->ts1);
}
static void buffer_finish(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
- struct cx23885_buffer *buf = container_of(vb,
+ struct cx23885_buffer *buf = container_of(vbuf,
struct cx23885_buffer, vb);
cx23885_free_buffer(dev, buf);
@@ -1173,8 +1175,9 @@ static void buffer_finish(struct vb2_buffer *vb)
static void buffer_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
- struct cx23885_buffer *buf = container_of(vb,
+ struct cx23885_buffer *buf = container_of(vbuf,
struct cx23885_buffer, vb);
cx23885_buf_queue(&dev->ts1, buf);
@@ -1201,7 +1204,7 @@ static int cx23885_start_streaming(struct vb2_queue *q, unsigned int count)
struct cx23885_buffer, queue);
list_del(&buf->queue);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED);
}
spin_unlock_irqrestore(&dev->slock, flags);
return ret;
diff --git a/kernel/drivers/media/pci/cx23885/cx23885-core.c b/kernel/drivers/media/pci/cx23885/cx23885-core.c
index 7aee76af7..e8f847226 100644
--- a/kernel/drivers/media/pci/cx23885/cx23885-core.c
+++ b/kernel/drivers/media/pci/cx23885/cx23885-core.c
@@ -427,12 +427,13 @@ static void cx23885_wakeup(struct cx23885_tsport *port,
buf = list_entry(q->active.next,
struct cx23885_buffer, queue);
- v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
- buf->vb.v4l2_buf.sequence = q->count++;
- dprintk(1, "[%p/%d] wakeup reg=%d buf=%d\n", buf, buf->vb.v4l2_buf.index,
+ v4l2_get_timestamp(&buf->vb.timestamp);
+ buf->vb.sequence = q->count++;
+ dprintk(1, "[%p/%d] wakeup reg=%d buf=%d\n", buf,
+ buf->vb.vb2_buf.index,
count, q->count);
list_del(&buf->queue);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
}
int cx23885_sram_channel_setup(struct cx23885_dev *dev,
@@ -1453,12 +1454,12 @@ int cx23885_buf_prepare(struct cx23885_buffer *buf, struct cx23885_tsport *port)
{
struct cx23885_dev *dev = port->dev;
int size = port->ts_packet_size * port->ts_packet_count;
- struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vb, 0);
+ struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vb.vb2_buf, 0);
dprintk(1, "%s: %p\n", __func__, buf);
- if (vb2_plane_size(&buf->vb, 0) < size)
+ if (vb2_plane_size(&buf->vb.vb2_buf, 0) < size)
return -EINVAL;
- vb2_set_plane_payload(&buf->vb, 0, size);
+ vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size);
cx23885_risc_databuffer(dev->pci, &buf->risc,
sgt->sgl,
@@ -1503,7 +1504,7 @@ void cx23885_buf_queue(struct cx23885_tsport *port, struct cx23885_buffer *buf)
if (list_empty(&cx88q->active)) {
list_add_tail(&buf->queue, &cx88q->active);
dprintk(1, "[%p/%d] %s - first active\n",
- buf, buf->vb.v4l2_buf.index, __func__);
+ buf, buf->vb.vb2_buf.index, __func__);
} else {
buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1);
prev = list_entry(cx88q->active.prev, struct cx23885_buffer,
@@ -1511,7 +1512,7 @@ void cx23885_buf_queue(struct cx23885_tsport *port, struct cx23885_buffer *buf)
list_add_tail(&buf->queue, &cx88q->active);
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__);
+ buf, buf->vb.vb2_buf.index, __func__);
}
spin_unlock_irqrestore(&dev->slock, flags);
}
@@ -1530,9 +1531,10 @@ static void do_cancel_buffers(struct cx23885_tsport *port, char *reason)
buf = list_entry(q->active.next, struct cx23885_buffer,
queue);
list_del(&buf->queue);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
dprintk(1, "[%p/%d] %s - dma=0x%08lx\n",
- buf, buf->vb.v4l2_buf.index, reason, (unsigned long)buf->risc.dma);
+ buf, buf->vb.vb2_buf.index, reason,
+ (unsigned long)buf->risc.dma);
}
spin_unlock_irqrestore(&port->slock, flags);
}
@@ -1990,9 +1992,9 @@ static int cx23885_initdev(struct pci_dev *pci_dev,
(unsigned long long)pci_resource_start(pci_dev, 0));
pci_set_master(pci_dev);
- if (!pci_dma_supported(pci_dev, 0xffffffff)) {
+ err = pci_set_dma_mask(pci_dev, 0xffffffff);
+ if (err) {
printk("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);
- err = -EIO;
goto fail_context;
}
diff --git a/kernel/drivers/media/pci/cx23885/cx23885-dvb.c b/kernel/drivers/media/pci/cx23885/cx23885-dvb.c
index 745caabe3..c4307ad85 100644
--- a/kernel/drivers/media/pci/cx23885/cx23885-dvb.c
+++ b/kernel/drivers/media/pci/cx23885/cx23885-dvb.c
@@ -92,7 +92,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
/* ------------------------------------------------------------------ */
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
unsigned int *num_buffers, unsigned int *num_planes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -110,18 +110,20 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
static int buffer_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx23885_tsport *port = vb->vb2_queue->drv_priv;
struct cx23885_buffer *buf =
- container_of(vb, struct cx23885_buffer, vb);
+ container_of(vbuf, struct cx23885_buffer, vb);
return cx23885_buf_prepare(buf, port);
}
static void buffer_finish(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx23885_tsport *port = vb->vb2_queue->drv_priv;
struct cx23885_dev *dev = port->dev;
- struct cx23885_buffer *buf = container_of(vb,
+ struct cx23885_buffer *buf = container_of(vbuf,
struct cx23885_buffer, vb);
cx23885_free_buffer(dev, buf);
@@ -129,8 +131,9 @@ static void buffer_finish(struct vb2_buffer *vb)
static void buffer_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx23885_tsport *port = vb->vb2_queue->drv_priv;
- struct cx23885_buffer *buf = container_of(vb,
+ struct cx23885_buffer *buf = container_of(vbuf,
struct cx23885_buffer, vb);
cx23885_buf_queue(port, buf);
@@ -572,7 +575,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 +591,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 +620,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 +860,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 +1188,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 +1797,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 +1854,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 +1911,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 +1967,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 +2013,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 +2043,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 +2089,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 +2152,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 +2171,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 +2183,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 +2243,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 +2310,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 +2419,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/kernel/drivers/media/pci/cx23885/cx23885-f300.c b/kernel/drivers/media/pci/cx23885/cx23885-f300.c
index 6f817d873..a6c45eb0a 100644
--- a/kernel/drivers/media/pci/cx23885/cx23885-f300.c
+++ b/kernel/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/kernel/drivers/media/pci/cx23885/cx23885-f300.h b/kernel/drivers/media/pci/cx23885/cx23885-f300.h
index e73344c94..be14d7de7 100644
--- a/kernel/drivers/media/pci/cx23885/cx23885-f300.h
+++ b/kernel/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/kernel/drivers/media/pci/cx23885/cx23885-vbi.c b/kernel/drivers/media/pci/cx23885/cx23885-vbi.c
index d362d3838..cf3cb1324 100644
--- a/kernel/drivers/media/pci/cx23885/cx23885-vbi.c
+++ b/kernel/drivers/media/pci/cx23885/cx23885-vbi.c
@@ -121,7 +121,7 @@ static int cx23885_start_vbi_dma(struct cx23885_dev *dev,
/* ------------------------------------------------------------------ */
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
unsigned int *num_buffers, unsigned int *num_planes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -138,8 +138,9 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
static int buffer_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
- struct cx23885_buffer *buf = container_of(vb,
+ struct cx23885_buffer *buf = container_of(vbuf,
struct cx23885_buffer, vb);
struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
unsigned lines = VBI_PAL_LINE_COUNT;
@@ -161,7 +162,8 @@ static int buffer_prepare(struct vb2_buffer *vb)
static void buffer_finish(struct vb2_buffer *vb)
{
- struct cx23885_buffer *buf = container_of(vb,
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct cx23885_buffer *buf = container_of(vbuf,
struct cx23885_buffer, vb);
cx23885_free_buffer(vb->vb2_queue->drv_priv, buf);
@@ -190,8 +192,10 @@ static void buffer_finish(struct vb2_buffer *vb)
*/
static void buffer_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
- struct cx23885_buffer *buf = container_of(vb, struct cx23885_buffer, vb);
+ struct cx23885_buffer *buf = container_of(vbuf,
+ struct cx23885_buffer, vb);
struct cx23885_buffer *prev;
struct cx23885_dmaqueue *q = &dev->vbiq;
unsigned long flags;
@@ -206,7 +210,7 @@ static void buffer_queue(struct vb2_buffer *vb)
list_add_tail(&buf->queue, &q->active);
spin_unlock_irqrestore(&dev->slock, flags);
dprintk(2, "[%p/%d] vbi_queue - first active\n",
- buf, buf->vb.v4l2_buf.index);
+ buf, buf->vb.vb2_buf.index);
} else {
buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1);
@@ -217,7 +221,7 @@ static void buffer_queue(struct vb2_buffer *vb)
spin_unlock_irqrestore(&dev->slock, flags);
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);
+ buf, buf->vb.vb2_buf.index);
}
}
@@ -245,7 +249,7 @@ static void cx23885_stop_streaming(struct vb2_queue *q)
struct cx23885_buffer, queue);
list_del(&buf->queue);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&dev->slock, flags);
}
diff --git a/kernel/drivers/media/pci/cx23885/cx23885-video.c b/kernel/drivers/media/pci/cx23885/cx23885-video.c
index 2232b389c..71a80e2b8 100644
--- a/kernel/drivers/media/pci/cx23885/cx23885-video.c
+++ b/kernel/drivers/media/pci/cx23885/cx23885-video.c
@@ -104,12 +104,12 @@ void cx23885_video_wakeup(struct cx23885_dev *dev,
buf = list_entry(q->active.next,
struct cx23885_buffer, queue);
- buf->vb.v4l2_buf.sequence = q->count++;
- v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
- dprintk(2, "[%p/%d] wakeup reg=%d buf=%d\n", buf, buf->vb.v4l2_buf.index,
- count, q->count);
+ buf->vb.sequence = q->count++;
+ v4l2_get_timestamp(&buf->vb.timestamp);
+ dprintk(2, "[%p/%d] wakeup reg=%d buf=%d\n", buf,
+ buf->vb.vb2_buf.index, count, q->count);
list_del(&buf->queue);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
}
int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm)
@@ -315,7 +315,7 @@ static int cx23885_start_video_dma(struct cx23885_dev *dev,
return 0;
}
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
unsigned int *num_buffers, unsigned int *num_planes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -329,9 +329,10 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
static int buffer_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
struct cx23885_buffer *buf =
- container_of(vb, struct cx23885_buffer, vb);
+ container_of(vbuf, struct cx23885_buffer, vb);
u32 line0_offset, line1_offset;
struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
int field_tff;
@@ -401,7 +402,7 @@ static int buffer_prepare(struct vb2_buffer *vb)
BUG();
}
dprintk(2, "[%p/%d] buffer_init - %dx%d %dbpp \"%s\" - dma=0x%08lx\n",
- buf, buf->vb.v4l2_buf.index,
+ buf, buf->vb.vb2_buf.index,
dev->width, dev->height, dev->fmt->depth, dev->fmt->name,
(unsigned long)buf->risc.dma);
return 0;
@@ -409,7 +410,8 @@ static int buffer_prepare(struct vb2_buffer *vb)
static void buffer_finish(struct vb2_buffer *vb)
{
- struct cx23885_buffer *buf = container_of(vb,
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct cx23885_buffer *buf = container_of(vbuf,
struct cx23885_buffer, vb);
cx23885_free_buffer(vb->vb2_queue->drv_priv, buf);
@@ -438,8 +440,9 @@ static void buffer_finish(struct vb2_buffer *vb)
*/
static void buffer_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
- struct cx23885_buffer *buf = container_of(vb,
+ struct cx23885_buffer *buf = container_of(vbuf,
struct cx23885_buffer, vb);
struct cx23885_buffer *prev;
struct cx23885_dmaqueue *q = &dev->vidq;
@@ -455,7 +458,7 @@ static void buffer_queue(struct vb2_buffer *vb)
if (list_empty(&q->active)) {
list_add_tail(&buf->queue, &q->active);
dprintk(2, "[%p/%d] buffer_queue - first active\n",
- buf, buf->vb.v4l2_buf.index);
+ buf, buf->vb.vb2_buf.index);
} else {
buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1);
prev = list_entry(q->active.prev, struct cx23885_buffer,
@@ -463,7 +466,7 @@ static void buffer_queue(struct vb2_buffer *vb)
list_add_tail(&buf->queue, &q->active);
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);
+ buf, buf->vb.vb2_buf.index);
}
spin_unlock_irqrestore(&dev->slock, flags);
}
@@ -492,7 +495,7 @@ static void cx23885_stop_streaming(struct vb2_queue *q)
struct cx23885_buffer, queue);
list_del(&buf->queue);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&dev->slock, flags);
}
@@ -581,7 +584,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 +605,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/kernel/drivers/media/pci/cx23885/cx23885.h b/kernel/drivers/media/pci/cx23885/cx23885.h
index aeda8d399..c5ba0833f 100644
--- a/kernel/drivers/media/pci/cx23885/cx23885.h
+++ b/kernel/drivers/media/pci/cx23885/cx23885.h
@@ -170,7 +170,7 @@ struct cx23885_riscmem {
/* buffer for one video frame */
struct cx23885_buffer {
/* common v4l buffer stuff -- must be first */
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct list_head queue;
/* cx23885 specific */
@@ -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/kernel/drivers/media/pci/cx25821/cx25821-alsa.c b/kernel/drivers/media/pci/cx25821/cx25821-alsa.c
index 24f964bcc..b602eba2b 100644
--- a/kernel/drivers/media/pci/cx25821/cx25821-alsa.c
+++ b/kernel/drivers/media/pci/cx25821/cx25821-alsa.c
@@ -102,7 +102,7 @@ struct cx25821_audio_dev {
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static bool enable[SNDRV_CARDS] = { 1, [1 ... (SNDRV_CARDS - 1)] = 1 };
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable cx25821 soundcard. default enabled.");
diff --git a/kernel/drivers/media/pci/cx25821/cx25821-core.c b/kernel/drivers/media/pci/cx25821/cx25821-core.c
index 559f8293c..0042803a9 100644
--- a/kernel/drivers/media/pci/cx25821/cx25821-core.c
+++ b/kernel/drivers/media/pci/cx25821/cx25821-core.c
@@ -1319,7 +1319,8 @@ static int cx25821_initdev(struct pci_dev *pci_dev,
dev->pci_lat, (unsigned long long)dev->base_io_addr);
pci_set_master(pci_dev);
- if (!pci_dma_supported(pci_dev, 0xffffffff)) {
+ err = pci_set_dma_mask(pci_dev, 0xffffffff);
+ if (err) {
pr_err("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);
err = -EIO;
goto fail_irq;
diff --git a/kernel/drivers/media/pci/cx25821/cx25821-medusa-reg.h b/kernel/drivers/media/pci/cx25821/cx25821-medusa-reg.h
index c98ac946b..2e10643a8 100644
--- a/kernel/drivers/media/pci/cx25821/cx25821-medusa-reg.h
+++ b/kernel/drivers/media/pci/cx25821/cx25821-medusa-reg.h
@@ -84,9 +84,9 @@
#define ABIST_BIN4_VGA3 0x01D4
#define ABIST_BIN5_VGA4 0x01D8
#define ABIST_BIN6_VGA5 0x01DC
-#define ABIST_BIN7_VGA6 0x0x1E0
-#define ABIST_CLAMP_A 0x0x1E4
-#define ABIST_CLAMP_B 0x0x1E8
+#define ABIST_BIN7_VGA6 0x01E0
+#define ABIST_CLAMP_A 0x01E4
+#define ABIST_CLAMP_B 0x01E8
#define ABIST_CLAMP_C 0x01EC
#define ABIST_CLAMP_D 0x01F0
#define ABIST_CLAMP_E 0x01F4
diff --git a/kernel/drivers/media/pci/cx25821/cx25821-video.c b/kernel/drivers/media/pci/cx25821/cx25821-video.c
index 7bc495e4e..26e3e296d 100644
--- a/kernel/drivers/media/pci/cx25821/cx25821-video.c
+++ b/kernel/drivers/media/pci/cx25821/cx25821-video.c
@@ -130,10 +130,10 @@ int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status)
buf = list_entry(dmaq->active.next,
struct cx25821_buffer, queue);
- v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
- buf->vb.v4l2_buf.sequence = dmaq->count++;
+ v4l2_get_timestamp(&buf->vb.timestamp);
+ buf->vb.sequence = dmaq->count++;
list_del(&buf->queue);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
}
spin_unlock(&dev->slock);
handled++;
@@ -141,10 +141,11 @@ int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status)
return handled;
}
-static int cx25821_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int cx25821_queue_setup(struct vb2_queue *q, const void *parg,
unsigned int *num_buffers, unsigned int *num_planes,
unsigned int sizes[], void *alloc_ctxs[])
{
+ const struct v4l2_format *fmt = parg;
struct cx25821_channel *chan = q->drv_priv;
unsigned size = (chan->fmt->depth * chan->width * chan->height) >> 3;
@@ -159,10 +160,11 @@ static int cx25821_queue_setup(struct vb2_queue *q, const struct v4l2_format *fm
static int cx25821_buffer_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx25821_channel *chan = vb->vb2_queue->drv_priv;
struct cx25821_dev *dev = chan->dev;
struct cx25821_buffer *buf =
- container_of(vb, struct cx25821_buffer, vb);
+ container_of(vbuf, struct cx25821_buffer, vb);
struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
u32 line0_offset;
int bpl_local = LINE_SIZE_D1;
@@ -176,7 +178,7 @@ static int cx25821_buffer_prepare(struct vb2_buffer *vb)
if (vb2_plane_size(vb, 0) < chan->height * buf->bpl)
return -EINVAL;
vb2_set_plane_payload(vb, 0, chan->height * buf->bpl);
- buf->vb.v4l2_buf.field = chan->field;
+ buf->vb.field = chan->field;
if (chan->pixel_formats == PIXEL_FRMT_411) {
bpl_local = buf->bpl;
@@ -231,7 +233,7 @@ static int cx25821_buffer_prepare(struct vb2_buffer *vb)
}
dprintk(2, "[%p/%d] buffer_prep - %dx%d %dbpp \"%s\" - dma=0x%08lx\n",
- buf, buf->vb.v4l2_buf.index, chan->width, chan->height,
+ buf, buf->vb.vb2_buf.index, chan->width, chan->height,
chan->fmt->depth, chan->fmt->name,
(unsigned long)buf->risc.dma);
@@ -240,8 +242,9 @@ static int cx25821_buffer_prepare(struct vb2_buffer *vb)
static void cx25821_buffer_finish(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx25821_buffer *buf =
- container_of(vb, struct cx25821_buffer, vb);
+ container_of(vbuf, struct cx25821_buffer, vb);
struct cx25821_channel *chan = vb->vb2_queue->drv_priv;
struct cx25821_dev *dev = chan->dev;
@@ -250,8 +253,9 @@ static void cx25821_buffer_finish(struct vb2_buffer *vb)
static void cx25821_buffer_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx25821_buffer *buf =
- container_of(vb, struct cx25821_buffer, vb);
+ container_of(vbuf, struct cx25821_buffer, vb);
struct cx25821_channel *chan = vb->vb2_queue->drv_priv;
struct cx25821_dev *dev = chan->dev;
struct cx25821_buffer *prev;
@@ -300,7 +304,7 @@ static void cx25821_stop_streaming(struct vb2_queue *q)
struct cx25821_buffer, queue);
list_del(&buf->queue);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&dev->slock, flags);
}
diff --git a/kernel/drivers/media/pci/cx25821/cx25821.h b/kernel/drivers/media/pci/cx25821/cx25821.h
index d81a08a2d..a513b68be 100644
--- a/kernel/drivers/media/pci/cx25821/cx25821.h
+++ b/kernel/drivers/media/pci/cx25821/cx25821.h
@@ -34,6 +34,7 @@
#include <media/v4l2-common.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ctrls.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-dma-sg.h>
#include "cx25821-reg.h"
@@ -127,7 +128,7 @@ struct cx25821_riscmem {
/* buffer for one video frame */
struct cx25821_buffer {
/* common v4l buffer stuff -- must be first */
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct list_head queue;
/* cx25821 specific */
diff --git a/kernel/drivers/media/pci/cx88/cx88-alsa.c b/kernel/drivers/media/pci/cx88/cx88-alsa.c
index 7f8dc6002..1b5268f9b 100644
--- a/kernel/drivers/media/pci/cx88/cx88-alsa.c
+++ b/kernel/drivers/media/pci/cx88/cx88-alsa.c
@@ -101,7 +101,7 @@ typedef struct cx88_audio_dev snd_cx88_card_t;
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static const char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static bool enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1};
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable cx88x soundcard. default enabled.");
@@ -890,9 +890,9 @@ static int snd_cx88_create(struct snd_card *card, struct pci_dev *pci,
return err;
}
- if (!pci_dma_supported(pci,DMA_BIT_MASK(32))) {
+ err = pci_set_dma_mask(pci,DMA_BIT_MASK(32));
+ if (err) {
dprintk(0, "%s/1: Oops: no 32bit PCI DMA ???\n",core->name);
- err = -EIO;
cx88_core_put(core, pci);
return err;
}
diff --git a/kernel/drivers/media/pci/cx88/cx88-blackbird.c b/kernel/drivers/media/pci/cx88/cx88-blackbird.c
index 24216efa5..8b889135b 100644
--- a/kernel/drivers/media/pci/cx88/cx88-blackbird.c
+++ b/kernel/drivers/media/pci/cx88/cx88-blackbird.c
@@ -637,7 +637,7 @@ static int blackbird_stop_codec(struct cx8802_dev *dev)
/* ------------------------------------------------------------------ */
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
unsigned int *num_buffers, unsigned int *num_planes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -653,16 +653,18 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
static int buffer_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
- struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+ struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
return cx8802_buf_prepare(vb->vb2_queue, dev, buf);
}
static void buffer_finish(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
- struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+ struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
struct cx88_riscmem *risc = &buf->risc;
if (risc->cpu)
@@ -672,8 +674,9 @@ static void buffer_finish(struct vb2_buffer *vb)
static void buffer_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
- struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+ struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
cx8802_buf_queue(dev, buf);
}
@@ -721,7 +724,7 @@ fail:
struct cx88_buffer, list);
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED);
}
spin_unlock_irqrestore(&dev->slock, flags);
return err;
@@ -749,7 +752,7 @@ static void stop_streaming(struct vb2_queue *q)
struct cx88_buffer, list);
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&dev->slock, flags);
}
diff --git a/kernel/drivers/media/pci/cx88/cx88-core.c b/kernel/drivers/media/pci/cx88/cx88-core.c
index 3501be9f1..9a43c7826 100644
--- a/kernel/drivers/media/pci/cx88/cx88-core.c
+++ b/kernel/drivers/media/pci/cx88/cx88-core.c
@@ -518,9 +518,11 @@ 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);
+ v4l2_get_timestamp(&buf->vb.timestamp);
+ buf->vb.field = core->field;
+ buf->vb.sequence = q->count++;
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
}
void cx88_shutdown(struct cx88_core *core)
diff --git a/kernel/drivers/media/pci/cx88/cx88-dvb.c b/kernel/drivers/media/pci/cx88/cx88-dvb.c
index 1b2ed238c..f04835073 100644
--- a/kernel/drivers/media/pci/cx88/cx88-dvb.c
+++ b/kernel/drivers/media/pci/cx88/cx88-dvb.c
@@ -82,7 +82,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
/* ------------------------------------------------------------------ */
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
unsigned int *num_buffers, unsigned int *num_planes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -99,16 +99,18 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
static int buffer_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
- struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+ struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
return cx8802_buf_prepare(vb->vb2_queue, dev, buf);
}
static void buffer_finish(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
- struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+ struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
struct cx88_riscmem *risc = &buf->risc;
if (risc->cpu)
@@ -118,8 +120,9 @@ static void buffer_finish(struct vb2_buffer *vb)
static void buffer_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
- struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+ struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
cx8802_buf_queue(dev, buf);
}
@@ -149,7 +152,7 @@ static void stop_streaming(struct vb2_queue *q)
struct cx88_buffer, list);
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&dev->slock, flags);
}
@@ -449,7 +452,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 +468,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 +484,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 +508,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 +900,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 +922,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/kernel/drivers/media/pci/cx88/cx88-mpeg.c b/kernel/drivers/media/pci/cx88/cx88-mpeg.c
index 98344540c..f34c229f9 100644
--- a/kernel/drivers/media/pci/cx88/cx88-mpeg.c
+++ b/kernel/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" );
@@ -214,10 +214,8 @@ static int cx8802_restart_queue(struct cx8802_dev *dev,
buf = list_entry(q->active.next, struct cx88_buffer, list);
dprintk(2,"restart_queue [%p/%d]: restart dma\n",
- buf, buf->vb.v4l2_buf.index);
+ buf, buf->vb.vb2_buf.index);
cx8802_start_dma(dev, q, buf);
- list_for_each_entry(buf, &q->active, list)
- buf->count = q->count++;
return 0;
}
@@ -227,13 +225,13 @@ int cx8802_buf_prepare(struct vb2_queue *q, struct cx8802_dev *dev,
struct cx88_buffer *buf)
{
int size = dev->ts_packet_size * dev->ts_packet_count;
- struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vb, 0);
+ struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vb.vb2_buf, 0);
struct cx88_riscmem *risc = &buf->risc;
int rc;
- if (vb2_plane_size(&buf->vb, 0) < size)
+ if (vb2_plane_size(&buf->vb.vb2_buf, 0) < size)
return -EINVAL;
- vb2_set_plane_payload(&buf->vb, 0, size);
+ vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size);
rc = cx88_risc_databuffer(dev->pci, risc, sgt->sgl,
dev->ts_packet_size, dev->ts_packet_count, 0);
@@ -260,19 +258,17 @@ 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__);
+ buf, buf->vb.vb2_buf.index, __func__);
} else {
buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1);
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__);
+ buf, buf->vb.vb2_buf.index, __func__);
}
}
@@ -288,7 +284,7 @@ static void do_cancel_buffers(struct cx8802_dev *dev)
while (!list_empty(&q->active)) {
buf = list_entry(q->active.next, struct cx88_buffer, list);
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&dev->slock,flags);
}
@@ -397,7 +393,8 @@ static int cx8802_init_common(struct cx8802_dev *dev)
if (pci_enable_device(dev->pci))
return -EIO;
pci_set_master(dev->pci);
- if (!pci_dma_supported(dev->pci,DMA_BIT_MASK(32))) {
+ err = pci_set_dma_mask(dev->pci,DMA_BIT_MASK(32));
+ if (err) {
printk("%s/2: Oops: no 32bit PCI DMA ???\n",dev->core->name);
return -EIO;
}
diff --git a/kernel/drivers/media/pci/cx88/cx88-vbi.c b/kernel/drivers/media/pci/cx88/cx88-vbi.c
index 32eb7fdb8..007a5eee8 100644
--- a/kernel/drivers/media/pci/cx88/cx88-vbi.c
+++ b/kernel/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);
@@ -100,16 +100,14 @@ int cx8800_restart_vbi_queue(struct cx8800_dev *dev,
buf = list_entry(q->active.next, struct cx88_buffer, list);
dprintk(2,"restart_queue [%p/%d]: restart dma\n",
- buf, buf->vb.v4l2_buf.index);
+ buf, buf->vb.vb2_buf.index);
cx8800_start_vbi_dma(dev, q, buf);
- list_for_each_entry(buf, &q->active, list)
- buf->count = q->count++;
return 0;
}
/* ------------------------------------------------------------------ */
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
unsigned int *num_buffers, unsigned int *num_planes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -127,8 +125,9 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
static int buffer_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
- struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+ struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
unsigned int lines;
unsigned int size;
@@ -151,8 +150,9 @@ static int buffer_prepare(struct vb2_buffer *vb)
static void buffer_finish(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
- struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+ struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
struct cx88_riscmem *risc = &buf->risc;
if (risc->cpu)
@@ -162,8 +162,9 @@ static void buffer_finish(struct vb2_buffer *vb)
static void buffer_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
- struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+ struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
struct cx88_buffer *prev;
struct cx88_dmaqueue *q = &dev->vbiq;
@@ -175,18 +176,16 @@ 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);
+ buf, buf->vb.vb2_buf.index);
} else {
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);
+ buf, buf->vb.vb2_buf.index);
}
}
@@ -217,7 +216,7 @@ static void stop_streaming(struct vb2_queue *q)
struct cx88_buffer, list);
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&dev->slock, flags);
}
diff --git a/kernel/drivers/media/pci/cx88/cx88-video.c b/kernel/drivers/media/pci/cx88/cx88-video.c
index c9decd80b..aef9acf35 100644
--- a/kernel/drivers/media/pci/cx88/cx88-video.c
+++ b/kernel/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)
@@ -421,17 +420,16 @@ static int restart_video_queue(struct cx8800_dev *dev,
if (!list_empty(&q->active)) {
buf = list_entry(q->active.next, struct cx88_buffer, list);
dprintk(2,"restart_queue [%p/%d]: restart dma\n",
- buf, buf->vb.v4l2_buf.index);
+ buf, buf->vb.vb2_buf.index);
start_video_dma(dev, q, buf);
- list_for_each_entry(buf, &q->active, list)
- buf->count = q->count++;
}
return 0;
}
+#endif
/* ------------------------------------------------------------------ */
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
unsigned int *num_buffers, unsigned int *num_planes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -446,9 +444,10 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
static int buffer_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
struct cx88_core *core = dev->core;
- struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+ struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
buf->bpl = core->width * dev->fmt->depth >> 3;
@@ -491,7 +490,7 @@ static int buffer_prepare(struct vb2_buffer *vb)
break;
}
dprintk(2,"[%p/%d] buffer_prepare - %dx%d %dbpp \"%s\" - dma=0x%08lx\n",
- buf, buf->vb.v4l2_buf.index,
+ buf, buf->vb.vb2_buf.index,
core->width, core->height, dev->fmt->depth, dev->fmt->name,
(unsigned long)buf->risc.dma);
return 0;
@@ -499,8 +498,9 @@ static int buffer_prepare(struct vb2_buffer *vb)
static void buffer_finish(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
- struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+ struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
struct cx88_riscmem *risc = &buf->risc;
if (risc->cpu)
@@ -510,8 +510,9 @@ static void buffer_finish(struct vb2_buffer *vb)
static void buffer_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
- struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+ struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
struct cx88_buffer *prev;
struct cx88_core *core = dev->core;
struct cx88_dmaqueue *q = &dev->vidq;
@@ -523,18 +524,16 @@ 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);
+ buf, buf->vb.vb2_buf.index);
} else {
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);
+ buf, buf->vb.vb2_buf.index);
}
}
@@ -564,7 +563,7 @@ static void stop_streaming(struct vb2_queue *q)
struct cx88_buffer, list);
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&dev->slock, flags);
}
@@ -771,6 +770,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;
}
@@ -1314,9 +1314,9 @@ static int cx8800_initdev(struct pci_dev *pci_dev,
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))) {
+ err = pci_set_dma_mask(pci_dev,DMA_BIT_MASK(32));
+ if (err) {
printk("%s/0: Oops: no 32bit PCI DMA ???\n",core->name);
- err = -EIO;
goto fail_core;
}
dev->alloc_ctx = vb2_dma_sg_init_ctx(&pci_dev->dev);
diff --git a/kernel/drivers/media/pci/cx88/cx88.h b/kernel/drivers/media/pci/cx88/cx88.h
index b9fe1ac24..2996eb3ea 100644
--- a/kernel/drivers/media/pci/cx88/cx88.h
+++ b/kernel/drivers/media/pci/cx88/cx88.h
@@ -321,13 +321,12 @@ struct cx88_riscmem {
/* buffer for one video frame */
struct cx88_buffer {
/* common v4l buffer stuff -- must be first */
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct list_head list;
/* 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/kernel/drivers/media/pci/ddbridge/ddbridge-core.c b/kernel/drivers/media/pci/ddbridge/ddbridge-core.c
index 9e3492e20..0ac2dd35f 100644
--- a/kernel/drivers/media/pci/ddbridge/ddbridge-core.c
+++ b/kernel/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/kernel/drivers/media/pci/dm1105/dm1105.c b/kernel/drivers/media/pci/dm1105/dm1105.c
index ed1171673..88915fb87 100644
--- a/kernel/drivers/media/pci/dm1105/dm1105.c
+++ b/kernel/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/kernel/drivers/media/pci/dt3155/Kconfig b/kernel/drivers/media/pci/dt3155/Kconfig
new file mode 100644
index 000000000..5145e0dfa
--- /dev/null
+++ b/kernel/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/kernel/drivers/media/pci/dt3155/Makefile b/kernel/drivers/media/pci/dt3155/Makefile
new file mode 100644
index 000000000..89fa637ec
--- /dev/null
+++ b/kernel/drivers/media/pci/dt3155/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_VIDEO_DT3155) += dt3155.o
diff --git a/kernel/drivers/media/pci/dt3155/dt3155.c b/kernel/drivers/media/pci/dt3155/dt3155.c
new file mode 100644
index 000000000..d84abde5e
--- /dev/null
+++ b/kernel/drivers/media/pci/dt3155/dt3155.c
@@ -0,0 +1,633 @@
+/***************************************************************************
+ * 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/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 void *parg,
+ unsigned int *nbuffers, unsigned int *num_planes,
+ unsigned int sizes[], void *alloc_ctxs[])
+
+{
+ const struct v4l2_format *fmt = parg;
+ 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->vb2_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, 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 vb2_v4l2_buffer *vbuf = to_vb2_v4l2_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 = vbuf;
+ 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->timestamp);
+ ipd->curr_buf->sequence = ipd->sequence++;
+ ipd->curr_buf->field = V4L2_FIELD_NONE;
+ vb2_buffer_done(&ipd->curr_buf->vb2_buf, VB2_BUF_STATE_DONE);
+
+ ivb = list_first_entry(&ipd->dmaq, typeof(*ivb), done_entry);
+ list_del(&ivb->done_entry);
+ ipd->curr_buf = to_vb2_v4l2_buffer(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/kernel/drivers/media/pci/dt3155/dt3155.h b/kernel/drivers/media/pci/dt3155/dt3155.h
new file mode 100644
index 000000000..b3531e0bc
--- /dev/null
+++ b/kernel/drivers/media/pci/dt3155/dt3155.h
@@ -0,0 +1,197 @@
+/***************************************************************************
+ * 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>
+#include <media/videobuf2-v4l2.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_v4l2_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/kernel/drivers/media/pci/ivtv/Kconfig b/kernel/drivers/media/pci/ivtv/Kconfig
index dd6ee57e3..6e5867c57 100644
--- a/kernel/drivers/media/pci/ivtv/Kconfig
+++ b/kernel/drivers/media/pci/ivtv/Kconfig
@@ -57,5 +57,8 @@ config VIDEO_FB_IVTV
This is used in the Hauppauge PVR-350 card. There is a driver
homepage at <http://www.ivtvdriver.org>.
+ In order to use this module, you will need to boot with PAT disabled
+ on x86 systems, using the nopat kernel parameter.
+
To compile this driver as a module, choose M here: the
module will be called ivtvfb.
diff --git a/kernel/drivers/media/pci/ivtv/ivtv-alsa-main.c b/kernel/drivers/media/pci/ivtv/ivtv-alsa-main.c
index 41fa21534..8a86b61a8 100644
--- a/kernel/drivers/media/pci/ivtv/ivtv-alsa-main.c
+++ b/kernel/drivers/media/pci/ivtv/ivtv-alsa-main.c
@@ -41,6 +41,7 @@
#include "ivtv-alsa-pcm.h"
int ivtv_alsa_debug;
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
#define IVTV_DEBUG_ALSA_INFO(fmt, arg...) \
do { \
@@ -54,6 +55,10 @@ MODULE_PARM_DESC(debug,
"\t\t\t 1/0x0001: warning\n"
"\t\t\t 2/0x0002: info\n");
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index,
+ "Index value for IVTV ALSA capture interface(s).\n");
+
MODULE_AUTHOR("Andy Walls");
MODULE_DESCRIPTION("CX23415/CX23416 ALSA Interface");
MODULE_SUPPORTED_DEVICE("CX23415/CX23416 MPEG2 encoder");
@@ -137,7 +142,7 @@ static int snd_ivtv_init(struct v4l2_device *v4l2_dev)
struct ivtv *itv = to_ivtv(v4l2_dev);
struct snd_card *sc = NULL;
struct snd_ivtv_card *itvsc;
- int ret;
+ int ret, idx;
/* Numbrs steps from "Writing an ALSA Driver" by Takashi Iwai */
@@ -145,8 +150,10 @@ static int snd_ivtv_init(struct v4l2_device *v4l2_dev)
/* This is a no-op for us. We'll use the itv->instance */
/* (2) Create a card instance */
+ /* use first available id if not specified otherwise*/
+ idx = index[itv->instance] == -1 ? SNDRV_DEFAULT_IDX1 : index[itv->instance];
ret = snd_card_new(&itv->pdev->dev,
- SNDRV_DEFAULT_IDX1, /* use first available id */
+ idx,
SNDRV_DEFAULT_STR1, /* xid from end of shortname*/
THIS_MODULE, 0, &sc);
if (ret) {
@@ -196,6 +203,9 @@ static int snd_ivtv_init(struct v4l2_device *v4l2_dev)
goto err_exit_free;
}
+ IVTV_ALSA_INFO("%s: Instance %d registered as ALSA card %d\n",
+ __func__, itv->instance, sc->number);
+
return 0;
err_exit_free:
diff --git a/kernel/drivers/media/pci/ivtv/ivtv-controls.c b/kernel/drivers/media/pci/ivtv/ivtv-controls.c
index ccf548c25..8a55ccb8f 100644
--- a/kernel/drivers/media/pci/ivtv/ivtv-controls.c
+++ b/kernel/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/kernel/drivers/media/pci/ivtv/ivtv-driver.h b/kernel/drivers/media/pci/ivtv/ivtv-driver.h
index e8b6c7ad2..ee0ef6e48 100644
--- a/kernel/drivers/media/pci/ivtv/ivtv-driver.h
+++ b/kernel/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/kernel/drivers/media/pci/ivtv/ivtv-gpio.c b/kernel/drivers/media/pci/ivtv/ivtv-gpio.c
index af52def70..f752f3993 100644
--- a/kernel/drivers/media/pci/ivtv/ivtv-gpio.c
+++ b/kernel/drivers/media/pci/ivtv/ivtv-gpio.c
@@ -313,13 +313,6 @@ static const struct v4l2_ctrl_ops gpio_ctrl_ops = {
static const struct v4l2_subdev_core_ops subdev_core_ops = {
.log_status = subdev_log_status,
- .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
- .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
- .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
- .g_ctrl = v4l2_subdev_g_ctrl,
- .s_ctrl = v4l2_subdev_s_ctrl,
- .queryctrl = v4l2_subdev_queryctrl,
- .querymenu = v4l2_subdev_querymenu,
};
static const struct v4l2_subdev_tuner_ops subdev_tuner_ops = {
diff --git a/kernel/drivers/media/pci/ivtv/ivtv-ioctl.c b/kernel/drivers/media/pci/ivtv/ivtv-ioctl.c
index 6fe6c4a0e..9a21c17fc 100644
--- a/kernel/drivers/media/pci/ivtv/ivtv-ioctl.c
+++ b/kernel/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/kernel/drivers/media/pci/ivtv/ivtv-yuv.c b/kernel/drivers/media/pci/ivtv/ivtv-yuv.c
index 2ad65eb29..2b8e7b2f2 100644
--- a/kernel/drivers/media/pci/ivtv/ivtv-yuv.c
+++ b/kernel/drivers/media/pci/ivtv/ivtv-yuv.c
@@ -75,15 +75,15 @@ static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma,
ivtv_udma_get_page_info (&uv_dma, (unsigned long)args->uv_source, 360 * uv_decode_height);
/* Get user pages for DMA Xfer */
- down_read(&current->mm->mmap_sem);
- y_pages = get_user_pages(current, current->mm, y_dma.uaddr, y_dma.page_count, 0, 1, &dma->map[0], NULL);
+ y_pages = get_user_pages_unlocked(current, current->mm,
+ y_dma.uaddr, y_dma.page_count, 0, 1,
+ &dma->map[0]);
uv_pages = 0; /* silence gcc. value is set and consumed only if: */
if (y_pages == y_dma.page_count) {
- uv_pages = get_user_pages(current, current->mm,
- uv_dma.uaddr, uv_dma.page_count, 0, 1,
- &dma->map[y_pages], NULL);
+ uv_pages = get_user_pages_unlocked(current, current->mm,
+ uv_dma.uaddr, uv_dma.page_count, 0, 1,
+ &dma->map[y_pages]);
}
- up_read(&current->mm->mmap_sem);
if (y_pages != y_dma.page_count || uv_pages != uv_dma.page_count) {
int rc = -EFAULT;
diff --git a/kernel/drivers/media/pci/ivtv/ivtvfb.c b/kernel/drivers/media/pci/ivtv/ivtvfb.c
index 9ff123019..8b95eefb6 100644
--- a/kernel/drivers/media/pci/ivtv/ivtvfb.c
+++ b/kernel/drivers/media/pci/ivtv/ivtvfb.c
@@ -38,14 +38,16 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fb.h>
#include <linux/ivtvfb.h>
#include <linux/slab.h>
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
+#ifdef CONFIG_X86_64
+#include <asm/pat.h>
#endif
#include "ivtv-driver.h"
@@ -155,12 +157,11 @@ struct osd_info {
/* Buffer size */
u32 video_buffer_size;
-#ifdef CONFIG_MTRR
/* video_base rounded down as required by hardware MTRRs */
unsigned long fb_start_aligned_physaddr;
/* video_base rounded up as required by hardware MTRRs */
unsigned long fb_end_aligned_physaddr;
-#endif
+ int wc_cookie;
/* Store the buffer offset */
int set_osd_coords_x;
@@ -1099,6 +1100,8 @@ static int ivtvfb_init_vidmode(struct ivtv *itv)
static int ivtvfb_init_io(struct ivtv *itv)
{
struct osd_info *oi = itv->osd_info;
+ /* Find the largest power of two that maps the whole buffer */
+ int size_shift = 31;
mutex_lock(&itv->serialize_lock);
if (ivtv_init_on_first_open(itv)) {
@@ -1132,29 +1135,16 @@ static int ivtvfb_init_io(struct ivtv *itv)
oi->video_pbase, oi->video_vbase,
oi->video_buffer_size / 1024);
-#ifdef CONFIG_MTRR
- {
- /* Find the largest power of two that maps the whole buffer */
- int size_shift = 31;
-
- while (!(oi->video_buffer_size & (1 << size_shift))) {
- size_shift--;
- }
- size_shift++;
- oi->fb_start_aligned_physaddr = oi->video_pbase & ~((1 << size_shift) - 1);
- oi->fb_end_aligned_physaddr = oi->video_pbase + oi->video_buffer_size;
- oi->fb_end_aligned_physaddr += (1 << size_shift) - 1;
- oi->fb_end_aligned_physaddr &= ~((1 << size_shift) - 1);
- if (mtrr_add(oi->fb_start_aligned_physaddr,
- oi->fb_end_aligned_physaddr - oi->fb_start_aligned_physaddr,
- MTRR_TYPE_WRCOMB, 1) < 0) {
- IVTVFB_INFO("disabled mttr\n");
- oi->fb_start_aligned_physaddr = 0;
- oi->fb_end_aligned_physaddr = 0;
- }
- }
-#endif
-
+ while (!(oi->video_buffer_size & (1 << size_shift)))
+ size_shift--;
+ size_shift++;
+ oi->fb_start_aligned_physaddr = oi->video_pbase & ~((1 << size_shift) - 1);
+ oi->fb_end_aligned_physaddr = oi->video_pbase + oi->video_buffer_size;
+ oi->fb_end_aligned_physaddr += (1 << size_shift) - 1;
+ oi->fb_end_aligned_physaddr &= ~((1 << size_shift) - 1);
+ oi->wc_cookie = arch_phys_wc_add(oi->fb_start_aligned_physaddr,
+ oi->fb_end_aligned_physaddr -
+ oi->fb_start_aligned_physaddr);
/* Blank the entire osd. */
memset_io(oi->video_vbase, 0, oi->video_buffer_size);
@@ -1172,14 +1162,7 @@ static void ivtvfb_release_buffers (struct ivtv *itv)
/* Release pseudo palette */
kfree(oi->ivtvfb_info.pseudo_palette);
-
-#ifdef CONFIG_MTRR
- if (oi->fb_end_aligned_physaddr) {
- mtrr_del(-1, oi->fb_start_aligned_physaddr,
- oi->fb_end_aligned_physaddr - oi->fb_start_aligned_physaddr);
- }
-#endif
-
+ arch_phys_wc_del(oi->wc_cookie);
kfree(oi);
itv->osd_info = NULL;
}
@@ -1190,6 +1173,13 @@ static int ivtvfb_init_card(struct ivtv *itv)
{
int rc;
+#ifdef CONFIG_X86_64
+ if (pat_enabled()) {
+ pr_warn("ivtvfb needs PAT disabled, boot with nopat kernel parameter\n");
+ return -ENODEV;
+ }
+#endif
+
if (itv->osd_info) {
IVTVFB_ERR("Card %d already initialised\n", ivtvfb_card_id);
return -EBUSY;
@@ -1284,6 +1274,7 @@ static int __init ivtvfb_init(void)
int registered = 0;
int err;
+
if (ivtvfb_card_id < -1 || ivtvfb_card_id >= IVTV_MAX_CARDS) {
printk(KERN_ERR "ivtvfb: ivtvfb_card_id parameter is out of range (valid range: -1 - %d)\n",
IVTV_MAX_CARDS - 1);
diff --git a/kernel/drivers/media/pci/mantis/hopper_cards.c b/kernel/drivers/media/pci/mantis/hopper_cards.c
index 104914a5b..68b580003 100644
--- a/kernel/drivers/media/pci/mantis/hopper_cards.c
+++ b/kernel/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/kernel/drivers/media/pci/mantis/mantis_cards.c b/kernel/drivers/media/pci/mantis/mantis_cards.c
index 801fc55b6..cdefffc16 100644
--- a/kernel/drivers/media/pci/mantis/mantis_cards.c
+++ b/kernel/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/kernel/drivers/media/pci/mantis/mantis_common.h b/kernel/drivers/media/pci/mantis/mantis_common.h
index 8ff448bb7..d48778a36 100644
--- a/kernel/drivers/media/pci/mantis/mantis_common.h
+++ b/kernel/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/kernel/drivers/media/pci/mantis/mantis_dma.c b/kernel/drivers/media/pci/mantis/mantis_dma.c
index 566c40717..2ce310b0a 100644
--- a/kernel/drivers/media/pci/mantis/mantis_dma.c
+++ b/kernel/drivers/media/pci/mantis/mantis_dma.c
@@ -130,21 +130,20 @@ err:
int mantis_dma_init(struct mantis_pci *mantis)
{
- int err = 0;
+ int err;
dprintk(MANTIS_DEBUG, 1, "Mantis DMA init");
- if (mantis_alloc_buffers(mantis) < 0) {
+ err = mantis_alloc_buffers(mantis);
+ if (err < 0) {
dprintk(MANTIS_ERROR, 1, "Error allocating DMA buffer");
/* Stop RISC Engine */
mmwrite(0, MANTIS_DMA_CTL);
- goto err;
+ return err;
}
return 0;
-err:
- return err;
}
EXPORT_SYMBOL_GPL(mantis_dma_init);
@@ -190,7 +189,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 +208,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/kernel/drivers/media/pci/mantis/mantis_i2c.c b/kernel/drivers/media/pci/mantis/mantis_i2c.c
index 895ddba3c..d72ee47dc 100644
--- a/kernel/drivers/media/pci/mantis/mantis_i2c.c
+++ b/kernel/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/kernel/drivers/media/pci/mantis/mantis_input.c b/kernel/drivers/media/pci/mantis/mantis_input.c
index 0e5252e5c..7f7f1d4d7 100644
--- a/kernel/drivers/media/pci/mantis/mantis_input.c
+++ b/kernel/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/kernel/drivers/media/pci/mantis/mantis_input.h b/kernel/drivers/media/pci/mantis/mantis_input.h
new file mode 100644
index 000000000..0fbd92987
--- /dev/null
+++ b/kernel/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/kernel/drivers/media/pci/mantis/mantis_pcmcia.c b/kernel/drivers/media/pci/mantis/mantis_pcmcia.c
index 2f188c089..b2dbc7b2e 100644
--- a/kernel/drivers/media/pci/mantis/mantis_pcmcia.c
+++ b/kernel/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/kernel/drivers/media/pci/mantis/mantis_uart.c b/kernel/drivers/media/pci/mantis/mantis_uart.c
index a70719218..f1c96aec8 100644
--- a/kernel/drivers/media/pci/mantis/mantis_uart.c
+++ b/kernel/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/kernel/drivers/media/pci/mantis/mantis_vp1034.c b/kernel/drivers/media/pci/mantis/mantis_vp1034.c
index 7c1bd1672..3b1928594 100644
--- a/kernel/drivers/media/pci/mantis/mantis_vp1034.c
+++ b/kernel/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/kernel/drivers/media/pci/mantis/mantis_vp1034.h b/kernel/drivers/media/pci/mantis/mantis_vp1034.h
index 323f38ef8..764b1c66e 100644
--- a/kernel/drivers/media/pci/mantis/mantis_vp1034.h
+++ b/kernel/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/kernel/drivers/media/pci/netup_unidvb/Kconfig b/kernel/drivers/media/pci/netup_unidvb/Kconfig
new file mode 100644
index 000000000..f277b0b10
--- /dev/null
+++ b/kernel/drivers/media/pci/netup_unidvb/Kconfig
@@ -0,0 +1,12 @@
+config DVB_NETUP_UNIDVB
+ tristate "NetUP Universal DVB card support"
+ depends on DVB_CORE && VIDEO_DEV && PCI && I2C && SPI_MASTER
+ select VIDEOBUF2_DVB
+ select VIDEOBUF2_VMALLOC
+ select DVB_HORUS3A if MEDIA_SUBDRV_AUTOSELECT
+ select DVB_ASCOT2E if MEDIA_SUBDRV_AUTOSELECT
+ select DVB_LNBH25 if MEDIA_SUBDRV_AUTOSELECT
+ select DVB_CXD2841ER if MEDIA_SUBDRV_AUTOSELECT
+ ---help---
+ Support for NetUP PCI express Universal DVB card.
+
diff --git a/kernel/drivers/media/pci/netup_unidvb/Makefile b/kernel/drivers/media/pci/netup_unidvb/Makefile
new file mode 100644
index 000000000..ee6ae0501
--- /dev/null
+++ b/kernel/drivers/media/pci/netup_unidvb/Makefile
@@ -0,0 +1,9 @@
+netup-unidvb-objs += netup_unidvb_core.o
+netup-unidvb-objs += netup_unidvb_i2c.o
+netup-unidvb-objs += netup_unidvb_ci.o
+netup-unidvb-objs += netup_unidvb_spi.o
+
+obj-$(CONFIG_DVB_NETUP_UNIDVB) += netup-unidvb.o
+
+ccflags-y += -Idrivers/media/dvb-core
+ccflags-y += -Idrivers/media/dvb-frontends
diff --git a/kernel/drivers/media/pci/netup_unidvb/netup_unidvb.h b/kernel/drivers/media/pci/netup_unidvb/netup_unidvb.h
new file mode 100644
index 000000000..a67b28111
--- /dev/null
+++ b/kernel/drivers/media/pci/netup_unidvb/netup_unidvb.h
@@ -0,0 +1,133 @@
+/*
+ * netup_unidvb.h
+ *
+ * Data type definitions for NetUP Universal Dual DVB-CI
+ *
+ * Copyright (C) 2014 NetUP Inc.
+ * Copyright (C) 2014 Sergey Kozlov <serjk@netup.ru>
+ * Copyright (C) 2014 Abylay Ospan <aospan@netup.ru>
+ *
+ * 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/pci.h>
+#include <linux/i2c.h>
+#include <linux/workqueue.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
+#include <media/videobuf2-dvb.h>
+#include <dvb_ca_en50221.h>
+
+#define NETUP_UNIDVB_NAME "netup_unidvb"
+#define NETUP_UNIDVB_VERSION "0.0.1"
+#define NETUP_VENDOR_ID 0x1b55
+#define NETUP_PCI_DEV_REVISION 0x2
+
+/* IRQ-related regisers */
+#define REG_ISR 0x4890
+#define REG_ISR_MASKED 0x4892
+#define REG_IMASK_SET 0x4894
+#define REG_IMASK_CLEAR 0x4896
+/* REG_ISR register bits */
+#define NETUP_UNIDVB_IRQ_SPI (1 << 0)
+#define NETUP_UNIDVB_IRQ_I2C0 (1 << 1)
+#define NETUP_UNIDVB_IRQ_I2C1 (1 << 2)
+#define NETUP_UNIDVB_IRQ_FRA0 (1 << 4)
+#define NETUP_UNIDVB_IRQ_FRA1 (1 << 5)
+#define NETUP_UNIDVB_IRQ_FRB0 (1 << 6)
+#define NETUP_UNIDVB_IRQ_FRB1 (1 << 7)
+#define NETUP_UNIDVB_IRQ_DMA1 (1 << 8)
+#define NETUP_UNIDVB_IRQ_DMA2 (1 << 9)
+#define NETUP_UNIDVB_IRQ_CI (1 << 10)
+#define NETUP_UNIDVB_IRQ_CAM0 (1 << 11)
+#define NETUP_UNIDVB_IRQ_CAM1 (1 << 12)
+
+struct netup_dma {
+ u8 num;
+ spinlock_t lock;
+ struct netup_unidvb_dev *ndev;
+ struct netup_dma_regs __iomem *regs;
+ u32 ring_buffer_size;
+ u8 *addr_virt;
+ dma_addr_t addr_phys;
+ u64 addr_last;
+ u32 high_addr;
+ u32 data_offset;
+ u32 data_size;
+ struct list_head free_buffers;
+ struct work_struct work;
+ struct timer_list timeout;
+};
+
+enum netup_i2c_state {
+ STATE_DONE,
+ STATE_WAIT,
+ STATE_WANT_READ,
+ STATE_WANT_WRITE,
+ STATE_ERROR
+};
+
+struct netup_i2c_regs;
+
+struct netup_i2c {
+ spinlock_t lock;
+ wait_queue_head_t wq;
+ struct i2c_adapter adap;
+ struct netup_unidvb_dev *dev;
+ struct netup_i2c_regs __iomem *regs;
+ struct i2c_msg *msg;
+ enum netup_i2c_state state;
+ u32 xmit_size;
+};
+
+struct netup_ci_state {
+ struct dvb_ca_en50221 ca;
+ u8 __iomem *membase8_config;
+ u8 __iomem *membase8_io;
+ struct netup_unidvb_dev *dev;
+ int status;
+ int nr;
+};
+
+struct netup_spi;
+
+struct netup_unidvb_dev {
+ struct pci_dev *pci_dev;
+ int pci_bus;
+ int pci_slot;
+ int pci_func;
+ int board_num;
+ int old_fw;
+ u32 __iomem *lmmio0;
+ u8 __iomem *bmmio0;
+ u32 __iomem *lmmio1;
+ u8 __iomem *bmmio1;
+ u8 *dma_virt;
+ dma_addr_t dma_phys;
+ u32 dma_size;
+ struct vb2_dvb_frontends frontends[2];
+ struct netup_i2c i2c[2];
+ struct workqueue_struct *wq;
+ struct netup_dma dma[2];
+ struct netup_ci_state ci[2];
+ struct netup_spi *spi;
+};
+
+int netup_i2c_register(struct netup_unidvb_dev *ndev);
+void netup_i2c_unregister(struct netup_unidvb_dev *ndev);
+irqreturn_t netup_ci_interrupt(struct netup_unidvb_dev *ndev);
+irqreturn_t netup_i2c_interrupt(struct netup_i2c *i2c);
+irqreturn_t netup_spi_interrupt(struct netup_spi *spi);
+int netup_unidvb_ci_register(struct netup_unidvb_dev *dev,
+ int num, struct pci_dev *pci_dev);
+void netup_unidvb_ci_unregister(struct netup_unidvb_dev *dev, int num);
+int netup_spi_init(struct netup_unidvb_dev *ndev);
+void netup_spi_release(struct netup_unidvb_dev *ndev);
diff --git a/kernel/drivers/media/pci/netup_unidvb/netup_unidvb_ci.c b/kernel/drivers/media/pci/netup_unidvb/netup_unidvb_ci.c
new file mode 100644
index 000000000..f46ffac66
--- /dev/null
+++ b/kernel/drivers/media/pci/netup_unidvb/netup_unidvb_ci.c
@@ -0,0 +1,248 @@
+/*
+ * netup_unidvb_ci.c
+ *
+ * DVB CAM support for NetUP Universal Dual DVB-CI
+ *
+ * Copyright (C) 2014 NetUP Inc.
+ * Copyright (C) 2014 Sergey Kozlov <serjk@netup.ru>
+ * Copyright (C) 2014 Abylay Ospan <aospan@netup.ru>
+ *
+ * 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/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kmod.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include "netup_unidvb.h"
+
+/* CI slot 0 base address */
+#define CAM0_CONFIG 0x0
+#define CAM0_IO 0x8000
+#define CAM0_MEM 0x10000
+#define CAM0_SZ 32
+/* CI slot 1 base address */
+#define CAM1_CONFIG 0x20000
+#define CAM1_IO 0x28000
+#define CAM1_MEM 0x30000
+#define CAM1_SZ 32
+/* ctrlstat registers */
+#define CAM_CTRLSTAT_READ_SET 0x4980
+#define CAM_CTRLSTAT_CLR 0x4982
+/* register bits */
+#define BIT_CAM_STCHG (1<<0)
+#define BIT_CAM_PRESENT (1<<1)
+#define BIT_CAM_RESET (1<<2)
+#define BIT_CAM_BYPASS (1<<3)
+#define BIT_CAM_READY (1<<4)
+#define BIT_CAM_ERROR (1<<5)
+#define BIT_CAM_OVERCURR (1<<6)
+/* BIT_CAM_BYPASS bit shift for SLOT 1 */
+#define CAM1_SHIFT 8
+
+irqreturn_t netup_ci_interrupt(struct netup_unidvb_dev *ndev)
+{
+ writew(0x101, ndev->bmmio0 + CAM_CTRLSTAT_CLR);
+ return IRQ_HANDLED;
+}
+
+static int netup_unidvb_ci_slot_ts_ctl(struct dvb_ca_en50221 *en50221,
+ int slot)
+{
+ struct netup_ci_state *state = en50221->data;
+ struct netup_unidvb_dev *dev = state->dev;
+ u16 shift = (state->nr == 1) ? CAM1_SHIFT : 0;
+
+ dev_dbg(&dev->pci_dev->dev, "%s(): CAM_CTRLSTAT=0x%x\n",
+ __func__, readw(dev->bmmio0 + CAM_CTRLSTAT_READ_SET));
+ if (slot != 0)
+ return -EINVAL;
+ /* pass data to CAM module */
+ writew(BIT_CAM_BYPASS << shift, dev->bmmio0 + CAM_CTRLSTAT_CLR);
+ dev_dbg(&dev->pci_dev->dev, "%s(): CAM_CTRLSTAT=0x%x done\n",
+ __func__, readw(dev->bmmio0 + CAM_CTRLSTAT_READ_SET));
+ return 0;
+}
+
+static int netup_unidvb_ci_slot_shutdown(struct dvb_ca_en50221 *en50221,
+ int slot)
+{
+ struct netup_ci_state *state = en50221->data;
+ struct netup_unidvb_dev *dev = state->dev;
+
+ dev_dbg(&dev->pci_dev->dev, "%s()\n", __func__);
+ return 0;
+}
+
+static int netup_unidvb_ci_slot_reset(struct dvb_ca_en50221 *en50221,
+ int slot)
+{
+ struct netup_ci_state *state = en50221->data;
+ struct netup_unidvb_dev *dev = state->dev;
+ unsigned long timeout = 0;
+ u16 shift = (state->nr == 1) ? CAM1_SHIFT : 0;
+ u16 ci_stat = 0;
+ int reset_counter = 3;
+
+ dev_dbg(&dev->pci_dev->dev, "%s(): CAM_CTRLSTAT_READ_SET=0x%x\n",
+ __func__, readw(dev->bmmio0 + CAM_CTRLSTAT_READ_SET));
+reset:
+ timeout = jiffies + msecs_to_jiffies(5000);
+ /* start reset */
+ writew(BIT_CAM_RESET << shift, dev->bmmio0 + CAM_CTRLSTAT_READ_SET);
+ dev_dbg(&dev->pci_dev->dev, "%s(): waiting for reset\n", __func__);
+ /* wait until reset done */
+ while (time_before(jiffies, timeout)) {
+ ci_stat = readw(dev->bmmio0 + CAM_CTRLSTAT_READ_SET);
+ if (ci_stat & (BIT_CAM_READY << shift))
+ break;
+ udelay(1000);
+ }
+ if (!(ci_stat & (BIT_CAM_READY << shift)) && reset_counter > 0) {
+ dev_dbg(&dev->pci_dev->dev,
+ "%s(): CAMP reset timeout! Will try again..\n",
+ __func__);
+ reset_counter--;
+ goto reset;
+ }
+ return 0;
+}
+
+static int netup_unidvb_poll_ci_slot_status(struct dvb_ca_en50221 *en50221,
+ int slot, int open)
+{
+ struct netup_ci_state *state = en50221->data;
+ struct netup_unidvb_dev *dev = state->dev;
+ u16 shift = (state->nr == 1) ? CAM1_SHIFT : 0;
+ u16 ci_stat = 0;
+
+ dev_dbg(&dev->pci_dev->dev, "%s(): CAM_CTRLSTAT_READ_SET=0x%x\n",
+ __func__, readw(dev->bmmio0 + CAM_CTRLSTAT_READ_SET));
+ ci_stat = readw(dev->bmmio0 + CAM_CTRLSTAT_READ_SET);
+ if (ci_stat & (BIT_CAM_READY << shift)) {
+ state->status = DVB_CA_EN50221_POLL_CAM_PRESENT |
+ DVB_CA_EN50221_POLL_CAM_READY;
+ } else if (ci_stat & (BIT_CAM_PRESENT << shift)) {
+ state->status = DVB_CA_EN50221_POLL_CAM_PRESENT;
+ } else {
+ state->status = 0;
+ }
+ return state->status;
+}
+
+static int netup_unidvb_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221,
+ int slot, int addr)
+{
+ struct netup_ci_state *state = en50221->data;
+ struct netup_unidvb_dev *dev = state->dev;
+ u8 val = *((u8 __force *)state->membase8_io + addr);
+
+ dev_dbg(&dev->pci_dev->dev,
+ "%s(): addr=0x%x val=0x%x\n", __func__, addr, val);
+ return val;
+}
+
+static int netup_unidvb_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221,
+ int slot, int addr, u8 data)
+{
+ struct netup_ci_state *state = en50221->data;
+ struct netup_unidvb_dev *dev = state->dev;
+
+ dev_dbg(&dev->pci_dev->dev,
+ "%s(): addr=0x%x data=0x%x\n", __func__, addr, data);
+ *((u8 __force *)state->membase8_io + addr) = data;
+ return 0;
+}
+
+static int netup_unidvb_ci_read_cam_ctl(struct dvb_ca_en50221 *en50221,
+ int slot, u8 addr)
+{
+ struct netup_ci_state *state = en50221->data;
+ struct netup_unidvb_dev *dev = state->dev;
+ u8 val = *((u8 __force *)state->membase8_io + addr);
+
+ dev_dbg(&dev->pci_dev->dev,
+ "%s(): addr=0x%x val=0x%x\n", __func__, addr, val);
+ return val;
+}
+
+static int netup_unidvb_ci_write_cam_ctl(struct dvb_ca_en50221 *en50221,
+ int slot, u8 addr, u8 data)
+{
+ struct netup_ci_state *state = en50221->data;
+ struct netup_unidvb_dev *dev = state->dev;
+
+ dev_dbg(&dev->pci_dev->dev,
+ "%s(): addr=0x%x data=0x%x\n", __func__, addr, data);
+ *((u8 __force *)state->membase8_io + addr) = data;
+ return 0;
+}
+
+int netup_unidvb_ci_register(struct netup_unidvb_dev *dev,
+ int num, struct pci_dev *pci_dev)
+{
+ int result;
+ struct netup_ci_state *state;
+
+ if (num < 0 || num > 1) {
+ dev_err(&pci_dev->dev, "%s(): invalid CI adapter %d\n",
+ __func__, num);
+ return -EINVAL;
+ }
+ state = &dev->ci[num];
+ state->nr = num;
+ state->membase8_config = dev->bmmio1 +
+ ((num == 0) ? CAM0_CONFIG : CAM1_CONFIG);
+ state->membase8_io = dev->bmmio1 +
+ ((num == 0) ? CAM0_IO : CAM1_IO);
+ state->dev = dev;
+ state->ca.owner = THIS_MODULE;
+ state->ca.read_attribute_mem = netup_unidvb_ci_read_attribute_mem;
+ state->ca.write_attribute_mem = netup_unidvb_ci_write_attribute_mem;
+ state->ca.read_cam_control = netup_unidvb_ci_read_cam_ctl;
+ state->ca.write_cam_control = netup_unidvb_ci_write_cam_ctl;
+ state->ca.slot_reset = netup_unidvb_ci_slot_reset;
+ state->ca.slot_shutdown = netup_unidvb_ci_slot_shutdown;
+ state->ca.slot_ts_enable = netup_unidvb_ci_slot_ts_ctl;
+ state->ca.poll_slot_status = netup_unidvb_poll_ci_slot_status;
+ state->ca.data = state;
+ result = dvb_ca_en50221_init(&dev->frontends[num].adapter,
+ &state->ca, 0, 1);
+ if (result < 0) {
+ dev_err(&pci_dev->dev,
+ "%s(): dvb_ca_en50221_init result %d\n",
+ __func__, result);
+ return result;
+ }
+ writew(NETUP_UNIDVB_IRQ_CI, dev->bmmio0 + REG_IMASK_SET);
+ dev_info(&pci_dev->dev,
+ "%s(): CI adapter %d init done\n", __func__, num);
+ return 0;
+}
+
+void netup_unidvb_ci_unregister(struct netup_unidvb_dev *dev, int num)
+{
+ struct netup_ci_state *state;
+
+ dev_dbg(&dev->pci_dev->dev, "%s()\n", __func__);
+ if (num < 0 || num > 1) {
+ dev_err(&dev->pci_dev->dev, "%s(): invalid CI adapter %d\n",
+ __func__, num);
+ return;
+ }
+ state = &dev->ci[num];
+ dvb_ca_en50221_release(&state->ca);
+}
+
diff --git a/kernel/drivers/media/pci/netup_unidvb/netup_unidvb_core.c b/kernel/drivers/media/pci/netup_unidvb/netup_unidvb_core.c
new file mode 100644
index 000000000..3fdbd81b5
--- /dev/null
+++ b/kernel/drivers/media/pci/netup_unidvb/netup_unidvb_core.c
@@ -0,0 +1,1002 @@
+/*
+ * netup_unidvb_core.c
+ *
+ * Main module for NetUP Universal Dual DVB-CI
+ *
+ * Copyright (C) 2014 NetUP Inc.
+ * Copyright (C) 2014 Sergey Kozlov <serjk@netup.ru>
+ * Copyright (C) 2014 Abylay Ospan <aospan@netup.ru>
+ *
+ * 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/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kmod.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/list.h>
+#include <media/videobuf2-v4l2.h>
+#include <media/videobuf2-vmalloc.h>
+
+#include "netup_unidvb.h"
+#include "cxd2841er.h"
+#include "horus3a.h"
+#include "ascot2e.h"
+#include "lnbh25.h"
+
+static int spi_enable;
+module_param(spi_enable, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+
+MODULE_DESCRIPTION("Driver for NetUP Dual Universal DVB CI PCIe card");
+MODULE_AUTHOR("info@netup.ru");
+MODULE_VERSION(NETUP_UNIDVB_VERSION);
+MODULE_LICENSE("GPL");
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+/* Avalon-MM PCI-E registers */
+#define AVL_PCIE_IENR 0x50
+#define AVL_PCIE_ISR 0x40
+#define AVL_IRQ_ENABLE 0x80
+#define AVL_IRQ_ASSERTED 0x80
+/* GPIO registers */
+#define GPIO_REG_IO 0x4880
+#define GPIO_REG_IO_TOGGLE 0x4882
+#define GPIO_REG_IO_SET 0x4884
+#define GPIO_REG_IO_CLEAR 0x4886
+/* GPIO bits */
+#define GPIO_FEA_RESET (1 << 0)
+#define GPIO_FEB_RESET (1 << 1)
+#define GPIO_RFA_CTL (1 << 2)
+#define GPIO_RFB_CTL (1 << 3)
+#define GPIO_FEA_TU_RESET (1 << 4)
+#define GPIO_FEB_TU_RESET (1 << 5)
+/* DMA base address */
+#define NETUP_DMA0_ADDR 0x4900
+#define NETUP_DMA1_ADDR 0x4940
+/* 8 DMA blocks * 128 packets * 188 bytes*/
+#define NETUP_DMA_BLOCKS_COUNT 8
+#define NETUP_DMA_PACKETS_COUNT 128
+/* DMA status bits */
+#define BIT_DMA_RUN 1
+#define BIT_DMA_ERROR 2
+#define BIT_DMA_IRQ 0x200
+
+/**
+ * struct netup_dma_regs - the map of DMA module registers
+ * @ctrlstat_set: Control register, write to set control bits
+ * @ctrlstat_clear: Control register, write to clear control bits
+ * @start_addr_lo: DMA ring buffer start address, lower part
+ * @start_addr_hi: DMA ring buffer start address, higher part
+ * @size: DMA ring buffer size register
+ Bits [0-7]: DMA packet size, 188 bytes
+ Bits [16-23]: packets count in block, 128 packets
+ Bits [24-31]: blocks count, 8 blocks
+ * @timeout: DMA timeout in units of 8ns
+ For example, value of 375000000 equals to 3 sec
+ * @curr_addr_lo: Current ring buffer head address, lower part
+ * @curr_addr_hi: Current ring buffer head address, higher part
+ * @stat_pkt_received: Statistic register, not tested
+ * @stat_pkt_accepted: Statistic register, not tested
+ * @stat_pkt_overruns: Statistic register, not tested
+ * @stat_pkt_underruns: Statistic register, not tested
+ * @stat_fifo_overruns: Statistic register, not tested
+ */
+struct netup_dma_regs {
+ __le32 ctrlstat_set;
+ __le32 ctrlstat_clear;
+ __le32 start_addr_lo;
+ __le32 start_addr_hi;
+ __le32 size;
+ __le32 timeout;
+ __le32 curr_addr_lo;
+ __le32 curr_addr_hi;
+ __le32 stat_pkt_received;
+ __le32 stat_pkt_accepted;
+ __le32 stat_pkt_overruns;
+ __le32 stat_pkt_underruns;
+ __le32 stat_fifo_overruns;
+} __packed __aligned(1);
+
+struct netup_unidvb_buffer {
+ struct vb2_v4l2_buffer vb;
+ struct list_head list;
+ u32 size;
+};
+
+static int netup_unidvb_tuner_ctrl(void *priv, int is_dvb_tc);
+static void netup_unidvb_queue_cleanup(struct netup_dma *dma);
+
+static struct cxd2841er_config demod_config = {
+ .i2c_addr = 0xc8
+};
+
+static struct horus3a_config horus3a_conf = {
+ .i2c_address = 0xc0,
+ .xtal_freq_mhz = 16,
+ .set_tuner_callback = netup_unidvb_tuner_ctrl
+};
+
+static struct ascot2e_config ascot2e_conf = {
+ .i2c_address = 0xc2,
+ .set_tuner_callback = netup_unidvb_tuner_ctrl
+};
+
+static struct lnbh25_config lnbh25_conf = {
+ .i2c_address = 0x10,
+ .data2_config = LNBH25_TEN | LNBH25_EXTM
+};
+
+static int netup_unidvb_tuner_ctrl(void *priv, int is_dvb_tc)
+{
+ u8 reg, mask;
+ struct netup_dma *dma = priv;
+ struct netup_unidvb_dev *ndev;
+
+ if (!priv)
+ return -EINVAL;
+ ndev = dma->ndev;
+ dev_dbg(&ndev->pci_dev->dev, "%s(): num %d is_dvb_tc %d\n",
+ __func__, dma->num, is_dvb_tc);
+ reg = readb(ndev->bmmio0 + GPIO_REG_IO);
+ mask = (dma->num == 0) ? GPIO_RFA_CTL : GPIO_RFB_CTL;
+ if (!is_dvb_tc)
+ reg |= mask;
+ else
+ reg &= ~mask;
+ writeb(reg, ndev->bmmio0 + GPIO_REG_IO);
+ return 0;
+}
+
+static void netup_unidvb_dev_enable(struct netup_unidvb_dev *ndev)
+{
+ u16 gpio_reg;
+
+ /* enable PCI-E interrupts */
+ writel(AVL_IRQ_ENABLE, ndev->bmmio0 + AVL_PCIE_IENR);
+ /* unreset frontends bits[0:1] */
+ writeb(0x00, ndev->bmmio0 + GPIO_REG_IO);
+ msleep(100);
+ gpio_reg =
+ GPIO_FEA_RESET | GPIO_FEB_RESET |
+ GPIO_FEA_TU_RESET | GPIO_FEB_TU_RESET |
+ GPIO_RFA_CTL | GPIO_RFB_CTL;
+ writeb(gpio_reg, ndev->bmmio0 + GPIO_REG_IO);
+ dev_dbg(&ndev->pci_dev->dev,
+ "%s(): AVL_PCIE_IENR 0x%x GPIO_REG_IO 0x%x\n",
+ __func__, readl(ndev->bmmio0 + AVL_PCIE_IENR),
+ (int)readb(ndev->bmmio0 + GPIO_REG_IO));
+
+}
+
+static void netup_unidvb_dma_enable(struct netup_dma *dma, int enable)
+{
+ u32 irq_mask = (dma->num == 0 ?
+ NETUP_UNIDVB_IRQ_DMA1 : NETUP_UNIDVB_IRQ_DMA2);
+
+ dev_dbg(&dma->ndev->pci_dev->dev,
+ "%s(): DMA%d enable %d\n", __func__, dma->num, enable);
+ if (enable) {
+ writel(BIT_DMA_RUN, &dma->regs->ctrlstat_set);
+ writew(irq_mask, dma->ndev->bmmio0 + REG_IMASK_SET);
+ } else {
+ writel(BIT_DMA_RUN, &dma->regs->ctrlstat_clear);
+ writew(irq_mask, dma->ndev->bmmio0 + REG_IMASK_CLEAR);
+ }
+}
+
+static irqreturn_t netup_dma_interrupt(struct netup_dma *dma)
+{
+ u64 addr_curr;
+ u32 size;
+ unsigned long flags;
+ struct device *dev = &dma->ndev->pci_dev->dev;
+
+ spin_lock_irqsave(&dma->lock, flags);
+ addr_curr = ((u64)readl(&dma->regs->curr_addr_hi) << 32) |
+ (u64)readl(&dma->regs->curr_addr_lo) | dma->high_addr;
+ /* clear IRQ */
+ writel(BIT_DMA_IRQ, &dma->regs->ctrlstat_clear);
+ /* sanity check */
+ if (addr_curr < dma->addr_phys ||
+ addr_curr > dma->addr_phys + dma->ring_buffer_size) {
+ if (addr_curr != 0) {
+ dev_err(dev,
+ "%s(): addr 0x%llx not from 0x%llx:0x%llx\n",
+ __func__, addr_curr, (u64)dma->addr_phys,
+ (u64)(dma->addr_phys + dma->ring_buffer_size));
+ }
+ goto irq_handled;
+ }
+ size = (addr_curr >= dma->addr_last) ?
+ (u32)(addr_curr - dma->addr_last) :
+ (u32)(dma->ring_buffer_size - (dma->addr_last - addr_curr));
+ if (dma->data_size != 0) {
+ printk_ratelimited("%s(): lost interrupt, data size %d\n",
+ __func__, dma->data_size);
+ dma->data_size += size;
+ }
+ if (dma->data_size == 0 || dma->data_size > dma->ring_buffer_size) {
+ dma->data_size = size;
+ dma->data_offset = (u32)(dma->addr_last - dma->addr_phys);
+ }
+ dma->addr_last = addr_curr;
+ queue_work(dma->ndev->wq, &dma->work);
+irq_handled:
+ spin_unlock_irqrestore(&dma->lock, flags);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t netup_unidvb_isr(int irq, void *dev_id)
+{
+ struct pci_dev *pci_dev = (struct pci_dev *)dev_id;
+ struct netup_unidvb_dev *ndev = pci_get_drvdata(pci_dev);
+ u32 reg40, reg_isr;
+ irqreturn_t iret = IRQ_NONE;
+
+ /* disable interrupts */
+ writel(0, ndev->bmmio0 + AVL_PCIE_IENR);
+ /* check IRQ source */
+ reg40 = readl(ndev->bmmio0 + AVL_PCIE_ISR);
+ if ((reg40 & AVL_IRQ_ASSERTED) != 0) {
+ /* IRQ is being signaled */
+ reg_isr = readw(ndev->bmmio0 + REG_ISR);
+ if (reg_isr & NETUP_UNIDVB_IRQ_I2C0) {
+ iret = netup_i2c_interrupt(&ndev->i2c[0]);
+ } else if (reg_isr & NETUP_UNIDVB_IRQ_I2C1) {
+ iret = netup_i2c_interrupt(&ndev->i2c[1]);
+ } else if (reg_isr & NETUP_UNIDVB_IRQ_SPI) {
+ iret = netup_spi_interrupt(ndev->spi);
+ } else if (reg_isr & NETUP_UNIDVB_IRQ_DMA1) {
+ iret = netup_dma_interrupt(&ndev->dma[0]);
+ } else if (reg_isr & NETUP_UNIDVB_IRQ_DMA2) {
+ iret = netup_dma_interrupt(&ndev->dma[1]);
+ } else if (reg_isr & NETUP_UNIDVB_IRQ_CI) {
+ iret = netup_ci_interrupt(ndev);
+ } else {
+ dev_err(&pci_dev->dev,
+ "%s(): unknown interrupt 0x%x\n",
+ __func__, reg_isr);
+ }
+ }
+ /* re-enable interrupts */
+ writel(AVL_IRQ_ENABLE, ndev->bmmio0 + AVL_PCIE_IENR);
+ return iret;
+}
+
+static int netup_unidvb_queue_setup(struct vb2_queue *vq,
+ const void *parg,
+ unsigned int *nbuffers,
+ unsigned int *nplanes,
+ unsigned int sizes[],
+ void *alloc_ctxs[])
+{
+ struct netup_dma *dma = vb2_get_drv_priv(vq);
+
+ dev_dbg(&dma->ndev->pci_dev->dev, "%s()\n", __func__);
+
+ *nplanes = 1;
+ if (vq->num_buffers + *nbuffers < VIDEO_MAX_FRAME)
+ *nbuffers = VIDEO_MAX_FRAME - vq->num_buffers;
+ sizes[0] = PAGE_ALIGN(NETUP_DMA_PACKETS_COUNT * 188);
+ dev_dbg(&dma->ndev->pci_dev->dev, "%s() nbuffers=%d sizes[0]=%d\n",
+ __func__, *nbuffers, sizes[0]);
+ return 0;
+}
+
+static int netup_unidvb_buf_prepare(struct vb2_buffer *vb)
+{
+ struct netup_dma *dma = vb2_get_drv_priv(vb->vb2_queue);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct netup_unidvb_buffer *buf = container_of(vbuf,
+ struct netup_unidvb_buffer, vb);
+
+ dev_dbg(&dma->ndev->pci_dev->dev, "%s(): buf 0x%p\n", __func__, buf);
+ buf->size = 0;
+ return 0;
+}
+
+static void netup_unidvb_buf_queue(struct vb2_buffer *vb)
+{
+ unsigned long flags;
+ struct netup_dma *dma = vb2_get_drv_priv(vb->vb2_queue);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct netup_unidvb_buffer *buf = container_of(vbuf,
+ struct netup_unidvb_buffer, vb);
+
+ dev_dbg(&dma->ndev->pci_dev->dev, "%s(): %p\n", __func__, buf);
+ spin_lock_irqsave(&dma->lock, flags);
+ list_add_tail(&buf->list, &dma->free_buffers);
+ spin_unlock_irqrestore(&dma->lock, flags);
+ mod_timer(&dma->timeout, jiffies + msecs_to_jiffies(1000));
+}
+
+static int netup_unidvb_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+ struct netup_dma *dma = vb2_get_drv_priv(q);
+
+ dev_dbg(&dma->ndev->pci_dev->dev, "%s()\n", __func__);
+ netup_unidvb_dma_enable(dma, 1);
+ return 0;
+}
+
+static void netup_unidvb_stop_streaming(struct vb2_queue *q)
+{
+ struct netup_dma *dma = vb2_get_drv_priv(q);
+
+ dev_dbg(&dma->ndev->pci_dev->dev, "%s()\n", __func__);
+ netup_unidvb_dma_enable(dma, 0);
+ netup_unidvb_queue_cleanup(dma);
+}
+
+static struct vb2_ops dvb_qops = {
+ .queue_setup = netup_unidvb_queue_setup,
+ .buf_prepare = netup_unidvb_buf_prepare,
+ .buf_queue = netup_unidvb_buf_queue,
+ .start_streaming = netup_unidvb_start_streaming,
+ .stop_streaming = netup_unidvb_stop_streaming,
+};
+
+static int netup_unidvb_queue_init(struct netup_dma *dma,
+ struct vb2_queue *vb_queue)
+{
+ int res;
+
+ /* Init videobuf2 queue structure */
+ vb_queue->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ vb_queue->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
+ vb_queue->drv_priv = dma;
+ vb_queue->buf_struct_size = sizeof(struct netup_unidvb_buffer);
+ vb_queue->ops = &dvb_qops;
+ vb_queue->mem_ops = &vb2_vmalloc_memops;
+ vb_queue->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+ res = vb2_queue_init(vb_queue);
+ if (res != 0) {
+ dev_err(&dma->ndev->pci_dev->dev,
+ "%s(): vb2_queue_init failed (%d)\n", __func__, res);
+ }
+ return res;
+}
+
+static int netup_unidvb_dvb_init(struct netup_unidvb_dev *ndev,
+ int num)
+{
+ struct vb2_dvb_frontend *fe0, *fe1, *fe2;
+
+ if (num < 0 || num > 1) {
+ dev_dbg(&ndev->pci_dev->dev,
+ "%s(): unable to init DVB bus %d\n", __func__, num);
+ return -ENODEV;
+ }
+ mutex_init(&ndev->frontends[num].lock);
+ INIT_LIST_HEAD(&ndev->frontends[num].felist);
+ if (vb2_dvb_alloc_frontend(&ndev->frontends[num], 1) == NULL ||
+ vb2_dvb_alloc_frontend(
+ &ndev->frontends[num], 2) == NULL ||
+ vb2_dvb_alloc_frontend(
+ &ndev->frontends[num], 3) == NULL) {
+ dev_dbg(&ndev->pci_dev->dev,
+ "%s(): unable to to alllocate vb2_dvb_frontend\n",
+ __func__);
+ return -ENOMEM;
+ }
+ fe0 = vb2_dvb_get_frontend(&ndev->frontends[num], 1);
+ fe1 = vb2_dvb_get_frontend(&ndev->frontends[num], 2);
+ fe2 = vb2_dvb_get_frontend(&ndev->frontends[num], 3);
+ if (fe0 == NULL || fe1 == NULL || fe2 == NULL) {
+ dev_dbg(&ndev->pci_dev->dev,
+ "%s(): frontends has not been allocated\n", __func__);
+ return -EINVAL;
+ }
+ netup_unidvb_queue_init(&ndev->dma[num], &fe0->dvb.dvbq);
+ netup_unidvb_queue_init(&ndev->dma[num], &fe1->dvb.dvbq);
+ netup_unidvb_queue_init(&ndev->dma[num], &fe2->dvb.dvbq);
+ fe0->dvb.name = "netup_fe0";
+ fe1->dvb.name = "netup_fe1";
+ fe2->dvb.name = "netup_fe2";
+ fe0->dvb.frontend = dvb_attach(cxd2841er_attach_s,
+ &demod_config, &ndev->i2c[num].adap);
+ if (fe0->dvb.frontend == NULL) {
+ dev_dbg(&ndev->pci_dev->dev,
+ "%s(): unable to attach DVB-S/S2 frontend\n",
+ __func__);
+ goto frontend_detach;
+ }
+ horus3a_conf.set_tuner_priv = &ndev->dma[num];
+ if (!dvb_attach(horus3a_attach, fe0->dvb.frontend,
+ &horus3a_conf, &ndev->i2c[num].adap)) {
+ dev_dbg(&ndev->pci_dev->dev,
+ "%s(): unable to attach DVB-S/S2 tuner frontend\n",
+ __func__);
+ goto frontend_detach;
+ }
+ if (!dvb_attach(lnbh25_attach, fe0->dvb.frontend,
+ &lnbh25_conf, &ndev->i2c[num].adap)) {
+ dev_dbg(&ndev->pci_dev->dev,
+ "%s(): unable to attach SEC frontend\n", __func__);
+ goto frontend_detach;
+ }
+ /* DVB-T/T2 frontend */
+ fe1->dvb.frontend = dvb_attach(cxd2841er_attach_t,
+ &demod_config, &ndev->i2c[num].adap);
+ if (fe1->dvb.frontend == NULL) {
+ dev_dbg(&ndev->pci_dev->dev,
+ "%s(): unable to attach DVB-T frontend\n", __func__);
+ goto frontend_detach;
+ }
+ fe1->dvb.frontend->id = 1;
+ ascot2e_conf.set_tuner_priv = &ndev->dma[num];
+ if (!dvb_attach(ascot2e_attach, fe1->dvb.frontend,
+ &ascot2e_conf, &ndev->i2c[num].adap)) {
+ dev_dbg(&ndev->pci_dev->dev,
+ "%s(): unable to attach DVB-T tuner frontend\n",
+ __func__);
+ goto frontend_detach;
+ }
+ /* DVB-C/C2 frontend */
+ fe2->dvb.frontend = dvb_attach(cxd2841er_attach_c,
+ &demod_config, &ndev->i2c[num].adap);
+ if (fe2->dvb.frontend == NULL) {
+ dev_dbg(&ndev->pci_dev->dev,
+ "%s(): unable to attach DVB-C frontend\n", __func__);
+ goto frontend_detach;
+ }
+ fe2->dvb.frontend->id = 2;
+ if (!dvb_attach(ascot2e_attach, fe2->dvb.frontend,
+ &ascot2e_conf, &ndev->i2c[num].adap)) {
+ dev_dbg(&ndev->pci_dev->dev,
+ "%s(): unable to attach DVB-T/C tuner frontend\n",
+ __func__);
+ goto frontend_detach;
+ }
+
+ if (vb2_dvb_register_bus(&ndev->frontends[num],
+ THIS_MODULE, NULL,
+ &ndev->pci_dev->dev, adapter_nr, 1)) {
+ dev_dbg(&ndev->pci_dev->dev,
+ "%s(): unable to register DVB bus %d\n",
+ __func__, num);
+ goto frontend_detach;
+ }
+ dev_info(&ndev->pci_dev->dev, "DVB init done, num=%d\n", num);
+ return 0;
+frontend_detach:
+ vb2_dvb_dealloc_frontends(&ndev->frontends[num]);
+ return -EINVAL;
+}
+
+static void netup_unidvb_dvb_fini(struct netup_unidvb_dev *ndev, int num)
+{
+ if (num < 0 || num > 1) {
+ dev_err(&ndev->pci_dev->dev,
+ "%s(): unable to unregister DVB bus %d\n",
+ __func__, num);
+ return;
+ }
+ vb2_dvb_unregister_bus(&ndev->frontends[num]);
+ dev_info(&ndev->pci_dev->dev,
+ "%s(): DVB bus %d unregistered\n", __func__, num);
+}
+
+static int netup_unidvb_dvb_setup(struct netup_unidvb_dev *ndev)
+{
+ int res;
+
+ res = netup_unidvb_dvb_init(ndev, 0);
+ if (res)
+ return res;
+ res = netup_unidvb_dvb_init(ndev, 1);
+ if (res) {
+ netup_unidvb_dvb_fini(ndev, 0);
+ return res;
+ }
+ return 0;
+}
+
+static int netup_unidvb_ring_copy(struct netup_dma *dma,
+ struct netup_unidvb_buffer *buf)
+{
+ u32 copy_bytes, ring_bytes;
+ u32 buff_bytes = NETUP_DMA_PACKETS_COUNT * 188 - buf->size;
+ u8 *p = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
+ struct netup_unidvb_dev *ndev = dma->ndev;
+
+ if (p == NULL) {
+ dev_err(&ndev->pci_dev->dev,
+ "%s(): buffer is NULL\n", __func__);
+ return -EINVAL;
+ }
+ p += buf->size;
+ if (dma->data_offset + dma->data_size > dma->ring_buffer_size) {
+ ring_bytes = dma->ring_buffer_size - dma->data_offset;
+ copy_bytes = (ring_bytes > buff_bytes) ?
+ buff_bytes : ring_bytes;
+ memcpy_fromio(p, (u8 __iomem *)(dma->addr_virt + dma->data_offset), copy_bytes);
+ p += copy_bytes;
+ buf->size += copy_bytes;
+ buff_bytes -= copy_bytes;
+ dma->data_size -= copy_bytes;
+ dma->data_offset += copy_bytes;
+ if (dma->data_offset == dma->ring_buffer_size)
+ dma->data_offset = 0;
+ }
+ if (buff_bytes > 0) {
+ ring_bytes = dma->data_size;
+ copy_bytes = (ring_bytes > buff_bytes) ?
+ buff_bytes : ring_bytes;
+ memcpy_fromio(p, (u8 __iomem *)(dma->addr_virt + dma->data_offset), copy_bytes);
+ buf->size += copy_bytes;
+ dma->data_size -= copy_bytes;
+ dma->data_offset += copy_bytes;
+ if (dma->data_offset == dma->ring_buffer_size)
+ dma->data_offset = 0;
+ }
+ return 0;
+}
+
+static void netup_unidvb_dma_worker(struct work_struct *work)
+{
+ struct netup_dma *dma = container_of(work, struct netup_dma, work);
+ struct netup_unidvb_dev *ndev = dma->ndev;
+ struct netup_unidvb_buffer *buf;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dma->lock, flags);
+ if (dma->data_size == 0) {
+ dev_dbg(&ndev->pci_dev->dev,
+ "%s(): data_size == 0\n", __func__);
+ goto work_done;
+ }
+ while (dma->data_size > 0) {
+ if (list_empty(&dma->free_buffers)) {
+ dev_dbg(&ndev->pci_dev->dev,
+ "%s(): no free buffers\n", __func__);
+ goto work_done;
+ }
+ buf = list_first_entry(&dma->free_buffers,
+ struct netup_unidvb_buffer, list);
+ if (buf->size >= NETUP_DMA_PACKETS_COUNT * 188) {
+ dev_dbg(&ndev->pci_dev->dev,
+ "%s(): buffer overflow, size %d\n",
+ __func__, buf->size);
+ goto work_done;
+ }
+ if (netup_unidvb_ring_copy(dma, buf))
+ goto work_done;
+ if (buf->size == NETUP_DMA_PACKETS_COUNT * 188) {
+ list_del(&buf->list);
+ dev_dbg(&ndev->pci_dev->dev,
+ "%s(): buffer %p done, size %d\n",
+ __func__, buf, buf->size);
+ v4l2_get_timestamp(&buf->vb.timestamp);
+ vb2_set_plane_payload(&buf->vb.vb2_buf, 0, buf->size);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
+ }
+ }
+work_done:
+ dma->data_size = 0;
+ spin_unlock_irqrestore(&dma->lock, flags);
+}
+
+static void netup_unidvb_queue_cleanup(struct netup_dma *dma)
+{
+ struct netup_unidvb_buffer *buf;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dma->lock, flags);
+ while (!list_empty(&dma->free_buffers)) {
+ buf = list_first_entry(&dma->free_buffers,
+ struct netup_unidvb_buffer, list);
+ list_del(&buf->list);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+ }
+ spin_unlock_irqrestore(&dma->lock, flags);
+}
+
+static void netup_unidvb_dma_timeout(unsigned long data)
+{
+ struct netup_dma *dma = (struct netup_dma *)data;
+ struct netup_unidvb_dev *ndev = dma->ndev;
+
+ dev_dbg(&ndev->pci_dev->dev, "%s()\n", __func__);
+ netup_unidvb_queue_cleanup(dma);
+}
+
+static int netup_unidvb_dma_init(struct netup_unidvb_dev *ndev, int num)
+{
+ struct netup_dma *dma;
+ struct device *dev = &ndev->pci_dev->dev;
+
+ if (num < 0 || num > 1) {
+ dev_err(dev, "%s(): unable to register DMA%d\n",
+ __func__, num);
+ return -ENODEV;
+ }
+ dma = &ndev->dma[num];
+ dev_info(dev, "%s(): starting DMA%d\n", __func__, num);
+ dma->num = num;
+ dma->ndev = ndev;
+ spin_lock_init(&dma->lock);
+ INIT_WORK(&dma->work, netup_unidvb_dma_worker);
+ INIT_LIST_HEAD(&dma->free_buffers);
+ dma->timeout.function = netup_unidvb_dma_timeout;
+ dma->timeout.data = (unsigned long)dma;
+ init_timer(&dma->timeout);
+ dma->ring_buffer_size = ndev->dma_size / 2;
+ dma->addr_virt = ndev->dma_virt + dma->ring_buffer_size * num;
+ dma->addr_phys = (dma_addr_t)((u64)ndev->dma_phys +
+ dma->ring_buffer_size * num);
+ dev_info(dev, "%s(): DMA%d buffer virt/phys 0x%p/0x%llx size %d\n",
+ __func__, num, dma->addr_virt,
+ (unsigned long long)dma->addr_phys,
+ dma->ring_buffer_size);
+ memset_io((u8 __iomem *)dma->addr_virt, 0, dma->ring_buffer_size);
+ dma->addr_last = dma->addr_phys;
+ dma->high_addr = (u32)(dma->addr_phys & 0xC0000000);
+ dma->regs = (struct netup_dma_regs __iomem *)(num == 0 ?
+ ndev->bmmio0 + NETUP_DMA0_ADDR :
+ ndev->bmmio0 + NETUP_DMA1_ADDR);
+ writel((NETUP_DMA_BLOCKS_COUNT << 24) |
+ (NETUP_DMA_PACKETS_COUNT << 8) | 188, &dma->regs->size);
+ writel((u32)(dma->addr_phys & 0x3FFFFFFF), &dma->regs->start_addr_lo);
+ writel(0, &dma->regs->start_addr_hi);
+ writel(dma->high_addr, ndev->bmmio0 + 0x1000);
+ writel(375000000, &dma->regs->timeout);
+ msleep(1000);
+ writel(BIT_DMA_IRQ, &dma->regs->ctrlstat_clear);
+ return 0;
+}
+
+static void netup_unidvb_dma_fini(struct netup_unidvb_dev *ndev, int num)
+{
+ struct netup_dma *dma;
+
+ if (num < 0 || num > 1)
+ return;
+ dev_dbg(&ndev->pci_dev->dev, "%s(): num %d\n", __func__, num);
+ dma = &ndev->dma[num];
+ netup_unidvb_dma_enable(dma, 0);
+ msleep(50);
+ cancel_work_sync(&dma->work);
+ del_timer(&dma->timeout);
+}
+
+static int netup_unidvb_dma_setup(struct netup_unidvb_dev *ndev)
+{
+ int res;
+
+ res = netup_unidvb_dma_init(ndev, 0);
+ if (res)
+ return res;
+ res = netup_unidvb_dma_init(ndev, 1);
+ if (res) {
+ netup_unidvb_dma_fini(ndev, 0);
+ return res;
+ }
+ netup_unidvb_dma_enable(&ndev->dma[0], 0);
+ netup_unidvb_dma_enable(&ndev->dma[1], 0);
+ return 0;
+}
+
+static int netup_unidvb_ci_setup(struct netup_unidvb_dev *ndev,
+ struct pci_dev *pci_dev)
+{
+ int res;
+
+ writew(NETUP_UNIDVB_IRQ_CI, ndev->bmmio0 + REG_IMASK_SET);
+ res = netup_unidvb_ci_register(ndev, 0, pci_dev);
+ if (res)
+ return res;
+ res = netup_unidvb_ci_register(ndev, 1, pci_dev);
+ if (res)
+ netup_unidvb_ci_unregister(ndev, 0);
+ return res;
+}
+
+static int netup_unidvb_request_mmio(struct pci_dev *pci_dev)
+{
+ if (!request_mem_region(pci_resource_start(pci_dev, 0),
+ pci_resource_len(pci_dev, 0), NETUP_UNIDVB_NAME)) {
+ dev_err(&pci_dev->dev,
+ "%s(): unable to request MMIO bar 0 at 0x%llx\n",
+ __func__,
+ (unsigned long long)pci_resource_start(pci_dev, 0));
+ return -EBUSY;
+ }
+ if (!request_mem_region(pci_resource_start(pci_dev, 1),
+ pci_resource_len(pci_dev, 1), NETUP_UNIDVB_NAME)) {
+ dev_err(&pci_dev->dev,
+ "%s(): unable to request MMIO bar 1 at 0x%llx\n",
+ __func__,
+ (unsigned long long)pci_resource_start(pci_dev, 1));
+ release_mem_region(pci_resource_start(pci_dev, 0),
+ pci_resource_len(pci_dev, 0));
+ return -EBUSY;
+ }
+ return 0;
+}
+
+static int netup_unidvb_request_modules(struct device *dev)
+{
+ static const char * const modules[] = {
+ "lnbh25", "ascot2e", "horus3a", "cxd2841er", NULL
+ };
+ const char * const *curr_mod = modules;
+ int err;
+
+ while (*curr_mod != NULL) {
+ err = request_module(*curr_mod);
+ if (err) {
+ dev_warn(dev, "request_module(%s) failed: %d\n",
+ *curr_mod, err);
+ }
+ ++curr_mod;
+ }
+ return 0;
+}
+
+static int netup_unidvb_initdev(struct pci_dev *pci_dev,
+ const struct pci_device_id *pci_id)
+{
+ u8 board_revision;
+ u16 board_vendor;
+ struct netup_unidvb_dev *ndev;
+ int old_firmware = 0;
+
+ netup_unidvb_request_modules(&pci_dev->dev);
+
+ /* Check card revision */
+ if (pci_dev->revision != NETUP_PCI_DEV_REVISION) {
+ dev_err(&pci_dev->dev,
+ "netup_unidvb: expected card revision %d, got %d\n",
+ NETUP_PCI_DEV_REVISION, pci_dev->revision);
+ dev_err(&pci_dev->dev,
+ "Please upgrade firmware!\n");
+ dev_err(&pci_dev->dev,
+ "Instructions on http://www.netup.tv\n");
+ old_firmware = 1;
+ spi_enable = 1;
+ }
+
+ /* allocate device context */
+ ndev = kzalloc(sizeof(*ndev), GFP_KERNEL);
+
+ if (!ndev)
+ goto dev_alloc_err;
+ memset(ndev, 0, sizeof(*ndev));
+ ndev->old_fw = old_firmware;
+ ndev->wq = create_singlethread_workqueue(NETUP_UNIDVB_NAME);
+ if (!ndev->wq) {
+ dev_err(&pci_dev->dev,
+ "%s(): unable to create workqueue\n", __func__);
+ goto wq_create_err;
+ }
+ ndev->pci_dev = pci_dev;
+ ndev->pci_bus = pci_dev->bus->number;
+ ndev->pci_slot = PCI_SLOT(pci_dev->devfn);
+ ndev->pci_func = PCI_FUNC(pci_dev->devfn);
+ ndev->board_num = ndev->pci_bus*10 + ndev->pci_slot;
+ pci_set_drvdata(pci_dev, ndev);
+ /* PCI init */
+ dev_info(&pci_dev->dev, "%s(): PCI device (%d). Bus:0x%x Slot:0x%x\n",
+ __func__, ndev->board_num, ndev->pci_bus, ndev->pci_slot);
+
+ if (pci_enable_device(pci_dev)) {
+ dev_err(&pci_dev->dev, "%s(): pci_enable_device failed\n",
+ __func__);
+ goto pci_enable_err;
+ }
+ /* read PCI info */
+ pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &board_revision);
+ pci_read_config_word(pci_dev, PCI_VENDOR_ID, &board_vendor);
+ if (board_vendor != NETUP_VENDOR_ID) {
+ dev_err(&pci_dev->dev, "%s(): unknown board vendor 0x%x",
+ __func__, board_vendor);
+ goto pci_detect_err;
+ }
+ dev_info(&pci_dev->dev,
+ "%s(): board vendor 0x%x, revision 0x%x\n",
+ __func__, board_vendor, board_revision);
+ pci_set_master(pci_dev);
+ if (pci_set_dma_mask(pci_dev, 0xffffffff) < 0) {
+ dev_err(&pci_dev->dev,
+ "%s(): 32bit PCI DMA is not supported\n", __func__);
+ goto pci_detect_err;
+ }
+ dev_info(&pci_dev->dev, "%s(): using 32bit PCI DMA\n", __func__);
+ /* Clear "no snoop" and "relaxed ordering" bits, use default MRRS. */
+ pcie_capability_clear_and_set_word(pci_dev, PCI_EXP_DEVCTL,
+ PCI_EXP_DEVCTL_READRQ | PCI_EXP_DEVCTL_RELAX_EN |
+ PCI_EXP_DEVCTL_NOSNOOP_EN, 0);
+ /* Adjust PCIe completion timeout. */
+ pcie_capability_clear_and_set_word(pci_dev,
+ PCI_EXP_DEVCTL2, 0xf, 0x2);
+
+ if (netup_unidvb_request_mmio(pci_dev)) {
+ dev_err(&pci_dev->dev,
+ "%s(): unable to request MMIO regions\n", __func__);
+ goto pci_detect_err;
+ }
+ ndev->lmmio0 = ioremap(pci_resource_start(pci_dev, 0),
+ pci_resource_len(pci_dev, 0));
+ if (!ndev->lmmio0) {
+ dev_err(&pci_dev->dev,
+ "%s(): unable to remap MMIO bar 0\n", __func__);
+ goto pci_bar0_error;
+ }
+ ndev->lmmio1 = ioremap(pci_resource_start(pci_dev, 1),
+ pci_resource_len(pci_dev, 1));
+ if (!ndev->lmmio1) {
+ dev_err(&pci_dev->dev,
+ "%s(): unable to remap MMIO bar 1\n", __func__);
+ goto pci_bar1_error;
+ }
+ ndev->bmmio0 = (u8 __iomem *)ndev->lmmio0;
+ ndev->bmmio1 = (u8 __iomem *)ndev->lmmio1;
+ dev_info(&pci_dev->dev,
+ "%s(): PCI MMIO at 0x%p (%d); 0x%p (%d); IRQ %d",
+ __func__,
+ ndev->lmmio0, (u32)pci_resource_len(pci_dev, 0),
+ ndev->lmmio1, (u32)pci_resource_len(pci_dev, 1),
+ pci_dev->irq);
+ if (request_irq(pci_dev->irq, netup_unidvb_isr, IRQF_SHARED,
+ "netup_unidvb", pci_dev) < 0) {
+ dev_err(&pci_dev->dev,
+ "%s(): can't get IRQ %d\n", __func__, pci_dev->irq);
+ goto irq_request_err;
+ }
+ ndev->dma_size = 2 * 188 *
+ NETUP_DMA_BLOCKS_COUNT * NETUP_DMA_PACKETS_COUNT;
+ ndev->dma_virt = dma_alloc_coherent(&pci_dev->dev,
+ ndev->dma_size, &ndev->dma_phys, GFP_KERNEL);
+ if (!ndev->dma_virt) {
+ dev_err(&pci_dev->dev, "%s(): unable to allocate DMA buffer\n",
+ __func__);
+ goto dma_alloc_err;
+ }
+ netup_unidvb_dev_enable(ndev);
+ if (spi_enable && netup_spi_init(ndev)) {
+ dev_warn(&pci_dev->dev,
+ "netup_unidvb: SPI flash setup failed\n");
+ goto spi_setup_err;
+ }
+ if (old_firmware) {
+ dev_err(&pci_dev->dev,
+ "netup_unidvb: card initialization was incomplete\n");
+ return 0;
+ }
+ if (netup_i2c_register(ndev)) {
+ dev_err(&pci_dev->dev, "netup_unidvb: I2C setup failed\n");
+ goto i2c_setup_err;
+ }
+ /* enable I2C IRQs */
+ writew(NETUP_UNIDVB_IRQ_I2C0 | NETUP_UNIDVB_IRQ_I2C1,
+ ndev->bmmio0 + REG_IMASK_SET);
+ usleep_range(5000, 10000);
+ if (netup_unidvb_dvb_setup(ndev)) {
+ dev_err(&pci_dev->dev, "netup_unidvb: DVB setup failed\n");
+ goto dvb_setup_err;
+ }
+ if (netup_unidvb_ci_setup(ndev, pci_dev)) {
+ dev_err(&pci_dev->dev, "netup_unidvb: CI setup failed\n");
+ goto ci_setup_err;
+ }
+ if (netup_unidvb_dma_setup(ndev)) {
+ dev_err(&pci_dev->dev, "netup_unidvb: DMA setup failed\n");
+ goto dma_setup_err;
+ }
+ dev_info(&pci_dev->dev,
+ "netup_unidvb: device has been initialized\n");
+ return 0;
+dma_setup_err:
+ netup_unidvb_ci_unregister(ndev, 0);
+ netup_unidvb_ci_unregister(ndev, 1);
+ci_setup_err:
+ netup_unidvb_dvb_fini(ndev, 0);
+ netup_unidvb_dvb_fini(ndev, 1);
+dvb_setup_err:
+ netup_i2c_unregister(ndev);
+i2c_setup_err:
+ if (ndev->spi)
+ netup_spi_release(ndev);
+spi_setup_err:
+ dma_free_coherent(&pci_dev->dev, ndev->dma_size,
+ ndev->dma_virt, ndev->dma_phys);
+dma_alloc_err:
+ free_irq(pci_dev->irq, pci_dev);
+irq_request_err:
+ iounmap(ndev->lmmio1);
+pci_bar1_error:
+ iounmap(ndev->lmmio0);
+pci_bar0_error:
+ release_mem_region(pci_resource_start(pci_dev, 0),
+ pci_resource_len(pci_dev, 0));
+ release_mem_region(pci_resource_start(pci_dev, 1),
+ pci_resource_len(pci_dev, 1));
+pci_detect_err:
+ pci_disable_device(pci_dev);
+pci_enable_err:
+ pci_set_drvdata(pci_dev, NULL);
+ destroy_workqueue(ndev->wq);
+wq_create_err:
+ kfree(ndev);
+dev_alloc_err:
+ dev_err(&pci_dev->dev,
+ "%s(): failed to initizalize device\n", __func__);
+ return -EIO;
+}
+
+static void netup_unidvb_finidev(struct pci_dev *pci_dev)
+{
+ struct netup_unidvb_dev *ndev = pci_get_drvdata(pci_dev);
+
+ dev_info(&pci_dev->dev, "%s(): trying to stop device\n", __func__);
+ if (!ndev->old_fw) {
+ netup_unidvb_dma_fini(ndev, 0);
+ netup_unidvb_dma_fini(ndev, 1);
+ netup_unidvb_ci_unregister(ndev, 0);
+ netup_unidvb_ci_unregister(ndev, 1);
+ netup_unidvb_dvb_fini(ndev, 0);
+ netup_unidvb_dvb_fini(ndev, 1);
+ netup_i2c_unregister(ndev);
+ }
+ if (ndev->spi)
+ netup_spi_release(ndev);
+ writew(0xffff, ndev->bmmio0 + REG_IMASK_CLEAR);
+ dma_free_coherent(&ndev->pci_dev->dev, ndev->dma_size,
+ ndev->dma_virt, ndev->dma_phys);
+ free_irq(pci_dev->irq, pci_dev);
+ iounmap(ndev->lmmio0);
+ iounmap(ndev->lmmio1);
+ release_mem_region(pci_resource_start(pci_dev, 0),
+ pci_resource_len(pci_dev, 0));
+ release_mem_region(pci_resource_start(pci_dev, 1),
+ pci_resource_len(pci_dev, 1));
+ pci_disable_device(pci_dev);
+ pci_set_drvdata(pci_dev, NULL);
+ destroy_workqueue(ndev->wq);
+ kfree(ndev);
+ dev_info(&pci_dev->dev,
+ "%s(): device has been successfully stopped\n", __func__);
+}
+
+
+static struct pci_device_id netup_unidvb_pci_tbl[] = {
+ { PCI_DEVICE(0x1b55, 0x18f6) },
+ { 0, }
+};
+MODULE_DEVICE_TABLE(pci, netup_unidvb_pci_tbl);
+
+static struct pci_driver netup_unidvb_pci_driver = {
+ .name = "netup_unidvb",
+ .id_table = netup_unidvb_pci_tbl,
+ .probe = netup_unidvb_initdev,
+ .remove = netup_unidvb_finidev,
+ .suspend = NULL,
+ .resume = NULL,
+};
+
+static int __init netup_unidvb_init(void)
+{
+ return pci_register_driver(&netup_unidvb_pci_driver);
+}
+
+static void __exit netup_unidvb_fini(void)
+{
+ pci_unregister_driver(&netup_unidvb_pci_driver);
+}
+
+module_init(netup_unidvb_init);
+module_exit(netup_unidvb_fini);
diff --git a/kernel/drivers/media/pci/netup_unidvb/netup_unidvb_i2c.c b/kernel/drivers/media/pci/netup_unidvb/netup_unidvb_i2c.c
new file mode 100644
index 000000000..c09c52bc6
--- /dev/null
+++ b/kernel/drivers/media/pci/netup_unidvb/netup_unidvb_i2c.c
@@ -0,0 +1,381 @@
+/*
+ * netup_unidvb_i2c.c
+ *
+ * Internal I2C bus driver for NetUP Universal Dual DVB-CI
+ *
+ * Copyright (C) 2014 NetUP Inc.
+ * Copyright (C) 2014 Sergey Kozlov <serjk@netup.ru>
+ * Copyright (C) 2014 Abylay Ospan <aospan@netup.ru>
+ *
+ * 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/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include "netup_unidvb.h"
+
+#define NETUP_I2C_BUS0_ADDR 0x4800
+#define NETUP_I2C_BUS1_ADDR 0x4840
+#define NETUP_I2C_TIMEOUT 1000
+
+/* twi_ctrl0_stat reg bits */
+#define TWI_IRQEN_COMPL 0x1
+#define TWI_IRQEN_ANACK 0x2
+#define TWI_IRQEN_DNACK 0x4
+#define TWI_IRQ_COMPL (TWI_IRQEN_COMPL << 8)
+#define TWI_IRQ_ANACK (TWI_IRQEN_ANACK << 8)
+#define TWI_IRQ_DNACK (TWI_IRQEN_DNACK << 8)
+#define TWI_IRQ_TX 0x800
+#define TWI_IRQ_RX 0x1000
+#define TWI_IRQEN (TWI_IRQEN_COMPL | TWI_IRQEN_ANACK | TWI_IRQEN_DNACK)
+/* twi_addr_ctrl1 reg bits*/
+#define TWI_TRANSFER 0x100
+#define TWI_NOSTOP 0x200
+#define TWI_SOFT_RESET 0x2000
+/* twi_clkdiv reg value */
+#define TWI_CLKDIV 156
+/* fifo_stat_ctrl reg bits */
+#define FIFO_IRQEN 0x8000
+#define FIFO_RESET 0x4000
+/* FIFO size */
+#define FIFO_SIZE 16
+
+struct netup_i2c_fifo_regs {
+ union {
+ __u8 data8;
+ __le16 data16;
+ __le32 data32;
+ };
+ __u8 padding[4];
+ __le16 stat_ctrl;
+} __packed __aligned(1);
+
+struct netup_i2c_regs {
+ __le16 clkdiv;
+ __le16 twi_ctrl0_stat;
+ __le16 twi_addr_ctrl1;
+ __le16 length;
+ __u8 padding1[8];
+ struct netup_i2c_fifo_regs tx_fifo;
+ __u8 padding2[6];
+ struct netup_i2c_fifo_regs rx_fifo;
+} __packed __aligned(1);
+
+irqreturn_t netup_i2c_interrupt(struct netup_i2c *i2c)
+{
+ u16 reg, tmp;
+ unsigned long flags;
+ irqreturn_t iret = IRQ_HANDLED;
+
+ spin_lock_irqsave(&i2c->lock, flags);
+ reg = readw(&i2c->regs->twi_ctrl0_stat);
+ writew(reg & ~TWI_IRQEN, &i2c->regs->twi_ctrl0_stat);
+ dev_dbg(i2c->adap.dev.parent,
+ "%s(): twi_ctrl0_state 0x%x\n", __func__, reg);
+ if ((reg & TWI_IRQEN_COMPL) != 0 && (reg & TWI_IRQ_COMPL)) {
+ dev_dbg(i2c->adap.dev.parent,
+ "%s(): TWI_IRQEN_COMPL\n", __func__);
+ i2c->state = STATE_DONE;
+ goto irq_ok;
+ }
+ if ((reg & TWI_IRQEN_ANACK) != 0 && (reg & TWI_IRQ_ANACK)) {
+ dev_dbg(i2c->adap.dev.parent,
+ "%s(): TWI_IRQEN_ANACK\n", __func__);
+ i2c->state = STATE_ERROR;
+ goto irq_ok;
+ }
+ if ((reg & TWI_IRQEN_DNACK) != 0 && (reg & TWI_IRQ_DNACK)) {
+ dev_dbg(i2c->adap.dev.parent,
+ "%s(): TWI_IRQEN_DNACK\n", __func__);
+ i2c->state = STATE_ERROR;
+ goto irq_ok;
+ }
+ if ((reg & TWI_IRQ_RX) != 0) {
+ tmp = readw(&i2c->regs->rx_fifo.stat_ctrl);
+ writew(tmp & ~FIFO_IRQEN, &i2c->regs->rx_fifo.stat_ctrl);
+ i2c->state = STATE_WANT_READ;
+ dev_dbg(i2c->adap.dev.parent,
+ "%s(): want read\n", __func__);
+ goto irq_ok;
+ }
+ if ((reg & TWI_IRQ_TX) != 0) {
+ tmp = readw(&i2c->regs->tx_fifo.stat_ctrl);
+ writew(tmp & ~FIFO_IRQEN, &i2c->regs->tx_fifo.stat_ctrl);
+ i2c->state = STATE_WANT_WRITE;
+ dev_dbg(i2c->adap.dev.parent,
+ "%s(): want write\n", __func__);
+ goto irq_ok;
+ }
+ dev_warn(&i2c->adap.dev, "%s(): not mine interrupt\n", __func__);
+ iret = IRQ_NONE;
+irq_ok:
+ spin_unlock_irqrestore(&i2c->lock, flags);
+ if (iret == IRQ_HANDLED)
+ wake_up(&i2c->wq);
+ return iret;
+}
+
+static void netup_i2c_reset(struct netup_i2c *i2c)
+{
+ dev_dbg(i2c->adap.dev.parent, "%s()\n", __func__);
+ i2c->state = STATE_DONE;
+ writew(TWI_SOFT_RESET, &i2c->regs->twi_addr_ctrl1);
+ writew(TWI_CLKDIV, &i2c->regs->clkdiv);
+ writew(FIFO_RESET, &i2c->regs->tx_fifo.stat_ctrl);
+ writew(FIFO_RESET, &i2c->regs->rx_fifo.stat_ctrl);
+ writew(0x800, &i2c->regs->tx_fifo.stat_ctrl);
+ writew(0x800, &i2c->regs->rx_fifo.stat_ctrl);
+}
+
+static void netup_i2c_fifo_tx(struct netup_i2c *i2c)
+{
+ u8 data;
+ u32 fifo_space = FIFO_SIZE -
+ (readw(&i2c->regs->tx_fifo.stat_ctrl) & 0x3f);
+ u32 msg_length = i2c->msg->len - i2c->xmit_size;
+
+ msg_length = (msg_length < fifo_space ? msg_length : fifo_space);
+ while (msg_length--) {
+ data = i2c->msg->buf[i2c->xmit_size++];
+ writeb(data, &i2c->regs->tx_fifo.data8);
+ dev_dbg(i2c->adap.dev.parent,
+ "%s(): write 0x%02x\n", __func__, data);
+ }
+ if (i2c->xmit_size < i2c->msg->len) {
+ dev_dbg(i2c->adap.dev.parent,
+ "%s(): TX IRQ enabled\n", __func__);
+ writew(readw(&i2c->regs->tx_fifo.stat_ctrl) | FIFO_IRQEN,
+ &i2c->regs->tx_fifo.stat_ctrl);
+ }
+}
+
+static void netup_i2c_fifo_rx(struct netup_i2c *i2c)
+{
+ u8 data;
+ u32 fifo_size = readw(&i2c->regs->rx_fifo.stat_ctrl) & 0x3f;
+
+ dev_dbg(i2c->adap.dev.parent,
+ "%s(): RX fifo size %d\n", __func__, fifo_size);
+ while (fifo_size--) {
+ data = readb(&i2c->regs->rx_fifo.data8);
+ if ((i2c->msg->flags & I2C_M_RD) != 0 &&
+ i2c->xmit_size < i2c->msg->len) {
+ i2c->msg->buf[i2c->xmit_size++] = data;
+ dev_dbg(i2c->adap.dev.parent,
+ "%s(): read 0x%02x\n", __func__, data);
+ }
+ }
+ if (i2c->xmit_size < i2c->msg->len) {
+ dev_dbg(i2c->adap.dev.parent,
+ "%s(): RX IRQ enabled\n", __func__);
+ writew(readw(&i2c->regs->rx_fifo.stat_ctrl) | FIFO_IRQEN,
+ &i2c->regs->rx_fifo.stat_ctrl);
+ }
+}
+
+static void netup_i2c_start_xfer(struct netup_i2c *i2c)
+{
+ u16 rdflag = ((i2c->msg->flags & I2C_M_RD) ? 1 : 0);
+ u16 reg = readw(&i2c->regs->twi_ctrl0_stat);
+
+ writew(TWI_IRQEN | reg, &i2c->regs->twi_ctrl0_stat);
+ writew(i2c->msg->len, &i2c->regs->length);
+ writew(TWI_TRANSFER | (i2c->msg->addr << 1) | rdflag,
+ &i2c->regs->twi_addr_ctrl1);
+ dev_dbg(i2c->adap.dev.parent,
+ "%s(): length %d twi_addr_ctrl1 0x%x twi_ctrl0_stat 0x%x\n",
+ __func__, readw(&i2c->regs->length),
+ readw(&i2c->regs->twi_addr_ctrl1),
+ readw(&i2c->regs->twi_ctrl0_stat));
+ i2c->state = STATE_WAIT;
+ i2c->xmit_size = 0;
+ if (!rdflag)
+ netup_i2c_fifo_tx(i2c);
+ else
+ writew(FIFO_IRQEN | readw(&i2c->regs->rx_fifo.stat_ctrl),
+ &i2c->regs->rx_fifo.stat_ctrl);
+}
+
+static int netup_i2c_xfer(struct i2c_adapter *adap,
+ struct i2c_msg *msgs, int num)
+{
+ unsigned long flags;
+ int i, trans_done, res = num;
+ struct netup_i2c *i2c = i2c_get_adapdata(adap);
+ u16 reg;
+
+ if (num <= 0) {
+ dev_dbg(i2c->adap.dev.parent,
+ "%s(): num == %d\n", __func__, num);
+ return -EINVAL;
+ }
+ spin_lock_irqsave(&i2c->lock, flags);
+ if (i2c->state != STATE_DONE) {
+ dev_dbg(i2c->adap.dev.parent,
+ "%s(): i2c->state == %d, resetting I2C\n",
+ __func__, i2c->state);
+ netup_i2c_reset(i2c);
+ }
+ dev_dbg(i2c->adap.dev.parent, "%s() num %d\n", __func__, num);
+ for (i = 0; i < num; i++) {
+ i2c->msg = &msgs[i];
+ netup_i2c_start_xfer(i2c);
+ trans_done = 0;
+ while (!trans_done) {
+ spin_unlock_irqrestore(&i2c->lock, flags);
+ if (wait_event_timeout(i2c->wq,
+ i2c->state != STATE_WAIT,
+ msecs_to_jiffies(NETUP_I2C_TIMEOUT))) {
+ spin_lock_irqsave(&i2c->lock, flags);
+ switch (i2c->state) {
+ case STATE_WANT_READ:
+ netup_i2c_fifo_rx(i2c);
+ break;
+ case STATE_WANT_WRITE:
+ netup_i2c_fifo_tx(i2c);
+ break;
+ case STATE_DONE:
+ if ((i2c->msg->flags & I2C_M_RD) != 0 &&
+ i2c->xmit_size != i2c->msg->len)
+ netup_i2c_fifo_rx(i2c);
+ dev_dbg(i2c->adap.dev.parent,
+ "%s(): msg %d OK\n",
+ __func__, i);
+ trans_done = 1;
+ break;
+ case STATE_ERROR:
+ res = -EIO;
+ dev_dbg(i2c->adap.dev.parent,
+ "%s(): error state\n",
+ __func__);
+ goto done;
+ default:
+ dev_dbg(i2c->adap.dev.parent,
+ "%s(): invalid state %d\n",
+ __func__, i2c->state);
+ res = -EINVAL;
+ goto done;
+ }
+ if (!trans_done) {
+ i2c->state = STATE_WAIT;
+ reg = readw(
+ &i2c->regs->twi_ctrl0_stat);
+ writew(TWI_IRQEN | reg,
+ &i2c->regs->twi_ctrl0_stat);
+ }
+ spin_unlock_irqrestore(&i2c->lock, flags);
+ } else {
+ spin_lock_irqsave(&i2c->lock, flags);
+ dev_dbg(i2c->adap.dev.parent,
+ "%s(): wait timeout\n", __func__);
+ res = -ETIMEDOUT;
+ goto done;
+ }
+ spin_lock_irqsave(&i2c->lock, flags);
+ }
+ }
+done:
+ spin_unlock_irqrestore(&i2c->lock, flags);
+ dev_dbg(i2c->adap.dev.parent, "%s(): result %d\n", __func__, res);
+ return res;
+}
+
+static u32 netup_i2c_func(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm netup_i2c_algorithm = {
+ .master_xfer = netup_i2c_xfer,
+ .functionality = netup_i2c_func,
+};
+
+static struct i2c_adapter netup_i2c_adapter = {
+ .owner = THIS_MODULE,
+ .name = NETUP_UNIDVB_NAME,
+ .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
+ .algo = &netup_i2c_algorithm,
+};
+
+static int netup_i2c_init(struct netup_unidvb_dev *ndev, int bus_num)
+{
+ int ret;
+ struct netup_i2c *i2c;
+
+ if (bus_num < 0 || bus_num > 1) {
+ dev_err(&ndev->pci_dev->dev,
+ "%s(): invalid bus_num %d\n", __func__, bus_num);
+ return -EINVAL;
+ }
+ i2c = &ndev->i2c[bus_num];
+ spin_lock_init(&i2c->lock);
+ init_waitqueue_head(&i2c->wq);
+ i2c->regs = (struct netup_i2c_regs __iomem *)(ndev->bmmio0 +
+ (bus_num == 0 ? NETUP_I2C_BUS0_ADDR : NETUP_I2C_BUS1_ADDR));
+ netup_i2c_reset(i2c);
+ i2c->adap = netup_i2c_adapter;
+ i2c->adap.dev.parent = &ndev->pci_dev->dev;
+ i2c_set_adapdata(&i2c->adap, i2c);
+ ret = i2c_add_adapter(&i2c->adap);
+ if (ret) {
+ dev_err(&ndev->pci_dev->dev,
+ "%s(): failed to add I2C adapter\n", __func__);
+ return ret;
+ }
+ dev_info(&ndev->pci_dev->dev,
+ "%s(): registered I2C bus %d at 0x%x\n",
+ __func__,
+ bus_num, (bus_num == 0 ?
+ NETUP_I2C_BUS0_ADDR :
+ NETUP_I2C_BUS1_ADDR));
+ return 0;
+}
+
+static void netup_i2c_remove(struct netup_unidvb_dev *ndev, int bus_num)
+{
+ struct netup_i2c *i2c;
+
+ if (bus_num < 0 || bus_num > 1) {
+ dev_err(&ndev->pci_dev->dev,
+ "%s(): invalid bus number %d\n", __func__, bus_num);
+ return;
+ }
+ i2c = &ndev->i2c[bus_num];
+ netup_i2c_reset(i2c);
+ /* remove adapter */
+ i2c_del_adapter(&i2c->adap);
+ dev_info(&ndev->pci_dev->dev,
+ "netup_i2c_remove: unregistered I2C bus %d\n", bus_num);
+}
+
+int netup_i2c_register(struct netup_unidvb_dev *ndev)
+{
+ int ret;
+
+ ret = netup_i2c_init(ndev, 0);
+ if (ret)
+ return ret;
+ ret = netup_i2c_init(ndev, 1);
+ if (ret) {
+ netup_i2c_remove(ndev, 0);
+ return ret;
+ }
+ return 0;
+}
+
+void netup_i2c_unregister(struct netup_unidvb_dev *ndev)
+{
+ netup_i2c_remove(ndev, 0);
+ netup_i2c_remove(ndev, 1);
+}
+
diff --git a/kernel/drivers/media/pci/netup_unidvb/netup_unidvb_spi.c b/kernel/drivers/media/pci/netup_unidvb/netup_unidvb_spi.c
new file mode 100644
index 000000000..f33c0de3e
--- /dev/null
+++ b/kernel/drivers/media/pci/netup_unidvb/netup_unidvb_spi.c
@@ -0,0 +1,248 @@
+/*
+ * netup_unidvb_spi.c
+ *
+ * Internal SPI driver for NetUP Universal Dual DVB-CI
+ *
+ * Copyright (C) 2014 NetUP Inc.
+ * Copyright (C) 2014 Sergey Kozlov <serjk@netup.ru>
+ * Copyright (C) 2014 Abylay Ospan <aospan@netup.ru>
+ *
+ * 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 "netup_unidvb.h"
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/mtd/partitions.h>
+#include <mtd/mtd-abi.h>
+
+#define NETUP_SPI_CTRL_IRQ 0x1000
+#define NETUP_SPI_CTRL_IMASK 0x2000
+#define NETUP_SPI_CTRL_START 0x8000
+#define NETUP_SPI_CTRL_LAST_CS 0x4000
+
+#define NETUP_SPI_TIMEOUT 6000
+
+enum netup_spi_state {
+ SPI_STATE_START,
+ SPI_STATE_DONE,
+};
+
+struct netup_spi_regs {
+ __u8 data[1024];
+ __le16 control_stat;
+ __le16 clock_divider;
+} __packed __aligned(1);
+
+struct netup_spi {
+ struct device *dev;
+ struct spi_master *master;
+ struct netup_spi_regs __iomem *regs;
+ u8 __iomem *mmio;
+ spinlock_t lock;
+ wait_queue_head_t waitq;
+ enum netup_spi_state state;
+};
+
+static char netup_spi_name[64] = "fpga";
+
+static struct mtd_partition netup_spi_flash_partitions = {
+ .name = netup_spi_name,
+ .size = 0x1000000, /* 16MB */
+ .offset = 0,
+ .mask_flags = MTD_CAP_ROM
+};
+
+static struct flash_platform_data spi_flash_data = {
+ .name = "netup0_m25p128",
+ .parts = &netup_spi_flash_partitions,
+ .nr_parts = 1,
+};
+
+static struct spi_board_info netup_spi_board = {
+ .modalias = "m25p128",
+ .max_speed_hz = 11000000,
+ .chip_select = 0,
+ .mode = SPI_MODE_0,
+ .platform_data = &spi_flash_data,
+};
+
+irqreturn_t netup_spi_interrupt(struct netup_spi *spi)
+{
+ u16 reg;
+ unsigned long flags;
+
+ if (!spi)
+ return IRQ_NONE;
+
+ spin_lock_irqsave(&spi->lock, flags);
+ reg = readw(&spi->regs->control_stat);
+ if (!(reg & NETUP_SPI_CTRL_IRQ)) {
+ spin_unlock_irqrestore(&spi->lock, flags);
+ dev_dbg(&spi->master->dev,
+ "%s(): not mine interrupt\n", __func__);
+ return IRQ_NONE;
+ }
+ writew(reg | NETUP_SPI_CTRL_IRQ, &spi->regs->control_stat);
+ reg = readw(&spi->regs->control_stat);
+ writew(reg & ~NETUP_SPI_CTRL_IMASK, &spi->regs->control_stat);
+ spi->state = SPI_STATE_DONE;
+ wake_up(&spi->waitq);
+ spin_unlock_irqrestore(&spi->lock, flags);
+ dev_dbg(&spi->master->dev,
+ "%s(): SPI interrupt handled\n", __func__);
+ return IRQ_HANDLED;
+}
+
+static int netup_spi_transfer(struct spi_master *master,
+ struct spi_message *msg)
+{
+ struct netup_spi *spi = spi_master_get_devdata(master);
+ struct spi_transfer *t;
+ int result = 0;
+ u32 tr_size;
+
+ /* reset CS */
+ writew(NETUP_SPI_CTRL_LAST_CS, &spi->regs->control_stat);
+ writew(0, &spi->regs->control_stat);
+ list_for_each_entry(t, &msg->transfers, transfer_list) {
+ tr_size = t->len;
+ while (tr_size) {
+ u32 frag_offset = t->len - tr_size;
+ u32 frag_size = (tr_size > sizeof(spi->regs->data)) ?
+ sizeof(spi->regs->data) : tr_size;
+ int frag_last = 0;
+
+ if (list_is_last(&t->transfer_list,
+ &msg->transfers) &&
+ frag_offset + frag_size == t->len) {
+ frag_last = 1;
+ }
+ if (t->tx_buf) {
+ memcpy_toio(spi->regs->data,
+ t->tx_buf + frag_offset,
+ frag_size);
+ } else {
+ memset_io(spi->regs->data,
+ 0, frag_size);
+ }
+ spi->state = SPI_STATE_START;
+ writew((frag_size & 0x3ff) |
+ NETUP_SPI_CTRL_IMASK |
+ NETUP_SPI_CTRL_START |
+ (frag_last ? NETUP_SPI_CTRL_LAST_CS : 0),
+ &spi->regs->control_stat);
+ dev_dbg(&spi->master->dev,
+ "%s(): control_stat 0x%04x\n",
+ __func__, readw(&spi->regs->control_stat));
+ wait_event_timeout(spi->waitq,
+ spi->state != SPI_STATE_START,
+ msecs_to_jiffies(NETUP_SPI_TIMEOUT));
+ if (spi->state == SPI_STATE_DONE) {
+ if (t->rx_buf) {
+ memcpy_fromio(t->rx_buf + frag_offset,
+ spi->regs->data, frag_size);
+ }
+ } else {
+ if (spi->state == SPI_STATE_START) {
+ dev_dbg(&spi->master->dev,
+ "%s(): transfer timeout\n",
+ __func__);
+ } else {
+ dev_dbg(&spi->master->dev,
+ "%s(): invalid state %d\n",
+ __func__, spi->state);
+ }
+ result = -EIO;
+ goto done;
+ }
+ tr_size -= frag_size;
+ msg->actual_length += frag_size;
+ }
+ }
+done:
+ msg->status = result;
+ spi_finalize_current_message(master);
+ return result;
+}
+
+static int netup_spi_setup(struct spi_device *spi)
+{
+ return 0;
+}
+
+int netup_spi_init(struct netup_unidvb_dev *ndev)
+{
+ struct spi_master *master;
+ struct netup_spi *nspi;
+
+ master = spi_alloc_master(&ndev->pci_dev->dev,
+ sizeof(struct netup_spi));
+ if (!master) {
+ dev_err(&ndev->pci_dev->dev,
+ "%s(): unable to alloc SPI master\n", __func__);
+ return -EINVAL;
+ }
+ nspi = spi_master_get_devdata(master);
+ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
+ master->bus_num = -1;
+ master->num_chipselect = 1;
+ master->transfer_one_message = netup_spi_transfer;
+ master->setup = netup_spi_setup;
+ spin_lock_init(&nspi->lock);
+ init_waitqueue_head(&nspi->waitq);
+ nspi->master = master;
+ nspi->regs = (struct netup_spi_regs __iomem *)(ndev->bmmio0 + 0x4000);
+ writew(2, &nspi->regs->clock_divider);
+ writew(NETUP_UNIDVB_IRQ_SPI, ndev->bmmio0 + REG_IMASK_SET);
+ ndev->spi = nspi;
+ if (spi_register_master(master)) {
+ ndev->spi = NULL;
+ dev_err(&ndev->pci_dev->dev,
+ "%s(): unable to register SPI bus\n", __func__);
+ return -EINVAL;
+ }
+ snprintf(netup_spi_name,
+ sizeof(netup_spi_name),
+ "fpga_%02x:%02x.%01x",
+ ndev->pci_bus,
+ ndev->pci_slot,
+ ndev->pci_func);
+ if (!spi_new_device(master, &netup_spi_board)) {
+ ndev->spi = NULL;
+ dev_err(&ndev->pci_dev->dev,
+ "%s(): unable to create SPI device\n", __func__);
+ return -EINVAL;
+ }
+ dev_dbg(&ndev->pci_dev->dev, "%s(): SPI init OK\n", __func__);
+ return 0;
+}
+
+void netup_spi_release(struct netup_unidvb_dev *ndev)
+{
+ u16 reg;
+ unsigned long flags;
+ struct netup_spi *spi = ndev->spi;
+
+ if (!spi)
+ return;
+
+ spin_lock_irqsave(&spi->lock, flags);
+ reg = readw(&spi->regs->control_stat);
+ writew(reg | NETUP_SPI_CTRL_IRQ, &spi->regs->control_stat);
+ reg = readw(&spi->regs->control_stat);
+ writew(reg & ~NETUP_SPI_CTRL_IMASK, &spi->regs->control_stat);
+ spin_unlock_irqrestore(&spi->lock, flags);
+ spi_unregister_master(spi->master);
+ ndev->spi = NULL;
+}
+
+
diff --git a/kernel/drivers/media/pci/ngene/ngene-core.c b/kernel/drivers/media/pci/ngene/ngene-core.c
index e29bc3af4..1b92d836a 100644
--- a/kernel/drivers/media/pci/ngene/ngene-core.c
+++ b/kernel/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/kernel/drivers/media/pci/ngene/ngene.h b/kernel/drivers/media/pci/ngene/ngene.h
index 51e2fbd18..fa30930d7 100644
--- a/kernel/drivers/media/pci/ngene/ngene.h
+++ b/kernel/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/kernel/drivers/media/pci/pt1/pt1.c b/kernel/drivers/media/pci/pt1/pt1.c
index acc35b42e..e7e442810 100644
--- a/kernel/drivers/media/pci/pt1/pt1.c
+++ b/kernel/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/kernel/drivers/media/pci/pt1/va1j5jf8007s.c b/kernel/drivers/media/pci/pt1/va1j5jf8007s.c
index 1b637b74e..d0e70dc0e 100644
--- a/kernel/drivers/media/pci/pt1/va1j5jf8007s.c
+++ b/kernel/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/kernel/drivers/media/pci/pt1/va1j5jf8007t.c b/kernel/drivers/media/pci/pt1/va1j5jf8007t.c
index 2db15159d..0268f20b8 100644
--- a/kernel/drivers/media/pci/pt1/va1j5jf8007t.c
+++ b/kernel/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/kernel/drivers/media/pci/pt3/pt3.c b/kernel/drivers/media/pci/pt3/pt3.c
index 7a37e8fe2..0d2e2b217 100644
--- a/kernel/drivers/media/pci/pt3/pt3.c
+++ b/kernel/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/kernel/drivers/media/pci/saa7134/saa7134-alsa.c b/kernel/drivers/media/pci/saa7134/saa7134-alsa.c
index ac3cd74e8..94f816244 100644
--- a/kernel/drivers/media/pci/saa7134/saa7134-alsa.c
+++ b/kernel/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;
@@ -1218,6 +1211,8 @@ static int alsa_device_init(struct saa7134_dev *dev)
static int alsa_device_exit(struct saa7134_dev *dev)
{
+ if (!snd_saa7134_cards[dev->nr])
+ return 1;
snd_card_free(snd_saa7134_cards[dev->nr]);
snd_saa7134_cards[dev->nr] = NULL;
@@ -1240,19 +1235,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;
@@ -1267,12 +1262,13 @@ static void saa7134_alsa_exit(void)
int idx;
for (idx = 0; idx < SNDRV_CARDS; idx++) {
- snd_card_free(snd_saa7134_cards[idx]);
+ if (snd_saa7134_cards[idx])
+ snd_card_free(snd_saa7134_cards[idx]);
}
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/kernel/drivers/media/pci/saa7134/saa7134-cards.c b/kernel/drivers/media/pci/saa7134/saa7134-cards.c
index 3ca078057..29d2094c4 100644
--- a/kernel/drivers/media/pci/saa7134/saa7134-cards.c
+++ b/kernel/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,75 @@ 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,
+ },
+ },
+ [SAA7134_BOARD_LEADTEK_WINFAST_TV2100_FM] = {
+ .name = "Leadtek Winfast TV2100 FM",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_TNF_5335MF,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .gpiomask = 0x0d,
+ .inputs = {{
+ .name = name_tv_mono,
+ .vmux = 1,
+ .amux = LINE1,
+ .gpio = 0x00,
+ .tv = 1,
+ }, {
+ .name = name_comp1,
+ .vmux = 3,
+ .amux = LINE2,
+ .gpio = 0x08,
+ }, {
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE2,
+ .gpio = 0x08,
+ } },
+ .radio = {
+ .name = name_radio,
+ .amux = LINE1,
+ .gpio = 0x04,
+ },
+ .mute = {
+ .name = name_mute,
+ .amux = LINE1,
+ .gpio = 0x08,
+ },
+ },
};
@@ -7109,6 +7179,18 @@ 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,
+ }, {
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7130,
+ .subvendor = 0x107d,
+ .subdevice = 0x6f3a,
+ .driver_data = SAA7134_BOARD_LEADTEK_WINFAST_TV2100_FM,
+ }, {
/* --- boards without eeprom + subsystem ID --- */
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
@@ -7158,10 +7240,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 +7276,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 +7462,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 +7493,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 +7509,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 +7530,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:
@@ -7504,6 +7587,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS:
case SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM:
case SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S:
+ case SAA7134_BOARD_LEADTEK_WINFAST_TV2100_FM:
dev->has_remote = SAA7134_REMOTE_GPIO;
break;
case SAA7134_BOARD_FLYDVBS_LR300:
@@ -7512,10 +7596,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 +7724,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 +7873,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 +7881,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 +7895,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 +7910,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 +7928,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 +7957,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 +7985,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 +8001,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 +8071,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 +8117,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 +8142,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 +8159,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/kernel/drivers/media/pci/saa7134/saa7134-core.c b/kernel/drivers/media/pci/saa7134/saa7134-core.c
index a349e964e..f720cea80 100644
--- a/kernel/drivers/media/pci/saa7134/saa7134-core.c
+++ b/kernel/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;
}
@@ -209,13 +216,14 @@ int saa7134_buffer_count(unsigned int size, unsigned int count)
int saa7134_buffer_startpage(struct saa7134_buf *buf)
{
- return saa7134_buffer_pages(vb2_plane_size(&buf->vb2, 0)) * buf->vb2.v4l2_buf.index;
+ return saa7134_buffer_pages(vb2_plane_size(&buf->vb2.vb2_buf, 0))
+ * buf->vb2.vb2_buf.index;
}
unsigned long saa7134_buffer_base(struct saa7134_buf *buf)
{
unsigned long base;
- struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
+ struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2.vb2_buf, 0);
base = saa7134_buffer_startpage(buf) * 4096;
base += dma->sgl[0].offset;
@@ -274,7 +282,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,12 +306,12 @@ 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);
- q->curr->vb2.v4l2_buf.sequence = q->seq_nr++;
- vb2_buffer_done(&q->curr->vb2, state);
+ v4l2_get_timestamp(&q->curr->vb2.timestamp);
+ q->curr->vb2.sequence = q->seq_nr++;
+ vb2_buffer_done(&q->curr->vb2.vb2_buf, state);
q->curr = NULL;
}
@@ -318,18 +326,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 +359,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);
@@ -368,7 +376,8 @@ void saa7134_stop_streaming(struct saa7134_dev *dev, struct saa7134_dmaqueue *q)
if (!list_empty(&q->queue)) {
list_for_each_safe(pos, n, &q->queue) {
tmp = list_entry(pos, struct saa7134_buf, entry);
- vb2_buffer_done(&tmp->vb2, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&tmp->vb2.vb2_buf,
+ VB2_BUF_STATE_ERROR);
list_del(pos);
tmp = NULL;
}
@@ -474,7 +483,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 +505,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 +541,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 +619,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 +685,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 +747,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 +761,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 +777,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 +906,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 +938,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,14 +946,14 @@ 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);
- err = -EIO;
+ err = pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32));
+ if (err) {
+ pr_warn("%s: Oops: no 32bit PCI DMA ???\n", dev->name);
goto fail1;
}
@@ -972,7 +975,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 +986,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 +995,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 +1013,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 +1043,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 +1062,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 +1071,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 +1087,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 +1098,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 +1207,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 +1361,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/kernel/drivers/media/pci/saa7134/saa7134-dvb.c b/kernel/drivers/media/pci/saa7134/saa7134-dvb.c
index 73ffbabf8..101ba8729 100644
--- a/kernel/drivers/media/pci/saa7134/saa7134-dvb.c
+++ b/kernel/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/kernel/drivers/media/pci/saa7134/saa7134-empress.c b/kernel/drivers/media/pci/saa7134/saa7134-empress.c
index 594dc3ad4..56b932c97 100644
--- a/kernel/drivers/media/pci/saa7134/saa7134-empress.c
+++ b/kernel/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/kernel/drivers/media/pci/saa7134/saa7134-go7007.c b/kernel/drivers/media/pci/saa7134/saa7134-go7007.c
index 54e650b4d..8a2abb341 100644
--- a/kernel/drivers/media/pci/saa7134/saa7134-go7007.c
+++ b/kernel/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/kernel/drivers/media/pci/saa7134/saa7134-i2c.c b/kernel/drivers/media/pci/saa7134/saa7134-i2c.c
index f4da674e7..8ef6399d7 100644
--- a/kernel/drivers/media/pci/saa7134/saa7134-i2c.c
+++ b/kernel/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/kernel/drivers/media/pci/saa7134/saa7134-input.c b/kernel/drivers/media/pci/saa7134/saa7134-input.c
index dc3d6516e..69d32d3fa 100644
--- a/kernel/drivers/media/pci/saa7134/saa7134-input.c
+++ b/kernel/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:
@@ -829,10 +835,16 @@ int saa7134_input_init1(struct saa7134_dev *dev)
mask_keycode = 0xffff;
raw_decode = true;
break;
+ case SAA7134_BOARD_LEADTEK_WINFAST_TV2100_FM:
+ ir_codes = RC_MAP_LEADTEK_Y04G0051;
+ mask_keydown = 0x0040000; /* Enable GPIO18 line on both edges */
+ mask_keyup = 0x0040000;
+ mask_keycode = 0xffff;
+ raw_decode = true;
+ 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 +928,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 +971,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 +986,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 +1031,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/kernel/drivers/media/pci/saa7134/saa7134-ts.c b/kernel/drivers/media/pci/saa7134/saa7134-ts.c
index 2709b83d5..7fb5ee7e2 100644
--- a/kernel/drivers/media/pci/saa7134/saa7134-ts.c
+++ b/kernel/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;
@@ -77,8 +79,9 @@ static int buffer_activate(struct saa7134_dev *dev,
int saa7134_ts_buffer_init(struct vb2_buffer *vb2)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2);
struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
- struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
+ struct saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, vb2);
dmaq->curr = NULL;
buf->activate = buffer_activate;
@@ -89,13 +92,14 @@ EXPORT_SYMBOL_GPL(saa7134_ts_buffer_init);
int saa7134_ts_buffer_prepare(struct vb2_buffer *vb2)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2);
struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
struct saa7134_dev *dev = dmaq->dev;
- struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
+ struct saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, 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;
@@ -105,14 +109,14 @@ int saa7134_ts_buffer_prepare(struct vb2_buffer *vb2)
return -EINVAL;
vb2_set_plane_payload(vb2, 0, size);
- vb2->v4l2_buf.field = dev->field;
+ vbuf->field = dev->field;
return saa7134_pgtable_build(dev->pci, &dmaq->pt, dma->sgl, dma->nents,
saa7134_buffer_startpage(buf));
}
EXPORT_SYMBOL_GPL(saa7134_ts_buffer_prepare);
-int saa7134_ts_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+int saa7134_ts_queue_setup(struct vb2_queue *q, const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -146,10 +150,12 @@ int saa7134_ts_start_streaming(struct vb2_queue *vq, unsigned int count)
list_for_each_entry_safe(buf, tmp, &dmaq->queue, entry) {
list_del(&buf->entry);
- vb2_buffer_done(&buf->vb2, VB2_BUF_STATE_QUEUED);
+ vb2_buffer_done(&buf->vb2.vb2_buf,
+ VB2_BUF_STATE_QUEUED);
}
if (dmaq->curr) {
- vb2_buffer_done(&dmaq->curr->vb2, VB2_BUF_STATE_QUEUED);
+ vb2_buffer_done(&dmaq->curr->vb2.vb2_buf,
+ VB2_BUF_STATE_QUEUED);
dmaq->curr = NULL;
}
return -EBUSY;
@@ -239,7 +245,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 +267,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/kernel/drivers/media/pci/saa7134/saa7134-tvaudio.c b/kernel/drivers/media/pci/saa7134/saa7134-tvaudio.c
index 3afbcb70b..21a579309 100644
--- a/kernel/drivers/media/pci/saa7134/saa7134-tvaudio.c
+++ b/kernel/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/kernel/drivers/media/pci/saa7134/saa7134-vbi.c b/kernel/drivers/media/pci/saa7134/saa7134-vbi.c
index 5306e549e..6271b0eb0 100644
--- a/kernel/drivers/media/pci/saa7134/saa7134-vbi.c
+++ b/kernel/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)
/* ------------------------------------------------------------------ */
@@ -81,10 +83,10 @@ static int buffer_activate(struct saa7134_dev *dev,
struct saa7134_buf *buf,
struct saa7134_buf *next)
{
- struct saa7134_dmaqueue *dmaq = buf->vb2.vb2_queue->drv_priv;
+ struct saa7134_dmaqueue *dmaq = buf->vb2.vb2_buf.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);
@@ -117,8 +119,9 @@ static int buffer_prepare(struct vb2_buffer *vb2)
{
struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
struct saa7134_dev *dev = dmaq->dev;
- struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
- struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2);
+ struct saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, vb2);
+ struct sg_table *dma = vb2_dma_sg_plane_desc(vb2, 0);
unsigned int size;
if (dma->sgl->offset) {
@@ -135,7 +138,7 @@ static int buffer_prepare(struct vb2_buffer *vb2)
saa7134_buffer_startpage(buf));
}
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -159,7 +162,8 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
static int buffer_init(struct vb2_buffer *vb2)
{
struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
- struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2);
+ struct saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, vb2);
dmaq->curr = NULL;
buf->activate = buffer_activate;
diff --git a/kernel/drivers/media/pci/saa7134/saa7134-video.c b/kernel/drivers/media/pci/saa7134/saa7134-video.c
index 99d09a756..518086c7a 100644
--- a/kernel/drivers/media/pci/saa7134/saa7134-video.c
+++ b/kernel/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]);
@@ -788,11 +791,11 @@ static int buffer_activate(struct saa7134_dev *dev,
struct saa7134_buf *buf,
struct saa7134_buf *next)
{
- struct saa7134_dmaqueue *dmaq = buf->vb2.vb2_queue->drv_priv;
+ struct saa7134_dmaqueue *dmaq = buf->vb2.vb2_buf.vb2_queue->drv_priv;
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 */
@@ -869,7 +872,8 @@ static int buffer_activate(struct saa7134_dev *dev,
static int buffer_init(struct vb2_buffer *vb2)
{
struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
- struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2);
+ struct saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, vb2);
dmaq->curr = NULL;
buf->activate = buffer_activate;
@@ -880,8 +884,9 @@ static int buffer_prepare(struct vb2_buffer *vb2)
{
struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
struct saa7134_dev *dev = dmaq->dev;
- struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
- struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2);
+ struct saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, vb2);
+ struct sg_table *dma = vb2_dma_sg_plane_desc(vb2, 0);
unsigned int size;
if (dma->sgl->offset) {
@@ -893,13 +898,13 @@ static int buffer_prepare(struct vb2_buffer *vb2)
return -EINVAL;
vb2_set_plane_payload(vb2, 0, size);
- vb2->v4l2_buf.field = dev->field;
+ vbuf->field = dev->field;
return saa7134_pgtable_build(dev->pci, &dmaq->pt, dma->sgl, dma->nents,
saa7134_buffer_startpage(buf));
}
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -929,7 +934,8 @@ void saa7134_vb2_buffer_queue(struct vb2_buffer *vb)
{
struct saa7134_dmaqueue *dmaq = vb->vb2_queue->drv_priv;
struct saa7134_dev *dev = dmaq->dev;
- struct saa7134_buf *buf = container_of(vb, struct saa7134_buf, vb2);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, vb2);
saa7134_buffer_queue(dev, dmaq, buf);
}
@@ -950,10 +956,12 @@ int saa7134_vb2_start_streaming(struct vb2_queue *vq, unsigned int count)
list_for_each_entry_safe(buf, tmp, &dmaq->queue, entry) {
list_del(&buf->entry);
- vb2_buffer_done(&buf->vb2, VB2_BUF_STATE_QUEUED);
+ vb2_buffer_done(&buf->vb2.vb2_buf,
+ VB2_BUF_STATE_QUEUED);
}
if (dmaq->curr) {
- vb2_buffer_done(&dmaq->curr->vb2, VB2_BUF_STATE_QUEUED);
+ vb2_buffer_done(&dmaq->curr->vb2.vb2_buf,
+ VB2_BUF_STATE_QUEUED);
dmaq->curr = NULL;
}
return -EBUSY;
@@ -1229,7 +1237,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 +1313,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 +1347,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 +1746,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 +1803,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 +2192,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/kernel/drivers/media/pci/saa7134/saa7134.h b/kernel/drivers/media/pci/saa7134/saa7134.h
index 8bf0553b8..6b6d234f5 100644
--- a/kernel/drivers/media/pci/saa7134/saa7134.h
+++ b/kernel/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,8 @@ 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_BOARD_LEADTEK_WINFAST_TV2100_FM 195
#define SAA7134_MAXBOARDS 32
#define SAA7134_INPUT_MAX 8
@@ -456,7 +460,7 @@ struct saa7134_thread {
/* buffer for one video/vbi/ts frame */
struct saa7134_buf {
/* common v4l buffer stuff -- must be first */
- struct vb2_buffer vb2;
+ struct vb2_v4l2_buffer vb2;
/* saa7134 specific */
unsigned int top_seen;
@@ -654,7 +658,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);
@@ -815,7 +820,7 @@ void saa7134_video_fini(struct saa7134_dev *dev);
int saa7134_ts_buffer_init(struct vb2_buffer *vb2);
int saa7134_ts_buffer_prepare(struct vb2_buffer *vb2);
-int saa7134_ts_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+int saa7134_ts_queue_setup(struct vb2_queue *q, const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[]);
int saa7134_ts_start_streaming(struct vb2_queue *vq, unsigned int count);
diff --git a/kernel/drivers/media/pci/saa7164/Kconfig b/kernel/drivers/media/pci/saa7164/Kconfig
index a53db7d1c..9098ef5fe 100644
--- a/kernel/drivers/media/pci/saa7164/Kconfig
+++ b/kernel/drivers/media/pci/saa7164/Kconfig
@@ -5,7 +5,6 @@ config VIDEO_SAA7164
select FW_LOADER
select VIDEO_TUNER
select VIDEO_TVEEPROM
- select VIDEOBUF_DVB
select DVB_TDA10048 if MEDIA_SUBDRV_AUTOSELECT
select DVB_S5H1411 if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT
diff --git a/kernel/drivers/media/pci/saa7164/saa7164-api.c b/kernel/drivers/media/pci/saa7164/saa7164-api.c
index 4f3b1dd18..e7e586c1b 100644
--- a/kernel/drivers/media/pci/saa7164/saa7164-api.c
+++ b/kernel/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/kernel/drivers/media/pci/saa7164/saa7164-buffer.c b/kernel/drivers/media/pci/saa7164/saa7164-buffer.c
index 9bd1f73f8..f30758e24 100644
--- a/kernel/drivers/media/pci/saa7164/saa7164-buffer.c
+++ b/kernel/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/kernel/drivers/media/pci/saa7164/saa7164-bus.c b/kernel/drivers/media/pci/saa7164/saa7164-bus.c
index 6c73f5b15..a18fe5d47 100644
--- a/kernel/drivers/media/pci/saa7164/saa7164-bus.c
+++ b/kernel/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/kernel/drivers/media/pci/saa7164/saa7164-cards.c b/kernel/drivers/media/pci/saa7164/saa7164-cards.c
index 5b72da5ce..c2b738227 100644
--- a/kernel/drivers/media/pci/saa7164/saa7164-cards.c
+++ b/kernel/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/kernel/drivers/media/pci/saa7164/saa7164-cmd.c b/kernel/drivers/media/pci/saa7164/saa7164-cmd.c
index cfabcbacc..3285c37b4 100644
--- a/kernel/drivers/media/pci/saa7164/saa7164-cmd.c
+++ b/kernel/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/kernel/drivers/media/pci/saa7164/saa7164-core.c b/kernel/drivers/media/pci/saa7164/saa7164-core.c
index 9cf3c6cba..8bbd092fb 100644
--- a/kernel/drivers/media/pci/saa7164/saa7164-core.c
+++ b/kernel/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)
{
@@ -1224,19 +1264,28 @@ static int saa7164_initdev(struct pci_dev *pci_dev,
pci_set_master(pci_dev);
/* TODO */
- if (!pci_dma_supported(pci_dev, 0xffffffff)) {
+ err = pci_set_dma_mask(pci_dev, 0xffffffff);
+ if (err) {
printk("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);
- err = -EIO;
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/kernel/drivers/media/pci/saa7164/saa7164-dvb.c b/kernel/drivers/media/pci/saa7164/saa7164-dvb.c
index 16ae71592..e9a783b71 100644
--- a/kernel/drivers/media/pci/saa7164/saa7164-dvb.c
+++ b/kernel/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/kernel/drivers/media/pci/saa7164/saa7164-encoder.c b/kernel/drivers/media/pci/saa7164/saa7164-encoder.c
index 7a0a65146..1b184c39b 100644
--- a/kernel/drivers/media/pci/saa7164/saa7164-encoder.c
+++ b/kernel/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
@@ -25,6 +25,18 @@
#define ENCODER_MIN_BITRATE 1000000
#define ENCODER_DEF_BITRATE 5000000
+/*
+ * This is a dummy non-zero value for the sizeimage field of v4l2_pix_format.
+ * It is not actually used for anything since this driver does not support
+ * stream I/O, only read(), and because this driver produces an MPEG stream
+ * and not discrete frames. But the V4L2 spec doesn't allow for this value
+ * to be 0, so set it to 0x10000 instead.
+ *
+ * If we ever change this driver to support stream I/O, then this field
+ * will be the size of the streaming buffers.
+ */
+#define SAA7164_SIZEIMAGE (0x10000)
+
static struct saa7164_tvnorm saa7164_tvnorms[] = {
{
.name = "NTSC-M",
@@ -35,24 +47,6 @@ static struct saa7164_tvnorm saa7164_tvnorms[] = {
}
};
-static const u32 saa7164_v4l2_ctrls[] = {
- V4L2_CID_BRIGHTNESS,
- V4L2_CID_CONTRAST,
- V4L2_CID_SATURATION,
- V4L2_CID_HUE,
- V4L2_CID_AUDIO_VOLUME,
- V4L2_CID_SHARPNESS,
- V4L2_CID_MPEG_STREAM_TYPE,
- V4L2_CID_MPEG_VIDEO_ASPECT,
- V4L2_CID_MPEG_VIDEO_B_FRAMES,
- V4L2_CID_MPEG_VIDEO_GOP_SIZE,
- V4L2_CID_MPEG_AUDIO_MUTE,
- V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
- V4L2_CID_MPEG_VIDEO_BITRATE,
- V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
- 0
-};
-
/* Take the encoder configuration form the port struct and
* flush it to the hardware.
*/
@@ -211,10 +205,8 @@ static int saa7164_encoder_initialize(struct saa7164_port *port)
}
/* -- V4L2 --------------------------------------------------------- */
-static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id)
+int saa7164_s_std(struct saa7164_port *port, v4l2_std_id id)
{
- struct saa7164_encoder_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
struct saa7164_dev *dev = port->dev;
unsigned int i;
@@ -240,22 +232,33 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id)
return 0;
}
-static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id)
{
struct saa7164_encoder_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
+ return saa7164_s_std(fh->port, id);
+}
+
+int saa7164_g_std(struct saa7164_port *port, v4l2_std_id *id)
+{
*id = port->std;
return 0;
}
-static int vidioc_enum_input(struct file *file, void *priv,
- struct v4l2_input *i)
+static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
{
- int n;
+ struct saa7164_encoder_fh *fh = file->private_data;
+
+ return saa7164_g_std(fh->port, id);
+}
- char *inputs[] = { "tuner", "composite", "svideo", "aux",
- "composite 2", "svideo 2", "aux 2" };
+int saa7164_enum_input(struct file *file, void *priv, struct v4l2_input *i)
+{
+ static const char * const inputs[] = {
+ "tuner", "composite", "svideo", "aux",
+ "composite 2", "svideo 2", "aux 2"
+ };
+ int n;
if (i->index >= 7)
return -EINVAL;
@@ -273,10 +276,8 @@ static int vidioc_enum_input(struct file *file, void *priv,
return 0;
}
-static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+int saa7164_g_input(struct saa7164_port *port, unsigned int *i)
{
- struct saa7164_encoder_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
struct saa7164_dev *dev = port->dev;
if (saa7164_api_get_videomux(port) != SAA_OK)
@@ -289,10 +290,15 @@ static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
return 0;
}
-static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
{
struct saa7164_encoder_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
+
+ return saa7164_g_input(fh->port, i);
+}
+
+int saa7164_s_input(struct saa7164_port *port, unsigned int i)
+{
struct saa7164_dev *dev = port->dev;
dprintk(DBGLVL_ENC, "%s() input=%d\n", __func__, i);
@@ -308,8 +314,14 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
return 0;
}
-static int vidioc_g_tuner(struct file *file, void *priv,
- struct v4l2_tuner *t)
+static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
+{
+ struct saa7164_encoder_fh *fh = file->private_data;
+
+ return saa7164_s_input(fh->port, i);
+}
+
+int saa7164_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
{
struct saa7164_encoder_fh *fh = file->private_data;
struct saa7164_port *port = fh->port;
@@ -319,38 +331,45 @@ static int vidioc_g_tuner(struct file *file, void *priv,
return -EINVAL;
strcpy(t->name, "tuner");
- t->type = V4L2_TUNER_ANALOG_TV;
t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO;
+ t->rangelow = SAA7164_TV_MIN_FREQ;
+ t->rangehigh = SAA7164_TV_MAX_FREQ;
dprintk(DBGLVL_ENC, "VIDIOC_G_TUNER: tuner type %d\n", t->type);
return 0;
}
-static int vidioc_s_tuner(struct file *file, void *priv,
- const struct v4l2_tuner *t)
+int saa7164_s_tuner(struct file *file, void *priv,
+ const struct v4l2_tuner *t)
{
+ if (0 != t->index)
+ return -EINVAL;
+
/* Update the A/V core */
return 0;
}
-static int vidioc_g_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
+int saa7164_g_frequency(struct saa7164_port *port, struct v4l2_frequency *f)
{
- struct saa7164_encoder_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
+ if (f->tuner)
+ return -EINVAL;
- f->type = V4L2_TUNER_ANALOG_TV;
f->frequency = port->freq;
-
return 0;
}
-static int vidioc_s_frequency(struct file *file, void *priv,
- const struct v4l2_frequency *f)
+static int vidioc_g_frequency(struct file *file, void *priv,
+ struct v4l2_frequency *f)
{
struct saa7164_encoder_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
+
+ return saa7164_g_frequency(fh->port, f);
+}
+
+int saa7164_s_frequency(struct saa7164_port *port,
+ const struct v4l2_frequency *f)
+{
struct saa7164_dev *dev = port->dev;
struct saa7164_port *tsport;
struct dvb_frontend *fe;
@@ -370,16 +389,13 @@ static int vidioc_s_frequency(struct file *file, void *priv,
if (f->tuner != 0)
return -EINVAL;
- if (f->type != V4L2_TUNER_ANALOG_TV)
- return -EINVAL;
-
- port->freq = f->frequency;
+ port->freq = clamp(f->frequency,
+ SAA7164_TV_MIN_FREQ, SAA7164_TV_MAX_FREQ);
/* Update the hardware */
if (port->nr == SAA7164_PORT_ENC1)
tsport = &dev->ports[SAA7164_PORT_TS1];
- else
- if (port->nr == SAA7164_PORT_ENC2)
+ else if (port->nr == SAA7164_PORT_ENC2)
tsport = &dev->ports[SAA7164_PORT_TS2];
else
BUG();
@@ -396,253 +412,54 @@ static int vidioc_s_frequency(struct file *file, void *priv,
return 0;
}
-static int vidioc_g_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctl)
+static int vidioc_s_frequency(struct file *file, void *priv,
+ const struct v4l2_frequency *f)
{
struct saa7164_encoder_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- struct saa7164_dev *dev = port->dev;
-
- dprintk(DBGLVL_ENC, "%s(id=%d, value=%d)\n", __func__,
- ctl->id, ctl->value);
-
- switch (ctl->id) {
- case V4L2_CID_BRIGHTNESS:
- ctl->value = port->ctl_brightness;
- break;
- case V4L2_CID_CONTRAST:
- ctl->value = port->ctl_contrast;
- break;
- case V4L2_CID_SATURATION:
- ctl->value = port->ctl_saturation;
- break;
- case V4L2_CID_HUE:
- ctl->value = port->ctl_hue;
- break;
- case V4L2_CID_SHARPNESS:
- ctl->value = port->ctl_sharpness;
- break;
- case V4L2_CID_AUDIO_VOLUME:
- ctl->value = port->ctl_volume;
- break;
- default:
- return -EINVAL;
- }
- return 0;
+ return saa7164_s_frequency(fh->port, f);
}
-static int vidioc_s_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctl)
+static int saa7164_s_ctrl(struct v4l2_ctrl *ctrl)
{
- struct saa7164_encoder_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- struct saa7164_dev *dev = port->dev;
+ struct saa7164_port *port =
+ container_of(ctrl->handler, struct saa7164_port, ctrl_handler);
+ struct saa7164_encoder_params *params = &port->encoder_params;
int ret = 0;
- dprintk(DBGLVL_ENC, "%s(id=%d, value=%d)\n", __func__,
- ctl->id, ctl->value);
-
- switch (ctl->id) {
+ switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
- if ((ctl->value >= 0) && (ctl->value <= 255)) {
- port->ctl_brightness = ctl->value;
- saa7164_api_set_usercontrol(port,
- PU_BRIGHTNESS_CONTROL);
- } else
- ret = -EINVAL;
+ port->ctl_brightness = ctrl->val;
+ saa7164_api_set_usercontrol(port, PU_BRIGHTNESS_CONTROL);
break;
case V4L2_CID_CONTRAST:
- if ((ctl->value >= 0) && (ctl->value <= 255)) {
- port->ctl_contrast = ctl->value;
- saa7164_api_set_usercontrol(port, PU_CONTRAST_CONTROL);
- } else
- ret = -EINVAL;
+ port->ctl_contrast = ctrl->val;
+ saa7164_api_set_usercontrol(port, PU_CONTRAST_CONTROL);
break;
case V4L2_CID_SATURATION:
- if ((ctl->value >= 0) && (ctl->value <= 255)) {
- port->ctl_saturation = ctl->value;
- saa7164_api_set_usercontrol(port,
- PU_SATURATION_CONTROL);
- } else
- ret = -EINVAL;
+ port->ctl_saturation = ctrl->val;
+ saa7164_api_set_usercontrol(port, PU_SATURATION_CONTROL);
break;
case V4L2_CID_HUE:
- if ((ctl->value >= 0) && (ctl->value <= 255)) {
- port->ctl_hue = ctl->value;
- saa7164_api_set_usercontrol(port, PU_HUE_CONTROL);
- } else
- ret = -EINVAL;
+ port->ctl_hue = ctrl->val;
+ saa7164_api_set_usercontrol(port, PU_HUE_CONTROL);
break;
case V4L2_CID_SHARPNESS:
- if ((ctl->value >= 0) && (ctl->value <= 255)) {
- port->ctl_sharpness = ctl->value;
- saa7164_api_set_usercontrol(port, PU_SHARPNESS_CONTROL);
- } else
- ret = -EINVAL;
+ port->ctl_sharpness = ctrl->val;
+ saa7164_api_set_usercontrol(port, PU_SHARPNESS_CONTROL);
break;
case V4L2_CID_AUDIO_VOLUME:
- if ((ctl->value >= -83) && (ctl->value <= 24)) {
- port->ctl_volume = ctl->value;
- saa7164_api_set_audio_volume(port, port->ctl_volume);
- } else
- ret = -EINVAL;
- break;
- default:
- ret = -EINVAL;
- }
-
- return ret;
-}
-
-static int saa7164_get_ctrl(struct saa7164_port *port,
- struct v4l2_ext_control *ctrl)
-{
- struct saa7164_encoder_params *params = &port->encoder_params;
-
- switch (ctrl->id) {
- case V4L2_CID_MPEG_VIDEO_BITRATE:
- ctrl->value = params->bitrate;
- break;
- case V4L2_CID_MPEG_STREAM_TYPE:
- ctrl->value = params->stream_type;
- break;
- case V4L2_CID_MPEG_AUDIO_MUTE:
- ctrl->value = params->ctl_mute;
- break;
- case V4L2_CID_MPEG_VIDEO_ASPECT:
- ctrl->value = params->ctl_aspect;
- break;
- case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
- ctrl->value = params->bitrate_mode;
- break;
- case V4L2_CID_MPEG_VIDEO_B_FRAMES:
- ctrl->value = params->refdist;
- break;
- case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
- ctrl->value = params->bitrate_peak;
- break;
- case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
- ctrl->value = params->gop_size;
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-static int vidioc_g_ext_ctrls(struct file *file, void *priv,
- struct v4l2_ext_controls *ctrls)
-{
- struct saa7164_encoder_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- int i, err = 0;
-
- if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
- for (i = 0; i < ctrls->count; i++) {
- struct v4l2_ext_control *ctrl = ctrls->controls + i;
-
- err = saa7164_get_ctrl(port, ctrl);
- if (err) {
- ctrls->error_idx = i;
- break;
- }
- }
- return err;
-
- }
-
- return -EINVAL;
-}
-
-static int saa7164_try_ctrl(struct v4l2_ext_control *ctrl, int ac3)
-{
- int ret = -EINVAL;
-
- switch (ctrl->id) {
- case V4L2_CID_MPEG_VIDEO_BITRATE:
- if ((ctrl->value >= ENCODER_MIN_BITRATE) &&
- (ctrl->value <= ENCODER_MAX_BITRATE))
- ret = 0;
+ port->ctl_volume = ctrl->val;
+ saa7164_api_set_audio_volume(port, port->ctl_volume);
break;
- case V4L2_CID_MPEG_STREAM_TYPE:
- if ((ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_PS) ||
- (ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_TS))
- ret = 0;
- break;
- case V4L2_CID_MPEG_AUDIO_MUTE:
- if ((ctrl->value >= 0) &&
- (ctrl->value <= 1))
- ret = 0;
- break;
- case V4L2_CID_MPEG_VIDEO_ASPECT:
- if ((ctrl->value >= V4L2_MPEG_VIDEO_ASPECT_1x1) &&
- (ctrl->value <= V4L2_MPEG_VIDEO_ASPECT_221x100))
- ret = 0;
- break;
- case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
- if ((ctrl->value >= 0) &&
- (ctrl->value <= 255))
- ret = 0;
- break;
- case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
- if ((ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) ||
- (ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR))
- ret = 0;
- break;
- case V4L2_CID_MPEG_VIDEO_B_FRAMES:
- if ((ctrl->value >= 1) &&
- (ctrl->value <= 3))
- ret = 0;
- break;
- case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
- if ((ctrl->value >= ENCODER_MIN_BITRATE) &&
- (ctrl->value <= ENCODER_MAX_BITRATE))
- ret = 0;
- break;
- default:
- ret = -EINVAL;
- }
-
- return ret;
-}
-
-static int vidioc_try_ext_ctrls(struct file *file, void *priv,
- struct v4l2_ext_controls *ctrls)
-{
- int i, err = 0;
-
- if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
- for (i = 0; i < ctrls->count; i++) {
- struct v4l2_ext_control *ctrl = ctrls->controls + i;
-
- err = saa7164_try_ctrl(ctrl, 0);
- if (err) {
- ctrls->error_idx = i;
- break;
- }
- }
- return err;
- }
-
- return -EINVAL;
-}
-
-static int saa7164_set_ctrl(struct saa7164_port *port,
- struct v4l2_ext_control *ctrl)
-{
- struct saa7164_encoder_params *params = &port->encoder_params;
- int ret = 0;
-
- switch (ctrl->id) {
case V4L2_CID_MPEG_VIDEO_BITRATE:
- params->bitrate = ctrl->value;
+ params->bitrate = ctrl->val;
break;
case V4L2_CID_MPEG_STREAM_TYPE:
- params->stream_type = ctrl->value;
+ params->stream_type = ctrl->val;
break;
case V4L2_CID_MPEG_AUDIO_MUTE:
- params->ctl_mute = ctrl->value;
+ params->ctl_mute = ctrl->val;
ret = saa7164_api_audio_mute(port, params->ctl_mute);
if (ret != SAA_OK) {
printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__,
@@ -651,7 +468,7 @@ static int saa7164_set_ctrl(struct saa7164_port *port,
}
break;
case V4L2_CID_MPEG_VIDEO_ASPECT:
- params->ctl_aspect = ctrl->value;
+ params->ctl_aspect = ctrl->val;
ret = saa7164_api_set_aspect_ratio(port);
if (ret != SAA_OK) {
printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__,
@@ -660,55 +477,24 @@ static int saa7164_set_ctrl(struct saa7164_port *port,
}
break;
case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
- params->bitrate_mode = ctrl->value;
+ params->bitrate_mode = ctrl->val;
break;
case V4L2_CID_MPEG_VIDEO_B_FRAMES:
- params->refdist = ctrl->value;
+ params->refdist = ctrl->val;
break;
case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
- params->bitrate_peak = ctrl->value;
+ params->bitrate_peak = ctrl->val;
break;
case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
- params->gop_size = ctrl->value;
+ params->gop_size = ctrl->val;
break;
default:
- return -EINVAL;
+ ret = -EINVAL;
}
- /* TODO: Update the hardware */
-
return ret;
}
-static int vidioc_s_ext_ctrls(struct file *file, void *priv,
- struct v4l2_ext_controls *ctrls)
-{
- struct saa7164_encoder_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- int i, err = 0;
-
- if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
- for (i = 0; i < ctrls->count; i++) {
- struct v4l2_ext_control *ctrl = ctrls->controls + i;
-
- err = saa7164_try_ctrl(ctrl, 0);
- if (err) {
- ctrls->error_idx = i;
- break;
- }
- err = saa7164_set_ctrl(port, ctrl);
- if (err) {
- ctrls->error_idx = i;
- break;
- }
- }
- return err;
-
- }
-
- return -EINVAL;
-}
-
static int vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
@@ -745,145 +531,22 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
return 0;
}
-static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+static int vidioc_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct saa7164_encoder_fh *fh = file->private_data;
struct saa7164_port *port = fh->port;
- struct saa7164_dev *dev = port->dev;
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.bytesperline = 0;
- f->fmt.pix.sizeimage =
- port->ts_packet_size * port->ts_packet_count;
- f->fmt.pix.colorspace = 0;
+ f->fmt.pix.sizeimage = SAA7164_SIZEIMAGE;
+ f->fmt.pix.field = V4L2_FIELD_INTERLACED;
+ f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
f->fmt.pix.width = port->width;
f->fmt.pix.height = port->height;
-
- dprintk(DBGLVL_ENC, "VIDIOC_G_FMT: w: %d, h: %d\n",
- port->width, port->height);
-
- return 0;
-}
-
-static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct saa7164_encoder_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- struct saa7164_dev *dev = port->dev;
-
- f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
- f->fmt.pix.bytesperline = 0;
- f->fmt.pix.sizeimage =
- port->ts_packet_size * port->ts_packet_count;
- f->fmt.pix.colorspace = 0;
- dprintk(DBGLVL_ENC, "VIDIOC_TRY_FMT: w: %d, h: %d\n",
- port->width, port->height);
return 0;
}
-static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct saa7164_encoder_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- struct saa7164_dev *dev = port->dev;
-
- f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
- f->fmt.pix.bytesperline = 0;
- f->fmt.pix.sizeimage =
- port->ts_packet_size * port->ts_packet_count;
- f->fmt.pix.colorspace = 0;
-
- dprintk(DBGLVL_ENC, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
- f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
-
- return 0;
-}
-
-static int fill_queryctrl(struct saa7164_encoder_params *params,
- struct v4l2_queryctrl *c)
-{
- switch (c->id) {
- case V4L2_CID_BRIGHTNESS:
- return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 127);
- case V4L2_CID_CONTRAST:
- return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 66);
- case V4L2_CID_SATURATION:
- return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 62);
- case V4L2_CID_HUE:
- return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 128);
- case V4L2_CID_SHARPNESS:
- return v4l2_ctrl_query_fill(c, 0x0, 0x0f, 1, 8);
- case V4L2_CID_MPEG_AUDIO_MUTE:
- return v4l2_ctrl_query_fill(c, 0x0, 0x01, 1, 0);
- case V4L2_CID_AUDIO_VOLUME:
- return v4l2_ctrl_query_fill(c, -83, 24, 1, 20);
- case V4L2_CID_MPEG_VIDEO_BITRATE:
- return v4l2_ctrl_query_fill(c,
- ENCODER_MIN_BITRATE, ENCODER_MAX_BITRATE,
- 100000, ENCODER_DEF_BITRATE);
- case V4L2_CID_MPEG_STREAM_TYPE:
- return v4l2_ctrl_query_fill(c,
- V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
- V4L2_MPEG_STREAM_TYPE_MPEG2_TS,
- 1, V4L2_MPEG_STREAM_TYPE_MPEG2_PS);
- case V4L2_CID_MPEG_VIDEO_ASPECT:
- return v4l2_ctrl_query_fill(c,
- V4L2_MPEG_VIDEO_ASPECT_1x1,
- V4L2_MPEG_VIDEO_ASPECT_221x100,
- 1, V4L2_MPEG_VIDEO_ASPECT_4x3);
- case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
- return v4l2_ctrl_query_fill(c, 1, 255, 1, 15);
- case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
- return v4l2_ctrl_query_fill(c,
- V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
- V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
- 1, V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
- case V4L2_CID_MPEG_VIDEO_B_FRAMES:
- return v4l2_ctrl_query_fill(c,
- 1, 3, 1, 1);
- case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
- return v4l2_ctrl_query_fill(c,
- ENCODER_MIN_BITRATE, ENCODER_MAX_BITRATE,
- 100000, ENCODER_DEF_BITRATE);
- default:
- return -EINVAL;
- }
-}
-
-static int vidioc_queryctrl(struct file *file, void *priv,
- struct v4l2_queryctrl *c)
-{
- struct saa7164_encoder_fh *fh = priv;
- struct saa7164_port *port = fh->port;
- int i, next;
- u32 id = c->id;
-
- memset(c, 0, sizeof(*c));
-
- next = !!(id & V4L2_CTRL_FLAG_NEXT_CTRL);
- c->id = id & ~V4L2_CTRL_FLAG_NEXT_CTRL;
-
- for (i = 0; i < ARRAY_SIZE(saa7164_v4l2_ctrls); i++) {
- if (next) {
- if (c->id < saa7164_v4l2_ctrls[i])
- c->id = saa7164_v4l2_ctrls[i];
- else
- continue;
- }
-
- if (c->id == saa7164_v4l2_ctrls[i])
- return fill_queryctrl(&port->encoder_params, c);
-
- if (c->id < saa7164_v4l2_ctrls[i])
- break;
- }
-
- return -EINVAL;
-}
-
static int saa7164_encoder_stop_port(struct saa7164_port *port)
{
struct saa7164_dev *dev = port->dev;
@@ -1084,8 +747,10 @@ static int fops_open(struct file *file)
if (NULL == fh)
return -ENOMEM;
- file->private_data = fh;
fh->port = port;
+ v4l2_fh_init(&fh->fh, video_devdata(file));
+ v4l2_fh_add(&fh->fh);
+ file->private_data = fh;
return 0;
}
@@ -1106,7 +771,8 @@ static int fops_release(struct file *file)
}
}
- file->private_data = NULL;
+ v4l2_fh_del(&fh->fh);
+ v4l2_fh_exit(&fh->fh);
kfree(fh);
return 0;
@@ -1250,10 +916,11 @@ err:
static unsigned int fops_poll(struct file *file, poll_table *wait)
{
+ unsigned long req_events = poll_requested_events(wait);
struct saa7164_encoder_fh *fh =
(struct saa7164_encoder_fh *)file->private_data;
struct saa7164_port *port = fh->port;
- unsigned int mask = 0;
+ unsigned int mask = v4l2_ctrl_poll(file, wait);
port->last_poll_msecs_diff = port->last_poll_msecs;
port->last_poll_msecs = jiffies_to_msecs(jiffies);
@@ -1263,26 +930,18 @@ static unsigned int fops_poll(struct file *file, poll_table *wait)
saa7164_histogram_update(&port->poll_interval,
port->last_poll_msecs_diff);
- if (!video_is_registered(port->v4l_device))
- return -EIO;
+ if (!(req_events & (POLLIN | POLLRDNORM)))
+ return mask;
if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
if (atomic_inc_return(&port->v4l_reader_count) == 1) {
if (saa7164_encoder_initialize(port) < 0)
- return -EINVAL;
+ return mask | POLLERR;
saa7164_encoder_start_streaming(port);
msleep(200);
}
}
- /* blocking wait for buffer */
- if ((file->f_flags & O_NONBLOCK) == 0) {
- if (wait_event_interruptible(port->wait_read,
- saa7164_enc_next_buf(port))) {
- return -ERESTARTSYS;
- }
- }
-
/* Pull the first buffer from the used list */
if (!list_empty(&port->list_buf_used.list))
mask |= POLLIN | POLLRDNORM;
@@ -1290,6 +949,10 @@ static unsigned int fops_poll(struct file *file, poll_table *wait)
return mask;
}
+static const struct v4l2_ctrl_ops saa7164_ctrl_ops = {
+ .s_ctrl = saa7164_s_ctrl,
+};
+
static const struct v4l2_file_operations mpeg_fops = {
.owner = THIS_MODULE,
.open = fops_open,
@@ -1302,24 +965,21 @@ static const struct v4l2_file_operations mpeg_fops = {
static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
.vidioc_s_std = vidioc_s_std,
.vidioc_g_std = vidioc_g_std,
- .vidioc_enum_input = vidioc_enum_input,
+ .vidioc_enum_input = saa7164_enum_input,
.vidioc_g_input = vidioc_g_input,
.vidioc_s_input = vidioc_s_input,
- .vidioc_g_tuner = vidioc_g_tuner,
- .vidioc_s_tuner = vidioc_s_tuner,
+ .vidioc_g_tuner = saa7164_g_tuner,
+ .vidioc_s_tuner = saa7164_s_tuner,
.vidioc_g_frequency = vidioc_g_frequency,
.vidioc_s_frequency = vidioc_s_frequency,
- .vidioc_s_ctrl = vidioc_s_ctrl,
- .vidioc_g_ctrl = vidioc_g_ctrl,
.vidioc_querycap = vidioc_querycap,
.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
- .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
- .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
- .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
- .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls,
- .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls,
- .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls,
- .vidioc_queryctrl = vidioc_queryctrl,
+ .vidioc_g_fmt_vid_cap = vidioc_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = vidioc_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = vidioc_fmt_vid_cap,
+ .vidioc_log_status = v4l2_ctrl_log_status,
+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
};
static struct video_device saa7164_mpeg_template = {
@@ -1357,6 +1017,7 @@ static struct video_device *saa7164_encoder_alloc(
int saa7164_encoder_register(struct saa7164_port *port)
{
struct saa7164_dev *dev = port->dev;
+ struct v4l2_ctrl_handler *hdl = &port->ctrl_handler;
int result = -ENODEV;
dprintk(DBGLVL_ENC, "%s()\n", __func__);
@@ -1381,19 +1042,52 @@ int saa7164_encoder_register(struct saa7164_port *port)
port->video_format = EU_VIDEO_FORMAT_MPEG_2;
port->audio_format = 0;
port->video_resolution = 0;
- port->ctl_brightness = 127;
- port->ctl_contrast = 66;
- port->ctl_hue = 128;
- port->ctl_saturation = 62;
- port->ctl_sharpness = 8;
- port->encoder_params.bitrate = ENCODER_DEF_BITRATE;
- port->encoder_params.bitrate_peak = ENCODER_DEF_BITRATE;
- port->encoder_params.bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
- port->encoder_params.stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
- port->encoder_params.ctl_mute = 0;
- port->encoder_params.ctl_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3;
- port->encoder_params.refdist = 1;
- port->encoder_params.gop_size = SAA7164_ENCODER_DEFAULT_GOP_SIZE;
+ port->freq = SAA7164_TV_MIN_FREQ;
+
+ v4l2_ctrl_handler_init(hdl, 14);
+ v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops,
+ V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
+ v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops,
+ V4L2_CID_CONTRAST, 0, 255, 1, 66);
+ v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops,
+ V4L2_CID_SATURATION, 0, 255, 1, 62);
+ v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops,
+ V4L2_CID_HUE, 0, 255, 1, 128);
+ v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops,
+ V4L2_CID_SHARPNESS, 0x0, 0x0f, 1, 8);
+ v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops,
+ V4L2_CID_MPEG_AUDIO_MUTE, 0x0, 0x01, 1, 0);
+ v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops,
+ V4L2_CID_AUDIO_VOLUME, -83, 24, 1, 20);
+ v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_BITRATE,
+ ENCODER_MIN_BITRATE, ENCODER_MAX_BITRATE,
+ 100000, ENCODER_DEF_BITRATE);
+ v4l2_ctrl_new_std_menu(hdl, &saa7164_ctrl_ops,
+ V4L2_CID_MPEG_STREAM_TYPE,
+ V4L2_MPEG_STREAM_TYPE_MPEG2_TS, 0,
+ V4L2_MPEG_STREAM_TYPE_MPEG2_PS);
+ v4l2_ctrl_new_std_menu(hdl, &saa7164_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_ASPECT,
+ V4L2_MPEG_VIDEO_ASPECT_221x100, 0,
+ V4L2_MPEG_VIDEO_ASPECT_4x3);
+ v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_GOP_SIZE, 1, 255, 1, 15);
+ v4l2_ctrl_new_std_menu(hdl, &saa7164_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
+ V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 0,
+ V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
+ v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_B_FRAMES, 1, 3, 1, 1);
+ v4l2_ctrl_new_std(hdl, &saa7164_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
+ ENCODER_MIN_BITRATE, ENCODER_MAX_BITRATE,
+ 100000, ENCODER_DEF_BITRATE);
+ if (hdl->error) {
+ result = hdl->error;
+ goto failed;
+ }
+
port->std = V4L2_STD_NTSC_M;
if (port->encodernorm.id & V4L2_STD_525_60)
@@ -1412,6 +1106,8 @@ int saa7164_encoder_register(struct saa7164_port *port)
goto failed;
}
+ port->v4l_device->ctrl_handler = hdl;
+ v4l2_ctrl_handler_setup(hdl);
video_set_drvdata(port->v4l_device, port);
result = video_register_device(port->v4l_device,
VFL_TYPE_GRABBER, -1);
@@ -1466,6 +1162,7 @@ void saa7164_encoder_unregister(struct saa7164_port *port)
port->v4l_device = NULL;
}
+ v4l2_ctrl_handler_free(&port->ctrl_handler);
dprintk(DBGLVL_ENC, "%s(port=%d) done\n", __func__, port->nr);
}
diff --git a/kernel/drivers/media/pci/saa7164/saa7164-fw.c b/kernel/drivers/media/pci/saa7164/saa7164-fw.c
index add06ab51..269e0782c 100644
--- a/kernel/drivers/media/pci/saa7164/saa7164-fw.c
+++ b/kernel/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/kernel/drivers/media/pci/saa7164/saa7164-i2c.c b/kernel/drivers/media/pci/saa7164/saa7164-i2c.c
index 4f7e3b422..0342d8491 100644
--- a/kernel/drivers/media/pci/saa7164/saa7164-i2c.c
+++ b/kernel/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/kernel/drivers/media/pci/saa7164/saa7164-reg.h b/kernel/drivers/media/pci/saa7164/saa7164-reg.h
index 2bbf81583..37521a2ee 100644
--- a/kernel/drivers/media/pci/saa7164/saa7164-reg.h
+++ b/kernel/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/kernel/drivers/media/pci/saa7164/saa7164-types.h b/kernel/drivers/media/pci/saa7164/saa7164-types.h
index f48ba978f..1efba6c64 100644
--- a/kernel/drivers/media/pci/saa7164/saa7164-types.h
+++ b/kernel/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/kernel/drivers/media/pci/saa7164/saa7164-vbi.c b/kernel/drivers/media/pci/saa7164/saa7164-vbi.c
index 06117e6c0..ee5449145 100644
--- a/kernel/drivers/media/pci/saa7164/saa7164-vbi.c
+++ b/kernel/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
@@ -21,20 +21,6 @@
#include "saa7164.h"
-static struct saa7164_tvnorm saa7164_tvnorms[] = {
- {
- .name = "NTSC-M",
- .id = V4L2_STD_NTSC_M,
- }, {
- .name = "NTSC-JP",
- .id = V4L2_STD_NTSC_M_JP,
- }
-};
-
-static const u32 saa7164_v4l2_ctrls[] = {
- 0
-};
-
/* Take the encoder configuration from the port struct and
* flush it to the hardware.
*/
@@ -43,23 +29,13 @@ static void saa7164_vbi_configure(struct saa7164_port *port)
struct saa7164_dev *dev = port->dev;
dprintk(DBGLVL_VBI, "%s()\n", __func__);
- port->vbi_params.width = port->width;
- port->vbi_params.height = port->height;
+ port->vbi_params.width = port->enc_port->width;
+ port->vbi_params.height = port->enc_port->height;
port->vbi_params.is_50hz =
- (port->encodernorm.id & V4L2_STD_625_50) != 0;
+ (port->enc_port->encodernorm.id & V4L2_STD_625_50) != 0;
/* Set up the DIF (enable it) for analog mode by default */
saa7164_api_initialize_dif(port);
-
- /* Configure the correct video standard */
-#if 0
- saa7164_api_configure_dif(port, port->encodernorm.id);
-#endif
-
-#if 0
- /* Ensure the audio decoder is correct configured */
- saa7164_api_set_audio_std(port);
-#endif
dprintk(DBGLVL_VBI, "%s() ends\n", __func__);
}
@@ -186,468 +162,50 @@ static int saa7164_vbi_initialize(struct saa7164_port *port)
static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id)
{
struct saa7164_vbi_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- struct saa7164_dev *dev = port->dev;
- unsigned int i;
- dprintk(DBGLVL_VBI, "%s(id=0x%x)\n", __func__, (u32)id);
-
- for (i = 0; i < ARRAY_SIZE(saa7164_tvnorms); i++) {
- if (id & saa7164_tvnorms[i].id)
- break;
- }
- if (i == ARRAY_SIZE(saa7164_tvnorms))
- return -EINVAL;
-
- port->encodernorm = saa7164_tvnorms[i];
- port->std = id;
-
- /* Update the audio decoder while is not running in
- * auto detect mode.
- */
- saa7164_api_set_audio_std(port);
-
- dprintk(DBGLVL_VBI, "%s(id=0x%x) OK\n", __func__, (u32)id);
-
- return 0;
+ return saa7164_s_std(fh->port->enc_port, id);
}
static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
{
struct saa7164_encoder_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- *id = port->std;
- return 0;
-}
-
-static int vidioc_enum_input(struct file *file, void *priv,
- struct v4l2_input *i)
-{
- int n;
-
- char *inputs[] = { "tuner", "composite", "svideo", "aux",
- "composite 2", "svideo 2", "aux 2" };
-
- if (i->index >= 7)
- return -EINVAL;
-
- strcpy(i->name, inputs[i->index]);
-
- if (i->index == 0)
- i->type = V4L2_INPUT_TYPE_TUNER;
- else
- i->type = V4L2_INPUT_TYPE_CAMERA;
-
- for (n = 0; n < ARRAY_SIZE(saa7164_tvnorms); n++)
- i->std |= saa7164_tvnorms[n].id;
-
- return 0;
+ return saa7164_g_std(fh->port->enc_port, id);
}
static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
{
struct saa7164_vbi_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- struct saa7164_dev *dev = port->dev;
-
- if (saa7164_api_get_videomux(port) != SAA_OK)
- return -EIO;
-
- *i = (port->mux_input - 1);
-
- dprintk(DBGLVL_VBI, "%s() input=%d\n", __func__, *i);
- return 0;
+ return saa7164_g_input(fh->port->enc_port, i);
}
static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
{
struct saa7164_vbi_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- struct saa7164_dev *dev = port->dev;
-
- dprintk(DBGLVL_VBI, "%s() input=%d\n", __func__, i);
-
- if (i >= 7)
- return -EINVAL;
-
- port->mux_input = i + 1;
- if (saa7164_api_set_videomux(port) != SAA_OK)
- return -EIO;
-
- return 0;
-}
-
-static int vidioc_g_tuner(struct file *file, void *priv,
- struct v4l2_tuner *t)
-{
- struct saa7164_vbi_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- struct saa7164_dev *dev = port->dev;
-
- if (0 != t->index)
- return -EINVAL;
-
- strcpy(t->name, "tuner");
- t->type = V4L2_TUNER_ANALOG_TV;
- t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO;
-
- dprintk(DBGLVL_VBI, "VIDIOC_G_TUNER: tuner type %d\n", t->type);
-
- return 0;
-}
-
-static int vidioc_s_tuner(struct file *file, void *priv,
- const struct v4l2_tuner *t)
-{
- /* Update the A/V core */
- return 0;
+ return saa7164_s_input(fh->port->enc_port, i);
}
static int vidioc_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
struct saa7164_vbi_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- f->type = V4L2_TUNER_ANALOG_TV;
- f->frequency = port->freq;
-
- return 0;
+ return saa7164_g_frequency(fh->port->enc_port, f);
}
static int vidioc_s_frequency(struct file *file, void *priv,
const struct v4l2_frequency *f)
{
struct saa7164_vbi_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- struct saa7164_dev *dev = port->dev;
- struct saa7164_port *tsport;
- struct dvb_frontend *fe;
-
- /* TODO: Pull this for the std */
- struct analog_parameters params = {
- .mode = V4L2_TUNER_ANALOG_TV,
- .audmode = V4L2_TUNER_MODE_STEREO,
- .std = port->encodernorm.id,
- .frequency = f->frequency
- };
-
- /* Stop the encoder */
- dprintk(DBGLVL_VBI, "%s() frequency=%d tuner=%d\n", __func__,
- f->frequency, f->tuner);
-
- if (f->tuner != 0)
- return -EINVAL;
-
- if (f->type != V4L2_TUNER_ANALOG_TV)
- return -EINVAL;
-
- port->freq = f->frequency;
-
- /* Update the hardware */
- if (port->nr == SAA7164_PORT_VBI1)
- tsport = &dev->ports[SAA7164_PORT_TS1];
- else
- if (port->nr == SAA7164_PORT_VBI2)
- tsport = &dev->ports[SAA7164_PORT_TS2];
- else
- BUG();
-
- fe = tsport->dvb.frontend;
-
- if (fe && fe->ops.tuner_ops.set_analog_params)
- fe->ops.tuner_ops.set_analog_params(fe, &params);
- else
- printk(KERN_ERR "%s() No analog tuner, aborting\n", __func__);
-
- saa7164_vbi_initialize(port);
-
- return 0;
-}
-
-static int vidioc_g_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctl)
-{
- struct saa7164_vbi_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- struct saa7164_dev *dev = port->dev;
-
- dprintk(DBGLVL_VBI, "%s(id=%d, value=%d)\n", __func__,
- ctl->id, ctl->value);
-
- switch (ctl->id) {
- case V4L2_CID_BRIGHTNESS:
- ctl->value = port->ctl_brightness;
- break;
- case V4L2_CID_CONTRAST:
- ctl->value = port->ctl_contrast;
- break;
- case V4L2_CID_SATURATION:
- ctl->value = port->ctl_saturation;
- break;
- case V4L2_CID_HUE:
- ctl->value = port->ctl_hue;
- break;
- case V4L2_CID_SHARPNESS:
- ctl->value = port->ctl_sharpness;
- break;
- case V4L2_CID_AUDIO_VOLUME:
- ctl->value = port->ctl_volume;
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int vidioc_s_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctl)
-{
- struct saa7164_vbi_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- struct saa7164_dev *dev = port->dev;
- int ret = 0;
-
- dprintk(DBGLVL_VBI, "%s(id=%d, value=%d)\n", __func__,
- ctl->id, ctl->value);
-
- switch (ctl->id) {
- case V4L2_CID_BRIGHTNESS:
- if ((ctl->value >= 0) && (ctl->value <= 255)) {
- port->ctl_brightness = ctl->value;
- saa7164_api_set_usercontrol(port,
- PU_BRIGHTNESS_CONTROL);
- } else
- ret = -EINVAL;
- break;
- case V4L2_CID_CONTRAST:
- if ((ctl->value >= 0) && (ctl->value <= 255)) {
- port->ctl_contrast = ctl->value;
- saa7164_api_set_usercontrol(port, PU_CONTRAST_CONTROL);
- } else
- ret = -EINVAL;
- break;
- case V4L2_CID_SATURATION:
- if ((ctl->value >= 0) && (ctl->value <= 255)) {
- port->ctl_saturation = ctl->value;
- saa7164_api_set_usercontrol(port,
- PU_SATURATION_CONTROL);
- } else
- ret = -EINVAL;
- break;
- case V4L2_CID_HUE:
- if ((ctl->value >= 0) && (ctl->value <= 255)) {
- port->ctl_hue = ctl->value;
- saa7164_api_set_usercontrol(port, PU_HUE_CONTROL);
- } else
- ret = -EINVAL;
- break;
- case V4L2_CID_SHARPNESS:
- if ((ctl->value >= 0) && (ctl->value <= 255)) {
- port->ctl_sharpness = ctl->value;
- saa7164_api_set_usercontrol(port, PU_SHARPNESS_CONTROL);
- } else
- ret = -EINVAL;
- break;
- case V4L2_CID_AUDIO_VOLUME:
- if ((ctl->value >= -83) && (ctl->value <= 24)) {
- port->ctl_volume = ctl->value;
- saa7164_api_set_audio_volume(port, port->ctl_volume);
- } else
- ret = -EINVAL;
- break;
- default:
- ret = -EINVAL;
- }
+ int ret = saa7164_s_frequency(fh->port->enc_port, f);
+ if (ret == 0)
+ saa7164_vbi_initialize(fh->port);
return ret;
}
-static int saa7164_get_ctrl(struct saa7164_port *port,
- struct v4l2_ext_control *ctrl)
-{
- struct saa7164_vbi_params *params = &port->vbi_params;
-
- switch (ctrl->id) {
- case V4L2_CID_MPEG_STREAM_TYPE:
- ctrl->value = params->stream_type;
- break;
- case V4L2_CID_MPEG_AUDIO_MUTE:
- ctrl->value = params->ctl_mute;
- break;
- case V4L2_CID_MPEG_VIDEO_ASPECT:
- ctrl->value = params->ctl_aspect;
- break;
- case V4L2_CID_MPEG_VIDEO_B_FRAMES:
- ctrl->value = params->refdist;
- break;
- case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
- ctrl->value = params->gop_size;
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-static int vidioc_g_ext_ctrls(struct file *file, void *priv,
- struct v4l2_ext_controls *ctrls)
-{
- struct saa7164_vbi_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- int i, err = 0;
-
- if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
- for (i = 0; i < ctrls->count; i++) {
- struct v4l2_ext_control *ctrl = ctrls->controls + i;
-
- err = saa7164_get_ctrl(port, ctrl);
- if (err) {
- ctrls->error_idx = i;
- break;
- }
- }
- return err;
-
- }
-
- return -EINVAL;
-}
-
-static int saa7164_try_ctrl(struct v4l2_ext_control *ctrl, int ac3)
-{
- int ret = -EINVAL;
-
- switch (ctrl->id) {
- case V4L2_CID_MPEG_STREAM_TYPE:
- if ((ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_PS) ||
- (ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_TS))
- ret = 0;
- break;
- case V4L2_CID_MPEG_AUDIO_MUTE:
- if ((ctrl->value >= 0) &&
- (ctrl->value <= 1))
- ret = 0;
- break;
- case V4L2_CID_MPEG_VIDEO_ASPECT:
- if ((ctrl->value >= V4L2_MPEG_VIDEO_ASPECT_1x1) &&
- (ctrl->value <= V4L2_MPEG_VIDEO_ASPECT_221x100))
- ret = 0;
- break;
- case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
- if ((ctrl->value >= 0) &&
- (ctrl->value <= 255))
- ret = 0;
- break;
- case V4L2_CID_MPEG_VIDEO_B_FRAMES:
- if ((ctrl->value >= 1) &&
- (ctrl->value <= 3))
- ret = 0;
- break;
- default:
- ret = -EINVAL;
- }
-
- return ret;
-}
-
-static int vidioc_try_ext_ctrls(struct file *file, void *priv,
- struct v4l2_ext_controls *ctrls)
-{
- int i, err = 0;
-
- if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
- for (i = 0; i < ctrls->count; i++) {
- struct v4l2_ext_control *ctrl = ctrls->controls + i;
-
- err = saa7164_try_ctrl(ctrl, 0);
- if (err) {
- ctrls->error_idx = i;
- break;
- }
- }
- return err;
- }
-
- return -EINVAL;
-}
-
-static int saa7164_set_ctrl(struct saa7164_port *port,
- struct v4l2_ext_control *ctrl)
-{
- struct saa7164_vbi_params *params = &port->vbi_params;
- int ret = 0;
-
- switch (ctrl->id) {
- case V4L2_CID_MPEG_STREAM_TYPE:
- params->stream_type = ctrl->value;
- break;
- case V4L2_CID_MPEG_AUDIO_MUTE:
- params->ctl_mute = ctrl->value;
- ret = saa7164_api_audio_mute(port, params->ctl_mute);
- if (ret != SAA_OK) {
- printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__,
- ret);
- ret = -EIO;
- }
- break;
- case V4L2_CID_MPEG_VIDEO_ASPECT:
- params->ctl_aspect = ctrl->value;
- ret = saa7164_api_set_aspect_ratio(port);
- if (ret != SAA_OK) {
- printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__,
- ret);
- ret = -EIO;
- }
- break;
- case V4L2_CID_MPEG_VIDEO_B_FRAMES:
- params->refdist = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
- params->gop_size = ctrl->value;
- break;
- default:
- return -EINVAL;
- }
-
- /* TODO: Update the hardware */
-
- return ret;
-}
-
-static int vidioc_s_ext_ctrls(struct file *file, void *priv,
- struct v4l2_ext_controls *ctrls)
-{
- struct saa7164_vbi_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- int i, err = 0;
-
- if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
- for (i = 0; i < ctrls->count; i++) {
- struct v4l2_ext_control *ctrl = ctrls->controls + i;
-
- err = saa7164_try_ctrl(ctrl, 0);
- if (err) {
- ctrls->error_idx = i;
- break;
- }
- err = saa7164_set_ctrl(port, ctrl);
- if (err) {
- ctrls->error_idx = i;
- break;
- }
- }
- return err;
-
- }
-
- return -EINVAL;
-}
-
static int vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
@@ -672,144 +230,6 @@ static int vidioc_querycap(struct file *file, void *priv,
return 0;
}
-static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_fmtdesc *f)
-{
- if (f->index != 0)
- return -EINVAL;
-
- strlcpy(f->description, "VBI", sizeof(f->description));
- f->pixelformat = V4L2_PIX_FMT_MPEG;
-
- return 0;
-}
-
-static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct saa7164_vbi_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- struct saa7164_dev *dev = port->dev;
-
- f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
- f->fmt.pix.bytesperline = 0;
- f->fmt.pix.sizeimage =
- port->ts_packet_size * port->ts_packet_count;
- f->fmt.pix.colorspace = 0;
- f->fmt.pix.width = port->width;
- f->fmt.pix.height = port->height;
-
- dprintk(DBGLVL_VBI, "VIDIOC_G_FMT: w: %d, h: %d\n",
- port->width, port->height);
-
- return 0;
-}
-
-static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct saa7164_vbi_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- struct saa7164_dev *dev = port->dev;
-
- f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
- f->fmt.pix.bytesperline = 0;
- f->fmt.pix.sizeimage =
- port->ts_packet_size * port->ts_packet_count;
- f->fmt.pix.colorspace = 0;
- dprintk(DBGLVL_VBI, "VIDIOC_TRY_FMT: w: %d, h: %d\n",
- port->width, port->height);
- return 0;
-}
-
-static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct saa7164_vbi_fh *fh = file->private_data;
- struct saa7164_port *port = fh->port;
- struct saa7164_dev *dev = port->dev;
-
- f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
- f->fmt.pix.bytesperline = 0;
- f->fmt.pix.sizeimage =
- port->ts_packet_size * port->ts_packet_count;
- f->fmt.pix.colorspace = 0;
-
- dprintk(DBGLVL_VBI, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
- f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
-
- return 0;
-}
-
-static int fill_queryctrl(struct saa7164_vbi_params *params,
- struct v4l2_queryctrl *c)
-{
- switch (c->id) {
- case V4L2_CID_BRIGHTNESS:
- return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 127);
- case V4L2_CID_CONTRAST:
- return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 66);
- case V4L2_CID_SATURATION:
- return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 62);
- case V4L2_CID_HUE:
- return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 128);
- case V4L2_CID_SHARPNESS:
- return v4l2_ctrl_query_fill(c, 0x0, 0x0f, 1, 8);
- case V4L2_CID_MPEG_AUDIO_MUTE:
- return v4l2_ctrl_query_fill(c, 0x0, 0x01, 1, 0);
- case V4L2_CID_AUDIO_VOLUME:
- return v4l2_ctrl_query_fill(c, -83, 24, 1, 20);
- case V4L2_CID_MPEG_STREAM_TYPE:
- return v4l2_ctrl_query_fill(c,
- V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
- V4L2_MPEG_STREAM_TYPE_MPEG2_TS,
- 1, V4L2_MPEG_STREAM_TYPE_MPEG2_PS);
- case V4L2_CID_MPEG_VIDEO_ASPECT:
- return v4l2_ctrl_query_fill(c,
- V4L2_MPEG_VIDEO_ASPECT_1x1,
- V4L2_MPEG_VIDEO_ASPECT_221x100,
- 1, V4L2_MPEG_VIDEO_ASPECT_4x3);
- case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
- return v4l2_ctrl_query_fill(c, 1, 255, 1, 15);
- case V4L2_CID_MPEG_VIDEO_B_FRAMES:
- return v4l2_ctrl_query_fill(c,
- 1, 3, 1, 1);
- default:
- return -EINVAL;
- }
-}
-
-static int vidioc_queryctrl(struct file *file, void *priv,
- struct v4l2_queryctrl *c)
-{
- struct saa7164_vbi_fh *fh = priv;
- struct saa7164_port *port = fh->port;
- int i, next;
- u32 id = c->id;
-
- memset(c, 0, sizeof(*c));
-
- next = !!(id & V4L2_CTRL_FLAG_NEXT_CTRL);
- c->id = id & ~V4L2_CTRL_FLAG_NEXT_CTRL;
-
- for (i = 0; i < ARRAY_SIZE(saa7164_v4l2_ctrls); i++) {
- if (next) {
- if (c->id < saa7164_v4l2_ctrls[i])
- c->id = saa7164_v4l2_ctrls[i];
- else
- continue;
- }
-
- if (c->id == saa7164_v4l2_ctrls[i])
- return fill_queryctrl(&port->vbi_params, c);
-
- if (c->id < saa7164_v4l2_ctrls[i])
- break;
- }
-
- return -EINVAL;
-}
-
static int saa7164_vbi_stop_port(struct saa7164_port *port)
{
struct saa7164_dev *dev = port->dev;
@@ -999,7 +419,6 @@ static int saa7164_vbi_fmt(struct file *file, void *priv,
struct v4l2_format *f)
{
/* ntsc */
- f->fmt.vbi.samples_per_line = 1600;
f->fmt.vbi.samples_per_line = 1440;
f->fmt.vbi.sampling_rate = 27000000;
f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
@@ -1009,6 +428,7 @@ static int saa7164_vbi_fmt(struct file *file, void *priv,
f->fmt.vbi.count[0] = 18;
f->fmt.vbi.start[1] = 263 + 10 + 1;
f->fmt.vbi.count[1] = 18;
+ memset(f->fmt.vbi.reserved, 0, sizeof(f->fmt.vbi.reserved));
return 0;
}
@@ -1031,8 +451,10 @@ static int fops_open(struct file *file)
if (NULL == fh)
return -ENOMEM;
- file->private_data = fh;
fh->port = port;
+ v4l2_fh_init(&fh->fh, video_devdata(file));
+ v4l2_fh_add(&fh->fh);
+ file->private_data = fh;
return 0;
}
@@ -1053,7 +475,8 @@ static int fops_release(struct file *file)
}
}
- file->private_data = NULL;
+ v4l2_fh_del(&fh->fh);
+ v4l2_fh_exit(&fh->fh);
kfree(fh);
return 0;
@@ -1248,24 +671,14 @@ static const struct v4l2_file_operations vbi_fops = {
static const struct v4l2_ioctl_ops vbi_ioctl_ops = {
.vidioc_s_std = vidioc_s_std,
.vidioc_g_std = vidioc_g_std,
- .vidioc_enum_input = vidioc_enum_input,
+ .vidioc_enum_input = saa7164_enum_input,
.vidioc_g_input = vidioc_g_input,
.vidioc_s_input = vidioc_s_input,
- .vidioc_g_tuner = vidioc_g_tuner,
- .vidioc_s_tuner = vidioc_s_tuner,
+ .vidioc_g_tuner = saa7164_g_tuner,
+ .vidioc_s_tuner = saa7164_s_tuner,
.vidioc_g_frequency = vidioc_g_frequency,
.vidioc_s_frequency = vidioc_s_frequency,
- .vidioc_s_ctrl = vidioc_s_ctrl,
- .vidioc_g_ctrl = vidioc_g_ctrl,
.vidioc_querycap = vidioc_querycap,
- .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
- .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
- .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
- .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
- .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls,
- .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls,
- .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls,
- .vidioc_queryctrl = vidioc_queryctrl,
.vidioc_g_fmt_vbi_cap = saa7164_vbi_fmt,
.vidioc_try_fmt_vbi_cap = saa7164_vbi_fmt,
.vidioc_s_fmt_vbi_cap = saa7164_vbi_fmt,
@@ -1335,7 +748,7 @@ int saa7164_vbi_register(struct saa7164_port *port)
goto failed;
}
- port->std = V4L2_STD_NTSC_M;
+ port->enc_port = &dev->ports[port->nr - 2];
video_set_drvdata(port->v4l_device, port);
result = video_register_device(port->v4l_device,
VFL_TYPE_VBI, -1);
diff --git a/kernel/drivers/media/pci/saa7164/saa7164.h b/kernel/drivers/media/pci/saa7164/saa7164.h
index cd1a07ce2..8337524bf 100644
--- a/kernel/drivers/media/pci/saa7164/saa7164.h
+++ b/kernel/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
@@ -54,8 +54,6 @@
#include <media/tuner.h>
#include <media/tveeprom.h>
-#include <media/videobuf-dma-sg.h>
-#include <media/videobuf-dvb.h>
#include <dvb_demux.h>
#include <dvb_frontend.h>
#include <dvb_net.h>
@@ -64,6 +62,8 @@
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
#include "saa7164-reg.h"
#include "saa7164-types.h"
@@ -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
@@ -114,7 +117,11 @@
#define DBGLVL_CPU 8192
#define SAA7164_NORMS \
- (V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP | V4L2_STD_NTSC_443)
+ (V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP)
+
+/* TV frequency range copied from tuner-core.c */
+#define SAA7164_TV_MIN_FREQ (44U * 16U)
+#define SAA7164_TV_MAX_FREQ (958U * 16U)
enum port_t {
SAA7164_MPEG_UNDEFINED = 0,
@@ -182,11 +189,13 @@ struct saa7164_subid {
};
struct saa7164_encoder_fh {
+ struct v4l2_fh fh;
struct saa7164_port *port;
atomic_t v4l_reading;
};
struct saa7164_vbi_fh {
+ struct v4l2_fh fh;
struct saa7164_port *port;
atomic_t v4l_reading;
};
@@ -371,17 +380,18 @@ 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 */
/* Defaults established in saa7164-encoder.c */
struct saa7164_tvnorm encodernorm;
+ struct v4l2_ctrl_handler ctrl_handler;
v4l2_std_id std;
u32 height;
u32 width;
u32 freq;
- u32 ts_packet_size;
- u32 ts_packet_count;
u8 mux_input;
u8 encoder_profile;
u8 video_format;
@@ -414,6 +424,7 @@ struct saa7164_port {
/* V4L VBI */
struct tmComResVBIFormatDescrHeader vbi_fmt_ntsc;
struct saa7164_vbi_params vbi_params;
+ struct saa7164_port *enc_port;
/* Debug */
u32 sync_errors;
@@ -459,6 +470,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;
@@ -588,6 +600,16 @@ extern int saa7164_buffer_zero_offsets(struct saa7164_port *port, int i);
/* ----------------------------------------------------------- */
/* saa7164-encoder.c */
+int saa7164_s_std(struct saa7164_port *port, v4l2_std_id id);
+int saa7164_g_std(struct saa7164_port *port, v4l2_std_id *id);
+int saa7164_enum_input(struct file *file, void *priv, struct v4l2_input *i);
+int saa7164_g_input(struct saa7164_port *port, unsigned int *i);
+int saa7164_s_input(struct saa7164_port *port, unsigned int i);
+int saa7164_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t);
+int saa7164_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *t);
+int saa7164_g_frequency(struct saa7164_port *port, struct v4l2_frequency *f);
+int saa7164_s_frequency(struct saa7164_port *port,
+ const struct v4l2_frequency *f);
int saa7164_encoder_register(struct saa7164_port *port);
void saa7164_encoder_unregister(struct saa7164_port *port);
diff --git a/kernel/drivers/media/pci/smipcie/Kconfig b/kernel/drivers/media/pci/smipcie/Kconfig
index 21a1583db..c11c77283 100644
--- a/kernel/drivers/media/pci/smipcie/Kconfig
+++ b/kernel/drivers/media/pci/smipcie/Kconfig
@@ -7,6 +7,7 @@ config DVB_SMIPCIE
select DVB_TS2020 if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_M88RS6000T if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT
+ depends on RC_CORE
help
Support for cards with SMI PCIe bridge:
- DVBSky S950 V3
diff --git a/kernel/drivers/media/pci/smipcie/Makefile b/kernel/drivers/media/pci/smipcie/Makefile
index be55481a6..013bc3fe4 100644
--- a/kernel/drivers/media/pci/smipcie/Makefile
+++ b/kernel/drivers/media/pci/smipcie/Makefile
@@ -1,3 +1,6 @@
+
+smipcie-objs := smipcie-main.o smipcie-ir.o
+
obj-$(CONFIG_DVB_SMIPCIE) += smipcie.o
ccflags-y += -Idrivers/media/tuners
diff --git a/kernel/drivers/media/pci/smipcie/smipcie-ir.c b/kernel/drivers/media/pci/smipcie/smipcie-ir.c
new file mode 100644
index 000000000..d018673c7
--- /dev/null
+++ b/kernel/drivers/media/pci/smipcie/smipcie-ir.c
@@ -0,0 +1,232 @@
+/*
+ * SMI PCIe driver for DVBSky cards.
+ *
+ * Copyright (C) 2014 Max nibble <nibble.max@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.
+ */
+
+#include "smipcie.h"
+
+static void smi_ir_enableInterrupt(struct smi_rc *ir)
+{
+ struct smi_dev *dev = ir->dev;
+
+ smi_write(MSI_INT_ENA_SET, IR_X_INT);
+}
+
+static void smi_ir_disableInterrupt(struct smi_rc *ir)
+{
+ struct smi_dev *dev = ir->dev;
+
+ smi_write(MSI_INT_ENA_CLR, IR_X_INT);
+}
+
+static void smi_ir_clearInterrupt(struct smi_rc *ir)
+{
+ struct smi_dev *dev = ir->dev;
+
+ smi_write(MSI_INT_STATUS_CLR, IR_X_INT);
+}
+
+static void smi_ir_stop(struct smi_rc *ir)
+{
+ struct smi_dev *dev = ir->dev;
+
+ smi_ir_disableInterrupt(ir);
+ smi_clear(IR_Init_Reg, 0x80);
+}
+
+#define BITS_PER_COMMAND 14
+#define GROUPS_PER_BIT 2
+#define IR_RC5_MIN_BIT 36
+#define IR_RC5_MAX_BIT 52
+static u32 smi_decode_rc5(u8 *pData, u8 size)
+{
+ u8 index, current_bit, bit_count;
+ u8 group_array[BITS_PER_COMMAND * GROUPS_PER_BIT + 4];
+ u8 group_index = 0;
+ u32 command = 0xFFFFFFFF;
+
+ group_array[group_index++] = 1;
+
+ for (index = 0; index < size; index++) {
+
+ current_bit = (pData[index] & 0x80) ? 1 : 0;
+ bit_count = pData[index] & 0x7f;
+
+ if ((current_bit == 1) && (bit_count >= 2*IR_RC5_MAX_BIT + 1)) {
+ goto process_code;
+ } else if ((bit_count >= IR_RC5_MIN_BIT) &&
+ (bit_count <= IR_RC5_MAX_BIT)) {
+ group_array[group_index++] = current_bit;
+ } else if ((bit_count > IR_RC5_MAX_BIT) &&
+ (bit_count <= 2*IR_RC5_MAX_BIT)) {
+ group_array[group_index++] = current_bit;
+ group_array[group_index++] = current_bit;
+ } else {
+ goto invalid_timing;
+ }
+ if (group_index >= BITS_PER_COMMAND*GROUPS_PER_BIT)
+ goto process_code;
+
+ if ((group_index == BITS_PER_COMMAND*GROUPS_PER_BIT - 1)
+ && (group_array[group_index-1] == 0)) {
+ group_array[group_index++] = 1;
+ goto process_code;
+ }
+ }
+
+process_code:
+ if (group_index == (BITS_PER_COMMAND*GROUPS_PER_BIT-1))
+ group_array[group_index++] = 1;
+
+ if (group_index == BITS_PER_COMMAND*GROUPS_PER_BIT) {
+ command = 0;
+ for (index = 0; index < (BITS_PER_COMMAND*GROUPS_PER_BIT);
+ index = index + 2) {
+ if ((group_array[index] == 1) &&
+ (group_array[index+1] == 0)) {
+ command |= (1 << (BITS_PER_COMMAND -
+ (index/2) - 1));
+ } else if ((group_array[index] == 0) &&
+ (group_array[index+1] == 1)) {
+ /* */
+ } else {
+ command = 0xFFFFFFFF;
+ goto invalid_timing;
+ }
+ }
+ }
+
+invalid_timing:
+ return command;
+}
+
+static void smi_ir_decode(struct work_struct *work)
+{
+ struct smi_rc *ir = container_of(work, struct smi_rc, work);
+ struct smi_dev *dev = ir->dev;
+ struct rc_dev *rc_dev = ir->rc_dev;
+ u32 dwIRControl, dwIRData, dwIRCode, scancode;
+ u8 index, ucIRCount, readLoop, rc5_command, rc5_system, toggle;
+
+ dwIRControl = smi_read(IR_Init_Reg);
+ if (dwIRControl & rbIRVld) {
+ ucIRCount = (u8) smi_read(IR_Data_Cnt);
+
+ if (ucIRCount < 4)
+ goto end_ir_decode;
+
+ readLoop = ucIRCount/4;
+ if (ucIRCount % 4)
+ readLoop += 1;
+ for (index = 0; index < readLoop; index++) {
+ dwIRData = smi_read(IR_DATA_BUFFER_BASE + (index*4));
+
+ ir->irData[index*4 + 0] = (u8)(dwIRData);
+ ir->irData[index*4 + 1] = (u8)(dwIRData >> 8);
+ ir->irData[index*4 + 2] = (u8)(dwIRData >> 16);
+ ir->irData[index*4 + 3] = (u8)(dwIRData >> 24);
+ }
+ dwIRCode = smi_decode_rc5(ir->irData, ucIRCount);
+
+ if (dwIRCode != 0xFFFFFFFF) {
+ rc5_command = dwIRCode & 0x3F;
+ rc5_system = (dwIRCode & 0x7C0) >> 6;
+ toggle = (dwIRCode & 0x800) ? 1 : 0;
+ scancode = rc5_system << 8 | rc5_command;
+ rc_keydown(rc_dev, RC_TYPE_RC5, scancode, toggle);
+ }
+ }
+end_ir_decode:
+ smi_set(IR_Init_Reg, 0x04);
+ smi_ir_enableInterrupt(ir);
+}
+
+/* ir functions call by main driver.*/
+int smi_ir_irq(struct smi_rc *ir, u32 int_status)
+{
+ int handled = 0;
+
+ if (int_status & IR_X_INT) {
+ smi_ir_disableInterrupt(ir);
+ smi_ir_clearInterrupt(ir);
+ schedule_work(&ir->work);
+ handled = 1;
+ }
+ return handled;
+}
+
+void smi_ir_start(struct smi_rc *ir)
+{
+ struct smi_dev *dev = ir->dev;
+
+ smi_write(IR_Idle_Cnt_Low, 0x00140070);
+ msleep(20);
+ smi_set(IR_Init_Reg, 0x90);
+
+ smi_ir_enableInterrupt(ir);
+}
+
+int smi_ir_init(struct smi_dev *dev)
+{
+ int ret;
+ struct rc_dev *rc_dev;
+ struct smi_rc *ir = &dev->ir;
+
+ rc_dev = rc_allocate_device();
+ if (!rc_dev)
+ return -ENOMEM;
+
+ /* init input device */
+ snprintf(ir->input_name, sizeof(ir->input_name), "IR (%s)",
+ dev->info->name);
+ snprintf(ir->input_phys, sizeof(ir->input_phys), "pci-%s/ir0",
+ pci_name(dev->pci_dev));
+
+ rc_dev->driver_name = "SMI_PCIe";
+ rc_dev->input_phys = ir->input_phys;
+ rc_dev->input_name = ir->input_name;
+ rc_dev->input_id.bustype = BUS_PCI;
+ rc_dev->input_id.version = 1;
+ rc_dev->input_id.vendor = dev->pci_dev->subsystem_vendor;
+ rc_dev->input_id.product = dev->pci_dev->subsystem_device;
+ rc_dev->dev.parent = &dev->pci_dev->dev;
+
+ rc_dev->driver_type = RC_DRIVER_SCANCODE;
+ rc_dev->map_name = RC_MAP_DVBSKY;
+
+ ir->rc_dev = rc_dev;
+ ir->dev = dev;
+
+ INIT_WORK(&ir->work, smi_ir_decode);
+ smi_ir_disableInterrupt(ir);
+
+ ret = rc_register_device(rc_dev);
+ if (ret)
+ goto ir_err;
+
+ return 0;
+ir_err:
+ rc_free_device(rc_dev);
+ return ret;
+}
+
+void smi_ir_exit(struct smi_dev *dev)
+{
+ struct smi_rc *ir = &dev->ir;
+ struct rc_dev *rc_dev = ir->rc_dev;
+
+ smi_ir_stop(ir);
+ rc_unregister_device(rc_dev);
+ ir->rc_dev = NULL;
+}
diff --git a/kernel/drivers/media/pci/smipcie/smipcie.c b/kernel/drivers/media/pci/smipcie/smipcie-main.c
index 411592524..b039a229b 100644
--- a/kernel/drivers/media/pci/smipcie/smipcie.c
+++ b/kernel/drivers/media/pci/smipcie/smipcie-main.c
@@ -468,6 +468,7 @@ static irqreturn_t smi_irq_handler(int irq, void *dev_id)
struct smi_dev *dev = dev_id;
struct smi_port *port0 = &dev->ts_port[0];
struct smi_port *port1 = &dev->ts_port[1];
+ struct smi_rc *ir = &dev->ir;
int handled = 0;
u32 intr_status = smi_read(MSI_INT_STATUS);
@@ -480,6 +481,9 @@ static irqreturn_t smi_irq_handler(int irq, void *dev_id)
if (dev->info->ts_1)
handled += smi_port_irq(port1, intr_status);
+ /* ir interrupt.*/
+ handled += smi_ir_irq(ir, intr_status);
+
return IRQ_RETVAL(handled);
}
@@ -657,6 +661,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);
@@ -992,6 +997,10 @@ static int smi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto err_del_port0_attach;
}
+ ret = smi_ir_init(dev);
+ if (ret < 0)
+ goto err_del_port1_attach;
+
#ifdef CONFIG_PCI_MSI /* to do msi interrupt.???*/
if (pci_msi_enabled())
ret = pci_enable_msi(dev->pci_dev);
@@ -1002,10 +1011,13 @@ static int smi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
ret = request_irq(dev->pci_dev->irq, smi_irq_handler,
IRQF_SHARED, "SMI_PCIE", dev);
if (ret < 0)
- goto err_del_port1_attach;
+ goto err_del_ir;
+ smi_ir_start(&dev->ir);
return 0;
+err_del_ir:
+ smi_ir_exit(dev);
err_del_port1_attach:
if (dev->info->ts_1)
smi_port_detach(&dev->ts_port[1]);
@@ -1038,6 +1050,7 @@ static void smi_remove(struct pci_dev *pdev)
if (dev->info->ts_0)
smi_port_detach(&dev->ts_port[0]);
+ smi_ir_exit(dev);
smi_i2c_exit(dev);
iounmap(dev->lmmio);
pci_set_drvdata(pdev, NULL);
diff --git a/kernel/drivers/media/pci/smipcie/smipcie.h b/kernel/drivers/media/pci/smipcie/smipcie.h
index 10cdf20f4..68cdda28f 100644
--- a/kernel/drivers/media/pci/smipcie/smipcie.h
+++ b/kernel/drivers/media/pci/smipcie/smipcie.h
@@ -234,6 +234,17 @@ struct smi_cfg_info {
int fe_1;
};
+struct smi_rc {
+ struct smi_dev *dev;
+ struct rc_dev *rc_dev;
+ char input_phys[64];
+ char input_name[64];
+ struct work_struct work;
+ u8 irData[256];
+
+ int users;
+};
+
struct smi_port {
struct smi_dev *dev;
int idx;
@@ -284,6 +295,9 @@ struct smi_dev {
/* i2c */
struct i2c_adapter i2c_bus[2];
struct i2c_algo_bit_data i2c_bit[2];
+
+ /* ir */
+ struct smi_rc ir;
};
#define smi_read(reg) readl(dev->lmmio + ((reg)>>2))
@@ -296,4 +310,9 @@ struct smi_dev {
#define smi_set(reg, bit) smi_andor((reg), (bit), (bit))
#define smi_clear(reg, bit) smi_andor((reg), (bit), 0)
+int smi_ir_irq(struct smi_rc *ir, u32 int_status);
+void smi_ir_start(struct smi_rc *ir);
+void smi_ir_exit(struct smi_dev *dev);
+int smi_ir_init(struct smi_dev *dev);
+
#endif /* #ifndef _SMI_PCIE_H_ */
diff --git a/kernel/drivers/media/pci/solo6x10/solo6x10-core.c b/kernel/drivers/media/pci/solo6x10/solo6x10-core.c
index 570d119ea..f50d07229 100644
--- a/kernel/drivers/media/pci/solo6x10/solo6x10-core.c
+++ b/kernel/drivers/media/pci/solo6x10/solo6x10-core.c
@@ -134,23 +134,11 @@ static irqreturn_t solo_isr(int irq, void *data)
static void free_solo_dev(struct solo_dev *solo_dev)
{
- struct pci_dev *pdev;
-
- if (!solo_dev)
- return;
+ struct pci_dev *pdev = solo_dev->pdev;
if (solo_dev->dev.parent)
device_unregister(&solo_dev->dev);
- pdev = solo_dev->pdev;
-
- /* If we never initialized the PCI device, then nothing else
- * below here needs cleanup */
- if (!pdev) {
- kfree(solo_dev);
- return;
- }
-
if (solo_dev->reg_base) {
/* Bring down the sub-devices first */
solo_g723_exit(solo_dev);
@@ -164,9 +152,8 @@ static void free_solo_dev(struct solo_dev *solo_dev)
/* Now cleanup the PCI device */
solo_irq_off(solo_dev, ~0);
+ free_irq(pdev->irq, solo_dev);
pci_iounmap(pdev, solo_dev->reg_base);
- if (pdev->irq)
- free_irq(pdev->irq, solo_dev);
}
pci_release_regions(pdev);
@@ -483,7 +470,6 @@ static int solo_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
solo_dev->type = id->driver_data;
solo_dev->pdev = pdev;
- spin_lock_init(&solo_dev->reg_io_lock);
ret = v4l2_device_register(&pdev->dev, &solo_dev->v4l2_dev);
if (ret)
goto fail_probe;
diff --git a/kernel/drivers/media/pci/solo6x10/solo6x10-g723.c b/kernel/drivers/media/pci/solo6x10/solo6x10-g723.c
index 7ddc76709..4a37a1c51 100644
--- a/kernel/drivers/media/pci/solo6x10/solo6x10-g723.c
+++ b/kernel/drivers/media/pci/solo6x10/solo6x10-g723.c
@@ -48,10 +48,8 @@
/* The solo writes to 1k byte pages, 32 pages, in the dma. Each 1k page
* is broken down to 20 * 48 byte regions (one for each channel possible)
* with the rest of the page being dummy data. */
-#define G723_MAX_BUFFER (G723_PERIOD_BYTES * PERIODS_MAX)
+#define PERIODS G723_FDMA_PAGES
#define G723_INTR_ORDER 4 /* 0 - 4 */
-#define PERIODS_MIN (1 << G723_INTR_ORDER)
-#define PERIODS_MAX G723_FDMA_PAGES
struct solo_snd_pcm {
int on;
@@ -130,11 +128,11 @@ static const struct snd_pcm_hardware snd_solo_pcm_hw = {
.rate_max = SAMPLERATE,
.channels_min = 1,
.channels_max = 1,
- .buffer_bytes_max = G723_MAX_BUFFER,
+ .buffer_bytes_max = G723_PERIOD_BYTES * PERIODS,
.period_bytes_min = G723_PERIOD_BYTES,
.period_bytes_max = G723_PERIOD_BYTES,
- .periods_min = PERIODS_MIN,
- .periods_max = PERIODS_MAX,
+ .periods_min = PERIODS,
+ .periods_max = PERIODS,
};
static int snd_solo_pcm_open(struct snd_pcm_substream *ss)
@@ -340,7 +338,8 @@ static int solo_snd_pcm_init(struct solo_dev *solo_dev)
ret = snd_pcm_lib_preallocate_pages_for_all(pcm,
SNDRV_DMA_TYPE_CONTINUOUS,
snd_dma_continuous_data(GFP_KERNEL),
- G723_MAX_BUFFER, G723_MAX_BUFFER);
+ G723_PERIOD_BYTES * PERIODS,
+ G723_PERIOD_BYTES * PERIODS);
if (ret < 0)
return ret;
diff --git a/kernel/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c b/kernel/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
index 53fff5425..4432fd69b 100644
--- a/kernel/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
+++ b/kernel/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
@@ -458,11 +458,12 @@ static inline u32 vop_usec(const vop_header *vh)
static int solo_fill_jpeg(struct solo_enc_dev *solo_enc,
struct vb2_buffer *vb, const vop_header *vh)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct solo_dev *solo_dev = solo_enc->solo_dev;
- struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0);
+ struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
int frame_size;
- vb->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
+ vbuf->flags |= V4L2_BUF_FLAG_KEYFRAME;
if (vb2_plane_size(vb, 0) < vop_jpeg_size(vh) + solo_enc->jpeg_len)
return -EIO;
@@ -470,7 +471,7 @@ static int solo_fill_jpeg(struct solo_enc_dev *solo_enc,
frame_size = ALIGN(vop_jpeg_size(vh) + solo_enc->jpeg_len, DMA_ALIGN);
vb2_set_plane_payload(vb, 0, vop_jpeg_size(vh) + solo_enc->jpeg_len);
- return solo_send_desc(solo_enc, solo_enc->jpeg_len, vbuf,
+ return solo_send_desc(solo_enc, solo_enc->jpeg_len, sgt,
vop_jpeg_offset(vh) - SOLO_JPEG_EXT_ADDR(solo_dev),
frame_size, SOLO_JPEG_EXT_ADDR(solo_dev),
SOLO_JPEG_EXT_SIZE(solo_dev));
@@ -479,8 +480,9 @@ static int solo_fill_jpeg(struct solo_enc_dev *solo_enc,
static int solo_fill_mpeg(struct solo_enc_dev *solo_enc,
struct vb2_buffer *vb, const vop_header *vh)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct solo_dev *solo_dev = solo_enc->solo_dev;
- struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0);
+ struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
int frame_off, frame_size;
int skip = 0;
@@ -488,15 +490,15 @@ static int solo_fill_mpeg(struct solo_enc_dev *solo_enc,
return -EIO;
/* If this is a key frame, add extra header */
- vb->v4l2_buf.flags &= ~(V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_PFRAME |
+ vbuf->flags &= ~(V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_PFRAME |
V4L2_BUF_FLAG_BFRAME);
if (!vop_type(vh)) {
skip = solo_enc->vop_len;
- vb->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
+ vbuf->flags |= V4L2_BUF_FLAG_KEYFRAME;
vb2_set_plane_payload(vb, 0, vop_mpeg_size(vh) +
solo_enc->vop_len);
} else {
- vb->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME;
+ vbuf->flags |= V4L2_BUF_FLAG_PFRAME;
vb2_set_plane_payload(vb, 0, vop_mpeg_size(vh));
}
@@ -505,7 +507,7 @@ static int solo_fill_mpeg(struct solo_enc_dev *solo_enc,
sizeof(*vh)) % SOLO_MP4E_EXT_SIZE(solo_dev);
frame_size = ALIGN(vop_mpeg_size(vh) + skip, DMA_ALIGN);
- return solo_send_desc(solo_enc, skip, vbuf, frame_off, frame_size,
+ return solo_send_desc(solo_enc, skip, sgt, frame_off, frame_size,
SOLO_MP4E_EXT_ADDR(solo_dev),
SOLO_MP4E_EXT_SIZE(solo_dev));
}
@@ -513,6 +515,7 @@ static int solo_fill_mpeg(struct solo_enc_dev *solo_enc,
static int solo_enc_fillbuf(struct solo_enc_dev *solo_enc,
struct vb2_buffer *vb, struct solo_enc_buf *enc_buf)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
const vop_header *vh = enc_buf->vh;
int ret;
@@ -527,17 +530,18 @@ static int solo_enc_fillbuf(struct solo_enc_dev *solo_enc,
}
if (!ret) {
- vb->v4l2_buf.sequence = solo_enc->sequence++;
- vb->v4l2_buf.timestamp.tv_sec = vop_sec(vh);
- vb->v4l2_buf.timestamp.tv_usec = vop_usec(vh);
+ vbuf->sequence = solo_enc->sequence++;
+ vbuf->timestamp.tv_sec = vop_sec(vh);
+ vbuf->timestamp.tv_usec = vop_usec(vh);
/* Check for motion flags */
if (solo_is_motion_on(solo_enc) && enc_buf->motion) {
struct v4l2_event ev = {
.type = V4L2_EVENT_MOTION_DET,
.u.motion_det = {
- .flags = V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ,
- .frame_sequence = vb->v4l2_buf.sequence,
+ .flags
+ = V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ,
+ .frame_sequence = vbuf->sequence,
.region_mask = enc_buf->motion ? 1 : 0,
},
};
@@ -571,7 +575,7 @@ static void solo_enc_handle_one(struct solo_enc_dev *solo_enc,
list_del(&vb->list);
spin_unlock_irqrestore(&solo_enc->av_lock, flags);
- solo_enc_fillbuf(solo_enc, &vb->vb, enc_buf);
+ solo_enc_fillbuf(solo_enc, &vb->vb.vb2_buf, enc_buf);
unlock:
mutex_unlock(&solo_enc->lock);
}
@@ -659,7 +663,7 @@ static int solo_ring_thread(void *data)
}
static int solo_enc_queue_setup(struct vb2_queue *q,
- const struct v4l2_format *fmt,
+ const void *parg,
unsigned int *num_buffers,
unsigned int *num_planes, unsigned int sizes[],
void *alloc_ctxs[])
@@ -678,10 +682,11 @@ static int solo_enc_queue_setup(struct vb2_queue *q,
static void solo_enc_buf_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct vb2_queue *vq = vb->vb2_queue;
struct solo_enc_dev *solo_enc = vb2_get_drv_priv(vq);
struct solo_vb2_buf *solo_vb =
- container_of(vb, struct solo_vb2_buf, vb);
+ container_of(vbuf, struct solo_vb2_buf, vb);
spin_lock(&solo_enc->av_lock);
list_add_tail(&solo_vb->list, &solo_enc->vidq_active);
@@ -734,25 +739,26 @@ static void solo_enc_stop_streaming(struct vb2_queue *q)
struct solo_vb2_buf, list);
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&solo_enc->av_lock, flags);
}
static void solo_enc_buf_finish(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct solo_enc_dev *solo_enc = vb2_get_drv_priv(vb->vb2_queue);
- struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0);
+ struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
switch (solo_enc->fmt) {
case V4L2_PIX_FMT_MPEG4:
case V4L2_PIX_FMT_H264:
- if (vb->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME)
- sg_copy_from_buffer(vbuf->sgl, vbuf->nents,
+ if (vbuf->flags & V4L2_BUF_FLAG_KEYFRAME)
+ sg_copy_from_buffer(sgt->sgl, sgt->nents,
solo_enc->vop, solo_enc->vop_len);
break;
default: /* V4L2_PIX_FMT_MJPEG */
- sg_copy_from_buffer(vbuf->sgl, vbuf->nents,
+ sg_copy_from_buffer(sgt->sgl, sgt->nents,
solo_enc->jpeg_header, solo_enc->jpeg_len);
break;
}
@@ -1291,7 +1297,7 @@ static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev,
solo_enc->vidq.ops = &solo_enc_video_qops;
solo_enc->vidq.mem_ops = &vb2_dma_sg_memops;
solo_enc->vidq.drv_priv = solo_enc;
- solo_enc->vidq.gfp_flags = __GFP_DMA32;
+ solo_enc->vidq.gfp_flags = __GFP_DMA32 | __GFP_KSWAPD_RECLAIM;
solo_enc->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
solo_enc->vidq.buf_struct_size = sizeof(struct solo_vb2_buf);
solo_enc->vidq.lock = &solo_enc->lock;
diff --git a/kernel/drivers/media/pci/solo6x10/solo6x10-v4l2.c b/kernel/drivers/media/pci/solo6x10/solo6x10-v4l2.c
index 63ae8a61f..f7ce493b1 100644
--- a/kernel/drivers/media/pci/solo6x10/solo6x10-v4l2.c
+++ b/kernel/drivers/media/pci/solo6x10/solo6x10-v4l2.c
@@ -26,6 +26,7 @@
#include <media/v4l2-ioctl.h>
#include <media/v4l2-common.h>
#include <media/v4l2-event.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-dma-contig.h>
#include "solo6x10.h"
@@ -191,13 +192,14 @@ static int solo_v4l2_set_ch(struct solo_dev *solo_dev, u8 ch)
static void solo_fillbuf(struct solo_dev *solo_dev,
struct vb2_buffer *vb)
{
- dma_addr_t vbuf;
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ dma_addr_t addr;
unsigned int fdma_addr;
int error = -1;
int i;
- vbuf = vb2_dma_contig_plane_dma_addr(vb, 0);
- if (!vbuf)
+ addr = vb2_dma_contig_plane_dma_addr(vb, 0);
+ if (!addr)
goto finish_buf;
if (erase_off(solo_dev)) {
@@ -213,7 +215,7 @@ static void solo_fillbuf(struct solo_dev *solo_dev,
fdma_addr = SOLO_DISP_EXT_ADDR + (solo_dev->old_write *
(SOLO_HW_BPL * solo_vlines(solo_dev)));
- error = solo_p2m_dma_t(solo_dev, 0, vbuf, fdma_addr,
+ error = solo_p2m_dma_t(solo_dev, 0, addr, fdma_addr,
solo_bytesperline(solo_dev),
solo_vlines(solo_dev), SOLO_HW_BPL);
}
@@ -222,8 +224,8 @@ finish_buf:
if (!error) {
vb2_set_plane_payload(vb, 0,
solo_vlines(solo_dev) * solo_bytesperline(solo_dev));
- vb->v4l2_buf.sequence = solo_dev->sequence++;
- v4l2_get_timestamp(&vb->v4l2_buf.timestamp);
+ vbuf->sequence = solo_dev->sequence++;
+ v4l2_get_timestamp(&vbuf->timestamp);
}
vb2_buffer_done(vb, error ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
@@ -256,7 +258,7 @@ static void solo_thread_try(struct solo_dev *solo_dev)
spin_unlock(&solo_dev->slock);
- solo_fillbuf(solo_dev, &vb->vb);
+ solo_fillbuf(solo_dev, &vb->vb.vb2_buf);
}
assert_spin_locked(&solo_dev->slock);
@@ -311,7 +313,7 @@ static void solo_stop_thread(struct solo_dev *solo_dev)
solo_dev->kthread = NULL;
}
-static int solo_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int solo_queue_setup(struct vb2_queue *q, const void *parg,
unsigned int *num_buffers, unsigned int *num_planes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -345,10 +347,11 @@ static void solo_stop_streaming(struct vb2_queue *q)
static void solo_buf_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct vb2_queue *vq = vb->vb2_queue;
struct solo_dev *solo_dev = vb2_get_drv_priv(vq);
struct solo_vb2_buf *solo_vb =
- container_of(vb, struct solo_vb2_buf, vb);
+ container_of(vbuf, struct solo_vb2_buf, vb);
spin_lock(&solo_dev->slock);
list_add_tail(&solo_vb->list, &solo_dev->vidq_active);
@@ -675,7 +678,7 @@ int solo_v4l2_init(struct solo_dev *solo_dev, unsigned nr)
solo_dev->vidq.mem_ops = &vb2_dma_contig_memops;
solo_dev->vidq.drv_priv = solo_dev;
solo_dev->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
- solo_dev->vidq.gfp_flags = __GFP_DMA32;
+ solo_dev->vidq.gfp_flags = __GFP_DMA32 | __GFP_KSWAPD_RECLAIM;
solo_dev->vidq.buf_struct_size = sizeof(struct solo_vb2_buf);
solo_dev->vidq.lock = &solo_dev->lock;
ret = vb2_queue_init(&solo_dev->vidq);
diff --git a/kernel/drivers/media/pci/solo6x10/solo6x10.h b/kernel/drivers/media/pci/solo6x10/solo6x10.h
index 1ca54b08b..4ab6586c0 100644
--- a/kernel/drivers/media/pci/solo6x10/solo6x10.h
+++ b/kernel/drivers/media/pci/solo6x10/solo6x10.h
@@ -35,7 +35,7 @@
#include <media/v4l2-dev.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ctrls.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
#include "solo6x10-regs.h"
@@ -135,7 +135,7 @@ struct solo_p2m_dev {
#define OSD_TEXT_MAX 44
struct solo_vb2_buf {
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct list_head list;
};
@@ -199,7 +199,6 @@ struct solo_dev {
int nr_ext;
u32 irq_mask;
u32 motion_mask;
- spinlock_t reg_io_lock;
struct v4l2_device v4l2_dev;
/* tw28xx accounting */
@@ -281,36 +280,13 @@ struct solo_dev {
static inline u32 solo_reg_read(struct solo_dev *solo_dev, int reg)
{
- unsigned long flags;
- u32 ret;
- u16 val;
-
- spin_lock_irqsave(&solo_dev->reg_io_lock, flags);
-
- ret = readl(solo_dev->reg_base + reg);
- rmb();
- pci_read_config_word(solo_dev->pdev, PCI_STATUS, &val);
- rmb();
-
- spin_unlock_irqrestore(&solo_dev->reg_io_lock, flags);
-
- return ret;
+ return readl(solo_dev->reg_base + reg);
}
static inline void solo_reg_write(struct solo_dev *solo_dev, int reg,
u32 data)
{
- unsigned long flags;
- u16 val;
-
- spin_lock_irqsave(&solo_dev->reg_io_lock, flags);
-
writel(data, solo_dev->reg_base + reg);
- wmb();
- pci_read_config_word(solo_dev->pdev, PCI_STATUS, &val);
- rmb();
-
- spin_unlock_irqrestore(&solo_dev->reg_io_lock, flags);
}
static inline void solo_irq_on(struct solo_dev *dev, u32 mask)
diff --git a/kernel/drivers/media/pci/sta2x11/sta2x11_vip.c b/kernel/drivers/media/pci/sta2x11/sta2x11_vip.c
index d384a6b0b..6367b455a 100644
--- a/kernel/drivers/media/pci/sta2x11/sta2x11_vip.c
+++ b/kernel/drivers/media/pci/sta2x11/sta2x11_vip.c
@@ -88,11 +88,11 @@
struct vip_buffer {
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct list_head list;
dma_addr_t dma;
};
-static inline struct vip_buffer *to_vip_buffer(struct vb2_buffer *vb2)
+static inline struct vip_buffer *to_vip_buffer(struct vb2_v4l2_buffer *vb2)
{
return container_of(vb2, struct vip_buffer, vb);
}
@@ -265,7 +265,7 @@ static void vip_active_buf_next(struct sta2x11_vip *vip)
/* Videobuf2 Operations */
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *vq, const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -287,7 +287,8 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
};
static int buffer_init(struct vb2_buffer *vb)
{
- struct vip_buffer *vip_buf = to_vip_buffer(vb);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct vip_buffer *vip_buf = to_vip_buffer(vbuf);
vip_buf->dma = vb2_dma_contig_plane_dma_addr(vb, 0);
INIT_LIST_HEAD(&vip_buf->list);
@@ -296,8 +297,9 @@ static int buffer_init(struct vb2_buffer *vb)
static int buffer_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct sta2x11_vip *vip = vb2_get_drv_priv(vb->vb2_queue);
- struct vip_buffer *vip_buf = to_vip_buffer(vb);
+ struct vip_buffer *vip_buf = to_vip_buffer(vbuf);
unsigned long size;
size = vip->format.sizeimage;
@@ -307,14 +309,15 @@ static int buffer_prepare(struct vb2_buffer *vb)
return -EINVAL;
}
- vb2_set_plane_payload(&vip_buf->vb, 0, size);
+ vb2_set_plane_payload(&vip_buf->vb.vb2_buf, 0, size);
return 0;
}
static void buffer_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct sta2x11_vip *vip = vb2_get_drv_priv(vb->vb2_queue);
- struct vip_buffer *vip_buf = to_vip_buffer(vb);
+ struct vip_buffer *vip_buf = to_vip_buffer(vbuf);
spin_lock(&vip->lock);
list_add_tail(&vip_buf->list, &vip->buffer_list);
@@ -329,8 +332,9 @@ static void buffer_queue(struct vb2_buffer *vb)
}
static void buffer_finish(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct sta2x11_vip *vip = vb2_get_drv_priv(vb->vb2_queue);
- struct vip_buffer *vip_buf = to_vip_buffer(vb);
+ struct vip_buffer *vip_buf = to_vip_buffer(vbuf);
/* Buffer handled, remove it from the list */
spin_lock(&vip->lock);
@@ -370,7 +374,7 @@ static void stop_streaming(struct vb2_queue *vq)
/* Release all active buffers */
spin_lock(&vip->lock);
list_for_each_entry_safe(vip_buf, node, &vip->buffer_list, list) {
- vb2_buffer_done(&vip_buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&vip_buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
list_del(&vip_buf->list);
}
spin_unlock(&vip->lock);
@@ -813,9 +817,9 @@ 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);
- vip->active->vb.v4l2_buf.sequence = vip->sequence++;
- vb2_buffer_done(&vip->active->vb, VB2_BUF_STATE_DONE);
+ v4l2_get_timestamp(&vip->active->vb.timestamp);
+ vip->active->vb.sequence = vip->sequence++;
+ vb2_buffer_done(&vip->active->vb.vb2_buf, VB2_BUF_STATE_DONE);
}
return IRQ_HANDLED;
@@ -864,6 +868,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/kernel/drivers/media/pci/ttpci/av7110.c b/kernel/drivers/media/pci/ttpci/av7110.c
index 45199a12b..f89364951 100644
--- a/kernel/drivers/media/pci/ttpci/av7110.c
+++ b/kernel/drivers/media/pci/ttpci/av7110.c
@@ -303,7 +303,6 @@ static int arm_thread(void *data)
static int DvbDmxFilterCallback(u8 *buffer1, size_t buffer1_len,
u8 *buffer2, size_t buffer2_len,
struct dvb_demux_filter *dvbdmxfilter,
- enum dmx_success success,
struct av7110 *av7110)
{
if (!dvbdmxfilter->feed->demux->dmx.frontend)
@@ -329,16 +328,14 @@ static int DvbDmxFilterCallback(u8 *buffer1, size_t buffer1_len,
}
return dvbdmxfilter->feed->cb.sec(buffer1, buffer1_len,
buffer2, buffer2_len,
- &dvbdmxfilter->filter,
- DMX_OK);
+ &dvbdmxfilter->filter);
case DMX_TYPE_TS:
if (!(dvbdmxfilter->feed->ts_type & TS_PACKET))
return 0;
if (dvbdmxfilter->feed->ts_type & TS_PAYLOAD_ONLY)
return dvbdmxfilter->feed->cb.ts(buffer1, buffer1_len,
buffer2, buffer2_len,
- &dvbdmxfilter->feed->feed.ts,
- DMX_OK);
+ &dvbdmxfilter->feed->feed.ts);
else
av7110_p2t_write(buffer1, buffer1_len,
dvbdmxfilter->feed->pid,
@@ -422,7 +419,7 @@ static void debiirq(unsigned long cookie)
DvbDmxFilterCallback((u8 *)av7110->debi_virt,
av7110->debilen, NULL, 0,
av7110->handle2filter[handle],
- DMX_OK, av7110);
+ av7110);
xfer = RX_BUFF;
break;
@@ -1172,7 +1169,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 +1194,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 +1943,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 +2005,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 +2041,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 +2054,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 +2067,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/kernel/drivers/media/pci/ttpci/av7110.h b/kernel/drivers/media/pci/ttpci/av7110.h
index 835635b0c..3a55927ed 100644
--- a/kernel/drivers/media/pci/ttpci/av7110.h
+++ b/kernel/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/kernel/drivers/media/pci/ttpci/av7110_av.c b/kernel/drivers/media/pci/ttpci/av7110_av.c
index 9544cfc06..9ed1ec7d3 100644
--- a/kernel/drivers/media/pci/ttpci/av7110_av.c
+++ b/kernel/drivers/media/pci/ttpci/av7110_av.c
@@ -102,7 +102,7 @@ int av7110_record_cb(struct dvb_filter_pes2ts *p2t, u8 *buf, size_t len)
buf[4] = buf[5] = 0;
if (dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY)
return dvbdmxfeed->cb.ts(buf, len, NULL, 0,
- &dvbdmxfeed->feed.ts, DMX_OK);
+ &dvbdmxfeed->feed.ts);
else
return dvb_filter_pes2ts(p2t, buf, len, 1);
}
@@ -112,7 +112,7 @@ static int dvb_filter_pes2ts_cb(void *priv, unsigned char *data)
struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) priv;
dvbdmxfeed->cb.ts(data, 188, NULL, 0,
- &dvbdmxfeed->feed.ts, DMX_OK);
+ &dvbdmxfeed->feed.ts);
return 0;
}
@@ -815,7 +815,7 @@ static void p_to_t(u8 const *buf, long int length, u16 pid, u8 *counter,
memcpy(obuf + l, buf + c, TS_SIZE - l);
c = length;
}
- feed->cb.ts(obuf, 188, NULL, 0, &feed->feed.ts, DMX_OK);
+ feed->cb.ts(obuf, 188, NULL, 0, &feed->feed.ts);
pes_start = 0;
}
}
diff --git a/kernel/drivers/media/pci/ttpci/budget-av.c b/kernel/drivers/media/pci/ttpci/budget-av.c
index 54c991025..3e469d4e0 100644
--- a/kernel/drivers/media/pci/ttpci/budget-av.c
+++ b/kernel/drivers/media/pci/ttpci/budget-av.c
@@ -1508,7 +1508,7 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
if (i2c_readregs(&budget_av->budget.i2c_adap, 0xa0, 0x30, mac, 6)) {
pr_err("KNC1-%d: Could not read MAC from KNC1 card\n",
budget_av->budget.dvb_adapter.num);
- memset(mac, 0, 6);
+ eth_zero_addr(mac);
} else {
pr_info("KNC1-%d: MAC addr = %pM\n",
budget_av->budget.dvb_adapter.num, mac);
diff --git a/kernel/drivers/media/pci/ttpci/budget-core.c b/kernel/drivers/media/pci/ttpci/budget-core.c
index 23e05499b..e9674b400 100644
--- a/kernel/drivers/media/pci/ttpci/budget-core.c
+++ b/kernel/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/kernel/drivers/media/pci/ttpci/budget-patch.c b/kernel/drivers/media/pci/ttpci/budget-patch.c
index a4d8867e1..b5b65962c 100644
--- a/kernel/drivers/media/pci/ttpci/budget-patch.c
+++ b/kernel/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/kernel/drivers/media/pci/ttpci/budget.c b/kernel/drivers/media/pci/ttpci/budget.c
index 6ccc48833..99972beca 100644
--- a/kernel/drivers/media/pci/ttpci/budget.c
+++ b/kernel/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/kernel/drivers/media/pci/ttpci/budget.h b/kernel/drivers/media/pci/ttpci/budget.h
index 3d8a806c2..1ccbe1a49 100644
--- a/kernel/drivers/media/pci/ttpci/budget.h
+++ b/kernel/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/kernel/drivers/media/pci/ttpci/ttpci-eeprom.c b/kernel/drivers/media/pci/ttpci/ttpci-eeprom.c
index 32d43156c..079ee098b 100644
--- a/kernel/drivers/media/pci/ttpci/ttpci-eeprom.c
+++ b/kernel/drivers/media/pci/ttpci/ttpci-eeprom.c
@@ -36,6 +36,7 @@
#include <linux/module.h>
#include <linux/string.h>
#include <linux/i2c.h>
+#include <linux/etherdevice.h>
#include "ttpci-eeprom.h"
@@ -145,7 +146,7 @@ int ttpci_eeprom_parse_mac(struct i2c_adapter *adapter, u8 *proposed_mac)
if (ret != 0) { /* Will only be -ENODEV */
dprintk("Couldn't read from EEPROM: not there?\n");
- memset(proposed_mac, 0, 6);
+ eth_zero_addr(proposed_mac);
return ret;
}
@@ -157,14 +158,12 @@ int ttpci_eeprom_parse_mac(struct i2c_adapter *adapter, u8 *proposed_mac)
dprintk( "%.2x:", encodedMAC[i]);
}
dprintk("%.2x\n", encodedMAC[19]);
- memset(proposed_mac, 0, 6);
+ eth_zero_addr(proposed_mac);
return ret;
}
memcpy(proposed_mac, decodedMAC, 6);
- dprintk("adapter has MAC addr = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
- decodedMAC[0], decodedMAC[1], decodedMAC[2],
- decodedMAC[3], decodedMAC[4], decodedMAC[5]);
+ dprintk("adapter has MAC addr = %pM\n", decodedMAC);
return 0;
}
diff --git a/kernel/drivers/media/pci/tw68/tw68-core.c b/kernel/drivers/media/pci/tw68/tw68-core.c
index c135165a8..4e77618fb 100644
--- a/kernel/drivers/media/pci/tw68/tw68-core.c
+++ b/kernel/drivers/media/pci/tw68/tw68-core.c
@@ -37,6 +37,7 @@
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/dma-mapping.h>
+#include <linux/pci_ids.h>
#include <linux/pm.h>
#include <media/v4l2-dev.h>
@@ -70,13 +71,13 @@ static atomic_t tw68_instance = ATOMIC_INIT(0);
* added under vendor 0x1797 (Techwell Inc.) as subsystem IDs.
*/
static const struct pci_device_id tw68_pci_tbl[] = {
- {PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, PCI_DEVICE_ID_6800)},
- {PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, PCI_DEVICE_ID_6801)},
- {PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, PCI_DEVICE_ID_6804)},
- {PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, PCI_DEVICE_ID_6816_1)},
- {PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, PCI_DEVICE_ID_6816_2)},
- {PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, PCI_DEVICE_ID_6816_3)},
- {PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, PCI_DEVICE_ID_6816_4)},
+ {PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, PCI_DEVICE_ID_TECHWELL_6800)},
+ {PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, PCI_DEVICE_ID_TECHWELL_6801)},
+ {PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, PCI_DEVICE_ID_TECHWELL_6804)},
+ {PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, PCI_DEVICE_ID_TECHWELL_6816_1)},
+ {PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, PCI_DEVICE_ID_TECHWELL_6816_2)},
+ {PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, PCI_DEVICE_ID_TECHWELL_6816_3)},
+ {PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, PCI_DEVICE_ID_TECHWELL_6816_4)},
{0,}
};
@@ -256,22 +257,22 @@ static int tw68_initdev(struct pci_dev *pci_dev,
dev->name, pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
dev->pci_lat, (u64)pci_resource_start(pci_dev, 0));
pci_set_master(pci_dev);
- if (!pci_dma_supported(pci_dev, DMA_BIT_MASK(32))) {
+ err = pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32));
+ if (err) {
pr_info("%s: Oops: no 32bit PCI DMA ???\n", dev->name);
- err = -EIO;
goto fail1;
}
switch (pci_id->device) {
- case PCI_DEVICE_ID_6800: /* TW6800 */
+ case PCI_DEVICE_ID_TECHWELL_6800: /* TW6800 */
dev->vdecoder = TW6800;
dev->board_virqmask = TW68_VID_INTS;
break;
- case PCI_DEVICE_ID_6801: /* Video decoder for TW6802 */
+ case PCI_DEVICE_ID_TECHWELL_6801: /* Video decoder for TW6802 */
dev->vdecoder = TW6801;
dev->board_virqmask = TW68_VID_INTS | TW68_VID_INTSX;
break;
- case PCI_DEVICE_ID_6804: /* Video decoder for TW6804 */
+ case PCI_DEVICE_ID_TECHWELL_6804: /* Video decoder for TW6804 */
dev->vdecoder = TW6804;
dev->board_virqmask = TW68_VID_INTS | TW68_VID_INTSX;
break;
diff --git a/kernel/drivers/media/pci/tw68/tw68-video.c b/kernel/drivers/media/pci/tw68/tw68-video.c
index 8355e55b4..46642ef91 100644
--- a/kernel/drivers/media/pci/tw68/tw68-video.c
+++ b/kernel/drivers/media/pci/tw68/tw68-video.c
@@ -376,10 +376,11 @@ static int tw68_buffer_count(unsigned int size, unsigned int count)
/* ------------------------------------------------------------- */
/* vb2 queue operations */
-static int tw68_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int tw68_queue_setup(struct vb2_queue *q, const void *parg,
unsigned int *num_buffers, unsigned int *num_planes,
unsigned int sizes[], void *alloc_ctxs[])
{
+ const struct v4l2_format *fmt = parg;
struct tw68_dev *dev = vb2_get_drv_priv(q);
unsigned tot_bufs = q->num_buffers + *num_buffers;
@@ -423,9 +424,10 @@ static int tw68_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
*/
static void tw68_buf_queue(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct vb2_queue *vq = vb->vb2_queue;
struct tw68_dev *dev = vb2_get_drv_priv(vq);
- struct tw68_buf *buf = container_of(vb, struct tw68_buf, vb);
+ struct tw68_buf *buf = container_of(vbuf, struct tw68_buf, vb);
struct tw68_buf *prev;
unsigned long flags;
@@ -457,9 +459,10 @@ static void tw68_buf_queue(struct vb2_buffer *vb)
*/
static int tw68_buf_prepare(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct vb2_queue *vq = vb->vb2_queue;
struct tw68_dev *dev = vb2_get_drv_priv(vq);
- struct tw68_buf *buf = container_of(vb, struct tw68_buf, vb);
+ struct tw68_buf *buf = container_of(vbuf, struct tw68_buf, vb);
struct sg_table *dma = vb2_dma_sg_plane_desc(vb, 0);
unsigned size, bpl;
@@ -499,9 +502,10 @@ static int tw68_buf_prepare(struct vb2_buffer *vb)
static void tw68_buf_finish(struct vb2_buffer *vb)
{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct vb2_queue *vq = vb->vb2_queue;
struct tw68_dev *dev = vb2_get_drv_priv(vq);
- struct tw68_buf *buf = container_of(vb, struct tw68_buf, vb);
+ struct tw68_buf *buf = container_of(vbuf, struct tw68_buf, vb);
pci_free_consistent(dev->pci, buf->size, buf->cpu, buf->dma);
}
@@ -528,7 +532,7 @@ static void tw68_stop_streaming(struct vb2_queue *q)
container_of(dev->active.next, struct tw68_buf, list);
list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
}
@@ -975,7 +979,7 @@ int tw68_video_init2(struct tw68_dev *dev, int video_nr)
dev->vidq.ops = &tw68_video_qops;
dev->vidq.mem_ops = &vb2_dma_sg_memops;
dev->vidq.drv_priv = dev;
- dev->vidq.gfp_flags = __GFP_DMA32;
+ dev->vidq.gfp_flags = __GFP_DMA32 | __GFP_KSWAPD_RECLAIM;
dev->vidq.buf_struct_size = sizeof(struct tw68_buf);
dev->vidq.lock = &dev->lock;
dev->vidq.min_buffers_needed = 2;
@@ -1012,10 +1016,10 @@ void tw68_irq_video_done(struct tw68_dev *dev, unsigned long status)
buf = list_entry(dev->active.next, struct tw68_buf, list);
list_del(&buf->list);
spin_unlock(&dev->slock);
- v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
- buf->vb.v4l2_buf.field = dev->field;
- buf->vb.v4l2_buf.sequence = dev->seqnr++;
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
+ v4l2_get_timestamp(&buf->vb.timestamp);
+ buf->vb.field = dev->field;
+ buf->vb.sequence = dev->seqnr++;
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
status &= ~(TW68_DMAPI);
if (0 == status)
return;
diff --git a/kernel/drivers/media/pci/tw68/tw68.h b/kernel/drivers/media/pci/tw68/tw68.h
index 93f2335e0..6c7dcb300 100644
--- a/kernel/drivers/media/pci/tw68/tw68.h
+++ b/kernel/drivers/media/pci/tw68/tw68.h
@@ -36,28 +36,13 @@
#include <media/v4l2-ioctl.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
+#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-dma-sg.h>
#include "tw68-reg.h"
#define UNSET (-1U)
-/* system vendor and device ID's */
-#define PCI_VENDOR_ID_TECHWELL 0x1797
-#define PCI_DEVICE_ID_6800 0x6800
-#define PCI_DEVICE_ID_6801 0x6801
-#define PCI_DEVICE_ID_AUDIO2 0x6802
-#define PCI_DEVICE_ID_TS3 0x6803
-#define PCI_DEVICE_ID_6804 0x6804
-#define PCI_DEVICE_ID_AUDIO5 0x6805
-#define PCI_DEVICE_ID_TS6 0x6806
-
-/* tw6816 based cards */
-#define PCI_DEVICE_ID_6816_1 0x6810
-#define PCI_DEVICE_ID_6816_2 0x6811
-#define PCI_DEVICE_ID_6816_3 0x6812
-#define PCI_DEVICE_ID_6816_4 0x6813
-
#define TW68_NORMS ( \
V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM | \
V4L2_STD_PAL_M | V4L2_STD_PAL_Nc | V4L2_STD_PAL_60)
@@ -134,7 +119,7 @@ struct tw68_dev; /* forward delclaration */
/* buffer for one video/vbi/ts frame */
struct tw68_buf {
- struct vb2_buffer vb;
+ struct vb2_v4l2_buffer vb;
struct list_head list;
unsigned int size;
diff --git a/kernel/drivers/media/pci/zoran/zoran.h b/kernel/drivers/media/pci/zoran/zoran.h
index 5e040085c..4e7db8939 100644
--- a/kernel/drivers/media/pci/zoran/zoran.h
+++ b/kernel/drivers/media/pci/zoran/zoran.h
@@ -32,6 +32,8 @@
#define _BUZ_H_
#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-fh.h>
struct zoran_sync {
unsigned long frame; /* number of buffer that has been free'd */
@@ -216,6 +218,7 @@ struct zoran;
/* zoran_fh contains per-open() settings */
struct zoran_fh {
+ struct v4l2_fh fh;
struct zoran *zr;
enum zoran_map_mode map_mode; /* Flag which bufferset will map by next mmap() */
@@ -268,6 +271,7 @@ struct card_info {
struct zoran {
struct v4l2_device v4l2_dev;
+ struct v4l2_ctrl_handler hdl;
struct video_device *video_dev;
struct i2c_adapter i2c_adapter; /* */
@@ -280,8 +284,7 @@ struct zoran {
struct videocodec *codec; /* video codec */
struct videocodec *vfe; /* video front end */
- struct mutex resource_lock; /* prevent evil stuff */
- struct mutex other_lock; /* please merge with above */
+ struct mutex lock; /* file ops serialize lock */
u8 initialized; /* flag if zoran has been correctly initialized */
int user; /* number of current users */
diff --git a/kernel/drivers/media/pci/zoran/zoran_card.c b/kernel/drivers/media/pci/zoran/zoran_card.c
index cec5b7553..1136d92af 100644
--- a/kernel/drivers/media/pci/zoran/zoran_card.c
+++ b/kernel/drivers/media/pci/zoran/zoran_card.c
@@ -1049,8 +1049,9 @@ static int zr36057_init (struct zoran *zr)
/*
* Now add the template and register the device unit.
*/
- memcpy(zr->video_dev, &zoran_template, sizeof(zoran_template));
+ *zr->video_dev = zoran_template;
zr->video_dev->v4l2_dev = &zr->v4l2_dev;
+ zr->video_dev->lock = &zr->lock;
strcpy(zr->video_dev->name, ZR_DEVNAME(zr));
/* It's not a mem2mem device, but you can both capture and output from
one and the same device. This should really be split up into two
@@ -1116,6 +1117,7 @@ static void zoran_remove(struct pci_dev *pdev)
pci_disable_device(zr->pci_dev);
video_unregister_device(zr->video_dev);
exit_free:
+ v4l2_ctrl_handler_free(&zr->hdl);
v4l2_device_unregister(&zr->v4l2_dev);
kfree(zr);
}
@@ -1219,9 +1221,11 @@ static int zoran_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
zr->pci_dev = pdev;
zr->id = nr;
snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)), "MJPEG[%u]", zr->id);
+ if (v4l2_ctrl_handler_init(&zr->hdl, 10))
+ goto zr_unreg;
+ zr->v4l2_dev.ctrl_handler = &zr->hdl;
spin_lock_init(&zr->spinlock);
- mutex_init(&zr->resource_lock);
- mutex_init(&zr->other_lock);
+ mutex_init(&zr->lock);
if (pci_enable_device(pdev))
goto zr_unreg;
zr->revision = zr->pci_dev->revision;
@@ -1443,6 +1447,7 @@ zr_free_irq:
zr_unmap:
iounmap(zr->zr36057_mem);
zr_unreg:
+ v4l2_ctrl_handler_free(&zr->hdl);
v4l2_device_unregister(&zr->v4l2_dev);
zr_free_mem:
kfree(zr);
diff --git a/kernel/drivers/media/pci/zoran/zoran_device.c b/kernel/drivers/media/pci/zoran/zoran_device.c
index b6801e035..4d47ddac9 100644
--- a/kernel/drivers/media/pci/zoran/zoran_device.c
+++ b/kernel/drivers/media/pci/zoran/zoran_device.c
@@ -31,6 +31,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/vmalloc.h>
+#include <linux/ktime.h>
#include <linux/interrupt.h>
#include <linux/proc_fs.h>
@@ -181,20 +182,11 @@ dump_guests (struct zoran *zr)
}
}
-static inline unsigned long
-get_time (void)
-{
- struct timeval tv;
-
- do_gettimeofday(&tv);
- return (1000000 * tv.tv_sec + tv.tv_usec);
-}
-
void
detect_guest_activity (struct zoran *zr)
{
int timeout, i, j, res, guest[8], guest0[8], change[8][3];
- unsigned long t0, t1;
+ ktime_t t0, t1;
dump_guests(zr);
printk(KERN_INFO "%s: Detecting guests activity, please wait...\n",
@@ -205,15 +197,15 @@ detect_guest_activity (struct zoran *zr)
timeout = 0;
j = 0;
- t0 = get_time();
+ t0 = ktime_get();
while (timeout < 10000) {
udelay(10);
timeout++;
for (i = 1; (i < 8) && (j < 8); i++) {
res = post_office_read(zr, i, 0);
if (res != guest[i]) {
- t1 = get_time();
- change[j][0] = (t1 - t0);
+ t1 = ktime_get();
+ change[j][0] = ktime_to_us(ktime_sub(t1, t0));
t0 = t1;
change[j][1] = i;
change[j][2] = res;
@@ -1584,14 +1576,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);
diff --git a/kernel/drivers/media/pci/zoran/zoran_driver.c b/kernel/drivers/media/pci/zoran/zoran_driver.c
index 2b25d31c4..80caa70c6 100644
--- a/kernel/drivers/media/pci/zoran/zoran_driver.c
+++ b/kernel/drivers/media/pci/zoran/zoran_driver.c
@@ -61,6 +61,7 @@
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
+#include <media/v4l2-event.h>
#include "videocodec.h"
#include <asm/byteorder.h>
@@ -592,10 +593,14 @@ static int v4l_sync(struct zoran_fh *fh, int frame)
return -EPROTO;
}
+ mutex_unlock(&zr->lock);
/* wait on this buffer to get ready */
if (!wait_event_interruptible_timeout(zr->v4l_capq,
- (zr->v4l_buffers.buffer[frame].state != BUZ_STATE_PEND), 10*HZ))
+ (zr->v4l_buffers.buffer[frame].state != BUZ_STATE_PEND), 10*HZ)) {
+ mutex_lock(&zr->lock);
return -ETIME;
+ }
+ mutex_lock(&zr->lock);
if (signal_pending(current))
return -ERESTARTSYS;
@@ -783,6 +788,7 @@ static int jpg_sync(struct zoran_fh *fh, struct zoran_sync *bs)
ZR_DEVNAME(zr), __func__);
return -EINVAL;
}
+ mutex_unlock(&zr->lock);
if (!wait_event_interruptible_timeout(zr->jpg_capq,
(zr->jpg_que_tail != zr->jpg_dma_tail ||
zr->jpg_dma_tail == zr->jpg_dma_head),
@@ -793,6 +799,7 @@ static int jpg_sync(struct zoran_fh *fh, struct zoran_sync *bs)
udelay(1);
zr->codec->control(zr->codec, CODEC_G_STATUS,
sizeof(isr), &isr);
+ mutex_lock(&zr->lock);
dprintk(1,
KERN_ERR
"%s: %s - timeout: codec isr=0x%02x\n",
@@ -801,6 +808,7 @@ static int jpg_sync(struct zoran_fh *fh, struct zoran_sync *bs)
return -ETIME;
}
+ mutex_lock(&zr->lock);
if (signal_pending(current))
return -ERESTARTSYS;
@@ -911,7 +919,7 @@ static int zoran_open(struct file *file)
dprintk(2, KERN_INFO "%s: %s(%s, pid=[%d]), users(-)=%d\n",
ZR_DEVNAME(zr), __func__, current->comm, task_pid_nr(current), zr->user + 1);
- mutex_lock(&zr->other_lock);
+ mutex_lock(&zr->lock);
if (zr->user >= 2048) {
dprintk(1, KERN_ERR "%s: too many users (%d) on device\n",
@@ -930,6 +938,8 @@ static int zoran_open(struct file *file)
res = -ENOMEM;
goto fail_unlock;
}
+ v4l2_fh_init(&fh->fh, video_devdata(file));
+
/* used to be BUZ_MAX_WIDTH/HEIGHT, but that gives overflows
* on norm-change! */
fh->overlay_mask =
@@ -946,8 +956,6 @@ static int zoran_open(struct file *file)
if (zr->user++ == 0)
first_open = 1;
- /*mutex_unlock(&zr->resource_lock);*/
-
/* default setup - TODO: look at flags */
if (first_open) { /* First device open */
zr36057_restart(zr);
@@ -961,14 +969,15 @@ static int zoran_open(struct file *file)
file->private_data = fh;
fh->zr = zr;
zoran_open_init_session(fh);
- mutex_unlock(&zr->other_lock);
+ v4l2_fh_add(&fh->fh);
+ mutex_unlock(&zr->lock);
return 0;
fail_fh:
kfree(fh);
fail_unlock:
- mutex_unlock(&zr->other_lock);
+ mutex_unlock(&zr->lock);
dprintk(2, KERN_INFO "%s: open failed (%d), users(-)=%d\n",
ZR_DEVNAME(zr), res, zr->user);
@@ -987,7 +996,7 @@ zoran_close(struct file *file)
/* kernel locks (fs/device.c), so don't do that ourselves
* (prevents deadlocks) */
- mutex_lock(&zr->other_lock);
+ mutex_lock(&zr->lock);
zoran_close_end_session(fh);
@@ -1021,9 +1030,10 @@ zoran_close(struct file *file)
encoder_call(zr, video, s_routing, 2, 0, 0);
}
}
- mutex_unlock(&zr->other_lock);
+ mutex_unlock(&zr->lock);
- file->private_data = NULL;
+ v4l2_fh_del(&fh->fh);
+ v4l2_fh_exit(&fh->fh);
kfree(fh->overlay_mask);
kfree(fh);
@@ -1032,29 +1042,6 @@ zoran_close(struct file *file)
return 0;
}
-
-static ssize_t
-zoran_read (struct file *file,
- char __user *data,
- size_t count,
- loff_t *ppos)
-{
- /* we simply don't support read() (yet)... */
-
- return -EINVAL;
-}
-
-static ssize_t
-zoran_write (struct file *file,
- const char __user *data,
- size_t count,
- loff_t *ppos)
-{
- /* ...and the same goes for write() */
-
- return -EINVAL;
-}
-
static int setup_fbuffer(struct zoran_fh *fh,
void *base,
const struct zoran_format *fmt,
@@ -1523,7 +1510,6 @@ static int zoran_querycap(struct file *file, void *__fh, struct v4l2_capability
struct zoran_fh *fh = __fh;
struct zoran *zr = fh->zr;
- memset(cap, 0, sizeof(*cap));
strncpy(cap->card, ZR_DEVNAME(zr), sizeof(cap->card)-1);
strncpy(cap->driver, "zoran", sizeof(cap->driver)-1);
snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
@@ -1583,9 +1569,6 @@ static int zoran_g_fmt_vid_out(struct file *file, void *__fh,
struct v4l2_format *fmt)
{
struct zoran_fh *fh = __fh;
- struct zoran *zr = fh->zr;
-
- mutex_lock(&zr->resource_lock);
fmt->fmt.pix.width = fh->jpg_settings.img_width / fh->jpg_settings.HorDcm;
fmt->fmt.pix.height = fh->jpg_settings.img_height * 2 /
@@ -1601,7 +1584,6 @@ static int zoran_g_fmt_vid_out(struct file *file, void *__fh,
fmt->fmt.pix.bytesperline = 0;
fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
- mutex_unlock(&zr->resource_lock);
return 0;
}
@@ -1614,7 +1596,6 @@ static int zoran_g_fmt_vid_cap(struct file *file, void *__fh,
if (fh->map_mode != ZORAN_MAP_MODE_RAW)
return zoran_g_fmt_vid_out(file, fh, fmt);
- mutex_lock(&zr->resource_lock);
fmt->fmt.pix.width = fh->v4l_settings.width;
fmt->fmt.pix.height = fh->v4l_settings.height;
fmt->fmt.pix.sizeimage = fh->v4l_settings.bytesperline *
@@ -1626,7 +1607,6 @@ static int zoran_g_fmt_vid_cap(struct file *file, void *__fh,
fmt->fmt.pix.field = V4L2_FIELD_INTERLACED;
else
fmt->fmt.pix.field = V4L2_FIELD_TOP;
- mutex_unlock(&zr->resource_lock);
return 0;
}
@@ -1636,8 +1616,6 @@ static int zoran_g_fmt_vid_overlay(struct file *file, void *__fh,
struct zoran_fh *fh = __fh;
struct zoran *zr = fh->zr;
- mutex_lock(&zr->resource_lock);
-
fmt->fmt.win.w.left = fh->overlay_settings.x;
fmt->fmt.win.w.top = fh->overlay_settings.y;
fmt->fmt.win.w.width = fh->overlay_settings.width;
@@ -1647,7 +1625,6 @@ static int zoran_g_fmt_vid_overlay(struct file *file, void *__fh,
else
fmt->fmt.win.field = V4L2_FIELD_TOP;
- mutex_unlock(&zr->resource_lock);
return 0;
}
@@ -1657,8 +1634,6 @@ static int zoran_try_fmt_vid_overlay(struct file *file, void *__fh,
struct zoran_fh *fh = __fh;
struct zoran *zr = fh->zr;
- mutex_lock(&zr->resource_lock);
-
if (fmt->fmt.win.w.width > BUZ_MAX_WIDTH)
fmt->fmt.win.w.width = BUZ_MAX_WIDTH;
if (fmt->fmt.win.w.width < BUZ_MIN_WIDTH)
@@ -1668,7 +1643,6 @@ static int zoran_try_fmt_vid_overlay(struct file *file, void *__fh,
if (fmt->fmt.win.w.height < BUZ_MIN_HEIGHT)
fmt->fmt.win.w.height = BUZ_MIN_HEIGHT;
- mutex_unlock(&zr->resource_lock);
return 0;
}
@@ -1683,7 +1657,6 @@ static int zoran_try_fmt_vid_out(struct file *file, void *__fh,
if (fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
return -EINVAL;
- mutex_lock(&zr->resource_lock);
settings = fh->jpg_settings;
/* we actually need to set 'real' parameters now */
@@ -1718,7 +1691,7 @@ static int zoran_try_fmt_vid_out(struct file *file, void *__fh,
/* check */
res = zoran_check_jpg_settings(zr, &settings, 1);
if (res)
- goto tryfmt_unlock_and_return;
+ return res;
/* tell the user what we actually did */
fmt->fmt.pix.width = settings.img_width / settings.HorDcm;
@@ -1734,8 +1707,6 @@ static int zoran_try_fmt_vid_out(struct file *file, void *__fh,
fmt->fmt.pix.sizeimage = zoran_v4l2_calc_bufsize(&settings);
fmt->fmt.pix.bytesperline = 0;
fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-tryfmt_unlock_and_return:
- mutex_unlock(&zr->resource_lock);
return res;
}
@@ -1750,23 +1721,17 @@ static int zoran_try_fmt_vid_cap(struct file *file, void *__fh,
if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG)
return zoran_try_fmt_vid_out(file, fh, fmt);
- mutex_lock(&zr->resource_lock);
-
for (i = 0; i < NUM_FORMATS; i++)
if (zoran_formats[i].fourcc == fmt->fmt.pix.pixelformat)
break;
- if (i == NUM_FORMATS) {
- mutex_unlock(&zr->resource_lock);
+ if (i == NUM_FORMATS)
return -EINVAL;
- }
bpp = DIV_ROUND_UP(zoran_formats[i].depth, 8);
v4l_bound_align_image(
&fmt->fmt.pix.width, BUZ_MIN_WIDTH, BUZ_MAX_WIDTH, bpp == 2 ? 1 : 2,
&fmt->fmt.pix.height, BUZ_MIN_HEIGHT, BUZ_MAX_HEIGHT, 0, 0);
- mutex_unlock(&zr->resource_lock);
-
return 0;
}
@@ -1774,7 +1739,6 @@ static int zoran_s_fmt_vid_overlay(struct file *file, void *__fh,
struct v4l2_format *fmt)
{
struct zoran_fh *fh = __fh;
- struct zoran *zr = fh->zr;
int res;
dprintk(3, "x=%d, y=%d, w=%d, h=%d, cnt=%d, map=0x%p\n",
@@ -1783,12 +1747,10 @@ static int zoran_s_fmt_vid_overlay(struct file *file, void *__fh,
fmt->fmt.win.w.height,
fmt->fmt.win.clipcount,
fmt->fmt.win.bitmap);
- mutex_lock(&zr->resource_lock);
res = setup_window(fh, fmt->fmt.win.w.left, fmt->fmt.win.w.top,
fmt->fmt.win.w.width, fmt->fmt.win.w.height,
(struct v4l2_clip __user *)fmt->fmt.win.clips,
fmt->fmt.win.clipcount, fmt->fmt.win.bitmap);
- mutex_unlock(&zr->resource_lock);
return res;
}
@@ -1808,13 +1770,11 @@ static int zoran_s_fmt_vid_out(struct file *file, void *__fh,
if (fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
return -EINVAL;
- mutex_lock(&zr->resource_lock);
-
if (fh->buffers.allocated) {
dprintk(1, KERN_ERR "%s: VIDIOC_S_FMT - cannot change capture mode\n",
ZR_DEVNAME(zr));
res = -EBUSY;
- goto sfmtjpg_unlock_and_return;
+ return res;
}
settings = fh->jpg_settings;
@@ -1851,7 +1811,7 @@ static int zoran_s_fmt_vid_out(struct file *file, void *__fh,
/* check */
res = zoran_check_jpg_settings(zr, &settings, 0);
if (res)
- goto sfmtjpg_unlock_and_return;
+ return res;
/* it's ok, so set them */
fh->jpg_settings = settings;
@@ -1872,9 +1832,6 @@ static int zoran_s_fmt_vid_out(struct file *file, void *__fh,
fmt->fmt.pix.bytesperline = 0;
fmt->fmt.pix.sizeimage = fh->buffers.buffer_size;
fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-
-sfmtjpg_unlock_and_return:
- mutex_unlock(&zr->resource_lock);
return res;
}
@@ -1898,14 +1855,12 @@ static int zoran_s_fmt_vid_cap(struct file *file, void *__fh,
return -EINVAL;
}
- mutex_lock(&zr->resource_lock);
-
if ((fh->map_mode != ZORAN_MAP_MODE_RAW && fh->buffers.allocated) ||
fh->buffers.active != ZORAN_FREE) {
dprintk(1, KERN_ERR "%s: VIDIOC_S_FMT - cannot change capture mode\n",
ZR_DEVNAME(zr));
res = -EBUSY;
- goto sfmtv4l_unlock_and_return;
+ return res;
}
if (fmt->fmt.pix.height > BUZ_MAX_HEIGHT)
fmt->fmt.pix.height = BUZ_MAX_HEIGHT;
@@ -1917,7 +1872,7 @@ static int zoran_s_fmt_vid_cap(struct file *file, void *__fh,
res = zoran_v4l_set_format(fh, fmt->fmt.pix.width, fmt->fmt.pix.height,
&zoran_formats[i]);
if (res)
- goto sfmtv4l_unlock_and_return;
+ return res;
/* tell the user the results/missing stuff */
fmt->fmt.pix.bytesperline = fh->v4l_settings.bytesperline;
@@ -1927,9 +1882,6 @@ static int zoran_s_fmt_vid_cap(struct file *file, void *__fh,
fmt->fmt.pix.field = V4L2_FIELD_INTERLACED;
else
fmt->fmt.pix.field = V4L2_FIELD_TOP;
-
-sfmtv4l_unlock_and_return:
- mutex_unlock(&zr->resource_lock);
return res;
}
@@ -1940,14 +1892,12 @@ static int zoran_g_fbuf(struct file *file, void *__fh,
struct zoran *zr = fh->zr;
memset(fb, 0, sizeof(*fb));
- mutex_lock(&zr->resource_lock);
fb->base = zr->vbuf_base;
fb->fmt.width = zr->vbuf_width;
fb->fmt.height = zr->vbuf_height;
if (zr->overlay_settings.format)
fb->fmt.pixelformat = fh->overlay_settings.format->fourcc;
fb->fmt.bytesperline = zr->vbuf_bytesperline;
- mutex_unlock(&zr->resource_lock);
fb->fmt.colorspace = V4L2_COLORSPACE_SRGB;
fb->fmt.field = V4L2_FIELD_INTERLACED;
fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
@@ -1973,10 +1923,8 @@ static int zoran_s_fbuf(struct file *file, void *__fh,
return -EINVAL;
}
- mutex_lock(&zr->resource_lock);
res = setup_fbuffer(fh, fb->base, &zoran_formats[i], fb->fmt.width,
fb->fmt.height, fb->fmt.bytesperline);
- mutex_unlock(&zr->resource_lock);
return res;
}
@@ -1984,12 +1932,9 @@ static int zoran_s_fbuf(struct file *file, void *__fh,
static int zoran_overlay(struct file *file, void *__fh, unsigned int on)
{
struct zoran_fh *fh = __fh;
- struct zoran *zr = fh->zr;
int res;
- mutex_lock(&zr->resource_lock);
res = setup_overlay(fh, on);
- mutex_unlock(&zr->resource_lock);
return res;
}
@@ -2013,14 +1958,13 @@ static int zoran_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffe
if (req->count == 0)
return zoran_streamoff(file, fh, req->type);
- mutex_lock(&zr->resource_lock);
if (fh->buffers.allocated) {
dprintk(2,
KERN_ERR
"%s: VIDIOC_REQBUFS - buffers already allocated\n",
ZR_DEVNAME(zr));
res = -EBUSY;
- goto v4l2reqbuf_unlock_and_return;
+ return res;
}
if (fh->map_mode == ZORAN_MAP_MODE_RAW &&
@@ -2037,7 +1981,7 @@ static int zoran_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffe
if (v4l_fbuffer_alloc(fh)) {
res = -ENOMEM;
- goto v4l2reqbuf_unlock_and_return;
+ return res;
}
} else if (fh->map_mode == ZORAN_MAP_MODE_JPG_REC ||
fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY) {
@@ -2054,7 +1998,7 @@ static int zoran_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffe
if (jpg_fbuffer_alloc(fh)) {
res = -ENOMEM;
- goto v4l2reqbuf_unlock_and_return;
+ return res;
}
} else {
dprintk(1,
@@ -2062,23 +2006,17 @@ static int zoran_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffe
"%s: VIDIOC_REQBUFS - unknown type %d\n",
ZR_DEVNAME(zr), req->type);
res = -EINVAL;
- goto v4l2reqbuf_unlock_and_return;
+ return res;
}
-v4l2reqbuf_unlock_and_return:
- mutex_unlock(&zr->resource_lock);
-
return res;
}
static int zoran_querybuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
{
struct zoran_fh *fh = __fh;
- struct zoran *zr = fh->zr;
int res;
- mutex_lock(&zr->resource_lock);
res = zoran_v4l2_buffer_status(fh, buf, buf->index);
- mutex_unlock(&zr->resource_lock);
return res;
}
@@ -2089,8 +2027,6 @@ static int zoran_qbuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
struct zoran *zr = fh->zr;
int res = 0, codec_mode, buf_type;
- mutex_lock(&zr->resource_lock);
-
switch (fh->map_mode) {
case ZORAN_MAP_MODE_RAW:
if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
@@ -2098,12 +2034,12 @@ static int zoran_qbuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
"%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n",
ZR_DEVNAME(zr), buf->type, fh->map_mode);
res = -EINVAL;
- goto qbuf_unlock_and_return;
+ return res;
}
res = zoran_v4l_queue_frame(fh, buf->index);
if (res)
- goto qbuf_unlock_and_return;
+ return res;
if (!zr->v4l_memgrab_active && fh->buffers.active == ZORAN_LOCKED)
zr36057_set_memgrab(zr, 1);
break;
@@ -2123,12 +2059,12 @@ static int zoran_qbuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
"%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n",
ZR_DEVNAME(zr), buf->type, fh->map_mode);
res = -EINVAL;
- goto qbuf_unlock_and_return;
+ return res;
}
res = zoran_jpg_queue_frame(fh, buf->index, codec_mode);
if (res != 0)
- goto qbuf_unlock_and_return;
+ return res;
if (zr->codec_mode == BUZ_MODE_IDLE &&
fh->buffers.active == ZORAN_LOCKED)
zr36057_enable_jpg(zr, codec_mode);
@@ -2142,9 +2078,6 @@ static int zoran_qbuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
res = -EINVAL;
break;
}
-qbuf_unlock_and_return:
- mutex_unlock(&zr->resource_lock);
-
return res;
}
@@ -2154,8 +2087,6 @@ static int zoran_dqbuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
struct zoran *zr = fh->zr;
int res = 0, buf_type, num = -1; /* compiler borks here (?) */
- mutex_lock(&zr->resource_lock);
-
switch (fh->map_mode) {
case ZORAN_MAP_MODE_RAW:
if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
@@ -2163,18 +2094,18 @@ static int zoran_dqbuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
"%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n",
ZR_DEVNAME(zr), buf->type, fh->map_mode);
res = -EINVAL;
- goto dqbuf_unlock_and_return;
+ return res;
}
num = zr->v4l_pend[zr->v4l_sync_tail & V4L_MASK_FRAME];
if (file->f_flags & O_NONBLOCK &&
zr->v4l_buffers.buffer[num].state != BUZ_STATE_DONE) {
res = -EAGAIN;
- goto dqbuf_unlock_and_return;
+ return res;
}
res = v4l_sync(fh, num);
if (res)
- goto dqbuf_unlock_and_return;
+ return res;
zr->v4l_sync_tail++;
res = zoran_v4l2_buffer_status(fh, buf, num);
break;
@@ -2194,7 +2125,7 @@ static int zoran_dqbuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
"%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n",
ZR_DEVNAME(zr), buf->type, fh->map_mode);
res = -EINVAL;
- goto dqbuf_unlock_and_return;
+ return res;
}
num = zr->jpg_pend[zr->jpg_que_tail & BUZ_MASK_FRAME];
@@ -2202,12 +2133,12 @@ static int zoran_dqbuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
if (file->f_flags & O_NONBLOCK &&
zr->jpg_buffers.buffer[num].state != BUZ_STATE_DONE) {
res = -EAGAIN;
- goto dqbuf_unlock_and_return;
+ return res;
}
bs.frame = 0; /* suppress compiler warning */
res = jpg_sync(fh, &bs);
if (res)
- goto dqbuf_unlock_and_return;
+ return res;
res = zoran_v4l2_buffer_status(fh, buf, bs.frame);
break;
}
@@ -2219,9 +2150,6 @@ static int zoran_dqbuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
res = -EINVAL;
break;
}
-dqbuf_unlock_and_return:
- mutex_unlock(&zr->resource_lock);
-
return res;
}
@@ -2231,14 +2159,12 @@ static int zoran_streamon(struct file *file, void *__fh, enum v4l2_buf_type type
struct zoran *zr = fh->zr;
int res = 0;
- mutex_lock(&zr->resource_lock);
-
switch (fh->map_mode) {
case ZORAN_MAP_MODE_RAW: /* raw capture */
if (zr->v4l_buffers.active != ZORAN_ACTIVE ||
fh->buffers.active != ZORAN_ACTIVE) {
res = -EBUSY;
- goto strmon_unlock_and_return;
+ return res;
}
zr->v4l_buffers.active = fh->buffers.active = ZORAN_LOCKED;
@@ -2257,7 +2183,7 @@ static int zoran_streamon(struct file *file, void *__fh, enum v4l2_buf_type type
if (zr->jpg_buffers.active != ZORAN_ACTIVE ||
fh->buffers.active != ZORAN_ACTIVE) {
res = -EBUSY;
- goto strmon_unlock_and_return;
+ return res;
}
zr->jpg_buffers.active = fh->buffers.active = ZORAN_LOCKED;
@@ -2276,9 +2202,6 @@ static int zoran_streamon(struct file *file, void *__fh, enum v4l2_buf_type type
res = -EINVAL;
break;
}
-strmon_unlock_and_return:
- mutex_unlock(&zr->resource_lock);
-
return res;
}
@@ -2289,17 +2212,15 @@ static int zoran_streamoff(struct file *file, void *__fh, enum v4l2_buf_type typ
int i, res = 0;
unsigned long flags;
- mutex_lock(&zr->resource_lock);
-
switch (fh->map_mode) {
case ZORAN_MAP_MODE_RAW: /* raw capture */
if (fh->buffers.active == ZORAN_FREE &&
zr->v4l_buffers.active != ZORAN_FREE) {
res = -EPERM; /* stay off other's settings! */
- goto strmoff_unlock_and_return;
+ return res;
}
if (zr->v4l_buffers.active == ZORAN_FREE)
- goto strmoff_unlock_and_return;
+ return res;
spin_lock_irqsave(&zr->spinlock, flags);
/* unload capture */
@@ -2327,17 +2248,17 @@ static int zoran_streamoff(struct file *file, void *__fh, enum v4l2_buf_type typ
if (fh->buffers.active == ZORAN_FREE &&
zr->jpg_buffers.active != ZORAN_FREE) {
res = -EPERM; /* stay off other's settings! */
- goto strmoff_unlock_and_return;
+ return res;
}
if (zr->jpg_buffers.active == ZORAN_FREE)
- goto strmoff_unlock_and_return;
+ return res;
res = jpg_qbuf(fh, -1,
(fh->map_mode == ZORAN_MAP_MODE_JPG_REC) ?
BUZ_MODE_MOTION_COMPRESS :
BUZ_MODE_MOTION_DECOMPRESS);
if (res)
- goto strmoff_unlock_and_return;
+ return res;
break;
default:
dprintk(1, KERN_ERR
@@ -2346,70 +2267,14 @@ static int zoran_streamoff(struct file *file, void *__fh, enum v4l2_buf_type typ
res = -EINVAL;
break;
}
-strmoff_unlock_and_return:
- mutex_unlock(&zr->resource_lock);
-
return res;
}
-
-static int zoran_queryctrl(struct file *file, void *__fh,
- struct v4l2_queryctrl *ctrl)
-{
- struct zoran_fh *fh = __fh;
- struct zoran *zr = fh->zr;
-
- /* we only support hue/saturation/contrast/brightness */
- if (ctrl->id < V4L2_CID_BRIGHTNESS ||
- ctrl->id > V4L2_CID_HUE)
- return -EINVAL;
-
- decoder_call(zr, core, queryctrl, ctrl);
-
- return 0;
-}
-
-static int zoran_g_ctrl(struct file *file, void *__fh, struct v4l2_control *ctrl)
-{
- struct zoran_fh *fh = __fh;
- struct zoran *zr = fh->zr;
-
- /* we only support hue/saturation/contrast/brightness */
- if (ctrl->id < V4L2_CID_BRIGHTNESS ||
- ctrl->id > V4L2_CID_HUE)
- return -EINVAL;
-
- mutex_lock(&zr->resource_lock);
- decoder_call(zr, core, g_ctrl, ctrl);
- mutex_unlock(&zr->resource_lock);
-
- return 0;
-}
-
-static int zoran_s_ctrl(struct file *file, void *__fh, struct v4l2_control *ctrl)
-{
- struct zoran_fh *fh = __fh;
- struct zoran *zr = fh->zr;
-
- /* we only support hue/saturation/contrast/brightness */
- if (ctrl->id < V4L2_CID_BRIGHTNESS ||
- ctrl->id > V4L2_CID_HUE)
- return -EINVAL;
-
- mutex_lock(&zr->resource_lock);
- decoder_call(zr, core, s_ctrl, ctrl);
- mutex_unlock(&zr->resource_lock);
-
- return 0;
-}
-
static int zoran_g_std(struct file *file, void *__fh, v4l2_std_id *std)
{
struct zoran_fh *fh = __fh;
struct zoran *zr = fh->zr;
- mutex_lock(&zr->resource_lock);
*std = zr->norm;
- mutex_unlock(&zr->resource_lock);
return 0;
}
@@ -2419,14 +2284,11 @@ static int zoran_s_std(struct file *file, void *__fh, v4l2_std_id std)
struct zoran *zr = fh->zr;
int res = 0;
- mutex_lock(&zr->resource_lock);
res = zoran_set_norm(zr, std);
if (res)
- goto sstd_unlock_and_return;
+ return res;
res = wait_grab_pending(zr);
-sstd_unlock_and_return:
- mutex_unlock(&zr->resource_lock);
return res;
}
@@ -2445,9 +2307,7 @@ static int zoran_enum_input(struct file *file, void *__fh,
inp->std = V4L2_STD_ALL;
/* Get status of video decoder */
- mutex_lock(&zr->resource_lock);
decoder_call(zr, video, g_input_status, &inp->status);
- mutex_unlock(&zr->resource_lock);
return 0;
}
@@ -2456,9 +2316,7 @@ static int zoran_g_input(struct file *file, void *__fh, unsigned int *input)
struct zoran_fh *fh = __fh;
struct zoran *zr = fh->zr;
- mutex_lock(&zr->resource_lock);
*input = zr->input;
- mutex_unlock(&zr->resource_lock);
return 0;
}
@@ -2469,15 +2327,12 @@ static int zoran_s_input(struct file *file, void *__fh, unsigned int input)
struct zoran *zr = fh->zr;
int res;
- mutex_lock(&zr->resource_lock);
res = zoran_set_input(zr, input);
if (res)
- goto sinput_unlock_and_return;
+ return res;
/* Make sure the changes come into effect */
res = wait_grab_pending(zr);
-sinput_unlock_and_return:
- mutex_unlock(&zr->resource_lock);
return res;
}
@@ -2520,8 +2375,6 @@ static int zoran_cropcap(struct file *file, void *__fh,
memset(cropcap, 0, sizeof(*cropcap));
cropcap->type = type;
- mutex_lock(&zr->resource_lock);
-
if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
(cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
fh->map_mode == ZORAN_MAP_MODE_RAW)) {
@@ -2529,7 +2382,7 @@ static int zoran_cropcap(struct file *file, void *__fh,
"%s: VIDIOC_CROPCAP - subcapture only supported for compressed capture\n",
ZR_DEVNAME(zr));
res = -EINVAL;
- goto cropcap_unlock_and_return;
+ return res;
}
cropcap->bounds.top = cropcap->bounds.left = 0;
@@ -2538,8 +2391,6 @@ static int zoran_cropcap(struct file *file, void *__fh,
cropcap->defrect.top = cropcap->defrect.left = 0;
cropcap->defrect.width = BUZ_MIN_WIDTH;
cropcap->defrect.height = BUZ_MIN_HEIGHT;
-cropcap_unlock_and_return:
- mutex_unlock(&zr->resource_lock);
return res;
}
@@ -2552,8 +2403,6 @@ static int zoran_g_crop(struct file *file, void *__fh, struct v4l2_crop *crop)
memset(crop, 0, sizeof(*crop));
crop->type = type;
- mutex_lock(&zr->resource_lock);
-
if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
(crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
fh->map_mode == ZORAN_MAP_MODE_RAW)) {
@@ -2562,17 +2411,13 @@ static int zoran_g_crop(struct file *file, void *__fh, struct v4l2_crop *crop)
"%s: VIDIOC_G_CROP - subcapture only supported for compressed capture\n",
ZR_DEVNAME(zr));
res = -EINVAL;
- goto gcrop_unlock_and_return;
+ return res;
}
crop->c.top = fh->jpg_settings.img_y;
crop->c.left = fh->jpg_settings.img_x;
crop->c.width = fh->jpg_settings.img_width;
crop->c.height = fh->jpg_settings.img_height;
-
-gcrop_unlock_and_return:
- mutex_unlock(&zr->resource_lock);
-
return res;
}
@@ -2585,14 +2430,12 @@ static int zoran_s_crop(struct file *file, void *__fh, const struct v4l2_crop *c
settings = fh->jpg_settings;
- mutex_lock(&zr->resource_lock);
-
if (fh->buffers.allocated) {
dprintk(1, KERN_ERR
"%s: VIDIOC_S_CROP - cannot change settings while active\n",
ZR_DEVNAME(zr));
res = -EBUSY;
- goto scrop_unlock_and_return;
+ return res;
}
if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
@@ -2602,7 +2445,7 @@ static int zoran_s_crop(struct file *file, void *__fh, const struct v4l2_crop *c
"%s: VIDIOC_G_CROP - subcapture only supported for compressed capture\n",
ZR_DEVNAME(zr));
res = -EINVAL;
- goto scrop_unlock_and_return;
+ return res;
}
/* move into a form that we understand */
@@ -2614,13 +2457,10 @@ static int zoran_s_crop(struct file *file, void *__fh, const struct v4l2_crop *c
/* check validity */
res = zoran_check_jpg_settings(zr, &settings, 0);
if (res)
- goto scrop_unlock_and_return;
+ return res;
/* accept */
fh->jpg_settings = settings;
-
-scrop_unlock_and_return:
- mutex_unlock(&zr->resource_lock);
return res;
}
@@ -2628,11 +2468,8 @@ static int zoran_g_jpegcomp(struct file *file, void *__fh,
struct v4l2_jpegcompression *params)
{
struct zoran_fh *fh = __fh;
- struct zoran *zr = fh->zr;
memset(params, 0, sizeof(*params));
- mutex_lock(&zr->resource_lock);
-
params->quality = fh->jpg_settings.jpg_comp.quality;
params->APPn = fh->jpg_settings.jpg_comp.APPn;
memcpy(params->APP_data,
@@ -2646,8 +2483,6 @@ static int zoran_g_jpegcomp(struct file *file, void *__fh,
params->jpeg_markers =
fh->jpg_settings.jpg_comp.jpeg_markers;
- mutex_unlock(&zr->resource_lock);
-
return 0;
}
@@ -2663,26 +2498,21 @@ static int zoran_s_jpegcomp(struct file *file, void *__fh,
settings.jpg_comp = *params;
- mutex_lock(&zr->resource_lock);
-
if (fh->buffers.active != ZORAN_FREE) {
dprintk(1, KERN_WARNING
"%s: VIDIOC_S_JPEGCOMP called while in playback/capture mode\n",
ZR_DEVNAME(zr));
res = -EBUSY;
- goto sjpegc_unlock_and_return;
+ return res;
}
res = zoran_check_jpg_settings(zr, &settings, 0);
if (res)
- goto sjpegc_unlock_and_return;
+ return res;
if (!fh->buffers.allocated)
fh->buffers.buffer_size =
zoran_v4l2_calc_bufsize(&fh->jpg_settings);
fh->jpg_settings.jpg_comp = settings.jpg_comp;
-sjpegc_unlock_and_return:
- mutex_unlock(&zr->resource_lock);
-
return res;
}
@@ -2692,7 +2522,8 @@ zoran_poll (struct file *file,
{
struct zoran_fh *fh = file->private_data;
struct zoran *zr = fh->zr;
- int res = 0, frame;
+ int res = v4l2_ctrl_poll(file, wait);
+ int frame;
unsigned long flags;
/* we should check whether buffers are ready to be synced on
@@ -2703,8 +2534,6 @@ zoran_poll (struct file *file,
* if no buffers queued or so, return POLLNVAL
*/
- mutex_lock(&zr->resource_lock);
-
switch (fh->map_mode) {
case ZORAN_MAP_MODE_RAW:
poll_wait(file, &zr->v4l_capq, wait);
@@ -2722,7 +2551,7 @@ zoran_poll (struct file *file,
if (fh->buffers.active != ZORAN_FREE &&
/* Buffer ready to DQBUF? */
zr->v4l_buffers.buffer[frame].state == BUZ_STATE_DONE)
- res = POLLIN | POLLRDNORM;
+ res |= POLLIN | POLLRDNORM;
spin_unlock_irqrestore(&zr->spinlock, flags);
break;
@@ -2743,9 +2572,9 @@ zoran_poll (struct file *file,
if (fh->buffers.active != ZORAN_FREE &&
zr->jpg_buffers.buffer[frame].state == BUZ_STATE_DONE) {
if (fh->map_mode == ZORAN_MAP_MODE_JPG_REC)
- res = POLLIN | POLLRDNORM;
+ res |= POLLIN | POLLRDNORM;
else
- res = POLLOUT | POLLWRNORM;
+ res |= POLLOUT | POLLWRNORM;
}
spin_unlock_irqrestore(&zr->spinlock, flags);
@@ -2756,11 +2585,9 @@ zoran_poll (struct file *file,
KERN_ERR
"%s: %s - internal error, unknown map_mode=%d\n",
ZR_DEVNAME(zr), __func__, fh->map_mode);
- res = POLLNVAL;
+ res |= POLLERR;
}
- mutex_unlock(&zr->resource_lock);
-
return res;
}
@@ -2792,9 +2619,6 @@ zoran_vm_close (struct vm_area_struct *vma)
struct zoran *zr = fh->zr;
int i;
- if (!atomic_dec_and_mutex_lock(&map->count, &zr->resource_lock))
- return;
-
dprintk(3, KERN_INFO "%s: %s - munmap(%s)\n", ZR_DEVNAME(zr),
__func__, mode_name(fh->map_mode));
@@ -2807,7 +2631,6 @@ zoran_vm_close (struct vm_area_struct *vma)
/* Any buffers still mapped? */
for (i = 0; i < fh->buffers.num_buffers; i++) {
if (fh->buffers.buffer[i].map) {
- mutex_unlock(&zr->resource_lock);
return;
}
}
@@ -2815,7 +2638,6 @@ zoran_vm_close (struct vm_area_struct *vma)
dprintk(3, KERN_INFO "%s: %s - free %s buffers\n", ZR_DEVNAME(zr),
__func__, mode_name(fh->map_mode));
-
if (fh->map_mode == ZORAN_MAP_MODE_RAW) {
if (fh->buffers.active != ZORAN_FREE) {
unsigned long flags;
@@ -2835,8 +2657,6 @@ zoran_vm_close (struct vm_area_struct *vma)
}
jpg_fbuffer_free(fh);
}
-
- mutex_unlock(&zr->resource_lock);
}
static const struct vm_operations_struct zoran_vm_ops = {
@@ -2872,15 +2692,13 @@ zoran_mmap (struct file *file,
return -EINVAL;
}
- mutex_lock(&zr->resource_lock);
-
if (!fh->buffers.allocated) {
dprintk(1,
KERN_ERR
"%s: %s(%s) - buffers not yet allocated\n",
ZR_DEVNAME(zr), __func__, mode_name(fh->map_mode));
res = -ENOMEM;
- goto mmap_unlock_and_return;
+ return res;
}
first = offset / fh->buffers.buffer_size;
@@ -2896,7 +2714,7 @@ zoran_mmap (struct file *file,
fh->buffers.buffer_size,
fh->buffers.num_buffers);
res = -EINVAL;
- goto mmap_unlock_and_return;
+ return res;
}
/* Check if any buffers are already mapped */
@@ -2907,7 +2725,7 @@ zoran_mmap (struct file *file,
"%s: %s(%s) - buffer %d already mapped\n",
ZR_DEVNAME(zr), __func__, mode_name(fh->map_mode), i);
res = -EBUSY;
- goto mmap_unlock_and_return;
+ return res;
}
}
@@ -2915,7 +2733,7 @@ zoran_mmap (struct file *file,
map = kmalloc(sizeof(struct zoran_mapping), GFP_KERNEL);
if (!map) {
res = -ENOMEM;
- goto mmap_unlock_and_return;
+ return res;
}
map->fh = fh;
atomic_set(&map->count, 1);
@@ -2937,7 +2755,7 @@ zoran_mmap (struct file *file,
"%s: %s(V4L) - remap_pfn_range failed\n",
ZR_DEVNAME(zr), __func__);
res = -EAGAIN;
- goto mmap_unlock_and_return;
+ return res;
}
size -= todo;
start += todo;
@@ -2969,7 +2787,7 @@ zoran_mmap (struct file *file,
"%s: %s(V4L) - remap_pfn_range failed\n",
ZR_DEVNAME(zr), __func__);
res = -EAGAIN;
- goto mmap_unlock_and_return;
+ return res;
}
size -= todo;
start += todo;
@@ -2985,10 +2803,6 @@ zoran_mmap (struct file *file,
}
}
-
-mmap_unlock_and_return:
- mutex_unlock(&zr->resource_lock);
-
return res;
}
@@ -3028,33 +2842,15 @@ static const struct v4l2_ioctl_ops zoran_ioctl_ops = {
.vidioc_try_fmt_vid_cap = zoran_try_fmt_vid_cap,
.vidioc_try_fmt_vid_out = zoran_try_fmt_vid_out,
.vidioc_try_fmt_vid_overlay = zoran_try_fmt_vid_overlay,
- .vidioc_queryctrl = zoran_queryctrl,
- .vidioc_s_ctrl = zoran_s_ctrl,
- .vidioc_g_ctrl = zoran_g_ctrl,
+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
};
-/* please use zr->resource_lock consistently and kill this wrapper */
-static long zoran_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- struct zoran_fh *fh = file->private_data;
- struct zoran *zr = fh->zr;
- int ret;
-
- mutex_lock(&zr->other_lock);
- ret = video_ioctl2(file, cmd, arg);
- mutex_unlock(&zr->other_lock);
-
- return ret;
-}
-
static const struct v4l2_file_operations zoran_fops = {
.owner = THIS_MODULE,
.open = zoran_open,
.release = zoran_close,
- .unlocked_ioctl = zoran_ioctl,
- .read = zoran_read,
- .write = zoran_write,
+ .unlocked_ioctl = video_ioctl2,
.mmap = zoran_mmap,
.poll = zoran_poll,
};