summaryrefslogtreecommitdiffstats
path: root/drivers/media/pci
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/pci')
-rw-r--r--drivers/media/pci/Kconfig4
-rw-r--r--drivers/media/pci/Makefile6
-rw-r--r--drivers/media/pci/cx18/cx18-av-audio.c2
-rw-r--r--drivers/media/pci/cx18/cx18-firmware.c2
-rw-r--r--drivers/media/pci/cx23885/cx23885-core.c3
-rw-r--r--drivers/media/pci/cx23885/cx23888-ir.c2
-rw-r--r--drivers/media/pci/cx88/cx88-dsp.c2
-rw-r--r--drivers/media/pci/cx88/cx88-vbi.c9
-rw-r--r--drivers/media/pci/cx88/cx88-video.c43
-rw-r--r--drivers/media/pci/ivtv/ivtv-yuv.c2
-rw-r--r--drivers/media/pci/meye/Kconfig16
-rw-r--r--drivers/media/pci/meye/Makefile2
-rw-r--r--drivers/media/pci/meye/meye.c1814
-rw-r--r--drivers/media/pci/meye/meye.h311
-rw-r--r--drivers/media/pci/ngene/ngene.h78
-rw-r--r--drivers/media/pci/saa7146/Kconfig39
-rw-r--r--drivers/media/pci/saa7146/Makefile6
-rw-r--r--drivers/media/pci/saa7146/hexium_gemini.c425
-rw-r--r--drivers/media/pci/saa7146/hexium_orion.c496
-rw-r--r--drivers/media/pci/saa7146/mxb.c873
-rw-r--r--drivers/media/pci/saa7164/saa7164-core.c2
-rw-r--r--drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c2
-rw-r--r--drivers/media/pci/ttpci/Kconfig86
-rw-r--r--drivers/media/pci/ttpci/Makefile13
-rw-r--r--drivers/media/pci/ttpci/budget-av.c1622
-rw-r--r--drivers/media/pci/ttpci/budget-ci.c1574
-rw-r--r--drivers/media/pci/ttpci/budget-core.c603
-rw-r--r--drivers/media/pci/ttpci/budget.c883
-rw-r--r--drivers/media/pci/ttpci/budget.h129
-rw-r--r--drivers/media/pci/zoran/Kconfig74
-rw-r--r--drivers/media/pci/zoran/Makefile7
-rw-r--r--drivers/media/pci/zoran/videocodec.c278
-rw-r--r--drivers/media/pci/zoran/videocodec.h325
-rw-r--r--drivers/media/pci/zoran/zoran.h328
-rw-r--r--drivers/media/pci/zoran/zoran_card.c1440
-rw-r--r--drivers/media/pci/zoran/zoran_card.h29
-rw-r--r--drivers/media/pci/zoran/zoran_device.c956
-rw-r--r--drivers/media/pci/zoran/zoran_device.h60
-rw-r--r--drivers/media/pci/zoran/zoran_driver.c986
-rw-r--r--drivers/media/pci/zoran/zr36016.c406
-rw-r--r--drivers/media/pci/zoran/zr36016.h94
-rw-r--r--drivers/media/pci/zoran/zr36050.c817
-rw-r--r--drivers/media/pci/zoran/zr36050.h165
-rw-r--r--drivers/media/pci/zoran/zr36057.h154
-rw-r--r--drivers/media/pci/zoran/zr36060.c870
-rw-r--r--drivers/media/pci/zoran/zr36060.h203
46 files changed, 7231 insertions, 9010 deletions
diff --git a/drivers/media/pci/Kconfig b/drivers/media/pci/Kconfig
index 1224d908713a..dff0b450f387 100644
--- a/drivers/media/pci/Kconfig
+++ b/drivers/media/pci/Kconfig
@@ -13,12 +13,12 @@ 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/tw5864/Kconfig"
source "drivers/media/pci/tw68/Kconfig"
source "drivers/media/pci/tw686x/Kconfig"
+source "drivers/media/pci/zoran/Kconfig"
endif
@@ -27,7 +27,6 @@ if MEDIA_ANALOG_TV_SUPPORT
source "drivers/media/pci/dt3155/Kconfig"
source "drivers/media/pci/ivtv/Kconfig"
-source "drivers/media/pci/saa7146/Kconfig"
endif
@@ -58,7 +57,6 @@ source "drivers/media/pci/pluto2/Kconfig"
source "drivers/media/pci/pt1/Kconfig"
source "drivers/media/pci/pt3/Kconfig"
source "drivers/media/pci/smipcie/Kconfig"
-source "drivers/media/pci/ttpci/Kconfig"
endif
diff --git a/drivers/media/pci/Makefile b/drivers/media/pci/Makefile
index 551169a3e434..8f887a8a7f17 100644
--- a/drivers/media/pci/Makefile
+++ b/drivers/media/pci/Makefile
@@ -5,8 +5,7 @@
# Please keep it alphabetically sorted by directory
# (e. g. LC_ALL=C sort Makefile)
-obj-y += ttpci/ \
- b2c2/ \
+obj-y += b2c2/ \
pluto2/ \
dm1105/ \
pt1/ \
@@ -14,7 +13,6 @@ obj-y += ttpci/ \
mantis/ \
ngene/ \
ddbridge/ \
- saa7146/ \
smipcie/ \
netup_unidvb/ \
intel/
@@ -32,10 +30,10 @@ obj-$(CONFIG_VIDEO_CX25821) += cx25821/
obj-$(CONFIG_VIDEO_CX88) += cx88/
obj-$(CONFIG_VIDEO_DT3155) += dt3155/
obj-$(CONFIG_VIDEO_IVTV) += ivtv/
-obj-$(CONFIG_VIDEO_MEYE) += meye/
obj-$(CONFIG_VIDEO_SAA7134) += saa7134/
obj-$(CONFIG_VIDEO_SAA7164) += saa7164/
obj-$(CONFIG_VIDEO_SOLO6X10) += solo6x10/
obj-$(CONFIG_VIDEO_TW5864) += tw5864/
obj-$(CONFIG_VIDEO_TW686X) += tw686x/
obj-$(CONFIG_VIDEO_TW68) += tw68/
+obj-$(CONFIG_VIDEO_ZORAN) += zoran/
diff --git a/drivers/media/pci/cx18/cx18-av-audio.c b/drivers/media/pci/cx18/cx18-av-audio.c
index 833baa934448..78e05df9a7ba 100644
--- a/drivers/media/pci/cx18/cx18-av-audio.c
+++ b/drivers/media/pci/cx18/cx18-av-audio.c
@@ -50,7 +50,7 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
*
* Many thanks to Jeff Campbell and Mike Bradley for their extensive
* investigation, experimentation, testing, and suggested solutions of
- * of audio/video sync problems with SVideo and CVBS captures.
+ * audio/video sync problems with SVideo and CVBS captures.
*/
if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
diff --git a/drivers/media/pci/cx18/cx18-firmware.c b/drivers/media/pci/cx18/cx18-firmware.c
index fdac310d7477..1b038b2802bf 100644
--- a/drivers/media/pci/cx18/cx18-firmware.c
+++ b/drivers/media/pci/cx18/cx18-firmware.c
@@ -248,7 +248,7 @@ void cx18_init_power(struct cx18 *cx, int lowpwr)
*
* Many thanks to Jeff Campbell and Mike Bradley for their extensive
* investigation, experimentation, testing, and suggested solutions of
- * of audio/video sync problems with SVideo and CVBS captures.
+ * audio/video sync problems with SVideo and CVBS captures.
*/
/* the fast clock is at 200/245 MHz */
diff --git a/drivers/media/pci/cx23885/cx23885-core.c b/drivers/media/pci/cx23885/cx23885-core.c
index a07b18f2034e..9232a966bcab 100644
--- a/drivers/media/pci/cx23885/cx23885-core.c
+++ b/drivers/media/pci/cx23885/cx23885-core.c
@@ -2086,6 +2086,9 @@ static struct {
/* 0x1419 is the PCI ID for the IOMMU found on 15h (Models 10h-1fh) family
*/
{ PCI_VENDOR_ID_AMD, 0x1419 },
+ /* 0x1631 is the PCI ID for the IOMMU found on Renoir/Cezanne
+ */
+ { PCI_VENDOR_ID_AMD, 0x1631 },
/* 0x5a23 is the PCI ID for the IOMMU found on RD890S/RD990
*/
{ PCI_VENDOR_ID_ATI, 0x5a23 },
diff --git a/drivers/media/pci/cx23885/cx23888-ir.c b/drivers/media/pci/cx23885/cx23888-ir.c
index ddfd2eb37484..222d04421468 100644
--- a/drivers/media/pci/cx23885/cx23888-ir.c
+++ b/drivers/media/pci/cx23885/cx23888-ir.c
@@ -235,7 +235,7 @@ static u32 clock_divider_to_resolution(u16 divider)
{
/*
* Resolution is the duration of 1 tick of the readable portion of
- * of the pulse width counter as read from the FIFO. The two lsb's are
+ * the pulse width counter as read from the FIFO. The two lsb's are
* not readable, hence the << 2. This function returns ns.
*/
return DIV_ROUND_CLOSEST((1 << 2) * ((u32) divider + 1) * 1000,
diff --git a/drivers/media/pci/cx88/cx88-dsp.c b/drivers/media/pci/cx88/cx88-dsp.c
index f1e1fc1cb4bd..e378f3b215c7 100644
--- a/drivers/media/pci/cx88/cx88-dsp.c
+++ b/drivers/media/pci/cx88/cx88-dsp.c
@@ -24,7 +24,7 @@
/*
* We calculate the baseband frequencies of the carrier and the pilot tones
- * based on the the sampling rate of the audio rds fifo.
+ * based on the sampling rate of the audio rds fifo.
*/
#define FREQ_A2_CARRIER baseband_freq(54687.5, 2689.36, 0.0)
diff --git a/drivers/media/pci/cx88/cx88-vbi.c b/drivers/media/pci/cx88/cx88-vbi.c
index a075788c64d4..469aeaa725ad 100644
--- a/drivers/media/pci/cx88/cx88-vbi.c
+++ b/drivers/media/pci/cx88/cx88-vbi.c
@@ -144,11 +144,10 @@ static int buffer_prepare(struct vb2_buffer *vb)
return -EINVAL;
vb2_set_plane_payload(vb, 0, size);
- cx88_risc_buffer(dev->pci, &buf->risc, sgt->sgl,
- 0, VBI_LINE_LENGTH * lines,
- VBI_LINE_LENGTH, 0,
- lines);
- return 0;
+ return cx88_risc_buffer(dev->pci, &buf->risc, sgt->sgl,
+ 0, VBI_LINE_LENGTH * lines,
+ VBI_LINE_LENGTH, 0,
+ lines);
}
static void buffer_finish(struct vb2_buffer *vb)
diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c
index d3729be89252..b509c2a03852 100644
--- a/drivers/media/pci/cx88/cx88-video.c
+++ b/drivers/media/pci/cx88/cx88-video.c
@@ -431,6 +431,7 @@ static int queue_setup(struct vb2_queue *q,
static int buffer_prepare(struct vb2_buffer *vb)
{
+ int ret;
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;
@@ -445,35 +446,35 @@ static int buffer_prepare(struct vb2_buffer *vb)
switch (core->field) {
case V4L2_FIELD_TOP:
- cx88_risc_buffer(dev->pci, &buf->risc,
- sgt->sgl, 0, UNSET,
- buf->bpl, 0, core->height);
+ ret = cx88_risc_buffer(dev->pci, &buf->risc,
+ sgt->sgl, 0, UNSET,
+ buf->bpl, 0, core->height);
break;
case V4L2_FIELD_BOTTOM:
- cx88_risc_buffer(dev->pci, &buf->risc,
- sgt->sgl, UNSET, 0,
- buf->bpl, 0, core->height);
+ ret = cx88_risc_buffer(dev->pci, &buf->risc,
+ sgt->sgl, UNSET, 0,
+ buf->bpl, 0, core->height);
break;
case V4L2_FIELD_SEQ_TB:
- cx88_risc_buffer(dev->pci, &buf->risc,
- sgt->sgl,
- 0, buf->bpl * (core->height >> 1),
- buf->bpl, 0,
- core->height >> 1);
+ ret = cx88_risc_buffer(dev->pci, &buf->risc,
+ sgt->sgl,
+ 0, buf->bpl * (core->height >> 1),
+ buf->bpl, 0,
+ core->height >> 1);
break;
case V4L2_FIELD_SEQ_BT:
- cx88_risc_buffer(dev->pci, &buf->risc,
- sgt->sgl,
- buf->bpl * (core->height >> 1), 0,
- buf->bpl, 0,
- core->height >> 1);
+ ret = cx88_risc_buffer(dev->pci, &buf->risc,
+ sgt->sgl,
+ buf->bpl * (core->height >> 1), 0,
+ buf->bpl, 0,
+ core->height >> 1);
break;
case V4L2_FIELD_INTERLACED:
default:
- cx88_risc_buffer(dev->pci, &buf->risc,
- sgt->sgl, 0, buf->bpl,
- buf->bpl, buf->bpl,
- core->height >> 1);
+ ret = cx88_risc_buffer(dev->pci, &buf->risc,
+ sgt->sgl, 0, buf->bpl,
+ buf->bpl, buf->bpl,
+ core->height >> 1);
break;
}
dprintk(2,
@@ -481,7 +482,7 @@ static int buffer_prepare(struct vb2_buffer *vb)
buf, buf->vb.vb2_buf.index, __func__,
core->width, core->height, dev->fmt->depth, dev->fmt->fourcc,
(unsigned long)buf->risc.dma);
- return 0;
+ return ret;
}
static void buffer_finish(struct vb2_buffer *vb)
diff --git a/drivers/media/pci/ivtv/ivtv-yuv.c b/drivers/media/pci/ivtv/ivtv-yuv.c
index e79e8a5a744a..4ba10c34a16a 100644
--- a/drivers/media/pci/ivtv/ivtv-yuv.c
+++ b/drivers/media/pci/ivtv/ivtv-yuv.c
@@ -538,7 +538,7 @@ static void ivtv_yuv_handle_vertical(struct ivtv *itv, struct yuv_frame_info *f)
reg_2964 = (reg_2964 << 16) + reg_2964 + (reg_2964 * 46 / 94);
/* Okay, we've wasted time working out the correct value,
- but if we use it, it fouls the the window alignment.
+ but if we use it, it fouls the window alignment.
Fudge it to what we want... */
reg_2964 = 0x00010001 + ((reg_2964 & 0x0000FFFF) - (reg_2964 >> 16));
reg_2968 = 0x00010001 + ((reg_2968 & 0x0000FFFF) - (reg_2968 >> 16));
diff --git a/drivers/media/pci/meye/Kconfig b/drivers/media/pci/meye/Kconfig
deleted file mode 100644
index 3e69b66f1a5b..000000000000
--- a/drivers/media/pci/meye/Kconfig
+++ /dev/null
@@ -1,16 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-config VIDEO_MEYE
- tristate "Sony Vaio Picturebook Motion Eye Video For Linux"
- depends on PCI && VIDEO_DEV
- depends on SONY_LAPTOP
- depends on X86 || COMPILE_TEST
- help
- This is the video4linux driver for the Motion Eye camera found
- in the Vaio Picturebook laptops. Please read the material in
- <file:Documentation/admin-guide/media/meye.rst> for more information.
-
- If you say Y or M here, you need to say Y or M to "Sony Laptop
- Extras" in the misc device section.
-
- To compile this driver as a module, choose M here: the
- module will be called meye.
diff --git a/drivers/media/pci/meye/Makefile b/drivers/media/pci/meye/Makefile
deleted file mode 100644
index 36f1f86f0d58..000000000000
--- a/drivers/media/pci/meye/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_VIDEO_MEYE) += meye.o
diff --git a/drivers/media/pci/meye/meye.c b/drivers/media/pci/meye/meye.c
deleted file mode 100644
index 5d87efd9b95c..000000000000
--- a/drivers/media/pci/meye/meye.c
+++ /dev/null
@@ -1,1814 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Motion Eye video4linux driver for Sony Vaio PictureBook
- *
- * Copyright (C) 2001-2004 Stelian Pop <stelian@popies.net>
- *
- * Copyright (C) 2001-2002 AlcĂ´ve <www.alcove.com>
- *
- * Copyright (C) 2000 Andrew Tridgell <tridge@valinux.com>
- *
- * Earlier work by Werner Almesberger, Paul `Rusty' Russell and Paul Mackerras.
- *
- * Some parts borrowed from various video4linux drivers, especially
- * bttv-driver.c and zoran.c, see original files for credits.
- */
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/gfp.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-fh.h>
-#include <media/v4l2-event.h>
-#include <linux/uaccess.h>
-#include <asm/io.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/vmalloc.h>
-#include <linux/dma-mapping.h>
-
-#include "meye.h"
-#include <linux/meye.h>
-
-MODULE_AUTHOR("Stelian Pop <stelian@popies.net>");
-MODULE_DESCRIPTION("v4l2 driver for the MotionEye camera");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(MEYE_DRIVER_VERSION);
-
-/* number of grab buffers */
-static unsigned int gbuffers = 2;
-module_param(gbuffers, int, 0444);
-MODULE_PARM_DESC(gbuffers, "number of capture buffers, default is 2 (32 max)");
-
-/* size of a grab buffer */
-static unsigned int gbufsize = MEYE_MAX_BUFSIZE;
-module_param(gbufsize, int, 0444);
-MODULE_PARM_DESC(gbufsize, "size of the capture buffers, default is 614400 (will be rounded up to a page multiple)");
-
-/* /dev/videoX registration number */
-static int video_nr = -1;
-module_param(video_nr, int, 0444);
-MODULE_PARM_DESC(video_nr, "video device to register (0=/dev/video0, etc)");
-
-/* driver structure - only one possible */
-static struct meye meye;
-
-/****************************************************************************/
-/* Memory allocation routines (stolen from bttv-driver.c) */
-/****************************************************************************/
-static void *rvmalloc(unsigned long size)
-{
- void *mem;
- unsigned long adr;
-
- size = PAGE_ALIGN(size);
- mem = vmalloc_32(size);
- if (mem) {
- memset(mem, 0, size);
- adr = (unsigned long) mem;
- while (size > 0) {
- SetPageReserved(vmalloc_to_page((void *)adr));
- adr += PAGE_SIZE;
- size -= PAGE_SIZE;
- }
- }
- return mem;
-}
-
-static void rvfree(void * mem, unsigned long size)
-{
- unsigned long adr;
-
- if (mem) {
- adr = (unsigned long) mem;
- while ((long) size > 0) {
- ClearPageReserved(vmalloc_to_page((void *)adr));
- adr += PAGE_SIZE;
- size -= PAGE_SIZE;
- }
- vfree(mem);
- }
-}
-
-/*
- * return a page table pointing to N pages of locked memory
- *
- * NOTE: The meye device expects DMA addresses on 32 bits, we build
- * a table of 1024 entries = 4 bytes * 1024 = 4096 bytes.
- */
-static int ptable_alloc(void)
-{
- u32 *pt;
- int i;
-
- memset(meye.mchip_ptable, 0, sizeof(meye.mchip_ptable));
-
- /* give only 32 bit DMA addresses */
- if (dma_set_mask(&meye.mchip_dev->dev, DMA_BIT_MASK(32)))
- return -1;
-
- meye.mchip_ptable_toc = dma_alloc_coherent(&meye.mchip_dev->dev,
- PAGE_SIZE,
- &meye.mchip_dmahandle,
- GFP_KERNEL);
- if (!meye.mchip_ptable_toc) {
- meye.mchip_dmahandle = 0;
- return -1;
- }
-
- pt = meye.mchip_ptable_toc;
- for (i = 0; i < MCHIP_NB_PAGES; i++) {
- dma_addr_t dma;
- meye.mchip_ptable[i] = dma_alloc_coherent(&meye.mchip_dev->dev,
- PAGE_SIZE,
- &dma,
- GFP_KERNEL);
- if (!meye.mchip_ptable[i]) {
- int j;
- pt = meye.mchip_ptable_toc;
- for (j = 0; j < i; ++j) {
- dma = (dma_addr_t) *pt;
- dma_free_coherent(&meye.mchip_dev->dev,
- PAGE_SIZE,
- meye.mchip_ptable[j], dma);
- pt++;
- }
- dma_free_coherent(&meye.mchip_dev->dev,
- PAGE_SIZE,
- meye.mchip_ptable_toc,
- meye.mchip_dmahandle);
- meye.mchip_ptable_toc = NULL;
- meye.mchip_dmahandle = 0;
- return -1;
- }
- *pt = (u32) dma;
- pt++;
- }
- return 0;
-}
-
-static void ptable_free(void)
-{
- u32 *pt;
- int i;
-
- pt = meye.mchip_ptable_toc;
- for (i = 0; i < MCHIP_NB_PAGES; i++) {
- dma_addr_t dma = (dma_addr_t) *pt;
- if (meye.mchip_ptable[i])
- dma_free_coherent(&meye.mchip_dev->dev,
- PAGE_SIZE,
- meye.mchip_ptable[i], dma);
- pt++;
- }
-
- if (meye.mchip_ptable_toc)
- dma_free_coherent(&meye.mchip_dev->dev,
- PAGE_SIZE,
- meye.mchip_ptable_toc,
- meye.mchip_dmahandle);
-
- memset(meye.mchip_ptable, 0, sizeof(meye.mchip_ptable));
- meye.mchip_ptable_toc = NULL;
- meye.mchip_dmahandle = 0;
-}
-
-/* copy data from ptable into buf */
-static void ptable_copy(u8 *buf, int start, int size, int pt_pages)
-{
- int i;
-
- for (i = 0; i < (size / PAGE_SIZE) * PAGE_SIZE; i += PAGE_SIZE) {
- memcpy(buf + i, meye.mchip_ptable[start++], PAGE_SIZE);
- if (start >= pt_pages)
- start = 0;
- }
- memcpy(buf + i, meye.mchip_ptable[start], size % PAGE_SIZE);
-}
-
-/****************************************************************************/
-/* JPEG tables at different qualities to load into the VRJ chip */
-/****************************************************************************/
-
-/* return a set of quantisation tables based on a quality from 1 to 10 */
-static u16 *jpeg_quantisation_tables(int *length, int quality)
-{
- static u16 jpeg_tables[][70] = { {
- 0xdbff, 0x4300, 0xff00, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0xffff,
- 0xdbff, 0x4300, 0xff01, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0xffff,
- },
- {
- 0xdbff, 0x4300, 0x5000, 0x3c37, 0x3c46, 0x5032, 0x4146, 0x5a46,
- 0x5055, 0x785f, 0x82c8, 0x6e78, 0x786e, 0xaff5, 0x91b9, 0xffc8,
- 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0xffff,
- 0xdbff, 0x4300, 0x5501, 0x5a5a, 0x6978, 0xeb78, 0x8282, 0xffeb,
- 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0xffff,
- },
- {
- 0xdbff, 0x4300, 0x2800, 0x1e1c, 0x1e23, 0x2819, 0x2123, 0x2d23,
- 0x282b, 0x3c30, 0x4164, 0x373c, 0x3c37, 0x587b, 0x495d, 0x9164,
- 0x9980, 0x8f96, 0x8c80, 0xa08a, 0xe6b4, 0xa0c3, 0xdaaa, 0x8aad,
- 0xc88c, 0xcbff, 0xeeda, 0xfff5, 0xffff, 0xc19b, 0xffff, 0xfaff,
- 0xe6ff, 0xfffd, 0xfff8,
- 0xdbff, 0x4300, 0x2b01, 0x2d2d, 0x353c, 0x763c, 0x4141, 0xf876,
- 0x8ca5, 0xf8a5, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8,
- 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8,
- 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8,
- 0xf8f8, 0xf8f8, 0xfff8,
- },
- {
- 0xdbff, 0x4300, 0x1b00, 0x1412, 0x1417, 0x1b11, 0x1617, 0x1e17,
- 0x1b1c, 0x2820, 0x2b42, 0x2528, 0x2825, 0x3a51, 0x303d, 0x6042,
- 0x6555, 0x5f64, 0x5d55, 0x6a5b, 0x9978, 0x6a81, 0x9071, 0x5b73,
- 0x855d, 0x86b5, 0x9e90, 0xaba3, 0xabad, 0x8067, 0xc9bc, 0xa6ba,
- 0x99c7, 0xaba8, 0xffa4,
- 0xdbff, 0x4300, 0x1c01, 0x1e1e, 0x2328, 0x4e28, 0x2b2b, 0xa44e,
- 0x5d6e, 0xa46e, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
- 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
- 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
- 0xa4a4, 0xa4a4, 0xffa4,
- },
- {
- 0xdbff, 0x4300, 0x1400, 0x0f0e, 0x0f12, 0x140d, 0x1012, 0x1712,
- 0x1415, 0x1e18, 0x2132, 0x1c1e, 0x1e1c, 0x2c3d, 0x242e, 0x4932,
- 0x4c40, 0x474b, 0x4640, 0x5045, 0x735a, 0x5062, 0x6d55, 0x4556,
- 0x6446, 0x6588, 0x776d, 0x817b, 0x8182, 0x604e, 0x978d, 0x7d8c,
- 0x7396, 0x817e, 0xff7c,
- 0xdbff, 0x4300, 0x1501, 0x1717, 0x1a1e, 0x3b1e, 0x2121, 0x7c3b,
- 0x4653, 0x7c53, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c,
- 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c,
- 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c,
- 0x7c7c, 0x7c7c, 0xff7c,
- },
- {
- 0xdbff, 0x4300, 0x1000, 0x0c0b, 0x0c0e, 0x100a, 0x0d0e, 0x120e,
- 0x1011, 0x1813, 0x1a28, 0x1618, 0x1816, 0x2331, 0x1d25, 0x3a28,
- 0x3d33, 0x393c, 0x3833, 0x4037, 0x5c48, 0x404e, 0x5744, 0x3745,
- 0x5038, 0x516d, 0x5f57, 0x6762, 0x6768, 0x4d3e, 0x7971, 0x6470,
- 0x5c78, 0x6765, 0xff63,
- 0xdbff, 0x4300, 0x1101, 0x1212, 0x1518, 0x2f18, 0x1a1a, 0x632f,
- 0x3842, 0x6342, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363,
- 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363,
- 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363,
- 0x6363, 0x6363, 0xff63,
- },
- {
- 0xdbff, 0x4300, 0x0d00, 0x0a09, 0x0a0b, 0x0d08, 0x0a0b, 0x0e0b,
- 0x0d0e, 0x130f, 0x1520, 0x1213, 0x1312, 0x1c27, 0x171e, 0x2e20,
- 0x3129, 0x2e30, 0x2d29, 0x332c, 0x4a3a, 0x333e, 0x4636, 0x2c37,
- 0x402d, 0x4157, 0x4c46, 0x524e, 0x5253, 0x3e32, 0x615a, 0x505a,
- 0x4a60, 0x5251, 0xff4f,
- 0xdbff, 0x4300, 0x0e01, 0x0e0e, 0x1113, 0x2613, 0x1515, 0x4f26,
- 0x2d35, 0x4f35, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f,
- 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f,
- 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f,
- 0x4f4f, 0x4f4f, 0xff4f,
- },
- {
- 0xdbff, 0x4300, 0x0a00, 0x0707, 0x0708, 0x0a06, 0x0808, 0x0b08,
- 0x0a0a, 0x0e0b, 0x1018, 0x0d0e, 0x0e0d, 0x151d, 0x1116, 0x2318,
- 0x251f, 0x2224, 0x221f, 0x2621, 0x372b, 0x262f, 0x3429, 0x2129,
- 0x3022, 0x3141, 0x3934, 0x3e3b, 0x3e3e, 0x2e25, 0x4944, 0x3c43,
- 0x3748, 0x3e3d, 0xff3b,
- 0xdbff, 0x4300, 0x0a01, 0x0b0b, 0x0d0e, 0x1c0e, 0x1010, 0x3b1c,
- 0x2228, 0x3b28, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b,
- 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b,
- 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b,
- 0x3b3b, 0x3b3b, 0xff3b,
- },
- {
- 0xdbff, 0x4300, 0x0600, 0x0504, 0x0506, 0x0604, 0x0506, 0x0706,
- 0x0607, 0x0a08, 0x0a10, 0x090a, 0x0a09, 0x0e14, 0x0c0f, 0x1710,
- 0x1814, 0x1718, 0x1614, 0x1a16, 0x251d, 0x1a1f, 0x231b, 0x161c,
- 0x2016, 0x202c, 0x2623, 0x2927, 0x292a, 0x1f19, 0x302d, 0x282d,
- 0x2530, 0x2928, 0xff28,
- 0xdbff, 0x4300, 0x0701, 0x0707, 0x080a, 0x130a, 0x0a0a, 0x2813,
- 0x161a, 0x281a, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828,
- 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828,
- 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828,
- 0x2828, 0x2828, 0xff28,
- },
- {
- 0xdbff, 0x4300, 0x0300, 0x0202, 0x0203, 0x0302, 0x0303, 0x0403,
- 0x0303, 0x0504, 0x0508, 0x0405, 0x0504, 0x070a, 0x0607, 0x0c08,
- 0x0c0a, 0x0b0c, 0x0b0a, 0x0d0b, 0x120e, 0x0d10, 0x110e, 0x0b0e,
- 0x100b, 0x1016, 0x1311, 0x1514, 0x1515, 0x0f0c, 0x1817, 0x1416,
- 0x1218, 0x1514, 0xff14,
- 0xdbff, 0x4300, 0x0301, 0x0404, 0x0405, 0x0905, 0x0505, 0x1409,
- 0x0b0d, 0x140d, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414,
- 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414,
- 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414,
- 0x1414, 0x1414, 0xff14,
- },
- {
- 0xdbff, 0x4300, 0x0100, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
- 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
- 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
- 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
- 0x0101, 0x0101, 0xff01,
- 0xdbff, 0x4300, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
- 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
- 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
- 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
- 0x0101, 0x0101, 0xff01,
- } };
-
- if (quality < 0 || quality > 10) {
- printk(KERN_WARNING
- "meye: invalid quality level %d - using 8\n", quality);
- quality = 8;
- }
-
- *length = ARRAY_SIZE(jpeg_tables[quality]);
- return jpeg_tables[quality];
-}
-
-/* return a generic set of huffman tables */
-static u16 *jpeg_huffman_tables(int *length)
-{
- static u16 tables[] = {
- 0xC4FF, 0xB500, 0x0010, 0x0102, 0x0303, 0x0402, 0x0503, 0x0405,
- 0x0004, 0x0100, 0x017D, 0x0302, 0x0400, 0x0511, 0x2112, 0x4131,
- 0x1306, 0x6151, 0x2207, 0x1471, 0x8132, 0xA191, 0x2308, 0xB142,
- 0x15C1, 0xD152, 0x24F0, 0x6233, 0x8272, 0x0A09, 0x1716, 0x1918,
- 0x251A, 0x2726, 0x2928, 0x342A, 0x3635, 0x3837, 0x3A39, 0x4443,
- 0x4645, 0x4847, 0x4A49, 0x5453, 0x5655, 0x5857, 0x5A59, 0x6463,
- 0x6665, 0x6867, 0x6A69, 0x7473, 0x7675, 0x7877, 0x7A79, 0x8483,
- 0x8685, 0x8887, 0x8A89, 0x9392, 0x9594, 0x9796, 0x9998, 0xA29A,
- 0xA4A3, 0xA6A5, 0xA8A7, 0xAAA9, 0xB3B2, 0xB5B4, 0xB7B6, 0xB9B8,
- 0xC2BA, 0xC4C3, 0xC6C5, 0xC8C7, 0xCAC9, 0xD3D2, 0xD5D4, 0xD7D6,
- 0xD9D8, 0xE1DA, 0xE3E2, 0xE5E4, 0xE7E6, 0xE9E8, 0xF1EA, 0xF3F2,
- 0xF5F4, 0xF7F6, 0xF9F8, 0xFFFA,
- 0xC4FF, 0xB500, 0x0011, 0x0102, 0x0402, 0x0304, 0x0704, 0x0405,
- 0x0004, 0x0201, 0x0077, 0x0201, 0x1103, 0x0504, 0x3121, 0x1206,
- 0x5141, 0x6107, 0x1371, 0x3222, 0x0881, 0x4214, 0xA191, 0xC1B1,
- 0x2309, 0x5233, 0x15F0, 0x7262, 0x0AD1, 0x2416, 0xE134, 0xF125,
- 0x1817, 0x1A19, 0x2726, 0x2928, 0x352A, 0x3736, 0x3938, 0x433A,
- 0x4544, 0x4746, 0x4948, 0x534A, 0x5554, 0x5756, 0x5958, 0x635A,
- 0x6564, 0x6766, 0x6968, 0x736A, 0x7574, 0x7776, 0x7978, 0x827A,
- 0x8483, 0x8685, 0x8887, 0x8A89, 0x9392, 0x9594, 0x9796, 0x9998,
- 0xA29A, 0xA4A3, 0xA6A5, 0xA8A7, 0xAAA9, 0xB3B2, 0xB5B4, 0xB7B6,
- 0xB9B8, 0xC2BA, 0xC4C3, 0xC6C5, 0xC8C7, 0xCAC9, 0xD3D2, 0xD5D4,
- 0xD7D6, 0xD9D8, 0xE2DA, 0xE4E3, 0xE6E5, 0xE8E7, 0xEAE9, 0xF3F2,
- 0xF5F4, 0xF7F6, 0xF9F8, 0xFFFA,
- 0xC4FF, 0x1F00, 0x0000, 0x0501, 0x0101, 0x0101, 0x0101, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0201, 0x0403, 0x0605, 0x0807, 0x0A09,
- 0xFF0B,
- 0xC4FF, 0x1F00, 0x0001, 0x0103, 0x0101, 0x0101, 0x0101, 0x0101,
- 0x0000, 0x0000, 0x0000, 0x0201, 0x0403, 0x0605, 0x0807, 0x0A09,
- 0xFF0B
- };
-
- *length = ARRAY_SIZE(tables);
- return tables;
-}
-
-/****************************************************************************/
-/* MCHIP low-level functions */
-/****************************************************************************/
-
-/* returns the horizontal capture size */
-static inline int mchip_hsize(void)
-{
- return meye.params.subsample ? 320 : 640;
-}
-
-/* returns the vertical capture size */
-static inline int mchip_vsize(void)
-{
- return meye.params.subsample ? 240 : 480;
-}
-
-/* waits for a register to be available */
-static void mchip_sync(int reg)
-{
- u32 status;
- int i;
-
- if (reg == MCHIP_MM_FIFO_DATA) {
- for (i = 0; i < MCHIP_REG_TIMEOUT; i++) {
- status = readl(meye.mchip_mmregs +
- MCHIP_MM_FIFO_STATUS);
- if (!(status & MCHIP_MM_FIFO_WAIT)) {
- printk(KERN_WARNING "meye: fifo not ready\n");
- return;
- }
- if (status & MCHIP_MM_FIFO_READY)
- return;
- udelay(1);
- }
- } else if (reg > 0x80) {
- u32 mask = (reg < 0x100) ? MCHIP_HIC_STATUS_MCC_RDY
- : MCHIP_HIC_STATUS_VRJ_RDY;
- for (i = 0; i < MCHIP_REG_TIMEOUT; i++) {
- status = readl(meye.mchip_mmregs + MCHIP_HIC_STATUS);
- if (status & mask)
- return;
- udelay(1);
- }
- } else
- return;
- printk(KERN_WARNING
- "meye: mchip_sync() timeout on reg 0x%x status=0x%x\n",
- reg, status);
-}
-
-/* sets a value into the register */
-static inline void mchip_set(int reg, u32 v)
-{
- mchip_sync(reg);
- writel(v, meye.mchip_mmregs + reg);
-}
-
-/* get the register value */
-static inline u32 mchip_read(int reg)
-{
- mchip_sync(reg);
- return readl(meye.mchip_mmregs + reg);
-}
-
-/* wait for a register to become a particular value */
-static inline int mchip_delay(u32 reg, u32 v)
-{
- int n = 10;
- while (--n && mchip_read(reg) != v)
- udelay(1);
- return n;
-}
-
-/* setup subsampling */
-static void mchip_subsample(void)
-{
- mchip_set(MCHIP_MCC_R_SAMPLING, meye.params.subsample);
- mchip_set(MCHIP_MCC_R_XRANGE, mchip_hsize());
- mchip_set(MCHIP_MCC_R_YRANGE, mchip_vsize());
- mchip_set(MCHIP_MCC_B_XRANGE, mchip_hsize());
- mchip_set(MCHIP_MCC_B_YRANGE, mchip_vsize());
- mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE);
-}
-
-/* set the framerate into the mchip */
-static void mchip_set_framerate(void)
-{
- mchip_set(MCHIP_HIC_S_RATE, meye.params.framerate);
-}
-
-/* load some huffman and quantisation tables into the VRJ chip ready
- for JPEG compression */
-static void mchip_load_tables(void)
-{
- int i;
- int length;
- u16 *tables;
-
- tables = jpeg_huffman_tables(&length);
- for (i = 0; i < length; i++)
- writel(tables[i], meye.mchip_mmregs + MCHIP_VRJ_TABLE_DATA);
-
- tables = jpeg_quantisation_tables(&length, meye.params.quality);
- for (i = 0; i < length; i++)
- writel(tables[i], meye.mchip_mmregs + MCHIP_VRJ_TABLE_DATA);
-}
-
-/* setup the VRJ parameters in the chip */
-static void mchip_vrj_setup(u8 mode)
-{
- mchip_set(MCHIP_VRJ_BUS_MODE, 5);
- mchip_set(MCHIP_VRJ_SIGNAL_ACTIVE_LEVEL, 0x1f);
- mchip_set(MCHIP_VRJ_PDAT_USE, 1);
- mchip_set(MCHIP_VRJ_IRQ_FLAG, 0xa0);
- mchip_set(MCHIP_VRJ_MODE_SPECIFY, mode);
- mchip_set(MCHIP_VRJ_NUM_LINES, mchip_vsize());
- mchip_set(MCHIP_VRJ_NUM_PIXELS, mchip_hsize());
- mchip_set(MCHIP_VRJ_NUM_COMPONENTS, 0x1b);
- mchip_set(MCHIP_VRJ_LIMIT_COMPRESSED_LO, 0xFFFF);
- mchip_set(MCHIP_VRJ_LIMIT_COMPRESSED_HI, 0xFFFF);
- mchip_set(MCHIP_VRJ_COMP_DATA_FORMAT, 0xC);
- mchip_set(MCHIP_VRJ_RESTART_INTERVAL, 0);
- mchip_set(MCHIP_VRJ_SOF1, 0x601);
- mchip_set(MCHIP_VRJ_SOF2, 0x1502);
- mchip_set(MCHIP_VRJ_SOF3, 0x1503);
- mchip_set(MCHIP_VRJ_SOF4, 0x1596);
- mchip_set(MCHIP_VRJ_SOS, 0x0ed0);
-
- mchip_load_tables();
-}
-
-/* sets the DMA parameters into the chip */
-static void mchip_dma_setup(dma_addr_t dma_addr)
-{
- int i;
-
- mchip_set(MCHIP_MM_PT_ADDR, (u32)dma_addr);
- for (i = 0; i < 4; i++)
- mchip_set(MCHIP_MM_FIR(i), 0);
- meye.mchip_fnum = 0;
-}
-
-/* setup for DMA transfers - also zeros the framebuffer */
-static int mchip_dma_alloc(void)
-{
- if (!meye.mchip_dmahandle)
- if (ptable_alloc())
- return -1;
- return 0;
-}
-
-/* frees the DMA buffer */
-static void mchip_dma_free(void)
-{
- if (meye.mchip_dmahandle) {
- mchip_dma_setup(0);
- ptable_free();
- }
-}
-
-/* stop any existing HIC action and wait for any dma to complete then
- reset the dma engine */
-static void mchip_hic_stop(void)
-{
- int i, j;
-
- meye.mchip_mode = MCHIP_HIC_MODE_NOOP;
- if (!(mchip_read(MCHIP_HIC_STATUS) & MCHIP_HIC_STATUS_BUSY))
- return;
- for (i = 0; i < 20; ++i) {
- mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_STOP);
- mchip_delay(MCHIP_HIC_CMD, 0);
- for (j = 0; j < 100; ++j) {
- if (mchip_delay(MCHIP_HIC_STATUS,
- MCHIP_HIC_STATUS_IDLE))
- return;
- msleep(1);
- }
- printk(KERN_ERR "meye: need to reset HIC!\n");
-
- mchip_set(MCHIP_HIC_CTL, MCHIP_HIC_CTL_SOFT_RESET);
- msleep(250);
- }
- printk(KERN_ERR "meye: resetting HIC hanged!\n");
-}
-
-/****************************************************************************/
-/* MCHIP frame processing functions */
-/****************************************************************************/
-
-/* get the next ready frame from the dma engine */
-static u32 mchip_get_frame(void)
-{
- return mchip_read(MCHIP_MM_FIR(meye.mchip_fnum));
-}
-
-/* frees the current frame from the dma engine */
-static void mchip_free_frame(void)
-{
- mchip_set(MCHIP_MM_FIR(meye.mchip_fnum), 0);
- meye.mchip_fnum++;
- meye.mchip_fnum %= 4;
-}
-
-/* read one frame from the framebuffer assuming it was captured using
- a uncompressed transfer */
-static void mchip_cont_read_frame(u32 v, u8 *buf, int size)
-{
- int pt_id;
-
- pt_id = (v >> 17) & 0x3FF;
-
- ptable_copy(buf, pt_id, size, MCHIP_NB_PAGES);
-}
-
-/* read a compressed frame from the framebuffer */
-static int mchip_comp_read_frame(u32 v, u8 *buf, int size)
-{
- int pt_start, pt_end, trailer;
- int fsize;
- int i;
-
- pt_start = (v >> 19) & 0xFF;
- pt_end = (v >> 11) & 0xFF;
- trailer = (v >> 1) & 0x3FF;
-
- if (pt_end < pt_start)
- fsize = (MCHIP_NB_PAGES_MJPEG - pt_start) * PAGE_SIZE +
- pt_end * PAGE_SIZE + trailer * 4;
- else
- fsize = (pt_end - pt_start) * PAGE_SIZE + trailer * 4;
-
- if (fsize > size) {
- printk(KERN_WARNING "meye: oversized compressed frame %d\n",
- fsize);
- return -1;
- }
-
- ptable_copy(buf, pt_start, fsize, MCHIP_NB_PAGES_MJPEG);
-
-#ifdef MEYE_JPEG_CORRECTION
-
- /* Some mchip generated jpeg frames are incorrect. In most
- * (all ?) of those cases, the final EOI (0xff 0xd9) marker
- * is not present at the end of the frame.
- *
- * Since adding the final marker is not enough to restore
- * the jpeg integrity, we drop the frame.
- */
-
- for (i = fsize - 1; i > 0 && buf[i] == 0xff; i--) ;
-
- if (i < 2 || buf[i - 1] != 0xff || buf[i] != 0xd9)
- return -1;
-
-#endif
-
- return fsize;
-}
-
-/* take a picture into SDRAM */
-static void mchip_take_picture(void)
-{
- int i;
-
- mchip_hic_stop();
- mchip_subsample();
- mchip_dma_setup(meye.mchip_dmahandle);
-
- mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_STILL_CAP);
- mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START);
-
- mchip_delay(MCHIP_HIC_CMD, 0);
-
- for (i = 0; i < 100; ++i) {
- if (mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE))
- break;
- msleep(1);
- }
-}
-
-/* dma a previously taken picture into a buffer */
-static void mchip_get_picture(u8 *buf, int bufsize)
-{
- u32 v;
- int i;
-
- mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_STILL_OUT);
- mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START);
-
- mchip_delay(MCHIP_HIC_CMD, 0);
- for (i = 0; i < 100; ++i) {
- if (mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE))
- break;
- msleep(1);
- }
- for (i = 0; i < 4; ++i) {
- v = mchip_get_frame();
- if (v & MCHIP_MM_FIR_RDY) {
- mchip_cont_read_frame(v, buf, bufsize);
- break;
- }
- mchip_free_frame();
- }
-}
-
-/* start continuous dma capture */
-static void mchip_continuous_start(void)
-{
- mchip_hic_stop();
- mchip_subsample();
- mchip_set_framerate();
- mchip_dma_setup(meye.mchip_dmahandle);
-
- meye.mchip_mode = MCHIP_HIC_MODE_CONT_OUT;
-
- mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_CONT_OUT);
- mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START);
-
- mchip_delay(MCHIP_HIC_CMD, 0);
-}
-
-/* compress one frame into a buffer */
-static int mchip_compress_frame(u8 *buf, int bufsize)
-{
- u32 v;
- int len = -1, i;
-
- mchip_vrj_setup(0x3f);
- udelay(50);
-
- mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_STILL_COMP);
- mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START);
-
- mchip_delay(MCHIP_HIC_CMD, 0);
- for (i = 0; i < 100; ++i) {
- if (mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE))
- break;
- msleep(1);
- }
-
- for (i = 0; i < 4; ++i) {
- v = mchip_get_frame();
- if (v & MCHIP_MM_FIR_RDY) {
- len = mchip_comp_read_frame(v, buf, bufsize);
- break;
- }
- mchip_free_frame();
- }
- return len;
-}
-
-#if 0
-/* uncompress one image into a buffer */
-static int mchip_uncompress_frame(u8 *img, int imgsize, u8 *buf, int bufsize)
-{
- mchip_vrj_setup(0x3f);
- udelay(50);
-
- mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_STILL_DECOMP);
- mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START);
-
- mchip_delay(MCHIP_HIC_CMD, 0);
-
- return mchip_comp_read_frame(buf, bufsize);
-}
-#endif
-
-/* start continuous compressed capture */
-static void mchip_cont_compression_start(void)
-{
- mchip_hic_stop();
- mchip_vrj_setup(0x3f);
- mchip_subsample();
- mchip_set_framerate();
- mchip_dma_setup(meye.mchip_dmahandle);
-
- meye.mchip_mode = MCHIP_HIC_MODE_CONT_COMP;
-
- mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_CONT_COMP);
- mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START);
-
- mchip_delay(MCHIP_HIC_CMD, 0);
-}
-
-/****************************************************************************/
-/* Interrupt handling */
-/****************************************************************************/
-
-static irqreturn_t meye_irq(int irq, void *dev_id)
-{
- u32 v;
- int reqnr;
- static int sequence;
-
- v = mchip_read(MCHIP_MM_INTA);
-
- if (meye.mchip_mode != MCHIP_HIC_MODE_CONT_OUT &&
- meye.mchip_mode != MCHIP_HIC_MODE_CONT_COMP)
- return IRQ_NONE;
-
-again:
- v = mchip_get_frame();
- if (!(v & MCHIP_MM_FIR_RDY))
- return IRQ_HANDLED;
-
- if (meye.mchip_mode == MCHIP_HIC_MODE_CONT_OUT) {
- if (kfifo_out_locked(&meye.grabq, (unsigned char *)&reqnr,
- sizeof(int), &meye.grabq_lock) != sizeof(int)) {
- mchip_free_frame();
- return IRQ_HANDLED;
- }
- mchip_cont_read_frame(v, meye.grab_fbuffer + gbufsize * reqnr,
- mchip_hsize() * mchip_vsize() * 2);
- meye.grab_buffer[reqnr].size = mchip_hsize() * mchip_vsize() * 2;
- meye.grab_buffer[reqnr].state = MEYE_BUF_DONE;
- meye.grab_buffer[reqnr].ts = ktime_get_ns();
- meye.grab_buffer[reqnr].sequence = sequence++;
- kfifo_in_locked(&meye.doneq, (unsigned char *)&reqnr,
- sizeof(int), &meye.doneq_lock);
- wake_up_interruptible(&meye.proc_list);
- } else {
- int size;
- size = mchip_comp_read_frame(v, meye.grab_temp, gbufsize);
- if (size == -1) {
- mchip_free_frame();
- goto again;
- }
- if (kfifo_out_locked(&meye.grabq, (unsigned char *)&reqnr,
- sizeof(int), &meye.grabq_lock) != sizeof(int)) {
- mchip_free_frame();
- goto again;
- }
- memcpy(meye.grab_fbuffer + gbufsize * reqnr, meye.grab_temp,
- size);
- meye.grab_buffer[reqnr].size = size;
- meye.grab_buffer[reqnr].state = MEYE_BUF_DONE;
- meye.grab_buffer[reqnr].ts = ktime_get_ns();
- meye.grab_buffer[reqnr].sequence = sequence++;
- kfifo_in_locked(&meye.doneq, (unsigned char *)&reqnr,
- sizeof(int), &meye.doneq_lock);
- wake_up_interruptible(&meye.proc_list);
- }
- mchip_free_frame();
- goto again;
-}
-
-/****************************************************************************/
-/* video4linux integration */
-/****************************************************************************/
-
-static int meye_open(struct file *file)
-{
- int i;
-
- if (test_and_set_bit(0, &meye.in_use))
- return -EBUSY;
-
- mchip_hic_stop();
-
- if (mchip_dma_alloc()) {
- printk(KERN_ERR "meye: mchip framebuffer allocation failed\n");
- clear_bit(0, &meye.in_use);
- return -ENOBUFS;
- }
-
- for (i = 0; i < MEYE_MAX_BUFNBRS; i++)
- meye.grab_buffer[i].state = MEYE_BUF_UNUSED;
- kfifo_reset(&meye.grabq);
- kfifo_reset(&meye.doneq);
- return v4l2_fh_open(file);
-}
-
-static int meye_release(struct file *file)
-{
- mchip_hic_stop();
- mchip_dma_free();
- clear_bit(0, &meye.in_use);
- return v4l2_fh_release(file);
-}
-
-static int meyeioc_g_params(struct meye_params *p)
-{
- *p = meye.params;
- return 0;
-}
-
-static int meyeioc_s_params(struct meye_params *jp)
-{
- if (jp->subsample > 1)
- return -EINVAL;
-
- if (jp->quality > 10)
- return -EINVAL;
-
- if (jp->sharpness > 63 || jp->agc > 63 || jp->picture > 63)
- return -EINVAL;
-
- if (jp->framerate > 31)
- return -EINVAL;
-
- mutex_lock(&meye.lock);
-
- if (meye.params.subsample != jp->subsample ||
- meye.params.quality != jp->quality)
- mchip_hic_stop(); /* need restart */
-
- meye.params = *jp;
- sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERASHARPNESS,
- meye.params.sharpness);
- sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC,
- meye.params.agc);
- sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE,
- meye.params.picture);
- mutex_unlock(&meye.lock);
-
- return 0;
-}
-
-static int meyeioc_qbuf_capt(int *nb)
-{
- if (!meye.grab_fbuffer)
- return -EINVAL;
-
- if (*nb >= gbuffers)
- return -EINVAL;
-
- if (*nb < 0) {
- /* stop capture */
- mchip_hic_stop();
- return 0;
- }
-
- if (meye.grab_buffer[*nb].state != MEYE_BUF_UNUSED)
- return -EBUSY;
-
- mutex_lock(&meye.lock);
-
- if (meye.mchip_mode != MCHIP_HIC_MODE_CONT_COMP)
- mchip_cont_compression_start();
-
- meye.grab_buffer[*nb].state = MEYE_BUF_USING;
- kfifo_in_locked(&meye.grabq, (unsigned char *)nb, sizeof(int),
- &meye.grabq_lock);
- mutex_unlock(&meye.lock);
-
- return 0;
-}
-
-static int meyeioc_sync(struct file *file, void *fh, int *i)
-{
- int unused;
-
- if (*i < 0 || *i >= gbuffers)
- return -EINVAL;
-
- mutex_lock(&meye.lock);
- switch (meye.grab_buffer[*i].state) {
-
- case MEYE_BUF_UNUSED:
- mutex_unlock(&meye.lock);
- return -EINVAL;
- case MEYE_BUF_USING:
- if (file->f_flags & O_NONBLOCK) {
- mutex_unlock(&meye.lock);
- return -EAGAIN;
- }
- if (wait_event_interruptible(meye.proc_list,
- (meye.grab_buffer[*i].state != MEYE_BUF_USING))) {
- mutex_unlock(&meye.lock);
- return -EINTR;
- }
- fallthrough;
- case MEYE_BUF_DONE:
- meye.grab_buffer[*i].state = MEYE_BUF_UNUSED;
- if (kfifo_out_locked(&meye.doneq, (unsigned char *)&unused,
- sizeof(int), &meye.doneq_lock) != sizeof(int))
- break;
- }
- *i = meye.grab_buffer[*i].size;
- mutex_unlock(&meye.lock);
- return 0;
-}
-
-static int meyeioc_stillcapt(void)
-{
- if (!meye.grab_fbuffer)
- return -EINVAL;
-
- if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED)
- return -EBUSY;
-
- mutex_lock(&meye.lock);
- meye.grab_buffer[0].state = MEYE_BUF_USING;
- mchip_take_picture();
-
- mchip_get_picture(meye.grab_fbuffer,
- mchip_hsize() * mchip_vsize() * 2);
-
- meye.grab_buffer[0].state = MEYE_BUF_DONE;
- mutex_unlock(&meye.lock);
-
- return 0;
-}
-
-static int meyeioc_stilljcapt(int *len)
-{
- if (!meye.grab_fbuffer)
- return -EINVAL;
-
- if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED)
- return -EBUSY;
-
- mutex_lock(&meye.lock);
- meye.grab_buffer[0].state = MEYE_BUF_USING;
- *len = -1;
-
- while (*len == -1) {
- mchip_take_picture();
- *len = mchip_compress_frame(meye.grab_fbuffer, gbufsize);
- }
-
- meye.grab_buffer[0].state = MEYE_BUF_DONE;
- mutex_unlock(&meye.lock);
- return 0;
-}
-
-static int vidioc_querycap(struct file *file, void *fh,
- struct v4l2_capability *cap)
-{
- strscpy(cap->driver, "meye", sizeof(cap->driver));
- strscpy(cap->card, "meye", sizeof(cap->card));
- return 0;
-}
-
-static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
-{
- if (i->index != 0)
- return -EINVAL;
-
- strscpy(i->name, "Camera", sizeof(i->name));
- i->type = V4L2_INPUT_TYPE_CAMERA;
-
- return 0;
-}
-
-static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
-{
- *i = 0;
- return 0;
-}
-
-static int vidioc_s_input(struct file *file, void *fh, unsigned int i)
-{
- if (i != 0)
- return -EINVAL;
-
- return 0;
-}
-
-static int meye_s_ctrl(struct v4l2_ctrl *ctrl)
-{
- mutex_lock(&meye.lock);
- switch (ctrl->id) {
- case V4L2_CID_BRIGHTNESS:
- sony_pic_camera_command(
- SONY_PIC_COMMAND_SETCAMERABRIGHTNESS, ctrl->val);
- meye.brightness = ctrl->val << 10;
- break;
- case V4L2_CID_HUE:
- sony_pic_camera_command(
- SONY_PIC_COMMAND_SETCAMERAHUE, ctrl->val);
- meye.hue = ctrl->val << 10;
- break;
- case V4L2_CID_CONTRAST:
- sony_pic_camera_command(
- SONY_PIC_COMMAND_SETCAMERACONTRAST, ctrl->val);
- meye.contrast = ctrl->val << 10;
- break;
- case V4L2_CID_SATURATION:
- sony_pic_camera_command(
- SONY_PIC_COMMAND_SETCAMERACOLOR, ctrl->val);
- meye.colour = ctrl->val << 10;
- break;
- case V4L2_CID_MEYE_AGC:
- sony_pic_camera_command(
- SONY_PIC_COMMAND_SETCAMERAAGC, ctrl->val);
- meye.params.agc = ctrl->val;
- break;
- case V4L2_CID_SHARPNESS:
- sony_pic_camera_command(
- SONY_PIC_COMMAND_SETCAMERASHARPNESS, ctrl->val);
- meye.params.sharpness = ctrl->val;
- break;
- case V4L2_CID_MEYE_PICTURE:
- sony_pic_camera_command(
- SONY_PIC_COMMAND_SETCAMERAPICTURE, ctrl->val);
- meye.params.picture = ctrl->val;
- break;
- case V4L2_CID_JPEG_COMPRESSION_QUALITY:
- meye.params.quality = ctrl->val;
- break;
- case V4L2_CID_MEYE_FRAMERATE:
- meye.params.framerate = ctrl->val;
- break;
- default:
- mutex_unlock(&meye.lock);
- return -EINVAL;
- }
- mutex_unlock(&meye.lock);
-
- return 0;
-}
-
-static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh,
- struct v4l2_fmtdesc *f)
-{
- if (f->index > 1)
- return -EINVAL;
-
- if (f->index == 0) {
- /* standard YUV 422 capture */
- f->flags = 0;
- f->pixelformat = V4L2_PIX_FMT_YUYV;
- } else {
- /* compressed MJPEG capture */
- f->pixelformat = V4L2_PIX_FMT_MJPEG;
- }
-
- return 0;
-}
-
-static int vidioc_try_fmt_vid_cap(struct file *file, void *fh,
- struct v4l2_format *f)
-{
- if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV &&
- f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
- return -EINVAL;
-
- if (f->fmt.pix.field != V4L2_FIELD_ANY &&
- f->fmt.pix.field != V4L2_FIELD_NONE)
- return -EINVAL;
-
- f->fmt.pix.field = V4L2_FIELD_NONE;
-
- if (f->fmt.pix.width <= 320) {
- f->fmt.pix.width = 320;
- f->fmt.pix.height = 240;
- } else {
- f->fmt.pix.width = 640;
- f->fmt.pix.height = 480;
- }
-
- f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
- f->fmt.pix.sizeimage = f->fmt.pix.height *
- f->fmt.pix.bytesperline;
- f->fmt.pix.colorspace = 0;
-
- return 0;
-}
-
-static int vidioc_g_fmt_vid_cap(struct file *file, void *fh,
- struct v4l2_format *f)
-{
- switch (meye.mchip_mode) {
- case MCHIP_HIC_MODE_CONT_OUT:
- default:
- f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
- break;
- case MCHIP_HIC_MODE_CONT_COMP:
- f->fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
- break;
- }
-
- f->fmt.pix.field = V4L2_FIELD_NONE;
- f->fmt.pix.width = mchip_hsize();
- f->fmt.pix.height = mchip_vsize();
- f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
- f->fmt.pix.sizeimage = f->fmt.pix.height *
- f->fmt.pix.bytesperline;
-
- return 0;
-}
-
-static int vidioc_s_fmt_vid_cap(struct file *file, void *fh,
- struct v4l2_format *f)
-{
- if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV &&
- f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
- return -EINVAL;
-
- if (f->fmt.pix.field != V4L2_FIELD_ANY &&
- f->fmt.pix.field != V4L2_FIELD_NONE)
- return -EINVAL;
-
- f->fmt.pix.field = V4L2_FIELD_NONE;
- mutex_lock(&meye.lock);
-
- if (f->fmt.pix.width <= 320) {
- f->fmt.pix.width = 320;
- f->fmt.pix.height = 240;
- meye.params.subsample = 1;
- } else {
- f->fmt.pix.width = 640;
- f->fmt.pix.height = 480;
- meye.params.subsample = 0;
- }
-
- switch (f->fmt.pix.pixelformat) {
- case V4L2_PIX_FMT_YUYV:
- meye.mchip_mode = MCHIP_HIC_MODE_CONT_OUT;
- break;
- case V4L2_PIX_FMT_MJPEG:
- meye.mchip_mode = MCHIP_HIC_MODE_CONT_COMP;
- break;
- }
-
- mutex_unlock(&meye.lock);
- f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
- f->fmt.pix.sizeimage = f->fmt.pix.height *
- f->fmt.pix.bytesperline;
- f->fmt.pix.colorspace = 0;
-
- return 0;
-}
-
-static int vidioc_reqbufs(struct file *file, void *fh,
- struct v4l2_requestbuffers *req)
-{
- int i;
-
- if (req->memory != V4L2_MEMORY_MMAP)
- return -EINVAL;
-
- if (meye.grab_fbuffer && req->count == gbuffers) {
- /* already allocated, no modifications */
- return 0;
- }
-
- mutex_lock(&meye.lock);
- if (meye.grab_fbuffer) {
- for (i = 0; i < gbuffers; i++)
- if (meye.vma_use_count[i]) {
- mutex_unlock(&meye.lock);
- return -EINVAL;
- }
- rvfree(meye.grab_fbuffer, gbuffers * gbufsize);
- meye.grab_fbuffer = NULL;
- }
-
- gbuffers = max(2, min((int)req->count, MEYE_MAX_BUFNBRS));
- req->count = gbuffers;
- meye.grab_fbuffer = rvmalloc(gbuffers * gbufsize);
-
- if (!meye.grab_fbuffer) {
- printk(KERN_ERR "meye: v4l framebuffer allocation failed\n");
- mutex_unlock(&meye.lock);
- return -ENOMEM;
- }
-
- for (i = 0; i < gbuffers; i++)
- meye.vma_use_count[i] = 0;
-
- mutex_unlock(&meye.lock);
-
- return 0;
-}
-
-static int vidioc_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf)
-{
- unsigned int index = buf->index;
-
- if (index >= gbuffers)
- return -EINVAL;
-
- buf->bytesused = meye.grab_buffer[index].size;
- buf->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
-
- if (meye.grab_buffer[index].state == MEYE_BUF_USING)
- buf->flags |= V4L2_BUF_FLAG_QUEUED;
-
- if (meye.grab_buffer[index].state == MEYE_BUF_DONE)
- buf->flags |= V4L2_BUF_FLAG_DONE;
-
- buf->field = V4L2_FIELD_NONE;
- v4l2_buffer_set_timestamp(buf, meye.grab_buffer[index].ts);
- buf->sequence = meye.grab_buffer[index].sequence;
- buf->memory = V4L2_MEMORY_MMAP;
- buf->m.offset = index * gbufsize;
- buf->length = gbufsize;
-
- return 0;
-}
-
-static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
-{
- if (buf->memory != V4L2_MEMORY_MMAP)
- return -EINVAL;
-
- if (buf->index >= gbuffers)
- return -EINVAL;
-
- if (meye.grab_buffer[buf->index].state != MEYE_BUF_UNUSED)
- return -EINVAL;
-
- mutex_lock(&meye.lock);
- buf->flags |= V4L2_BUF_FLAG_QUEUED;
- buf->flags &= ~V4L2_BUF_FLAG_DONE;
- meye.grab_buffer[buf->index].state = MEYE_BUF_USING;
- kfifo_in_locked(&meye.grabq, (unsigned char *)&buf->index,
- sizeof(int), &meye.grabq_lock);
- mutex_unlock(&meye.lock);
-
- return 0;
-}
-
-static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
-{
- int reqnr;
-
- if (buf->memory != V4L2_MEMORY_MMAP)
- return -EINVAL;
-
- mutex_lock(&meye.lock);
-
- if (kfifo_len(&meye.doneq) == 0 && file->f_flags & O_NONBLOCK) {
- mutex_unlock(&meye.lock);
- return -EAGAIN;
- }
-
- if (wait_event_interruptible(meye.proc_list,
- kfifo_len(&meye.doneq) != 0) < 0) {
- mutex_unlock(&meye.lock);
- return -EINTR;
- }
-
- if (!kfifo_out_locked(&meye.doneq, (unsigned char *)&reqnr,
- sizeof(int), &meye.doneq_lock)) {
- mutex_unlock(&meye.lock);
- return -EBUSY;
- }
-
- if (meye.grab_buffer[reqnr].state != MEYE_BUF_DONE) {
- mutex_unlock(&meye.lock);
- return -EINVAL;
- }
-
- buf->index = reqnr;
- buf->bytesused = meye.grab_buffer[reqnr].size;
- buf->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
- buf->field = V4L2_FIELD_NONE;
- v4l2_buffer_set_timestamp(buf, meye.grab_buffer[reqnr].ts);
- buf->sequence = meye.grab_buffer[reqnr].sequence;
- buf->memory = V4L2_MEMORY_MMAP;
- buf->m.offset = reqnr * gbufsize;
- buf->length = gbufsize;
- meye.grab_buffer[reqnr].state = MEYE_BUF_UNUSED;
- mutex_unlock(&meye.lock);
-
- return 0;
-}
-
-static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
-{
- mutex_lock(&meye.lock);
-
- switch (meye.mchip_mode) {
- case MCHIP_HIC_MODE_CONT_OUT:
- mchip_continuous_start();
- break;
- case MCHIP_HIC_MODE_CONT_COMP:
- mchip_cont_compression_start();
- break;
- default:
- mutex_unlock(&meye.lock);
- return -EINVAL;
- }
-
- mutex_unlock(&meye.lock);
-
- return 0;
-}
-
-static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i)
-{
- mutex_lock(&meye.lock);
- mchip_hic_stop();
- kfifo_reset(&meye.grabq);
- kfifo_reset(&meye.doneq);
-
- for (i = 0; i < MEYE_MAX_BUFNBRS; i++)
- meye.grab_buffer[i].state = MEYE_BUF_UNUSED;
-
- mutex_unlock(&meye.lock);
- return 0;
-}
-
-static long vidioc_default(struct file *file, void *fh, bool valid_prio,
- unsigned int cmd, void *arg)
-{
- switch (cmd) {
- case MEYEIOC_G_PARAMS:
- return meyeioc_g_params((struct meye_params *) arg);
-
- case MEYEIOC_S_PARAMS:
- return meyeioc_s_params((struct meye_params *) arg);
-
- case MEYEIOC_QBUF_CAPT:
- return meyeioc_qbuf_capt((int *) arg);
-
- case MEYEIOC_SYNC:
- return meyeioc_sync(file, fh, (int *) arg);
-
- case MEYEIOC_STILLCAPT:
- return meyeioc_stillcapt();
-
- case MEYEIOC_STILLJCAPT:
- return meyeioc_stilljcapt((int *) arg);
-
- default:
- return -ENOTTY;
- }
-
-}
-
-static __poll_t meye_poll(struct file *file, poll_table *wait)
-{
- __poll_t res = v4l2_ctrl_poll(file, wait);
-
- mutex_lock(&meye.lock);
- poll_wait(file, &meye.proc_list, wait);
- if (kfifo_len(&meye.doneq))
- res |= EPOLLIN | EPOLLRDNORM;
- mutex_unlock(&meye.lock);
- return res;
-}
-
-static void meye_vm_open(struct vm_area_struct *vma)
-{
- long idx = (long)vma->vm_private_data;
- meye.vma_use_count[idx]++;
-}
-
-static void meye_vm_close(struct vm_area_struct *vma)
-{
- long idx = (long)vma->vm_private_data;
- meye.vma_use_count[idx]--;
-}
-
-static const struct vm_operations_struct meye_vm_ops = {
- .open = meye_vm_open,
- .close = meye_vm_close,
-};
-
-static int meye_mmap(struct file *file, struct vm_area_struct *vma)
-{
- unsigned long start = vma->vm_start;
- unsigned long size = vma->vm_end - vma->vm_start;
- unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
- unsigned long page, pos;
-
- mutex_lock(&meye.lock);
- if (size > gbuffers * gbufsize || offset > gbuffers * gbufsize - size) {
- mutex_unlock(&meye.lock);
- return -EINVAL;
- }
- if (!meye.grab_fbuffer) {
- int i;
-
- /* lazy allocation */
- meye.grab_fbuffer = rvmalloc(gbuffers*gbufsize);
- if (!meye.grab_fbuffer) {
- printk(KERN_ERR "meye: v4l framebuffer allocation failed\n");
- mutex_unlock(&meye.lock);
- return -ENOMEM;
- }
- for (i = 0; i < gbuffers; i++)
- meye.vma_use_count[i] = 0;
- }
- pos = (unsigned long)meye.grab_fbuffer + offset;
-
- while (size > 0) {
- page = vmalloc_to_pfn((void *)pos);
- if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
- mutex_unlock(&meye.lock);
- return -EAGAIN;
- }
- start += PAGE_SIZE;
- pos += PAGE_SIZE;
- if (size > PAGE_SIZE)
- size -= PAGE_SIZE;
- else
- size = 0;
- }
-
- vma->vm_ops = &meye_vm_ops;
- vma->vm_flags &= ~VM_IO; /* not I/O memory */
- vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
- vma->vm_private_data = (void *) (offset / gbufsize);
- meye_vm_open(vma);
-
- mutex_unlock(&meye.lock);
- return 0;
-}
-
-static const struct v4l2_file_operations meye_fops = {
- .owner = THIS_MODULE,
- .open = meye_open,
- .release = meye_release,
- .mmap = meye_mmap,
- .unlocked_ioctl = video_ioctl2,
- .poll = meye_poll,
-};
-
-static const struct v4l2_ioctl_ops meye_ioctl_ops = {
- .vidioc_querycap = vidioc_querycap,
- .vidioc_enum_input = vidioc_enum_input,
- .vidioc_g_input = vidioc_g_input,
- .vidioc_s_input = vidioc_s_input,
- .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
- .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
- .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
- .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
- .vidioc_reqbufs = vidioc_reqbufs,
- .vidioc_querybuf = vidioc_querybuf,
- .vidioc_qbuf = vidioc_qbuf,
- .vidioc_dqbuf = vidioc_dqbuf,
- .vidioc_streamon = vidioc_streamon,
- .vidioc_streamoff = vidioc_streamoff,
- .vidioc_log_status = v4l2_ctrl_log_status,
- .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
- .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
- .vidioc_default = vidioc_default,
-};
-
-static const struct video_device meye_template = {
- .name = "meye",
- .fops = &meye_fops,
- .ioctl_ops = &meye_ioctl_ops,
- .release = video_device_release_empty,
- .device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING,
-};
-
-static const struct v4l2_ctrl_ops meye_ctrl_ops = {
- .s_ctrl = meye_s_ctrl,
-};
-
-static int __maybe_unused meye_suspend(struct device *dev)
-{
- meye.pm_mchip_mode = meye.mchip_mode;
- mchip_hic_stop();
- mchip_set(MCHIP_MM_INTA, 0x0);
- return 0;
-}
-
-static int __maybe_unused meye_resume(struct device *dev)
-{
- pci_write_config_word(meye.mchip_dev, MCHIP_PCI_SOFTRESET_SET, 1);
-
- mchip_delay(MCHIP_HIC_CMD, 0);
- mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE);
- msleep(1);
- mchip_set(MCHIP_VRJ_SOFT_RESET, 1);
- msleep(1);
- mchip_set(MCHIP_MM_PCI_MODE, 5);
- msleep(1);
- mchip_set(MCHIP_MM_INTA, MCHIP_MM_INTA_HIC_1_MASK);
-
- switch (meye.pm_mchip_mode) {
- case MCHIP_HIC_MODE_CONT_OUT:
- mchip_continuous_start();
- break;
- case MCHIP_HIC_MODE_CONT_COMP:
- mchip_cont_compression_start();
- break;
- }
- return 0;
-}
-
-static int meye_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
-{
- static const struct v4l2_ctrl_config ctrl_agc = {
- .id = V4L2_CID_MEYE_AGC,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .ops = &meye_ctrl_ops,
- .name = "AGC",
- .max = 63,
- .step = 1,
- .def = 48,
- .flags = V4L2_CTRL_FLAG_SLIDER,
- };
- static const struct v4l2_ctrl_config ctrl_picture = {
- .id = V4L2_CID_MEYE_PICTURE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .ops = &meye_ctrl_ops,
- .name = "Picture",
- .max = 63,
- .step = 1,
- };
- static const struct v4l2_ctrl_config ctrl_framerate = {
- .id = V4L2_CID_MEYE_FRAMERATE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .ops = &meye_ctrl_ops,
- .name = "Framerate",
- .max = 31,
- .step = 1,
- };
- struct v4l2_device *v4l2_dev = &meye.v4l2_dev;
- int ret = -EBUSY;
- unsigned long mchip_adr;
-
- if (meye.mchip_dev != NULL) {
- printk(KERN_ERR "meye: only one device allowed!\n");
- return ret;
- }
-
- ret = v4l2_device_register(&pcidev->dev, v4l2_dev);
- if (ret < 0) {
- v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
- return ret;
- }
- ret = -ENOMEM;
- meye.mchip_dev = pcidev;
-
- meye.grab_temp = vmalloc(array_size(PAGE_SIZE, MCHIP_NB_PAGES_MJPEG));
- if (!meye.grab_temp)
- goto outvmalloc;
-
- spin_lock_init(&meye.grabq_lock);
- if (kfifo_alloc(&meye.grabq, sizeof(int) * MEYE_MAX_BUFNBRS,
- GFP_KERNEL))
- goto outkfifoalloc1;
-
- spin_lock_init(&meye.doneq_lock);
- if (kfifo_alloc(&meye.doneq, sizeof(int) * MEYE_MAX_BUFNBRS,
- GFP_KERNEL))
- goto outkfifoalloc2;
-
- meye.vdev = meye_template;
- meye.vdev.v4l2_dev = &meye.v4l2_dev;
-
- ret = sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 1);
- if (ret) {
- v4l2_err(v4l2_dev, "meye: unable to power on the camera\n");
- v4l2_err(v4l2_dev, "meye: did you enable the camera in sonypi using the module options ?\n");
- goto outsonypienable;
- }
-
- ret = pci_enable_device(meye.mchip_dev);
- if (ret) {
- v4l2_err(v4l2_dev, "meye: pci_enable_device failed\n");
- goto outenabledev;
- }
-
- ret = -EIO;
- mchip_adr = pci_resource_start(meye.mchip_dev,0);
- if (!mchip_adr) {
- v4l2_err(v4l2_dev, "meye: mchip has no device base address\n");
- goto outregions;
- }
- if (!request_mem_region(pci_resource_start(meye.mchip_dev, 0),
- pci_resource_len(meye.mchip_dev, 0),
- "meye")) {
- v4l2_err(v4l2_dev, "meye: request_mem_region failed\n");
- goto outregions;
- }
- meye.mchip_mmregs = ioremap(mchip_adr, MCHIP_MM_REGS);
- if (!meye.mchip_mmregs) {
- v4l2_err(v4l2_dev, "meye: ioremap failed\n");
- goto outremap;
- }
-
- meye.mchip_irq = pcidev->irq;
- if (request_irq(meye.mchip_irq, meye_irq,
- IRQF_SHARED, "meye", meye_irq)) {
- v4l2_err(v4l2_dev, "request_irq failed\n");
- goto outreqirq;
- }
-
- pci_write_config_byte(meye.mchip_dev, PCI_CACHE_LINE_SIZE, 8);
- pci_write_config_byte(meye.mchip_dev, PCI_LATENCY_TIMER, 64);
-
- pci_set_master(meye.mchip_dev);
-
- /* Ask the camera to perform a soft reset. */
- pci_write_config_word(meye.mchip_dev, MCHIP_PCI_SOFTRESET_SET, 1);
-
- mchip_delay(MCHIP_HIC_CMD, 0);
- mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE);
-
- msleep(1);
- mchip_set(MCHIP_VRJ_SOFT_RESET, 1);
-
- msleep(1);
- mchip_set(MCHIP_MM_PCI_MODE, 5);
-
- msleep(1);
- mchip_set(MCHIP_MM_INTA, MCHIP_MM_INTA_HIC_1_MASK);
-
- mutex_init(&meye.lock);
- init_waitqueue_head(&meye.proc_list);
-
- v4l2_ctrl_handler_init(&meye.hdl, 3);
- v4l2_ctrl_new_std(&meye.hdl, &meye_ctrl_ops,
- V4L2_CID_BRIGHTNESS, 0, 63, 1, 32);
- v4l2_ctrl_new_std(&meye.hdl, &meye_ctrl_ops,
- V4L2_CID_HUE, 0, 63, 1, 32);
- v4l2_ctrl_new_std(&meye.hdl, &meye_ctrl_ops,
- V4L2_CID_CONTRAST, 0, 63, 1, 32);
- v4l2_ctrl_new_std(&meye.hdl, &meye_ctrl_ops,
- V4L2_CID_SATURATION, 0, 63, 1, 32);
- v4l2_ctrl_new_custom(&meye.hdl, &ctrl_agc, NULL);
- v4l2_ctrl_new_std(&meye.hdl, &meye_ctrl_ops,
- V4L2_CID_SHARPNESS, 0, 63, 1, 32);
- v4l2_ctrl_new_custom(&meye.hdl, &ctrl_picture, NULL);
- v4l2_ctrl_new_std(&meye.hdl, &meye_ctrl_ops,
- V4L2_CID_JPEG_COMPRESSION_QUALITY, 0, 10, 1, 8);
- v4l2_ctrl_new_custom(&meye.hdl, &ctrl_framerate, NULL);
- if (meye.hdl.error) {
- v4l2_err(v4l2_dev, "couldn't register controls\n");
- goto outvideoreg;
- }
-
- v4l2_ctrl_handler_setup(&meye.hdl);
- meye.vdev.ctrl_handler = &meye.hdl;
-
- if (video_register_device(&meye.vdev, VFL_TYPE_VIDEO,
- video_nr) < 0) {
- v4l2_err(v4l2_dev, "video_register_device failed\n");
- goto outvideoreg;
- }
-
- v4l2_info(v4l2_dev, "Motion Eye Camera Driver v%s.\n",
- MEYE_DRIVER_VERSION);
- v4l2_info(v4l2_dev, "mchip KL5A72002 rev. %d, base %lx, irq %d\n",
- meye.mchip_dev->revision, mchip_adr, meye.mchip_irq);
-
- return 0;
-
-outvideoreg:
- v4l2_ctrl_handler_free(&meye.hdl);
- free_irq(meye.mchip_irq, meye_irq);
-outreqirq:
- iounmap(meye.mchip_mmregs);
-outremap:
- release_mem_region(pci_resource_start(meye.mchip_dev, 0),
- pci_resource_len(meye.mchip_dev, 0));
-outregions:
- pci_disable_device(meye.mchip_dev);
-outenabledev:
- sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 0);
-outsonypienable:
- kfifo_free(&meye.doneq);
-outkfifoalloc2:
- kfifo_free(&meye.grabq);
-outkfifoalloc1:
- vfree(meye.grab_temp);
-outvmalloc:
- return ret;
-}
-
-static void meye_remove(struct pci_dev *pcidev)
-{
- video_unregister_device(&meye.vdev);
-
- mchip_hic_stop();
-
- mchip_dma_free();
-
- /* disable interrupts */
- mchip_set(MCHIP_MM_INTA, 0x0);
-
- free_irq(meye.mchip_irq, meye_irq);
-
- iounmap(meye.mchip_mmregs);
-
- release_mem_region(pci_resource_start(meye.mchip_dev, 0),
- pci_resource_len(meye.mchip_dev, 0));
-
- pci_disable_device(meye.mchip_dev);
-
- sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 0);
-
- kfifo_free(&meye.doneq);
- kfifo_free(&meye.grabq);
-
- vfree(meye.grab_temp);
-
- if (meye.grab_fbuffer) {
- rvfree(meye.grab_fbuffer, gbuffers*gbufsize);
- meye.grab_fbuffer = NULL;
- }
-
- printk(KERN_INFO "meye: removed\n");
-}
-
-static const struct pci_device_id meye_pci_tbl[] = {
- { PCI_VDEVICE(KAWASAKI, PCI_DEVICE_ID_MCHIP_KL5A72002), 0 },
- { }
-};
-
-MODULE_DEVICE_TABLE(pci, meye_pci_tbl);
-
-static SIMPLE_DEV_PM_OPS(meye_pm_ops, meye_suspend, meye_resume);
-
-static struct pci_driver meye_driver = {
- .name = "meye",
- .id_table = meye_pci_tbl,
- .probe = meye_probe,
- .remove = meye_remove,
- .driver.pm = &meye_pm_ops,
-};
-
-static int __init meye_init(void)
-{
- gbuffers = max(2, min((int)gbuffers, MEYE_MAX_BUFNBRS));
- if (gbufsize > MEYE_MAX_BUFSIZE)
- gbufsize = MEYE_MAX_BUFSIZE;
- gbufsize = PAGE_ALIGN(gbufsize);
- printk(KERN_INFO "meye: using %d buffers with %dk (%dk total) for capture\n",
- gbuffers,
- gbufsize / 1024, gbuffers * gbufsize / 1024);
- return pci_register_driver(&meye_driver);
-}
-
-static void __exit meye_exit(void)
-{
- pci_unregister_driver(&meye_driver);
-}
-
-module_init(meye_init);
-module_exit(meye_exit);
diff --git a/drivers/media/pci/meye/meye.h b/drivers/media/pci/meye/meye.h
deleted file mode 100644
index 5fa6552cf93d..000000000000
--- a/drivers/media/pci/meye/meye.h
+++ /dev/null
@@ -1,311 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Motion Eye video4linux driver for Sony Vaio PictureBook
- *
- * Copyright (C) 2001-2004 Stelian Pop <stelian@popies.net>
- *
- * Copyright (C) 2001-2002 AlcĂ´ve <www.alcove.com>
- *
- * Copyright (C) 2000 Andrew Tridgell <tridge@valinux.com>
- *
- * Earlier work by Werner Almesberger, Paul `Rusty' Russell and Paul Mackerras.
- *
- * Some parts borrowed from various video4linux drivers, especially
- * bttv-driver.c and zoran.c, see original files for credits.
- */
-
-#ifndef _MEYE_PRIV_H_
-#define _MEYE_PRIV_H_
-
-#define MEYE_DRIVER_MAJORVERSION 1
-#define MEYE_DRIVER_MINORVERSION 14
-
-#define MEYE_DRIVER_VERSION __stringify(MEYE_DRIVER_MAJORVERSION) "." \
- __stringify(MEYE_DRIVER_MINORVERSION)
-
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/kfifo.h>
-#include <media/v4l2-ctrls.h>
-
-/****************************************************************************/
-/* Motion JPEG chip registers */
-/****************************************************************************/
-
-/* Motion JPEG chip PCI configuration registers */
-#define MCHIP_PCI_POWER_CSR 0x54
-#define MCHIP_PCI_MCORE_STATUS 0x60 /* see HIC_STATUS */
-#define MCHIP_PCI_HOSTUSEREQ_SET 0x64
-#define MCHIP_PCI_HOSTUSEREQ_CLR 0x68
-#define MCHIP_PCI_LOWPOWER_SET 0x6c
-#define MCHIP_PCI_LOWPOWER_CLR 0x70
-#define MCHIP_PCI_SOFTRESET_SET 0x74
-
-/* Motion JPEG chip memory mapped registers */
-#define MCHIP_MM_REGS 0x200 /* 512 bytes */
-#define MCHIP_REG_TIMEOUT 1000 /* reg access, ~us */
-#define MCHIP_MCC_VRJ_TIMEOUT 1000 /* MCC & VRJ access */
-
-#define MCHIP_MM_PCI_MODE 0x00 /* PCI access mode */
-#define MCHIP_MM_PCI_MODE_RETRY 0x00000001 /* retry mode */
-#define MCHIP_MM_PCI_MODE_MASTER 0x00000002 /* master access */
-#define MCHIP_MM_PCI_MODE_READ_LINE 0x00000004 /* read line */
-
-#define MCHIP_MM_INTA 0x04 /* Int status/mask */
-#define MCHIP_MM_INTA_MCC 0x00000001 /* MCC interrupt */
-#define MCHIP_MM_INTA_VRJ 0x00000002 /* VRJ interrupt */
-#define MCHIP_MM_INTA_HIC_1 0x00000004 /* one frame done */
-#define MCHIP_MM_INTA_HIC_1_MASK 0x00000400 /* 1: enable */
-#define MCHIP_MM_INTA_HIC_END 0x00000008 /* all frames done */
-#define MCHIP_MM_INTA_HIC_END_MASK 0x00000800
-#define MCHIP_MM_INTA_JPEG 0x00000010 /* decompress. error */
-#define MCHIP_MM_INTA_JPEG_MASK 0x00001000
-#define MCHIP_MM_INTA_CAPTURE 0x00000020 /* capture end */
-#define MCHIP_MM_INTA_PCI_ERR 0x00000040 /* PCI error */
-#define MCHIP_MM_INTA_PCI_ERR_MASK 0x00004000
-
-#define MCHIP_MM_PT_ADDR 0x08 /* page table address*/
- /* n*4kB */
-#define MCHIP_NB_PAGES 1024 /* pages for display */
-#define MCHIP_NB_PAGES_MJPEG 256 /* pages for mjpeg */
-
-#define MCHIP_MM_FIR(n) (0x0c+(n)*4) /* Frame info 0-3 */
-#define MCHIP_MM_FIR_RDY 0x00000001 /* frame ready */
-#define MCHIP_MM_FIR_FAILFR_MASK 0xf8000000 /* # of failed frames */
-#define MCHIP_MM_FIR_FAILFR_SHIFT 27
-
- /* continuous comp/decomp mode */
-#define MCHIP_MM_FIR_C_ENDL_MASK 0x000007fe /* end DW [10] */
-#define MCHIP_MM_FIR_C_ENDL_SHIFT 1
-#define MCHIP_MM_FIR_C_ENDP_MASK 0x0007f800 /* end page [8] */
-#define MCHIP_MM_FIR_C_ENDP_SHIFT 11
-#define MCHIP_MM_FIR_C_STARTP_MASK 0x07f80000 /* start page [8] */
-#define MCHIP_MM_FIR_C_STARTP_SHIFT 19
-
- /* continuous picture output mode */
-#define MCHIP_MM_FIR_O_STARTP_MASK 0x7ffe0000 /* start page [10] */
-#define MCHIP_MM_FIR_O_STARTP_SHIFT 17
-
-#define MCHIP_MM_FIFO_DATA 0x1c /* PCI TGT FIFO data */
-#define MCHIP_MM_FIFO_STATUS 0x20 /* PCI TGT FIFO stat */
-#define MCHIP_MM_FIFO_MASK 0x00000003
-#define MCHIP_MM_FIFO_WAIT_OR_READY 0x00000002 /* Bits common to WAIT & READY*/
-#define MCHIP_MM_FIFO_IDLE 0x0 /* HIC idle */
-#define MCHIP_MM_FIFO_IDLE1 0x1 /* idem ??? */
-#define MCHIP_MM_FIFO_WAIT 0x2 /* wait request */
-#define MCHIP_MM_FIFO_READY 0x3 /* data ready */
-
-#define MCHIP_HIC_HOST_USEREQ 0x40 /* host uses MCORE */
-
-#define MCHIP_HIC_TP_BUSY 0x44 /* taking picture */
-
-#define MCHIP_HIC_PIC_SAVED 0x48 /* pic in SDRAM */
-
-#define MCHIP_HIC_LOWPOWER 0x4c /* clock stopped */
-
-#define MCHIP_HIC_CTL 0x50 /* HIC control */
-#define MCHIP_HIC_CTL_SOFT_RESET 0x00000001 /* MCORE reset */
-#define MCHIP_HIC_CTL_MCORE_RDY 0x00000002 /* MCORE ready */
-
-#define MCHIP_HIC_CMD 0x54 /* HIC command */
-#define MCHIP_HIC_CMD_BITS 0x00000003 /* cmd width=[1:0]*/
-#define MCHIP_HIC_CMD_NOOP 0x0
-#define MCHIP_HIC_CMD_START 0x1
-#define MCHIP_HIC_CMD_STOP 0x2
-
-#define MCHIP_HIC_MODE 0x58
-#define MCHIP_HIC_MODE_NOOP 0x0
-#define MCHIP_HIC_MODE_STILL_CAP 0x1 /* still pic capt */
-#define MCHIP_HIC_MODE_DISPLAY 0x2 /* display */
-#define MCHIP_HIC_MODE_STILL_COMP 0x3 /* still pic comp. */
-#define MCHIP_HIC_MODE_STILL_DECOMP 0x4 /* still pic decomp. */
-#define MCHIP_HIC_MODE_CONT_COMP 0x5 /* cont capt+comp */
-#define MCHIP_HIC_MODE_CONT_DECOMP 0x6 /* cont decomp+disp */
-#define MCHIP_HIC_MODE_STILL_OUT 0x7 /* still pic output */
-#define MCHIP_HIC_MODE_CONT_OUT 0x8 /* cont output */
-
-#define MCHIP_HIC_STATUS 0x5c
-#define MCHIP_HIC_STATUS_MCC_RDY 0x00000001 /* MCC reg acc ok */
-#define MCHIP_HIC_STATUS_VRJ_RDY 0x00000002 /* VRJ reg acc ok */
-#define MCHIP_HIC_STATUS_IDLE 0x00000003
-#define MCHIP_HIC_STATUS_CAPDIS 0x00000004 /* cap/disp in prog */
-#define MCHIP_HIC_STATUS_COMPDEC 0x00000008 /* (de)comp in prog */
-#define MCHIP_HIC_STATUS_BUSY 0x00000010 /* HIC busy */
-
-#define MCHIP_HIC_S_RATE 0x60 /* MJPEG # frames */
-
-#define MCHIP_HIC_PCI_VFMT 0x64 /* video format */
-#define MCHIP_HIC_PCI_VFMT_YVYU 0x00000001 /* 0: V Y' U Y */
- /* 1: Y' V Y U */
-
-#define MCHIP_MCC_CMD 0x80 /* MCC commands */
-#define MCHIP_MCC_CMD_INITIAL 0x0 /* idle ? */
-#define MCHIP_MCC_CMD_IIC_START_SET 0x1
-#define MCHIP_MCC_CMD_IIC_END_SET 0x2
-#define MCHIP_MCC_CMD_FM_WRITE 0x3 /* frame memory */
-#define MCHIP_MCC_CMD_FM_READ 0x4
-#define MCHIP_MCC_CMD_FM_STOP 0x5
-#define MCHIP_MCC_CMD_CAPTURE 0x6
-#define MCHIP_MCC_CMD_DISPLAY 0x7
-#define MCHIP_MCC_CMD_END_DISP 0x8
-#define MCHIP_MCC_CMD_STILL_COMP 0x9
-#define MCHIP_MCC_CMD_STILL_DECOMP 0xa
-#define MCHIP_MCC_CMD_STILL_OUTPUT 0xb
-#define MCHIP_MCC_CMD_CONT_OUTPUT 0xc
-#define MCHIP_MCC_CMD_CONT_COMP 0xd
-#define MCHIP_MCC_CMD_CONT_DECOMP 0xe
-#define MCHIP_MCC_CMD_RESET 0xf /* MCC reset */
-
-#define MCHIP_MCC_IIC_WR 0x84
-
-#define MCHIP_MCC_MCC_WR 0x88
-
-#define MCHIP_MCC_MCC_RD 0x8c
-
-#define MCHIP_MCC_STATUS 0x90
-#define MCHIP_MCC_STATUS_CAPT 0x00000001 /* capturing */
-#define MCHIP_MCC_STATUS_DISP 0x00000002 /* displaying */
-#define MCHIP_MCC_STATUS_COMP 0x00000004 /* compressing */
-#define MCHIP_MCC_STATUS_DECOMP 0x00000008 /* decompressing */
-#define MCHIP_MCC_STATUS_MCC_WR 0x00000010 /* register ready */
-#define MCHIP_MCC_STATUS_MCC_RD 0x00000020 /* register ready */
-#define MCHIP_MCC_STATUS_IIC_WR 0x00000040 /* register ready */
-#define MCHIP_MCC_STATUS_OUTPUT 0x00000080 /* output in prog */
-
-#define MCHIP_MCC_SIG_POLARITY 0x94
-#define MCHIP_MCC_SIG_POL_VS_H 0x00000001 /* VS active-high */
-#define MCHIP_MCC_SIG_POL_HS_H 0x00000002 /* HS active-high */
-#define MCHIP_MCC_SIG_POL_DOE_H 0x00000004 /* DOE active-high */
-
-#define MCHIP_MCC_IRQ 0x98
-#define MCHIP_MCC_IRQ_CAPDIS_STRT 0x00000001 /* cap/disp started */
-#define MCHIP_MCC_IRQ_CAPDIS_STRT_MASK 0x00000010
-#define MCHIP_MCC_IRQ_CAPDIS_END 0x00000002 /* cap/disp ended */
-#define MCHIP_MCC_IRQ_CAPDIS_END_MASK 0x00000020
-#define MCHIP_MCC_IRQ_COMPDEC_STRT 0x00000004 /* (de)comp started */
-#define MCHIP_MCC_IRQ_COMPDEC_STRT_MASK 0x00000040
-#define MCHIP_MCC_IRQ_COMPDEC_END 0x00000008 /* (de)comp ended */
-#define MCHIP_MCC_IRQ_COMPDEC_END_MASK 0x00000080
-
-#define MCHIP_MCC_HSTART 0x9c /* video in */
-#define MCHIP_MCC_VSTART 0xa0
-#define MCHIP_MCC_HCOUNT 0xa4
-#define MCHIP_MCC_VCOUNT 0xa8
-#define MCHIP_MCC_R_XBASE 0xac /* capt/disp */
-#define MCHIP_MCC_R_YBASE 0xb0
-#define MCHIP_MCC_R_XRANGE 0xb4
-#define MCHIP_MCC_R_YRANGE 0xb8
-#define MCHIP_MCC_B_XBASE 0xbc /* comp/decomp */
-#define MCHIP_MCC_B_YBASE 0xc0
-#define MCHIP_MCC_B_XRANGE 0xc4
-#define MCHIP_MCC_B_YRANGE 0xc8
-
-#define MCHIP_MCC_R_SAMPLING 0xcc /* 1: 1:4 */
-
-#define MCHIP_VRJ_CMD 0x100 /* VRJ commands */
-
-/* VRJ registers (see table 12.2.4) */
-#define MCHIP_VRJ_COMPRESSED_DATA 0x1b0
-#define MCHIP_VRJ_PIXEL_DATA 0x1b8
-
-#define MCHIP_VRJ_BUS_MODE 0x100
-#define MCHIP_VRJ_SIGNAL_ACTIVE_LEVEL 0x108
-#define MCHIP_VRJ_PDAT_USE 0x110
-#define MCHIP_VRJ_MODE_SPECIFY 0x118
-#define MCHIP_VRJ_LIMIT_COMPRESSED_LO 0x120
-#define MCHIP_VRJ_LIMIT_COMPRESSED_HI 0x124
-#define MCHIP_VRJ_COMP_DATA_FORMAT 0x128
-#define MCHIP_VRJ_TABLE_DATA 0x140
-#define MCHIP_VRJ_RESTART_INTERVAL 0x148
-#define MCHIP_VRJ_NUM_LINES 0x150
-#define MCHIP_VRJ_NUM_PIXELS 0x158
-#define MCHIP_VRJ_NUM_COMPONENTS 0x160
-#define MCHIP_VRJ_SOF1 0x168
-#define MCHIP_VRJ_SOF2 0x170
-#define MCHIP_VRJ_SOF3 0x178
-#define MCHIP_VRJ_SOF4 0x180
-#define MCHIP_VRJ_SOS 0x188
-#define MCHIP_VRJ_SOFT_RESET 0x190
-
-#define MCHIP_VRJ_STATUS 0x1c0
-#define MCHIP_VRJ_STATUS_BUSY 0x00001
-#define MCHIP_VRJ_STATUS_COMP_ACCESS 0x00002
-#define MCHIP_VRJ_STATUS_PIXEL_ACCESS 0x00004
-#define MCHIP_VRJ_STATUS_ERROR 0x00008
-
-#define MCHIP_VRJ_IRQ_FLAG 0x1c8
-#define MCHIP_VRJ_ERROR_REPORT 0x1d8
-
-#define MCHIP_VRJ_START_COMMAND 0x1a0
-
-/****************************************************************************/
-/* Driver definitions. */
-/****************************************************************************/
-
-/* Sony Programmable I/O Controller for accessing the camera commands */
-#include <linux/sony-laptop.h>
-
-/* private API definitions */
-#include <linux/meye.h>
-#include <linux/mutex.h>
-
-
-/* Enable jpg software correction */
-#define MEYE_JPEG_CORRECTION 1
-
-/* Maximum size of a buffer */
-#define MEYE_MAX_BUFSIZE 614400 /* 640 * 480 * 2 */
-
-/* Maximum number of buffers */
-#define MEYE_MAX_BUFNBRS 32
-
-/* State of a buffer */
-#define MEYE_BUF_UNUSED 0 /* not used */
-#define MEYE_BUF_USING 1 /* currently grabbing / playing */
-#define MEYE_BUF_DONE 2 /* done */
-
-/* grab buffer */
-struct meye_grab_buffer {
- int state; /* state of buffer */
- unsigned long size; /* size of jpg frame */
- u64 ts; /* timestamp */
- unsigned long sequence; /* sequence number */
-};
-
-/* size of kfifos containing buffer indices */
-#define MEYE_QUEUE_SIZE MEYE_MAX_BUFNBRS
-
-/* Motion Eye device structure */
-struct meye {
- struct v4l2_device v4l2_dev; /* Main v4l2_device struct */
- struct v4l2_ctrl_handler hdl;
- struct pci_dev *mchip_dev; /* pci device */
- u8 mchip_irq; /* irq */
- u8 mchip_mode; /* actual mchip mode: HIC_MODE... */
- u8 mchip_fnum; /* current mchip frame number */
- unsigned char __iomem *mchip_mmregs;/* mchip: memory mapped registers */
- u8 *mchip_ptable[MCHIP_NB_PAGES];/* mchip: ptable */
- void *mchip_ptable_toc; /* mchip: ptable toc */
- dma_addr_t mchip_dmahandle; /* mchip: dma handle to ptable toc */
- unsigned char *grab_fbuffer; /* capture framebuffer */
- unsigned char *grab_temp; /* temporary buffer */
- /* list of buffers */
- struct meye_grab_buffer grab_buffer[MEYE_MAX_BUFNBRS];
- int vma_use_count[MEYE_MAX_BUFNBRS]; /* mmap count */
- struct mutex lock; /* mutex for open/mmap... */
- struct kfifo grabq; /* queue for buffers to be grabbed */
- spinlock_t grabq_lock; /* lock protecting the queue */
- struct kfifo doneq; /* queue for grabbed buffers */
- spinlock_t doneq_lock; /* lock protecting the queue */
- wait_queue_head_t proc_list; /* wait queue */
- struct video_device vdev; /* video device parameters */
- u16 brightness;
- u16 hue;
- u16 contrast;
- u16 colour;
- struct meye_params params; /* additional parameters */
- unsigned long in_use; /* set to 1 if the device is in use */
- u8 pm_mchip_mode; /* old mchip mode */
-};
-
-#endif
diff --git a/drivers/media/pci/ngene/ngene.h b/drivers/media/pci/ngene/ngene.h
index 3d296f1998a1..d1d7da84cd9d 100644
--- a/drivers/media/pci/ngene/ngene.h
+++ b/drivers/media/pci/ngene/ngene.h
@@ -596,43 +596,6 @@ struct mychip {
int capture_source[MIXER_ADDR_LAST + 1][2];
};
-#ifdef NGENE_V4L
-struct ngene_overlay {
- int tvnorm;
- struct v4l2_rect w;
- enum v4l2_field field;
- struct v4l2_clip *clips;
- int nclips;
- int setup_ok;
-};
-
-struct ngene_tvnorm {
- int v4l2_id;
- char *name;
- u16 swidth, sheight; /* scaled standard width, height */
- int tuner_norm;
- int soundstd;
-};
-
-struct ngene_vopen {
- struct ngene_channel *ch;
- enum v4l2_priority prio;
- int width;
- int height;
- int depth;
- struct videobuf_queue vbuf_q;
- struct videobuf_queue vbi;
- int fourcc;
- int picxcount;
- int resources;
- enum v4l2_buf_type type;
- const struct ngene_format *fmt;
-
- const struct ngene_format *ovfmt;
- struct ngene_overlay ov;
-};
-#endif
-
struct ngene_channel {
struct device device;
struct i2c_adapter i2c_adapter;
@@ -709,18 +672,6 @@ struct ngene_channel {
int tvnorm_num;
int tvnorm;
-#ifdef NGENE_V4L
- int videousers;
- struct v4l2_prio_state prio;
- struct ngene_vopen init;
- int resources;
- struct v4l2_framebuffer fbuf;
- struct ngene_buffer *screen; /* overlay */
- struct list_head capture; /* video capture queue */
- spinlock_t s_lock;
- struct semaphore reslock;
-#endif
-
int running;
int tsin_offset;
@@ -863,35 +814,6 @@ struct ngene_info {
int (*switch_ctrl)(struct ngene_channel *, int, int);
};
-#ifdef NGENE_V4L
-struct ngene_format {
- char *name;
- int fourcc; /* video4linux 2 */
- int btformat; /* BT848_COLOR_FMT_* */
- int format;
- int btswap; /* BT848_COLOR_CTL_* */
- int depth; /* bit/pixel */
- int flags;
- int hshift, vshift; /* for planar modes */
- int palette;
-};
-
-#define RESOURCE_OVERLAY 1
-#define RESOURCE_VIDEO 2
-#define RESOURCE_VBI 4
-
-struct ngene_buffer {
- /* common v4l buffer stuff -- must be first */
- struct videobuf_buffer vb;
-
- /* ngene specific */
- const struct ngene_format *fmt;
- int tvnorm;
- int btformat;
- int btswap;
-};
-#endif
-
/* Provided by ngene-core.c */
int ngene_probe(struct pci_dev *pci_dev, const struct pci_device_id *id);
diff --git a/drivers/media/pci/saa7146/Kconfig b/drivers/media/pci/saa7146/Kconfig
deleted file mode 100644
index 3bbb68a0ed7b..000000000000
--- a/drivers/media/pci/saa7146/Kconfig
+++ /dev/null
@@ -1,39 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-config VIDEO_HEXIUM_GEMINI
- tristate "Hexium Gemini frame grabber"
- depends on PCI && VIDEO_DEV && I2C
- select VIDEO_SAA7146_VV
- help
- This is a video4linux driver for the Hexium Gemini frame
- grabber card by Hexium. Please note that the Gemini Dual
- card is *not* fully supported.
-
- To compile this driver as a module, choose M here: the
- module will be called hexium_gemini.
-
-config VIDEO_HEXIUM_ORION
- tristate "Hexium HV-PCI6 and Orion frame grabber"
- depends on PCI && VIDEO_DEV && I2C
- select VIDEO_SAA7146_VV
- help
- This is a video4linux driver for the Hexium HV-PCI6 and
- Orion frame grabber cards by Hexium.
-
- To compile this driver as a module, choose M here: the
- module will be called hexium_orion.
-
-config VIDEO_MXB
- tristate "Siemens-Nixdorf 'Multimedia eXtension Board'"
- depends on PCI && VIDEO_DEV && I2C
- select VIDEO_SAA7146_VV
- select VIDEO_TUNER
- select VIDEO_SAA711X if MEDIA_SUBDRV_AUTOSELECT
- select VIDEO_TDA9840 if MEDIA_SUBDRV_AUTOSELECT
- select VIDEO_TEA6415C if MEDIA_SUBDRV_AUTOSELECT
- select VIDEO_TEA6420 if MEDIA_SUBDRV_AUTOSELECT
- help
- This is a video4linux driver for the 'Multimedia eXtension Board'
- TV card by Siemens-Nixdorf.
-
- To compile this driver as a module, choose M here: the
- module will be called mxb.
diff --git a/drivers/media/pci/saa7146/Makefile b/drivers/media/pci/saa7146/Makefile
deleted file mode 100644
index 37c9336f83d5..000000000000
--- a/drivers/media/pci/saa7146/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_VIDEO_MXB) += mxb.o
-obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o
-obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o
-
-ccflags-y += -I$(srctree)/drivers/media/i2c
diff --git a/drivers/media/pci/saa7146/hexium_gemini.c b/drivers/media/pci/saa7146/hexium_gemini.c
deleted file mode 100644
index 3947701cd6c7..000000000000
--- a/drivers/media/pci/saa7146/hexium_gemini.c
+++ /dev/null
@@ -1,425 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- hexium_gemini.c - v4l2 driver for Hexium Gemini frame grabber cards
-
- Visit http://www.mihu.de/linux/saa7146/ and follow the link
- to "hexium" for further details about this card.
-
- Copyright (C) 2003 Michael Hunold <michael@mihu.de>
-
-*/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define DEBUG_VARIABLE debug
-
-#include <media/drv-intf/saa7146_vv.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-
-static int debug;
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "debug verbosity");
-
-/* global variables */
-static int hexium_num;
-
-#define HEXIUM_GEMINI 4
-#define HEXIUM_GEMINI_DUAL 5
-
-#define HEXIUM_INPUTS 9
-static struct v4l2_input hexium_inputs[HEXIUM_INPUTS] = {
- { 0, "CVBS 1", V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
- { 1, "CVBS 2", V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
- { 2, "CVBS 3", V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
- { 3, "CVBS 4", V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
- { 4, "CVBS 5", V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
- { 5, "CVBS 6", V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
- { 6, "Y/C 1", V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
- { 7, "Y/C 2", V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
- { 8, "Y/C 3", V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
-};
-
-#define HEXIUM_AUDIOS 0
-
-struct hexium_data
-{
- s8 adr;
- u8 byte;
-};
-
-#define HEXIUM_GEMINI_V_1_0 1
-#define HEXIUM_GEMINI_DUAL_V_1_0 2
-
-struct hexium
-{
- int type;
-
- struct video_device video_dev;
- struct i2c_adapter i2c_adapter;
-
- int cur_input; /* current input */
- v4l2_std_id cur_std; /* current standard */
-};
-
-/* Samsung KS0127B decoder default registers */
-static u8 hexium_ks0127b[0x100]={
-/*00*/ 0x00,0x52,0x30,0x40,0x01,0x0C,0x2A,0x10,
-/*08*/ 0x00,0x00,0x00,0x60,0x00,0x00,0x0F,0x06,
-/*10*/ 0x00,0x00,0xE4,0xC0,0x00,0x00,0x00,0x00,
-/*18*/ 0x14,0x9B,0xFE,0xFF,0xFC,0xFF,0x03,0x22,
-/*20*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/*28*/ 0x00,0x00,0x00,0x00,0x00,0x2C,0x9B,0x00,
-/*30*/ 0x00,0x00,0x10,0x80,0x80,0x10,0x80,0x80,
-/*38*/ 0x01,0x04,0x00,0x00,0x00,0x29,0xC0,0x00,
-/*40*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/*48*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/*50*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/*58*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/*60*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/*68*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/*70*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/*78*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/*80*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/*88*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/*90*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/*98*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/*A0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/*A8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/*B0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/*B8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/*C0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/*C8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/*D0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/*D8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/*E0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/*E8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/*F0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/*F8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
-};
-
-static struct hexium_data hexium_pal[] = {
- { 0x01, 0x52 }, { 0x12, 0x64 }, { 0x2D, 0x2C }, { 0x2E, 0x9B }, { -1 , 0xFF }
-};
-
-static struct hexium_data hexium_ntsc[] = {
- { 0x01, 0x53 }, { 0x12, 0x04 }, { 0x2D, 0x23 }, { 0x2E, 0x81 }, { -1 , 0xFF }
-};
-
-static struct hexium_data hexium_secam[] = {
- { 0x01, 0x52 }, { 0x12, 0x64 }, { 0x2D, 0x2C }, { 0x2E, 0x9B }, { -1 , 0xFF }
-};
-
-static struct hexium_data hexium_input_select[] = {
- { 0x02, 0x60 },
- { 0x02, 0x64 },
- { 0x02, 0x61 },
- { 0x02, 0x65 },
- { 0x02, 0x62 },
- { 0x02, 0x66 },
- { 0x02, 0x68 },
- { 0x02, 0x69 },
- { 0x02, 0x6A },
-};
-
-/* fixme: h_offset = 0 for Hexium Gemini *Dual*, which
- are currently *not* supported*/
-static struct saa7146_standard hexium_standards[] = {
- {
- .name = "PAL", .id = V4L2_STD_PAL,
- .v_offset = 28, .v_field = 288,
- .h_offset = 1, .h_pixels = 680,
- .v_max_out = 576, .h_max_out = 768,
- }, {
- .name = "NTSC", .id = V4L2_STD_NTSC,
- .v_offset = 28, .v_field = 240,
- .h_offset = 1, .h_pixels = 640,
- .v_max_out = 480, .h_max_out = 640,
- }, {
- .name = "SECAM", .id = V4L2_STD_SECAM,
- .v_offset = 28, .v_field = 288,
- .h_offset = 1, .h_pixels = 720,
- .v_max_out = 576, .h_max_out = 768,
- }
-};
-
-/* bring hardware to a sane state. this has to be done, just in case someone
- wants to capture from this device before it has been properly initialized.
- the capture engine would badly fail, because no valid signal arrives on the
- saa7146, thus leading to timeouts and stuff. */
-static int hexium_init_done(struct saa7146_dev *dev)
-{
- struct hexium *hexium = (struct hexium *) dev->ext_priv;
- union i2c_smbus_data data;
- int i = 0;
-
- DEB_D("hexium_init_done called\n");
-
- /* initialize the helper ics to useful values */
- for (i = 0; i < sizeof(hexium_ks0127b); i++) {
- data.byte = hexium_ks0127b[i];
- if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, i, I2C_SMBUS_BYTE_DATA, &data)) {
- pr_err("hexium_init_done() failed for address 0x%02x\n",
- i);
- }
- }
-
- return 0;
-}
-
-static int hexium_set_input(struct hexium *hexium, int input)
-{
- union i2c_smbus_data data;
-
- DEB_D("\n");
-
- data.byte = hexium_input_select[input].byte;
- if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, hexium_input_select[input].adr, I2C_SMBUS_BYTE_DATA, &data)) {
- return -1;
- }
-
- return 0;
-}
-
-static int hexium_set_standard(struct hexium *hexium, struct hexium_data *vdec)
-{
- union i2c_smbus_data data;
- int i = 0;
-
- DEB_D("\n");
-
- while (vdec[i].adr != -1) {
- data.byte = vdec[i].byte;
- if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, vdec[i].adr, I2C_SMBUS_BYTE_DATA, &data)) {
- pr_err("hexium_init_done: hexium_set_standard() failed for address 0x%02x\n",
- i);
- return -1;
- }
- i++;
- }
- return 0;
-}
-
-static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
-{
- DEB_EE("VIDIOC_ENUMINPUT %d\n", i->index);
-
- if (i->index >= HEXIUM_INPUTS)
- return -EINVAL;
-
- memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input));
-
- DEB_D("v4l2_ioctl: VIDIOC_ENUMINPUT %d\n", i->index);
- return 0;
-}
-
-static int vidioc_g_input(struct file *file, void *fh, unsigned int *input)
-{
- struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
- struct hexium *hexium = (struct hexium *) dev->ext_priv;
-
- *input = hexium->cur_input;
-
- DEB_D("VIDIOC_G_INPUT: %d\n", *input);
- return 0;
-}
-
-static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
-{
- struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
- struct hexium *hexium = (struct hexium *) dev->ext_priv;
-
- DEB_EE("VIDIOC_S_INPUT %d\n", input);
-
- if (input >= HEXIUM_INPUTS)
- return -EINVAL;
-
- hexium->cur_input = input;
- hexium_set_input(hexium, input);
- return 0;
-}
-
-static struct saa7146_ext_vv vv_data;
-
-/* this function only gets called when the probing was successful */
-static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
-{
- struct hexium *hexium;
- int ret;
-
- DEB_EE("\n");
-
- hexium = kzalloc(sizeof(*hexium), GFP_KERNEL);
- if (!hexium)
- return -ENOMEM;
-
- dev->ext_priv = hexium;
-
- /* enable i2c-port pins */
- saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26));
-
- strscpy(hexium->i2c_adapter.name, "hexium gemini",
- sizeof(hexium->i2c_adapter.name));
- saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
- if (i2c_add_adapter(&hexium->i2c_adapter) < 0) {
- DEB_S("cannot register i2c-device. skipping.\n");
- kfree(hexium);
- return -EFAULT;
- }
-
- /* set HWControl GPIO number 2 */
- saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
-
- saa7146_write(dev, DD1_INIT, 0x07000700);
- saa7146_write(dev, DD1_STREAM_B, 0x00000000);
- saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
-
- /* the rest */
- hexium->cur_input = 0;
- hexium_init_done(dev);
-
- hexium_set_standard(hexium, hexium_pal);
- hexium->cur_std = V4L2_STD_PAL;
-
- hexium_set_input(hexium, 0);
- hexium->cur_input = 0;
-
- ret = saa7146_vv_init(dev, &vv_data);
- if (ret) {
- i2c_del_adapter(&hexium->i2c_adapter);
- kfree(hexium);
- return ret;
- }
-
- vv_data.vid_ops.vidioc_enum_input = vidioc_enum_input;
- vv_data.vid_ops.vidioc_g_input = vidioc_g_input;
- vv_data.vid_ops.vidioc_s_input = vidioc_s_input;
- ret = saa7146_register_device(&hexium->video_dev, dev, "hexium gemini", VFL_TYPE_VIDEO);
- if (ret < 0) {
- pr_err("cannot register capture v4l2 device. skipping.\n");
- saa7146_vv_release(dev);
- i2c_del_adapter(&hexium->i2c_adapter);
- kfree(hexium);
- return ret;
- }
-
- pr_info("found 'hexium gemini' frame grabber-%d\n", hexium_num);
- hexium_num++;
-
- return 0;
-}
-
-static int hexium_detach(struct saa7146_dev *dev)
-{
- struct hexium *hexium = (struct hexium *) dev->ext_priv;
-
- DEB_EE("dev:%p\n", dev);
-
- saa7146_unregister_device(&hexium->video_dev, dev);
- saa7146_vv_release(dev);
-
- hexium_num--;
-
- i2c_del_adapter(&hexium->i2c_adapter);
- kfree(hexium);
- return 0;
-}
-
-static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *std)
-{
- struct hexium *hexium = (struct hexium *) dev->ext_priv;
-
- if (V4L2_STD_PAL == std->id) {
- hexium_set_standard(hexium, hexium_pal);
- hexium->cur_std = V4L2_STD_PAL;
- return 0;
- } else if (V4L2_STD_NTSC == std->id) {
- hexium_set_standard(hexium, hexium_ntsc);
- hexium->cur_std = V4L2_STD_NTSC;
- return 0;
- } else if (V4L2_STD_SECAM == std->id) {
- hexium_set_standard(hexium, hexium_secam);
- hexium->cur_std = V4L2_STD_SECAM;
- return 0;
- }
-
- return -1;
-}
-
-static struct saa7146_extension hexium_extension;
-
-static struct saa7146_pci_extension_data hexium_gemini_4bnc = {
- .ext_priv = "Hexium Gemini (4 BNC)",
- .ext = &hexium_extension,
-};
-
-static struct saa7146_pci_extension_data hexium_gemini_dual_4bnc = {
- .ext_priv = "Hexium Gemini Dual (4 BNC)",
- .ext = &hexium_extension,
-};
-
-static const struct pci_device_id pci_tbl[] = {
- {
- .vendor = PCI_VENDOR_ID_PHILIPS,
- .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
- .subvendor = 0x17c8,
- .subdevice = 0x2401,
- .driver_data = (unsigned long) &hexium_gemini_4bnc,
- },
- {
- .vendor = PCI_VENDOR_ID_PHILIPS,
- .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
- .subvendor = 0x17c8,
- .subdevice = 0x2402,
- .driver_data = (unsigned long) &hexium_gemini_dual_4bnc,
- },
- {
- .vendor = 0,
- }
-};
-
-MODULE_DEVICE_TABLE(pci, pci_tbl);
-
-static struct saa7146_ext_vv vv_data = {
- .inputs = HEXIUM_INPUTS,
- .capabilities = 0,
- .stds = &hexium_standards[0],
- .num_stds = ARRAY_SIZE(hexium_standards),
- .std_callback = &std_callback,
-};
-
-static struct saa7146_extension hexium_extension = {
- .name = "hexium gemini",
- .flags = SAA7146_USE_I2C_IRQ,
-
- .pci_tbl = &pci_tbl[0],
- .module = THIS_MODULE,
-
- .attach = hexium_attach,
- .detach = hexium_detach,
-
- .irq_mask = 0,
- .irq_func = NULL,
-};
-
-static int __init hexium_init_module(void)
-{
- if (0 != saa7146_register_extension(&hexium_extension)) {
- DEB_S("failed to register extension\n");
- return -ENODEV;
- }
-
- return 0;
-}
-
-static void __exit hexium_cleanup_module(void)
-{
- saa7146_unregister_extension(&hexium_extension);
-}
-
-module_init(hexium_init_module);
-module_exit(hexium_cleanup_module);
-
-MODULE_DESCRIPTION("video4linux-2 driver for Hexium Gemini frame grabber cards");
-MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/pci/saa7146/hexium_orion.c b/drivers/media/pci/saa7146/hexium_orion.c
deleted file mode 100644
index 2eb4bee16b71..000000000000
--- a/drivers/media/pci/saa7146/hexium_orion.c
+++ /dev/null
@@ -1,496 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- hexium_orion.c - v4l2 driver for the Hexium Orion frame grabber cards
-
- Visit http://www.mihu.de/linux/saa7146/ and follow the link
- to "hexium" for further details about this card.
-
- Copyright (C) 2003 Michael Hunold <michael@mihu.de>
-
-*/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define DEBUG_VARIABLE debug
-
-#include <media/drv-intf/saa7146_vv.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-
-static int debug;
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "debug verbosity");
-
-/* global variables */
-static int hexium_num;
-
-#define HEXIUM_HV_PCI6_ORION 1
-#define HEXIUM_ORION_1SVHS_3BNC 2
-#define HEXIUM_ORION_4BNC 3
-
-#define HEXIUM_INPUTS 9
-static struct v4l2_input hexium_inputs[HEXIUM_INPUTS] = {
- { 0, "CVBS 1", V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
- { 1, "CVBS 2", V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
- { 2, "CVBS 3", V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
- { 3, "CVBS 4", V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
- { 4, "CVBS 5", V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
- { 5, "CVBS 6", V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
- { 6, "Y/C 1", V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
- { 7, "Y/C 2", V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
- { 8, "Y/C 3", V4L2_INPUT_TYPE_CAMERA, 0, 0, V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
-};
-
-#define HEXIUM_AUDIOS 0
-
-struct hexium_data
-{
- s8 adr;
- u8 byte;
-};
-
-struct hexium
-{
- int type;
- struct video_device video_dev;
- struct i2c_adapter i2c_adapter;
-
- int cur_input; /* current input */
-};
-
-/* Philips SAA7110 decoder default registers */
-static u8 hexium_saa7110[53]={
-/*00*/ 0x4C,0x3C,0x0D,0xEF,0xBD,0xF0,0x00,0x00,
-/*08*/ 0xF8,0xF8,0x60,0x60,0x40,0x86,0x18,0x90,
-/*10*/ 0x00,0x2C,0x40,0x46,0x42,0x1A,0xFF,0xDA,
-/*18*/ 0xF0,0x8B,0x00,0x00,0x00,0x00,0x00,0x00,
-/*20*/ 0xD9,0x17,0x40,0x41,0x80,0x41,0x80,0x4F,
-/*28*/ 0xFE,0x01,0x0F,0x0F,0x03,0x01,0x81,0x03,
-/*30*/ 0x44,0x75,0x01,0x8C,0x03
-};
-
-static struct {
- struct hexium_data data[8];
-} hexium_input_select[] = {
-{
- { /* cvbs 1 */
- { 0x06, 0x00 },
- { 0x20, 0xD9 },
- { 0x21, 0x17 }, // 0x16,
- { 0x22, 0x40 },
- { 0x2C, 0x03 },
- { 0x30, 0x44 },
- { 0x31, 0x75 }, // ??
- { 0x21, 0x16 }, // 0x03,
- }
-}, {
- { /* cvbs 2 */
- { 0x06, 0x00 },
- { 0x20, 0x78 },
- { 0x21, 0x07 }, // 0x03,
- { 0x22, 0xD2 },
- { 0x2C, 0x83 },
- { 0x30, 0x60 },
- { 0x31, 0xB5 }, // ?
- { 0x21, 0x03 },
- }
-}, {
- { /* cvbs 3 */
- { 0x06, 0x00 },
- { 0x20, 0xBA },
- { 0x21, 0x07 }, // 0x05,
- { 0x22, 0x91 },
- { 0x2C, 0x03 },
- { 0x30, 0x60 },
- { 0x31, 0xB5 }, // ??
- { 0x21, 0x05 }, // 0x03,
- }
-}, {
- { /* cvbs 4 */
- { 0x06, 0x00 },
- { 0x20, 0xD8 },
- { 0x21, 0x17 }, // 0x16,
- { 0x22, 0x40 },
- { 0x2C, 0x03 },
- { 0x30, 0x44 },
- { 0x31, 0x75 }, // ??
- { 0x21, 0x16 }, // 0x03,
- }
-}, {
- { /* cvbs 5 */
- { 0x06, 0x00 },
- { 0x20, 0xB8 },
- { 0x21, 0x07 }, // 0x05,
- { 0x22, 0x91 },
- { 0x2C, 0x03 },
- { 0x30, 0x60 },
- { 0x31, 0xB5 }, // ??
- { 0x21, 0x05 }, // 0x03,
- }
-}, {
- { /* cvbs 6 */
- { 0x06, 0x00 },
- { 0x20, 0x7C },
- { 0x21, 0x07 }, // 0x03
- { 0x22, 0xD2 },
- { 0x2C, 0x83 },
- { 0x30, 0x60 },
- { 0x31, 0xB5 }, // ??
- { 0x21, 0x03 },
- }
-}, {
- { /* y/c 1 */
- { 0x06, 0x80 },
- { 0x20, 0x59 },
- { 0x21, 0x17 },
- { 0x22, 0x42 },
- { 0x2C, 0xA3 },
- { 0x30, 0x44 },
- { 0x31, 0x75 },
- { 0x21, 0x12 },
- }
-}, {
- { /* y/c 2 */
- { 0x06, 0x80 },
- { 0x20, 0x9A },
- { 0x21, 0x17 },
- { 0x22, 0xB1 },
- { 0x2C, 0x13 },
- { 0x30, 0x60 },
- { 0x31, 0xB5 },
- { 0x21, 0x14 },
- }
-}, {
- { /* y/c 3 */
- { 0x06, 0x80 },
- { 0x20, 0x3C },
- { 0x21, 0x27 },
- { 0x22, 0xC1 },
- { 0x2C, 0x23 },
- { 0x30, 0x44 },
- { 0x31, 0x75 },
- { 0x21, 0x21 },
- }
-}
-};
-
-static struct saa7146_standard hexium_standards[] = {
- {
- .name = "PAL", .id = V4L2_STD_PAL,
- .v_offset = 16, .v_field = 288,
- .h_offset = 1, .h_pixels = 680,
- .v_max_out = 576, .h_max_out = 768,
- }, {
- .name = "NTSC", .id = V4L2_STD_NTSC,
- .v_offset = 16, .v_field = 240,
- .h_offset = 1, .h_pixels = 640,
- .v_max_out = 480, .h_max_out = 640,
- }, {
- .name = "SECAM", .id = V4L2_STD_SECAM,
- .v_offset = 16, .v_field = 288,
- .h_offset = 1, .h_pixels = 720,
- .v_max_out = 576, .h_max_out = 768,
- }
-};
-
-/* this is only called for old HV-PCI6/Orion cards
- without eeprom */
-static int hexium_probe(struct saa7146_dev *dev)
-{
- struct hexium *hexium = NULL;
- union i2c_smbus_data data;
- int err = 0;
-
- DEB_EE("\n");
-
- /* there are no hexium orion cards with revision 0 saa7146s */
- if (0 == dev->revision) {
- return -EFAULT;
- }
-
- hexium = kzalloc(sizeof(*hexium), GFP_KERNEL);
- if (!hexium)
- return -ENOMEM;
-
- /* enable i2c-port pins */
- saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26));
-
- saa7146_write(dev, DD1_INIT, 0x01000100);
- saa7146_write(dev, DD1_STREAM_B, 0x00000000);
- saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
-
- strscpy(hexium->i2c_adapter.name, "hexium orion",
- sizeof(hexium->i2c_adapter.name));
- saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
- if (i2c_add_adapter(&hexium->i2c_adapter) < 0) {
- DEB_S("cannot register i2c-device. skipping.\n");
- kfree(hexium);
- return -EFAULT;
- }
-
- /* set SAA7110 control GPIO 0 */
- saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTHI);
- /* set HWControl GPIO number 2 */
- saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
-
- mdelay(10);
-
- /* detect newer Hexium Orion cards by subsystem ids */
- if (0x17c8 == dev->pci->subsystem_vendor && 0x0101 == dev->pci->subsystem_device) {
- pr_info("device is a Hexium Orion w/ 1 SVHS + 3 BNC inputs\n");
- /* we store the pointer in our private data field */
- dev->ext_priv = hexium;
- hexium->type = HEXIUM_ORION_1SVHS_3BNC;
- return 0;
- }
-
- if (0x17c8 == dev->pci->subsystem_vendor && 0x2101 == dev->pci->subsystem_device) {
- pr_info("device is a Hexium Orion w/ 4 BNC inputs\n");
- /* we store the pointer in our private data field */
- dev->ext_priv = hexium;
- hexium->type = HEXIUM_ORION_4BNC;
- return 0;
- }
-
- /* check if this is an old hexium Orion card by looking at
- a saa7110 at address 0x4e */
- err = i2c_smbus_xfer(&hexium->i2c_adapter, 0x4e, 0, I2C_SMBUS_READ,
- 0x00, I2C_SMBUS_BYTE_DATA, &data);
- if (err == 0) {
- pr_info("device is a Hexium HV-PCI6/Orion (old)\n");
- /* we store the pointer in our private data field */
- dev->ext_priv = hexium;
- hexium->type = HEXIUM_HV_PCI6_ORION;
- return 0;
- }
-
- i2c_del_adapter(&hexium->i2c_adapter);
- kfree(hexium);
- return -EFAULT;
-}
-
-/* bring hardware to a sane state. this has to be done, just in case someone
- wants to capture from this device before it has been properly initialized.
- the capture engine would badly fail, because no valid signal arrives on the
- saa7146, thus leading to timeouts and stuff. */
-static int hexium_init_done(struct saa7146_dev *dev)
-{
- struct hexium *hexium = (struct hexium *) dev->ext_priv;
- union i2c_smbus_data data;
- int i = 0;
-
- DEB_D("hexium_init_done called\n");
-
- /* initialize the helper ics to useful values */
- for (i = 0; i < sizeof(hexium_saa7110); i++) {
- data.byte = hexium_saa7110[i];
- if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, i, I2C_SMBUS_BYTE_DATA, &data)) {
- pr_err("failed for address 0x%02x\n", i);
- }
- }
-
- return 0;
-}
-
-static int hexium_set_input(struct hexium *hexium, int input)
-{
- union i2c_smbus_data data;
- int i = 0;
-
- DEB_D("\n");
-
- for (i = 0; i < 8; i++) {
- int adr = hexium_input_select[input].data[i].adr;
- data.byte = hexium_input_select[input].data[i].byte;
- if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, adr, I2C_SMBUS_BYTE_DATA, &data)) {
- return -1;
- }
- pr_debug("%d: 0x%02x => 0x%02x\n", input, adr, data.byte);
- }
-
- return 0;
-}
-
-static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
-{
- DEB_EE("VIDIOC_ENUMINPUT %d\n", i->index);
-
- if (i->index >= HEXIUM_INPUTS)
- return -EINVAL;
-
- memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input));
-
- DEB_D("v4l2_ioctl: VIDIOC_ENUMINPUT %d\n", i->index);
- return 0;
-}
-
-static int vidioc_g_input(struct file *file, void *fh, unsigned int *input)
-{
- struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
- struct hexium *hexium = (struct hexium *) dev->ext_priv;
-
- *input = hexium->cur_input;
-
- DEB_D("VIDIOC_G_INPUT: %d\n", *input);
- return 0;
-}
-
-static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
-{
- struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
- struct hexium *hexium = (struct hexium *) dev->ext_priv;
-
- if (input >= HEXIUM_INPUTS)
- return -EINVAL;
-
- hexium->cur_input = input;
- hexium_set_input(hexium, input);
-
- return 0;
-}
-
-static struct saa7146_ext_vv vv_data;
-
-/* this function only gets called when the probing was successful */
-static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
-{
- struct hexium *hexium = (struct hexium *) dev->ext_priv;
- int ret;
-
- DEB_EE("\n");
-
- ret = saa7146_vv_init(dev, &vv_data);
- if (ret) {
- pr_err("Error in saa7146_vv_init()\n");
- return ret;
- }
-
- vv_data.vid_ops.vidioc_enum_input = vidioc_enum_input;
- vv_data.vid_ops.vidioc_g_input = vidioc_g_input;
- vv_data.vid_ops.vidioc_s_input = vidioc_s_input;
- if (0 != saa7146_register_device(&hexium->video_dev, dev, "hexium orion", VFL_TYPE_VIDEO)) {
- pr_err("cannot register capture v4l2 device. skipping.\n");
- return -1;
- }
-
- pr_err("found 'hexium orion' frame grabber-%d\n", hexium_num);
- hexium_num++;
-
- /* the rest */
- hexium->cur_input = 0;
- hexium_init_done(dev);
-
- return 0;
-}
-
-static int hexium_detach(struct saa7146_dev *dev)
-{
- struct hexium *hexium = (struct hexium *) dev->ext_priv;
-
- DEB_EE("dev:%p\n", dev);
-
- saa7146_unregister_device(&hexium->video_dev, dev);
- saa7146_vv_release(dev);
-
- hexium_num--;
-
- i2c_del_adapter(&hexium->i2c_adapter);
- kfree(hexium);
- return 0;
-}
-
-static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *std)
-{
- return 0;
-}
-
-static struct saa7146_extension extension;
-
-static struct saa7146_pci_extension_data hexium_hv_pci6 = {
- .ext_priv = "Hexium HV-PCI6 / Orion",
- .ext = &extension,
-};
-
-static struct saa7146_pci_extension_data hexium_orion_1svhs_3bnc = {
- .ext_priv = "Hexium HV-PCI6 / Orion (1 SVHS/3 BNC)",
- .ext = &extension,
-};
-
-static struct saa7146_pci_extension_data hexium_orion_4bnc = {
- .ext_priv = "Hexium HV-PCI6 / Orion (4 BNC)",
- .ext = &extension,
-};
-
-static const struct pci_device_id pci_tbl[] = {
- {
- .vendor = PCI_VENDOR_ID_PHILIPS,
- .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
- .subvendor = 0x0000,
- .subdevice = 0x0000,
- .driver_data = (unsigned long) &hexium_hv_pci6,
- },
- {
- .vendor = PCI_VENDOR_ID_PHILIPS,
- .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
- .subvendor = 0x17c8,
- .subdevice = 0x0101,
- .driver_data = (unsigned long) &hexium_orion_1svhs_3bnc,
- },
- {
- .vendor = PCI_VENDOR_ID_PHILIPS,
- .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
- .subvendor = 0x17c8,
- .subdevice = 0x2101,
- .driver_data = (unsigned long) &hexium_orion_4bnc,
- },
- {
- .vendor = 0,
- }
-};
-
-MODULE_DEVICE_TABLE(pci, pci_tbl);
-
-static struct saa7146_ext_vv vv_data = {
- .inputs = HEXIUM_INPUTS,
- .capabilities = 0,
- .stds = &hexium_standards[0],
- .num_stds = ARRAY_SIZE(hexium_standards),
- .std_callback = &std_callback,
-};
-
-static struct saa7146_extension extension = {
- .name = "hexium HV-PCI6 Orion",
- .flags = 0, // SAA7146_USE_I2C_IRQ,
-
- .pci_tbl = &pci_tbl[0],
- .module = THIS_MODULE,
-
- .probe = hexium_probe,
- .attach = hexium_attach,
- .detach = hexium_detach,
-
- .irq_mask = 0,
- .irq_func = NULL,
-};
-
-static int __init hexium_init_module(void)
-{
- if (0 != saa7146_register_extension(&extension)) {
- DEB_S("failed to register extension\n");
- return -ENODEV;
- }
-
- return 0;
-}
-
-static void __exit hexium_cleanup_module(void)
-{
- saa7146_unregister_extension(&extension);
-}
-
-module_init(hexium_init_module);
-module_exit(hexium_cleanup_module);
-
-MODULE_DESCRIPTION("video4linux-2 driver for Hexium Orion frame grabber cards");
-MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/pci/saa7146/mxb.c b/drivers/media/pci/saa7146/mxb.c
deleted file mode 100644
index 7ded8f5b05cb..000000000000
--- a/drivers/media/pci/saa7146/mxb.c
+++ /dev/null
@@ -1,873 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- mxb - v4l2 driver for the Multimedia eXtension Board
-
- Copyright (C) 1998-2006 Michael Hunold <michael@mihu.de>
-
- Visit http://www.themm.net/~mihu/linux/saa7146/mxb.html
- for further details about this card.
-
-*/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define DEBUG_VARIABLE debug
-
-#include <media/drv-intf/saa7146_vv.h>
-#include <media/tuner.h>
-#include <media/v4l2-common.h>
-#include <media/i2c/saa7115.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-
-#include "tea6415c.h"
-#include "tea6420.h"
-
-#define MXB_AUDIOS 6
-
-#define I2C_SAA7111A 0x24
-#define I2C_TDA9840 0x42
-#define I2C_TEA6415C 0x43
-#define I2C_TEA6420_1 0x4c
-#define I2C_TEA6420_2 0x4d
-#define I2C_TUNER 0x60
-
-#define MXB_BOARD_CAN_DO_VBI(dev) (dev->revision != 0)
-
-/* global variable */
-static int mxb_num;
-
-/* initial frequence the tuner will be tuned to.
- in verden (lower saxony, germany) 4148 is a
- channel called "phoenix" */
-static int freq = 4148;
-module_param(freq, int, 0644);
-MODULE_PARM_DESC(freq, "initial frequency the tuner will be tuned to while setup");
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
-
-#define MXB_INPUTS 4
-enum { TUNER, AUX1, AUX3, AUX3_YC };
-
-static struct v4l2_input mxb_inputs[MXB_INPUTS] = {
- { TUNER, "Tuner", V4L2_INPUT_TYPE_TUNER, 0x3f, 0,
- V4L2_STD_PAL_BG | V4L2_STD_PAL_I, 0, V4L2_IN_CAP_STD },
- { AUX1, "AUX1", V4L2_INPUT_TYPE_CAMERA, 0x3f, 0,
- V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
- { AUX3, "AUX3 Composite", V4L2_INPUT_TYPE_CAMERA, 0x3f, 0,
- V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
- { AUX3_YC, "AUX3 S-Video", V4L2_INPUT_TYPE_CAMERA, 0x3f, 0,
- V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
-};
-
-/* this array holds the information, which port of the saa7146 each
- input actually uses. the mxb uses port 0 for every input */
-static struct {
- int hps_source;
- int hps_sync;
-} input_port_selection[MXB_INPUTS] = {
- { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
- { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
- { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
- { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
-};
-
-/* this array holds the information of the audio source (mxb_audios),
- which has to be switched corresponding to the video source (mxb_channels) */
-static int video_audio_connect[MXB_INPUTS] =
- { 0, 1, 3, 3 };
-
-struct mxb_routing {
- u32 input;
- u32 output;
-};
-
-/* these are the available audio sources, which can switched
- to the line- and cd-output individually */
-static struct v4l2_audio mxb_audios[MXB_AUDIOS] = {
- {
- .index = 0,
- .name = "Tuner",
- .capability = V4L2_AUDCAP_STEREO,
- } , {
- .index = 1,
- .name = "AUX1",
- .capability = V4L2_AUDCAP_STEREO,
- } , {
- .index = 2,
- .name = "AUX2",
- .capability = V4L2_AUDCAP_STEREO,
- } , {
- .index = 3,
- .name = "AUX3",
- .capability = V4L2_AUDCAP_STEREO,
- } , {
- .index = 4,
- .name = "Radio (X9)",
- .capability = V4L2_AUDCAP_STEREO,
- } , {
- .index = 5,
- .name = "CD-ROM (X10)",
- .capability = V4L2_AUDCAP_STEREO,
- }
-};
-
-/* These are the necessary input-output-pins for bringing one audio source
- (see above) to the CD-output. Note that gain is set to 0 in this table. */
-static struct mxb_routing TEA6420_cd[MXB_AUDIOS + 1][2] = {
- { { 1, 1 }, { 1, 1 } }, /* Tuner */
- { { 5, 1 }, { 6, 1 } }, /* AUX 1 */
- { { 4, 1 }, { 6, 1 } }, /* AUX 2 */
- { { 3, 1 }, { 6, 1 } }, /* AUX 3 */
- { { 1, 1 }, { 3, 1 } }, /* Radio */
- { { 1, 1 }, { 2, 1 } }, /* CD-Rom */
- { { 6, 1 }, { 6, 1 } } /* Mute */
-};
-
-/* These are the necessary input-output-pins for bringing one audio source
- (see above) to the line-output. Note that gain is set to 0 in this table. */
-static struct mxb_routing TEA6420_line[MXB_AUDIOS + 1][2] = {
- { { 2, 3 }, { 1, 2 } },
- { { 5, 3 }, { 6, 2 } },
- { { 4, 3 }, { 6, 2 } },
- { { 3, 3 }, { 6, 2 } },
- { { 2, 3 }, { 3, 2 } },
- { { 2, 3 }, { 2, 2 } },
- { { 6, 3 }, { 6, 2 } } /* Mute */
-};
-
-struct mxb
-{
- struct video_device video_dev;
- struct video_device vbi_dev;
-
- struct i2c_adapter i2c_adapter;
-
- struct v4l2_subdev *saa7111a;
- struct v4l2_subdev *tda9840;
- struct v4l2_subdev *tea6415c;
- struct v4l2_subdev *tuner;
- struct v4l2_subdev *tea6420_1;
- struct v4l2_subdev *tea6420_2;
-
- int cur_mode; /* current audio mode (mono, stereo, ...) */
- int cur_input; /* current input */
- int cur_audinput; /* current audio input */
- int cur_mute; /* current mute status */
- struct v4l2_frequency cur_freq; /* current frequency the tuner is tuned to */
-};
-
-#define saa7111a_call(mxb, o, f, args...) \
- v4l2_subdev_call(mxb->saa7111a, o, f, ##args)
-#define tda9840_call(mxb, o, f, args...) \
- v4l2_subdev_call(mxb->tda9840, o, f, ##args)
-#define tea6415c_call(mxb, o, f, args...) \
- v4l2_subdev_call(mxb->tea6415c, o, f, ##args)
-#define tuner_call(mxb, o, f, args...) \
- v4l2_subdev_call(mxb->tuner, o, f, ##args)
-#define call_all(dev, o, f, args...) \
- v4l2_device_call_until_err(&dev->v4l2_dev, 0, o, f, ##args)
-
-static void mxb_update_audmode(struct mxb *mxb)
-{
- struct v4l2_tuner t = {
- .audmode = mxb->cur_mode,
- };
-
- tda9840_call(mxb, tuner, s_tuner, &t);
-}
-
-static inline void tea6420_route(struct mxb *mxb, int idx)
-{
- v4l2_subdev_call(mxb->tea6420_1, audio, s_routing,
- TEA6420_cd[idx][0].input, TEA6420_cd[idx][0].output, 0);
- v4l2_subdev_call(mxb->tea6420_2, audio, s_routing,
- TEA6420_cd[idx][1].input, TEA6420_cd[idx][1].output, 0);
- v4l2_subdev_call(mxb->tea6420_1, audio, s_routing,
- TEA6420_line[idx][0].input, TEA6420_line[idx][0].output, 0);
- v4l2_subdev_call(mxb->tea6420_2, audio, s_routing,
- TEA6420_line[idx][1].input, TEA6420_line[idx][1].output, 0);
-}
-
-static struct saa7146_extension extension;
-
-static int mxb_s_ctrl(struct v4l2_ctrl *ctrl)
-{
- struct saa7146_dev *dev = container_of(ctrl->handler,
- struct saa7146_dev, ctrl_handler);
- struct mxb *mxb = dev->ext_priv;
-
- switch (ctrl->id) {
- case V4L2_CID_AUDIO_MUTE:
- mxb->cur_mute = ctrl->val;
- /* switch the audio-source */
- tea6420_route(mxb, ctrl->val ? 6 :
- video_audio_connect[mxb->cur_input]);
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-static const struct v4l2_ctrl_ops mxb_ctrl_ops = {
- .s_ctrl = mxb_s_ctrl,
-};
-
-static int mxb_probe(struct saa7146_dev *dev)
-{
- struct v4l2_ctrl_handler *hdl = &dev->ctrl_handler;
- struct mxb *mxb = NULL;
-
- v4l2_ctrl_new_std(hdl, &mxb_ctrl_ops,
- V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
- if (hdl->error)
- return hdl->error;
- mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL);
- if (mxb == NULL) {
- DEB_D("not enough kernel memory\n");
- return -ENOMEM;
- }
-
-
- snprintf(mxb->i2c_adapter.name, sizeof(mxb->i2c_adapter.name), "mxb%d", mxb_num);
-
- saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
- if (i2c_add_adapter(&mxb->i2c_adapter) < 0) {
- DEB_S("cannot register i2c-device. skipping.\n");
- kfree(mxb);
- return -EFAULT;
- }
-
- mxb->saa7111a = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
- "saa7111", I2C_SAA7111A, NULL);
- mxb->tea6420_1 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
- "tea6420", I2C_TEA6420_1, NULL);
- mxb->tea6420_2 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
- "tea6420", I2C_TEA6420_2, NULL);
- mxb->tea6415c = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
- "tea6415c", I2C_TEA6415C, NULL);
- mxb->tda9840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
- "tda9840", I2C_TDA9840, NULL);
- mxb->tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
- "tuner", I2C_TUNER, NULL);
-
- /* check if all devices are present */
- if (!mxb->tea6420_1 || !mxb->tea6420_2 || !mxb->tea6415c ||
- !mxb->tda9840 || !mxb->saa7111a || !mxb->tuner) {
- pr_err("did not find all i2c devices. aborting\n");
- i2c_del_adapter(&mxb->i2c_adapter);
- kfree(mxb);
- return -ENODEV;
- }
-
- /* all devices are present, probe was successful */
-
- /* we store the pointer in our private data field */
- dev->ext_priv = mxb;
-
- v4l2_ctrl_handler_setup(hdl);
-
- return 0;
-}
-
-/* some init data for the saa7740, the so-called 'sound arena module'.
- there are no specs available, so we simply use some init values */
-static struct {
- int length;
- char data[9];
-} mxb_saa7740_init[] = {
- { 3, { 0x80, 0x00, 0x00 } },{ 3, { 0x80, 0x89, 0x00 } },
- { 3, { 0x80, 0xb0, 0x0a } },{ 3, { 0x00, 0x00, 0x00 } },
- { 3, { 0x49, 0x00, 0x00 } },{ 3, { 0x4a, 0x00, 0x00 } },
- { 3, { 0x4b, 0x00, 0x00 } },{ 3, { 0x4c, 0x00, 0x00 } },
- { 3, { 0x4d, 0x00, 0x00 } },{ 3, { 0x4e, 0x00, 0x00 } },
- { 3, { 0x4f, 0x00, 0x00 } },{ 3, { 0x50, 0x00, 0x00 } },
- { 3, { 0x51, 0x00, 0x00 } },{ 3, { 0x52, 0x00, 0x00 } },
- { 3, { 0x53, 0x00, 0x00 } },{ 3, { 0x54, 0x00, 0x00 } },
- { 3, { 0x55, 0x00, 0x00 } },{ 3, { 0x56, 0x00, 0x00 } },
- { 3, { 0x57, 0x00, 0x00 } },{ 3, { 0x58, 0x00, 0x00 } },
- { 3, { 0x59, 0x00, 0x00 } },{ 3, { 0x5a, 0x00, 0x00 } },
- { 3, { 0x5b, 0x00, 0x00 } },{ 3, { 0x5c, 0x00, 0x00 } },
- { 3, { 0x5d, 0x00, 0x00 } },{ 3, { 0x5e, 0x00, 0x00 } },
- { 3, { 0x5f, 0x00, 0x00 } },{ 3, { 0x60, 0x00, 0x00 } },
- { 3, { 0x61, 0x00, 0x00 } },{ 3, { 0x62, 0x00, 0x00 } },
- { 3, { 0x63, 0x00, 0x00 } },{ 3, { 0x64, 0x00, 0x00 } },
- { 3, { 0x65, 0x00, 0x00 } },{ 3, { 0x66, 0x00, 0x00 } },
- { 3, { 0x67, 0x00, 0x00 } },{ 3, { 0x68, 0x00, 0x00 } },
- { 3, { 0x69, 0x00, 0x00 } },{ 3, { 0x6a, 0x00, 0x00 } },
- { 3, { 0x6b, 0x00, 0x00 } },{ 3, { 0x6c, 0x00, 0x00 } },
- { 3, { 0x6d, 0x00, 0x00 } },{ 3, { 0x6e, 0x00, 0x00 } },
- { 3, { 0x6f, 0x00, 0x00 } },{ 3, { 0x70, 0x00, 0x00 } },
- { 3, { 0x71, 0x00, 0x00 } },{ 3, { 0x72, 0x00, 0x00 } },
- { 3, { 0x73, 0x00, 0x00 } },{ 3, { 0x74, 0x00, 0x00 } },
- { 3, { 0x75, 0x00, 0x00 } },{ 3, { 0x76, 0x00, 0x00 } },
- { 3, { 0x77, 0x00, 0x00 } },{ 3, { 0x41, 0x00, 0x42 } },
- { 3, { 0x42, 0x10, 0x42 } },{ 3, { 0x43, 0x20, 0x42 } },
- { 3, { 0x44, 0x30, 0x42 } },{ 3, { 0x45, 0x00, 0x01 } },
- { 3, { 0x46, 0x00, 0x01 } },{ 3, { 0x47, 0x00, 0x01 } },
- { 3, { 0x48, 0x00, 0x01 } },
- { 9, { 0x01, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
- { 9, { 0x21, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
- { 9, { 0x09, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
- { 9, { 0x29, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
- { 9, { 0x11, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
- { 9, { 0x31, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
- { 9, { 0x19, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
- { 9, { 0x39, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
- { 9, { 0x05, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
- { 9, { 0x25, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
- { 9, { 0x0d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
- { 9, { 0x2d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
- { 9, { 0x15, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
- { 9, { 0x35, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
- { 9, { 0x1d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
- { 9, { 0x3d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
- { 3, { 0x80, 0xb3, 0x0a } },
- {-1, { 0 } }
-};
-
-/* bring hardware to a sane state. this has to be done, just in case someone
- wants to capture from this device before it has been properly initialized.
- the capture engine would badly fail, because no valid signal arrives on the
- saa7146, thus leading to timeouts and stuff. */
-static int mxb_init_done(struct saa7146_dev* dev)
-{
- struct mxb* mxb = (struct mxb*)dev->ext_priv;
- struct i2c_msg msg;
- struct tuner_setup tun_setup;
- v4l2_std_id std = V4L2_STD_PAL_BG;
-
- int i, err = 0;
-
- /* mute audio on tea6420s */
- tea6420_route(mxb, 6);
-
- /* select video mode in saa7111a */
- saa7111a_call(mxb, video, s_std, std);
-
- /* select tuner-output on saa7111a */
- saa7111a_call(mxb, video, s_routing, SAA7115_COMPOSITE0,
- SAA7111_FMT_CCIR, 0);
-
- /* select a tuner type */
- tun_setup.mode_mask = T_ANALOG_TV;
- tun_setup.addr = ADDR_UNSET;
- tun_setup.type = TUNER_PHILIPS_PAL;
- tuner_call(mxb, tuner, s_type_addr, &tun_setup);
- /* tune in some frequency on tuner */
- mxb->cur_freq.tuner = 0;
- mxb->cur_freq.type = V4L2_TUNER_ANALOG_TV;
- mxb->cur_freq.frequency = freq;
- tuner_call(mxb, tuner, s_frequency, &mxb->cur_freq);
-
- /* set a default video standard */
- /* These two gpio calls set the GPIO pins that control the tda9820 */
- saa7146_write(dev, GPIO_CTRL, 0x00404050);
- saa7111a_call(mxb, core, s_gpio, 1);
- saa7111a_call(mxb, video, s_std, std);
- tuner_call(mxb, video, s_std, std);
-
- /* switch to tuner-channel on tea6415c */
- tea6415c_call(mxb, video, s_routing, 3, 17, 0);
-
- /* select tuner-output on multicable on tea6415c */
- tea6415c_call(mxb, video, s_routing, 3, 13, 0);
-
- /* the rest for mxb */
- mxb->cur_input = 0;
- mxb->cur_audinput = video_audio_connect[mxb->cur_input];
- mxb->cur_mute = 1;
-
- mxb->cur_mode = V4L2_TUNER_MODE_STEREO;
- mxb_update_audmode(mxb);
-
- /* check if the saa7740 (aka 'sound arena module') is present
- on the mxb. if so, we must initialize it. due to lack of
- information about the saa7740, the values were reverse
- engineered. */
- msg.addr = 0x1b;
- msg.flags = 0;
- msg.len = mxb_saa7740_init[0].length;
- msg.buf = &mxb_saa7740_init[0].data[0];
-
- err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
- if (err == 1) {
- /* the sound arena module is a pos, that's probably the reason
- philips refuses to hand out a datasheet for the saa7740...
- it seems to screw up the i2c bus, so we disable fast irq
- based i2c transactions here and rely on the slow and safe
- polling method ... */
- extension.flags &= ~SAA7146_USE_I2C_IRQ;
- for (i = 1; ; i++) {
- if (-1 == mxb_saa7740_init[i].length)
- break;
-
- msg.len = mxb_saa7740_init[i].length;
- msg.buf = &mxb_saa7740_init[i].data[0];
- err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
- if (err != 1) {
- DEB_D("failed to initialize 'sound arena module'\n");
- goto err;
- }
- }
- pr_info("'sound arena module' detected\n");
- }
-err:
- /* the rest for saa7146: you should definitely set some basic values
- for the input-port handling of the saa7146. */
-
- /* ext->saa has been filled by the core driver */
-
- /* some stuff is done via variables */
- saa7146_set_hps_source_and_sync(dev, input_port_selection[mxb->cur_input].hps_source,
- input_port_selection[mxb->cur_input].hps_sync);
-
- /* some stuff is done via direct write to the registers */
-
- /* this is ugly, but because of the fact that this is completely
- hardware dependend, it should be done directly... */
- saa7146_write(dev, DD1_STREAM_B, 0x00000000);
- saa7146_write(dev, DD1_INIT, 0x02000200);
- saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
-
- return 0;
-}
-
-/* interrupt-handler. this gets called when irq_mask is != 0.
- it must clear the interrupt-bits in irq_mask it has handled */
-/*
-void mxb_irq_bh(struct saa7146_dev* dev, u32* irq_mask)
-{
- struct mxb* mxb = (struct mxb*)dev->ext_priv;
-}
-*/
-
-static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
-{
- DEB_EE("VIDIOC_ENUMINPUT %d\n", i->index);
- if (i->index >= MXB_INPUTS)
- return -EINVAL;
- memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input));
- return 0;
-}
-
-static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
-{
- struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
- struct mxb *mxb = (struct mxb *)dev->ext_priv;
- *i = mxb->cur_input;
-
- DEB_EE("VIDIOC_G_INPUT %d\n", *i);
- return 0;
-}
-
-static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
-{
- struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
- struct mxb *mxb = (struct mxb *)dev->ext_priv;
- int err = 0;
- int i = 0;
-
- DEB_EE("VIDIOC_S_INPUT %d\n", input);
-
- if (input >= MXB_INPUTS)
- return -EINVAL;
-
- mxb->cur_input = input;
-
- saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source,
- input_port_selection[input].hps_sync);
-
- /* prepare switching of tea6415c and saa7111a;
- have a look at the 'background'-file for further information */
- switch (input) {
- case TUNER:
- i = SAA7115_COMPOSITE0;
-
- err = tea6415c_call(mxb, video, s_routing, 3, 17, 0);
-
- /* connect tuner-output always to multicable */
- if (!err)
- err = tea6415c_call(mxb, video, s_routing, 3, 13, 0);
- break;
- case AUX3_YC:
- /* nothing to be done here. aux3_yc is
- directly connected to the saa711a */
- i = SAA7115_SVIDEO1;
- break;
- case AUX3:
- /* nothing to be done here. aux3 is
- directly connected to the saa711a */
- i = SAA7115_COMPOSITE1;
- break;
- case AUX1:
- i = SAA7115_COMPOSITE0;
- err = tea6415c_call(mxb, video, s_routing, 1, 17, 0);
- break;
- }
-
- if (err)
- return err;
-
- /* switch video in saa7111a */
- if (saa7111a_call(mxb, video, s_routing, i, SAA7111_FMT_CCIR, 0))
- pr_err("VIDIOC_S_INPUT: could not address saa7111a\n");
-
- mxb->cur_audinput = video_audio_connect[input];
- /* switch the audio-source only if necessary */
- if (0 == mxb->cur_mute)
- tea6420_route(mxb, mxb->cur_audinput);
- if (mxb->cur_audinput == 0)
- mxb_update_audmode(mxb);
-
- return 0;
-}
-
-static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
-{
- struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
- struct mxb *mxb = (struct mxb *)dev->ext_priv;
-
- if (t->index) {
- DEB_D("VIDIOC_G_TUNER: channel %d does not have a tuner attached\n",
- t->index);
- return -EINVAL;
- }
-
- DEB_EE("VIDIOC_G_TUNER: %d\n", t->index);
-
- memset(t, 0, sizeof(*t));
- strscpy(t->name, "TV Tuner", sizeof(t->name));
- t->type = V4L2_TUNER_ANALOG_TV;
- t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO |
- V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
- t->audmode = mxb->cur_mode;
- return call_all(dev, tuner, g_tuner, t);
-}
-
-static int vidioc_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *t)
-{
- struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
- struct mxb *mxb = (struct mxb *)dev->ext_priv;
-
- if (t->index) {
- DEB_D("VIDIOC_S_TUNER: channel %d does not have a tuner attached\n",
- t->index);
- return -EINVAL;
- }
-
- mxb->cur_mode = t->audmode;
- return call_all(dev, tuner, s_tuner, t);
-}
-
-static int vidioc_querystd(struct file *file, void *fh, v4l2_std_id *norm)
-{
- struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
-
- return call_all(dev, video, querystd, norm);
-}
-
-static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
-{
- struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
- struct mxb *mxb = (struct mxb *)dev->ext_priv;
-
- if (f->tuner)
- return -EINVAL;
- *f = mxb->cur_freq;
-
- DEB_EE("VIDIOC_G_FREQ: freq:0x%08x\n", mxb->cur_freq.frequency);
- return 0;
-}
-
-static int vidioc_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *f)
-{
- struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
- struct mxb *mxb = (struct mxb *)dev->ext_priv;
- struct saa7146_vv *vv = dev->vv_data;
-
- if (f->tuner)
- return -EINVAL;
-
- if (V4L2_TUNER_ANALOG_TV != f->type)
- return -EINVAL;
-
- DEB_EE("VIDIOC_S_FREQUENCY: freq:0x%08x\n", mxb->cur_freq.frequency);
-
- /* tune in desired frequency */
- tuner_call(mxb, tuner, s_frequency, f);
- /* let the tuner subdev clamp the frequency to the tuner range */
- mxb->cur_freq = *f;
- tuner_call(mxb, tuner, g_frequency, &mxb->cur_freq);
- if (mxb->cur_audinput == 0)
- mxb_update_audmode(mxb);
-
- if (mxb->cur_input)
- return 0;
-
- /* hack: changing the frequency should invalidate the vbi-counter (=> alevt) */
- spin_lock(&dev->slock);
- vv->vbi_fieldcount = 0;
- spin_unlock(&dev->slock);
-
- return 0;
-}
-
-static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a)
-{
- if (a->index >= MXB_AUDIOS)
- return -EINVAL;
- *a = mxb_audios[a->index];
- return 0;
-}
-
-static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
-{
- struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
- struct mxb *mxb = (struct mxb *)dev->ext_priv;
-
- DEB_EE("VIDIOC_G_AUDIO\n");
- *a = mxb_audios[mxb->cur_audinput];
- return 0;
-}
-
-static int vidioc_s_audio(struct file *file, void *fh, const struct v4l2_audio *a)
-{
- struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
- struct mxb *mxb = (struct mxb *)dev->ext_priv;
-
- DEB_D("VIDIOC_S_AUDIO %d\n", a->index);
- if (a->index >= 32 ||
- !(mxb_inputs[mxb->cur_input].audioset & (1 << a->index)))
- return -EINVAL;
-
- if (mxb->cur_audinput != a->index) {
- mxb->cur_audinput = a->index;
- tea6420_route(mxb, a->index);
- if (mxb->cur_audinput == 0)
- mxb_update_audmode(mxb);
- }
- return 0;
-}
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int vidioc_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
-{
- struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
-
- if (reg->reg > pci_resource_len(dev->pci, 0) - 4)
- return -EINVAL;
- reg->val = saa7146_read(dev, reg->reg);
- reg->size = 4;
- return 0;
-}
-
-static int vidioc_s_register(struct file *file, void *fh, const struct v4l2_dbg_register *reg)
-{
- struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
-
- if (reg->reg > pci_resource_len(dev->pci, 0) - 4)
- return -EINVAL;
- saa7146_write(dev, reg->reg, reg->val);
- return 0;
-}
-#endif
-
-static struct saa7146_ext_vv vv_data;
-
-/* this function only gets called when the probing was successful */
-static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
-{
- struct mxb *mxb;
- int ret;
-
- DEB_EE("dev:%p\n", dev);
-
- ret = saa7146_vv_init(dev, &vv_data);
- if (ret) {
- ERR("Error in saa7146_vv_init()");
- return ret;
- }
-
- if (mxb_probe(dev)) {
- saa7146_vv_release(dev);
- return -1;
- }
- mxb = (struct mxb *)dev->ext_priv;
-
- vv_data.vid_ops.vidioc_enum_input = vidioc_enum_input;
- vv_data.vid_ops.vidioc_g_input = vidioc_g_input;
- vv_data.vid_ops.vidioc_s_input = vidioc_s_input;
- vv_data.vid_ops.vidioc_querystd = vidioc_querystd;
- vv_data.vid_ops.vidioc_g_tuner = vidioc_g_tuner;
- vv_data.vid_ops.vidioc_s_tuner = vidioc_s_tuner;
- vv_data.vid_ops.vidioc_g_frequency = vidioc_g_frequency;
- vv_data.vid_ops.vidioc_s_frequency = vidioc_s_frequency;
- vv_data.vid_ops.vidioc_enumaudio = vidioc_enumaudio;
- vv_data.vid_ops.vidioc_g_audio = vidioc_g_audio;
- vv_data.vid_ops.vidioc_s_audio = vidioc_s_audio;
-#ifdef CONFIG_VIDEO_ADV_DEBUG
- vv_data.vid_ops.vidioc_g_register = vidioc_g_register;
- vv_data.vid_ops.vidioc_s_register = vidioc_s_register;
-#endif
- if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_VIDEO)) {
- ERR("cannot register capture v4l2 device. skipping.\n");
- saa7146_vv_release(dev);
- return -1;
- }
-
- /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/
- if (MXB_BOARD_CAN_DO_VBI(dev)) {
- if (saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) {
- ERR("cannot register vbi v4l2 device. skipping.\n");
- }
- }
-
- pr_info("found Multimedia eXtension Board #%d\n", mxb_num);
-
- mxb_num++;
- mxb_init_done(dev);
- return 0;
-}
-
-static int mxb_detach(struct saa7146_dev *dev)
-{
- struct mxb *mxb = (struct mxb *)dev->ext_priv;
-
- DEB_EE("dev:%p\n", dev);
-
- /* mute audio on tea6420s */
- tea6420_route(mxb, 6);
-
- saa7146_unregister_device(&mxb->video_dev,dev);
- if (MXB_BOARD_CAN_DO_VBI(dev))
- saa7146_unregister_device(&mxb->vbi_dev, dev);
- saa7146_vv_release(dev);
-
- mxb_num--;
-
- i2c_del_adapter(&mxb->i2c_adapter);
- kfree(mxb);
-
- return 0;
-}
-
-static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standard)
-{
- struct mxb *mxb = (struct mxb *)dev->ext_priv;
-
- if (V4L2_STD_PAL_I == standard->id) {
- v4l2_std_id std = V4L2_STD_PAL_I;
-
- DEB_D("VIDIOC_S_STD: setting mxb for PAL_I\n");
- /* These two gpio calls set the GPIO pins that control the tda9820 */
- saa7146_write(dev, GPIO_CTRL, 0x00404050);
- saa7111a_call(mxb, core, s_gpio, 0);
- saa7111a_call(mxb, video, s_std, std);
- if (mxb->cur_input == 0)
- tuner_call(mxb, video, s_std, std);
- } else {
- v4l2_std_id std = V4L2_STD_PAL_BG;
-
- if (mxb->cur_input)
- std = standard->id;
- DEB_D("VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM\n");
- /* These two gpio calls set the GPIO pins that control the tda9820 */
- saa7146_write(dev, GPIO_CTRL, 0x00404050);
- saa7111a_call(mxb, core, s_gpio, 1);
- saa7111a_call(mxb, video, s_std, std);
- if (mxb->cur_input == 0)
- tuner_call(mxb, video, s_std, std);
- }
- return 0;
-}
-
-static struct saa7146_standard standard[] = {
- {
- .name = "PAL-BG", .id = V4L2_STD_PAL_BG,
- .v_offset = 0x17, .v_field = 288,
- .h_offset = 0x14, .h_pixels = 680,
- .v_max_out = 576, .h_max_out = 768,
- }, {
- .name = "PAL-I", .id = V4L2_STD_PAL_I,
- .v_offset = 0x17, .v_field = 288,
- .h_offset = 0x14, .h_pixels = 680,
- .v_max_out = 576, .h_max_out = 768,
- }, {
- .name = "NTSC", .id = V4L2_STD_NTSC,
- .v_offset = 0x16, .v_field = 240,
- .h_offset = 0x06, .h_pixels = 708,
- .v_max_out = 480, .h_max_out = 640,
- }, {
- .name = "SECAM", .id = V4L2_STD_SECAM,
- .v_offset = 0x14, .v_field = 288,
- .h_offset = 0x14, .h_pixels = 720,
- .v_max_out = 576, .h_max_out = 768,
- }
-};
-
-static struct saa7146_pci_extension_data mxb = {
- .ext_priv = "Multimedia eXtension Board",
- .ext = &extension,
-};
-
-static const struct pci_device_id pci_tbl[] = {
- {
- .vendor = PCI_VENDOR_ID_PHILIPS,
- .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
- .subvendor = 0x0000,
- .subdevice = 0x0000,
- .driver_data = (unsigned long)&mxb,
- }, {
- .vendor = 0,
- }
-};
-
-MODULE_DEVICE_TABLE(pci, pci_tbl);
-
-static struct saa7146_ext_vv vv_data = {
- .inputs = MXB_INPUTS,
- .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_AUDIO,
- .stds = &standard[0],
- .num_stds = ARRAY_SIZE(standard),
- .std_callback = &std_callback,
-};
-
-static struct saa7146_extension extension = {
- .name = "Multimedia eXtension Board",
- .flags = SAA7146_USE_I2C_IRQ,
-
- .pci_tbl = &pci_tbl[0],
- .module = THIS_MODULE,
-
- .attach = mxb_attach,
- .detach = mxb_detach,
-
- .irq_mask = 0,
- .irq_func = NULL,
-};
-
-static int __init mxb_init_module(void)
-{
- if (saa7146_register_extension(&extension)) {
- DEB_S("failed to register extension\n");
- return -ENODEV;
- }
-
- return 0;
-}
-
-static void __exit mxb_cleanup_module(void)
-{
- saa7146_unregister_extension(&extension);
-}
-
-module_init(mxb_init_module);
-module_exit(mxb_cleanup_module);
-
-MODULE_DESCRIPTION("video4linux-2 driver for the Siemens-Nixdorf 'Multimedia eXtension board'");
-MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/pci/saa7164/saa7164-core.c b/drivers/media/pci/saa7164/saa7164-core.c
index 7973ae42873a..d5f32e3ff544 100644
--- a/drivers/media/pci/saa7164/saa7164-core.c
+++ b/drivers/media/pci/saa7164/saa7164-core.c
@@ -626,7 +626,7 @@ static irqreturn_t saa7164_irq(int irq, void *dev_id)
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
+ * 0xFF then the device is not accessible, the IRQ belongs
* to another driver.
* 4 x u32 interrupt registers.
*/
diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
index 80d20e2a2099..0adf3d80f248 100644
--- a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
+++ b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
@@ -1020,7 +1020,7 @@ static int solo_g_parm(struct file *file, void *priv,
cp->timeperframe.numerator = solo_enc->interval;
cp->timeperframe.denominator = solo_enc->solo_dev->fps;
cp->capturemode = 0;
- /* XXX: Shouldn't we be able to get/set this from videobuf? */
+ /* XXX: Shouldn't we be able to get/set this from vb2? */
cp->readbuffers = 2;
return 0;
diff --git a/drivers/media/pci/ttpci/Kconfig b/drivers/media/pci/ttpci/Kconfig
deleted file mode 100644
index 65a6832a6b96..000000000000
--- a/drivers/media/pci/ttpci/Kconfig
+++ /dev/null
@@ -1,86 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-config DVB_BUDGET_CORE
- tristate "SAA7146 DVB cards (aka Budget, Nova-PCI)"
- depends on DVB_CORE && PCI && I2C
- select VIDEO_SAA7146
- select TTPCI_EEPROM
- help
- Support for simple SAA7146 based DVB cards
- (so called Budget- or Nova-PCI cards) without onboard
- MPEG2 decoder.
-
-config DVB_BUDGET
- tristate "Budget cards"
- depends on DVB_BUDGET_CORE && I2C
- select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT
- select DVB_VES1X93 if MEDIA_SUBDRV_AUTOSELECT
- select DVB_VES1820 if MEDIA_SUBDRV_AUTOSELECT
- select DVB_L64781 if MEDIA_SUBDRV_AUTOSELECT
- select DVB_TDA8083 if MEDIA_SUBDRV_AUTOSELECT
- select DVB_S5H1420 if MEDIA_SUBDRV_AUTOSELECT
- select DVB_TDA10086 if MEDIA_SUBDRV_AUTOSELECT
- select DVB_TDA826X if MEDIA_SUBDRV_AUTOSELECT
- select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT
- select DVB_TDA1004X if MEDIA_SUBDRV_AUTOSELECT
- select DVB_ISL6423 if MEDIA_SUBDRV_AUTOSELECT
- select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT
- select DVB_STV6110x if MEDIA_SUBDRV_AUTOSELECT
- help
- Support for simple SAA7146 based DVB cards (so called Budget-
- or Nova-PCI cards) without onboard MPEG2 decoder, and without
- analog inputs or an onboard Common Interface connector.
-
- Say Y if you own such a card and want to use it.
-
- To compile this driver as a module, choose M here: the
- module will be called budget.
-
-config DVB_BUDGET_CI
- tristate "Budget cards with onboard CI connector"
- depends on DVB_BUDGET_CORE && I2C
- select DVB_STV0297 if MEDIA_SUBDRV_AUTOSELECT
- select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT
- select DVB_TDA1004X if MEDIA_SUBDRV_AUTOSELECT
- select DVB_STB0899 if MEDIA_SUBDRV_AUTOSELECT
- select DVB_STB6100 if MEDIA_SUBDRV_AUTOSELECT
- select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT
- select DVB_STV0288 if MEDIA_SUBDRV_AUTOSELECT
- select DVB_STB6000 if MEDIA_SUBDRV_AUTOSELECT
- select DVB_TDA10023 if MEDIA_SUBDRV_AUTOSELECT
- select MEDIA_TUNER_TDA827X if MEDIA_SUBDRV_AUTOSELECT
- depends on RC_CORE
- help
- Support for simple SAA7146 based DVB cards
- (so called Budget- or Nova-PCI cards) without onboard
- MPEG2 decoder, but with onboard Common Interface connector.
-
- Note: The Common Interface is not yet supported by this driver
- due to lack of information from the vendor.
-
- Say Y if you own such a card and want to use it.
-
- To compile this driver as a module, choose M here: the
- module will be called budget-ci.
-
-config DVB_BUDGET_AV
- tristate "Budget cards with analog video inputs"
- depends on DVB_BUDGET_CORE && I2C
- select VIDEO_SAA7146_VV
- depends on VIDEO_DEV # dependencies of VIDEO_SAA7146_VV
- select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT
- select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT
- select DVB_TDA1004X if MEDIA_SUBDRV_AUTOSELECT
- select DVB_TDA10021 if MEDIA_SUBDRV_AUTOSELECT
- select DVB_TDA10023 if MEDIA_SUBDRV_AUTOSELECT
- select DVB_STB0899 if MEDIA_SUBDRV_AUTOSELECT
- select DVB_TDA8261 if MEDIA_SUBDRV_AUTOSELECT
- select DVB_TUA6100 if MEDIA_SUBDRV_AUTOSELECT
- help
- Support for simple SAA7146 based DVB cards
- (so called Budget- or Nova-PCI cards) without onboard
- MPEG2 decoder, but with one or more analog video inputs.
-
- Say Y if you own such a card and want to use it.
-
- To compile this driver as a module, choose M here: the
- module will be called budget-av.
diff --git a/drivers/media/pci/ttpci/Makefile b/drivers/media/pci/ttpci/Makefile
deleted file mode 100644
index b0708f6e40cc..000000000000
--- a/drivers/media/pci/ttpci/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# Makefile for the kernel SAA7146 FULL TS DVB device driver
-#
-
-obj-$(CONFIG_DVB_BUDGET_CORE) += budget-core.o
-obj-$(CONFIG_DVB_BUDGET) += budget.o
-obj-$(CONFIG_DVB_BUDGET_AV) += budget-av.o
-obj-$(CONFIG_DVB_BUDGET_CI) += budget-ci.o
-
-ccflags-y += -I $(srctree)/drivers/media/dvb-frontends/
-ccflags-y += -I $(srctree)/drivers/media/tuners
-ccflags-y += -I $(srctree)/drivers/media/common
diff --git a/drivers/media/pci/ttpci/budget-av.c b/drivers/media/pci/ttpci/budget-av.c
deleted file mode 100644
index 3cb83005cf09..000000000000
--- a/drivers/media/pci/ttpci/budget-av.c
+++ /dev/null
@@ -1,1622 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * budget-av.c: driver for the SAA7146 based Budget DVB cards
- * with analog video in
- *
- * Compiled from various sources by Michael Hunold <michael@mihu.de>
- *
- * CI interface support (c) 2004 Olivier Gournet <ogournet@anevia.com> &
- * Andrew de Quincey <adq_dvb@lidskialf.net>
- *
- * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
- *
- * Copyright (C) 1999-2002 Ralph Metzler
- * & Marcus Metzler for convergence integrated media GmbH
- *
- * the project's page is at https://linuxtv.org
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include "budget.h"
-#include "stv0299.h"
-#include "stb0899_drv.h"
-#include "stb0899_reg.h"
-#include "stb0899_cfg.h"
-#include "tda8261.h"
-#include "tda8261_cfg.h"
-#include "tda1002x.h"
-#include "tda1004x.h"
-#include "tua6100.h"
-#include "dvb-pll.h"
-#include <media/drv-intf/saa7146_vv.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/input.h>
-#include <linux/spinlock.h>
-
-#include <media/dvb_ca_en50221.h>
-
-#define DEBICICAM 0x02420000
-
-#define SLOTSTATUS_NONE 1
-#define SLOTSTATUS_PRESENT 2
-#define SLOTSTATUS_RESET 4
-#define SLOTSTATUS_READY 8
-#define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-struct budget_av {
- struct budget budget;
- struct video_device vd;
- int cur_input;
- int has_saa7113;
- struct tasklet_struct ciintf_irq_tasklet;
- int slot_status;
- struct dvb_ca_en50221 ca;
- u8 reinitialise_demod:1;
-};
-
-static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot);
-
-
-/* GPIO Connections:
- * 0 - Vcc/Reset (Reset is controlled by capacitor). Resets the frontend *AS WELL*!
- * 1 - CI memory select 0=>IO memory, 1=>Attribute Memory
- * 2 - CI Card Enable (Active Low)
- * 3 - CI Card Detect
- */
-
-/****************************************************************************
- * INITIALIZATION
- ****************************************************************************/
-
-static u8 i2c_readreg(struct i2c_adapter *i2c, u8 id, u8 reg)
-{
- u8 mm1[] = { 0x00 };
- u8 mm2[] = { 0x00 };
- struct i2c_msg msgs[2];
-
- msgs[0].flags = 0;
- msgs[1].flags = I2C_M_RD;
- msgs[0].addr = msgs[1].addr = id / 2;
- mm1[0] = reg;
- msgs[0].len = 1;
- msgs[1].len = 1;
- msgs[0].buf = mm1;
- msgs[1].buf = mm2;
-
- i2c_transfer(i2c, msgs, 2);
-
- return mm2[0];
-}
-
-static int i2c_readregs(struct i2c_adapter *i2c, u8 id, u8 reg, u8 * buf, u8 len)
-{
- u8 mm1[] = { reg };
- struct i2c_msg msgs[2] = {
- {.addr = id / 2,.flags = 0,.buf = mm1,.len = 1},
- {.addr = id / 2,.flags = I2C_M_RD,.buf = buf,.len = len}
- };
-
- if (i2c_transfer(i2c, msgs, 2) != 2)
- return -EIO;
-
- return 0;
-}
-
-static int i2c_writereg(struct i2c_adapter *i2c, u8 id, u8 reg, u8 val)
-{
- u8 msg[2] = { reg, val };
- struct i2c_msg msgs;
-
- msgs.flags = 0;
- msgs.addr = id / 2;
- msgs.len = 2;
- msgs.buf = msg;
- return i2c_transfer(i2c, &msgs, 1);
-}
-
-static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
-{
- struct budget_av *budget_av = (struct budget_av *) ca->data;
- int result;
-
- if (slot != 0)
- return -EINVAL;
-
- saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI);
- udelay(1);
-
- result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 1);
- if (result == -ETIMEDOUT) {
- ciintf_slot_shutdown(ca, slot);
- pr_info("cam ejected 1\n");
- }
- return result;
-}
-
-static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)
-{
- struct budget_av *budget_av = (struct budget_av *) ca->data;
- int result;
-
- if (slot != 0)
- return -EINVAL;
-
- saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI);
- udelay(1);
-
- result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 1);
- if (result == -ETIMEDOUT) {
- ciintf_slot_shutdown(ca, slot);
- pr_info("cam ejected 2\n");
- }
- return result;
-}
-
-static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)
-{
- struct budget_av *budget_av = (struct budget_av *) ca->data;
- int result;
-
- if (slot != 0)
- return -EINVAL;
-
- saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
- udelay(1);
-
- result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 3, 1, 0, 0);
- if (result == -ETIMEDOUT) {
- ciintf_slot_shutdown(ca, slot);
- pr_info("cam ejected 3\n");
- return -ETIMEDOUT;
- }
- return result;
-}
-
-static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)
-{
- struct budget_av *budget_av = (struct budget_av *) ca->data;
- int result;
-
- if (slot != 0)
- return -EINVAL;
-
- saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
- udelay(1);
-
- result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 3, 1, value, 0, 0);
- if (result == -ETIMEDOUT) {
- ciintf_slot_shutdown(ca, slot);
- pr_info("cam ejected 5\n");
- }
- return result;
-}
-
-static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
-{
- struct budget_av *budget_av = (struct budget_av *) ca->data;
- struct saa7146_dev *saa = budget_av->budget.dev;
-
- if (slot != 0)
- return -EINVAL;
-
- dprintk(1, "ciintf_slot_reset\n");
- budget_av->slot_status = SLOTSTATUS_RESET;
-
- saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
-
- saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI); /* Vcc off */
- msleep(2);
- saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO); /* Vcc on */
- msleep(20); /* 20 ms Vcc settling time */
-
- saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO); /* enable card */
- ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
- msleep(20);
-
- /* reinitialise the frontend if necessary */
- if (budget_av->reinitialise_demod)
- dvb_frontend_reinitialise(budget_av->budget.dvb_frontend);
-
- return 0;
-}
-
-static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
-{
- struct budget_av *budget_av = (struct budget_av *) ca->data;
- struct saa7146_dev *saa = budget_av->budget.dev;
-
- if (slot != 0)
- return -EINVAL;
-
- dprintk(1, "ciintf_slot_shutdown\n");
-
- ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
- budget_av->slot_status = SLOTSTATUS_NONE;
-
- return 0;
-}
-
-static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
-{
- struct budget_av *budget_av = (struct budget_av *) ca->data;
- struct saa7146_dev *saa = budget_av->budget.dev;
-
- if (slot != 0)
- return -EINVAL;
-
- dprintk(1, "ciintf_slot_ts_enable: %d\n", budget_av->slot_status);
-
- ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA);
-
- return 0;
-}
-
-static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
-{
- struct budget_av *budget_av = (struct budget_av *) ca->data;
- struct saa7146_dev *saa = budget_av->budget.dev;
- int result;
-
- if (slot != 0)
- return -EINVAL;
-
- /* test the card detect line - needs to be done carefully
- * since it never goes high for some CAMs on this interface (e.g. topuptv) */
- if (budget_av->slot_status == SLOTSTATUS_NONE) {
- saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
- udelay(1);
- if (saa7146_read(saa, PSR) & MASK_06) {
- if (budget_av->slot_status == SLOTSTATUS_NONE) {
- budget_av->slot_status = SLOTSTATUS_PRESENT;
- pr_info("cam inserted A\n");
- }
- }
- saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
- }
-
- /* We also try and read from IO memory to work round the above detection bug. If
- * there is no CAM, we will get a timeout. Only done if there is no cam
- * present, since this test actually breaks some cams :(
- *
- * if the CI interface is not open, we also do the above test since we
- * don't care if the cam has problems - we'll be resetting it on open() anyway */
- if ((budget_av->slot_status == SLOTSTATUS_NONE) || (!open)) {
- saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
- result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1);
- if ((result >= 0) && (budget_av->slot_status == SLOTSTATUS_NONE)) {
- budget_av->slot_status = SLOTSTATUS_PRESENT;
- pr_info("cam inserted B\n");
- } else if (result < 0) {
- if (budget_av->slot_status != SLOTSTATUS_NONE) {
- ciintf_slot_shutdown(ca, slot);
- pr_info("cam ejected 5\n");
- return 0;
- }
- }
- }
-
- /* read from attribute memory in reset/ready state to know when the CAM is ready */
- if (budget_av->slot_status == SLOTSTATUS_RESET) {
- result = ciintf_read_attribute_mem(ca, slot, 0);
- if (result == 0x1d) {
- budget_av->slot_status = SLOTSTATUS_READY;
- }
- }
-
- /* work out correct return code */
- if (budget_av->slot_status != SLOTSTATUS_NONE) {
- if (budget_av->slot_status & SLOTSTATUS_READY) {
- return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
- }
- return DVB_CA_EN50221_POLL_CAM_PRESENT;
- }
- return 0;
-}
-
-static int ciintf_init(struct budget_av *budget_av)
-{
- struct saa7146_dev *saa = budget_av->budget.dev;
- int result;
-
- memset(&budget_av->ca, 0, sizeof(struct dvb_ca_en50221));
-
- saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
- saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTLO);
- saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO);
- saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
-
- /* Enable DEBI pins */
- saa7146_write(saa, MC1, MASK_27 | MASK_11);
-
- /* register CI interface */
- budget_av->ca.owner = THIS_MODULE;
- budget_av->ca.read_attribute_mem = ciintf_read_attribute_mem;
- budget_av->ca.write_attribute_mem = ciintf_write_attribute_mem;
- budget_av->ca.read_cam_control = ciintf_read_cam_control;
- budget_av->ca.write_cam_control = ciintf_write_cam_control;
- budget_av->ca.slot_reset = ciintf_slot_reset;
- budget_av->ca.slot_shutdown = ciintf_slot_shutdown;
- budget_av->ca.slot_ts_enable = ciintf_slot_ts_enable;
- budget_av->ca.poll_slot_status = ciintf_poll_slot_status;
- budget_av->ca.data = budget_av;
- budget_av->budget.ci_present = 1;
- budget_av->slot_status = SLOTSTATUS_NONE;
-
- if ((result = dvb_ca_en50221_init(&budget_av->budget.dvb_adapter,
- &budget_av->ca, 0, 1)) != 0) {
- pr_err("ci initialisation failed\n");
- goto error;
- }
-
- pr_info("ci interface initialised\n");
- return 0;
-
-error:
- saa7146_write(saa, MC1, MASK_27);
- return result;
-}
-
-static void ciintf_deinit(struct budget_av *budget_av)
-{
- struct saa7146_dev *saa = budget_av->budget.dev;
-
- saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);
- saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT);
- saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT);
- saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
-
- /* release the CA device */
- dvb_ca_en50221_release(&budget_av->ca);
-
- /* disable DEBI pins */
- saa7146_write(saa, MC1, MASK_27);
-}
-
-
-static const u8 saa7113_tab[] = {
- 0x01, 0x08,
- 0x02, 0xc0,
- 0x03, 0x33,
- 0x04, 0x00,
- 0x05, 0x00,
- 0x06, 0xeb,
- 0x07, 0xe0,
- 0x08, 0x28,
- 0x09, 0x00,
- 0x0a, 0x80,
- 0x0b, 0x47,
- 0x0c, 0x40,
- 0x0d, 0x00,
- 0x0e, 0x01,
- 0x0f, 0x44,
-
- 0x10, 0x08,
- 0x11, 0x0c,
- 0x12, 0x7b,
- 0x13, 0x00,
- 0x15, 0x00, 0x16, 0x00, 0x17, 0x00,
-
- 0x57, 0xff,
- 0x40, 0x82, 0x58, 0x00, 0x59, 0x54, 0x5a, 0x07,
- 0x5b, 0x83, 0x5e, 0x00,
- 0xff
-};
-
-static int saa7113_init(struct budget_av *budget_av)
-{
- struct budget *budget = &budget_av->budget;
- struct saa7146_dev *saa = budget->dev;
- const u8 *data = saa7113_tab;
-
- saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI);
- msleep(200);
-
- if (i2c_writereg(&budget->i2c_adap, 0x4a, 0x01, 0x08) != 1) {
- dprintk(1, "saa7113 not found on KNC card\n");
- return -ENODEV;
- }
-
- dprintk(1, "saa7113 detected and initializing\n");
-
- while (*data != 0xff) {
- i2c_writereg(&budget->i2c_adap, 0x4a, *data, *(data + 1));
- data += 2;
- }
-
- dprintk(1, "saa7113 status=%02x\n", i2c_readreg(&budget->i2c_adap, 0x4a, 0x1f));
-
- return 0;
-}
-
-static int saa7113_setinput(struct budget_av *budget_av, int input)
-{
- struct budget *budget = &budget_av->budget;
-
- if (1 != budget_av->has_saa7113)
- return -ENODEV;
-
- if (input == 1) {
- i2c_writereg(&budget->i2c_adap, 0x4a, 0x02, 0xc7);
- i2c_writereg(&budget->i2c_adap, 0x4a, 0x09, 0x80);
- } else if (input == 0) {
- i2c_writereg(&budget->i2c_adap, 0x4a, 0x02, 0xc0);
- i2c_writereg(&budget->i2c_adap, 0x4a, 0x09, 0x00);
- } else
- return -EINVAL;
-
- budget_av->cur_input = input;
- return 0;
-}
-
-
-static int philips_su1278_ty_ci_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)
-{
- u8 aclk = 0;
- u8 bclk = 0;
- u8 m1;
-
- aclk = 0xb5;
- if (srate < 2000000)
- bclk = 0x86;
- else if (srate < 5000000)
- bclk = 0x89;
- else if (srate < 15000000)
- bclk = 0x8f;
- else if (srate < 45000000)
- bclk = 0x95;
-
- m1 = 0x14;
- if (srate < 4000000)
- m1 = 0x10;
-
- stv0299_writereg(fe, 0x13, aclk);
- stv0299_writereg(fe, 0x14, bclk);
- stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
- stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
- stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
- stv0299_writereg(fe, 0x0f, 0x80 | m1);
-
- return 0;
-}
-
-static int philips_su1278_ty_ci_tuner_set_params(struct dvb_frontend *fe)
-{
- struct dtv_frontend_properties *c = &fe->dtv_property_cache;
- u32 div;
- u8 buf[4];
- struct budget *budget = (struct budget *) fe->dvb->priv;
- struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) };
-
- if ((c->frequency < 950000) || (c->frequency > 2150000))
- return -EINVAL;
-
- div = (c->frequency + (125 - 1)) / 125; /* round correctly */
- buf[0] = (div >> 8) & 0x7f;
- buf[1] = div & 0xff;
- buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
- buf[3] = 0x20;
-
- if (c->symbol_rate < 4000000)
- buf[3] |= 1;
-
- if (c->frequency < 1250000)
- buf[3] |= 0;
- else if (c->frequency < 1550000)
- buf[3] |= 0x40;
- else if (c->frequency < 2050000)
- buf[3] |= 0x80;
- else if (c->frequency < 2150000)
- buf[3] |= 0xC0;
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
- if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
- return -EIO;
- return 0;
-}
-
-static u8 typhoon_cinergy1200s_inittab[] = {
- 0x01, 0x15,
- 0x02, 0x30,
- 0x03, 0x00,
- 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
- 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */
- 0x06, 0x40, /* DAC not used, set to high impendance mode */
- 0x07, 0x00, /* DAC LSB */
- 0x08, 0x40, /* DiSEqC off */
- 0x09, 0x00, /* FIFO */
- 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
- 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */
- 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
- 0x10, 0x3f, // AGC2 0x3d
- 0x11, 0x84,
- 0x12, 0xb9,
- 0x15, 0xc9, // lock detector threshold
- 0x16, 0x00,
- 0x17, 0x00,
- 0x18, 0x00,
- 0x19, 0x00,
- 0x1a, 0x00,
- 0x1f, 0x50,
- 0x20, 0x00,
- 0x21, 0x00,
- 0x22, 0x00,
- 0x23, 0x00,
- 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0
- 0x29, 0x1e, // 1/2 threshold
- 0x2a, 0x14, // 2/3 threshold
- 0x2b, 0x0f, // 3/4 threshold
- 0x2c, 0x09, // 5/6 threshold
- 0x2d, 0x05, // 7/8 threshold
- 0x2e, 0x01,
- 0x31, 0x1f, // test all FECs
- 0x32, 0x19, // viterbi and synchro search
- 0x33, 0xfc, // rs control
- 0x34, 0x93, // error control
- 0x0f, 0x92,
- 0xff, 0xff
-};
-
-static const struct stv0299_config typhoon_config = {
- .demod_address = 0x68,
- .inittab = typhoon_cinergy1200s_inittab,
- .mclk = 88000000UL,
- .invert = 0,
- .skip_reinit = 0,
- .lock_output = STV0299_LOCKOUTPUT_1,
- .volt13_op0_op1 = STV0299_VOLT13_OP0,
- .min_delay_ms = 100,
- .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
-};
-
-
-static const struct stv0299_config cinergy_1200s_config = {
- .demod_address = 0x68,
- .inittab = typhoon_cinergy1200s_inittab,
- .mclk = 88000000UL,
- .invert = 0,
- .skip_reinit = 0,
- .lock_output = STV0299_LOCKOUTPUT_0,
- .volt13_op0_op1 = STV0299_VOLT13_OP0,
- .min_delay_ms = 100,
- .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
-};
-
-static const struct stv0299_config cinergy_1200s_1894_0010_config = {
- .demod_address = 0x68,
- .inittab = typhoon_cinergy1200s_inittab,
- .mclk = 88000000UL,
- .invert = 1,
- .skip_reinit = 0,
- .lock_output = STV0299_LOCKOUTPUT_1,
- .volt13_op0_op1 = STV0299_VOLT13_OP0,
- .min_delay_ms = 100,
- .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
-};
-
-static int philips_cu1216_tuner_set_params(struct dvb_frontend *fe)
-{
- struct dtv_frontend_properties *c = &fe->dtv_property_cache;
- struct budget *budget = (struct budget *) fe->dvb->priv;
- u8 buf[6];
- struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) };
- int i;
-
-#define CU1216_IF 36125000
-#define TUNER_MUL 62500
-
- u32 div = (c->frequency + CU1216_IF + TUNER_MUL / 2) / TUNER_MUL;
-
- buf[0] = (div >> 8) & 0x7f;
- buf[1] = div & 0xff;
- buf[2] = 0xce;
- buf[3] = (c->frequency < 150000000 ? 0x01 :
- c->frequency < 445000000 ? 0x02 : 0x04);
- buf[4] = 0xde;
- buf[5] = 0x20;
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
- if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
- return -EIO;
-
- /* wait for the pll lock */
- msg.flags = I2C_M_RD;
- msg.len = 1;
- for (i = 0; i < 20; i++) {
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
- if (i2c_transfer(&budget->i2c_adap, &msg, 1) == 1 && (buf[0] & 0x40))
- break;
- msleep(10);
- }
-
- /* switch the charge pump to the lower current */
- msg.flags = 0;
- msg.len = 2;
- msg.buf = &buf[2];
- buf[2] &= ~0x40;
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
- if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
- return -EIO;
-
- return 0;
-}
-
-static struct tda1002x_config philips_cu1216_config = {
- .demod_address = 0x0c,
- .invert = 1,
-};
-
-static struct tda1002x_config philips_cu1216_config_altaddress = {
- .demod_address = 0x0d,
- .invert = 0,
-};
-
-static struct tda10023_config philips_cu1216_tda10023_config = {
- .demod_address = 0x0c,
- .invert = 1,
-};
-
-static int philips_tu1216_tuner_init(struct dvb_frontend *fe)
-{
- struct budget *budget = (struct budget *) fe->dvb->priv;
- static u8 tu1216_init[] = { 0x0b, 0xf5, 0x85, 0xab };
- struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tu1216_init,.len = sizeof(tu1216_init) };
-
- // setup PLL configuration
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
- if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1)
- return -EIO;
- msleep(1);
-
- return 0;
-}
-
-static int philips_tu1216_tuner_set_params(struct dvb_frontend *fe)
-{
- struct dtv_frontend_properties *c = &fe->dtv_property_cache;
- struct budget *budget = (struct budget *) fe->dvb->priv;
- u8 tuner_buf[4];
- struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tuner_buf,.len =
- sizeof(tuner_buf) };
- int tuner_frequency = 0;
- u8 band, cp, filter;
-
- // determine charge pump
- tuner_frequency = c->frequency + 36166000;
- if (tuner_frequency < 87000000)
- return -EINVAL;
- else if (tuner_frequency < 130000000)
- cp = 3;
- else if (tuner_frequency < 160000000)
- cp = 5;
- else if (tuner_frequency < 200000000)
- cp = 6;
- else if (tuner_frequency < 290000000)
- cp = 3;
- else if (tuner_frequency < 420000000)
- cp = 5;
- else if (tuner_frequency < 480000000)
- cp = 6;
- else if (tuner_frequency < 620000000)
- cp = 3;
- else if (tuner_frequency < 830000000)
- cp = 5;
- else if (tuner_frequency < 895000000)
- cp = 7;
- else
- return -EINVAL;
-
- // determine band
- if (c->frequency < 49000000)
- return -EINVAL;
- else if (c->frequency < 161000000)
- band = 1;
- else if (c->frequency < 444000000)
- band = 2;
- else if (c->frequency < 861000000)
- band = 4;
- else
- return -EINVAL;
-
- // setup PLL filter
- switch (c->bandwidth_hz) {
- case 6000000:
- filter = 0;
- break;
-
- case 7000000:
- filter = 0;
- break;
-
- case 8000000:
- filter = 1;
- break;
-
- default:
- return -EINVAL;
- }
-
- // calculate divisor
- // ((36166000+((1000000/6)/2)) + Finput)/(1000000/6)
- tuner_frequency = (((c->frequency / 1000) * 6) + 217496) / 1000;
-
- // setup tuner buffer
- tuner_buf[0] = (tuner_frequency >> 8) & 0x7f;
- tuner_buf[1] = tuner_frequency & 0xff;
- tuner_buf[2] = 0xca;
- tuner_buf[3] = (cp << 5) | (filter << 3) | band;
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
- if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1)
- return -EIO;
-
- msleep(1);
- return 0;
-}
-
-static int philips_tu1216_request_firmware(struct dvb_frontend *fe,
- const struct firmware **fw, char *name)
-{
- struct budget *budget = (struct budget *) fe->dvb->priv;
-
- return request_firmware(fw, name, &budget->dev->pci->dev);
-}
-
-static struct tda1004x_config philips_tu1216_config = {
-
- .demod_address = 0x8,
- .invert = 1,
- .invert_oclk = 1,
- .xtal_freq = TDA10046_XTAL_4M,
- .agc_config = TDA10046_AGC_DEFAULT,
- .if_freq = TDA10046_FREQ_3617,
- .request_firmware = philips_tu1216_request_firmware,
-};
-
-static u8 philips_sd1878_inittab[] = {
- 0x01, 0x15,
- 0x02, 0x30,
- 0x03, 0x00,
- 0x04, 0x7d,
- 0x05, 0x35,
- 0x06, 0x40,
- 0x07, 0x00,
- 0x08, 0x43,
- 0x09, 0x02,
- 0x0C, 0x51,
- 0x0D, 0x82,
- 0x0E, 0x23,
- 0x10, 0x3f,
- 0x11, 0x84,
- 0x12, 0xb9,
- 0x15, 0xc9,
- 0x16, 0x19,
- 0x17, 0x8c,
- 0x18, 0x59,
- 0x19, 0xf8,
- 0x1a, 0xfe,
- 0x1c, 0x7f,
- 0x1d, 0x00,
- 0x1e, 0x00,
- 0x1f, 0x50,
- 0x20, 0x00,
- 0x21, 0x00,
- 0x22, 0x00,
- 0x23, 0x00,
- 0x28, 0x00,
- 0x29, 0x28,
- 0x2a, 0x14,
- 0x2b, 0x0f,
- 0x2c, 0x09,
- 0x2d, 0x09,
- 0x31, 0x1f,
- 0x32, 0x19,
- 0x33, 0xfc,
- 0x34, 0x93,
- 0xff, 0xff
-};
-
-static int philips_sd1878_ci_set_symbol_rate(struct dvb_frontend *fe,
- u32 srate, u32 ratio)
-{
- u8 aclk = 0;
- u8 bclk = 0;
- u8 m1;
-
- aclk = 0xb5;
- if (srate < 2000000)
- bclk = 0x86;
- else if (srate < 5000000)
- bclk = 0x89;
- else if (srate < 15000000)
- bclk = 0x8f;
- else if (srate < 45000000)
- bclk = 0x95;
-
- m1 = 0x14;
- if (srate < 4000000)
- m1 = 0x10;
-
- stv0299_writereg(fe, 0x0e, 0x23);
- stv0299_writereg(fe, 0x0f, 0x94);
- stv0299_writereg(fe, 0x10, 0x39);
- stv0299_writereg(fe, 0x13, aclk);
- stv0299_writereg(fe, 0x14, bclk);
- stv0299_writereg(fe, 0x15, 0xc9);
- stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
- stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
- stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
- stv0299_writereg(fe, 0x0f, 0x80 | m1);
-
- return 0;
-}
-
-static const struct stv0299_config philips_sd1878_config = {
- .demod_address = 0x68,
- .inittab = philips_sd1878_inittab,
- .mclk = 88000000UL,
- .invert = 0,
- .skip_reinit = 0,
- .lock_output = STV0299_LOCKOUTPUT_1,
- .volt13_op0_op1 = STV0299_VOLT13_OP0,
- .min_delay_ms = 100,
- .set_symbol_rate = philips_sd1878_ci_set_symbol_rate,
-};
-
-/* KNC1 DVB-S (STB0899) Inittab */
-static const struct stb0899_s1_reg knc1_stb0899_s1_init_1[] = {
-
- { STB0899_DEV_ID , 0x81 },
- { STB0899_DISCNTRL1 , 0x32 },
- { STB0899_DISCNTRL2 , 0x80 },
- { STB0899_DISRX_ST0 , 0x04 },
- { STB0899_DISRX_ST1 , 0x00 },
- { STB0899_DISPARITY , 0x00 },
- { STB0899_DISSTATUS , 0x20 },
- { STB0899_DISF22 , 0x8c },
- { STB0899_DISF22RX , 0x9a },
- { STB0899_SYSREG , 0x0b },
- { STB0899_ACRPRESC , 0x11 },
- { STB0899_ACRDIV1 , 0x0a },
- { STB0899_ACRDIV2 , 0x05 },
- { STB0899_DACR1 , 0x00 },
- { STB0899_DACR2 , 0x00 },
- { STB0899_OUTCFG , 0x00 },
- { STB0899_MODECFG , 0x00 },
- { STB0899_IRQSTATUS_3 , 0x30 },
- { STB0899_IRQSTATUS_2 , 0x00 },
- { STB0899_IRQSTATUS_1 , 0x00 },
- { STB0899_IRQSTATUS_0 , 0x00 },
- { STB0899_IRQMSK_3 , 0xf3 },
- { STB0899_IRQMSK_2 , 0xfc },
- { STB0899_IRQMSK_1 , 0xff },
- { STB0899_IRQMSK_0 , 0xff },
- { STB0899_IRQCFG , 0x00 },
- { STB0899_I2CCFG , 0x88 },
- { STB0899_I2CRPT , 0x58 }, /* Repeater=8, Stop=disabled */
- { STB0899_IOPVALUE5 , 0x00 },
- { STB0899_IOPVALUE4 , 0x20 },
- { STB0899_IOPVALUE3 , 0xc9 },
- { STB0899_IOPVALUE2 , 0x90 },
- { STB0899_IOPVALUE1 , 0x40 },
- { STB0899_IOPVALUE0 , 0x00 },
- { STB0899_GPIO00CFG , 0x82 },
- { STB0899_GPIO01CFG , 0x82 },
- { STB0899_GPIO02CFG , 0x82 },
- { STB0899_GPIO03CFG , 0x82 },
- { STB0899_GPIO04CFG , 0x82 },
- { STB0899_GPIO05CFG , 0x82 },
- { STB0899_GPIO06CFG , 0x82 },
- { STB0899_GPIO07CFG , 0x82 },
- { STB0899_GPIO08CFG , 0x82 },
- { STB0899_GPIO09CFG , 0x82 },
- { STB0899_GPIO10CFG , 0x82 },
- { STB0899_GPIO11CFG , 0x82 },
- { STB0899_GPIO12CFG , 0x82 },
- { STB0899_GPIO13CFG , 0x82 },
- { STB0899_GPIO14CFG , 0x82 },
- { STB0899_GPIO15CFG , 0x82 },
- { STB0899_GPIO16CFG , 0x82 },
- { STB0899_GPIO17CFG , 0x82 },
- { STB0899_GPIO18CFG , 0x82 },
- { STB0899_GPIO19CFG , 0x82 },
- { STB0899_GPIO20CFG , 0x82 },
- { STB0899_SDATCFG , 0xb8 },
- { STB0899_SCLTCFG , 0xba },
- { STB0899_AGCRFCFG , 0x08 }, /* 0x1c */
- { STB0899_GPIO22 , 0x82 }, /* AGCBB2CFG */
- { STB0899_GPIO21 , 0x91 }, /* AGCBB1CFG */
- { STB0899_DIRCLKCFG , 0x82 },
- { STB0899_CLKOUT27CFG , 0x7e },
- { STB0899_STDBYCFG , 0x82 },
- { STB0899_CS0CFG , 0x82 },
- { STB0899_CS1CFG , 0x82 },
- { STB0899_DISEQCOCFG , 0x20 },
- { STB0899_GPIO32CFG , 0x82 },
- { STB0899_GPIO33CFG , 0x82 },
- { STB0899_GPIO34CFG , 0x82 },
- { STB0899_GPIO35CFG , 0x82 },
- { STB0899_GPIO36CFG , 0x82 },
- { STB0899_GPIO37CFG , 0x82 },
- { STB0899_GPIO38CFG , 0x82 },
- { STB0899_GPIO39CFG , 0x82 },
- { STB0899_NCOARSE , 0x15 }, /* 0x15 = 27 Mhz Clock, F/3 = 198MHz, F/6 = 99MHz */
- { STB0899_SYNTCTRL , 0x02 }, /* 0x00 = CLK from CLKI, 0x02 = CLK from XTALI */
- { STB0899_FILTCTRL , 0x00 },
- { STB0899_SYSCTRL , 0x00 },
- { STB0899_STOPCLK1 , 0x20 },
- { STB0899_STOPCLK2 , 0x00 },
- { STB0899_INTBUFSTATUS , 0x00 },
- { STB0899_INTBUFCTRL , 0x0a },
- { 0xffff , 0xff },
-};
-
-static const struct stb0899_s1_reg knc1_stb0899_s1_init_3[] = {
- { STB0899_DEMOD , 0x00 },
- { STB0899_RCOMPC , 0xc9 },
- { STB0899_AGC1CN , 0x41 },
- { STB0899_AGC1REF , 0x08 },
- { STB0899_RTC , 0x7a },
- { STB0899_TMGCFG , 0x4e },
- { STB0899_AGC2REF , 0x33 },
- { STB0899_TLSR , 0x84 },
- { STB0899_CFD , 0xee },
- { STB0899_ACLC , 0x87 },
- { STB0899_BCLC , 0x94 },
- { STB0899_EQON , 0x41 },
- { STB0899_LDT , 0xdd },
- { STB0899_LDT2 , 0xc9 },
- { STB0899_EQUALREF , 0xb4 },
- { STB0899_TMGRAMP , 0x10 },
- { STB0899_TMGTHD , 0x30 },
- { STB0899_IDCCOMP , 0xfb },
- { STB0899_QDCCOMP , 0x03 },
- { STB0899_POWERI , 0x3b },
- { STB0899_POWERQ , 0x3d },
- { STB0899_RCOMP , 0x81 },
- { STB0899_AGCIQIN , 0x80 },
- { STB0899_AGC2I1 , 0x04 },
- { STB0899_AGC2I2 , 0xf5 },
- { STB0899_TLIR , 0x25 },
- { STB0899_RTF , 0x80 },
- { STB0899_DSTATUS , 0x00 },
- { STB0899_LDI , 0xca },
- { STB0899_CFRM , 0xf1 },
- { STB0899_CFRL , 0xf3 },
- { STB0899_NIRM , 0x2a },
- { STB0899_NIRL , 0x05 },
- { STB0899_ISYMB , 0x17 },
- { STB0899_QSYMB , 0xfa },
- { STB0899_SFRH , 0x2f },
- { STB0899_SFRM , 0x68 },
- { STB0899_SFRL , 0x40 },
- { STB0899_SFRUPH , 0x2f },
- { STB0899_SFRUPM , 0x68 },
- { STB0899_SFRUPL , 0x40 },
- { STB0899_EQUAI1 , 0xfd },
- { STB0899_EQUAQ1 , 0x04 },
- { STB0899_EQUAI2 , 0x0f },
- { STB0899_EQUAQ2 , 0xff },
- { STB0899_EQUAI3 , 0xdf },
- { STB0899_EQUAQ3 , 0xfa },
- { STB0899_EQUAI4 , 0x37 },
- { STB0899_EQUAQ4 , 0x0d },
- { STB0899_EQUAI5 , 0xbd },
- { STB0899_EQUAQ5 , 0xf7 },
- { STB0899_DSTATUS2 , 0x00 },
- { STB0899_VSTATUS , 0x00 },
- { STB0899_VERROR , 0xff },
- { STB0899_IQSWAP , 0x2a },
- { STB0899_ECNT1M , 0x00 },
- { STB0899_ECNT1L , 0x00 },
- { STB0899_ECNT2M , 0x00 },
- { STB0899_ECNT2L , 0x00 },
- { STB0899_ECNT3M , 0x00 },
- { STB0899_ECNT3L , 0x00 },
- { STB0899_FECAUTO1 , 0x06 },
- { STB0899_FECM , 0x01 },
- { STB0899_VTH12 , 0xf0 },
- { STB0899_VTH23 , 0xa0 },
- { STB0899_VTH34 , 0x78 },
- { STB0899_VTH56 , 0x4e },
- { STB0899_VTH67 , 0x48 },
- { STB0899_VTH78 , 0x38 },
- { STB0899_PRVIT , 0xff },
- { STB0899_VITSYNC , 0x19 },
- { STB0899_RSULC , 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */
- { STB0899_TSULC , 0x42 },
- { STB0899_RSLLC , 0x40 },
- { STB0899_TSLPL , 0x12 },
- { STB0899_TSCFGH , 0x0c },
- { STB0899_TSCFGM , 0x00 },
- { STB0899_TSCFGL , 0x0c },
- { STB0899_TSOUT , 0x4d }, /* 0x0d for CAM */
- { STB0899_RSSYNCDEL , 0x00 },
- { STB0899_TSINHDELH , 0x02 },
- { STB0899_TSINHDELM , 0x00 },
- { STB0899_TSINHDELL , 0x00 },
- { STB0899_TSLLSTKM , 0x00 },
- { STB0899_TSLLSTKL , 0x00 },
- { STB0899_TSULSTKM , 0x00 },
- { STB0899_TSULSTKL , 0xab },
- { STB0899_PCKLENUL , 0x00 },
- { STB0899_PCKLENLL , 0xcc },
- { STB0899_RSPCKLEN , 0xcc },
- { STB0899_TSSTATUS , 0x80 },
- { STB0899_ERRCTRL1 , 0xb6 },
- { STB0899_ERRCTRL2 , 0x96 },
- { STB0899_ERRCTRL3 , 0x89 },
- { STB0899_DMONMSK1 , 0x27 },
- { STB0899_DMONMSK0 , 0x03 },
- { STB0899_DEMAPVIT , 0x5c },
- { STB0899_PLPARM , 0x1f },
- { STB0899_PDELCTRL , 0x48 },
- { STB0899_PDELCTRL2 , 0x00 },
- { STB0899_BBHCTRL1 , 0x00 },
- { STB0899_BBHCTRL2 , 0x00 },
- { STB0899_HYSTTHRESH , 0x77 },
- { STB0899_MATCSTM , 0x00 },
- { STB0899_MATCSTL , 0x00 },
- { STB0899_UPLCSTM , 0x00 },
- { STB0899_UPLCSTL , 0x00 },
- { STB0899_DFLCSTM , 0x00 },
- { STB0899_DFLCSTL , 0x00 },
- { STB0899_SYNCCST , 0x00 },
- { STB0899_SYNCDCSTM , 0x00 },
- { STB0899_SYNCDCSTL , 0x00 },
- { STB0899_ISI_ENTRY , 0x00 },
- { STB0899_ISI_BIT_EN , 0x00 },
- { STB0899_MATSTRM , 0x00 },
- { STB0899_MATSTRL , 0x00 },
- { STB0899_UPLSTRM , 0x00 },
- { STB0899_UPLSTRL , 0x00 },
- { STB0899_DFLSTRM , 0x00 },
- { STB0899_DFLSTRL , 0x00 },
- { STB0899_SYNCSTR , 0x00 },
- { STB0899_SYNCDSTRM , 0x00 },
- { STB0899_SYNCDSTRL , 0x00 },
- { STB0899_CFGPDELSTATUS1 , 0x10 },
- { STB0899_CFGPDELSTATUS2 , 0x00 },
- { STB0899_BBFERRORM , 0x00 },
- { STB0899_BBFERRORL , 0x00 },
- { STB0899_UPKTERRORM , 0x00 },
- { STB0899_UPKTERRORL , 0x00 },
- { 0xffff , 0xff },
-};
-
-/* STB0899 demodulator config for the KNC1 and clones */
-static struct stb0899_config knc1_dvbs2_config = {
- .init_dev = knc1_stb0899_s1_init_1,
- .init_s2_demod = stb0899_s2_init_2,
- .init_s1_demod = knc1_stb0899_s1_init_3,
- .init_s2_fec = stb0899_s2_init_4,
- .init_tst = stb0899_s1_init_5,
-
- .postproc = NULL,
-
- .demod_address = 0x68,
-// .ts_output_mode = STB0899_OUT_PARALLEL, /* types = SERIAL/PARALLEL */
- .block_sync_mode = STB0899_SYNC_FORCED, /* DSS, SYNC_FORCED/UNSYNCED */
-// .ts_pfbit_toggle = STB0899_MPEG_NORMAL, /* DirecTV, MPEG toggling seq */
-
- .xtal_freq = 27000000,
- .inversion = IQ_SWAP_OFF,
-
- .lo_clk = 76500000,
- .hi_clk = 90000000,
-
- .esno_ave = STB0899_DVBS2_ESNO_AVE,
- .esno_quant = STB0899_DVBS2_ESNO_QUANT,
- .avframes_coarse = STB0899_DVBS2_AVFRAMES_COARSE,
- .avframes_fine = STB0899_DVBS2_AVFRAMES_FINE,
- .miss_threshold = STB0899_DVBS2_MISS_THRESHOLD,
- .uwp_threshold_acq = STB0899_DVBS2_UWP_THRESHOLD_ACQ,
- .uwp_threshold_track = STB0899_DVBS2_UWP_THRESHOLD_TRACK,
- .uwp_threshold_sof = STB0899_DVBS2_UWP_THRESHOLD_SOF,
- .sof_search_timeout = STB0899_DVBS2_SOF_SEARCH_TIMEOUT,
-
- .btr_nco_bits = STB0899_DVBS2_BTR_NCO_BITS,
- .btr_gain_shift_offset = STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET,
- .crl_nco_bits = STB0899_DVBS2_CRL_NCO_BITS,
- .ldpc_max_iter = STB0899_DVBS2_LDPC_MAX_ITER,
-
- .tuner_get_frequency = tda8261_get_frequency,
- .tuner_set_frequency = tda8261_set_frequency,
- .tuner_set_bandwidth = NULL,
- .tuner_get_bandwidth = tda8261_get_bandwidth,
- .tuner_set_rfsiggain = NULL
-};
-
-/*
- * SD1878/SHA tuner config
- * 1F, Single I/P, Horizontal mount, High Sensitivity
- */
-static const struct tda8261_config sd1878c_config = {
-// .name = "SD1878/SHA",
- .addr = 0x60,
- .step_size = TDA8261_STEP_1000 /* kHz */
-};
-
-static u8 read_pwm(struct budget_av *budget_av)
-{
- u8 b = 0xff;
- u8 pwm;
- struct i2c_msg msg[] = { {.addr = 0x50,.flags = 0,.buf = &b,.len = 1},
- {.addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1}
- };
-
- if ((i2c_transfer(&budget_av->budget.i2c_adap, msg, 2) != 2)
- || (pwm == 0xff))
- pwm = 0x48;
-
- return pwm;
-}
-
-#define SUBID_DVBS_KNC1 0x0010
-#define SUBID_DVBS_KNC1_PLUS 0x0011
-#define SUBID_DVBS_TYPHOON 0x4f56
-#define SUBID_DVBS_CINERGY1200 0x1154
-#define SUBID_DVBS_CYNERGY1200N 0x1155
-#define SUBID_DVBS_TV_STAR 0x0014
-#define SUBID_DVBS_TV_STAR_PLUS_X4 0x0015
-#define SUBID_DVBS_TV_STAR_CI 0x0016
-#define SUBID_DVBS2_KNC1 0x0018
-#define SUBID_DVBS2_KNC1_OEM 0x0019
-#define SUBID_DVBS_EASYWATCH_1 0x001a
-#define SUBID_DVBS_EASYWATCH_2 0x001b
-#define SUBID_DVBS2_EASYWATCH 0x001d
-#define SUBID_DVBS_EASYWATCH 0x001e
-
-#define SUBID_DVBC_EASYWATCH 0x002a
-#define SUBID_DVBC_EASYWATCH_MK3 0x002c
-#define SUBID_DVBC_KNC1 0x0020
-#define SUBID_DVBC_KNC1_PLUS 0x0021
-#define SUBID_DVBC_KNC1_MK3 0x0022
-#define SUBID_DVBC_KNC1_TDA10024 0x0028
-#define SUBID_DVBC_KNC1_PLUS_MK3 0x0023
-#define SUBID_DVBC_CINERGY1200 0x1156
-#define SUBID_DVBC_CINERGY1200_MK3 0x1176
-
-#define SUBID_DVBT_EASYWATCH 0x003a
-#define SUBID_DVBT_KNC1_PLUS 0x0031
-#define SUBID_DVBT_KNC1 0x0030
-#define SUBID_DVBT_CINERGY1200 0x1157
-
-static void frontend_init(struct budget_av *budget_av)
-{
- struct saa7146_dev * saa = budget_av->budget.dev;
- struct dvb_frontend * fe = NULL;
-
- /* Enable / PowerON Frontend */
- saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
-
- /* Wait for PowerON */
- msleep(100);
-
- /* additional setup necessary for the PLUS cards */
- switch (saa->pci->subsystem_device) {
- case SUBID_DVBS_KNC1_PLUS:
- case SUBID_DVBC_KNC1_PLUS:
- case SUBID_DVBT_KNC1_PLUS:
- case SUBID_DVBC_EASYWATCH:
- case SUBID_DVBC_KNC1_PLUS_MK3:
- case SUBID_DVBS2_KNC1:
- case SUBID_DVBS2_KNC1_OEM:
- case SUBID_DVBS2_EASYWATCH:
- saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTHI);
- break;
- }
-
- switch (saa->pci->subsystem_device) {
-
- case SUBID_DVBS_KNC1:
- /*
- * maybe that setting is needed for other dvb-s cards as well,
- * but so far it has been only confirmed for this type
- */
- budget_av->reinitialise_demod = 1;
- fallthrough;
- case SUBID_DVBS_KNC1_PLUS:
- case SUBID_DVBS_EASYWATCH_1:
- if (saa->pci->subsystem_vendor == 0x1894) {
- fe = dvb_attach(stv0299_attach, &cinergy_1200s_1894_0010_config,
- &budget_av->budget.i2c_adap);
- if (fe) {
- dvb_attach(tua6100_attach, fe, 0x60, &budget_av->budget.i2c_adap);
- }
- } else {
- fe = dvb_attach(stv0299_attach, &typhoon_config,
- &budget_av->budget.i2c_adap);
- if (fe) {
- fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;
- }
- }
- break;
-
- case SUBID_DVBS_TV_STAR:
- case SUBID_DVBS_TV_STAR_PLUS_X4:
- case SUBID_DVBS_TV_STAR_CI:
- case SUBID_DVBS_CYNERGY1200N:
- case SUBID_DVBS_EASYWATCH:
- case SUBID_DVBS_EASYWATCH_2:
- fe = dvb_attach(stv0299_attach, &philips_sd1878_config,
- &budget_av->budget.i2c_adap);
- if (fe) {
- dvb_attach(dvb_pll_attach, fe, 0x60,
- &budget_av->budget.i2c_adap,
- DVB_PLL_PHILIPS_SD1878_TDA8261);
- }
- break;
-
- case SUBID_DVBS_TYPHOON:
- fe = dvb_attach(stv0299_attach, &typhoon_config,
- &budget_av->budget.i2c_adap);
- if (fe) {
- fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;
- }
- break;
- case SUBID_DVBS2_KNC1:
- case SUBID_DVBS2_KNC1_OEM:
- case SUBID_DVBS2_EASYWATCH:
- budget_av->reinitialise_demod = 1;
- if ((fe = dvb_attach(stb0899_attach, &knc1_dvbs2_config, &budget_av->budget.i2c_adap)))
- dvb_attach(tda8261_attach, fe, &sd1878c_config, &budget_av->budget.i2c_adap);
-
- break;
- case SUBID_DVBS_CINERGY1200:
- fe = dvb_attach(stv0299_attach, &cinergy_1200s_config,
- &budget_av->budget.i2c_adap);
- if (fe) {
- fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;
- }
- break;
-
- case SUBID_DVBC_KNC1:
- case SUBID_DVBC_KNC1_PLUS:
- case SUBID_DVBC_CINERGY1200:
- case SUBID_DVBC_EASYWATCH:
- budget_av->reinitialise_demod = 1;
- budget_av->budget.dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
- fe = dvb_attach(tda10021_attach, &philips_cu1216_config,
- &budget_av->budget.i2c_adap,
- read_pwm(budget_av));
- if (fe == NULL)
- fe = dvb_attach(tda10021_attach, &philips_cu1216_config_altaddress,
- &budget_av->budget.i2c_adap,
- read_pwm(budget_av));
- if (fe) {
- fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set_params;
- }
- break;
-
- case SUBID_DVBC_EASYWATCH_MK3:
- case SUBID_DVBC_CINERGY1200_MK3:
- case SUBID_DVBC_KNC1_MK3:
- case SUBID_DVBC_KNC1_TDA10024:
- case SUBID_DVBC_KNC1_PLUS_MK3:
- budget_av->reinitialise_demod = 1;
- budget_av->budget.dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
- fe = dvb_attach(tda10023_attach,
- &philips_cu1216_tda10023_config,
- &budget_av->budget.i2c_adap,
- read_pwm(budget_av));
- if (fe) {
- fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set_params;
- }
- break;
-
- case SUBID_DVBT_EASYWATCH:
- case SUBID_DVBT_KNC1:
- case SUBID_DVBT_KNC1_PLUS:
- case SUBID_DVBT_CINERGY1200:
- budget_av->reinitialise_demod = 1;
- fe = dvb_attach(tda10046_attach, &philips_tu1216_config,
- &budget_av->budget.i2c_adap);
- if (fe) {
- fe->ops.tuner_ops.init = philips_tu1216_tuner_init;
- fe->ops.tuner_ops.set_params = philips_tu1216_tuner_set_params;
- }
- break;
- }
-
- if (fe == NULL) {
- pr_err("A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
- saa->pci->vendor,
- saa->pci->device,
- saa->pci->subsystem_vendor,
- saa->pci->subsystem_device);
- return;
- }
-
- budget_av->budget.dvb_frontend = fe;
-
- if (dvb_register_frontend(&budget_av->budget.dvb_adapter,
- budget_av->budget.dvb_frontend)) {
- pr_err("Frontend registration failed!\n");
- dvb_frontend_detach(budget_av->budget.dvb_frontend);
- budget_av->budget.dvb_frontend = NULL;
- }
-}
-
-
-static void budget_av_irq(struct saa7146_dev *dev, u32 * isr)
-{
- struct budget_av *budget_av = (struct budget_av *) dev->ext_priv;
-
- dprintk(8, "dev: %p, budget_av: %p\n", dev, budget_av);
-
- if (*isr & MASK_10)
- ttpci_budget_irq10_handler(dev, isr);
-}
-
-static int budget_av_detach(struct saa7146_dev *dev)
-{
- struct budget_av *budget_av = (struct budget_av *) dev->ext_priv;
- int err;
-
- dprintk(2, "dev: %p\n", dev);
-
- if (1 == budget_av->has_saa7113) {
- saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO);
-
- msleep(200);
-
- saa7146_unregister_device(&budget_av->vd, dev);
-
- saa7146_vv_release(dev);
- }
-
- if (budget_av->budget.ci_present)
- ciintf_deinit(budget_av);
-
- if (budget_av->budget.dvb_frontend != NULL) {
- dvb_unregister_frontend(budget_av->budget.dvb_frontend);
- dvb_frontend_detach(budget_av->budget.dvb_frontend);
- }
- err = ttpci_budget_deinit(&budget_av->budget);
-
- kfree(budget_av);
-
- return err;
-}
-
-#define KNC1_INPUTS 2
-static struct v4l2_input knc1_inputs[KNC1_INPUTS] = {
- { 0, "Composite", V4L2_INPUT_TYPE_TUNER, 1, 0,
- V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
- { 1, "S-Video", V4L2_INPUT_TYPE_CAMERA, 2, 0,
- V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
-};
-
-static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
-{
- dprintk(1, "VIDIOC_ENUMINPUT %d\n", i->index);
- if (i->index >= KNC1_INPUTS)
- return -EINVAL;
- memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input));
- return 0;
-}
-
-static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
-{
- struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
- struct budget_av *budget_av = (struct budget_av *)dev->ext_priv;
-
- *i = budget_av->cur_input;
-
- dprintk(1, "VIDIOC_G_INPUT %d\n", *i);
- return 0;
-}
-
-static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
-{
- struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
- struct budget_av *budget_av = (struct budget_av *)dev->ext_priv;
-
- dprintk(1, "VIDIOC_S_INPUT %d\n", input);
- return saa7113_setinput(budget_av, input);
-}
-
-static struct saa7146_ext_vv vv_data;
-
-static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
-{
- struct budget_av *budget_av;
- u8 *mac;
- int err;
-
- dprintk(2, "dev: %p\n", dev);
-
- if (!(budget_av = kzalloc(sizeof(struct budget_av), GFP_KERNEL)))
- return -ENOMEM;
-
- budget_av->has_saa7113 = 0;
- budget_av->budget.ci_present = 0;
-
- dev->ext_priv = budget_av;
-
- err = ttpci_budget_init(&budget_av->budget, dev, info, THIS_MODULE,
- adapter_nr);
- if (err) {
- kfree(budget_av);
- return err;
- }
-
- /* knc1 initialization */
- saa7146_write(dev, DD1_STREAM_B, 0x04000000);
- saa7146_write(dev, DD1_INIT, 0x07000600);
- saa7146_write(dev, MC2, MASK_09 | MASK_25 | MASK_10 | MASK_26);
-
- if (saa7113_init(budget_av) == 0) {
- budget_av->has_saa7113 = 1;
- err = saa7146_vv_init(dev, &vv_data);
- if (err != 0) {
- /* fixme: proper cleanup here */
- ERR("cannot init vv subsystem\n");
- return err;
- }
- vv_data.vid_ops.vidioc_enum_input = vidioc_enum_input;
- vv_data.vid_ops.vidioc_g_input = vidioc_g_input;
- vv_data.vid_ops.vidioc_s_input = vidioc_s_input;
-
- if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1", VFL_TYPE_VIDEO))) {
- /* fixme: proper cleanup here */
- ERR("cannot register capture v4l2 device\n");
- saa7146_vv_release(dev);
- return err;
- }
-
- /* beware: this modifies dev->vv ... */
- saa7146_set_hps_source_and_sync(dev, SAA7146_HPS_SOURCE_PORT_A,
- SAA7146_HPS_SYNC_PORT_A);
-
- saa7113_setinput(budget_av, 0);
- }
-
- /* fixme: find some sane values here... */
- saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
-
- mac = budget_av->budget.dvb_adapter.proposed_mac;
- 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);
- eth_zero_addr(mac);
- } else {
- pr_info("KNC1-%d: MAC addr = %pM\n",
- budget_av->budget.dvb_adapter.num, mac);
- }
-
- budget_av->budget.dvb_adapter.priv = budget_av;
- frontend_init(budget_av);
- ciintf_init(budget_av);
-
- ttpci_budget_init_hooks(&budget_av->budget);
-
- return 0;
-}
-
-static struct saa7146_standard standard[] = {
- {.name = "PAL",.id = V4L2_STD_PAL,
- .v_offset = 0x17,.v_field = 288,
- .h_offset = 0x14,.h_pixels = 680,
- .v_max_out = 576,.h_max_out = 768 },
-
- {.name = "NTSC",.id = V4L2_STD_NTSC,
- .v_offset = 0x16,.v_field = 240,
- .h_offset = 0x06,.h_pixels = 708,
- .v_max_out = 480,.h_max_out = 640, },
-};
-
-static struct saa7146_ext_vv vv_data = {
- .inputs = 2,
- .capabilities = 0, // perhaps later: V4L2_CAP_VBI_CAPTURE, but that need tweaking with the saa7113
- .flags = 0,
- .stds = &standard[0],
- .num_stds = ARRAY_SIZE(standard),
-};
-
-static struct saa7146_extension budget_extension;
-
-MAKE_BUDGET_INFO(knc1s, "KNC1 DVB-S", BUDGET_KNC1S);
-MAKE_BUDGET_INFO(knc1s2,"KNC1 DVB-S2", BUDGET_KNC1S2);
-MAKE_BUDGET_INFO(sates2,"Satelco EasyWatch DVB-S2", BUDGET_KNC1S2);
-MAKE_BUDGET_INFO(knc1c, "KNC1 DVB-C", BUDGET_KNC1C);
-MAKE_BUDGET_INFO(knc1t, "KNC1 DVB-T", BUDGET_KNC1T);
-MAKE_BUDGET_INFO(kncxs, "KNC TV STAR DVB-S", BUDGET_TVSTAR);
-MAKE_BUDGET_INFO(satewpls, "Satelco EasyWatch DVB-S light", BUDGET_TVSTAR);
-MAKE_BUDGET_INFO(satewpls1, "Satelco EasyWatch DVB-S light", BUDGET_KNC1S);
-MAKE_BUDGET_INFO(satewps, "Satelco EasyWatch DVB-S", BUDGET_KNC1S);
-MAKE_BUDGET_INFO(satewplc, "Satelco EasyWatch DVB-C", BUDGET_KNC1CP);
-MAKE_BUDGET_INFO(satewcmk3, "Satelco EasyWatch DVB-C MK3", BUDGET_KNC1C_MK3);
-MAKE_BUDGET_INFO(satewt, "Satelco EasyWatch DVB-T", BUDGET_KNC1T);
-MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plus", BUDGET_KNC1SP);
-MAKE_BUDGET_INFO(knc1spx4, "KNC1 DVB-S Plus X4", BUDGET_KNC1SP);
-MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus", BUDGET_KNC1CP);
-MAKE_BUDGET_INFO(knc1cmk3, "KNC1 DVB-C MK3", BUDGET_KNC1C_MK3);
-MAKE_BUDGET_INFO(knc1ctda10024, "KNC1 DVB-C TDA10024", BUDGET_KNC1C_TDA10024);
-MAKE_BUDGET_INFO(knc1cpmk3, "KNC1 DVB-C Plus MK3", BUDGET_KNC1CP_MK3);
-MAKE_BUDGET_INFO(knc1tp, "KNC1 DVB-T Plus", BUDGET_KNC1TP);
-MAKE_BUDGET_INFO(cin1200s, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200S);
-MAKE_BUDGET_INFO(cin1200sn, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200S);
-MAKE_BUDGET_INFO(cin1200c, "Terratec Cinergy 1200 DVB-C", BUDGET_CIN1200C);
-MAKE_BUDGET_INFO(cin1200cmk3, "Terratec Cinergy 1200 DVB-C MK3", BUDGET_CIN1200C_MK3);
-MAKE_BUDGET_INFO(cin1200t, "Terratec Cinergy 1200 DVB-T", BUDGET_CIN1200T);
-
-static const struct pci_device_id pci_tbl[] = {
- MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x4f56),
- MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x0010),
- MAKE_EXTENSION_PCI(knc1s, 0x1894, 0x0010),
- MAKE_EXTENSION_PCI(knc1sp, 0x1131, 0x0011),
- MAKE_EXTENSION_PCI(knc1sp, 0x1894, 0x0011),
- MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0014),
- MAKE_EXTENSION_PCI(knc1spx4, 0x1894, 0x0015),
- MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0016),
- MAKE_EXTENSION_PCI(knc1s2, 0x1894, 0x0018),
- MAKE_EXTENSION_PCI(knc1s2, 0x1894, 0x0019),
- MAKE_EXTENSION_PCI(sates2, 0x1894, 0x001d),
- MAKE_EXTENSION_PCI(satewpls, 0x1894, 0x001e),
- MAKE_EXTENSION_PCI(satewpls1, 0x1894, 0x001a),
- MAKE_EXTENSION_PCI(satewps, 0x1894, 0x001b),
- MAKE_EXTENSION_PCI(satewplc, 0x1894, 0x002a),
- MAKE_EXTENSION_PCI(satewcmk3, 0x1894, 0x002c),
- MAKE_EXTENSION_PCI(satewt, 0x1894, 0x003a),
- MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020),
- MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021),
- MAKE_EXTENSION_PCI(knc1cmk3, 0x1894, 0x0022),
- MAKE_EXTENSION_PCI(knc1ctda10024, 0x1894, 0x0028),
- MAKE_EXTENSION_PCI(knc1cpmk3, 0x1894, 0x0023),
- MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030),
- MAKE_EXTENSION_PCI(knc1tp, 0x1894, 0x0031),
- MAKE_EXTENSION_PCI(cin1200s, 0x153b, 0x1154),
- MAKE_EXTENSION_PCI(cin1200sn, 0x153b, 0x1155),
- MAKE_EXTENSION_PCI(cin1200c, 0x153b, 0x1156),
- MAKE_EXTENSION_PCI(cin1200cmk3, 0x153b, 0x1176),
- MAKE_EXTENSION_PCI(cin1200t, 0x153b, 0x1157),
- {
- .vendor = 0,
- }
-};
-
-MODULE_DEVICE_TABLE(pci, pci_tbl);
-
-static struct saa7146_extension budget_extension = {
- .name = "budget_av",
- .flags = SAA7146_USE_I2C_IRQ,
-
- .pci_tbl = pci_tbl,
-
- .module = THIS_MODULE,
- .attach = budget_av_attach,
- .detach = budget_av_detach,
-
- .irq_mask = MASK_10,
- .irq_func = budget_av_irq,
-};
-
-static int __init budget_av_init(void)
-{
- return saa7146_register_extension(&budget_extension);
-}
-
-static void __exit budget_av_exit(void)
-{
- saa7146_unregister_extension(&budget_extension);
-}
-
-module_init(budget_av_init);
-module_exit(budget_av_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others");
-MODULE_DESCRIPTION("driver for the SAA7146 based so-called budget PCI DVB w/ analog input and CI-module (e.g. the KNC cards)");
diff --git a/drivers/media/pci/ttpci/budget-ci.c b/drivers/media/pci/ttpci/budget-ci.c
deleted file mode 100644
index d59d18647371..000000000000
--- a/drivers/media/pci/ttpci/budget-ci.c
+++ /dev/null
@@ -1,1574 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * budget-ci.c: driver for the SAA7146 based Budget DVB cards
- *
- * Compiled from various sources by Michael Hunold <michael@mihu.de>
- *
- * msp430 IR support contributed by Jack Thomasson <jkt@Helius.COM>
- * partially based on the Siemens DVB driver by Ralph+Marcus Metzler
- *
- * CI interface support (c) 2004 Andrew de Quincey <adq_dvb@lidskialf.net>
- *
- * the project's page is at https://linuxtv.org
- */
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <media/rc-core.h>
-
-#include "budget.h"
-
-#include <media/dvb_ca_en50221.h>
-#include "stv0299.h"
-#include "stv0297.h"
-#include "tda1004x.h"
-#include "stb0899_drv.h"
-#include "stb0899_reg.h"
-#include "stb0899_cfg.h"
-#include "stb6100.h"
-#include "stb6100_cfg.h"
-#include "lnbp21.h"
-#include "bsbe1.h"
-#include "bsru6.h"
-#include "tda1002x.h"
-#include "tda827x.h"
-#include "bsbe1-d01a.h"
-
-#define MODULE_NAME "budget_ci"
-
-/*
- * Regarding DEBIADDR_IR:
- * Some CI modules hang if random addresses are read.
- * Using address 0x4000 for the IR read means that we
- * use the same address as for CI version, which should
- * be a safe default.
- */
-#define DEBIADDR_IR 0x4000
-#define DEBIADDR_CICONTROL 0x0000
-#define DEBIADDR_CIVERSION 0x4000
-#define DEBIADDR_IO 0x1000
-#define DEBIADDR_ATTR 0x3000
-
-#define CICONTROL_RESET 0x01
-#define CICONTROL_ENABLETS 0x02
-#define CICONTROL_CAMDETECT 0x08
-
-#define DEBICICTL 0x00420000
-#define DEBICICAM 0x02420000
-
-#define SLOTSTATUS_NONE 1
-#define SLOTSTATUS_PRESENT 2
-#define SLOTSTATUS_RESET 4
-#define SLOTSTATUS_READY 8
-#define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)
-
-/* RC5 device wildcard */
-#define IR_DEVICE_ANY 255
-
-static int rc5_device = -1;
-module_param(rc5_device, int, 0644);
-MODULE_PARM_DESC(rc5_device, "only IR commands to given RC5 device (device = 0 - 31, any device = 255, default: autodetect)");
-
-static int ir_debug;
-module_param(ir_debug, int, 0644);
-MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding");
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-struct budget_ci_ir {
- struct rc_dev *dev;
- struct tasklet_struct msp430_irq_tasklet;
- char name[72]; /* 40 + 32 for (struct saa7146_dev).name */
- char phys[32];
- int rc5_device;
- u32 ir_key;
- bool have_command;
- bool full_rc5; /* Outputs a full RC5 code */
-};
-
-struct budget_ci {
- struct budget budget;
- struct tasklet_struct ciintf_irq_tasklet;
- int slot_status;
- int ci_irq;
- struct dvb_ca_en50221 ca;
- struct budget_ci_ir ir;
- u8 tuner_pll_address; /* used for philips_tdm1316l configs */
-};
-
-static void msp430_ir_interrupt(struct tasklet_struct *t)
-{
- struct budget_ci_ir *ir = from_tasklet(ir, t, msp430_irq_tasklet);
- struct budget_ci *budget_ci = container_of(ir, typeof(*budget_ci), ir);
- struct rc_dev *dev = budget_ci->ir.dev;
- u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
-
- /*
- * The msp430 chip can generate two different bytes, command and device
- *
- * type1: X1CCCCCC, C = command bits (0 - 63)
- * type2: X0TDDDDD, D = device bits (0 - 31), T = RC5 toggle bit
- *
- * Each signal from the remote control can generate one or more command
- * bytes and one or more device bytes. For the repeated bytes, the
- * highest bit (X) is set. The first command byte is always generated
- * before the first device byte. Other than that, no specific order
- * seems to apply. To make life interesting, bytes can also be lost.
- *
- * Only when we have a command and device byte, a keypress is
- * generated.
- */
-
- if (ir_debug)
- printk("budget_ci: received byte 0x%02x\n", command);
-
- /* Remove repeat bit, we use every command */
- command = command & 0x7f;
-
- /* Is this a RC5 command byte? */
- if (command & 0x40) {
- budget_ci->ir.have_command = true;
- budget_ci->ir.ir_key = command & 0x3f;
- return;
- }
-
- /* It's a RC5 device byte */
- if (!budget_ci->ir.have_command)
- return;
- budget_ci->ir.have_command = false;
-
- if (budget_ci->ir.rc5_device != IR_DEVICE_ANY &&
- budget_ci->ir.rc5_device != (command & 0x1f))
- return;
-
- if (budget_ci->ir.full_rc5) {
- rc_keydown(dev, RC_PROTO_RC5,
- RC_SCANCODE_RC5(budget_ci->ir.rc5_device, budget_ci->ir.ir_key),
- !!(command & 0x20));
- return;
- }
-
- /* FIXME: We should generate complete scancodes for all devices */
- rc_keydown(dev, RC_PROTO_UNKNOWN, budget_ci->ir.ir_key,
- !!(command & 0x20));
-}
-
-static int msp430_ir_init(struct budget_ci *budget_ci)
-{
- struct saa7146_dev *saa = budget_ci->budget.dev;
- struct rc_dev *dev;
- int error;
-
- dev = rc_allocate_device(RC_DRIVER_SCANCODE);
- if (!dev) {
- printk(KERN_ERR "budget_ci: IR interface initialisation failed\n");
- return -ENOMEM;
- }
-
- snprintf(budget_ci->ir.name, sizeof(budget_ci->ir.name),
- "Budget-CI dvb ir receiver %s", saa->name);
- snprintf(budget_ci->ir.phys, sizeof(budget_ci->ir.phys),
- "pci-%s/ir0", pci_name(saa->pci));
-
- dev->driver_name = MODULE_NAME;
- dev->device_name = budget_ci->ir.name;
- dev->input_phys = budget_ci->ir.phys;
- dev->input_id.bustype = BUS_PCI;
- dev->input_id.version = 1;
- if (saa->pci->subsystem_vendor) {
- dev->input_id.vendor = saa->pci->subsystem_vendor;
- dev->input_id.product = saa->pci->subsystem_device;
- } else {
- dev->input_id.vendor = saa->pci->vendor;
- dev->input_id.product = saa->pci->device;
- }
- dev->dev.parent = &saa->pci->dev;
-
- if (rc5_device < 0)
- budget_ci->ir.rc5_device = IR_DEVICE_ANY;
- else
- budget_ci->ir.rc5_device = rc5_device;
-
- /* Select keymap and address */
- switch (budget_ci->budget.dev->pci->subsystem_device) {
- case 0x100c:
- case 0x100f:
- case 0x1011:
- case 0x1012:
- /* The hauppauge keymap is a superset of these remotes */
- dev->map_name = RC_MAP_HAUPPAUGE;
- budget_ci->ir.full_rc5 = true;
-
- if (rc5_device < 0)
- budget_ci->ir.rc5_device = 0x1f;
- break;
- case 0x1010:
- case 0x1017:
- case 0x1019:
- case 0x101a:
- case 0x101b:
- /* for the Technotrend 1500 bundled remote */
- dev->map_name = RC_MAP_TT_1500;
- break;
- default:
- /* unknown remote */
- dev->map_name = RC_MAP_BUDGET_CI_OLD;
- break;
- }
- if (!budget_ci->ir.full_rc5)
- dev->scancode_mask = 0xff;
-
- error = rc_register_device(dev);
- if (error) {
- printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error);
- rc_free_device(dev);
- return error;
- }
-
- budget_ci->ir.dev = dev;
-
- tasklet_setup(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt);
-
- SAA7146_IER_ENABLE(saa, MASK_06);
- saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI);
-
- return 0;
-}
-
-static void msp430_ir_deinit(struct budget_ci *budget_ci)
-{
- struct saa7146_dev *saa = budget_ci->budget.dev;
-
- SAA7146_IER_DISABLE(saa, MASK_06);
- saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
- tasklet_kill(&budget_ci->ir.msp430_irq_tasklet);
-
- rc_unregister_device(budget_ci->ir.dev);
-}
-
-static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
-{
- struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
-
- if (slot != 0)
- return -EINVAL;
-
- return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM,
- DEBIADDR_ATTR | (address & 0xfff), 1, 1, 0);
-}
-
-static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)
-{
- struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
-
- if (slot != 0)
- return -EINVAL;
-
- return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM,
- DEBIADDR_ATTR | (address & 0xfff), 1, value, 1, 0);
-}
-
-static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)
-{
- struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
-
- if (slot != 0)
- return -EINVAL;
-
- return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM,
- DEBIADDR_IO | (address & 3), 1, 1, 0);
-}
-
-static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)
-{
- struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
-
- if (slot != 0)
- return -EINVAL;
-
- return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM,
- DEBIADDR_IO | (address & 3), 1, value, 1, 0);
-}
-
-static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
-{
- struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
- struct saa7146_dev *saa = budget_ci->budget.dev;
-
- if (slot != 0)
- return -EINVAL;
-
- if (budget_ci->ci_irq) {
- // trigger on RISING edge during reset so we know when READY is re-asserted
- saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
- }
- budget_ci->slot_status = SLOTSTATUS_RESET;
- ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);
- msleep(1);
- ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
- CICONTROL_RESET, 1, 0);
-
- saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
- ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
- return 0;
-}
-
-static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
-{
- struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
- struct saa7146_dev *saa = budget_ci->budget.dev;
-
- if (slot != 0)
- return -EINVAL;
-
- saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
- ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
- return 0;
-}
-
-static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
-{
- struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
- struct saa7146_dev *saa = budget_ci->budget.dev;
- int tmp;
-
- if (slot != 0)
- return -EINVAL;
-
- saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTLO);
-
- tmp = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
- ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
- tmp | CICONTROL_ENABLETS, 1, 0);
-
- ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA);
- return 0;
-}
-
-static void ciintf_interrupt(struct tasklet_struct *t)
-{
- struct budget_ci *budget_ci = from_tasklet(budget_ci, t,
- ciintf_irq_tasklet);
- struct saa7146_dev *saa = budget_ci->budget.dev;
- unsigned int flags;
-
- // ensure we don't get spurious IRQs during initialisation
- if (!budget_ci->budget.ci_present)
- return;
-
- // read the CAM status
- flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
- if (flags & CICONTROL_CAMDETECT) {
-
- // GPIO should be set to trigger on falling edge if a CAM is present
- saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
-
- if (budget_ci->slot_status & SLOTSTATUS_NONE) {
- // CAM insertion IRQ
- budget_ci->slot_status = SLOTSTATUS_PRESENT;
- dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0,
- DVB_CA_EN50221_CAMCHANGE_INSERTED);
-
- } else if (budget_ci->slot_status & SLOTSTATUS_RESET) {
- // CAM ready (reset completed)
- budget_ci->slot_status = SLOTSTATUS_READY;
- dvb_ca_en50221_camready_irq(&budget_ci->ca, 0);
-
- } else if (budget_ci->slot_status & SLOTSTATUS_READY) {
- // FR/DA IRQ
- dvb_ca_en50221_frda_irq(&budget_ci->ca, 0);
- }
- } else {
-
- // trigger on rising edge if a CAM is not present - when a CAM is inserted, we
- // only want to get the IRQ when it sets READY. If we trigger on the falling edge,
- // the CAM might not actually be ready yet.
- saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
-
- // generate a CAM removal IRQ if we haven't already
- if (budget_ci->slot_status & SLOTSTATUS_OCCUPIED) {
- // CAM removal IRQ
- budget_ci->slot_status = SLOTSTATUS_NONE;
- dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0,
- DVB_CA_EN50221_CAMCHANGE_REMOVED);
- }
- }
-}
-
-static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
-{
- struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
- unsigned int flags;
-
- // ensure we don't get spurious IRQs during initialisation
- if (!budget_ci->budget.ci_present)
- return -EINVAL;
-
- // read the CAM status
- flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
- if (flags & CICONTROL_CAMDETECT) {
- // mark it as present if it wasn't before
- if (budget_ci->slot_status & SLOTSTATUS_NONE) {
- budget_ci->slot_status = SLOTSTATUS_PRESENT;
- }
-
- // during a RESET, we check if we can read from IO memory to see when CAM is ready
- if (budget_ci->slot_status & SLOTSTATUS_RESET) {
- if (ciintf_read_attribute_mem(ca, slot, 0) == 0x1d) {
- budget_ci->slot_status = SLOTSTATUS_READY;
- }
- }
- } else {
- budget_ci->slot_status = SLOTSTATUS_NONE;
- }
-
- if (budget_ci->slot_status != SLOTSTATUS_NONE) {
- if (budget_ci->slot_status & SLOTSTATUS_READY) {
- return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
- }
- return DVB_CA_EN50221_POLL_CAM_PRESENT;
- }
-
- return 0;
-}
-
-static int ciintf_init(struct budget_ci *budget_ci)
-{
- struct saa7146_dev *saa = budget_ci->budget.dev;
- int flags;
- int result;
- int ci_version;
- int ca_flags;
-
- memset(&budget_ci->ca, 0, sizeof(struct dvb_ca_en50221));
-
- // enable DEBI pins
- saa7146_write(saa, MC1, MASK_27 | MASK_11);
-
- // test if it is there
- ci_version = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0);
- if ((ci_version & 0xa0) != 0xa0) {
- result = -ENODEV;
- goto error;
- }
-
- // determine whether a CAM is present or not
- flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
- budget_ci->slot_status = SLOTSTATUS_NONE;
- if (flags & CICONTROL_CAMDETECT)
- budget_ci->slot_status = SLOTSTATUS_PRESENT;
-
- // version 0xa2 of the CI firmware doesn't generate interrupts
- if (ci_version == 0xa2) {
- ca_flags = 0;
- budget_ci->ci_irq = 0;
- } else {
- ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE |
- DVB_CA_EN50221_FLAG_IRQ_FR |
- DVB_CA_EN50221_FLAG_IRQ_DA;
- budget_ci->ci_irq = 1;
- }
-
- // register CI interface
- budget_ci->ca.owner = THIS_MODULE;
- budget_ci->ca.read_attribute_mem = ciintf_read_attribute_mem;
- budget_ci->ca.write_attribute_mem = ciintf_write_attribute_mem;
- budget_ci->ca.read_cam_control = ciintf_read_cam_control;
- budget_ci->ca.write_cam_control = ciintf_write_cam_control;
- budget_ci->ca.slot_reset = ciintf_slot_reset;
- budget_ci->ca.slot_shutdown = ciintf_slot_shutdown;
- budget_ci->ca.slot_ts_enable = ciintf_slot_ts_enable;
- budget_ci->ca.poll_slot_status = ciintf_poll_slot_status;
- budget_ci->ca.data = budget_ci;
- if ((result = dvb_ca_en50221_init(&budget_ci->budget.dvb_adapter,
- &budget_ci->ca,
- ca_flags, 1)) != 0) {
- printk("budget_ci: CI interface detected, but initialisation failed.\n");
- goto error;
- }
-
- // Setup CI slot IRQ
- if (budget_ci->ci_irq) {
- tasklet_setup(&budget_ci->ciintf_irq_tasklet, ciintf_interrupt);
- if (budget_ci->slot_status != SLOTSTATUS_NONE) {
- saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
- } else {
- saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
- }
- SAA7146_IER_ENABLE(saa, MASK_03);
- }
-
- // enable interface
- ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
- CICONTROL_RESET, 1, 0);
-
- // success!
- printk("budget_ci: CI interface initialised\n");
- budget_ci->budget.ci_present = 1;
-
- // forge a fake CI IRQ so the CAM state is setup correctly
- if (budget_ci->ci_irq) {
- flags = DVB_CA_EN50221_CAMCHANGE_REMOVED;
- if (budget_ci->slot_status != SLOTSTATUS_NONE)
- flags = DVB_CA_EN50221_CAMCHANGE_INSERTED;
- dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, flags);
- }
-
- return 0;
-
-error:
- saa7146_write(saa, MC1, MASK_27);
- return result;
-}
-
-static void ciintf_deinit(struct budget_ci *budget_ci)
-{
- struct saa7146_dev *saa = budget_ci->budget.dev;
-
- // disable CI interrupts
- if (budget_ci->ci_irq) {
- SAA7146_IER_DISABLE(saa, MASK_03);
- saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);
- tasklet_kill(&budget_ci->ciintf_irq_tasklet);
- }
-
- // reset interface
- ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);
- msleep(1);
- ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
- CICONTROL_RESET, 1, 0);
-
- // disable TS data stream to CI interface
- saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT);
-
- // release the CA device
- dvb_ca_en50221_release(&budget_ci->ca);
-
- // disable DEBI pins
- saa7146_write(saa, MC1, MASK_27);
-}
-
-static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr)
-{
- struct budget_ci *budget_ci = (struct budget_ci *) dev->ext_priv;
-
- dprintk(8, "dev: %p, budget_ci: %p\n", dev, budget_ci);
-
- if (*isr & MASK_06)
- tasklet_schedule(&budget_ci->ir.msp430_irq_tasklet);
-
- if (*isr & MASK_10)
- ttpci_budget_irq10_handler(dev, isr);
-
- if ((*isr & MASK_03) && (budget_ci->budget.ci_present) && (budget_ci->ci_irq))
- tasklet_schedule(&budget_ci->ciintf_irq_tasklet);
-}
-
-static u8 philips_su1278_tt_inittab[] = {
- 0x01, 0x0f,
- 0x02, 0x30,
- 0x03, 0x00,
- 0x04, 0x5b,
- 0x05, 0x85,
- 0x06, 0x02,
- 0x07, 0x00,
- 0x08, 0x02,
- 0x09, 0x00,
- 0x0C, 0x01,
- 0x0D, 0x81,
- 0x0E, 0x44,
- 0x0f, 0x14,
- 0x10, 0x3c,
- 0x11, 0x84,
- 0x12, 0xda,
- 0x13, 0x97,
- 0x14, 0x95,
- 0x15, 0xc9,
- 0x16, 0x19,
- 0x17, 0x8c,
- 0x18, 0x59,
- 0x19, 0xf8,
- 0x1a, 0xfe,
- 0x1c, 0x7f,
- 0x1d, 0x00,
- 0x1e, 0x00,
- 0x1f, 0x50,
- 0x20, 0x00,
- 0x21, 0x00,
- 0x22, 0x00,
- 0x23, 0x00,
- 0x28, 0x00,
- 0x29, 0x28,
- 0x2a, 0x14,
- 0x2b, 0x0f,
- 0x2c, 0x09,
- 0x2d, 0x09,
- 0x31, 0x1f,
- 0x32, 0x19,
- 0x33, 0xfc,
- 0x34, 0x93,
- 0xff, 0xff
-};
-
-static int philips_su1278_tt_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)
-{
- stv0299_writereg(fe, 0x0e, 0x44);
- if (srate >= 10000000) {
- stv0299_writereg(fe, 0x13, 0x97);
- stv0299_writereg(fe, 0x14, 0x95);
- stv0299_writereg(fe, 0x15, 0xc9);
- stv0299_writereg(fe, 0x17, 0x8c);
- stv0299_writereg(fe, 0x1a, 0xfe);
- stv0299_writereg(fe, 0x1c, 0x7f);
- stv0299_writereg(fe, 0x2d, 0x09);
- } else {
- stv0299_writereg(fe, 0x13, 0x99);
- stv0299_writereg(fe, 0x14, 0x8d);
- stv0299_writereg(fe, 0x15, 0xce);
- stv0299_writereg(fe, 0x17, 0x43);
- stv0299_writereg(fe, 0x1a, 0x1d);
- stv0299_writereg(fe, 0x1c, 0x12);
- stv0299_writereg(fe, 0x2d, 0x05);
- }
- stv0299_writereg(fe, 0x0e, 0x23);
- stv0299_writereg(fe, 0x0f, 0x94);
- stv0299_writereg(fe, 0x10, 0x39);
- stv0299_writereg(fe, 0x15, 0xc9);
-
- stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
- stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
- stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
-
- return 0;
-}
-
-static int philips_su1278_tt_tuner_set_params(struct dvb_frontend *fe)
-{
- struct dtv_frontend_properties *p = &fe->dtv_property_cache;
- struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
- u32 div;
- u8 buf[4];
- struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) };
-
- if ((p->frequency < 950000) || (p->frequency > 2150000))
- return -EINVAL;
-
- div = (p->frequency + (500 - 1)) / 500; /* round correctly */
- buf[0] = (div >> 8) & 0x7f;
- buf[1] = div & 0xff;
- buf[2] = 0x80 | ((div & 0x18000) >> 10) | 2;
- buf[3] = 0x20;
-
- if (p->symbol_rate < 4000000)
- buf[3] |= 1;
-
- if (p->frequency < 1250000)
- buf[3] |= 0;
- else if (p->frequency < 1550000)
- buf[3] |= 0x40;
- else if (p->frequency < 2050000)
- buf[3] |= 0x80;
- else if (p->frequency < 2150000)
- buf[3] |= 0xC0;
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
- if (i2c_transfer(&budget_ci->budget.i2c_adap, &msg, 1) != 1)
- return -EIO;
- return 0;
-}
-
-static const struct stv0299_config philips_su1278_tt_config = {
-
- .demod_address = 0x68,
- .inittab = philips_su1278_tt_inittab,
- .mclk = 64000000UL,
- .invert = 0,
- .skip_reinit = 1,
- .lock_output = STV0299_LOCKOUTPUT_1,
- .volt13_op0_op1 = STV0299_VOLT13_OP1,
- .min_delay_ms = 50,
- .set_symbol_rate = philips_su1278_tt_set_symbol_rate,
-};
-
-
-
-static int philips_tdm1316l_tuner_init(struct dvb_frontend *fe)
-{
- struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
- static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab };
- static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 };
- struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,.flags = 0,.buf = td1316_init,.len =
- sizeof(td1316_init) };
-
- // setup PLL configuration
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
- if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
- return -EIO;
- msleep(1);
-
- // disable the mc44BC374c (do not check for errors)
- tuner_msg.addr = 0x65;
- tuner_msg.buf = disable_mc44BC374c;
- tuner_msg.len = sizeof(disable_mc44BC374c);
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
- if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) {
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
- i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1);
- }
-
- return 0;
-}
-
-static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe)
-{
- struct dtv_frontend_properties *p = &fe->dtv_property_cache;
- struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
- u8 tuner_buf[4];
- struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,.flags = 0,.buf = tuner_buf,.len = sizeof(tuner_buf) };
- int tuner_frequency = 0;
- u8 band, cp, filter;
-
- // determine charge pump
- tuner_frequency = p->frequency + 36130000;
- if (tuner_frequency < 87000000)
- return -EINVAL;
- else if (tuner_frequency < 130000000)
- cp = 3;
- else if (tuner_frequency < 160000000)
- cp = 5;
- else if (tuner_frequency < 200000000)
- cp = 6;
- else if (tuner_frequency < 290000000)
- cp = 3;
- else if (tuner_frequency < 420000000)
- cp = 5;
- else if (tuner_frequency < 480000000)
- cp = 6;
- else if (tuner_frequency < 620000000)
- cp = 3;
- else if (tuner_frequency < 830000000)
- cp = 5;
- else if (tuner_frequency < 895000000)
- cp = 7;
- else
- return -EINVAL;
-
- // determine band
- if (p->frequency < 49000000)
- return -EINVAL;
- else if (p->frequency < 159000000)
- band = 1;
- else if (p->frequency < 444000000)
- band = 2;
- else if (p->frequency < 861000000)
- band = 4;
- else
- return -EINVAL;
-
- // setup PLL filter and TDA9889
- switch (p->bandwidth_hz) {
- case 6000000:
- tda1004x_writereg(fe, 0x0C, 0x14);
- filter = 0;
- break;
-
- case 7000000:
- tda1004x_writereg(fe, 0x0C, 0x80);
- filter = 0;
- break;
-
- case 8000000:
- tda1004x_writereg(fe, 0x0C, 0x14);
- filter = 1;
- break;
-
- default:
- return -EINVAL;
- }
-
- // calculate divisor
- // ((36130000+((1000000/6)/2)) + Finput)/(1000000/6)
- tuner_frequency = (((p->frequency / 1000) * 6) + 217280) / 1000;
-
- // setup tuner buffer
- tuner_buf[0] = tuner_frequency >> 8;
- tuner_buf[1] = tuner_frequency & 0xff;
- tuner_buf[2] = 0xca;
- tuner_buf[3] = (cp << 5) | (filter << 3) | band;
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
- if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
- return -EIO;
-
- msleep(1);
- return 0;
-}
-
-static int philips_tdm1316l_request_firmware(struct dvb_frontend *fe,
- const struct firmware **fw, char *name)
-{
- struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
-
- return request_firmware(fw, name, &budget_ci->budget.dev->pci->dev);
-}
-
-static struct tda1004x_config philips_tdm1316l_config = {
-
- .demod_address = 0x8,
- .invert = 0,
- .invert_oclk = 0,
- .xtal_freq = TDA10046_XTAL_4M,
- .agc_config = TDA10046_AGC_DEFAULT,
- .if_freq = TDA10046_FREQ_3617,
- .request_firmware = philips_tdm1316l_request_firmware,
-};
-
-static struct tda1004x_config philips_tdm1316l_config_invert = {
-
- .demod_address = 0x8,
- .invert = 1,
- .invert_oclk = 0,
- .xtal_freq = TDA10046_XTAL_4M,
- .agc_config = TDA10046_AGC_DEFAULT,
- .if_freq = TDA10046_FREQ_3617,
- .request_firmware = philips_tdm1316l_request_firmware,
-};
-
-static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe)
-{
- struct dtv_frontend_properties *p = &fe->dtv_property_cache;
- struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
- u8 tuner_buf[5];
- struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,
- .flags = 0,
- .buf = tuner_buf,
- .len = sizeof(tuner_buf) };
- int tuner_frequency = 0;
- u8 band, cp, filter;
-
- // determine charge pump
- tuner_frequency = p->frequency + 36125000;
- if (tuner_frequency < 87000000)
- return -EINVAL;
- else if (tuner_frequency < 130000000) {
- cp = 3;
- band = 1;
- } else if (tuner_frequency < 160000000) {
- cp = 5;
- band = 1;
- } else if (tuner_frequency < 200000000) {
- cp = 6;
- band = 1;
- } else if (tuner_frequency < 290000000) {
- cp = 3;
- band = 2;
- } else if (tuner_frequency < 420000000) {
- cp = 5;
- band = 2;
- } else if (tuner_frequency < 480000000) {
- cp = 6;
- band = 2;
- } else if (tuner_frequency < 620000000) {
- cp = 3;
- band = 4;
- } else if (tuner_frequency < 830000000) {
- cp = 5;
- band = 4;
- } else if (tuner_frequency < 895000000) {
- cp = 7;
- band = 4;
- } else
- return -EINVAL;
-
- // assume PLL filter should always be 8MHz for the moment.
- filter = 1;
-
- // calculate divisor
- tuner_frequency = (p->frequency + 36125000 + (62500/2)) / 62500;
-
- // setup tuner buffer
- tuner_buf[0] = tuner_frequency >> 8;
- tuner_buf[1] = tuner_frequency & 0xff;
- tuner_buf[2] = 0xc8;
- tuner_buf[3] = (cp << 5) | (filter << 3) | band;
- tuner_buf[4] = 0x80;
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
- if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
- return -EIO;
-
- msleep(50);
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
- if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
- return -EIO;
-
- msleep(1);
-
- return 0;
-}
-
-static u8 dvbc_philips_tdm1316l_inittab[] = {
- 0x80, 0x01,
- 0x80, 0x00,
- 0x81, 0x01,
- 0x81, 0x00,
- 0x00, 0x09,
- 0x01, 0x69,
- 0x03, 0x00,
- 0x04, 0x00,
- 0x07, 0x00,
- 0x08, 0x00,
- 0x20, 0x00,
- 0x21, 0x40,
- 0x22, 0x00,
- 0x23, 0x00,
- 0x24, 0x40,
- 0x25, 0x88,
- 0x30, 0xff,
- 0x31, 0x00,
- 0x32, 0xff,
- 0x33, 0x00,
- 0x34, 0x50,
- 0x35, 0x7f,
- 0x36, 0x00,
- 0x37, 0x20,
- 0x38, 0x00,
- 0x40, 0x1c,
- 0x41, 0xff,
- 0x42, 0x29,
- 0x43, 0x20,
- 0x44, 0xff,
- 0x45, 0x00,
- 0x46, 0x00,
- 0x49, 0x04,
- 0x4a, 0x00,
- 0x4b, 0x7b,
- 0x52, 0x30,
- 0x55, 0xae,
- 0x56, 0x47,
- 0x57, 0xe1,
- 0x58, 0x3a,
- 0x5a, 0x1e,
- 0x5b, 0x34,
- 0x60, 0x00,
- 0x63, 0x00,
- 0x64, 0x00,
- 0x65, 0x00,
- 0x66, 0x00,
- 0x67, 0x00,
- 0x68, 0x00,
- 0x69, 0x00,
- 0x6a, 0x02,
- 0x6b, 0x00,
- 0x70, 0xff,
- 0x71, 0x00,
- 0x72, 0x00,
- 0x73, 0x00,
- 0x74, 0x0c,
- 0x80, 0x00,
- 0x81, 0x00,
- 0x82, 0x00,
- 0x83, 0x00,
- 0x84, 0x04,
- 0x85, 0x80,
- 0x86, 0x24,
- 0x87, 0x78,
- 0x88, 0x10,
- 0x89, 0x00,
- 0x90, 0x01,
- 0x91, 0x01,
- 0xa0, 0x04,
- 0xa1, 0x00,
- 0xa2, 0x00,
- 0xb0, 0x91,
- 0xb1, 0x0b,
- 0xc0, 0x53,
- 0xc1, 0x70,
- 0xc2, 0x12,
- 0xd0, 0x00,
- 0xd1, 0x00,
- 0xd2, 0x00,
- 0xd3, 0x00,
- 0xd4, 0x00,
- 0xd5, 0x00,
- 0xde, 0x00,
- 0xdf, 0x00,
- 0x61, 0x38,
- 0x62, 0x0a,
- 0x53, 0x13,
- 0x59, 0x08,
- 0xff, 0xff,
-};
-
-static struct stv0297_config dvbc_philips_tdm1316l_config = {
- .demod_address = 0x1c,
- .inittab = dvbc_philips_tdm1316l_inittab,
- .invert = 0,
- .stop_during_read = 1,
-};
-
-static struct tda10023_config tda10023_config = {
- .demod_address = 0xc,
- .invert = 0,
- .xtal = 16000000,
- .pll_m = 11,
- .pll_p = 3,
- .pll_n = 1,
- .deltaf = 0xa511,
-};
-
-static struct tda827x_config tda827x_config = {
- .config = 0,
-};
-
-/* TT S2-3200 DVB-S (STB0899) Inittab */
-static const struct stb0899_s1_reg tt3200_stb0899_s1_init_1[] = {
-
- { STB0899_DEV_ID , 0x81 },
- { STB0899_DISCNTRL1 , 0x32 },
- { STB0899_DISCNTRL2 , 0x80 },
- { STB0899_DISRX_ST0 , 0x04 },
- { STB0899_DISRX_ST1 , 0x00 },
- { STB0899_DISPARITY , 0x00 },
- { STB0899_DISSTATUS , 0x20 },
- { STB0899_DISF22 , 0x8c },
- { STB0899_DISF22RX , 0x9a },
- { STB0899_SYSREG , 0x0b },
- { STB0899_ACRPRESC , 0x11 },
- { STB0899_ACRDIV1 , 0x0a },
- { STB0899_ACRDIV2 , 0x05 },
- { STB0899_DACR1 , 0x00 },
- { STB0899_DACR2 , 0x00 },
- { STB0899_OUTCFG , 0x00 },
- { STB0899_MODECFG , 0x00 },
- { STB0899_IRQSTATUS_3 , 0x30 },
- { STB0899_IRQSTATUS_2 , 0x00 },
- { STB0899_IRQSTATUS_1 , 0x00 },
- { STB0899_IRQSTATUS_0 , 0x00 },
- { STB0899_IRQMSK_3 , 0xf3 },
- { STB0899_IRQMSK_2 , 0xfc },
- { STB0899_IRQMSK_1 , 0xff },
- { STB0899_IRQMSK_0 , 0xff },
- { STB0899_IRQCFG , 0x00 },
- { STB0899_I2CCFG , 0x88 },
- { STB0899_I2CRPT , 0x48 }, /* 12k Pullup, Repeater=16, Stop=disabled */
- { STB0899_IOPVALUE5 , 0x00 },
- { STB0899_IOPVALUE4 , 0x20 },
- { STB0899_IOPVALUE3 , 0xc9 },
- { STB0899_IOPVALUE2 , 0x90 },
- { STB0899_IOPVALUE1 , 0x40 },
- { STB0899_IOPVALUE0 , 0x00 },
- { STB0899_GPIO00CFG , 0x82 },
- { STB0899_GPIO01CFG , 0x82 },
- { STB0899_GPIO02CFG , 0x82 },
- { STB0899_GPIO03CFG , 0x82 },
- { STB0899_GPIO04CFG , 0x82 },
- { STB0899_GPIO05CFG , 0x82 },
- { STB0899_GPIO06CFG , 0x82 },
- { STB0899_GPIO07CFG , 0x82 },
- { STB0899_GPIO08CFG , 0x82 },
- { STB0899_GPIO09CFG , 0x82 },
- { STB0899_GPIO10CFG , 0x82 },
- { STB0899_GPIO11CFG , 0x82 },
- { STB0899_GPIO12CFG , 0x82 },
- { STB0899_GPIO13CFG , 0x82 },
- { STB0899_GPIO14CFG , 0x82 },
- { STB0899_GPIO15CFG , 0x82 },
- { STB0899_GPIO16CFG , 0x82 },
- { STB0899_GPIO17CFG , 0x82 },
- { STB0899_GPIO18CFG , 0x82 },
- { STB0899_GPIO19CFG , 0x82 },
- { STB0899_GPIO20CFG , 0x82 },
- { STB0899_SDATCFG , 0xb8 },
- { STB0899_SCLTCFG , 0xba },
- { STB0899_AGCRFCFG , 0x1c }, /* 0x11 */
- { STB0899_GPIO22 , 0x82 }, /* AGCBB2CFG */
- { STB0899_GPIO21 , 0x91 }, /* AGCBB1CFG */
- { STB0899_DIRCLKCFG , 0x82 },
- { STB0899_CLKOUT27CFG , 0x7e },
- { STB0899_STDBYCFG , 0x82 },
- { STB0899_CS0CFG , 0x82 },
- { STB0899_CS1CFG , 0x82 },
- { STB0899_DISEQCOCFG , 0x20 },
- { STB0899_GPIO32CFG , 0x82 },
- { STB0899_GPIO33CFG , 0x82 },
- { STB0899_GPIO34CFG , 0x82 },
- { STB0899_GPIO35CFG , 0x82 },
- { STB0899_GPIO36CFG , 0x82 },
- { STB0899_GPIO37CFG , 0x82 },
- { STB0899_GPIO38CFG , 0x82 },
- { STB0899_GPIO39CFG , 0x82 },
- { STB0899_NCOARSE , 0x15 }, /* 0x15 = 27 Mhz Clock, F/3 = 198MHz, F/6 = 99MHz */
- { STB0899_SYNTCTRL , 0x02 }, /* 0x00 = CLK from CLKI, 0x02 = CLK from XTALI */
- { STB0899_FILTCTRL , 0x00 },
- { STB0899_SYSCTRL , 0x00 },
- { STB0899_STOPCLK1 , 0x20 },
- { STB0899_STOPCLK2 , 0x00 },
- { STB0899_INTBUFSTATUS , 0x00 },
- { STB0899_INTBUFCTRL , 0x0a },
- { 0xffff , 0xff },
-};
-
-static const struct stb0899_s1_reg tt3200_stb0899_s1_init_3[] = {
- { STB0899_DEMOD , 0x00 },
- { STB0899_RCOMPC , 0xc9 },
- { STB0899_AGC1CN , 0x41 },
- { STB0899_AGC1REF , 0x10 },
- { STB0899_RTC , 0x7a },
- { STB0899_TMGCFG , 0x4e },
- { STB0899_AGC2REF , 0x34 },
- { STB0899_TLSR , 0x84 },
- { STB0899_CFD , 0xc7 },
- { STB0899_ACLC , 0x87 },
- { STB0899_BCLC , 0x94 },
- { STB0899_EQON , 0x41 },
- { STB0899_LDT , 0xdd },
- { STB0899_LDT2 , 0xc9 },
- { STB0899_EQUALREF , 0xb4 },
- { STB0899_TMGRAMP , 0x10 },
- { STB0899_TMGTHD , 0x30 },
- { STB0899_IDCCOMP , 0xfb },
- { STB0899_QDCCOMP , 0x03 },
- { STB0899_POWERI , 0x3b },
- { STB0899_POWERQ , 0x3d },
- { STB0899_RCOMP , 0x81 },
- { STB0899_AGCIQIN , 0x80 },
- { STB0899_AGC2I1 , 0x04 },
- { STB0899_AGC2I2 , 0xf5 },
- { STB0899_TLIR , 0x25 },
- { STB0899_RTF , 0x80 },
- { STB0899_DSTATUS , 0x00 },
- { STB0899_LDI , 0xca },
- { STB0899_CFRM , 0xf1 },
- { STB0899_CFRL , 0xf3 },
- { STB0899_NIRM , 0x2a },
- { STB0899_NIRL , 0x05 },
- { STB0899_ISYMB , 0x17 },
- { STB0899_QSYMB , 0xfa },
- { STB0899_SFRH , 0x2f },
- { STB0899_SFRM , 0x68 },
- { STB0899_SFRL , 0x40 },
- { STB0899_SFRUPH , 0x2f },
- { STB0899_SFRUPM , 0x68 },
- { STB0899_SFRUPL , 0x40 },
- { STB0899_EQUAI1 , 0xfd },
- { STB0899_EQUAQ1 , 0x04 },
- { STB0899_EQUAI2 , 0x0f },
- { STB0899_EQUAQ2 , 0xff },
- { STB0899_EQUAI3 , 0xdf },
- { STB0899_EQUAQ3 , 0xfa },
- { STB0899_EQUAI4 , 0x37 },
- { STB0899_EQUAQ4 , 0x0d },
- { STB0899_EQUAI5 , 0xbd },
- { STB0899_EQUAQ5 , 0xf7 },
- { STB0899_DSTATUS2 , 0x00 },
- { STB0899_VSTATUS , 0x00 },
- { STB0899_VERROR , 0xff },
- { STB0899_IQSWAP , 0x2a },
- { STB0899_ECNT1M , 0x00 },
- { STB0899_ECNT1L , 0x00 },
- { STB0899_ECNT2M , 0x00 },
- { STB0899_ECNT2L , 0x00 },
- { STB0899_ECNT3M , 0x00 },
- { STB0899_ECNT3L , 0x00 },
- { STB0899_FECAUTO1 , 0x06 },
- { STB0899_FECM , 0x01 },
- { STB0899_VTH12 , 0xf0 },
- { STB0899_VTH23 , 0xa0 },
- { STB0899_VTH34 , 0x78 },
- { STB0899_VTH56 , 0x4e },
- { STB0899_VTH67 , 0x48 },
- { STB0899_VTH78 , 0x38 },
- { STB0899_PRVIT , 0xff },
- { STB0899_VITSYNC , 0x19 },
- { STB0899_RSULC , 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */
- { STB0899_TSULC , 0x42 },
- { STB0899_RSLLC , 0x40 },
- { STB0899_TSLPL , 0x12 },
- { STB0899_TSCFGH , 0x0c },
- { STB0899_TSCFGM , 0x00 },
- { STB0899_TSCFGL , 0x0c },
- { STB0899_TSOUT , 0x4d }, /* 0x0d for CAM */
- { STB0899_RSSYNCDEL , 0x00 },
- { STB0899_TSINHDELH , 0x02 },
- { STB0899_TSINHDELM , 0x00 },
- { STB0899_TSINHDELL , 0x00 },
- { STB0899_TSLLSTKM , 0x00 },
- { STB0899_TSLLSTKL , 0x00 },
- { STB0899_TSULSTKM , 0x00 },
- { STB0899_TSULSTKL , 0xab },
- { STB0899_PCKLENUL , 0x00 },
- { STB0899_PCKLENLL , 0xcc },
- { STB0899_RSPCKLEN , 0xcc },
- { STB0899_TSSTATUS , 0x80 },
- { STB0899_ERRCTRL1 , 0xb6 },
- { STB0899_ERRCTRL2 , 0x96 },
- { STB0899_ERRCTRL3 , 0x89 },
- { STB0899_DMONMSK1 , 0x27 },
- { STB0899_DMONMSK0 , 0x03 },
- { STB0899_DEMAPVIT , 0x5c },
- { STB0899_PLPARM , 0x1f },
- { STB0899_PDELCTRL , 0x48 },
- { STB0899_PDELCTRL2 , 0x00 },
- { STB0899_BBHCTRL1 , 0x00 },
- { STB0899_BBHCTRL2 , 0x00 },
- { STB0899_HYSTTHRESH , 0x77 },
- { STB0899_MATCSTM , 0x00 },
- { STB0899_MATCSTL , 0x00 },
- { STB0899_UPLCSTM , 0x00 },
- { STB0899_UPLCSTL , 0x00 },
- { STB0899_DFLCSTM , 0x00 },
- { STB0899_DFLCSTL , 0x00 },
- { STB0899_SYNCCST , 0x00 },
- { STB0899_SYNCDCSTM , 0x00 },
- { STB0899_SYNCDCSTL , 0x00 },
- { STB0899_ISI_ENTRY , 0x00 },
- { STB0899_ISI_BIT_EN , 0x00 },
- { STB0899_MATSTRM , 0x00 },
- { STB0899_MATSTRL , 0x00 },
- { STB0899_UPLSTRM , 0x00 },
- { STB0899_UPLSTRL , 0x00 },
- { STB0899_DFLSTRM , 0x00 },
- { STB0899_DFLSTRL , 0x00 },
- { STB0899_SYNCSTR , 0x00 },
- { STB0899_SYNCDSTRM , 0x00 },
- { STB0899_SYNCDSTRL , 0x00 },
- { STB0899_CFGPDELSTATUS1 , 0x10 },
- { STB0899_CFGPDELSTATUS2 , 0x00 },
- { STB0899_BBFERRORM , 0x00 },
- { STB0899_BBFERRORL , 0x00 },
- { STB0899_UPKTERRORM , 0x00 },
- { STB0899_UPKTERRORL , 0x00 },
- { 0xffff , 0xff },
-};
-
-static struct stb0899_config tt3200_config = {
- .init_dev = tt3200_stb0899_s1_init_1,
- .init_s2_demod = stb0899_s2_init_2,
- .init_s1_demod = tt3200_stb0899_s1_init_3,
- .init_s2_fec = stb0899_s2_init_4,
- .init_tst = stb0899_s1_init_5,
-
- .postproc = NULL,
-
- .demod_address = 0x68,
-
- .xtal_freq = 27000000,
- .inversion = IQ_SWAP_ON,
-
- .lo_clk = 76500000,
- .hi_clk = 99000000,
-
- .esno_ave = STB0899_DVBS2_ESNO_AVE,
- .esno_quant = STB0899_DVBS2_ESNO_QUANT,
- .avframes_coarse = STB0899_DVBS2_AVFRAMES_COARSE,
- .avframes_fine = STB0899_DVBS2_AVFRAMES_FINE,
- .miss_threshold = STB0899_DVBS2_MISS_THRESHOLD,
- .uwp_threshold_acq = STB0899_DVBS2_UWP_THRESHOLD_ACQ,
- .uwp_threshold_track = STB0899_DVBS2_UWP_THRESHOLD_TRACK,
- .uwp_threshold_sof = STB0899_DVBS2_UWP_THRESHOLD_SOF,
- .sof_search_timeout = STB0899_DVBS2_SOF_SEARCH_TIMEOUT,
-
- .btr_nco_bits = STB0899_DVBS2_BTR_NCO_BITS,
- .btr_gain_shift_offset = STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET,
- .crl_nco_bits = STB0899_DVBS2_CRL_NCO_BITS,
- .ldpc_max_iter = STB0899_DVBS2_LDPC_MAX_ITER,
-
- .tuner_get_frequency = stb6100_get_frequency,
- .tuner_set_frequency = stb6100_set_frequency,
- .tuner_set_bandwidth = stb6100_set_bandwidth,
- .tuner_get_bandwidth = stb6100_get_bandwidth,
- .tuner_set_rfsiggain = NULL
-};
-
-static struct stb6100_config tt3200_stb6100_config = {
- .tuner_address = 0x60,
- .refclock = 27000000,
-};
-
-static void frontend_init(struct budget_ci *budget_ci)
-{
- switch (budget_ci->budget.dev->pci->subsystem_device) {
- case 0x100c: // Hauppauge/TT Nova-CI budget (stv0299/ALPS BSRU6(tsa5059))
- budget_ci->budget.dvb_frontend =
- dvb_attach(stv0299_attach, &alps_bsru6_config, &budget_ci->budget.i2c_adap);
- if (budget_ci->budget.dvb_frontend) {
- budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
- budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
- break;
- }
- break;
-
- case 0x100f: // Hauppauge/TT Nova-CI budget (stv0299b/Philips su1278(tsa5059))
- budget_ci->budget.dvb_frontend =
- dvb_attach(stv0299_attach, &philips_su1278_tt_config, &budget_ci->budget.i2c_adap);
- if (budget_ci->budget.dvb_frontend) {
- budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_su1278_tt_tuner_set_params;
- break;
- }
- break;
-
- case 0x1010: // TT DVB-C CI budget (stv0297/Philips tdm1316l(tda6651tt))
- budget_ci->tuner_pll_address = 0x61;
- budget_ci->budget.dvb_frontend =
- dvb_attach(stv0297_attach, &dvbc_philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
- if (budget_ci->budget.dvb_frontend) {
- budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = dvbc_philips_tdm1316l_tuner_set_params;
- break;
- }
- break;
-
- case 0x1011: // Hauppauge/TT Nova-T budget (tda10045/Philips tdm1316l(tda6651tt) + TDA9889)
- budget_ci->tuner_pll_address = 0x63;
- budget_ci->budget.dvb_frontend =
- dvb_attach(tda10045_attach, &philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
- if (budget_ci->budget.dvb_frontend) {
- budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
- budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
- break;
- }
- break;
-
- case 0x1012: // TT DVB-T CI budget (tda10046/Philips tdm1316l(tda6651tt))
- budget_ci->tuner_pll_address = 0x60;
- budget_ci->budget.dvb_frontend =
- dvb_attach(tda10046_attach, &philips_tdm1316l_config_invert, &budget_ci->budget.i2c_adap);
- if (budget_ci->budget.dvb_frontend) {
- budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
- budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
- break;
- }
- break;
-
- case 0x1017: // TT S-1500 PCI
- budget_ci->budget.dvb_frontend = dvb_attach(stv0299_attach, &alps_bsbe1_config, &budget_ci->budget.i2c_adap);
- if (budget_ci->budget.dvb_frontend) {
- budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
- budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
-
- budget_ci->budget.dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
- if (dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, LNBP21_LLC, 0) == NULL) {
- printk("%s: No LNBP21 found!\n", __func__);
- dvb_frontend_detach(budget_ci->budget.dvb_frontend);
- budget_ci->budget.dvb_frontend = NULL;
- }
- }
- break;
-
- case 0x101a: /* TT Budget-C-1501 (philips tda10023/philips tda8274A) */
- budget_ci->budget.dvb_frontend = dvb_attach(tda10023_attach, &tda10023_config, &budget_ci->budget.i2c_adap, 0x48);
- if (budget_ci->budget.dvb_frontend) {
- if (dvb_attach(tda827x_attach, budget_ci->budget.dvb_frontend, 0x61, &budget_ci->budget.i2c_adap, &tda827x_config) == NULL) {
- printk(KERN_ERR "%s: No tda827x found!\n", __func__);
- dvb_frontend_detach(budget_ci->budget.dvb_frontend);
- budget_ci->budget.dvb_frontend = NULL;
- }
- }
- break;
-
- case 0x101b: /* TT S-1500B (BSBE1-D01A - STV0288/STB6000/LNBP21) */
- budget_ci->budget.dvb_frontend = dvb_attach(stv0288_attach, &stv0288_bsbe1_d01a_config, &budget_ci->budget.i2c_adap);
- if (budget_ci->budget.dvb_frontend) {
- if (dvb_attach(stb6000_attach, budget_ci->budget.dvb_frontend, 0x63, &budget_ci->budget.i2c_adap)) {
- if (!dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, 0, 0)) {
- printk(KERN_ERR "%s: No LNBP21 found!\n", __func__);
- dvb_frontend_detach(budget_ci->budget.dvb_frontend);
- budget_ci->budget.dvb_frontend = NULL;
- }
- } else {
- printk(KERN_ERR "%s: No STB6000 found!\n", __func__);
- dvb_frontend_detach(budget_ci->budget.dvb_frontend);
- budget_ci->budget.dvb_frontend = NULL;
- }
- }
- break;
-
- case 0x1019: // TT S2-3200 PCI
- /*
- * NOTE! on some STB0899 versions, the internal PLL takes a longer time
- * to settle, aka LOCK. On the older revisions of the chip, we don't see
- * this, as a result on the newer chips the entire clock tree, will not
- * be stable after a freshly POWER 'ed up situation.
- * In this case, we should RESET the STB0899 (Active LOW) and wait for
- * PLL stabilization.
- *
- * On the TT S2 3200 and clones, the STB0899 demodulator's RESETB is
- * connected to the SAA7146 GPIO, GPIO2, Pin 142
- */
- /* Reset Demodulator */
- saa7146_setgpio(budget_ci->budget.dev, 2, SAA7146_GPIO_OUTLO);
- /* Wait for everything to die */
- msleep(50);
- /* Pull it up out of Reset state */
- saa7146_setgpio(budget_ci->budget.dev, 2, SAA7146_GPIO_OUTHI);
- /* Wait for PLL to stabilize */
- msleep(250);
- /*
- * PLL state should be stable now. Ideally, we should check
- * for PLL LOCK status. But well, never mind!
- */
- budget_ci->budget.dvb_frontend = dvb_attach(stb0899_attach, &tt3200_config, &budget_ci->budget.i2c_adap);
- if (budget_ci->budget.dvb_frontend) {
- if (dvb_attach(stb6100_attach, budget_ci->budget.dvb_frontend, &tt3200_stb6100_config, &budget_ci->budget.i2c_adap)) {
- if (!dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, 0, 0)) {
- printk("%s: No LNBP21 found!\n", __func__);
- dvb_frontend_detach(budget_ci->budget.dvb_frontend);
- budget_ci->budget.dvb_frontend = NULL;
- }
- } else {
- dvb_frontend_detach(budget_ci->budget.dvb_frontend);
- budget_ci->budget.dvb_frontend = NULL;
- }
- }
- break;
-
- }
-
- if (budget_ci->budget.dvb_frontend == NULL) {
- printk("budget-ci: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
- budget_ci->budget.dev->pci->vendor,
- budget_ci->budget.dev->pci->device,
- budget_ci->budget.dev->pci->subsystem_vendor,
- budget_ci->budget.dev->pci->subsystem_device);
- } else {
- if (dvb_register_frontend
- (&budget_ci->budget.dvb_adapter, budget_ci->budget.dvb_frontend)) {
- printk("budget-ci: Frontend registration failed!\n");
- dvb_frontend_detach(budget_ci->budget.dvb_frontend);
- budget_ci->budget.dvb_frontend = NULL;
- }
- }
-}
-
-static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
-{
- struct budget_ci *budget_ci;
- int err;
-
- budget_ci = kzalloc(sizeof(struct budget_ci), GFP_KERNEL);
- if (!budget_ci) {
- err = -ENOMEM;
- goto out1;
- }
-
- dprintk(2, "budget_ci: %p\n", budget_ci);
-
- dev->ext_priv = budget_ci;
-
- err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE,
- adapter_nr);
- if (err)
- goto out2;
-
- err = msp430_ir_init(budget_ci);
- if (err)
- goto out3;
-
- ciintf_init(budget_ci);
-
- budget_ci->budget.dvb_adapter.priv = budget_ci;
- frontend_init(budget_ci);
-
- ttpci_budget_init_hooks(&budget_ci->budget);
-
- return 0;
-
-out3:
- ttpci_budget_deinit(&budget_ci->budget);
-out2:
- kfree(budget_ci);
-out1:
- return err;
-}
-
-static int budget_ci_detach(struct saa7146_dev *dev)
-{
- struct budget_ci *budget_ci = (struct budget_ci *) dev->ext_priv;
- struct saa7146_dev *saa = budget_ci->budget.dev;
- int err;
-
- if (budget_ci->budget.ci_present)
- ciintf_deinit(budget_ci);
- msp430_ir_deinit(budget_ci);
- if (budget_ci->budget.dvb_frontend) {
- dvb_unregister_frontend(budget_ci->budget.dvb_frontend);
- dvb_frontend_detach(budget_ci->budget.dvb_frontend);
- }
- err = ttpci_budget_deinit(&budget_ci->budget);
-
- // disable frontend and CI interface
- saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT);
-
- kfree(budget_ci);
-
- return err;
-}
-
-static struct saa7146_extension budget_extension;
-
-MAKE_BUDGET_INFO(ttbs2, "TT-Budget/S-1500 PCI", BUDGET_TT);
-MAKE_BUDGET_INFO(ttbci, "TT-Budget/WinTV-NOVA-CI PCI", BUDGET_TT_HW_DISEQC);
-MAKE_BUDGET_INFO(ttbt2, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT);
-MAKE_BUDGET_INFO(ttbtci, "TT-Budget-T-CI PCI", BUDGET_TT);
-MAKE_BUDGET_INFO(ttbcci, "TT-Budget-C-CI PCI", BUDGET_TT);
-MAKE_BUDGET_INFO(ttc1501, "TT-Budget C-1501 PCI", BUDGET_TT);
-MAKE_BUDGET_INFO(tt3200, "TT-Budget S2-3200 PCI", BUDGET_TT);
-MAKE_BUDGET_INFO(ttbs1500b, "TT-Budget S-1500B PCI", BUDGET_TT);
-
-static const struct pci_device_id pci_tbl[] = {
- MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c),
- MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100f),
- MAKE_EXTENSION_PCI(ttbcci, 0x13c2, 0x1010),
- MAKE_EXTENSION_PCI(ttbt2, 0x13c2, 0x1011),
- MAKE_EXTENSION_PCI(ttbtci, 0x13c2, 0x1012),
- MAKE_EXTENSION_PCI(ttbs2, 0x13c2, 0x1017),
- MAKE_EXTENSION_PCI(ttc1501, 0x13c2, 0x101a),
- MAKE_EXTENSION_PCI(tt3200, 0x13c2, 0x1019),
- MAKE_EXTENSION_PCI(ttbs1500b, 0x13c2, 0x101b),
- {
- .vendor = 0,
- }
-};
-
-MODULE_DEVICE_TABLE(pci, pci_tbl);
-
-static struct saa7146_extension budget_extension = {
- .name = "budget_ci dvb",
- .flags = SAA7146_USE_I2C_IRQ,
-
- .module = THIS_MODULE,
- .pci_tbl = &pci_tbl[0],
- .attach = budget_ci_attach,
- .detach = budget_ci_detach,
-
- .irq_mask = MASK_03 | MASK_06 | MASK_10,
- .irq_func = budget_ci_irq,
-};
-
-static int __init budget_ci_init(void)
-{
- return saa7146_register_extension(&budget_extension);
-}
-
-static void __exit budget_ci_exit(void)
-{
- saa7146_unregister_extension(&budget_extension);
-}
-
-module_init(budget_ci_init);
-module_exit(budget_ci_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Michael Hunold, Jack Thomasson, Andrew de Quincey, others");
-MODULE_DESCRIPTION("driver for the SAA7146 based so-called budget PCI DVB cards w/ CI-module produced by Siemens, Technotrend, Hauppauge");
diff --git a/drivers/media/pci/ttpci/budget-core.c b/drivers/media/pci/ttpci/budget-core.c
deleted file mode 100644
index 5d5796f24469..000000000000
--- a/drivers/media/pci/ttpci/budget-core.c
+++ /dev/null
@@ -1,603 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * budget-core.c: driver for the SAA7146 based Budget DVB cards
- *
- * Compiled from various sources by Michael Hunold <michael@mihu.de>
- *
- * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
- *
- * Copyright (C) 1999-2002 Ralph Metzler
- * & Marcus Metzler for convergence integrated media GmbH
- *
- * 26feb2004 Support for FS Activy Card (Grundig tuner) by
- * Michael Dreher <michael@5dot1.de>,
- * Oliver Endriss <o.endriss@gmx.de>,
- * Andreas 'randy' Weinberger
- *
- * the project's page is at https://linuxtv.org
- */
-
-
-#include "budget.h"
-#include "ttpci-eeprom.h"
-
-#define TS_WIDTH (2 * TS_SIZE)
-#define TS_WIDTH_ACTIVY TS_SIZE
-#define TS_WIDTH_DVBC TS_SIZE
-#define TS_HEIGHT_MASK 0xf00
-#define TS_HEIGHT_MASK_ACTIVY 0xc00
-#define TS_HEIGHT_MASK_DVBC 0xe00
-#define TS_MIN_BUFSIZE_K 188
-#define TS_MAX_BUFSIZE_K 1410
-#define TS_MAX_BUFSIZE_K_ACTIVY 564
-#define TS_MAX_BUFSIZE_K_DVBC 1316
-#define BUFFER_WARNING_WAIT (30*HZ)
-
-int budget_debug;
-static int dma_buffer_size = TS_MIN_BUFSIZE_K;
-module_param_named(debug, budget_debug, int, 0644);
-module_param_named(bufsize, dma_buffer_size, int, 0444);
-MODULE_PARM_DESC(debug, "Turn on/off budget debugging (default:off).");
-MODULE_PARM_DESC(bufsize, "DMA buffer size in KB, default: 188, min: 188, max: 1410 (Activy: 564)");
-
-/****************************************************************************
- * TT budget / WinTV Nova
- ****************************************************************************/
-
-static int stop_ts_capture(struct budget *budget)
-{
- dprintk(2, "budget: %p\n", budget);
-
- saa7146_write(budget->dev, MC1, MASK_20); // DMA3 off
- SAA7146_IER_DISABLE(budget->dev, MASK_10);
- return 0;
-}
-
-static int start_ts_capture(struct budget *budget)
-{
- struct saa7146_dev *dev = budget->dev;
-
- dprintk(2, "budget: %p\n", budget);
-
- if (!budget->feeding || !budget->fe_synced)
- return 0;
-
- saa7146_write(dev, MC1, MASK_20); // DMA3 off
-
- memset(budget->grabbing, 0x00, budget->buffer_size);
-
- saa7146_write(dev, PCI_BT_V1, 0x001c0000 | (saa7146_read(dev, PCI_BT_V1) & ~0x001f0000));
-
- budget->ttbp = 0;
-
- /*
- * Signal path on the Activy:
- *
- * tuner -> SAA7146 port A -> SAA7146 BRS -> SAA7146 DMA3 -> memory
- *
- * Since the tuner feeds 204 bytes packets into the SAA7146,
- * DMA3 is configured to strip the trailing 16 FEC bytes:
- * Pitch: 188, NumBytes3: 188, NumLines3: 1024
- */
-
- switch(budget->card->type) {
- case BUDGET_FS_ACTIVY:
- saa7146_write(dev, DD1_INIT, 0x04000000);
- saa7146_write(dev, MC2, (MASK_09 | MASK_25));
- saa7146_write(dev, BRS_CTRL, 0x00000000);
- break;
- case BUDGET_PATCH:
- saa7146_write(dev, DD1_INIT, 0x00000200);
- saa7146_write(dev, MC2, (MASK_10 | MASK_26));
- saa7146_write(dev, BRS_CTRL, 0x60000000);
- break;
- case BUDGET_CIN1200C_MK3:
- case BUDGET_KNC1C_MK3:
- case BUDGET_KNC1C_TDA10024:
- case BUDGET_KNC1CP_MK3:
- if (budget->video_port == BUDGET_VIDEO_PORTA) {
- saa7146_write(dev, DD1_INIT, 0x06000200);
- saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
- saa7146_write(dev, BRS_CTRL, 0x00000000);
- } else {
- saa7146_write(dev, DD1_INIT, 0x00000600);
- saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
- saa7146_write(dev, BRS_CTRL, 0x60000000);
- }
- break;
- default:
- if (budget->video_port == BUDGET_VIDEO_PORTA) {
- saa7146_write(dev, DD1_INIT, 0x06000200);
- saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
- saa7146_write(dev, BRS_CTRL, 0x00000000);
- } else {
- saa7146_write(dev, DD1_INIT, 0x02000600);
- saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
- saa7146_write(dev, BRS_CTRL, 0x60000000);
- }
- }
-
- saa7146_write(dev, MC2, (MASK_08 | MASK_24));
- mdelay(10);
-
- saa7146_write(dev, BASE_ODD3, 0);
- if (budget->buffer_size > budget->buffer_height * budget->buffer_width) {
- // using odd/even buffers
- saa7146_write(dev, BASE_EVEN3, budget->buffer_height * budget->buffer_width);
- } else {
- // using a single buffer
- saa7146_write(dev, BASE_EVEN3, 0);
- }
- saa7146_write(dev, PROT_ADDR3, budget->buffer_size);
- saa7146_write(dev, BASE_PAGE3, budget->pt.dma | ME1 | 0x90);
-
- saa7146_write(dev, PITCH3, budget->buffer_width);
- saa7146_write(dev, NUM_LINE_BYTE3,
- (budget->buffer_height << 16) | budget->buffer_width);
-
- saa7146_write(dev, MC2, (MASK_04 | MASK_20));
-
- SAA7146_ISR_CLEAR(budget->dev, MASK_10); /* VPE */
- SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */
- saa7146_write(dev, MC1, (MASK_04 | MASK_20)); /* DMA3 on */
-
- return 0;
-}
-
-static int budget_read_fe_status(struct dvb_frontend *fe,
- enum fe_status *status)
-{
- struct budget *budget = (struct budget *) fe->dvb->priv;
- int synced;
- int ret;
-
- if (budget->read_fe_status)
- ret = budget->read_fe_status(fe, status);
- else
- ret = -EINVAL;
-
- if (!ret) {
- synced = (*status & FE_HAS_LOCK);
- if (synced != budget->fe_synced) {
- budget->fe_synced = synced;
- spin_lock(&budget->feedlock);
- if (synced)
- start_ts_capture(budget);
- else
- stop_ts_capture(budget);
- spin_unlock(&budget->feedlock);
- }
- }
- return ret;
-}
-
-static void vpeirq(struct tasklet_struct *t)
-{
- struct budget *budget = from_tasklet(budget, t, vpe_tasklet);
- u8 *mem = (u8 *) (budget->grabbing);
- u32 olddma = budget->ttbp;
- u32 newdma = saa7146_read(budget->dev, PCI_VDP3);
- u32 count;
-
- /* Ensure streamed PCI data is synced to CPU */
- dma_sync_sg_for_cpu(&budget->dev->pci->dev, budget->pt.slist,
- budget->pt.nents, DMA_FROM_DEVICE);
-
- /* nearest lower position divisible by 188 */
- newdma -= newdma % 188;
-
- if (newdma >= budget->buffer_size)
- return;
-
- budget->ttbp = newdma;
-
- if (budget->feeding == 0 || newdma == olddma)
- return;
-
- if (newdma > olddma) { /* no wraparound, dump olddma..newdma */
- count = newdma - olddma;
- dvb_dmx_swfilter_packets(&budget->demux, mem + olddma, count / 188);
- } else { /* wraparound, dump olddma..buflen and 0..newdma */
- count = budget->buffer_size - olddma;
- dvb_dmx_swfilter_packets(&budget->demux, mem + olddma, count / 188);
- count += newdma;
- dvb_dmx_swfilter_packets(&budget->demux, mem, newdma / 188);
- }
-
- if (count > budget->buffer_warning_threshold)
- budget->buffer_warnings++;
-
- if (budget->buffer_warnings && time_after(jiffies, budget->buffer_warning_time)) {
- printk("%s %s: used %d times >80%% of buffer (%u bytes now)\n",
- budget->dev->name, __func__, budget->buffer_warnings, count);
- budget->buffer_warning_time = jiffies + BUFFER_WARNING_WAIT;
- budget->buffer_warnings = 0;
- }
-}
-
-
-static int ttpci_budget_debiread_nolock(struct budget *budget, u32 config,
- int addr, int count, int nobusyloop)
-{
- struct saa7146_dev *saa = budget->dev;
- int result;
-
- result = saa7146_wait_for_debi_done(saa, nobusyloop);
- if (result < 0)
- return result;
-
- saa7146_write(saa, DEBI_COMMAND, (count << 17) | 0x10000 | (addr & 0xffff));
- saa7146_write(saa, DEBI_CONFIG, config);
- saa7146_write(saa, DEBI_PAGE, 0);
- saa7146_write(saa, MC2, (2 << 16) | 2);
-
- result = saa7146_wait_for_debi_done(saa, nobusyloop);
- if (result < 0)
- return result;
-
- result = saa7146_read(saa, DEBI_AD);
- result &= (0xffffffffUL >> ((4 - count) * 8));
- return result;
-}
-
-int ttpci_budget_debiread(struct budget *budget, u32 config, int addr, int count,
- int uselocks, int nobusyloop)
-{
- if (count > 4 || count <= 0)
- return 0;
-
- if (uselocks) {
- unsigned long flags;
- int result;
-
- spin_lock_irqsave(&budget->debilock, flags);
- result = ttpci_budget_debiread_nolock(budget, config, addr,
- count, nobusyloop);
- spin_unlock_irqrestore(&budget->debilock, flags);
- return result;
- }
- return ttpci_budget_debiread_nolock(budget, config, addr,
- count, nobusyloop);
-}
-
-static int ttpci_budget_debiwrite_nolock(struct budget *budget, u32 config,
- int addr, int count, u32 value, int nobusyloop)
-{
- struct saa7146_dev *saa = budget->dev;
- int result;
-
- result = saa7146_wait_for_debi_done(saa, nobusyloop);
- if (result < 0)
- return result;
-
- saa7146_write(saa, DEBI_COMMAND, (count << 17) | 0x00000 | (addr & 0xffff));
- saa7146_write(saa, DEBI_CONFIG, config);
- saa7146_write(saa, DEBI_PAGE, 0);
- saa7146_write(saa, DEBI_AD, value);
- saa7146_write(saa, MC2, (2 << 16) | 2);
-
- result = saa7146_wait_for_debi_done(saa, nobusyloop);
- return result < 0 ? result : 0;
-}
-
-int ttpci_budget_debiwrite(struct budget *budget, u32 config, int addr,
- int count, u32 value, int uselocks, int nobusyloop)
-{
- if (count > 4 || count <= 0)
- return 0;
-
- if (uselocks) {
- unsigned long flags;
- int result;
-
- spin_lock_irqsave(&budget->debilock, flags);
- result = ttpci_budget_debiwrite_nolock(budget, config, addr,
- count, value, nobusyloop);
- spin_unlock_irqrestore(&budget->debilock, flags);
- return result;
- }
- return ttpci_budget_debiwrite_nolock(budget, config, addr,
- count, value, nobusyloop);
-}
-
-
-/****************************************************************************
- * DVB API SECTION
- ****************************************************************************/
-
-static int budget_start_feed(struct dvb_demux_feed *feed)
-{
- struct dvb_demux *demux = feed->demux;
- struct budget *budget = (struct budget *) demux->priv;
- int status = 0;
-
- dprintk(2, "budget: %p\n", budget);
-
- if (!demux->dmx.frontend)
- return -EINVAL;
-
- spin_lock(&budget->feedlock);
- feed->pusi_seen = false; /* have a clean section start */
- if (budget->feeding++ == 0)
- status = start_ts_capture(budget);
- spin_unlock(&budget->feedlock);
- return status;
-}
-
-static int budget_stop_feed(struct dvb_demux_feed *feed)
-{
- struct dvb_demux *demux = feed->demux;
- struct budget *budget = (struct budget *) demux->priv;
- int status = 0;
-
- dprintk(2, "budget: %p\n", budget);
-
- spin_lock(&budget->feedlock);
- if (--budget->feeding == 0)
- status = stop_ts_capture(budget);
- spin_unlock(&budget->feedlock);
- return status;
-}
-
-static int budget_register(struct budget *budget)
-{
- struct dvb_demux *dvbdemux = &budget->demux;
- int ret;
-
- dprintk(2, "budget: %p\n", budget);
-
- dvbdemux->priv = (void *) budget;
-
- dvbdemux->filternum = 256;
- dvbdemux->feednum = 256;
- dvbdemux->start_feed = budget_start_feed;
- dvbdemux->stop_feed = budget_stop_feed;
- dvbdemux->write_to_decoder = NULL;
-
- dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
- DMX_MEMORY_BASED_FILTERING);
-
- dvb_dmx_init(&budget->demux);
-
- budget->dmxdev.filternum = 256;
- budget->dmxdev.demux = &dvbdemux->dmx;
- budget->dmxdev.capabilities = 0;
-
- dvb_dmxdev_init(&budget->dmxdev, &budget->dvb_adapter);
-
- budget->hw_frontend.source = DMX_FRONTEND_0;
-
- ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &budget->hw_frontend);
-
- if (ret < 0)
- goto err_release_dmx;
-
- budget->mem_frontend.source = DMX_MEMORY_FE;
- ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &budget->mem_frontend);
- if (ret < 0)
- goto err_release_dmx;
-
- ret = dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, &budget->hw_frontend);
- if (ret < 0)
- goto err_release_dmx;
-
- dvb_net_init(&budget->dvb_adapter, &budget->dvb_net, &dvbdemux->dmx);
-
- return 0;
-
-err_release_dmx:
- dvb_dmxdev_release(&budget->dmxdev);
- dvb_dmx_release(&budget->demux);
- return ret;
-}
-
-static void budget_unregister(struct budget *budget)
-{
- struct dvb_demux *dvbdemux = &budget->demux;
-
- dprintk(2, "budget: %p\n", budget);
-
- dvb_net_release(&budget->dvb_net);
-
- dvbdemux->dmx.close(&dvbdemux->dmx);
- dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &budget->hw_frontend);
- dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &budget->mem_frontend);
-
- dvb_dmxdev_release(&budget->dmxdev);
- dvb_dmx_release(&budget->demux);
-}
-
-int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
- struct saa7146_pci_extension_data *info,
- struct module *owner, short *adapter_nums)
-{
- int ret = 0;
- struct budget_info *bi = info->ext_priv;
- int max_bufsize;
- int height_mask;
-
- memset(budget, 0, sizeof(struct budget));
-
- dprintk(2, "dev: %p, budget: %p\n", dev, budget);
-
- budget->card = bi;
- budget->dev = (struct saa7146_dev *) dev;
-
- switch(budget->card->type) {
- case BUDGET_FS_ACTIVY:
- budget->buffer_width = TS_WIDTH_ACTIVY;
- max_bufsize = TS_MAX_BUFSIZE_K_ACTIVY;
- height_mask = TS_HEIGHT_MASK_ACTIVY;
- break;
-
- case BUDGET_KNC1C:
- case BUDGET_KNC1CP:
- case BUDGET_CIN1200C:
- case BUDGET_KNC1C_MK3:
- case BUDGET_KNC1C_TDA10024:
- case BUDGET_KNC1CP_MK3:
- case BUDGET_CIN1200C_MK3:
- budget->buffer_width = TS_WIDTH_DVBC;
- max_bufsize = TS_MAX_BUFSIZE_K_DVBC;
- height_mask = TS_HEIGHT_MASK_DVBC;
- break;
-
- default:
- budget->buffer_width = TS_WIDTH;
- max_bufsize = TS_MAX_BUFSIZE_K;
- height_mask = TS_HEIGHT_MASK;
- }
-
- if (dma_buffer_size < TS_MIN_BUFSIZE_K)
- dma_buffer_size = TS_MIN_BUFSIZE_K;
- else if (dma_buffer_size > max_bufsize)
- dma_buffer_size = max_bufsize;
-
- budget->buffer_height = dma_buffer_size * 1024 / budget->buffer_width;
- if (budget->buffer_height > 0xfff) {
- budget->buffer_height /= 2;
- budget->buffer_height &= height_mask;
- budget->buffer_size = 2 * budget->buffer_height * budget->buffer_width;
- } else {
- budget->buffer_height &= height_mask;
- budget->buffer_size = budget->buffer_height * budget->buffer_width;
- }
- budget->buffer_warning_threshold = budget->buffer_size * 80/100;
- budget->buffer_warnings = 0;
- budget->buffer_warning_time = jiffies;
-
- dprintk(2, "%s: buffer type = %s, width = %d, height = %d\n",
- budget->dev->name,
- budget->buffer_size > budget->buffer_width * budget->buffer_height ? "odd/even" : "single",
- budget->buffer_width, budget->buffer_height);
- printk("%s: dma buffer size %u\n", budget->dev->name, budget->buffer_size);
-
- ret = dvb_register_adapter(&budget->dvb_adapter, budget->card->name,
- owner, &budget->dev->pci->dev, adapter_nums);
- if (ret < 0)
- return ret;
-
- /* set dd1 stream a & b */
- saa7146_write(dev, DD1_STREAM_B, 0x00000000);
- saa7146_write(dev, MC2, (MASK_09 | MASK_25));
- saa7146_write(dev, MC2, (MASK_10 | MASK_26));
- saa7146_write(dev, DD1_INIT, 0x02000000);
- saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
-
- if (bi->type != BUDGET_FS_ACTIVY)
- budget->video_port = BUDGET_VIDEO_PORTB;
- else
- budget->video_port = BUDGET_VIDEO_PORTA;
- spin_lock_init(&budget->feedlock);
- spin_lock_init(&budget->debilock);
-
- /* the Siemens DVB needs this if you want to have the i2c chips
- get recognized before the main driver is loaded */
- if (bi->type != BUDGET_FS_ACTIVY)
- saa7146_write(dev, GPIO_CTRL, 0x500000); /* GPIO 3 = 1 */
-
- strscpy(budget->i2c_adap.name, budget->card->name,
- sizeof(budget->i2c_adap.name));
-
- saa7146_i2c_adapter_prepare(dev, &budget->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120);
- strscpy(budget->i2c_adap.name, budget->card->name,
- sizeof(budget->i2c_adap.name));
-
- if (i2c_add_adapter(&budget->i2c_adap) < 0) {
- ret = -ENOMEM;
- goto err_dvb_unregister;
- }
-
- ttpci_eeprom_parse_mac(&budget->i2c_adap, budget->dvb_adapter.proposed_mac);
-
- budget->grabbing = saa7146_vmalloc_build_pgtable(dev->pci, budget->buffer_size, &budget->pt);
- if (NULL == budget->grabbing) {
- ret = -ENOMEM;
- goto err_del_i2c;
- }
-
- saa7146_write(dev, PCI_BT_V1, 0x001c0000);
- /* upload all */
- saa7146_write(dev, GPIO_CTRL, 0x000000);
-
- tasklet_setup(&budget->vpe_tasklet, vpeirq);
-
- /* frontend power on */
- if (bi->type != BUDGET_FS_ACTIVY)
- saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
-
- if ((ret = budget_register(budget)) == 0)
- return 0; /* Everything OK */
-
- /* An error occurred, cleanup resources */
- saa7146_vfree_destroy_pgtable(dev->pci, budget->grabbing, &budget->pt);
-
-err_del_i2c:
- i2c_del_adapter(&budget->i2c_adap);
-
-err_dvb_unregister:
- dvb_unregister_adapter(&budget->dvb_adapter);
-
- return ret;
-}
-
-void ttpci_budget_init_hooks(struct budget *budget)
-{
- if (budget->dvb_frontend && !budget->read_fe_status) {
- budget->read_fe_status = budget->dvb_frontend->ops.read_status;
- budget->dvb_frontend->ops.read_status = budget_read_fe_status;
- }
-}
-
-int ttpci_budget_deinit(struct budget *budget)
-{
- struct saa7146_dev *dev = budget->dev;
-
- dprintk(2, "budget: %p\n", budget);
-
- budget_unregister(budget);
-
- tasklet_kill(&budget->vpe_tasklet);
-
- saa7146_vfree_destroy_pgtable(dev->pci, budget->grabbing, &budget->pt);
-
- i2c_del_adapter(&budget->i2c_adap);
-
- dvb_unregister_adapter(&budget->dvb_adapter);
-
- return 0;
-}
-
-void ttpci_budget_irq10_handler(struct saa7146_dev *dev, u32 * isr)
-{
- struct budget *budget = (struct budget *) dev->ext_priv;
-
- dprintk(8, "dev: %p, budget: %p\n", dev, budget);
-
- if (*isr & MASK_10)
- tasklet_schedule(&budget->vpe_tasklet);
-}
-
-void ttpci_budget_set_video_port(struct saa7146_dev *dev, int video_port)
-{
- struct budget *budget = (struct budget *) dev->ext_priv;
-
- spin_lock(&budget->feedlock);
- budget->video_port = video_port;
- if (budget->feeding) {
- stop_ts_capture(budget);
- start_ts_capture(budget);
- }
- spin_unlock(&budget->feedlock);
-}
-
-EXPORT_SYMBOL_GPL(ttpci_budget_debiread);
-EXPORT_SYMBOL_GPL(ttpci_budget_debiwrite);
-EXPORT_SYMBOL_GPL(ttpci_budget_init);
-EXPORT_SYMBOL_GPL(ttpci_budget_init_hooks);
-EXPORT_SYMBOL_GPL(ttpci_budget_deinit);
-EXPORT_SYMBOL_GPL(ttpci_budget_irq10_handler);
-EXPORT_SYMBOL_GPL(ttpci_budget_set_video_port);
-EXPORT_SYMBOL_GPL(budget_debug);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/pci/ttpci/budget.c b/drivers/media/pci/ttpci/budget.c
deleted file mode 100644
index a88711a3ac7f..000000000000
--- a/drivers/media/pci/ttpci/budget.c
+++ /dev/null
@@ -1,883 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * budget.c: driver for the SAA7146 based Budget DVB cards
- *
- * Compiled from various sources by Michael Hunold <michael@mihu.de>
- *
- * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
- *
- * Copyright (C) 1999-2002 Ralph Metzler
- * & Marcus Metzler for convergence integrated media GmbH
- *
- * 26feb2004 Support for FS Activy Card (Grundig tuner) by
- * Michael Dreher <michael@5dot1.de>,
- * Oliver Endriss <o.endriss@gmx.de> and
- * Andreas 'randy' Weinberger
- *
- * the project's page is at https://linuxtv.org
- */
-
-#include "budget.h"
-#include "stv0299.h"
-#include "ves1x93.h"
-#include "ves1820.h"
-#include "l64781.h"
-#include "tda8083.h"
-#include "s5h1420.h"
-#include "tda10086.h"
-#include "tda826x.h"
-#include "lnbp21.h"
-#include "bsru6.h"
-#include "bsbe1.h"
-#include "tdhd1.h"
-#include "stv6110x.h"
-#include "stv090x.h"
-#include "isl6423.h"
-#include "lnbh24.h"
-
-
-static int diseqc_method;
-module_param(diseqc_method, int, 0444);
-MODULE_PARM_DESC(diseqc_method, "Select DiSEqC method for subsystem id 13c2:1003, 0: default, 1: more reliable (for newer revisions only)");
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-static void Set22K (struct budget *budget, int state)
-{
- struct saa7146_dev *dev=budget->dev;
- dprintk(2, "budget: %p\n", budget);
- saa7146_setgpio(dev, 3, (state ? SAA7146_GPIO_OUTHI : SAA7146_GPIO_OUTLO));
-}
-
-/* Diseqc functions only for TT Budget card */
-/* taken from the Skyvision DVB driver by
- Ralph Metzler <rjkm@metzlerbros.de> */
-
-static void DiseqcSendBit (struct budget *budget, int data)
-{
- struct saa7146_dev *dev=budget->dev;
- dprintk(2, "budget: %p\n", budget);
-
- saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
- udelay(data ? 500 : 1000);
- saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
- udelay(data ? 1000 : 500);
-}
-
-static void DiseqcSendByte (struct budget *budget, int data)
-{
- int i, par=1, d;
-
- dprintk(2, "budget: %p\n", budget);
-
- for (i=7; i>=0; i--) {
- d = (data>>i)&1;
- par ^= d;
- DiseqcSendBit(budget, d);
- }
-
- DiseqcSendBit(budget, par);
-}
-
-static int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long burst)
-{
- struct saa7146_dev *dev=budget->dev;
- int i;
-
- dprintk(2, "budget: %p\n", budget);
-
- saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
- mdelay(16);
-
- for (i=0; i<len; i++)
- DiseqcSendByte(budget, msg[i]);
-
- mdelay(16);
-
- if (burst!=-1) {
- if (burst)
- DiseqcSendByte(budget, 0xff);
- else {
- saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
- mdelay(12);
- udelay(500);
- saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
- }
- msleep(20);
- }
-
- return 0;
-}
-
-/*
- * Routines for the Fujitsu Siemens Activy budget card
- * 22 kHz tone and DiSEqC are handled by the frontend.
- * Voltage must be set here.
- * GPIO 1: LNBP EN, GPIO 2: LNBP VSEL
- */
-static int SetVoltage_Activy(struct budget *budget,
- enum fe_sec_voltage voltage)
-{
- struct saa7146_dev *dev=budget->dev;
-
- dprintk(2, "budget: %p\n", budget);
-
- switch (voltage) {
- case SEC_VOLTAGE_13:
- saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI);
- saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTLO);
- break;
- case SEC_VOLTAGE_18:
- saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI);
- saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
- break;
- case SEC_VOLTAGE_OFF:
- saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTLO);
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-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,
- enum fe_sec_tone_mode tone)
-{
- struct budget* budget = (struct budget*) fe->dvb->priv;
-
- switch (tone) {
- case SEC_TONE_ON:
- Set22K (budget, 1);
- break;
-
- case SEC_TONE_OFF:
- Set22K (budget, 0);
- break;
-
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int budget_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
-{
- struct budget* budget = (struct budget*) fe->dvb->priv;
-
- SendDiSEqCMsg (budget, cmd->msg_len, cmd->msg, 0);
-
- return 0;
-}
-
-static int budget_diseqc_send_burst(struct dvb_frontend *fe,
- enum fe_sec_mini_cmd minicmd)
-{
- struct budget* budget = (struct budget*) fe->dvb->priv;
-
- SendDiSEqCMsg (budget, 0, NULL, minicmd);
-
- return 0;
-}
-
-static int alps_bsrv2_tuner_set_params(struct dvb_frontend *fe)
-{
- struct dtv_frontend_properties *c = &fe->dtv_property_cache;
- struct budget* budget = (struct budget*) fe->dvb->priv;
- u8 pwr = 0;
- u8 buf[4];
- struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
- u32 div = (c->frequency + 479500) / 125;
-
- if (c->frequency > 2000000)
- pwr = 3;
- else if (c->frequency > 1800000)
- pwr = 2;
- else if (c->frequency > 1600000)
- pwr = 1;
- else if (c->frequency > 1200000)
- pwr = 0;
- else if (c->frequency >= 1100000)
- pwr = 1;
- else pwr = 2;
-
- buf[0] = (div >> 8) & 0x7f;
- buf[1] = div & 0xff;
- buf[2] = ((div & 0x18000) >> 10) | 0x95;
- buf[3] = (pwr << 6) | 0x30;
-
- // NOTE: since we're using a prescaler of 2, we set the
- // divisor frequency to 62.5kHz and divide by 125 above
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
- if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
- return 0;
-}
-
-static struct ves1x93_config alps_bsrv2_config =
-{
- .demod_address = 0x08,
- .xin = 90100000UL,
- .invert_pwm = 0,
-};
-
-static int alps_tdbe2_tuner_set_params(struct dvb_frontend *fe)
-{
- struct dtv_frontend_properties *c = &fe->dtv_property_cache;
- struct budget* budget = (struct budget*) fe->dvb->priv;
- u32 div;
- u8 data[4];
- struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
-
- div = (c->frequency + 35937500 + 31250) / 62500;
-
- data[0] = (div >> 8) & 0x7f;
- data[1] = div & 0xff;
- data[2] = 0x85 | ((div >> 10) & 0x60);
- data[3] = (c->frequency < 174000000 ? 0x88 : c->frequency < 470000000 ? 0x84 : 0x81);
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
- if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
- return 0;
-}
-
-static struct ves1820_config alps_tdbe2_config = {
- .demod_address = 0x09,
- .xin = 57840000UL,
- .invert = 1,
- .selagc = VES1820_SELAGC_SIGNAMPERR,
-};
-
-static int grundig_29504_401_tuner_set_params(struct dvb_frontend *fe)
-{
- struct dtv_frontend_properties *c = &fe->dtv_property_cache;
- struct budget *budget = fe->dvb->priv;
- u8 *tuner_addr = fe->tuner_priv;
- u32 div;
- u8 cfg, cpump, band_select;
- u8 data[4];
- struct i2c_msg msg = { .flags = 0, .buf = data, .len = sizeof(data) };
-
- if (tuner_addr)
- msg.addr = *tuner_addr;
- else
- msg.addr = 0x61;
-
- div = (36125000 + c->frequency) / 166666;
-
- cfg = 0x88;
-
- if (c->frequency < 175000000)
- cpump = 2;
- else if (c->frequency < 390000000)
- cpump = 1;
- else if (c->frequency < 470000000)
- cpump = 2;
- else if (c->frequency < 750000000)
- cpump = 1;
- else
- cpump = 3;
-
- if (c->frequency < 175000000)
- band_select = 0x0e;
- else if (c->frequency < 470000000)
- band_select = 0x05;
- else
- band_select = 0x03;
-
- data[0] = (div >> 8) & 0x7f;
- data[1] = div & 0xff;
- data[2] = ((div >> 10) & 0x60) | cfg;
- data[3] = (cpump << 6) | band_select;
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
- if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
- return 0;
-}
-
-static struct l64781_config grundig_29504_401_config = {
- .demod_address = 0x55,
-};
-
-static struct l64781_config grundig_29504_401_config_activy = {
- .demod_address = 0x54,
-};
-
-static u8 tuner_address_grundig_29504_401_activy = 0x60;
-
-static int grundig_29504_451_tuner_set_params(struct dvb_frontend *fe)
-{
- struct dtv_frontend_properties *c = &fe->dtv_property_cache;
- struct budget* budget = (struct budget*) fe->dvb->priv;
- u32 div;
- u8 data[4];
- struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
-
- div = c->frequency / 125;
- data[0] = (div >> 8) & 0x7f;
- data[1] = div & 0xff;
- data[2] = 0x8e;
- data[3] = 0x00;
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
- if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
- return 0;
-}
-
-static struct tda8083_config grundig_29504_451_config = {
- .demod_address = 0x68,
-};
-
-static int s5h1420_tuner_set_params(struct dvb_frontend *fe)
-{
- struct dtv_frontend_properties *c = &fe->dtv_property_cache;
- struct budget* budget = (struct budget*) fe->dvb->priv;
- u32 div;
- u8 data[4];
- struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
-
- div = c->frequency / 1000;
- data[0] = (div >> 8) & 0x7f;
- data[1] = div & 0xff;
- data[2] = 0xc2;
-
- if (div < 1450)
- data[3] = 0x00;
- else if (div < 1850)
- data[3] = 0x40;
- else if (div < 2000)
- data[3] = 0x80;
- else
- data[3] = 0xc0;
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
- if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
-
- return 0;
-}
-
-static struct s5h1420_config s5h1420_config = {
- .demod_address = 0x53,
- .invert = 1,
- .cdclk_polarity = 1,
-};
-
-static struct tda10086_config tda10086_config = {
- .demod_address = 0x0e,
- .invert = 0,
- .diseqc_tone = 1,
- .xtal_freq = TDA10086_XTAL_16M,
-};
-
-static const struct stv0299_config alps_bsru6_config_activy = {
- .demod_address = 0x68,
- .inittab = alps_bsru6_inittab,
- .mclk = 88000000UL,
- .invert = 1,
- .op0_off = 1,
- .min_delay_ms = 100,
- .set_symbol_rate = alps_bsru6_set_symbol_rate,
-};
-
-static const struct stv0299_config alps_bsbe1_config_activy = {
- .demod_address = 0x68,
- .inittab = alps_bsbe1_inittab,
- .mclk = 88000000UL,
- .invert = 1,
- .op0_off = 1,
- .min_delay_ms = 100,
- .set_symbol_rate = alps_bsbe1_set_symbol_rate,
-};
-
-static int alps_tdhd1_204_request_firmware(struct dvb_frontend *fe, const struct firmware **fw, char *name)
-{
- struct budget *budget = (struct budget *)fe->dvb->priv;
-
- return request_firmware(fw, name, &budget->dev->pci->dev);
-}
-
-
-static int i2c_readreg(struct i2c_adapter *i2c, u8 adr, u8 reg)
-{
- u8 val;
- struct i2c_msg msg[] = {
- { .addr = adr, .flags = 0, .buf = &reg, .len = 1 },
- { .addr = adr, .flags = I2C_M_RD, .buf = &val, .len = 1 }
- };
-
- return (i2c_transfer(i2c, msg, 2) != 2) ? -EIO : val;
-}
-
-static u8 read_pwm(struct budget* budget)
-{
- u8 b = 0xff;
- u8 pwm;
- struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 },
- { .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} };
-
- if ((i2c_transfer(&budget->i2c_adap, msg, 2) != 2) || (pwm == 0xff))
- pwm = 0x48;
-
- return pwm;
-}
-
-static struct stv090x_config tt1600_stv090x_config = {
- .device = STV0903,
- .demod_mode = STV090x_SINGLE,
- .clk_mode = STV090x_CLK_EXT,
-
- .xtal = 13500000,
- .address = 0x68,
-
- .ts1_mode = STV090x_TSMODE_DVBCI,
- .ts2_mode = STV090x_TSMODE_SERIAL_CONTINUOUS,
-
- .repeater_level = STV090x_RPTLEVEL_16,
-
- .tuner_init = NULL,
- .tuner_sleep = NULL,
- .tuner_set_mode = NULL,
- .tuner_set_frequency = NULL,
- .tuner_get_frequency = NULL,
- .tuner_set_bandwidth = NULL,
- .tuner_get_bandwidth = NULL,
- .tuner_set_bbgain = NULL,
- .tuner_get_bbgain = NULL,
- .tuner_set_refclk = NULL,
- .tuner_get_status = NULL,
-};
-
-static struct stv6110x_config tt1600_stv6110x_config = {
- .addr = 0x60,
- .refclk = 27000000,
- .clk_div = 2,
-};
-
-static struct isl6423_config tt1600_isl6423_config = {
- .current_max = SEC_CURRENT_515m,
- .curlim = SEC_CURRENT_LIM_ON,
- .mod_extern = 1,
- .addr = 0x08,
-};
-
-static void frontend_init(struct budget *budget)
-{
- (void)alps_bsbe1_config; /* avoid warning */
-
- switch(budget->dev->pci->subsystem_device) {
- case 0x1003: // Hauppauge/TT Nova budget (stv0299/ALPS BSRU6(tsa5059) OR ves1893/ALPS BSRV2(sp5659))
- case 0x1013:
- // try the ALPS BSRV2 first of all
- budget->dvb_frontend = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &budget->i2c_adap);
- if (budget->dvb_frontend) {
- budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
- budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
- budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst;
- budget->dvb_frontend->ops.set_tone = budget_set_tone;
- break;
- }
-
- // try the ALPS BSRU6 now
- budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config, &budget->i2c_adap);
- if (budget->dvb_frontend) {
- budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
- budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
- if (budget->dev->pci->subsystem_device == 0x1003 && diseqc_method == 0) {
- budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
- budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst;
- budget->dvb_frontend->ops.set_tone = budget_set_tone;
- }
- break;
- }
- break;
-
- case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659))
-
- budget->dvb_frontend = dvb_attach(ves1820_attach, &alps_tdbe2_config, &budget->i2c_adap, read_pwm(budget));
- if (budget->dvb_frontend) {
- budget->dvb_frontend->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
- break;
- }
- break;
-
- case 0x1005: // Hauppauge/TT Nova-T budget (L64781/Grundig 29504-401(tsa5060))
-
- budget->dvb_frontend = dvb_attach(l64781_attach, &grundig_29504_401_config, &budget->i2c_adap);
- if (budget->dvb_frontend) {
- budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
- budget->dvb_frontend->tuner_priv = NULL;
- break;
- }
- break;
-
- case 0x4f52: /* Cards based on Philips Semi Sylt PCI ref. design */
- budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config, &budget->i2c_adap);
- if (budget->dvb_frontend) {
- printk(KERN_INFO "budget: tuner ALPS BSRU6 in Philips Semi. Sylt detected\n");
- budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
- budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
- break;
- }
- break;
-
- case 0x4f60: /* Fujitsu Siemens Activy Budget-S PCI rev AL (stv0299/tsa5059) */
- {
- int subtype = i2c_readreg(&budget->i2c_adap, 0x50, 0x67);
-
- if (subtype < 0)
- break;
- /* fixme: find a better way to identify the card */
- if (subtype < 0x36) {
- /* assume ALPS BSRU6 */
- budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config_activy, &budget->i2c_adap);
- if (budget->dvb_frontend) {
- printk(KERN_INFO "budget: tuner ALPS BSRU6 detected\n");
- budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
- budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
- budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage;
- budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
- break;
- }
- } else {
- /* assume ALPS BSBE1 */
- /* reset tuner */
- saa7146_setgpio(budget->dev, 3, SAA7146_GPIO_OUTLO);
- msleep(50);
- saa7146_setgpio(budget->dev, 3, SAA7146_GPIO_OUTHI);
- msleep(250);
- budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsbe1_config_activy, &budget->i2c_adap);
- if (budget->dvb_frontend) {
- printk(KERN_INFO "budget: tuner ALPS BSBE1 detected\n");
- budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
- budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
- budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage;
- budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
- break;
- }
- }
- break;
- }
-
- case 0x4f61: // Fujitsu Siemens Activy Budget-S PCI rev GR (tda8083/Grundig 29504-451(tsa5522))
- budget->dvb_frontend = dvb_attach(tda8083_attach, &grundig_29504_451_config, &budget->i2c_adap);
- if (budget->dvb_frontend) {
- budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
- budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage;
- budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
- }
- break;
-
- case 0x5f60: /* Fujitsu Siemens Activy Budget-T PCI rev AL (tda10046/ALPS TDHD1-204A) */
- budget->dvb_frontend = dvb_attach(tda10046_attach, &alps_tdhd1_204a_config, &budget->i2c_adap);
- if (budget->dvb_frontend) {
- budget->dvb_frontend->ops.tuner_ops.set_params = alps_tdhd1_204a_tuner_set_params;
- budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
- }
- break;
-
- case 0x5f61: /* Fujitsu Siemens Activy Budget-T PCI rev GR (L64781/Grundig 29504-401(tsa5060)) */
- budget->dvb_frontend = dvb_attach(l64781_attach, &grundig_29504_401_config_activy, &budget->i2c_adap);
- if (budget->dvb_frontend) {
- budget->dvb_frontend->tuner_priv = &tuner_address_grundig_29504_401_activy;
- budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
- }
- break;
-
- case 0x1016: // Hauppauge/TT Nova-S SE (samsung s5h1420/????(tda8260))
- {
- struct dvb_frontend *fe;
-
- fe = dvb_attach(s5h1420_attach, &s5h1420_config, &budget->i2c_adap);
- if (fe) {
- fe->ops.tuner_ops.set_params = s5h1420_tuner_set_params;
- budget->dvb_frontend = fe;
- if (dvb_attach(lnbp21_attach, fe, &budget->i2c_adap,
- 0, 0) == NULL) {
- printk("%s: No LNBP21 found!\n", __func__);
- goto error_out;
- }
- break;
- }
- }
- fallthrough;
- case 0x1018: // TT Budget-S-1401 (philips tda10086/philips tda8262)
- {
- struct dvb_frontend *fe;
-
- // gpio2 is connected to CLB - reset it + leave it high
- saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTLO);
- msleep(1);
- saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTHI);
- msleep(1);
-
- fe = dvb_attach(tda10086_attach, &tda10086_config, &budget->i2c_adap);
- if (fe) {
- budget->dvb_frontend = fe;
- if (dvb_attach(tda826x_attach, fe, 0x60,
- &budget->i2c_adap, 0) == NULL)
- printk("%s: No tda826x found!\n", __func__);
- if (dvb_attach(lnbp21_attach, fe,
- &budget->i2c_adap, 0, 0) == NULL) {
- printk("%s: No LNBP21 found!\n", __func__);
- goto error_out;
- }
- break;
- }
- }
- fallthrough;
-
- case 0x101c: { /* TT S2-1600 */
- const struct stv6110x_devctl *ctl;
- saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTLO);
- msleep(50);
- saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTHI);
- msleep(250);
-
- budget->dvb_frontend = dvb_attach(stv090x_attach,
- &tt1600_stv090x_config,
- &budget->i2c_adap,
- STV090x_DEMODULATOR_0);
-
- if (budget->dvb_frontend) {
-
- ctl = dvb_attach(stv6110x_attach,
- budget->dvb_frontend,
- &tt1600_stv6110x_config,
- &budget->i2c_adap);
-
- if (ctl) {
- tt1600_stv090x_config.tuner_init = ctl->tuner_init;
- tt1600_stv090x_config.tuner_sleep = ctl->tuner_sleep;
- tt1600_stv090x_config.tuner_set_mode = ctl->tuner_set_mode;
- tt1600_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency;
- tt1600_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency;
- tt1600_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth;
- tt1600_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth;
- tt1600_stv090x_config.tuner_set_bbgain = ctl->tuner_set_bbgain;
- tt1600_stv090x_config.tuner_get_bbgain = ctl->tuner_get_bbgain;
- tt1600_stv090x_config.tuner_set_refclk = ctl->tuner_set_refclk;
- tt1600_stv090x_config.tuner_get_status = ctl->tuner_get_status;
-
- /* call the init function once to initialize
- tuner's clock output divider and demod's
- master clock */
- if (budget->dvb_frontend->ops.init)
- budget->dvb_frontend->ops.init(budget->dvb_frontend);
-
- if (dvb_attach(isl6423_attach,
- budget->dvb_frontend,
- &budget->i2c_adap,
- &tt1600_isl6423_config) == NULL) {
- printk(KERN_ERR "%s: No Intersil ISL6423 found!\n", __func__);
- goto error_out;
- }
- } else {
- printk(KERN_ERR "%s: No STV6110(A) Silicon Tuner found!\n", __func__);
- goto error_out;
- }
- }
- }
- break;
-
- case 0x1020: { /* Omicom S2 */
- const struct stv6110x_devctl *ctl;
- saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTLO);
- msleep(50);
- saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTHI);
- msleep(250);
-
- budget->dvb_frontend = dvb_attach(stv090x_attach,
- &tt1600_stv090x_config,
- &budget->i2c_adap,
- STV090x_DEMODULATOR_0);
-
- if (budget->dvb_frontend) {
- printk(KERN_INFO "budget: Omicom S2 detected\n");
-
- ctl = dvb_attach(stv6110x_attach,
- budget->dvb_frontend,
- &tt1600_stv6110x_config,
- &budget->i2c_adap);
-
- if (ctl) {
- tt1600_stv090x_config.tuner_init = ctl->tuner_init;
- tt1600_stv090x_config.tuner_sleep = ctl->tuner_sleep;
- tt1600_stv090x_config.tuner_set_mode = ctl->tuner_set_mode;
- tt1600_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency;
- tt1600_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency;
- tt1600_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth;
- tt1600_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth;
- tt1600_stv090x_config.tuner_set_bbgain = ctl->tuner_set_bbgain;
- tt1600_stv090x_config.tuner_get_bbgain = ctl->tuner_get_bbgain;
- tt1600_stv090x_config.tuner_set_refclk = ctl->tuner_set_refclk;
- tt1600_stv090x_config.tuner_get_status = ctl->tuner_get_status;
-
- /* call the init function once to initialize
- tuner's clock output divider and demod's
- master clock */
- if (budget->dvb_frontend->ops.init)
- budget->dvb_frontend->ops.init(budget->dvb_frontend);
-
- if (dvb_attach(lnbh24_attach,
- budget->dvb_frontend,
- &budget->i2c_adap,
- LNBH24_PCL | LNBH24_TTX,
- LNBH24_TEN, 0x14>>1) == NULL) {
- printk(KERN_ERR
- "No LNBH24 found!\n");
- goto error_out;
- }
- } else {
- printk(KERN_ERR "%s: No STV6110(A) Silicon Tuner found!\n", __func__);
- goto error_out;
- }
- }
- }
- break;
- }
-
- if (budget->dvb_frontend == NULL) {
- printk("budget: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
- budget->dev->pci->vendor,
- budget->dev->pci->device,
- budget->dev->pci->subsystem_vendor,
- budget->dev->pci->subsystem_device);
- } else {
- if (dvb_register_frontend(&budget->dvb_adapter, budget->dvb_frontend))
- goto error_out;
- }
- return;
-
-error_out:
- printk("budget: Frontend registration failed!\n");
- dvb_frontend_detach(budget->dvb_frontend);
- budget->dvb_frontend = NULL;
- return;
-}
-
-static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info)
-{
- struct budget *budget = NULL;
- int err;
-
- budget = kmalloc(sizeof(struct budget), GFP_KERNEL);
- if( NULL == budget ) {
- return -ENOMEM;
- }
-
- dprintk(2, "dev:%p, info:%p, budget:%p\n", dev, info, budget);
-
- dev->ext_priv = budget;
-
- err = ttpci_budget_init(budget, dev, info, THIS_MODULE, adapter_nr);
- if (err) {
- printk("==> failed\n");
- kfree (budget);
- return err;
- }
-
- budget->dvb_adapter.priv = budget;
- frontend_init(budget);
-
- ttpci_budget_init_hooks(budget);
-
- return 0;
-}
-
-static int budget_detach (struct saa7146_dev* dev)
-{
- struct budget *budget = (struct budget*) dev->ext_priv;
- int err;
-
- if (budget->dvb_frontend) {
- dvb_unregister_frontend(budget->dvb_frontend);
- dvb_frontend_detach(budget->dvb_frontend);
- }
-
- err = ttpci_budget_deinit (budget);
-
- kfree (budget);
- dev->ext_priv = NULL;
-
- return err;
-}
-
-static struct saa7146_extension budget_extension;
-
-MAKE_BUDGET_INFO(ttbs, "TT-Budget/WinTV-NOVA-S PCI", BUDGET_TT);
-MAKE_BUDGET_INFO(ttbc, "TT-Budget/WinTV-NOVA-C PCI", BUDGET_TT);
-MAKE_BUDGET_INFO(ttbt, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT);
-MAKE_BUDGET_INFO(satel, "SATELCO Multimedia PCI", BUDGET_TT_HW_DISEQC);
-MAKE_BUDGET_INFO(ttbs1401, "TT-Budget-S-1401 PCI", BUDGET_TT);
-MAKE_BUDGET_INFO(tt1600, "TT-Budget S2-1600 PCI", BUDGET_TT);
-MAKE_BUDGET_INFO(fsacs0, "Fujitsu Siemens Activy Budget-S PCI (rev GR/grundig frontend)", BUDGET_FS_ACTIVY);
-MAKE_BUDGET_INFO(fsacs1, "Fujitsu Siemens Activy Budget-S PCI (rev AL/alps frontend)", BUDGET_FS_ACTIVY);
-MAKE_BUDGET_INFO(fsact, "Fujitsu Siemens Activy Budget-T PCI (rev GR/Grundig frontend)", BUDGET_FS_ACTIVY);
-MAKE_BUDGET_INFO(fsact1, "Fujitsu Siemens Activy Budget-T PCI (rev AL/ALPS TDHD1-204A)", BUDGET_FS_ACTIVY);
-MAKE_BUDGET_INFO(omicom, "Omicom S2 PCI", BUDGET_TT);
-MAKE_BUDGET_INFO(sylt, "Philips Semi Sylt PCI", BUDGET_TT_HW_DISEQC);
-
-static const struct pci_device_id pci_tbl[] = {
- MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1003),
- MAKE_EXTENSION_PCI(ttbc, 0x13c2, 0x1004),
- MAKE_EXTENSION_PCI(ttbt, 0x13c2, 0x1005),
- MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013),
- MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1016),
- MAKE_EXTENSION_PCI(ttbs1401, 0x13c2, 0x1018),
- MAKE_EXTENSION_PCI(tt1600, 0x13c2, 0x101c),
- MAKE_EXTENSION_PCI(fsacs1,0x1131, 0x4f60),
- MAKE_EXTENSION_PCI(fsacs0,0x1131, 0x4f61),
- MAKE_EXTENSION_PCI(fsact1, 0x1131, 0x5f60),
- MAKE_EXTENSION_PCI(fsact, 0x1131, 0x5f61),
- MAKE_EXTENSION_PCI(omicom, 0x14c4, 0x1020),
- MAKE_EXTENSION_PCI(sylt, 0x1131, 0x4f52),
- {
- .vendor = 0,
- }
-};
-
-MODULE_DEVICE_TABLE(pci, pci_tbl);
-
-static struct saa7146_extension budget_extension = {
- .name = "budget dvb",
- .flags = SAA7146_USE_I2C_IRQ,
-
- .module = THIS_MODULE,
- .pci_tbl = pci_tbl,
- .attach = budget_attach,
- .detach = budget_detach,
-
- .irq_mask = MASK_10,
- .irq_func = ttpci_budget_irq10_handler,
-};
-
-static int __init budget_init(void)
-{
- return saa7146_register_extension(&budget_extension);
-}
-
-static void __exit budget_exit(void)
-{
- saa7146_unregister_extension(&budget_extension);
-}
-
-module_init(budget_init);
-module_exit(budget_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others");
-MODULE_DESCRIPTION("driver for the SAA7146 based so-called budget PCI DVB cards by Siemens, Technotrend, Hauppauge");
diff --git a/drivers/media/pci/ttpci/budget.h b/drivers/media/pci/ttpci/budget.h
deleted file mode 100644
index bd87432e6cde..000000000000
--- a/drivers/media/pci/ttpci/budget.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-
-#ifndef __BUDGET_DVB__
-#define __BUDGET_DVB__
-
-#include <media/dvb_frontend.h>
-#include <media/dvbdev.h>
-#include <media/demux.h>
-#include <media/dvb_demux.h>
-#include <media/dmxdev.h>
-#include <media/dvb_net.h>
-
-#include <linux/module.h>
-#include <linux/mutex.h>
-
-#include <media/drv-intf/saa7146.h>
-
-extern int budget_debug;
-
-#ifdef dprintk
-#undef dprintk
-#endif
-
-#define dprintk(level, fmt, arg...) do { \
- if (level & budget_debug) \
- printk(KERN_DEBUG KBUILD_MODNAME ": %s(): " fmt, \
- __func__, ##arg); \
-} while (0)
-
-#define TS_SIZE 188
-
-struct budget_info {
- char *name;
- int type;
-};
-
-/* place to store all the necessary device information */
-struct budget {
-
- /* devices */
- struct dvb_device dvb_dev;
- struct dvb_net dvb_net;
-
- struct saa7146_dev *dev;
-
- struct i2c_adapter i2c_adap;
- struct budget_info *card;
-
- unsigned char *grabbing;
- struct saa7146_pgtable pt;
-
- struct tasklet_struct fidb_tasklet;
- struct tasklet_struct vpe_tasklet;
-
- struct dmxdev dmxdev;
- struct dvb_demux demux;
-
- struct dmx_frontend hw_frontend;
- struct dmx_frontend mem_frontend;
-
- int ci_present;
- int video_port;
-
- u32 buffer_width;
- u32 buffer_height;
- u32 buffer_size;
- u32 buffer_warning_threshold;
- u32 buffer_warnings;
- unsigned long buffer_warning_time;
-
- u32 ttbp;
- int feeding;
-
- spinlock_t feedlock;
-
- spinlock_t debilock;
-
- struct dvb_adapter dvb_adapter;
- struct dvb_frontend *dvb_frontend;
- int (*read_fe_status)(struct dvb_frontend *fe, enum fe_status *status);
- int fe_synced;
-
- void *priv;
-};
-
-#define MAKE_BUDGET_INFO(x_var,x_name,x_type) \
-static struct budget_info x_var ## _info = { \
- .name=x_name, \
- .type=x_type }; \
-static struct saa7146_pci_extension_data x_var = { \
- .ext_priv = &x_var ## _info, \
- .ext = &budget_extension };
-
-#define BUDGET_TT 0
-#define BUDGET_TT_HW_DISEQC 1
-#define BUDGET_PATCH 3
-#define BUDGET_FS_ACTIVY 4
-#define BUDGET_CIN1200S 5
-#define BUDGET_CIN1200C 6
-#define BUDGET_CIN1200T 7
-#define BUDGET_KNC1S 8
-#define BUDGET_KNC1C 9
-#define BUDGET_KNC1T 10
-#define BUDGET_KNC1SP 11
-#define BUDGET_KNC1CP 12
-#define BUDGET_KNC1TP 13
-#define BUDGET_TVSTAR 14
-#define BUDGET_CIN1200C_MK3 15
-#define BUDGET_KNC1C_MK3 16
-#define BUDGET_KNC1CP_MK3 17
-#define BUDGET_KNC1S2 18
-#define BUDGET_KNC1C_TDA10024 19
-
-#define BUDGET_VIDEO_PORTA 0
-#define BUDGET_VIDEO_PORTB 1
-
-extern int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
- struct saa7146_pci_extension_data *info,
- struct module *owner, short *adapter_nums);
-extern void ttpci_budget_init_hooks(struct budget *budget);
-extern int ttpci_budget_deinit(struct budget *budget);
-extern void ttpci_budget_irq10_handler(struct saa7146_dev *dev, u32 * isr);
-extern void ttpci_budget_set_video_port(struct saa7146_dev *dev, int video_port);
-extern int ttpci_budget_debiread(struct budget *budget, u32 config, int addr, int count,
- int uselocks, int nobusyloop);
-extern int ttpci_budget_debiwrite(struct budget *budget, u32 config, int addr, int count, u32 value,
- int uselocks, int nobusyloop);
-
-#endif
diff --git a/drivers/media/pci/zoran/Kconfig b/drivers/media/pci/zoran/Kconfig
new file mode 100644
index 000000000000..3fb3e27e04a8
--- /dev/null
+++ b/drivers/media/pci/zoran/Kconfig
@@ -0,0 +1,74 @@
+config VIDEO_ZORAN
+ tristate "Zoran ZR36057/36067 Video For Linux (Deprecated)"
+ depends on PCI && I2C_ALGOBIT && VIDEO_DEV
+ depends on !ALPHA
+ depends on DEBUG_FS
+ select VIDEOBUF2_DMA_CONTIG
+ select VIDEO_ADV7170 if VIDEO_ZORAN_LML33R10
+ select VIDEO_ADV7175 if VIDEO_ZORAN_DC10 || VIDEO_ZORAN_DC30
+ select VIDEO_BT819 if VIDEO_ZORAN_LML33
+ select VIDEO_BT856 if VIDEO_ZORAN_LML33 || VIDEO_ZORAN_AVS6EYES
+ select VIDEO_BT866 if VIDEO_ZORAN_AVS6EYES
+ select VIDEO_KS0127 if VIDEO_ZORAN_AVS6EYES
+ select VIDEO_SAA711X if VIDEO_ZORAN_BUZ || VIDEO_ZORAN_LML33R10
+ select VIDEO_SAA7110 if VIDEO_ZORAN_DC10
+ select VIDEO_SAA7185 if VIDEO_ZORAN_BUZ
+ select VIDEO_VPX3220 if VIDEO_ZORAN_DC30
+ help
+ Say Y for support for MJPEG capture cards based on the Zoran
+ 36057/36067 PCI controller chipset. This includes the Iomega
+ Buz, Pinnacle DC10+ and the Linux Media Labs LML33. There is
+ a driver homepage at <http://mjpeg.sf.net/driver-zoran/>. For
+ more information, check <file:Documentation/driver-api/media/drivers/zoran.rst>.
+
+ To compile this driver as a module, choose M here: the
+ module will be called zr36067.
+
+config VIDEO_ZORAN_DC30
+ bool "Pinnacle/Miro DC30(+) support"
+ depends on VIDEO_ZORAN
+ help
+ Support for the Pinnacle/Miro DC30(+) MJPEG capture/playback
+ card. This also supports really old DC10 cards based on the
+ zr36050 MJPEG codec and zr36016 VFE.
+
+config VIDEO_ZORAN_ZR36060
+ bool "Zoran ZR36060"
+ depends on VIDEO_ZORAN
+ help
+ Say Y to support Zoran boards based on 36060 chips.
+ This includes Iomega Buz, Pinnacle DC10, Linux media Labs 33
+ and 33 R10 and AverMedia 6 boards.
+
+config VIDEO_ZORAN_BUZ
+ bool "Iomega Buz support"
+ depends on VIDEO_ZORAN_ZR36060
+ help
+ Support for the Iomega Buz MJPEG capture/playback card.
+
+config VIDEO_ZORAN_DC10
+ bool "Pinnacle/Miro DC10(+) support"
+ depends on VIDEO_ZORAN_ZR36060
+ help
+ Support for the Pinnacle/Miro DC10(+) MJPEG capture/playback
+ card.
+
+config VIDEO_ZORAN_LML33
+ bool "Linux Media Labs LML33 support"
+ depends on VIDEO_ZORAN_ZR36060
+ help
+ Support for the Linux Media Labs LML33 MJPEG capture/playback
+ card.
+
+config VIDEO_ZORAN_LML33R10
+ bool "Linux Media Labs LML33R10 support"
+ depends on VIDEO_ZORAN_ZR36060
+ help
+ support for the Linux Media Labs LML33R10 MJPEG capture/playback
+ card.
+
+config VIDEO_ZORAN_AVS6EYES
+ bool "AverMedia 6 Eyes support"
+ depends on VIDEO_ZORAN_ZR36060
+ help
+ Support for the AverMedia 6 Eyes video surveillance card.
diff --git a/drivers/media/pci/zoran/Makefile b/drivers/media/pci/zoran/Makefile
new file mode 100644
index 000000000000..9603bac0195c
--- /dev/null
+++ b/drivers/media/pci/zoran/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0
+zr36067-objs := zoran_device.o \
+ zoran_driver.o zoran_card.o videocodec.o
+
+obj-$(CONFIG_VIDEO_ZORAN) += zr36067.o
+zr36067-$(CONFIG_VIDEO_ZORAN_DC30) += zr36050.o zr36016.o
+zr36067-$(CONFIG_VIDEO_ZORAN_ZR36060) += zr36060.o
diff --git a/drivers/media/pci/zoran/videocodec.c b/drivers/media/pci/zoran/videocodec.c
new file mode 100644
index 000000000000..8efc5e06b0f7
--- /dev/null
+++ b/drivers/media/pci/zoran/videocodec.c
@@ -0,0 +1,278 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * VIDEO MOTION CODECs internal API for video devices
+ *
+ * Interface for MJPEG (and maybe later MPEG/WAVELETS) codec's
+ * bound to a master device.
+ *
+ * (c) 2002 Wolfgang Scherr <scherr@net4you.at>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+
+#include "videocodec.h"
+
+struct attached_list {
+ struct videocodec *codec;
+ struct attached_list *next;
+};
+
+struct codec_list {
+ const struct videocodec *codec;
+ int attached;
+ struct attached_list *list;
+ struct codec_list *next;
+};
+
+static struct codec_list *codeclist_top;
+
+/* ================================================= */
+/* function prototypes of the master/slave interface */
+/* ================================================= */
+
+struct videocodec *videocodec_attach(struct videocodec_master *master)
+{
+ struct codec_list *h = codeclist_top;
+ struct zoran *zr;
+ struct attached_list *a, *ptr;
+ struct videocodec *codec;
+ int res;
+
+ if (!master) {
+ pr_err("%s: no data\n", __func__);
+ return NULL;
+ }
+
+ zr = videocodec_master_to_zoran(master);
+
+ zrdev_dbg(zr, "%s: '%s', flags %lx, magic %lx\n", __func__,
+ master->name, master->flags, master->magic);
+
+ if (!h) {
+ zrdev_err(zr, "%s: no device available\n", __func__);
+ return NULL;
+ }
+
+ while (h) {
+ // attach only if the slave has at least the flags
+ // expected by the master
+ if ((master->flags & h->codec->flags) == master->flags) {
+ zrdev_dbg(zr, "%s: try '%s'\n", __func__, h->codec->name);
+
+ codec = kmemdup(h->codec, sizeof(struct videocodec), GFP_KERNEL);
+ if (!codec)
+ goto out_kfree;
+
+ res = strlen(codec->name);
+ snprintf(codec->name + res, sizeof(codec->name) - res, "[%d]", h->attached);
+ codec->master_data = master;
+ res = codec->setup(codec);
+ if (res == 0) {
+ zrdev_dbg(zr, "%s: '%s'\n", __func__, codec->name);
+ ptr = kzalloc(sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ goto out_kfree;
+ ptr->codec = codec;
+
+ a = h->list;
+ if (!a) {
+ h->list = ptr;
+ zrdev_dbg(zr, "videocodec: first element\n");
+ } else {
+ while (a->next)
+ a = a->next; // find end
+ a->next = ptr;
+ zrdev_dbg(zr, "videocodec: in after '%s'\n",
+ h->codec->name);
+ }
+
+ h->attached += 1;
+ return codec;
+ }
+ kfree(codec);
+ }
+ h = h->next;
+ }
+
+ zrdev_err(zr, "%s: no codec found!\n", __func__);
+ return NULL;
+
+ out_kfree:
+ kfree(codec);
+ return NULL;
+}
+
+int videocodec_detach(struct videocodec *codec)
+{
+ struct codec_list *h = codeclist_top;
+ struct zoran *zr;
+ struct attached_list *a, *prev;
+ int res;
+
+ if (!codec) {
+ pr_err("%s: no data\n", __func__);
+ return -EINVAL;
+ }
+
+ zr = videocodec_to_zoran(codec);
+
+ zrdev_dbg(zr, "%s: '%s', type: %x, flags %lx, magic %lx\n", __func__,
+ codec->name, codec->type, codec->flags, codec->magic);
+
+ if (!h) {
+ zrdev_err(zr, "%s: no device left...\n", __func__);
+ return -ENXIO;
+ }
+
+ while (h) {
+ a = h->list;
+ prev = NULL;
+ while (a) {
+ if (codec == a->codec) {
+ res = a->codec->unset(a->codec);
+ if (res >= 0) {
+ zrdev_dbg(zr, "%s: '%s'\n", __func__,
+ a->codec->name);
+ a->codec->master_data = NULL;
+ } else {
+ zrdev_err(zr, "%s: '%s'\n", __func__, a->codec->name);
+ a->codec->master_data = NULL;
+ }
+ if (!prev) {
+ h->list = a->next;
+ zrdev_dbg(zr, "videocodec: delete first\n");
+ } else {
+ prev->next = a->next;
+ zrdev_dbg(zr, "videocodec: delete middle\n");
+ }
+ kfree(a->codec);
+ kfree(a);
+ h->attached -= 1;
+ return 0;
+ }
+ prev = a;
+ a = a->next;
+ }
+ h = h->next;
+ }
+
+ zrdev_err(zr, "%s: given codec not found!\n", __func__);
+ return -EINVAL;
+}
+
+int videocodec_register(const struct videocodec *codec)
+{
+ struct codec_list *ptr, *h = codeclist_top;
+ struct zoran *zr;
+
+ if (!codec) {
+ pr_err("%s: no data!\n", __func__);
+ return -EINVAL;
+ }
+
+ zr = videocodec_to_zoran((struct videocodec *)codec);
+
+ zrdev_dbg(zr,
+ "videocodec: register '%s', type: %x, flags %lx, magic %lx\n",
+ codec->name, codec->type, codec->flags, codec->magic);
+
+ ptr = kzalloc(sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ return -ENOMEM;
+ ptr->codec = codec;
+
+ if (!h) {
+ codeclist_top = ptr;
+ zrdev_dbg(zr, "videocodec: hooked in as first element\n");
+ } else {
+ while (h->next)
+ h = h->next; // find the end
+ h->next = ptr;
+ zrdev_dbg(zr, "videocodec: hooked in after '%s'\n",
+ h->codec->name);
+ }
+
+ return 0;
+}
+
+int videocodec_unregister(const struct videocodec *codec)
+{
+ struct codec_list *prev = NULL, *h = codeclist_top;
+ struct zoran *zr;
+
+ if (!codec) {
+ pr_err("%s: no data!\n", __func__);
+ return -EINVAL;
+ }
+
+ zr = videocodec_to_zoran((struct videocodec *)codec);
+
+ zrdev_dbg(zr,
+ "videocodec: unregister '%s', type: %x, flags %lx, magic %lx\n",
+ codec->name, codec->type, codec->flags, codec->magic);
+
+ if (!h) {
+ zrdev_err(zr, "%s: no device left...\n", __func__);
+ return -ENXIO;
+ }
+
+ while (h) {
+ if (codec == h->codec) {
+ if (h->attached) {
+ zrdev_err(zr, "videocodec: '%s' is used\n",
+ h->codec->name);
+ return -EBUSY;
+ }
+ zrdev_dbg(zr, "videocodec: unregister '%s' is ok.\n",
+ h->codec->name);
+ if (!prev) {
+ codeclist_top = h->next;
+ zrdev_dbg(zr,
+ "videocodec: delete first element\n");
+ } else {
+ prev->next = h->next;
+ zrdev_dbg(zr,
+ "videocodec: delete middle element\n");
+ }
+ kfree(h);
+ return 0;
+ }
+ prev = h;
+ h = h->next;
+ }
+
+ zrdev_err(zr, "%s: given codec not found!\n", __func__);
+ return -EINVAL;
+}
+
+int videocodec_debugfs_show(struct seq_file *m)
+{
+ struct codec_list *h = codeclist_top;
+ struct attached_list *a;
+
+ seq_puts(m, "<S>lave or attached <M>aster name type flags magic ");
+ seq_puts(m, "(connected as)\n");
+
+ while (h) {
+ seq_printf(m, "S %32s %04x %08lx %08lx (TEMPLATE)\n",
+ h->codec->name, h->codec->type,
+ h->codec->flags, h->codec->magic);
+ a = h->list;
+ while (a) {
+ seq_printf(m, "M %32s %04x %08lx %08lx (%s)\n",
+ a->codec->master_data->name,
+ a->codec->master_data->type,
+ a->codec->master_data->flags,
+ a->codec->master_data->magic,
+ a->codec->name);
+ a = a->next;
+ }
+ h = h->next;
+ }
+
+ return 0;
+}
diff --git a/drivers/media/pci/zoran/videocodec.h b/drivers/media/pci/zoran/videocodec.h
new file mode 100644
index 000000000000..6b69f69667f9
--- /dev/null
+++ b/drivers/media/pci/zoran/videocodec.h
@@ -0,0 +1,325 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * VIDEO MOTION CODECs internal API for video devices
+ *
+ * Interface for MJPEG (and maybe later MPEG/WAVELETS) codec's
+ * bound to a master device.
+ *
+ * (c) 2002 Wolfgang Scherr <scherr@net4you.at>
+ */
+
+/* =================== */
+/* general description */
+/* =================== */
+
+/*
+ * Should ease the (re-)usage of drivers supporting cards with (different)
+ * video codecs. The codecs register to this module their functionality,
+ * and the processors (masters) can attach to them if they fit.
+ *
+ * The codecs are typically have a "strong" binding to their master - so I
+ * don't think it makes sense to have a full blown interfacing as with e.g.
+ * i2c. If you have an other opinion, let's discuss & implement it :-)))
+ *
+ * Usage:
+ *
+ * The slave has just to setup the videocodec structure and use two functions:
+ * videocodec_register(codecdata);
+ * videocodec_unregister(codecdata);
+ * The best is just calling them at module (de-)initialisation.
+ *
+ * The master sets up the structure videocodec_master and calls:
+ * codecdata=videocodec_attach(master_codecdata);
+ * videocodec_detach(codecdata);
+ *
+ * The slave is called during attach/detach via functions setup previously
+ * during register. At that time, the master_data pointer is set up
+ * and the slave can access any io registers of the master device (in the case
+ * the slave is bound to it). Otherwise it doesn't need this functions and
+ * therefor they may not be initialized.
+ *
+ * The other functions are just for convenience, as they are for sure used by
+ * most/all of the codecs. The last ones may be omitted, too.
+ *
+ * See the structure declaration below for more information and which data has
+ * to be set up for the master and the slave.
+ *
+ * ----------------------------------------------------------------------------
+ * The master should have "knowledge" of the slave and vice versa. So the data
+ * structures sent to/from slave via set_data/get_data set_image/get_image are
+ * device dependent and vary between MJPEG/MPEG/WAVELET/... devices. (!!!!)
+ * ----------------------------------------------------------------------------
+ */
+
+/* ========================================== */
+/* description of the videocodec_io structure */
+/* ========================================== */
+
+/*
+ * ==== master setup ====
+ * name -> name of the device structure for reference and debugging
+ * master_data -> data ref. for the master (e.g. the zr36055,57,67)
+ * readreg -> ref. to read-fn from register (setup by master, used by slave)
+ * writereg -> ref. to write-fn to register (setup by master, used by slave)
+ * this two functions do the lowlevel I/O job
+ *
+ * ==== slave functionality setup ====
+ * slave_data -> data ref. for the slave (e.g. the zr36050,60)
+ * check -> fn-ref. checks availability of an device, returns -EIO on failure or
+ * the type on success
+ * this makes espcecially sense if a driver module supports more than
+ * one codec which may be quite similar to access, nevertheless it
+ * is good for a first functionality check
+ *
+ * -- main functions you always need for compression/decompression --
+ *
+ * set_mode -> this fn-ref. resets the entire codec, and sets up the mode
+ * with the last defined norm/size (or device default if not
+ * available) - it returns 0 if the mode is possible
+ * set_size -> this fn-ref. sets the norm and image size for
+ * compression/decompression (returns 0 on success)
+ * the norm param is defined in videodev2.h (V4L2_STD_*)
+ *
+ * additional setup may be available, too - but the codec should work with
+ * some default values even without this
+ *
+ * set_data -> sets device-specific data (tables, quality etc.)
+ * get_data -> query device-specific data (tables, quality etc.)
+ *
+ * if the device delivers interrupts, they may be setup/handled here
+ * setup_interrupt -> codec irq setup (not needed for 36050/60)
+ * handle_interrupt -> codec irq handling (not needed for 36050/60)
+
+ * if the device delivers pictures, they may be handled here
+ * put_image -> puts image data to the codec (not needed for 36050/60)
+ * get_image -> gets image data from the codec (not needed for 36050/60)
+ * the calls include frame numbers and flags (even/odd/...)
+ * if needed and a flag which allows blocking until its ready
+ */
+
+/* ============== */
+/* user interface */
+/* ============== */
+
+/*
+ * Currently there is only a information display planned, as the layer
+ * is not visible for the user space at all.
+ *
+ * Information is available via procfs. The current entry is "/proc/videocodecs"
+ * but it makes sense to "hide" it in the /proc/video tree of v4l(2) --TODO--.
+ *
+ * A example for such an output is:
+ *
+ * <S>lave or attached <M>aster name type flags magic (connected as)
+ * S zr36050 0002 0000d001 00000000 (TEMPLATE)
+ * M zr36055[0] 0001 0000c001 00000000 (zr36050[0])
+ * M zr36055[1] 0001 0000c001 00000000 (zr36050[1])
+ */
+
+/* =============================================== */
+/* special defines for the videocodec_io structure */
+/* =============================================== */
+
+#ifndef __LINUX_VIDEOCODEC_H
+#define __LINUX_VIDEOCODEC_H
+
+#include <linux/debugfs.h>
+#include <linux/videodev2.h>
+
+#define CODEC_DO_COMPRESSION 0
+#define CODEC_DO_EXPANSION 1
+
+/* this are the current codec flags I think they are needed */
+/* -> type value in structure */
+#define CODEC_FLAG_JPEG 0x00000001L // JPEG codec
+#define CODEC_FLAG_MPEG 0x00000002L // MPEG1/2/4 codec
+#define CODEC_FLAG_DIVX 0x00000004L // DIVX codec
+#define CODEC_FLAG_WAVELET 0x00000008L // WAVELET codec
+ // room for other types
+
+#define CODEC_FLAG_MAGIC 0x00000800L // magic key must match
+#define CODEC_FLAG_HARDWARE 0x00001000L // is a hardware codec
+#define CODEC_FLAG_VFE 0x00002000L // has direct video frontend
+#define CODEC_FLAG_ENCODER 0x00004000L // compression capability
+#define CODEC_FLAG_DECODER 0x00008000L // decompression capability
+#define CODEC_FLAG_NEEDIRQ 0x00010000L // needs irq handling
+#define CODEC_FLAG_RDWRPIC 0x00020000L // handles picture I/O
+
+/* a list of modes, some are just examples (is there any HW?) */
+#define CODEC_MODE_BJPG 0x0001 // Baseline JPEG
+#define CODEC_MODE_LJPG 0x0002 // Lossless JPEG
+#define CODEC_MODE_MPEG1 0x0003 // MPEG 1
+#define CODEC_MODE_MPEG2 0x0004 // MPEG 2
+#define CODEC_MODE_MPEG4 0x0005 // MPEG 4
+#define CODEC_MODE_MSDIVX 0x0006 // MS DivX
+#define CODEC_MODE_ODIVX 0x0007 // Open DivX
+#define CODEC_MODE_WAVELET 0x0008 // Wavelet
+
+/* this are the current codec types I want to implement */
+/* -> type value in structure */
+#define CODEC_TYPE_NONE 0
+#define CODEC_TYPE_L64702 1
+#define CODEC_TYPE_ZR36050 2
+#define CODEC_TYPE_ZR36016 3
+#define CODEC_TYPE_ZR36060 4
+
+/* the type of data may be enhanced by future implementations (data-fn.'s) */
+/* -> used in command */
+#define CODEC_G_STATUS 0x0000 /* codec status (query only) */
+#define CODEC_S_CODEC_MODE 0x0001 /* codec mode (baseline JPEG, MPEG1,... */
+#define CODEC_G_CODEC_MODE 0x8001
+#define CODEC_S_VFE 0x0002 /* additional video frontend setup */
+#define CODEC_G_VFE 0x8002
+#define CODEC_S_MMAP 0x0003 /* MMAP setup (if available) */
+
+#define CODEC_S_JPEG_TDS_BYTE 0x0010 /* target data size in bytes */
+#define CODEC_G_JPEG_TDS_BYTE 0x8010
+#define CODEC_S_JPEG_SCALE 0x0011 /* scaling factor for quant. tables */
+#define CODEC_G_JPEG_SCALE 0x8011
+#define CODEC_S_JPEG_HDT_DATA 0x0018 /* huffman-tables */
+#define CODEC_G_JPEG_HDT_DATA 0x8018
+#define CODEC_S_JPEG_QDT_DATA 0x0019 /* quantizing-tables */
+#define CODEC_G_JPEG_QDT_DATA 0x8019
+#define CODEC_S_JPEG_APP_DATA 0x001A /* APP marker */
+#define CODEC_G_JPEG_APP_DATA 0x801A
+#define CODEC_S_JPEG_COM_DATA 0x001B /* COM marker */
+#define CODEC_G_JPEG_COM_DATA 0x801B
+
+#define CODEC_S_PRIVATE 0x1000 /* "private" commands start here */
+#define CODEC_G_PRIVATE 0x9000
+
+#define CODEC_G_FLAG 0x8000 /* this is how 'get' is detected */
+
+/* types of transfer, directly user space or a kernel buffer (image-fn.'s) */
+/* -> used in get_image, put_image */
+#define CODEC_TRANSFER_KERNEL 0 /* use "memcopy" */
+#define CODEC_TRANSFER_USER 1 /* use "to/from_user" */
+
+/* ========================= */
+/* the structures itself ... */
+/* ========================= */
+
+struct vfe_polarity {
+ unsigned int vsync_pol:1;
+ unsigned int hsync_pol:1;
+ unsigned int field_pol:1;
+ unsigned int blank_pol:1;
+ unsigned int subimg_pol:1;
+ unsigned int poe_pol:1;
+ unsigned int pvalid_pol:1;
+ unsigned int vclk_pol:1;
+};
+
+struct vfe_settings {
+ __u32 x, y; /* Offsets into image */
+ __u32 width, height; /* Area to capture */
+ __u16 decimation; /* Decimation divider */
+ __u16 flags; /* Flags for capture */
+ __u16 quality; /* quality of the video */
+};
+
+struct tvnorm {
+ u16 wt, wa, h_start, h_sync_start, ht, ha, v_start;
+};
+
+struct jpeg_com_marker {
+ int len; /* number of usable bytes in data */
+ char data[60];
+};
+
+struct jpeg_app_marker {
+ int appn; /* number app segment */
+ int len; /* number of usable bytes in data */
+ char data[60];
+};
+
+struct videocodec {
+ /* -- filled in by slave device during register -- */
+ char name[32];
+ unsigned long magic; /* may be used for client<->master attaching */
+ unsigned long flags; /* functionality flags */
+ unsigned int type; /* codec type */
+
+ /* -- these is filled in later during master device attach -- */
+
+ struct videocodec_master *master_data;
+
+ /* -- these are filled in by the slave device during register -- */
+
+ void *data; /* private slave data */
+
+ /* attach/detach client functions (indirect call) */
+ int (*setup)(struct videocodec *codec);
+ int (*unset)(struct videocodec *codec);
+
+ /* main functions, every client needs them for sure! */
+ // set compression or decompression (or freeze, stop, standby, etc)
+ int (*set_mode)(struct videocodec *codec, int mode);
+ // setup picture size and norm (for the codec's video frontend)
+ int (*set_video)(struct videocodec *codec, const struct tvnorm *norm,
+ struct vfe_settings *cap, struct vfe_polarity *pol);
+ // other control commands, also mmap setup etc.
+ int (*control)(struct videocodec *codec, int type, int size, void *data);
+
+ /* additional setup/query/processing (may be NULL pointer) */
+ // interrupt setup / handling (for irq's delivered by master)
+ int (*setup_interrupt)(struct videocodec *codec, long mode);
+ int (*handle_interrupt)(struct videocodec *codec, int source, long flag);
+ // picture interface (if any)
+ long (*put_image)(struct videocodec *codec, int tr_type, int block,
+ long *fr_num, long *flag, long size, void *buf);
+ long (*get_image)(struct videocodec *codec, int tr_type, int block,
+ long *fr_num, long *flag, long size, void *buf);
+};
+
+struct videocodec_master {
+ /* -- filled in by master device for registration -- */
+ char name[32];
+ unsigned long magic; /* may be used for client<->master attaching */
+ unsigned long flags; /* functionality flags */
+ unsigned int type; /* master type */
+
+ void *data; /* private master data */
+
+ __u32 (*readreg)(struct videocodec *codec, __u16 reg);
+ void (*writereg)(struct videocodec *codec, __u16 reg, __u32 value);
+};
+
+/* ================================================= */
+/* function prototypes of the master/slave interface */
+/* ================================================= */
+
+/* attach and detach commands for the master */
+// * master structure needs to be kmalloc'ed before calling attach
+// and free'd after calling detach
+// * returns pointer on success, NULL on failure
+struct videocodec *videocodec_attach(struct videocodec_master *master);
+// * 0 on success, <0 (errno) on failure
+int videocodec_detach(struct videocodec *codec);
+
+/* register and unregister commands for the slaves */
+// * 0 on success, <0 (errno) on failure
+int videocodec_register(const struct videocodec *codec);
+// * 0 on success, <0 (errno) on failure
+int videocodec_unregister(const struct videocodec *codec);
+
+/* the other calls are directly done via the videocodec structure! */
+
+int videocodec_debugfs_show(struct seq_file *m);
+
+#include "zoran.h"
+static inline struct zoran *videocodec_master_to_zoran(struct videocodec_master *master)
+{
+ struct zoran *zr = master->data;
+
+ return zr;
+}
+
+static inline struct zoran *videocodec_to_zoran(struct videocodec *codec)
+{
+ struct videocodec_master *master = codec->master_data;
+
+ return videocodec_master_to_zoran(master);
+}
+
+#endif /*ifndef __LINUX_VIDEOCODEC_H */
diff --git a/drivers/media/pci/zoran/zoran.h b/drivers/media/pci/zoran/zoran.h
new file mode 100644
index 000000000000..56340553b282
--- /dev/null
+++ b/drivers/media/pci/zoran/zoran.h
@@ -0,0 +1,328 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * zoran - Iomega Buz driver
+ *
+ * Copyright (C) 1999 Rainer Johanni <Rainer@Johanni.de>
+ *
+ * based on
+ *
+ * zoran.0.0.3 Copyright (C) 1998 Dave Perks <dperks@ibm.net>
+ *
+ * and
+ *
+ * bttv - Bt848 frame grabber driver
+ * Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de)
+ * & Marcus Metzler (mocm@thp.uni-koeln.de)
+ */
+
+#ifndef _BUZ_H_
+#define _BUZ_H_
+
+#include <linux/debugfs.h>
+#include <linux/pci.h>
+#include <linux/i2c-algo-bit.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
+#include <media/videobuf2-dma-contig.h>
+
+#define ZR_NORM_PAL 0
+#define ZR_NORM_NTSC 1
+#define ZR_NORM_SECAM 2
+
+struct zr_buffer {
+ /* common v4l buffer stuff -- must be first */
+ struct vb2_v4l2_buffer vbuf;
+ struct list_head queue;
+};
+
+static inline struct zr_buffer *vb2_to_zr_buffer(struct vb2_buffer *vb)
+{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+
+ return container_of(vbuf, struct zr_buffer, vbuf);
+}
+
+#define ZORAN_NAME "ZORAN" /* name of the device */
+
+#define ZR_DEVNAME(zr) ((zr)->name)
+
+#define BUZ_MAX_WIDTH (zr->timing->wa)
+#define BUZ_MAX_HEIGHT (zr->timing->ha)
+#define BUZ_MIN_WIDTH 32 /* never display less than 32 pixels */
+#define BUZ_MIN_HEIGHT 24 /* never display less than 24 rows */
+
+#define BUZ_NUM_STAT_COM 4
+#define BUZ_MASK_STAT_COM 3
+
+#define BUZ_MAX_INPUT 16
+
+#include "zr36057.h"
+
+enum card_type {
+ UNKNOWN = -1,
+
+ /* Pinnacle/Miro */
+ DC10_OLD, /* DC30 like */
+ DC10_NEW, /* DC10_PLUS like */
+ DC10_PLUS,
+ DC30,
+ DC30_PLUS,
+
+ /* Linux Media Labs */
+ LML33,
+ LML33R10,
+
+ /* Iomega */
+ BUZ,
+
+ /* AverMedia */
+ AVS6EYES,
+
+ /* total number of cards */
+ NUM_CARDS
+};
+
+enum zoran_codec_mode {
+ BUZ_MODE_IDLE, /* nothing going on */
+ BUZ_MODE_MOTION_COMPRESS, /* grabbing frames */
+ BUZ_MODE_MOTION_DECOMPRESS, /* playing frames */
+ BUZ_MODE_STILL_COMPRESS, /* still frame conversion */
+ BUZ_MODE_STILL_DECOMPRESS /* still frame conversion */
+};
+
+enum zoran_map_mode {
+ ZORAN_MAP_MODE_NONE,
+ ZORAN_MAP_MODE_RAW,
+ ZORAN_MAP_MODE_JPG_REC,
+ ZORAN_MAP_MODE_JPG_PLAY,
+};
+
+enum gpio_type {
+ ZR_GPIO_JPEG_SLEEP = 0,
+ ZR_GPIO_JPEG_RESET,
+ ZR_GPIO_JPEG_FRAME,
+ ZR_GPIO_VID_DIR,
+ ZR_GPIO_VID_EN,
+ ZR_GPIO_VID_RESET,
+ ZR_GPIO_CLK_SEL1,
+ ZR_GPIO_CLK_SEL2,
+ ZR_GPIO_MAX,
+};
+
+enum gpcs_type {
+ GPCS_JPEG_RESET = 0,
+ GPCS_JPEG_START,
+ GPCS_MAX,
+};
+
+struct zoran_format {
+ char *name;
+ __u32 fourcc;
+ int colorspace;
+ int depth;
+ __u32 flags;
+ __u32 vfespfr;
+};
+
+/* flags */
+#define ZORAN_FORMAT_COMPRESSED BIT(0)
+#define ZORAN_FORMAT_OVERLAY BIT(1)
+#define ZORAN_FORMAT_CAPTURE BIT(2)
+#define ZORAN_FORMAT_PLAYBACK BIT(3)
+
+/* v4l-capture settings */
+struct zoran_v4l_settings {
+ int width, height, bytesperline; /* capture size */
+ const struct zoran_format *format; /* capture format */
+};
+
+/* jpg-capture/-playback settings */
+struct zoran_jpg_settings {
+ /* this bit is used to set everything to default */
+ int decimation;
+ /* capture decimation settings (tmp_dcm=1 means both fields) */
+ int hor_dcm, ver_dcm, tmp_dcm;
+ /* field-settings (odd_even=1 (+tmp_dcm=1) means top-field-first) */
+ int field_per_buff, odd_even;
+ /* crop settings (subframe capture) */
+ int img_x, img_y, img_width, img_height;
+ /* JPEG-specific capture settings */
+ struct v4l2_jpegcompression jpg_comp;
+};
+
+struct zoran;
+
+/* zoran_fh contains per-open() settings */
+struct zoran_fh {
+ struct v4l2_fh fh;
+ struct zoran *zr;
+};
+
+struct card_info {
+ enum card_type type;
+ char name[32];
+ const char *i2c_decoder; /* i2c decoder device */
+ const unsigned short *addrs_decoder;
+ const char *i2c_encoder; /* i2c encoder device */
+ const unsigned short *addrs_encoder;
+ u16 video_vfe, video_codec; /* videocodec types */
+ u16 audio_chip; /* audio type */
+
+ int inputs; /* number of video inputs */
+ struct input {
+ int muxsel;
+ char name[32];
+ } input[BUZ_MAX_INPUT];
+
+ v4l2_std_id norms;
+ const struct tvnorm *tvn[3]; /* supported TV norms */
+
+ u32 jpeg_int; /* JPEG interrupt */
+ u32 vsync_int; /* VSYNC interrupt */
+ s8 gpio[ZR_GPIO_MAX];
+ u8 gpcs[GPCS_MAX];
+
+ struct vfe_polarity vfe_pol;
+ u8 gpio_pol[ZR_GPIO_MAX];
+
+ /* is the /GWS line connected? */
+ u8 gws_not_connected;
+
+ /* avs6eyes mux setting */
+ u8 input_mux;
+
+ void (*init)(struct zoran *zr);
+};
+
+struct zoran {
+ struct v4l2_device v4l2_dev;
+ struct v4l2_ctrl_handler hdl;
+ struct video_device *video_dev;
+ struct vb2_queue vq;
+
+ struct i2c_adapter i2c_adapter; /* */
+ struct i2c_algo_bit_data i2c_algo; /* */
+ u32 i2cbr;
+
+ struct v4l2_subdev *decoder; /* video decoder sub-device */
+ struct v4l2_subdev *encoder; /* video encoder sub-device */
+
+ struct videocodec *codec; /* video codec */
+ struct videocodec *vfe; /* video front end */
+
+ struct mutex lock; /* file ops serialize lock */
+
+ u8 initialized; /* flag if zoran has been correctly initialized */
+ struct card_info card;
+ const struct tvnorm *timing;
+
+ unsigned short id; /* number of this device */
+ char name[32]; /* name of this device */
+ struct pci_dev *pci_dev; /* PCI device */
+ unsigned char revision; /* revision of zr36057 */
+ unsigned char __iomem *zr36057_mem;/* pointer to mapped IO memory */
+
+ spinlock_t spinlock; /* Spinlock */
+
+ /* Video for Linux parameters */
+ int input; /* card's norm and input */
+ v4l2_std_id norm;
+
+ /* Current buffer params */
+ unsigned int buffer_size;
+
+ struct zoran_v4l_settings v4l_settings; /* structure with a lot of things to play with */
+
+ /* Buz MJPEG parameters */
+ enum zoran_codec_mode codec_mode; /* status of codec */
+ struct zoran_jpg_settings jpg_settings; /* structure with a lot of things to play with */
+
+ /* grab queue counts/indices, mask with BUZ_MASK_STAT_COM before using as index */
+ /* (dma_head - dma_tail) is number active in DMA, must be <= BUZ_NUM_STAT_COM */
+ /* (value & BUZ_MASK_STAT_COM) corresponds to index in stat_com table */
+ unsigned long jpg_que_head; /* Index where to put next buffer which is queued */
+ unsigned long jpg_dma_head; /* Index of next buffer which goes into stat_com */
+ unsigned long jpg_dma_tail; /* Index of last buffer in stat_com */
+ unsigned long jpg_que_tail; /* Index of last buffer in queue */
+ unsigned long jpg_seq_num; /* count of frames since grab/play started */
+ unsigned long jpg_err_seq; /* last seq_num before error */
+ unsigned long jpg_err_shift;
+ unsigned long jpg_queued_num; /* count of frames queued since grab/play started */
+ unsigned long vbseq;
+
+ /* zr36057's code buffer table */
+ /* stat_com[i] is indexed by dma_head/tail & BUZ_MASK_STAT_COM */
+ __le32 *stat_com;
+
+ /* Additional stuff for testing */
+ unsigned int ghost_int;
+ int intr_counter_GIRQ1;
+ int intr_counter_GIRQ0;
+ int intr_counter_cod_rep_irq;
+ int intr_counter_jpeg_rep_irq;
+ int field_counter;
+ int irq1_in;
+ int irq1_out;
+ int jpeg_in;
+ int jpeg_out;
+ int JPEG_0;
+ int JPEG_1;
+ int end_event_missed;
+ int jpeg_missed;
+ int jpeg_error;
+ int num_errors;
+ int jpeg_max_missed;
+ int jpeg_min_missed;
+ unsigned int prepared;
+ unsigned int queued;
+
+ u32 last_isr;
+ unsigned long frame_num;
+ int running;
+ int buf_in_reserve;
+
+ dma_addr_t p_sc;
+ __le32 *stat_comb;
+ dma_addr_t p_scb;
+ enum zoran_map_mode map_mode;
+ struct list_head queued_bufs;
+ spinlock_t queued_bufs_lock; /* Protects queued_bufs */
+ struct zr_buffer *inuse[BUZ_NUM_STAT_COM * 2];
+ struct dentry *dbgfs_dir;
+};
+
+static inline struct zoran *to_zoran(struct v4l2_device *v4l2_dev)
+{
+ return container_of(v4l2_dev, struct zoran, v4l2_dev);
+}
+
+/*
+ * There was something called _ALPHA_BUZ that used the PCI address instead of
+ * the kernel iomapped address for btread/btwrite.
+ */
+#define btwrite(dat, adr) writel((dat), zr->zr36057_mem + (adr))
+#define btread(adr) readl(zr->zr36057_mem + (adr))
+
+#define btand(dat, adr) btwrite((dat) & btread(adr), (adr))
+#define btor(dat, adr) btwrite((dat) | btread(adr), (adr))
+#define btaor(dat, mask, adr) btwrite((dat) | ((mask) & btread(adr)), (adr))
+
+#endif
+
+/*
+ * Debugging macros
+ */
+#define zrdev_dbg(zr, format, args...) \
+ pci_dbg((zr)->pci_dev, format, ##args) \
+
+#define zrdev_err(zr, format, args...) \
+ pci_err((zr)->pci_dev, format, ##args) \
+
+#define zrdev_info(zr, format, args...) \
+ pci_info((zr)->pci_dev, format, ##args) \
+
+int zoran_queue_init(struct zoran *zr, struct vb2_queue *vq, int dir);
+void zoran_queue_exit(struct zoran *zr);
+int zr_set_buf(struct zoran *zr);
diff --git a/drivers/media/pci/zoran/zoran_card.c b/drivers/media/pci/zoran/zoran_card.c
new file mode 100644
index 000000000000..3975fc1b2ee3
--- /dev/null
+++ b/drivers/media/pci/zoran/zoran_card.c
@@ -0,0 +1,1440 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Zoran zr36057/zr36067 PCI controller driver, for the
+ * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux
+ * Media Labs LML33/LML33R10.
+ *
+ * This part handles card-specific data and detection
+ *
+ * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
+ */
+
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/videodev2.h>
+#include <linux/spinlock.h>
+
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <media/v4l2-common.h>
+#include <media/i2c/bt819.h>
+
+#include "videocodec.h"
+#include "zoran.h"
+#include "zoran_card.h"
+#include "zoran_device.h"
+#include "zr36016.h"
+#include "zr36050.h"
+#include "zr36060.h"
+
+extern const struct zoran_format zoran_formats[];
+
+static int card[BUZ_MAX] = { [0 ... (BUZ_MAX - 1)] = -1 };
+module_param_array(card, int, NULL, 0444);
+MODULE_PARM_DESC(card, "Card type");
+
+/* Default input and video norm at startup of the driver. */
+
+static unsigned int default_input; /* default 0 = Composite, 1 = S-Video */
+module_param(default_input, uint, 0444);
+MODULE_PARM_DESC(default_input,
+ "Default input (0=Composite, 1=S-Video, 2=Internal)");
+
+static int default_mux = 1; /* 6 Eyes input selection */
+module_param(default_mux, int, 0644);
+MODULE_PARM_DESC(default_mux,
+ "Default 6 Eyes mux setting (Input selection)");
+
+static int default_norm; /* default 0 = PAL, 1 = NTSC 2 = SECAM */
+module_param(default_norm, int, 0444);
+MODULE_PARM_DESC(default_norm, "Default norm (0=PAL, 1=NTSC, 2=SECAM)");
+
+/* /dev/videoN, -1 for autodetect */
+static int video_nr[BUZ_MAX] = { [0 ... (BUZ_MAX - 1)] = -1 };
+module_param_array(video_nr, int, NULL, 0444);
+MODULE_PARM_DESC(video_nr, "Video device number (-1=Auto)");
+
+/* 1=Pass through TV signal when device is not used */
+/* 0=Show color bar when device is not used (LML33: only if lml33dpath=1) */
+int pass_through;
+module_param(pass_through, int, 0644);
+MODULE_PARM_DESC(pass_through,
+ "Pass TV signal through to TV-out when idling");
+
+int zr36067_debug = 1;
+module_param_named(debug, zr36067_debug, int, 0644);
+MODULE_PARM_DESC(debug, "Debug level (0-5)");
+
+#define ZORAN_VERSION "0.10.1"
+
+MODULE_DESCRIPTION("Zoran-36057/36067 JPEG codec driver");
+MODULE_AUTHOR("Serguei Miridonov");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(ZORAN_VERSION);
+
+#define ZR_DEVICE(subven, subdev, data) { \
+ .vendor = PCI_VENDOR_ID_ZORAN, .device = PCI_DEVICE_ID_ZORAN_36057, \
+ .subvendor = (subven), .subdevice = (subdev), .driver_data = (data) }
+
+static const struct pci_device_id zr36067_pci_tbl[] = {
+ ZR_DEVICE(PCI_VENDOR_ID_MIRO, PCI_DEVICE_ID_MIRO_DC10PLUS, DC10_PLUS),
+ ZR_DEVICE(PCI_VENDOR_ID_MIRO, PCI_DEVICE_ID_MIRO_DC30PLUS, DC30_PLUS),
+ ZR_DEVICE(PCI_VENDOR_ID_ELECTRONICDESIGNGMBH, PCI_DEVICE_ID_LML_33R10, LML33R10),
+ ZR_DEVICE(PCI_VENDOR_ID_IOMEGA, PCI_DEVICE_ID_IOMEGA_BUZ, BUZ),
+ ZR_DEVICE(PCI_ANY_ID, PCI_ANY_ID, NUM_CARDS),
+ {0}
+};
+MODULE_DEVICE_TABLE(pci, zr36067_pci_tbl);
+
+static unsigned int zoran_num; /* number of cards found */
+
+/* videocodec bus functions ZR36060 */
+static u32 zr36060_read(struct videocodec *codec, u16 reg)
+{
+ struct zoran *zr = (struct zoran *)codec->master_data->data;
+ __u32 data;
+
+ if (post_office_wait(zr) || post_office_write(zr, 0, 1, reg >> 8) ||
+ post_office_write(zr, 0, 2, reg & 0xff))
+ return -1;
+
+ data = post_office_read(zr, 0, 3) & 0xff;
+ return data;
+}
+
+static void zr36060_write(struct videocodec *codec, u16 reg, u32 val)
+{
+ struct zoran *zr = (struct zoran *)codec->master_data->data;
+
+ if (post_office_wait(zr) || post_office_write(zr, 0, 1, reg >> 8) ||
+ post_office_write(zr, 0, 2, reg & 0xff))
+ return;
+
+ post_office_write(zr, 0, 3, val & 0xff);
+}
+
+/* videocodec bus functions ZR36050 */
+static u32 zr36050_read(struct videocodec *codec, u16 reg)
+{
+ struct zoran *zr = (struct zoran *)codec->master_data->data;
+ __u32 data;
+
+ if (post_office_wait(zr) || post_office_write(zr, 1, 0, reg >> 2)) // reg. HIGHBYTES
+ return -1;
+
+ data = post_office_read(zr, 0, reg & 0x03) & 0xff; // reg. LOWBYTES + read
+ return data;
+}
+
+static void zr36050_write(struct videocodec *codec, u16 reg, u32 val)
+{
+ struct zoran *zr = (struct zoran *)codec->master_data->data;
+
+ if (post_office_wait(zr) || post_office_write(zr, 1, 0, reg >> 2)) // reg. HIGHBYTES
+ return;
+
+ post_office_write(zr, 0, reg & 0x03, val & 0xff); // reg. LOWBYTES + wr. data
+}
+
+/* videocodec bus functions ZR36016 */
+static u32 zr36016_read(struct videocodec *codec, u16 reg)
+{
+ struct zoran *zr = (struct zoran *)codec->master_data->data;
+ __u32 data;
+
+ if (post_office_wait(zr))
+ return -1;
+
+ data = post_office_read(zr, 2, reg & 0x03) & 0xff; // read
+ return data;
+}
+
+/* hack for in zoran_device.c */
+void zr36016_write(struct videocodec *codec, u16 reg, u32 val)
+{
+ struct zoran *zr = (struct zoran *)codec->master_data->data;
+
+ if (post_office_wait(zr))
+ return;
+
+ post_office_write(zr, 2, reg & 0x03, val & 0x0ff); // wr. data
+}
+
+/*
+ * Board specific information
+ */
+
+static void dc10_init(struct zoran *zr)
+{
+ /* Pixel clock selection */
+ GPIO(zr, 4, 0);
+ GPIO(zr, 5, 1);
+ /* Enable the video bus sync signals */
+ GPIO(zr, 7, 0);
+}
+
+static void dc10plus_init(struct zoran *zr)
+{
+}
+
+static void buz_init(struct zoran *zr)
+{
+ /* some stuff from Iomega */
+ pci_write_config_dword(zr->pci_dev, 0xfc, 0x90680f15);
+ pci_write_config_dword(zr->pci_dev, 0x0c, 0x00012020);
+ pci_write_config_dword(zr->pci_dev, 0xe8, 0xc0200000);
+}
+
+static void lml33_init(struct zoran *zr)
+{
+ GPIO(zr, 2, 1); // Set Composite input/output
+}
+
+static void avs6eyes_init(struct zoran *zr)
+{
+ // AverMedia 6-Eyes original driver by Christer Weinigel
+
+ // Lifted straight from Christer's old driver and
+ // modified slightly by Martin Samuelsson.
+
+ int mux = default_mux; /* 1 = BT866, 7 = VID1 */
+
+ GPIO(zr, 4, 1); /* Bt866 SLEEP on */
+ udelay(2);
+
+ GPIO(zr, 0, 1); /* ZR36060 /RESET on */
+ GPIO(zr, 1, 0); /* ZR36060 /SLEEP on */
+ GPIO(zr, 2, mux & 1); /* MUX S0 */
+ GPIO(zr, 3, 0); /* /FRAME on */
+ GPIO(zr, 4, 0); /* Bt866 SLEEP off */
+ GPIO(zr, 5, mux & 2); /* MUX S1 */
+ GPIO(zr, 6, 0); /* ? */
+ GPIO(zr, 7, mux & 4); /* MUX S2 */
+}
+
+static const char *codecid_to_modulename(u16 codecid)
+{
+ const char *name = NULL;
+
+ switch (codecid) {
+ case CODEC_TYPE_ZR36060:
+ name = "zr36060";
+ break;
+ case CODEC_TYPE_ZR36050:
+ name = "zr36050";
+ break;
+ case CODEC_TYPE_ZR36016:
+ name = "zr36016";
+ break;
+ }
+
+ return name;
+}
+
+static int codec_init(struct zoran *zr, u16 codecid)
+{
+ switch (codecid) {
+ case CODEC_TYPE_ZR36060:
+#ifdef CONFIG_VIDEO_ZORAN_ZR36060
+ return zr36060_init_module();
+#else
+ pci_err(zr->pci_dev, "ZR36060 support is not enabled\n");
+ return -EINVAL;
+#endif
+ break;
+ case CODEC_TYPE_ZR36050:
+#ifdef CONFIG_VIDEO_ZORAN_DC30
+ return zr36050_init_module();
+#else
+ pci_err(zr->pci_dev, "ZR36050 support is not enabled\n");
+ return -EINVAL;
+#endif
+ break;
+ case CODEC_TYPE_ZR36016:
+#ifdef CONFIG_VIDEO_ZORAN_DC30
+ return zr36016_init_module();
+#else
+ pci_err(zr->pci_dev, "ZR36016 support is not enabled\n");
+ return -EINVAL;
+#endif
+ break;
+ }
+
+ pci_err(zr->pci_dev, "unknown codec id %x\n", codecid);
+ return -EINVAL;
+}
+
+static void codec_exit(struct zoran *zr, u16 codecid)
+{
+ switch (codecid) {
+ case CODEC_TYPE_ZR36060:
+#ifdef CONFIG_VIDEO_ZORAN_ZR36060
+ zr36060_cleanup_module();
+#endif
+ break;
+ case CODEC_TYPE_ZR36050:
+#ifdef CONFIG_VIDEO_ZORAN_DC30
+ zr36050_cleanup_module();
+#endif
+ break;
+ case CODEC_TYPE_ZR36016:
+#ifdef CONFIG_VIDEO_ZORAN_DC30
+ zr36016_cleanup_module();
+#endif
+ break;
+ }
+}
+
+static int videocodec_init(struct zoran *zr)
+{
+ const char *codec_name, *vfe_name;
+ int result;
+
+ codec_name = codecid_to_modulename(zr->card.video_codec);
+ if (codec_name) {
+ result = codec_init(zr, zr->card.video_codec);
+ if (result < 0) {
+ pci_err(zr->pci_dev, "failed to load video codec %s: %d\n",
+ codec_name, result);
+ return result;
+ }
+ }
+ vfe_name = codecid_to_modulename(zr->card.video_vfe);
+ if (vfe_name) {
+ result = codec_init(zr, zr->card.video_vfe);
+ if (result < 0) {
+ pci_err(zr->pci_dev, "failed to load video vfe %s: %d\n",
+ vfe_name, result);
+ if (codec_name)
+ codec_exit(zr, zr->card.video_codec);
+ return result;
+ }
+ }
+ return 0;
+}
+
+static void videocodec_exit(struct zoran *zr)
+{
+ if (zr->card.video_codec != CODEC_TYPE_NONE)
+ codec_exit(zr, zr->card.video_codec);
+ if (zr->card.video_vfe != CODEC_TYPE_NONE)
+ codec_exit(zr, zr->card.video_vfe);
+}
+
+static const struct tvnorm f50sqpixel = { 944, 768, 83, 880, 625, 576, 16 };
+static const struct tvnorm f60sqpixel = { 780, 640, 51, 716, 525, 480, 12 };
+static const struct tvnorm f50ccir601 = { 864, 720, 75, 804, 625, 576, 18 };
+static const struct tvnorm f60ccir601 = { 858, 720, 57, 788, 525, 480, 16 };
+
+static const struct tvnorm f50ccir601_lml33 = { 864, 720, 75 + 34, 804, 625, 576, 18 };
+static const struct tvnorm f60ccir601_lml33 = { 858, 720, 57 + 34, 788, 525, 480, 16 };
+
+/* The DC10 (57/16/50) uses VActive as HSync, so h_start must be 0 */
+static const struct tvnorm f50sqpixel_dc10 = { 944, 768, 0, 880, 625, 576, 0 };
+static const struct tvnorm f60sqpixel_dc10 = { 780, 640, 0, 716, 525, 480, 12 };
+
+/*
+ * FIXME: I cannot swap U and V in saa7114, so i do one pixel left shift in zoran (75 -> 74)
+ * (Maxim Yevtyushkin <max@linuxmedialabs.com>)
+ */
+static const struct tvnorm f50ccir601_lm33r10 = { 864, 720, 74 + 54, 804, 625, 576, 18 };
+static const struct tvnorm f60ccir601_lm33r10 = { 858, 720, 56 + 54, 788, 525, 480, 16 };
+
+/*
+ * FIXME: The ks0127 seem incapable of swapping U and V, too, which is why I copy Maxim's left
+ * shift hack for the 6 Eyes.
+ *
+ * Christer's driver used the unshifted norms, though...
+ * /Sam
+ */
+static const struct tvnorm f50ccir601_avs6eyes = { 864, 720, 74, 804, 625, 576, 18 };
+static const struct tvnorm f60ccir601_avs6eyes = { 858, 720, 56, 788, 525, 480, 16 };
+
+static const unsigned short vpx3220_addrs[] = { 0x43, 0x47, I2C_CLIENT_END };
+static const unsigned short saa7110_addrs[] = { 0x4e, 0x4f, I2C_CLIENT_END };
+static const unsigned short saa7111_addrs[] = { 0x25, 0x24, I2C_CLIENT_END };
+static const unsigned short saa7114_addrs[] = { 0x21, 0x20, I2C_CLIENT_END };
+static const unsigned short adv717x_addrs[] = { 0x6a, 0x6b, 0x2a, 0x2b, I2C_CLIENT_END };
+static const unsigned short ks0127_addrs[] = { 0x6c, 0x6d, I2C_CLIENT_END };
+static const unsigned short saa7185_addrs[] = { 0x44, I2C_CLIENT_END };
+static const unsigned short bt819_addrs[] = { 0x45, I2C_CLIENT_END };
+static const unsigned short bt856_addrs[] = { 0x44, I2C_CLIENT_END };
+static const unsigned short bt866_addrs[] = { 0x44, I2C_CLIENT_END };
+
+static struct card_info zoran_cards[NUM_CARDS] = {
+ {
+ .type = DC10_OLD,
+ .name = "DC10(old)",
+ .i2c_decoder = "vpx3220a",
+ .addrs_decoder = vpx3220_addrs,
+ .video_codec = CODEC_TYPE_ZR36050,
+ .video_vfe = CODEC_TYPE_ZR36016,
+
+ .inputs = 3,
+ .input = {
+ { 1, "Composite" },
+ { 2, "S-Video" },
+ { 0, "Internal/comp" }
+ },
+ .norms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM,
+ .tvn = {
+ &f50sqpixel_dc10,
+ &f60sqpixel_dc10,
+ &f50sqpixel_dc10
+ },
+ .jpeg_int = 0,
+ .vsync_int = ZR36057_ISR_GIRQ1,
+ .gpio = { 2, 1, -1, 3, 7, 0, 4, 5 },
+ .gpio_pol = { 0, 0, 0, 1, 0, 0, 0, 0 },
+ .gpcs = { -1, 0 },
+ .vfe_pol = { 0, 0, 0, 0, 0, 0, 0, 0 },
+ .gws_not_connected = 0,
+ .input_mux = 0,
+ .init = &dc10_init,
+ }, {
+ .type = DC10_NEW,
+ .name = "DC10(new)",
+ .i2c_decoder = "saa7110",
+ .addrs_decoder = saa7110_addrs,
+ .i2c_encoder = "adv7175",
+ .addrs_encoder = adv717x_addrs,
+ .video_codec = CODEC_TYPE_ZR36060,
+
+ .inputs = 3,
+ .input = {
+ { 0, "Composite" },
+ { 7, "S-Video" },
+ { 5, "Internal/comp" }
+ },
+ .norms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM,
+ .tvn = {
+ &f50sqpixel,
+ &f60sqpixel,
+ &f50sqpixel},
+ .jpeg_int = ZR36057_ISR_GIRQ0,
+ .vsync_int = ZR36057_ISR_GIRQ1,
+ .gpio = { 3, 0, 6, 1, 2, -1, 4, 5 },
+ .gpio_pol = { 0, 0, 0, 0, 0, 0, 0, 0 },
+ .gpcs = { -1, 1},
+ .vfe_pol = { 1, 1, 1, 1, 0, 0, 0, 0 },
+ .gws_not_connected = 0,
+ .input_mux = 0,
+ .init = &dc10plus_init,
+ }, {
+ .type = DC10_PLUS,
+ .name = "DC10_PLUS",
+ .i2c_decoder = "saa7110",
+ .addrs_decoder = saa7110_addrs,
+ .i2c_encoder = "adv7175",
+ .addrs_encoder = adv717x_addrs,
+ .video_codec = CODEC_TYPE_ZR36060,
+
+ .inputs = 3,
+ .input = {
+ { 0, "Composite" },
+ { 7, "S-Video" },
+ { 5, "Internal/comp" }
+ },
+ .norms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM,
+ .tvn = {
+ &f50sqpixel,
+ &f60sqpixel,
+ &f50sqpixel
+ },
+ .jpeg_int = ZR36057_ISR_GIRQ0,
+ .vsync_int = ZR36057_ISR_GIRQ1,
+ .gpio = { 3, 0, 6, 1, 2, -1, 4, 5 },
+ .gpio_pol = { 0, 0, 0, 0, 0, 0, 0, 0 },
+ .gpcs = { -1, 1 },
+ .vfe_pol = { 1, 1, 1, 1, 0, 0, 0, 0 },
+ .gws_not_connected = 0,
+ .input_mux = 0,
+ .init = &dc10plus_init,
+ }, {
+ .type = DC30,
+ .name = "DC30",
+ .i2c_decoder = "vpx3220a",
+ .addrs_decoder = vpx3220_addrs,
+ .i2c_encoder = "adv7175",
+ .addrs_encoder = adv717x_addrs,
+ .video_codec = CODEC_TYPE_ZR36050,
+ .video_vfe = CODEC_TYPE_ZR36016,
+
+ .inputs = 3,
+ .input = {
+ { 1, "Composite" },
+ { 2, "S-Video" },
+ { 0, "Internal/comp" }
+ },
+ .norms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM,
+ .tvn = {
+ &f50sqpixel_dc10,
+ &f60sqpixel_dc10,
+ &f50sqpixel_dc10
+ },
+ .jpeg_int = 0,
+ .vsync_int = ZR36057_ISR_GIRQ1,
+ .gpio = { 2, 1, -1, 3, 7, 0, 4, 5 },
+ .gpio_pol = { 0, 0, 0, 1, 0, 0, 0, 0 },
+ .gpcs = { -1, 0 },
+ .vfe_pol = { 0, 0, 0, 0, 0, 0, 0, 0 },
+ .gws_not_connected = 0,
+ .input_mux = 0,
+ .init = &dc10_init,
+ }, {
+ .type = DC30_PLUS,
+ .name = "DC30_PLUS",
+ .i2c_decoder = "vpx3220a",
+ .addrs_decoder = vpx3220_addrs,
+ .i2c_encoder = "adv7175",
+ .addrs_encoder = adv717x_addrs,
+ .video_codec = CODEC_TYPE_ZR36050,
+ .video_vfe = CODEC_TYPE_ZR36016,
+
+ .inputs = 3,
+ .input = {
+ { 1, "Composite" },
+ { 2, "S-Video" },
+ { 0, "Internal/comp" }
+ },
+ .norms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM,
+ .tvn = {
+ &f50sqpixel_dc10,
+ &f60sqpixel_dc10,
+ &f50sqpixel_dc10
+ },
+ .jpeg_int = 0,
+ .vsync_int = ZR36057_ISR_GIRQ1,
+ .gpio = { 2, 1, -1, 3, 7, 0, 4, 5 },
+ .gpio_pol = { 0, 0, 0, 1, 0, 0, 0, 0 },
+ .gpcs = { -1, 0 },
+ .vfe_pol = { 0, 0, 0, 0, 0, 0, 0, 0 },
+ .gws_not_connected = 0,
+ .input_mux = 0,
+ .init = &dc10_init,
+ }, {
+ .type = LML33,
+ .name = "LML33",
+ .i2c_decoder = "bt819a",
+ .addrs_decoder = bt819_addrs,
+ .i2c_encoder = "bt856",
+ .addrs_encoder = bt856_addrs,
+ .video_codec = CODEC_TYPE_ZR36060,
+
+ .inputs = 2,
+ .input = {
+ { 0, "Composite" },
+ { 7, "S-Video" }
+ },
+ .norms = V4L2_STD_NTSC | V4L2_STD_PAL,
+ .tvn = {
+ &f50ccir601_lml33,
+ &f60ccir601_lml33,
+ NULL
+ },
+ .jpeg_int = ZR36057_ISR_GIRQ1,
+ .vsync_int = ZR36057_ISR_GIRQ0,
+ .gpio = { 1, -1, 3, 5, 7, -1, -1, -1 },
+ .gpio_pol = { 0, 0, 0, 0, 1, 0, 0, 0 },
+ .gpcs = { 3, 1 },
+ .vfe_pol = { 1, 1, 0, 0, 0, 1, 0, 0 },
+ .gws_not_connected = 1,
+ .input_mux = 0,
+ .init = &lml33_init,
+ }, {
+ .type = LML33R10,
+ .name = "LML33R10",
+ .i2c_decoder = "saa7114",
+ .addrs_decoder = saa7114_addrs,
+ .i2c_encoder = "adv7170",
+ .addrs_encoder = adv717x_addrs,
+ .video_codec = CODEC_TYPE_ZR36060,
+
+ .inputs = 2,
+ .input = {
+ { 0, "Composite" },
+ { 7, "S-Video" }
+ },
+ .norms = V4L2_STD_NTSC | V4L2_STD_PAL,
+ .tvn = {
+ &f50ccir601_lm33r10,
+ &f60ccir601_lm33r10,
+ NULL
+ },
+ .jpeg_int = ZR36057_ISR_GIRQ1,
+ .vsync_int = ZR36057_ISR_GIRQ0,
+ .gpio = { 1, -1, 3, 5, 7, -1, -1, -1 },
+ .gpio_pol = { 0, 0, 0, 0, 1, 0, 0, 0 },
+ .gpcs = { 3, 1 },
+ .vfe_pol = { 1, 1, 0, 0, 0, 1, 0, 0 },
+ .gws_not_connected = 1,
+ .input_mux = 0,
+ .init = &lml33_init,
+ }, {
+ .type = BUZ,
+ .name = "Buz",
+ .i2c_decoder = "saa7111",
+ .addrs_decoder = saa7111_addrs,
+ .i2c_encoder = "saa7185",
+ .addrs_encoder = saa7185_addrs,
+ .video_codec = CODEC_TYPE_ZR36060,
+
+ .inputs = 2,
+ .input = {
+ { 3, "Composite" },
+ { 7, "S-Video" }
+ },
+ .norms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM,
+ .tvn = {
+ &f50ccir601,
+ &f60ccir601,
+ &f50ccir601
+ },
+ .jpeg_int = ZR36057_ISR_GIRQ1,
+ .vsync_int = ZR36057_ISR_GIRQ0,
+ .gpio = { 1, -1, 3, -1, -1, -1, -1, -1 },
+ .gpio_pol = { 0, 0, 0, 0, 0, 0, 0, 0 },
+ .gpcs = { 3, 1 },
+ .vfe_pol = { 1, 1, 0, 0, 0, 1, 0, 0 },
+ .gws_not_connected = 1,
+ .input_mux = 0,
+ .init = &buz_init,
+ }, {
+ .type = AVS6EYES,
+ .name = "6-Eyes",
+ /*
+ * AverMedia chose not to brand the 6-Eyes. Thus it can't be
+ * autodetected, and requires card=x.
+ */
+ .i2c_decoder = "ks0127",
+ .addrs_decoder = ks0127_addrs,
+ .i2c_encoder = "bt866",
+ .addrs_encoder = bt866_addrs,
+ .video_codec = CODEC_TYPE_ZR36060,
+
+ .inputs = 10,
+ .input = {
+ { 0, "Composite 1" },
+ { 1, "Composite 2" },
+ { 2, "Composite 3" },
+ { 4, "Composite 4" },
+ { 5, "Composite 5" },
+ { 6, "Composite 6" },
+ { 8, "S-Video 1" },
+ { 9, "S-Video 2" },
+ {10, "S-Video 3" },
+ {15, "YCbCr" }
+ },
+ .norms = V4L2_STD_NTSC | V4L2_STD_PAL,
+ .tvn = {
+ &f50ccir601_avs6eyes,
+ &f60ccir601_avs6eyes,
+ NULL
+ },
+ .jpeg_int = ZR36057_ISR_GIRQ1,
+ .vsync_int = ZR36057_ISR_GIRQ0,
+ .gpio = { 1, 0, 3, -1, -1, -1, -1, -1 },// Validity unknown /Sam
+ .gpio_pol = { 0, 0, 0, 0, 0, 0, 0, 0 }, // Validity unknown /Sam
+ .gpcs = { 3, 1 }, // Validity unknown /Sam
+ .vfe_pol = { 1, 0, 0, 0, 0, 1, 0, 0 }, // Validity unknown /Sam
+ .gws_not_connected = 1,
+ .input_mux = 1,
+ .init = &avs6eyes_init,
+ }
+
+};
+
+/*
+ * I2C functions
+ */
+/* software I2C functions */
+static int zoran_i2c_getsda(void *data)
+{
+ struct zoran *zr = (struct zoran *)data;
+
+ return (btread(ZR36057_I2CBR) >> 1) & 1;
+}
+
+static int zoran_i2c_getscl(void *data)
+{
+ struct zoran *zr = (struct zoran *)data;
+
+ return btread(ZR36057_I2CBR) & 1;
+}
+
+static void zoran_i2c_setsda(void *data, int state)
+{
+ struct zoran *zr = (struct zoran *)data;
+
+ if (state)
+ zr->i2cbr |= 2;
+ else
+ zr->i2cbr &= ~2;
+ btwrite(zr->i2cbr, ZR36057_I2CBR);
+}
+
+static void zoran_i2c_setscl(void *data, int state)
+{
+ struct zoran *zr = (struct zoran *)data;
+
+ if (state)
+ zr->i2cbr |= 1;
+ else
+ zr->i2cbr &= ~1;
+ btwrite(zr->i2cbr, ZR36057_I2CBR);
+}
+
+static const struct i2c_algo_bit_data zoran_i2c_bit_data_template = {
+ .setsda = zoran_i2c_setsda,
+ .setscl = zoran_i2c_setscl,
+ .getsda = zoran_i2c_getsda,
+ .getscl = zoran_i2c_getscl,
+ .udelay = 10,
+ .timeout = 100,
+};
+
+static int zoran_register_i2c(struct zoran *zr)
+{
+ zr->i2c_algo = zoran_i2c_bit_data_template;
+ zr->i2c_algo.data = zr;
+ strscpy(zr->i2c_adapter.name, ZR_DEVNAME(zr),
+ sizeof(zr->i2c_adapter.name));
+ i2c_set_adapdata(&zr->i2c_adapter, &zr->v4l2_dev);
+ zr->i2c_adapter.algo_data = &zr->i2c_algo;
+ zr->i2c_adapter.dev.parent = &zr->pci_dev->dev;
+ return i2c_bit_add_bus(&zr->i2c_adapter);
+}
+
+static void zoran_unregister_i2c(struct zoran *zr)
+{
+ i2c_del_adapter(&zr->i2c_adapter);
+}
+
+/* Check a zoran_params struct for correctness, insert default params */
+int zoran_check_jpg_settings(struct zoran *zr,
+ struct zoran_jpg_settings *settings, int try)
+{
+ int err = 0, err0 = 0;
+
+ pci_dbg(zr->pci_dev, "%s - dec: %d, Hdcm: %d, Vdcm: %d, Tdcm: %d\n",
+ __func__, settings->decimation, settings->hor_dcm,
+ settings->ver_dcm, settings->tmp_dcm);
+ pci_dbg(zr->pci_dev, "%s - x: %d, y: %d, w: %d, y: %d\n", __func__,
+ settings->img_x, settings->img_y,
+ settings->img_width, settings->img_height);
+ /* Check decimation, set default values for decimation = 1, 2, 4 */
+ switch (settings->decimation) {
+ case 1:
+
+ settings->hor_dcm = 1;
+ settings->ver_dcm = 1;
+ settings->tmp_dcm = 1;
+ settings->field_per_buff = 2;
+ settings->img_x = 0;
+ settings->img_y = 0;
+ settings->img_width = BUZ_MAX_WIDTH;
+ settings->img_height = BUZ_MAX_HEIGHT / 2;
+ break;
+ case 2:
+
+ settings->hor_dcm = 2;
+ settings->ver_dcm = 1;
+ settings->tmp_dcm = 2;
+ settings->field_per_buff = 1;
+ settings->img_x = (BUZ_MAX_WIDTH == 720) ? 8 : 0;
+ settings->img_y = 0;
+ settings->img_width =
+ (BUZ_MAX_WIDTH == 720) ? 704 : BUZ_MAX_WIDTH;
+ settings->img_height = BUZ_MAX_HEIGHT / 2;
+ break;
+ case 4:
+
+ if (zr->card.type == DC10_NEW) {
+ pci_dbg(zr->pci_dev,
+ "%s - HDec by 4 is not supported on the DC10\n",
+ __func__);
+ err0++;
+ break;
+ }
+
+ settings->hor_dcm = 4;
+ settings->ver_dcm = 2;
+ settings->tmp_dcm = 2;
+ settings->field_per_buff = 1;
+ settings->img_x = (BUZ_MAX_WIDTH == 720) ? 8 : 0;
+ settings->img_y = 0;
+ settings->img_width =
+ (BUZ_MAX_WIDTH == 720) ? 704 : BUZ_MAX_WIDTH;
+ settings->img_height = BUZ_MAX_HEIGHT / 2;
+ break;
+ case 0:
+
+ /* We have to check the data the user has set */
+
+ if (settings->hor_dcm != 1 && settings->hor_dcm != 2 &&
+ (zr->card.type == DC10_NEW || settings->hor_dcm != 4)) {
+ settings->hor_dcm = clamp(settings->hor_dcm, 1, 2);
+ err0++;
+ }
+ if (settings->ver_dcm != 1 && settings->ver_dcm != 2) {
+ settings->ver_dcm = clamp(settings->ver_dcm, 1, 2);
+ err0++;
+ }
+ if (settings->tmp_dcm != 1 && settings->tmp_dcm != 2) {
+ settings->tmp_dcm = clamp(settings->tmp_dcm, 1, 2);
+ err0++;
+ }
+ if (settings->field_per_buff != 1 &&
+ settings->field_per_buff != 2) {
+ settings->field_per_buff = clamp(settings->field_per_buff, 1, 2);
+ err0++;
+ }
+ if (settings->img_x < 0) {
+ settings->img_x = 0;
+ err0++;
+ }
+ if (settings->img_y < 0) {
+ settings->img_y = 0;
+ err0++;
+ }
+ if (settings->img_width < 0 || settings->img_width > BUZ_MAX_WIDTH) {
+ settings->img_width = clamp(settings->img_width, 0, (int)BUZ_MAX_WIDTH);
+ err0++;
+ }
+ if (settings->img_height < 0 || settings->img_height > BUZ_MAX_HEIGHT / 2) {
+ settings->img_height = clamp(settings->img_height, 0, BUZ_MAX_HEIGHT / 2);
+ err0++;
+ }
+ if (settings->img_x + settings->img_width > BUZ_MAX_WIDTH) {
+ settings->img_x = BUZ_MAX_WIDTH - settings->img_width;
+ err0++;
+ }
+ if (settings->img_y + settings->img_height > BUZ_MAX_HEIGHT / 2) {
+ settings->img_y = BUZ_MAX_HEIGHT / 2 - settings->img_height;
+ err0++;
+ }
+ if (settings->img_width % (16 * settings->hor_dcm) != 0) {
+ settings->img_width -= settings->img_width % (16 * settings->hor_dcm);
+ if (settings->img_width == 0)
+ settings->img_width = 16 * settings->hor_dcm;
+ err0++;
+ }
+ if (settings->img_height % (8 * settings->ver_dcm) != 0) {
+ settings->img_height -= settings->img_height % (8 * settings->ver_dcm);
+ if (settings->img_height == 0)
+ settings->img_height = 8 * settings->ver_dcm;
+ err0++;
+ }
+
+ if (!try && err0) {
+ pci_err(zr->pci_dev, "%s - error in params for decimation = 0\n", __func__);
+ err++;
+ }
+ break;
+ default:
+ pci_err(zr->pci_dev, "%s - decimation = %d, must be 0, 1, 2 or 4\n",
+ __func__, settings->decimation);
+ err++;
+ break;
+ }
+
+ if (settings->jpg_comp.quality > 100)
+ settings->jpg_comp.quality = 100;
+ if (settings->jpg_comp.quality < 5)
+ settings->jpg_comp.quality = 5;
+ if (settings->jpg_comp.APPn < 0)
+ settings->jpg_comp.APPn = 0;
+ if (settings->jpg_comp.APPn > 15)
+ settings->jpg_comp.APPn = 15;
+ if (settings->jpg_comp.APP_len < 0)
+ settings->jpg_comp.APP_len = 0;
+ if (settings->jpg_comp.APP_len > 60)
+ settings->jpg_comp.APP_len = 60;
+ if (settings->jpg_comp.COM_len < 0)
+ settings->jpg_comp.COM_len = 0;
+ if (settings->jpg_comp.COM_len > 60)
+ settings->jpg_comp.COM_len = 60;
+ if (err)
+ return -EINVAL;
+ return 0;
+}
+
+static int zoran_init_video_device(struct zoran *zr, struct video_device *video_dev, int dir)
+{
+ int err;
+
+ /* Now add the template and register the device unit. */
+ *video_dev = zoran_template;
+ video_dev->v4l2_dev = &zr->v4l2_dev;
+ video_dev->lock = &zr->lock;
+ video_dev->device_caps = V4L2_CAP_STREAMING | dir;
+
+ strscpy(video_dev->name, ZR_DEVNAME(zr), sizeof(video_dev->name));
+ video_dev->vfl_dir = VFL_DIR_RX;
+ zoran_queue_init(zr, &zr->vq, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+
+ err = video_register_device(video_dev, VFL_TYPE_VIDEO, video_nr[zr->id]);
+ if (err < 0)
+ return err;
+ video_set_drvdata(video_dev, zr);
+ return 0;
+}
+
+static void zoran_exit_video_devices(struct zoran *zr)
+{
+ video_unregister_device(zr->video_dev);
+ kfree(zr->video_dev);
+}
+
+static int zoran_init_video_devices(struct zoran *zr)
+{
+ int err;
+
+ zr->video_dev = video_device_alloc();
+ if (!zr->video_dev)
+ return -ENOMEM;
+
+ err = zoran_init_video_device(zr, zr->video_dev, V4L2_CAP_VIDEO_CAPTURE);
+ if (err)
+ kfree(zr->video_dev);
+ return err;
+}
+
+/*
+ * v4l2_device_unregister() will care about removing zr->encoder/zr->decoder
+ * via v4l2_i2c_subdev_unregister()
+ */
+static int zoran_i2c_init(struct zoran *zr)
+{
+ int err;
+
+ pci_info(zr->pci_dev, "Initializing i2c bus...\n");
+
+ err = zoran_register_i2c(zr);
+ if (err) {
+ pci_err(zr->pci_dev, "%s - cannot initialize i2c bus\n", __func__);
+ return err;
+ }
+
+ zr->decoder = v4l2_i2c_new_subdev(&zr->v4l2_dev, &zr->i2c_adapter,
+ zr->card.i2c_decoder, 0,
+ zr->card.addrs_decoder);
+ if (!zr->decoder) {
+ pci_err(zr->pci_dev, "Fail to get decoder %s\n", zr->card.i2c_decoder);
+ err = -EINVAL;
+ goto error_decoder;
+ }
+
+ if (zr->card.i2c_encoder) {
+ zr->encoder = v4l2_i2c_new_subdev(&zr->v4l2_dev, &zr->i2c_adapter,
+ zr->card.i2c_encoder, 0,
+ zr->card.addrs_encoder);
+ if (!zr->encoder) {
+ pci_err(zr->pci_dev, "Fail to get encoder %s\n", zr->card.i2c_encoder);
+ err = -EINVAL;
+ goto error_decoder;
+ }
+ }
+ return 0;
+
+error_decoder:
+ zoran_unregister_i2c(zr);
+ return err;
+}
+
+static void zoran_i2c_exit(struct zoran *zr)
+{
+ zoran_unregister_i2c(zr);
+}
+
+void zoran_open_init_params(struct zoran *zr)
+{
+ int i;
+
+ zr->v4l_settings.width = 192;
+ zr->v4l_settings.height = 144;
+ zr->v4l_settings.format = &zoran_formats[7]; /* YUY2 - YUV-4:2:2 packed */
+ zr->v4l_settings.bytesperline = zr->v4l_settings.width *
+ ((zr->v4l_settings.format->depth + 7) / 8);
+
+ /* Set necessary params and call zoran_check_jpg_settings to set the defaults */
+ zr->jpg_settings.decimation = 1;
+ zr->jpg_settings.jpg_comp.quality = 50; /* default compression factor 8 */
+ if (zr->card.type != BUZ)
+ zr->jpg_settings.odd_even = 1;
+ else
+ zr->jpg_settings.odd_even = 0;
+ zr->jpg_settings.jpg_comp.APPn = 0;
+ zr->jpg_settings.jpg_comp.APP_len = 0; /* No APPn marker */
+ memset(zr->jpg_settings.jpg_comp.APP_data, 0,
+ sizeof(zr->jpg_settings.jpg_comp.APP_data));
+ zr->jpg_settings.jpg_comp.COM_len = 0; /* No COM marker */
+ memset(zr->jpg_settings.jpg_comp.COM_data, 0,
+ sizeof(zr->jpg_settings.jpg_comp.COM_data));
+ zr->jpg_settings.jpg_comp.jpeg_markers =
+ V4L2_JPEG_MARKER_DHT | V4L2_JPEG_MARKER_DQT;
+ i = zoran_check_jpg_settings(zr, &zr->jpg_settings, 0);
+ if (i)
+ pci_err(zr->pci_dev, "%s internal error\n", __func__);
+
+ zr->buffer_size = zr->v4l_settings.bytesperline * zr->v4l_settings.height;
+
+ clear_interrupt_counters(zr);
+}
+
+static int zr36057_init(struct zoran *zr)
+{
+ int j, err;
+
+ pci_info(zr->pci_dev, "initializing card[%d]\n", zr->id);
+
+ /* Avoid nonsense settings from user for default input/norm */
+ if (default_norm < 0 || default_norm > 2)
+ default_norm = 0;
+ if (default_norm == 0) {
+ zr->norm = V4L2_STD_PAL;
+ zr->timing = zr->card.tvn[ZR_NORM_PAL];
+ } else if (default_norm == 1) {
+ zr->norm = V4L2_STD_NTSC;
+ zr->timing = zr->card.tvn[ZR_NORM_NTSC];
+ } else {
+ zr->norm = V4L2_STD_SECAM;
+ zr->timing = zr->card.tvn[ZR_NORM_SECAM];
+ }
+ if (!zr->timing) {
+ pci_warn(zr->pci_dev,
+ "%s - default TV standard not supported by hardware. PAL will be used.\n",
+ __func__);
+ zr->norm = V4L2_STD_PAL;
+ zr->timing = zr->card.tvn[ZR_NORM_PAL];
+ }
+
+ if (default_input > zr->card.inputs - 1) {
+ pci_warn(zr->pci_dev, "default_input value %d out of range (0-%d)\n",
+ default_input, zr->card.inputs - 1);
+ default_input = 0;
+ }
+ zr->input = default_input;
+
+ /* default setup (will be repeated at every open) */
+ zoran_open_init_params(zr);
+
+ /* allocate memory *before* doing anything to the hardware in case allocation fails */
+ zr->stat_com = dma_alloc_coherent(&zr->pci_dev->dev,
+ BUZ_NUM_STAT_COM * sizeof(u32),
+ &zr->p_sc, GFP_KERNEL);
+ if (!zr->stat_com)
+ return -ENOMEM;
+
+ for (j = 0; j < BUZ_NUM_STAT_COM; j++)
+ zr->stat_com[j] = cpu_to_le32(1); /* mark as unavailable to zr36057 */
+
+ zr->stat_comb = dma_alloc_coherent(&zr->pci_dev->dev,
+ BUZ_NUM_STAT_COM * sizeof(u32) * 2,
+ &zr->p_scb, GFP_KERNEL);
+ if (!zr->stat_comb) {
+ err = -ENOMEM;
+ goto exit_statcom;
+ }
+
+ err = zoran_init_video_devices(zr);
+ if (err)
+ goto exit_statcomb;
+
+ zoran_init_hardware(zr);
+ if (!pass_through) {
+ decoder_call(zr, video, s_stream, 0);
+ encoder_call(zr, video, s_routing, 2, 0, 0);
+ }
+
+ zr->initialized = 1;
+ return 0;
+
+exit_statcomb:
+ dma_free_coherent(&zr->pci_dev->dev, BUZ_NUM_STAT_COM * sizeof(u32) * 2,
+ zr->stat_comb, zr->p_scb);
+exit_statcom:
+ dma_free_coherent(&zr->pci_dev->dev, BUZ_NUM_STAT_COM * sizeof(u32),
+ zr->stat_com, zr->p_sc);
+ return err;
+}
+
+static void zoran_remove(struct pci_dev *pdev)
+{
+ struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev);
+ struct zoran *zr = to_zoran(v4l2_dev);
+
+ if (!zr->initialized)
+ goto exit_free;
+
+ debugfs_remove_recursive(zr->dbgfs_dir);
+
+ zoran_queue_exit(zr);
+
+ /* unregister videocodec bus */
+ if (zr->codec)
+ videocodec_detach(zr->codec);
+ if (zr->vfe)
+ videocodec_detach(zr->vfe);
+ videocodec_exit(zr);
+
+ /* unregister i2c bus */
+ zoran_i2c_exit(zr);
+ /* disable PCI bus-mastering */
+ zoran_set_pci_master(zr, 0);
+ /* put chip into reset */
+ btwrite(0, ZR36057_SPGPPCR);
+ pci_free_irq(zr->pci_dev, 0, zr);
+ /* unmap and free memory */
+ dma_free_coherent(&zr->pci_dev->dev, BUZ_NUM_STAT_COM * sizeof(u32),
+ zr->stat_com, zr->p_sc);
+ dma_free_coherent(&zr->pci_dev->dev, BUZ_NUM_STAT_COM * sizeof(u32) * 2,
+ zr->stat_comb, zr->p_scb);
+ pci_release_regions(pdev);
+ pci_disable_device(zr->pci_dev);
+ zoran_exit_video_devices(zr);
+exit_free:
+ v4l2_ctrl_handler_free(&zr->hdl);
+ v4l2_device_unregister(&zr->v4l2_dev);
+}
+
+void zoran_vdev_release(struct video_device *vdev)
+{
+ kfree(vdev);
+}
+
+static struct videocodec_master *zoran_setup_videocodec(struct zoran *zr,
+ int type)
+{
+ struct videocodec_master *m = NULL;
+
+ m = devm_kmalloc(&zr->pci_dev->dev, sizeof(*m), GFP_KERNEL);
+ if (!m)
+ return m;
+
+ /*
+ * magic and type are unused for master struct. Makes sense only at codec structs.
+ * In the past, .type were initialized to the old V4L1 .hardware value,
+ * as VID_HARDWARE_ZR36067
+ */
+ m->magic = 0L;
+ m->type = 0;
+
+ m->flags = CODEC_FLAG_ENCODER | CODEC_FLAG_DECODER;
+ strscpy(m->name, ZR_DEVNAME(zr), sizeof(m->name));
+ m->data = zr;
+
+ switch (type) {
+ case CODEC_TYPE_ZR36060:
+ m->readreg = zr36060_read;
+ m->writereg = zr36060_write;
+ m->flags |= CODEC_FLAG_JPEG | CODEC_FLAG_VFE;
+ break;
+ case CODEC_TYPE_ZR36050:
+ m->readreg = zr36050_read;
+ m->writereg = zr36050_write;
+ m->flags |= CODEC_FLAG_JPEG;
+ break;
+ case CODEC_TYPE_ZR36016:
+ m->readreg = zr36016_read;
+ m->writereg = zr36016_write;
+ m->flags |= CODEC_FLAG_VFE;
+ break;
+ }
+
+ return m;
+}
+
+static void zoran_subdev_notify(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
+{
+ struct zoran *zr = to_zoran(sd->v4l2_dev);
+
+ /*
+ * Bt819 needs to reset its FIFO buffer using #FRST pin and
+ * LML33 card uses GPIO(7) for that.
+ */
+ if (cmd == BT819_FIFO_RESET_LOW)
+ GPIO(zr, 7, 0);
+ else if (cmd == BT819_FIFO_RESET_HIGH)
+ GPIO(zr, 7, 1);
+}
+
+static int zoran_video_set_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct zoran *zr = container_of(ctrl->handler, struct zoran, hdl);
+
+ switch (ctrl->id) {
+ case V4L2_CID_JPEG_COMPRESSION_QUALITY:
+ zr->jpg_settings.jpg_comp.quality = ctrl->val;
+ return zoran_check_jpg_settings(zr, &zr->jpg_settings, 0);
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct v4l2_ctrl_ops zoran_video_ctrl_ops = {
+ .s_ctrl = zoran_video_set_ctrl,
+};
+
+static int zoran_debugfs_show(struct seq_file *seq, void *v)
+{
+ struct zoran *zr = seq->private;
+
+ seq_printf(seq, "Running mode %x\n", zr->running);
+ seq_printf(seq, "Codec mode %x\n", zr->codec_mode);
+ seq_printf(seq, "Norm %llx\n", zr->norm);
+ seq_printf(seq, "Input %d\n", zr->input);
+ seq_printf(seq, "Buffersize %d\n", zr->buffer_size);
+
+ seq_printf(seq, "V4L width %dx%d\n", zr->v4l_settings.width, zr->v4l_settings.height);
+ seq_printf(seq, "V4L bytesperline %d\n", zr->v4l_settings.bytesperline);
+
+ seq_printf(seq, "JPG decimation %u\n", zr->jpg_settings.decimation);
+ seq_printf(seq, "JPG hor_dcm %u\n", zr->jpg_settings.hor_dcm);
+ seq_printf(seq, "JPG ver_dcm %u\n", zr->jpg_settings.ver_dcm);
+ seq_printf(seq, "JPG tmp_dcm %u\n", zr->jpg_settings.tmp_dcm);
+ seq_printf(seq, "JPG odd_even %u\n", zr->jpg_settings.odd_even);
+ seq_printf(seq, "JPG crop %dx%d %d %d\n",
+ zr->jpg_settings.img_x,
+ zr->jpg_settings.img_y,
+ zr->jpg_settings.img_width,
+ zr->jpg_settings.img_height);
+
+ seq_printf(seq, "Prepared %u\n", zr->prepared);
+ seq_printf(seq, "Queued %u\n", zr->queued);
+
+ videocodec_debugfs_show(seq);
+ return 0;
+}
+
+DEFINE_SHOW_ATTRIBUTE(zoran_debugfs);
+
+/*
+ * Scan for a Buz card (actually for the PCI controller ZR36057),
+ * request the irq and map the io memory
+ */
+static int zoran_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ unsigned char latency, need_latency;
+ struct zoran *zr;
+ int result;
+ struct videocodec_master *master_vfe = NULL;
+ struct videocodec_master *master_codec = NULL;
+ int card_num;
+ unsigned int nr;
+ int err;
+
+ pci_info(pdev, "Zoran MJPEG board driver version %s\n", ZORAN_VERSION);
+
+ /* some mainboards might not do PCI-PCI data transfer well */
+ if (pci_pci_problems & (PCIPCI_FAIL | PCIAGP_FAIL | PCIPCI_ALIMAGIK))
+ pci_warn(pdev, "%s: chipset does not support reliable PCI-PCI DMA\n",
+ ZORAN_NAME);
+
+ err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+ if (err)
+ return err;
+ err = vb2_dma_contig_set_max_seg_size(&pdev->dev, U32_MAX);
+ if (err)
+ return err;
+
+ nr = zoran_num++;
+ if (nr >= BUZ_MAX) {
+ pci_err(pdev, "driver limited to %d card(s) maximum\n", BUZ_MAX);
+ return -ENOENT;
+ }
+
+ zr = devm_kzalloc(&pdev->dev, sizeof(*zr), GFP_KERNEL);
+ if (!zr)
+ return -ENOMEM;
+
+ zr->v4l2_dev.notify = zoran_subdev_notify;
+ if (v4l2_device_register(&pdev->dev, &zr->v4l2_dev))
+ goto zr_free_mem;
+ 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;
+ v4l2_ctrl_new_std(&zr->hdl, &zoran_video_ctrl_ops,
+ V4L2_CID_JPEG_COMPRESSION_QUALITY, 0,
+ 100, 1, 50);
+ spin_lock_init(&zr->spinlock);
+ mutex_init(&zr->lock);
+ if (pci_enable_device(pdev))
+ goto zr_unreg;
+ zr->revision = zr->pci_dev->revision;
+
+ pci_info(zr->pci_dev, "Zoran ZR360%c7 (rev %d), irq: %d, memory: 0x%08llx\n",
+ zr->revision < 2 ? '5' : '6', zr->revision,
+ zr->pci_dev->irq, (uint64_t)pci_resource_start(zr->pci_dev, 0));
+ if (zr->revision >= 2)
+ pci_info(zr->pci_dev, "Subsystem vendor=0x%04x id=0x%04x\n",
+ zr->pci_dev->subsystem_vendor, zr->pci_dev->subsystem_device);
+
+ /* Use auto-detected card type? */
+ if (card[nr] == -1) {
+ if (zr->revision < 2) {
+ pci_err(pdev, "No card type specified, please use the card=X module parameter\n");
+ pci_err(pdev, "It is not possible to auto-detect ZR36057 based cards\n");
+ goto zr_unreg;
+ }
+
+ card_num = ent->driver_data;
+ if (card_num >= NUM_CARDS) {
+ pci_err(pdev, "Unknown card, try specifying card=X module parameter\n");
+ goto zr_unreg;
+ }
+ pci_info(zr->pci_dev, "%s() - card %s detected\n", __func__,
+ zoran_cards[card_num].name);
+ } else {
+ card_num = card[nr];
+ if (card_num >= NUM_CARDS || card_num < 0) {
+ pci_err(pdev, "User specified card type %d out of range (0 .. %d)\n",
+ card_num, NUM_CARDS - 1);
+ goto zr_unreg;
+ }
+ }
+
+ /*
+ * even though we make this a non pointer and thus
+ * theoretically allow for making changes to this struct
+ * on a per-individual card basis at runtime, this is
+ * strongly discouraged. This structure is intended to
+ * keep general card information, no settings or anything
+ */
+ zr->card = zoran_cards[card_num];
+ snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)), "%s[%u]",
+ zr->card.name, zr->id);
+
+ err = pci_request_regions(pdev, ZR_DEVNAME(zr));
+ if (err)
+ goto zr_unreg;
+
+ zr->zr36057_mem = devm_ioremap(&pdev->dev, pci_resource_start(pdev, 0),
+ pci_resource_len(pdev, 0));
+ if (!zr->zr36057_mem) {
+ pci_err(pdev, "%s() - ioremap failed\n", __func__);
+ goto zr_pci_release;
+ }
+
+ result = pci_request_irq(pdev, 0, zoran_irq, NULL, zr, ZR_DEVNAME(zr));
+ if (result < 0) {
+ if (result == -EINVAL) {
+ pci_err(pdev, "%s - bad IRQ number or handler\n", __func__);
+ } else if (result == -EBUSY) {
+ pci_err(pdev, "%s - IRQ %d busy, change your PnP config in BIOS\n",
+ __func__, zr->pci_dev->irq);
+ } else {
+ pci_err(pdev, "%s - cannot assign IRQ, error code %d\n", __func__, result);
+ }
+ goto zr_pci_release;
+ }
+
+ /* set PCI latency timer */
+ pci_read_config_byte(zr->pci_dev, PCI_LATENCY_TIMER,
+ &latency);
+ need_latency = zr->revision > 1 ? 32 : 48;
+ if (latency != need_latency) {
+ pci_info(zr->pci_dev, "Changing PCI latency from %d to %d\n",
+ latency, need_latency);
+ pci_write_config_byte(zr->pci_dev, PCI_LATENCY_TIMER, need_latency);
+ }
+
+ zr36057_restart(zr);
+
+ err = zoran_i2c_init(zr);
+ if (err)
+ goto zr_free_irq;
+
+ pci_info(zr->pci_dev, "Initializing videocodec bus...\n");
+ err = videocodec_init(zr);
+ if (err)
+ goto zr_unreg_i2c;
+
+ /* reset JPEG codec */
+ jpeg_codec_sleep(zr, 1);
+ jpeg_codec_reset(zr);
+ /* video bus enabled */
+ /* display codec revision */
+ if (zr->card.video_codec != 0) {
+ master_codec = zoran_setup_videocodec(zr, zr->card.video_codec);
+ if (!master_codec)
+ goto zr_unreg_videocodec;
+ zr->codec = videocodec_attach(master_codec);
+ if (!zr->codec) {
+ pci_err(pdev, "%s - no codec found\n", __func__);
+ goto zr_unreg_videocodec;
+ }
+ if (zr->codec->type != zr->card.video_codec) {
+ pci_err(pdev, "%s - wrong codec\n", __func__);
+ goto zr_unreg_videocodec;
+ }
+ }
+ if (zr->card.video_vfe != 0) {
+ master_vfe = zoran_setup_videocodec(zr, zr->card.video_vfe);
+ if (!master_vfe)
+ goto zr_detach_codec;
+ zr->vfe = videocodec_attach(master_vfe);
+ if (!zr->vfe) {
+ pci_err(pdev, "%s - no VFE found\n", __func__);
+ goto zr_detach_codec;
+ }
+ if (zr->vfe->type != zr->card.video_vfe) {
+ pci_err(pdev, "%s = wrong VFE\n", __func__);
+ goto zr_detach_vfe;
+ }
+ }
+
+ /* take care of Natoma chipset and a revision 1 zr36057 */
+ if ((pci_pci_problems & PCIPCI_NATOMA) && zr->revision <= 1)
+ pci_info(zr->pci_dev, "ZR36057/Natoma bug, max. buffer size is 128K\n");
+
+ if (zr36057_init(zr) < 0)
+ goto zr_detach_vfe;
+
+ zr->map_mode = ZORAN_MAP_MODE_RAW;
+
+ zr->dbgfs_dir = debugfs_create_dir(ZR_DEVNAME(zr), NULL);
+ debugfs_create_file("debug", 0444, zr->dbgfs_dir, zr,
+ &zoran_debugfs_fops);
+ return 0;
+
+zr_detach_vfe:
+ videocodec_detach(zr->vfe);
+zr_detach_codec:
+ videocodec_detach(zr->codec);
+zr_unreg_videocodec:
+ videocodec_exit(zr);
+zr_unreg_i2c:
+ zoran_i2c_exit(zr);
+zr_free_irq:
+ btwrite(0, ZR36057_SPGPPCR);
+ pci_free_irq(zr->pci_dev, 0, zr);
+zr_pci_release:
+ pci_release_regions(pdev);
+zr_unreg:
+ v4l2_ctrl_handler_free(&zr->hdl);
+ v4l2_device_unregister(&zr->v4l2_dev);
+zr_free_mem:
+
+ return -ENODEV;
+}
+
+static struct pci_driver zoran_driver = {
+ .name = "zr36067",
+ .id_table = zr36067_pci_tbl,
+ .probe = zoran_probe,
+ .remove = zoran_remove,
+};
+
+module_pci_driver(zoran_driver);
diff --git a/drivers/media/pci/zoran/zoran_card.h b/drivers/media/pci/zoran/zoran_card.h
new file mode 100644
index 000000000000..518cb426b446
--- /dev/null
+++ b/drivers/media/pci/zoran/zoran_card.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Zoran zr36057/zr36067 PCI controller driver, for the
+ * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux
+ * Media Labs LML33/LML33R10.
+ *
+ * This part handles card-specific data and detection
+ *
+ * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
+ */
+
+#ifndef __ZORAN_CARD_H__
+#define __ZORAN_CARD_H__
+
+extern int zr36067_debug;
+
+/* Anybody who uses more than four? */
+#define BUZ_MAX 4
+
+extern const struct video_device zoran_template;
+
+int zoran_check_jpg_settings(struct zoran *zr,
+ struct zoran_jpg_settings *settings, int try);
+void zoran_open_init_params(struct zoran *zr);
+void zoran_vdev_release(struct video_device *vdev);
+
+void zr36016_write(struct videocodec *codec, u16 reg, u32 val);
+
+#endif /* __ZORAN_CARD_H__ */
diff --git a/drivers/media/pci/zoran/zoran_device.c b/drivers/media/pci/zoran/zoran_device.c
new file mode 100644
index 000000000000..31f049b55529
--- /dev/null
+++ b/drivers/media/pci/zoran/zoran_device.c
@@ -0,0 +1,956 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Zoran zr36057/zr36067 PCI controller driver, for the
+ * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux
+ * Media Labs LML33/LML33R10.
+ *
+ * This part handles device access (PCI/I2C/codec/...)
+ *
+ * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <linux/spinlock.h>
+
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/wait.h>
+#include <linux/dma-mapping.h>
+
+#include <linux/io.h>
+
+#include "videocodec.h"
+#include "zoran.h"
+#include "zoran_device.h"
+#include "zoran_card.h"
+
+#define IRQ_MASK (ZR36057_ISR_GIRQ0 | \
+ ZR36057_ISR_GIRQ1 | \
+ ZR36057_ISR_JPEG_REP_IRQ)
+
+static bool lml33dpath; /* default = 0
+ * 1 will use digital path in capture
+ * mode instead of analog. It can be
+ * used for picture adjustments using
+ * tool like xawtv while watching image
+ * on TV monitor connected to the output.
+ * However, due to absence of 75 Ohm
+ * load on Bt819 input, there will be
+ * some image imperfections
+ */
+
+module_param(lml33dpath, bool, 0644);
+MODULE_PARM_DESC(lml33dpath, "Use digital path capture mode (on LML33 cards)");
+
+/*
+ * initialize video front end
+ */
+static void zr36057_init_vfe(struct zoran *zr)
+{
+ u32 reg;
+
+ reg = btread(ZR36057_VFESPFR);
+ reg |= ZR36057_VFESPFR_LITTLE_ENDIAN;
+ reg &= ~ZR36057_VFESPFR_VCLK_POL;
+ reg |= ZR36057_VFESPFR_EXT_FL;
+ reg |= ZR36057_VFESPFR_TOP_FIELD;
+ btwrite(reg, ZR36057_VFESPFR);
+ reg = btread(ZR36057_VDCR);
+ if (pci_pci_problems & PCIPCI_TRITON)
+ // || zr->revision < 1) // Revision 1 has also Triton support
+ reg &= ~ZR36057_VDCR_TRITON;
+ else
+ reg |= ZR36057_VDCR_TRITON;
+ btwrite(reg, ZR36057_VDCR);
+}
+
+/*
+ * General Purpose I/O and Guest bus access
+ */
+
+/*
+ * This is a bit tricky. When a board lacks a GPIO function, the corresponding
+ * GPIO bit number in the card_info structure is set to 0.
+ */
+
+void GPIO(struct zoran *zr, int bit, unsigned int value)
+{
+ u32 reg;
+ u32 mask;
+
+ /* Make sure the bit number is legal
+ * A bit number of -1 (lacking) gives a mask of 0,
+ * making it harmless
+ */
+ mask = (1 << (24 + bit)) & 0xff000000;
+ reg = btread(ZR36057_GPPGCR1) & ~mask;
+ if (value)
+ reg |= mask;
+
+ btwrite(reg, ZR36057_GPPGCR1);
+ udelay(1);
+}
+
+/*
+ * Wait til post office is no longer busy
+ */
+
+int post_office_wait(struct zoran *zr)
+{
+ u32 por;
+
+ while ((por = btread(ZR36057_POR)) & ZR36057_POR_PO_PEN) {
+ /* wait for something to happen */
+ /* TODO add timeout */
+ }
+ if ((por & ZR36057_POR_PO_TIME) && !zr->card.gws_not_connected) {
+ /* In LML33/BUZ \GWS line is not connected, so it has always timeout set */
+ pci_info(zr->pci_dev, "pop timeout %08x\n", por);
+ return -1;
+ }
+
+ return 0;
+}
+
+int post_office_write(struct zoran *zr, unsigned int guest,
+ unsigned int reg, unsigned int value)
+{
+ u32 por;
+
+ por =
+ ZR36057_POR_PO_DIR | ZR36057_POR_PO_TIME | ((guest & 7) << 20) |
+ ((reg & 7) << 16) | (value & 0xFF);
+ btwrite(por, ZR36057_POR);
+
+ return post_office_wait(zr);
+}
+
+int post_office_read(struct zoran *zr, unsigned int guest, unsigned int reg)
+{
+ u32 por;
+
+ por = ZR36057_POR_PO_TIME | ((guest & 7) << 20) | ((reg & 7) << 16);
+ btwrite(por, ZR36057_POR);
+ if (post_office_wait(zr) < 0)
+ return -1;
+
+ return btread(ZR36057_POR) & 0xFF;
+}
+
+/*
+ * JPEG Codec access
+ */
+
+void jpeg_codec_sleep(struct zoran *zr, int sleep)
+{
+ GPIO(zr, zr->card.gpio[ZR_GPIO_JPEG_SLEEP], !sleep);
+ if (!sleep) {
+ pci_dbg(zr->pci_dev, "%s() - wake GPIO=0x%08x\n",
+ __func__, btread(ZR36057_GPPGCR1));
+ usleep_range(500, 1000);
+ } else {
+ pci_dbg(zr->pci_dev, "%s() - sleep GPIO=0x%08x\n",
+ __func__, btread(ZR36057_GPPGCR1));
+ udelay(2);
+ }
+}
+
+int jpeg_codec_reset(struct zoran *zr)
+{
+ /* Take the codec out of sleep */
+ jpeg_codec_sleep(zr, 0);
+
+ if (zr->card.gpcs[GPCS_JPEG_RESET] != 0xff) {
+ post_office_write(zr, zr->card.gpcs[GPCS_JPEG_RESET], 0,
+ 0);
+ udelay(2);
+ } else {
+ GPIO(zr, zr->card.gpio[ZR_GPIO_JPEG_RESET], 0);
+ udelay(2);
+ GPIO(zr, zr->card.gpio[ZR_GPIO_JPEG_RESET], 1);
+ udelay(2);
+ }
+
+ return 0;
+}
+
+/*
+ * Set the registers for the size we have specified. Don't bother
+ * trying to understand this without the ZR36057 manual in front of
+ * you [AC].
+ */
+static void zr36057_adjust_vfe(struct zoran *zr, enum zoran_codec_mode mode)
+{
+ u32 reg;
+
+ switch (mode) {
+ case BUZ_MODE_MOTION_DECOMPRESS:
+ btand(~ZR36057_VFESPFR_EXT_FL, ZR36057_VFESPFR);
+ reg = btread(ZR36057_VFEHCR);
+ if ((reg & (1 << 10)) && zr->card.type != LML33R10)
+ reg += ((1 << 10) | 1);
+
+ btwrite(reg, ZR36057_VFEHCR);
+ break;
+ case BUZ_MODE_MOTION_COMPRESS:
+ case BUZ_MODE_IDLE:
+ default:
+ if ((zr->norm & V4L2_STD_NTSC) ||
+ (zr->card.type == LML33R10 &&
+ (zr->norm & V4L2_STD_PAL)))
+ btand(~ZR36057_VFESPFR_EXT_FL, ZR36057_VFESPFR);
+ else
+ btor(ZR36057_VFESPFR_EXT_FL, ZR36057_VFESPFR);
+ reg = btread(ZR36057_VFEHCR);
+ if (!(reg & (1 << 10)) && zr->card.type != LML33R10)
+ reg -= ((1 << 10) | 1);
+
+ btwrite(reg, ZR36057_VFEHCR);
+ break;
+ }
+}
+
+/*
+ * set geometry
+ */
+
+static void zr36057_set_vfe(struct zoran *zr, int video_width, int video_height,
+ const struct zoran_format *format)
+{
+ const struct tvnorm *tvn;
+ unsigned int h_start, h_end, v_start, v_end;
+ unsigned int disp_mode;
+ unsigned int vid_win_wid, vid_win_ht;
+ unsigned int hcrop1, hcrop2, vcrop1, vcrop2;
+ unsigned int wa, we, ha, he;
+ unsigned int X, Y, hor_dcm, ver_dcm;
+ u32 reg;
+
+ tvn = zr->timing;
+
+ wa = tvn->wa;
+ ha = tvn->ha;
+
+ pci_dbg(zr->pci_dev, "set_vfe() - width = %d, height = %d\n", video_width, video_height);
+
+ if (video_width < BUZ_MIN_WIDTH ||
+ video_height < BUZ_MIN_HEIGHT ||
+ video_width > wa || video_height > ha) {
+ pci_err(zr->pci_dev, "set_vfe: w=%d h=%d not valid\n", video_width, video_height);
+ return;
+ }
+
+ /**** zr36057 ****/
+
+ /* horizontal */
+ vid_win_wid = video_width;
+ X = DIV_ROUND_UP(vid_win_wid * 64, tvn->wa);
+ we = (vid_win_wid * 64) / X;
+ hor_dcm = 64 - X;
+ hcrop1 = 2 * ((tvn->wa - we) / 4);
+ hcrop2 = tvn->wa - we - hcrop1;
+ h_start = tvn->h_start ? tvn->h_start : 1;
+ /* (Ronald) Original comment:
+ * "| 1 Doesn't have any effect, tested on both a DC10 and a DC10+"
+ * this is false. It inverses chroma values on the LML33R10 (so Cr
+ * suddenly is shown as Cb and reverse, really cool effect if you
+ * want to see blue faces, not useful otherwise). So don't use |1.
+ * However, the DC10 has '0' as h_start, but does need |1, so we
+ * use a dirty check...
+ */
+ h_end = h_start + tvn->wa - 1;
+ h_start += hcrop1;
+ h_end -= hcrop2;
+ reg = ((h_start & ZR36057_VFEHCR_HMASK) << ZR36057_VFEHCR_H_START)
+ | ((h_end & ZR36057_VFEHCR_HMASK) << ZR36057_VFEHCR_H_END);
+ if (zr->card.vfe_pol.hsync_pol)
+ reg |= ZR36057_VFEHCR_HS_POL;
+ btwrite(reg, ZR36057_VFEHCR);
+
+ /* Vertical */
+ disp_mode = !(video_height > BUZ_MAX_HEIGHT / 2);
+ vid_win_ht = disp_mode ? video_height : video_height / 2;
+ Y = DIV_ROUND_UP(vid_win_ht * 64 * 2, tvn->ha);
+ he = (vid_win_ht * 64) / Y;
+ ver_dcm = 64 - Y;
+ vcrop1 = (tvn->ha / 2 - he) / 2;
+ vcrop2 = tvn->ha / 2 - he - vcrop1;
+ v_start = tvn->v_start;
+ // FIXME SnapShot times out with -1 in 768*576 on the DC10 - LP
+ v_end = v_start + tvn->ha / 2; // - 1;
+ v_start += vcrop1;
+ v_end -= vcrop2;
+ reg = ((v_start & ZR36057_VFEVCR_VMASK) << ZR36057_VFEVCR_V_START)
+ | ((v_end & ZR36057_VFEVCR_VMASK) << ZR36057_VFEVCR_V_END);
+ if (zr->card.vfe_pol.vsync_pol)
+ reg |= ZR36057_VFEVCR_VS_POL;
+ btwrite(reg, ZR36057_VFEVCR);
+
+ /* scaler and pixel format */
+ reg = 0;
+ reg |= (hor_dcm << ZR36057_VFESPFR_HOR_DCM);
+ reg |= (ver_dcm << ZR36057_VFESPFR_VER_DCM);
+ reg |= (disp_mode << ZR36057_VFESPFR_DISP_MODE);
+ /*
+ * RJ: I don't know, why the following has to be the opposite
+ * of the corresponding ZR36060 setting, but only this way
+ * we get the correct colors when uncompressing to the screen
+ */
+ //reg |= ZR36057_VFESPFR_VCLK_POL;
+ /* RJ: Don't know if that is needed for NTSC also */
+ if (!(zr->norm & V4L2_STD_NTSC))
+ reg |= ZR36057_VFESPFR_EXT_FL; // NEEDED!!!!!!! Wolfgang
+ reg |= ZR36057_VFESPFR_TOP_FIELD;
+ if (hor_dcm >= 48)
+ reg |= 3 << ZR36057_VFESPFR_H_FILTER; /* 5 tap filter */
+ else if (hor_dcm >= 32)
+ reg |= 2 << ZR36057_VFESPFR_H_FILTER; /* 4 tap filter */
+ else if (hor_dcm >= 16)
+ reg |= 1 << ZR36057_VFESPFR_H_FILTER; /* 3 tap filter */
+
+ reg |= format->vfespfr;
+ btwrite(reg, ZR36057_VFESPFR);
+
+ /* display configuration */
+ reg = (16 << ZR36057_VDCR_MIN_PIX)
+ | (vid_win_ht << ZR36057_VDCR_VID_WIN_HT)
+ | (vid_win_wid << ZR36057_VDCR_VID_WIN_WID);
+ if (pci_pci_problems & PCIPCI_TRITON)
+ // || zr->revision < 1) // Revision 1 has also Triton support
+ reg &= ~ZR36057_VDCR_TRITON;
+ else
+ reg |= ZR36057_VDCR_TRITON;
+ btwrite(reg, ZR36057_VDCR);
+
+ zr36057_adjust_vfe(zr, zr->codec_mode);
+}
+
+/* Enable/Disable uncompressed memory grabbing of the 36057 */
+void zr36057_set_memgrab(struct zoran *zr, int mode)
+{
+ if (mode) {
+ /* We only check SnapShot and not FrameGrab here. SnapShot==1
+ * means a capture is already in progress, but FrameGrab==1
+ * doesn't necessary mean that. It's more correct to say a 1
+ * to 0 transition indicates a capture completed. If a
+ * capture is pending when capturing is tuned off, FrameGrab
+ * will be stuck at 1 until capturing is turned back on.
+ */
+ if (btread(ZR36057_VSSFGR) & ZR36057_VSSFGR_SNAP_SHOT)
+ pci_warn(zr->pci_dev, "%s(1) with SnapShot on!?\n", __func__);
+
+ /* switch on VSync interrupts */
+ btwrite(IRQ_MASK, ZR36057_ISR); // Clear Interrupts
+ btor(zr->card.vsync_int, ZR36057_ICR); // SW
+
+ /* enable SnapShot */
+ btor(ZR36057_VSSFGR_SNAP_SHOT, ZR36057_VSSFGR);
+
+ /* Set zr36057 video front end and enable video */
+ zr36057_set_vfe(zr, zr->v4l_settings.width,
+ zr->v4l_settings.height,
+ zr->v4l_settings.format);
+ } else {
+ /* switch off VSync interrupts */
+ btand(~zr->card.vsync_int, ZR36057_ICR); // SW
+
+ /* re-enable grabbing to screen if it was running */
+ btand(~ZR36057_VDCR_VID_EN, ZR36057_VDCR);
+ btand(~ZR36057_VSSFGR_SNAP_SHOT, ZR36057_VSSFGR);
+ }
+}
+
+/*****************************************************************************
+ * *
+ * Set up the Buz-specific MJPEG part *
+ * *
+ *****************************************************************************/
+
+static inline void set_frame(struct zoran *zr, int val)
+{
+ GPIO(zr, zr->card.gpio[ZR_GPIO_JPEG_FRAME], val);
+}
+
+static void set_videobus_dir(struct zoran *zr, int val)
+{
+ switch (zr->card.type) {
+ case LML33:
+ case LML33R10:
+ if (!lml33dpath)
+ GPIO(zr, 5, val);
+ else
+ GPIO(zr, 5, 1);
+ break;
+ default:
+ GPIO(zr, zr->card.gpio[ZR_GPIO_VID_DIR],
+ zr->card.gpio_pol[ZR_GPIO_VID_DIR] ? !val : val);
+ break;
+ }
+}
+
+static void init_jpeg_queue(struct zoran *zr)
+{
+ int i;
+
+ /* re-initialize DMA ring stuff */
+ zr->jpg_que_head = 0;
+ zr->jpg_dma_head = 0;
+ zr->jpg_dma_tail = 0;
+ zr->jpg_que_tail = 0;
+ zr->jpg_seq_num = 0;
+ zr->jpeg_error = 0;
+ zr->num_errors = 0;
+ zr->jpg_err_seq = 0;
+ zr->jpg_err_shift = 0;
+ zr->jpg_queued_num = 0;
+ for (i = 0; i < BUZ_NUM_STAT_COM; i++)
+ zr->stat_com[i] = cpu_to_le32(1); /* mark as unavailable to zr36057 */
+}
+
+static void zr36057_set_jpg(struct zoran *zr, enum zoran_codec_mode mode)
+{
+ const struct tvnorm *tvn;
+ u32 reg;
+
+ tvn = zr->timing;
+
+ /* assert P_Reset, disable code transfer, deassert Active */
+ btwrite(0, ZR36057_JPC);
+
+ /* MJPEG compression mode */
+ switch (mode) {
+ case BUZ_MODE_MOTION_COMPRESS:
+ default:
+ reg = ZR36057_JMC_MJPG_CMP_MODE;
+ break;
+
+ case BUZ_MODE_MOTION_DECOMPRESS:
+ reg = ZR36057_JMC_MJPG_EXP_MODE;
+ reg |= ZR36057_JMC_SYNC_MSTR;
+ /* RJ: The following is experimental - improves the output to screen */
+ //if(zr->jpg_settings.VFIFO_FB) reg |= ZR36057_JMC_VFIFO_FB; // No, it doesn't. SM
+ break;
+
+ case BUZ_MODE_STILL_COMPRESS:
+ reg = ZR36057_JMC_JPG_CMP_MODE;
+ break;
+
+ case BUZ_MODE_STILL_DECOMPRESS:
+ reg = ZR36057_JMC_JPG_EXP_MODE;
+ break;
+ }
+ reg |= ZR36057_JMC_JPG;
+ if (zr->jpg_settings.field_per_buff == 1)
+ reg |= ZR36057_JMC_FLD_PER_BUFF;
+ btwrite(reg, ZR36057_JMC);
+
+ /* vertical */
+ btor(ZR36057_VFEVCR_VS_POL, ZR36057_VFEVCR);
+ reg = (6 << ZR36057_VSP_VSYNC_SIZE) |
+ (tvn->ht << ZR36057_VSP_FRM_TOT);
+ btwrite(reg, ZR36057_VSP);
+ reg = ((zr->jpg_settings.img_y + tvn->v_start) << ZR36057_FVAP_NAY) |
+ (zr->jpg_settings.img_height << ZR36057_FVAP_PAY);
+ btwrite(reg, ZR36057_FVAP);
+
+ /* horizontal */
+ if (zr->card.vfe_pol.hsync_pol)
+ btor(ZR36057_VFEHCR_HS_POL, ZR36057_VFEHCR);
+ else
+ btand(~ZR36057_VFEHCR_HS_POL, ZR36057_VFEHCR);
+ reg = ((tvn->h_sync_start) << ZR36057_HSP_HSYNC_START) |
+ (tvn->wt << ZR36057_HSP_LINE_TOT);
+ btwrite(reg, ZR36057_HSP);
+ reg = ((zr->jpg_settings.img_x +
+ tvn->h_start + 4) << ZR36057_FHAP_NAX) |
+ (zr->jpg_settings.img_width << ZR36057_FHAP_PAX);
+ btwrite(reg, ZR36057_FHAP);
+
+ /* field process parameters */
+ if (zr->jpg_settings.odd_even)
+ reg = ZR36057_FPP_ODD_EVEN;
+ else
+ reg = 0;
+
+ btwrite(reg, ZR36057_FPP);
+
+ /* Set proper VCLK Polarity, else colors will be wrong during playback */
+ //btor(ZR36057_VFESPFR_VCLK_POL, ZR36057_VFESPFR);
+
+ /* code base address */
+ btwrite(zr->p_sc, ZR36057_JCBA);
+
+ /* FIFO threshold (FIFO is 160. double words) */
+ /* NOTE: decimal values here */
+ switch (mode) {
+ case BUZ_MODE_STILL_COMPRESS:
+ case BUZ_MODE_MOTION_COMPRESS:
+ if (zr->card.type != BUZ)
+ reg = 140;
+ else
+ reg = 60;
+ break;
+
+ case BUZ_MODE_STILL_DECOMPRESS:
+ case BUZ_MODE_MOTION_DECOMPRESS:
+ reg = 20;
+ break;
+
+ default:
+ reg = 80;
+ break;
+ }
+ btwrite(reg, ZR36057_JCFT);
+ zr36057_adjust_vfe(zr, mode);
+}
+
+void clear_interrupt_counters(struct zoran *zr)
+{
+ zr->intr_counter_GIRQ1 = 0;
+ zr->intr_counter_GIRQ0 = 0;
+ zr->intr_counter_cod_rep_irq = 0;
+ zr->intr_counter_jpeg_rep_irq = 0;
+ zr->field_counter = 0;
+ zr->irq1_in = 0;
+ zr->irq1_out = 0;
+ zr->jpeg_in = 0;
+ zr->jpeg_out = 0;
+ zr->JPEG_0 = 0;
+ zr->JPEG_1 = 0;
+ zr->end_event_missed = 0;
+ zr->jpeg_missed = 0;
+ zr->jpeg_max_missed = 0;
+ zr->jpeg_min_missed = 0x7fffffff;
+}
+
+static u32 count_reset_interrupt(struct zoran *zr)
+{
+ u32 isr;
+
+ isr = btread(ZR36057_ISR) & 0x78000000;
+ if (isr) {
+ if (isr & ZR36057_ISR_GIRQ1) {
+ btwrite(ZR36057_ISR_GIRQ1, ZR36057_ISR);
+ zr->intr_counter_GIRQ1++;
+ }
+ if (isr & ZR36057_ISR_GIRQ0) {
+ btwrite(ZR36057_ISR_GIRQ0, ZR36057_ISR);
+ zr->intr_counter_GIRQ0++;
+ }
+ if (isr & ZR36057_ISR_COD_REP_IRQ) {
+ btwrite(ZR36057_ISR_COD_REP_IRQ, ZR36057_ISR);
+ zr->intr_counter_cod_rep_irq++;
+ }
+ if (isr & ZR36057_ISR_JPEG_REP_IRQ) {
+ btwrite(ZR36057_ISR_JPEG_REP_IRQ, ZR36057_ISR);
+ zr->intr_counter_jpeg_rep_irq++;
+ }
+ }
+ return isr;
+}
+
+void jpeg_start(struct zoran *zr)
+{
+ int reg;
+
+ zr->frame_num = 0;
+
+ /* deassert P_reset, disable code transfer, deassert Active */
+ btwrite(ZR36057_JPC_P_RESET, ZR36057_JPC);
+ /* stop flushing the internal code buffer */
+ btand(~ZR36057_MCTCR_C_FLUSH, ZR36057_MCTCR);
+ /* enable code transfer */
+ btor(ZR36057_JPC_COD_TRNS_EN, ZR36057_JPC);
+
+ /* clear IRQs */
+ btwrite(IRQ_MASK, ZR36057_ISR);
+ /* enable the JPEG IRQs */
+ btwrite(zr->card.jpeg_int | ZR36057_ICR_JPEG_REP_IRQ | ZR36057_ICR_INT_PIN_EN,
+ ZR36057_ICR);
+
+ set_frame(zr, 0); // \FRAME
+
+ /* set the JPEG codec guest ID */
+ reg = (zr->card.gpcs[1] << ZR36057_JCGI_JPE_GUEST_ID) |
+ (0 << ZR36057_JCGI_JPE_GUEST_REG);
+ btwrite(reg, ZR36057_JCGI);
+
+ if (zr->card.video_vfe == CODEC_TYPE_ZR36016 &&
+ zr->card.video_codec == CODEC_TYPE_ZR36050) {
+ /* Enable processing on the ZR36016 */
+ if (zr->vfe)
+ zr36016_write(zr->vfe, 0, 1);
+
+ /* load the address of the GO register in the ZR36050 latch */
+ post_office_write(zr, 0, 0, 0);
+ }
+
+ /* assert Active */
+ btor(ZR36057_JPC_ACTIVE, ZR36057_JPC);
+
+ /* enable the Go generation */
+ btor(ZR36057_JMC_GO_EN, ZR36057_JMC);
+ usleep_range(30, 100);
+
+ set_frame(zr, 1); // /FRAME
+}
+
+void zr36057_enable_jpg(struct zoran *zr, enum zoran_codec_mode mode)
+{
+ struct vfe_settings cap;
+ int field_size = zr->buffer_size / zr->jpg_settings.field_per_buff;
+
+ zr->codec_mode = mode;
+
+ cap.x = zr->jpg_settings.img_x;
+ cap.y = zr->jpg_settings.img_y;
+ cap.width = zr->jpg_settings.img_width;
+ cap.height = zr->jpg_settings.img_height;
+ cap.decimation =
+ zr->jpg_settings.hor_dcm | (zr->jpg_settings.ver_dcm << 8);
+ cap.quality = zr->jpg_settings.jpg_comp.quality;
+
+ switch (mode) {
+ case BUZ_MODE_MOTION_COMPRESS: {
+ struct jpeg_app_marker app;
+ struct jpeg_com_marker com;
+
+ /* In motion compress mode, the decoder output must be enabled, and
+ * the video bus direction set to input.
+ */
+ set_videobus_dir(zr, 0);
+ decoder_call(zr, video, s_stream, 1);
+ encoder_call(zr, video, s_routing, 0, 0, 0);
+
+ /* Take the JPEG codec and the VFE out of sleep */
+ jpeg_codec_sleep(zr, 0);
+
+ /* set JPEG app/com marker */
+ app.appn = zr->jpg_settings.jpg_comp.APPn;
+ app.len = zr->jpg_settings.jpg_comp.APP_len;
+ memcpy(app.data, zr->jpg_settings.jpg_comp.APP_data, 60);
+ zr->codec->control(zr->codec, CODEC_S_JPEG_APP_DATA,
+ sizeof(struct jpeg_app_marker), &app);
+
+ com.len = zr->jpg_settings.jpg_comp.COM_len;
+ memcpy(com.data, zr->jpg_settings.jpg_comp.COM_data, 60);
+ zr->codec->control(zr->codec, CODEC_S_JPEG_COM_DATA,
+ sizeof(struct jpeg_com_marker), &com);
+
+ /* Setup the JPEG codec */
+ zr->codec->control(zr->codec, CODEC_S_JPEG_TDS_BYTE,
+ sizeof(int), &field_size);
+ zr->codec->set_video(zr->codec, zr->timing, &cap,
+ &zr->card.vfe_pol);
+ zr->codec->set_mode(zr->codec, CODEC_DO_COMPRESSION);
+
+ /* Setup the VFE */
+ if (zr->vfe) {
+ zr->vfe->control(zr->vfe, CODEC_S_JPEG_TDS_BYTE,
+ sizeof(int), &field_size);
+ zr->vfe->set_video(zr->vfe, zr->timing, &cap,
+ &zr->card.vfe_pol);
+ zr->vfe->set_mode(zr->vfe, CODEC_DO_COMPRESSION);
+ }
+
+ init_jpeg_queue(zr);
+ zr36057_set_jpg(zr, mode); // \P_Reset, ... Video param, FIFO
+
+ clear_interrupt_counters(zr);
+ pci_dbg(zr->pci_dev, "enable_jpg(MOTION_COMPRESS)\n");
+ break;
+ }
+
+ case BUZ_MODE_MOTION_DECOMPRESS:
+ /* In motion decompression mode, the decoder output must be disabled, and
+ * the video bus direction set to output.
+ */
+ decoder_call(zr, video, s_stream, 0);
+ set_videobus_dir(zr, 1);
+ encoder_call(zr, video, s_routing, 1, 0, 0);
+
+ /* Take the JPEG codec and the VFE out of sleep */
+ jpeg_codec_sleep(zr, 0);
+ /* Setup the VFE */
+ if (zr->vfe) {
+ zr->vfe->set_video(zr->vfe, zr->timing, &cap,
+ &zr->card.vfe_pol);
+ zr->vfe->set_mode(zr->vfe, CODEC_DO_EXPANSION);
+ }
+ /* Setup the JPEG codec */
+ zr->codec->set_video(zr->codec, zr->timing, &cap,
+ &zr->card.vfe_pol);
+ zr->codec->set_mode(zr->codec, CODEC_DO_EXPANSION);
+
+ init_jpeg_queue(zr);
+ zr36057_set_jpg(zr, mode); // \P_Reset, ... Video param, FIFO
+
+ clear_interrupt_counters(zr);
+ pci_dbg(zr->pci_dev, "enable_jpg(MOTION_DECOMPRESS)\n");
+ break;
+
+ case BUZ_MODE_IDLE:
+ default:
+ /* shut down processing */
+ btand(~(zr->card.jpeg_int | ZR36057_ICR_JPEG_REP_IRQ),
+ ZR36057_ICR);
+ btwrite(zr->card.jpeg_int | ZR36057_ICR_JPEG_REP_IRQ,
+ ZR36057_ISR);
+ btand(~ZR36057_JMC_GO_EN, ZR36057_JMC); // \Go_en
+
+ msleep(50);
+
+ set_videobus_dir(zr, 0);
+ set_frame(zr, 1); // /FRAME
+ btor(ZR36057_MCTCR_C_FLUSH, ZR36057_MCTCR); // /CFlush
+ btwrite(0, ZR36057_JPC); // \P_Reset,\CodTrnsEn,\Active
+ btand(~ZR36057_JMC_VFIFO_FB, ZR36057_JMC);
+ btand(~ZR36057_JMC_SYNC_MSTR, ZR36057_JMC);
+ jpeg_codec_reset(zr);
+ jpeg_codec_sleep(zr, 1);
+ zr36057_adjust_vfe(zr, mode);
+
+ decoder_call(zr, video, s_stream, 1);
+ encoder_call(zr, video, s_routing, 0, 0, 0);
+
+ pci_dbg(zr->pci_dev, "enable_jpg(IDLE)\n");
+ break;
+ }
+}
+
+/* when this is called the spinlock must be held */
+void zoran_feed_stat_com(struct zoran *zr)
+{
+ /* move frames from pending queue to DMA */
+
+ int i, max_stat_com;
+ struct zr_buffer *buf;
+ struct vb2_v4l2_buffer *vbuf;
+ dma_addr_t phys_addr = 0;
+ unsigned long flags;
+ unsigned long payload;
+
+ max_stat_com =
+ (zr->jpg_settings.tmp_dcm ==
+ 1) ? BUZ_NUM_STAT_COM : (BUZ_NUM_STAT_COM >> 1);
+
+ spin_lock_irqsave(&zr->queued_bufs_lock, flags);
+ while ((zr->jpg_dma_head - zr->jpg_dma_tail) < max_stat_com) {
+ buf = list_first_entry_or_null(&zr->queued_bufs, struct zr_buffer, queue);
+ if (!buf) {
+ pci_err(zr->pci_dev, "No buffer available to queue\n");
+ spin_unlock_irqrestore(&zr->queued_bufs_lock, flags);
+ return;
+ }
+ list_del(&buf->queue);
+ zr->buf_in_reserve--;
+ vbuf = &buf->vbuf;
+ vbuf->vb2_buf.state = VB2_BUF_STATE_ACTIVE;
+ phys_addr = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0);
+ payload = vb2_get_plane_payload(&vbuf->vb2_buf, 0);
+ if (payload == 0)
+ payload = zr->buffer_size;
+ if (zr->jpg_settings.tmp_dcm == 1) {
+ /* fill 1 stat_com entry */
+ i = (zr->jpg_dma_head -
+ zr->jpg_err_shift) & BUZ_MASK_STAT_COM;
+ if (!(zr->stat_com[i] & cpu_to_le32(1)))
+ break;
+ zr->stat_comb[i * 2] = cpu_to_le32(phys_addr);
+ zr->stat_comb[i * 2 + 1] = cpu_to_le32((payload >> 1) | 1);
+ zr->inuse[i] = buf;
+ zr->stat_com[i] = cpu_to_le32(zr->p_scb + i * 2 * 4);
+ } else {
+ /* fill 2 stat_com entries */
+ i = ((zr->jpg_dma_head -
+ zr->jpg_err_shift) & 1) * 2;
+ if (!(zr->stat_com[i] & cpu_to_le32(1)))
+ break;
+ zr->stat_com[i] = cpu_to_le32(zr->p_scb + i * 2 * 4);
+ zr->stat_com[i + 1] = cpu_to_le32(zr->p_scb + i * 2 * 4);
+
+ zr->stat_comb[i * 2] = cpu_to_le32(phys_addr);
+ zr->stat_comb[i * 2 + 1] = cpu_to_le32((payload >> 1) | 1);
+
+ zr->inuse[i] = buf;
+ zr->inuse[i + 1] = NULL;
+ }
+ zr->jpg_dma_head++;
+ }
+ spin_unlock_irqrestore(&zr->queued_bufs_lock, flags);
+ if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS)
+ zr->jpg_queued_num++;
+}
+
+/* when this is called the spinlock must be held */
+static void zoran_reap_stat_com(struct zoran *zr)
+{
+ /* move frames from DMA queue to done queue */
+
+ int i;
+ u32 stat_com;
+ unsigned int seq;
+ unsigned int dif;
+ unsigned long flags;
+ struct zr_buffer *buf;
+ unsigned int size = 0;
+ u32 fcnt;
+
+ /*
+ * In motion decompress we don't have a hardware frame counter,
+ * we just count the interrupts here
+ */
+
+ if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS)
+ zr->jpg_seq_num++;
+
+ spin_lock_irqsave(&zr->queued_bufs_lock, flags);
+ while (zr->jpg_dma_tail < zr->jpg_dma_head) {
+ if (zr->jpg_settings.tmp_dcm == 1)
+ i = (zr->jpg_dma_tail - zr->jpg_err_shift) & BUZ_MASK_STAT_COM;
+ else
+ i = ((zr->jpg_dma_tail - zr->jpg_err_shift) & 1) * 2;
+
+ stat_com = le32_to_cpu(zr->stat_com[i]);
+ if ((stat_com & 1) == 0) {
+ spin_unlock_irqrestore(&zr->queued_bufs_lock, flags);
+ return;
+ }
+
+ fcnt = (stat_com & GENMASK(31, 24)) >> 24;
+ size = (stat_com & GENMASK(22, 1)) >> 1;
+
+ buf = zr->inuse[i];
+ if (!buf) {
+ spin_unlock_irqrestore(&zr->queued_bufs_lock, flags);
+ pci_err(zr->pci_dev, "No buffer at slot %d\n", i);
+ return;
+ }
+ buf->vbuf.vb2_buf.timestamp = ktime_get_ns();
+
+ if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) {
+ vb2_set_plane_payload(&buf->vbuf.vb2_buf, 0, size);
+
+ /* update sequence number with the help of the counter in stat_com */
+ seq = (fcnt + zr->jpg_err_seq) & 0xff;
+ dif = (seq - zr->jpg_seq_num) & 0xff;
+ zr->jpg_seq_num += dif;
+ }
+ buf->vbuf.sequence = zr->jpg_settings.tmp_dcm ==
+ 2 ? (zr->jpg_seq_num >> 1) : zr->jpg_seq_num;
+ zr->inuse[i] = NULL;
+ if (zr->jpg_settings.tmp_dcm != 1)
+ buf->vbuf.field = zr->jpg_settings.odd_even ?
+ V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM;
+ else
+ buf->vbuf.field = zr->jpg_settings.odd_even ?
+ V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT;
+ vb2_buffer_done(&buf->vbuf.vb2_buf, VB2_BUF_STATE_DONE);
+
+ zr->jpg_dma_tail++;
+ }
+ spin_unlock_irqrestore(&zr->queued_bufs_lock, flags);
+}
+
+irqreturn_t zoran_irq(int irq, void *dev_id)
+{
+ struct zoran *zr = dev_id;
+ u32 stat, astat;
+
+ stat = count_reset_interrupt(zr);
+ astat = stat & IRQ_MASK;
+ if (astat & zr->card.vsync_int) {
+ if (zr->running == ZORAN_MAP_MODE_RAW) {
+ if ((btread(ZR36057_VSSFGR) & ZR36057_VSSFGR_SNAP_SHOT) == 0)
+ pci_warn(zr->pci_dev, "BuzIRQ with SnapShot off ???\n");
+ if ((btread(ZR36057_VSSFGR) & ZR36057_VSSFGR_FRAME_GRAB) == 0)
+ zr_set_buf(zr);
+ return IRQ_HANDLED;
+ }
+ if (astat & ZR36057_ISR_JPEG_REP_IRQ) {
+ if (zr->codec_mode != BUZ_MODE_MOTION_DECOMPRESS &&
+ zr->codec_mode != BUZ_MODE_MOTION_COMPRESS) {
+ pci_err(zr->pci_dev, "JPG IRQ when not in good mode\n");
+ return IRQ_HANDLED;
+ }
+ zr->frame_num++;
+ zoran_reap_stat_com(zr);
+ zoran_feed_stat_com(zr);
+ return IRQ_HANDLED;
+ }
+ /* unused interrupts */
+ }
+ zr->ghost_int++;
+ return IRQ_HANDLED;
+}
+
+void zoran_set_pci_master(struct zoran *zr, int set_master)
+{
+ if (set_master) {
+ pci_set_master(zr->pci_dev);
+ } else {
+ u16 command;
+
+ pci_read_config_word(zr->pci_dev, PCI_COMMAND, &command);
+ command &= ~PCI_COMMAND_MASTER;
+ pci_write_config_word(zr->pci_dev, PCI_COMMAND, command);
+ }
+}
+
+void zoran_init_hardware(struct zoran *zr)
+{
+ /* Enable bus-mastering */
+ zoran_set_pci_master(zr, 1);
+
+ /* Initialize the board */
+ if (zr->card.init)
+ zr->card.init(zr);
+
+ decoder_call(zr, core, init, 0);
+ decoder_call(zr, video, s_std, zr->norm);
+ decoder_call(zr, video, s_routing,
+ zr->card.input[zr->input].muxsel, 0, 0);
+
+ encoder_call(zr, core, init, 0);
+ encoder_call(zr, video, s_std_output, zr->norm);
+ encoder_call(zr, video, s_routing, 0, 0, 0);
+
+ /* toggle JPEG codec sleep to sync PLL */
+ jpeg_codec_sleep(zr, 1);
+ jpeg_codec_sleep(zr, 0);
+
+ /*
+ * 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);
+
+ btwrite(IRQ_MASK, ZR36057_ISR); // Clears interrupts
+}
+
+void zr36057_restart(struct zoran *zr)
+{
+ btwrite(0, ZR36057_SPGPPCR);
+ usleep_range(1000, 2000);
+ btor(ZR36057_SPGPPCR_SOFT_RESET, ZR36057_SPGPPCR);
+ usleep_range(1000, 2000);
+
+ /* assert P_Reset */
+ btwrite(0, ZR36057_JPC);
+ /* set up GPIO direction - all output */
+ btwrite(ZR36057_SPGPPCR_SOFT_RESET | 0, ZR36057_SPGPPCR);
+
+ /* set up GPIO pins and guest bus timing */
+ btwrite((0x81 << 24) | 0x8888, ZR36057_GPPGCR1);
+}
+
diff --git a/drivers/media/pci/zoran/zoran_device.h b/drivers/media/pci/zoran/zoran_device.h
new file mode 100644
index 000000000000..34fd5cc914eb
--- /dev/null
+++ b/drivers/media/pci/zoran/zoran_device.h
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Zoran zr36057/zr36067 PCI controller driver, for the
+ * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux
+ * Media Labs LML33/LML33R10.
+ *
+ * This part handles card-specific data and detection
+ *
+ * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
+ */
+
+#ifndef __ZORAN_DEVICE_H__
+#define __ZORAN_DEVICE_H__
+
+/* general purpose I/O */
+void GPIO(struct zoran *zr, int bit, unsigned int value);
+
+/* codec (or actually: guest bus) access */
+int post_office_wait(struct zoran *zr);
+int post_office_write(struct zoran *zr, unsigned int guest, unsigned int reg,
+ unsigned int value);
+int post_office_read(struct zoran *zr, unsigned int guest, unsigned int reg);
+
+void jpeg_codec_sleep(struct zoran *zr, int sleep);
+int jpeg_codec_reset(struct zoran *zr);
+
+/* zr360x7 access to raw capture */
+void zr36057_overlay(struct zoran *zr, int on);
+void write_overlay_mask(struct zoran_fh *fh, struct v4l2_clip *vp, int count);
+void zr36057_set_memgrab(struct zoran *zr, int mode);
+int wait_grab_pending(struct zoran *zr);
+
+/* interrupts */
+void print_interrupts(struct zoran *zr);
+void clear_interrupt_counters(struct zoran *zr);
+irqreturn_t zoran_irq(int irq, void *dev_id);
+
+/* JPEG codec access */
+void jpeg_start(struct zoran *zr);
+void zr36057_enable_jpg(struct zoran *zr, enum zoran_codec_mode mode);
+void zoran_feed_stat_com(struct zoran *zr);
+
+/* general */
+void zoran_set_pci_master(struct zoran *zr, int set_master);
+void zoran_init_hardware(struct zoran *zr);
+void zr36057_restart(struct zoran *zr);
+
+extern const struct zoran_format zoran_formats[];
+
+extern int v4l_bufsize;
+extern int jpg_bufsize;
+extern int pass_through;
+
+/* i2c */
+#define decoder_call(zr, o, f, args...) \
+ v4l2_subdev_call((zr)->decoder, o, f, ##args)
+#define encoder_call(zr, o, f, args...) \
+ v4l2_subdev_call((zr)->encoder, o, f, ##args)
+
+#endif /* __ZORAN_DEVICE_H__ */
diff --git a/drivers/media/pci/zoran/zoran_driver.c b/drivers/media/pci/zoran/zoran_driver.c
new file mode 100644
index 000000000000..fa672cc8bc67
--- /dev/null
+++ b/drivers/media/pci/zoran/zoran_driver.c
@@ -0,0 +1,986 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Zoran zr36057/zr36067 PCI controller driver, for the
+ * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux
+ * Media Labs LML33/LML33R10.
+ *
+ * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
+ *
+ * Changes for BUZ by Wolfgang Scherr <scherr@net4you.net>
+ *
+ * Changes for DC10/DC30 by Laurent Pinchart <laurent.pinchart@skynet.be>
+ *
+ * Changes for LML33R10 by Maxim Yevtyushkin <max@linuxmedialabs.com>
+ *
+ * Changes for videodev2/v4l2 by Ronald Bultje <rbultje@ronald.bitfreak.net>
+ *
+ * Based on
+ *
+ * Miro DC10 driver
+ * Copyright (C) 1999 Wolfgang Scherr <scherr@net4you.net>
+ *
+ * Iomega Buz driver version 1.0
+ * Copyright (C) 1999 Rainer Johanni <Rainer@Johanni.de>
+ *
+ * buz.0.0.3
+ * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
+ *
+ * bttv - Bt848 frame grabber driver
+ * Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de)
+ * & Marcus Metzler (mocm@thp.uni-koeln.de)
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/wait.h>
+
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+
+#include <linux/spinlock.h>
+
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-event.h>
+#include "videocodec.h"
+
+#include <linux/io.h>
+#include <linux/uaccess.h>
+
+#include <linux/mutex.h>
+#include "zoran.h"
+#include "zoran_device.h"
+#include "zoran_card.h"
+
+const struct zoran_format zoran_formats[] = {
+ {
+ .name = "15-bit RGB LE",
+ .fourcc = V4L2_PIX_FMT_RGB555,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .depth = 15,
+ .flags = ZORAN_FORMAT_CAPTURE,
+ .vfespfr = ZR36057_VFESPFR_RGB555 | ZR36057_VFESPFR_ERR_DIF |
+ ZR36057_VFESPFR_LITTLE_ENDIAN,
+ }, {
+ .name = "15-bit RGB BE",
+ .fourcc = V4L2_PIX_FMT_RGB555X,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .depth = 15,
+ .flags = ZORAN_FORMAT_CAPTURE,
+ .vfespfr = ZR36057_VFESPFR_RGB555 | ZR36057_VFESPFR_ERR_DIF,
+ }, {
+ .name = "16-bit RGB LE",
+ .fourcc = V4L2_PIX_FMT_RGB565,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .depth = 16,
+ .flags = ZORAN_FORMAT_CAPTURE,
+ .vfespfr = ZR36057_VFESPFR_RGB565 | ZR36057_VFESPFR_ERR_DIF |
+ ZR36057_VFESPFR_LITTLE_ENDIAN,
+ }, {
+ .name = "16-bit RGB BE",
+ .fourcc = V4L2_PIX_FMT_RGB565X,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .depth = 16,
+ .flags = ZORAN_FORMAT_CAPTURE,
+ .vfespfr = ZR36057_VFESPFR_RGB565 | ZR36057_VFESPFR_ERR_DIF,
+ }, {
+ .name = "24-bit RGB",
+ .fourcc = V4L2_PIX_FMT_BGR24,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .depth = 24,
+ .flags = ZORAN_FORMAT_CAPTURE,
+ .vfespfr = ZR36057_VFESPFR_RGB888 | ZR36057_VFESPFR_PACK24,
+ }, {
+ .name = "32-bit RGB LE",
+ .fourcc = V4L2_PIX_FMT_BGR32,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .depth = 32,
+ .flags = ZORAN_FORMAT_CAPTURE,
+ .vfespfr = ZR36057_VFESPFR_RGB888 | ZR36057_VFESPFR_LITTLE_ENDIAN,
+ }, {
+ .name = "32-bit RGB BE",
+ .fourcc = V4L2_PIX_FMT_RGB32,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .depth = 32,
+ .flags = ZORAN_FORMAT_CAPTURE,
+ .vfespfr = ZR36057_VFESPFR_RGB888,
+ }, {
+ .name = "4:2:2, packed, YUYV",
+ .fourcc = V4L2_PIX_FMT_YUYV,
+ .colorspace = V4L2_COLORSPACE_SMPTE170M,
+ .depth = 16,
+ .flags = ZORAN_FORMAT_CAPTURE,
+ .vfespfr = ZR36057_VFESPFR_YUV422,
+ }, {
+ .name = "4:2:2, packed, UYVY",
+ .fourcc = V4L2_PIX_FMT_UYVY,
+ .colorspace = V4L2_COLORSPACE_SMPTE170M,
+ .depth = 16,
+ .flags = ZORAN_FORMAT_CAPTURE,
+ .vfespfr = ZR36057_VFESPFR_YUV422 | ZR36057_VFESPFR_LITTLE_ENDIAN,
+ }, {
+ .name = "Hardware-encoded Motion-JPEG",
+ .fourcc = V4L2_PIX_FMT_MJPEG,
+ .colorspace = V4L2_COLORSPACE_SMPTE170M,
+ .depth = 0,
+ .flags = ZORAN_FORMAT_CAPTURE |
+ ZORAN_FORMAT_PLAYBACK |
+ ZORAN_FORMAT_COMPRESSED,
+ }
+};
+
+#define NUM_FORMATS ARRAY_SIZE(zoran_formats)
+
+ /*
+ * small helper function for calculating buffersizes for v4l2
+ * we calculate the nearest higher power-of-two, which
+ * will be the recommended buffersize
+ */
+static __u32 zoran_v4l2_calc_bufsize(struct zoran_jpg_settings *settings)
+{
+ __u8 div = settings->ver_dcm * settings->hor_dcm * settings->tmp_dcm;
+ __u32 num = (1024 * 512) / (div);
+ __u32 result = 2;
+
+ num--;
+ while (num) {
+ num >>= 1;
+ result <<= 1;
+ }
+
+ if (result < 8192)
+ return 8192;
+
+ return result;
+}
+
+/*
+ * V4L Buffer grabbing
+ */
+static int zoran_v4l_set_format(struct zoran *zr, int width, int height,
+ const struct zoran_format *format)
+{
+ int bpp;
+
+ /* Check size and format of the grab wanted */
+
+ if (height < BUZ_MIN_HEIGHT || width < BUZ_MIN_WIDTH ||
+ height > BUZ_MAX_HEIGHT || width > BUZ_MAX_WIDTH) {
+ pci_dbg(zr->pci_dev, "%s - wrong frame size (%dx%d)\n", __func__, width, height);
+ return -EINVAL;
+ }
+
+ bpp = (format->depth + 7) / 8;
+
+ zr->buffer_size = height * width * bpp;
+
+ /* Check against available buffer size */
+ if (height * width * bpp > zr->buffer_size) {
+ pci_dbg(zr->pci_dev, "%s - video buffer size (%d kB) is too small\n",
+ __func__, zr->buffer_size >> 10);
+ return -EINVAL;
+ }
+
+ /* The video front end needs 4-byte alinged line sizes */
+
+ if ((bpp == 2 && (width & 1)) || (bpp == 3 && (width & 3))) {
+ pci_dbg(zr->pci_dev, "%s - wrong frame alignment\n", __func__);
+ return -EINVAL;
+ }
+
+ zr->v4l_settings.width = width;
+ zr->v4l_settings.height = height;
+ zr->v4l_settings.format = format;
+ zr->v4l_settings.bytesperline = bpp * zr->v4l_settings.width;
+
+ return 0;
+}
+
+static int zoran_set_norm(struct zoran *zr, v4l2_std_id norm)
+{
+ if (!(norm & zr->card.norms)) {
+ pci_dbg(zr->pci_dev, "%s - unsupported norm %llx\n", __func__, norm);
+ return -EINVAL;
+ }
+
+ if (norm & V4L2_STD_SECAM)
+ zr->timing = zr->card.tvn[ZR_NORM_SECAM];
+ else if (norm & V4L2_STD_NTSC)
+ zr->timing = zr->card.tvn[ZR_NORM_NTSC];
+ else
+ zr->timing = zr->card.tvn[ZR_NORM_PAL];
+
+ decoder_call(zr, video, s_std, norm);
+ encoder_call(zr, video, s_std_output, norm);
+
+ /* Make sure the changes come into effect */
+ zr->norm = norm;
+
+ return 0;
+}
+
+static int zoran_set_input(struct zoran *zr, int input)
+{
+ if (input == zr->input)
+ return 0;
+
+ if (input < 0 || input >= zr->card.inputs) {
+ pci_dbg(zr->pci_dev, "%s - unsupported input %d\n", __func__, input);
+ return -EINVAL;
+ }
+
+ zr->input = input;
+
+ decoder_call(zr, video, s_routing, zr->card.input[input].muxsel, 0, 0);
+
+ return 0;
+}
+
+/*
+ * ioctl routine
+ */
+
+static int zoran_querycap(struct file *file, void *__fh, struct v4l2_capability *cap)
+{
+ struct zoran *zr = video_drvdata(file);
+
+ strscpy(cap->card, ZR_DEVNAME(zr), sizeof(cap->card));
+ strscpy(cap->driver, "zoran", sizeof(cap->driver));
+ snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", pci_name(zr->pci_dev));
+ return 0;
+}
+
+static int zoran_enum_fmt(struct zoran *zr, struct v4l2_fmtdesc *fmt, int flag)
+{
+ unsigned int num, i;
+
+ if (fmt->index >= ARRAY_SIZE(zoran_formats))
+ return -EINVAL;
+ if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ for (num = i = 0; i < NUM_FORMATS; i++) {
+ if (zoran_formats[i].flags & flag && num++ == fmt->index) {
+ strscpy(fmt->description, zoran_formats[i].name,
+ sizeof(fmt->description));
+ /* fmt struct pre-zeroed, so adding '\0' not needed */
+ fmt->pixelformat = zoran_formats[i].fourcc;
+ if (zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED)
+ fmt->flags |= V4L2_FMT_FLAG_COMPRESSED;
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+
+static int zoran_enum_fmt_vid_cap(struct file *file, void *__fh,
+ struct v4l2_fmtdesc *f)
+{
+ struct zoran *zr = video_drvdata(file);
+
+ return zoran_enum_fmt(zr, f, ZORAN_FORMAT_CAPTURE);
+}
+
+static int zoran_g_fmt_vid_out(struct file *file, void *__fh,
+ struct v4l2_format *fmt)
+{
+ struct zoran *zr = video_drvdata(file);
+
+ fmt->fmt.pix.width = zr->jpg_settings.img_width / zr->jpg_settings.hor_dcm;
+ fmt->fmt.pix.height = zr->jpg_settings.img_height * 2 /
+ (zr->jpg_settings.ver_dcm * zr->jpg_settings.tmp_dcm);
+ fmt->fmt.pix.sizeimage = zr->buffer_size;
+ fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
+ if (zr->jpg_settings.tmp_dcm == 1)
+ fmt->fmt.pix.field = (zr->jpg_settings.odd_even ?
+ V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT);
+ else
+ fmt->fmt.pix.field = (zr->jpg_settings.odd_even ?
+ V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM);
+ fmt->fmt.pix.bytesperline = 0;
+ fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+
+ return 0;
+}
+
+static int zoran_g_fmt_vid_cap(struct file *file, void *__fh,
+ struct v4l2_format *fmt)
+{
+ struct zoran *zr = video_drvdata(file);
+
+ if (zr->map_mode != ZORAN_MAP_MODE_RAW)
+ return zoran_g_fmt_vid_out(file, __fh, fmt);
+ fmt->fmt.pix.width = zr->v4l_settings.width;
+ fmt->fmt.pix.height = zr->v4l_settings.height;
+ fmt->fmt.pix.sizeimage = zr->buffer_size;
+ fmt->fmt.pix.pixelformat = zr->v4l_settings.format->fourcc;
+ fmt->fmt.pix.colorspace = zr->v4l_settings.format->colorspace;
+ fmt->fmt.pix.bytesperline = zr->v4l_settings.bytesperline;
+ if (BUZ_MAX_HEIGHT < (zr->v4l_settings.height * 2))
+ fmt->fmt.pix.field = V4L2_FIELD_INTERLACED;
+ else
+ fmt->fmt.pix.field = V4L2_FIELD_TOP;
+ return 0;
+}
+
+static int zoran_try_fmt_vid_out(struct file *file, void *__fh,
+ struct v4l2_format *fmt)
+{
+ struct zoran *zr = video_drvdata(file);
+ struct zoran_jpg_settings settings;
+ int res = 0;
+
+ if (fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
+ return -EINVAL;
+
+ settings = zr->jpg_settings;
+
+ /* we actually need to set 'real' parameters now */
+ if ((fmt->fmt.pix.height * 2) > BUZ_MAX_HEIGHT)
+ settings.tmp_dcm = 1;
+ else
+ settings.tmp_dcm = 2;
+ settings.decimation = 0;
+ if (fmt->fmt.pix.height <= zr->jpg_settings.img_height / 2)
+ settings.ver_dcm = 2;
+ else
+ settings.ver_dcm = 1;
+ if (fmt->fmt.pix.width <= zr->jpg_settings.img_width / 4)
+ settings.hor_dcm = 4;
+ else if (fmt->fmt.pix.width <= zr->jpg_settings.img_width / 2)
+ settings.hor_dcm = 2;
+ else
+ settings.hor_dcm = 1;
+ if (settings.tmp_dcm == 1)
+ settings.field_per_buff = 2;
+ else
+ settings.field_per_buff = 1;
+
+ if (settings.hor_dcm > 1) {
+ settings.img_x = (BUZ_MAX_WIDTH == 720) ? 8 : 0;
+ settings.img_width = (BUZ_MAX_WIDTH == 720) ? 704 : BUZ_MAX_WIDTH;
+ } else {
+ settings.img_x = 0;
+ settings.img_width = BUZ_MAX_WIDTH;
+ }
+
+ /* check */
+ res = zoran_check_jpg_settings(zr, &settings, 1);
+ if (res)
+ return res;
+
+ /* tell the user what we actually did */
+ fmt->fmt.pix.width = settings.img_width / settings.hor_dcm;
+ fmt->fmt.pix.height = settings.img_height * 2 /
+ (settings.tmp_dcm * settings.ver_dcm);
+ if (settings.tmp_dcm == 1)
+ fmt->fmt.pix.field = (zr->jpg_settings.odd_even ?
+ V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT);
+ else
+ fmt->fmt.pix.field = (zr->jpg_settings.odd_even ?
+ V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM);
+
+ fmt->fmt.pix.sizeimage = zoran_v4l2_calc_bufsize(&settings);
+ fmt->fmt.pix.bytesperline = 0;
+ fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+ return res;
+}
+
+static int zoran_try_fmt_vid_cap(struct file *file, void *__fh,
+ struct v4l2_format *fmt)
+{
+ struct zoran *zr = video_drvdata(file);
+ int bpp;
+ int i;
+
+ if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG)
+ return zoran_try_fmt_vid_out(file, __fh, fmt);
+
+ for (i = 0; i < NUM_FORMATS; i++)
+ if (zoran_formats[i].fourcc == fmt->fmt.pix.pixelformat)
+ break;
+
+ if (i == NUM_FORMATS) {
+ /* TODO do not return here to fix the TRY_FMT cannot handle an invalid pixelformat*/
+ return -EINVAL;
+ }
+
+ fmt->fmt.pix.pixelformat = zoran_formats[i].fourcc;
+ fmt->fmt.pix.colorspace = zoran_formats[i].colorspace;
+ if (BUZ_MAX_HEIGHT < (fmt->fmt.pix.height * 2))
+ fmt->fmt.pix.field = V4L2_FIELD_INTERLACED;
+ else
+ fmt->fmt.pix.field = V4L2_FIELD_TOP;
+
+ 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);
+ fmt->fmt.pix.bytesperline = fmt->fmt.pix.width * bpp;
+ fmt->fmt.pix.sizeimage = fmt->fmt.pix.bytesperline * fmt->fmt.pix.height;
+ return 0;
+}
+
+static int zoran_s_fmt_vid_out(struct file *file, void *__fh,
+ struct v4l2_format *fmt)
+{
+ struct zoran *zr = video_drvdata(file);
+ __le32 printformat = __cpu_to_le32(fmt->fmt.pix.pixelformat);
+ struct zoran_jpg_settings settings;
+ int res = 0;
+
+ pci_dbg(zr->pci_dev, "size=%dx%d, fmt=0x%x (%4.4s)\n",
+ fmt->fmt.pix.width, fmt->fmt.pix.height,
+ fmt->fmt.pix.pixelformat,
+ (char *)&printformat);
+ if (fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
+ return -EINVAL;
+
+ if (!fmt->fmt.pix.height || !fmt->fmt.pix.width)
+ return -EINVAL;
+
+ settings = zr->jpg_settings;
+
+ /* we actually need to set 'real' parameters now */
+ if (fmt->fmt.pix.height * 2 > BUZ_MAX_HEIGHT)
+ settings.tmp_dcm = 1;
+ else
+ settings.tmp_dcm = 2;
+ settings.decimation = 0;
+ if (fmt->fmt.pix.height <= zr->jpg_settings.img_height / 2)
+ settings.ver_dcm = 2;
+ else
+ settings.ver_dcm = 1;
+ if (fmt->fmt.pix.width <= zr->jpg_settings.img_width / 4)
+ settings.hor_dcm = 4;
+ else if (fmt->fmt.pix.width <= zr->jpg_settings.img_width / 2)
+ settings.hor_dcm = 2;
+ else
+ settings.hor_dcm = 1;
+ if (settings.tmp_dcm == 1)
+ settings.field_per_buff = 2;
+ else
+ settings.field_per_buff = 1;
+
+ if (settings.hor_dcm > 1) {
+ settings.img_x = (BUZ_MAX_WIDTH == 720) ? 8 : 0;
+ settings.img_width = (BUZ_MAX_WIDTH == 720) ? 704 : BUZ_MAX_WIDTH;
+ } else {
+ settings.img_x = 0;
+ settings.img_width = BUZ_MAX_WIDTH;
+ }
+
+ /* check */
+ res = zoran_check_jpg_settings(zr, &settings, 0);
+ if (res)
+ return res;
+
+ /* it's ok, so set them */
+ zr->jpg_settings = settings;
+
+ if (fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+ zr->map_mode = ZORAN_MAP_MODE_JPG_REC;
+ else
+ zr->map_mode = ZORAN_MAP_MODE_JPG_PLAY;
+
+ zr->buffer_size = zoran_v4l2_calc_bufsize(&zr->jpg_settings);
+
+ /* tell the user what we actually did */
+ fmt->fmt.pix.width = settings.img_width / settings.hor_dcm;
+ fmt->fmt.pix.height = settings.img_height * 2 /
+ (settings.tmp_dcm * settings.ver_dcm);
+ if (settings.tmp_dcm == 1)
+ fmt->fmt.pix.field = (zr->jpg_settings.odd_even ?
+ V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT);
+ else
+ fmt->fmt.pix.field = (zr->jpg_settings.odd_even ?
+ V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM);
+ fmt->fmt.pix.bytesperline = 0;
+ fmt->fmt.pix.sizeimage = zr->buffer_size;
+ fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+ return res;
+}
+
+static int zoran_s_fmt_vid_cap(struct file *file, void *__fh,
+ struct v4l2_format *fmt)
+{
+ struct zoran *zr = video_drvdata(file);
+ struct zoran_fh *fh = __fh;
+ int i;
+ int res = 0;
+
+ if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG)
+ return zoran_s_fmt_vid_out(file, fh, fmt);
+
+ for (i = 0; i < NUM_FORMATS; i++)
+ if (fmt->fmt.pix.pixelformat == zoran_formats[i].fourcc)
+ break;
+ if (i == NUM_FORMATS) {
+ pci_dbg(zr->pci_dev, "VIDIOC_S_FMT - unknown/unsupported format 0x%x\n",
+ fmt->fmt.pix.pixelformat);
+ /* TODO do not return here to fix the TRY_FMT cannot handle an invalid pixelformat*/
+ return -EINVAL;
+ }
+
+ fmt->fmt.pix.pixelformat = zoran_formats[i].fourcc;
+ if (fmt->fmt.pix.height > BUZ_MAX_HEIGHT)
+ fmt->fmt.pix.height = BUZ_MAX_HEIGHT;
+ if (fmt->fmt.pix.width > BUZ_MAX_WIDTH)
+ fmt->fmt.pix.width = BUZ_MAX_WIDTH;
+ if (fmt->fmt.pix.height < BUZ_MIN_HEIGHT)
+ fmt->fmt.pix.height = BUZ_MIN_HEIGHT;
+ if (fmt->fmt.pix.width < BUZ_MIN_WIDTH)
+ fmt->fmt.pix.width = BUZ_MIN_WIDTH;
+
+ zr->map_mode = ZORAN_MAP_MODE_RAW;
+
+ res = zoran_v4l_set_format(zr, fmt->fmt.pix.width, fmt->fmt.pix.height,
+ &zoran_formats[i]);
+ if (res)
+ return res;
+
+ /* tell the user the results/missing stuff */
+ fmt->fmt.pix.bytesperline = zr->v4l_settings.bytesperline;
+ fmt->fmt.pix.sizeimage = zr->buffer_size;
+ fmt->fmt.pix.colorspace = zr->v4l_settings.format->colorspace;
+ if (BUZ_MAX_HEIGHT < (zr->v4l_settings.height * 2))
+ fmt->fmt.pix.field = V4L2_FIELD_INTERLACED;
+ else
+ fmt->fmt.pix.field = V4L2_FIELD_TOP;
+ return res;
+}
+
+static int zoran_g_std(struct file *file, void *__fh, v4l2_std_id *std)
+{
+ struct zoran *zr = video_drvdata(file);
+
+ *std = zr->norm;
+ return 0;
+}
+
+static int zoran_s_std(struct file *file, void *__fh, v4l2_std_id std)
+{
+ struct zoran *zr = video_drvdata(file);
+ int res = 0;
+
+ if (zr->norm == std)
+ return 0;
+
+ if (zr->running != ZORAN_MAP_MODE_NONE)
+ return -EBUSY;
+
+ res = zoran_set_norm(zr, std);
+ return res;
+}
+
+static int zoran_enum_input(struct file *file, void *__fh,
+ struct v4l2_input *inp)
+{
+ struct zoran *zr = video_drvdata(file);
+
+ if (inp->index >= zr->card.inputs)
+ return -EINVAL;
+
+ strscpy(inp->name, zr->card.input[inp->index].name, sizeof(inp->name));
+ inp->type = V4L2_INPUT_TYPE_CAMERA;
+ inp->std = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM;
+
+ /* Get status of video decoder */
+ decoder_call(zr, video, g_input_status, &inp->status);
+ return 0;
+}
+
+static int zoran_g_input(struct file *file, void *__fh, unsigned int *input)
+{
+ struct zoran *zr = video_drvdata(file);
+
+ *input = zr->input;
+
+ return 0;
+}
+
+static int zoran_s_input(struct file *file, void *__fh, unsigned int input)
+{
+ struct zoran *zr = video_drvdata(file);
+ int res;
+
+ if (zr->running != ZORAN_MAP_MODE_NONE)
+ return -EBUSY;
+
+ res = zoran_set_input(zr, input);
+ return res;
+}
+
+/* cropping (sub-frame capture) */
+static int zoran_g_selection(struct file *file, void *__fh, struct v4l2_selection *sel)
+{
+ struct zoran *zr = video_drvdata(file);
+
+ if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+ sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ pci_dbg(zr->pci_dev, "%s invalid selection type combination\n", __func__);
+ return -EINVAL;
+ }
+
+ switch (sel->target) {
+ case V4L2_SEL_TGT_CROP:
+ sel->r.top = zr->jpg_settings.img_y;
+ sel->r.left = zr->jpg_settings.img_x;
+ sel->r.width = zr->jpg_settings.img_width;
+ sel->r.height = zr->jpg_settings.img_height;
+ break;
+ case V4L2_SEL_TGT_CROP_DEFAULT:
+ sel->r.top = 0;
+ sel->r.left = 0;
+ sel->r.width = BUZ_MIN_WIDTH;
+ sel->r.height = BUZ_MIN_HEIGHT;
+ break;
+ case V4L2_SEL_TGT_CROP_BOUNDS:
+ sel->r.top = 0;
+ sel->r.left = 0;
+ sel->r.width = BUZ_MAX_WIDTH;
+ sel->r.height = BUZ_MAX_HEIGHT;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int zoran_s_selection(struct file *file, void *__fh, struct v4l2_selection *sel)
+{
+ struct zoran *zr = video_drvdata(file);
+ struct zoran_jpg_settings settings;
+ int res;
+
+ if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+ sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ if (!sel->r.width || !sel->r.height)
+ return -EINVAL;
+
+ if (sel->target != V4L2_SEL_TGT_CROP)
+ return -EINVAL;
+
+ if (zr->map_mode == ZORAN_MAP_MODE_RAW) {
+ pci_dbg(zr->pci_dev, "VIDIOC_S_SELECTION - subcapture only supported for compressed capture\n");
+ return -EINVAL;
+ }
+
+ settings = zr->jpg_settings;
+
+ /* move into a form that we understand */
+ settings.img_x = sel->r.left;
+ settings.img_y = sel->r.top;
+ settings.img_width = sel->r.width;
+ settings.img_height = sel->r.height;
+
+ /* check validity */
+ res = zoran_check_jpg_settings(zr, &settings, 0);
+ if (res)
+ return res;
+
+ /* accept */
+ zr->jpg_settings = settings;
+ return res;
+}
+
+/*
+ * Output is disabled temporarily
+ * Zoran is picky about jpeg data it accepts. At least it seems to unsupport COM and APPn.
+ * So until a way to filter data will be done, disable output.
+ */
+static const struct v4l2_ioctl_ops zoran_ioctl_ops = {
+ .vidioc_querycap = zoran_querycap,
+ .vidioc_s_selection = zoran_s_selection,
+ .vidioc_g_selection = zoran_g_selection,
+ .vidioc_enum_input = zoran_enum_input,
+ .vidioc_g_input = zoran_g_input,
+ .vidioc_s_input = zoran_s_input,
+ .vidioc_g_std = zoran_g_std,
+ .vidioc_s_std = zoran_s_std,
+ .vidioc_create_bufs = vb2_ioctl_create_bufs,
+ .vidioc_reqbufs = vb2_ioctl_reqbufs,
+ .vidioc_querybuf = vb2_ioctl_querybuf,
+ .vidioc_qbuf = vb2_ioctl_qbuf,
+ .vidioc_dqbuf = vb2_ioctl_dqbuf,
+ .vidioc_expbuf = vb2_ioctl_expbuf,
+ .vidioc_streamon = vb2_ioctl_streamon,
+ .vidioc_streamoff = vb2_ioctl_streamoff,
+ .vidioc_enum_fmt_vid_cap = zoran_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = zoran_g_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = zoran_s_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = zoran_try_fmt_vid_cap,
+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+};
+
+static const struct v4l2_file_operations zoran_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = video_ioctl2,
+ .open = v4l2_fh_open,
+ .release = vb2_fop_release,
+ .mmap = vb2_fop_mmap,
+ .poll = vb2_fop_poll,
+};
+
+const struct video_device zoran_template = {
+ .name = ZORAN_NAME,
+ .fops = &zoran_fops,
+ .ioctl_ops = &zoran_ioctl_ops,
+ .release = &zoran_vdev_release,
+ .tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM,
+};
+
+static int zr_vb2_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes,
+ unsigned int sizes[], struct device *alloc_devs[])
+{
+ struct zoran *zr = vb2_get_drv_priv(vq);
+ unsigned int size = zr->buffer_size;
+
+ pci_dbg(zr->pci_dev, "%s nbuf=%u nplanes=%u", __func__, *nbuffers, *nplanes);
+
+ zr->buf_in_reserve = 0;
+
+ if (*nbuffers < vq->min_buffers_needed)
+ *nbuffers = vq->min_buffers_needed;
+
+ if (*nplanes) {
+ if (sizes[0] < size)
+ return -EINVAL;
+ else
+ return 0;
+ }
+
+ *nplanes = 1;
+ sizes[0] = size;
+
+ return 0;
+}
+
+static void zr_vb2_queue(struct vb2_buffer *vb)
+{
+ struct zoran *zr = vb2_get_drv_priv(vb->vb2_queue);
+ struct zr_buffer *buf = vb2_to_zr_buffer(vb);
+ unsigned long flags;
+
+ spin_lock_irqsave(&zr->queued_bufs_lock, flags);
+ list_add_tail(&buf->queue, &zr->queued_bufs);
+ zr->buf_in_reserve++;
+ spin_unlock_irqrestore(&zr->queued_bufs_lock, flags);
+ if (zr->running == ZORAN_MAP_MODE_JPG_REC)
+ zoran_feed_stat_com(zr);
+ zr->queued++;
+}
+
+static int zr_vb2_prepare(struct vb2_buffer *vb)
+{
+ struct zoran *zr = vb2_get_drv_priv(vb->vb2_queue);
+
+ if (vb2_plane_size(vb, 0) < zr->buffer_size)
+ return -EINVAL;
+ zr->prepared++;
+
+ return 0;
+}
+
+int zr_set_buf(struct zoran *zr)
+{
+ struct zr_buffer *buf;
+ struct vb2_v4l2_buffer *vbuf;
+ dma_addr_t phys_addr;
+ unsigned long flags;
+ u32 reg;
+
+ if (zr->running == ZORAN_MAP_MODE_NONE)
+ return 0;
+
+ if (zr->inuse[0]) {
+ buf = zr->inuse[0];
+ buf->vbuf.vb2_buf.timestamp = ktime_get_ns();
+ buf->vbuf.sequence = zr->vbseq++;
+ vbuf = &buf->vbuf;
+
+ buf->vbuf.field = V4L2_FIELD_INTERLACED;
+ if (BUZ_MAX_HEIGHT < (zr->v4l_settings.height * 2))
+ buf->vbuf.field = V4L2_FIELD_INTERLACED;
+ else
+ buf->vbuf.field = V4L2_FIELD_TOP;
+ vb2_set_plane_payload(&buf->vbuf.vb2_buf, 0, zr->buffer_size);
+ vb2_buffer_done(&buf->vbuf.vb2_buf, VB2_BUF_STATE_DONE);
+ zr->inuse[0] = NULL;
+ }
+
+ spin_lock_irqsave(&zr->queued_bufs_lock, flags);
+ if (list_empty(&zr->queued_bufs)) {
+ btand(~ZR36057_ICR_INT_PIN_EN, ZR36057_ICR);
+ vb2_queue_error(zr->video_dev->queue);
+ spin_unlock_irqrestore(&zr->queued_bufs_lock, flags);
+ return -EINVAL;
+ }
+ buf = list_first_entry_or_null(&zr->queued_bufs, struct zr_buffer, queue);
+ if (!buf) {
+ btand(~ZR36057_ICR_INT_PIN_EN, ZR36057_ICR);
+ vb2_queue_error(zr->video_dev->queue);
+ spin_unlock_irqrestore(&zr->queued_bufs_lock, flags);
+ return -EINVAL;
+ }
+ list_del(&buf->queue);
+ zr->buf_in_reserve--;
+ spin_unlock_irqrestore(&zr->queued_bufs_lock, flags);
+
+ vbuf = &buf->vbuf;
+ vbuf->vb2_buf.state = VB2_BUF_STATE_ACTIVE;
+ phys_addr = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0);
+
+ if (!phys_addr)
+ return -EINVAL;
+
+ zr->inuse[0] = buf;
+
+ reg = phys_addr;
+ btwrite(reg, ZR36057_VDTR);
+ if (zr->v4l_settings.height > BUZ_MAX_HEIGHT / 2)
+ reg += zr->v4l_settings.bytesperline;
+ btwrite(reg, ZR36057_VDBR);
+
+ reg = 0;
+ if (zr->v4l_settings.height > BUZ_MAX_HEIGHT / 2)
+ reg += zr->v4l_settings.bytesperline;
+ reg = (reg << ZR36057_VSSFGR_DISP_STRIDE);
+ reg |= ZR36057_VSSFGR_VID_OVF;
+ reg |= ZR36057_VSSFGR_SNAP_SHOT;
+ reg |= ZR36057_VSSFGR_FRAME_GRAB;
+ btwrite(reg, ZR36057_VSSFGR);
+
+ btor(ZR36057_VDCR_VID_EN, ZR36057_VDCR);
+ return 0;
+}
+
+static int zr_vb2_start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+ struct zoran *zr = vq->drv_priv;
+ int j;
+
+ for (j = 0; j < BUZ_NUM_STAT_COM; j++) {
+ zr->stat_com[j] = cpu_to_le32(1);
+ zr->inuse[j] = NULL;
+ }
+ zr->vbseq = 0;
+
+ if (zr->map_mode != ZORAN_MAP_MODE_RAW) {
+ pci_dbg(zr->pci_dev, "START JPG\n");
+ zr36057_restart(zr);
+ zoran_init_hardware(zr);
+ if (zr->map_mode == ZORAN_MAP_MODE_JPG_REC)
+ zr36057_enable_jpg(zr, BUZ_MODE_MOTION_DECOMPRESS);
+ else
+ zr36057_enable_jpg(zr, BUZ_MODE_MOTION_COMPRESS);
+ zoran_feed_stat_com(zr);
+ jpeg_start(zr);
+ zr->running = zr->map_mode;
+ btor(ZR36057_ICR_INT_PIN_EN, ZR36057_ICR);
+ return 0;
+ }
+
+ pci_dbg(zr->pci_dev, "START RAW\n");
+ zr36057_restart(zr);
+ zoran_init_hardware(zr);
+
+ zr36057_enable_jpg(zr, BUZ_MODE_IDLE);
+ zr36057_set_memgrab(zr, 1);
+ zr->running = zr->map_mode;
+ btor(ZR36057_ICR_INT_PIN_EN, ZR36057_ICR);
+ return 0;
+}
+
+static void zr_vb2_stop_streaming(struct vb2_queue *vq)
+{
+ struct zoran *zr = vq->drv_priv;
+ struct zr_buffer *buf;
+ unsigned long flags;
+ int j;
+
+ btand(~ZR36057_ICR_INT_PIN_EN, ZR36057_ICR);
+ if (zr->map_mode != ZORAN_MAP_MODE_RAW)
+ zr36057_enable_jpg(zr, BUZ_MODE_IDLE);
+ zr36057_set_memgrab(zr, 0);
+ zr->running = ZORAN_MAP_MODE_NONE;
+
+ zoran_set_pci_master(zr, 0);
+
+ if (!pass_through) { /* Switch to color bar */
+ decoder_call(zr, video, s_stream, 0);
+ encoder_call(zr, video, s_routing, 2, 0, 0);
+ }
+
+ for (j = 0; j < BUZ_NUM_STAT_COM; j++) {
+ zr->stat_com[j] = cpu_to_le32(1);
+ if (!zr->inuse[j])
+ continue;
+ buf = zr->inuse[j];
+ pci_dbg(zr->pci_dev, "%s clean buf %d\n", __func__, j);
+ vb2_buffer_done(&buf->vbuf.vb2_buf, VB2_BUF_STATE_ERROR);
+ zr->inuse[j] = NULL;
+ }
+
+ spin_lock_irqsave(&zr->queued_bufs_lock, flags);
+ while (!list_empty(&zr->queued_bufs)) {
+ buf = list_entry(zr->queued_bufs.next, struct zr_buffer, queue);
+ list_del(&buf->queue);
+ vb2_buffer_done(&buf->vbuf.vb2_buf, VB2_BUF_STATE_ERROR);
+ zr->buf_in_reserve--;
+ }
+ spin_unlock_irqrestore(&zr->queued_bufs_lock, flags);
+ if (zr->buf_in_reserve)
+ pci_dbg(zr->pci_dev, "Buffer remaining %d\n", zr->buf_in_reserve);
+ zr->map_mode = ZORAN_MAP_MODE_RAW;
+}
+
+static const struct vb2_ops zr_video_qops = {
+ .queue_setup = zr_vb2_queue_setup,
+ .buf_queue = zr_vb2_queue,
+ .buf_prepare = zr_vb2_prepare,
+ .start_streaming = zr_vb2_start_streaming,
+ .stop_streaming = zr_vb2_stop_streaming,
+ .wait_prepare = vb2_ops_wait_prepare,
+ .wait_finish = vb2_ops_wait_finish,
+};
+
+int zoran_queue_init(struct zoran *zr, struct vb2_queue *vq, int dir)
+{
+ int err;
+
+ spin_lock_init(&zr->queued_bufs_lock);
+ INIT_LIST_HEAD(&zr->queued_bufs);
+
+ vq->dev = &zr->pci_dev->dev;
+ vq->type = dir;
+
+ vq->io_modes = VB2_DMABUF | VB2_MMAP;
+ vq->drv_priv = zr;
+ vq->buf_struct_size = sizeof(struct zr_buffer);
+ vq->ops = &zr_video_qops;
+ vq->mem_ops = &vb2_dma_contig_memops;
+ vq->gfp_flags = GFP_DMA32;
+ vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+ vq->min_buffers_needed = 9;
+ vq->lock = &zr->lock;
+ err = vb2_queue_init(vq);
+ if (err)
+ return err;
+ zr->video_dev->queue = vq;
+ return 0;
+}
+
+void zoran_queue_exit(struct zoran *zr)
+{
+ vb2_queue_release(zr->video_dev->queue);
+}
diff --git a/drivers/media/pci/zoran/zr36016.c b/drivers/media/pci/zoran/zr36016.c
new file mode 100644
index 000000000000..4b328ad6083f
--- /dev/null
+++ b/drivers/media/pci/zoran/zr36016.c
@@ -0,0 +1,406 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Zoran ZR36016 basic configuration functions
+ *
+ * Copyright (C) 2001 Wolfgang Scherr <scherr@net4you.at>
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+
+/* headerfile of this module */
+#include "zr36016.h"
+
+/* codec io API */
+#include "videocodec.h"
+
+/*
+ * it doesn't make sense to have more than 20 or so,
+ * just to prevent some unwanted loops
+ */
+#define MAX_CODECS 20
+
+/* amount of chips attached via this driver */
+static int zr36016_codecs;
+
+/*
+ * Local hardware I/O functions: read/write via codec layer
+ * (registers are located in the master device)
+ */
+
+/* read and write functions */
+static u8 zr36016_read(struct zr36016 *ptr, u16 reg)
+{
+ u8 value = 0;
+ struct zoran *zr = videocodec_to_zoran(ptr->codec);
+
+ /* just in case something is wrong... */
+ if (ptr->codec->master_data->readreg)
+ value = (ptr->codec->master_data->readreg(ptr->codec, reg)) & 0xFF;
+ else
+ zrdev_err(zr, "%s: invalid I/O setup, nothing read!\n", ptr->name);
+
+ zrdev_dbg(zr, "%s: reading from 0x%04x: %02x\n", ptr->name, reg, value);
+
+ return value;
+}
+
+static void zr36016_write(struct zr36016 *ptr, u16 reg, u8 value)
+{
+ struct zoran *zr = videocodec_to_zoran(ptr->codec);
+
+ zrdev_dbg(zr, "%s: writing 0x%02x to 0x%04x\n", ptr->name, value, reg);
+
+ // just in case something is wrong...
+ if (ptr->codec->master_data->writereg)
+ ptr->codec->master_data->writereg(ptr->codec, reg, value);
+ else
+ zrdev_err(zr, "%s: invalid I/O setup, nothing written!\n", ptr->name);
+}
+
+/*
+ * indirect read and write functions
+ *
+ * the 016 supports auto-addr-increment, but
+ * writing it all time cost not much and is safer...
+ */
+static u8 zr36016_readi(struct zr36016 *ptr, u16 reg)
+{
+ u8 value = 0;
+ struct zoran *zr = videocodec_to_zoran(ptr->codec);
+
+ /* just in case something is wrong... */
+ if ((ptr->codec->master_data->writereg) && (ptr->codec->master_data->readreg)) {
+ ptr->codec->master_data->writereg(ptr->codec, ZR016_IADDR, reg & 0x0F);
+ value = (ptr->codec->master_data->readreg(ptr->codec, ZR016_IDATA)) & 0xFF;
+ } else {
+ zrdev_err(zr, "%s: invalid I/O setup, nothing read (i)!\n", ptr->name);
+ }
+
+ zrdev_dbg(zr, "%s: reading indirect from 0x%04x: %02x\n",
+ ptr->name, reg, value);
+ return value;
+}
+
+static void zr36016_writei(struct zr36016 *ptr, u16 reg, u8 value)
+{
+ struct zoran *zr = videocodec_to_zoran(ptr->codec);
+
+ zrdev_dbg(zr, "%s: writing indirect 0x%02x to 0x%04x\n", ptr->name,
+ value, reg);
+
+ /* just in case something is wrong... */
+ if (ptr->codec->master_data->writereg) {
+ ptr->codec->master_data->writereg(ptr->codec, ZR016_IADDR, reg & 0x0F);
+ ptr->codec->master_data->writereg(ptr->codec, ZR016_IDATA, value & 0x0FF);
+ } else {
+ zrdev_err(zr, "%s: invalid I/O setup, nothing written (i)!\n", ptr->name);
+ }
+}
+
+/* Local helper function: version read */
+
+/* version kept in datastructure */
+static u8 zr36016_read_version(struct zr36016 *ptr)
+{
+ ptr->version = zr36016_read(ptr, 0) >> 4;
+ return ptr->version;
+}
+
+/*
+ * Local helper function: basic test of "connectivity", writes/reads
+ * to/from PAX-Lo register
+ */
+
+static int zr36016_basic_test(struct zr36016 *ptr)
+{
+ struct zoran *zr = videocodec_to_zoran(ptr->codec);
+
+ if (*KERN_INFO <= CONSOLE_LOGLEVEL_DEFAULT) {
+ int i;
+
+ zr36016_writei(ptr, ZR016I_PAX_LO, 0x55);
+ zrdev_dbg(zr, "%s: registers: ", ptr->name);
+ for (i = 0; i <= 0x0b; i++)
+ zrdev_dbg(zr, "%02x ", zr36016_readi(ptr, i));
+ zrdev_dbg(zr, "\n");
+ }
+ // for testing just write 0, then the default value to a register and read
+ // it back in both cases
+ zr36016_writei(ptr, ZR016I_PAX_LO, 0x00);
+ if (zr36016_readi(ptr, ZR016I_PAX_LO) != 0x0) {
+ zrdev_err(zr, "%s: attach failed, can't connect to vfe processor!\n", ptr->name);
+ return -ENXIO;
+ }
+ zr36016_writei(ptr, ZR016I_PAX_LO, 0x0d0);
+ if (zr36016_readi(ptr, ZR016I_PAX_LO) != 0x0d0) {
+ zrdev_err(zr, "%s: attach failed, can't connect to vfe processor!\n", ptr->name);
+ return -ENXIO;
+ }
+ // we allow version numbers from 0-3, should be enough, though
+ zr36016_read_version(ptr);
+ if (ptr->version & 0x0c) {
+ zrdev_err(zr, "%s: attach failed, suspicious version %d found...\n", ptr->name,
+ ptr->version);
+ return -ENXIO;
+ }
+
+ return 0; /* looks good! */
+}
+
+/* Basic datasets & init */
+
+static void zr36016_init(struct zr36016 *ptr)
+{
+ // stop any processing
+ zr36016_write(ptr, ZR016_GOSTOP, 0);
+
+ // mode setup (yuv422 in and out, compression/expansuon due to mode)
+ zr36016_write(ptr, ZR016_MODE,
+ ZR016_YUV422 | ZR016_YUV422_YUV422 |
+ (ptr->mode == CODEC_DO_COMPRESSION ?
+ ZR016_COMPRESSION : ZR016_EXPANSION));
+
+ // misc setup
+ zr36016_writei(ptr, ZR016I_SETUP1,
+ (ptr->xdec ? (ZR016_HRFL | ZR016_HORZ) : 0) |
+ (ptr->ydec ? ZR016_VERT : 0) | ZR016_CNTI);
+ zr36016_writei(ptr, ZR016I_SETUP2, ZR016_CCIR);
+
+ // Window setup
+ // (no extra offset for now, norm defines offset, default width height)
+ zr36016_writei(ptr, ZR016I_PAX_HI, ptr->width >> 8);
+ zr36016_writei(ptr, ZR016I_PAX_LO, ptr->width & 0xFF);
+ zr36016_writei(ptr, ZR016I_PAY_HI, ptr->height >> 8);
+ zr36016_writei(ptr, ZR016I_PAY_LO, ptr->height & 0xFF);
+ zr36016_writei(ptr, ZR016I_NAX_HI, ptr->xoff >> 8);
+ zr36016_writei(ptr, ZR016I_NAX_LO, ptr->xoff & 0xFF);
+ zr36016_writei(ptr, ZR016I_NAY_HI, ptr->yoff >> 8);
+ zr36016_writei(ptr, ZR016I_NAY_LO, ptr->yoff & 0xFF);
+
+ /* shall we continue now, please? */
+ zr36016_write(ptr, ZR016_GOSTOP, 1);
+}
+
+/*
+ * CODEC API FUNCTIONS
+ *
+ * These functions are accessed by the master via the API structure
+ */
+
+/*
+ * set compression/expansion mode and launches codec -
+ * this should be the last call from the master before starting processing
+ */
+static int zr36016_set_mode(struct videocodec *codec, int mode)
+{
+ struct zr36016 *ptr = (struct zr36016 *)codec->data;
+ struct zoran *zr = videocodec_to_zoran(codec);
+
+ zrdev_dbg(zr, "%s: set_mode %d call\n", ptr->name, mode);
+
+ if ((mode != CODEC_DO_EXPANSION) && (mode != CODEC_DO_COMPRESSION))
+ return -EINVAL;
+
+ ptr->mode = mode;
+ zr36016_init(ptr);
+
+ return 0;
+}
+
+/* set picture size */
+static int zr36016_set_video(struct videocodec *codec, const struct tvnorm *norm,
+ struct vfe_settings *cap, struct vfe_polarity *pol)
+{
+ struct zr36016 *ptr = (struct zr36016 *)codec->data;
+ struct zoran *zr = videocodec_to_zoran(codec);
+
+ zrdev_dbg(zr, "%s: set_video %d.%d, %d/%d-%dx%d (0x%x) call\n",
+ ptr->name, norm->h_start, norm->v_start,
+ cap->x, cap->y, cap->width, cap->height,
+ cap->decimation);
+
+ /*
+ * if () return -EINVAL;
+ * trust the master driver that it knows what it does - so
+ * we allow invalid startx/y for now ...
+ */
+ ptr->width = cap->width;
+ ptr->height = cap->height;
+ /*
+ * (Ronald) This is ugly. zoran_device.c, line 387
+ * already mentions what happens if h_start is even
+ * (blue faces, etc., cr/cb inversed). There's probably
+ * some good reason why h_start is 0 instead of 1, so I'm
+ * leaving it to this for now, but really... This can be
+ * done a lot simpler
+ */
+ ptr->xoff = (norm->h_start ? norm->h_start : 1) + cap->x;
+ /*
+ * Something to note here (I don't understand it), setting
+ * v_start too high will cause the codec to 'not work'. I
+ * really don't get it. values of 16 (v_start) already break
+ * it here. Just '0' seems to work. More testing needed!
+ */
+ ptr->yoff = norm->v_start + cap->y;
+ /* (Ronald) dzjeeh, can't this thing do hor_decimation = 4? */
+ ptr->xdec = ((cap->decimation & 0xff) == 1) ? 0 : 1;
+ ptr->ydec = (((cap->decimation >> 8) & 0xff) == 1) ? 0 : 1;
+
+ return 0;
+}
+
+/* additional control functions */
+static int zr36016_control(struct videocodec *codec, int type, int size, void *data)
+{
+ struct zr36016 *ptr = (struct zr36016 *)codec->data;
+ struct zoran *zr = videocodec_to_zoran(codec);
+ int *ival = (int *)data;
+
+ zrdev_dbg(zr, "%s: control %d call with %d byte\n",
+ ptr->name, type, size);
+
+ switch (type) {
+ case CODEC_G_STATUS: /* get last status - we don't know it ... */
+ if (size != sizeof(int))
+ return -EFAULT;
+ *ival = 0;
+ break;
+
+ case CODEC_G_CODEC_MODE:
+ if (size != sizeof(int))
+ return -EFAULT;
+ *ival = 0;
+ break;
+
+ case CODEC_S_CODEC_MODE:
+ if (size != sizeof(int))
+ return -EFAULT;
+ if (*ival != 0)
+ return -EINVAL;
+ /* not needed, do nothing */
+ return 0;
+
+ case CODEC_G_VFE:
+ case CODEC_S_VFE:
+ return 0;
+
+ case CODEC_S_MMAP:
+ /* not available, give an error */
+ return -ENXIO;
+
+ default:
+ return -EINVAL;
+ }
+
+ return size;
+}
+
+/*
+ * Exit and unregister function:
+ *
+ * Deinitializes Zoran's JPEG processor
+ */
+
+static int zr36016_unset(struct videocodec *codec)
+{
+ struct zr36016 *ptr = codec->data;
+ struct zoran *zr = videocodec_to_zoran(codec);
+
+ if (ptr) {
+ /* do wee need some codec deinit here, too ???? */
+
+ zrdev_dbg(zr, "%s: finished codec #%d\n", ptr->name, ptr->num);
+ kfree(ptr);
+ codec->data = NULL;
+
+ zr36016_codecs--;
+ return 0;
+ }
+
+ return -EFAULT;
+}
+
+/*
+ * Setup and registry function:
+ *
+ * Initializes Zoran's JPEG processor
+ *
+ * Also sets pixel size, average code size, mode (compr./decompr.)
+ * (the given size is determined by the processor with the video interface)
+ */
+
+static int zr36016_setup(struct videocodec *codec)
+{
+ struct zr36016 *ptr;
+ struct zoran *zr = videocodec_to_zoran(codec);
+ int res;
+
+ zrdev_dbg(zr, "zr36016: initializing VFE subsystem #%d.\n", zr36016_codecs);
+
+ if (zr36016_codecs == MAX_CODECS) {
+ zrdev_err(zr, "zr36016: Can't attach more codecs!\n");
+ return -ENOSPC;
+ }
+ //mem structure init
+ ptr = kzalloc(sizeof(*ptr), GFP_KERNEL);
+ codec->data = ptr;
+ if (!ptr)
+ return -ENOMEM;
+
+ snprintf(ptr->name, sizeof(ptr->name), "zr36016[%d]", zr36016_codecs);
+ ptr->num = zr36016_codecs++;
+ ptr->codec = codec;
+
+ //testing
+ res = zr36016_basic_test(ptr);
+ if (res < 0) {
+ zr36016_unset(codec);
+ return res;
+ }
+ //final setup
+ ptr->mode = CODEC_DO_COMPRESSION;
+ ptr->width = 768;
+ ptr->height = 288;
+ ptr->xdec = 1;
+ ptr->ydec = 0;
+ zr36016_init(ptr);
+
+ zrdev_dbg(zr, "%s: codec v%d attached and running\n",
+ ptr->name, ptr->version);
+
+ return 0;
+}
+
+static const struct videocodec zr36016_codec = {
+ .name = "zr36016",
+ .magic = 0L, /* magic not used */
+ .flags =
+ CODEC_FLAG_HARDWARE | CODEC_FLAG_VFE | CODEC_FLAG_ENCODER |
+ CODEC_FLAG_DECODER,
+ .type = CODEC_TYPE_ZR36016,
+ .setup = zr36016_setup, /* functionality */
+ .unset = zr36016_unset,
+ .set_mode = zr36016_set_mode,
+ .set_video = zr36016_set_video,
+ .control = zr36016_control,
+ /* others are not used */
+};
+
+/* HOOK IN DRIVER AS KERNEL MODULE */
+
+int zr36016_init_module(void)
+{
+ zr36016_codecs = 0;
+ return videocodec_register(&zr36016_codec);
+}
+
+void zr36016_cleanup_module(void)
+{
+ if (zr36016_codecs) {
+ pr_debug("zr36016: something's wrong - %d codecs left somehow.\n",
+ zr36016_codecs);
+ }
+ videocodec_unregister(&zr36016_codec);
+}
diff --git a/drivers/media/pci/zoran/zr36016.h b/drivers/media/pci/zoran/zr36016.h
new file mode 100644
index 000000000000..04afba35669d
--- /dev/null
+++ b/drivers/media/pci/zoran/zr36016.h
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Zoran ZR36016 basic configuration functions - header file
+ *
+ * Copyright (C) 2001 Wolfgang Scherr <scherr@net4you.at>
+ */
+
+#ifndef ZR36016_H
+#define ZR36016_H
+
+/* data stored for each zoran jpeg codec chip */
+struct zr36016 {
+ char name[32];
+ int num;
+ /* io datastructure */
+ struct videocodec *codec;
+ // coder status
+ __u8 version;
+ // actual coder setup
+ int mode;
+
+ __u16 xoff;
+ __u16 yoff;
+ __u16 width;
+ __u16 height;
+ __u16 xdec;
+ __u16 ydec;
+};
+
+/* direct register addresses */
+#define ZR016_GOSTOP 0x00
+#define ZR016_MODE 0x01
+#define ZR016_IADDR 0x02
+#define ZR016_IDATA 0x03
+
+/* indirect register addresses */
+#define ZR016I_SETUP1 0x00
+#define ZR016I_SETUP2 0x01
+#define ZR016I_NAX_LO 0x02
+#define ZR016I_NAX_HI 0x03
+#define ZR016I_PAX_LO 0x04
+#define ZR016I_PAX_HI 0x05
+#define ZR016I_NAY_LO 0x06
+#define ZR016I_NAY_HI 0x07
+#define ZR016I_PAY_LO 0x08
+#define ZR016I_PAY_HI 0x09
+#define ZR016I_NOL_LO 0x0a
+#define ZR016I_NOL_HI 0x0b
+
+/* possible values for mode register */
+#define ZR016_RGB444_YUV444 0x00
+#define ZR016_RGB444_YUV422 0x01
+#define ZR016_RGB444_YUV411 0x02
+#define ZR016_RGB444_Y400 0x03
+#define ZR016_RGB444_RGB444 0x04
+#define ZR016_YUV444_YUV444 0x08
+#define ZR016_YUV444_YUV422 0x09
+#define ZR016_YUV444_YUV411 0x0a
+#define ZR016_YUV444_Y400 0x0b
+#define ZR016_YUV444_RGB444 0x0c
+#define ZR016_YUV422_YUV422 0x11
+#define ZR016_YUV422_YUV411 0x12
+#define ZR016_YUV422_Y400 0x13
+#define ZR016_YUV411_YUV411 0x16
+#define ZR016_YUV411_Y400 0x17
+#define ZR016_4444_4444 0x19
+#define ZR016_100_100 0x1b
+
+#define ZR016_RGB444 0x00
+#define ZR016_YUV444 0x20
+#define ZR016_YUV422 0x40
+
+#define ZR016_COMPRESSION 0x80
+#define ZR016_EXPANSION 0x80
+
+/* possible values for setup 1 register */
+#define ZR016_CKRT 0x80
+#define ZR016_VERT 0x40
+#define ZR016_HORZ 0x20
+#define ZR016_HRFL 0x10
+#define ZR016_DSFL 0x08
+#define ZR016_SBFL 0x04
+#define ZR016_RSTR 0x02
+#define ZR016_CNTI 0x01
+
+/* possible values for setup 2 register */
+#define ZR016_SYEN 0x40
+#define ZR016_CCIR 0x04
+#define ZR016_SIGN 0x02
+#define ZR016_YMCS 0x01
+
+int zr36016_init_module(void);
+void zr36016_cleanup_module(void);
+#endif /*fndef ZR36016_H */
diff --git a/drivers/media/pci/zoran/zr36050.c b/drivers/media/pci/zoran/zr36050.c
new file mode 100644
index 000000000000..b07d7e5c1b4a
--- /dev/null
+++ b/drivers/media/pci/zoran/zr36050.c
@@ -0,0 +1,817 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Zoran ZR36050 basic configuration functions
+ *
+ * Copyright (C) 2001 Wolfgang Scherr <scherr@net4you.at>
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+#include <linux/types.h>
+#include <linux/wait.h>
+
+/* I/O commands, error codes */
+#include <linux/io.h>
+
+/* headerfile of this module */
+#include "zr36050.h"
+
+/* codec io API */
+#include "videocodec.h"
+
+/*
+ * it doesn't make sense to have more than 20 or so,
+ * just to prevent some unwanted loops
+ */
+#define MAX_CODECS 20
+
+/* amount of chips attached via this driver */
+static int zr36050_codecs;
+
+/*
+ * Local hardware I/O functions:
+ *
+ * read/write via codec layer (registers are located in the master device)
+ */
+
+/* read and write functions */
+static u8 zr36050_read(struct zr36050 *ptr, u16 reg)
+{
+ struct zoran *zr = videocodec_to_zoran(ptr->codec);
+ u8 value = 0;
+
+ /* just in case something is wrong... */
+ if (ptr->codec->master_data->readreg)
+ value = (ptr->codec->master_data->readreg(ptr->codec, reg)) & 0xFF;
+ else
+ zrdev_err(zr, "%s: invalid I/O setup, nothing read!\n", ptr->name);
+
+ zrdev_dbg(zr, "%s: reading from 0x%04x: %02x\n", ptr->name, reg, value);
+
+ return value;
+}
+
+static void zr36050_write(struct zr36050 *ptr, u16 reg, u8 value)
+{
+ struct zoran *zr = videocodec_to_zoran(ptr->codec);
+
+ zrdev_dbg(zr, "%s: writing 0x%02x to 0x%04x\n", ptr->name, value, reg);
+
+ /* just in case something is wrong... */
+ if (ptr->codec->master_data->writereg)
+ ptr->codec->master_data->writereg(ptr->codec, reg, value);
+ else
+ zrdev_err(zr, "%s: invalid I/O setup, nothing written!\n",
+ ptr->name);
+}
+
+/* status is kept in datastructure */
+static u8 zr36050_read_status1(struct zr36050 *ptr)
+{
+ ptr->status1 = zr36050_read(ptr, ZR050_STATUS_1);
+
+ zr36050_read(ptr, 0);
+ return ptr->status1;
+}
+
+/* scale factor is kept in datastructure */
+static u16 zr36050_read_scalefactor(struct zr36050 *ptr)
+{
+ ptr->scalefact = (zr36050_read(ptr, ZR050_SF_HI) << 8) |
+ (zr36050_read(ptr, ZR050_SF_LO) & 0xFF);
+
+ /* leave 0 selected for an eventually GO from master */
+ zr36050_read(ptr, 0);
+ return ptr->scalefact;
+}
+
+/*
+ * Local helper function:
+ *
+ * wait if codec is ready to proceed (end of processing) or time is over
+ */
+
+static void zr36050_wait_end(struct zr36050 *ptr)
+{
+ struct zoran *zr = videocodec_to_zoran(ptr->codec);
+ int i = 0;
+
+ while (!(zr36050_read_status1(ptr) & 0x4)) {
+ udelay(1);
+ if (i++ > 200000) { // 200ms, there is for sure something wrong!!!
+ zrdev_err(zr,
+ "%s: timeout at wait_end (last status: 0x%02x)\n",
+ ptr->name, ptr->status1);
+ break;
+ }
+ }
+}
+
+/*
+ * Local helper function: basic test of "connectivity", writes/reads
+ * to/from memory the SOF marker
+ */
+
+static int zr36050_basic_test(struct zr36050 *ptr)
+{
+ struct zoran *zr = videocodec_to_zoran(ptr->codec);
+
+ zr36050_write(ptr, ZR050_SOF_IDX, 0x00);
+ zr36050_write(ptr, ZR050_SOF_IDX + 1, 0x00);
+ if ((zr36050_read(ptr, ZR050_SOF_IDX) |
+ zr36050_read(ptr, ZR050_SOF_IDX + 1)) != 0x0000) {
+ zrdev_err(zr,
+ "%s: attach failed, can't connect to jpeg processor!\n",
+ ptr->name);
+ return -ENXIO;
+ }
+ zr36050_write(ptr, ZR050_SOF_IDX, 0xff);
+ zr36050_write(ptr, ZR050_SOF_IDX + 1, 0xc0);
+ if (((zr36050_read(ptr, ZR050_SOF_IDX) << 8) |
+ zr36050_read(ptr, ZR050_SOF_IDX + 1)) != 0xffc0) {
+ zrdev_err(zr,
+ "%s: attach failed, can't connect to jpeg processor!\n",
+ ptr->name);
+ return -ENXIO;
+ }
+
+ zr36050_wait_end(ptr);
+ if ((ptr->status1 & 0x4) == 0) {
+ zrdev_err(zr,
+ "%s: attach failed, jpeg processor failed (end flag)!\n",
+ ptr->name);
+ return -EBUSY;
+ }
+
+ return 0; /* looks good! */
+}
+
+/* Local helper function: simple loop for pushing the init datasets */
+
+static int zr36050_pushit(struct zr36050 *ptr, u16 startreg, u16 len, const char *data)
+{
+ struct zoran *zr = videocodec_to_zoran(ptr->codec);
+ int i = 0;
+
+ zrdev_dbg(zr, "%s: write data block to 0x%04x (len=%d)\n", ptr->name,
+ startreg, len);
+ while (i < len)
+ zr36050_write(ptr, startreg++, data[i++]);
+
+ return i;
+}
+
+/*
+ * Basic datasets:
+ *
+ * jpeg baseline setup data (you find it on lots places in internet, or just
+ * extract it from any regular .jpg image...)
+ *
+ * Could be variable, but until it's not needed it they are just fixed to save
+ * memory. Otherwise expand zr36050 structure with arrays, push the values to
+ * it and initialize from there, as e.g. the linux zr36057/60 driver does it.
+ */
+
+static const char zr36050_dqt[0x86] = {
+ 0xff, 0xdb, //Marker: DQT
+ 0x00, 0x84, //Length: 2*65+2
+ 0x00, //Pq,Tq first table
+ 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e,
+ 0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28,
+ 0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
+ 0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33,
+ 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44,
+ 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57,
+ 0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71,
+ 0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63,
+ 0x01, //Pq,Tq second table
+ 0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
+ 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63
+};
+
+static const char zr36050_dht[0x1a4] = {
+ 0xff, 0xc4, //Marker: DHT
+ 0x01, 0xa2, //Length: 2*AC, 2*DC
+ 0x00, //DC first table
+ 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x01, //DC second table
+ 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x10, //AC first table
+ 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
+ 0x05, 0x05, 0x04, 0x04, 0x00, 0x00,
+ 0x01, 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11,
+ 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61,
+ 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1,
+ 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24,
+ 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34,
+ 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
+ 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56,
+ 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
+ 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
+ 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
+ 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
+ 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9,
+ 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8,
+ 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9,
+ 0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
+ 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+ 0xF8, 0xF9, 0xFA,
+ 0x11, //AC second table
+ 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
+ 0x07, 0x05, 0x04, 0x04, 0x00, 0x01,
+ 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04,
+ 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
+ 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
+ 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62,
+ 0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25,
+ 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A,
+ 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
+ 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56,
+ 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
+ 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+ 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
+ 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8,
+ 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
+ 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8,
+ 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
+ 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
+ 0xF9, 0xFA
+};
+
+/* jpeg baseline setup, this is just fixed in this driver (YUV pictures) */
+#define NO_OF_COMPONENTS 0x3 //Y,U,V
+#define BASELINE_PRECISION 0x8 //MCU size (?)
+static const char zr36050_tq[8] = { 0, 1, 1, 0, 0, 0, 0, 0 }; //table idx's QT
+static const char zr36050_td[8] = { 0, 1, 1, 0, 0, 0, 0, 0 }; //table idx's DC
+static const char zr36050_ta[8] = { 0, 1, 1, 0, 0, 0, 0, 0 }; //table idx's AC
+
+/* horizontal 422 decimation setup (maybe we support 411 or so later, too) */
+static const char zr36050_decimation_h[8] = { 2, 1, 1, 0, 0, 0, 0, 0 };
+static const char zr36050_decimation_v[8] = { 1, 1, 1, 0, 0, 0, 0, 0 };
+
+/*
+ * Local helper functions:
+ *
+ * calculation and setup of parameter-dependent JPEG baseline segments
+ * (needed for compression only)
+ */
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * SOF (start of frame) segment depends on width, height and sampling ratio
+ * of each color component
+ */
+static int zr36050_set_sof(struct zr36050 *ptr)
+{
+ struct zoran *zr = videocodec_to_zoran(ptr->codec);
+ char sof_data[34]; // max. size of register set
+ int i;
+
+ zrdev_dbg(zr, "%s: write SOF (%dx%d, %d components)\n", ptr->name,
+ ptr->width, ptr->height, NO_OF_COMPONENTS);
+ sof_data[0] = 0xff;
+ sof_data[1] = 0xc0;
+ sof_data[2] = 0x00;
+ sof_data[3] = (3 * NO_OF_COMPONENTS) + 8;
+ sof_data[4] = BASELINE_PRECISION; // only '8' possible with zr36050
+ sof_data[5] = (ptr->height) >> 8;
+ sof_data[6] = (ptr->height) & 0xff;
+ sof_data[7] = (ptr->width) >> 8;
+ sof_data[8] = (ptr->width) & 0xff;
+ sof_data[9] = NO_OF_COMPONENTS;
+ for (i = 0; i < NO_OF_COMPONENTS; i++) {
+ sof_data[10 + (i * 3)] = i; // index identifier
+ sof_data[11 + (i * 3)] = (ptr->h_samp_ratio[i] << 4) |
+ (ptr->v_samp_ratio[i]); // sampling ratios
+ sof_data[12 + (i * 3)] = zr36050_tq[i]; // Q table selection
+ }
+ return zr36050_pushit(ptr, ZR050_SOF_IDX,
+ (3 * NO_OF_COMPONENTS) + 10, sof_data);
+}
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * SOS (start of scan) segment depends on the used scan components
+ * of each color component
+ */
+
+static int zr36050_set_sos(struct zr36050 *ptr)
+{
+ struct zoran *zr = videocodec_to_zoran(ptr->codec);
+ char sos_data[16]; // max. size of register set
+ int i;
+
+ zrdev_dbg(zr, "%s: write SOS\n", ptr->name);
+ sos_data[0] = 0xff;
+ sos_data[1] = 0xda;
+ sos_data[2] = 0x00;
+ sos_data[3] = 2 + 1 + (2 * NO_OF_COMPONENTS) + 3;
+ sos_data[4] = NO_OF_COMPONENTS;
+ for (i = 0; i < NO_OF_COMPONENTS; i++) {
+ sos_data[5 + (i * 2)] = i; // index
+ sos_data[6 + (i * 2)] = (zr36050_td[i] << 4) | zr36050_ta[i]; // AC/DC tbl.sel.
+ }
+ sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 2] = 00; // scan start
+ sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 3] = 0x3F;
+ sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 4] = 00;
+ return zr36050_pushit(ptr, ZR050_SOS1_IDX,
+ 4 + 1 + (2 * NO_OF_COMPONENTS) + 3,
+ sos_data);
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* DRI (define restart interval) */
+
+static int zr36050_set_dri(struct zr36050 *ptr)
+{
+ struct zoran *zr = videocodec_to_zoran(ptr->codec);
+ char dri_data[6]; // max. size of register set
+
+ zrdev_dbg(zr, "%s: write DRI\n", ptr->name);
+ dri_data[0] = 0xff;
+ dri_data[1] = 0xdd;
+ dri_data[2] = 0x00;
+ dri_data[3] = 0x04;
+ dri_data[4] = ptr->dri >> 8;
+ dri_data[5] = ptr->dri & 0xff;
+ return zr36050_pushit(ptr, ZR050_DRI_IDX, 6, dri_data);
+}
+
+/*
+ * Setup function:
+ *
+ * Setup compression/decompression of Zoran's JPEG processor
+ * ( see also zoran 36050 manual )
+ *
+ * ... sorry for the spaghetti code ...
+ */
+static void zr36050_init(struct zr36050 *ptr)
+{
+ int sum = 0;
+ long bitcnt, tmp;
+ struct zoran *zr = videocodec_to_zoran(ptr->codec);
+
+ if (ptr->mode == CODEC_DO_COMPRESSION) {
+ zrdev_dbg(zr, "%s: COMPRESSION SETUP\n", ptr->name);
+
+ /* 050 communicates with 057 in master mode */
+ zr36050_write(ptr, ZR050_HARDWARE, ZR050_HW_MSTR);
+
+ /* encoding table preload for compression */
+ zr36050_write(ptr, ZR050_MODE,
+ ZR050_MO_COMP | ZR050_MO_TLM);
+ zr36050_write(ptr, ZR050_OPTIONS, 0);
+
+ /* disable all IRQs */
+ zr36050_write(ptr, ZR050_INT_REQ_0, 0);
+ zr36050_write(ptr, ZR050_INT_REQ_1, 3); // low 2 bits always 1
+
+ /* volume control settings */
+ /*zr36050_write(ptr, ZR050_MBCV, ptr->max_block_vol);*/
+ zr36050_write(ptr, ZR050_SF_HI, ptr->scalefact >> 8);
+ zr36050_write(ptr, ZR050_SF_LO, ptr->scalefact & 0xff);
+
+ zr36050_write(ptr, ZR050_AF_HI, 0xff);
+ zr36050_write(ptr, ZR050_AF_M, 0xff);
+ zr36050_write(ptr, ZR050_AF_LO, 0xff);
+
+ /* setup the variable jpeg tables */
+ sum += zr36050_set_sof(ptr);
+ sum += zr36050_set_sos(ptr);
+ sum += zr36050_set_dri(ptr);
+
+ /*
+ * setup the fixed jpeg tables - maybe variable, though -
+ * (see table init section above)
+ */
+ zrdev_dbg(zr, "%s: write DQT, DHT, APP\n", ptr->name);
+ sum += zr36050_pushit(ptr, ZR050_DQT_IDX,
+ sizeof(zr36050_dqt), zr36050_dqt);
+ sum += zr36050_pushit(ptr, ZR050_DHT_IDX,
+ sizeof(zr36050_dht), zr36050_dht);
+ zr36050_write(ptr, ZR050_APP_IDX, 0xff);
+ zr36050_write(ptr, ZR050_APP_IDX + 1, 0xe0 + ptr->app.appn);
+ zr36050_write(ptr, ZR050_APP_IDX + 2, 0x00);
+ zr36050_write(ptr, ZR050_APP_IDX + 3, ptr->app.len + 2);
+ sum += zr36050_pushit(ptr, ZR050_APP_IDX + 4, 60,
+ ptr->app.data) + 4;
+ zr36050_write(ptr, ZR050_COM_IDX, 0xff);
+ zr36050_write(ptr, ZR050_COM_IDX + 1, 0xfe);
+ zr36050_write(ptr, ZR050_COM_IDX + 2, 0x00);
+ zr36050_write(ptr, ZR050_COM_IDX + 3, ptr->com.len + 2);
+ sum += zr36050_pushit(ptr, ZR050_COM_IDX + 4, 60,
+ ptr->com.data) + 4;
+
+ /* do the internal huffman table preload */
+ zr36050_write(ptr, ZR050_MARKERS_EN, ZR050_ME_DHTI);
+
+ zr36050_write(ptr, ZR050_GO, 1); // launch codec
+ zr36050_wait_end(ptr);
+ zrdev_dbg(zr, "%s: Status after table preload: 0x%02x\n",
+ ptr->name, ptr->status1);
+
+ if ((ptr->status1 & 0x4) == 0) {
+ zrdev_err(zr, "%s: init aborted!\n", ptr->name);
+ return; // something is wrong, its timed out!!!!
+ }
+
+ /* setup misc. data for compression (target code sizes) */
+
+ /* size of compressed code to reach without header data */
+ sum = ptr->real_code_vol - sum;
+ bitcnt = sum << 3; /* need the size in bits */
+
+ tmp = bitcnt >> 16;
+ zrdev_dbg(zr,
+ "%s: code: csize=%d, tot=%d, bit=%ld, highbits=%ld\n",
+ ptr->name, sum, ptr->real_code_vol, bitcnt, tmp);
+ zr36050_write(ptr, ZR050_TCV_NET_HI, tmp >> 8);
+ zr36050_write(ptr, ZR050_TCV_NET_MH, tmp & 0xff);
+ tmp = bitcnt & 0xffff;
+ zr36050_write(ptr, ZR050_TCV_NET_ML, tmp >> 8);
+ zr36050_write(ptr, ZR050_TCV_NET_LO, tmp & 0xff);
+
+ bitcnt -= bitcnt >> 7; // bits without stuffing
+ bitcnt -= ((bitcnt * 5) >> 6); // bits without eob
+
+ tmp = bitcnt >> 16;
+ zrdev_dbg(zr, "%s: code: nettobit=%ld, highnettobits=%ld\n",
+ ptr->name, bitcnt, tmp);
+ zr36050_write(ptr, ZR050_TCV_DATA_HI, tmp >> 8);
+ zr36050_write(ptr, ZR050_TCV_DATA_MH, tmp & 0xff);
+ tmp = bitcnt & 0xffff;
+ zr36050_write(ptr, ZR050_TCV_DATA_ML, tmp >> 8);
+ zr36050_write(ptr, ZR050_TCV_DATA_LO, tmp & 0xff);
+
+ /* compression setup with or without bitrate control */
+ zr36050_write(ptr, ZR050_MODE,
+ ZR050_MO_COMP | ZR050_MO_PASS2 |
+ (ptr->bitrate_ctrl ? ZR050_MO_BRC : 0));
+
+ /* this headers seem to deliver "valid AVI" jpeg frames */
+ zr36050_write(ptr, ZR050_MARKERS_EN,
+ ZR050_ME_DQT | ZR050_ME_DHT |
+ ((ptr->app.len > 0) ? ZR050_ME_APP : 0) |
+ ((ptr->com.len > 0) ? ZR050_ME_COM : 0));
+ } else {
+ zrdev_dbg(zr, "%s: EXPANSION SETUP\n", ptr->name);
+
+ /* 050 communicates with 055 in master mode */
+ zr36050_write(ptr, ZR050_HARDWARE,
+ ZR050_HW_MSTR | ZR050_HW_CFIS_2_CLK);
+
+ /* encoding table preload */
+ zr36050_write(ptr, ZR050_MODE, ZR050_MO_TLM);
+
+ /* disable all IRQs */
+ zr36050_write(ptr, ZR050_INT_REQ_0, 0);
+ zr36050_write(ptr, ZR050_INT_REQ_1, 3); // low 2 bits always 1
+
+ zrdev_dbg(zr, "%s: write DHT\n", ptr->name);
+ zr36050_pushit(ptr, ZR050_DHT_IDX, sizeof(zr36050_dht),
+ zr36050_dht);
+
+ /* do the internal huffman table preload */
+ zr36050_write(ptr, ZR050_MARKERS_EN, ZR050_ME_DHTI);
+
+ zr36050_write(ptr, ZR050_GO, 1); // launch codec
+ zr36050_wait_end(ptr);
+ zrdev_dbg(zr, "%s: Status after table preload: 0x%02x\n",
+ ptr->name, ptr->status1);
+
+ if ((ptr->status1 & 0x4) == 0) {
+ zrdev_err(zr, "%s: init aborted!\n", ptr->name);
+ return; // something is wrong, its timed out!!!!
+ }
+
+ /* setup misc. data for expansion */
+ zr36050_write(ptr, ZR050_MODE, 0);
+ zr36050_write(ptr, ZR050_MARKERS_EN, 0);
+ }
+
+ /* adr on selected, to allow GO from master */
+ zr36050_read(ptr, 0);
+}
+
+/*
+ * CODEC API FUNCTIONS
+ *
+ * this functions are accessed by the master via the API structure
+ */
+
+/*
+ * set compression/expansion mode and launches codec -
+ * this should be the last call from the master before starting processing
+ */
+static int zr36050_set_mode(struct videocodec *codec, int mode)
+{
+ struct zr36050 *ptr = (struct zr36050 *)codec->data;
+ struct zoran *zr = videocodec_to_zoran(codec);
+
+ zrdev_dbg(zr, "%s: set_mode %d call\n", ptr->name, mode);
+
+ if ((mode != CODEC_DO_EXPANSION) && (mode != CODEC_DO_COMPRESSION))
+ return -EINVAL;
+
+ ptr->mode = mode;
+ zr36050_init(ptr);
+
+ return 0;
+}
+
+/* set picture size (norm is ignored as the codec doesn't know about it) */
+static int zr36050_set_video(struct videocodec *codec, const struct tvnorm *norm,
+ struct vfe_settings *cap, struct vfe_polarity *pol)
+{
+ struct zr36050 *ptr = (struct zr36050 *)codec->data;
+ struct zoran *zr = videocodec_to_zoran(codec);
+ int size;
+
+ zrdev_dbg(zr, "%s: set_video %d.%d, %d/%d-%dx%d (0x%x) q%d call\n",
+ ptr->name, norm->h_start, norm->v_start,
+ cap->x, cap->y, cap->width, cap->height,
+ cap->decimation, cap->quality);
+ /*
+ * trust the master driver that it knows what it does - so
+ * we allow invalid startx/y and norm for now ...
+ */
+ ptr->width = cap->width / (cap->decimation & 0xff);
+ ptr->height = cap->height / ((cap->decimation >> 8) & 0xff);
+
+ /* (KM) JPEG quality */
+ size = ptr->width * ptr->height;
+ size *= 16; /* size in bits */
+ /* apply quality setting */
+ size = size * cap->quality / 200;
+
+ /* Minimum: 1kb */
+ if (size < 8192)
+ size = 8192;
+ /* Maximum: 7/8 of code buffer */
+ if (size > ptr->total_code_vol * 7)
+ size = ptr->total_code_vol * 7;
+
+ ptr->real_code_vol = size >> 3; /* in bytes */
+
+ /*
+ * Set max_block_vol here (previously in zr36050_init, moved
+ * here for consistency with zr36060 code
+ */
+ zr36050_write(ptr, ZR050_MBCV, ptr->max_block_vol);
+
+ return 0;
+}
+
+/* additional control functions */
+static int zr36050_control(struct videocodec *codec, int type, int size, void *data)
+{
+ struct zr36050 *ptr = (struct zr36050 *)codec->data;
+ struct zoran *zr = videocodec_to_zoran(codec);
+ int *ival = (int *)data;
+
+ zrdev_dbg(zr, "%s: control %d call with %d byte\n", ptr->name, type,
+ size);
+
+ switch (type) {
+ case CODEC_G_STATUS: /* get last status */
+ if (size != sizeof(int))
+ return -EFAULT;
+ zr36050_read_status1(ptr);
+ *ival = ptr->status1;
+ break;
+
+ case CODEC_G_CODEC_MODE:
+ if (size != sizeof(int))
+ return -EFAULT;
+ *ival = CODEC_MODE_BJPG;
+ break;
+
+ case CODEC_S_CODEC_MODE:
+ if (size != sizeof(int))
+ return -EFAULT;
+ if (*ival != CODEC_MODE_BJPG)
+ return -EINVAL;
+ /* not needed, do nothing */
+ return 0;
+
+ case CODEC_G_VFE:
+ case CODEC_S_VFE:
+ /* not needed, do nothing */
+ return 0;
+
+ case CODEC_S_MMAP:
+ /* not available, give an error */
+ return -ENXIO;
+
+ case CODEC_G_JPEG_TDS_BYTE: /* get target volume in byte */
+ if (size != sizeof(int))
+ return -EFAULT;
+ *ival = ptr->total_code_vol;
+ break;
+
+ case CODEC_S_JPEG_TDS_BYTE: /* get target volume in byte */
+ if (size != sizeof(int))
+ return -EFAULT;
+ ptr->total_code_vol = *ival;
+ ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3;
+ break;
+
+ case CODEC_G_JPEG_SCALE: /* get scaling factor */
+ if (size != sizeof(int))
+ return -EFAULT;
+ *ival = zr36050_read_scalefactor(ptr);
+ break;
+
+ case CODEC_S_JPEG_SCALE: /* set scaling factor */
+ if (size != sizeof(int))
+ return -EFAULT;
+ ptr->scalefact = *ival;
+ break;
+
+ case CODEC_G_JPEG_APP_DATA: { /* get appn marker data */
+ struct jpeg_app_marker *app = data;
+
+ if (size != sizeof(struct jpeg_app_marker))
+ return -EFAULT;
+
+ *app = ptr->app;
+ break;
+ }
+
+ case CODEC_S_JPEG_APP_DATA: { /* set appn marker data */
+ struct jpeg_app_marker *app = data;
+
+ if (size != sizeof(struct jpeg_app_marker))
+ return -EFAULT;
+
+ ptr->app = *app;
+ break;
+ }
+
+ case CODEC_G_JPEG_COM_DATA: { /* get comment marker data */
+ struct jpeg_com_marker *com = data;
+
+ if (size != sizeof(struct jpeg_com_marker))
+ return -EFAULT;
+
+ *com = ptr->com;
+ break;
+ }
+
+ case CODEC_S_JPEG_COM_DATA: { /* set comment marker data */
+ struct jpeg_com_marker *com = data;
+
+ if (size != sizeof(struct jpeg_com_marker))
+ return -EFAULT;
+
+ ptr->com = *com;
+ break;
+ }
+
+ default:
+ return -EINVAL;
+ }
+
+ return size;
+}
+
+/* Exit and unregister function: Deinitializes Zoran's JPEG processor */
+
+static int zr36050_unset(struct videocodec *codec)
+{
+ struct zr36050 *ptr = codec->data;
+ struct zoran *zr = videocodec_to_zoran(codec);
+
+ if (ptr) {
+ /* do wee need some codec deinit here, too ???? */
+
+ zrdev_dbg(zr, "%s: finished codec #%d\n", ptr->name,
+ ptr->num);
+ kfree(ptr);
+ codec->data = NULL;
+
+ zr36050_codecs--;
+ return 0;
+ }
+
+ return -EFAULT;
+}
+
+/*
+ * Setup and registry function:
+ *
+ * Initializes Zoran's JPEG processor
+ *
+ * Also sets pixel size, average code size, mode (compr./decompr.)
+ * (the given size is determined by the processor with the video interface)
+ */
+
+static int zr36050_setup(struct videocodec *codec)
+{
+ struct zr36050 *ptr;
+ struct zoran *zr = videocodec_to_zoran(codec);
+ int res;
+
+ zrdev_dbg(zr, "zr36050: initializing MJPEG subsystem #%d.\n",
+ zr36050_codecs);
+
+ if (zr36050_codecs == MAX_CODECS) {
+ zrdev_err(zr,
+ "zr36050: Can't attach more codecs!\n");
+ return -ENOSPC;
+ }
+ //mem structure init
+ ptr = kzalloc(sizeof(*ptr), GFP_KERNEL);
+ codec->data = ptr;
+ if (!ptr)
+ return -ENOMEM;
+
+ snprintf(ptr->name, sizeof(ptr->name), "zr36050[%d]",
+ zr36050_codecs);
+ ptr->num = zr36050_codecs++;
+ ptr->codec = codec;
+
+ //testing
+ res = zr36050_basic_test(ptr);
+ if (res < 0) {
+ zr36050_unset(codec);
+ return res;
+ }
+ //final setup
+ memcpy(ptr->h_samp_ratio, zr36050_decimation_h, 8);
+ memcpy(ptr->v_samp_ratio, zr36050_decimation_v, 8);
+
+ /* 0 or 1 - fixed file size flag (what is the difference?) */
+ ptr->bitrate_ctrl = 0;
+ ptr->mode = CODEC_DO_COMPRESSION;
+ ptr->width = 384;
+ ptr->height = 288;
+ ptr->total_code_vol = 16000;
+ ptr->max_block_vol = 240;
+ ptr->scalefact = 0x100;
+ ptr->dri = 1;
+
+ /* no app/com marker by default */
+ ptr->app.appn = 0;
+ ptr->app.len = 0;
+ ptr->com.len = 0;
+
+ zr36050_init(ptr);
+
+ zrdev_info(zr, "%s: codec attached and running\n",
+ ptr->name);
+
+ return 0;
+}
+
+static const struct videocodec zr36050_codec = {
+ .name = "zr36050",
+ .magic = 0L, // magic not used
+ .flags =
+ CODEC_FLAG_JPEG | CODEC_FLAG_HARDWARE | CODEC_FLAG_ENCODER |
+ CODEC_FLAG_DECODER,
+ .type = CODEC_TYPE_ZR36050,
+ .setup = zr36050_setup, // functionality
+ .unset = zr36050_unset,
+ .set_mode = zr36050_set_mode,
+ .set_video = zr36050_set_video,
+ .control = zr36050_control,
+ // others are not used
+};
+
+/* HOOK IN DRIVER AS KERNEL MODULE */
+
+int zr36050_init_module(void)
+{
+ zr36050_codecs = 0;
+ return videocodec_register(&zr36050_codec);
+}
+
+void zr36050_cleanup_module(void)
+{
+ if (zr36050_codecs) {
+ pr_debug("zr36050: something's wrong - %d codecs left somehow.\n",
+ zr36050_codecs);
+ }
+ videocodec_unregister(&zr36050_codec);
+}
diff --git a/drivers/media/pci/zoran/zr36050.h b/drivers/media/pci/zoran/zr36050.h
new file mode 100644
index 000000000000..f9b58f4c77b9
--- /dev/null
+++ b/drivers/media/pci/zoran/zr36050.h
@@ -0,0 +1,165 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Zoran ZR36050 basic configuration functions - header file
+ *
+ * Copyright (C) 2001 Wolfgang Scherr <scherr@net4you.at>
+ */
+
+#ifndef ZR36050_H
+#define ZR36050_H
+
+#include "videocodec.h"
+
+/* data stored for each zoran jpeg codec chip */
+struct zr36050 {
+ char name[32];
+ int num;
+ /* io datastructure */
+ struct videocodec *codec;
+ // last coder status
+ __u8 status1;
+ // actual coder setup
+ int mode;
+
+ __u16 width;
+ __u16 height;
+
+ __u16 bitrate_ctrl;
+
+ __u32 total_code_vol;
+ __u32 real_code_vol;
+ __u16 max_block_vol;
+
+ __u8 h_samp_ratio[8];
+ __u8 v_samp_ratio[8];
+ __u16 scalefact;
+ __u16 dri;
+
+ /* com/app marker */
+ struct jpeg_com_marker com;
+ struct jpeg_app_marker app;
+};
+
+/* zr36050 register addresses */
+#define ZR050_GO 0x000
+#define ZR050_HARDWARE 0x002
+#define ZR050_MODE 0x003
+#define ZR050_OPTIONS 0x004
+#define ZR050_MBCV 0x005
+#define ZR050_MARKERS_EN 0x006
+#define ZR050_INT_REQ_0 0x007
+#define ZR050_INT_REQ_1 0x008
+#define ZR050_TCV_NET_HI 0x009
+#define ZR050_TCV_NET_MH 0x00a
+#define ZR050_TCV_NET_ML 0x00b
+#define ZR050_TCV_NET_LO 0x00c
+#define ZR050_TCV_DATA_HI 0x00d
+#define ZR050_TCV_DATA_MH 0x00e
+#define ZR050_TCV_DATA_ML 0x00f
+#define ZR050_TCV_DATA_LO 0x010
+#define ZR050_SF_HI 0x011
+#define ZR050_SF_LO 0x012
+#define ZR050_AF_HI 0x013
+#define ZR050_AF_M 0x014
+#define ZR050_AF_LO 0x015
+#define ZR050_ACV_HI 0x016
+#define ZR050_ACV_MH 0x017
+#define ZR050_ACV_ML 0x018
+#define ZR050_ACV_LO 0x019
+#define ZR050_ACT_HI 0x01a
+#define ZR050_ACT_MH 0x01b
+#define ZR050_ACT_ML 0x01c
+#define ZR050_ACT_LO 0x01d
+#define ZR050_ACV_TURN_HI 0x01e
+#define ZR050_ACV_TURN_MH 0x01f
+#define ZR050_ACV_TURN_ML 0x020
+#define ZR050_ACV_TURN_LO 0x021
+#define ZR050_STATUS_0 0x02e
+#define ZR050_STATUS_1 0x02f
+
+#define ZR050_SOF_IDX 0x040
+#define ZR050_SOS1_IDX 0x07a
+#define ZR050_SOS2_IDX 0x08a
+#define ZR050_SOS3_IDX 0x09a
+#define ZR050_SOS4_IDX 0x0aa
+#define ZR050_DRI_IDX 0x0c0
+#define ZR050_DNL_IDX 0x0c6
+#define ZR050_DQT_IDX 0x0cc
+#define ZR050_DHT_IDX 0x1d4
+#define ZR050_APP_IDX 0x380
+#define ZR050_COM_IDX 0x3c0
+
+/* zr36050 hardware register bits */
+
+#define ZR050_HW_BSWD 0x80
+#define ZR050_HW_MSTR 0x40
+#define ZR050_HW_DMA 0x20
+#define ZR050_HW_CFIS_1_CLK 0x00
+#define ZR050_HW_CFIS_2_CLK 0x04
+#define ZR050_HW_CFIS_3_CLK 0x08
+#define ZR050_HW_CFIS_4_CLK 0x0C
+#define ZR050_HW_CFIS_5_CLK 0x10
+#define ZR050_HW_CFIS_6_CLK 0x14
+#define ZR050_HW_CFIS_7_CLK 0x18
+#define ZR050_HW_CFIS_8_CLK 0x1C
+#define ZR050_HW_BELE 0x01
+
+/* zr36050 mode register bits */
+
+#define ZR050_MO_COMP 0x80
+#define ZR050_MO_ATP 0x40
+#define ZR050_MO_PASS2 0x20
+#define ZR050_MO_TLM 0x10
+#define ZR050_MO_DCONLY 0x08
+#define ZR050_MO_BRC 0x04
+
+#define ZR050_MO_ATP 0x40
+#define ZR050_MO_PASS2 0x20
+#define ZR050_MO_TLM 0x10
+#define ZR050_MO_DCONLY 0x08
+
+/* zr36050 option register bits */
+
+#define ZR050_OP_NSCN_1 0x00
+#define ZR050_OP_NSCN_2 0x20
+#define ZR050_OP_NSCN_3 0x40
+#define ZR050_OP_NSCN_4 0x60
+#define ZR050_OP_NSCN_5 0x80
+#define ZR050_OP_NSCN_6 0xA0
+#define ZR050_OP_NSCN_7 0xC0
+#define ZR050_OP_NSCN_8 0xE0
+#define ZR050_OP_OVF 0x10
+
+/* zr36050 markers-enable register bits */
+
+#define ZR050_ME_APP 0x80
+#define ZR050_ME_COM 0x40
+#define ZR050_ME_DRI 0x20
+#define ZR050_ME_DQT 0x10
+#define ZR050_ME_DHT 0x08
+#define ZR050_ME_DNL 0x04
+#define ZR050_ME_DQTI 0x02
+#define ZR050_ME_DHTI 0x01
+
+/* zr36050 status0/1 register bit masks */
+
+#define ZR050_ST_RST_MASK 0x20
+#define ZR050_ST_SOF_MASK 0x02
+#define ZR050_ST_SOS_MASK 0x02
+#define ZR050_ST_DATRDY_MASK 0x80
+#define ZR050_ST_MRKDET_MASK 0x40
+#define ZR050_ST_RFM_MASK 0x10
+#define ZR050_ST_RFD_MASK 0x08
+#define ZR050_ST_END_MASK 0x04
+#define ZR050_ST_TCVOVF_MASK 0x02
+#define ZR050_ST_DATOVF_MASK 0x01
+
+/* pixel component idx */
+
+#define ZR050_Y_COMPONENT 0
+#define ZR050_U_COMPONENT 1
+#define ZR050_V_COMPONENT 2
+
+int zr36050_init_module(void);
+void zr36050_cleanup_module(void);
+#endif /*fndef ZR36050_H */
diff --git a/drivers/media/pci/zoran/zr36057.h b/drivers/media/pci/zoran/zr36057.h
new file mode 100644
index 000000000000..45d8afc62b37
--- /dev/null
+++ b/drivers/media/pci/zoran/zr36057.h
@@ -0,0 +1,154 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * zr36057.h - zr36057 register offsets
+ *
+ * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
+ */
+
+#ifndef _ZR36057_H_
+#define _ZR36057_H_
+
+/* Zoran ZR36057 registers */
+
+#define ZR36057_VFEHCR 0x000 /* Video Front End, Horizontal Configuration Register */
+#define ZR36057_VFEHCR_HS_POL BIT(30)
+#define ZR36057_VFEHCR_H_START 10
+#define ZR36057_VFEHCR_H_END 0
+#define ZR36057_VFEHCR_HMASK 0x3ff
+
+#define ZR36057_VFEVCR 0x004 /* Video Front End, Vertical Configuration Register */
+#define ZR36057_VFEVCR_VS_POL BIT(30)
+#define ZR36057_VFEVCR_V_START 10
+#define ZR36057_VFEVCR_V_END 0
+#define ZR36057_VFEVCR_VMASK 0x3ff
+
+#define ZR36057_VFESPFR 0x008 /* Video Front End, Scaler and Pixel Format Register */
+#define ZR36057_VFESPFR_EXT_FL BIT(26)
+#define ZR36057_VFESPFR_TOP_FIELD BIT(25)
+#define ZR36057_VFESPFR_VCLK_POL BIT(24)
+#define ZR36057_VFESPFR_H_FILTER 21
+#define ZR36057_VFESPFR_HOR_DCM 14
+#define ZR36057_VFESPFR_VER_DCM 8
+#define ZR36057_VFESPFR_DISP_MODE 6
+#define ZR36057_VFESPFR_YUV422 (0 << 3)
+#define ZR36057_VFESPFR_RGB888 (1 << 3)
+#define ZR36057_VFESPFR_RGB565 (2 << 3)
+#define ZR36057_VFESPFR_RGB555 (3 << 3)
+#define ZR36057_VFESPFR_ERR_DIF BIT(2)
+#define ZR36057_VFESPFR_PACK24 BIT(1)
+#define ZR36057_VFESPFR_LITTLE_ENDIAN BIT(0)
+
+#define ZR36057_VDTR 0x00c /* Video Display "Top" Register */
+
+#define ZR36057_VDBR 0x010 /* Video Display "Bottom" Register */
+
+#define ZR36057_VSSFGR 0x014 /* Video Stride, Status, and Frame Grab Register */
+#define ZR36057_VSSFGR_DISP_STRIDE 16
+#define ZR36057_VSSFGR_VID_OVF BIT(8)
+#define ZR36057_VSSFGR_SNAP_SHOT BIT(1)
+#define ZR36057_VSSFGR_FRAME_GRAB BIT(0)
+
+#define ZR36057_VDCR 0x018 /* Video Display Configuration Register */
+#define ZR36057_VDCR_VID_EN BIT(31)
+#define ZR36057_VDCR_MIN_PIX 24
+#define ZR36057_VDCR_TRITON BIT(24)
+#define ZR36057_VDCR_VID_WIN_HT 12
+#define ZR36057_VDCR_VID_WIN_WID 0
+
+#define ZR36057_MMTR 0x01c /* Masking Map "Top" Register */
+
+#define ZR36057_MMBR 0x020 /* Masking Map "Bottom" Register */
+
+#define ZR36057_OCR 0x024 /* Overlay Control Register */
+#define ZR36057_OCR_OVL_ENABLE BIT(15)
+#define ZR36057_OCR_MASK_STRIDE 0
+
+#define ZR36057_SPGPPCR 0x028 /* System, PCI, and General Purpose Pins Control Register */
+#define ZR36057_SPGPPCR_SOFT_RESET BIT(24)
+
+#define ZR36057_GPPGCR1 0x02c /* General Purpose Pins and GuestBus Control Register (1) */
+
+#define ZR36057_MCSAR 0x030 /* MPEG Code Source Address Register */
+
+#define ZR36057_MCTCR 0x034 /* MPEG Code Transfer Control Register */
+#define ZR36057_MCTCR_COD_TIME BIT(30)
+#define ZR36057_MCTCR_C_EMPTY BIT(29)
+#define ZR36057_MCTCR_C_FLUSH BIT(28)
+#define ZR36057_MCTCR_COD_GUEST_ID 20
+#define ZR36057_MCTCR_COD_GUEST_REG 16
+
+#define ZR36057_MCMPR 0x038 /* MPEG Code Memory Pointer Register */
+
+#define ZR36057_ISR 0x03c /* Interrupt Status Register */
+#define ZR36057_ISR_GIRQ1 BIT(30)
+#define ZR36057_ISR_GIRQ0 BIT(29)
+#define ZR36057_ISR_COD_REP_IRQ BIT(28)
+#define ZR36057_ISR_JPEG_REP_IRQ BIT(27)
+
+#define ZR36057_ICR 0x040 /* Interrupt Control Register */
+#define ZR36057_ICR_GIRQ1 BIT(30)
+#define ZR36057_ICR_GIRQ0 BIT(29)
+#define ZR36057_ICR_COD_REP_IRQ BIT(28)
+#define ZR36057_ICR_JPEG_REP_IRQ BIT(27)
+#define ZR36057_ICR_INT_PIN_EN BIT(24)
+
+#define ZR36057_I2CBR 0x044 /* I2C Bus Register */
+#define ZR36057_I2CBR_SDA BIT(1)
+#define ZR36057_I2CBR_SCL BIT(0)
+
+#define ZR36057_JMC 0x100 /* JPEG Mode and Control */
+#define ZR36057_JMC_JPG BIT(31)
+#define ZR36057_JMC_JPG_EXP_MODE (0 << 29)
+#define ZR36057_JMC_JPG_CMP_MODE BIT(29)
+#define ZR36057_JMC_MJPG_EXP_MODE (2 << 29)
+#define ZR36057_JMC_MJPG_CMP_MODE (3 << 29)
+#define ZR36057_JMC_RTBUSY_FB BIT(6)
+#define ZR36057_JMC_GO_EN BIT(5)
+#define ZR36057_JMC_SYNC_MSTR BIT(4)
+#define ZR36057_JMC_FLD_PER_BUFF BIT(3)
+#define ZR36057_JMC_VFIFO_FB BIT(2)
+#define ZR36057_JMC_CFIFO_FB BIT(1)
+#define ZR36057_JMC_STLL_LIT_ENDIAN BIT(0)
+
+#define ZR36057_JPC 0x104 /* JPEG Process Control */
+#define ZR36057_JPC_P_RESET BIT(7)
+#define ZR36057_JPC_COD_TRNS_EN BIT(5)
+#define ZR36057_JPC_ACTIVE BIT(0)
+
+#define ZR36057_VSP 0x108 /* Vertical Sync Parameters */
+#define ZR36057_VSP_VSYNC_SIZE 16
+#define ZR36057_VSP_FRM_TOT 0
+
+#define ZR36057_HSP 0x10c /* Horizontal Sync Parameters */
+#define ZR36057_HSP_HSYNC_START 16
+#define ZR36057_HSP_LINE_TOT 0
+
+#define ZR36057_FHAP 0x110 /* Field Horizontal Active Portion */
+#define ZR36057_FHAP_NAX 16
+#define ZR36057_FHAP_PAX 0
+
+#define ZR36057_FVAP 0x114 /* Field Vertical Active Portion */
+#define ZR36057_FVAP_NAY 16
+#define ZR36057_FVAP_PAY 0
+
+#define ZR36057_FPP 0x118 /* Field Process Parameters */
+#define ZR36057_FPP_ODD_EVEN BIT(0)
+
+#define ZR36057_JCBA 0x11c /* JPEG Code Base Address */
+
+#define ZR36057_JCFT 0x120 /* JPEG Code FIFO Threshold */
+
+#define ZR36057_JCGI 0x124 /* JPEG Codec Guest ID */
+#define ZR36057_JCGI_JPE_GUEST_ID 4
+#define ZR36057_JCGI_JPE_GUEST_REG 0
+
+#define ZR36057_GCR2 0x12c /* GuestBus Control Register (2) */
+
+#define ZR36057_POR 0x200 /* Post Office Register */
+#define ZR36057_POR_PO_PEN BIT(25)
+#define ZR36057_POR_PO_TIME BIT(24)
+#define ZR36057_POR_PO_DIR BIT(23)
+
+#define ZR36057_STR 0x300 /* "Still" Transfer Register */
+
+#endif
diff --git a/drivers/media/pci/zoran/zr36060.c b/drivers/media/pci/zoran/zr36060.c
new file mode 100644
index 000000000000..75fd167603dc
--- /dev/null
+++ b/drivers/media/pci/zoran/zr36060.c
@@ -0,0 +1,870 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Zoran ZR36060 basic configuration functions
+ *
+ * Copyright (C) 2002 Laurent Pinchart <laurent.pinchart@skynet.be>
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+#include <linux/types.h>
+#include <linux/wait.h>
+
+/* I/O commands, error codes */
+#include <linux/io.h>
+
+/* headerfile of this module */
+#include "zr36060.h"
+
+/* codec io API */
+#include "videocodec.h"
+
+/* it doesn't make sense to have more than 20 or so, just to prevent some unwanted loops */
+#define MAX_CODECS 20
+
+/* amount of chips attached via this driver */
+static int zr36060_codecs;
+
+static bool low_bitrate;
+module_param(low_bitrate, bool, 0);
+MODULE_PARM_DESC(low_bitrate, "Buz compatibility option, halves bitrate");
+
+/* =========================================================================
+ * Local hardware I/O functions:
+ * read/write via codec layer (registers are located in the master device)
+ * =========================================================================
+ */
+
+static u8 zr36060_read(struct zr36060 *ptr, u16 reg)
+{
+ u8 value = 0;
+ struct zoran *zr = videocodec_to_zoran(ptr->codec);
+
+ // just in case something is wrong...
+ if (ptr->codec->master_data->readreg)
+ value = (ptr->codec->master_data->readreg(ptr->codec, reg)) & 0xff;
+ else
+ zrdev_err(zr, "%s: invalid I/O setup, nothing read!\n", ptr->name);
+
+ return value;
+}
+
+static void zr36060_write(struct zr36060 *ptr, u16 reg, u8 value)
+{
+ struct zoran *zr = videocodec_to_zoran(ptr->codec);
+
+ zrdev_dbg(zr, "0x%02x @0x%04x\n", value, reg);
+
+ // just in case something is wrong...
+ if (ptr->codec->master_data->writereg)
+ ptr->codec->master_data->writereg(ptr->codec, reg, value);
+ else
+ zrdev_err(zr, "%s: invalid I/O setup, nothing written!\n", ptr->name);
+}
+
+/* =========================================================================
+ * Local helper function:
+ * status read
+ * =========================================================================
+ */
+
+/* status is kept in datastructure */
+static u8 zr36060_read_status(struct zr36060 *ptr)
+{
+ ptr->status = zr36060_read(ptr, ZR060_CFSR);
+
+ zr36060_read(ptr, 0);
+ return ptr->status;
+}
+
+/* scale factor is kept in datastructure */
+static u16 zr36060_read_scalefactor(struct zr36060 *ptr)
+{
+ ptr->scalefact = (zr36060_read(ptr, ZR060_SF_HI) << 8) |
+ (zr36060_read(ptr, ZR060_SF_LO) & 0xFF);
+
+ /* leave 0 selected for an eventually GO from master */
+ zr36060_read(ptr, 0);
+ return ptr->scalefact;
+}
+
+/* wait if codec is ready to proceed (end of processing) or time is over */
+static void zr36060_wait_end(struct zr36060 *ptr)
+{
+ struct zoran *zr = videocodec_to_zoran(ptr->codec);
+ int i = 0;
+
+ while (zr36060_read_status(ptr) & ZR060_CFSR_BUSY) {
+ udelay(1);
+ if (i++ > 200000) { // 200ms, there is for sure something wrong!!!
+ zrdev_dbg(zr,
+ "%s: timeout at wait_end (last status: 0x%02x)\n",
+ ptr->name, ptr->status);
+ break;
+ }
+ }
+}
+
+/* Basic test of "connectivity", writes/reads to/from memory the SOF marker */
+static int zr36060_basic_test(struct zr36060 *ptr)
+{
+ struct zoran *zr = videocodec_to_zoran(ptr->codec);
+
+ if ((zr36060_read(ptr, ZR060_IDR_DEV) != 0x33) &&
+ (zr36060_read(ptr, ZR060_IDR_REV) != 0x01)) {
+ zrdev_err(zr, "%s: attach failed, can't connect to jpeg processor!\n", ptr->name);
+ return -ENXIO;
+ }
+
+ zr36060_wait_end(ptr);
+ if (ptr->status & ZR060_CFSR_BUSY) {
+ zrdev_err(zr, "%s: attach failed, jpeg processor failed (end flag)!\n", ptr->name);
+ return -EBUSY;
+ }
+
+ return 0; /* looks good! */
+}
+
+/* simple loop for pushing the init datasets */
+static int zr36060_pushit(struct zr36060 *ptr, u16 startreg, u16 len, const char *data)
+{
+ struct zoran *zr = videocodec_to_zoran(ptr->codec);
+ int i = 0;
+
+ zrdev_dbg(zr, "%s: write data block to 0x%04x (len=%d)\n", ptr->name,
+ startreg, len);
+ while (i < len)
+ zr36060_write(ptr, startreg++, data[i++]);
+
+ return i;
+}
+
+/* =========================================================================
+ * Basic datasets:
+ * jpeg baseline setup data (you find it on lots places in internet, or just
+ * extract it from any regular .jpg image...)
+ *
+ * Could be variable, but until it's not needed it they are just fixed to save
+ * memory. Otherwise expand zr36060 structure with arrays, push the values to
+ * it and initialize from there, as e.g. the linux zr36057/60 driver does it.
+ * =========================================================================
+ */
+static const char zr36060_dqt[0x86] = {
+ 0xff, 0xdb, //Marker: DQT
+ 0x00, 0x84, //Length: 2*65+2
+ 0x00, //Pq,Tq first table
+ 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e,
+ 0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28,
+ 0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
+ 0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33,
+ 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44,
+ 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57,
+ 0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71,
+ 0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63,
+ 0x01, //Pq,Tq second table
+ 0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
+ 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63
+};
+
+static const char zr36060_dht[0x1a4] = {
+ 0xff, 0xc4, //Marker: DHT
+ 0x01, 0xa2, //Length: 2*AC, 2*DC
+ 0x00, //DC first table
+ 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x01, //DC second table
+ 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x10, //AC first table
+ 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
+ 0x05, 0x05, 0x04, 0x04, 0x00, 0x00,
+ 0x01, 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11,
+ 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61,
+ 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1,
+ 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24,
+ 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34,
+ 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
+ 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56,
+ 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
+ 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
+ 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
+ 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
+ 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9,
+ 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8,
+ 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9,
+ 0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
+ 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+ 0xF8, 0xF9, 0xFA,
+ 0x11, //AC second table
+ 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
+ 0x07, 0x05, 0x04, 0x04, 0x00, 0x01,
+ 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04,
+ 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
+ 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
+ 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62,
+ 0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25,
+ 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A,
+ 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
+ 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56,
+ 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
+ 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+ 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
+ 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8,
+ 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
+ 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8,
+ 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
+ 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
+ 0xF9, 0xFA
+};
+
+/* jpeg baseline setup, this is just fixed in this driver (YUV pictures) */
+#define NO_OF_COMPONENTS 0x3 //Y,U,V
+#define BASELINE_PRECISION 0x8 //MCU size (?)
+static const char zr36060_tq[8] = { 0, 1, 1, 0, 0, 0, 0, 0 }; //table idx's QT
+static const char zr36060_td[8] = { 0, 1, 1, 0, 0, 0, 0, 0 }; //table idx's DC
+static const char zr36060_ta[8] = { 0, 1, 1, 0, 0, 0, 0, 0 }; //table idx's AC
+
+/* horizontal 422 decimation setup (maybe we support 411 or so later, too) */
+static const char zr36060_decimation_h[8] = { 2, 1, 1, 0, 0, 0, 0, 0 };
+static const char zr36060_decimation_v[8] = { 1, 1, 1, 0, 0, 0, 0, 0 };
+
+/*
+ * SOF (start of frame) segment depends on width, height and sampling ratio
+ * of each color component
+ */
+static int zr36060_set_sof(struct zr36060 *ptr)
+{
+ struct zoran *zr = videocodec_to_zoran(ptr->codec);
+ char sof_data[34]; // max. size of register set
+ int i;
+
+ zrdev_dbg(zr, "%s: write SOF (%dx%d, %d components)\n", ptr->name,
+ ptr->width, ptr->height, NO_OF_COMPONENTS);
+ sof_data[0] = 0xff;
+ sof_data[1] = 0xc0;
+ sof_data[2] = 0x00;
+ sof_data[3] = (3 * NO_OF_COMPONENTS) + 8;
+ sof_data[4] = BASELINE_PRECISION; // only '8' possible with zr36060
+ sof_data[5] = (ptr->height) >> 8;
+ sof_data[6] = (ptr->height) & 0xff;
+ sof_data[7] = (ptr->width) >> 8;
+ sof_data[8] = (ptr->width) & 0xff;
+ sof_data[9] = NO_OF_COMPONENTS;
+ for (i = 0; i < NO_OF_COMPONENTS; i++) {
+ sof_data[10 + (i * 3)] = i; // index identifier
+ sof_data[11 + (i * 3)] = (ptr->h_samp_ratio[i] << 4) |
+ (ptr->v_samp_ratio[i]); // sampling ratios
+ sof_data[12 + (i * 3)] = zr36060_tq[i]; // Q table selection
+ }
+ return zr36060_pushit(ptr, ZR060_SOF_IDX,
+ (3 * NO_OF_COMPONENTS) + 10, sof_data);
+}
+
+/* SOS (start of scan) segment depends on the used scan components of each color component */
+static int zr36060_set_sos(struct zr36060 *ptr)
+{
+ struct zoran *zr = videocodec_to_zoran(ptr->codec);
+ char sos_data[16]; // max. size of register set
+ int i;
+
+ zrdev_dbg(zr, "%s: write SOS\n", ptr->name);
+ sos_data[0] = 0xff;
+ sos_data[1] = 0xda;
+ sos_data[2] = 0x00;
+ sos_data[3] = 2 + 1 + (2 * NO_OF_COMPONENTS) + 3;
+ sos_data[4] = NO_OF_COMPONENTS;
+ for (i = 0; i < NO_OF_COMPONENTS; i++) {
+ sos_data[5 + (i * 2)] = i; // index
+ sos_data[6 + (i * 2)] = (zr36060_td[i] << 4) |
+ zr36060_ta[i]; // AC/DC tbl.sel.
+ }
+ sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 2] = 00; // scan start
+ sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 3] = 0x3f;
+ sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 4] = 00;
+ return zr36060_pushit(ptr, ZR060_SOS_IDX,
+ 4 + 1 + (2 * NO_OF_COMPONENTS) + 3,
+ sos_data);
+}
+
+/* DRI (define restart interval) */
+static int zr36060_set_dri(struct zr36060 *ptr)
+{
+ struct zoran *zr = videocodec_to_zoran(ptr->codec);
+ char dri_data[6]; // max. size of register set
+
+ zrdev_dbg(zr, "%s: write DRI\n", ptr->name);
+ dri_data[0] = 0xff;
+ dri_data[1] = 0xdd;
+ dri_data[2] = 0x00;
+ dri_data[3] = 0x04;
+ dri_data[4] = (ptr->dri) >> 8;
+ dri_data[5] = (ptr->dri) & 0xff;
+ return zr36060_pushit(ptr, ZR060_DRI_IDX, 6, dri_data);
+}
+
+/* Setup compression/decompression of Zoran's JPEG processor ( see also zoran 36060 manual )
+ * ... sorry for the spaghetti code ...
+ */
+static void zr36060_init(struct zr36060 *ptr)
+{
+ int sum = 0;
+ long bitcnt, tmp;
+ struct zoran *zr = videocodec_to_zoran(ptr->codec);
+
+ if (ptr->mode == CODEC_DO_COMPRESSION) {
+ zrdev_dbg(zr, "%s: COMPRESSION SETUP\n", ptr->name);
+
+ zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SYNC_RST);
+
+ /* 060 communicates with 067 in master mode */
+ zr36060_write(ptr, ZR060_CIR, ZR060_CIR_CODE_MSTR);
+
+ /* Compression with or without variable scale factor */
+ /*FIXME: What about ptr->bitrate_ctrl? */
+ zr36060_write(ptr, ZR060_CMR, ZR060_CMR_COMP | ZR060_CMR_PASS2 | ZR060_CMR_BRB);
+
+ /* Must be zero */
+ zr36060_write(ptr, ZR060_MBZ, 0x00);
+ zr36060_write(ptr, ZR060_TCR_HI, 0x00);
+ zr36060_write(ptr, ZR060_TCR_LO, 0x00);
+
+ /* Disable all IRQs - no DataErr means autoreset */
+ zr36060_write(ptr, ZR060_IMR, 0);
+
+ /* volume control settings */
+ zr36060_write(ptr, ZR060_SF_HI, ptr->scalefact >> 8);
+ zr36060_write(ptr, ZR060_SF_LO, ptr->scalefact & 0xff);
+
+ zr36060_write(ptr, ZR060_AF_HI, 0xff);
+ zr36060_write(ptr, ZR060_AF_M, 0xff);
+ zr36060_write(ptr, ZR060_AF_LO, 0xff);
+
+ /* setup the variable jpeg tables */
+ sum += zr36060_set_sof(ptr);
+ sum += zr36060_set_sos(ptr);
+ sum += zr36060_set_dri(ptr);
+
+/* setup the fixed jpeg tables - maybe variable, though - (see table init section above) */
+ sum += zr36060_pushit(ptr, ZR060_DQT_IDX, sizeof(zr36060_dqt), zr36060_dqt);
+ sum += zr36060_pushit(ptr, ZR060_DHT_IDX, sizeof(zr36060_dht), zr36060_dht);
+ zr36060_write(ptr, ZR060_APP_IDX, 0xff);
+ zr36060_write(ptr, ZR060_APP_IDX + 1, 0xe0 + ptr->app.appn);
+ zr36060_write(ptr, ZR060_APP_IDX + 2, 0x00);
+ zr36060_write(ptr, ZR060_APP_IDX + 3, ptr->app.len + 2);
+ sum += zr36060_pushit(ptr, ZR060_APP_IDX + 4, 60, ptr->app.data) + 4;
+ zr36060_write(ptr, ZR060_COM_IDX, 0xff);
+ zr36060_write(ptr, ZR060_COM_IDX + 1, 0xfe);
+ zr36060_write(ptr, ZR060_COM_IDX + 2, 0x00);
+ zr36060_write(ptr, ZR060_COM_IDX + 3, ptr->com.len + 2);
+ sum += zr36060_pushit(ptr, ZR060_COM_IDX + 4, 60, ptr->com.data) + 4;
+
+ /* setup misc. data for compression (target code sizes) */
+
+ /* size of compressed code to reach without header data */
+ sum = ptr->real_code_vol - sum;
+ bitcnt = sum << 3; /* need the size in bits */
+
+ tmp = bitcnt >> 16;
+ zrdev_dbg(zr,
+ "%s: code: csize=%d, tot=%d, bit=%ld, highbits=%ld\n",
+ ptr->name, sum, ptr->real_code_vol, bitcnt, tmp);
+ zr36060_write(ptr, ZR060_TCV_NET_HI, tmp >> 8);
+ zr36060_write(ptr, ZR060_TCV_NET_MH, tmp & 0xff);
+ tmp = bitcnt & 0xffff;
+ zr36060_write(ptr, ZR060_TCV_NET_ML, tmp >> 8);
+ zr36060_write(ptr, ZR060_TCV_NET_LO, tmp & 0xff);
+
+ bitcnt -= bitcnt >> 7; // bits without stuffing
+ bitcnt -= ((bitcnt * 5) >> 6); // bits without eob
+
+ tmp = bitcnt >> 16;
+ zrdev_dbg(zr, "%s: code: nettobit=%ld, highnettobits=%ld\n",
+ ptr->name, bitcnt, tmp);
+ zr36060_write(ptr, ZR060_TCV_DATA_HI, tmp >> 8);
+ zr36060_write(ptr, ZR060_TCV_DATA_MH, tmp & 0xff);
+ tmp = bitcnt & 0xffff;
+ zr36060_write(ptr, ZR060_TCV_DATA_ML, tmp >> 8);
+ zr36060_write(ptr, ZR060_TCV_DATA_LO, tmp & 0xff);
+
+ /* JPEG markers to be included in the compressed stream */
+ zr36060_write(ptr, ZR060_MER,
+ ZR060_MER_DQT | ZR060_MER_DHT |
+ ((ptr->com.len > 0) ? ZR060_MER_COM : 0) |
+ ((ptr->app.len > 0) ? ZR060_MER_APP : 0));
+
+ /* Setup the Video Frontend */
+ /* Limit pixel range to 16..235 as per CCIR-601 */
+ zr36060_write(ptr, ZR060_VCR, ZR060_VCR_RANGE);
+
+ } else {
+ zrdev_dbg(zr, "%s: EXPANSION SETUP\n", ptr->name);
+
+ zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SYNC_RST);
+
+ /* 060 communicates with 067 in master mode */
+ zr36060_write(ptr, ZR060_CIR, ZR060_CIR_CODE_MSTR);
+
+ /* Decompression */
+ zr36060_write(ptr, ZR060_CMR, 0);
+
+ /* Must be zero */
+ zr36060_write(ptr, ZR060_MBZ, 0x00);
+ zr36060_write(ptr, ZR060_TCR_HI, 0x00);
+ zr36060_write(ptr, ZR060_TCR_LO, 0x00);
+
+ /* Disable all IRQs - no DataErr means autoreset */
+ zr36060_write(ptr, ZR060_IMR, 0);
+
+ /* setup misc. data for expansion */
+ zr36060_write(ptr, ZR060_MER, 0);
+
+/* setup the fixed jpeg tables - maybe variable, though - (see table init section above) */
+ zr36060_pushit(ptr, ZR060_DHT_IDX, sizeof(zr36060_dht), zr36060_dht);
+
+ /* Setup the Video Frontend */
+ //zr36060_write(ptr, ZR060_VCR, ZR060_VCR_FI_EXT);
+ //this doesn't seem right and doesn't work...
+ zr36060_write(ptr, ZR060_VCR, ZR060_VCR_RANGE);
+ }
+
+ /* Load the tables */
+ zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SYNC_RST | ZR060_LOAD_LOAD);
+ zr36060_wait_end(ptr);
+ zrdev_dbg(zr, "%s: Status after table preload: 0x%02x\n",
+ ptr->name, ptr->status);
+
+ if (ptr->status & ZR060_CFSR_BUSY) {
+ zrdev_err(zr, "%s: init aborted!\n", ptr->name);
+ return; // something is wrong, its timed out!!!!
+ }
+}
+
+/* =========================================================================
+ * CODEC API FUNCTIONS
+ * this functions are accessed by the master via the API structure
+ * =========================================================================
+ */
+
+/* set compressiion/expansion mode and launches codec -
+ * this should be the last call from the master before starting processing
+ */
+static int zr36060_set_mode(struct videocodec *codec, int mode)
+{
+ struct zr36060 *ptr = (struct zr36060 *)codec->data;
+ struct zoran *zr = videocodec_to_zoran(codec);
+
+ zrdev_dbg(zr, "%s: set_mode %d call\n", ptr->name, mode);
+
+ if (mode != CODEC_DO_EXPANSION && mode != CODEC_DO_COMPRESSION)
+ return -EINVAL;
+
+ ptr->mode = mode;
+ zr36060_init(ptr);
+
+ return 0;
+}
+
+/* set picture size (norm is ignored as the codec doesn't know about it) */
+static int zr36060_set_video(struct videocodec *codec, const struct tvnorm *norm,
+ struct vfe_settings *cap, struct vfe_polarity *pol)
+{
+ struct zr36060 *ptr = (struct zr36060 *)codec->data;
+ struct zoran *zr = videocodec_to_zoran(codec);
+ u32 reg;
+ int size;
+
+ zrdev_dbg(zr, "%s: set_video %d/%d-%dx%d (%%%d) call\n", ptr->name,
+ cap->x, cap->y, cap->width, cap->height, cap->decimation);
+
+ /* if () return -EINVAL;
+ * trust the master driver that it knows what it does - so
+ * we allow invalid startx/y and norm for now ...
+ */
+ ptr->width = cap->width / (cap->decimation & 0xff);
+ ptr->height = cap->height / (cap->decimation >> 8);
+
+ zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SYNC_RST);
+
+ /* Note that VSPol/HSPol bits in zr36060 have the opposite
+ * meaning of their zr360x7 counterparts with the same names
+ * N.b. for VSPol this is only true if FIVEdge = 0 (default,
+ * left unchanged here - in accordance with datasheet).
+ */
+ reg = (!pol->vsync_pol ? ZR060_VPR_VS_POL : 0)
+ | (!pol->hsync_pol ? ZR060_VPR_HS_POL : 0)
+ | (pol->field_pol ? ZR060_VPR_FI_POL : 0)
+ | (pol->blank_pol ? ZR060_VPR_BL_POL : 0)
+ | (pol->subimg_pol ? ZR060_VPR_S_IMG_POL : 0)
+ | (pol->poe_pol ? ZR060_VPR_POE_POL : 0)
+ | (pol->pvalid_pol ? ZR060_VPR_P_VAL_POL : 0)
+ | (pol->vclk_pol ? ZR060_VPR_VCLK_POL : 0);
+ zr36060_write(ptr, ZR060_VPR, reg);
+
+ reg = 0;
+ switch (cap->decimation & 0xff) {
+ default:
+ case 1:
+ break;
+
+ case 2:
+ reg |= ZR060_SR_H_SCALE2;
+ break;
+
+ case 4:
+ reg |= ZR060_SR_H_SCALE4;
+ break;
+ }
+
+ switch (cap->decimation >> 8) {
+ default:
+ case 1:
+ break;
+
+ case 2:
+ reg |= ZR060_SR_V_SCALE;
+ break;
+ }
+ zr36060_write(ptr, ZR060_SR, reg);
+
+ zr36060_write(ptr, ZR060_BCR_Y, 0x00);
+ zr36060_write(ptr, ZR060_BCR_U, 0x80);
+ zr36060_write(ptr, ZR060_BCR_V, 0x80);
+
+ /* sync generator */
+
+ reg = norm->ht - 1; /* Vtotal */
+ zr36060_write(ptr, ZR060_SGR_VTOTAL_HI, (reg >> 8) & 0xff);
+ zr36060_write(ptr, ZR060_SGR_VTOTAL_LO, (reg >> 0) & 0xff);
+
+ reg = norm->wt - 1; /* Htotal */
+ zr36060_write(ptr, ZR060_SGR_HTOTAL_HI, (reg >> 8) & 0xff);
+ zr36060_write(ptr, ZR060_SGR_HTOTAL_LO, (reg >> 0) & 0xff);
+
+ reg = 6 - 1; /* VsyncSize */
+ zr36060_write(ptr, ZR060_SGR_VSYNC, reg);
+
+ reg = 68;
+ zr36060_write(ptr, ZR060_SGR_HSYNC, reg);
+
+ reg = norm->v_start - 1; /* BVstart */
+ zr36060_write(ptr, ZR060_SGR_BVSTART, reg);
+
+ reg += norm->ha / 2; /* BVend */
+ zr36060_write(ptr, ZR060_SGR_BVEND_HI, (reg >> 8) & 0xff);
+ zr36060_write(ptr, ZR060_SGR_BVEND_LO, (reg >> 0) & 0xff);
+
+ reg = norm->h_start - 1; /* BHstart */
+ zr36060_write(ptr, ZR060_SGR_BHSTART, reg);
+
+ reg += norm->wa; /* BHend */
+ zr36060_write(ptr, ZR060_SGR_BHEND_HI, (reg >> 8) & 0xff);
+ zr36060_write(ptr, ZR060_SGR_BHEND_LO, (reg >> 0) & 0xff);
+
+ /* active area */
+ reg = cap->y + norm->v_start; /* Vstart */
+ zr36060_write(ptr, ZR060_AAR_VSTART_HI, (reg >> 8) & 0xff);
+ zr36060_write(ptr, ZR060_AAR_VSTART_LO, (reg >> 0) & 0xff);
+
+ reg += cap->height; /* Vend */
+ zr36060_write(ptr, ZR060_AAR_VEND_HI, (reg >> 8) & 0xff);
+ zr36060_write(ptr, ZR060_AAR_VEND_LO, (reg >> 0) & 0xff);
+
+ reg = cap->x + norm->h_start; /* Hstart */
+ zr36060_write(ptr, ZR060_AAR_HSTART_HI, (reg >> 8) & 0xff);
+ zr36060_write(ptr, ZR060_AAR_HSTART_LO, (reg >> 0) & 0xff);
+
+ reg += cap->width; /* Hend */
+ zr36060_write(ptr, ZR060_AAR_HEND_HI, (reg >> 8) & 0xff);
+ zr36060_write(ptr, ZR060_AAR_HEND_LO, (reg >> 0) & 0xff);
+
+ /* subimage area */
+ reg = norm->v_start - 4; /* SVstart */
+ zr36060_write(ptr, ZR060_SWR_VSTART_HI, (reg >> 8) & 0xff);
+ zr36060_write(ptr, ZR060_SWR_VSTART_LO, (reg >> 0) & 0xff);
+
+ reg += norm->ha / 2 + 8; /* SVend */
+ zr36060_write(ptr, ZR060_SWR_VEND_HI, (reg >> 8) & 0xff);
+ zr36060_write(ptr, ZR060_SWR_VEND_LO, (reg >> 0) & 0xff);
+
+ reg = norm->h_start /*+ 64 */ - 4; /* SHstart */
+ zr36060_write(ptr, ZR060_SWR_HSTART_HI, (reg >> 8) & 0xff);
+ zr36060_write(ptr, ZR060_SWR_HSTART_LO, (reg >> 0) & 0xff);
+
+ reg += norm->wa + 8; /* SHend */
+ zr36060_write(ptr, ZR060_SWR_HEND_HI, (reg >> 8) & 0xff);
+ zr36060_write(ptr, ZR060_SWR_HEND_LO, (reg >> 0) & 0xff);
+
+ size = ptr->width * ptr->height;
+ /* Target compressed field size in bits: */
+ size = size * 16; /* uncompressed size in bits */
+ /* (Ronald) by default, quality = 100 is a compression
+ * ratio 1:2. Setting low_bitrate (insmod option) sets
+ * it to 1:4 (instead of 1:2, zr36060 max) as limit because the
+ * buz can't handle more at decimation=1... Use low_bitrate if
+ * you have a Buz, unless you know what you're doing
+ */
+ size = size * cap->quality / (low_bitrate ? 400 : 200);
+ /* Lower limit (arbitrary, 1 KB) */
+ if (size < 8192)
+ size = 8192;
+ /* Upper limit: 7/8 of the code buffers */
+ if (size > ptr->total_code_vol * 7)
+ size = ptr->total_code_vol * 7;
+
+ ptr->real_code_vol = size >> 3; /* in bytes */
+
+ /* the MBCVR is the *maximum* block volume, according to the
+ * JPEG ISO specs, this shouldn't be used, since that allows
+ * for the best encoding quality. So set it to it's max value
+ */
+ reg = ptr->max_block_vol;
+ zr36060_write(ptr, ZR060_MBCVR, reg);
+
+ return 0;
+}
+
+/* additional control functions */
+static int zr36060_control(struct videocodec *codec, int type, int size, void *data)
+{
+ struct zr36060 *ptr = (struct zr36060 *)codec->data;
+ struct zoran *zr = videocodec_to_zoran(codec);
+ int *ival = (int *)data;
+
+ zrdev_dbg(zr, "%s: control %d call with %d byte\n", ptr->name, type,
+ size);
+
+ switch (type) {
+ case CODEC_G_STATUS: /* get last status */
+ if (size != sizeof(int))
+ return -EFAULT;
+ zr36060_read_status(ptr);
+ *ival = ptr->status;
+ break;
+
+ case CODEC_G_CODEC_MODE:
+ if (size != sizeof(int))
+ return -EFAULT;
+ *ival = CODEC_MODE_BJPG;
+ break;
+
+ case CODEC_S_CODEC_MODE:
+ if (size != sizeof(int))
+ return -EFAULT;
+ if (*ival != CODEC_MODE_BJPG)
+ return -EINVAL;
+ /* not needed, do nothing */
+ return 0;
+
+ case CODEC_G_VFE:
+ case CODEC_S_VFE:
+ /* not needed, do nothing */
+ return 0;
+
+ case CODEC_S_MMAP:
+ /* not available, give an error */
+ return -ENXIO;
+
+ case CODEC_G_JPEG_TDS_BYTE: /* get target volume in byte */
+ if (size != sizeof(int))
+ return -EFAULT;
+ *ival = ptr->total_code_vol;
+ break;
+
+ case CODEC_S_JPEG_TDS_BYTE: /* get target volume in byte */
+ if (size != sizeof(int))
+ return -EFAULT;
+ ptr->total_code_vol = *ival;
+ ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3;
+ break;
+
+ case CODEC_G_JPEG_SCALE: /* get scaling factor */
+ if (size != sizeof(int))
+ return -EFAULT;
+ *ival = zr36060_read_scalefactor(ptr);
+ break;
+
+ case CODEC_S_JPEG_SCALE: /* set scaling factor */
+ if (size != sizeof(int))
+ return -EFAULT;
+ ptr->scalefact = *ival;
+ break;
+
+ case CODEC_G_JPEG_APP_DATA: { /* get appn marker data */
+ struct jpeg_app_marker *app = data;
+
+ if (size != sizeof(struct jpeg_app_marker))
+ return -EFAULT;
+
+ *app = ptr->app;
+ break;
+ }
+
+ case CODEC_S_JPEG_APP_DATA: { /* set appn marker data */
+ struct jpeg_app_marker *app = data;
+
+ if (size != sizeof(struct jpeg_app_marker))
+ return -EFAULT;
+
+ ptr->app = *app;
+ break;
+ }
+
+ case CODEC_G_JPEG_COM_DATA: { /* get comment marker data */
+ struct jpeg_com_marker *com = data;
+
+ if (size != sizeof(struct jpeg_com_marker))
+ return -EFAULT;
+
+ *com = ptr->com;
+ break;
+ }
+
+ case CODEC_S_JPEG_COM_DATA: { /* set comment marker data */
+ struct jpeg_com_marker *com = data;
+
+ if (size != sizeof(struct jpeg_com_marker))
+ return -EFAULT;
+
+ ptr->com = *com;
+ break;
+ }
+
+ default:
+ return -EINVAL;
+ }
+
+ return size;
+}
+
+/* =========================================================================
+ * Exit and unregister function:
+ * Deinitializes Zoran's JPEG processor
+ * =========================================================================
+ */
+static int zr36060_unset(struct videocodec *codec)
+{
+ struct zr36060 *ptr = codec->data;
+ struct zoran *zr = videocodec_to_zoran(codec);
+
+ if (ptr) {
+ /* do wee need some codec deinit here, too ???? */
+
+ zrdev_dbg(zr, "%s: finished codec #%d\n", ptr->name, ptr->num);
+ kfree(ptr);
+ codec->data = NULL;
+
+ zr36060_codecs--;
+ return 0;
+ }
+
+ return -EFAULT;
+}
+
+/* =========================================================================
+ * Setup and registry function:
+ * Initializes Zoran's JPEG processor
+ * Also sets pixel size, average code size, mode (compr./decompr.)
+ * (the given size is determined by the processor with the video interface)
+ * =========================================================================
+ */
+static int zr36060_setup(struct videocodec *codec)
+{
+ struct zr36060 *ptr;
+ struct zoran *zr = videocodec_to_zoran(codec);
+ int res;
+
+ zrdev_dbg(zr, "zr36060: initializing MJPEG subsystem #%d.\n",
+ zr36060_codecs);
+
+ if (zr36060_codecs == MAX_CODECS) {
+ zrdev_err(zr, "zr36060: Can't attach more codecs!\n");
+ return -ENOSPC;
+ }
+ //mem structure init
+ ptr = kzalloc(sizeof(*ptr), GFP_KERNEL);
+ codec->data = ptr;
+ if (!ptr)
+ return -ENOMEM;
+
+ snprintf(ptr->name, sizeof(ptr->name), "zr36060[%d]", zr36060_codecs);
+ ptr->num = zr36060_codecs++;
+ ptr->codec = codec;
+
+ //testing
+ res = zr36060_basic_test(ptr);
+ if (res < 0) {
+ zr36060_unset(codec);
+ return res;
+ }
+ //final setup
+ memcpy(ptr->h_samp_ratio, zr36060_decimation_h, 8);
+ memcpy(ptr->v_samp_ratio, zr36060_decimation_v, 8);
+
+ ptr->bitrate_ctrl = 0; /* 0 or 1 - fixed file size flag (what is the difference?) */
+ ptr->mode = CODEC_DO_COMPRESSION;
+ ptr->width = 384;
+ ptr->height = 288;
+ ptr->total_code_vol = 16000; /* CHECKME */
+ ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3;
+ ptr->max_block_vol = 240; /* CHECKME, was 120 is 240 */
+ ptr->scalefact = 0x100;
+ ptr->dri = 1; /* CHECKME, was 8 is 1 */
+
+ /* by default, no COM or APP markers - app should set those */
+ ptr->com.len = 0;
+ ptr->app.appn = 0;
+ ptr->app.len = 0;
+
+ zr36060_init(ptr);
+
+ zrdev_info(zr, "%s: codec attached and running\n", ptr->name);
+
+ return 0;
+}
+
+static const struct videocodec zr36060_codec = {
+ .name = "zr36060",
+ .magic = 0L, // magic not used
+ .flags =
+ CODEC_FLAG_JPEG | CODEC_FLAG_HARDWARE | CODEC_FLAG_ENCODER |
+ CODEC_FLAG_DECODER | CODEC_FLAG_VFE,
+ .type = CODEC_TYPE_ZR36060,
+ .setup = zr36060_setup, // functionality
+ .unset = zr36060_unset,
+ .set_mode = zr36060_set_mode,
+ .set_video = zr36060_set_video,
+ .control = zr36060_control,
+ // others are not used
+};
+
+int zr36060_init_module(void)
+{
+ zr36060_codecs = 0;
+ return videocodec_register(&zr36060_codec);
+}
+
+void zr36060_cleanup_module(void)
+{
+ if (zr36060_codecs) {
+ pr_debug("zr36060: something's wrong - %d codecs left somehow.\n",
+ zr36060_codecs);
+ }
+
+ /* however, we can't just stay alive */
+ videocodec_unregister(&zr36060_codec);
+}
diff --git a/drivers/media/pci/zoran/zr36060.h b/drivers/media/pci/zoran/zr36060.h
new file mode 100644
index 000000000000..75c88677a4bd
--- /dev/null
+++ b/drivers/media/pci/zoran/zr36060.h
@@ -0,0 +1,203 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Zoran ZR36060 basic configuration functions - header file
+ *
+ * Copyright (C) 2002 Laurent Pinchart <laurent.pinchart@skynet.be>
+ */
+
+#ifndef ZR36060_H
+#define ZR36060_H
+
+#include "videocodec.h"
+
+/* data stored for each zoran jpeg codec chip */
+struct zr36060 {
+ char name[32];
+ int num;
+ /* io datastructure */
+ struct videocodec *codec;
+ // last coder status
+ __u8 status;
+ // actual coder setup
+ int mode;
+
+ __u16 width;
+ __u16 height;
+
+ __u16 bitrate_ctrl;
+
+ __u32 total_code_vol;
+ __u32 real_code_vol;
+ __u16 max_block_vol;
+
+ __u8 h_samp_ratio[8];
+ __u8 v_samp_ratio[8];
+ __u16 scalefact;
+ __u16 dri;
+
+ /* app/com marker data */
+ struct jpeg_app_marker app;
+ struct jpeg_com_marker com;
+};
+
+/* ZR36060 register addresses */
+#define ZR060_LOAD 0x000
+#define ZR060_CFSR 0x001
+#define ZR060_CIR 0x002
+#define ZR060_CMR 0x003
+#define ZR060_MBZ 0x004
+#define ZR060_MBCVR 0x005
+#define ZR060_MER 0x006
+#define ZR060_IMR 0x007
+#define ZR060_ISR 0x008
+#define ZR060_TCV_NET_HI 0x009
+#define ZR060_TCV_NET_MH 0x00a
+#define ZR060_TCV_NET_ML 0x00b
+#define ZR060_TCV_NET_LO 0x00c
+#define ZR060_TCV_DATA_HI 0x00d
+#define ZR060_TCV_DATA_MH 0x00e
+#define ZR060_TCV_DATA_ML 0x00f
+#define ZR060_TCV_DATA_LO 0x010
+#define ZR060_SF_HI 0x011
+#define ZR060_SF_LO 0x012
+#define ZR060_AF_HI 0x013
+#define ZR060_AF_M 0x014
+#define ZR060_AF_LO 0x015
+#define ZR060_ACV_HI 0x016
+#define ZR060_ACV_MH 0x017
+#define ZR060_ACV_ML 0x018
+#define ZR060_ACV_LO 0x019
+#define ZR060_ACT_HI 0x01a
+#define ZR060_ACT_MH 0x01b
+#define ZR060_ACT_ML 0x01c
+#define ZR060_ACT_LO 0x01d
+#define ZR060_ACV_TURN_HI 0x01e
+#define ZR060_ACV_TURN_MH 0x01f
+#define ZR060_ACV_TURN_ML 0x020
+#define ZR060_ACV_TURN_LO 0x021
+#define ZR060_IDR_DEV 0x022
+#define ZR060_IDR_REV 0x023
+#define ZR060_TCR_HI 0x024
+#define ZR060_TCR_LO 0x025
+#define ZR060_VCR 0x030
+#define ZR060_VPR 0x031
+#define ZR060_SR 0x032
+#define ZR060_BCR_Y 0x033
+#define ZR060_BCR_U 0x034
+#define ZR060_BCR_V 0x035
+#define ZR060_SGR_VTOTAL_HI 0x036
+#define ZR060_SGR_VTOTAL_LO 0x037
+#define ZR060_SGR_HTOTAL_HI 0x038
+#define ZR060_SGR_HTOTAL_LO 0x039
+#define ZR060_SGR_VSYNC 0x03a
+#define ZR060_SGR_HSYNC 0x03b
+#define ZR060_SGR_BVSTART 0x03c
+#define ZR060_SGR_BHSTART 0x03d
+#define ZR060_SGR_BVEND_HI 0x03e
+#define ZR060_SGR_BVEND_LO 0x03f
+#define ZR060_SGR_BHEND_HI 0x040
+#define ZR060_SGR_BHEND_LO 0x041
+#define ZR060_AAR_VSTART_HI 0x042
+#define ZR060_AAR_VSTART_LO 0x043
+#define ZR060_AAR_VEND_HI 0x044
+#define ZR060_AAR_VEND_LO 0x045
+#define ZR060_AAR_HSTART_HI 0x046
+#define ZR060_AAR_HSTART_LO 0x047
+#define ZR060_AAR_HEND_HI 0x048
+#define ZR060_AAR_HEND_LO 0x049
+#define ZR060_SWR_VSTART_HI 0x04a
+#define ZR060_SWR_VSTART_LO 0x04b
+#define ZR060_SWR_VEND_HI 0x04c
+#define ZR060_SWR_VEND_LO 0x04d
+#define ZR060_SWR_HSTART_HI 0x04e
+#define ZR060_SWR_HSTART_LO 0x04f
+#define ZR060_SWR_HEND_HI 0x050
+#define ZR060_SWR_HEND_LO 0x051
+
+#define ZR060_SOF_IDX 0x060
+#define ZR060_SOS_IDX 0x07a
+#define ZR060_DRI_IDX 0x0c0
+#define ZR060_DQT_IDX 0x0cc
+#define ZR060_DHT_IDX 0x1d4
+#define ZR060_APP_IDX 0x380
+#define ZR060_COM_IDX 0x3c0
+
+/* ZR36060 LOAD register bits */
+
+#define ZR060_LOAD_LOAD BIT(7)
+#define ZR060_LOAD_SYNC_RST BIT(0)
+
+/* ZR36060 Code FIFO Status register bits */
+
+#define ZR060_CFSR_BUSY BIT(7)
+#define ZR060_CFSR_C_BUSY BIT(2)
+#define ZR060_CFSR_CFIFO (3 << 0)
+
+/* ZR36060 Code Interface register */
+
+#define ZR060_CIR_CODE16 BIT(7)
+#define ZR060_CIR_ENDIAN BIT(6)
+#define ZR060_CIR_CFIS BIT(2)
+#define ZR060_CIR_CODE_MSTR BIT(0)
+
+/* ZR36060 Codec Mode register */
+
+#define ZR060_CMR_COMP BIT(7)
+#define ZR060_CMR_ATP BIT(6)
+#define ZR060_CMR_PASS2 BIT(5)
+#define ZR060_CMR_TLM BIT(4)
+#define ZR060_CMR_BRB BIT(2)
+#define ZR060_CMR_FSF BIT(1)
+
+/* ZR36060 Markers Enable register */
+
+#define ZR060_MER_APP BIT(7)
+#define ZR060_MER_COM BIT(6)
+#define ZR060_MER_DRI BIT(5)
+#define ZR060_MER_DQT BIT(4)
+#define ZR060_MER_DHT BIT(3)
+
+/* ZR36060 Interrupt Mask register */
+
+#define ZR060_IMR_EOAV BIT(3)
+#define ZR060_IMR_EOI BIT(2)
+#define ZR060_IMR_END BIT(1)
+#define ZR060_IMR_DATA_ERR BIT(0)
+
+/* ZR36060 Interrupt Status register */
+
+#define ZR060_ISR_PRO_CNT (3 << 6)
+#define ZR060_ISR_EOAV BIT(3)
+#define ZR060_ISR_EOI BIT(2)
+#define ZR060_ISR_END BIT(1)
+#define ZR060_ISR_DATA_ERR BIT(0)
+
+/* ZR36060 Video Control register */
+
+#define ZR060_VCR_VIDEO8 BIT(7)
+#define ZR060_VCR_RANGE BIT(6)
+#define ZR060_VCR_FI_DET BIT(3)
+#define ZR060_VCR_FI_VEDGE BIT(2)
+#define ZR060_VCR_FI_EXT BIT(1)
+#define ZR060_VCR_SYNC_MSTR BIT(0)
+
+/* ZR36060 Video Polarity register */
+
+#define ZR060_VPR_VCLK_POL BIT(7)
+#define ZR060_VPR_P_VAL_POL BIT(6)
+#define ZR060_VPR_POE_POL BIT(5)
+#define ZR060_VPR_S_IMG_POL BIT(4)
+#define ZR060_VPR_BL_POL BIT(3)
+#define ZR060_VPR_FI_POL BIT(2)
+#define ZR060_VPR_HS_POL BIT(1)
+#define ZR060_VPR_VS_POL BIT(0)
+
+/* ZR36060 Scaling register */
+
+#define ZR060_SR_V_SCALE BIT(2)
+#define ZR060_SR_H_SCALE2 BIT(0)
+#define ZR060_SR_H_SCALE4 (2 << 0)
+
+int zr36060_init_module(void);
+void zr36060_cleanup_module(void);
+#endif /*fndef ZR36060_H */