diff options
Diffstat (limited to 'drivers/media/pci')
109 files changed, 3503 insertions, 907 deletions
diff --git a/drivers/media/pci/Kconfig b/drivers/media/pci/Kconfig index da28e68c87d8..5932e225f9c0 100644 --- a/drivers/media/pci/Kconfig +++ b/drivers/media/pci/Kconfig @@ -54,5 +54,7 @@ source "drivers/media/pci/smipcie/Kconfig" source "drivers/media/pci/netup_unidvb/Kconfig" endif +source "drivers/media/pci/intel/ipu3/Kconfig" + endif #MEDIA_PCI_SUPPORT endif #PCI diff --git a/drivers/media/pci/Makefile b/drivers/media/pci/Makefile index 1ab759e9b1bb..1c5ab07a8cff 100644 --- a/drivers/media/pci/Makefile +++ b/drivers/media/pci/Makefile @@ -14,7 +14,8 @@ obj-y += ttpci/ \ ddbridge/ \ saa7146/ \ smipcie/ \ - netup_unidvb/ + netup_unidvb/ \ + intel/ obj-$(CONFIG_VIDEO_IVTV) += ivtv/ obj-$(CONFIG_VIDEO_ZORAN) += zoran/ diff --git a/drivers/media/pci/b2c2/Makefile b/drivers/media/pci/b2c2/Makefile index 35d6835ae43e..b43b9167db5a 100644 --- a/drivers/media/pci/b2c2/Makefile +++ b/drivers/media/pci/b2c2/Makefile @@ -6,5 +6,4 @@ endif b2c2-flexcop-pci-objs += flexcop-pci.o obj-$(CONFIG_DVB_B2C2_FLEXCOP_PCI) += b2c2-flexcop-pci.o -ccflags-y += -Idrivers/media/dvb-core/ ccflags-y += -Idrivers/media/common/b2c2/ diff --git a/drivers/media/pci/bt8xx/Makefile b/drivers/media/pci/bt8xx/Makefile index 009f1dc1521f..7f1c3beb1bbc 100644 --- a/drivers/media/pci/bt8xx/Makefile +++ b/drivers/media/pci/bt8xx/Makefile @@ -6,8 +6,6 @@ bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \ obj-$(CONFIG_VIDEO_BT848) += bttv.o obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o -ccflags-y += -Idrivers/media/dvb-core ccflags-y += -Idrivers/media/dvb-frontends -ccflags-y += -Idrivers/media/i2c ccflags-y += -Idrivers/media/common ccflags-y += -Idrivers/media/tuners diff --git a/drivers/media/pci/bt8xx/bt878.c b/drivers/media/pci/bt8xx/bt878.c index a5f52137d306..f5f87e03f94b 100644 --- a/drivers/media/pci/bt8xx/bt878.c +++ b/drivers/media/pci/bt8xx/bt878.c @@ -40,8 +40,8 @@ #include <linux/vmalloc.h> #include <linux/init.h> -#include "dmxdev.h" -#include "dvbdev.h" +#include <media/dmxdev.h> +#include <media/dvbdev.h> #include "bt878.h" #include "dst_priv.h" @@ -422,8 +422,7 @@ static int bt878_probe(struct pci_dev *dev, const struct pci_device_id *pci_id) bt878_num); if (bt878_num >= BT878_MAX) { printk(KERN_ERR "bt878: Too many devices inserted\n"); - result = -ENOMEM; - goto fail0; + return -ENOMEM; } if (pci_enable_device(dev)) return -EIO; diff --git a/drivers/media/pci/bt8xx/bttv-cards.c b/drivers/media/pci/bt8xx/bttv-cards.c index 5cc42b426715..7dcf509e66d9 100644 --- a/drivers/media/pci/bt8xx/bttv-cards.c +++ b/drivers/media/pci/bt8xx/bttv-cards.c @@ -141,6 +141,13 @@ MODULE_PARM_DESC(audiodev, "specify audio device:\n" MODULE_PARM_DESC(saa6588, "if 1, then load the saa6588 RDS module, default (0) is to use the card definition."); MODULE_PARM_DESC(no_overlay, "allow override overlay default (0 disables, 1 enables) [some VIA/SIS chipsets are known to have problem with overlay]"); + +/* I2C addresses list */ +#define I2C_ADDR_TDA7432 0x8a +#define I2C_ADDR_MSP3400 0x80 +#define I2C_ADDR_MSP3400_ALT 0x88 + + /* ----------------------------------------------------------------------- */ /* list of card IDs for bt878+ cards */ diff --git a/drivers/media/pci/bt8xx/bttv.h b/drivers/media/pci/bt8xx/bttv.h index eb67e362acf7..cc555a4d4462 100644 --- a/drivers/media/pci/bt8xx/bttv.h +++ b/drivers/media/pci/bt8xx/bttv.h @@ -18,7 +18,6 @@ #include <linux/videodev2.h> #include <linux/i2c.h> #include <media/v4l2-device.h> -#include <media/i2c-addr.h> #include <media/tuner.h> /* ---------------------------------------------------------- */ diff --git a/drivers/media/pci/bt8xx/dst.c b/drivers/media/pci/bt8xx/dst.c index 7166d2279465..4f0bba9e4c48 100644 --- a/drivers/media/pci/bt8xx/dst.c +++ b/drivers/media/pci/bt8xx/dst.c @@ -28,7 +28,7 @@ #include <linux/vmalloc.h> #include <linux/delay.h> #include <asm/div64.h> -#include "dvb_frontend.h" +#include <media/dvb_frontend.h> #include "dst_priv.h" #include "dst_common.h" diff --git a/drivers/media/pci/bt8xx/dst_ca.c b/drivers/media/pci/bt8xx/dst_ca.c index 530b3e9764ce..0a7623c0fc8e 100644 --- a/drivers/media/pci/bt8xx/dst_ca.c +++ b/drivers/media/pci/bt8xx/dst_ca.c @@ -25,8 +25,8 @@ #include <linux/mutex.h> #include <linux/string.h> #include <linux/dvb/ca.h> -#include "dvbdev.h" -#include "dvb_frontend.h" +#include <media/dvbdev.h> +#include <media/dvb_frontend.h> #include "dst_ca.h" #include "dst_common.h" diff --git a/drivers/media/pci/bt8xx/dvb-bt8xx.c b/drivers/media/pci/bt8xx/dvb-bt8xx.c index ad617871ce9b..f60d69ac515b 100644 --- a/drivers/media/pci/bt8xx/dvb-bt8xx.c +++ b/drivers/media/pci/bt8xx/dvb-bt8xx.c @@ -26,10 +26,10 @@ #include <linux/slab.h> #include <linux/i2c.h> -#include "dmxdev.h" -#include "dvbdev.h" -#include "dvb_demux.h" -#include "dvb_frontend.h" +#include <media/dmxdev.h> +#include <media/dvbdev.h> +#include <media/dvb_demux.h> +#include <media/dvb_frontend.h> #include "dvb-bt8xx.h" #include "bt878.h" diff --git a/drivers/media/pci/bt8xx/dvb-bt8xx.h b/drivers/media/pci/bt8xx/dvb-bt8xx.h index 0ec538e23b4e..3184b3f3a85e 100644 --- a/drivers/media/pci/bt8xx/dvb-bt8xx.h +++ b/drivers/media/pci/bt8xx/dvb-bt8xx.h @@ -23,8 +23,8 @@ #include <linux/i2c.h> #include <linux/mutex.h> -#include "dvbdev.h" -#include "dvb_net.h" +#include <media/dvbdev.h> +#include <media/dvb_net.h> #include "bttv.h" #include "mt352.h" #include "sp887x.h" diff --git a/drivers/media/pci/cx18/Makefile b/drivers/media/pci/cx18/Makefile index 98914a40f6ac..9c82c2df05e1 100644 --- a/drivers/media/pci/cx18/Makefile +++ b/drivers/media/pci/cx18/Makefile @@ -9,6 +9,5 @@ cx18-alsa-objs := cx18-alsa-main.o cx18-alsa-pcm.o obj-$(CONFIG_VIDEO_CX18) += cx18.o obj-$(CONFIG_VIDEO_CX18_ALSA) += cx18-alsa.o -ccflags-y += -Idrivers/media/dvb-core ccflags-y += -Idrivers/media/dvb-frontends ccflags-y += -Idrivers/media/tuners diff --git a/drivers/media/pci/cx18/cx18-cards.h b/drivers/media/pci/cx18/cx18-cards.h index 667e2d7b1d03..5478f62b5cf3 100644 --- a/drivers/media/pci/cx18/cx18-cards.h +++ b/drivers/media/pci/cx18/cx18-cards.h @@ -25,13 +25,7 @@ #define CX18_HW_418_AV (1 << 4) #define CX18_HW_GPIO_MUX (1 << 5) #define CX18_HW_GPIO_RESET_CTRL (1 << 6) -#define CX18_HW_Z8F0811_IR_TX_HAUP (1 << 7) -#define CX18_HW_Z8F0811_IR_RX_HAUP (1 << 8) -#define CX18_HW_Z8F0811_IR_HAUP (CX18_HW_Z8F0811_IR_RX_HAUP | \ - CX18_HW_Z8F0811_IR_TX_HAUP) - -#define CX18_HW_IR_ANY (CX18_HW_Z8F0811_IR_RX_HAUP | \ - CX18_HW_Z8F0811_IR_TX_HAUP) +#define CX18_HW_Z8F0811_IR_HAUP (1 << 7) /* video inputs */ #define CX18_CARD_INPUT_VID_TUNER 1 diff --git a/drivers/media/pci/cx18/cx18-driver.h b/drivers/media/pci/cx18/cx18-driver.h index 7be2088c45fe..3492023a8675 100644 --- a/drivers/media/pci/cx18/cx18-driver.h +++ b/drivers/media/pci/cx18/cx18-driver.h @@ -50,12 +50,12 @@ #include "cx23418.h" /* DVB */ -#include "demux.h" -#include "dmxdev.h" -#include "dvb_demux.h" -#include "dvb_frontend.h" -#include "dvb_net.h" -#include "dvbdev.h" +#include <media/demux.h> +#include <media/dmxdev.h> +#include <media/dvb_demux.h> +#include <media/dvb_frontend.h> +#include <media/dvb_net.h> +#include <media/dvbdev.h> /* Videobuf / YUV support */ #include <media/videobuf-core.h> diff --git a/drivers/media/pci/cx18/cx18-i2c.c b/drivers/media/pci/cx18/cx18-i2c.c index 7f588eeac60f..f0eb181f2b94 100644 --- a/drivers/media/pci/cx18/cx18-i2c.c +++ b/drivers/media/pci/cx18/cx18-i2c.c @@ -47,8 +47,7 @@ static const u8 hw_addrs[] = { 0, /* CX18_HW_418_AV */ 0, /* CX18_HW_GPIO_MUX */ 0, /* CX18_HW_GPIO_RESET_CTRL */ - CX18_Z8F0811_IR_TX_I2C_ADDR, /* CX18_HW_Z8F0811_IR_TX_HAUP */ - CX18_Z8F0811_IR_RX_I2C_ADDR, /* CX18_HW_Z8F0811_IR_RX_HAUP */ + CX18_Z8F0811_IR_RX_I2C_ADDR, /* CX18_HW_Z8F0811_IR_HAUP */ }; /* This array should match the CX18_HW_ defines */ @@ -61,8 +60,7 @@ static const u8 hw_bus[] = { 0, /* CX18_HW_418_AV */ 0, /* CX18_HW_GPIO_MUX */ 0, /* CX18_HW_GPIO_RESET_CTRL */ - 0, /* CX18_HW_Z8F0811_IR_TX_HAUP */ - 0, /* CX18_HW_Z8F0811_IR_RX_HAUP */ + 0, /* CX18_HW_Z8F0811_IR_HAUP */ }; /* This array should match the CX18_HW_ defines */ @@ -74,8 +72,7 @@ static const char * const hw_devicenames[] = { "cx23418_AV", "gpio_mux", "gpio_reset_ctrl", - "ir_tx_z8f0811_haup", - "ir_rx_z8f0811_haup", + "ir_z8f0811_haup", }; static int cx18_i2c_new_ir(struct cx18 *cx, struct i2c_adapter *adap, u32 hw, @@ -90,7 +87,7 @@ static int cx18_i2c_new_ir(struct cx18 *cx, struct i2c_adapter *adap, u32 hw, /* Our default information for ir-kbd-i2c.c to use */ switch (hw) { - case CX18_HW_Z8F0811_IR_RX_HAUP: + case CX18_HW_Z8F0811_IR_HAUP: init_data->ir_codes = RC_MAP_HAUPPAUGE; init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; init_data->type = RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC6_MCE | @@ -129,7 +126,7 @@ int cx18_i2c_register(struct cx18 *cx, unsigned idx) return sd != NULL ? 0 : -1; } - if (hw & CX18_HW_IR_ANY) + if (hw == CX18_HW_Z8F0811_IR_HAUP) return cx18_i2c_new_ir(cx, adap, hw, type, hw_addrs[idx]); /* Is it not an I2C device or one we do not wish to register? */ diff --git a/drivers/media/pci/cx23885/Makefile b/drivers/media/pci/cx23885/Makefile index b8bf7806124b..130f0aa29ac6 100644 --- a/drivers/media/pci/cx23885/Makefile +++ b/drivers/media/pci/cx23885/Makefile @@ -8,9 +8,7 @@ cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o \ obj-$(CONFIG_VIDEO_CX23885) += cx23885.o obj-$(CONFIG_MEDIA_ALTERA_CI) += altera-ci.o -ccflags-y += -Idrivers/media/i2c ccflags-y += -Idrivers/media/tuners -ccflags-y += -Idrivers/media/dvb-core ccflags-y += -Idrivers/media/dvb-frontends ccflags-y += $(extra-cflags-y) $(extra-cflags-m) diff --git a/drivers/media/pci/cx23885/altera-ci.c b/drivers/media/pci/cx23885/altera-ci.c index 5c94e312cba3..70aec9bb7e95 100644 --- a/drivers/media/pci/cx23885/altera-ci.c +++ b/drivers/media/pci/cx23885/altera-ci.c @@ -51,10 +51,10 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include <dvb_demux.h> -#include <dvb_frontend.h> +#include <media/dvb_demux.h> +#include <media/dvb_frontend.h> #include "altera-ci.h" -#include "dvb_ca_en50221.h" +#include <media/dvb_ca_en50221.h> /* FPGA regs */ #define NETUP_CI_INT_CTRL 0x00 diff --git a/drivers/media/pci/cx23885/cimax2.c b/drivers/media/pci/cx23885/cimax2.c index 5e8e134d81c2..96f75f658b1b 100644 --- a/drivers/media/pci/cx23885/cimax2.c +++ b/drivers/media/pci/cx23885/cimax2.c @@ -21,7 +21,7 @@ #include "cx23885.h" #include "cimax2.h" -#include "dvb_ca_en50221.h" +#include <media/dvb_ca_en50221.h> /* Max transfer size done by I2C transfer functions */ #define MAX_XFER_SIZE 64 diff --git a/drivers/media/pci/cx23885/cimax2.h b/drivers/media/pci/cx23885/cimax2.h index 565e958f6f8d..167ffe205b5d 100644 --- a/drivers/media/pci/cx23885/cimax2.h +++ b/drivers/media/pci/cx23885/cimax2.h @@ -21,7 +21,7 @@ #ifndef CIMAX2_H #define CIMAX2_H -#include "dvb_ca_en50221.h" +#include <media/dvb_ca_en50221.h> extern int netup_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221, int slot, int addr); diff --git a/drivers/media/pci/cx23885/cx23885-cards.c b/drivers/media/pci/cx23885/cx23885-cards.c index 28eab9c518c5..3622521431f5 100644 --- a/drivers/media/pci/cx23885/cx23885-cards.c +++ b/drivers/media/pci/cx23885/cx23885-cards.c @@ -1816,13 +1816,13 @@ int cx23885_ir_init(struct cx23885_dev *dev) { static struct v4l2_subdev_io_pin_config ir_rxtx_pin_cfg[] = { { - .flags = V4L2_SUBDEV_IO_PIN_INPUT, + .flags = BIT(V4L2_SUBDEV_IO_PIN_INPUT), .pin = CX23885_PIN_IR_RX_GPIO19, .function = CX23885_PAD_IR_RX, .value = 0, .strength = CX25840_PIN_DRIVE_MEDIUM, }, { - .flags = V4L2_SUBDEV_IO_PIN_OUTPUT, + .flags = BIT(V4L2_SUBDEV_IO_PIN_OUTPUT), .pin = CX23885_PIN_IR_TX_GPIO20, .function = CX23885_PAD_IR_TX, .value = 0, @@ -1833,7 +1833,7 @@ int cx23885_ir_init(struct cx23885_dev *dev) static struct v4l2_subdev_io_pin_config ir_rx_pin_cfg[] = { { - .flags = V4L2_SUBDEV_IO_PIN_INPUT, + .flags = BIT(V4L2_SUBDEV_IO_PIN_INPUT), .pin = CX23885_PIN_IR_RX_GPIO19, .function = CX23885_PAD_IR_RX, .value = 0, diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c index e795ddeb7fe2..700422b538c0 100644 --- a/drivers/media/pci/cx23885/cx23885-dvb.c +++ b/drivers/media/pci/cx23885/cx23885-dvb.c @@ -27,7 +27,7 @@ #include <media/v4l2-common.h> -#include "dvb_ca_en50221.h" +#include <media/dvb_ca_en50221.h> #include "s5h1409.h" #include "s5h1411.h" #include "mt2131.h" @@ -1852,8 +1852,8 @@ static int dvb_register(struct cx23885_tsport *port) /* attach frontend */ memset(&si2165_pdata, 0, sizeof(si2165_pdata)); si2165_pdata.fe = &fe0->dvb.frontend; - si2165_pdata.chip_mode = SI2165_MODE_PLL_XTAL, - si2165_pdata.ref_freq_Hz = 16000000, + si2165_pdata.chip_mode = SI2165_MODE_PLL_XTAL; + si2165_pdata.ref_freq_hz = 16000000; memset(&info, 0, sizeof(struct i2c_board_info)); strlcpy(info.type, "si2165", I2C_NAME_SIZE); info.addr = 0x64; diff --git a/drivers/media/pci/cx23885/cx23885-input.c b/drivers/media/pci/cx23885/cx23885-input.c index 944b70831f12..0f4e54294bb7 100644 --- a/drivers/media/pci/cx23885/cx23885-input.c +++ b/drivers/media/pci/cx23885/cx23885-input.c @@ -340,14 +340,23 @@ int cx23885_input_init(struct cx23885_dev *dev) kernel_ir->cx = dev; kernel_ir->name = kasprintf(GFP_KERNEL, "cx23885 IR (%s)", cx23885_boards[dev->board].name); + if (!kernel_ir->name) { + ret = -ENOMEM; + goto err_out_free; + } + kernel_ir->phys = kasprintf(GFP_KERNEL, "pci-%s/ir0", pci_name(dev->pci)); + if (!kernel_ir->phys) { + ret = -ENOMEM; + goto err_out_free_name; + } /* input device */ rc = rc_allocate_device(RC_DRIVER_IR_RAW); if (!rc) { ret = -ENOMEM; - goto err_out_free; + goto err_out_free_phys; } kernel_ir->rc = rc; @@ -382,9 +391,11 @@ err_out_stop: cx23885_input_ir_stop(dev); dev->kernel_ir = NULL; rc_free_device(rc); -err_out_free: +err_out_free_phys: kfree(kernel_ir->phys); +err_out_free_name: kfree(kernel_ir->name); +err_out_free: kfree(kernel_ir); return ret; } diff --git a/drivers/media/pci/cx25821/Makefile b/drivers/media/pci/cx25821/Makefile index d14d65b1b042..94633d02ac7f 100644 --- a/drivers/media/pci/cx25821/Makefile +++ b/drivers/media/pci/cx25821/Makefile @@ -5,5 +5,3 @@ cx25821-y := cx25821-core.o cx25821-cards.o cx25821-i2c.o \ obj-$(CONFIG_VIDEO_CX25821) += cx25821.o obj-$(CONFIG_VIDEO_CX25821_ALSA) += cx25821-alsa.o - -ccflags-y += -Idrivers/media/i2c diff --git a/drivers/media/pci/cx25821/cx25821-alsa.c b/drivers/media/pci/cx25821/cx25821-alsa.c index 2b34990e86f2..a45bf0331eeb 100644 --- a/drivers/media/pci/cx25821/cx25821-alsa.c +++ b/drivers/media/pci/cx25821/cx25821-alsa.c @@ -152,8 +152,8 @@ static int cx25821_alsa_dma_init(struct cx25821_audio_dev *chip, int nr_pages) return -ENOMEM; } - dprintk(1, "vmalloc is at addr 0x%08lx, size=%d\n", - (unsigned long)buf->vaddr, + dprintk(1, "vmalloc is at addr 0x%p, size=%d\n", + buf->vaddr, nr_pages << PAGE_SHIFT); memset(buf->vaddr, 0, nr_pages << PAGE_SHIFT); diff --git a/drivers/media/pci/cx88/Makefile b/drivers/media/pci/cx88/Makefile index 86646eee4e6b..d0f45d652d6e 100644 --- a/drivers/media/pci/cx88/Makefile +++ b/drivers/media/pci/cx88/Makefile @@ -10,8 +10,5 @@ obj-$(CONFIG_VIDEO_CX88_ALSA) += cx88-alsa.o obj-$(CONFIG_VIDEO_CX88_BLACKBIRD) += cx88-blackbird.o obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o - -ccflags-y += -Idrivers/media/i2c ccflags-y += -Idrivers/media/tuners -ccflags-y += -Idrivers/media/dvb-core ccflags-y += -Idrivers/media/dvb-frontends diff --git a/drivers/media/pci/cx88/cx88-blackbird.c b/drivers/media/pci/cx88/cx88-blackbird.c index e3101f04941c..0e0952e60795 100644 --- a/drivers/media/pci/cx88/cx88-blackbird.c +++ b/drivers/media/pci/cx88/cx88-blackbird.c @@ -805,8 +805,7 @@ static int vidioc_querycap(struct file *file, void *priv, strcpy(cap->driver, "cx88_blackbird"); sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci)); - cx88_querycap(file, core, cap); - return 0; + return cx88_querycap(file, core, cap); } static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c index 7d25ecd4404b..9be682cdb644 100644 --- a/drivers/media/pci/cx88/cx88-video.c +++ b/drivers/media/pci/cx88/cx88-video.c @@ -806,8 +806,8 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, return 0; } -void cx88_querycap(struct file *file, struct cx88_core *core, - struct v4l2_capability *cap) +int cx88_querycap(struct file *file, struct cx88_core *core, + struct v4l2_capability *cap) { struct video_device *vdev = video_devdata(file); @@ -825,11 +825,14 @@ void cx88_querycap(struct file *file, struct cx88_core *core, case VFL_TYPE_VBI: cap->device_caps |= V4L2_CAP_VBI_CAPTURE; break; + default: + return -EINVAL; } cap->capabilities = cap->device_caps | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_DEVICE_CAPS; if (core->board.radio.type == CX88_RADIO) cap->capabilities |= V4L2_CAP_RADIO; + return 0; } EXPORT_SYMBOL(cx88_querycap); @@ -841,8 +844,7 @@ static int vidioc_querycap(struct file *file, void *priv, strcpy(cap->driver, "cx8800"); sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci)); - cx88_querycap(file, core, cap); - return 0; + return cx88_querycap(file, core, cap); } static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, diff --git a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h index 6777926f20f2..07a33f02fef4 100644 --- a/drivers/media/pci/cx88/cx88.h +++ b/drivers/media/pci/cx88/cx88.h @@ -734,7 +734,7 @@ int cx8802_start_dma(struct cx8802_dev *dev, int cx88_enum_input(struct cx88_core *core, struct v4l2_input *i); int cx88_set_freq(struct cx88_core *core, const struct v4l2_frequency *f); int cx88_video_mux(struct cx88_core *core, unsigned int input); -void cx88_querycap(struct file *file, struct cx88_core *core, - struct v4l2_capability *cap); +int cx88_querycap(struct file *file, struct cx88_core *core, + struct v4l2_capability *cap); #endif diff --git a/drivers/media/pci/ddbridge/Makefile b/drivers/media/pci/ddbridge/Makefile index 7453b65104ff..f58fdec50eab 100644 --- a/drivers/media/pci/ddbridge/Makefile +++ b/drivers/media/pci/ddbridge/Makefile @@ -3,12 +3,11 @@ # Makefile for the ddbridge device driver # -ddbridge-objs := ddbridge-main.o ddbridge-core.o ddbridge-hw.o \ - ddbridge-i2c.o ddbridge-maxs8.o +ddbridge-objs := ddbridge-main.o ddbridge-core.o ddbridge-ci.o \ + ddbridge-hw.o ddbridge-i2c.o ddbridge-max.o obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o -ccflags-y += -Idrivers/media/dvb-core/ ccflags-y += -Idrivers/media/dvb-frontends/ ccflags-y += -Idrivers/media/tuners/ diff --git a/drivers/media/pci/ddbridge/ddbridge-ci.c b/drivers/media/pci/ddbridge/ddbridge-ci.c new file mode 100644 index 000000000000..5828111487b0 --- /dev/null +++ b/drivers/media/pci/ddbridge/ddbridge-ci.c @@ -0,0 +1,359 @@ +/* + * ddbridge-ci.c: Digital Devices bridge CI (DuoFlex, CI Bridge) support + * + * Copyright (C) 2010-2017 Digital Devices GmbH + * Marcus Metzler <mocm@metzlerbros.de> + * Ralph Metzler <rjkm@metzlerbros.de> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 only, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * To obtain the license, point your browser to + * http://www.gnu.org/copyleft/gpl.html + */ + +#include "ddbridge.h" +#include "ddbridge-regs.h" +#include "ddbridge-ci.h" +#include "ddbridge-io.h" +#include "ddbridge-i2c.h" + +#include "cxd2099.h" + +/* Octopus CI internal CI interface */ + +static int wait_ci_ready(struct ddb_ci *ci) +{ + u32 count = 10; + + ndelay(500); + do { + if (ddbreadl(ci->port->dev, + CI_CONTROL(ci->nr)) & CI_READY) + break; + usleep_range(1, 2); + if ((--count) == 0) + return -1; + } while (1); + return 0; +} + +static int read_attribute_mem(struct dvb_ca_en50221 *ca, + int slot, int address) +{ + struct ddb_ci *ci = ca->data; + u32 val, off = (address >> 1) & (CI_BUFFER_SIZE - 1); + + if (address > CI_BUFFER_SIZE) + return -1; + ddbwritel(ci->port->dev, CI_READ_CMD | (1 << 16) | address, + CI_DO_READ_ATTRIBUTES(ci->nr)); + wait_ci_ready(ci); + val = 0xff & ddbreadl(ci->port->dev, CI_BUFFER(ci->nr) + off); + return val; +} + +static int write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, + int address, u8 value) +{ + struct ddb_ci *ci = ca->data; + + ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address, + CI_DO_ATTRIBUTE_RW(ci->nr)); + wait_ci_ready(ci); + return 0; +} + +static int read_cam_control(struct dvb_ca_en50221 *ca, + int slot, u8 address) +{ + u32 count = 100; + struct ddb_ci *ci = ca->data; + u32 res; + + ddbwritel(ci->port->dev, CI_READ_CMD | address, + CI_DO_IO_RW(ci->nr)); + ndelay(500); + do { + res = ddbreadl(ci->port->dev, CI_READDATA(ci->nr)); + if (res & CI_READY) + break; + usleep_range(1, 2); + if ((--count) == 0) + return -1; + } while (1); + return 0xff & res; +} + +static int write_cam_control(struct dvb_ca_en50221 *ca, int slot, + u8 address, u8 value) +{ + struct ddb_ci *ci = ca->data; + + ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address, + CI_DO_IO_RW(ci->nr)); + wait_ci_ready(ci); + return 0; +} + +static int slot_reset(struct dvb_ca_en50221 *ca, int slot) +{ + struct ddb_ci *ci = ca->data; + + ddbwritel(ci->port->dev, CI_POWER_ON, + CI_CONTROL(ci->nr)); + msleep(100); + ddbwritel(ci->port->dev, CI_POWER_ON | CI_RESET_CAM, + CI_CONTROL(ci->nr)); + ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON | CI_RESET_CAM, + CI_CONTROL(ci->nr)); + usleep_range(20, 25); + ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON, + CI_CONTROL(ci->nr)); + return 0; +} + +static int slot_shutdown(struct dvb_ca_en50221 *ca, int slot) +{ + struct ddb_ci *ci = ca->data; + + ddbwritel(ci->port->dev, 0, CI_CONTROL(ci->nr)); + msleep(300); + return 0; +} + +static int slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) +{ + struct ddb_ci *ci = ca->data; + u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci->nr)); + + ddbwritel(ci->port->dev, val | CI_BYPASS_DISABLE, + CI_CONTROL(ci->nr)); + return 0; +} + +static int poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open) +{ + struct ddb_ci *ci = ca->data; + u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci->nr)); + int stat = 0; + + if (val & CI_CAM_DETECT) + stat |= DVB_CA_EN50221_POLL_CAM_PRESENT; + if (val & CI_CAM_READY) + stat |= DVB_CA_EN50221_POLL_CAM_READY; + return stat; +} + +static struct dvb_ca_en50221 en_templ = { + .read_attribute_mem = read_attribute_mem, + .write_attribute_mem = write_attribute_mem, + .read_cam_control = read_cam_control, + .write_cam_control = write_cam_control, + .slot_reset = slot_reset, + .slot_shutdown = slot_shutdown, + .slot_ts_enable = slot_ts_enable, + .poll_slot_status = poll_slot_status, +}; + +static void ci_attach(struct ddb_port *port) +{ + struct ddb_ci *ci = NULL; + + ci = kzalloc(sizeof(*ci), GFP_KERNEL); + if (!ci) + return; + memcpy(&ci->en, &en_templ, sizeof(en_templ)); + ci->en.data = ci; + port->en = &ci->en; + ci->port = port; + ci->nr = port->nr - 2; +} + +/* DuoFlex Dual CI support */ + +static int write_creg(struct ddb_ci *ci, u8 data, u8 mask) +{ + struct i2c_adapter *i2c = &ci->port->i2c->adap; + u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13; + + ci->port->creg = (ci->port->creg & ~mask) | data; + return i2c_write_reg(i2c, adr, 0x02, ci->port->creg); +} + +static int read_attribute_mem_xo2(struct dvb_ca_en50221 *ca, + int slot, int address) +{ + struct ddb_ci *ci = ca->data; + struct i2c_adapter *i2c = &ci->port->i2c->adap; + u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13; + int res; + u8 val; + + res = i2c_read_reg16(i2c, adr, 0x8000 | address, &val); + return res ? res : val; +} + +static int write_attribute_mem_xo2(struct dvb_ca_en50221 *ca, int slot, + int address, u8 value) +{ + struct ddb_ci *ci = ca->data; + struct i2c_adapter *i2c = &ci->port->i2c->adap; + u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13; + + return i2c_write_reg16(i2c, adr, 0x8000 | address, value); +} + +static int read_cam_control_xo2(struct dvb_ca_en50221 *ca, + int slot, u8 address) +{ + struct ddb_ci *ci = ca->data; + struct i2c_adapter *i2c = &ci->port->i2c->adap; + u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13; + u8 val; + int res; + + res = i2c_read_reg(i2c, adr, 0x20 | (address & 3), &val); + return res ? res : val; +} + +static int write_cam_control_xo2(struct dvb_ca_en50221 *ca, int slot, + u8 address, u8 value) +{ + struct ddb_ci *ci = ca->data; + struct i2c_adapter *i2c = &ci->port->i2c->adap; + u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13; + + return i2c_write_reg(i2c, adr, 0x20 | (address & 3), value); +} + +static int slot_reset_xo2(struct dvb_ca_en50221 *ca, int slot) +{ + struct ddb_ci *ci = ca->data; + + dev_dbg(ci->port->dev->dev, "%s\n", __func__); + write_creg(ci, 0x01, 0x01); + write_creg(ci, 0x04, 0x04); + msleep(20); + write_creg(ci, 0x02, 0x02); + write_creg(ci, 0x00, 0x04); + write_creg(ci, 0x18, 0x18); + return 0; +} + +static int slot_shutdown_xo2(struct dvb_ca_en50221 *ca, int slot) +{ + struct ddb_ci *ci = ca->data; + + dev_dbg(ci->port->dev->dev, "%s\n", __func__); + write_creg(ci, 0x10, 0xff); + write_creg(ci, 0x08, 0x08); + return 0; +} + +static int slot_ts_enable_xo2(struct dvb_ca_en50221 *ca, int slot) +{ + struct ddb_ci *ci = ca->data; + + dev_dbg(ci->port->dev->dev, "%s\n", __func__); + write_creg(ci, 0x00, 0x10); + return 0; +} + +static int poll_slot_status_xo2(struct dvb_ca_en50221 *ca, int slot, int open) +{ + struct ddb_ci *ci = ca->data; + struct i2c_adapter *i2c = &ci->port->i2c->adap; + u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13; + u8 val = 0; + int stat = 0; + + i2c_read_reg(i2c, adr, 0x01, &val); + + if (val & 2) + stat |= DVB_CA_EN50221_POLL_CAM_PRESENT; + if (val & 1) + stat |= DVB_CA_EN50221_POLL_CAM_READY; + return stat; +} + +static struct dvb_ca_en50221 en_xo2_templ = { + .read_attribute_mem = read_attribute_mem_xo2, + .write_attribute_mem = write_attribute_mem_xo2, + .read_cam_control = read_cam_control_xo2, + .write_cam_control = write_cam_control_xo2, + .slot_reset = slot_reset_xo2, + .slot_shutdown = slot_shutdown_xo2, + .slot_ts_enable = slot_ts_enable_xo2, + .poll_slot_status = poll_slot_status_xo2, +}; + +static void ci_xo2_attach(struct ddb_port *port) +{ + struct ddb_ci *ci; + + ci = kzalloc(sizeof(*ci), GFP_KERNEL); + if (!ci) + return; + memcpy(&ci->en, &en_xo2_templ, sizeof(en_xo2_templ)); + ci->en.data = ci; + port->en = &ci->en; + ci->port = port; + ci->nr = port->nr - 2; + ci->port->creg = 0; + write_creg(ci, 0x10, 0xff); + write_creg(ci, 0x08, 0x08); +} + +static struct cxd2099_cfg cxd_cfg = { + .bitrate = 72000, + .adr = 0x40, + .polarity = 1, + .clock_mode = 1, + .max_i2c = 512, +}; + +int ddb_ci_attach(struct ddb_port *port, u32 bitrate) +{ + switch (port->type) { + case DDB_CI_EXTERNAL_SONY: + cxd_cfg.bitrate = bitrate; + port->en = cxd2099_attach(&cxd_cfg, port, &port->i2c->adap); + if (!port->en) + return -ENODEV; + break; + + case DDB_CI_EXTERNAL_XO2: + case DDB_CI_EXTERNAL_XO2_B: + ci_xo2_attach(port); + if (!port->en) + return -ENODEV; + break; + + case DDB_CI_INTERNAL: + ci_attach(port); + if (!port->en) + return -ENODEV; + break; + } + + dvb_ca_en50221_init(port->dvb[0].adap, port->en, 0, 1); + return 0; +} + +void ddb_ci_detach(struct ddb_port *port) +{ + if (port->dvb[0].dev) + dvb_unregister_device(port->dvb[0].dev); + if (port->en) { + dvb_ca_en50221_release(port->en); + kfree(port->en->data); + port->en = NULL; + } +} diff --git a/drivers/media/pci/ddbridge/ddbridge-ci.h b/drivers/media/pci/ddbridge/ddbridge-ci.h new file mode 100644 index 000000000000..35a39182dd83 --- /dev/null +++ b/drivers/media/pci/ddbridge/ddbridge-ci.h @@ -0,0 +1,31 @@ +/* + * ddbridge-ci.h: Digital Devices bridge CI (DuoFlex, CI Bridge) support + * + * Copyright (C) 2010-2017 Digital Devices GmbH + * Marcus Metzler <mocm@metzlerbros.de> + * Ralph Metzler <rjkm@metzlerbros.de> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 only, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * To obtain the license, point your browser to + * http://www.gnu.org/copyleft/gpl.html + */ + +#ifndef __DDBRIDGE_CI_H__ +#define __DDBRIDGE_CI_H__ + +#include "ddbridge.h" + +/******************************************************************************/ + +int ddb_ci_attach(struct ddb_port *port, u32 bitrate); +void ddb_ci_detach(struct ddb_port *port); + +#endif /* __DDBRIDGE_CI_H__ */ diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c index f4bd4908acdd..c7d923e0e21a 100644 --- a/drivers/media/pci/ddbridge/ddbridge-core.c +++ b/drivers/media/pci/ddbridge/ddbridge-core.c @@ -37,7 +37,8 @@ #include "ddbridge.h" #include "ddbridge-i2c.h" #include "ddbridge-regs.h" -#include "ddbridge-maxs8.h" +#include "ddbridge-max.h" +#include "ddbridge-ci.h" #include "ddbridge-io.h" #include "tda18271c2dd.h" @@ -112,7 +113,6 @@ static void ddb_set_dma_tables(struct ddb *dev) } } - /****************************************************************************/ /****************************************************************************/ /****************************************************************************/ @@ -210,8 +210,9 @@ static int ddb_redirect(u32 i, u32 p) if (input->redi) { input2->redi = input->redi; input->redi = NULL; - } else + } else { input2->redi = input; + } } input->redo = port->output; port->output->redi = input; @@ -357,9 +358,9 @@ static void calc_con(struct ddb_output *output, u32 *con, u32 *con2, u32 flags) max_bitrate = 0; gap = 0; if (bitrate != 72000) { - if (bitrate >= 96000) + if (bitrate >= 96000) { *con |= 0x800; - else { + } else { *con |= 0x1000; nco = (bitrate * 8192 + 71999) / 72000; @@ -506,7 +507,6 @@ static void ddb_input_start(struct ddb_input *input) } } - static void ddb_input_start_all(struct ddb_input *input) { struct ddb_input *i = input; @@ -572,7 +572,7 @@ static ssize_t ddb_output_write(struct ddb_output *output, while (left) { len = output->dma->size - output->dma->coff; if ((((output->dma->cbuf + 1) % output->dma->num) == idx) && - (off == 0)) { + off == 0) { if (len <= 188) break; len -= 188; @@ -593,7 +593,8 @@ static ssize_t ddb_output_write(struct ddb_output *output, buf, len)) return -EIO; if (alt_dma) - dma_sync_single_for_device(dev->dev, + dma_sync_single_for_device( + dev->dev, output->dma->pbuf[output->dma->cbuf], output->dma->size, DMA_TO_DEVICE); left -= len; @@ -632,7 +633,7 @@ static u32 ddb_input_avail(struct ddb_input *input) } static ssize_t ddb_input_read(struct ddb_input *input, - __user u8 *buf, size_t count) + __user u8 *buf, size_t count) { struct ddb *dev = input->port->dev; u32 left = count; @@ -648,7 +649,8 @@ static ssize_t ddb_input_read(struct ddb_input *input, if (free > left) free = left; if (alt_dma) - dma_sync_single_for_cpu(dev->dev, + dma_sync_single_for_cpu( + dev->dev, input->dma->pbuf[input->dma->cbuf], input->dma->size, DMA_FROM_DEVICE); ret = copy_to_user(buf, input->dma->vbuf[input->dma->cbuf] + @@ -792,8 +794,10 @@ static int ts_open(struct inode *inode, struct file *file) } else if ((file->f_flags & O_ACCMODE) == O_WRONLY) { if (!output) return -EINVAL; - } else + } else { return -EINVAL; + } + err = dvb_generic_open(inode, file); if (err < 0) return err; @@ -822,7 +826,6 @@ static struct dvb_device dvbdev_ci = { .fops = &ci_fops, }; - /****************************************************************************/ /****************************************************************************/ @@ -848,21 +851,20 @@ static int demod_attach_drxk(struct ddb_input *input) struct i2c_adapter *i2c = &input->port->i2c->adap; struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; struct device *dev = input->port->dev->dev; - struct dvb_frontend *fe; struct drxk_config config; memset(&config, 0, sizeof(config)); config.adr = 0x29 + (input->nr & 1); config.microcode_name = "drxk_a3.mc"; - fe = dvb->fe = dvb_attach(drxk_attach, &config, i2c); - if (!fe) { + dvb->fe = dvb_attach(drxk_attach, &config, i2c); + if (!dvb->fe) { dev_err(dev, "No DRXK found!\n"); return -ENODEV; } - fe->sec_priv = input; - dvb->i2c_gate_ctrl = fe->ops.i2c_gate_ctrl; - fe->ops.i2c_gate_ctrl = locked_gate_ctrl; + dvb->fe->sec_priv = input; + dvb->i2c_gate_ctrl = dvb->fe->ops.i2c_gate_ctrl; + dvb->fe->ops.i2c_gate_ctrl = locked_gate_ctrl; return 0; } @@ -912,19 +914,18 @@ static int demod_attach_stv0367(struct ddb_input *input) struct i2c_adapter *i2c = &input->port->i2c->adap; struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; struct device *dev = input->port->dev->dev; - struct dvb_frontend *fe; /* attach frontend */ - fe = dvb->fe = dvb_attach(stv0367ddb_attach, - &ddb_stv0367_config[(input->nr & 1)], i2c); + dvb->fe = dvb_attach(stv0367ddb_attach, + &ddb_stv0367_config[(input->nr & 1)], i2c); if (!dvb->fe) { dev_err(dev, "No stv0367 found!\n"); return -ENODEV; } - fe->sec_priv = input; - dvb->i2c_gate_ctrl = fe->ops.i2c_gate_ctrl; - fe->ops.i2c_gate_ctrl = locked_gate_ctrl; + dvb->fe->sec_priv = input; + dvb->i2c_gate_ctrl = dvb->fe->ops.i2c_gate_ctrl; + dvb->fe->ops.i2c_gate_ctrl = locked_gate_ctrl; return 0; } @@ -956,7 +957,6 @@ static int demod_attach_cxd28xx(struct ddb_input *input, int par, int osc24) struct i2c_adapter *i2c = &input->port->i2c->adap; struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1]; struct device *dev = input->port->dev->dev; - struct dvb_frontend *fe; struct cxd2841er_config cfg; /* the cxd2841er driver expects 8bit/shifted I2C addresses */ @@ -971,15 +971,15 @@ static int demod_attach_cxd28xx(struct ddb_input *input, int par, int osc24) cfg.flags |= CXD2841ER_TS_SERIAL; /* attach frontend */ - fe = dvb->fe = dvb_attach(cxd2841er_attach_t_c, &cfg, i2c); + dvb->fe = dvb_attach(cxd2841er_attach_t_c, &cfg, i2c); if (!dvb->fe) { dev_err(dev, "No cxd2837/38/43/54 found!\n"); return -ENODEV; } - fe->sec_priv = input; - dvb->i2c_gate_ctrl = fe->ops.i2c_gate_ctrl; - fe->ops.i2c_gate_ctrl = locked_gate_ctrl; + dvb->fe->sec_priv = input; + dvb->i2c_gate_ctrl = dvb->fe->ops.i2c_gate_ctrl; + dvb->fe->ops.i2c_gate_ctrl = locked_gate_ctrl; return 0; } @@ -1020,7 +1020,7 @@ static int tuner_attach_tda18212(struct ddb_input *input, u32 porttype) /* perform tuner init/attach */ client = i2c_new_device(adapter, &board_info); - if (client == NULL || client->dev.driver == NULL) + if (!client || !client->dev.driver) goto err; if (!try_module_get(client->dev.driver->owner)) { @@ -1032,7 +1032,7 @@ static int tuner_attach_tda18212(struct ddb_input *input, u32 porttype) return 0; err: - dev_notice(dev, "TDA18212 tuner not found. Device is not fully operational.\n"); + dev_err(dev, "TDA18212 tuner not found. Device is not fully operational.\n"); return -ENODEV; } @@ -1114,6 +1114,7 @@ static int demod_attach_stv0900(struct ddb_input *input, int type) 0, (input->nr & 1) ? (0x09 - type) : (0x0b - type))) { dev_err(dev, "No LNBH24 found!\n"); + dvb_frontend_detach(dvb->fe); return -ENODEV; } return 0; @@ -1135,7 +1136,7 @@ static int tuner_attach_stv6110(struct ddb_input *input, int type) return -ENODEV; } dev_info(dev, "attach tuner input %d adr %02x\n", - input->nr, tunerconf->addr); + input->nr, tunerconf->addr); feconf->tuner_init = ctl->tuner_init; feconf->tuner_sleep = ctl->tuner_sleep; @@ -1196,6 +1197,7 @@ static int demod_attach_stv0910(struct ddb_input *input, int type) lnbcfg.i2c_address = (((input->nr & 1) ? 0x09 : 0x08) << 1); if (!dvb_attach(lnbh25_attach, dvb->fe, &lnbcfg, i2c)) { dev_err(dev, "No LNBH25 found!\n"); + dvb_frontend_detach(dvb->fe); return -ENODEV; } } @@ -1261,19 +1263,22 @@ static void dvb_input_detach(struct ddb_input *input) dvb_unregister_frontend(dvb->fe); /* fallthrough */ case 0x30: - if (dvb->fe2) - dvb_frontend_detach(dvb->fe2); - if (dvb->fe) - dvb_frontend_detach(dvb->fe); - dvb->fe = dvb->fe2 = NULL; - /* fallthrough */ - case 0x20: client = dvb->i2c_client[0]; if (client) { module_put(client->dev.driver->owner); i2c_unregister_device(client); + dvb->i2c_client[0] = NULL; + client = NULL; } + if (dvb->fe2) + dvb_frontend_detach(dvb->fe2); + if (dvb->fe) + dvb_frontend_detach(dvb->fe); + dvb->fe = NULL; + dvb->fe2 = NULL; + /* fallthrough */ + case 0x20: dvb_net_release(&dvb->dvbnet); /* fallthrough */ case 0x12: @@ -1409,7 +1414,8 @@ static int dvb_input_attach(struct ddb_input *input) DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING; dvbdemux->start_feed = start_feed; dvbdemux->stop_feed = stop_feed; - dvbdemux->filternum = dvbdemux->feednum = 256; + dvbdemux->filternum = 256; + dvbdemux->feednum = 256; ret = dvb_dmx_init(dvbdemux); if (ret < 0) return ret; @@ -1419,7 +1425,7 @@ static int dvb_input_attach(struct ddb_input *input) dvb->dmxdev.demux = &dvbdemux->dmx; ret = dvb_dmxdev_init(&dvb->dmxdev, adap); if (ret < 0) - return ret; + goto err_detach; dvb->attached = 0x11; dvb->mem_frontend.source = DMX_MEMORY_FE; @@ -1428,66 +1434,62 @@ static int dvb_input_attach(struct ddb_input *input) dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->hw_frontend); ret = dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, &dvb->hw_frontend); if (ret < 0) - return ret; + goto err_detach; dvb->attached = 0x12; ret = dvb_net_init(adap, &dvb->dvbnet, dvb->dmxdev.demux); if (ret < 0) - return ret; + goto err_detach; dvb->attached = 0x20; - dvb->fe = dvb->fe2 = NULL; + dvb->fe = NULL; + dvb->fe2 = NULL; switch (port->type) { case DDB_TUNER_MXL5XX: - if (fe_attach_mxl5xx(input) < 0) - return -ENODEV; + if (ddb_fe_attach_mxl5xx(input) < 0) + goto err_detach; break; case DDB_TUNER_DVBS_ST: if (demod_attach_stv0900(input, 0) < 0) - return -ENODEV; + goto err_detach; if (tuner_attach_stv6110(input, 0) < 0) - return -ENODEV; + goto err_tuner; break; case DDB_TUNER_DVBS_ST_AA: if (demod_attach_stv0900(input, 1) < 0) - return -ENODEV; + goto err_detach; if (tuner_attach_stv6110(input, 1) < 0) - return -ENODEV; + goto err_tuner; break; case DDB_TUNER_DVBS_STV0910: if (demod_attach_stv0910(input, 0) < 0) - return -ENODEV; + goto err_detach; if (tuner_attach_stv6111(input, 0) < 0) - return -ENODEV; + goto err_tuner; break; case DDB_TUNER_DVBS_STV0910_PR: if (demod_attach_stv0910(input, 1) < 0) - return -ENODEV; + goto err_detach; if (tuner_attach_stv6111(input, 1) < 0) - return -ENODEV; + goto err_tuner; break; case DDB_TUNER_DVBS_STV0910_P: if (demod_attach_stv0910(input, 0) < 0) - return -ENODEV; + goto err_detach; if (tuner_attach_stv6111(input, 1) < 0) - return -ENODEV; + goto err_tuner; break; case DDB_TUNER_DVBCT_TR: if (demod_attach_drxk(input) < 0) - return -ENODEV; + goto err_detach; if (tuner_attach_tda18271(input) < 0) - return -ENODEV; + goto err_tuner; break; case DDB_TUNER_DVBCT_ST: if (demod_attach_stv0367(input) < 0) - return -ENODEV; - if (tuner_attach_tda18212(input, port->type) < 0) { - if (dvb->fe2) - dvb_frontend_detach(dvb->fe2); - if (dvb->fe) - dvb_frontend_detach(dvb->fe); - return -ENODEV; - } + goto err_detach; + if (tuner_attach_tda18212(input, port->type) < 0) + goto err_tuner; break; case DDB_TUNER_DVBC2T2I_SONY_P: if (input->port->dev->link[input->port->lnr].info->ts_quirks & @@ -1505,14 +1507,9 @@ static int dvb_input_attach(struct ddb_input *input) else par = 1; if (demod_attach_cxd28xx(input, par, osc24) < 0) - return -ENODEV; - if (tuner_attach_tda18212(input, port->type) < 0) { - if (dvb->fe2) - dvb_frontend_detach(dvb->fe2); - if (dvb->fe) - dvb_frontend_detach(dvb->fe); - return -ENODEV; - } + goto err_detach; + if (tuner_attach_tda18212(input, port->type) < 0) + goto err_tuner; break; case DDB_TUNER_DVBC2T2I_SONY: osc24 = 1; @@ -1521,14 +1518,9 @@ static int dvb_input_attach(struct ddb_input *input) case DDB_TUNER_DVBC2T2_SONY: case DDB_TUNER_ISDBT_SONY: if (demod_attach_cxd28xx(input, 0, osc24) < 0) - return -ENODEV; - if (tuner_attach_tda18212(input, port->type) < 0) { - if (dvb->fe2) - dvb_frontend_detach(dvb->fe2); - if (dvb->fe) - dvb_frontend_detach(dvb->fe); - return -ENODEV; - } + goto err_detach; + if (tuner_attach_tda18212(input, port->type) < 0) + goto err_tuner; break; default: return 0; @@ -1537,11 +1529,13 @@ static int dvb_input_attach(struct ddb_input *input) if (dvb->fe) { if (dvb_register_frontend(adap, dvb->fe) < 0) - return -ENODEV; + goto err_detach; if (dvb->fe2) { - if (dvb_register_frontend(adap, dvb->fe2) < 0) - return -ENODEV; + if (dvb_register_frontend(adap, dvb->fe2) < 0) { + dvb_unregister_frontend(dvb->fe); + goto err_detach; + } dvb->fe2->tuner_priv = dvb->fe->tuner_priv; memcpy(&dvb->fe2->ops.tuner_ops, &dvb->fe->ops.tuner_ops, @@ -1551,6 +1545,22 @@ static int dvb_input_attach(struct ddb_input *input) dvb->attached = 0x31; return 0; + +err_tuner: + dev_err(port->dev->dev, "tuner attach failed!\n"); + + if (dvb->fe2) + dvb_frontend_detach(dvb->fe2); + if (dvb->fe) + dvb_frontend_detach(dvb->fe); +err_detach: + dvb_input_detach(input); + + /* return error from ret if set */ + if (ret < 0) + return ret; + + return -ENODEV; } static int port_has_encti(struct ddb_port *port) @@ -1703,11 +1713,11 @@ static int init_xo2_ci(struct ddb_port *port) if (data[0] > 1) { dev_info(dev->dev, "Port %d: invalid XO2 CI %02x\n", - port->nr, data[0]); + port->nr, data[0]); return -1; } dev_info(dev->dev, "Port %d: DuoFlex CI %u.%u\n", - port->nr, data[0], data[1]); + port->nr, data[0], data[1]); i2c_read_reg(i2c, 0x10, 0x08, &val); if (val != 0) { @@ -1718,7 +1728,6 @@ static int init_xo2_ci(struct ddb_port *port) i2c_write_reg(i2c, 0x10, 0x08, 3); usleep_range(2000, 3000); - /* speed: 0=55,1=75,2=90,3=104 MBit/s */ i2c_write_reg(i2c, 0x10, 0x09, 1); @@ -1821,7 +1830,7 @@ static void ddb_port_probe(struct ddb_port *port) port->i2c->regs + I2C_TIMING); } else { dev_info(dev->dev, "Port %d: Uninitialized DuoFlex\n", - port->nr); + port->nr); return; } } else if (port_has_xo2(port, &type, &id)) { @@ -1912,338 +1921,10 @@ static void ddb_port_probe(struct ddb_port *port) } } - -/****************************************************************************/ -/****************************************************************************/ -/****************************************************************************/ - -static int wait_ci_ready(struct ddb_ci *ci) -{ - u32 count = 10; - - ndelay(500); - do { - if (ddbreadl(ci->port->dev, - CI_CONTROL(ci->nr)) & CI_READY) - break; - usleep_range(1, 2); - if ((--count) == 0) - return -1; - } while (1); - return 0; -} - -static int read_attribute_mem(struct dvb_ca_en50221 *ca, - int slot, int address) -{ - struct ddb_ci *ci = ca->data; - u32 val, off = (address >> 1) & (CI_BUFFER_SIZE - 1); - - if (address > CI_BUFFER_SIZE) - return -1; - ddbwritel(ci->port->dev, CI_READ_CMD | (1 << 16) | address, - CI_DO_READ_ATTRIBUTES(ci->nr)); - wait_ci_ready(ci); - val = 0xff & ddbreadl(ci->port->dev, CI_BUFFER(ci->nr) + off); - return val; -} - -static int write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, - int address, u8 value) -{ - struct ddb_ci *ci = ca->data; - - ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address, - CI_DO_ATTRIBUTE_RW(ci->nr)); - wait_ci_ready(ci); - return 0; -} - -static int read_cam_control(struct dvb_ca_en50221 *ca, - int slot, u8 address) -{ - u32 count = 100; - struct ddb_ci *ci = ca->data; - u32 res; - - ddbwritel(ci->port->dev, CI_READ_CMD | address, - CI_DO_IO_RW(ci->nr)); - ndelay(500); - do { - res = ddbreadl(ci->port->dev, CI_READDATA(ci->nr)); - if (res & CI_READY) - break; - usleep_range(1, 2); - if ((--count) == 0) - return -1; - } while (1); - return 0xff & res; -} - -static int write_cam_control(struct dvb_ca_en50221 *ca, int slot, - u8 address, u8 value) -{ - struct ddb_ci *ci = ca->data; - - ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address, - CI_DO_IO_RW(ci->nr)); - wait_ci_ready(ci); - return 0; -} - -static int slot_reset(struct dvb_ca_en50221 *ca, int slot) -{ - struct ddb_ci *ci = ca->data; - - ddbwritel(ci->port->dev, CI_POWER_ON, - CI_CONTROL(ci->nr)); - msleep(100); - ddbwritel(ci->port->dev, CI_POWER_ON | CI_RESET_CAM, - CI_CONTROL(ci->nr)); - ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON | CI_RESET_CAM, - CI_CONTROL(ci->nr)); - udelay(20); - ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON, - CI_CONTROL(ci->nr)); - return 0; -} - -static int slot_shutdown(struct dvb_ca_en50221 *ca, int slot) -{ - struct ddb_ci *ci = ca->data; - - ddbwritel(ci->port->dev, 0, CI_CONTROL(ci->nr)); - msleep(300); - return 0; -} - -static int slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) -{ - struct ddb_ci *ci = ca->data; - u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci->nr)); - - ddbwritel(ci->port->dev, val | CI_BYPASS_DISABLE, - CI_CONTROL(ci->nr)); - return 0; -} - -static int poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open) -{ - struct ddb_ci *ci = ca->data; - u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci->nr)); - int stat = 0; - - if (val & CI_CAM_DETECT) - stat |= DVB_CA_EN50221_POLL_CAM_PRESENT; - if (val & CI_CAM_READY) - stat |= DVB_CA_EN50221_POLL_CAM_READY; - return stat; -} - -static struct dvb_ca_en50221 en_templ = { - .read_attribute_mem = read_attribute_mem, - .write_attribute_mem = write_attribute_mem, - .read_cam_control = read_cam_control, - .write_cam_control = write_cam_control, - .slot_reset = slot_reset, - .slot_shutdown = slot_shutdown, - .slot_ts_enable = slot_ts_enable, - .poll_slot_status = poll_slot_status, -}; - -static void ci_attach(struct ddb_port *port) -{ - struct ddb_ci *ci = NULL; - - ci = kzalloc(sizeof(*ci), GFP_KERNEL); - if (!ci) - return; - memcpy(&ci->en, &en_templ, sizeof(en_templ)); - ci->en.data = ci; - port->en = &ci->en; - ci->port = port; - ci->nr = port->nr - 2; -} - /****************************************************************************/ /****************************************************************************/ /****************************************************************************/ -static int write_creg(struct ddb_ci *ci, u8 data, u8 mask) -{ - struct i2c_adapter *i2c = &ci->port->i2c->adap; - u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13; - - ci->port->creg = (ci->port->creg & ~mask) | data; - return i2c_write_reg(i2c, adr, 0x02, ci->port->creg); -} - -static int read_attribute_mem_xo2(struct dvb_ca_en50221 *ca, - int slot, int address) -{ - struct ddb_ci *ci = ca->data; - struct i2c_adapter *i2c = &ci->port->i2c->adap; - u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13; - int res; - u8 val; - - res = i2c_read_reg16(i2c, adr, 0x8000 | address, &val); - return res ? res : val; -} - -static int write_attribute_mem_xo2(struct dvb_ca_en50221 *ca, int slot, - int address, u8 value) -{ - struct ddb_ci *ci = ca->data; - struct i2c_adapter *i2c = &ci->port->i2c->adap; - u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13; - - return i2c_write_reg16(i2c, adr, 0x8000 | address, value); -} - -static int read_cam_control_xo2(struct dvb_ca_en50221 *ca, - int slot, u8 address) -{ - struct ddb_ci *ci = ca->data; - struct i2c_adapter *i2c = &ci->port->i2c->adap; - u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13; - u8 val; - int res; - - res = i2c_read_reg(i2c, adr, 0x20 | (address & 3), &val); - return res ? res : val; -} - -static int write_cam_control_xo2(struct dvb_ca_en50221 *ca, int slot, - u8 address, u8 value) -{ - struct ddb_ci *ci = ca->data; - struct i2c_adapter *i2c = &ci->port->i2c->adap; - u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13; - - return i2c_write_reg(i2c, adr, 0x20 | (address & 3), value); -} - -static int slot_reset_xo2(struct dvb_ca_en50221 *ca, int slot) -{ - struct ddb_ci *ci = ca->data; - - dev_dbg(ci->port->dev->dev, "%s\n", __func__); - write_creg(ci, 0x01, 0x01); - write_creg(ci, 0x04, 0x04); - msleep(20); - write_creg(ci, 0x02, 0x02); - write_creg(ci, 0x00, 0x04); - write_creg(ci, 0x18, 0x18); - return 0; -} - -static int slot_shutdown_xo2(struct dvb_ca_en50221 *ca, int slot) -{ - struct ddb_ci *ci = ca->data; - - dev_dbg(ci->port->dev->dev, "%s\n", __func__); - write_creg(ci, 0x10, 0xff); - write_creg(ci, 0x08, 0x08); - return 0; -} - -static int slot_ts_enable_xo2(struct dvb_ca_en50221 *ca, int slot) -{ - struct ddb_ci *ci = ca->data; - - dev_info(ci->port->dev->dev, "%s\n", __func__); - write_creg(ci, 0x00, 0x10); - return 0; -} - -static int poll_slot_status_xo2(struct dvb_ca_en50221 *ca, int slot, int open) -{ - struct ddb_ci *ci = ca->data; - struct i2c_adapter *i2c = &ci->port->i2c->adap; - u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13; - u8 val = 0; - int stat = 0; - - i2c_read_reg(i2c, adr, 0x01, &val); - - if (val & 2) - stat |= DVB_CA_EN50221_POLL_CAM_PRESENT; - if (val & 1) - stat |= DVB_CA_EN50221_POLL_CAM_READY; - return stat; -} - -static struct dvb_ca_en50221 en_xo2_templ = { - .read_attribute_mem = read_attribute_mem_xo2, - .write_attribute_mem = write_attribute_mem_xo2, - .read_cam_control = read_cam_control_xo2, - .write_cam_control = write_cam_control_xo2, - .slot_reset = slot_reset_xo2, - .slot_shutdown = slot_shutdown_xo2, - .slot_ts_enable = slot_ts_enable_xo2, - .poll_slot_status = poll_slot_status_xo2, -}; - -static void ci_xo2_attach(struct ddb_port *port) -{ - struct ddb_ci *ci; - - ci = kzalloc(sizeof(*ci), GFP_KERNEL); - if (!ci) - return; - memcpy(&ci->en, &en_xo2_templ, sizeof(en_xo2_templ)); - ci->en.data = ci; - port->en = &ci->en; - ci->port = port; - ci->nr = port->nr - 2; - ci->port->creg = 0; - write_creg(ci, 0x10, 0xff); - write_creg(ci, 0x08, 0x08); -} - -/****************************************************************************/ -/****************************************************************************/ -/****************************************************************************/ - -static struct cxd2099_cfg cxd_cfg = { - .bitrate = 72000, - .adr = 0x40, - .polarity = 1, - .clock_mode = 1, - .max_i2c = 512, -}; - -static int ddb_ci_attach(struct ddb_port *port) -{ - switch (port->type) { - case DDB_CI_EXTERNAL_SONY: - cxd_cfg.bitrate = ci_bitrate; - port->en = cxd2099_attach(&cxd_cfg, port, &port->i2c->adap); - if (!port->en) - return -ENODEV; - dvb_ca_en50221_init(port->dvb[0].adap, - port->en, 0, 1); - break; - - case DDB_CI_EXTERNAL_XO2: - case DDB_CI_EXTERNAL_XO2_B: - ci_xo2_attach(port); - if (!port->en) - return -ENODEV; - dvb_ca_en50221_init(port->dvb[0].adap, port->en, 0, 1); - break; - - case DDB_CI_INTERNAL: - ci_attach(port); - if (!port->en) - return -ENODEV; - dvb_ca_en50221_init(port->dvb[0].adap, port->en, 0, 1); - break; - } - return 0; -} - static int ddb_port_attach(struct ddb_port *port) { int ret = 0; @@ -2254,20 +1935,22 @@ static int ddb_port_attach(struct ddb_port *port) if (ret < 0) break; ret = dvb_input_attach(port->input[1]); - if (ret < 0) + if (ret < 0) { + dvb_input_detach(port->input[0]); break; + } port->input[0]->redi = port->input[0]; port->input[1]->redi = port->input[1]; break; case DDB_PORT_CI: - ret = ddb_ci_attach(port); + ret = ddb_ci_attach(port, ci_bitrate); if (ret < 0) break; /* fall-through */ case DDB_PORT_LOOP: ret = dvb_register_device(port->dvb[0].adap, &port->dvb[0].dev, - &dvbdev_ci, (void *) port->output, + &dvbdev_ci, (void *)port->output, DVB_DEVICE_SEC, 0); break; default: @@ -2281,7 +1964,7 @@ static int ddb_port_attach(struct ddb_port *port) int ddb_ports_attach(struct ddb *dev) { - int i, ret = 0; + int i, numports, err_ports = 0, ret = 0; struct ddb_port *port; if (dev->port_num) { @@ -2291,11 +1974,31 @@ int ddb_ports_attach(struct ddb *dev) return ret; } } + + numports = dev->port_num; + for (i = 0; i < dev->port_num; i++) { port = &dev->port[i]; - ret = ddb_port_attach(port); + if (port->class != DDB_PORT_NONE) { + ret = ddb_port_attach(port); + if (ret) + err_ports++; + } else { + numports--; + } } - return ret; + + if (err_ports) { + if (err_ports == numports) { + dev_err(dev->dev, "All connected ports failed to initialise!\n"); + return -ENODEV; + } + + dev_warn(dev->dev, "%d of %d connected ports failed to initialise!\n", + err_ports, numports); + } + + return 0; } void ddb_ports_detach(struct ddb *dev) @@ -2308,25 +2011,18 @@ void ddb_ports_detach(struct ddb *dev) switch (port->class) { case DDB_PORT_TUNER: - dvb_input_detach(port->input[0]); dvb_input_detach(port->input[1]); + dvb_input_detach(port->input[0]); break; case DDB_PORT_CI: case DDB_PORT_LOOP: - if (port->dvb[0].dev) - dvb_unregister_device(port->dvb[0].dev); - if (port->en) { - dvb_ca_en50221_release(port->en); - kfree(port->en); - port->en = NULL; - } + ddb_ci_detach(port); break; } } dvb_unregister_adapters(dev); } - /* Copy input DMA pointers to output DMA and ACK. */ static void input_write_output(struct ddb_input *input, @@ -2353,16 +2049,18 @@ static void input_write_dvb(struct ddb_input *input, struct ddb *dev = input->port->dev; int ack = 1; - dma = dma2 = input->dma; - /* if there also is an output connected, do not ACK. + dma = input->dma; + dma2 = input->dma; + /* + * if there also is an output connected, do not ACK. * input_write_output will ACK. */ if (input->redo) { dma2 = input->redo->dma; ack = 0; } - while (dma->cbuf != ((dma->stat >> 11) & 0x1f) - || (4 & dma->ctrl)) { + while (dma->cbuf != ((dma->stat >> 11) & 0x1f) || + (4 & dma->ctrl)) { if (4 & dma->ctrl) { /* dev_err(dev->dev, "Overflow dma %d\n", dma->nr); */ ack = 1; @@ -2385,7 +2083,7 @@ static void input_write_dvb(struct ddb_input *input, static void input_work(struct work_struct *work) { struct ddb_dma *dma = container_of(work, struct ddb_dma, work); - struct ddb_input *input = (struct ddb_input *) dma->io; + struct ddb_input *input = (struct ddb_input *)dma->io; struct ddb *dev = input->port->dev; unsigned long flags; @@ -2407,11 +2105,11 @@ static void input_work(struct work_struct *work) static void input_handler(unsigned long data) { - struct ddb_input *input = (struct ddb_input *) data; + struct ddb_input *input = (struct ddb_input *)data; struct ddb_dma *dma = input->dma; - - /* If there is no input connected, input_tasklet() will + /* + * If there is no input connected, input_tasklet() will * just copy pointers and ACK. So, there is no need to go * through the tasklet scheduler. */ @@ -2423,7 +2121,7 @@ static void input_handler(unsigned long data) static void output_handler(unsigned long data) { - struct ddb_output *output = (struct ddb_output *) data; + struct ddb_output *output = (struct ddb_output *)data; struct ddb_dma *dma = output->dma; struct ddb *dev = output->port->dev; @@ -2512,10 +2210,10 @@ static void ddb_input_init(struct ddb_port *port, int nr, int pnr, int anr) dma_nr += 32 + (port->lnr - 1) * 8; dev_dbg(dev->dev, "init link %u, input %u, handler %u\n", - port->lnr, nr, dma_nr + base); + port->lnr, nr, dma_nr + base); dev->handler[0][dma_nr + base] = input_handler; - dev->handler_data[0][dma_nr + base] = (unsigned long) input; + dev->handler_data[0][dma_nr + base] = (unsigned long)input; ddb_dma_init(input, dma_nr, 0); } } @@ -2534,14 +2232,14 @@ static void ddb_output_init(struct ddb_port *port, int nr) (rm->output->base + rm->output->size * nr); dev_dbg(dev->dev, "init link %u, output %u, regs %08x\n", - port->lnr, nr, output->regs); + port->lnr, nr, output->regs); if (dev->has_dma) { const struct ddb_regmap *rm0 = io_regmap(output, 0); u32 base = rm0->irq_base_odma; dev->handler[0][nr + base] = output_handler; - dev->handler_data[0][nr + base] = (unsigned long) output; + dev->handler_data[0][nr + base] = (unsigned long)output; ddb_dma_init(output, nr, 1); } } @@ -2609,7 +2307,7 @@ void ddb_ports_init(struct ddb *dev) port->dvb[0].adap = &dev->adap[2 * p]; port->dvb[1].adap = &dev->adap[2 * p + 1]; - if ((port->class == DDB_PORT_NONE) && i && p && + if (port->class == DDB_PORT_NONE && i && p && dev->port[p - 1].type == DDB_CI_EXTERNAL_XO2) { port->class = DDB_PORT_CI; port->type = DDB_CI_EXTERNAL_XO2_B; @@ -2618,8 +2316,8 @@ void ddb_ports_init(struct ddb *dev) } dev_info(dev->dev, "Port %u: Link %u, Link Port %u (TAB %u): %s\n", - port->pnr, port->lnr, port->nr, port->nr + 1, - port->name); + port->pnr, port->lnr, port->nr, port->nr + 1, + port->name); if (port->class == DDB_PORT_CI && port->type == DDB_CI_EXTERNAL_XO2) { @@ -2741,7 +2439,7 @@ static void irq_handle_io(struct ddb *dev, u32 s) irqreturn_t ddb_irq_handler0(int irq, void *dev_id) { - struct ddb *dev = (struct ddb *) dev_id; + struct ddb *dev = (struct ddb *)dev_id; u32 s = ddbreadl(dev, INTERRUPT_STATUS); do { @@ -2758,7 +2456,7 @@ irqreturn_t ddb_irq_handler0(int irq, void *dev_id) irqreturn_t ddb_irq_handler1(int irq, void *dev_id) { - struct ddb *dev = (struct ddb *) dev_id; + struct ddb *dev = (struct ddb *)dev_id; u32 s = ddbreadl(dev, INTERRUPT_STATUS); do { @@ -2775,7 +2473,7 @@ irqreturn_t ddb_irq_handler1(int irq, void *dev_id) irqreturn_t ddb_irq_handler(int irq, void *dev_id) { - struct ddb *dev = (struct ddb *) dev_id; + struct ddb *dev = (struct ddb *)dev_id; u32 s = ddbreadl(dev, INTERRUPT_STATUS); int ret = IRQ_HANDLED; @@ -2812,7 +2510,7 @@ static int reg_wait(struct ddb *dev, u32 reg, u32 bit) } static int flashio(struct ddb *dev, u32 lnr, u8 *wbuf, u32 wlen, u8 *rbuf, - u32 rlen) + u32 rlen) { u32 data, shift; u32 tag = DDB_LINK_TAG(lnr); @@ -2823,7 +2521,7 @@ static int flashio(struct ddb *dev, u32 lnr, u8 *wbuf, u32 wlen, u8 *rbuf, ddbwritel(dev, 1, tag | SPI_CONTROL); while (wlen > 4) { /* FIXME: check for big-endian */ - data = swab32(*(u32 *) wbuf); + data = swab32(*(u32 *)wbuf); wbuf += 4; wlen -= 4; ddbwritel(dev, data, tag | SPI_DATA); @@ -2863,12 +2561,12 @@ static int flashio(struct ddb *dev, u32 lnr, u8 *wbuf, u32 wlen, u8 *rbuf, if (reg_wait(dev, tag | SPI_CONTROL, 4)) goto fail; data = ddbreadl(dev, tag | SPI_DATA); - *(u32 *) rbuf = swab32(data); + *(u32 *)rbuf = swab32(data); rbuf += 4; rlen -= 4; } ddbwritel(dev, 0x0003 | ((rlen << (8 + 3)) & 0x1F00), - tag | SPI_CONTROL); + tag | SPI_CONTROL); ddbwritel(dev, 0xffffffff, tag | SPI_DATA); if (reg_wait(dev, tag | SPI_CONTROL, 4)) goto fail; @@ -3011,7 +2709,7 @@ static ssize_t fan_store(struct device *device, struct device_attribute *d, } static ssize_t fanspeed_show(struct device *device, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, char *buf) { struct ddb *dev = dev_get_drvdata(device); int num = attr->attr.name[8] - 0x30; @@ -3049,7 +2747,7 @@ static ssize_t temp_show(struct device *device, } static ssize_t ctemp_show(struct device *device, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, char *buf) { struct ddb *dev = dev_get_drvdata(device); struct i2c_adapter *adap; @@ -3076,7 +2774,6 @@ static ssize_t led_show(struct device *device, return sprintf(buf, "%d\n", dev->leds & (1 << num) ? 1 : 0); } - static void ddb_set_led(struct ddb *dev, int num, int val) { if (!dev->link[0].info->led_num) @@ -3163,7 +2860,7 @@ static ssize_t bsnr_show(struct device *device, } static ssize_t bpsnr_show(struct device *device, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, char *buf) { struct ddb *dev = dev_get_drvdata(device); unsigned char snr[32]; @@ -3208,7 +2905,6 @@ static ssize_t gap_show(struct device *device, int num = attr->attr.name[3] - 0x30; return sprintf(buf, "%d\n", dev->port[num].gap); - } static ssize_t gap_store(struct device *device, struct device_attribute *attr, @@ -3254,7 +2950,7 @@ static ssize_t regmap_show(struct device *device, } static ssize_t fmode_show(struct device *device, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, char *buf) { int num = attr->attr.name[5] - 0x30; struct ddb *dev = dev_get_drvdata(device); @@ -3272,7 +2968,7 @@ static ssize_t devid_show(struct device *device, } static ssize_t fmode_store(struct device *device, struct device_attribute *attr, - const char *buf, size_t count) + const char *buf, size_t count) { struct ddb *dev = dev_get_drvdata(device); int num = attr->attr.name[5] - 0x30; @@ -3282,7 +2978,7 @@ static ssize_t fmode_store(struct device *device, struct device_attribute *attr, return -EINVAL; if (val > 3) return -EINVAL; - lnb_init_fmode(dev, &dev->link[num], val); + ddb_lnb_init_fmode(dev, &dev->link[num], val); return count; } @@ -3387,7 +3083,7 @@ static void ddb_device_attrs_del(struct ddb *dev) device_remove_file(dev->ddb_dev, &ddb_attrs_snr[i]); device_remove_file(dev->ddb_dev, &ddb_attrs_ctemp[i]); } - for (i = 0; ddb_attrs[i].attr.name != NULL; i++) + for (i = 0; ddb_attrs[i].attr.name; i++) device_remove_file(dev->ddb_dev, &ddb_attrs[i]); } @@ -3395,7 +3091,7 @@ static int ddb_device_attrs_add(struct ddb *dev) { int i; - for (i = 0; ddb_attrs[i].attr.name != NULL; i++) + for (i = 0; ddb_attrs[i].attr.name; i++) if (device_create_file(dev->ddb_dev, &ddb_attrs[i])) goto fail; for (i = 0; i < dev->link[0].info->temp_num; i++) @@ -3447,8 +3143,9 @@ int ddb_device_create(struct ddb *dev) device_destroy(&ddb_class, MKDEV(ddb_major, dev->nr)); ddbs[dev->nr] = NULL; dev->ddb_dev = ERR_PTR(-ENODEV); - } else + } else { ddb_num++; + } fail: mutex_unlock(&ddb_mutex); return res; @@ -3500,7 +3197,7 @@ static void tempmon_setfan(struct ddb_link *link) static void temp_handler(unsigned long data) { - struct ddb_link *link = (struct ddb_link *) data; + struct ddb_link *link = (struct ddb_link *)data; spin_lock(&link->temp_lock); tempmon_setfan(link); @@ -3519,10 +3216,10 @@ static int tempmon_init(struct ddb_link *link, int first_time) 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80 }; memcpy(link->temp_tab, temperature_table, - sizeof(temperature_table)); + sizeof(temperature_table)); } dev->handler[l][link->info->tempmon_irq] = temp_handler; - dev->handler_data[l][link->info->tempmon_irq] = (unsigned long) link; + dev->handler_data[l][link->info->tempmon_irq] = (unsigned long)link; ddblwritel(link, (TEMPMON_CONTROL_OVERTEMP | TEMPMON_CONTROL_AUTOSCAN | TEMPMON_CONTROL_INTENABLE), TEMPMON_CONTROL); @@ -3574,11 +3271,11 @@ static int ddb_init_boards(struct ddb *dev) ddbwritel(dev, 0, DDB_LINK_TAG(l) | BOARD_CONTROL); msleep(100); ddbwritel(dev, info->board_control_2, - DDB_LINK_TAG(l) | BOARD_CONTROL); + DDB_LINK_TAG(l) | BOARD_CONTROL); usleep_range(2000, 3000); ddbwritel(dev, - info->board_control_2 | info->board_control, - DDB_LINK_TAG(l) | BOARD_CONTROL); + info->board_control_2 | info->board_control, + DDB_LINK_TAG(l) | BOARD_CONTROL); usleep_range(2000, 3000); } ddb_init_tempmon(link); @@ -3598,7 +3295,7 @@ int ddb_init(struct ddb *dev) ddb_init_boards(dev); if (ddb_i2c_init(dev) < 0) - goto fail; + goto fail1; ddb_ports_init(dev); if (ddb_buffers_alloc(dev) < 0) { dev_info(dev->dev, "Could not allocate buffer memory\n"); @@ -3616,14 +3313,14 @@ int ddb_init(struct ddb *dev) return 0; fail3: - ddb_ports_detach(dev); dev_err(dev->dev, "fail3\n"); - ddb_ports_release(dev); + ddb_ports_detach(dev); + ddb_buffers_free(dev); fail2: dev_err(dev->dev, "fail2\n"); - ddb_buffers_free(dev); + ddb_ports_release(dev); ddb_i2c_release(dev); -fail: +fail1: dev_err(dev->dev, "fail1\n"); return -1; } diff --git a/drivers/media/pci/ddbridge/ddbridge-hw.c b/drivers/media/pci/ddbridge/ddbridge-hw.c index 48248bcd59c2..c6d14925e2fc 100644 --- a/drivers/media/pci/ddbridge/ddbridge-hw.c +++ b/drivers/media/pci/ddbridge/ddbridge-hw.c @@ -185,7 +185,7 @@ static const struct ddb_info ddb_ctv7 = { .board_control_2 = 4, }; -static const struct ddb_info ddb_satixS2v3 = { +static const struct ddb_info ddb_satixs2v3 = { .type = DDB_OCTOPUS, .name = "Mystique SaTiX-S2 V3 DVB adapter", .regmap = &octopus_map, @@ -336,7 +336,7 @@ static const struct ddb_device_id ddb_device_ids[] = { DDB_DEVID(0x0006, 0x0022, ddb_v7), DDB_DEVID(0x0006, 0x0024, ddb_v7a), DDB_DEVID(0x0003, 0x0030, ddb_dvbct), - DDB_DEVID(0x0003, 0xdb03, ddb_satixS2v3), + DDB_DEVID(0x0003, 0xdb03, ddb_satixs2v3), DDB_DEVID(0x0006, 0x0031, ddb_ctv7), DDB_DEVID(0x0006, 0x0032, ddb_ctv7), DDB_DEVID(0x0006, 0x0033, ddb_ctv7), @@ -367,8 +367,8 @@ const struct ddb_info *get_ddb_info(u16 vendor, u16 device, if (vendor == id->vendor && device == id->device && subvendor == id->subvendor && - ((subdevice == id->subdevice) || - (id->subdevice == 0xffff))) + (subdevice == id->subdevice || + id->subdevice == 0xffff)) return id->info; } diff --git a/drivers/media/pci/ddbridge/ddbridge-i2c.c b/drivers/media/pci/ddbridge/ddbridge-i2c.c index e4d39c3270ae..82a9a0e806fc 100644 --- a/drivers/media/pci/ddbridge/ddbridge-i2c.c +++ b/drivers/media/pci/ddbridge/ddbridge-i2c.c @@ -81,7 +81,7 @@ static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd) static int ddb_i2c_master_xfer(struct i2c_adapter *adapter, struct i2c_msg msg[], int num) { - struct ddb_i2c *i2c = (struct ddb_i2c *) i2c_get_adapdata(adapter); + struct ddb_i2c *i2c = (struct ddb_i2c *)i2c_get_adapdata(adapter); struct ddb *dev = i2c->dev; u8 addr = 0; @@ -149,7 +149,7 @@ void ddb_i2c_release(struct ddb *dev) static void i2c_handler(unsigned long priv) { - struct ddb_i2c *i2c = (struct ddb_i2c *) priv; + struct ddb_i2c *i2c = (struct ddb_i2c *)priv; complete(&i2c->completion); } @@ -171,20 +171,20 @@ static int ddb_i2c_add(struct ddb *dev, struct ddb_i2c *i2c, (regmap->i2c->base + regmap->i2c->size * i); ddbwritel(dev, I2C_SPEED_100, i2c->regs + I2C_TIMING); ddbwritel(dev, ((i2c->rbuf & 0xffff) << 16) | (i2c->wbuf & 0xffff), - i2c->regs + I2C_TASKADDRESS); + i2c->regs + I2C_TASKADDRESS); init_completion(&i2c->completion); adap = &i2c->adap; i2c_set_adapdata(adap, i2c); #ifdef I2C_ADAP_CLASS_TV_DIGITAL - adap->class = I2C_ADAP_CLASS_TV_DIGITAL|I2C_CLASS_TV_ANALOG; + adap->class = I2C_ADAP_CLASS_TV_DIGITAL | I2C_CLASS_TV_ANALOG; #else #ifdef I2C_CLASS_TV_ANALOG adap->class = I2C_CLASS_TV_ANALOG; #endif #endif snprintf(adap->name, I2C_NAME_SIZE, "ddbridge_%02x.%x.%x", - dev->nr, i2c->link, i); + dev->nr, i2c->link, i); adap->algo = &ddb_i2c_algo; adap->algo_data = (void *)i2c; adap->dev.parent = dev->dev; @@ -210,7 +210,7 @@ int ddb_i2c_init(struct ddb *dev) if (!(dev->link[l].info->i2c_mask & (1 << i))) continue; i2c = &dev->i2c[num]; - dev->handler_data[l][i + base] = (unsigned long) i2c; + dev->handler_data[l][i + base] = (unsigned long)i2c; dev->handler[l][i + base] = i2c_handler; stat = ddb_i2c_add(dev, i2c, regmap, l, i, num); if (stat) @@ -224,7 +224,9 @@ int ddb_i2c_init(struct ddb *dev) adap = &i2c->adap; i2c_del_adapter(adap); } - } else + } else { dev->i2c_num = num; + } + return stat; } diff --git a/drivers/media/pci/ddbridge/ddbridge-main.c b/drivers/media/pci/ddbridge/ddbridge-main.c index ccac7fe31336..26497d6b1395 100644 --- a/drivers/media/pci/ddbridge/ddbridge-main.c +++ b/drivers/media/pci/ddbridge/ddbridge-main.c @@ -107,7 +107,7 @@ static void ddb_irq_exit(struct ddb *dev) static void ddb_remove(struct pci_dev *pdev) { - struct ddb *dev = (struct ddb *) pci_get_drvdata(pdev); + struct ddb *dev = (struct ddb *)pci_get_drvdata(pdev); ddb_device_destroy(dev); ddb_ports_detach(dev); @@ -132,9 +132,10 @@ static void ddb_irq_msi(struct ddb *dev, int nr) if (stat >= 1) { dev->msi = stat; dev_info(dev->dev, "using %d MSI interrupt(s)\n", - dev->msi); - } else + dev->msi); + } else { dev_info(dev->dev, "MSI not available.\n"); + } } } #endif @@ -160,11 +161,11 @@ static int ddb_irq_init(struct ddb *dev) irq_flag = 0; if (dev->msi == 2) { stat = request_irq(dev->pdev->irq, ddb_irq_handler0, - irq_flag, "ddbridge", (void *) dev); + irq_flag, "ddbridge", (void *)dev); if (stat < 0) return stat; stat = request_irq(dev->pdev->irq + 1, ddb_irq_handler1, - irq_flag, "ddbridge", (void *) dev); + irq_flag, "ddbridge", (void *)dev); if (stat < 0) { free_irq(dev->pdev->irq, dev); return stat; @@ -173,7 +174,7 @@ static int ddb_irq_init(struct ddb *dev) #endif { stat = request_irq(dev->pdev->irq, ddb_irq_handler, - irq_flag, "ddbridge", (void *) dev); + irq_flag, "ddbridge", (void *)dev); if (stat < 0) return stat; } @@ -188,7 +189,7 @@ static int ddb_irq_init(struct ddb *dev) } static int ddb_probe(struct pci_dev *pdev, - const struct pci_device_id *id) + const struct pci_device_id *id) { struct ddb *dev; int stat = 0; @@ -202,8 +203,8 @@ static int ddb_probe(struct pci_dev *pdev, if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) return -ENODEV; - dev = vzalloc(sizeof(struct ddb)); - if (dev == NULL) + dev = vzalloc(sizeof(*dev)); + if (!dev) return -ENOMEM; mutex_init(&dev->mutex); @@ -242,7 +243,7 @@ static int ddb_probe(struct pci_dev *pdev, dev->link[0].ids.regmapid = ddbreadl(dev, 4); dev_info(&pdev->dev, "HW %08x REGMAP %08x\n", - dev->link[0].ids.hwid, dev->link[0].ids.regmapid); + dev->link[0].ids.hwid, dev->link[0].ids.regmapid); ddbwritel(dev, 0, DMA_BASE_READ); ddbwritel(dev, 0, DMA_BASE_WRITE); @@ -317,7 +318,7 @@ static __init int module_init_ddbridge(void) if (ddb_class_create() < 0) return -1; ddb_wq = create_workqueue("ddbridge"); - if (ddb_wq == NULL) + if (!ddb_wq) goto exit1; stat = pci_register_driver(&ddb_pci_driver); if (stat < 0) diff --git a/drivers/media/pci/ddbridge/ddbridge-maxs8.c b/drivers/media/pci/ddbridge/ddbridge-max.c index f8a53bc7c86c..dc6b81488746 100644 --- a/drivers/media/pci/ddbridge/ddbridge-maxs8.c +++ b/drivers/media/pci/ddbridge/ddbridge-max.c @@ -1,5 +1,5 @@ /* - * ddbridge-maxs8.c: Digital Devices bridge MaxS4/8 support + * ddbridge-max.c: Digital Devices bridge MAX card support * * Copyright (C) 2010-2017 Digital Devices GmbH * Ralph Metzler <rjkm@metzlerbros.de> @@ -34,7 +34,7 @@ #include "ddbridge-regs.h" #include "ddbridge-io.h" -#include "ddbridge-maxs8.h" +#include "ddbridge-max.h" #include "mxl5xx.h" /******************************************************************************/ @@ -68,7 +68,7 @@ static int lnb_command(struct ddb *dev, u32 link, u32 lnb, u32 cmd) } if (c == 10) dev_info(dev->dev, "%s lnb = %08x cmd = %08x\n", - __func__, lnb, cmd); + __func__, lnb, cmd); return 0; } @@ -123,7 +123,7 @@ static int lnb_set_sat(struct ddb *dev, u32 link, u32 input, u32 sat, u32 band, } static int lnb_set_tone(struct ddb *dev, u32 link, u32 input, - enum fe_sec_tone_mode tone) + enum fe_sec_tone_mode tone) { int s = 0; u32 mask = (1ULL << input); @@ -149,7 +149,7 @@ static int lnb_set_tone(struct ddb *dev, u32 link, u32 input, } static int lnb_set_voltage(struct ddb *dev, u32 link, u32 input, - enum fe_sec_voltage voltage) + enum fe_sec_voltage voltage) { int s = 0; @@ -291,34 +291,45 @@ static int max_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage) if (nv != ov) { if (nv) { - lnb_set_voltage(dev, - port->lnr, 0, SEC_VOLTAGE_13); + lnb_set_voltage( + dev, port->lnr, + 0, SEC_VOLTAGE_13); if (fmode == 1) { - lnb_set_voltage(dev, port->lnr, + lnb_set_voltage( + dev, port->lnr, 0, SEC_VOLTAGE_13); if (old_quattro) { - lnb_set_voltage(dev, port->lnr, + lnb_set_voltage( + dev, port->lnr, 1, SEC_VOLTAGE_18); - lnb_set_voltage(dev, port->lnr, + lnb_set_voltage( + dev, port->lnr, 2, SEC_VOLTAGE_13); } else { - lnb_set_voltage(dev, port->lnr, + lnb_set_voltage( + dev, port->lnr, 1, SEC_VOLTAGE_13); - lnb_set_voltage(dev, port->lnr, + lnb_set_voltage( + dev, port->lnr, 2, SEC_VOLTAGE_18); } - lnb_set_voltage(dev, port->lnr, + lnb_set_voltage( + dev, port->lnr, 3, SEC_VOLTAGE_18); } } else { - lnb_set_voltage(dev, port->lnr, + lnb_set_voltage( + dev, port->lnr, 0, SEC_VOLTAGE_OFF); if (fmode == 1) { - lnb_set_voltage(dev, port->lnr, + lnb_set_voltage( + dev, port->lnr, 1, SEC_VOLTAGE_OFF); - lnb_set_voltage(dev, port->lnr, + lnb_set_voltage( + dev, port->lnr, 2, SEC_VOLTAGE_OFF); - lnb_set_voltage(dev, port->lnr, + lnb_set_voltage( + dev, port->lnr, 3, SEC_VOLTAGE_OFF); } } @@ -331,7 +342,6 @@ static int max_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage) static int max_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg) { - return 0; } @@ -350,7 +360,7 @@ static int mxl_fw_read(void *priv, u8 *buf, u32 len) return ddbridge_flashread(dev, link->nr, buf, 0xc0000, len); } -int lnb_init_fmode(struct ddb *dev, struct ddb_link *link, u32 fm) +int ddb_lnb_init_fmode(struct ddb *dev, struct ddb_link *link, u32 fm) { u32 l = link->nr; @@ -394,7 +404,7 @@ static struct mxl5xx_cfg mxl5xx = { .fw_read = mxl_fw_read, }; -int fe_attach_mxl5xx(struct ddb_input *input) +int ddb_fe_attach_mxl5xx(struct ddb_input *input) { struct ddb *dev = input->port->dev; struct i2c_adapter *i2c = &input->port->i2c->adap; @@ -414,7 +424,7 @@ int fe_attach_mxl5xx(struct ddb_input *input) tuner = 0; dvb->fe = dvb_attach(mxl5xx_attach, i2c, &cfg, - demod, tuner, &dvb->set_input); + demod, tuner, &dvb->set_input); if (!dvb->fe) { dev_err(dev->dev, "No MXL5XX found!\n"); @@ -430,7 +440,7 @@ int fe_attach_mxl5xx(struct ddb_input *input) lnb_command(dev, port->lnr, input->nr, LNB_CMD_INIT); lnb_set_voltage(dev, port->lnr, input->nr, SEC_VOLTAGE_OFF); } - lnb_init_fmode(dev, link, fmode); + ddb_lnb_init_fmode(dev, link, fmode); dvb->fe->ops.set_voltage = max_set_voltage; dvb->fe->ops.enable_high_lnb_voltage = max_enable_high_lnb_voltage; diff --git a/drivers/media/pci/ddbridge/ddbridge-maxs8.h b/drivers/media/pci/ddbridge/ddbridge-max.h index bb8884811a46..bf8bf38739f6 100644 --- a/drivers/media/pci/ddbridge/ddbridge-maxs8.h +++ b/drivers/media/pci/ddbridge/ddbridge-max.h @@ -1,5 +1,5 @@ /* - * ddbridge-maxs8.h: Digital Devices bridge MaxS4/8 support + * ddbridge-max.h: Digital Devices bridge MAX card support * * Copyright (C) 2010-2017 Digital Devices GmbH * Ralph Metzler <rjkm@metzlerbros.de> @@ -16,14 +16,14 @@ * */ -#ifndef _DDBRIDGE_MAXS8_H_ -#define _DDBRIDGE_MAXS8_H_ +#ifndef _DDBRIDGE_MAX_H_ +#define _DDBRIDGE_MAX_H_ #include "ddbridge.h" /******************************************************************************/ -int lnb_init_fmode(struct ddb *dev, struct ddb_link *link, u32 fm); -int fe_attach_mxl5xx(struct ddb_input *input); +int ddb_lnb_init_fmode(struct ddb *dev, struct ddb_link *link, u32 fm); +int ddb_fe_attach_mxl5xx(struct ddb_input *input); -#endif /* _DDBRIDGE_MAXS8_H */ +#endif /* _DDBRIDGE_MAX_H */ diff --git a/drivers/media/pci/ddbridge/ddbridge-regs.h b/drivers/media/pci/ddbridge/ddbridge-regs.h index 9d44f8d3af75..23d74ff83fe4 100644 --- a/drivers/media/pci/ddbridge/ddbridge-regs.h +++ b/drivers/media/pci/ddbridge/ddbridge-regs.h @@ -95,27 +95,27 @@ #define DMA_BASE_WRITE (0x100) #define DMA_BASE_READ (0x140) -#define TS_CONTROL(_io) (_io->regs + 0x00) -#define TS_CONTROL2(_io) (_io->regs + 0x04) +#define TS_CONTROL(_io) ((_io)->regs + 0x00) +#define TS_CONTROL2(_io) ((_io)->regs + 0x04) /* ------------------------------------------------------------------------- */ /* DMA Buffer */ -#define DMA_BUFFER_CONTROL(_dma) (_dma->regs + 0x00) -#define DMA_BUFFER_ACK(_dma) (_dma->regs + 0x04) -#define DMA_BUFFER_CURRENT(_dma) (_dma->regs + 0x08) -#define DMA_BUFFER_SIZE(_dma) (_dma->regs + 0x0c) +#define DMA_BUFFER_CONTROL(_dma) ((_dma)->regs + 0x00) +#define DMA_BUFFER_ACK(_dma) ((_dma)->regs + 0x04) +#define DMA_BUFFER_CURRENT(_dma) ((_dma)->regs + 0x08) +#define DMA_BUFFER_SIZE(_dma) ((_dma)->regs + 0x0c) /* ------------------------------------------------------------------------- */ /* CI Interface (only CI-Bridge) */ -#define CI_BASE (0x400) -#define CI_CONTROL(i) (CI_BASE + (i) * 32 + 0x00) +#define CI_BASE (0x400) +#define CI_CONTROL(i) (CI_BASE + (i) * 32 + 0x00) -#define CI_DO_ATTRIBUTE_RW(i) (CI_BASE + (i) * 32 + 0x04) -#define CI_DO_IO_RW(i) (CI_BASE + (i) * 32 + 0x08) -#define CI_READDATA(i) (CI_BASE + (i) * 32 + 0x0c) -#define CI_DO_READ_ATTRIBUTES(i) (CI_BASE + (i) * 32 + 0x10) +#define CI_DO_ATTRIBUTE_RW(i) (CI_BASE + (i) * 32 + 0x04) +#define CI_DO_IO_RW(i) (CI_BASE + (i) * 32 + 0x08) +#define CI_READDATA(i) (CI_BASE + (i) * 32 + 0x0c) +#define CI_DO_READ_ATTRIBUTES(i) (CI_BASE + (i) * 32 + 0x10) #define CI_RESET_CAM (0x00000001) #define CI_POWER_ON (0x00000002) @@ -132,7 +132,7 @@ #define CI_BUFFER_BASE (0x3000) #define CI_BUFFER_SIZE (0x0800) -#define CI_BUFFER(i) (CI_BUFFER_BASE + (i) * CI_BUFFER_SIZE) +#define CI_BUFFER(i) (CI_BUFFER_BASE + (i) * CI_BUFFER_SIZE) /* ------------------------------------------------------------------------- */ /* LNB commands (mxl5xx / Max S8) */ @@ -140,7 +140,7 @@ #define LNB_BASE (0x400) #define LNB_CONTROL(i) (LNB_BASE + (i) * 0x20 + 0x00) -#define LNB_CMD (7ULL << 0) +#define LNB_CMD (7ULL << 0) #define LNB_CMD_NOP 0 #define LNB_CMD_INIT 1 #define LNB_CMD_LOW 3 @@ -148,8 +148,8 @@ #define LNB_CMD_OFF 5 #define LNB_CMD_DISEQC 6 -#define LNB_BUSY (1ULL << 4) -#define LNB_TONE (1ULL << 15) +#define LNB_BUSY BIT_ULL(4) +#define LNB_TONE BIT_ULL(15) #define LNB_BUF_LEVEL(i) (LNB_BASE + (i) * 0x20 + 0x10) #define LNB_BUF_WRITE(i) (LNB_BASE + (i) * 0x20 + 0x14) diff --git a/drivers/media/pci/ddbridge/ddbridge.h b/drivers/media/pci/ddbridge/ddbridge.h index e9afa96bd9df..095457737bc1 100644 --- a/drivers/media/pci/ddbridge/ddbridge.h +++ b/drivers/media/pci/ddbridge/ddbridge.h @@ -55,15 +55,15 @@ #include <linux/device.h> #include <linux/io.h> -#include "dmxdev.h" -#include "dvbdev.h" -#include "dvb_demux.h" -#include "dvb_frontend.h" -#include "dvb_ringbuffer.h" -#include "dvb_ca_en50221.h" -#include "dvb_net.h" +#include <media/dmxdev.h> +#include <media/dvbdev.h> +#include <media/dvb_demux.h> +#include <media/dvb_frontend.h> +#include <media/dvb_ringbuffer.h> +#include <media/dvb_ca_en50221.h> +#include <media/dvb_net.h> -#define DDBRIDGE_VERSION "0.9.31intermediate-integrated" +#define DDBRIDGE_VERSION "0.9.32-integrated" #define DDB_MAX_I2C 32 #define DDB_MAX_PORT 32 @@ -143,11 +143,11 @@ struct ddb_info { #define DMA_MAX_BUFS 32 /* hardware table limit */ #define INPUT_DMA_BUFS 8 -#define INPUT_DMA_SIZE (128*47*21) +#define INPUT_DMA_SIZE (128 * 47 * 21) #define INPUT_DMA_IRQ_DIV 1 #define OUTPUT_DMA_BUFS 8 -#define OUTPUT_DMA_SIZE (128*47*21) +#define OUTPUT_DMA_SIZE (128 * 47 * 21) #define OUTPUT_DMA_IRQ_DIV 1 struct ddb; @@ -166,7 +166,7 @@ struct ddb_dma { u32 bufval; struct work_struct work; - spinlock_t lock; + spinlock_t lock; /* DMA lock */ wait_queue_head_t wq; int running; u32 stat; @@ -196,17 +196,16 @@ struct ddb_dvb { int (*i2c_gate_ctrl)(struct dvb_frontend *, int); int (*set_voltage)(struct dvb_frontend *fe, - enum fe_sec_voltage voltage); + enum fe_sec_voltage voltage); int (*set_input)(struct dvb_frontend *fe, int input); int (*diseqc_send_master_cmd)(struct dvb_frontend *fe, - struct dvb_diseqc_master_cmd *cmd); + struct dvb_diseqc_master_cmd *cmd); }; struct ddb_ci { struct dvb_ca_en50221 en; struct ddb_port *port; u32 nr; - struct mutex lock; }; struct ddb_io { @@ -240,7 +239,7 @@ struct ddb_port { u32 regs; u32 lnr; struct ddb_i2c *i2c; - struct mutex i2c_gate_lock; + struct mutex i2c_gate_lock; /* I2C access lock */ u32 class; #define DDB_PORT_NONE 0 #define DDB_PORT_CI 1 @@ -297,7 +296,7 @@ struct ddb_port { #define TS_CAPTURE_LEN (4096) struct ddb_lnb { - struct mutex lock; + struct mutex lock; /* lock lnb access */ u32 tone; enum fe_sec_voltage oldvoltage[4]; u32 voltage[4]; @@ -310,54 +309,54 @@ struct ddb_link { const struct ddb_info *info; u32 nr; u32 regs; - spinlock_t lock; - struct mutex flash_mutex; + spinlock_t lock; /* lock link access */ + struct mutex flash_mutex; /* lock flash access */ struct ddb_lnb lnb; struct tasklet_struct tasklet; struct ddb_ids ids; - spinlock_t temp_lock; + spinlock_t temp_lock; /* lock temp chip access */ int overtemperature_error; u8 temp_tab[11]; }; struct ddb { - struct pci_dev *pdev; - struct platform_device *pfdev; - struct device *dev; + struct pci_dev *pdev; + struct platform_device *pfdev; + struct device *dev; - int msi; + int msi; struct workqueue_struct *wq; - u32 has_dma; - - struct ddb_link link[DDB_MAX_LINK]; - unsigned char __iomem *regs; - u32 regs_len; - u32 port_num; - struct ddb_port port[DDB_MAX_PORT]; - u32 i2c_num; - struct ddb_i2c i2c[DDB_MAX_I2C]; - struct ddb_input input[DDB_MAX_INPUT]; - struct ddb_output output[DDB_MAX_OUTPUT]; - struct dvb_adapter adap[DDB_MAX_INPUT]; - struct ddb_dma idma[DDB_MAX_INPUT]; - struct ddb_dma odma[DDB_MAX_OUTPUT]; - - void (*handler[4][256])(unsigned long); - unsigned long handler_data[4][256]; - - struct device *ddb_dev; - u32 ddb_dev_users; - u32 nr; - u8 iobuf[1028]; - - u8 leds; - u32 ts_irq; - u32 i2c_irq; - - struct mutex mutex; - - u8 tsbuf[TS_CAPTURE_LEN]; + u32 has_dma; + + struct ddb_link link[DDB_MAX_LINK]; + unsigned char __iomem *regs; + u32 regs_len; + u32 port_num; + struct ddb_port port[DDB_MAX_PORT]; + u32 i2c_num; + struct ddb_i2c i2c[DDB_MAX_I2C]; + struct ddb_input input[DDB_MAX_INPUT]; + struct ddb_output output[DDB_MAX_OUTPUT]; + struct dvb_adapter adap[DDB_MAX_INPUT]; + struct ddb_dma idma[DDB_MAX_INPUT]; + struct ddb_dma odma[DDB_MAX_OUTPUT]; + + void (*handler[4][256])(unsigned long); + unsigned long handler_data[4][256]; + + struct device *ddb_dev; + u32 ddb_dev_users; + u32 nr; + u8 iobuf[1028]; + + u8 leds; + u32 ts_irq; + u32 i2c_irq; + + struct mutex mutex; /* lock access to global ddb array */ + + u8 tsbuf[TS_CAPTURE_LEN]; }; /****************************************************************************/ diff --git a/drivers/media/pci/dm1105/Makefile b/drivers/media/pci/dm1105/Makefile index 327585143c83..d22c2547ee86 100644 --- a/drivers/media/pci/dm1105/Makefile +++ b/drivers/media/pci/dm1105/Makefile @@ -1,3 +1,3 @@ obj-$(CONFIG_DVB_DM1105) += dm1105.o -ccflags-y += -Idrivers/media/dvb-core/ -Idrivers/media/dvb-frontends +ccflags-y += -Idrivers/media/dvb-frontends diff --git a/drivers/media/pci/dm1105/dm1105.c b/drivers/media/pci/dm1105/dm1105.c index 7c3900dec368..c9db108751a7 100644 --- a/drivers/media/pci/dm1105/dm1105.c +++ b/drivers/media/pci/dm1105/dm1105.c @@ -27,12 +27,12 @@ #include <linux/slab.h> #include <media/rc-core.h> -#include "demux.h" -#include "dmxdev.h" -#include "dvb_demux.h" -#include "dvb_frontend.h" -#include "dvb_net.h" -#include "dvbdev.h" +#include <media/demux.h> +#include <media/dmxdev.h> +#include <media/dvb_demux.h> +#include <media/dvb_frontend.h> +#include <media/dvb_net.h> +#include <media/dvbdev.h> #include "dvb-pll.h" #include "stv0299.h" diff --git a/drivers/media/pci/intel/Makefile b/drivers/media/pci/intel/Makefile new file mode 100644 index 000000000000..745c8b2a7819 --- /dev/null +++ b/drivers/media/pci/intel/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for the IPU3 cio2 and ImGU drivers +# + +obj-y += ipu3/ diff --git a/drivers/media/pci/intel/ipu3/Kconfig b/drivers/media/pci/intel/ipu3/Kconfig new file mode 100644 index 000000000000..a82d3fe277d2 --- /dev/null +++ b/drivers/media/pci/intel/ipu3/Kconfig @@ -0,0 +1,19 @@ +config VIDEO_IPU3_CIO2 + tristate "Intel ipu3-cio2 driver" + depends on VIDEO_V4L2 && PCI + depends on VIDEO_V4L2_SUBDEV_API + depends on X86 || COMPILE_TEST + depends on MEDIA_CONTROLLER + depends on HAS_DMA + depends on ACPI + select V4L2_FWNODE + select VIDEOBUF2_DMA_SG + + ---help--- + This is the Intel IPU3 CIO2 CSI-2 receiver unit, found in Intel + Skylake and Kaby Lake SoCs and used for capturing images and + video from a camera sensor. + + Say Y or M here if you have a Skylake/Kaby Lake SoC with MIPI CSI-2 + connected camera. + The module will be called ipu3-cio2. diff --git a/drivers/media/pci/intel/ipu3/Makefile b/drivers/media/pci/intel/ipu3/Makefile new file mode 100644 index 000000000000..20186e3ff2ae --- /dev/null +++ b/drivers/media/pci/intel/ipu3/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_VIDEO_IPU3_CIO2) += ipu3-cio2.o diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2.c new file mode 100644 index 000000000000..941caa987dab --- /dev/null +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.c @@ -0,0 +1,2048 @@ +/* + * Copyright (c) 2017 Intel Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Based partially on Intel IPU4 driver written by + * Sakari Ailus <sakari.ailus@linux.intel.com> + * Samu Onkalo <samu.onkalo@intel.com> + * Jouni Högander <jouni.hogander@intel.com> + * Jouni Ukkonen <jouni.ukkonen@intel.com> + * Antti Laakso <antti.laakso@intel.com> + * et al. + * + */ + +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/pm_runtime.h> +#include <linux/property.h> +#include <linux/vmalloc.h> +#include <media/v4l2-ctrls.h> +#include <media/v4l2-device.h> +#include <media/v4l2-event.h> +#include <media/v4l2-fwnode.h> +#include <media/v4l2-ioctl.h> +#include <media/videobuf2-dma-sg.h> + +#include "ipu3-cio2.h" + +struct ipu3_cio2_fmt { + u32 mbus_code; + u32 fourcc; + u8 mipicode; +}; + +/* + * These are raw formats used in Intel's third generation of + * Image Processing Unit known as IPU3. + * 10bit raw bayer packed, 32 bytes for every 25 pixels, + * last LSB 6 bits unused. + */ +static const struct ipu3_cio2_fmt formats[] = { + { /* put default entry at beginning */ + .mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10, + .fourcc = V4L2_PIX_FMT_IPU3_SGRBG10, + .mipicode = 0x2b, + }, { + .mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10, + .fourcc = V4L2_PIX_FMT_IPU3_SGBRG10, + .mipicode = 0x2b, + }, { + .mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10, + .fourcc = V4L2_PIX_FMT_IPU3_SBGGR10, + .mipicode = 0x2b, + }, { + .mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10, + .fourcc = V4L2_PIX_FMT_IPU3_SRGGB10, + .mipicode = 0x2b, + }, +}; + +/* + * cio2_find_format - lookup color format by fourcc or/and media bus code + * @pixelformat: fourcc to match, ignored if null + * @mbus_code: media bus code to match, ignored if null + */ +static const struct ipu3_cio2_fmt *cio2_find_format(const u32 *pixelformat, + const u32 *mbus_code) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(formats); i++) { + if (pixelformat && *pixelformat != formats[i].fourcc) + continue; + if (mbus_code && *mbus_code != formats[i].mbus_code) + continue; + + return &formats[i]; + } + + return NULL; +} + +static inline u32 cio2_bytesperline(const unsigned int width) +{ + /* + * 64 bytes for every 50 pixels, the line length + * in bytes is multiple of 64 (line end alignment). + */ + return DIV_ROUND_UP(width, 50) * 64; +} + +/**************** FBPT operations ****************/ + +static void cio2_fbpt_exit_dummy(struct cio2_device *cio2) +{ + if (cio2->dummy_lop) { + dma_free_coherent(&cio2->pci_dev->dev, CIO2_PAGE_SIZE, + cio2->dummy_lop, cio2->dummy_lop_bus_addr); + cio2->dummy_lop = NULL; + } + if (cio2->dummy_page) { + dma_free_coherent(&cio2->pci_dev->dev, CIO2_PAGE_SIZE, + cio2->dummy_page, cio2->dummy_page_bus_addr); + cio2->dummy_page = NULL; + } +} + +static int cio2_fbpt_init_dummy(struct cio2_device *cio2) +{ + unsigned int i; + + cio2->dummy_page = dma_alloc_coherent(&cio2->pci_dev->dev, + CIO2_PAGE_SIZE, + &cio2->dummy_page_bus_addr, + GFP_KERNEL); + cio2->dummy_lop = dma_alloc_coherent(&cio2->pci_dev->dev, + CIO2_PAGE_SIZE, + &cio2->dummy_lop_bus_addr, + GFP_KERNEL); + if (!cio2->dummy_page || !cio2->dummy_lop) { + cio2_fbpt_exit_dummy(cio2); + return -ENOMEM; + } + /* + * List of Pointers(LOP) contains 1024x32b pointers to 4KB page each + * Initialize each entry to dummy_page bus base address. + */ + for (i = 0; i < CIO2_PAGE_SIZE / sizeof(*cio2->dummy_lop); i++) + cio2->dummy_lop[i] = cio2->dummy_page_bus_addr >> PAGE_SHIFT; + + return 0; +} + +static void cio2_fbpt_entry_enable(struct cio2_device *cio2, + struct cio2_fbpt_entry entry[CIO2_MAX_LOPS]) +{ + /* + * The CPU first initializes some fields in fbpt, then sets + * the VALID bit, this barrier is to ensure that the DMA(device) + * does not see the VALID bit enabled before other fields are + * initialized; otherwise it could lead to havoc. + */ + dma_wmb(); + + /* + * Request interrupts for start and completion + * Valid bit is applicable only to 1st entry + */ + entry[0].first_entry.ctrl = CIO2_FBPT_CTRL_VALID | + CIO2_FBPT_CTRL_IOC | CIO2_FBPT_CTRL_IOS; +} + +/* Initialize fpbt entries to point to dummy frame */ +static void cio2_fbpt_entry_init_dummy(struct cio2_device *cio2, + struct cio2_fbpt_entry + entry[CIO2_MAX_LOPS]) +{ + unsigned int i; + + entry[0].first_entry.first_page_offset = 0; + entry[1].second_entry.num_of_pages = + CIO2_PAGE_SIZE / sizeof(u32) * CIO2_MAX_LOPS; + entry[1].second_entry.last_page_available_bytes = CIO2_PAGE_SIZE - 1; + + for (i = 0; i < CIO2_MAX_LOPS; i++) + entry[i].lop_page_addr = cio2->dummy_lop_bus_addr >> PAGE_SHIFT; + + cio2_fbpt_entry_enable(cio2, entry); +} + +/* Initialize fpbt entries to point to a given buffer */ +static void cio2_fbpt_entry_init_buf(struct cio2_device *cio2, + struct cio2_buffer *b, + struct cio2_fbpt_entry + entry[CIO2_MAX_LOPS]) +{ + struct vb2_buffer *vb = &b->vbb.vb2_buf; + unsigned int length = vb->planes[0].length; + int remaining, i; + + entry[0].first_entry.first_page_offset = b->offset; + remaining = length + entry[0].first_entry.first_page_offset; + entry[1].second_entry.num_of_pages = + DIV_ROUND_UP(remaining, CIO2_PAGE_SIZE); + /* + * last_page_available_bytes has the offset of the last byte in the + * last page which is still accessible by DMA. DMA cannot access + * beyond this point. Valid range for this is from 0 to 4095. + * 0 indicates 1st byte in the page is DMA accessible. + * 4095 (CIO2_PAGE_SIZE - 1) means every single byte in the last page + * is available for DMA transfer. + */ + entry[1].second_entry.last_page_available_bytes = + (remaining & ~PAGE_MASK) ? + (remaining & ~PAGE_MASK) - 1 : + CIO2_PAGE_SIZE - 1; + /* Fill FBPT */ + remaining = length; + i = 0; + while (remaining > 0) { + entry->lop_page_addr = b->lop_bus_addr[i] >> PAGE_SHIFT; + remaining -= CIO2_PAGE_SIZE / sizeof(u32) * CIO2_PAGE_SIZE; + entry++; + i++; + } + + /* + * The first not meaningful FBPT entry should point to a valid LOP + */ + entry->lop_page_addr = cio2->dummy_lop_bus_addr >> PAGE_SHIFT; + + cio2_fbpt_entry_enable(cio2, entry); +} + +static int cio2_fbpt_init(struct cio2_device *cio2, struct cio2_queue *q) +{ + struct device *dev = &cio2->pci_dev->dev; + + q->fbpt = dma_alloc_coherent(dev, CIO2_FBPT_SIZE, &q->fbpt_bus_addr, + GFP_KERNEL); + if (!q->fbpt) + return -ENOMEM; + + memset(q->fbpt, 0, CIO2_FBPT_SIZE); + + return 0; +} + +static void cio2_fbpt_exit(struct cio2_queue *q, struct device *dev) +{ + dma_free_coherent(dev, CIO2_FBPT_SIZE, q->fbpt, q->fbpt_bus_addr); +} + +/**************** CSI2 hardware setup ****************/ + +/* + * The CSI2 receiver has several parameters affecting + * the receiver timings. These depend on the MIPI bus frequency + * F in Hz (sensor transmitter rate) as follows: + * register value = (A/1e9 + B * UI) / COUNT_ACC + * where + * UI = 1 / (2 * F) in seconds + * COUNT_ACC = counter accuracy in seconds + * For IPU3 COUNT_ACC = 0.0625 + * + * A and B are coefficients from the table below, + * depending whether the register minimum or maximum value is + * calculated. + * Minimum Maximum + * Clock lane A B A B + * reg_rx_csi_dly_cnt_termen_clane 0 0 38 0 + * reg_rx_csi_dly_cnt_settle_clane 95 -8 300 -16 + * Data lanes + * reg_rx_csi_dly_cnt_termen_dlane0 0 0 35 4 + * reg_rx_csi_dly_cnt_settle_dlane0 85 -2 145 -6 + * reg_rx_csi_dly_cnt_termen_dlane1 0 0 35 4 + * reg_rx_csi_dly_cnt_settle_dlane1 85 -2 145 -6 + * reg_rx_csi_dly_cnt_termen_dlane2 0 0 35 4 + * reg_rx_csi_dly_cnt_settle_dlane2 85 -2 145 -6 + * reg_rx_csi_dly_cnt_termen_dlane3 0 0 35 4 + * reg_rx_csi_dly_cnt_settle_dlane3 85 -2 145 -6 + * + * We use the minimum values of both A and B. + */ + +/* + * shift for keeping value range suitable for 32-bit integer arithmetics + */ +#define LIMIT_SHIFT 8 + +static s32 cio2_rx_timing(s32 a, s32 b, s64 freq, int def) +{ + const u32 accinv = 16; /* invert of counter resolution */ + const u32 uiinv = 500000000; /* 1e9 / 2 */ + s32 r; + + freq >>= LIMIT_SHIFT; + + if (WARN_ON(freq <= 0 || freq > S32_MAX)) + return def; + /* + * b could be 0, -2 or -8, so |accinv * b| is always + * less than (1 << ds) and thus |r| < 500000000. + */ + r = accinv * b * (uiinv >> LIMIT_SHIFT); + r = r / (s32)freq; + /* max value of a is 95 */ + r += accinv * a; + + return r; +}; + +/* Calculate the the delay value for termination enable of clock lane HS Rx */ +static int cio2_csi2_calc_timing(struct cio2_device *cio2, struct cio2_queue *q, + struct cio2_csi2_timing *timing) +{ + struct device *dev = &cio2->pci_dev->dev; + struct v4l2_querymenu qm = {.id = V4L2_CID_LINK_FREQ, }; + struct v4l2_ctrl *link_freq; + s64 freq; + int r; + + if (!q->sensor) + return -ENODEV; + + link_freq = v4l2_ctrl_find(q->sensor->ctrl_handler, V4L2_CID_LINK_FREQ); + if (!link_freq) { + dev_err(dev, "failed to find LINK_FREQ\n"); + return -EPIPE; + } + + qm.index = v4l2_ctrl_g_ctrl(link_freq); + r = v4l2_querymenu(q->sensor->ctrl_handler, &qm); + if (r) { + dev_err(dev, "failed to get menu item\n"); + return r; + } + + if (!qm.value) { + dev_err(dev, "error invalid link_freq\n"); + return -EINVAL; + } + freq = qm.value; + + timing->clk_termen = cio2_rx_timing(CIO2_CSIRX_DLY_CNT_TERMEN_CLANE_A, + CIO2_CSIRX_DLY_CNT_TERMEN_CLANE_B, + freq, + CIO2_CSIRX_DLY_CNT_TERMEN_DEFAULT); + timing->clk_settle = cio2_rx_timing(CIO2_CSIRX_DLY_CNT_SETTLE_CLANE_A, + CIO2_CSIRX_DLY_CNT_SETTLE_CLANE_B, + freq, + CIO2_CSIRX_DLY_CNT_SETTLE_DEFAULT); + timing->dat_termen = cio2_rx_timing(CIO2_CSIRX_DLY_CNT_TERMEN_DLANE_A, + CIO2_CSIRX_DLY_CNT_TERMEN_DLANE_B, + freq, + CIO2_CSIRX_DLY_CNT_TERMEN_DEFAULT); + timing->dat_settle = cio2_rx_timing(CIO2_CSIRX_DLY_CNT_SETTLE_DLANE_A, + CIO2_CSIRX_DLY_CNT_SETTLE_DLANE_B, + freq, + CIO2_CSIRX_DLY_CNT_SETTLE_DEFAULT); + + dev_dbg(dev, "freq ct value is %d\n", timing->clk_termen); + dev_dbg(dev, "freq cs value is %d\n", timing->clk_settle); + dev_dbg(dev, "freq dt value is %d\n", timing->dat_termen); + dev_dbg(dev, "freq ds value is %d\n", timing->dat_settle); + + return 0; +}; + +static int cio2_hw_init(struct cio2_device *cio2, struct cio2_queue *q) +{ + static const int NUM_VCS = 4; + static const int SID; /* Stream id */ + static const int ENTRY; + static const int FBPT_WIDTH = DIV_ROUND_UP(CIO2_MAX_LOPS, + CIO2_FBPT_SUBENTRY_UNIT); + const u32 num_buffers1 = CIO2_MAX_BUFFERS - 1; + const struct ipu3_cio2_fmt *fmt; + void __iomem *const base = cio2->base; + u8 lanes, csi2bus = q->csi2.port; + u8 sensor_vc = SENSOR_VIR_CH_DFLT; + struct cio2_csi2_timing timing; + int i, r; + + fmt = cio2_find_format(NULL, &q->subdev_fmt.code); + if (!fmt) + return -EINVAL; + + lanes = q->csi2.lanes; + + r = cio2_csi2_calc_timing(cio2, q, &timing); + if (r) + return r; + + writel(timing.clk_termen, q->csi_rx_base + + CIO2_REG_CSIRX_DLY_CNT_TERMEN(CIO2_CSIRX_DLY_CNT_CLANE_IDX)); + writel(timing.clk_settle, q->csi_rx_base + + CIO2_REG_CSIRX_DLY_CNT_SETTLE(CIO2_CSIRX_DLY_CNT_CLANE_IDX)); + + for (i = 0; i < lanes; i++) { + writel(timing.dat_termen, q->csi_rx_base + + CIO2_REG_CSIRX_DLY_CNT_TERMEN(i)); + writel(timing.dat_settle, q->csi_rx_base + + CIO2_REG_CSIRX_DLY_CNT_SETTLE(i)); + } + + writel(CIO2_PBM_WMCTRL1_MIN_2CK | + CIO2_PBM_WMCTRL1_MID1_2CK | + CIO2_PBM_WMCTRL1_MID2_2CK, base + CIO2_REG_PBM_WMCTRL1); + writel(CIO2_PBM_WMCTRL2_HWM_2CK << CIO2_PBM_WMCTRL2_HWM_2CK_SHIFT | + CIO2_PBM_WMCTRL2_LWM_2CK << CIO2_PBM_WMCTRL2_LWM_2CK_SHIFT | + CIO2_PBM_WMCTRL2_OBFFWM_2CK << + CIO2_PBM_WMCTRL2_OBFFWM_2CK_SHIFT | + CIO2_PBM_WMCTRL2_TRANSDYN << CIO2_PBM_WMCTRL2_TRANSDYN_SHIFT | + CIO2_PBM_WMCTRL2_OBFF_MEM_EN, base + CIO2_REG_PBM_WMCTRL2); + writel(CIO2_PBM_ARB_CTRL_LANES_DIV << + CIO2_PBM_ARB_CTRL_LANES_DIV_SHIFT | + CIO2_PBM_ARB_CTRL_LE_EN | + CIO2_PBM_ARB_CTRL_PLL_POST_SHTDN << + CIO2_PBM_ARB_CTRL_PLL_POST_SHTDN_SHIFT | + CIO2_PBM_ARB_CTRL_PLL_AHD_WK_UP << + CIO2_PBM_ARB_CTRL_PLL_AHD_WK_UP_SHIFT, + base + CIO2_REG_PBM_ARB_CTRL); + writel(CIO2_CSIRX_STATUS_DLANE_HS_MASK, + q->csi_rx_base + CIO2_REG_CSIRX_STATUS_DLANE_HS); + writel(CIO2_CSIRX_STATUS_DLANE_LP_MASK, + q->csi_rx_base + CIO2_REG_CSIRX_STATUS_DLANE_LP); + + writel(CIO2_FB_HPLL_FREQ, base + CIO2_REG_FB_HPLL_FREQ); + writel(CIO2_ISCLK_RATIO, base + CIO2_REG_ISCLK_RATIO); + + /* Configure MIPI backend */ + for (i = 0; i < NUM_VCS; i++) + writel(1, q->csi_rx_base + CIO2_REG_MIPIBE_SP_LUT_ENTRY(i)); + + /* There are 16 short packet LUT entry */ + for (i = 0; i < 16; i++) + writel(CIO2_MIPIBE_LP_LUT_ENTRY_DISREGARD, + q->csi_rx_base + CIO2_REG_MIPIBE_LP_LUT_ENTRY(i)); + writel(CIO2_MIPIBE_GLOBAL_LUT_DISREGARD, + q->csi_rx_base + CIO2_REG_MIPIBE_GLOBAL_LUT_DISREGARD); + + writel(CIO2_INT_EN_EXT_IE_MASK, base + CIO2_REG_INT_EN_EXT_IE); + writel(CIO2_IRQCTRL_MASK, q->csi_rx_base + CIO2_REG_IRQCTRL_MASK); + writel(CIO2_IRQCTRL_MASK, q->csi_rx_base + CIO2_REG_IRQCTRL_ENABLE); + writel(0, q->csi_rx_base + CIO2_REG_IRQCTRL_EDGE); + writel(0, q->csi_rx_base + CIO2_REG_IRQCTRL_LEVEL_NOT_PULSE); + writel(CIO2_INT_EN_EXT_OE_MASK, base + CIO2_REG_INT_EN_EXT_OE); + + writel(CIO2_REG_INT_EN_IRQ | CIO2_INT_IOC(CIO2_DMA_CHAN) | + CIO2_REG_INT_EN_IOS(CIO2_DMA_CHAN), + base + CIO2_REG_INT_EN); + + writel((CIO2_PXM_PXF_FMT_CFG_BPP_10 | CIO2_PXM_PXF_FMT_CFG_PCK_64B) + << CIO2_PXM_PXF_FMT_CFG_SID0_SHIFT, + base + CIO2_REG_PXM_PXF_FMT_CFG0(csi2bus)); + writel(SID << CIO2_MIPIBE_LP_LUT_ENTRY_SID_SHIFT | + sensor_vc << CIO2_MIPIBE_LP_LUT_ENTRY_VC_SHIFT | + fmt->mipicode << CIO2_MIPIBE_LP_LUT_ENTRY_FORMAT_TYPE_SHIFT, + q->csi_rx_base + CIO2_REG_MIPIBE_LP_LUT_ENTRY(ENTRY)); + writel(0, q->csi_rx_base + CIO2_REG_MIPIBE_COMP_FORMAT(sensor_vc)); + writel(0, q->csi_rx_base + CIO2_REG_MIPIBE_FORCE_RAW8); + writel(0, base + CIO2_REG_PXM_SID2BID0(csi2bus)); + + writel(lanes, q->csi_rx_base + CIO2_REG_CSIRX_NOF_ENABLED_LANES); + writel(CIO2_CGC_PRIM_TGE | + CIO2_CGC_SIDE_TGE | + CIO2_CGC_XOSC_TGE | + CIO2_CGC_D3I3_TGE | + CIO2_CGC_CSI2_INTERFRAME_TGE | + CIO2_CGC_CSI2_PORT_DCGE | + CIO2_CGC_SIDE_DCGE | + CIO2_CGC_PRIM_DCGE | + CIO2_CGC_ROSC_DCGE | + CIO2_CGC_XOSC_DCGE | + CIO2_CGC_CLKGATE_HOLDOFF << CIO2_CGC_CLKGATE_HOLDOFF_SHIFT | + CIO2_CGC_CSI_CLKGATE_HOLDOFF + << CIO2_CGC_CSI_CLKGATE_HOLDOFF_SHIFT, base + CIO2_REG_CGC); + writel(CIO2_LTRCTRL_LTRDYNEN, base + CIO2_REG_LTRCTRL); + writel(CIO2_LTRVAL0_VAL << CIO2_LTRVAL02_VAL_SHIFT | + CIO2_LTRVAL0_SCALE << CIO2_LTRVAL02_SCALE_SHIFT | + CIO2_LTRVAL1_VAL << CIO2_LTRVAL13_VAL_SHIFT | + CIO2_LTRVAL1_SCALE << CIO2_LTRVAL13_SCALE_SHIFT, + base + CIO2_REG_LTRVAL01); + writel(CIO2_LTRVAL2_VAL << CIO2_LTRVAL02_VAL_SHIFT | + CIO2_LTRVAL2_SCALE << CIO2_LTRVAL02_SCALE_SHIFT | + CIO2_LTRVAL3_VAL << CIO2_LTRVAL13_VAL_SHIFT | + CIO2_LTRVAL3_SCALE << CIO2_LTRVAL13_SCALE_SHIFT, + base + CIO2_REG_LTRVAL23); + + for (i = 0; i < CIO2_NUM_DMA_CHAN; i++) { + writel(0, base + CIO2_REG_CDMABA(i)); + writel(0, base + CIO2_REG_CDMAC0(i)); + writel(0, base + CIO2_REG_CDMAC1(i)); + } + + /* Enable DMA */ + writel(q->fbpt_bus_addr >> PAGE_SHIFT, + base + CIO2_REG_CDMABA(CIO2_DMA_CHAN)); + + writel(num_buffers1 << CIO2_CDMAC0_FBPT_LEN_SHIFT | + FBPT_WIDTH << CIO2_CDMAC0_FBPT_WIDTH_SHIFT | + CIO2_CDMAC0_DMA_INTR_ON_FE | + CIO2_CDMAC0_FBPT_UPDATE_FIFO_FULL | + CIO2_CDMAC0_DMA_EN | + CIO2_CDMAC0_DMA_INTR_ON_FS | + CIO2_CDMAC0_DMA_HALTED, base + CIO2_REG_CDMAC0(CIO2_DMA_CHAN)); + + writel(1 << CIO2_CDMAC1_LINENUMUPDATE_SHIFT, + base + CIO2_REG_CDMAC1(CIO2_DMA_CHAN)); + + writel(0, base + CIO2_REG_PBM_FOPN_ABORT); + + writel(CIO2_PXM_FRF_CFG_CRC_TH << CIO2_PXM_FRF_CFG_CRC_TH_SHIFT | + CIO2_PXM_FRF_CFG_MSK_ECC_DPHY_NR | + CIO2_PXM_FRF_CFG_MSK_ECC_RE | + CIO2_PXM_FRF_CFG_MSK_ECC_DPHY_NE, + base + CIO2_REG_PXM_FRF_CFG(q->csi2.port)); + + /* Clear interrupts */ + writel(CIO2_IRQCTRL_MASK, q->csi_rx_base + CIO2_REG_IRQCTRL_CLEAR); + writel(~0, base + CIO2_REG_INT_STS_EXT_OE); + writel(~0, base + CIO2_REG_INT_STS_EXT_IE); + writel(~0, base + CIO2_REG_INT_STS); + + /* Enable devices, starting from the last device in the pipe */ + writel(1, q->csi_rx_base + CIO2_REG_MIPIBE_ENABLE); + writel(1, q->csi_rx_base + CIO2_REG_CSIRX_ENABLE); + + return 0; +} + +static void cio2_hw_exit(struct cio2_device *cio2, struct cio2_queue *q) +{ + void __iomem *base = cio2->base; + unsigned int i, maxloops = 1000; + + /* Disable CSI receiver and MIPI backend devices */ + writel(0, q->csi_rx_base + CIO2_REG_CSIRX_ENABLE); + writel(0, q->csi_rx_base + CIO2_REG_MIPIBE_ENABLE); + + /* Halt DMA */ + writel(0, base + CIO2_REG_CDMAC0(CIO2_DMA_CHAN)); + do { + if (readl(base + CIO2_REG_CDMAC0(CIO2_DMA_CHAN)) & + CIO2_CDMAC0_DMA_HALTED) + break; + usleep_range(1000, 2000); + } while (--maxloops); + if (!maxloops) + dev_err(&cio2->pci_dev->dev, + "DMA %i can not be halted\n", CIO2_DMA_CHAN); + + for (i = 0; i < CIO2_NUM_PORTS; i++) { + writel(readl(base + CIO2_REG_PXM_FRF_CFG(i)) | + CIO2_PXM_FRF_CFG_ABORT, base + CIO2_REG_PXM_FRF_CFG(i)); + writel(readl(base + CIO2_REG_PBM_FOPN_ABORT) | + CIO2_PBM_FOPN_ABORT(i), base + CIO2_REG_PBM_FOPN_ABORT); + } +} + +static void cio2_buffer_done(struct cio2_device *cio2, unsigned int dma_chan) +{ + struct device *dev = &cio2->pci_dev->dev; + struct cio2_queue *q = cio2->cur_queue; + int buffers_found = 0; + u64 ns = ktime_get_ns(); + + if (dma_chan >= CIO2_QUEUES) { + dev_err(dev, "bad DMA channel %i\n", dma_chan); + return; + } + + /* Find out which buffer(s) are ready */ + do { + struct cio2_fbpt_entry *const entry = + &q->fbpt[q->bufs_first * CIO2_MAX_LOPS]; + struct cio2_buffer *b; + + if (entry->first_entry.ctrl & CIO2_FBPT_CTRL_VALID) + break; + + b = q->bufs[q->bufs_first]; + if (b) { + unsigned int bytes = entry[1].second_entry.num_of_bytes; + + q->bufs[q->bufs_first] = NULL; + atomic_dec(&q->bufs_queued); + dev_dbg(&cio2->pci_dev->dev, + "buffer %i done\n", b->vbb.vb2_buf.index); + + b->vbb.vb2_buf.timestamp = ns; + b->vbb.field = V4L2_FIELD_NONE; + b->vbb.sequence = atomic_read(&q->frame_sequence); + if (b->vbb.vb2_buf.planes[0].length != bytes) + dev_warn(dev, "buffer length is %d received %d\n", + b->vbb.vb2_buf.planes[0].length, + bytes); + vb2_buffer_done(&b->vbb.vb2_buf, VB2_BUF_STATE_DONE); + } + atomic_inc(&q->frame_sequence); + cio2_fbpt_entry_init_dummy(cio2, entry); + q->bufs_first = (q->bufs_first + 1) % CIO2_MAX_BUFFERS; + buffers_found++; + } while (1); + + if (buffers_found == 0) + dev_warn(&cio2->pci_dev->dev, + "no ready buffers found on DMA channel %u\n", + dma_chan); +} + +static void cio2_queue_event_sof(struct cio2_device *cio2, struct cio2_queue *q) +{ + /* + * For the user space camera control algorithms it is essential + * to know when the reception of a frame has begun. That's often + * the best timing information to get from the hardware. + */ + struct v4l2_event event = { + .type = V4L2_EVENT_FRAME_SYNC, + .u.frame_sync.frame_sequence = atomic_read(&q->frame_sequence), + }; + + v4l2_event_queue(q->subdev.devnode, &event); +} + +static const char *const cio2_irq_errs[] = { + "single packet header error corrected", + "multiple packet header errors detected", + "payload checksum (CRC) error", + "fifo overflow", + "reserved short packet data type detected", + "reserved long packet data type detected", + "incomplete long packet detected", + "frame sync error", + "line sync error", + "DPHY start of transmission error", + "DPHY synchronization error", + "escape mode error", + "escape mode trigger event", + "escape mode ultra-low power state for data lane(s)", + "escape mode ultra-low power state exit for clock lane", + "inter-frame short packet discarded", + "inter-frame long packet discarded", + "non-matching Long Packet stalled", +}; + +static const char *const cio2_port_errs[] = { + "ECC recoverable", + "DPHY not recoverable", + "ECC not recoverable", + "CRC error", + "INTERFRAMEDATA", + "PKT2SHORT", + "PKT2LONG", +}; + +static irqreturn_t cio2_irq(int irq, void *cio2_ptr) +{ + struct cio2_device *cio2 = cio2_ptr; + void __iomem *const base = cio2->base; + struct device *dev = &cio2->pci_dev->dev; + u32 int_status, int_clear; + + int_status = readl(base + CIO2_REG_INT_STS); + int_clear = int_status; + + if (!int_status) + return IRQ_NONE; + + if (int_status & CIO2_INT_IOOE) { + /* + * Interrupt on Output Error: + * 1) SRAM is full and FS received, or + * 2) An invalid bit detected by DMA. + */ + u32 oe_status, oe_clear; + + oe_clear = readl(base + CIO2_REG_INT_STS_EXT_OE); + oe_status = oe_clear; + + if (oe_status & CIO2_INT_EXT_OE_DMAOE_MASK) { + dev_err(dev, "DMA output error: 0x%x\n", + (oe_status & CIO2_INT_EXT_OE_DMAOE_MASK) + >> CIO2_INT_EXT_OE_DMAOE_SHIFT); + oe_status &= ~CIO2_INT_EXT_OE_DMAOE_MASK; + } + if (oe_status & CIO2_INT_EXT_OE_OES_MASK) { + dev_err(dev, "DMA output error on CSI2 buses: 0x%x\n", + (oe_status & CIO2_INT_EXT_OE_OES_MASK) + >> CIO2_INT_EXT_OE_OES_SHIFT); + oe_status &= ~CIO2_INT_EXT_OE_OES_MASK; + } + writel(oe_clear, base + CIO2_REG_INT_STS_EXT_OE); + if (oe_status) + dev_warn(dev, "unknown interrupt 0x%x on OE\n", + oe_status); + int_status &= ~CIO2_INT_IOOE; + } + + if (int_status & CIO2_INT_IOC_MASK) { + /* DMA IO done -- frame ready */ + u32 clr = 0; + unsigned int d; + + for (d = 0; d < CIO2_NUM_DMA_CHAN; d++) + if (int_status & CIO2_INT_IOC(d)) { + clr |= CIO2_INT_IOC(d); + cio2_buffer_done(cio2, d); + } + int_status &= ~clr; + } + + if (int_status & CIO2_INT_IOS_IOLN_MASK) { + /* DMA IO starts or reached specified line */ + u32 clr = 0; + unsigned int d; + + for (d = 0; d < CIO2_NUM_DMA_CHAN; d++) + if (int_status & CIO2_INT_IOS_IOLN(d)) { + clr |= CIO2_INT_IOS_IOLN(d); + if (d == CIO2_DMA_CHAN) + cio2_queue_event_sof(cio2, + cio2->cur_queue); + } + int_status &= ~clr; + } + + if (int_status & (CIO2_INT_IOIE | CIO2_INT_IOIRQ)) { + /* CSI2 receiver (error) interrupt */ + u32 ie_status, ie_clear; + unsigned int port; + + ie_clear = readl(base + CIO2_REG_INT_STS_EXT_IE); + ie_status = ie_clear; + + for (port = 0; port < CIO2_NUM_PORTS; port++) { + u32 port_status = (ie_status >> (port * 8)) & 0xff; + u32 err_mask = BIT_MASK(ARRAY_SIZE(cio2_port_errs)) - 1; + void __iomem *const csi_rx_base = + base + CIO2_REG_PIPE_BASE(port); + unsigned int i; + + while (port_status & err_mask) { + i = ffs(port_status) - 1; + dev_err(dev, "port %i error %s\n", + port, cio2_port_errs[i]); + ie_status &= ~BIT(port * 8 + i); + port_status &= ~BIT(i); + } + + if (ie_status & CIO2_INT_EXT_IE_IRQ(port)) { + u32 csi2_status, csi2_clear; + + csi2_status = readl(csi_rx_base + + CIO2_REG_IRQCTRL_STATUS); + csi2_clear = csi2_status; + err_mask = + BIT_MASK(ARRAY_SIZE(cio2_irq_errs)) - 1; + + while (csi2_status & err_mask) { + i = ffs(csi2_status) - 1; + dev_err(dev, + "CSI-2 receiver port %i: %s\n", + port, cio2_irq_errs[i]); + csi2_status &= ~BIT(i); + } + + writel(csi2_clear, + csi_rx_base + CIO2_REG_IRQCTRL_CLEAR); + if (csi2_status) + dev_warn(dev, + "unknown CSI2 error 0x%x on port %i\n", + csi2_status, port); + + ie_status &= ~CIO2_INT_EXT_IE_IRQ(port); + } + } + + writel(ie_clear, base + CIO2_REG_INT_STS_EXT_IE); + if (ie_status) + dev_warn(dev, "unknown interrupt 0x%x on IE\n", + ie_status); + + int_status &= ~(CIO2_INT_IOIE | CIO2_INT_IOIRQ); + } + + writel(int_clear, base + CIO2_REG_INT_STS); + if (int_status) + dev_warn(dev, "unknown interrupt 0x%x on INT\n", int_status); + + return IRQ_HANDLED; +} + +/**************** Videobuf2 interface ****************/ + +static void cio2_vb2_return_all_buffers(struct cio2_queue *q) +{ + unsigned int i; + + for (i = 0; i < CIO2_MAX_BUFFERS; i++) { + if (q->bufs[i]) { + atomic_dec(&q->bufs_queued); + vb2_buffer_done(&q->bufs[i]->vbb.vb2_buf, + VB2_BUF_STATE_ERROR); + } + } +} + +static int cio2_vb2_queue_setup(struct vb2_queue *vq, + unsigned int *num_buffers, + unsigned int *num_planes, + unsigned int sizes[], + struct device *alloc_devs[]) +{ + struct cio2_device *cio2 = vb2_get_drv_priv(vq); + struct cio2_queue *q = vb2q_to_cio2_queue(vq); + unsigned int i; + + *num_planes = q->format.num_planes; + + for (i = 0; i < *num_planes; ++i) { + sizes[i] = q->format.plane_fmt[i].sizeimage; + alloc_devs[i] = &cio2->pci_dev->dev; + } + + *num_buffers = clamp_val(*num_buffers, 1, CIO2_MAX_BUFFERS); + + /* Initialize buffer queue */ + for (i = 0; i < CIO2_MAX_BUFFERS; i++) { + q->bufs[i] = NULL; + cio2_fbpt_entry_init_dummy(cio2, &q->fbpt[i * CIO2_MAX_LOPS]); + } + atomic_set(&q->bufs_queued, 0); + q->bufs_first = 0; + q->bufs_next = 0; + + return 0; +} + +/* Called after each buffer is allocated */ +static int cio2_vb2_buf_init(struct vb2_buffer *vb) +{ + struct cio2_device *cio2 = vb2_get_drv_priv(vb->vb2_queue); + struct device *dev = &cio2->pci_dev->dev; + struct cio2_buffer *b = + container_of(vb, struct cio2_buffer, vbb.vb2_buf); + static const unsigned int entries_per_page = + CIO2_PAGE_SIZE / sizeof(u32); + unsigned int pages = DIV_ROUND_UP(vb->planes[0].length, CIO2_PAGE_SIZE); + unsigned int lops = DIV_ROUND_UP(pages + 1, entries_per_page); + struct sg_table *sg; + struct sg_page_iter sg_iter; + int i, j; + + if (lops <= 0 || lops > CIO2_MAX_LOPS) { + dev_err(dev, "%s: bad buffer size (%i)\n", __func__, + vb->planes[0].length); + return -ENOSPC; /* Should never happen */ + } + + memset(b->lop, 0, sizeof(b->lop)); + /* Allocate LOP table */ + for (i = 0; i < lops; i++) { + b->lop[i] = dma_alloc_coherent(dev, CIO2_PAGE_SIZE, + &b->lop_bus_addr[i], GFP_KERNEL); + if (!b->lop[i]) + goto fail; + } + + /* Fill LOP */ + sg = vb2_dma_sg_plane_desc(vb, 0); + if (!sg) + return -ENOMEM; + + if (sg->nents && sg->sgl) + b->offset = sg->sgl->offset; + + i = j = 0; + for_each_sg_page(sg->sgl, &sg_iter, sg->nents, 0) { + b->lop[i][j] = sg_page_iter_dma_address(&sg_iter) >> PAGE_SHIFT; + j++; + if (j == entries_per_page) { + i++; + j = 0; + } + } + + b->lop[i][j] = cio2->dummy_page_bus_addr >> PAGE_SHIFT; + return 0; +fail: + for (i--; i >= 0; i--) + dma_free_coherent(dev, CIO2_PAGE_SIZE, + b->lop[i], b->lop_bus_addr[i]); + return -ENOMEM; +} + +/* Transfer buffer ownership to cio2 */ +static void cio2_vb2_buf_queue(struct vb2_buffer *vb) +{ + struct cio2_device *cio2 = vb2_get_drv_priv(vb->vb2_queue); + struct cio2_queue *q = + container_of(vb->vb2_queue, struct cio2_queue, vbq); + struct cio2_buffer *b = + container_of(vb, struct cio2_buffer, vbb.vb2_buf); + struct cio2_fbpt_entry *entry; + unsigned long flags; + unsigned int i, j, next = q->bufs_next; + int bufs_queued = atomic_inc_return(&q->bufs_queued); + u32 fbpt_rp; + + dev_dbg(&cio2->pci_dev->dev, "queue buffer %d\n", vb->index); + + /* + * This code queues the buffer to the CIO2 DMA engine, which starts + * running once streaming has started. It is possible that this code + * gets pre-empted due to increased CPU load. Upon this, the driver + * does not get an opportunity to queue new buffers to the CIO2 DMA + * engine. When the DMA engine encounters an FBPT entry without the + * VALID bit set, the DMA engine halts, which requires a restart of + * the DMA engine and sensor, to continue streaming. + * This is not desired and is highly unlikely given that there are + * 32 FBPT entries that the DMA engine needs to process, to run into + * an FBPT entry, without the VALID bit set. We try to mitigate this + * by disabling interrupts for the duration of this queueing. + */ + local_irq_save(flags); + + fbpt_rp = (readl(cio2->base + CIO2_REG_CDMARI(CIO2_DMA_CHAN)) + >> CIO2_CDMARI_FBPT_RP_SHIFT) + & CIO2_CDMARI_FBPT_RP_MASK; + + /* + * fbpt_rp is the fbpt entry that the dma is currently working + * on, but since it could jump to next entry at any time, + * assume that we might already be there. + */ + fbpt_rp = (fbpt_rp + 1) % CIO2_MAX_BUFFERS; + + if (bufs_queued <= 1 || fbpt_rp == next) + /* Buffers were drained */ + next = (fbpt_rp + 1) % CIO2_MAX_BUFFERS; + + for (i = 0; i < CIO2_MAX_BUFFERS; i++) { + /* + * We have allocated CIO2_MAX_BUFFERS circularly for the + * hw, the user has requested N buffer queue. The driver + * ensures N <= CIO2_MAX_BUFFERS and guarantees that whenever + * user queues a buffer, there necessarily is a free buffer. + */ + if (!q->bufs[next]) { + q->bufs[next] = b; + entry = &q->fbpt[next * CIO2_MAX_LOPS]; + cio2_fbpt_entry_init_buf(cio2, b, entry); + local_irq_restore(flags); + q->bufs_next = (next + 1) % CIO2_MAX_BUFFERS; + for (j = 0; j < vb->num_planes; j++) + vb2_set_plane_payload(vb, j, + q->format.plane_fmt[j].sizeimage); + return; + } + + dev_dbg(&cio2->pci_dev->dev, "entry %i was full!\n", next); + next = (next + 1) % CIO2_MAX_BUFFERS; + } + + local_irq_restore(flags); + dev_err(&cio2->pci_dev->dev, "error: all cio2 entries were full!\n"); + atomic_dec(&q->bufs_queued); + vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); +} + +/* Called when each buffer is freed */ +static void cio2_vb2_buf_cleanup(struct vb2_buffer *vb) +{ + struct cio2_device *cio2 = vb2_get_drv_priv(vb->vb2_queue); + struct cio2_buffer *b = + container_of(vb, struct cio2_buffer, vbb.vb2_buf); + unsigned int i; + + /* Free LOP table */ + for (i = 0; i < CIO2_MAX_LOPS; i++) { + if (b->lop[i]) + dma_free_coherent(&cio2->pci_dev->dev, CIO2_PAGE_SIZE, + b->lop[i], b->lop_bus_addr[i]); + } +} + +static int cio2_vb2_start_streaming(struct vb2_queue *vq, unsigned int count) +{ + struct cio2_queue *q = vb2q_to_cio2_queue(vq); + struct cio2_device *cio2 = vb2_get_drv_priv(vq); + int r; + + cio2->cur_queue = q; + atomic_set(&q->frame_sequence, 0); + + r = pm_runtime_get_sync(&cio2->pci_dev->dev); + if (r < 0) { + dev_info(&cio2->pci_dev->dev, "failed to set power %d\n", r); + pm_runtime_put_noidle(&cio2->pci_dev->dev); + return r; + } + + r = media_pipeline_start(&q->vdev.entity, &q->pipe); + if (r) + goto fail_pipeline; + + r = cio2_hw_init(cio2, q); + if (r) + goto fail_hw; + + /* Start streaming on sensor */ + r = v4l2_subdev_call(q->sensor, video, s_stream, 1); + if (r) + goto fail_csi2_subdev; + + cio2->streaming = true; + + return 0; + +fail_csi2_subdev: + cio2_hw_exit(cio2, q); +fail_hw: + media_pipeline_stop(&q->vdev.entity); +fail_pipeline: + dev_dbg(&cio2->pci_dev->dev, "failed to start streaming (%d)\n", r); + cio2_vb2_return_all_buffers(q); + pm_runtime_put(&cio2->pci_dev->dev); + + return r; +} + +static void cio2_vb2_stop_streaming(struct vb2_queue *vq) +{ + struct cio2_queue *q = vb2q_to_cio2_queue(vq); + struct cio2_device *cio2 = vb2_get_drv_priv(vq); + + if (v4l2_subdev_call(q->sensor, video, s_stream, 0)) + dev_err(&cio2->pci_dev->dev, + "failed to stop sensor streaming\n"); + + cio2_hw_exit(cio2, q); + cio2_vb2_return_all_buffers(q); + media_pipeline_stop(&q->vdev.entity); + pm_runtime_put(&cio2->pci_dev->dev); + cio2->streaming = false; +} + +static const struct vb2_ops cio2_vb2_ops = { + .buf_init = cio2_vb2_buf_init, + .buf_queue = cio2_vb2_buf_queue, + .buf_cleanup = cio2_vb2_buf_cleanup, + .queue_setup = cio2_vb2_queue_setup, + .start_streaming = cio2_vb2_start_streaming, + .stop_streaming = cio2_vb2_stop_streaming, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, +}; + +/**************** V4L2 interface ****************/ + +static int cio2_v4l2_querycap(struct file *file, void *fh, + struct v4l2_capability *cap) +{ + struct cio2_device *cio2 = video_drvdata(file); + + strlcpy(cap->driver, CIO2_NAME, sizeof(cap->driver)); + strlcpy(cap->card, CIO2_DEVICE_NAME, sizeof(cap->card)); + snprintf(cap->bus_info, sizeof(cap->bus_info), + "PCI:%s", pci_name(cio2->pci_dev)); + + return 0; +} + +static int cio2_v4l2_enum_fmt(struct file *file, void *fh, + struct v4l2_fmtdesc *f) +{ + if (f->index >= ARRAY_SIZE(formats)) + return -EINVAL; + + f->pixelformat = formats[f->index].fourcc; + + return 0; +} + +/* The format is validated in cio2_video_link_validate() */ +static int cio2_v4l2_g_fmt(struct file *file, void *fh, struct v4l2_format *f) +{ + struct cio2_queue *q = file_to_cio2_queue(file); + + f->fmt.pix_mp = q->format; + + return 0; +} + +static int cio2_v4l2_try_fmt(struct file *file, void *fh, struct v4l2_format *f) +{ + const struct ipu3_cio2_fmt *fmt; + struct v4l2_pix_format_mplane *mpix = &f->fmt.pix_mp; + + fmt = cio2_find_format(&mpix->pixelformat, NULL); + if (!fmt) + fmt = &formats[0]; + + /* Only supports up to 4224x3136 */ + if (mpix->width > CIO2_IMAGE_MAX_WIDTH) + mpix->width = CIO2_IMAGE_MAX_WIDTH; + if (mpix->height > CIO2_IMAGE_MAX_LENGTH) + mpix->height = CIO2_IMAGE_MAX_LENGTH; + + mpix->num_planes = 1; + mpix->pixelformat = fmt->fourcc; + mpix->colorspace = V4L2_COLORSPACE_RAW; + mpix->field = V4L2_FIELD_NONE; + memset(mpix->reserved, 0, sizeof(mpix->reserved)); + mpix->plane_fmt[0].bytesperline = cio2_bytesperline(mpix->width); + mpix->plane_fmt[0].sizeimage = mpix->plane_fmt[0].bytesperline * + mpix->height; + memset(mpix->plane_fmt[0].reserved, 0, + sizeof(mpix->plane_fmt[0].reserved)); + + /* use default */ + mpix->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; + mpix->quantization = V4L2_QUANTIZATION_DEFAULT; + mpix->xfer_func = V4L2_XFER_FUNC_DEFAULT; + + return 0; +} + +static int cio2_v4l2_s_fmt(struct file *file, void *fh, struct v4l2_format *f) +{ + struct cio2_queue *q = file_to_cio2_queue(file); + + cio2_v4l2_try_fmt(file, fh, f); + q->format = f->fmt.pix_mp; + + return 0; +} + +static int +cio2_video_enum_input(struct file *file, void *fh, struct v4l2_input *input) +{ + if (input->index > 0) + return -EINVAL; + + strlcpy(input->name, "camera", sizeof(input->name)); + input->type = V4L2_INPUT_TYPE_CAMERA; + + return 0; +} + +static int +cio2_video_g_input(struct file *file, void *fh, unsigned int *input) +{ + *input = 0; + + return 0; +} + +static int +cio2_video_s_input(struct file *file, void *fh, unsigned int input) +{ + return input == 0 ? 0 : -EINVAL; +} + +static const struct v4l2_file_operations cio2_v4l2_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = video_ioctl2, + .open = v4l2_fh_open, + .release = vb2_fop_release, + .poll = vb2_fop_poll, + .mmap = vb2_fop_mmap, +}; + +static const struct v4l2_ioctl_ops cio2_v4l2_ioctl_ops = { + .vidioc_querycap = cio2_v4l2_querycap, + .vidioc_enum_fmt_vid_cap_mplane = cio2_v4l2_enum_fmt, + .vidioc_g_fmt_vid_cap_mplane = cio2_v4l2_g_fmt, + .vidioc_s_fmt_vid_cap_mplane = cio2_v4l2_s_fmt, + .vidioc_try_fmt_vid_cap_mplane = cio2_v4l2_try_fmt, + .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_create_bufs = vb2_ioctl_create_bufs, + .vidioc_prepare_buf = vb2_ioctl_prepare_buf, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, + .vidioc_expbuf = vb2_ioctl_expbuf, + .vidioc_enum_input = cio2_video_enum_input, + .vidioc_g_input = cio2_video_g_input, + .vidioc_s_input = cio2_video_s_input, +}; + +static int cio2_subdev_subscribe_event(struct v4l2_subdev *sd, + struct v4l2_fh *fh, + struct v4l2_event_subscription *sub) +{ + if (sub->type != V4L2_EVENT_FRAME_SYNC) + return -EINVAL; + + /* Line number. For now only zero accepted. */ + if (sub->id != 0) + return -EINVAL; + + return v4l2_event_subscribe(fh, sub, 0, NULL); +} + +static int cio2_subdev_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + struct v4l2_mbus_framefmt *format; + const struct v4l2_mbus_framefmt fmt_default = { + .width = 1936, + .height = 1096, + .code = formats[0].mbus_code, + .field = V4L2_FIELD_NONE, + .colorspace = V4L2_COLORSPACE_RAW, + .ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT, + .quantization = V4L2_QUANTIZATION_DEFAULT, + .xfer_func = V4L2_XFER_FUNC_DEFAULT, + }; + + /* Initialize try_fmt */ + format = v4l2_subdev_get_try_format(sd, fh->pad, CIO2_PAD_SINK); + *format = fmt_default; + + /* same as sink */ + format = v4l2_subdev_get_try_format(sd, fh->pad, CIO2_PAD_SOURCE); + *format = fmt_default; + + return 0; +} + +/* + * cio2_subdev_get_fmt - Handle get format by pads subdev method + * @sd : pointer to v4l2 subdev structure + * @cfg: V4L2 subdev pad config + * @fmt: pointer to v4l2 subdev format structure + * return -EINVAL or zero on success + */ +static int cio2_subdev_get_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *fmt) +{ + struct cio2_queue *q = container_of(sd, struct cio2_queue, subdev); + struct v4l2_subdev_format format; + int ret; + + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { + fmt->format = *v4l2_subdev_get_try_format(sd, cfg, fmt->pad); + return 0; + } + + if (fmt->pad == CIO2_PAD_SINK) { + format.which = V4L2_SUBDEV_FORMAT_ACTIVE; + ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, + &format); + + if (ret) + return ret; + /* update colorspace etc */ + q->subdev_fmt.colorspace = format.format.colorspace; + q->subdev_fmt.ycbcr_enc = format.format.ycbcr_enc; + q->subdev_fmt.quantization = format.format.quantization; + q->subdev_fmt.xfer_func = format.format.xfer_func; + } + + fmt->format = q->subdev_fmt; + + return 0; +} + +/* + * cio2_subdev_set_fmt - Handle set format by pads subdev method + * @sd : pointer to v4l2 subdev structure + * @cfg: V4L2 subdev pad config + * @fmt: pointer to v4l2 subdev format structure + * return -EINVAL or zero on success + */ +static int cio2_subdev_set_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *fmt) +{ + struct cio2_queue *q = container_of(sd, struct cio2_queue, subdev); + + /* + * Only allow setting sink pad format; + * source always propagates from sink + */ + if (fmt->pad == CIO2_PAD_SOURCE) + return cio2_subdev_get_fmt(sd, cfg, fmt); + + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { + *v4l2_subdev_get_try_format(sd, cfg, fmt->pad) = fmt->format; + } else { + /* It's the sink, allow changing frame size */ + q->subdev_fmt.width = fmt->format.width; + q->subdev_fmt.height = fmt->format.height; + q->subdev_fmt.code = fmt->format.code; + fmt->format = q->subdev_fmt; + } + + return 0; +} + +static int cio2_subdev_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_mbus_code_enum *code) +{ + if (code->index >= ARRAY_SIZE(formats)) + return -EINVAL; + + code->code = formats[code->index].mbus_code; + return 0; +} + +static int cio2_subdev_link_validate_get_format(struct media_pad *pad, + struct v4l2_subdev_format *fmt) +{ + if (is_media_entity_v4l2_subdev(pad->entity)) { + struct v4l2_subdev *sd = + media_entity_to_v4l2_subdev(pad->entity); + + fmt->which = V4L2_SUBDEV_FORMAT_ACTIVE; + fmt->pad = pad->index; + return v4l2_subdev_call(sd, pad, get_fmt, NULL, fmt); + } + + return -EINVAL; +} + +static int cio2_video_link_validate(struct media_link *link) +{ + struct video_device *vd = container_of(link->sink->entity, + struct video_device, entity); + struct cio2_queue *q = container_of(vd, struct cio2_queue, vdev); + struct cio2_device *cio2 = video_get_drvdata(vd); + struct v4l2_subdev_format source_fmt; + int ret; + + if (!media_entity_remote_pad(link->sink->entity->pads)) { + dev_info(&cio2->pci_dev->dev, + "video node %s pad not connected\n", vd->name); + return -ENOTCONN; + } + + ret = cio2_subdev_link_validate_get_format(link->source, &source_fmt); + if (ret < 0) + return 0; + + if (source_fmt.format.width != q->format.width || + source_fmt.format.height != q->format.height) { + dev_err(&cio2->pci_dev->dev, + "Wrong width or height %ux%u (%ux%u expected)\n", + q->format.width, q->format.height, + source_fmt.format.width, source_fmt.format.height); + return -EINVAL; + } + + if (!cio2_find_format(&q->format.pixelformat, &source_fmt.format.code)) + return -EINVAL; + + return 0; +} + +static const struct v4l2_subdev_core_ops cio2_subdev_core_ops = { + .subscribe_event = cio2_subdev_subscribe_event, + .unsubscribe_event = v4l2_event_subdev_unsubscribe, +}; + +static const struct v4l2_subdev_internal_ops cio2_subdev_internal_ops = { + .open = cio2_subdev_open, +}; + +static const struct v4l2_subdev_pad_ops cio2_subdev_pad_ops = { + .link_validate = v4l2_subdev_link_validate_default, + .get_fmt = cio2_subdev_get_fmt, + .set_fmt = cio2_subdev_set_fmt, + .enum_mbus_code = cio2_subdev_enum_mbus_code, +}; + +static const struct v4l2_subdev_ops cio2_subdev_ops = { + .core = &cio2_subdev_core_ops, + .pad = &cio2_subdev_pad_ops, +}; + +/******* V4L2 sub-device asynchronous registration callbacks***********/ + +struct sensor_async_subdev { + struct v4l2_async_subdev asd; + struct csi2_bus_info csi2; +}; + +/* The .bound() notifier callback when a match is found */ +static int cio2_notifier_bound(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *sd, + struct v4l2_async_subdev *asd) +{ + struct cio2_device *cio2 = container_of(notifier, + struct cio2_device, notifier); + struct sensor_async_subdev *s_asd = container_of(asd, + struct sensor_async_subdev, asd); + struct cio2_queue *q; + + if (cio2->queue[s_asd->csi2.port].sensor) + return -EBUSY; + + q = &cio2->queue[s_asd->csi2.port]; + + q->csi2 = s_asd->csi2; + q->sensor = sd; + q->csi_rx_base = cio2->base + CIO2_REG_PIPE_BASE(q->csi2.port); + + return 0; +} + +/* The .unbind callback */ +static void cio2_notifier_unbind(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *sd, + struct v4l2_async_subdev *asd) +{ + struct cio2_device *cio2 = container_of(notifier, + struct cio2_device, notifier); + struct sensor_async_subdev *s_asd = container_of(asd, + struct sensor_async_subdev, asd); + + cio2->queue[s_asd->csi2.port].sensor = NULL; +} + +/* .complete() is called after all subdevices have been located */ +static int cio2_notifier_complete(struct v4l2_async_notifier *notifier) +{ + struct cio2_device *cio2 = container_of(notifier, struct cio2_device, + notifier); + struct sensor_async_subdev *s_asd; + struct cio2_queue *q; + unsigned int i, pad; + int ret; + + for (i = 0; i < notifier->num_subdevs; i++) { + s_asd = container_of(cio2->notifier.subdevs[i], + struct sensor_async_subdev, asd); + q = &cio2->queue[s_asd->csi2.port]; + + for (pad = 0; pad < q->sensor->entity.num_pads; pad++) + if (q->sensor->entity.pads[pad].flags & + MEDIA_PAD_FL_SOURCE) + break; + + if (pad == q->sensor->entity.num_pads) { + dev_err(&cio2->pci_dev->dev, + "failed to find src pad for %s\n", + q->sensor->name); + return -ENXIO; + } + + ret = media_create_pad_link( + &q->sensor->entity, pad, + &q->subdev.entity, CIO2_PAD_SINK, + 0); + if (ret) { + dev_err(&cio2->pci_dev->dev, + "failed to create link for %s\n", + cio2->queue[i].sensor->name); + return ret; + } + } + + return v4l2_device_register_subdev_nodes(&cio2->v4l2_dev); +} + +static const struct v4l2_async_notifier_operations cio2_async_ops = { + .bound = cio2_notifier_bound, + .unbind = cio2_notifier_unbind, + .complete = cio2_notifier_complete, +}; + +static int cio2_fwnode_parse(struct device *dev, + struct v4l2_fwnode_endpoint *vep, + struct v4l2_async_subdev *asd) +{ + struct sensor_async_subdev *s_asd = + container_of(asd, struct sensor_async_subdev, asd); + + if (vep->bus_type != V4L2_MBUS_CSI2) { + dev_err(dev, "Only CSI2 bus type is currently supported\n"); + return -EINVAL; + } + + s_asd->csi2.port = vep->base.port; + s_asd->csi2.lanes = vep->bus.mipi_csi2.num_data_lanes; + + return 0; +} + +static int cio2_notifier_init(struct cio2_device *cio2) +{ + int ret; + + ret = v4l2_async_notifier_parse_fwnode_endpoints( + &cio2->pci_dev->dev, &cio2->notifier, + sizeof(struct sensor_async_subdev), + cio2_fwnode_parse); + if (ret < 0) + return ret; + + if (!cio2->notifier.num_subdevs) + return -ENODEV; /* no endpoint */ + + cio2->notifier.ops = &cio2_async_ops; + ret = v4l2_async_notifier_register(&cio2->v4l2_dev, &cio2->notifier); + if (ret) { + dev_err(&cio2->pci_dev->dev, + "failed to register async notifier : %d\n", ret); + v4l2_async_notifier_cleanup(&cio2->notifier); + } + + return ret; +} + +static void cio2_notifier_exit(struct cio2_device *cio2) +{ + v4l2_async_notifier_unregister(&cio2->notifier); + v4l2_async_notifier_cleanup(&cio2->notifier); +} + +/**************** Queue initialization ****************/ +static const struct media_entity_operations cio2_media_ops = { + .link_validate = v4l2_subdev_link_validate, +}; + +static const struct media_entity_operations cio2_video_entity_ops = { + .link_validate = cio2_video_link_validate, +}; + +static int cio2_queue_init(struct cio2_device *cio2, struct cio2_queue *q) +{ + static const u32 default_width = 1936; + static const u32 default_height = 1096; + const struct ipu3_cio2_fmt dflt_fmt = formats[0]; + + struct video_device *vdev = &q->vdev; + struct vb2_queue *vbq = &q->vbq; + struct v4l2_subdev *subdev = &q->subdev; + struct v4l2_mbus_framefmt *fmt; + int r; + + /* Initialize miscellaneous variables */ + mutex_init(&q->lock); + + /* Initialize formats to default values */ + fmt = &q->subdev_fmt; + fmt->width = default_width; + fmt->height = default_height; + fmt->code = dflt_fmt.mbus_code; + fmt->field = V4L2_FIELD_NONE; + + q->format.width = default_width; + q->format.height = default_height; + q->format.pixelformat = dflt_fmt.fourcc; + q->format.colorspace = V4L2_COLORSPACE_RAW; + q->format.field = V4L2_FIELD_NONE; + q->format.num_planes = 1; + q->format.plane_fmt[0].bytesperline = + cio2_bytesperline(q->format.width); + q->format.plane_fmt[0].sizeimage = q->format.plane_fmt[0].bytesperline * + q->format.height; + + /* Initialize fbpt */ + r = cio2_fbpt_init(cio2, q); + if (r) + goto fail_fbpt; + + /* Initialize media entities */ + q->subdev_pads[CIO2_PAD_SINK].flags = MEDIA_PAD_FL_SINK | + MEDIA_PAD_FL_MUST_CONNECT; + q->subdev_pads[CIO2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; + subdev->entity.ops = &cio2_media_ops; + subdev->internal_ops = &cio2_subdev_internal_ops; + r = media_entity_pads_init(&subdev->entity, CIO2_PADS, q->subdev_pads); + if (r) { + dev_err(&cio2->pci_dev->dev, + "failed initialize subdev media entity (%d)\n", r); + goto fail_subdev_media_entity; + } + + q->vdev_pad.flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT; + vdev->entity.ops = &cio2_video_entity_ops; + r = media_entity_pads_init(&vdev->entity, 1, &q->vdev_pad); + if (r) { + dev_err(&cio2->pci_dev->dev, + "failed initialize videodev media entity (%d)\n", r); + goto fail_vdev_media_entity; + } + + /* Initialize subdev */ + v4l2_subdev_init(subdev, &cio2_subdev_ops); + subdev->flags = V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; + subdev->owner = THIS_MODULE; + snprintf(subdev->name, sizeof(subdev->name), + CIO2_ENTITY_NAME " %td", q - cio2->queue); + v4l2_set_subdevdata(subdev, cio2); + r = v4l2_device_register_subdev(&cio2->v4l2_dev, subdev); + if (r) { + dev_err(&cio2->pci_dev->dev, + "failed initialize subdev (%d)\n", r); + goto fail_subdev; + } + + /* Initialize vbq */ + vbq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + vbq->io_modes = VB2_USERPTR | VB2_MMAP | VB2_DMABUF; + vbq->ops = &cio2_vb2_ops; + vbq->mem_ops = &vb2_dma_sg_memops; + vbq->buf_struct_size = sizeof(struct cio2_buffer); + vbq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + vbq->min_buffers_needed = 1; + vbq->drv_priv = cio2; + vbq->lock = &q->lock; + r = vb2_queue_init(vbq); + if (r) { + dev_err(&cio2->pci_dev->dev, + "failed to initialize videobuf2 queue (%d)\n", r); + goto fail_vbq; + } + + /* Initialize vdev */ + snprintf(vdev->name, sizeof(vdev->name), + "%s %td", CIO2_NAME, q - cio2->queue); + vdev->release = video_device_release_empty; + vdev->fops = &cio2_v4l2_fops; + vdev->ioctl_ops = &cio2_v4l2_ioctl_ops; + vdev->lock = &cio2->lock; + vdev->v4l2_dev = &cio2->v4l2_dev; + vdev->queue = &q->vbq; + vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING; + video_set_drvdata(vdev, cio2); + r = video_register_device(vdev, VFL_TYPE_GRABBER, -1); + if (r) { + dev_err(&cio2->pci_dev->dev, + "failed to register video device (%d)\n", r); + goto fail_vdev; + } + + /* Create link from CIO2 subdev to output node */ + r = media_create_pad_link( + &subdev->entity, CIO2_PAD_SOURCE, &vdev->entity, 0, + MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE); + if (r) + goto fail_link; + + return 0; + +fail_link: + video_unregister_device(&q->vdev); +fail_vdev: + vb2_queue_release(vbq); +fail_vbq: + v4l2_device_unregister_subdev(subdev); +fail_subdev: + media_entity_cleanup(&vdev->entity); +fail_vdev_media_entity: + media_entity_cleanup(&subdev->entity); +fail_subdev_media_entity: + cio2_fbpt_exit(q, &cio2->pci_dev->dev); +fail_fbpt: + mutex_destroy(&q->lock); + + return r; +} + +static void cio2_queue_exit(struct cio2_device *cio2, struct cio2_queue *q) +{ + video_unregister_device(&q->vdev); + media_entity_cleanup(&q->vdev.entity); + vb2_queue_release(&q->vbq); + v4l2_device_unregister_subdev(&q->subdev); + media_entity_cleanup(&q->subdev.entity); + cio2_fbpt_exit(q, &cio2->pci_dev->dev); + mutex_destroy(&q->lock); +} + +static int cio2_queues_init(struct cio2_device *cio2) +{ + int i, r; + + for (i = 0; i < CIO2_QUEUES; i++) { + r = cio2_queue_init(cio2, &cio2->queue[i]); + if (r) + break; + } + + if (i == CIO2_QUEUES) + return 0; + + for (i--; i >= 0; i--) + cio2_queue_exit(cio2, &cio2->queue[i]); + + return r; +} + +static void cio2_queues_exit(struct cio2_device *cio2) +{ + unsigned int i; + + for (i = 0; i < CIO2_QUEUES; i++) + cio2_queue_exit(cio2, &cio2->queue[i]); +} + +/**************** PCI interface ****************/ + +static int cio2_pci_config_setup(struct pci_dev *dev) +{ + u16 pci_command; + int r = pci_enable_msi(dev); + + if (r) { + dev_err(&dev->dev, "failed to enable MSI (%d)\n", r); + return r; + } + + pci_read_config_word(dev, PCI_COMMAND, &pci_command); + pci_command |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | + PCI_COMMAND_INTX_DISABLE; + pci_write_config_word(dev, PCI_COMMAND, pci_command); + + return 0; +} + +static int cio2_pci_probe(struct pci_dev *pci_dev, + const struct pci_device_id *id) +{ + struct cio2_device *cio2; + void __iomem *const *iomap; + int r; + + cio2 = devm_kzalloc(&pci_dev->dev, sizeof(*cio2), GFP_KERNEL); + if (!cio2) + return -ENOMEM; + cio2->pci_dev = pci_dev; + + r = pcim_enable_device(pci_dev); + if (r) { + dev_err(&pci_dev->dev, "failed to enable device (%d)\n", r); + return r; + } + + dev_info(&pci_dev->dev, "device 0x%x (rev: 0x%x)\n", + pci_dev->device, pci_dev->revision); + + r = pcim_iomap_regions(pci_dev, 1 << CIO2_PCI_BAR, pci_name(pci_dev)); + if (r) { + dev_err(&pci_dev->dev, "failed to remap I/O memory (%d)\n", r); + return -ENODEV; + } + + iomap = pcim_iomap_table(pci_dev); + if (!iomap) { + dev_err(&pci_dev->dev, "failed to iomap table\n"); + return -ENODEV; + } + + cio2->base = iomap[CIO2_PCI_BAR]; + + pci_set_drvdata(pci_dev, cio2); + + pci_set_master(pci_dev); + + r = pci_set_dma_mask(pci_dev, CIO2_DMA_MASK); + if (r) { + dev_err(&pci_dev->dev, "failed to set DMA mask (%d)\n", r); + return -ENODEV; + } + + r = cio2_pci_config_setup(pci_dev); + if (r) + return -ENODEV; + + r = cio2_fbpt_init_dummy(cio2); + if (r) + return r; + + mutex_init(&cio2->lock); + + cio2->media_dev.dev = &cio2->pci_dev->dev; + strlcpy(cio2->media_dev.model, CIO2_DEVICE_NAME, + sizeof(cio2->media_dev.model)); + snprintf(cio2->media_dev.bus_info, sizeof(cio2->media_dev.bus_info), + "PCI:%s", pci_name(cio2->pci_dev)); + cio2->media_dev.hw_revision = 0; + + media_device_init(&cio2->media_dev); + r = media_device_register(&cio2->media_dev); + if (r < 0) + goto fail_mutex_destroy; + + cio2->v4l2_dev.mdev = &cio2->media_dev; + r = v4l2_device_register(&pci_dev->dev, &cio2->v4l2_dev); + if (r) { + dev_err(&pci_dev->dev, + "failed to register V4L2 device (%d)\n", r); + goto fail_media_device_unregister; + } + + r = cio2_queues_init(cio2); + if (r) + goto fail_v4l2_device_unregister; + + /* Register notifier for subdevices we care */ + r = cio2_notifier_init(cio2); + if (r) + goto fail_cio2_queue_exit; + + r = devm_request_irq(&pci_dev->dev, pci_dev->irq, cio2_irq, + IRQF_SHARED, CIO2_NAME, cio2); + if (r) { + dev_err(&pci_dev->dev, "failed to request IRQ (%d)\n", r); + goto fail; + } + + pm_runtime_put_noidle(&pci_dev->dev); + pm_runtime_allow(&pci_dev->dev); + + return 0; + +fail: + cio2_notifier_exit(cio2); +fail_cio2_queue_exit: + cio2_queues_exit(cio2); +fail_v4l2_device_unregister: + v4l2_device_unregister(&cio2->v4l2_dev); +fail_media_device_unregister: + media_device_unregister(&cio2->media_dev); + media_device_cleanup(&cio2->media_dev); +fail_mutex_destroy: + mutex_destroy(&cio2->lock); + cio2_fbpt_exit_dummy(cio2); + + return r; +} + +static void cio2_pci_remove(struct pci_dev *pci_dev) +{ + struct cio2_device *cio2 = pci_get_drvdata(pci_dev); + unsigned int i; + + cio2_notifier_exit(cio2); + cio2_fbpt_exit_dummy(cio2); + for (i = 0; i < CIO2_QUEUES; i++) + cio2_queue_exit(cio2, &cio2->queue[i]); + v4l2_device_unregister(&cio2->v4l2_dev); + media_device_unregister(&cio2->media_dev); + media_device_cleanup(&cio2->media_dev); + mutex_destroy(&cio2->lock); +} + +static int cio2_runtime_suspend(struct device *dev) +{ + struct pci_dev *pci_dev = to_pci_dev(dev); + struct cio2_device *cio2 = pci_get_drvdata(pci_dev); + void __iomem *const base = cio2->base; + u16 pm; + + writel(CIO2_D0I3C_I3, base + CIO2_REG_D0I3C); + dev_dbg(dev, "cio2 runtime suspend.\n"); + + pci_read_config_word(pci_dev, pci_dev->pm_cap + CIO2_PMCSR_OFFSET, &pm); + pm = (pm >> CIO2_PMCSR_D0D3_SHIFT) << CIO2_PMCSR_D0D3_SHIFT; + pm |= CIO2_PMCSR_D3; + pci_write_config_word(pci_dev, pci_dev->pm_cap + CIO2_PMCSR_OFFSET, pm); + + return 0; +} + +static int cio2_runtime_resume(struct device *dev) +{ + struct pci_dev *pci_dev = to_pci_dev(dev); + struct cio2_device *cio2 = pci_get_drvdata(pci_dev); + void __iomem *const base = cio2->base; + u16 pm; + + writel(CIO2_D0I3C_RR, base + CIO2_REG_D0I3C); + dev_dbg(dev, "cio2 runtime resume.\n"); + + pci_read_config_word(pci_dev, pci_dev->pm_cap + CIO2_PMCSR_OFFSET, &pm); + pm = (pm >> CIO2_PMCSR_D0D3_SHIFT) << CIO2_PMCSR_D0D3_SHIFT; + pci_write_config_word(pci_dev, pci_dev->pm_cap + CIO2_PMCSR_OFFSET, pm); + + return 0; +} + +/* + * Helper function to advance all the elements of a circular buffer by "start" + * positions + */ +static void arrange(void *ptr, size_t elem_size, size_t elems, size_t start) +{ + struct { + size_t begin, end; + } arr[2] = { + { 0, start - 1 }, + { start, elems - 1 }, + }; + +#define arr_size(a) ((a)->end - (a)->begin + 1) + + /* Loop as long as we have out-of-place entries */ + while (arr_size(&arr[0]) && arr_size(&arr[1])) { + size_t size0, i; + + /* + * Find the number of entries that can be arranged on this + * iteration. + */ + if (arr_size(&arr[0]) > arr_size(&arr[1])) + size0 = arr_size(&arr[1]); + else + size0 = arr_size(&arr[0]); + + /* Swap the entries in two parts of the array. */ + for (i = 0; i < size0; i++) { + u8 *d = ptr + elem_size * (arr[1].begin + i); + u8 *s = ptr + elem_size * (arr[0].begin + i); + size_t j; + + for (j = 0; j < elem_size; j++) + swap(d[j], s[j]); + } + + if (arr_size(&arr[0]) > arr_size(&arr[1])) { + /* The end of the first array remains unarranged. */ + arr[0].begin += size0; + } else { + /* + * The first array is fully arranged so we proceed + * handling the next one. + */ + arr[0].begin = arr[1].begin; + arr[0].end = arr[1].begin + size0 - 1; + arr[1].begin += size0; + } + } +} + +static void cio2_fbpt_rearrange(struct cio2_device *cio2, struct cio2_queue *q) +{ + unsigned int i, j; + + for (i = 0, j = q->bufs_first; i < CIO2_MAX_BUFFERS; + i++, j = (j + 1) % CIO2_MAX_BUFFERS) + if (q->bufs[j]) + break; + + if (i == CIO2_MAX_BUFFERS) + return; + + if (j) { + arrange(q->fbpt, sizeof(struct cio2_fbpt_entry) * CIO2_MAX_LOPS, + CIO2_MAX_BUFFERS, j); + arrange(q->bufs, sizeof(struct cio2_buffer *), + CIO2_MAX_BUFFERS, j); + } + + /* + * DMA clears the valid bit when accessing the buffer. + * When stopping stream in suspend callback, some of the buffers + * may be in invalid state. After resume, when DMA meets the invalid + * buffer, it will halt and stop receiving new data. + * To avoid DMA halting, set the valid bit for all buffers in FBPT. + */ + for (i = 0; i < CIO2_MAX_BUFFERS; i++) + cio2_fbpt_entry_enable(cio2, q->fbpt + i * CIO2_MAX_LOPS); +} + +static int cio2_suspend(struct device *dev) +{ + struct pci_dev *pci_dev = to_pci_dev(dev); + struct cio2_device *cio2 = pci_get_drvdata(pci_dev); + struct cio2_queue *q = cio2->cur_queue; + + dev_dbg(dev, "cio2 suspend\n"); + if (!cio2->streaming) + return 0; + + /* Stop stream */ + cio2_hw_exit(cio2, q); + + pm_runtime_force_suspend(dev); + + /* + * Upon resume, hw starts to process the fbpt entries from beginning, + * so relocate the queued buffs to the fbpt head before suspend. + */ + cio2_fbpt_rearrange(cio2, q); + q->bufs_first = 0; + q->bufs_next = 0; + + return 0; +} + +static int cio2_resume(struct device *dev) +{ + struct pci_dev *pci_dev = to_pci_dev(dev); + struct cio2_device *cio2 = pci_get_drvdata(pci_dev); + int r = 0; + struct cio2_queue *q = cio2->cur_queue; + + dev_dbg(dev, "cio2 resume\n"); + if (!cio2->streaming) + return 0; + /* Start stream */ + r = pm_runtime_force_resume(&cio2->pci_dev->dev); + if (r < 0) { + dev_err(&cio2->pci_dev->dev, + "failed to set power %d\n", r); + return r; + } + + r = cio2_hw_init(cio2, q); + if (r) + dev_err(dev, "fail to init cio2 hw\n"); + + return r; +} + +static const struct dev_pm_ops cio2_pm_ops = { + SET_RUNTIME_PM_OPS(&cio2_runtime_suspend, &cio2_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(&cio2_suspend, &cio2_resume) +}; + +static const struct pci_device_id cio2_pci_id_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, CIO2_PCI_ID) }, + { 0 } +}; + +MODULE_DEVICE_TABLE(pci, cio2_pci_id_table); + +static struct pci_driver cio2_pci_driver = { + .name = CIO2_NAME, + .id_table = cio2_pci_id_table, + .probe = cio2_pci_probe, + .remove = cio2_pci_remove, + .driver = { + .pm = &cio2_pm_ops, + }, +}; + +module_pci_driver(cio2_pci_driver); + +MODULE_AUTHOR("Tuukka Toivonen <tuukka.toivonen@intel.com>"); +MODULE_AUTHOR("Tianshu Qiu <tian.shu.qiu@intel.com>"); +MODULE_AUTHOR("Jian Xu Zheng <jian.xu.zheng@intel.com>"); +MODULE_AUTHOR("Yuning Pu <yuning.pu@intel.com>"); +MODULE_AUTHOR("Yong Zhi <yong.zhi@intel.com>"); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("IPU3 CIO2 driver"); diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.h b/drivers/media/pci/intel/ipu3/ipu3-cio2.h new file mode 100644 index 000000000000..1a559990920f --- /dev/null +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.h @@ -0,0 +1,449 @@ +/* + * Copyright (c) 2017 Intel Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __IPU3_CIO2_H +#define __IPU3_CIO2_H + +#define CIO2_NAME "ipu3-cio2" +#define CIO2_DEVICE_NAME "Intel IPU3 CIO2" +#define CIO2_ENTITY_NAME "ipu3-csi2" +#define CIO2_PCI_ID 0x9d32 +#define CIO2_PCI_BAR 0 +#define CIO2_DMA_MASK DMA_BIT_MASK(39) +#define CIO2_IMAGE_MAX_WIDTH 4224 +#define CIO2_IMAGE_MAX_LENGTH 3136 + +#define CIO2_IMAGE_MAX_WIDTH 4224 +#define CIO2_IMAGE_MAX_LENGTH 3136 + +/* 32MB = 8xFBPT_entry */ +#define CIO2_MAX_LOPS 8 +#define CIO2_MAX_BUFFERS (PAGE_SIZE / 16 / CIO2_MAX_LOPS) + +#define CIO2_PAD_SINK 0 +#define CIO2_PAD_SOURCE 1 +#define CIO2_PADS 2 + +#define CIO2_NUM_DMA_CHAN 20 +#define CIO2_NUM_PORTS 4 /* DPHYs */ + +/* 1 for each sensor */ +#define CIO2_QUEUES CIO2_NUM_PORTS + +/* Register and bit field definitions */ +#define CIO2_REG_PIPE_BASE(n) ((n) * 0x0400) /* n = 0..3 */ +#define CIO2_REG_CSIRX_BASE 0x000 +#define CIO2_REG_MIPIBE_BASE 0x100 +#define CIO2_REG_PIXELGEN_BAS 0x200 +#define CIO2_REG_IRQCTRL_BASE 0x300 +#define CIO2_REG_GPREG_BASE 0x1000 + +/* base register: CIO2_REG_PIPE_BASE(pipe) * CIO2_REG_CSIRX_BASE */ +#define CIO2_REG_CSIRX_ENABLE (CIO2_REG_CSIRX_BASE + 0x0) +#define CIO2_REG_CSIRX_NOF_ENABLED_LANES (CIO2_REG_CSIRX_BASE + 0x4) +#define CIO2_REG_CSIRX_SP_IF_CONFIG (CIO2_REG_CSIRX_BASE + 0x10) +#define CIO2_REG_CSIRX_LP_IF_CONFIG (CIO2_REG_CSIRX_BASE + 0x14) +#define CIO2_CSIRX_IF_CONFIG_FILTEROUT 0x00 +#define CIO2_CSIRX_IF_CONFIG_FILTEROUT_VC_INACTIVE 0x01 +#define CIO2_CSIRX_IF_CONFIG_PASS 0x02 +#define CIO2_CSIRX_IF_CONFIG_FLAG_ERROR BIT(2) +#define CIO2_REG_CSIRX_STATUS (CIO2_REG_CSIRX_BASE + 0x18) +#define CIO2_REG_CSIRX_STATUS_DLANE_HS (CIO2_REG_CSIRX_BASE + 0x1c) +#define CIO2_CSIRX_STATUS_DLANE_HS_MASK 0xff +#define CIO2_REG_CSIRX_STATUS_DLANE_LP (CIO2_REG_CSIRX_BASE + 0x20) +#define CIO2_CSIRX_STATUS_DLANE_LP_MASK 0xffffff +/* Termination enable and settle in 0.0625ns units, lane=0..3 or -1 for clock */ +#define CIO2_REG_CSIRX_DLY_CNT_TERMEN(lane) \ + (CIO2_REG_CSIRX_BASE + 0x2c + 8 * (lane)) +#define CIO2_REG_CSIRX_DLY_CNT_SETTLE(lane) \ + (CIO2_REG_CSIRX_BASE + 0x30 + 8 * (lane)) +/* base register: CIO2_REG_PIPE_BASE(pipe) * CIO2_REG_MIPIBE_BASE */ +#define CIO2_REG_MIPIBE_ENABLE (CIO2_REG_MIPIBE_BASE + 0x0) +#define CIO2_REG_MIPIBE_STATUS (CIO2_REG_MIPIBE_BASE + 0x4) +#define CIO2_REG_MIPIBE_COMP_FORMAT(vc) \ + (CIO2_REG_MIPIBE_BASE + 0x8 + 0x4 * (vc)) +#define CIO2_REG_MIPIBE_FORCE_RAW8 (CIO2_REG_MIPIBE_BASE + 0x20) +#define CIO2_REG_MIPIBE_FORCE_RAW8_ENABLE BIT(0) +#define CIO2_REG_MIPIBE_FORCE_RAW8_USE_TYPEID BIT(1) +#define CIO2_REG_MIPIBE_FORCE_RAW8_TYPEID_SHIFT 2 + +#define CIO2_REG_MIPIBE_IRQ_STATUS (CIO2_REG_MIPIBE_BASE + 0x24) +#define CIO2_REG_MIPIBE_IRQ_CLEAR (CIO2_REG_MIPIBE_BASE + 0x28) +#define CIO2_REG_MIPIBE_GLOBAL_LUT_DISREGARD (CIO2_REG_MIPIBE_BASE + 0x68) +#define CIO2_MIPIBE_GLOBAL_LUT_DISREGARD 1 +#define CIO2_REG_MIPIBE_PKT_STALL_STATUS (CIO2_REG_MIPIBE_BASE + 0x6c) +#define CIO2_REG_MIPIBE_PARSE_GSP_THROUGH_LP_LUT_REG_IDX \ + (CIO2_REG_MIPIBE_BASE + 0x70) +#define CIO2_REG_MIPIBE_SP_LUT_ENTRY(vc) \ + (CIO2_REG_MIPIBE_BASE + 0x74 + 4 * (vc)) +#define CIO2_REG_MIPIBE_LP_LUT_ENTRY(m) /* m = 0..15 */ \ + (CIO2_REG_MIPIBE_BASE + 0x84 + 4 * (m)) +#define CIO2_MIPIBE_LP_LUT_ENTRY_DISREGARD 1 +#define CIO2_MIPIBE_LP_LUT_ENTRY_SID_SHIFT 1 +#define CIO2_MIPIBE_LP_LUT_ENTRY_VC_SHIFT 5 +#define CIO2_MIPIBE_LP_LUT_ENTRY_FORMAT_TYPE_SHIFT 7 + +/* base register: CIO2_REG_PIPE_BASE(pipe) * CIO2_REG_IRQCTRL_BASE */ +/* IRQ registers are 18-bit wide, see cio2_irq_error for bit definitions */ +#define CIO2_REG_IRQCTRL_EDGE (CIO2_REG_IRQCTRL_BASE + 0x00) +#define CIO2_REG_IRQCTRL_MASK (CIO2_REG_IRQCTRL_BASE + 0x04) +#define CIO2_REG_IRQCTRL_STATUS (CIO2_REG_IRQCTRL_BASE + 0x08) +#define CIO2_REG_IRQCTRL_CLEAR (CIO2_REG_IRQCTRL_BASE + 0x0c) +#define CIO2_REG_IRQCTRL_ENABLE (CIO2_REG_IRQCTRL_BASE + 0x10) +#define CIO2_REG_IRQCTRL_LEVEL_NOT_PULSE (CIO2_REG_IRQCTRL_BASE + 0x14) + +#define CIO2_REG_GPREG_SRST (CIO2_REG_GPREG_BASE + 0x0) +#define CIO2_GPREG_SRST_ALL 0xffff /* Reset all */ +#define CIO2_REG_FB_HPLL_FREQ (CIO2_REG_GPREG_BASE + 0x08) +#define CIO2_REG_ISCLK_RATIO (CIO2_REG_GPREG_BASE + 0xc) + +#define CIO2_REG_CGC 0x1400 +#define CIO2_CGC_CSI2_TGE BIT(0) +#define CIO2_CGC_PRIM_TGE BIT(1) +#define CIO2_CGC_SIDE_TGE BIT(2) +#define CIO2_CGC_XOSC_TGE BIT(3) +#define CIO2_CGC_MPLL_SHUTDOWN_EN BIT(4) +#define CIO2_CGC_D3I3_TGE BIT(5) +#define CIO2_CGC_CSI2_INTERFRAME_TGE BIT(6) +#define CIO2_CGC_CSI2_PORT_DCGE BIT(8) +#define CIO2_CGC_CSI2_DCGE BIT(9) +#define CIO2_CGC_SIDE_DCGE BIT(10) +#define CIO2_CGC_PRIM_DCGE BIT(11) +#define CIO2_CGC_ROSC_DCGE BIT(12) +#define CIO2_CGC_XOSC_DCGE BIT(13) +#define CIO2_CGC_FLIS_DCGE BIT(14) +#define CIO2_CGC_CLKGATE_HOLDOFF_SHIFT 20 +#define CIO2_CGC_CSI_CLKGATE_HOLDOFF_SHIFT 24 +#define CIO2_REG_D0I3C 0x1408 +#define CIO2_D0I3C_I3 BIT(2) /* Set D0I3 */ +#define CIO2_D0I3C_RR BIT(3) /* Restore? */ +#define CIO2_REG_SWRESET 0x140c +#define CIO2_SWRESET_SWRESET 1 +#define CIO2_REG_SENSOR_ACTIVE 0x1410 +#define CIO2_REG_INT_STS 0x1414 +#define CIO2_REG_INT_STS_EXT_OE 0x1418 +#define CIO2_INT_EXT_OE_DMAOE_SHIFT 0 +#define CIO2_INT_EXT_OE_DMAOE_MASK 0x7ffff +#define CIO2_INT_EXT_OE_OES_SHIFT 24 +#define CIO2_INT_EXT_OE_OES_MASK (0xf << CIO2_INT_EXT_OE_OES_SHIFT) +#define CIO2_REG_INT_EN 0x1420 +#define CIO2_REG_INT_EN_IRQ (1 << 24) +#define CIO2_REG_INT_EN_IOS(dma) (1 << (((dma) >> 1) + 12)) +/* + * Interrupt on completion bit, Eg. DMA 0-3 maps to bit 0-3, + * DMA4 & DMA5 map to bit 4 ... DMA18 & DMA19 map to bit 11 Et cetera + */ +#define CIO2_INT_IOC(dma) (1 << ((dma) < 4 ? (dma) : ((dma) >> 1) + 2)) +#define CIO2_INT_IOC_SHIFT 0 +#define CIO2_INT_IOC_MASK (0x7ff << CIO2_INT_IOC_SHIFT) +#define CIO2_INT_IOS_IOLN(dma) (1 << (((dma) >> 1) + 12)) +#define CIO2_INT_IOS_IOLN_SHIFT 12 +#define CIO2_INT_IOS_IOLN_MASK (0x3ff << CIO2_INT_IOS_IOLN_SHIFT) +#define CIO2_INT_IOIE BIT(22) +#define CIO2_INT_IOOE BIT(23) +#define CIO2_INT_IOIRQ BIT(24) +#define CIO2_REG_INT_EN_EXT_OE 0x1424 +#define CIO2_REG_DMA_DBG 0x1448 +#define CIO2_REG_DMA_DBG_DMA_INDEX_SHIFT 0 +#define CIO2_REG_PBM_ARB_CTRL 0x1460 +#define CIO2_PBM_ARB_CTRL_LANES_DIV 0 /* 4-4-2-2 lanes */ +#define CIO2_PBM_ARB_CTRL_LANES_DIV_SHIFT 0 +#define CIO2_PBM_ARB_CTRL_LE_EN BIT(7) +#define CIO2_PBM_ARB_CTRL_PLL_POST_SHTDN 2 +#define CIO2_PBM_ARB_CTRL_PLL_POST_SHTDN_SHIFT 8 +#define CIO2_PBM_ARB_CTRL_PLL_AHD_WK_UP 480 +#define CIO2_PBM_ARB_CTRL_PLL_AHD_WK_UP_SHIFT 16 +#define CIO2_REG_PBM_WMCTRL1 0x1464 +#define CIO2_PBM_WMCTRL1_MIN_2CK_SHIFT 0 +#define CIO2_PBM_WMCTRL1_MID1_2CK_SHIFT 8 +#define CIO2_PBM_WMCTRL1_MID2_2CK_SHIFT 16 +#define CIO2_PBM_WMCTRL1_TS_COUNT_DISABLE BIT(31) +#define CIO2_PBM_WMCTRL1_MIN_2CK (4 << CIO2_PBM_WMCTRL1_MIN_2CK_SHIFT) +#define CIO2_PBM_WMCTRL1_MID1_2CK (16 << CIO2_PBM_WMCTRL1_MID1_2CK_SHIFT) +#define CIO2_PBM_WMCTRL1_MID2_2CK (21 << CIO2_PBM_WMCTRL1_MID2_2CK_SHIFT) +#define CIO2_REG_PBM_WMCTRL2 0x1468 +#define CIO2_PBM_WMCTRL2_HWM_2CK 40 +#define CIO2_PBM_WMCTRL2_HWM_2CK_SHIFT 0 +#define CIO2_PBM_WMCTRL2_LWM_2CK 22 +#define CIO2_PBM_WMCTRL2_LWM_2CK_SHIFT 8 +#define CIO2_PBM_WMCTRL2_OBFFWM_2CK 2 +#define CIO2_PBM_WMCTRL2_OBFFWM_2CK_SHIFT 16 +#define CIO2_PBM_WMCTRL2_TRANSDYN 1 +#define CIO2_PBM_WMCTRL2_TRANSDYN_SHIFT 24 +#define CIO2_PBM_WMCTRL2_DYNWMEN BIT(28) +#define CIO2_PBM_WMCTRL2_OBFF_MEM_EN BIT(29) +#define CIO2_PBM_WMCTRL2_OBFF_CPU_EN BIT(30) +#define CIO2_PBM_WMCTRL2_DRAINNOW BIT(31) +#define CIO2_REG_PBM_TS_COUNT 0x146c +#define CIO2_REG_PBM_FOPN_ABORT 0x1474 +/* below n = 0..3 */ +#define CIO2_PBM_FOPN_ABORT(n) (0x1 << 8 * (n)) +#define CIO2_PBM_FOPN_FORCE_ABORT(n) (0x2 << 8 * (n)) +#define CIO2_PBM_FOPN_FRAMEOPEN(n) (0x8 << 8 * (n)) +#define CIO2_REG_LTRCTRL 0x1480 +#define CIO2_LTRCTRL_LTRDYNEN BIT(16) +#define CIO2_LTRCTRL_LTRSTABLETIME_SHIFT 8 +#define CIO2_LTRCTRL_LTRSTABLETIME_MASK 0xff +#define CIO2_LTRCTRL_LTRSEL1S3 BIT(7) +#define CIO2_LTRCTRL_LTRSEL1S2 BIT(6) +#define CIO2_LTRCTRL_LTRSEL1S1 BIT(5) +#define CIO2_LTRCTRL_LTRSEL1S0 BIT(4) +#define CIO2_LTRCTRL_LTRSEL2S3 BIT(3) +#define CIO2_LTRCTRL_LTRSEL2S2 BIT(2) +#define CIO2_LTRCTRL_LTRSEL2S1 BIT(1) +#define CIO2_LTRCTRL_LTRSEL2S0 BIT(0) +#define CIO2_REG_LTRVAL23 0x1484 +#define CIO2_REG_LTRVAL01 0x1488 +#define CIO2_LTRVAL02_VAL_SHIFT 0 +#define CIO2_LTRVAL02_SCALE_SHIFT 10 +#define CIO2_LTRVAL13_VAL_SHIFT 16 +#define CIO2_LTRVAL13_SCALE_SHIFT 26 + +#define CIO2_LTRVAL0_VAL 175 +/* Value times 1024 ns */ +#define CIO2_LTRVAL0_SCALE 2 +#define CIO2_LTRVAL1_VAL 90 +#define CIO2_LTRVAL1_SCALE 2 +#define CIO2_LTRVAL2_VAL 90 +#define CIO2_LTRVAL2_SCALE 2 +#define CIO2_LTRVAL3_VAL 90 +#define CIO2_LTRVAL3_SCALE 2 + +#define CIO2_REG_CDMABA(n) (0x1500 + 0x10 * (n)) /* n = 0..19 */ +#define CIO2_REG_CDMARI(n) (0x1504 + 0x10 * (n)) +#define CIO2_CDMARI_FBPT_RP_SHIFT 0 +#define CIO2_CDMARI_FBPT_RP_MASK 0xff +#define CIO2_REG_CDMAC0(n) (0x1508 + 0x10 * (n)) +#define CIO2_CDMAC0_FBPT_LEN_SHIFT 0 +#define CIO2_CDMAC0_FBPT_WIDTH_SHIFT 8 +#define CIO2_CDMAC0_FBPT_NS BIT(25) +#define CIO2_CDMAC0_DMA_INTR_ON_FS BIT(26) +#define CIO2_CDMAC0_DMA_INTR_ON_FE BIT(27) +#define CIO2_CDMAC0_FBPT_UPDATE_FIFO_FULL BIT(28) +#define CIO2_CDMAC0_FBPT_FIFO_FULL_FIX_DIS BIT(29) +#define CIO2_CDMAC0_DMA_EN BIT(30) +#define CIO2_CDMAC0_DMA_HALTED BIT(31) +#define CIO2_REG_CDMAC1(n) (0x150c + 0x10 * (n)) +#define CIO2_CDMAC1_LINENUMINT_SHIFT 0 +#define CIO2_CDMAC1_LINENUMUPDATE_SHIFT 16 +/* n = 0..3 */ +#define CIO2_REG_PXM_PXF_FMT_CFG0(n) (0x1700 + 0x30 * (n)) +#define CIO2_PXM_PXF_FMT_CFG_SID0_SHIFT 0 +#define CIO2_PXM_PXF_FMT_CFG_SID1_SHIFT 16 +#define CIO2_PXM_PXF_FMT_CFG_PCK_64B (0 << 0) +#define CIO2_PXM_PXF_FMT_CFG_PCK_32B (1 << 0) +#define CIO2_PXM_PXF_FMT_CFG_BPP_08 (0 << 2) +#define CIO2_PXM_PXF_FMT_CFG_BPP_10 (1 << 2) +#define CIO2_PXM_PXF_FMT_CFG_BPP_12 (2 << 2) +#define CIO2_PXM_PXF_FMT_CFG_BPP_14 (3 << 2) +#define CIO2_PXM_PXF_FMT_CFG_SPEC_4PPC (0 << 4) +#define CIO2_PXM_PXF_FMT_CFG_SPEC_3PPC_RGBA (1 << 4) +#define CIO2_PXM_PXF_FMT_CFG_SPEC_3PPC_ARGB (2 << 4) +#define CIO2_PXM_PXF_FMT_CFG_SPEC_PLANAR2 (3 << 4) +#define CIO2_PXM_PXF_FMT_CFG_SPEC_PLANAR3 (4 << 4) +#define CIO2_PXM_PXF_FMT_CFG_SPEC_NV16 (5 << 4) +#define CIO2_PXM_PXF_FMT_CFG_PSWAP4_1ST_AB (1 << 7) +#define CIO2_PXM_PXF_FMT_CFG_PSWAP4_1ST_CD (1 << 8) +#define CIO2_PXM_PXF_FMT_CFG_PSWAP4_2ND_AC (1 << 9) +#define CIO2_PXM_PXF_FMT_CFG_PSWAP4_2ND_BD (1 << 10) +#define CIO2_REG_INT_STS_EXT_IE 0x17e4 +#define CIO2_REG_INT_EN_EXT_IE 0x17e8 +#define CIO2_INT_EXT_IE_ECC_RE(n) (0x01 << (8 * (n))) +#define CIO2_INT_EXT_IE_DPHY_NR(n) (0x02 << (8 * (n))) +#define CIO2_INT_EXT_IE_ECC_NR(n) (0x04 << (8 * (n))) +#define CIO2_INT_EXT_IE_CRCERR(n) (0x08 << (8 * (n))) +#define CIO2_INT_EXT_IE_INTERFRAMEDATA(n) (0x10 << (8 * (n))) +#define CIO2_INT_EXT_IE_PKT2SHORT(n) (0x20 << (8 * (n))) +#define CIO2_INT_EXT_IE_PKT2LONG(n) (0x40 << (8 * (n))) +#define CIO2_INT_EXT_IE_IRQ(n) (0x80 << (8 * (n))) +#define CIO2_REG_PXM_FRF_CFG(n) (0x1720 + 0x30 * (n)) +#define CIO2_PXM_FRF_CFG_FNSEL BIT(0) +#define CIO2_PXM_FRF_CFG_FN_RST BIT(1) +#define CIO2_PXM_FRF_CFG_ABORT BIT(2) +#define CIO2_PXM_FRF_CFG_CRC_TH_SHIFT 3 +#define CIO2_PXM_FRF_CFG_MSK_ECC_DPHY_NR BIT(8) +#define CIO2_PXM_FRF_CFG_MSK_ECC_RE BIT(9) +#define CIO2_PXM_FRF_CFG_MSK_ECC_DPHY_NE BIT(10) +#define CIO2_PXM_FRF_CFG_EVEN_ODD_MODE_SHIFT 11 +#define CIO2_PXM_FRF_CFG_MASK_CRC_THRES BIT(13) +#define CIO2_PXM_FRF_CFG_MASK_CSI_ACCEPT BIT(14) +#define CIO2_PXM_FRF_CFG_CIOHC_FS_MODE BIT(15) +#define CIO2_PXM_FRF_CFG_CIOHC_FRST_FRM_SHIFT 16 +#define CIO2_REG_PXM_SID2BID0(n) (0x1724 + 0x30 * (n)) +#define CIO2_FB_HPLL_FREQ 0x2 +#define CIO2_ISCLK_RATIO 0xc + +#define CIO2_IRQCTRL_MASK 0x3ffff + +#define CIO2_INT_EN_EXT_OE_MASK 0x8f0fffff + +#define CIO2_CGC_CLKGATE_HOLDOFF 3 +#define CIO2_CGC_CSI_CLKGATE_HOLDOFF 5 + +#define CIO2_PXM_FRF_CFG_CRC_TH 16 + +#define CIO2_INT_EN_EXT_IE_MASK 0xffffffff + +#define CIO2_DMA_CHAN 0 + +#define CIO2_CSIRX_DLY_CNT_CLANE_IDX -1 + +#define CIO2_CSIRX_DLY_CNT_TERMEN_CLANE_A 0 +#define CIO2_CSIRX_DLY_CNT_TERMEN_CLANE_B 0 +#define CIO2_CSIRX_DLY_CNT_SETTLE_CLANE_A 95 +#define CIO2_CSIRX_DLY_CNT_SETTLE_CLANE_B -8 + +#define CIO2_CSIRX_DLY_CNT_TERMEN_DLANE_A 0 +#define CIO2_CSIRX_DLY_CNT_TERMEN_DLANE_B 0 +#define CIO2_CSIRX_DLY_CNT_SETTLE_DLANE_A 85 +#define CIO2_CSIRX_DLY_CNT_SETTLE_DLANE_B -2 + +#define CIO2_CSIRX_DLY_CNT_TERMEN_DEFAULT 0x4 +#define CIO2_CSIRX_DLY_CNT_SETTLE_DEFAULT 0x570 + +#define CIO2_PMCSR_OFFSET 4 +#define CIO2_PMCSR_D0D3_SHIFT 2 +#define CIO2_PMCSR_D3 0x3 + +struct cio2_csi2_timing { + s32 clk_termen; + s32 clk_settle; + s32 dat_termen; + s32 dat_settle; +}; + +struct cio2_buffer { + struct vb2_v4l2_buffer vbb; + u32 *lop[CIO2_MAX_LOPS]; + dma_addr_t lop_bus_addr[CIO2_MAX_LOPS]; + unsigned int offset; +}; + +struct csi2_bus_info { + u32 port; + u32 lanes; +}; + +struct cio2_queue { + /* mutex to be used by vb2_queue */ + struct mutex lock; + struct media_pipeline pipe; + struct csi2_bus_info csi2; + struct v4l2_subdev *sensor; + void __iomem *csi_rx_base; + + /* Subdev, /dev/v4l-subdevX */ + struct v4l2_subdev subdev; + struct media_pad subdev_pads[CIO2_PADS]; + struct v4l2_mbus_framefmt subdev_fmt; + atomic_t frame_sequence; + + /* Video device, /dev/videoX */ + struct video_device vdev; + struct media_pad vdev_pad; + struct v4l2_pix_format_mplane format; + struct vb2_queue vbq; + + /* Buffer queue handling */ + struct cio2_fbpt_entry *fbpt; /* Frame buffer pointer table */ + dma_addr_t fbpt_bus_addr; + struct cio2_buffer *bufs[CIO2_MAX_BUFFERS]; + unsigned int bufs_first; /* Index of the first used entry */ + unsigned int bufs_next; /* Index of the first unused entry */ + atomic_t bufs_queued; +}; + +struct cio2_device { + struct pci_dev *pci_dev; + void __iomem *base; + struct v4l2_device v4l2_dev; + struct cio2_queue queue[CIO2_QUEUES]; + struct cio2_queue *cur_queue; + /* mutex to be used by video_device */ + struct mutex lock; + + bool streaming; + struct v4l2_async_notifier notifier; + struct media_device media_dev; + + /* + * Safety net to catch DMA fetch ahead + * when reaching the end of LOP + */ + void *dummy_page; + /* DMA handle of dummy_page */ + dma_addr_t dummy_page_bus_addr; + /* single List of Pointers (LOP) page */ + u32 *dummy_lop; + /* DMA handle of dummy_lop */ + dma_addr_t dummy_lop_bus_addr; +}; + +/**************** Virtual channel ****************/ +/* + * This should come from sensor driver. No + * driver interface nor requirement yet. + */ +#define SENSOR_VIR_CH_DFLT 0 + +/**************** FBPT operations ****************/ +#define CIO2_FBPT_SIZE (CIO2_MAX_BUFFERS * CIO2_MAX_LOPS * \ + sizeof(struct cio2_fbpt_entry)) + +#define CIO2_FBPT_SUBENTRY_UNIT 4 +#define CIO2_PAGE_SIZE PAGE_SIZE + +/* cio2 fbpt first_entry ctrl status */ +#define CIO2_FBPT_CTRL_VALID BIT(0) +#define CIO2_FBPT_CTRL_IOC BIT(1) +#define CIO2_FBPT_CTRL_IOS BIT(2) +#define CIO2_FBPT_CTRL_SUCCXFAIL BIT(3) +#define CIO2_FBPT_CTRL_CMPLCODE_SHIFT 4 + +/* + * Frame Buffer Pointer Table(FBPT) entry + * each entry describe an output buffer and consists of + * several sub-entries + */ +struct __packed cio2_fbpt_entry { + union { + struct __packed { + u32 ctrl; /* status ctrl */ + u16 cur_line_num; /* current line # written to DDR */ + u16 frame_num; /* updated by DMA upon FE */ + u32 first_page_offset; /* offset for 1st page in LOP */ + } first_entry; + /* Second entry per buffer */ + struct __packed { + u32 timestamp; + u32 num_of_bytes; + /* the number of bytes for write on last page */ + u16 last_page_available_bytes; + /* the number of pages allocated for this buf */ + u16 num_of_pages; + } second_entry; + }; + u32 lop_page_addr; /* Points to list of pointers (LOP) table */ +}; + +static inline struct cio2_queue *file_to_cio2_queue(struct file *file) +{ + return container_of(video_devdata(file), struct cio2_queue, vdev); +} + +static inline struct cio2_queue *vb2q_to_cio2_queue(struct vb2_queue *vq) +{ + return container_of(vq, struct cio2_queue, vbq); +} + +#endif diff --git a/drivers/media/pci/ivtv/Makefile b/drivers/media/pci/ivtv/Makefile index 48f8a23f9a0f..5de95dbe3256 100644 --- a/drivers/media/pci/ivtv/Makefile +++ b/drivers/media/pci/ivtv/Makefile @@ -10,8 +10,6 @@ obj-$(CONFIG_VIDEO_IVTV) += ivtv.o obj-$(CONFIG_VIDEO_IVTV_ALSA) += ivtv-alsa.o obj-$(CONFIG_VIDEO_FB_IVTV) += ivtvfb.o -ccflags-y += -I$(srctree)/drivers/media/i2c ccflags-y += -I$(srctree)/drivers/media/tuners -ccflags-y += -I$(srctree)/drivers/media/dvb-core ccflags-y += -I$(srctree)/drivers/media/dvb-frontends diff --git a/drivers/media/pci/ivtv/ivtv-cards.h b/drivers/media/pci/ivtv/ivtv-cards.h index e6f5c02981f1..06e7b4ed6444 100644 --- a/drivers/media/pci/ivtv/ivtv-cards.h +++ b/drivers/media/pci/ivtv/ivtv-cards.h @@ -109,24 +109,16 @@ #define IVTV_HW_I2C_IR_RX_AVER (1 << 16) #define IVTV_HW_I2C_IR_RX_HAUP_EXT (1 << 17) /* External before internal */ #define IVTV_HW_I2C_IR_RX_HAUP_INT (1 << 18) -#define IVTV_HW_Z8F0811_IR_TX_HAUP (1 << 19) -#define IVTV_HW_Z8F0811_IR_RX_HAUP (1 << 20) -#define IVTV_HW_I2C_IR_RX_ADAPTEC (1 << 21) - -#define IVTV_HW_Z8F0811_IR_HAUP (IVTV_HW_Z8F0811_IR_RX_HAUP | \ - IVTV_HW_Z8F0811_IR_TX_HAUP) +#define IVTV_HW_Z8F0811_IR_HAUP (1 << 19) +#define IVTV_HW_I2C_IR_RX_ADAPTEC (1 << 20) #define IVTV_HW_SAA711X (IVTV_HW_SAA7115 | IVTV_HW_SAA7114) -#define IVTV_HW_IR_RX_ANY (IVTV_HW_I2C_IR_RX_AVER | \ - IVTV_HW_I2C_IR_RX_HAUP_EXT | \ - IVTV_HW_I2C_IR_RX_HAUP_INT | \ - IVTV_HW_Z8F0811_IR_RX_HAUP | \ - IVTV_HW_I2C_IR_RX_ADAPTEC) - -#define IVTV_HW_IR_TX_ANY (IVTV_HW_Z8F0811_IR_TX_HAUP) - -#define IVTV_HW_IR_ANY (IVTV_HW_IR_RX_ANY | IVTV_HW_IR_TX_ANY) +#define IVTV_HW_IR_ANY (IVTV_HW_I2C_IR_RX_AVER | \ + IVTV_HW_I2C_IR_RX_HAUP_EXT | \ + IVTV_HW_I2C_IR_RX_HAUP_INT | \ + IVTV_HW_Z8F0811_IR_HAUP | \ + IVTV_HW_I2C_IR_RX_ADAPTEC) /* video inputs */ #define IVTV_CARD_INPUT_VID_TUNER 1 diff --git a/drivers/media/pci/ivtv/ivtv-i2c.c b/drivers/media/pci/ivtv/ivtv-i2c.c index 893962ac85de..66696e6ee587 100644 --- a/drivers/media/pci/ivtv/ivtv-i2c.c +++ b/drivers/media/pci/ivtv/ivtv-i2c.c @@ -117,8 +117,7 @@ static const u8 hw_addrs[] = { IVTV_AVERMEDIA_IR_RX_I2C_ADDR, /* IVTV_HW_I2C_IR_RX_AVER */ IVTV_HAUP_EXT_IR_RX_I2C_ADDR, /* IVTV_HW_I2C_IR_RX_HAUP_EXT */ IVTV_HAUP_INT_IR_RX_I2C_ADDR, /* IVTV_HW_I2C_IR_RX_HAUP_INT */ - IVTV_Z8F0811_IR_TX_I2C_ADDR, /* IVTV_HW_Z8F0811_IR_TX_HAUP */ - IVTV_Z8F0811_IR_RX_I2C_ADDR, /* IVTV_HW_Z8F0811_IR_RX_HAUP */ + IVTV_Z8F0811_IR_RX_I2C_ADDR, /* IVTV_HW_Z8F0811_IR_HAUP */ IVTV_ADAPTEC_IR_ADDR, /* IVTV_HW_I2C_IR_RX_ADAPTEC */ }; @@ -143,8 +142,7 @@ static const char * const hw_devicenames[] = { "ir_video", /* IVTV_HW_I2C_IR_RX_AVER */ "ir_video", /* IVTV_HW_I2C_IR_RX_HAUP_EXT */ "ir_video", /* IVTV_HW_I2C_IR_RX_HAUP_INT */ - "ir_tx_z8f0811_haup", /* IVTV_HW_Z8F0811_IR_TX_HAUP */ - "ir_rx_z8f0811_haup", /* IVTV_HW_Z8F0811_IR_RX_HAUP */ + "ir_z8f0811_haup", /* IVTV_HW_Z8F0811_IR_HAUP */ "ir_video", /* IVTV_HW_I2C_IR_RX_ADAPTEC */ }; @@ -181,18 +179,8 @@ static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr) struct IR_i2c_init_data *init_data = &itv->ir_i2c_init_data; unsigned short addr_list[2] = { addr, I2C_CLIENT_END }; - /* Only allow one IR transmitter to be registered per board */ - if (hw & IVTV_HW_IR_TX_ANY) { - if (itv->hw_flags & IVTV_HW_IR_TX_ANY) - return -1; - memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, type, I2C_NAME_SIZE); - return i2c_new_probed_device(adap, &info, addr_list, NULL) - == NULL ? -1 : 0; - } - /* Only allow one IR receiver to be registered per board */ - if (itv->hw_flags & IVTV_HW_IR_RX_ANY) + if (itv->hw_flags & IVTV_HW_IR_ANY) return -1; /* Our default information for ir-kbd-i2c.c to use */ @@ -211,7 +199,7 @@ static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr) init_data->type = RC_PROTO_BIT_RC5; init_data->name = itv->card_name; break; - case IVTV_HW_Z8F0811_IR_RX_HAUP: + case IVTV_HW_Z8F0811_IR_HAUP: /* Default to grey remote */ init_data->ir_codes = RC_MAP_HAUPPAUGE; init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; diff --git a/drivers/media/pci/mantis/Makefile b/drivers/media/pci/mantis/Makefile index a684dc2ec79e..b5ef39692cb0 100644 --- a/drivers/media/pci/mantis/Makefile +++ b/drivers/media/pci/mantis/Makefile @@ -26,4 +26,4 @@ obj-$(CONFIG_MANTIS_CORE) += mantis_core.o obj-$(CONFIG_DVB_MANTIS) += mantis.o obj-$(CONFIG_DVB_HOPPER) += hopper.o -ccflags-y += -Idrivers/media/dvb-core/ -Idrivers/media/dvb-frontends/ +ccflags-y += -Idrivers/media/dvb-frontends/ diff --git a/drivers/media/pci/mantis/hopper_cards.c b/drivers/media/pci/mantis/hopper_cards.c index ed855e3df558..89759cb80ecb 100644 --- a/drivers/media/pci/mantis/hopper_cards.c +++ b/drivers/media/pci/mantis/hopper_cards.c @@ -26,11 +26,11 @@ #include <asm/irq.h> #include <linux/interrupt.h> -#include "dmxdev.h" -#include "dvbdev.h" -#include "dvb_demux.h" -#include "dvb_frontend.h" -#include "dvb_net.h" +#include <media/dmxdev.h> +#include <media/dvbdev.h> +#include <media/dvb_demux.h> +#include <media/dvb_frontend.h> +#include <media/dvb_net.h> #include "mantis_common.h" #include "hopper_vp3028.h" diff --git a/drivers/media/pci/mantis/hopper_vp3028.c b/drivers/media/pci/mantis/hopper_vp3028.c index 1032db6bb789..d58ae0097fea 100644 --- a/drivers/media/pci/mantis/hopper_vp3028.c +++ b/drivers/media/pci/mantis/hopper_vp3028.c @@ -22,11 +22,11 @@ #include <linux/sched.h> #include <linux/interrupt.h> -#include "dmxdev.h" -#include "dvbdev.h" -#include "dvb_demux.h" -#include "dvb_frontend.h" -#include "dvb_net.h" +#include <media/dmxdev.h> +#include <media/dvbdev.h> +#include <media/dvb_demux.h> +#include <media/dvb_frontend.h> +#include <media/dvb_net.h> #include "zl10353.h" #include "mantis_common.h" diff --git a/drivers/media/pci/mantis/mantis_ca.c b/drivers/media/pci/mantis/mantis_ca.c index 60c6c2f24066..4f0ba457c7e5 100644 --- a/drivers/media/pci/mantis/mantis_ca.c +++ b/drivers/media/pci/mantis/mantis_ca.c @@ -24,11 +24,11 @@ #include <linux/interrupt.h> #include <asm/io.h> -#include "dmxdev.h" -#include "dvbdev.h" -#include "dvb_demux.h" -#include "dvb_frontend.h" -#include "dvb_net.h" +#include <media/dmxdev.h> +#include <media/dvbdev.h> +#include <media/dvb_demux.h> +#include <media/dvb_frontend.h> +#include <media/dvb_net.h> #include "mantis_common.h" #include "mantis_link.h" diff --git a/drivers/media/pci/mantis/mantis_cards.c b/drivers/media/pci/mantis/mantis_cards.c index 4ce8a90d69dc..7eb75cb7d75a 100644 --- a/drivers/media/pci/mantis/mantis_cards.c +++ b/drivers/media/pci/mantis/mantis_cards.c @@ -27,11 +27,11 @@ #include <linux/interrupt.h> #include <media/rc-map.h> -#include "dmxdev.h" -#include "dvbdev.h" -#include "dvb_demux.h" -#include "dvb_frontend.h" -#include "dvb_net.h" +#include <media/dmxdev.h> +#include <media/dvbdev.h> +#include <media/dvb_demux.h> +#include <media/dvb_frontend.h> +#include <media/dvb_net.h> #include "mantis_common.h" diff --git a/drivers/media/pci/mantis/mantis_dma.c b/drivers/media/pci/mantis/mantis_dma.c index 2ce310b0a022..84406a428330 100644 --- a/drivers/media/pci/mantis/mantis_dma.c +++ b/drivers/media/pci/mantis/mantis_dma.c @@ -28,11 +28,11 @@ #include <linux/sched.h> #include <linux/interrupt.h> -#include "dmxdev.h" -#include "dvbdev.h" -#include "dvb_demux.h" -#include "dvb_frontend.h" -#include "dvb_net.h" +#include <media/dmxdev.h> +#include <media/dvbdev.h> +#include <media/dvb_demux.h> +#include <media/dvb_frontend.h> +#include <media/dvb_net.h> #include "mantis_common.h" #include "mantis_reg.h" diff --git a/drivers/media/pci/mantis/mantis_dvb.c b/drivers/media/pci/mantis/mantis_dvb.c index 0db4de3a2285..54dbaa700fa3 100644 --- a/drivers/media/pci/mantis/mantis_dvb.c +++ b/drivers/media/pci/mantis/mantis_dvb.c @@ -26,11 +26,11 @@ #include <linux/pci.h> #include <linux/i2c.h> -#include "dmxdev.h" -#include "dvbdev.h" -#include "dvb_demux.h" -#include "dvb_frontend.h" -#include "dvb_net.h" +#include <media/dmxdev.h> +#include <media/dvbdev.h> +#include <media/dvb_demux.h> +#include <media/dvb_frontend.h> +#include <media/dvb_net.h> #include "mantis_common.h" #include "mantis_dma.h" diff --git a/drivers/media/pci/mantis/mantis_evm.c b/drivers/media/pci/mantis/mantis_evm.c index 909ff54868a3..443ac5ab4902 100644 --- a/drivers/media/pci/mantis/mantis_evm.c +++ b/drivers/media/pci/mantis/mantis_evm.c @@ -25,11 +25,11 @@ #include <linux/interrupt.h> #include <asm/io.h> -#include "dmxdev.h" -#include "dvbdev.h" -#include "dvb_demux.h" -#include "dvb_frontend.h" -#include "dvb_net.h" +#include <media/dmxdev.h> +#include <media/dvbdev.h> +#include <media/dvb_demux.h> +#include <media/dvb_frontend.h> +#include <media/dvb_net.h> #include "mantis_common.h" #include "mantis_link.h" diff --git a/drivers/media/pci/mantis/mantis_hif.c b/drivers/media/pci/mantis/mantis_hif.c index 10c68df7e16f..bf61f8c5a59f 100644 --- a/drivers/media/pci/mantis/mantis_hif.c +++ b/drivers/media/pci/mantis/mantis_hif.c @@ -25,11 +25,11 @@ #include <linux/interrupt.h> #include <asm/io.h> -#include "dmxdev.h" -#include "dvbdev.h" -#include "dvb_demux.h" -#include "dvb_frontend.h" -#include "dvb_net.h" +#include <media/dmxdev.h> +#include <media/dvbdev.h> +#include <media/dvb_demux.h> +#include <media/dvb_frontend.h> +#include <media/dvb_net.h> #include "mantis_common.h" diff --git a/drivers/media/pci/mantis/mantis_i2c.c b/drivers/media/pci/mantis/mantis_i2c.c index 496c10dfc4df..6528a2180119 100644 --- a/drivers/media/pci/mantis/mantis_i2c.c +++ b/drivers/media/pci/mantis/mantis_i2c.c @@ -23,11 +23,11 @@ #include <linux/pci.h> #include <linux/i2c.h> -#include "dmxdev.h" -#include "dvbdev.h" -#include "dvb_demux.h" -#include "dvb_frontend.h" -#include "dvb_net.h" +#include <media/dmxdev.h> +#include <media/dvbdev.h> +#include <media/dvb_demux.h> +#include <media/dvb_frontend.h> +#include <media/dvb_net.h> #include "mantis_common.h" #include "mantis_reg.h" diff --git a/drivers/media/pci/mantis/mantis_input.c b/drivers/media/pci/mantis/mantis_input.c index 7519dcc934dd..5b472e9b9542 100644 --- a/drivers/media/pci/mantis/mantis_input.c +++ b/drivers/media/pci/mantis/mantis_input.c @@ -17,11 +17,11 @@ #include <media/rc-core.h> #include <linux/pci.h> -#include "dmxdev.h" -#include "dvbdev.h" -#include "dvb_demux.h" -#include "dvb_frontend.h" -#include "dvb_net.h" +#include <media/dmxdev.h> +#include <media/dvbdev.h> +#include <media/dvb_demux.h> +#include <media/dvb_frontend.h> +#include <media/dvb_net.h> #include "mantis_common.h" #include "mantis_input.h" diff --git a/drivers/media/pci/mantis/mantis_ioc.c b/drivers/media/pci/mantis/mantis_ioc.c index 24fcdc63d6d5..f45c2340a493 100644 --- a/drivers/media/pci/mantis/mantis_ioc.c +++ b/drivers/media/pci/mantis/mantis_ioc.c @@ -26,11 +26,11 @@ #include <linux/interrupt.h> #include <asm/io.h> -#include "dmxdev.h" -#include "dvbdev.h" -#include "dvb_demux.h" -#include "dvb_frontend.h" -#include "dvb_net.h" +#include <media/dmxdev.h> +#include <media/dvbdev.h> +#include <media/dvb_demux.h> +#include <media/dvb_frontend.h> +#include <media/dvb_net.h> #include "mantis_common.h" #include "mantis_reg.h" diff --git a/drivers/media/pci/mantis/mantis_link.h b/drivers/media/pci/mantis/mantis_link.h index 2a814774a001..c6698976fc2f 100644 --- a/drivers/media/pci/mantis/mantis_link.h +++ b/drivers/media/pci/mantis/mantis_link.h @@ -23,7 +23,7 @@ #include <linux/mutex.h> #include <linux/workqueue.h> -#include "dvb_ca_en50221.h" +#include <media/dvb_ca_en50221.h> enum mantis_sbuf_status { MANTIS_SBUF_DATA_AVAIL = 1, diff --git a/drivers/media/pci/mantis/mantis_pci.c b/drivers/media/pci/mantis/mantis_pci.c index 9e89e045213a..d590524b4171 100644 --- a/drivers/media/pci/mantis/mantis_pci.c +++ b/drivers/media/pci/mantis/mantis_pci.c @@ -34,11 +34,11 @@ #include <linux/sched.h> #include <linux/interrupt.h> -#include "dmxdev.h" -#include "dvbdev.h" -#include "dvb_demux.h" -#include "dvb_frontend.h" -#include "dvb_net.h" +#include <media/dmxdev.h> +#include <media/dvbdev.h> +#include <media/dvb_demux.h> +#include <media/dvb_frontend.h> +#include <media/dvb_net.h> #include "mantis_common.h" #include "mantis_reg.h" diff --git a/drivers/media/pci/mantis/mantis_pcmcia.c b/drivers/media/pci/mantis/mantis_pcmcia.c index b2dbc7b2e0f6..2a316b988c07 100644 --- a/drivers/media/pci/mantis/mantis_pcmcia.c +++ b/drivers/media/pci/mantis/mantis_pcmcia.c @@ -25,11 +25,11 @@ #include <linux/interrupt.h> #include <asm/io.h> -#include "dmxdev.h" -#include "dvbdev.h" -#include "dvb_demux.h" -#include "dvb_frontend.h" -#include "dvb_net.h" +#include <media/dmxdev.h> +#include <media/dvbdev.h> +#include <media/dvb_demux.h> +#include <media/dvb_frontend.h> +#include <media/dvb_net.h> #include "mantis_common.h" #include "mantis_link.h" /* temporary due to physical layer stuff */ diff --git a/drivers/media/pci/mantis/mantis_uart.c b/drivers/media/pci/mantis/mantis_uart.c index f1c96aec8c7b..18f81c135996 100644 --- a/drivers/media/pci/mantis/mantis_uart.c +++ b/drivers/media/pci/mantis/mantis_uart.c @@ -27,11 +27,11 @@ #include <linux/interrupt.h> #include <linux/pci.h> -#include "dmxdev.h" -#include "dvbdev.h" -#include "dvb_demux.h" -#include "dvb_frontend.h" -#include "dvb_net.h" +#include <media/dmxdev.h> +#include <media/dvbdev.h> +#include <media/dvb_demux.h> +#include <media/dvb_frontend.h> +#include <media/dvb_net.h> #include "mantis_common.h" #include "mantis_reg.h" diff --git a/drivers/media/pci/mantis/mantis_vp1033.c b/drivers/media/pci/mantis/mantis_vp1033.c index 12a6adb2bd7e..54d2ab409cc5 100644 --- a/drivers/media/pci/mantis/mantis_vp1033.c +++ b/drivers/media/pci/mantis/mantis_vp1033.c @@ -22,11 +22,11 @@ #include <linux/sched.h> #include <linux/interrupt.h> -#include "dmxdev.h" -#include "dvbdev.h" -#include "dvb_demux.h" -#include "dvb_frontend.h" -#include "dvb_net.h" +#include <media/dmxdev.h> +#include <media/dvbdev.h> +#include <media/dvb_demux.h> +#include <media/dvb_frontend.h> +#include <media/dvb_net.h> #include "stv0299.h" #include "mantis_common.h" diff --git a/drivers/media/pci/mantis/mantis_vp1034.c b/drivers/media/pci/mantis/mantis_vp1034.c index e4972ff823c2..26672a49b86f 100644 --- a/drivers/media/pci/mantis/mantis_vp1034.c +++ b/drivers/media/pci/mantis/mantis_vp1034.c @@ -23,11 +23,11 @@ #include <linux/interrupt.h> #include <asm/io.h> -#include "dmxdev.h" -#include "dvbdev.h" -#include "dvb_demux.h" -#include "dvb_frontend.h" -#include "dvb_net.h" +#include <media/dmxdev.h> +#include <media/dvbdev.h> +#include <media/dvb_demux.h> +#include <media/dvb_frontend.h> +#include <media/dvb_net.h> #include "mb86a16.h" #include "mantis_common.h" diff --git a/drivers/media/pci/mantis/mantis_vp1034.h b/drivers/media/pci/mantis/mantis_vp1034.h index 764b1c66ea1b..35af4e5dcc8c 100644 --- a/drivers/media/pci/mantis/mantis_vp1034.h +++ b/drivers/media/pci/mantis/mantis_vp1034.h @@ -21,7 +21,7 @@ #ifndef __MANTIS_VP1034_H #define __MANTIS_VP1034_H -#include "dvb_frontend.h" +#include <media/dvb_frontend.h> #include "mantis_common.h" diff --git a/drivers/media/pci/mantis/mantis_vp1041.c b/drivers/media/pci/mantis/mantis_vp1041.c index 7082fcbc94a1..47e0c48c3abc 100644 --- a/drivers/media/pci/mantis/mantis_vp1041.c +++ b/drivers/media/pci/mantis/mantis_vp1041.c @@ -22,11 +22,11 @@ #include <linux/sched.h> #include <linux/interrupt.h> -#include "dmxdev.h" -#include "dvbdev.h" -#include "dvb_demux.h" -#include "dvb_frontend.h" -#include "dvb_net.h" +#include <media/dmxdev.h> +#include <media/dvbdev.h> +#include <media/dvb_demux.h> +#include <media/dvb_frontend.h> +#include <media/dvb_net.h> #include "mantis_common.h" #include "mantis_ioc.h" diff --git a/drivers/media/pci/mantis/mantis_vp2033.c b/drivers/media/pci/mantis/mantis_vp2033.c index 8d48b5abe04a..d98e0a3edaab 100644 --- a/drivers/media/pci/mantis/mantis_vp2033.c +++ b/drivers/media/pci/mantis/mantis_vp2033.c @@ -22,11 +22,11 @@ #include <linux/sched.h> #include <linux/interrupt.h> -#include "dmxdev.h" -#include "dvbdev.h" -#include "dvb_demux.h" -#include "dvb_frontend.h" -#include "dvb_net.h" +#include <media/dmxdev.h> +#include <media/dvbdev.h> +#include <media/dvb_demux.h> +#include <media/dvb_frontend.h> +#include <media/dvb_net.h> #include "tda1002x.h" #include "mantis_common.h" diff --git a/drivers/media/pci/mantis/mantis_vp2040.c b/drivers/media/pci/mantis/mantis_vp2040.c index 8dd17d7c0881..2c52f3d4e2bc 100644 --- a/drivers/media/pci/mantis/mantis_vp2040.c +++ b/drivers/media/pci/mantis/mantis_vp2040.c @@ -22,11 +22,11 @@ #include <linux/sched.h> #include <linux/interrupt.h> -#include "dmxdev.h" -#include "dvbdev.h" -#include "dvb_demux.h" -#include "dvb_frontend.h" -#include "dvb_net.h" +#include <media/dmxdev.h> +#include <media/dvbdev.h> +#include <media/dvb_demux.h> +#include <media/dvb_frontend.h> +#include <media/dvb_net.h> #include "tda1002x.h" #include "mantis_common.h" diff --git a/drivers/media/pci/mantis/mantis_vp3028.h b/drivers/media/pci/mantis/mantis_vp3028.h index b07be6adc522..34130d29e0aa 100644 --- a/drivers/media/pci/mantis/mantis_vp3028.h +++ b/drivers/media/pci/mantis/mantis_vp3028.h @@ -21,7 +21,7 @@ #ifndef __MANTIS_VP3028_H #define __MANTIS_VP3028_H -#include "dvb_frontend.h" +#include <media/dvb_frontend.h> #include "mantis_common.h" #include "zl10353.h" diff --git a/drivers/media/pci/mantis/mantis_vp3030.c b/drivers/media/pci/mantis/mantis_vp3030.c index 5c1dd925bdd5..14f6e153000c 100644 --- a/drivers/media/pci/mantis/mantis_vp3030.c +++ b/drivers/media/pci/mantis/mantis_vp3030.c @@ -22,11 +22,11 @@ #include <linux/sched.h> #include <linux/interrupt.h> -#include "dmxdev.h" -#include "dvbdev.h" -#include "dvb_demux.h" -#include "dvb_frontend.h" -#include "dvb_net.h" +#include <media/dmxdev.h> +#include <media/dvbdev.h> +#include <media/dvb_demux.h> +#include <media/dvb_frontend.h> +#include <media/dvb_net.h> #include "zl10353.h" #include "tda665x.h" diff --git a/drivers/media/pci/netup_unidvb/Makefile b/drivers/media/pci/netup_unidvb/Makefile index 07d3f1eb728b..944c3e164157 100644 --- a/drivers/media/pci/netup_unidvb/Makefile +++ b/drivers/media/pci/netup_unidvb/Makefile @@ -6,5 +6,4 @@ netup-unidvb-objs += netup_unidvb_spi.o obj-$(CONFIG_DVB_NETUP_UNIDVB) += netup-unidvb.o -ccflags-y += -Idrivers/media/dvb-core ccflags-y += -Idrivers/media/dvb-frontends diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb.h b/drivers/media/pci/netup_unidvb/netup_unidvb.h index 39b08ecda1fc..3253ac324841 100644 --- a/drivers/media/pci/netup_unidvb/netup_unidvb.h +++ b/drivers/media/pci/netup_unidvb/netup_unidvb.h @@ -24,7 +24,7 @@ #include <media/v4l2-common.h> #include <media/v4l2-device.h> #include <media/videobuf2-dvb.h> -#include <dvb_ca_en50221.h> +#include <media/dvb_ca_en50221.h> #define NETUP_UNIDVB_NAME "netup_unidvb" #define NETUP_UNIDVB_VERSION "0.0.1" diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c index 509d69e6ca4a..ead59fabd15f 100644 --- a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c +++ b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c @@ -862,7 +862,7 @@ static int netup_unidvb_initdev(struct pci_dev *pci_dev, PCI_EXP_DEVCTL_NOSNOOP_EN, 0); /* Adjust PCIe completion timeout. */ pcie_capability_clear_and_set_word(pci_dev, - PCI_EXP_DEVCTL2, 0xf, 0x2); + PCI_EXP_DEVCTL2, PCI_EXP_DEVCTL2_COMP_TIMEOUT, 0x2); if (netup_unidvb_request_mmio(pci_dev)) { dev_err(&pci_dev->dev, diff --git a/drivers/media/pci/ngene/Makefile b/drivers/media/pci/ngene/Makefile index dbdf284970f8..e4208f5ed215 100644 --- a/drivers/media/pci/ngene/Makefile +++ b/drivers/media/pci/ngene/Makefile @@ -7,7 +7,6 @@ ngene-objs := ngene-core.o ngene-i2c.o ngene-cards.o ngene-dvb.o obj-$(CONFIG_DVB_NGENE) += ngene.o -ccflags-y += -Idrivers/media/dvb-core/ ccflags-y += -Idrivers/media/dvb-frontends/ ccflags-y += -Idrivers/media/tuners/ diff --git a/drivers/media/pci/ngene/ngene.h b/drivers/media/pci/ngene/ngene.h index 7c7cd217333d..02dbd18f92d0 100644 --- a/drivers/media/pci/ngene/ngene.h +++ b/drivers/media/pci/ngene/ngene.h @@ -29,13 +29,13 @@ #include <linux/dvb/frontend.h> -#include "dmxdev.h" -#include "dvbdev.h" -#include "dvb_demux.h" -#include "dvb_ca_en50221.h" -#include "dvb_frontend.h" -#include "dvb_ringbuffer.h" -#include "dvb_net.h" +#include <media/dmxdev.h> +#include <media/dvbdev.h> +#include <media/dvb_demux.h> +#include <media/dvb_ca_en50221.h> +#include <media/dvb_frontend.h> +#include <media/dvb_ringbuffer.h> +#include <media/dvb_net.h> #include "cxd2099.h" #define DEVICE_NAME "ngene" diff --git a/drivers/media/pci/pluto2/Makefile b/drivers/media/pci/pluto2/Makefile index 524bf841f42b..3c2aea1ac752 100644 --- a/drivers/media/pci/pluto2/Makefile +++ b/drivers/media/pci/pluto2/Makefile @@ -1,3 +1,3 @@ obj-$(CONFIG_DVB_PLUTO2) += pluto2.o -ccflags-y += -Idrivers/media/dvb-core/ -Idrivers/media/dvb-frontends/ +ccflags-y += -Idrivers/media/dvb-frontends/ diff --git a/drivers/media/pci/pluto2/pluto2.c b/drivers/media/pci/pluto2/pluto2.c index 39dcba2b620c..ecdca0ba3e66 100644 --- a/drivers/media/pci/pluto2/pluto2.c +++ b/drivers/media/pci/pluto2/pluto2.c @@ -29,12 +29,12 @@ #include <linux/dma-mapping.h> #include <linux/slab.h> -#include "demux.h" -#include "dmxdev.h" -#include "dvb_demux.h" -#include "dvb_frontend.h" -#include "dvb_net.h" -#include "dvbdev.h" +#include <media/demux.h> +#include <media/dmxdev.h> +#include <media/dvb_demux.h> +#include <media/dvb_frontend.h> +#include <media/dvb_net.h> +#include <media/dvbdev.h> #include "tda1004x.h" DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); diff --git a/drivers/media/pci/pt1/Makefile b/drivers/media/pci/pt1/Makefile index 98e391295afe..ab873ae088a0 100644 --- a/drivers/media/pci/pt1/Makefile +++ b/drivers/media/pci/pt1/Makefile @@ -2,4 +2,4 @@ earth-pt1-objs := pt1.o va1j5jf8007s.o va1j5jf8007t.o obj-$(CONFIG_DVB_PT1) += earth-pt1.o -ccflags-y += -Idrivers/media/dvb-core -Idrivers/media/dvb-frontends +ccflags-y += -Idrivers/media/dvb-frontends diff --git a/drivers/media/pci/pt1/pt1.c b/drivers/media/pci/pt1/pt1.c index b6b1a8d20d86..ac16cf3b065b 100644 --- a/drivers/media/pci/pt1/pt1.c +++ b/drivers/media/pci/pt1/pt1.c @@ -27,11 +27,11 @@ #include <linux/freezer.h> #include <linux/ratelimit.h> -#include "dvbdev.h" -#include "dvb_demux.h" -#include "dmxdev.h" -#include "dvb_net.h" -#include "dvb_frontend.h" +#include <media/dvbdev.h> +#include <media/dvb_demux.h> +#include <media/dmxdev.h> +#include <media/dvb_net.h> +#include <media/dvb_frontend.h> #include "va1j5jf8007t.h" #include "va1j5jf8007s.h" @@ -116,8 +116,8 @@ static u32 pt1_read_reg(struct pt1 *pt1, int reg) return readl(pt1->regs + reg * 4); } -static int pt1_nr_tables = 8; -module_param_named(nr_tables, pt1_nr_tables, int, 0); +static unsigned int pt1_nr_tables = 8; +module_param_named(nr_tables, pt1_nr_tables, uint, 0); static void pt1_increment_table_count(struct pt1 *pt1) { @@ -443,6 +443,9 @@ static int pt1_init_tables(struct pt1 *pt1) int i, ret; u32 first_pfn, pfn; + if (!pt1_nr_tables) + return 0; + tables = vmalloc(sizeof(struct pt1_table) * pt1_nr_tables); if (tables == NULL) return -ENOMEM; @@ -450,12 +453,10 @@ static int pt1_init_tables(struct pt1 *pt1) pt1_init_table_count(pt1); i = 0; - if (pt1_nr_tables) { - ret = pt1_init_table(pt1, &tables[0], &first_pfn); - if (ret) - goto err; - i++; - } + ret = pt1_init_table(pt1, &tables[0], &first_pfn); + if (ret) + goto err; + i++; while (i < pt1_nr_tables) { ret = pt1_init_table(pt1, &tables[i], &pfn); diff --git a/drivers/media/pci/pt1/va1j5jf8007s.c b/drivers/media/pci/pt1/va1j5jf8007s.c index f75f69556be7..2cf776531dc6 100644 --- a/drivers/media/pci/pt1/va1j5jf8007s.c +++ b/drivers/media/pci/pt1/va1j5jf8007s.c @@ -21,7 +21,7 @@ #include <linux/module.h> #include <linux/slab.h> #include <linux/i2c.h> -#include "dvb_frontend.h" +#include <media/dvb_frontend.h> #include "va1j5jf8007s.h" enum va1j5jf8007s_tune_state { diff --git a/drivers/media/pci/pt1/va1j5jf8007t.c b/drivers/media/pci/pt1/va1j5jf8007t.c index 63fda79a75c0..d9788d153bb6 100644 --- a/drivers/media/pci/pt1/va1j5jf8007t.c +++ b/drivers/media/pci/pt1/va1j5jf8007t.c @@ -21,8 +21,8 @@ #include <linux/module.h> #include <linux/slab.h> #include <linux/i2c.h> -#include "dvb_frontend.h" -#include "dvb_math.h" +#include <media/dvb_frontend.h> +#include <media/dvb_math.h> #include "va1j5jf8007t.h" enum va1j5jf8007t_tune_state { diff --git a/drivers/media/pci/pt3/Makefile b/drivers/media/pci/pt3/Makefile index aded8752ac2b..8698d5dfaf52 100644 --- a/drivers/media/pci/pt3/Makefile +++ b/drivers/media/pci/pt3/Makefile @@ -4,6 +4,5 @@ earth-pt3-objs += pt3.o pt3_i2c.o pt3_dma.o obj-$(CONFIG_DVB_PT3) += earth-pt3.o -ccflags-y += -Idrivers/media/dvb-core ccflags-y += -Idrivers/media/dvb-frontends ccflags-y += -Idrivers/media/tuners diff --git a/drivers/media/pci/pt3/pt3.c b/drivers/media/pci/pt3/pt3.c index 34044a45fecc..da74828805bc 100644 --- a/drivers/media/pci/pt3/pt3.c +++ b/drivers/media/pci/pt3/pt3.c @@ -23,10 +23,10 @@ #include <linux/string.h> #include <linux/sched/signal.h> -#include "dmxdev.h" -#include "dvbdev.h" -#include "dvb_demux.h" -#include "dvb_frontend.h" +#include <media/dmxdev.h> +#include <media/dvbdev.h> +#include <media/dvb_demux.h> +#include <media/dvb_frontend.h> #include "pt3.h" diff --git a/drivers/media/pci/pt3/pt3.h b/drivers/media/pci/pt3/pt3.h index 1b3f2ad25db3..fbe8d9b847b0 100644 --- a/drivers/media/pci/pt3/pt3.h +++ b/drivers/media/pci/pt3/pt3.h @@ -20,9 +20,9 @@ #include <linux/atomic.h> #include <linux/types.h> -#include "dvb_demux.h" -#include "dvb_frontend.h" -#include "dmxdev.h" +#include <media/dvb_demux.h> +#include <media/dvb_frontend.h> +#include <media/dmxdev.h> #include "tc90522.h" #include "mxl301rf.h" diff --git a/drivers/media/pci/pt3/pt3_i2c.c b/drivers/media/pci/pt3/pt3_i2c.c index ec6a8a2e4744..b66138c7b364 100644 --- a/drivers/media/pci/pt3/pt3_i2c.c +++ b/drivers/media/pci/pt3/pt3_i2c.c @@ -85,7 +85,6 @@ static void put_byte_write(struct pt3_i2cbuf *cbuf, u8 val) { u8 mask; - mask = 0x80; for (mask = 0x80; mask > 0; mask >>= 1) cmdbuf_add(cbuf, (val & mask) ? I_DATA_H_NOP : I_DATA_L_NOP); cmdbuf_add(cbuf, I_DATA_H_ACK0); diff --git a/drivers/media/pci/saa7134/Makefile b/drivers/media/pci/saa7134/Makefile index dbaadddf4320..82ac7f31221b 100644 --- a/drivers/media/pci/saa7134/Makefile +++ b/drivers/media/pci/saa7134/Makefile @@ -12,8 +12,6 @@ obj-$(CONFIG_VIDEO_SAA7134_ALSA) += saa7134-alsa.o obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o -ccflags-y += -I$(srctree)/drivers/media/i2c ccflags-y += -I$(srctree)/drivers/media/tuners -ccflags-y += -I$(srctree)/drivers/media/dvb-core ccflags-y += -I$(srctree)/drivers/media/dvb-frontends ccflags-y += -I$(srctree)/drivers/media/usb/go7007 diff --git a/drivers/media/pci/saa7134/saa7134-dvb.c b/drivers/media/pci/saa7134/saa7134-dvb.c index 731dee0a66e7..b55f9a1d9a63 100644 --- a/drivers/media/pci/saa7134/saa7134-dvb.c +++ b/drivers/media/pci/saa7134/saa7134-dvb.c @@ -29,7 +29,7 @@ #include <media/v4l2-common.h> #include "dvb-pll.h" -#include <dvb_frontend.h> +#include <media/dvb_frontend.h> #include "mt352.h" #include "mt352_priv.h" /* FIXME */ diff --git a/drivers/media/pci/saa7134/saa7134-input.c b/drivers/media/pci/saa7134/saa7134-input.c index 2d5abeddc079..33ee8322895e 100644 --- a/drivers/media/pci/saa7134/saa7134-input.c +++ b/drivers/media/pci/saa7134/saa7134-input.c @@ -43,7 +43,8 @@ MODULE_PARM_DESC(pinnacle_remote, "Specify Pinnacle PCTV remote: 0=coloured, 1=g } while (0) #define ir_dbg(ir, fmt, arg...) do { \ if (ir_debug) \ - printk(KERN_DEBUG pr_fmt("ir %s: " fmt), ir->name, ## arg); \ + printk(KERN_DEBUG pr_fmt("ir %s: " fmt), ir->rc->device_name, \ + ## arg); \ } while (0) /* Helper function for raw decoding at GPIO16 or GPIO18 */ diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index 82d2a24644e4..1ae5d2dac3bf 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -1531,6 +1531,8 @@ int saa7134_querycap(struct file *file, void *priv, case VFL_TYPE_VBI: cap->device_caps |= vbi_caps; break; + default: + return -EINVAL; } cap->capabilities = radio_caps | video_caps | vbi_caps | cap->device_caps | V4L2_CAP_DEVICE_CAPS; diff --git a/drivers/media/pci/saa7146/hexium_gemini.c b/drivers/media/pci/saa7146/hexium_gemini.c index d31a2d4494d1..39357eddee32 100644 --- a/drivers/media/pci/saa7146/hexium_gemini.c +++ b/drivers/media/pci/saa7146/hexium_gemini.c @@ -27,6 +27,7 @@ #include <media/drv-intf/saa7146_vv.h> #include <linux/module.h> +#include <linux/kernel.h> static int debug; module_param(debug, int, 0); @@ -388,7 +389,7 @@ static struct saa7146_ext_vv vv_data = { .inputs = HEXIUM_INPUTS, .capabilities = 0, .stds = &hexium_standards[0], - .num_stds = sizeof(hexium_standards) / sizeof(struct saa7146_standard), + .num_stds = ARRAY_SIZE(hexium_standards), .std_callback = &std_callback, }; diff --git a/drivers/media/pci/saa7146/hexium_orion.c b/drivers/media/pci/saa7146/hexium_orion.c index 043318aa19e2..461e421080f3 100644 --- a/drivers/media/pci/saa7146/hexium_orion.c +++ b/drivers/media/pci/saa7146/hexium_orion.c @@ -27,6 +27,7 @@ #include <media/drv-intf/saa7146_vv.h> #include <linux/module.h> +#include <linux/kernel.h> static int debug; module_param(debug, int, 0); @@ -460,7 +461,7 @@ static struct saa7146_ext_vv vv_data = { .inputs = HEXIUM_INPUTS, .capabilities = 0, .stds = &hexium_standards[0], - .num_stds = sizeof(hexium_standards) / sizeof(struct saa7146_standard), + .num_stds = ARRAY_SIZE(hexium_standards), .std_callback = &std_callback, }; diff --git a/drivers/media/pci/saa7146/mxb.c b/drivers/media/pci/saa7146/mxb.c index 930218cc2de1..0144f305ea24 100644 --- a/drivers/media/pci/saa7146/mxb.c +++ b/drivers/media/pci/saa7146/mxb.c @@ -30,6 +30,7 @@ #include <media/v4l2-common.h> #include <media/i2c/saa7115.h> #include <linux/module.h> +#include <linux/kernel.h> #include "tea6415c.h" #include "tea6420.h" @@ -837,7 +838,7 @@ 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 = sizeof(standard)/sizeof(struct saa7146_standard), + .num_stds = ARRAY_SIZE(standard), .std_callback = &std_callback, }; diff --git a/drivers/media/pci/saa7164/Makefile b/drivers/media/pci/saa7164/Makefile index 3896bcdb99d2..dea076744ec9 100644 --- a/drivers/media/pci/saa7164/Makefile +++ b/drivers/media/pci/saa7164/Makefile @@ -5,9 +5,5 @@ saa7164-objs := saa7164-cards.o saa7164-core.o saa7164-i2c.o saa7164-dvb.o \ obj-$(CONFIG_VIDEO_SAA7164) += saa7164.o -ccflags-y += -I$(srctree)/drivers/media/i2c ccflags-y += -I$(srctree)/drivers/media/tuners -ccflags-y += -I$(srctree)/drivers/media/dvb-core ccflags-y += -I$(srctree)/drivers/media/dvb-frontends - -ccflags-y += $(extra-cflags-y) $(extra-cflags-m) diff --git a/drivers/media/pci/saa7164/saa7164.h b/drivers/media/pci/saa7164/saa7164.h index 81b3f0e19993..f3358f43195f 100644 --- a/drivers/media/pci/saa7164/saa7164.h +++ b/drivers/media/pci/saa7164/saa7164.h @@ -50,11 +50,11 @@ #include <media/tuner.h> #include <media/tveeprom.h> -#include <dvb_demux.h> -#include <dvb_frontend.h> -#include <dvb_net.h> -#include <dvbdev.h> -#include <dmxdev.h> +#include <media/dvb_demux.h> +#include <media/dvb_frontend.h> +#include <media/dvb_net.h> +#include <media/dvbdev.h> +#include <media/dmxdev.h> #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-device.h> diff --git a/drivers/media/pci/smipcie/Makefile b/drivers/media/pci/smipcie/Makefile index 6006aac3c41f..214ebfe12cf7 100644 --- a/drivers/media/pci/smipcie/Makefile +++ b/drivers/media/pci/smipcie/Makefile @@ -5,6 +5,5 @@ smipcie-objs := smipcie-main.o smipcie-ir.o obj-$(CONFIG_DVB_SMIPCIE) += smipcie.o ccflags-y += -Idrivers/media/tuners -ccflags-y += -Idrivers/media/dvb-core ccflags-y += -Idrivers/media/dvb-frontends diff --git a/drivers/media/pci/smipcie/smipcie.h b/drivers/media/pci/smipcie/smipcie.h index c8368c78ddd5..a6c5b1bd7edb 100644 --- a/drivers/media/pci/smipcie/smipcie.h +++ b/drivers/media/pci/smipcie/smipcie.h @@ -29,12 +29,12 @@ #include <linux/slab.h> #include <media/rc-core.h> -#include "demux.h" -#include "dmxdev.h" -#include "dvb_demux.h" -#include "dvb_frontend.h" -#include "dvb_net.h" -#include "dvbdev.h" +#include <media/demux.h> +#include <media/dmxdev.h> +#include <media/dvb_demux.h> +#include <media/dvb_frontend.h> +#include <media/dvb_net.h> +#include <media/dvbdev.h> /* -------- Register Base -------- */ #define MSI_CONTROL_REG_BASE 0x0800 diff --git a/drivers/media/pci/solo6x10/solo6x10-core.c b/drivers/media/pci/solo6x10/solo6x10-core.c index ca0873e47bea..19ffd2ed3cc7 100644 --- a/drivers/media/pci/solo6x10/solo6x10-core.c +++ b/drivers/media/pci/solo6x10/solo6x10-core.c @@ -47,18 +47,19 @@ MODULE_PARM_DESC(full_eeprom, "Allow access to full 128B EEPROM (dangerous)"); static void solo_set_time(struct solo_dev *solo_dev) { - struct timespec ts; + struct timespec64 ts; - ktime_get_ts(&ts); + ktime_get_ts64(&ts); - solo_reg_write(solo_dev, SOLO_TIMER_SEC, ts.tv_sec); - solo_reg_write(solo_dev, SOLO_TIMER_USEC, ts.tv_nsec / NSEC_PER_USEC); + /* no overflow because we use monotonic timestamps */ + solo_reg_write(solo_dev, SOLO_TIMER_SEC, (u32)ts.tv_sec); + solo_reg_write(solo_dev, SOLO_TIMER_USEC, (u32)ts.tv_nsec / NSEC_PER_USEC); } static void solo_timer_sync(struct solo_dev *solo_dev) { u32 sec, usec; - struct timespec ts; + struct timespec64 ts; long diff; if (solo_dev->type != SOLO_DEV_6110) @@ -72,11 +73,11 @@ static void solo_timer_sync(struct solo_dev *solo_dev) sec = solo_reg_read(solo_dev, SOLO_TIMER_SEC); usec = solo_reg_read(solo_dev, SOLO_TIMER_USEC); - ktime_get_ts(&ts); + ktime_get_ts64(&ts); - diff = (long)ts.tv_sec - (long)sec; + diff = (s32)ts.tv_sec - (s32)sec; diff = (diff * 1000000) - + ((long)(ts.tv_nsec / NSEC_PER_USEC) - (long)usec); + + ((s32)(ts.tv_nsec / NSEC_PER_USEC) - (s32)usec); if (diff > 1000 || diff < -1000) { solo_set_time(solo_dev); diff --git a/drivers/media/pci/solo6x10/solo6x10-gpio.c b/drivers/media/pci/solo6x10/solo6x10-gpio.c index 3d0d1aa2f6a8..7b4641a2cb84 100644 --- a/drivers/media/pci/solo6x10/solo6x10-gpio.c +++ b/drivers/media/pci/solo6x10/solo6x10-gpio.c @@ -162,7 +162,9 @@ static void solo_gpiochip_set(struct gpio_chip *chip, int solo_gpio_init(struct solo_dev *solo_dev) { +#ifdef CONFIG_GPIOLIB int ret; +#endif solo_gpio_config(solo_dev); #ifdef CONFIG_GPIOLIB diff --git a/drivers/media/pci/ttpci/Makefile b/drivers/media/pci/ttpci/Makefile index 0b805339c123..58ca12732aad 100644 --- a/drivers/media/pci/ttpci/Makefile +++ b/drivers/media/pci/ttpci/Makefile @@ -18,5 +18,5 @@ obj-$(CONFIG_DVB_BUDGET_CI) += budget-ci.o obj-$(CONFIG_DVB_BUDGET_PATCH) += budget-patch.o obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o -ccflags-y += -Idrivers/media/dvb-core/ -Idrivers/media/dvb-frontends/ +ccflags-y += -Idrivers/media/dvb-frontends/ ccflags-y += -Idrivers/media/tuners diff --git a/drivers/media/pci/ttpci/av7110.c b/drivers/media/pci/ttpci/av7110.c index 6d415bdeef18..dc8e577b2f74 100644 --- a/drivers/media/pci/ttpci/av7110.c +++ b/drivers/media/pci/ttpci/av7110.c @@ -53,7 +53,7 @@ #include <linux/dvb/frontend.h> -#include "dvb_frontend.h" +#include <media/dvb_frontend.h> #include "ttpci-eeprom.h" #include "av7110.h" diff --git a/drivers/media/pci/ttpci/av7110.h b/drivers/media/pci/ttpci/av7110.h index cbb150d6cbb1..9bfbb1471717 100644 --- a/drivers/media/pci/ttpci/av7110.h +++ b/drivers/media/pci/ttpci/av7110.h @@ -17,14 +17,14 @@ #include <linux/dvb/net.h> #include <linux/mutex.h> -#include "dvbdev.h" -#include "demux.h" -#include "dvb_demux.h" -#include "dmxdev.h" +#include <media/dvbdev.h> +#include <media/demux.h> +#include <media/dvb_demux.h> +#include <media/dmxdev.h> #include "dvb_filter.h" -#include "dvb_net.h" -#include "dvb_ringbuffer.h" -#include "dvb_frontend.h" +#include <media/dvb_net.h> +#include <media/dvb_ringbuffer.h> +#include <media/dvb_frontend.h> #include "ves1820.h" #include "ves1x93.h" #include "stv0299.h" diff --git a/drivers/media/pci/ttpci/budget-av.c b/drivers/media/pci/ttpci/budget-av.c index ac83fff9fe0b..6b0e09ca01dc 100644 --- a/drivers/media/pci/ttpci/budget-av.c +++ b/drivers/media/pci/ttpci/budget-av.c @@ -51,7 +51,7 @@ #include <linux/input.h> #include <linux/spinlock.h> -#include "dvb_ca_en50221.h" +#include <media/dvb_ca_en50221.h> #define DEBICICAM 0x02420000 diff --git a/drivers/media/pci/ttpci/budget-ci.c b/drivers/media/pci/ttpci/budget-ci.c index 57af11804fd6..f67ed118f273 100644 --- a/drivers/media/pci/ttpci/budget-ci.c +++ b/drivers/media/pci/ttpci/budget-ci.c @@ -35,7 +35,7 @@ #include "budget.h" -#include "dvb_ca_en50221.h" +#include <media/dvb_ca_en50221.h> #include "stv0299.h" #include "stv0297.h" #include "tda1004x.h" diff --git a/drivers/media/pci/ttpci/budget.h b/drivers/media/pci/ttpci/budget.h index fae83866b199..a7463daf39f1 100644 --- a/drivers/media/pci/ttpci/budget.h +++ b/drivers/media/pci/ttpci/budget.h @@ -3,13 +3,13 @@ #ifndef __BUDGET_DVB__ #define __BUDGET_DVB__ -#include "dvb_frontend.h" -#include "dvbdev.h" -#include "demux.h" -#include "dvb_demux.h" -#include "dmxdev.h" +#include <media/dvb_frontend.h> +#include <media/dvbdev.h> +#include <media/demux.h> +#include <media/dvb_demux.h> +#include <media/dmxdev.h> #include "dvb_filter.h" -#include "dvb_net.h" +#include <media/dvb_net.h> #include <linux/module.h> #include <linux/mutex.h> diff --git a/drivers/media/pci/ttpci/dvb_filter.h b/drivers/media/pci/ttpci/dvb_filter.h index 3d410d02a987..67a3c6333bca 100644 --- a/drivers/media/pci/ttpci/dvb_filter.h +++ b/drivers/media/pci/ttpci/dvb_filter.h @@ -19,7 +19,7 @@ #include <linux/slab.h> -#include "demux.h" +#include <media/demux.h> typedef int (dvb_filter_pes2ts_cb_t) (void *, unsigned char *); diff --git a/drivers/media/pci/zoran/videocodec.c b/drivers/media/pci/zoran/videocodec.c index 303289a7fd3f..5ff23ef89215 100644 --- a/drivers/media/pci/zoran/videocodec.c +++ b/drivers/media/pci/zoran/videocodec.c @@ -325,7 +325,6 @@ static int proc_videocodecs_show(struct seq_file *m, void *v) seq_printf(m, "<S>lave or attached <M>aster name type flags magic "); seq_printf(m, "(connected as)\n"); - h = codeclist_top; while (h) { seq_printf(m, "S %32s %04x %08lx %08lx (TEMPLATE)\n", h->codec->name, h->codec->type, |