From b949d4d65f0961dddd9305a017c30c6e65fb330d Mon Sep 17 00:00:00 2001 From: "Jan.Hannig" Date: Wed, 13 Oct 2021 13:53:26 +0200 Subject: [PATCH 01/11] [RDPHOEN-463/RDPHOEN-467] Clean Up Driver Code Removed unused v4l2_ioctl_ops functions Although ".vidioc_s_parm = epc660_s_parm" isn't used actually, it is left as it will be used later on for the driver interface. --- .../platform/iris-gen6/epc660_capture_sc57x.c | 96 ------------------- 1 file changed, 96 deletions(-) diff --git a/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c b/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c index 964732d02e72..90c85236d29d 100644 --- a/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c +++ b/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c @@ -700,37 +700,6 @@ static int epc660_streamon(struct file *file, void *priv, return ret; } -static int epc660_querystd(struct file *file, void *priv, v4l2_std_id *std) -{ - struct epc660_device *epc660_dev = video_drvdata(file); - - return v4l2_subdev_call(epc660_dev->sd, video, querystd, std); -} - -static int epc660_g_std(struct file *file, void *priv, v4l2_std_id *std) -{ - struct epc660_device *epc660_dev = video_drvdata(file); - - *std = epc660_dev->std; - return 0; -} - -static int epc660_s_std(struct file *file, void *priv, v4l2_std_id std) -{ - struct epc660_device *epc660_dev = video_drvdata(file); - int ret; - - if (vb2_is_busy(&epc660_dev->buffer_queue)) - return -EBUSY; - - ret = v4l2_subdev_call(epc660_dev->sd, video, s_std, std); - if (ret < 0) - return ret; - - epc660_dev->std = std; - return 0; -} - static int epc660_enum_input(struct file *file, void *priv, struct v4l2_input *input) { @@ -751,14 +720,6 @@ static int epc660_enum_input(struct file *file, void *priv, return 0; } -static int epc660_g_input(struct file *file, void *priv, unsigned int *index) -{ - struct epc660_device *epc660_dev = video_drvdata(file); - - *index = epc660_dev->cur_input; - return 0; -} - static int epc660_s_input(struct file *file, void *priv, unsigned int index) { struct epc660_device *epc660_dev = video_drvdata(file); @@ -824,30 +785,6 @@ static int epc660_try_format(struct epc660_device *epc660_dev, return 0; } -static int epc660_enum_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_fmtdesc *fmt) -{ - struct epc660_device *epc660_dev = video_drvdata(file); - struct imager_format *sf = epc660_dev->sensor_formats; - - if (fmt->index >= epc660_dev->num_sensor_formats) - return -EINVAL; - - fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - strlcpy(fmt->description, sf[fmt->index].desc, sizeof(fmt->description)); - fmt->pixelformat = sf[fmt->index].pixelformat; - return 0; -} - -static int epc660_try_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *fmt) -{ - struct epc660_device *epc660_dev = video_drvdata(file); - struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; - - return epc660_try_format(epc660_dev, pixfmt, NULL); -} - static int epc660_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *fmt) { @@ -910,28 +847,6 @@ static int epc660_s_fmt_vid_cap(struct file *file, void *priv, return 0; } -static int epc660_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct epc660_device *epc660_dev = video_drvdata(file); - - cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; - strlcpy(cap->driver, CAPTURE_DRV_NAME, sizeof(cap->driver)); - strlcpy(cap->bus_info, "Blackfin Platform", sizeof(cap->bus_info)); - strlcpy(cap->card, epc660_dev->cfg.card_name, sizeof(cap->card)); - return 0; -} - -static int epc660_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a) -{ - struct epc660_device *epc660_dev = video_drvdata(file); - - if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - return v4l2_subdev_call(epc660_dev->sd, video, g_parm, a); -} - static int epc660_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a) { struct epc660_device *epc660_dev = video_drvdata(file); @@ -951,26 +866,15 @@ static int epc660_log_status(struct file *file, void *priv) static const struct v4l2_ioctl_ops epc660_ioctl_ops = { - .vidioc_querycap = epc660_querycap, .vidioc_g_fmt_vid_cap = epc660_g_fmt_vid_cap, - .vidioc_enum_fmt_vid_cap = epc660_enum_fmt_vid_cap, .vidioc_s_fmt_vid_cap = epc660_s_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = epc660_try_fmt_vid_cap, .vidioc_enum_input = epc660_enum_input, - .vidioc_g_input = epc660_g_input, .vidioc_s_input = epc660_s_input, - .vidioc_querystd = epc660_querystd, - .vidioc_s_std = epc660_s_std, - .vidioc_g_std = epc660_g_std, .vidioc_reqbufs = vb2_ioctl_reqbufs, - .vidioc_create_bufs = vb2_ioctl_create_bufs, .vidioc_querybuf = vb2_ioctl_querybuf, .vidioc_qbuf = vb2_ioctl_qbuf, .vidioc_dqbuf = vb2_ioctl_dqbuf, - .vidioc_expbuf = vb2_ioctl_expbuf, .vidioc_streamon = epc660_streamon, - .vidioc_streamoff = vb2_ioctl_streamoff, - .vidioc_g_parm = epc660_g_parm, .vidioc_s_parm = epc660_s_parm, .vidioc_log_status = epc660_log_status, }; From 4327d0e6902e431f6639dc35b540bafbb88df791 Mon Sep 17 00:00:00 2001 From: "Jan.Hannig" Date: Wed, 13 Oct 2021 14:36:37 +0200 Subject: [PATCH 02/11] RDPHOEN-463/RDPHOEN-467] Added comments Doxygen comments for functions and structs. --- .../platform/iris-gen6/epc660_capture_sc57x.c | 202 +++++++++++++----- 1 file changed, 153 insertions(+), 49 deletions(-) diff --git a/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c b/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c index 90c85236d29d..e7550c0f9ee1 100644 --- a/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c +++ b/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c @@ -16,6 +16,10 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/** + * @file + * @brief Analog Devices video capture driver + */ #include #include @@ -46,6 +50,7 @@ #include #include +/* Actually included Header file: arch/arm/mach-sc57x/include/mach/dma.h */ #ifdef CONFIG_ARCH_HEADER_IN_MACH #include #else @@ -66,22 +71,31 @@ struct imager_format { int pixel_depth_bytes; }; - +/** + * @brief Points to memory that is allocated to be reacheable by the dma and holds an array of dma descriptors. + * @brief dma_addr_t - Bus address type of allocated DMA buffers + */ struct imager_dma_desc_list_item { dma_addr_t next_desc_addr; dma_addr_t start_addr; unsigned long cfg; }__packed; +/** + * @brief Basic struct for one buffer and the belonging DMA descriptors + * @brief "imager_dma_desc_list_item" points to memory that is allocated + * @brief to be reacheable by the dma and holds an array of dma descriptors + */ struct imager_buffer { - struct vb2_v4l2_buffer vb; - // points to memory that is allocated to be reacheable by the dma and holds an array of dma descriptors + struct vb2_v4l2_buffer vb; ///< Basic driver buffer, contains "struct vb2_buffer" struct imager_dma_desc_list_item *dma_desc; - // the dma reacheable address of the dma_desc - dma_addr_t desc_dma_addr; + dma_addr_t desc_dma_addr; ///< the dma reacheable address of the dma_desc struct list_head list; }; +/** + * @brief routing information for each input + */ struct imager_route { u32 input; u32 output; @@ -90,12 +104,9 @@ struct imager_route { struct capture_config { /* card name */ const char *card_name; - /* inputs available at the sub device */ - struct v4l2_input *inputs; - /* number of inputs supported */ - int num_inputs; - /* routing information for each input */ - struct imager_route *routes; + struct v4l2_input *inputs; ///< inputs available at the sub device. Instance of struct v4l2_input defined locally. + int num_inputs; ///< number of inputs supported + struct imager_route *routes; ///< routing information for each input. Defined locally. /* i2c bus adapter no */ int i2c_adapter_id; /* i2c subdevice board info */ @@ -120,10 +131,8 @@ struct epc660_device { struct video_device *video_dev; /* sub device instance */ struct v4l2_subdev *sd; - /* capture config */ - struct capture_config cfg; - /* dma channel */ - int dma_channel; + struct capture_config cfg; ///< capture config, defined locally + int dma_channel; ///< DMA channel /* ppi interface */ struct ppi_if *ppi; /* current input */ @@ -138,28 +147,26 @@ struct epc660_device { int bpp; /* data length for ppi in bits */ int dlen; - /* number of sub images */ - int pixel_channels; + int pixel_channels; ///< Number of sub images /* the size of each pixel in bytes */ int pixel_depth_bytes; - /* used to store sensor supported format */ - struct imager_format *sensor_formats; - /* number of sensor formats array */ - int num_sensor_formats; + struct imager_format *sensor_formats; ///< used to store sensor supported formats, defined locally + int num_sensor_formats; ///< number of sensor formats array /* buffer queue used in videobuf2 */ struct vb2_queue buffer_queue; - /* something to allocate memory for dma usage from */ - struct dma_pool *dma_pool; - /* queue of filled frames */ - struct list_head dma_queue; - /* a dma config holding information on how to paramererize the dma */ - struct dmasg dma_cfg_template; + struct dma_pool *dma_pool; ///< something to allocate memory for dma usage from + struct list_head dma_queue; ///< queue of filled frames + struct dmasg dma_cfg_template; ///< a dma config holding information on how to paramererize the dma /* used in videobuf2 callback */ spinlock_t lock; /* used to access capture device */ struct mutex mutex; }; +/** + * @brief used to store sensor supported format + * @brief corresponding with "static const struct epc660_datafmt epc660_monochrome_fmts[]" in epc660.c + */ static const struct imager_format epc660_formats[] = { { .desc = "12bit Grey Scale", @@ -231,17 +238,25 @@ static int epc660_start_transfering(struct epc660_device *epc660_dev, dma_addr_t descrAddr); static void epc660_stop_transfering(struct epc660_device *epc660_dev); +/* Used by diff fcts */ static struct imager_buffer *vb2v4l2_to_imagerbuffer(struct vb2_v4l2_buffer *vb) { return container_of(vb, struct imager_buffer, vb); } /* The queue is busy if there is a owner and you are not that owner. */ +/* Used by epc660_streamon*/ static inline bool vb2_queue_is_busy(struct video_device *vdev, struct file *file) { return vdev->queue->owner && vdev->queue->owner != file->private_data; } +/** + * @brief Initializes all available sensor formats in subdevice. + * @brief Used by epc660_probe, to be called once during boot + * @param *epc660_dev - epc660 driver device struct + * @return "0" for OK + */ static int epc660_init_sensor_formats(struct epc660_device *epc660_dev) { @@ -284,6 +299,7 @@ static int epc660_init_sensor_formats(struct epc660_device *epc660_dev) return 0; } +/* Used by epc660_remove */ static void epc660_free_sensor_formats(struct epc660_device *epc660_dev) { epc660_dev->num_sensor_formats = 0; @@ -311,6 +327,11 @@ static int epc660_queue_setup(struct vb2_queue *vq, return 0; } +/** + * @brief This function initializes and sets the DMA descriptor list/array for the given vb2-buffer + * @param *vb - pointer onto allocated buffer + * @return "0" for OK + */ static int epc660_buffer_init(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); @@ -324,6 +345,8 @@ static int epc660_buffer_init(struct vb2_buffer *vb) INIT_LIST_HEAD(&buf->list); + /* The DMA-Pool of DMA descriptors is organized as a list. + With each buffer, a new descriptor list is allocated and added to epc660_dev->dma_pool */ buf->dma_desc = dma_pool_alloc(epc660_dev->dma_pool, GFP_KERNEL, &buf->desc_dma_addr); if (!buf->dma_desc) { printk("cannot allocate memory from dma pool\n"); @@ -380,6 +403,11 @@ static int epc660_buffer_init(struct vb2_buffer *vb) return 0; } +/** + * @brief This function checks if the given vb2-buffer is correctly dimensioned + * @param *vb - pointer onto allocated buffer + * @return "0" for OK + */ static int epc660_buffer_prepare(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); @@ -398,6 +426,11 @@ static int epc660_buffer_prepare(struct vb2_buffer *vb) return 0; } +/** + * @brief This function adds the given vb2-buffer to the descriptor queue. If the list isn't empty, the last element is added. + * @param *vb - pointer onto allocated buffer + * @return "0" for OK + */ static void epc660_buffer_queue(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); @@ -445,6 +478,11 @@ static void epc660_buffer_cleanup(struct vb2_buffer *vb) dma_pool_free(epc660_dev->dma_pool, buf->dma_desc, buf->desc_dma_addr); } +/** + * @brief Enables streamon on sub device and calls the setting of PPI params + * @param *vq - pointer onto queue buffer. count - unused variable. + * @return "0" for OK + */ static int epc660_start_streaming(struct vb2_queue *vq, unsigned int count) { struct epc660_device *epc660_dev = vb2_get_drv_priv(vq); @@ -514,15 +552,15 @@ static void epc660_stop_streaming(struct vb2_queue *vq) static struct vb2_ops epc660_video_qops = { - .queue_setup = epc660_queue_setup, - .buf_init = epc660_buffer_init, - .buf_prepare = epc660_buffer_prepare, - .buf_cleanup = epc660_buffer_cleanup, - .buf_queue = epc660_buffer_queue, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, - .start_streaming = epc660_start_streaming, - .stop_streaming = epc660_stop_streaming, + .queue_setup = epc660_queue_setup, /* Call in Startup-Phase */ + .buf_init = epc660_buffer_init, /* Call in Startup-Phase */ + .buf_prepare = epc660_buffer_prepare,/* Call in all three Phases */ + .buf_cleanup = epc660_buffer_cleanup,/* Call in Shutdown-Phase*/ + .buf_queue = epc660_buffer_queue, /* Call in all three Phases */ + .wait_prepare = vb2_ops_wait_prepare, /* Keine Anwendung */ + .wait_finish = vb2_ops_wait_finish, /* Keine Anwendung */ + .start_streaming = epc660_start_streaming,/* Call in Startup-Phase */ + .stop_streaming = epc660_stop_streaming,/* Call in Shutdown-Phase */ }; #if 0 @@ -624,6 +662,14 @@ static irqreturn_t epc660_isr(int irq, void *dev_id) return IRQ_HANDLED; } +/** + * @brief Requests the DMA channel. Sets the configuration registers and configures PPI as callback functionality. + * @brief Starts the PPI and the DMA instance (the DMA by setting the config register and with it the DMA_ENABLE bit). + * @brief Used in epc660_streamon. + * @param epc660_dev - Actual driver device structure + * @param descrAddr - start address of the (first) DMA descriptor + * @return ret - result of DMA allocation fct "request_dma", "0" for OK + */ static int epc660_start_transfering(struct epc660_device *epc660_dev, dma_addr_t descrAddr) { int ret; //printk("start DMA\n"); @@ -636,7 +682,8 @@ static int epc660_start_transfering(struct epc660_device *epc660_dev, dma_addr_t /* attach ppi DMA irq handler */ set_dma_callback(epc660_dev->dma_channel, epc660_isr, epc660_dev->ppi); - + /* Sets the different HW registers of the DMA on chip. + As the descriptor doesn't change, it's called only once in the beginning. */ set_dma_next_desc_addr(epc660_dev->dma_channel, (void*)descrAddr); set_dma_x_count(epc660_dev->dma_channel, epc660_dev->dma_cfg_template.x_count), set_dma_x_modify(epc660_dev->dma_channel, epc660_dev->dma_cfg_template.x_modify), @@ -648,6 +695,7 @@ static int epc660_start_transfering(struct epc660_device *epc660_dev, dma_addr_t return ret; } +/* Used in epc660_stop_streaming*/ static void epc660_stop_transfering(struct epc660_device *epc660_dev) { /* disable ppi */ @@ -662,6 +710,12 @@ static void epc660_stop_transfering(struct epc660_device *epc660_dev) //printk("stopped DMA\n"); } +/** + * @brief + * @param *file -file descriptor of sub device + * @param * + * @return "0" for OK + */ static int epc660_streamon(struct file *file, void *priv, enum v4l2_buf_type buf_type) { @@ -700,6 +754,12 @@ static int epc660_streamon(struct file *file, void *priv, return ret; } +/** + * @brief The function delivers the input instance according to the number which is set in struct input + * @param *file -file descriptor of sub device + * @param *input - instance to be filled with data according to the index value + * @return "0" for OK + */ static int epc660_enum_input(struct file *file, void *priv, struct v4l2_input *input) { @@ -709,9 +769,11 @@ static int epc660_enum_input(struct file *file, void *priv, int ret; u32 status; + /* Compare the input value with the value in the driver */ if (input->index >= config->num_inputs) return -EINVAL; + /* set the input value for the required input instance */ *input = config->inputs[input->index]; /* get input status */ ret = v4l2_subdev_call(epc660_dev->sd, video, g_input_status, &status); @@ -720,6 +782,13 @@ static int epc660_enum_input(struct file *file, void *priv, return 0; } + +/** + * @brief This function sets "epc660_dev->cur_input" with the value "index" given from application + * @param *file -file descriptor of sub device + * @param *input - instance to be filled with data according to the index value + * @return "0" for OK + */ static int epc660_s_input(struct file *file, void *priv, unsigned int index) { struct epc660_device *epc660_dev = video_drvdata(file); @@ -785,6 +854,7 @@ static int epc660_try_format(struct epc660_device *epc660_dev, return 0; } +/* this function isn't called but necessary for kernel function (v4l2_ioctl_ops) */ static int epc660_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *fmt) { @@ -794,6 +864,11 @@ static int epc660_g_fmt_vid_cap(struct file *file, void *priv, return 0; } +/** + * @brief Sets the sensor values of *fmt for Application, and of epc660_dev. Initial DMA configuration. + * @param *fmt: Representation of the platform device in the kernel to be set in this function + * @return "0" for OK + */ static int epc660_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *fmt) { @@ -819,6 +894,8 @@ static int epc660_s_fmt_vid_cap(struct file *file, void *priv, ret = v4l2_subdev_call(epc660_dev->sd, pad, set_fmt, NULL, &format); if (ret < 0) return ret; + + /* Store the parameter of the configured video format (application) into epc660_dev module struct */ epc660_dev->fmt = *pixfmt; epc660_dev->bpp = epc660_fmt.bpp; epc660_dev->dlen = epc660_fmt.dlen; @@ -866,16 +943,16 @@ static int epc660_log_status(struct file *file, void *priv) static const struct v4l2_ioctl_ops epc660_ioctl_ops = { - .vidioc_g_fmt_vid_cap = epc660_g_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = epc660_s_fmt_vid_cap, - .vidioc_enum_input = epc660_enum_input, - .vidioc_s_input = epc660_s_input, - .vidioc_reqbufs = vb2_ioctl_reqbufs, - .vidioc_querybuf = vb2_ioctl_querybuf, - .vidioc_qbuf = vb2_ioctl_qbuf, - .vidioc_dqbuf = vb2_ioctl_dqbuf, - .vidioc_streamon = epc660_streamon, - .vidioc_s_parm = epc660_s_parm, + .vidioc_g_fmt_vid_cap = epc660_g_fmt_vid_cap, ///< No official usage, but driver doesn't run without the function implemented + .vidioc_s_fmt_vid_cap = epc660_s_fmt_vid_cap, ///< Call during start phase by EPC660_Imager.cpp + .vidioc_enum_input = epc660_enum_input, ///< Call during start phase by EPC660_Imager.cpp + .vidioc_s_input = epc660_s_input, ///< Call during start phase by EPC660_Imager.cpp + .vidioc_reqbufs = vb2_ioctl_reqbufs, ///< Call during start phase by EPC660_Imager.cpp + .vidioc_querybuf = vb2_ioctl_querybuf, ///< Call in EPC660_Imager.cpp for V4L2_MEMORY_MMAP + .vidioc_qbuf = vb2_ioctl_qbuf, ///< Call in EPC660_Imager.cpp during all three phases + .vidioc_dqbuf = vb2_ioctl_dqbuf, ///< Call during all three phases + .vidioc_streamon = epc660_streamon, ///< Call during start phase by EPC660_Imager.cpp + .vidioc_s_parm = epc660_s_parm, .vidioc_log_status = epc660_log_status, }; @@ -912,8 +989,8 @@ static int epc660_release(struct file* filp) { static struct v4l2_file_operations epc660_fops = { .owner = THIS_MODULE, - .open = epc660_open, - .release = epc660_release, + .open = epc660_open, ///< Call during start phase + .release = epc660_release, ///< Call during start and shutdown phase .unlocked_ioctl = video_ioctl2, .mmap = vb2_fop_mmap, #ifndef CONFIG_MMU @@ -922,6 +999,9 @@ static struct v4l2_file_operations epc660_fops = { .poll = vb2_fop_poll }; +/** + * @brief Wrapper for of_property_read_u32, used by diff fcts + */ static int get_int_prop(struct device_node *dn, const char *s) { int ret; @@ -933,6 +1013,9 @@ static int get_int_prop(struct device_node *dn, const char *s) return val; } +/** + * @brief Basic structure for registering the driver to the kernel (with MODULE_DEVICE_TABLE, of = open firmware) + */ static const struct of_device_id cap_match[] = { { .compatible = COMPATIBLE_DT_NAME, }, @@ -940,6 +1023,12 @@ static const struct of_device_id cap_match[] = }; MODULE_DEVICE_TABLE(of, cap_match); +/** + * @brief Used by epc660_probe to initialize/configure both input structs (ppi info struct and i2c config/infos) + * @param *pdev - representation of the platform device in the kernel + * @param *o_config - video capture/epc660 chip information + * @return "0" for OK or error msg + */ static int fill_config(struct platform_device *pdev, struct capture_config *o_config) { @@ -972,6 +1061,11 @@ static int fill_config(struct platform_device *pdev, return 0; } +/** + * @brief Basic function after initilization called by the kernel to gather structs/values of the driver device + * @param struct platform_device - Representation of the platform device in the kernel to be set in this function + * @return "0" for OK or error msg + */ static int epc660_probe(struct platform_device *pdev) { struct epc660_device *epc660_dev; @@ -997,6 +1091,7 @@ static int epc660_probe(struct platform_device *pdev) return -ENOMEM; } + /* struct device_node *of_node : associated device tree node */ if (dev->of_node) { fill_config(pdev, &epc660_dev->cfg); } else { @@ -1105,6 +1200,7 @@ static int epc660_probe(struct platform_device *pdev) memset(&epc660_dev->cfg.board_info, 0, sizeof(epc660_dev->cfg.board_info)); strlcpy(epc660_dev->cfg.board_info.type, epc660_dev->cfg.card_name, sizeof(epc660_dev->cfg.board_info.type)); + /* ToDo @JAHA: Set this magic value into Device Tree Configuration ... */ epc660_dev->cfg.board_info.addr = 0x22; epc660_dev->cfg.board_info.platform_data = NULL; @@ -1200,6 +1296,11 @@ static int epc660_probe(struct platform_device *pdev) return ret; } +/** + * @brief Basic function before freeing the driver device called by the kernel to free storage and remove structs + * @param struct platform_device - Representation of the platform device in the kernel + * @return "0" for OK + */ static int epc660_remove(struct platform_device *pdev) { struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); @@ -1217,6 +1318,9 @@ static int epc660_remove(struct platform_device *pdev) return 0; } +/** + * @brief Basic structure for announcing the driver to the kernel (with "module_platform_driver") + */ static struct platform_driver epc660_driver = { .driver = { From 479b9ebb68db7ac9225981d0d2aaa4f82d78497b Mon Sep 17 00:00:00 2001 From: "Jan.Hannig" Date: Wed, 13 Oct 2021 15:15:22 +0200 Subject: [PATCH 03/11] [RDPHOEN-463/RDPHOEN-467] Removed unused code Removed unused subdev calls (fct not implemented). Removed unused video formats in capture driver: "2DCS + gray interleaved" and "4DCS + gray interleaved" Renamed the other formats Removed corresponding lines in epc660_monochrome_fmts in epc660.c --- drivers/media/i2c/soc_camera/epc660.c | 2 - .../platform/iris-gen6/epc660_capture_sc57x.c | 42 ++----------------- 2 files changed, 4 insertions(+), 40 deletions(-) diff --git a/drivers/media/i2c/soc_camera/epc660.c b/drivers/media/i2c/soc_camera/epc660.c index 5676003e3949..f256d1c5d00b 100755 --- a/drivers/media/i2c/soc_camera/epc660.c +++ b/drivers/media/i2c/soc_camera/epc660.c @@ -62,9 +62,7 @@ static const struct epc660_datafmt epc660_monochrome_fmts[] = { /* Order important - see above */ {MEDIA_BUS_FMT_Y12_1X12, V4L2_COLORSPACE_JPEG}, {MEDIA_BUS_FMT_EPC660_2X12, V4L2_COLORSPACE_JPEG}, - {MEDIA_BUS_FMT_EPC660_3X12, V4L2_COLORSPACE_JPEG}, {MEDIA_BUS_FMT_EPC660_4X12, V4L2_COLORSPACE_JPEG}, - {MEDIA_BUS_FMT_EPC660_5X12, V4L2_COLORSPACE_JPEG}, }; struct epc660 { diff --git a/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c b/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c index e7550c0f9ee1..534221b33fe0 100644 --- a/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c +++ b/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c @@ -169,7 +169,7 @@ struct epc660_device { */ static const struct imager_format epc660_formats[] = { { - .desc = "12bit Grey Scale", + .desc = "1DCS_12bpp", .pixelformat = V4L2_PIX_FMT_Y12, .mbus_code = MEDIA_BUS_FMT_Y12_1X12, .bpp = 16, @@ -178,7 +178,7 @@ static const struct imager_format epc660_formats[] = { .pixel_depth_bytes = 2, }, { - .desc = "2DCS interleaved", + .desc = "2DCS_12bpp", .pixelformat = v4l2_fourcc('2', 'D', 'C', 'S'), .mbus_code = MEDIA_BUS_FMT_EPC660_2X12, .bpp = 16, @@ -187,16 +187,7 @@ static const struct imager_format epc660_formats[] = { .pixel_depth_bytes = 4, }, { - .desc = "2DCS + gray interleaved", - .pixelformat = v4l2_fourcc('2', 'D', 'C', 'G'), - .mbus_code = MEDIA_BUS_FMT_EPC660_3X12, - .bpp = 16, - .dlen = 12, // 12 bit samples are mapped to 16 bits - .channels = 3, - .pixel_depth_bytes = 8, - }, - { - .desc = "4DCS interleaved", + .desc = "4DCS_12bpp", .pixelformat = v4l2_fourcc('4', 'D', 'C', 'S'), .mbus_code = MEDIA_BUS_FMT_EPC660_4X12, .bpp = 16, @@ -204,16 +195,6 @@ static const struct imager_format epc660_formats[] = { .channels = 4, .pixel_depth_bytes = 8, }, - { - .desc = "4DCS + gray interleaved", - .pixelformat = v4l2_fourcc('4', 'D', 'C', 'G'), - .mbus_code = MEDIA_BUS_FMT_EPC660_5X12, - .bpp = 16, - .dlen = 12, // 12 bit samples are mapped to 16 bits - .channels = 5, - .pixel_depth_bytes = 16, - }, - }; #define MAX_FMTS ARRAY_SIZE(epc660_formats) @@ -766,19 +747,13 @@ static int epc660_enum_input(struct file *file, void *priv, struct epc660_device *epc660_dev = video_drvdata(file); struct capture_config *config = &epc660_dev->cfg; - int ret; - u32 status; - /* Compare the input value with the value in the driver */ if (input->index >= config->num_inputs) return -EINVAL; /* set the input value for the required input instance */ *input = config->inputs[input->index]; - /* get input status */ - ret = v4l2_subdev_call(epc660_dev->sd, video, g_input_status, &status); - if (!ret) - input->status = status; + return 0; } @@ -794,8 +769,6 @@ static int epc660_s_input(struct file *file, void *priv, unsigned int index) struct epc660_device *epc660_dev = video_drvdata(file); struct vb2_queue *vq = &epc660_dev->buffer_queue; struct capture_config *config = &epc660_dev->cfg; - struct imager_route *route; - int ret; if (vb2_is_busy(vq)) return -EBUSY; @@ -803,13 +776,6 @@ static int epc660_s_input(struct file *file, void *priv, unsigned int index) if (index >= config->num_inputs) return -EINVAL; - route = &config->routes[index]; - ret = v4l2_subdev_call(epc660_dev->sd, video, s_routing, route->input, - route->output, 0); - if ((ret < 0) && (ret != -ENOIOCTLCMD)) { - v4l2_err(&epc660_dev->v4l2_dev, "Failed to set input\n"); - return ret; - } epc660_dev->cur_input = index; return 0; } From 31b7b8c446c57766acdfff87e5a5a1a244835f7b Mon Sep 17 00:00:00 2001 From: "Jan.Hannig" Date: Wed, 13 Oct 2021 15:51:35 +0200 Subject: [PATCH 04/11] [RDPHOEN-463] Added #define DEBUG and printouts For the development and debug code in the driver, a DEBUG macro is created. Debug-printouts for functions are added. Added doxygen comments to epc660.c --- drivers/media/i2c/soc_camera/epc660.c | 21 ++- .../platform/iris-gen6/epc660_capture_sc57x.c | 164 ++++++++++++++---- 2 files changed, 142 insertions(+), 43 deletions(-) diff --git a/drivers/media/i2c/soc_camera/epc660.c b/drivers/media/i2c/soc_camera/epc660.c index f256d1c5d00b..5fb2b6d58f6b 100755 --- a/drivers/media/i2c/soc_camera/epc660.c +++ b/drivers/media/i2c/soc_camera/epc660.c @@ -45,7 +45,10 @@ struct epc660_datafmt { enum v4l2_colorspace colorspace; }; -/* Find a data format by a pixel code in an array */ +/** + * @brief Find a data format by a pixel code in an array + * @brief Used in epc660_set_fmt + */ static const struct epc660_datafmt *epc660_find_datafmt( u32 code, const struct epc660_datafmt *fmt, int n) @@ -58,6 +61,10 @@ static const struct epc660_datafmt *epc660_find_datafmt( return NULL; } +/** + * @brief used to store sensor supported formats + * @brief corresponding with "static const struct imager_format epc660_formats[]" in epc660_capture_sc57x.c @JAHA ToDo: Change this? + */ static const struct epc660_datafmt epc660_monochrome_fmts[] = { /* Order important - see above */ {MEDIA_BUS_FMT_Y12_1X12, V4L2_COLORSPACE_JPEG}, @@ -164,9 +171,8 @@ static int epc660_eeprom_read_word(struct i2c_client *client, } /* - * Send an I2C sequence to the imager. - * - * Return 0 on success, otherwise the i2c return code. + * @brief Send an I2C sequence to the imager. Used in function epc660_load_fw + * @brief Return 0 on success, otherwise the i2c return code. */ static int epc660_send_i2c_sequence(struct i2c_client *client, const u8 *seq) @@ -403,6 +409,9 @@ static long epc660_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void* arg) return 0; } +/** + * @brief Function for (re-)setting the reset pin of the EPC660 + */ static int epc660_reset(struct v4l2_subdev *sd, u32 val) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct epc660 *epc660 = to_epc660(client); @@ -455,8 +464,8 @@ static int epc660_load_fw(struct v4l2_subdev *sd) { /* - * Interface active, can use i2c. If it fails, it can indeed mean, that - * this wasn't our capture interface, so, we wait for the right one + * @brief Interface active, can use i2c. If it fails, it can indeed mean, that + * @brief this wasn't our capture interface, so, we wait for the right one. Used by epc660_probe. */ static int epc660_video_probe(struct i2c_client *client) { diff --git a/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c b/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c index 534221b33fe0..5761165de5de 100644 --- a/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c +++ b/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c @@ -60,6 +60,7 @@ #define COMPATIBLE_DT_NAME "iris,gen6-epc660" #define CAPTURE_DRV_NAME "epc660_capture" #define MIN_NUM_BUF 2 +#define DEBUG 0 struct imager_format { char *desc; @@ -296,6 +297,10 @@ static int epc660_queue_setup(struct vb2_queue *vq, { struct epc660_device *epc660_dev = vb2_get_drv_priv(vq); + #if DEBUG + printk(KERN_INFO "#### epc660_queue_setup: num_buffers: %d *nbuffers: %d *nplanes: %d sizeimage: %d sizes[0]: %d\n", vq->num_buffers, *nbuffers, *nplanes, epc660_dev->fmt.sizeimage, sizes[0] ); + #endif /*DEBUG*/ + if (vq->num_buffers + *nbuffers < MIN_NUM_BUF) *nbuffers = MIN_NUM_BUF; @@ -324,6 +329,10 @@ static int epc660_buffer_init(struct vb2_buffer *vb) struct imager_dma_desc_list_item *dma_desc; int halfImageSizeBytes, rowSizeBytes; + #if DEBUG +// printk(KERN_INFO "#### epc660_buffer_init\n"); + #endif /*DEBUG*/ + INIT_LIST_HEAD(&buf->list); /* The DMA-Pool of DMA descriptors is organized as a list. @@ -368,19 +377,24 @@ static int epc660_buffer_init(struct vb2_buffer *vb) (dma_desc-1)->cfg |= DI_EN_X; // print the descriptors -// dma_desc = buf->dma_desc; -// printk("buf->desc_dma_addr %08x\n", buf->desc_dma_addr); -// for (i = 0; i < dmaDescArrCount; ++i) { -// printk("dma_descriptor %d:" -// "\n\t next_desc_addr %x" -// "\n\t start_addr %x" -// "\n\t cfg %08lx\n", -// i, -// buf->dma_desc[i].next_desc_addr, -// buf->dma_desc[i].start_addr, -// buf->dma_desc[i].cfg -// ); -// } + #if DEBUG + { + int i; + int dmaDescArrCount = epc660_dev->pixel_channels; + printk("buf->desc_dma_addr %08x\n", buf->desc_dma_addr); + for (i = 0; i < dmaDescArrCount; ++i) { + printk("dma_descriptor %d:" + "\n\t next_desc_addr %x" + "\n\t start_addr %x" + "\n\t cfg %08lx\n", + i, + buf->dma_desc[i].next_desc_addr, + buf->dma_desc[i].start_addr, + buf->dma_desc[i].cfg + ); + } + } + #endif /*DEBUG*/ return 0; } @@ -402,6 +416,10 @@ static int epc660_buffer_prepare(struct vb2_buffer *vb) } vb2_set_plane_payload(vb, 0, size); + #if DEBUG + printk(KERN_INFO "#### epc660_buffer_prepare: size: %ld, fmtfield: %d\n", size, epc660_dev->fmt.field); + #endif /*DEBUG*/ + vbuf->field = epc660_dev->fmt.field; return 0; @@ -419,8 +437,15 @@ static void epc660_buffer_queue(struct vb2_buffer *vb) struct imager_buffer *buf = vb2v4l2_to_imagerbuffer(vbuf); unsigned long flags; int last_dma_desc_idx; + + #if DEBUG +// printk(KERN_INFO "#### epc660_buffer_queue\n"); + #endif /*DEBUG*/ last_dma_desc_idx = epc660_dev->pixel_channels * epc660_dev->fmt.height - 1; buf->dma_desc[last_dma_desc_idx].next_desc_addr = buf->desc_dma_addr; + #if DEBUG + printk(KERN_INFO "#### epc660_buffer_queue: start_adresse: %x desc_dma_addr: %x\n", buf->dma_desc[0].start_addr , buf->desc_dma_addr); + #endif /*DEBUG*/ spin_lock_irqsave(&epc660_dev->lock, flags); // setup the dma descriptor @@ -428,18 +453,22 @@ static void epc660_buffer_queue(struct vb2_buffer *vb) struct imager_buffer* lastBuffer; lastBuffer = list_last_entry(&epc660_dev->dma_queue, struct imager_buffer, list); lastBuffer->dma_desc[last_dma_desc_idx].next_desc_addr = buf->desc_dma_addr; + #if DEBUG + //printk(KERN_INFO "#### epc660_buffer_queue: !list_empty\n"); + #endif /*DEBUG*/ } - -// { -// struct list_head *pos; -// int listSize = 0; -// list_for_each(pos, &epc660_dev->dma_queue) -// { -// ++listSize; -// } -// printk("listsize: %d\n", listSize); -// } + #if 0// DEBUG + { + struct list_head *pos; + int listSize = 0; + list_for_each(pos, &epc660_dev->dma_queue) + { + ++listSize; + } + printk("listsize: %d\n", listSize); + } + #endif /*DEBUG*/ list_add_tail(&buf->list, &epc660_dev->dma_queue); @@ -453,6 +482,10 @@ static void epc660_buffer_cleanup(struct vb2_buffer *vb) struct imager_buffer *buf = vb2v4l2_to_imagerbuffer(vbuf); unsigned long flags; + #if DEBUG + printk(KERN_INFO "#### epc660_buffer_cleanup\n"); + #endif /*DEBUG*/ + spin_lock_irqsave(&epc660_dev->lock, flags); list_del_init(&buf->list); spin_unlock_irqrestore(&epc660_dev->lock, flags); @@ -471,6 +504,10 @@ static int epc660_start_streaming(struct vb2_queue *vq, unsigned int count) struct ppi_params params; int ret; + #if DEBUG + printk(KERN_INFO "#### epc660_start_streaming\n"); + #endif /*DEBUG*/ + /* enable streamon on the sub device */ ret = v4l2_subdev_call(epc660_dev->sd, video, s_stream, 1); if (ret && (ret != -ENOIOCTLCMD)) { @@ -512,6 +549,10 @@ static void epc660_stop_streaming(struct vb2_queue *vq) int ret; unsigned long flags; + #if DEBUG + printk(KERN_INFO "#### epc660_stop_streaming\n"); + #endif /*DEBUG*/ + spin_lock_irqsave(&epc660_dev->lock, flags); epc660_stop_transfering(epc660_dev); @@ -544,7 +585,7 @@ static struct vb2_ops epc660_video_qops = .stop_streaming = epc660_stop_streaming,/* Call in Shutdown-Phase */ }; -#if 0 +#if DEBUG static void printDMAState(struct epc660_device *epc660_dev) { printk("dma config:" @@ -553,28 +594,28 @@ static void printDMAState(struct epc660_device *epc660_dev) "\n\t cfg %08lx" "\n\t x_count %lu" "\n\t x_modify %ld" - "\n\t y_count %lu" - "\n\t y_modify %ld" + /*"\n\t y_count %lu"*/ + /*"\n\t y_modify %ld"*/ "\n\t curr_desc_ptr %p" "\n\t prev_desc_ptr %p" - "\n\t curr_addr_ptr %08lx" - "\n\t irq_status %08lx" - "\n\t curr_x_count %ld" - "\n\t curr_y_count %ld\n", + /*"\n\t curr_addr_ptr %08lx" + "\n\t irq_status %08lx"*/ + "\n\t curr_x_count %ld\n" + /*"\t curr_y_count %ld\n"*/, - get_dma_next_desc_ptr(epc660_dev->dma_channel), + get_dma_next_desc_ptr(epc660_dev->dma_channel), get_dma_start_addr(epc660_dev->dma_channel), get_dma_config(epc660_dev->dma_channel), get_dma_x_count(epc660_dev->dma_channel), get_dma_x_modify(epc660_dev->dma_channel), - get_dma_y_count(epc660_dev->dma_channel), - get_dma_y_modify(epc660_dev->dma_channel), + /*get_dma_y_count(epc660_dev->dma_channel),*/ + /*get_dma_y_modify(epc660_dev->dma_channel),*/ get_dma_curr_desc_ptr(epc660_dev->dma_channel), get_dma_prev_desc_ptr(epc660_dev->dma_channel), - get_dma_curr_addr(epc660_dev->dma_channel), - get_dma_curr_irqstat(epc660_dev->dma_channel), - get_dma_curr_xcount(epc660_dev->dma_channel), - get_dma_curr_ycount(epc660_dev->dma_channel)); + /*get_dma_curr_addr(epc660_dev->dma_channel), + get_dma_curr_irqstat(epc660_dev->dma_channel),*/ + get_dma_curr_xcount(epc660_dev->dma_channel)/*, + get_dma_curr_ycount(epc660_dev->dma_channel)*/); } #endif @@ -586,7 +627,11 @@ static irqreturn_t epc660_isr(int irq, void *dev_id) dma_addr_t lastDmaDescriptor; struct list_head* iterator; + #if DEBUG // printk("epc660_isr\n"); +// printk(KERN_INFO "#### epc660_isr\n"); + #endif /*DEBUG*/ + spin_lock(&epc660_dev->lock); dmaStatus = get_dma_curr_irqstat(epc660_dev->dma_channel); @@ -595,8 +640,10 @@ static irqreturn_t epc660_isr(int irq, void *dev_id) if (dmaStatus & DMA_DONE) { // if there are at least two buffers in the queue we can deque one if (&epc660_dev->dma_queue == epc660_dev->dma_queue.next->next) { + #if DEBUG // printk("buffer underrun in epc660 capture\n"); // epc660_stop_transfering(epc660_dev); + #endif /*DEBUG*/ } else { /* publish all buffers that are done */ int completedCnt = 0; @@ -611,12 +658,16 @@ static irqreturn_t epc660_isr(int irq, void *dev_id) } // printk("lastDmaDescriptor: 0x%08x\n", lastDmaDescriptor); if (0 == completedCnt) { + #if DEBUG printk("cannot find any completed buffers!\n"); // epc660_stop_transfering(epc660_dev); + #endif /*DEBUG*/ } else { struct imager_buffer* buf; struct vb2_buffer *vb; + #if DEBUG // printk("found %d completed buffers\n", completedCnt); + #endif /*DEBUG*/ while (completedCnt--) { if (&epc660_dev->dma_queue == epc660_dev->dma_queue.next->next) { break; @@ -706,6 +757,10 @@ static int epc660_streamon(struct file *file, void *priv, int ret; struct imager_buffer* buf; + #if DEBUG + //printk(KERN_INFO "#### epc660_streamon\n"); + #endif /*DEBUG*/ + if (vb2_queue_is_busy(epc660_dev->video_dev, file)) return -EBUSY; @@ -726,6 +781,9 @@ static int epc660_streamon(struct file *file, void *priv, /* get the next frame from the dma queue */ buf = list_entry(epc660_dev->dma_queue.next, struct imager_buffer, list); + #if DEBUG + printk("##streamon: buf->desc_dma_addr %08x\n", buf->desc_dma_addr); + #endif /*DEBUG*/ epc660_start_transfering(epc660_dev, buf->desc_dma_addr); spin_unlock_irqrestore(&epc660_dev->lock, flags); @@ -747,6 +805,10 @@ static int epc660_enum_input(struct file *file, void *priv, struct epc660_device *epc660_dev = video_drvdata(file); struct capture_config *config = &epc660_dev->cfg; + #if DEBUG + //printk(KERN_INFO "#### epc660_enum_input\n"); + #endif /*DEBUG*/ + /* Compare the input value with the value in the driver */ if (input->index >= config->num_inputs) return -EINVAL; @@ -770,6 +832,10 @@ static int epc660_s_input(struct file *file, void *priv, unsigned int index) struct vb2_queue *vq = &epc660_dev->buffer_queue; struct capture_config *config = &epc660_dev->cfg; + #if DEBUG + printk(KERN_INFO "#### epc660_s_input\n"); + #endif /*DEBUG*/ + if (vb2_is_busy(vq)) return -EBUSY; @@ -826,6 +892,10 @@ static int epc660_g_fmt_vid_cap(struct file *file, void *priv, { struct epc660_device *epc660_dev = video_drvdata(file); + #if DEBUG + printk(KERN_INFO "#### epc660_g_fmt_vid_cap\n"); + #endif /*DEBUG*/ + fmt->fmt.pix = epc660_dev->fmt; return 0; } @@ -901,9 +971,13 @@ static int epc660_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a) static int epc660_log_status(struct file *file, void *priv) { +#if DEBUG struct epc660_device *epc660_dev = video_drvdata(file); + printk(KERN_INFO "#### epc660_log_status\n"); + /* status for sub devices */ v4l2_device_call_all(&epc660_dev->v4l2_dev, 0, core, log_status); +#endif /*DEBUG*/ return 0; } @@ -926,6 +1000,10 @@ static const struct v4l2_ioctl_ops epc660_ioctl_ops = static int epc660_open(struct file* filp) { int ret; struct epc660_device *epc660_dev = video_drvdata(filp); + #if DEBUG + printk(KERN_INFO "#### epc660_open\n"); + #endif /*DEBUG*/ + if (!epc660_dev) { return -EINVAL; } @@ -940,6 +1018,10 @@ static int epc660_open(struct file* filp) { static int epc660_release(struct file* filp) { int ret; struct epc660_device *epc660_dev = video_drvdata(filp); + #if DEBUG + printk(KERN_INFO "#### epc660_release\n"); + #endif /*DEBUG*/ + if (!epc660_dev) { return -EINVAL; } @@ -1044,6 +1126,10 @@ static int epc660_probe(struct platform_device *pdev) struct gpio_desc *gpio; int ret; + #if DEBUG + printk(KERN_INFO "#### epc660_probe\n"); + #endif /*DEBUG*/ + match = of_match_device(cap_match, &pdev->dev); if (!match) { dev_err(dev, "failed to matching of_match node\n"); @@ -1273,6 +1359,10 @@ static int epc660_remove(struct platform_device *pdev) struct epc660_device *epc660_dev = container_of(v4l2_dev, struct epc660_device, v4l2_dev); + #if DEBUG + printk(KERN_INFO "#### epc660_remove\n"); + #endif /*DEBUG*/ + epc660_free_sensor_formats(epc660_dev); video_unregister_device(epc660_dev->video_dev); v4l2_ctrl_handler_free(&epc660_dev->ctrl_handler); From e63d7800aa51c0ac2c9e0f161e9c2f37507cff5c Mon Sep 17 00:00:00 2001 From: "Jan.Hannig" Date: Wed, 13 Oct 2021 16:49:36 +0200 Subject: [PATCH 05/11] [RDPHOEN-463/RDPHOEN-507] Removed "epc660_try_format" Re-Integrated still necessary code into "epc660_s_fmt_vid_cap". --- .../platform/iris-gen6/epc660_capture_sc57x.c | 82 +++++++------------ 1 file changed, 30 insertions(+), 52 deletions(-) diff --git a/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c b/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c index 5761165de5de..04db56d7ecff 100644 --- a/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c +++ b/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c @@ -846,46 +846,6 @@ static int epc660_s_input(struct file *file, void *priv, unsigned int index) return 0; } -static int epc660_try_format(struct epc660_device *epc660_dev, - struct v4l2_pix_format *pixfmt, - struct imager_format *epc660_fmt) -{ - struct imager_format *sf = epc660_dev->sensor_formats; - struct imager_format *fmt = NULL; - struct v4l2_subdev_pad_config pad_cfg; - struct v4l2_subdev_format format = { - .which = V4L2_SUBDEV_FORMAT_TRY, - }; - int ret, i; - - for (i = 0; i < epc660_dev->num_sensor_formats; i++) { - fmt = &sf[i]; - if (pixfmt->pixelformat == fmt->pixelformat) - break; - } - if (i == epc660_dev->num_sensor_formats) - fmt = &sf[0]; - - v4l2_fill_mbus_format(&format.format, pixfmt, fmt->mbus_code); - ret = v4l2_subdev_call(epc660_dev->sd, pad, set_fmt, &pad_cfg, - &format); - if (ret < 0) - return ret; - v4l2_fill_pix_format(pixfmt, &format.format); - if (epc660_fmt) { - for (i = 0; i < epc660_dev->num_sensor_formats; i++) { - fmt = &sf[i]; - if (format.format.code == fmt->mbus_code) - break; - } - *epc660_fmt = *fmt; - } - - pixfmt->bytesperline = pixfmt->width * epc660_fmt->pixel_depth_bytes; - pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height; - return 0; -} - /* this function isn't called but necessary for kernel function (v4l2_ioctl_ops) */ static int epc660_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *fmt) @@ -909,35 +869,53 @@ static int epc660_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *fmt) { struct epc660_device *epc660_dev = video_drvdata(file); + struct imager_format *sf = epc660_dev->sensor_formats; struct vb2_queue *vq = &epc660_dev->buffer_queue; struct v4l2_subdev_format format = { .which = V4L2_SUBDEV_FORMAT_ACTIVE, }; - struct imager_format epc660_fmt; + struct imager_format *epc660_fmt; struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; int dmaPoolMemorySize; - int ret; + int ret, i; if (vb2_is_busy(vq)) return -EBUSY; - /* see if format works */ - ret = epc660_try_format(epc660_dev, pixfmt, &epc660_fmt); - if (ret < 0) - return ret; + /* Searches in the format array of all available formats in the capture driver + for that pixelformat which was given into driver by application. */ + for (i = 0; i < epc660_dev->num_sensor_formats; i++) { + epc660_fmt = &sf[i]; + if (pixfmt->pixelformat == epc660_fmt->pixelformat) + break; + } + /* If the configured format isn't found in list, take the first one + in array as default.*/ + if (i == epc660_dev->num_sensor_formats) + epc660_fmt = &sf[0]; + + pixfmt->bytesperline = pixfmt->width * epc660_fmt->pixel_depth_bytes; + pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height; + + #if DEBUG + printk(KERN_INFO "#### epc660_s_fmt_vid_cap width: %d, height: %d\n", pixfmt->width, pixfmt->height); + //printk(KERN_INFO "#### epc660_s_fmt_vid_cap wdth: %d, px_dpthbyts: %d, bytperln: %d, hght: %d\n", pixfmt->width, epc660_fmt->pixel_depth_bytes, pixfmt->bytesperline, pixfmt->height); + #endif /*DEBUG*/ - v4l2_fill_mbus_format(&format.format, pixfmt, epc660_fmt.mbus_code); + /* Fills format.format for usage in v4l2_subdev_call */ + v4l2_fill_mbus_format(&format.format, pixfmt, epc660_fmt->mbus_code); + /* Sets the format parameter in the epc660.c I2C- Driver + This function might be called during runtime without further implications */ ret = v4l2_subdev_call(epc660_dev->sd, pad, set_fmt, NULL, &format); if (ret < 0) return ret; /* Store the parameter of the configured video format (application) into epc660_dev module struct */ epc660_dev->fmt = *pixfmt; - epc660_dev->bpp = epc660_fmt.bpp; - epc660_dev->dlen = epc660_fmt.dlen; - epc660_dev->pixel_channels = epc660_fmt.channels; - /* align the pixels to 4 bytes */ - epc660_dev->pixel_depth_bytes = epc660_fmt.pixel_depth_bytes; + epc660_dev->bpp = epc660_fmt->bpp; + epc660_dev->dlen = epc660_fmt->dlen; + epc660_dev->pixel_channels = epc660_fmt->channels; + epc660_dev->pixel_depth_bytes = epc660_fmt->pixel_depth_bytes; memset(&epc660_dev->dma_cfg_template, 0, sizeof(epc660_dev->dma_cfg_template)); epc660_dev->dma_cfg_template.cfg = RESTART | From 1c1f5fc7dc08a453852ebb9ee28b4e467d7a7900 Mon Sep 17 00:00:00 2001 From: "Jan.Hannig" Date: Wed, 13 Oct 2021 17:19:21 +0200 Subject: [PATCH 06/11] [RDPHOEN-463/RDPHOEN-464] Remove line sorting in "buffer_init" [RDPHOEN-463/RDPHOEN-439] Rearrange the pixel/channel order within one line - Added #define PIXEL_PER_CYCLE for magic number 16 - Added information for the connection between DMA_WORDSIZE and pixel per cycle. - Set pixel_depth_bytes = 2 in all video formats as the pixel size is "2 Bytes" in all formats: This corrects the DMA sorting in the raw pictures. --- .../platform/iris-gen6/epc660_capture_sc57x.c | 93 ++++++++++--------- 1 file changed, 49 insertions(+), 44 deletions(-) diff --git a/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c b/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c index 04db56d7ecff..5bbfdaf2f26d 100644 --- a/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c +++ b/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c @@ -60,6 +60,12 @@ #define COMPATIBLE_DT_NAME "iris,gen6-epc660" #define CAPTURE_DRV_NAME "epc660_capture" #define MIN_NUM_BUF 2 +/** + * @brief PIXEL_PER_CYCLE: With a WORDSIZE of 256, the DMA transfers 256 Bit = 32 Byte per cycle. + * @brief With a size of 16 Bit/Pixel = 2 Bytes/Pixel, the DMA transfers 32 Byte/Cycle * (1/2) Pixel/Byte = 16 Pixel/Cycle + * @brief Corresponds with WDSIZE_256 (e.g. with WDSIZE_128, PIXEL_PER_CYCLE is 8) + */ +#define PIXEL_PER_CYCLE 16 #define DEBUG 0 struct imager_format { @@ -185,7 +191,7 @@ static const struct imager_format epc660_formats[] = { .bpp = 16, .dlen = 12, // 12 bit samples are mapped to 16 bits .channels = 2, - .pixel_depth_bytes = 4, + .pixel_depth_bytes = 2, }, { .desc = "4DCS_12bpp", @@ -194,7 +200,7 @@ static const struct imager_format epc660_formats[] = { .bpp = 16, .dlen = 12, // 12 bit samples are mapped to 16 bits .channels = 4, - .pixel_depth_bytes = 8, + .pixel_depth_bytes = 2, }, }; #define MAX_FMTS ARRAY_SIZE(epc660_formats) @@ -323,11 +329,9 @@ static int epc660_buffer_init(struct vb2_buffer *vb) struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct epc660_device *epc660_dev = vb2_get_drv_priv(vb->vb2_queue); struct imager_buffer *buf = vb2v4l2_to_imagerbuffer(vbuf); - int dmaDescArrCount; - int i, channel; - dma_addr_t start_addr, channelStartAddr, nextDescrDMAAddr; + int channel; + dma_addr_t start_addr, nextDescrDMAAddr; struct imager_dma_desc_list_item *dma_desc; - int halfImageSizeBytes, rowSizeBytes; #if DEBUG // printk(KERN_INFO "#### epc660_buffer_init\n"); @@ -343,38 +347,32 @@ static int epc660_buffer_init(struct vb2_buffer *vb) return -ENOMEM; } - dmaDescArrCount = epc660_dev->pixel_channels * epc660_dev->fmt.height; - start_addr = vb2_dma_contig_plane_dma_addr(vb, 0); - rowSizeBytes = epc660_dev->fmt.width * epc660_dev->pixel_depth_bytes; - halfImageSizeBytes = rowSizeBytes * epc660_dev->fmt.height / 2; - + #if DEBUG + printk(KERN_INFO "##buffer_init## fmt-width: %d fmt-height: %d pix-dpth: %d\n", epc660_dev->fmt.width, epc660_dev->fmt.height, epc660_dev->pixel_depth_bytes); + #endif /*DEBUG*/ + /* With every call of this function, with a new DMA allocation a new start address is evaluated */ + start_addr = vb2_dma_contig_plane_dma_addr(vb, 0); dma_desc = buf->dma_desc; nextDescrDMAAddr = buf->desc_dma_addr + sizeof(*dma_desc); for (channel = 0; channel < epc660_dev->pixel_channels; ++channel) { - channelStartAddr = start_addr + channel * ((epc660_dev->bpp + 7) / 8) * 16; // * 16 because the dma transfers sixteen pixels at a time - for (i = 0; i < epc660_dev->fmt.height/2; i += 1) { - /* bottom half */ - dma_desc->next_desc_addr = nextDescrDMAAddr; - dma_desc->start_addr = channelStartAddr + halfImageSizeBytes + i * rowSizeBytes; - dma_desc->cfg = epc660_dev->dma_cfg_template.cfg; - ++dma_desc; - nextDescrDMAAddr += sizeof(*dma_desc); - - /* top half */ - dma_desc->next_desc_addr = nextDescrDMAAddr; - dma_desc->start_addr = channelStartAddr + halfImageSizeBytes - ((i+1) * rowSizeBytes); - dma_desc->cfg = epc660_dev->dma_cfg_template.cfg; - ++dma_desc; - nextDescrDMAAddr += sizeof(*dma_desc); - } - } - /* copy the descriptor config on the first transfer */ - buf->dma_desc->cfg |= DESCIDCPY; - + /* ((epc660_dev->bpp + 7) / 8): We want the minimum necessary size of Bytes for a given number of bits. + Maximum pixel line length (fmt.width) and the complete line number of one picture (fmt.height): buffer for one channel/plane/picture*/ + dma_desc->start_addr = start_addr + channel * ((epc660_dev->bpp + 7) / 8) * epc660_dev->fmt.width * epc660_dev->fmt.height; + #if DEBUG + printk("##buffer_init## start_addr %x; channel %d; dma_desc-start_addr: %x\n", start_addr, channel, dma_desc->start_addr ); + #endif /*DEBUG*/ + dma_desc->next_desc_addr = nextDescrDMAAddr; + dma_desc->cfg = epc660_dev->dma_cfg_template.cfg; + ++dma_desc; + nextDescrDMAAddr += sizeof(*dma_desc); + } + /* copy the descriptor config into the DMA_DSCPTR_PRV register to be read out from there (on the first transfer) */ + buf->dma_desc->cfg |= DESCIDCPY; /*<0x02000000>*/ + /* If channel==1, the next two lines work on the one and only DMA descriptor element and overwrite some for-loop settings*/ /* the very last element must be a list element that makes the dma point to the beginning */ (dma_desc-1)->next_desc_addr = buf->desc_dma_addr; /* the last transfer shall generate an interrupt */ - (dma_desc-1)->cfg |= DI_EN_X; + (dma_desc-1)->cfg |= DI_EN_X; /*0x00100000*/ // print the descriptors #if DEBUG @@ -441,7 +439,7 @@ static void epc660_buffer_queue(struct vb2_buffer *vb) #if DEBUG // printk(KERN_INFO "#### epc660_buffer_queue\n"); #endif /*DEBUG*/ - last_dma_desc_idx = epc660_dev->pixel_channels * epc660_dev->fmt.height - 1; + last_dma_desc_idx = epc660_dev->pixel_channels - 1; buf->dma_desc[last_dma_desc_idx].next_desc_addr = buf->desc_dma_addr; #if DEBUG printk(KERN_INFO "#### epc660_buffer_queue: start_adresse: %x desc_dma_addr: %x\n", buf->dma_desc[0].start_addr , buf->desc_dma_addr); @@ -918,22 +916,29 @@ static int epc660_s_fmt_vid_cap(struct file *file, void *priv, epc660_dev->pixel_depth_bytes = epc660_fmt->pixel_depth_bytes; memset(&epc660_dev->dma_cfg_template, 0, sizeof(epc660_dev->dma_cfg_template)); - epc660_dev->dma_cfg_template.cfg = RESTART | - DMATOVEN | - WNR | - WDSIZE_256 | - PSIZE_32 | - NDSIZE_2 | - DMAFLOW_LIST | - DMAEN; - epc660_dev->dma_cfg_template.x_count = epc660_dev->fmt.width / 16; - epc660_dev->dma_cfg_template.x_modify = epc660_dev->pixel_depth_bytes * 16; + /* The following config bits configure the DMA with the reg value 0x01024527 + As DMA2D is not set, the DMA mode is 1D automatically.*/ + epc660_dev->dma_cfg_template.cfg = RESTART | ///< DMA Buffer Clear SYNC <0x00000004> + DMATOVEN | ///< DMA Trigger Overrun Error Enable <0x01000000> + WNR | ///< Channel Direction (W/R*) <0x00000002> + WDSIZE_256 | ///< Transfer Word Size 256 Bit <0x00000500> --> Corresponds to PIXEL_PER_CYCLE + PSIZE_32 | ///< Peripheral Transfer Word Size 32 Bit = 4 Byte <0x00000020> + NDSIZE_2 | ///< Next Descriptor Size = 3 <0x00020000> + DMAFLOW_LIST | ///< Descriptor List Mode <0x00004000> + DMAEN; ///< DMA Channel Enable <0x00000001> + + epc660_dev->dma_cfg_template.x_count = epc660_dev->fmt.width * (epc660_dev->fmt.height) / PIXEL_PER_CYCLE; + epc660_dev->dma_cfg_template.x_modify = epc660_dev->pixel_depth_bytes * PIXEL_PER_CYCLE;// After 32 Bytes = 256 Bit WORDSIZE + + #if DEBUG + //printk("#### epc660_s_fmt_vid_cap: x_count %ld, x_modify %ld\n", epc660_dev->dma_cfg_template.x_count, epc660_dev->dma_cfg_template.x_modify); + #endif /*DEBUG*/ if (epc660_dev->dma_pool) { dma_pool_destroy(epc660_dev->dma_pool); } - dmaPoolMemorySize = (epc660_dev->pixel_channels * epc660_dev->fmt.height) * sizeof(struct imager_dma_desc_list_item); + dmaPoolMemorySize = (epc660_dev->pixel_channels ) * sizeof(struct imager_dma_desc_list_item); epc660_dev->dma_pool = dma_pool_create(CAPTURE_DRV_NAME, epc660_dev->v4l2_dev.dev, dmaPoolMemorySize, 16, 0); return 0; } From 888c5e9a00ff8f3f98f034be5b7eb1f58f970007 Mon Sep 17 00:00:00 2001 From: "Jan.Hannig" Date: Wed, 13 Oct 2021 17:40:38 +0200 Subject: [PATCH 07/11] [RDPHOEN-463/RDPHOEN-593] ioctl function "epc600_s_parm" Implemented as interface function for reconfiguring by application during runtime. Extracted "set_PPI_params" and "epc660_set_DMA_registers" for being called seperately during runtime reconfiguration. Re-arranged "epc660_start_streaming" and "epc660_start_transfering" with usage of the new functions. --- .../platform/iris-gen6/epc660_capture_sc57x.c | 152 ++++++++++++++---- 1 file changed, 123 insertions(+), 29 deletions(-) diff --git a/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c b/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c index 5bbfdaf2f26d..a839c3563061 100644 --- a/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c +++ b/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c @@ -491,37 +491,27 @@ static void epc660_buffer_cleanup(struct vb2_buffer *vb) } /** - * @brief Enables streamon on sub device and calls the setting of PPI params - * @param *vq - pointer onto queue buffer. count - unused variable. - * @return "0" for OK + * @brief Sets the PPI params locally and into PPI with the function of ppi->ops + * @brief Handles the error ret value of ppi->ops + * @param *epc660_dev - epc660 driver device struct + * @return "0" for OK or the error ret of ppi->ops */ -static int epc660_start_streaming(struct vb2_queue *vq, unsigned int count) +static int set_PPI_params (struct epc660_device *epc660_dev) { - struct epc660_device *epc660_dev = vb2_get_drv_priv(vq); struct ppi_if *ppi = epc660_dev->ppi; struct ppi_params params; int ret; - #if DEBUG - printk(KERN_INFO "#### epc660_start_streaming\n"); - #endif /*DEBUG*/ - - /* enable streamon on the sub device */ - ret = v4l2_subdev_call(epc660_dev->sd, video, s_stream, 1); - if (ret && (ret != -ENOIOCTLCMD)) { - v4l2_err(&epc660_dev->v4l2_dev, "stream on failed in subdev\n"); - return ret; - } - - /* set ppi params */ + /* As fmt.width==160, the length of the whole line is multipied with 2 (==320), as each Pixel contains of 2 Byte; + As fmt.height==240, for the half picture filled it is divided by 2 (==120) */ params.width = epc660_dev->fmt.width * 2; params.height = epc660_dev->fmt.height / 2; - params.bpp = epc660_dev->bpp; - params.dlen = epc660_dev->dlen; + params.bpp = epc660_dev->bpp; /* 16 */ + params.dlen = epc660_dev->dlen; /* 12 Bits of the 16 Bits are relevant (data word length)*/ params.ppi_control = (EPPI_CTL_DLEN12 | /* Data Word Length: 12 bit */ EPPI_CTL_NON656 | /* XFRTYPE: Non-ITU656 Mode (GP Mode) */ EPPI_CTL_SYNC2 | /* 2 external frame syncs */ - EPPI_CTL_FS1LO_FS2LO | /* FS1 and FS2 are active low */ + EPPI_CTL_FS1LO_FS2LO | /* FS1 and FS2 are active low (FS - frame sync) */ EPPI_CTL_POLC0 | /* sample on falling DCLK */ EPPI_CTL_PACKEN | /* assemble two incomming 16Bit words into one 32Bit word (reduces RAM-load a lot) */ EPPI_CTL_SIGNEXT); @@ -541,6 +531,32 @@ static int epc660_start_streaming(struct vb2_queue *vq, unsigned int count) return 0; } +/** + * @brief Enables streamon on sub device and calls the setting of PPI params + * @param *vq - pointer onto queue buffer. count - unused variable. + * @return "0" for OK + */ +static int epc660_start_streaming(struct vb2_queue *vq, unsigned int count) +{ + struct epc660_device *epc660_dev = vb2_get_drv_priv(vq); + int ret; + + #if DEBUG + printk(KERN_INFO "#### epc660_start_streaming\n"); + #endif /*DEBUG*/ + + /* enable streamon on the sub device */ + ret = v4l2_subdev_call(epc660_dev->sd, video, s_stream, 1); + if (ret && (ret != -ENOIOCTLCMD)) { + v4l2_err(&epc660_dev->v4l2_dev, "stream on failed in subdev\n"); + return ret; + } + + ret = set_PPI_params (epc660_dev); + + return ret; +} + static void epc660_stop_streaming(struct vb2_queue *vq) { struct epc660_device *epc660_dev = vb2_get_drv_priv(vq); @@ -692,6 +708,35 @@ static irqreturn_t epc660_isr(int irq, void *dev_id) return IRQ_HANDLED; } +/** + * @brief This function sets registers of the DMA and enables the DMA with setting the enable bit. + * @brief Setting the DMA register requires a disabled DMA and the IRQ off. + * @brief This function is implemented to be used after epc660_s_fmt_vid_cap; otherwise it doesn't take any effect + * @param *epc660_dev - epc660 driver device struct + * @return "0" for OK + */ +static int epc660_set_DMA_registers (struct epc660_device *epc660_dev) +{ + /* Clear Interrupt Error-Part in status register before enable the DMA again*/ + clear_dma_irqstat(epc660_dev->dma_channel); + set_dma_x_count(epc660_dev->dma_channel, epc660_dev->dma_cfg_template.x_count), + set_dma_x_modify(epc660_dev->dma_channel, epc660_dev->dma_cfg_template.x_modify), + /* The ENABLE Bit is set separately after the other bits + to avoid side effects during setting the config register in the DMA: + First remove the DMA Enable Bit DMAEN from the template, then set the bit separately directly in the register.*/ + epc660_dev->dma_cfg_template.cfg = epc660_dev->dma_cfg_template.cfg & ~DMAEN; + set_dma_config(epc660_dev->dma_channel, epc660_dev->dma_cfg_template.cfg); + enable_dma(epc660_dev->dma_channel); + /* After using the template, reset it to original state */ + epc660_dev->dma_cfg_template.cfg = epc660_dev->dma_cfg_template.cfg | DMAEN; + #if DEBUG + printk("#### epc660_set_DMA_registers\n"); + printDMAState(epc660_dev); + //printk("#### epc660_set_DMA_registers: dmaStatus: 0x%08lx\n", get_dma_curr_irqstat(epc660_dev->dma_channel)); + #endif /*DEBUG*/ + return 0; +} + /** * @brief Requests the DMA channel. Sets the configuration registers and configures PPI as callback functionality. * @brief Starts the PPI and the DMA instance (the DMA by setting the config register and with it the DMA_ENABLE bit). @@ -706,7 +751,7 @@ static int epc660_start_transfering(struct epc660_device *epc660_dev, dma_addr_t ret = request_dma(epc660_dev->dma_channel, "EPC660_dma"); if (ret) { - printk("Unable to allocate DMA channel\n"); + printk("Unable to allocate DMA channel: %d\n", ret); return ret; } @@ -715,10 +760,9 @@ static int epc660_start_transfering(struct epc660_device *epc660_dev, dma_addr_t /* Sets the different HW registers of the DMA on chip. As the descriptor doesn't change, it's called only once in the beginning. */ set_dma_next_desc_addr(epc660_dev->dma_channel, (void*)descrAddr); - set_dma_x_count(epc660_dev->dma_channel, epc660_dev->dma_cfg_template.x_count), - set_dma_x_modify(epc660_dev->dma_channel, epc660_dev->dma_cfg_template.x_modify), - set_dma_config(epc660_dev->dma_channel, epc660_dev->dma_cfg_template.cfg); + /* Set the registers in the DMA and enables the DMA (explicitly) */ + epc660_set_DMA_registers (epc660_dev); /* enable ppi */ epc660_dev->ppi->ops->start(epc660_dev->ppi); @@ -943,13 +987,63 @@ static int epc660_s_fmt_vid_cap(struct file *file, void *priv, return 0; } -static int epc660_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a) +/** + * @brief Sets the variables necessary for configuration fo new picture format by application + * @brief For changing the format by application, before epc660_s_parm, "epc660_s_fmt_vid_cap" has to be called + * @param *strprm: struct with the variables set by application + * @return "0" for OK + */ +static int epc660_s_parm (struct file *file, void *priv, + struct v4l2_streamparm *strprm) { struct epc660_device *epc660_dev = video_drvdata(file); + unsigned long flags; + static long unsigned int dmaStatus_s_parm = 0; + struct imager_buffer* buf; - if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - return v4l2_subdev_call(epc660_dev->sd, video, s_parm, a); + switch (strprm->parm.raw_data[0]){ + + case 246: + dmaStatus_s_parm = get_dma_curr_irqstat(epc660_dev->dma_channel); + break; + + case 253: + #if DEBUG + printk("#### epc660_s_parm 253: width: %d hght: %d\n", epc660_dev->fmt.width, epc660_dev->fmt.height); + #endif /* DEBUG */ + + buf = list_entry(epc660_dev->dma_queue.next, struct imager_buffer, list); + spin_lock_irqsave(&epc660_dev->lock, flags); + set_dma_next_desc_addr(epc660_dev->dma_channel, (void*)buf->desc_dma_addr); + /* Function contains the re-enabling of DMA again */ + epc660_set_DMA_registers (epc660_dev); + + set_PPI_params (epc660_dev); + + /* enable ppi */ + epc660_dev->ppi->ops->start(epc660_dev->ppi); + spin_unlock_irqrestore(&epc660_dev->lock, flags); + + break; + + case 210: + + #if DEBUG + //printDMAState(epc660_dev); + printk("\n#### epc660_s_parm: DMA strt addr: %lx\n", get_dma_start_addr(epc660_dev->dma_channel)); + //printk("#### epc660_s_parm: dma cfg %lx, dmaStatus: 0x%08x curr_x_count_1: %ld curr_x_count_2: %ld \n", get_dma_config(epc660_dev->dma_channel), dmaStatus_s_parm, curr_x_count_1, curr_x_count_2 ); + #endif /*DEBUG*/ + + default: + break; + + } + + #if DEBUG + //printk(KERN_INFO "#### epc660_s_parm: raw_data[0]: %d\n", strprm->parm.raw_data[0]); + #endif /*DEBUG*/ + + return 0; } static int epc660_log_status(struct file *file, void *priv) @@ -975,7 +1069,7 @@ static const struct v4l2_ioctl_ops epc660_ioctl_ops = .vidioc_qbuf = vb2_ioctl_qbuf, ///< Call in EPC660_Imager.cpp during all three phases .vidioc_dqbuf = vb2_ioctl_dqbuf, ///< Call during all three phases .vidioc_streamon = epc660_streamon, ///< Call during start phase by EPC660_Imager.cpp - .vidioc_s_parm = epc660_s_parm, + .vidioc_s_parm = epc660_s_parm, ///< Call with each new parameterizing by application .vidioc_log_status = epc660_log_status, }; From 3b562c120d7931d68c175e37e6fd003ab3d37fff Mon Sep 17 00:00:00 2001 From: "Jan.Hannig" Date: Fri, 15 Oct 2021 09:31:32 +0200 Subject: [PATCH 08/11] [RDPHOEN-463/RDPHOEN-522] Bugfix the EPC660 driver [RDPHOEN-463/RDPHOEN-611] Working with DMA during runtime @RDPHOEN-522: The buffer size is enlarged for the maximum of 4 frames for 4 DCS in full resolution. For this, the corresponding constant value EPC660_MAX_DCS_IMAGES (EPC660_Sensor.h) and #define MAX_DCS_IMAGES (epc660_capture) are introduced. @RDPHOEN-611: For configuring the DMA during runtime, it is stopped in the ISR and restarted again in the ioctl function VIDIOC_S_PARM (epc600_s_parm). --- .../media/platform/iris-gen6/epc660_capture_sc57x.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c b/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c index a839c3563061..c59bf61fde41 100644 --- a/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c +++ b/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c @@ -60,6 +60,7 @@ #define COMPATIBLE_DT_NAME "iris,gen6-epc660" #define CAPTURE_DRV_NAME "epc660_capture" #define MIN_NUM_BUF 2 +#define MAX_DCS_IMAGES 4 ///< This value corresponds to "maxDcsImages" in EPC660_Sensor.h/EPC660_Imager.cpp /** * @brief PIXEL_PER_CYCLE: With a WORDSIZE of 256, the DMA transfers 256 Bit = 32 Byte per cycle. * @brief With a size of 16 Bit/Pixel = 2 Bytes/Pixel, the DMA transfers 32 Byte/Cycle * (1/2) Pixel/Byte = 16 Pixel/Cycle @@ -181,7 +182,7 @@ static const struct imager_format epc660_formats[] = { .mbus_code = MEDIA_BUS_FMT_Y12_1X12, .bpp = 16, .dlen = 12, // 12 bit samples are mapped to 16 bits - .channels = 1, + .channels = 4,// Set to maximum value to get the maximum buffer size during initialization .pixel_depth_bytes = 2, }, { @@ -314,7 +315,7 @@ static int epc660_queue_setup(struct vb2_queue *vq, return sizes[0] < epc660_dev->fmt.sizeimage ? -EINVAL : 0; *nplanes = 1; - sizes[0] = epc660_dev->fmt.sizeimage; + sizes[0] = (epc660_dev->fmt.sizeimage * MAX_DCS_IMAGES); return 0; } @@ -373,6 +374,8 @@ static int epc660_buffer_init(struct vb2_buffer *vb) (dma_desc-1)->next_desc_addr = buf->desc_dma_addr; /* the last transfer shall generate an interrupt */ (dma_desc-1)->cfg |= DI_EN_X; /*0x00100000*/ + /* the last transfer sets the Stop Mode by disabling the LIST_MODE */ + (dma_desc-1)->cfg &= ~DMAFLOW_LIST; /*0x00004000*/ // print the descriptors #if DEBUG @@ -405,7 +408,7 @@ static int epc660_buffer_prepare(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct epc660_device *epc660_dev = vb2_get_drv_priv(vb->vb2_queue); - unsigned long size = epc660_dev->fmt.sizeimage; + unsigned long size = epc660_dev->fmt.sizeimage * MAX_DCS_IMAGES; if (vb2_plane_size(vb, 0) < size) { v4l2_err(&epc660_dev->v4l2_dev, "buffer too small (%lu < %lu)\n", @@ -651,6 +654,8 @@ static irqreturn_t epc660_isr(int irq, void *dev_id) dmaStatus = get_dma_curr_irqstat(epc660_dev->dma_channel); clear_dma_irqstat(epc660_dev->dma_channel); + disable_dma(epc660_dev->dma_channel); + epc660_dev->ppi->ops->stop(epc660_dev->ppi); if (dmaStatus & DMA_DONE) { // if there are at least two buffers in the queue we can deque one if (&epc660_dev->dma_queue == epc660_dev->dma_queue.next->next) { From e9bf8dce86c62f752029ddf58d33246d0b786911 Mon Sep 17 00:00:00 2001 From: "Jan.Hannig" Date: Fri, 15 Oct 2021 11:32:56 +0200 Subject: [PATCH 09/11] [RDPHOEN-644] Enable the DCS configuration Adding the function "adapt_DMA_DescriptorElements" Adding the strprm->parm.raw_data[x] struct members as interface for setting the values of width, height and DCS. Commenting the change form DMA configuration "List Mode" to "Stop Mode" Adding enum "NumberDcsFrames". Adding else path to if statement of ISR. --- .../platform/iris-gen6/epc660_capture_sc57x.c | 124 +++++++++++++++++- 1 file changed, 121 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c b/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c index c59bf61fde41..dd2a17b3b939 100644 --- a/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c +++ b/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c @@ -68,6 +68,8 @@ */ #define PIXEL_PER_CYCLE 16 #define DEBUG 0 +#define FIRST_DESC 0 +#define SECOND_DESC 1 struct imager_format { char *desc; @@ -171,6 +173,15 @@ struct epc660_device { struct mutex mutex; }; +/** + * @brief enum replacing 1 DCS, 2 DCS and 4 DCS + */ +enum NumberDcsFrames { + ONE_DCS = 1, + TWO_DCS = 2, + FOUR_DCS = 4 +}; + /** * @brief used to store sensor supported format * @brief corresponding with "static const struct epc660_datafmt epc660_monochrome_fmts[]" in epc660.c @@ -374,7 +385,10 @@ static int epc660_buffer_init(struct vb2_buffer *vb) (dma_desc-1)->next_desc_addr = buf->desc_dma_addr; /* the last transfer shall generate an interrupt */ (dma_desc-1)->cfg |= DI_EN_X; /*0x00100000*/ - /* the last transfer sets the Stop Mode by disabling the LIST_MODE */ + /* After the last transfer, the Stop Mode is set by disabling the LIST_MODE in the last descriptor. + This prevents the DMA from automatically loading the next descriptor with finishing the last transfer. + So, the descriptor list may be re-configured (see function epc660_s_parm). + Then the next descriptor has to be loaded manually and the DMA can be re-started. */ (dma_desc-1)->cfg &= ~DMAFLOW_LIST; /*0x00004000*/ // print the descriptors @@ -706,7 +720,14 @@ static irqreturn_t epc660_isr(int irq, void *dev_id) } /* clear error flag for the next frame */ ppi->err = false; - } + + } else { + /* The else path catches all other cases/reasons for the ISR than "DMA_DONE". + As it is empirically quite improbable, that the ISR is called without "DMA_DONE", those other cases aren't handled further. + The DMA and the PPI were disabled above already. They only are enabled by the call of "onImage" in the application, which is never called without "DMA_DONE". + For getting a result of analyzing the problem, this printk is set to get information about the cause of problems during runtime.*/ + printk("## isr ## dmaStatus: 0x%08x\n", dmaStatus); + } spin_unlock(&epc660_dev->lock); @@ -992,6 +1013,90 @@ static int epc660_s_fmt_vid_cap(struct file *file, void *priv, return 0; } +/** + * @brief The DMA descriptor element list is adapted according the number of DCS frames. + * @brief Only the last element of the list changes (--> adaptation for DCS=1 and DCS=2). + * @brief Precondition for function call: For re-arranging the descriptor elements and re-loading the DMA descriptor, + * @brief the DMA has to be set to "Stop Mode" with the last transfer (in the last descriptor; see also function "buffer_init"). + * @param int nrDCS_Frames - Number of configured DCS frames + * @return "0" for OK + */ +static int adapt_DMA_DescriptorElements (struct epc660_device *epc660_dev, int nrDCS_Frames) +{ + struct imager_buffer* buf; + struct list_head* iterator; + struct imager_dma_desc_list_item *dma_desc; + dma_addr_t nextDescrDMAAddr; + int i; + + list_for_each(iterator, &epc660_dev->dma_queue) { + buf = list_entry(iterator, struct imager_buffer, list); + /* The dma_desc[i] array starts with "0", nrDCS_Frames contains 1,2,4 */ + for (i= FIRST_DESC; i <= (nrDCS_Frames-1); i++){ + + #if DEBUG + //printk("#### DMA %d vorher %d: 0x%08lx buf->desc_dma_addr: 0x%08x start: %08x, next: %08x\n", nrDCS_Frames, i, buf->dma_desc[i].cfg, buf->desc_dma_addr, buf->dma_desc[i].start_addr, buf->dma_desc[i].next_desc_addr ); + #endif /*DEBUG*/ + + /* Actions for the first descriptor element */ + if ( i == FIRST_DESC ){ + if (nrDCS_Frames == ONE_DCS){ + /* the last transfer shall generate an interrupt */ + buf->dma_desc[i].cfg |= DI_EN_X; /*0x00100000*/ + /* the last transfer sets the Stop Mode by disabling the LIST_MODE */ + buf->dma_desc[i].cfg &= ~DMAFLOW_LIST; /*0x00004000*/ + /* the very last element must be a list element that makes the dma point to the beginning */ + buf->dma_desc[i].next_desc_addr = buf->desc_dma_addr; + break; + } else { + /* As the item isn't the last one, remove the interrupt generation*/ + buf->dma_desc[i].cfg &= ~DI_EN_X; /*0x00100000*/ + /* Activate descriptor list mode if element isn't the last one */ + buf->dma_desc[i].cfg |= DMAFLOW_LIST; /*0x00004000*/ + /* "next descriptor address" of first descriptor is the start address of the 2nd descriptor */ + nextDescrDMAAddr = buf->desc_dma_addr + sizeof(*dma_desc); + buf->dma_desc[i].next_desc_addr = nextDescrDMAAddr; + } + } + + if (i == SECOND_DESC) { + if (nrDCS_Frames == TWO_DCS) { + /* the last transfer shall generate an interrupt */ + buf->dma_desc[i].cfg |= DI_EN_X; /*0x00100000*/ + /* the last transfer sets the Stop Mode by disabling the LIST_MODE */ + buf->dma_desc[i].cfg &= ~DMAFLOW_LIST; /*0x00004000*/ + /* the very last element must be a list element that makes the dma point to the beginning */ + buf->dma_desc[i].next_desc_addr = buf->desc_dma_addr; + break; + } else { + /* As the item isn't the last one, remove the interrupt generation*/ + buf->dma_desc[i].cfg &= ~DI_EN_X; /*0x00100000*/ + /* Activate descriptor list mode if element isn't the last one */ + buf->dma_desc[i].cfg |= DMAFLOW_LIST; /*0x00004000*/ + /* Use the stored address of the 2nd descriptor for evaluating the next of the 2nd */ + buf->dma_desc[i].next_desc_addr = nextDescrDMAAddr + sizeof(*dma_desc); + } + } + /* The third element is never changed */ + /* The fourth element also isn't changed. The next_desc_addr of the very last descriptor of the last buffer + is set with the function buffer_prepare with the return of the buffer from application. + It doesn't have to be considered here. */ + #if DEBUG + //printk("#### DMA %d nachher %d: 0x%08lx buf->desc_dma_addr: 0x%08x start: %08x, next: %08x\n", nrDCS_Frames, i, buf->dma_desc[i].cfg, buf->desc_dma_addr, buf->dma_desc[i].start_addr, buf->dma_desc[i].next_desc_addr ); + #endif /*DEBUG*/ + } /*for*/ + #if DEBUG + //printk("#### DMA %d nach for %d: 0x%08lx buf->desc_dma_addr: 0x%08x start: %08x, next: %08x\n", nrDCS_Frames, i, buf->dma_desc[i].cfg, buf->desc_dma_addr, buf->dma_desc[i].start_addr, buf->dma_desc[i].next_desc_addr ); + #endif /*DEBUG*/ + } /*list for each*/ + #if DEBUG + //printk("#### DMA %d nachlisteach%d: 0x%08lx buf->desc_dma_addr: 0x%08x start: %08x, next: %08x\n", nrDCS_Frames, i, buf->dma_desc[i].cfg, buf->desc_dma_addr, buf->dma_desc[i].start_addr, buf->dma_desc[i].next_desc_addr ); + #endif /*DEBUG*/ + + return 0; + +} + /** * @brief Sets the variables necessary for configuration fo new picture format by application * @brief For changing the format by application, before epc660_s_parm, "epc660_s_fmt_vid_cap" has to be called @@ -1013,10 +1118,23 @@ static int epc660_s_parm (struct file *file, void *priv, break; case 253: + /* As raw_data is an u8 value, it is limited to 255. + All larger values have to be shrinked/resized. For binning_horizontal, the value is divided by 16 implicitly + (horizontal size 160/320 --> 10/20) in EPC660_Imager.cpp and is multiplied here to regain original value. */ + epc660_dev->fmt.width = strprm->parm.raw_data[1]*16; + epc660_dev->fmt.height = strprm->parm.raw_data[2]; + epc660_dev->dma_cfg_template.x_count = epc660_dev->fmt.width * (epc660_dev->fmt.height) / PIXEL_PER_CYCLE; ///< The DMA shall throw an interrupt when the whole channel picture is read into storage + #if DEBUG - printk("#### epc660_s_parm 253: width: %d hght: %d\n", epc660_dev->fmt.width, epc660_dev->fmt.height); + //printk("#### epc660_s_parm 253: raw_data[3]: %d\n", strprm->parm.raw_data[3] ); + //printk("#### epc660_s_parm 253: width: %d hght: %d\n", epc660_dev->fmt.width, epc660_dev->fmt.height); #endif /* DEBUG */ + /* Precondition: For re-arranging the descriptor elements and re-loading the DMA descriptor (set_dma_next_desc_addr), + the DMA has to be set to "Stop Mode" with the last transfer/in the last descriptor. + See function "buffer_init". */ + adapt_DMA_DescriptorElements (epc660_dev, strprm->parm.raw_data[3]); + buf = list_entry(epc660_dev->dma_queue.next, struct imager_buffer, list); spin_lock_irqsave(&epc660_dev->lock, flags); set_dma_next_desc_addr(epc660_dev->dma_channel, (void*)buf->desc_dma_addr); From e16a60edb89c5f8b9e4f55bc803bb650f86a2601 Mon Sep 17 00:00:00 2001 From: "Jan.Hannig" Date: Thu, 21 Oct 2021 12:13:25 +0200 Subject: [PATCH 10/11] [PDPHOEN-463/RDPHOEN-689] Set 1_DCS channels to "1" As the application configures the driver with 1, 2 or 4_DCS basically, the "channels" variables in epc660_formats are set accordingly. As "maxDcsImages" changed to "EPC660_MAX_DCS_IMAGES" in application, this is corrected in comment. --- drivers/media/platform/iris-gen6/epc660_capture_sc57x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c b/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c index dd2a17b3b939..649eeabb4c8e 100644 --- a/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c +++ b/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c @@ -60,7 +60,7 @@ #define COMPATIBLE_DT_NAME "iris,gen6-epc660" #define CAPTURE_DRV_NAME "epc660_capture" #define MIN_NUM_BUF 2 -#define MAX_DCS_IMAGES 4 ///< This value corresponds to "maxDcsImages" in EPC660_Sensor.h/EPC660_Imager.cpp +#define MAX_DCS_IMAGES 4 ///< This value corresponds to "EPC660_MAX_DCS_IMAGES" in EPC660_Sensor.h/EPC660_Imager.cpp /** * @brief PIXEL_PER_CYCLE: With a WORDSIZE of 256, the DMA transfers 256 Bit = 32 Byte per cycle. * @brief With a size of 16 Bit/Pixel = 2 Bytes/Pixel, the DMA transfers 32 Byte/Cycle * (1/2) Pixel/Byte = 16 Pixel/Cycle @@ -193,7 +193,7 @@ static const struct imager_format epc660_formats[] = { .mbus_code = MEDIA_BUS_FMT_Y12_1X12, .bpp = 16, .dlen = 12, // 12 bit samples are mapped to 16 bits - .channels = 4,// Set to maximum value to get the maximum buffer size during initialization + .channels = 1, .pixel_depth_bytes = 2, }, { From ef79f186870d1d94515ace4bbeb34243498bc720 Mon Sep 17 00:00:00 2001 From: "Jan.Hannig" Date: Thu, 21 Oct 2021 12:22:25 +0200 Subject: [PATCH 11/11] [PDPHOEN-463/RDPHOEN-689] Some formatting changes tabs --> spaces, empty lines; commented some #DEBUG printfs Added "break" in switch-case. --- .../platform/iris-gen6/epc660_capture_sc57x.c | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c b/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c index 649eeabb4c8e..195682819567 100644 --- a/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c +++ b/drivers/media/platform/iris-gen6/epc660_capture_sc57x.c @@ -432,7 +432,7 @@ static int epc660_buffer_prepare(struct vb2_buffer *vb) vb2_set_plane_payload(vb, 0, size); #if DEBUG - printk(KERN_INFO "#### epc660_buffer_prepare: size: %ld, fmtfield: %d\n", size, epc660_dev->fmt.field); + //printk(KERN_INFO "#### epc660_buffer_prepare: size: %ld, fmtfield: %d\n", size, epc660_dev->fmt.field); #endif /*DEBUG*/ vbuf->field = epc660_dev->fmt.field; @@ -457,9 +457,9 @@ static void epc660_buffer_queue(struct vb2_buffer *vb) // printk(KERN_INFO "#### epc660_buffer_queue\n"); #endif /*DEBUG*/ last_dma_desc_idx = epc660_dev->pixel_channels - 1; - buf->dma_desc[last_dma_desc_idx].next_desc_addr = buf->desc_dma_addr; + buf->dma_desc[last_dma_desc_idx].next_desc_addr = buf->desc_dma_addr; #if DEBUG - printk(KERN_INFO "#### epc660_buffer_queue: start_adresse: %x desc_dma_addr: %x\n", buf->dma_desc[0].start_addr , buf->desc_dma_addr); + //printk(KERN_INFO "#### epc660_buffer_queue: start_adresse: %x desc_dma_addr: %x\n", buf->dma_desc[0].start_addr , buf->desc_dma_addr); #endif /*DEBUG*/ spin_lock_irqsave(&epc660_dev->lock, flags); @@ -659,7 +659,6 @@ static irqreturn_t epc660_isr(int irq, void *dev_id) struct list_head* iterator; #if DEBUG -// printk("epc660_isr\n"); // printk(KERN_INFO "#### epc660_isr\n"); #endif /*DEBUG*/ @@ -670,11 +669,15 @@ static irqreturn_t epc660_isr(int irq, void *dev_id) disable_dma(epc660_dev->dma_channel); epc660_dev->ppi->ops->stop(epc660_dev->ppi); + #if DEBUG + //printk("#### isr dmacfg %lx\n", get_dma_config(epc660_dev->dma_channel)); + //printk("## isr ## dmaStatus: 0x%08x\n", dmaStatus); + #endif /*DEBUG*/ if (dmaStatus & DMA_DONE) { // if there are at least two buffers in the queue we can deque one if (&epc660_dev->dma_queue == epc660_dev->dma_queue.next->next) { #if DEBUG -// printk("buffer underrun in epc660 capture\n"); + printk("buffer underrun in epc660 capture\n"); // epc660_stop_transfering(epc660_dev); #endif /*DEBUG*/ } else { @@ -689,7 +692,9 @@ static irqreturn_t epc660_isr(int irq, void *dev_id) break; } } + #if DEBUG // printk("lastDmaDescriptor: 0x%08x\n", lastDmaDescriptor); + #endif /* DEBUG */ if (0 == completedCnt) { #if DEBUG printk("cannot find any completed buffers!\n"); @@ -699,7 +704,7 @@ static irqreturn_t epc660_isr(int irq, void *dev_id) struct imager_buffer* buf; struct vb2_buffer *vb; #if DEBUG -// printk("found %d completed buffers\n", completedCnt); + //printk("found %d completed buffers\n", completedCnt); #endif /*DEBUG*/ while (completedCnt--) { if (&epc660_dev->dma_queue == epc660_dev->dma_queue.next->next) { @@ -756,8 +761,8 @@ static int epc660_set_DMA_registers (struct epc660_device *epc660_dev) /* After using the template, reset it to original state */ epc660_dev->dma_cfg_template.cfg = epc660_dev->dma_cfg_template.cfg | DMAEN; #if DEBUG - printk("#### epc660_set_DMA_registers\n"); - printDMAState(epc660_dev); + //printk("#### epc660_set_DMA_registers\n"); + //printDMAState(epc660_dev); //printk("#### epc660_set_DMA_registers: dmaStatus: 0x%08lx\n", get_dma_curr_irqstat(epc660_dev->dma_channel)); #endif /*DEBUG*/ return 0; @@ -985,7 +990,7 @@ static int epc660_s_fmt_vid_cap(struct file *file, void *priv, epc660_dev->pixel_channels = epc660_fmt->channels; epc660_dev->pixel_depth_bytes = epc660_fmt->pixel_depth_bytes; - memset(&epc660_dev->dma_cfg_template, 0, sizeof(epc660_dev->dma_cfg_template)); + memset(&epc660_dev->dma_cfg_template, 0, sizeof(epc660_dev->dma_cfg_template)); /* The following config bits configure the DMA with the reg value 0x01024527 As DMA2D is not set, the DMA mode is 1D automatically.*/ epc660_dev->dma_cfg_template.cfg = RESTART | ///< DMA Buffer Clear SYNC <0x00000004> @@ -997,7 +1002,7 @@ static int epc660_s_fmt_vid_cap(struct file *file, void *priv, DMAFLOW_LIST | ///< Descriptor List Mode <0x00004000> DMAEN; ///< DMA Channel Enable <0x00000001> - epc660_dev->dma_cfg_template.x_count = epc660_dev->fmt.width * (epc660_dev->fmt.height) / PIXEL_PER_CYCLE; + epc660_dev->dma_cfg_template.x_count = epc660_dev->fmt.width * (epc660_dev->fmt.height) / PIXEL_PER_CYCLE; ///< The DMA shall throw an interrupt when the whole channel picture is read into storage epc660_dev->dma_cfg_template.x_modify = epc660_dev->pixel_depth_bytes * PIXEL_PER_CYCLE;// After 32 Bytes = 256 Bit WORDSIZE #if DEBUG @@ -1146,16 +1151,15 @@ static int epc660_s_parm (struct file *file, void *priv, /* enable ppi */ epc660_dev->ppi->ops->start(epc660_dev->ppi); spin_unlock_irqrestore(&epc660_dev->lock, flags); - break; case 210: - #if DEBUG //printDMAState(epc660_dev); printk("\n#### epc660_s_parm: DMA strt addr: %lx\n", get_dma_start_addr(epc660_dev->dma_channel)); //printk("#### epc660_s_parm: dma cfg %lx, dmaStatus: 0x%08x curr_x_count_1: %ld curr_x_count_2: %ld \n", get_dma_config(epc660_dev->dma_channel), dmaStatus_s_parm, curr_x_count_1, curr_x_count_2 ); #endif /*DEBUG*/ + break; default: break;