// SPDX-License-Identifier: GPL-2.0-only /* * This is the driver for the STA2x11 Video Input Port. * * Copyright (C) 2012 ST Microelectronics * author: Federico Vaga <[email protected]> * Copyright (C) 2010 WindRiver Systems, Inc. * authors: Andreas Kies <[email protected]> * Vlad Lungu <[email protected]> */ #include <linux/types.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> #include <linux/videodev2.h> #include <linux/kmod.h> #include <linux/pci.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/gpio/consumer.h> #include <linux/gpio.h> #include <linux/i2c.h> #include <linux/delay.h> #include <media/v4l2-common.h> #include <media/v4l2-device.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-fh.h> #include <media/v4l2-event.h> #include <media/videobuf2-dma-contig.h> #include "sta2x11_vip.h" #define DRV_VERSION … #ifndef PCI_DEVICE_ID_STMICRO_VIP #define PCI_DEVICE_ID_STMICRO_VIP … #endif #define MAX_FRAMES … /*Register offsets*/ #define DVP_CTL … #define DVP_TFO … #define DVP_TFS … #define DVP_BFO … #define DVP_BFS … #define DVP_VTP … #define DVP_VBP … #define DVP_VMP … #define DVP_ITM … #define DVP_ITS … #define DVP_STA … #define DVP_HLFLN … #define DVP_RGB … #define DVP_PKZ … /*Register fields*/ #define DVP_CTL_ENA … #define DVP_CTL_RST … #define DVP_CTL_DIS … #define DVP_IT_VSB … #define DVP_IT_VST … #define DVP_IT_FIFO … #define DVP_HLFLN_SD … #define SAVE_COUNT … #define AUX_COUNT … #define IRQ_COUNT … struct vip_buffer { … }; static inline struct vip_buffer *to_vip_buffer(struct vb2_v4l2_buffer *vb2) { … } /** * struct sta2x11_vip - All internal data for one instance of device * @v4l2_dev: device registered in v4l layer * @video_dev: properties of our device * @pdev: PCI device * @adapter: contains I2C adapter information * @register_save_area: All relevant register are saved here during suspend * @decoder: contains information about video DAC * @ctrl_hdl: handler for control framework * @format: pixel format, fixed UYVY * @std: video standard (e.g. PAL/NTSC) * @input: input line for video signal ( 0 or 1 ) * @disabled: Device is in power down state * @slock: for excluse access of registers * @vb_vidq: queue maintained by videobuf2 layer * @buffer_list: list of buffer in use * @sequence: sequence number of acquired buffer * @active: current active buffer * @lock: used in videobuf2 callback * @v4l_lock: serialize its video4linux ioctls * @tcount: Number of top frames * @bcount: Number of bottom frames * @overflow: Number of FIFO overflows * @iomem: hardware base address * @config: I2C and gpio config from platform * * All non-local data is accessed via this structure. */ struct sta2x11_vip { … }; static const unsigned int registers_to_save[AUX_COUNT] = …; static struct v4l2_pix_format formats_50[] = …; static struct v4l2_pix_format formats_60[] = …; /* Write VIP register */ static inline void reg_write(struct sta2x11_vip *vip, unsigned int reg, u32 val) { … } /* Read VIP register */ static inline u32 reg_read(struct sta2x11_vip *vip, unsigned int reg) { … } /* Start DMA acquisition */ static void start_dma(struct sta2x11_vip *vip, struct vip_buffer *vip_buf) { … } /* Fetch the next buffer to activate */ static void vip_active_buf_next(struct sta2x11_vip *vip) { … } /* Videobuf2 Operations */ static int queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], struct device *alloc_devs[]) { struct sta2x11_vip *vip = vb2_get_drv_priv(vq); if (!(*nbuffers) || *nbuffers < MAX_FRAMES) *nbuffers = MAX_FRAMES; *nplanes = 1; sizes[0] = vip->format.sizeimage; vip->sequence = 0; vip->active = NULL; vip->tcount = 0; vip->bcount = 0; return 0; }; static int buffer_init(struct vb2_buffer *vb) { … } static int buffer_prepare(struct vb2_buffer *vb) { … } static void buffer_queue(struct vb2_buffer *vb) { … } static void buffer_finish(struct vb2_buffer *vb) { … } static int start_streaming(struct vb2_queue *vq, unsigned int count) { … } /* abort streaming and wait for last buffer */ static void stop_streaming(struct vb2_queue *vq) { … } static const struct vb2_ops vip_video_qops = …; /* File Operations */ static const struct v4l2_file_operations vip_fops = …; /** * vidioc_querycap - return capabilities of device * @file: descriptor of device * @cap: contains return values * @priv: unused * * the capabilities of the device are returned * * return value: 0, no error. */ static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { … } /** * vidioc_s_std - set video standard * @file: descriptor of device * @std: contains standard to be set * @priv: unused * * the video standard is set * * return value: 0, no error. * * -EIO, no input signal detected * * other, returned from video DAC. */ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id std) { … } /** * vidioc_g_std - get video standard * @file: descriptor of device * @priv: unused * @std: contains return values * * the current video standard is returned * * return value: 0, no error. */ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *std) { … } /** * vidioc_querystd - get possible video standards * @file: descriptor of device * @priv: unused * @std: contains return values * * all possible video standards are returned * * return value: delivered by video DAC routine. */ static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *std) { … } static int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *inp) { … } /** * vidioc_s_input - set input line * @file: descriptor of device * @priv: unused * @i: new input line number * * the current active input line is set * * return value: 0, no error. * * -EINVAL, line number out of range */ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) { … } /** * vidioc_g_input - return input line * @file: descriptor of device * @priv: unused * @i: returned input line number * * the current active input line is returned * * return value: always 0. */ static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) { … } /** * vidioc_enum_fmt_vid_cap - return video capture format * @file: descriptor of device * @priv: unused * @f: returned format information * * returns name and format of video capture * Only UYVY is supported by hardware. * * return value: always 0. */ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { … } /** * vidioc_try_fmt_vid_cap - set video capture format * @file: descriptor of device * @priv: unused * @f: new format * * new video format is set which includes width and * field type. width is fixed to 720, no scaling. * Only UYVY is supported by this hardware. * the minimum height is 200, the maximum is 576 (PAL) * * return value: 0, no error * * -EINVAL, pixel or field format not supported * */ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { … } /** * vidioc_s_fmt_vid_cap - set current video format parameters * @file: descriptor of device * @priv: unused * @f: returned format information * * set new capture format * return value: 0, no error * * other, delivered by video DAC routine. */ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { … } /** * vidioc_g_fmt_vid_cap - get current video format parameters * @file: descriptor of device * @priv: unused * @f: contains format information * * returns current video format parameters * * return value: 0, always successful */ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { … } static const struct v4l2_ioctl_ops vip_ioctl_ops = …; static const struct video_device video_dev_template = …; /** * vip_irq - interrupt routine * @irq: Number of interrupt ( not used, correct number is assumed ) * @data: local data structure containing all information * * check for both frame interrupts set ( top and bottom ). * check FIFO overflow, but limit number of log messages after open. * signal a complete buffer if done * * return value: IRQ_NONE, interrupt was not generated by VIP * * IRQ_HANDLED, interrupt done. */ static irqreturn_t vip_irq(int irq, void *data) { … } static void sta2x11_vip_init_register(struct sta2x11_vip *vip) { … } static void sta2x11_vip_clear_register(struct sta2x11_vip *vip) { … } static int sta2x11_vip_init_buffer(struct sta2x11_vip *vip) { … } static int sta2x11_vip_init_controls(struct sta2x11_vip *vip) { … } /** * vip_gpio_reserve - reserve gpio pin * @dev: device * @pin: GPIO pin number * @dir: direction, input or output * @name: GPIO pin name * */ static int vip_gpio_reserve(struct device *dev, int pin, int dir, const char *name) { … } /** * vip_gpio_release - release gpio pin * @dev: device * @pin: GPIO pin number * @name: GPIO pin name * */ static void vip_gpio_release(struct device *dev, int pin, const char *name) { … } /** * sta2x11_vip_init_one - init one instance of video device * @pdev: PCI device * @ent: (not used) * * allocate reset pins for DAC. * Reset video DAC, this is done via reset line. * allocate memory for managing device * request interrupt * map IO region * register device * find and initialize video DAC * * return value: 0, no error * * -ENOMEM, no memory * * -ENODEV, device could not be detected or registered */ static int sta2x11_vip_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { … } /** * sta2x11_vip_remove_one - release device * @pdev: PCI device * * Undo everything done in .._init_one * * unregister video device * free interrupt * unmap ioadresses * free memory * free GPIO pins */ static void sta2x11_vip_remove_one(struct pci_dev *pdev) { … } /** * sta2x11_vip_suspend - set device into power save mode * @dev_d: PCI device * * all relevant registers are saved and an attempt to set a new state is made. * * return value: 0 always indicate success, * even if device could not be disabled. (workaround for hardware problem) */ static int __maybe_unused sta2x11_vip_suspend(struct device *dev_d) { … } /** * sta2x11_vip_resume - resume device operation * @dev_d : PCI device * * return value: 0, no error. * * other, could not set device to power on state. */ static int __maybe_unused sta2x11_vip_resume(struct device *dev_d) { … } static const struct pci_device_id sta2x11_vip_pci_tbl[] = …; static SIMPLE_DEV_PM_OPS(sta2x11_vip_pm_ops, sta2x11_vip_suspend, sta2x11_vip_resume); static struct pci_driver sta2x11_vip_driver = …; static int __init sta2x11_vip_init_module(void) { … } static void __exit sta2x11_vip_exit_module(void) { … } #ifdef MODULE module_init(sta2x11_vip_init_module); module_exit(sta2x11_vip_exit_module); #else late_initcall_sync(sta2x11_vip_init_module); #endif MODULE_DESCRIPTION(…) …; MODULE_AUTHOR(…) …; MODULE_LICENSE(…) …; MODULE_VERSION(…); MODULE_DEVICE_TABLE(pci, sta2x11_vip_pci_tbl);