// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (C) 2009 Texas Instruments Inc * Copyright (C) 2014 Lad, Prabhakar <[email protected]> * * TODO : add support for VBI & HBI data service * add static buffer allocation */ #include <linux/module.h> #include <linux/interrupt.h> #include <linux/of_graph.h> #include <linux/platform_device.h> #include <linux/slab.h> #include <media/v4l2-fwnode.h> #include <media/v4l2-ioctl.h> #include <media/i2c/tvp514x.h> #include <media/v4l2-mediabus.h> #include <linux/videodev2.h> #include "vpif.h" #include "vpif_capture.h" MODULE_DESCRIPTION(…) …; MODULE_LICENSE(…) …; MODULE_VERSION(…); #define vpif_err(fmt, arg...) … #define vpif_dbg(level, debug, fmt, arg...) … static int debug = …; module_param(debug, int, 0644); MODULE_PARM_DESC(…) …; #define VPIF_DRIVER_NAME … MODULE_ALIAS(…) …; /* global variables */ static struct vpif_device vpif_obj = …; static struct device *vpif_dev; static void vpif_calculate_offsets(struct channel_obj *ch); static void vpif_config_addr(struct channel_obj *ch, int muxmode); static u8 channel_first_int[VPIF_NUMBER_OF_OBJECTS][2] = …; /* Is set to 1 in case of SDTV formats, 2 in case of HDTV formats. */ static int ycmux_mode; static inline struct vpif_cap_buffer *to_vpif_buffer(struct vb2_v4l2_buffer *vb) { … } /** * vpif_buffer_prepare : callback function for buffer prepare * @vb: ptr to vb2_buffer * * This is the callback function for buffer prepare when vb2_qbuf() * function is called. The buffer is prepared and user space virtual address * or user address is converted into physical address */ static int vpif_buffer_prepare(struct vb2_buffer *vb) { … } /** * vpif_buffer_queue_setup : Callback function for buffer setup. * @vq: vb2_queue ptr * @nbuffers: ptr to number of buffers requested by application * @nplanes: contains number of distinct video planes needed to hold a frame * @sizes: contains the size (in bytes) of each plane. * @alloc_devs: ptr to allocation context * * This callback function is called when reqbuf() is called to adjust * the buffer count and buffer size */ static int vpif_buffer_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], struct device *alloc_devs[]) { … } /** * vpif_buffer_queue : Callback function to add buffer to DMA queue * @vb: ptr to vb2_buffer */ static void vpif_buffer_queue(struct vb2_buffer *vb) { … } /** * vpif_start_streaming : Starts the DMA engine for streaming * @vq: ptr to vb2_buffer * @count: number of buffers */ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) { … } /** * vpif_stop_streaming : Stop the DMA engine * @vq: ptr to vb2_queue * * This callback stops the DMA engine and any remaining buffers * in the DMA queue are released. */ static void vpif_stop_streaming(struct vb2_queue *vq) { … } static const struct vb2_ops video_qops = …; /** * vpif_process_buffer_complete: process a completed buffer * @common: ptr to common channel object * * This function time stamp the buffer and mark it as DONE. It also * wake up any process waiting on the QUEUE and set the next buffer * as current */ static void vpif_process_buffer_complete(struct common_obj *common) { … } /** * vpif_schedule_next_buffer: set next buffer address for capture * @common : ptr to common channel object * * This function will get next buffer from the dma queue and * set the buffer address in the vpif register for capture. * the buffer is marked active */ static void vpif_schedule_next_buffer(struct common_obj *common) { … } /** * vpif_channel_isr : ISR handler for vpif capture * @irq: irq number * @dev_id: dev_id ptr * * It changes status of the captured buffer, takes next buffer from the queue * and sets its address in VPIF registers */ static irqreturn_t vpif_channel_isr(int irq, void *dev_id) { … } /** * vpif_update_std_info() - update standard related info * @ch: ptr to channel object * * For a given standard selected by application, update values * in the device data structures */ static int vpif_update_std_info(struct channel_obj *ch) { … } /** * vpif_calculate_offsets : This function calculates buffers offsets * @ch : ptr to channel object * * This function calculates buffer offsets for Y and C in the top and * bottom field */ static void vpif_calculate_offsets(struct channel_obj *ch) { … } /** * vpif_config_addr() - function to configure buffer address in vpif * @ch: channel ptr * @muxmode: channel mux mode */ static void vpif_config_addr(struct channel_obj *ch, int muxmode) { … } /** * vpif_input_to_subdev() - Maps input to sub device * @vpif_cfg: global config ptr * @chan_cfg: channel config ptr * @input_index: Given input index from application * * lookup the sub device information for a given input index. * we report all the inputs to application. inputs table also * has sub device name for the each input */ static int vpif_input_to_subdev( struct vpif_capture_config *vpif_cfg, struct vpif_capture_chan_config *chan_cfg, int input_index) { … } /** * vpif_set_input() - Select an input * @vpif_cfg: global config ptr * @ch: channel * @index: Given input index from application * * Select the given input. */ static int vpif_set_input( struct vpif_capture_config *vpif_cfg, struct channel_obj *ch, int index) { … } /** * vpif_querystd() - querystd handler * @file: file ptr * @priv: file handle * @std_id: ptr to std id * * This function is called to detect standard at the selected input */ static int vpif_querystd(struct file *file, void *priv, v4l2_std_id *std_id) { … } /** * vpif_g_std() - get STD handler * @file: file ptr * @priv: file handle * @std: ptr to std id */ static int vpif_g_std(struct file *file, void *priv, v4l2_std_id *std) { … } /** * vpif_s_std() - set STD handler * @file: file ptr * @priv: file handle * @std_id: ptr to std id */ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id std_id) { … } /** * vpif_enum_input() - ENUMINPUT handler * @file: file ptr * @priv: file handle * @input: ptr to input structure */ static int vpif_enum_input(struct file *file, void *priv, struct v4l2_input *input) { … } /** * vpif_g_input() - Get INPUT handler * @file: file ptr * @priv: file handle * @index: ptr to input index */ static int vpif_g_input(struct file *file, void *priv, unsigned int *index) { … } /** * vpif_s_input() - Set INPUT handler * @file: file ptr * @priv: file handle * @index: input index */ static int vpif_s_input(struct file *file, void *priv, unsigned int index) { … } /** * vpif_enum_fmt_vid_cap() - ENUM_FMT handler * @file: file ptr * @priv: file handle * @fmt: ptr to V4L2 format descriptor */ static int vpif_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *fmt) { … } /** * vpif_try_fmt_vid_cap() - TRY_FMT handler * @file: file ptr * @priv: file handle * @fmt: ptr to v4l2 format structure */ static int vpif_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *fmt) { … } /** * vpif_g_fmt_vid_cap() - Set INPUT handler * @file: file ptr * @priv: file handle * @fmt: ptr to v4l2 format structure */ static int vpif_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *fmt) { … } /** * vpif_s_fmt_vid_cap() - Set FMT handler * @file: file ptr * @priv: file handle * @fmt: ptr to v4l2 format structure */ static int vpif_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *fmt) { … } /** * vpif_querycap() - QUERYCAP handler * @file: file ptr * @priv: file handle * @cap: ptr to v4l2_capability structure */ static int vpif_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { … } /** * vpif_enum_dv_timings() - ENUM_DV_TIMINGS handler * @file: file ptr * @priv: file handle * @timings: input timings */ static int vpif_enum_dv_timings(struct file *file, void *priv, struct v4l2_enum_dv_timings *timings) { … } /** * vpif_query_dv_timings() - QUERY_DV_TIMINGS handler * @file: file ptr * @priv: file handle * @timings: input timings */ static int vpif_query_dv_timings(struct file *file, void *priv, struct v4l2_dv_timings *timings) { … } /** * vpif_s_dv_timings() - S_DV_TIMINGS handler * @file: file ptr * @priv: file handle * @timings: digital video timings */ static int vpif_s_dv_timings(struct file *file, void *priv, struct v4l2_dv_timings *timings) { … } /** * vpif_g_dv_timings() - G_DV_TIMINGS handler * @file: file ptr * @priv: file handle * @timings: digital video timings */ static int vpif_g_dv_timings(struct file *file, void *priv, struct v4l2_dv_timings *timings) { … } /* * vpif_log_status() - Status information * @file: file ptr * @priv: file handle * * Returns zero. */ static int vpif_log_status(struct file *filep, void *priv) { … } /* vpif capture ioctl operations */ static const struct v4l2_ioctl_ops vpif_ioctl_ops = …; /* vpif file operations */ static const struct v4l2_file_operations vpif_fops = …; /** * initialize_vpif() - Initialize vpif data structures * * Allocate memory for data structures and initialize them */ static int initialize_vpif(void) { … } static inline void free_vpif_objs(void) { … } static int vpif_async_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, struct v4l2_async_connection *asd) { … } static int vpif_probe_complete(void) { … } static int vpif_async_complete(struct v4l2_async_notifier *notifier) { … } static const struct v4l2_async_notifier_operations vpif_async_ops = …; static struct vpif_capture_config * vpif_capture_get_pdata(struct platform_device *pdev, struct v4l2_device *v4l2_dev) { … } /** * vpif_probe : This function probes the vpif capture driver * @pdev: platform device pointer * * This creates device entries by register itself to the V4L2 driver and * initializes fields of each channel objects */ static __init int vpif_probe(struct platform_device *pdev) { … } /** * vpif_remove() - driver remove handler * @device: ptr to platform device structure * * The vidoe device is unregistered */ static void vpif_remove(struct platform_device *device) { … } #ifdef CONFIG_PM_SLEEP /** * vpif_suspend: vpif device suspend * @dev: pointer to &struct device */ static int vpif_suspend(struct device *dev) { … } /* * vpif_resume: vpif device suspend */ static int vpif_resume(struct device *dev) { … } #endif static SIMPLE_DEV_PM_OPS(vpif_pm_ops, vpif_suspend, vpif_resume); static __refdata struct platform_driver vpif_driver = …; module_platform_driver(…) …;