diff options
24 files changed, 0 insertions, 14028 deletions
diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig index 45075f977f1b..642adc4c24d2 100644 --- a/drivers/staging/media/Kconfig +++ b/drivers/staging/media/Kconfig @@ -22,8 +22,6 @@ if STAGING_MEDIA && MEDIA_SUPPORT # Please keep them in alphabetic order source "drivers/staging/media/allegro-dvt/Kconfig" -source "drivers/staging/media/davinci_vpfe/Kconfig" - source "drivers/staging/media/hantro/Kconfig" source "drivers/staging/media/imx/Kconfig" diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile index c19cfed0b059..2f1711a8aeed 100644 --- a/drivers/staging/media/Makefile +++ b/drivers/staging/media/Makefile @@ -1,7 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_VIDEO_ALLEGRO_DVT) += allegro-dvt/ obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx/ -obj-$(CONFIG_VIDEO_DM365_VPFE) += davinci_vpfe/ obj-$(CONFIG_VIDEO_MESON_VDEC) += meson/vdec/ obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/ obj-$(CONFIG_VIDEO_SUNXI) += sunxi/ diff --git a/drivers/staging/media/davinci_vpfe/Kconfig b/drivers/staging/media/davinci_vpfe/Kconfig deleted file mode 100644 index 94bf6746c03f..000000000000 --- a/drivers/staging/media/davinci_vpfe/Kconfig +++ /dev/null @@ -1,13 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -config VIDEO_DM365_VPFE - tristate "DM365 VPFE Media Controller Capture Driver" - depends on VIDEO_V4L2 - depends on (ARCH_DAVINCI_DM365 && !VIDEO_DM365_ISIF) || (COMPILE_TEST && !ARCH_OMAP1) - depends on VIDEO_V4L2_SUBDEV_API - depends on VIDEO_DAVINCI_VPBE_DISPLAY - select VIDEOBUF2_DMA_CONTIG - help - Support for DM365 VPFE based Media Controller Capture driver. - - To compile this driver as a module, choose M here: the - module will be called vpfe-mc-capture. diff --git a/drivers/staging/media/davinci_vpfe/Makefile b/drivers/staging/media/davinci_vpfe/Makefile deleted file mode 100644 index 0ae8c5014f74..000000000000 --- a/drivers/staging/media/davinci_vpfe/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_VIDEO_DM365_VPFE) += davinci-vfpe.o - -davinci-vfpe-objs := \ - dm365_isif.o dm365_ipipe_hw.o dm365_ipipe.o \ - dm365_resizer.o dm365_ipipeif.o vpfe_mc_capture.o vpfe_video.o - -# Allow building it with COMPILE_TEST on other archs -ifndef CONFIG_ARCH_DAVINCI -ccflags-y += -I $(srctree)/arch/arm/mach-davinci/include/ -endif diff --git a/drivers/staging/media/davinci_vpfe/TODO b/drivers/staging/media/davinci_vpfe/TODO deleted file mode 100644 index cc8bd9306f2a..000000000000 --- a/drivers/staging/media/davinci_vpfe/TODO +++ /dev/null @@ -1,38 +0,0 @@ -TODO (general): -================================== - -- User space interface refinement - - Controls should be used when possible rather than private ioctl - - No enums should be used - - Use of MC and V4L2 subdev APIs when applicable - - Single interface header might suffice - - Current interface forces to configure everything at once -- Get rid of the dm365_ipipe_hw.[ch] layer -- Active external sub-devices defined by link configuration; no strcmp - needed -- More generic platform data (i2c adapters) -- The driver should have no knowledge of possible external subdevs; see - struct vpfe_subdev_id -- Some of the hardware control should be refactorede -- Check proper serialisation (through mutexes and spinlocks) -- Names that are visible in kernel global namespace should have a common - prefix (or a few) -- While replacing the older driver in media folder, provide a compatibility - layer and compatibility tests that warrants (using the libv4l's LD_PRELOAD - approach) there is no regression for the users using the older driver. -- make it independent of arch-specific APIs (mach/mux.h). - -Building of uImage and Applications: -================================== - -As of now since the interface will undergo few changes all the include -files are present in staging itself, to build for dm365 follow below steps, - -- copy vpfe.h from drivers/staging/media/davinci_vpfe/ to - include/media/davinci/ folder for building the uImage. -- copy davinci_vpfe_user.h from drivers/staging/media/davinci_vpfe/ to - include/uapi/linux/davinci_vpfe.h, and add a entry in Kbuild (required - for building application). -- copy dm365_ipipeif_user.h from drivers/staging/media/davinci_vpfe/ to - include/uapi/linux/dm365_ipipeif.h and a entry in Kbuild (required - for building application). diff --git a/drivers/staging/media/davinci_vpfe/davinci-vpfe-mc.txt b/drivers/staging/media/davinci_vpfe/davinci-vpfe-mc.txt deleted file mode 100644 index a1e91778aa9b..000000000000 --- a/drivers/staging/media/davinci_vpfe/davinci-vpfe-mc.txt +++ /dev/null @@ -1,154 +0,0 @@ -Davinci Video processing Front End (VPFE) driver - -Copyright (C) 2012 Texas Instruments Inc - -Contacts: Manjunath Hadli <manjunath.hadli@ti.com> - Prabhakar Lad <prabhakar.lad@ti.com> - - -Introduction -============ - -This file documents the Texas Instruments Davinci Video processing Front End -(VPFE) driver located under drivers/media/platform/davinci. The original driver -exists for Davinci VPFE, which is now being changed to Media Controller -Framework. - -Currently the driver has been successfully used on the following -version of Davinci: - - DM365/DM368 - -The driver implements V4L2, Media controller and v4l2_subdev interfaces. Sensor, -lens and flash drivers using the v4l2_subdev interface in the kernel are -supported. - - -Split to subdevs -================ - -The Davinci VPFE is split into V4L2 subdevs, each of the blocks inside the VPFE -having one subdev to represent it. Each of the subdevs provide a V4L2 subdev -interface to userspace. - - DAVINCI ISIF - DAVINCI IPIPEIF - DAVINCI IPIPE - DAVINCI CROP RESIZER - DAVINCI RESIZER A - DAVINCI RESIZER B - -Each possible link in the VPFE is modelled by a link in the Media controller -interface. For an example program see [1]. - - -ISIF, IPIPE, and RESIZER block IOCTLs -====================================== - -The Davinci Video processing Front End (VPFE) driver supports standard V4L2 -IOCTLs and controls where possible and practical. Much of the functions provided -by the VPFE, however, does not fall under the standard IOCTL's. - -In general, there is a private ioctl for configuring each of the blocks -containing hardware-dependent functions. - -The following private IOCTLs are supported: - - VIDIOC_VPFE_ISIF_[S/G]_RAW_PARAMS - VIDIOC_VPFE_IPIPE_[S/G]_CONFIG - VIDIOC_VPFE_RSZ_[S/G]_CONFIG - -The parameter structures used by these ioctl's are described in -include/uapi/linux/davinci_vpfe.h. - -The VIDIOC_VPFE_ISIF_S_RAW_PARAMS, VIDIOC_VPFE_IPIPE_S_CONFIG and -VIDIOC_VPFE_RSZ_S_CONFIG are used to configure, enable and disable functions in -the isif, ipipe and resizer blocks respectively. These IOCTL's control several -functions in the blocks they control. VIDIOC_VPFE_ISIF_S_RAW_PARAMS IOCTL -accepts a pointer to struct vpfe_isif_raw_config as its argument. Similarly -VIDIOC_VPFE_IPIPE_S_CONFIG accepts a pointer to struct vpfe_ipipe_config. And -VIDIOC_VPFE_RSZ_S_CONFIG accepts a pointer to struct vpfe_rsz_config as its -argument. Similarly VIDIOC_VPFE_ISIF_G_RAW_PARAMS, VIDIOC_VPFE_IPIPE_G_CONFIG -and VIDIOC_VPFE_RSZ_G_CONFIG are used to get the current configuration set in -the isif, ipipe and resizer blocks respectively. - -The detailed functions of the VPFE itself related to a given VPFE block is -described in the Technical Reference Manuals (TRMs) --- see the end of the -document for those. - - -IPIPEIF block IOCTLs -====================================== - -The following private IOCTLs are supported: - - VIDIOC_VPFE_IPIPEIF_[S/G]_CONFIG - -The parameter structures used by these ioctl's are described in -include/uapi/linux/dm365_ipipeif.h - -The VIDIOC_VPFE_IPIPEIF_S_CONFIG is used to configure the ipipeif -hardware block. The VIDIOC_VPFE_IPIPEIF_S_CONFIG and -VIDIOC_VPFE_IPIPEIF_G_CONFIG accepts a pointer to struct ipipeif_params -as its argument. - - -VPFE Operating Modes -========================================== - -a: Continuous Modes ------------------------- - -1: tvp514x/tvp7002/mt9p031---> DAVINCI ISIF---> SDRAM - -2: tvp514x/tvp7002/mt9p031---> DAVINCI ISIF---> DAVINCI IPIPEIF--->| - | - <--------------------<----------------<---------------------<---| - | - V - DAVINCI CROP RESIZER--->DAVINCI RESIZER [A/B]---> SDRAM - -3: tvp514x/tvp7002/mt9p031---> DAVINCI ISIF---> DAVINCI IPIPEIF--->| - | - <--------------------<----------------<---------------------<---| - | - V - DAVINCI IPIPE---> DAVINCI CROP RESIZER--->DAVINCI RESIZER [A/B]---> SDRAM - -a: Single Shot Modes ------------------------- - -1: SDRAM---> DAVINCI IPIPEIF---> DAVINCI IPIPE---> DAVINCI CROP RESIZER--->| - | - <----------------<----------------<------------------<---------------<--| - | - V -DAVINCI RESIZER [A/B]---> SDRAM - -2: SDRAM---> DAVINCI IPIPEIF---> DAVINCI CROP RESIZER--->| - | - <----------------<----------------<---------------<---| - | - V -DAVINCI RESIZER [A/B]---> SDRAM - - -Technical reference manuals (TRMs) and other documentation -========================================================== - -Davinci DM365 TRM: -<URL:http://www.ti.com/lit/ds/sprs457e/sprs457e.pdf> -Referenced MARCH 2009-REVISED JUNE 2011 - -Davinci DM368 TRM: -<URL:http://www.ti.com/lit/ds/sprs668c/sprs668c.pdf> -Referenced APRIL 2010-REVISED JUNE 2011 - -Davinci Video Processing Front End (VPFE) DM36x -<URL:http://www.ti.com/lit/ug/sprufg8c/sprufg8c.pdf> - - -References -========== - -[1] http://git.ideasonboard.org/?p=media-ctl.git;a=summary diff --git a/drivers/staging/media/davinci_vpfe/davinci_vpfe_user.h b/drivers/staging/media/davinci_vpfe/davinci_vpfe_user.h deleted file mode 100644 index 8d772029c91d..000000000000 --- a/drivers/staging/media/davinci_vpfe/davinci_vpfe_user.h +++ /dev/null @@ -1,1287 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) 2012 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Contributors: - * Manjunath Hadli <manjunath.hadli@ti.com> - * Prabhakar Lad <prabhakar.lad@ti.com> - */ - -#ifndef _DAVINCI_VPFE_USER_H -#define _DAVINCI_VPFE_USER_H - -#include <linux/types.h> -#include <linux/videodev2.h> - -/* - * Private IOCTL - * - * VIDIOC_VPFE_ISIF_S_RAW_PARAMS: Set raw params in isif - * VIDIOC_VPFE_ISIF_G_RAW_PARAMS: Get raw params from isif - * VIDIOC_VPFE_PRV_S_CONFIG: Set ipipe engine configuration - * VIDIOC_VPFE_PRV_G_CONFIG: Get ipipe engine configuration - * VIDIOC_VPFE_RSZ_S_CONFIG: Set resizer engine configuration - * VIDIOC_VPFE_RSZ_G_CONFIG: Get resizer engine configuration - */ - -#define VIDIOC_VPFE_ISIF_S_RAW_PARAMS \ - _IOW('V', BASE_VIDIOC_PRIVATE + 1, struct vpfe_isif_raw_config) -#define VIDIOC_VPFE_ISIF_G_RAW_PARAMS \ - _IOR('V', BASE_VIDIOC_PRIVATE + 2, struct vpfe_isif_raw_config) -#define VIDIOC_VPFE_IPIPE_S_CONFIG \ - _IOWR('P', BASE_VIDIOC_PRIVATE + 3, struct vpfe_ipipe_config) -#define VIDIOC_VPFE_IPIPE_G_CONFIG \ - _IOWR('P', BASE_VIDIOC_PRIVATE + 4, struct vpfe_ipipe_config) -#define VIDIOC_VPFE_RSZ_S_CONFIG \ - _IOWR('R', BASE_VIDIOC_PRIVATE + 5, struct vpfe_rsz_config) -#define VIDIOC_VPFE_RSZ_G_CONFIG \ - _IOWR('R', BASE_VIDIOC_PRIVATE + 6, struct vpfe_rsz_config) - -/* - * Private Control's for ISIF - */ -#define VPFE_ISIF_CID_CRGAIN (V4L2_CID_USER_BASE | 0xa001) -#define VPFE_ISIF_CID_CGRGAIN (V4L2_CID_USER_BASE | 0xa002) -#define VPFE_ISIF_CID_CGBGAIN (V4L2_CID_USER_BASE | 0xa003) -#define VPFE_ISIF_CID_CBGAIN (V4L2_CID_USER_BASE | 0xa004) -#define VPFE_ISIF_CID_GAIN_OFFSET (V4L2_CID_USER_BASE | 0xa005) - -/* - * Private Control's for ISIF and IPIPEIF - */ -#define VPFE_CID_DPCM_PREDICTOR (V4L2_CID_USER_BASE | 0xa006) - -/************************************************************************ - * Vertical Defect Correction parameters - ***********************************************************************/ - -/** - * vertical defect correction methods - */ -enum vpfe_isif_vdfc_corr_mode { - /* Defect level subtraction. Just fed through if saturating */ - VPFE_ISIF_VDFC_NORMAL, - /** - * Defect level subtraction. Horizontal interpolation ((i-2)+(i+2))/2 - * if data saturating - */ - VPFE_ISIF_VDFC_HORZ_INTERPOL_IF_SAT, - /* Horizontal interpolation (((i-2)+(i+2))/2) */ - VPFE_ISIF_VDFC_HORZ_INTERPOL -}; - -/** - * Max Size of the Vertical Defect Correction table - */ -#define VPFE_ISIF_VDFC_TABLE_SIZE 8 - -/** - * Values used for shifting up the vdfc defect level - */ -enum vpfe_isif_vdfc_shift { - /* No Shift */ - VPFE_ISIF_VDFC_NO_SHIFT, - /* Shift by 1 bit */ - VPFE_ISIF_VDFC_SHIFT_1, - /* Shift by 2 bit */ - VPFE_ISIF_VDFC_SHIFT_2, - /* Shift by 3 bit */ - VPFE_ISIF_VDFC_SHIFT_3, - /* Shift by 4 bit */ - VPFE_ISIF_VDFC_SHIFT_4 -}; - -/** - * Defect Correction (DFC) table entry - */ -struct vpfe_isif_vdfc_entry { - /* vertical position of defect */ - unsigned short pos_vert; - /* horizontal position of defect */ - unsigned short pos_horz; - /** - * Defect level of Vertical line defect position. This is subtracted - * from the data at the defect position - */ - unsigned char level_at_pos; - /** - * Defect level of the pixels upper than the vertical line defect. - * This is subtracted from the data - */ - unsigned char level_up_pixels; - /** - * Defect level of the pixels lower than the vertical line defect. - * This is subtracted from the data - */ - unsigned char level_low_pixels; -}; - -/** - * Structure for Defect Correction (DFC) parameter - */ -struct vpfe_isif_dfc { - /* enable vertical defect correction */ - unsigned char en; - /* Correction methods */ - enum vpfe_isif_vdfc_corr_mode corr_mode; - /** - * 0 - whole line corrected, 1 - not - * pixels upper than the defect - */ - unsigned char corr_whole_line; - /** - * defect level shift value. level_at_pos, level_upper_pos, - * and level_lower_pos can be shifted up by this value - */ - enum vpfe_isif_vdfc_shift def_level_shift; - /* defect saturation level */ - unsigned short def_sat_level; - /* number of vertical defects. Max is VPFE_ISIF_VDFC_TABLE_SIZE */ - short num_vdefects; - /* VDFC table ptr */ - struct vpfe_isif_vdfc_entry table[VPFE_ISIF_VDFC_TABLE_SIZE]; -}; - -/************************************************************************ - * Digital/Black clamp or DC Subtract parameters - ************************************************************************/ -/** - * Horizontal Black Clamp modes - */ -enum vpfe_isif_horz_bc_mode { - /** - * Horizontal clamp disabled. Only vertical clamp - * value is subtracted - */ - VPFE_ISIF_HORZ_BC_DISABLE, - /** - * Horizontal clamp value is calculated and subtracted - * from image data along with vertical clamp value - */ - VPFE_ISIF_HORZ_BC_CLAMP_CALC_ENABLED, - /** - * Horizontal clamp value calculated from previous image - * is subtracted from image data along with vertical clamp - * value. How the horizontal clamp value for the first image - * is calculated in this case ??? - */ - VPFE_ISIF_HORZ_BC_CLAMP_NOT_UPDATED -}; - -/** - * Base window selection for Horizontal Black Clamp calculations - */ -enum vpfe_isif_horz_bc_base_win_sel { - /* Select Most left window for bc calculation */ - VPFE_ISIF_SEL_MOST_LEFT_WIN, - - /* Select Most right window for bc calculation */ - VPFE_ISIF_SEL_MOST_RIGHT_WIN, -}; - -/* Size of window in horizontal direction for horizontal bc */ -enum vpfe_isif_horz_bc_sz_h { - VPFE_ISIF_HORZ_BC_SZ_H_2PIXELS, - VPFE_ISIF_HORZ_BC_SZ_H_4PIXELS, - VPFE_ISIF_HORZ_BC_SZ_H_8PIXELS, - VPFE_ISIF_HORZ_BC_SZ_H_16PIXELS -}; - -/* Size of window in vertcal direction for vertical bc */ -enum vpfe_isif_horz_bc_sz_v { - VPFE_ISIF_HORZ_BC_SZ_H_32PIXELS, - VPFE_ISIF_HORZ_BC_SZ_H_64PIXELS, - VPFE_ISIF_HORZ_BC_SZ_H_128PIXELS, - VPFE_ISIF_HORZ_BC_SZ_H_256PIXELS -}; - -/** - * Structure for Horizontal Black Clamp config params - */ -struct vpfe_isif_horz_bclamp { - /* horizontal clamp mode */ - enum vpfe_isif_horz_bc_mode mode; - /** - * pixel value limit enable. - * 0 - limit disabled - * 1 - pixel value limited to 1023 - */ - unsigned char clamp_pix_limit; - /** - * Select most left or right window for clamp val - * calculation - */ - enum vpfe_isif_horz_bc_base_win_sel base_win_sel_calc; - /* Window count per color for calculation. range 1-32 */ - unsigned char win_count_calc; - /* Window start position - horizontal for calculation. 0 - 8191 */ - unsigned short win_start_h_calc; - /* Window start position - vertical for calculation 0 - 8191 */ - unsigned short win_start_v_calc; - /* Width of the sample window in pixels for calculation */ - enum vpfe_isif_horz_bc_sz_h win_h_sz_calc; - /* Height of the sample window in pixels for calculation */ - enum vpfe_isif_horz_bc_sz_v win_v_sz_calc; -}; - -/** - * Black Clamp vertical reset values - */ -enum vpfe_isif_vert_bc_reset_val_sel { - /* Reset value used is the clamp value calculated */ - VPFE_ISIF_VERT_BC_USE_HORZ_CLAMP_VAL, - /* Reset value used is reset_clamp_val configured */ - VPFE_ISIF_VERT_BC_USE_CONFIG_CLAMP_VAL, - /* No update, previous image value is used */ - VPFE_ISIF_VERT_BC_NO_UPDATE -}; - -enum vpfe_isif_vert_bc_sz_h { - VPFE_ISIF_VERT_BC_SZ_H_2PIXELS, - VPFE_ISIF_VERT_BC_SZ_H_4PIXELS, - VPFE_ISIF_VERT_BC_SZ_H_8PIXELS, - VPFE_ISIF_VERT_BC_SZ_H_16PIXELS, - VPFE_ISIF_VERT_BC_SZ_H_32PIXELS, - VPFE_ISIF_VERT_BC_SZ_H_64PIXELS -}; - -/** - * Structure for Vertical Black Clamp configuration params - */ -struct vpfe_isif_vert_bclamp { - /* Reset value selection for vertical clamp calculation */ - enum vpfe_isif_vert_bc_reset_val_sel reset_val_sel; - /* U12 value if reset_sel = ISIF_BC_VERT_USE_CONFIG_CLAMP_VAL */ - unsigned short reset_clamp_val; - /** - * U8Q8. Line average coefficient used in vertical clamp - * calculation - */ - unsigned char line_ave_coef; - /* Width in pixels of the optical black region used for calculation. */ - enum vpfe_isif_vert_bc_sz_h ob_h_sz_calc; - /* Height of the optical black region for calculation */ - unsigned short ob_v_sz_calc; - /* Optical black region start position - horizontal. 0 - 8191 */ - unsigned short ob_start_h; - /* Optical black region start position - vertical 0 - 8191 */ - unsigned short ob_start_v; -}; - -/** - * Structure for Black Clamp configuration params - */ -struct vpfe_isif_black_clamp { - /** - * this offset value is added irrespective of the clamp - * enable status. S13 - */ - unsigned short dc_offset; - /** - * Enable black/digital clamp value to be subtracted - * from the image data - */ - unsigned char en; - /** - * black clamp mode. same/separate clamp for 4 colors - * 0 - disable - same clamp value for all colors - * 1 - clamp value calculated separately for all colors - */ - unsigned char bc_mode_color; - /* Vertical start position for bc subtraction */ - unsigned short vert_start_sub; - /* Black clamp for horizontal direction */ - struct vpfe_isif_horz_bclamp horz; - /* Black clamp for vertical direction */ - struct vpfe_isif_vert_bclamp vert; -}; - -/************************************************************************* - ** Color Space Conversion (CSC) - *************************************************************************/ -/** - * Number of Coefficient values used for CSC - */ -#define VPFE_ISIF_CSC_NUM_COEFF 16 - -struct float_8_bit { - /* 8 bit integer part */ - __u8 integer; - /* 8 bit decimal part */ - __u8 decimal; -}; - -struct float_16_bit { - /* 16 bit integer part */ - __u16 integer; - /* 16 bit decimal part */ - __u16 decimal; -}; - -/************************************************************************* - ** Color Space Conversion parameters - *************************************************************************/ -/** - * Structure used for CSC config params - */ -struct vpfe_isif_color_space_conv { - /* Enable color space conversion */ - unsigned char en; - /** - * csc coefficient table. S8Q5, M00 at index 0, M01 at index 1, and - * so forth - */ - struct float_8_bit coeff[VPFE_ISIF_CSC_NUM_COEFF]; -}; - -enum vpfe_isif_datasft { - /* No Shift */ - VPFE_ISIF_NO_SHIFT, - /* 1 bit Shift */ - VPFE_ISIF_1BIT_SHIFT, - /* 2 bit Shift */ - VPFE_ISIF_2BIT_SHIFT, - /* 3 bit Shift */ - VPFE_ISIF_3BIT_SHIFT, - /* 4 bit Shift */ - VPFE_ISIF_4BIT_SHIFT, - /* 5 bit Shift */ - VPFE_ISIF_5BIT_SHIFT, - /* 6 bit Shift */ - VPFE_ISIF_6BIT_SHIFT -}; - -#define VPFE_ISIF_LINEAR_TAB_SIZE 192 -/************************************************************************* - ** Linearization parameters - *************************************************************************/ -/** - * Structure for Sensor data linearization - */ -struct vpfe_isif_linearize { - /* Enable or Disable linearization of data */ - unsigned char en; - /* Shift value applied */ - enum vpfe_isif_datasft corr_shft; - /* scale factor applied U11Q10 */ - struct float_16_bit scale_fact; - /* Size of the linear table */ - unsigned short table[VPFE_ISIF_LINEAR_TAB_SIZE]; -}; - -/************************************************************************* - ** ISIF Raw configuration parameters - *************************************************************************/ -enum vpfe_isif_fmt_mode { - VPFE_ISIF_SPLIT, - VPFE_ISIF_COMBINE -}; - -enum vpfe_isif_lnum { - VPFE_ISIF_1LINE, - VPFE_ISIF_2LINES, - VPFE_ISIF_3LINES, - VPFE_ISIF_4LINES -}; - -enum vpfe_isif_line { - VPFE_ISIF_1STLINE, - VPFE_ISIF_2NDLINE, - VPFE_ISIF_3RDLINE, - VPFE_ISIF_4THLINE -}; - -struct vpfe_isif_fmtplen { - /** - * number of program entries for SET0, range 1 - 16 - * when fmtmode is ISIF_SPLIT, 1 - 8 when fmtmode is - * ISIF_COMBINE - */ - unsigned short plen0; - /** - * number of program entries for SET1, range 1 - 16 - * when fmtmode is ISIF_SPLIT, 1 - 8 when fmtmode is - * ISIF_COMBINE - */ - unsigned short plen1; - /** - * number of program entries for SET2, range 1 - 16 - * when fmtmode is ISIF_SPLIT, 1 - 8 when fmtmode is - * ISIF_COMBINE - */ - unsigned short plen2; - /** - * number of program entries for SET3, range 1 - 16 - * when fmtmode is ISIF_SPLIT, 1 - 8 when fmtmode is - * ISIF_COMBINE - */ - unsigned short plen3; -}; - -struct vpfe_isif_fmt_cfg { - /* Split or combine or line alternate */ - enum vpfe_isif_fmt_mode fmtmode; - /* enable or disable line alternating mode */ - unsigned char ln_alter_en; - /* Split/combine line number */ - enum vpfe_isif_lnum lnum; - /* Address increment Range 1 - 16 */ - unsigned int addrinc; -}; - -struct vpfe_isif_fmt_addr_ptr { - /* Initial address */ - unsigned int init_addr; - /* output line number */ - enum vpfe_isif_line out_line; -}; - -struct vpfe_isif_fmtpgm_ap { - /* program address pointer */ - unsigned char pgm_aptr; - /* program address increment or decrement */ - unsigned char pgmupdt; -}; - -struct vpfe_isif_data_formatter { - /* Enable/Disable data formatter */ - unsigned char en; - /* data formatter configuration */ - struct vpfe_isif_fmt_cfg cfg; - /* Formatter program entries length */ - struct vpfe_isif_fmtplen plen; - /* first pixel in a line fed to formatter */ - unsigned short fmtrlen; - /* HD interval for output line. Only valid when split line */ - unsigned short fmthcnt; - /* formatter address pointers */ - struct vpfe_isif_fmt_addr_ptr fmtaddr_ptr[16]; - /* program enable/disable */ - unsigned char pgm_en[32]; - /* program address pointers */ - struct vpfe_isif_fmtpgm_ap fmtpgm_ap[32]; -}; - -struct vpfe_isif_df_csc { - /* Color Space Conversion configuration, 0 - csc, 1 - df */ - unsigned int df_or_csc; - /* csc configuration valid if df_or_csc is 0 */ - struct vpfe_isif_color_space_conv csc; - /* data formatter configuration valid if df_or_csc is 1 */ - struct vpfe_isif_data_formatter df; - /* start pixel in a line at the input */ - unsigned int start_pix; - /* number of pixels in input line */ - unsigned int num_pixels; - /* start line at the input */ - unsigned int start_line; - /* number of lines at the input */ - unsigned int num_lines; -}; - -struct vpfe_isif_gain_offsets_adj { - /* Enable or Disable Gain adjustment for SDRAM data */ - unsigned char gain_sdram_en; - /* Enable or Disable Gain adjustment for IPIPE data */ - unsigned char gain_ipipe_en; - /* Enable or Disable Gain adjustment for H3A data */ - unsigned char gain_h3a_en; - /* Enable or Disable Gain adjustment for SDRAM data */ - unsigned char offset_sdram_en; - /* Enable or Disable Gain adjustment for IPIPE data */ - unsigned char offset_ipipe_en; - /* Enable or Disable Gain adjustment for H3A data */ - unsigned char offset_h3a_en; -}; - -struct vpfe_isif_cul { - /* Horizontal Cull pattern for odd lines */ - unsigned char hcpat_odd; - /* Horizontal Cull pattern for even lines */ - unsigned char hcpat_even; - /* Vertical Cull pattern */ - unsigned char vcpat; - /* Enable or disable lpf. Apply when cull is enabled */ - unsigned char en_lpf; -}; - -/* all the stuff in this struct will be provided by userland */ -struct vpfe_isif_raw_config { - /* Linearization parameters for image sensor data input */ - struct vpfe_isif_linearize linearize; - /* Data formatter or CSC */ - struct vpfe_isif_df_csc df_csc; - /* Defect Pixel Correction (DFC) confguration */ - struct vpfe_isif_dfc dfc; - /* Black/Digital Clamp configuration */ - struct vpfe_isif_black_clamp bclamp; - /* Gain, offset adjustments */ - struct vpfe_isif_gain_offsets_adj gain_offset; - /* Culling */ - struct vpfe_isif_cul culling; - /* horizontal offset for Gain/LSC/DFC */ - unsigned short horz_offset; - /* vertical offset for Gain/LSC/DFC */ - unsigned short vert_offset; -}; - -/********************************************************************** - * IPIPE API Structures - **********************************************************************/ - -/* IPIPE module configurations */ - -/* IPIPE input configuration */ -#define VPFE_IPIPE_INPUT_CONFIG BIT(0) -/* LUT based Defect Pixel Correction */ -#define VPFE_IPIPE_LUTDPC BIT(1) -/* On the fly (OTF) Defect Pixel Correction */ -#define VPFE_IPIPE_OTFDPC BIT(2) -/* Noise Filter - 1 */ -#define VPFE_IPIPE_NF1 BIT(3) -/* Noise Filter - 2 */ -#define VPFE_IPIPE_NF2 BIT(4) -/* White Balance. Also a control ID */ -#define VPFE_IPIPE_WB BIT(5) -/* 1st RGB to RBG Blend module */ -#define VPFE_IPIPE_RGB2RGB_1 BIT(6) -/* 2nd RGB to RBG Blend module */ -#define VPFE_IPIPE_RGB2RGB_2 BIT(7) -/* Gamma Correction */ -#define VPFE_IPIPE_GAMMA BIT(8) -/* 3D LUT color conversion */ -#define VPFE_IPIPE_3D_LUT BIT(9) -/* RGB to YCbCr module */ -#define VPFE_IPIPE_RGB2YUV BIT(10) -/* YUV 422 conversion module */ -#define VPFE_IPIPE_YUV422_CONV BIT(11) -/* Edge Enhancement */ -#define VPFE_IPIPE_YEE BIT(12) -/* Green Imbalance Correction */ -#define VPFE_IPIPE_GIC BIT(13) -/* CFA Interpolation */ -#define VPFE_IPIPE_CFA BIT(14) -/* Chroma Artifact Reduction */ -#define VPFE_IPIPE_CAR BIT(15) -/* Chroma Gain Suppression */ -#define VPFE_IPIPE_CGS BIT(16) -/* Global brightness and contrast control */ -#define VPFE_IPIPE_GBCE BIT(17) - -#define VPFE_IPIPE_MAX_MODULES 18 - -struct ipipe_float_u16 { - unsigned short integer; - unsigned short decimal; -}; - -struct ipipe_float_s16 { - short integer; - unsigned short decimal; -}; - -struct ipipe_float_u8 { - unsigned char integer; - unsigned char decimal; -}; - -/* Copy method selection for vertical correction - * Used when ipipe_dfc_corr_meth is IPIPE_DPC_CTORB_AFTER_HINT - */ -enum vpfe_ipipe_dpc_corr_meth { - /* replace by black or white dot specified by repl_white */ - VPFE_IPIPE_DPC_REPL_BY_DOT = 0, - /* Copy from left */ - VPFE_IPIPE_DPC_CL = 1, - /* Copy from right */ - VPFE_IPIPE_DPC_CR = 2, - /* Horizontal interpolation */ - VPFE_IPIPE_DPC_H_INTP = 3, - /* Vertical interpolation */ - VPFE_IPIPE_DPC_V_INTP = 4, - /* Copy from top */ - VPFE_IPIPE_DPC_CT = 5, - /* Copy from bottom */ - VPFE_IPIPE_DPC_CB = 6, - /* 2D interpolation */ - VPFE_IPIPE_DPC_2D_INTP = 7, -}; - -struct vpfe_ipipe_lutdpc_entry { - /* Horizontal position */ - unsigned short horz_pos; - /* vertical position */ - unsigned short vert_pos; - enum vpfe_ipipe_dpc_corr_meth method; -}; - -#define VPFE_IPIPE_MAX_SIZE_DPC 256 - -/* Structure for configuring DPC module */ -struct vpfe_ipipe_lutdpc { - /* 0 - disable, 1 - enable */ - unsigned char en; - /* 0 - replace with black dot, 1 - white dot when correction - * method is IPIPE_DFC_REPL_BY_DOT=0, - */ - unsigned char repl_white; - /* number of entries in the correction table. Currently only - * support up-to 256 entries. infinite mode is not supported - */ - unsigned short dpc_size; - struct vpfe_ipipe_lutdpc_entry table[VPFE_IPIPE_MAX_SIZE_DPC]; -}; - -enum vpfe_ipipe_otfdpc_det_meth { - VPFE_IPIPE_DPC_OTF_MIN_MAX, - VPFE_IPIPE_DPC_OTF_MIN_MAX2 -}; - -struct vpfe_ipipe_otfdpc_thr { - unsigned short r; - unsigned short gr; - unsigned short gb; - unsigned short b; -}; - -enum vpfe_ipipe_otfdpc_alg { - VPFE_IPIPE_OTFDPC_2_0, - VPFE_IPIPE_OTFDPC_3_0 -}; - -struct vpfe_ipipe_otfdpc_2_0_cfg { - /* defect detection threshold for MIN_MAX2 method (DPC 2.0 alg) */ - struct vpfe_ipipe_otfdpc_thr det_thr; - /* defect correction threshold for MIN_MAX2 method (DPC 2.0 alg) or - * maximum value for MIN_MAX method - */ - struct vpfe_ipipe_otfdpc_thr corr_thr; -}; - -struct vpfe_ipipe_otfdpc_3_0_cfg { - /* DPC3.0 activity adj shf. activity = (max2-min2) >> (6 -shf) - */ - unsigned char act_adj_shf; - /* DPC3.0 detection threshold, THR */ - unsigned short det_thr; - /* DPC3.0 detection threshold slope, SLP */ - unsigned short det_slp; - /* DPC3.0 detection threshold min, MIN */ - unsigned short det_thr_min; - /* DPC3.0 detection threshold max, MAX */ - unsigned short det_thr_max; - /* DPC3.0 correction threshold, THR */ - unsigned short corr_thr; - /* DPC3.0 correction threshold slope, SLP */ - unsigned short corr_slp; - /* DPC3.0 correction threshold min, MIN */ - unsigned short corr_thr_min; - /* DPC3.0 correction threshold max, MAX */ - unsigned short corr_thr_max; -}; - -struct vpfe_ipipe_otfdpc { - /* 0 - disable, 1 - enable */ - unsigned char en; - /* defect detection method */ - enum vpfe_ipipe_otfdpc_det_meth det_method; - /* Algorithm used. Applicable only when IPIPE_DPC_OTF_MIN_MAX2 is - * used - */ - enum vpfe_ipipe_otfdpc_alg alg; - union { - /* if alg is IPIPE_OTFDPC_2_0 */ - struct vpfe_ipipe_otfdpc_2_0_cfg dpc_2_0; - /* if alg is IPIPE_OTFDPC_3_0 */ - struct vpfe_ipipe_otfdpc_3_0_cfg dpc_3_0; - } alg_cfg; -}; - -/* Threshold values table size */ -#define VPFE_IPIPE_NF_THR_TABLE_SIZE 8 -/* Intensity values table size */ -#define VPFE_IPIPE_NF_STR_TABLE_SIZE 8 - -/* NF, sampling method for green pixels */ -enum vpfe_ipipe_nf_sampl_meth { - /* Same as R or B */ - VPFE_IPIPE_NF_BOX, - /* Diamond mode */ - VPFE_IPIPE_NF_DIAMOND -}; - -/* Structure for configuring NF module */ -struct vpfe_ipipe_nf { - /* 0 - disable, 1 - enable */ - unsigned char en; - /* Sampling method for green pixels */ - enum vpfe_ipipe_nf_sampl_meth gr_sample_meth; - /* Down shift value in LUT reference address - */ - unsigned char shft_val; - /* Spread value in NF algorithm - */ - unsigned char spread_val; - /* Apply LSC gain to threshold. Enable this only if - * LSC is enabled in ISIF - */ - unsigned char apply_lsc_gain; - /* Threshold values table */ - unsigned short thr[VPFE_IPIPE_NF_THR_TABLE_SIZE]; - /* intensity values table */ - unsigned char str[VPFE_IPIPE_NF_STR_TABLE_SIZE]; - /* Edge detection minimum threshold */ - unsigned short edge_det_min_thr; - /* Edge detection maximum threshold */ - unsigned short edge_det_max_thr; -}; - -enum vpfe_ipipe_gic_alg { - VPFE_IPIPE_GIC_ALG_CONST_GAIN, - VPFE_IPIPE_GIC_ALG_ADAPT_GAIN -}; - -enum vpfe_ipipe_gic_thr_sel { - VPFE_IPIPE_GIC_THR_REG, - VPFE_IPIPE_GIC_THR_NF -}; - -enum vpfe_ipipe_gic_wt_fn_type { - /* Use difference as index */ - VPFE_IPIPE_GIC_WT_FN_TYP_DIF, - /* Use weight function as index */ - VPFE_IPIPE_GIC_WT_FN_TYP_HP_VAL -}; - -/* structure for Green Imbalance Correction */ -struct vpfe_ipipe_gic { - /* 0 - disable, 1 - enable */ - unsigned char en; - /* 0 - Constant gain , 1 - Adaptive gain algorithm */ - enum vpfe_ipipe_gic_alg gic_alg; - /* GIC gain or weight. Used for Constant gain and Adaptive algorithms - */ - unsigned short gain; - /* Threshold selection. GIC register values or NF2 thr table */ - enum vpfe_ipipe_gic_thr_sel thr_sel; - /* thr1. Used when thr_sel is IPIPE_GIC_THR_REG */ - unsigned short thr; - /* this value is used for thr2-thr1, thr3-thr2 or - * thr4-thr3 when wt_fn_type is index. Otherwise it - * is the - */ - unsigned short slope; - /* Apply LSC gain to threshold. Enable this only if - * LSC is enabled in ISIF & thr_sel is IPIPE_GIC_THR_REG - */ - unsigned char apply_lsc_gain; - /* Multiply Nf2 threshold by this gain. Use this when thr_sel - * is IPIPE_GIC_THR_NF - */ - struct ipipe_float_u8 nf2_thr_gain; - /* Weight function uses difference as index or high pass value. - * Used for adaptive gain algorithm - */ - enum vpfe_ipipe_gic_wt_fn_type wt_fn_type; -}; - -/* Structure for configuring WB module */ -struct vpfe_ipipe_wb { - /* Offset (S12) for R */ - short ofst_r; - /* Offset (S12) for Gr */ - short ofst_gr; - /* Offset (S12) for Gb */ - short ofst_gb; - /* Offset (S12) for B */ - short ofst_b; - /* Gain (U13Q9) for Red */ - struct ipipe_float_u16 gain_r; - /* Gain (U13Q9) for Gr */ - struct ipipe_float_u16 gain_gr; - /* Gain (U13Q9) for Gb */ - struct ipipe_float_u16 gain_gb; - /* Gain (U13Q9) for Blue */ - struct ipipe_float_u16 gain_b; -}; - -enum vpfe_ipipe_cfa_alg { - /* Algorithm is 2DirAC */ - VPFE_IPIPE_CFA_ALG_2DIRAC, - /* Algorithm is 2DirAC + Digital Antialiasing (DAA) */ - VPFE_IPIPE_CFA_ALG_2DIRAC_DAA, - /* Algorithm is DAA */ - VPFE_IPIPE_CFA_ALG_DAA -}; - -/* Structure for CFA Interpolation */ -struct vpfe_ipipe_cfa { - /* 2DirAC or 2DirAC + DAA */ - enum vpfe_ipipe_cfa_alg alg; - /* 2Dir CFA HP value Low Threshold */ - unsigned short hpf_thr_2dir; - /* 2Dir CFA HP value slope */ - unsigned short hpf_slp_2dir; - /* 2Dir CFA HP mix threshold */ - unsigned short hp_mix_thr_2dir; - /* 2Dir CFA HP mix slope */ - unsigned short hp_mix_slope_2dir; - /* 2Dir Direction threshold */ - unsigned short dir_thr_2dir; - /* 2Dir Direction slope */ - unsigned short dir_slope_2dir; - /* 2Dir Non Directional Weight */ - unsigned short nd_wt_2dir; - /* DAA Mono Hue Fraction */ - unsigned short hue_fract_daa; - /* DAA Mono Edge threshold */ - unsigned short edge_thr_daa; - /* DAA Mono threshold minimum */ - unsigned short thr_min_daa; - /* DAA Mono threshold slope */ - unsigned short thr_slope_daa; - /* DAA Mono slope minimum */ - unsigned short slope_min_daa; - /* DAA Mono slope slope */ - unsigned short slope_slope_daa; - /* DAA Mono LP wight */ - unsigned short lp_wt_daa; -}; - -/* Struct for configuring RGB2RGB blending module */ -struct vpfe_ipipe_rgb2rgb { - /* Matrix coefficient for RR S12Q8 for ID = 1 and S11Q8 for ID = 2 */ - struct ipipe_float_s16 coef_rr; - /* Matrix coefficient for GR S12Q8/S11Q8 */ - struct ipipe_float_s16 coef_gr; - /* Matrix coefficient for BR S12Q8/S11Q8 */ - struct ipipe_float_s16 coef_br; - /* Matrix coefficient for RG S12Q8/S11Q8 */ - struct ipipe_float_s16 coef_rg; - /* Matrix coefficient for GG S12Q8/S11Q8 */ - struct ipipe_float_s16 coef_gg; - /* Matrix coefficient for BG S12Q8/S11Q8 */ - struct ipipe_float_s16 coef_bg; - /* Matrix coefficient for RB S12Q8/S11Q8 */ - struct ipipe_float_s16 coef_rb; - /* Matrix coefficient for GB S12Q8/S11Q8 */ - struct ipipe_float_s16 coef_gb; - /* Matrix coefficient for BB S12Q8/S11Q8 */ - struct ipipe_float_s16 coef_bb; - /* Output offset for R S13/S11 */ - int out_ofst_r; - /* Output offset for G S13/S11 */ - int out_ofst_g; - /* Output offset for B S13/S11 */ - int out_ofst_b; -}; - -#define VPFE_IPIPE_MAX_SIZE_GAMMA 512 - -enum vpfe_ipipe_gamma_tbl_size { - VPFE_IPIPE_GAMMA_TBL_SZ_64 = 64, - VPFE_IPIPE_GAMMA_TBL_SZ_128 = 128, - VPFE_IPIPE_GAMMA_TBL_SZ_256 = 256, - VPFE_IPIPE_GAMMA_TBL_SZ_512 = 512, -}; - -enum vpfe_ipipe_gamma_tbl_sel { - VPFE_IPIPE_GAMMA_TBL_RAM = 0, - VPFE_IPIPE_GAMMA_TBL_ROM = 1, -}; - -struct vpfe_ipipe_gamma_entry { - /* 10 bit slope */ - short slope; - /* 10 bit offset */ - unsigned short offset; -}; - -/* Structure for configuring Gamma correction module */ -struct vpfe_ipipe_gamma { - /* 0 - Enable Gamma correction for Red - * 1 - bypass Gamma correction. Data is divided by 16 - */ - unsigned char bypass_r; - /* 0 - Enable Gamma correction for Blue - * 1 - bypass Gamma correction. Data is divided by 16 - */ - unsigned char bypass_b; - /* 0 - Enable Gamma correction for Green - * 1 - bypass Gamma correction. Data is divided by 16 - */ - unsigned char bypass_g; - /* IPIPE_GAMMA_TBL_RAM or IPIPE_GAMMA_TBL_ROM */ - enum vpfe_ipipe_gamma_tbl_sel tbl_sel; - /* Table size for RAM gamma table. - */ - enum vpfe_ipipe_gamma_tbl_size tbl_size; - /* R table */ - struct vpfe_ipipe_gamma_entry table_r[VPFE_IPIPE_MAX_SIZE_GAMMA]; - /* Blue table */ - struct vpfe_ipipe_gamma_entry table_b[VPFE_IPIPE_MAX_SIZE_GAMMA]; - /* Green table */ - struct vpfe_ipipe_gamma_entry table_g[VPFE_IPIPE_MAX_SIZE_GAMMA]; -}; - -#define VPFE_IPIPE_MAX_SIZE_3D_LUT 729 - -struct vpfe_ipipe_3d_lut_entry { - /* 10 bit entry for red */ - unsigned short r; - /* 10 bit entry for green */ - unsigned short g; - /* 10 bit entry for blue */ - unsigned short b; -}; - -/* structure for 3D-LUT */ -struct vpfe_ipipe_3d_lut { - /* enable/disable 3D lut */ - unsigned char en; - /* 3D - LUT table entry */ - struct vpfe_ipipe_3d_lut_entry table[VPFE_IPIPE_MAX_SIZE_3D_LUT]; -}; - -/* Struct for configuring rgb2ycbcr module */ -struct vpfe_ipipe_rgb2yuv { - /* Matrix coefficient for RY S12Q8 */ - struct ipipe_float_s16 coef_ry; - /* Matrix coefficient for GY S12Q8 */ - struct ipipe_float_s16 coef_gy; - /* Matrix coefficient for BY S12Q8 */ - struct ipipe_float_s16 coef_by; - /* Matrix coefficient for RCb S12Q8 */ - struct ipipe_float_s16 coef_rcb; - /* Matrix coefficient for GCb S12Q8 */ - struct ipipe_float_s16 coef_gcb; - /* Matrix coefficient for BCb S12Q8 */ - struct ipipe_float_s16 coef_bcb; - /* Matrix coefficient for RCr S12Q8 */ - struct ipipe_float_s16 coef_rcr; - /* Matrix coefficient for GCr S12Q8 */ - struct ipipe_float_s16 coef_gcr; - /* Matrix coefficient for BCr S12Q8 */ - struct ipipe_float_s16 coef_bcr; - /* Output offset for R S11 */ - int out_ofst_y; - /* Output offset for Cb S11 */ - int out_ofst_cb; - /* Output offset for Cr S11 */ - int out_ofst_cr; -}; - -enum vpfe_ipipe_gbce_type { - VPFE_IPIPE_GBCE_Y_VAL_TBL = 0, - VPFE_IPIPE_GBCE_GAIN_TBL = 1, -}; - -#define VPFE_IPIPE_MAX_SIZE_GBCE_LUT 1024 - -/* structure for Global brightness and Contrast */ -struct vpfe_ipipe_gbce { - /* enable/disable GBCE */ - unsigned char en; - /* Y - value table or Gain table */ - enum vpfe_ipipe_gbce_type type; - /* ptr to LUT for GBCE with 1024 entries */ - unsigned short table[VPFE_IPIPE_MAX_SIZE_GBCE_LUT]; -}; - -/* Chrominance position. Applicable only for YCbCr input - * Applied after edge enhancement - */ -enum vpfe_chr_pos { - /* Co-siting, same position with luminance */ - VPFE_IPIPE_YUV422_CHR_POS_COSITE = 0, - /* Centering, In the middle of luminance */ - VPFE_IPIPE_YUV422_CHR_POS_CENTRE = 1, -}; - -/* Structure for configuring yuv422 conversion module */ -struct vpfe_ipipe_yuv422_conv { - /* Max Chrominance value */ - unsigned char en_chrom_lpf; - /* 1 - enable LPF for chrminance, 0 - disable */ - enum vpfe_chr_pos chrom_pos; -}; - -#define VPFE_IPIPE_MAX_SIZE_YEE_LUT 1024 - -enum vpfe_ipipe_yee_merge_meth { - VPFE_IPIPE_YEE_ABS_MAX = 0, - VPFE_IPIPE_YEE_EE_ES = 1, -}; - -/* Structure for configuring YUV Edge Enhancement module */ -struct vpfe_ipipe_yee { - /* 1 - enable enhancement, 0 - disable */ - unsigned char en; - /* enable/disable halo reduction in edge sharpner */ - unsigned char en_halo_red; - /* Merge method between Edge Enhancer and Edge sharpner */ - enum vpfe_ipipe_yee_merge_meth merge_meth; - /* HPF Shift length */ - unsigned char hpf_shft; - /* HPF Coefficient 00, S10 */ - short hpf_coef_00; - /* HPF Coefficient 01, S10 */ - short hpf_coef_01; - /* HPF Coefficient 02, S10 */ - short hpf_coef_02; - /* HPF Coefficient 10, S10 */ - short hpf_coef_10; - /* HPF Coefficient 11, S10 */ - short hpf_coef_11; - /* HPF Coefficient 12, S10 */ - short hpf_coef_12; - /* HPF Coefficient 20, S10 */ - short hpf_coef_20; - /* HPF Coefficient 21, S10 */ - short hpf_coef_21; - /* HPF Coefficient 22, S10 */ - short hpf_coef_22; - /* Lower threshold before referring to LUT */ - unsigned short yee_thr; - /* Edge sharpener Gain */ - unsigned short es_gain; - /* Edge sharpener lower threshold */ - unsigned short es_thr1; - /* Edge sharpener upper threshold */ - unsigned short es_thr2; - /* Edge sharpener gain on gradient */ - unsigned short es_gain_grad; - /* Edge sharpener offset on gradient */ - unsigned short es_ofst_grad; - /* Ptr to EE table. Must have 1024 entries */ - short table[VPFE_IPIPE_MAX_SIZE_YEE_LUT]; -}; - -enum vpfe_ipipe_car_meth { - /* Chromatic Gain Control */ - VPFE_IPIPE_CAR_CHR_GAIN_CTRL = 0, - /* Dynamic switching between CHR_GAIN_CTRL - * and MED_FLTR - */ - VPFE_IPIPE_CAR_DYN_SWITCH = 1, - /* Median Filter */ - VPFE_IPIPE_CAR_MED_FLTR = 2, -}; - -enum vpfe_ipipe_car_hpf_type { - VPFE_IPIPE_CAR_HPF_Y = 0, - VPFE_IPIPE_CAR_HPF_H = 1, - VPFE_IPIPE_CAR_HPF_V = 2, - VPFE_IPIPE_CAR_HPF_2D = 3, - /* 2D HPF from YUV Edge Enhancement */ - VPFE_IPIPE_CAR_HPF_2D_YEE = 4, -}; - -struct vpfe_ipipe_car_gain { - /* csup_gain */ - unsigned char gain; - /* csup_shf. */ - unsigned char shft; - /* gain minimum */ - unsigned short gain_min; -}; - -/* Structure for Chromatic Artifact Reduction */ -struct vpfe_ipipe_car { - /* enable/disable */ - unsigned char en; - /* Gain control or Dynamic switching */ - enum vpfe_ipipe_car_meth meth; - /* Gain1 function configuration for Gain control */ - struct vpfe_ipipe_car_gain gain1; - /* Gain2 function configuration for Gain control */ - struct vpfe_ipipe_car_gain gain2; - /* HPF type used for CAR */ - enum vpfe_ipipe_car_hpf_type hpf; - /* csup_thr: HPF threshold for Gain control */ - unsigned char hpf_thr; - /* Down shift value for hpf. 2 bits */ - unsigned char hpf_shft; - /* switch limit for median filter */ - unsigned char sw0; - /* switch coefficient for Gain control */ - unsigned char sw1; -}; - -/* structure for Chromatic Gain Suppression */ -struct vpfe_ipipe_cgs { - /* enable/disable */ - unsigned char en; - /* gain1 bright side threshold */ - unsigned char h_thr; - /* gain1 bright side slope */ - unsigned char h_slope; - /* gain1 down shift value for bright side */ - unsigned char h_shft; - /* gain1 bright side minimum gain */ - unsigned char h_min; -}; - -/* Max pixels allowed in the input. If above this either decimation - * or frame division mode to be enabled - */ -#define VPFE_IPIPE_MAX_INPUT_WIDTH 2600 - -struct vpfe_ipipe_input_config { - unsigned int vst; - unsigned int hst; -}; - -/** - * struct vpfe_ipipe_config - IPIPE engine configuration (user) - * @input_config: Pointer to structure for ipipe configuration. - * @flag: Specifies which ISP IPIPE functions should be enabled. - * @lutdpc: Pointer to luma enhancement structure. - * @otfdpc: Pointer to structure for defect correction. - * @nf1: Pointer to structure for Noise Filter. - * @nf2: Pointer to structure for Noise Filter. - * @gic: Pointer to structure for Green Imbalance. - * @wbal: Pointer to structure for White Balance. - * @cfa: Pointer to structure containing the CFA interpolation. - * @rgb2rgb1: Pointer to structure for RGB to RGB Blending. - * @rgb2rgb2: Pointer to structure for RGB to RGB Blending. - * @gamma: Pointer to gamma structure. - * @lut: Pointer to structure for 3D LUT. - * @rgb2yuv: Pointer to structure for RGB-YCbCr conversion. - * @gbce: Pointer to structure for Global Brightness,Contrast Control. - * @yuv422_conv: Pointer to structure for YUV 422 conversion. - * @yee: Pointer to structure for Edge Enhancer. - * @car: Pointer to structure for Chromatic Artifact Reduction. - * @cgs: Pointer to structure for Chromatic Gain Suppression. - */ -struct vpfe_ipipe_config { - __u32 flag; - struct vpfe_ipipe_input_config __user *input_config; - struct vpfe_ipipe_lutdpc __user *lutdpc; - struct vpfe_ipipe_otfdpc __user *otfdpc; - struct vpfe_ipipe_nf __user *nf1; - struct vpfe_ipipe_nf __user *nf2; - struct vpfe_ipipe_gic __user *gic; - struct vpfe_ipipe_wb __user *wbal; - struct vpfe_ipipe_cfa __user *cfa; - struct vpfe_ipipe_rgb2rgb __user *rgb2rgb1; - struct vpfe_ipipe_rgb2rgb __user *rgb2rgb2; - struct vpfe_ipipe_gamma __user *gamma; - struct vpfe_ipipe_3d_lut __user *lut; - struct vpfe_ipipe_rgb2yuv __user *rgb2yuv; - struct vpfe_ipipe_gbce __user *gbce; - struct vpfe_ipipe_yuv422_conv __user *yuv422_conv; - struct vpfe_ipipe_yee __user *yee; - struct vpfe_ipipe_car __user *car; - struct vpfe_ipipe_cgs __user *cgs; -}; - -/******************************************************************* - ** Resizer API structures - *******************************************************************/ -/* Interpolation types used for horizontal rescale */ -enum vpfe_rsz_intp_t { - VPFE_RSZ_INTP_CUBIC, - VPFE_RSZ_INTP_LINEAR -}; - -/* Horizontal LPF intensity selection */ -enum vpfe_rsz_h_lpf_lse_t { - VPFE_RSZ_H_LPF_LSE_INTERN, - VPFE_RSZ_H_LPF_LSE_USER_VAL -}; - -enum vpfe_rsz_down_scale_ave_sz { - VPFE_IPIPE_DWN_SCALE_1_OVER_2, - VPFE_IPIPE_DWN_SCALE_1_OVER_4, - VPFE_IPIPE_DWN_SCALE_1_OVER_8, - VPFE_IPIPE_DWN_SCALE_1_OVER_16, - VPFE_IPIPE_DWN_SCALE_1_OVER_32, - VPFE_IPIPE_DWN_SCALE_1_OVER_64, - VPFE_IPIPE_DWN_SCALE_1_OVER_128, - VPFE_IPIPE_DWN_SCALE_1_OVER_256 -}; - -struct vpfe_rsz_output_spec { - /* enable horizontal flip */ - unsigned char h_flip; - /* enable vertical flip */ - unsigned char v_flip; - /* line start offset for y. */ - unsigned int vst_y; - /* line start offset for c. Only for 420 */ - unsigned int vst_c; - /* vertical rescale interpolation type, YCbCr or Luminance */ - enum vpfe_rsz_intp_t v_typ_y; - /* vertical rescale interpolation type for Chrominance */ - enum vpfe_rsz_intp_t v_typ_c; - /* vertical lpf intensity - Luminance */ - unsigned char v_lpf_int_y; - /* vertical lpf intensity - Chrominance */ - unsigned char v_lpf_int_c; - /* horizontal rescale interpolation types, YCbCr or Luminance */ - enum vpfe_rsz_intp_t h_typ_y; - /* horizontal rescale interpolation types, Chrominance */ - enum vpfe_rsz_intp_t h_typ_c; - /* horizontal lpf intensity - Luminance */ - unsigned char h_lpf_int_y; - /* horizontal lpf intensity - Chrominance */ - unsigned char h_lpf_int_c; - /* Use down scale mode for scale down */ - unsigned char en_down_scale; - /* if downscale, set the downscale more average size for horizontal - * direction. Used only if output width and height is less than - * input sizes - */ - enum vpfe_rsz_down_scale_ave_sz h_dscale_ave_sz; - /* if downscale, set the downscale more average size for vertical - * direction. Used only if output width and height is less than - * input sizes - */ - enum vpfe_rsz_down_scale_ave_sz v_dscale_ave_sz; - /* Y offset. If set, the offset would be added to the base address - */ - unsigned int user_y_ofst; - /* C offset. If set, the offset would be added to the base address - */ - unsigned int user_c_ofst; -}; - -struct vpfe_rsz_config_params { - unsigned int vst; - /* horizontal start position of the image - * data to IPIPE - */ - unsigned int hst; - /* output spec of the image data coming out of resizer - 0(UYVY). - */ - struct vpfe_rsz_output_spec output1; - /* output spec of the image data coming out of resizer - 1(UYVY). - */ - struct vpfe_rsz_output_spec output2; - /* 0 , chroma sample at odd pixel, 1 - even pixel */ - unsigned char chroma_sample_even; - unsigned char frame_div_mode_en; - unsigned char yuv_y_min; - unsigned char yuv_y_max; - unsigned char yuv_c_min; - unsigned char yuv_c_max; - enum vpfe_chr_pos out_chr_pos; - unsigned char bypass; -}; - -/* Structure for VIDIOC_VPFE_RSZ_[S/G]_CONFIG IOCTLs */ -struct vpfe_rsz_config { - struct vpfe_rsz_config_params *config; -}; - -#endif /* _DAVINCI_VPFE_USER_H */ diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipe.c b/drivers/staging/media/davinci_vpfe/dm365_ipipe.c deleted file mode 100644 index 5d8ba357906b..000000000000 --- a/drivers/staging/media/davinci_vpfe/dm365_ipipe.c +++ /dev/null @@ -1,1857 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2012 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Contributors: - * Manjunath Hadli <manjunath.hadli@ti.com> - * Prabhakar Lad <prabhakar.lad@ti.com> - * - * - * IPIPE allows fine tuning of the input image using different - * tuning modules in IPIPE. Some examples :- Noise filter, Defect - * pixel correction etc. It essentially operate on Bayer Raw data - * or YUV raw data. To do image tuning, application call, - * - */ - -#include <linux/slab.h> -#include <linux/bitops.h> - -#include "dm365_ipipe.h" -#include "dm365_ipipe_hw.h" -#include "vpfe_mc_capture.h" - -#define MIN_OUT_WIDTH 32 -#define MIN_OUT_HEIGHT 32 - -/* ipipe input format's */ -static const unsigned int ipipe_input_fmts[] = { - MEDIA_BUS_FMT_UYVY8_2X8, - MEDIA_BUS_FMT_SGRBG12_1X12, - MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8, - MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8, -}; - -/* ipipe output format's */ -static const unsigned int ipipe_output_fmts[] = { - MEDIA_BUS_FMT_UYVY8_2X8, -}; - -static int ipipe_validate_lutdpc_params(struct vpfe_ipipe_lutdpc *lutdpc) -{ - int i; - - if (lutdpc->en > 1 || lutdpc->repl_white > 1 || - lutdpc->dpc_size > LUT_DPC_MAX_SIZE) - return -EINVAL; - - if (lutdpc->en) - return -EINVAL; - - for (i = 0; i < lutdpc->dpc_size; i++) - if (lutdpc->table[i].horz_pos > LUT_DPC_H_POS_MASK || - lutdpc->table[i].vert_pos > LUT_DPC_V_POS_MASK) - return -EINVAL; - - return 0; -} - -static int ipipe_set_lutdpc_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_lutdpc *lutdpc = &ipipe->config.lutdpc; - struct vpfe_ipipe_lutdpc *dpc_param; - - if (!param) { - memset((void *)lutdpc, 0, sizeof(struct vpfe_ipipe_lutdpc)); - goto success; - } - - dpc_param = param; - lutdpc->en = dpc_param->en; - lutdpc->repl_white = dpc_param->repl_white; - lutdpc->dpc_size = dpc_param->dpc_size; - memcpy(&lutdpc->table, &dpc_param->table, - (dpc_param->dpc_size * sizeof(struct vpfe_ipipe_lutdpc_entry))); - if (ipipe_validate_lutdpc_params(lutdpc) < 0) - return -EINVAL; - -success: - ipipe_set_lutdpc_regs(ipipe->base_addr, ipipe->isp5_base_addr, lutdpc); - - return 0; -} - -static int ipipe_get_lutdpc_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_lutdpc *lut_param = param; - struct vpfe_ipipe_lutdpc *lutdpc = &ipipe->config.lutdpc; - - lut_param->en = lutdpc->en; - lut_param->repl_white = lutdpc->repl_white; - lut_param->dpc_size = lutdpc->dpc_size; - memcpy(&lut_param->table, &lutdpc->table, - (lutdpc->dpc_size * sizeof(struct vpfe_ipipe_lutdpc_entry))); - - return 0; -} - -static int ipipe_set_input_config(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_input_config *config = &ipipe->config.input_config; - - if (!param) - memset(config, 0, sizeof(struct vpfe_ipipe_input_config)); - else - memcpy(config, param, sizeof(struct vpfe_ipipe_input_config)); - return 0; -} - -static int ipipe_get_input_config(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_input_config *config = &ipipe->config.input_config; - - if (!param) - return -EINVAL; - - memcpy(param, config, sizeof(struct vpfe_ipipe_input_config)); - - return 0; -} - -static int ipipe_validate_otfdpc_params(struct vpfe_ipipe_otfdpc *dpc_param) -{ - struct vpfe_ipipe_otfdpc_2_0_cfg *dpc_2_0; - struct vpfe_ipipe_otfdpc_3_0_cfg *dpc_3_0; - - if (dpc_param->en > 1) - return -EINVAL; - - if (dpc_param->alg == VPFE_IPIPE_OTFDPC_2_0) { - dpc_2_0 = &dpc_param->alg_cfg.dpc_2_0; - if (dpc_2_0->det_thr.r > OTFDPC_DPC2_THR_MASK || - dpc_2_0->det_thr.gr > OTFDPC_DPC2_THR_MASK || - dpc_2_0->det_thr.gb > OTFDPC_DPC2_THR_MASK || - dpc_2_0->det_thr.b > OTFDPC_DPC2_THR_MASK || - dpc_2_0->corr_thr.r > OTFDPC_DPC2_THR_MASK || - dpc_2_0->corr_thr.gr > OTFDPC_DPC2_THR_MASK || - dpc_2_0->corr_thr.gb > OTFDPC_DPC2_THR_MASK || - dpc_2_0->corr_thr.b > OTFDPC_DPC2_THR_MASK) - return -EINVAL; - return 0; - } - - dpc_3_0 = &dpc_param->alg_cfg.dpc_3_0; - - if (dpc_3_0->act_adj_shf > OTF_DPC3_0_SHF_MASK || - dpc_3_0->det_thr > OTF_DPC3_0_DET_MASK || - dpc_3_0->det_slp > OTF_DPC3_0_SLP_MASK || - dpc_3_0->det_thr_min > OTF_DPC3_0_DET_MASK || - dpc_3_0->det_thr_max > OTF_DPC3_0_DET_MASK || - dpc_3_0->corr_thr > OTF_DPC3_0_CORR_MASK || - dpc_3_0->corr_slp > OTF_DPC3_0_SLP_MASK || - dpc_3_0->corr_thr_min > OTF_DPC3_0_CORR_MASK || - dpc_3_0->corr_thr_max > OTF_DPC3_0_CORR_MASK) - return -EINVAL; - - return 0; -} - -static int ipipe_set_otfdpc_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_otfdpc *dpc_param = param; - struct vpfe_ipipe_otfdpc *otfdpc = &ipipe->config.otfdpc; - struct device *dev; - - if (!param) { - memset((void *)otfdpc, 0, sizeof(struct ipipe_otfdpc_2_0)); - goto success; - } - dev = ipipe->subdev.v4l2_dev->dev; - memcpy(otfdpc, dpc_param, sizeof(struct vpfe_ipipe_otfdpc)); - if (ipipe_validate_otfdpc_params(otfdpc) < 0) { - dev_err(dev, "Invalid otfdpc params\n"); - return -EINVAL; - } - -success: - ipipe_set_otfdpc_regs(ipipe->base_addr, otfdpc); - - return 0; -} - -static int ipipe_get_otfdpc_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_otfdpc *dpc_param = param; - struct vpfe_ipipe_otfdpc *otfdpc = &ipipe->config.otfdpc; - - memcpy(dpc_param, otfdpc, sizeof(struct vpfe_ipipe_otfdpc)); - return 0; -} - -static int ipipe_validate_nf_params(struct vpfe_ipipe_nf *nf_param) -{ - int i; - - if (nf_param->en > 1 || nf_param->shft_val > D2F_SHFT_VAL_MASK || - nf_param->spread_val > D2F_SPR_VAL_MASK || - nf_param->apply_lsc_gain > 1 || - nf_param->edge_det_min_thr > D2F_EDGE_DET_THR_MASK || - nf_param->edge_det_max_thr > D2F_EDGE_DET_THR_MASK) - return -EINVAL; - - for (i = 0; i < VPFE_IPIPE_NF_THR_TABLE_SIZE; i++) - if (nf_param->thr[i] > D2F_THR_VAL_MASK) - return -EINVAL; - - for (i = 0; i < VPFE_IPIPE_NF_STR_TABLE_SIZE; i++) - if (nf_param->str[i] > D2F_STR_VAL_MASK) - return -EINVAL; - - return 0; -} - -static int ipipe_set_nf_params(struct vpfe_ipipe_device *ipipe, - unsigned int id, void *param) -{ - struct vpfe_ipipe_nf *nf_param = param; - struct vpfe_ipipe_nf *nf = &ipipe->config.nf1; - struct device *dev; - - if (id == IPIPE_D2F_2ND) - nf = &ipipe->config.nf2; - - if (!nf_param) { - memset((void *)nf, 0, sizeof(struct vpfe_ipipe_nf)); - goto success; - } - - dev = ipipe->subdev.v4l2_dev->dev; - memcpy(nf, nf_param, sizeof(struct vpfe_ipipe_nf)); - if (ipipe_validate_nf_params(nf) < 0) { - dev_err(dev, "Invalid nf params\n"); - return -EINVAL; - } - -success: - ipipe_set_d2f_regs(ipipe->base_addr, id, nf); - - return 0; -} - -static int ipipe_set_nf1_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - return ipipe_set_nf_params(ipipe, IPIPE_D2F_1ST, param); -} - -static int ipipe_set_nf2_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - return ipipe_set_nf_params(ipipe, IPIPE_D2F_2ND, param); -} - -static int ipipe_get_nf_params(struct vpfe_ipipe_device *ipipe, - unsigned int id, void *param) -{ - struct vpfe_ipipe_nf *nf_param = param; - struct vpfe_ipipe_nf *nf = &ipipe->config.nf1; - - if (id == IPIPE_D2F_2ND) - nf = &ipipe->config.nf2; - - memcpy(nf_param, nf, sizeof(struct vpfe_ipipe_nf)); - - return 0; -} - -static int ipipe_get_nf1_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - return ipipe_get_nf_params(ipipe, IPIPE_D2F_1ST, param); -} - -static int ipipe_get_nf2_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - return ipipe_get_nf_params(ipipe, IPIPE_D2F_2ND, param); -} - -static int ipipe_validate_gic_params(struct vpfe_ipipe_gic *gic) -{ - if (gic->en > 1 || gic->gain > GIC_GAIN_MASK || - gic->thr > GIC_THR_MASK || gic->slope > GIC_SLOPE_MASK || - gic->apply_lsc_gain > 1 || - gic->nf2_thr_gain.integer > GIC_NFGAN_INT_MASK || - gic->nf2_thr_gain.decimal > GIC_NFGAN_DECI_MASK) - return -EINVAL; - - return 0; -} - -static int ipipe_set_gic_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_gic *gic_param = param; - struct device *dev = ipipe->subdev.v4l2_dev->dev; - struct vpfe_ipipe_gic *gic = &ipipe->config.gic; - - if (!gic_param) { - memset((void *)gic, 0, sizeof(struct vpfe_ipipe_gic)); - goto success; - } - - memcpy(gic, gic_param, sizeof(struct vpfe_ipipe_gic)); - if (ipipe_validate_gic_params(gic) < 0) { - dev_err(dev, "Invalid gic params\n"); - return -EINVAL; - } - -success: - ipipe_set_gic_regs(ipipe->base_addr, gic); - - return 0; -} - -static int ipipe_get_gic_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_gic *gic_param = param; - struct vpfe_ipipe_gic *gic = &ipipe->config.gic; - - memcpy(gic_param, gic, sizeof(struct vpfe_ipipe_gic)); - - return 0; -} - -static int ipipe_validate_wb_params(struct vpfe_ipipe_wb *wbal) -{ - if (wbal->ofst_r > WB_OFFSET_MASK || - wbal->ofst_gr > WB_OFFSET_MASK || - wbal->ofst_gb > WB_OFFSET_MASK || - wbal->ofst_b > WB_OFFSET_MASK || - wbal->gain_r.integer > WB_GAIN_INT_MASK || - wbal->gain_r.decimal > WB_GAIN_DECI_MASK || - wbal->gain_gr.integer > WB_GAIN_INT_MASK || - wbal->gain_gr.decimal > WB_GAIN_DECI_MASK || - wbal->gain_gb.integer > WB_GAIN_INT_MASK || - wbal->gain_gb.decimal > WB_GAIN_DECI_MASK || - wbal->gain_b.integer > WB_GAIN_INT_MASK || - wbal->gain_b.decimal > WB_GAIN_DECI_MASK) - return -EINVAL; - - return 0; -} - -static int ipipe_set_wb_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_wb *wb_param = param; - struct vpfe_ipipe_wb *wbal = &ipipe->config.wbal; - - if (!wb_param) { - const struct vpfe_ipipe_wb wb_defaults = { - .gain_r = {2, 0x0}, - .gain_gr = {2, 0x0}, - .gain_gb = {2, 0x0}, - .gain_b = {2, 0x0} - }; - memcpy(wbal, &wb_defaults, sizeof(struct vpfe_ipipe_wb)); - goto success; - } - - memcpy(wbal, wb_param, sizeof(struct vpfe_ipipe_wb)); - if (ipipe_validate_wb_params(wbal) < 0) - return -EINVAL; - -success: - ipipe_set_wb_regs(ipipe->base_addr, wbal); - - return 0; -} - -static int ipipe_get_wb_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_wb *wb_param = param; - struct vpfe_ipipe_wb *wbal = &ipipe->config.wbal; - - memcpy(wb_param, wbal, sizeof(struct vpfe_ipipe_wb)); - return 0; -} - -static int ipipe_validate_cfa_params(struct vpfe_ipipe_cfa *cfa) -{ - if (cfa->hpf_thr_2dir > CFA_HPF_THR_2DIR_MASK || - cfa->hpf_slp_2dir > CFA_HPF_SLOPE_2DIR_MASK || - cfa->hp_mix_thr_2dir > CFA_HPF_MIX_THR_2DIR_MASK || - cfa->hp_mix_slope_2dir > CFA_HPF_MIX_SLP_2DIR_MASK || - cfa->dir_thr_2dir > CFA_DIR_THR_2DIR_MASK || - cfa->dir_slope_2dir > CFA_DIR_SLP_2DIR_MASK || - cfa->nd_wt_2dir > CFA_ND_WT_2DIR_MASK || - cfa->hue_fract_daa > CFA_DAA_HUE_FRA_MASK || - cfa->edge_thr_daa > CFA_DAA_EDG_THR_MASK || - cfa->thr_min_daa > CFA_DAA_THR_MIN_MASK || - cfa->thr_slope_daa > CFA_DAA_THR_SLP_MASK || - cfa->slope_min_daa > CFA_DAA_SLP_MIN_MASK || - cfa->slope_slope_daa > CFA_DAA_SLP_SLP_MASK || - cfa->lp_wt_daa > CFA_DAA_LP_WT_MASK) - return -EINVAL; - - return 0; -} - -static int ipipe_set_cfa_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_cfa *cfa_param = param; - struct vpfe_ipipe_cfa *cfa = &ipipe->config.cfa; - - if (!cfa_param) { - memset(cfa, 0, sizeof(struct vpfe_ipipe_cfa)); - cfa->alg = VPFE_IPIPE_CFA_ALG_2DIRAC; - goto success; - } - - memcpy(cfa, cfa_param, sizeof(struct vpfe_ipipe_cfa)); - if (ipipe_validate_cfa_params(cfa) < 0) - return -EINVAL; - -success: - ipipe_set_cfa_regs(ipipe->base_addr, cfa); - - return 0; -} - -static int ipipe_get_cfa_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_cfa *cfa_param = param; - struct vpfe_ipipe_cfa *cfa = &ipipe->config.cfa; - - memcpy(cfa_param, cfa, sizeof(struct vpfe_ipipe_cfa)); - return 0; -} - -static int -ipipe_validate_rgb2rgb_params(struct vpfe_ipipe_rgb2rgb *rgb2rgb, - unsigned int id) -{ - u32 gain_int_upper = RGB2RGB_1_GAIN_INT_MASK; - u32 offset_upper = RGB2RGB_1_OFST_MASK; - - if (id == IPIPE_RGB2RGB_2) { - offset_upper = RGB2RGB_2_OFST_MASK; - gain_int_upper = RGB2RGB_2_GAIN_INT_MASK; - } - - if (rgb2rgb->coef_rr.decimal > RGB2RGB_GAIN_DECI_MASK || - rgb2rgb->coef_rr.integer > gain_int_upper) - return -EINVAL; - - if (rgb2rgb->coef_gr.decimal > RGB2RGB_GAIN_DECI_MASK || - rgb2rgb->coef_gr.integer > gain_int_upper) - return -EINVAL; - - if (rgb2rgb->coef_br.decimal > RGB2RGB_GAIN_DECI_MASK || - rgb2rgb->coef_br.integer > gain_int_upper) - return -EINVAL; - - if (rgb2rgb->coef_rg.decimal > RGB2RGB_GAIN_DECI_MASK || - rgb2rgb->coef_rg.integer > gain_int_upper) - return -EINVAL; - - if (rgb2rgb->coef_gg.decimal > RGB2RGB_GAIN_DECI_MASK || - rgb2rgb->coef_gg.integer > gain_int_upper) - return -EINVAL; - - if (rgb2rgb->coef_bg.decimal > RGB2RGB_GAIN_DECI_MASK || - rgb2rgb->coef_bg.integer > gain_int_upper) - return -EINVAL; - - if (rgb2rgb->coef_rb.decimal > RGB2RGB_GAIN_DECI_MASK || - rgb2rgb->coef_rb.integer > gain_int_upper) - return -EINVAL; - - if (rgb2rgb->coef_gb.decimal > RGB2RGB_GAIN_DECI_MASK || - rgb2rgb->coef_gb.integer > gain_int_upper) - return -EINVAL; - - if (rgb2rgb->coef_bb.decimal > RGB2RGB_GAIN_DECI_MASK || - rgb2rgb->coef_bb.integer > gain_int_upper) - return -EINVAL; - - if (rgb2rgb->out_ofst_r > offset_upper || - rgb2rgb->out_ofst_g > offset_upper || - rgb2rgb->out_ofst_b > offset_upper) - return -EINVAL; - - return 0; -} - -static int ipipe_set_rgb2rgb_params(struct vpfe_ipipe_device *ipipe, - unsigned int id, void *param) -{ - struct vpfe_ipipe_rgb2rgb *rgb2rgb = &ipipe->config.rgb2rgb1; - struct device *dev = ipipe->subdev.v4l2_dev->dev; - struct vpfe_ipipe_rgb2rgb *rgb2rgb_param; - - rgb2rgb_param = param; - - if (id == IPIPE_RGB2RGB_2) - rgb2rgb = &ipipe->config.rgb2rgb2; - - if (!rgb2rgb_param) { - const struct vpfe_ipipe_rgb2rgb rgb2rgb_defaults = { - .coef_rr = {1, 0}, /* 256 */ - .coef_gr = {0, 0}, - .coef_br = {0, 0}, - .coef_rg = {0, 0}, - .coef_gg = {1, 0}, /* 256 */ - .coef_bg = {0, 0}, - .coef_rb = {0, 0}, - .coef_gb = {0, 0}, - .coef_bb = {1, 0}, /* 256 */ - }; - /* Copy defaults for rgb2rgb conversion */ - memcpy(rgb2rgb, &rgb2rgb_defaults, - sizeof(struct vpfe_ipipe_rgb2rgb)); - goto success; - } - - memcpy(rgb2rgb, rgb2rgb_param, sizeof(struct vpfe_ipipe_rgb2rgb)); - if (ipipe_validate_rgb2rgb_params(rgb2rgb, id) < 0) { - dev_err(dev, "Invalid rgb2rgb params\n"); - return -EINVAL; - } - -success: - ipipe_set_rgb2rgb_regs(ipipe->base_addr, id, rgb2rgb); - - return 0; -} - -static int -ipipe_set_rgb2rgb_1_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - return ipipe_set_rgb2rgb_params(ipipe, IPIPE_RGB2RGB_1, param); -} - -static int -ipipe_set_rgb2rgb_2_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - return ipipe_set_rgb2rgb_params(ipipe, IPIPE_RGB2RGB_2, param); -} - -static int ipipe_get_rgb2rgb_params(struct vpfe_ipipe_device *ipipe, - unsigned int id, void *param) -{ - struct vpfe_ipipe_rgb2rgb *rgb2rgb = &ipipe->config.rgb2rgb1; - struct vpfe_ipipe_rgb2rgb *rgb2rgb_param; - - rgb2rgb_param = param; - - if (id == IPIPE_RGB2RGB_2) - rgb2rgb = &ipipe->config.rgb2rgb2; - - memcpy(rgb2rgb_param, rgb2rgb, sizeof(struct vpfe_ipipe_rgb2rgb)); - - return 0; -} - -static int -ipipe_get_rgb2rgb_1_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - return ipipe_get_rgb2rgb_params(ipipe, IPIPE_RGB2RGB_1, param); -} - -static int -ipipe_get_rgb2rgb_2_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - return ipipe_get_rgb2rgb_params(ipipe, IPIPE_RGB2RGB_2, param); -} - -static int -ipipe_validate_gamma_entry(struct vpfe_ipipe_gamma_entry *table, int size) -{ - int i; - - if (!table) - return -EINVAL; - - for (i = 0; i < size; i++) - if (table[i].slope > GAMMA_MASK || - table[i].offset > GAMMA_MASK) - return -EINVAL; - - return 0; -} - -static int -ipipe_validate_gamma_params(struct vpfe_ipipe_gamma *gamma, struct device *dev) -{ - int table_size; - int err; - - if (gamma->bypass_r > 1 || - gamma->bypass_b > 1 || - gamma->bypass_g > 1) - return -EINVAL; - - if (gamma->tbl_sel != VPFE_IPIPE_GAMMA_TBL_RAM) - return 0; - - table_size = gamma->tbl_size; - if (!gamma->bypass_r) { - err = ipipe_validate_gamma_entry(gamma->table_r, table_size); - if (err) { - dev_err(dev, "GAMMA R - table entry invalid\n"); - return err; - } - } - - if (!gamma->bypass_b) { - err = ipipe_validate_gamma_entry(gamma->table_b, table_size); - if (err) { - dev_err(dev, "GAMMA B - table entry invalid\n"); - return err; - } - } - - if (!gamma->bypass_g) { - err = ipipe_validate_gamma_entry(gamma->table_g, table_size); - if (err) { - dev_err(dev, "GAMMA G - table entry invalid\n"); - return err; - } - } - - return 0; -} - -static int -ipipe_set_gamma_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_gamma *gamma_param = param; - struct vpfe_ipipe_gamma *gamma = &ipipe->config.gamma; - struct device *dev = ipipe->subdev.v4l2_dev->dev; - int table_size; - - if (!gamma_param) { - memset(gamma, 0, sizeof(struct vpfe_ipipe_gamma)); - gamma->tbl_sel = VPFE_IPIPE_GAMMA_TBL_ROM; - goto success; - } - - gamma->bypass_r = gamma_param->bypass_r; - gamma->bypass_b = gamma_param->bypass_b; - gamma->bypass_g = gamma_param->bypass_g; - gamma->tbl_sel = gamma_param->tbl_sel; - gamma->tbl_size = gamma_param->tbl_size; - - if (ipipe_validate_gamma_params(gamma, dev) < 0) - return -EINVAL; - - if (gamma_param->tbl_sel != VPFE_IPIPE_GAMMA_TBL_RAM) - goto success; - - table_size = gamma->tbl_size; - if (!gamma_param->bypass_r) - memcpy(&gamma->table_r, &gamma_param->table_r, - (table_size * sizeof(struct vpfe_ipipe_gamma_entry))); - - if (!gamma_param->bypass_b) - memcpy(&gamma->table_b, &gamma_param->table_b, - (table_size * sizeof(struct vpfe_ipipe_gamma_entry))); - - if (!gamma_param->bypass_g) - memcpy(&gamma->table_g, &gamma_param->table_g, - (table_size * sizeof(struct vpfe_ipipe_gamma_entry))); - -success: - ipipe_set_gamma_regs(ipipe->base_addr, ipipe->isp5_base_addr, gamma); - - return 0; -} - -static int ipipe_get_gamma_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_gamma *gamma_param = param; - struct vpfe_ipipe_gamma *gamma = &ipipe->config.gamma; - struct device *dev = ipipe->subdev.v4l2_dev->dev; - int table_size; - - gamma_param->bypass_r = gamma->bypass_r; - gamma_param->bypass_g = gamma->bypass_g; - gamma_param->bypass_b = gamma->bypass_b; - gamma_param->tbl_sel = gamma->tbl_sel; - gamma_param->tbl_size = gamma->tbl_size; - - if (gamma->tbl_sel != VPFE_IPIPE_GAMMA_TBL_RAM) - return 0; - - table_size = gamma->tbl_size; - - if (!gamma->bypass_r) { - dev_err(dev, - "%s: table ptr empty for R\n", __func__); - return -EINVAL; - } - memcpy(gamma_param->table_r, gamma->table_r, - (table_size * sizeof(struct vpfe_ipipe_gamma_entry))); - - if (!gamma->bypass_g) { - dev_err(dev, "%s: table ptr empty for G\n", __func__); - return -EINVAL; - } - memcpy(gamma_param->table_g, gamma->table_g, - (table_size * sizeof(struct vpfe_ipipe_gamma_entry))); - - if (!gamma->bypass_b) { - dev_err(dev, "%s: table ptr empty for B\n", __func__); - return -EINVAL; - } - memcpy(gamma_param->table_b, gamma->table_b, - (table_size * sizeof(struct vpfe_ipipe_gamma_entry))); - - return 0; -} - -static int ipipe_validate_3d_lut_params(struct vpfe_ipipe_3d_lut *lut) -{ - int i; - - if (!lut->en) - return 0; - - for (i = 0; i < VPFE_IPIPE_MAX_SIZE_3D_LUT; i++) - if (lut->table[i].r > D3_LUT_ENTRY_MASK || - lut->table[i].g > D3_LUT_ENTRY_MASK || - lut->table[i].b > D3_LUT_ENTRY_MASK) - return -EINVAL; - - return 0; -} - -static int ipipe_get_3d_lut_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_3d_lut *lut_param = param; - struct vpfe_ipipe_3d_lut *lut = &ipipe->config.lut; - - lut_param->en = lut->en; - - memcpy(lut_param->table, &lut->table, - (VPFE_IPIPE_MAX_SIZE_3D_LUT * - sizeof(struct vpfe_ipipe_3d_lut_entry))); - - return 0; -} - -static int -ipipe_set_3d_lut_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_3d_lut *lut_param = param; - struct vpfe_ipipe_3d_lut *lut = &ipipe->config.lut; - struct device *dev = ipipe->subdev.v4l2_dev->dev; - - if (!lut_param) { - memset(lut, 0, sizeof(struct vpfe_ipipe_3d_lut)); - goto success; - } - - memcpy(lut, lut_param, sizeof(struct vpfe_ipipe_3d_lut)); - if (ipipe_validate_3d_lut_params(lut) < 0) { - dev_err(dev, "Invalid 3D-LUT Params\n"); - return -EINVAL; - } - -success: - ipipe_set_3d_lut_regs(ipipe->base_addr, ipipe->isp5_base_addr, lut); - - return 0; -} - -static int ipipe_validate_rgb2yuv_params(struct vpfe_ipipe_rgb2yuv *rgb2yuv) -{ - if (rgb2yuv->coef_ry.decimal > RGB2YCBCR_COEF_DECI_MASK || - rgb2yuv->coef_ry.integer > RGB2YCBCR_COEF_INT_MASK) - return -EINVAL; - - if (rgb2yuv->coef_gy.decimal > RGB2YCBCR_COEF_DECI_MASK || - rgb2yuv->coef_gy.integer > RGB2YCBCR_COEF_INT_MASK) - return -EINVAL; - - if (rgb2yuv->coef_by.decimal > RGB2YCBCR_COEF_DECI_MASK || - rgb2yuv->coef_by.integer > RGB2YCBCR_COEF_INT_MASK) - return -EINVAL; - - if (rgb2yuv->coef_rcb.decimal > RGB2YCBCR_COEF_DECI_MASK || - rgb2yuv->coef_rcb.integer > RGB2YCBCR_COEF_INT_MASK) - return -EINVAL; - - if (rgb2yuv->coef_gcb.decimal > RGB2YCBCR_COEF_DECI_MASK || - rgb2yuv->coef_gcb.integer > RGB2YCBCR_COEF_INT_MASK) - return -EINVAL; - - if (rgb2yuv->coef_bcb.decimal > RGB2YCBCR_COEF_DECI_MASK || - rgb2yuv->coef_bcb.integer > RGB2YCBCR_COEF_INT_MASK) - return -EINVAL; - - if (rgb2yuv->coef_rcr.decimal > RGB2YCBCR_COEF_DECI_MASK || - rgb2yuv->coef_rcr.integer > RGB2YCBCR_COEF_INT_MASK) - return -EINVAL; - - if (rgb2yuv->coef_gcr.decimal > RGB2YCBCR_COEF_DECI_MASK || - rgb2yuv->coef_gcr.integer > RGB2YCBCR_COEF_INT_MASK) - return -EINVAL; - - if (rgb2yuv->coef_bcr.decimal > RGB2YCBCR_COEF_DECI_MASK || - rgb2yuv->coef_bcr.integer > RGB2YCBCR_COEF_INT_MASK) - return -EINVAL; - - if (rgb2yuv->out_ofst_y > RGB2YCBCR_OFST_MASK || - rgb2yuv->out_ofst_cb > RGB2YCBCR_OFST_MASK || - rgb2yuv->out_ofst_cr > RGB2YCBCR_OFST_MASK) - return -EINVAL; - - return 0; -} - -static int -ipipe_set_rgb2yuv_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_rgb2yuv *rgb2yuv = &ipipe->config.rgb2yuv; - struct device *dev = ipipe->subdev.v4l2_dev->dev; - struct vpfe_ipipe_rgb2yuv *rgb2yuv_param; - - rgb2yuv_param = param; - if (!rgb2yuv_param) { - /* Defaults for rgb2yuv conversion */ - const struct vpfe_ipipe_rgb2yuv rgb2yuv_defaults = { - .coef_ry = {0, 0x4d}, - .coef_gy = {0, 0x96}, - .coef_by = {0, 0x1d}, - .coef_rcb = {0xf, 0xd5}, - .coef_gcb = {0xf, 0xab}, - .coef_bcb = {0, 0x80}, - .coef_rcr = {0, 0x80}, - .coef_gcr = {0xf, 0x95}, - .coef_bcr = {0xf, 0xeb}, - .out_ofst_cb = 0x80, - .out_ofst_cr = 0x80, - }; - /* Copy defaults for rgb2yuv conversion */ - memcpy(rgb2yuv, &rgb2yuv_defaults, - sizeof(struct vpfe_ipipe_rgb2yuv)); - goto success; - } - - memcpy(rgb2yuv, rgb2yuv_param, sizeof(struct vpfe_ipipe_rgb2yuv)); - if (ipipe_validate_rgb2yuv_params(rgb2yuv) < 0) { - dev_err(dev, "Invalid rgb2yuv params\n"); - return -EINVAL; - } - -success: - ipipe_set_rgb2ycbcr_regs(ipipe->base_addr, rgb2yuv); - - return 0; -} - -static int -ipipe_get_rgb2yuv_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_rgb2yuv *rgb2yuv = &ipipe->config.rgb2yuv; - struct vpfe_ipipe_rgb2yuv *rgb2yuv_param; - - rgb2yuv_param = param; - memcpy(rgb2yuv_param, rgb2yuv, sizeof(struct vpfe_ipipe_rgb2yuv)); - return 0; -} - -static int ipipe_validate_gbce_params(struct vpfe_ipipe_gbce *gbce) -{ - u32 max = GBCE_Y_VAL_MASK; - int i; - - if (!gbce->en) - return 0; - - if (gbce->type == VPFE_IPIPE_GBCE_GAIN_TBL) - max = GBCE_GAIN_VAL_MASK; - - for (i = 0; i < VPFE_IPIPE_MAX_SIZE_GBCE_LUT; i++) - if (gbce->table[i] > max) - return -EINVAL; - - return 0; -} - -static int ipipe_set_gbce_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_gbce *gbce_param = param; - struct vpfe_ipipe_gbce *gbce = &ipipe->config.gbce; - struct device *dev = ipipe->subdev.v4l2_dev->dev; - - if (!gbce_param) { - memset(gbce, 0, sizeof(struct vpfe_ipipe_gbce)); - } else { - memcpy(gbce, gbce_param, sizeof(struct vpfe_ipipe_gbce)); - if (ipipe_validate_gbce_params(gbce) < 0) { - dev_err(dev, "Invalid gbce params\n"); - return -EINVAL; - } - } - - ipipe_set_gbce_regs(ipipe->base_addr, ipipe->isp5_base_addr, gbce); - - return 0; -} - -static int ipipe_get_gbce_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_gbce *gbce_param = param; - struct vpfe_ipipe_gbce *gbce = &ipipe->config.gbce; - - gbce_param->en = gbce->en; - gbce_param->type = gbce->type; - - memcpy(gbce_param->table, gbce->table, - (VPFE_IPIPE_MAX_SIZE_GBCE_LUT * sizeof(unsigned short))); - - return 0; -} - -static int -ipipe_validate_yuv422_conv_params(struct vpfe_ipipe_yuv422_conv *yuv422_conv) -{ - if (yuv422_conv->en_chrom_lpf > 1) - return -EINVAL; - - return 0; -} - -static int -ipipe_set_yuv422_conv_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_yuv422_conv *yuv422_conv = &ipipe->config.yuv422_conv; - struct vpfe_ipipe_yuv422_conv *yuv422_conv_param; - struct device *dev = ipipe->subdev.v4l2_dev->dev; - - yuv422_conv_param = param; - if (!yuv422_conv_param) { - memset(yuv422_conv, 0, sizeof(struct vpfe_ipipe_yuv422_conv)); - yuv422_conv->chrom_pos = VPFE_IPIPE_YUV422_CHR_POS_COSITE; - } else { - memcpy(yuv422_conv, yuv422_conv_param, - sizeof(struct vpfe_ipipe_yuv422_conv)); - if (ipipe_validate_yuv422_conv_params(yuv422_conv) < 0) { - dev_err(dev, "Invalid yuv422 params\n"); - return -EINVAL; - } - } - - ipipe_set_yuv422_conv_regs(ipipe->base_addr, yuv422_conv); - - return 0; -} - -static int -ipipe_get_yuv422_conv_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_yuv422_conv *yuv422_conv = &ipipe->config.yuv422_conv; - struct vpfe_ipipe_yuv422_conv *yuv422_conv_param; - - yuv422_conv_param = param; - memcpy(yuv422_conv_param, yuv422_conv, - sizeof(struct vpfe_ipipe_yuv422_conv)); - - return 0; -} - -static int ipipe_validate_yee_params(struct vpfe_ipipe_yee *yee) -{ - int i; - - if (yee->en > 1 || - yee->en_halo_red > 1 || - yee->hpf_shft > YEE_HPF_SHIFT_MASK) - return -EINVAL; - - if (yee->hpf_coef_00 > YEE_COEF_MASK || - yee->hpf_coef_01 > YEE_COEF_MASK || - yee->hpf_coef_02 > YEE_COEF_MASK || - yee->hpf_coef_10 > YEE_COEF_MASK || - yee->hpf_coef_11 > YEE_COEF_MASK || - yee->hpf_coef_12 > YEE_COEF_MASK || - yee->hpf_coef_20 > YEE_COEF_MASK || - yee->hpf_coef_21 > YEE_COEF_MASK || - yee->hpf_coef_22 > YEE_COEF_MASK) - return -EINVAL; - - if (yee->yee_thr > YEE_THR_MASK || - yee->es_gain > YEE_ES_GAIN_MASK || - yee->es_thr1 > YEE_ES_THR1_MASK || - yee->es_thr2 > YEE_THR_MASK || - yee->es_gain_grad > YEE_THR_MASK || - yee->es_ofst_grad > YEE_THR_MASK) - return -EINVAL; - - for (i = 0; i < VPFE_IPIPE_MAX_SIZE_YEE_LUT; i++) - if (yee->table[i] > YEE_ENTRY_MASK) - return -EINVAL; - - return 0; -} - -static int ipipe_set_yee_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_yee *yee_param = param; - struct device *dev = ipipe->subdev.v4l2_dev->dev; - struct vpfe_ipipe_yee *yee = &ipipe->config.yee; - - if (!yee_param) { - memset(yee, 0, sizeof(struct vpfe_ipipe_yee)); - } else { - memcpy(yee, yee_param, sizeof(struct vpfe_ipipe_yee)); - if (ipipe_validate_yee_params(yee) < 0) { - dev_err(dev, "Invalid yee params\n"); - return -EINVAL; - } - } - - ipipe_set_ee_regs(ipipe->base_addr, ipipe->isp5_base_addr, yee); - - return 0; -} - -static int ipipe_get_yee_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_yee *yee_param = param; - struct vpfe_ipipe_yee *yee = &ipipe->config.yee; - - yee_param->en = yee->en; - yee_param->en_halo_red = yee->en_halo_red; - yee_param->merge_meth = yee->merge_meth; - yee_param->hpf_shft = yee->hpf_shft; - yee_param->hpf_coef_00 = yee->hpf_coef_00; - yee_param->hpf_coef_01 = yee->hpf_coef_01; - yee_param->hpf_coef_02 = yee->hpf_coef_02; - yee_param->hpf_coef_10 = yee->hpf_coef_10; - yee_param->hpf_coef_11 = yee->hpf_coef_11; - yee_param->hpf_coef_12 = yee->hpf_coef_12; - yee_param->hpf_coef_20 = yee->hpf_coef_20; - yee_param->hpf_coef_21 = yee->hpf_coef_21; - yee_param->hpf_coef_22 = yee->hpf_coef_22; - yee_param->yee_thr = yee->yee_thr; - yee_param->es_gain = yee->es_gain; - yee_param->es_thr1 = yee->es_thr1; - yee_param->es_thr2 = yee->es_thr2; - yee_param->es_gain_grad = yee->es_gain_grad; - yee_param->es_ofst_grad = yee->es_ofst_grad; - memcpy(yee_param->table, &yee->table, - (VPFE_IPIPE_MAX_SIZE_YEE_LUT * sizeof(short))); - - return 0; -} - -static int ipipe_validate_car_params(struct vpfe_ipipe_car *car) -{ - if (car->en > 1 || car->hpf_shft > CAR_HPF_SHIFT_MASK || - car->gain1.shft > CAR_GAIN1_SHFT_MASK || - car->gain1.gain_min > CAR_GAIN_MIN_MASK || - car->gain2.shft > CAR_GAIN2_SHFT_MASK || - car->gain2.gain_min > CAR_GAIN_MIN_MASK) - return -EINVAL; - - return 0; -} - -static int ipipe_set_car_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_car *car_param = param; - struct device *dev = ipipe->subdev.v4l2_dev->dev; - struct vpfe_ipipe_car *car = &ipipe->config.car; - - if (!car_param) { - memset(car, 0, sizeof(struct vpfe_ipipe_car)); - } else { - memcpy(car, car_param, sizeof(struct vpfe_ipipe_car)); - if (ipipe_validate_car_params(car) < 0) { - dev_err(dev, "Invalid car params\n"); - return -EINVAL; - } - } - - ipipe_set_car_regs(ipipe->base_addr, car); - - return 0; -} - -static int ipipe_get_car_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_car *car_param = param; - struct vpfe_ipipe_car *car = &ipipe->config.car; - - memcpy(car_param, car, sizeof(struct vpfe_ipipe_car)); - return 0; -} - -static int ipipe_validate_cgs_params(struct vpfe_ipipe_cgs *cgs) -{ - if (cgs->en > 1 || cgs->h_shft > CAR_SHIFT_MASK) - return -EINVAL; - - return 0; -} - -static int ipipe_set_cgs_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_cgs *cgs_param = param; - struct device *dev = ipipe->subdev.v4l2_dev->dev; - struct vpfe_ipipe_cgs *cgs = &ipipe->config.cgs; - - if (!cgs_param) { - memset(cgs, 0, sizeof(struct vpfe_ipipe_cgs)); - } else { - memcpy(cgs, cgs_param, sizeof(struct vpfe_ipipe_cgs)); - if (ipipe_validate_cgs_params(cgs) < 0) { - dev_err(dev, "Invalid cgs params\n"); - return -EINVAL; - } - } - - ipipe_set_cgs_regs(ipipe->base_addr, cgs); - - return 0; -} - -static int ipipe_get_cgs_params(struct vpfe_ipipe_device *ipipe, void *param) -{ - struct vpfe_ipipe_cgs *cgs_param = param; - struct vpfe_ipipe_cgs *cgs = &ipipe->config.cgs; - - memcpy(cgs_param, cgs, sizeof(struct vpfe_ipipe_cgs)); - - return 0; -} - -static const struct ipipe_module_if ipipe_modules[VPFE_IPIPE_MAX_MODULES] = { - /* VPFE_IPIPE_INPUT_CONFIG */ { - offsetof(struct ipipe_module_params, input_config), - FIELD_SIZEOF(struct ipipe_module_params, input_config), - offsetof(struct vpfe_ipipe_config, input_config), - ipipe_set_input_config, - ipipe_get_input_config, - }, /* VPFE_IPIPE_LUTDPC */ { - offsetof(struct ipipe_module_params, lutdpc), - FIELD_SIZEOF(struct ipipe_module_params, lutdpc), - offsetof(struct vpfe_ipipe_config, lutdpc), - ipipe_set_lutdpc_params, - ipipe_get_lutdpc_params, - }, /* VPFE_IPIPE_OTFDPC */ { - offsetof(struct ipipe_module_params, otfdpc), - FIELD_SIZEOF(struct ipipe_module_params, otfdpc), - offsetof(struct vpfe_ipipe_config, otfdpc), - ipipe_set_otfdpc_params, - ipipe_get_otfdpc_params, - }, /* VPFE_IPIPE_NF1 */ { - offsetof(struct ipipe_module_params, nf1), - FIELD_SIZEOF(struct ipipe_module_params, nf1), - offsetof(struct vpfe_ipipe_config, nf1), - ipipe_set_nf1_params, - ipipe_get_nf1_params, - }, /* VPFE_IPIPE_NF2 */ { - offsetof(struct ipipe_module_params, nf2), - FIELD_SIZEOF(struct ipipe_module_params, nf2), - offsetof(struct vpfe_ipipe_config, nf2), - ipipe_set_nf2_params, - ipipe_get_nf2_params, - }, /* VPFE_IPIPE_WB */ { - offsetof(struct ipipe_module_params, wbal), - FIELD_SIZEOF(struct ipipe_module_params, wbal), - offsetof(struct vpfe_ipipe_config, wbal), - ipipe_set_wb_params, - ipipe_get_wb_params, - }, /* VPFE_IPIPE_RGB2RGB_1 */ { - offsetof(struct ipipe_module_params, rgb2rgb1), - FIELD_SIZEOF(struct ipipe_module_params, rgb2rgb1), - offsetof(struct vpfe_ipipe_config, rgb2rgb1), - ipipe_set_rgb2rgb_1_params, - ipipe_get_rgb2rgb_1_params, - }, /* VPFE_IPIPE_RGB2RGB_2 */ { - offsetof(struct ipipe_module_params, rgb2rgb2), - FIELD_SIZEOF(struct ipipe_module_params, rgb2rgb2), - offsetof(struct vpfe_ipipe_config, rgb2rgb2), - ipipe_set_rgb2rgb_2_params, - ipipe_get_rgb2rgb_2_params, - }, /* VPFE_IPIPE_GAMMA */ { - offsetof(struct ipipe_module_params, gamma), - FIELD_SIZEOF(struct ipipe_module_params, gamma), - offsetof(struct vpfe_ipipe_config, gamma), - ipipe_set_gamma_params, - ipipe_get_gamma_params, - }, /* VPFE_IPIPE_3D_LUT */ { - offsetof(struct ipipe_module_params, lut), - FIELD_SIZEOF(struct ipipe_module_params, lut), - offsetof(struct vpfe_ipipe_config, lut), - ipipe_set_3d_lut_params, - ipipe_get_3d_lut_params, - }, /* VPFE_IPIPE_RGB2YUV */ { - offsetof(struct ipipe_module_params, rgb2yuv), - FIELD_SIZEOF(struct ipipe_module_params, rgb2yuv), - offsetof(struct vpfe_ipipe_config, rgb2yuv), - ipipe_set_rgb2yuv_params, - ipipe_get_rgb2yuv_params, - }, /* VPFE_IPIPE_YUV422_CONV */ { - offsetof(struct ipipe_module_params, yuv422_conv), - FIELD_SIZEOF(struct ipipe_module_params, yuv422_conv), - offsetof(struct vpfe_ipipe_config, yuv422_conv), - ipipe_set_yuv422_conv_params, - ipipe_get_yuv422_conv_params, - }, /* VPFE_IPIPE_YEE */ { - offsetof(struct ipipe_module_params, yee), - FIELD_SIZEOF(struct ipipe_module_params, yee), - offsetof(struct vpfe_ipipe_config, yee), - ipipe_set_yee_params, - ipipe_get_yee_params, - }, /* VPFE_IPIPE_GIC */ { - offsetof(struct ipipe_module_params, gic), - FIELD_SIZEOF(struct ipipe_module_params, gic), - offsetof(struct vpfe_ipipe_config, gic), - ipipe_set_gic_params, - ipipe_get_gic_params, - }, /* VPFE_IPIPE_CFA */ { - offsetof(struct ipipe_module_params, cfa), - FIELD_SIZEOF(struct ipipe_module_params, cfa), - offsetof(struct vpfe_ipipe_config, cfa), - ipipe_set_cfa_params, - ipipe_get_cfa_params, - }, /* VPFE_IPIPE_CAR */ { - offsetof(struct ipipe_module_params, car), - FIELD_SIZEOF(struct ipipe_module_params, car), - offsetof(struct vpfe_ipipe_config, car), - ipipe_set_car_params, - ipipe_get_car_params, - }, /* VPFE_IPIPE_CGS */ { - offsetof(struct ipipe_module_params, cgs), - FIELD_SIZEOF(struct ipipe_module_params, cgs), - offsetof(struct vpfe_ipipe_config, cgs), - ipipe_set_cgs_params, - ipipe_get_cgs_params, - }, /* VPFE_IPIPE_GBCE */ { - offsetof(struct ipipe_module_params, gbce), - FIELD_SIZEOF(struct ipipe_module_params, gbce), - offsetof(struct vpfe_ipipe_config, gbce), - ipipe_set_gbce_params, - ipipe_get_gbce_params, - }, -}; - -static int ipipe_s_config(struct v4l2_subdev *sd, struct vpfe_ipipe_config *cfg) -{ - struct vpfe_ipipe_device *ipipe = v4l2_get_subdevdata(sd); - unsigned int i; - int rval = 0; - struct ipipe_module_params *params; - - for (i = 0; i < ARRAY_SIZE(ipipe_modules); i++) { - const struct ipipe_module_if *module_if; - void *from, *to; - size_t size; - - if (!(cfg->flag & BIT(i))) - continue; - - module_if = &ipipe_modules[i]; - from = *(void **)((void *)cfg + module_if->config_offset); - - params = kmalloc(sizeof(*params), GFP_KERNEL); - if (!params) - return -ENOMEM; - to = (void *)params + module_if->param_offset; - size = module_if->param_size; - - if (to && from && size) { - if (copy_from_user(to, (void __user *)from, size)) { - rval = -EFAULT; - goto error_free; - } - rval = module_if->set(ipipe, to); - if (rval) - goto error_free; - } else if (to && !from && size) { - rval = module_if->set(ipipe, NULL); - if (rval) - goto error_free; - } - kfree(params); - } - return rval; - -error_free: - kfree(params); - return rval; -} - -static int ipipe_g_config(struct v4l2_subdev *sd, struct vpfe_ipipe_config *cfg) -{ - struct vpfe_ipipe_device *ipipe = v4l2_get_subdevdata(sd); - unsigned int i; - int rval = 0; - - for (i = 1; i < ARRAY_SIZE(ipipe_modules); i++) { - const struct ipipe_module_if *module_if; - struct ipipe_module_params *params; - void *from, *to; - size_t size; - - if (!(cfg->flag & BIT(i))) - continue; - - module_if = &ipipe_modules[i]; - to = *(void **)((void *)cfg + module_if->config_offset); - - params = kmalloc(sizeof(*params), GFP_KERNEL); - if (!params) { - rval = -ENOMEM; - goto error; - } - - from = (void *)params + module_if->param_offset; - size = module_if->param_size; - - if (to && from && size) { - rval = module_if->get(ipipe, from); - if (rval) - goto error; - if (copy_to_user((void __user *)to, from, size)) { - rval = -EFAULT; - break; - } - } - kfree(params); - } -error: - return rval; -} - -/* - * ipipe_ioctl() - Handle ipipe module private ioctl's - * @sd: pointer to v4l2 subdev structure - * @cmd: configuration command - * @arg: configuration argument - */ -static long ipipe_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) -{ - switch (cmd) { - case VIDIOC_VPFE_IPIPE_S_CONFIG: - return ipipe_s_config(sd, arg); - - case VIDIOC_VPFE_IPIPE_G_CONFIG: - return ipipe_g_config(sd, arg); - - default: - return -ENOIOCTLCMD; - } -} - -void vpfe_ipipe_enable(struct vpfe_device *vpfe_dev, int en) -{ - struct vpfe_ipipeif_device *ipipeif = &vpfe_dev->vpfe_ipipeif; - struct vpfe_ipipe_device *ipipe = &vpfe_dev->vpfe_ipipe; - unsigned char val; - - if (ipipe->input == IPIPE_INPUT_NONE) - return; - - /* ipipe is set to single shot */ - if (ipipeif->input == IPIPEIF_INPUT_MEMORY && en) { - /* for single-shot mode, need to wait for h/w to - * reset many register bits - */ - do { - val = regr_ip(vpfe_dev->vpfe_ipipe.base_addr, - IPIPE_SRC_EN); - } while (val); - } - regw_ip(vpfe_dev->vpfe_ipipe.base_addr, en, IPIPE_SRC_EN); -} - -/* - * ipipe_set_stream() - Enable/Disable streaming on the ipipe subdevice - * @sd: pointer to v4l2 subdev structure - * @enable: 1 == Enable, 0 == Disable - */ -static int ipipe_set_stream(struct v4l2_subdev *sd, int enable) -{ - struct vpfe_ipipe_device *ipipe = v4l2_get_subdevdata(sd); - struct vpfe_device *vpfe_dev = to_vpfe_device(ipipe); - - if (enable && ipipe->input != IPIPE_INPUT_NONE && - ipipe->output != IPIPE_OUTPUT_NONE) { - if (config_ipipe_hw(ipipe) < 0) - return -EINVAL; - } - - vpfe_ipipe_enable(vpfe_dev, enable); - - return 0; -} - -/* - * __ipipe_get_format() - helper function for getting ipipe format - * @ipipe: pointer to ipipe private structure. - * @pad: pad number. - * @cfg: V4L2 subdev pad config - * @which: wanted subdev format. - * - */ -static struct v4l2_mbus_framefmt * -__ipipe_get_format(struct vpfe_ipipe_device *ipipe, - struct v4l2_subdev_pad_config *cfg, unsigned int pad, - enum v4l2_subdev_format_whence which) -{ - if (which == V4L2_SUBDEV_FORMAT_TRY) - return v4l2_subdev_get_try_format(&ipipe->subdev, cfg, pad); - - return &ipipe->formats[pad]; -} - -/* - * ipipe_try_format() - Handle try format by pad subdev method - * @ipipe: VPFE ipipe device. - * @cfg: V4L2 subdev pad config - * @pad: pad num. - * @fmt: pointer to v4l2 format structure. - * @which : wanted subdev format - */ -static void -ipipe_try_format(struct vpfe_ipipe_device *ipipe, - struct v4l2_subdev_pad_config *cfg, unsigned int pad, - struct v4l2_mbus_framefmt *fmt, - enum v4l2_subdev_format_whence which) -{ - unsigned int max_out_height; - unsigned int max_out_width; - unsigned int i; - - max_out_width = IPIPE_MAX_OUTPUT_WIDTH_A; - max_out_height = IPIPE_MAX_OUTPUT_HEIGHT_A; - - if (pad == IPIPE_PAD_SINK) { - for (i = 0; i < ARRAY_SIZE(ipipe_input_fmts); i++) - if (fmt->code == ipipe_input_fmts[i]) - break; - - /* If not found, use SBGGR10 as default */ - if (i >= ARRAY_SIZE(ipipe_input_fmts)) - fmt->code = MEDIA_BUS_FMT_SGRBG12_1X12; - } else if (pad == IPIPE_PAD_SOURCE) { - for (i = 0; i < ARRAY_SIZE(ipipe_output_fmts); i++) - if (fmt->code == ipipe_output_fmts[i]) - break; - - /* If not found, use UYVY as default */ - if (i >= ARRAY_SIZE(ipipe_output_fmts)) - fmt->code = MEDIA_BUS_FMT_UYVY8_2X8; - } - - fmt->width = clamp_t(u32, fmt->width, MIN_OUT_HEIGHT, max_out_width); - fmt->height = clamp_t(u32, fmt->height, MIN_OUT_WIDTH, max_out_height); -} - -/* - * ipipe_set_format() - Handle set format by pads subdev method - * @sd: pointer to v4l2 subdev structure - * @cfg: V4L2 subdev pad config - * @fmt: pointer to v4l2 subdev format structure - * return -EINVAL or zero on success - */ -static int -ipipe_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) -{ - struct vpfe_ipipe_device *ipipe = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt *format; - - format = __ipipe_get_format(ipipe, cfg, fmt->pad, fmt->which); - if (!format) - return -EINVAL; - - ipipe_try_format(ipipe, cfg, fmt->pad, &fmt->format, fmt->which); - *format = fmt->format; - - if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) - return 0; - - if (fmt->pad == IPIPE_PAD_SINK && - (ipipe->input == IPIPE_INPUT_CCDC || - ipipe->input == IPIPE_INPUT_MEMORY)) - ipipe->formats[fmt->pad] = fmt->format; - else if (fmt->pad == IPIPE_PAD_SOURCE && - ipipe->output == IPIPE_OUTPUT_RESIZER) - ipipe->formats[fmt->pad] = fmt->format; - else - return -EINVAL; - - return 0; -} - -/* - * ipipe_get_format() - Handle get format by pads subdev method. - * @sd: pointer to v4l2 subdev structure. - * @cfg: V4L2 subdev pad config - * @fmt: pointer to v4l2 subdev format structure. - */ -static int -ipipe_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) -{ - struct vpfe_ipipe_device *ipipe = v4l2_get_subdevdata(sd); - - if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) - fmt->format = ipipe->formats[fmt->pad]; - else - fmt->format = *(v4l2_subdev_get_try_format(sd, cfg, fmt->pad)); - - return 0; -} - -/* - * ipipe_enum_frame_size() - enum frame sizes on pads - * @sd: pointer to v4l2 subdev structure. - * @cfg: V4L2 subdev pad config - * @fse: pointer to v4l2_subdev_frame_size_enum structure. - */ -static int -ipipe_enum_frame_size(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_frame_size_enum *fse) -{ - struct vpfe_ipipe_device *ipipe = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt format; - - if (fse->index != 0) - return -EINVAL; - - format.code = fse->code; - format.width = 1; - format.height = 1; - ipipe_try_format(ipipe, cfg, fse->pad, &format, fse->which); - fse->min_width = format.width; - fse->min_height = format.height; - - if (format.code != fse->code) - return -EINVAL; - - format.code = fse->code; - format.width = -1; - format.height = -1; - ipipe_try_format(ipipe, cfg, fse->pad, &format, fse->which); - fse->max_width = format.width; - fse->max_height = format.height; - - return 0; -} - -/* - * ipipe_enum_mbus_code() - enum mbus codes for pads - * @sd: pointer to v4l2 subdev structure. - * @cfg: V4L2 subdev pad config - * @code: pointer to v4l2_subdev_mbus_code_enum structure - */ -static int -ipipe_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_mbus_code_enum *code) -{ - switch (code->pad) { - case IPIPE_PAD_SINK: - if (code->index >= ARRAY_SIZE(ipipe_input_fmts)) - return -EINVAL; - code->code = ipipe_input_fmts[code->index]; - break; - - case IPIPE_PAD_SOURCE: - if (code->index >= ARRAY_SIZE(ipipe_output_fmts)) - return -EINVAL; - code->code = ipipe_output_fmts[code->index]; - break; - - default: - return -EINVAL; - } - - return 0; -} - -/* - * ipipe_s_ctrl() - Handle set control subdev method - * @ctrl: pointer to v4l2 control structure - */ -static int ipipe_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct vpfe_ipipe_device *ipipe = - container_of(ctrl->handler, struct vpfe_ipipe_device, ctrls); - struct ipipe_lum_adj *lum_adj = &ipipe->config.lum_adj; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - lum_adj->brightness = ctrl->val; - ipipe_set_lum_adj_regs(ipipe->base_addr, lum_adj); - break; - - case V4L2_CID_CONTRAST: - lum_adj->contrast = ctrl->val; - ipipe_set_lum_adj_regs(ipipe->base_addr, lum_adj); - break; - - default: - return -EINVAL; - } - - return 0; -} - -/* - * ipipe_init_formats() - Initialize formats on all pads - * @sd: pointer to v4l2 subdev structure. - * @fh: V4L2 subdev file handle - * - * Initialize all pad formats with default values. Try formats are initialized - * on the file handle. - */ -static int -ipipe_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) -{ - struct v4l2_subdev_format format; - - memset(&format, 0, sizeof(format)); - format.pad = IPIPE_PAD_SINK; - format.which = V4L2_SUBDEV_FORMAT_TRY; - format.format.code = MEDIA_BUS_FMT_SGRBG12_1X12; - format.format.width = IPIPE_MAX_OUTPUT_WIDTH_A; - format.format.height = IPIPE_MAX_OUTPUT_HEIGHT_A; - ipipe_set_format(sd, fh->pad, &format); - - memset(&format, 0, sizeof(format)); - format.pad = IPIPE_PAD_SOURCE; - format.which = V4L2_SUBDEV_FORMAT_TRY; - format.format.code = MEDIA_BUS_FMT_UYVY8_2X8; - format.format.width = IPIPE_MAX_OUTPUT_WIDTH_A; - format.format.height = IPIPE_MAX_OUTPUT_HEIGHT_A; - ipipe_set_format(sd, fh->pad, &format); - - return 0; -} - -/* subdev core operations */ -static const struct v4l2_subdev_core_ops ipipe_v4l2_core_ops = { - .ioctl = ipipe_ioctl, -}; - -static const struct v4l2_ctrl_ops ipipe_ctrl_ops = { - .s_ctrl = ipipe_s_ctrl, -}; - -/* subdev file operations */ -static const struct v4l2_subdev_internal_ops ipipe_v4l2_internal_ops = { - .open = ipipe_init_formats, -}; - -/* subdev video operations */ -static const struct v4l2_subdev_video_ops ipipe_v4l2_video_ops = { - .s_stream = ipipe_set_stream, -}; - -/* subdev pad operations */ -static const struct v4l2_subdev_pad_ops ipipe_v4l2_pad_ops = { - .enum_mbus_code = ipipe_enum_mbus_code, - .enum_frame_size = ipipe_enum_frame_size, - .get_fmt = ipipe_get_format, - .set_fmt = ipipe_set_format, -}; - -/* v4l2 subdev operation */ -static const struct v4l2_subdev_ops ipipe_v4l2_ops = { - .core = &ipipe_v4l2_core_ops, - .video = &ipipe_v4l2_video_ops, - .pad = &ipipe_v4l2_pad_ops, -}; - -/* - * Media entity operations - */ - -/* - * ipipe_link_setup() - Setup ipipe connections - * @entity: ipipe media entity - * @local: Pad at the local end of the link - * @remote: Pad at the remote end of the link - * @flags: Link flags - * - * return -EINVAL or zero on success - */ -static int -ipipe_link_setup(struct media_entity *entity, const struct media_pad *local, - const struct media_pad *remote, u32 flags) -{ - struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); - struct vpfe_ipipe_device *ipipe = v4l2_get_subdevdata(sd); - struct vpfe_device *vpfe_dev = to_vpfe_device(ipipe); - u16 ipipeif_sink = vpfe_dev->vpfe_ipipeif.input; - - if (!is_media_entity_v4l2_subdev(remote->entity)) - return -EINVAL; - - switch (local->index) { - case IPIPE_PAD_SINK: - if (!(flags & MEDIA_LNK_FL_ENABLED)) { - ipipe->input = IPIPE_INPUT_NONE; - break; - } - if (ipipe->input != IPIPE_INPUT_NONE) - return -EBUSY; - if (ipipeif_sink == IPIPEIF_INPUT_MEMORY) - ipipe->input = IPIPE_INPUT_MEMORY; - else - ipipe->input = IPIPE_INPUT_CCDC; - break; - - case IPIPE_PAD_SOURCE: - /* out to RESIZER */ - if (flags & MEDIA_LNK_FL_ENABLED) - ipipe->output = IPIPE_OUTPUT_RESIZER; - else - ipipe->output = IPIPE_OUTPUT_NONE; - break; - - default: - return -EINVAL; - } - - return 0; -} - -static const struct media_entity_operations ipipe_media_ops = { - .link_setup = ipipe_link_setup, -}; - -/* - * vpfe_ipipe_unregister_entities() - ipipe unregister entity - * @vpfe_ipipe: pointer to ipipe subdevice structure. - */ -void vpfe_ipipe_unregister_entities(struct vpfe_ipipe_device *vpfe_ipipe) -{ - /* unregister subdev */ - v4l2_device_unregister_subdev(&vpfe_ipipe->subdev); - /* cleanup entity */ - media_entity_cleanup(&vpfe_ipipe->subdev.entity); -} - -/* - * vpfe_ipipe_register_entities() - ipipe register entity - * @ipipe: pointer to ipipe subdevice structure. - * @vdev: pointer to v4l2 device structure. - */ -int -vpfe_ipipe_register_entities(struct vpfe_ipipe_device *ipipe, - struct v4l2_device *vdev) -{ - int ret; - - /* Register the subdev */ - ret = v4l2_device_register_subdev(vdev, &ipipe->subdev); - if (ret) { - pr_err("Failed to register ipipe as v4l2 subdevice\n"); - return ret; - } - - return ret; -} - -#define IPIPE_CONTRAST_HIGH 0xff -#define IPIPE_BRIGHT_HIGH 0xff - -/* - * vpfe_ipipe_init() - ipipe module initialization. - * @ipipe: pointer to ipipe subdevice structure. - * @pdev: platform device pointer. - */ -int -vpfe_ipipe_init(struct vpfe_ipipe_device *ipipe, struct platform_device *pdev) -{ - struct media_pad *pads = &ipipe->pads[0]; - struct v4l2_subdev *sd = &ipipe->subdev; - struct media_entity *me = &sd->entity; - struct resource *res, *res2, *memres; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 4); - if (!res) - return -ENOENT; - - memres = request_mem_region(res->start, resource_size(res), res->name); - if (!memres) - return -EBUSY; - ipipe->base_addr = ioremap_nocache(memres->start, - resource_size(memres)); - if (!ipipe->base_addr) - goto error_release; - - res2 = platform_get_resource(pdev, IORESOURCE_MEM, 6); - if (!res2) - goto error_unmap; - ipipe->isp5_base_addr = ioremap_nocache(res2->start, - resource_size(res2)); - if (!ipipe->isp5_base_addr) - goto error_unmap; - - v4l2_subdev_init(sd, &ipipe_v4l2_ops); - sd->internal_ops = &ipipe_v4l2_internal_ops; - strscpy(sd->name, "DAVINCI IPIPE", sizeof(sd->name)); - sd->grp_id = 1 << 16; /* group ID for davinci subdevs */ - v4l2_set_subdevdata(sd, ipipe); - sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - - pads[IPIPE_PAD_SINK].flags = MEDIA_PAD_FL_SINK; - pads[IPIPE_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; - - ipipe->input = IPIPE_INPUT_NONE; - ipipe->output = IPIPE_OUTPUT_NONE; - - me->ops = &ipipe_media_ops; - v4l2_ctrl_handler_init(&ipipe->ctrls, 2); - v4l2_ctrl_new_std(&ipipe->ctrls, &ipipe_ctrl_ops, - V4L2_CID_BRIGHTNESS, 0, - IPIPE_BRIGHT_HIGH, 1, 16); - v4l2_ctrl_new_std(&ipipe->ctrls, &ipipe_ctrl_ops, - V4L2_CID_CONTRAST, 0, - IPIPE_CONTRAST_HIGH, 1, 16); - v4l2_ctrl_handler_setup(&ipipe->ctrls); - sd->ctrl_handler = &ipipe->ctrls; - - return media_entity_pads_init(me, IPIPE_PADS_NUM, pads); - -error_unmap: - iounmap(ipipe->base_addr); -error_release: - release_mem_region(memres->start, resource_size(memres)); - return -ENOMEM; -} - -/* - * vpfe_ipipe_cleanup() - ipipe subdevice cleanup. - * @ipipe: pointer to ipipe subdevice - * @dev: pointer to platform device - */ -void vpfe_ipipe_cleanup(struct vpfe_ipipe_device *ipipe, - struct platform_device *pdev) -{ - struct resource *res; - - v4l2_ctrl_handler_free(&ipipe->ctrls); - - iounmap(ipipe->base_addr); - iounmap(ipipe->isp5_base_addr); - res = platform_get_resource(pdev, IORESOURCE_MEM, 4); - if (res) - release_mem_region(res->start, resource_size(res)); -} diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipe.h b/drivers/staging/media/davinci_vpfe/dm365_ipipe.h deleted file mode 100644 index 866ae12aeb07..000000000000 --- a/drivers/staging/media/davinci_vpfe/dm365_ipipe.h +++ /dev/null @@ -1,174 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) 2012 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Contributors: - * Manjunath Hadli <manjunath.hadli@ti.com> - * Prabhakar Lad <prabhakar.lad@ti.com> - */ - -#ifndef _DAVINCI_VPFE_DM365_IPIPE_H -#define _DAVINCI_VPFE_DM365_IPIPE_H - -#include <linux/platform_device.h> - -#include <media/v4l2-ctrls.h> -#include <media/v4l2-subdev.h> - -#include "davinci_vpfe_user.h" -#include "vpfe_video.h" - -enum ipipe_noise_filter { - IPIPE_D2F_1ST = 0, - IPIPE_D2F_2ND = 1, -}; - -/* Used for driver storage */ -struct ipipe_otfdpc_2_0 { - /* 0 - disable, 1 - enable */ - unsigned char en; - /* defect detection method */ - enum vpfe_ipipe_otfdpc_det_meth det_method; - /* Algorithm used. Applicable only when IPIPE_DPC_OTF_MIN_MAX2 is - * used - */ - enum vpfe_ipipe_otfdpc_alg alg; - struct vpfe_ipipe_otfdpc_2_0_cfg otfdpc_2_0; -}; - -struct ipipe_otfdpc_3_0 { - /* 0 - disable, 1 - enable */ - unsigned char en; - /* defect detection method */ - enum vpfe_ipipe_otfdpc_det_meth det_method; - /* Algorithm used. Applicable only when IPIPE_DPC_OTF_MIN_MAX2 is - * used - */ - enum vpfe_ipipe_otfdpc_alg alg; - struct vpfe_ipipe_otfdpc_3_0_cfg otfdpc_3_0; -}; - -/* Structure for configuring Luminance Adjustment module */ -struct ipipe_lum_adj { - /* Brightness adjustments */ - unsigned char brightness; - /* contrast adjustments */ - unsigned char contrast; -}; - -enum ipipe_rgb2rgb { - IPIPE_RGB2RGB_1 = 0, - IPIPE_RGB2RGB_2 = 1, -}; - -struct ipipe_module_params { - __u32 flag; - struct vpfe_ipipe_input_config input_config; - struct vpfe_ipipe_lutdpc lutdpc; - struct vpfe_ipipe_otfdpc otfdpc; - struct vpfe_ipipe_nf nf1; - struct vpfe_ipipe_nf nf2; - struct vpfe_ipipe_gic gic; - struct vpfe_ipipe_wb wbal; - struct vpfe_ipipe_cfa cfa; - struct vpfe_ipipe_rgb2rgb rgb2rgb1; - struct vpfe_ipipe_rgb2rgb rgb2rgb2; - struct vpfe_ipipe_gamma gamma; - struct vpfe_ipipe_3d_lut lut; - struct vpfe_ipipe_rgb2yuv rgb2yuv; - struct vpfe_ipipe_gbce gbce; - struct vpfe_ipipe_yuv422_conv yuv422_conv; - struct vpfe_ipipe_yee yee; - struct vpfe_ipipe_car car; - struct vpfe_ipipe_cgs cgs; - struct ipipe_lum_adj lum_adj; -}; - -#define IPIPE_PAD_SINK 0 -#define IPIPE_PAD_SOURCE 1 - -#define IPIPE_PADS_NUM 2 - -#define IPIPE_OUTPUT_NONE 0 -#define IPIPE_OUTPUT_RESIZER (1 << 0) - -enum ipipe_input_entity { - IPIPE_INPUT_NONE = 0, - IPIPE_INPUT_MEMORY = 1, - IPIPE_INPUT_CCDC = 2, -}; - - -struct vpfe_ipipe_device { - struct v4l2_subdev subdev; - struct media_pad pads[IPIPE_PADS_NUM]; - struct v4l2_mbus_framefmt formats[IPIPE_PADS_NUM]; - enum ipipe_input_entity input; - unsigned int output; - struct v4l2_ctrl_handler ctrls; - void __iomem *base_addr; - void __iomem *isp5_base_addr; - struct ipipe_module_params config; -}; - -struct ipipe_module_if { - unsigned int param_offset; - unsigned int param_size; - unsigned int config_offset; - int (*set)(struct vpfe_ipipe_device *ipipe, void *param); - int (*get)(struct vpfe_ipipe_device *ipipe, void *param); -}; - -/* data paths */ -enum ipipe_data_paths { - IPIPE_RAW2YUV, - /* Bayer RAW input to YCbCr output */ - IPIPE_RAW2RAW, - /* Bayer Raw to Bayer output */ - IPIPE_RAW2BOX, - /* Bayer Raw to Boxcar output */ - IPIPE_YUV2YUV - /* YUV Raw to YUV Raw output */ -}; - -#define IPIPE_COLPTN_R_Ye 0x0 -#define IPIPE_COLPTN_Gr_Cy 0x1 -#define IPIPE_COLPTN_Gb_G 0x2 -#define IPIPE_COLPTN_B_Mg 0x3 - -#define COLPAT_EE_SHIFT 0 -#define COLPAT_EO_SHIFT 2 -#define COLPAT_OE_SHIFT 4 -#define COLPAT_OO_SHIFT 6 - -#define ipipe_sgrbg_pattern \ - (IPIPE_COLPTN_Gr_Cy << COLPAT_EE_SHIFT | \ - IPIPE_COLPTN_R_Ye << COLPAT_EO_SHIFT | \ - IPIPE_COLPTN_B_Mg << COLPAT_OE_SHIFT | \ - IPIPE_COLPTN_Gb_G << COLPAT_OO_SHIFT) - -#define ipipe_srggb_pattern \ - (IPIPE_COLPTN_R_Ye << COLPAT_EE_SHIFT | \ - IPIPE_COLPTN_Gr_Cy << COLPAT_EO_SHIFT | \ - IPIPE_COLPTN_Gb_G << COLPAT_OE_SHIFT | \ - IPIPE_COLPTN_B_Mg << COLPAT_OO_SHIFT) - -int vpfe_ipipe_register_entities(struct vpfe_ipipe_device *ipipe, - struct v4l2_device *v4l2_dev); -int vpfe_ipipe_init(struct vpfe_ipipe_device *ipipe, - struct platform_device *pdev); -void vpfe_ipipe_unregister_entities(struct vpfe_ipipe_device *ipipe); -void vpfe_ipipe_cleanup(struct vpfe_ipipe_device *ipipe, - struct platform_device *pdev); -void vpfe_ipipe_enable(struct vpfe_device *vpfe_dev, int en); - -#endif /* _DAVINCI_VPFE_DM365_IPIPE_H */ diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.c b/drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.c deleted file mode 100644 index 110473c30577..000000000000 --- a/drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.c +++ /dev/null @@ -1,1038 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2012 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Contributors: - * Manjunath Hadli <manjunath.hadli@ti.com> - * Prabhakar Lad <prabhakar.lad@ti.com> - */ - -#include "dm365_ipipe_hw.h" - -#define IPIPE_MODE_CONTINUOUS 0 -#define IPIPE_MODE_SINGLE_SHOT 1 - -static void ipipe_clock_enable(void __iomem *base_addr) -{ - /* enable IPIPE MMR for register write access */ - regw_ip(base_addr, IPIPE_GCK_MMR_DEFAULT, IPIPE_GCK_MMR); - - /* enable the clock wb,cfa,dfc,d2f,pre modules */ - regw_ip(base_addr, IPIPE_GCK_PIX_DEFAULT, IPIPE_GCK_PIX); -} - -static void -rsz_set_common_params(void __iomem *rsz_base, struct resizer_params *params) -{ - struct rsz_common_params *rsz_common = ¶ms->rsz_common; - u32 val; - - /* Set mode */ - regw_rsz(rsz_base, params->oper_mode, RSZ_SRC_MODE); - - /* data source selection and bypass */ - val = (rsz_common->passthrough << RSZ_BYPASS_SHIFT) | - rsz_common->source; - regw_rsz(rsz_base, val, RSZ_SRC_FMT0); - - /* src image selection */ - val = (rsz_common->raw_flip & 1) | - (rsz_common->src_img_fmt << RSZ_SRC_IMG_FMT_SHIFT) | - ((rsz_common->y_c & 1) << RSZ_SRC_Y_C_SEL_SHIFT); - regw_rsz(rsz_base, val, RSZ_SRC_FMT1); - - regw_rsz(rsz_base, rsz_common->vps & IPIPE_RSZ_VPS_MASK, RSZ_SRC_VPS); - regw_rsz(rsz_base, rsz_common->hps & IPIPE_RSZ_HPS_MASK, RSZ_SRC_HPS); - regw_rsz(rsz_base, rsz_common->vsz & IPIPE_RSZ_VSZ_MASK, RSZ_SRC_VSZ); - regw_rsz(rsz_base, rsz_common->hsz & IPIPE_RSZ_HSZ_MASK, RSZ_SRC_HSZ); - regw_rsz(rsz_base, rsz_common->yuv_y_min, RSZ_YUV_Y_MIN); - regw_rsz(rsz_base, rsz_common->yuv_y_max, RSZ_YUV_Y_MAX); - regw_rsz(rsz_base, rsz_common->yuv_c_min, RSZ_YUV_C_MIN); - regw_rsz(rsz_base, rsz_common->yuv_c_max, RSZ_YUV_C_MAX); - /* chromatic position */ - regw_rsz(rsz_base, rsz_common->out_chr_pos, RSZ_YUV_PHS); -} - -static void -rsz_set_rsz_regs(void __iomem *rsz_base, unsigned int rsz_id, - struct resizer_params *params) -{ - struct resizer_scale_param *rsc_params; - struct rsz_ext_mem_param *ext_mem; - struct resizer_rgb *rgb; - u32 reg_base; - u32 val; - - rsc_params = ¶ms->rsz_rsc_param[rsz_id]; - rgb = ¶ms->rsz2rgb[rsz_id]; - ext_mem = ¶ms->ext_mem_param[rsz_id]; - - if (rsz_id == RSZ_A) { - val = rsc_params->h_flip << RSZA_H_FLIP_SHIFT; - val |= rsc_params->v_flip << RSZA_V_FLIP_SHIFT; - reg_base = RSZ_EN_A; - } else { - val = rsc_params->h_flip << RSZB_H_FLIP_SHIFT; - val |= rsc_params->v_flip << RSZB_V_FLIP_SHIFT; - reg_base = RSZ_EN_B; - } - /* update flip settings */ - regw_rsz(rsz_base, val, RSZ_SEQ); - - regw_rsz(rsz_base, params->oper_mode, reg_base + RSZ_MODE); - - val = (rsc_params->cen << RSZ_CEN_SHIFT) | rsc_params->yen; - regw_rsz(rsz_base, val, reg_base + RSZ_420); - - regw_rsz(rsz_base, rsc_params->i_vps & RSZ_VPS_MASK, - reg_base + RSZ_I_VPS); - regw_rsz(rsz_base, rsc_params->i_hps & RSZ_HPS_MASK, - reg_base + RSZ_I_HPS); - regw_rsz(rsz_base, rsc_params->o_vsz & RSZ_O_VSZ_MASK, - reg_base + RSZ_O_VSZ); - regw_rsz(rsz_base, rsc_params->o_hsz & RSZ_O_HSZ_MASK, - reg_base + RSZ_O_HSZ); - regw_rsz(rsz_base, rsc_params->v_phs_y & RSZ_V_PHS_MASK, - reg_base + RSZ_V_PHS_Y); - regw_rsz(rsz_base, rsc_params->v_phs_c & RSZ_V_PHS_MASK, - reg_base + RSZ_V_PHS_C); - - /* keep this additional adjustment to zero for now */ - regw_rsz(rsz_base, rsc_params->v_dif & RSZ_V_DIF_MASK, - reg_base + RSZ_V_DIF); - - val = (rsc_params->v_typ_y & 1) | - ((rsc_params->v_typ_c & 1) << RSZ_TYP_C_SHIFT); - regw_rsz(rsz_base, val, reg_base + RSZ_V_TYP); - - val = (rsc_params->v_lpf_int_y & RSZ_LPF_INT_MASK) | - ((rsc_params->v_lpf_int_c & RSZ_LPF_INT_MASK) << - RSZ_LPF_INT_C_SHIFT); - regw_rsz(rsz_base, val, reg_base + RSZ_V_LPF); - - regw_rsz(rsz_base, rsc_params->h_phs & - RSZ_H_PHS_MASK, reg_base + RSZ_H_PHS); - - regw_rsz(rsz_base, 0, reg_base + RSZ_H_PHS_ADJ); - regw_rsz(rsz_base, rsc_params->h_dif & - RSZ_H_DIF_MASK, reg_base + RSZ_H_DIF); - - val = (rsc_params->h_typ_y & 1) | - ((rsc_params->h_typ_c & 1) << RSZ_TYP_C_SHIFT); - regw_rsz(rsz_base, val, reg_base + RSZ_H_TYP); - - val = (rsc_params->h_lpf_int_y & RSZ_LPF_INT_MASK) | - ((rsc_params->h_lpf_int_c & RSZ_LPF_INT_MASK) << - RSZ_LPF_INT_C_SHIFT); - regw_rsz(rsz_base, val, reg_base + RSZ_H_LPF); - - regw_rsz(rsz_base, rsc_params->dscale_en & 1, reg_base + RSZ_DWN_EN); - - val = (rsc_params->h_dscale_ave_sz & RSZ_DWN_SCALE_AV_SZ_MASK) | - ((rsc_params->v_dscale_ave_sz & RSZ_DWN_SCALE_AV_SZ_MASK) << - RSZ_DWN_SCALE_AV_SZ_V_SHIFT); - regw_rsz(rsz_base, val, reg_base + RSZ_DWN_AV); - - /* setting rgb conversion parameters */ - regw_rsz(rsz_base, rgb->rgb_en, reg_base + RSZ_RGB_EN); - - val = (rgb->rgb_typ << RSZ_RGB_TYP_SHIFT) | - (rgb->rgb_msk0 << RSZ_RGB_MSK0_SHIFT) | - (rgb->rgb_msk1 << RSZ_RGB_MSK1_SHIFT); - regw_rsz(rsz_base, val, reg_base + RSZ_RGB_TYP); - - regw_rsz(rsz_base, rgb->rgb_alpha_val & RSZ_RGB_ALPHA_MASK, - reg_base + RSZ_RGB_BLD); - - /* setting external memory parameters */ - regw_rsz(rsz_base, ext_mem->rsz_sdr_oft_y, reg_base + RSZ_SDR_Y_OFT); - regw_rsz(rsz_base, ext_mem->rsz_sdr_ptr_s_y, - reg_base + RSZ_SDR_Y_PTR_S); - regw_rsz(rsz_base, ext_mem->rsz_sdr_ptr_e_y, - reg_base + RSZ_SDR_Y_PTR_E); - regw_rsz(rsz_base, ext_mem->rsz_sdr_oft_c, reg_base + RSZ_SDR_C_OFT); - regw_rsz(rsz_base, ext_mem->rsz_sdr_ptr_s_c, - reg_base + RSZ_SDR_C_PTR_S); - regw_rsz(rsz_base, (ext_mem->rsz_sdr_ptr_e_c >> 1), - reg_base + RSZ_SDR_C_PTR_E); -} - -/*set the registers of either RSZ0 or RSZ1 */ -static void -ipipe_setup_resizer(void __iomem *rsz_base, struct resizer_params *params) -{ - /* enable MMR gate to write to Resizer */ - regw_rsz(rsz_base, 1, RSZ_GCK_MMR); - - /* Enable resizer if it is not in bypass mode */ - if (params->rsz_common.passthrough) - regw_rsz(rsz_base, 0, RSZ_GCK_SDR); - else - regw_rsz(rsz_base, 1, RSZ_GCK_SDR); - - rsz_set_common_params(rsz_base, params); - - regw_rsz(rsz_base, params->rsz_en[RSZ_A], RSZ_EN_A); - - if (params->rsz_en[RSZ_A]) - /*setting rescale parameters */ - rsz_set_rsz_regs(rsz_base, RSZ_A, params); - - regw_rsz(rsz_base, params->rsz_en[RSZ_B], RSZ_EN_B); - - if (params->rsz_en[RSZ_B]) - rsz_set_rsz_regs(rsz_base, RSZ_B, params); -} - -static u32 ipipe_get_color_pat(u32 pix) -{ - switch (pix) { - case MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8: - case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8: - case MEDIA_BUS_FMT_SGRBG12_1X12: - return ipipe_sgrbg_pattern; - - default: - return ipipe_srggb_pattern; - } -} - -static int ipipe_get_data_path(struct vpfe_ipipe_device *ipipe) -{ - u32 temp_pix_fmt; - - switch (ipipe->formats[IPIPE_PAD_SINK].code) { - case MEDIA_BUS_FMT_SBGGR8_1X8: - case MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8: - case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8: - case MEDIA_BUS_FMT_SGRBG12_1X12: - temp_pix_fmt = MEDIA_BUS_FMT_SGRBG12_1X12; - break; - - default: - temp_pix_fmt = MEDIA_BUS_FMT_UYVY8_2X8; - } - - if (temp_pix_fmt == MEDIA_BUS_FMT_SGRBG12_1X12) { - if (ipipe->formats[IPIPE_PAD_SOURCE].code == - MEDIA_BUS_FMT_SGRBG12_1X12) - return IPIPE_RAW2RAW; - return IPIPE_RAW2YUV; - } - - return IPIPE_YUV2YUV; -} - -static int get_ipipe_mode(struct vpfe_ipipe_device *ipipe) -{ - struct vpfe_device *vpfe_dev = to_vpfe_device(ipipe); - u16 ipipeif_sink = vpfe_dev->vpfe_ipipeif.input; - - if (ipipeif_sink == IPIPEIF_INPUT_MEMORY) - return IPIPE_MODE_SINGLE_SHOT; - if (ipipeif_sink == IPIPEIF_INPUT_ISIF) - return IPIPE_MODE_CONTINUOUS; - - return -EINVAL; -} - -int config_ipipe_hw(struct vpfe_ipipe_device *ipipe) -{ - struct vpfe_ipipe_input_config *config = &ipipe->config.input_config; - void __iomem *ipipe_base = ipipe->base_addr; - struct v4l2_mbus_framefmt *outformat; - u32 color_pat; - int ipipe_mode; - u32 data_path; - - /* enable clock to IPIPE */ - vpss_enable_clock(VPSS_IPIPE_CLOCK, 1); - ipipe_clock_enable(ipipe_base); - - if (ipipe->input == IPIPE_INPUT_NONE) { - regw_ip(ipipe_base, 0, IPIPE_SRC_EN); - return 0; - } - - ipipe_mode = get_ipipe_mode(ipipe); - if (ipipe_mode < 0) { - pr_err("Failed to get ipipe mode"); - return -EINVAL; - } - regw_ip(ipipe_base, ipipe_mode, IPIPE_SRC_MODE); - - data_path = ipipe_get_data_path(ipipe); - regw_ip(ipipe_base, data_path, IPIPE_SRC_FMT); - - regw_ip(ipipe_base, config->vst & IPIPE_RSZ_VPS_MASK, IPIPE_SRC_VPS); - regw_ip(ipipe_base, config->hst & IPIPE_RSZ_HPS_MASK, IPIPE_SRC_HPS); - - outformat = &ipipe->formats[IPIPE_PAD_SOURCE]; - regw_ip(ipipe_base, (outformat->height + 1) & IPIPE_RSZ_VSZ_MASK, - IPIPE_SRC_VSZ); - regw_ip(ipipe_base, (outformat->width + 1) & IPIPE_RSZ_HSZ_MASK, - IPIPE_SRC_HSZ); - - if (data_path == IPIPE_RAW2YUV || - data_path == IPIPE_RAW2RAW) { - color_pat = - ipipe_get_color_pat(ipipe->formats[IPIPE_PAD_SINK].code); - regw_ip(ipipe_base, color_pat, IPIPE_SRC_COL); - } - - return 0; -} - -/* - * config_rsz_hw() - Performs hardware setup of resizer. - */ -int config_rsz_hw(struct vpfe_resizer_device *resizer, - struct resizer_params *config) -{ - struct vpfe_device *vpfe_dev = to_vpfe_device(resizer); - void __iomem *ipipe_base = vpfe_dev->vpfe_ipipe.base_addr; - void __iomem *rsz_base = vpfe_dev->vpfe_resizer.base_addr; - - /* enable VPSS clock */ - vpss_enable_clock(VPSS_IPIPE_CLOCK, 1); - ipipe_clock_enable(ipipe_base); - - ipipe_setup_resizer(rsz_base, config); - - return 0; -} - -static void -rsz_set_y_address(void __iomem *rsz_base, unsigned int address, - unsigned int offset) -{ - u32 val; - - val = address & SET_LOW_ADDR; - regw_rsz(rsz_base, val, offset + RSZ_SDR_Y_BAD_L); - regw_rsz(rsz_base, val, offset + RSZ_SDR_Y_SAD_L); - - val = (address & SET_HIGH_ADDR) >> 16; - regw_rsz(rsz_base, val, offset + RSZ_SDR_Y_BAD_H); - regw_rsz(rsz_base, val, offset + RSZ_SDR_Y_SAD_H); -} - -static void -rsz_set_c_address(void __iomem *rsz_base, unsigned int address, - unsigned int offset) -{ - u32 val; - - val = address & SET_LOW_ADDR; - regw_rsz(rsz_base, val, offset + RSZ_SDR_C_BAD_L); - regw_rsz(rsz_base, val, offset + RSZ_SDR_C_SAD_L); - - val = (address & SET_HIGH_ADDR) >> 16; - regw_rsz(rsz_base, val, offset + RSZ_SDR_C_BAD_H); - regw_rsz(rsz_base, val, offset + RSZ_SDR_C_SAD_H); -} - -/* - * resizer_set_outaddr() - set the address for given resize_no - * @rsz_base: resizer base address - * @params: pointer to ipipe_params structure - * @resize_no: 0 - Resizer-A, 1 - Resizer B - * @address: the address to set - */ -int -resizer_set_outaddr(void __iomem *rsz_base, struct resizer_params *params, - int resize_no, unsigned int address) -{ - struct resizer_scale_param *rsc_param; - struct rsz_ext_mem_param *mem_param; - struct rsz_common_params *rsz_common; - unsigned int rsz_start_add; - unsigned int val; - - if (resize_no != RSZ_A && resize_no != RSZ_B) - return -EINVAL; - - mem_param = ¶ms->ext_mem_param[resize_no]; - rsc_param = ¶ms->rsz_rsc_param[resize_no]; - rsz_common = ¶ms->rsz_common; - - if (resize_no == RSZ_A) - rsz_start_add = RSZ_EN_A; - else - rsz_start_add = RSZ_EN_B; - - /* y_c = 0 for y, = 1 for c */ - if (rsz_common->src_img_fmt == RSZ_IMG_420) { - if (rsz_common->y_c) { - /* C channel */ - val = address + mem_param->flip_ofst_c; - rsz_set_c_address(rsz_base, val, rsz_start_add); - } else { - val = address + mem_param->flip_ofst_y; - rsz_set_y_address(rsz_base, val, rsz_start_add); - } - } else { - if (rsc_param->cen && rsc_param->yen) { - /* 420 */ - val = address + mem_param->c_offset + - mem_param->flip_ofst_c + - mem_param->user_y_ofst + - mem_param->user_c_ofst; - if (resize_no == RSZ_B) - val += - params->ext_mem_param[RSZ_A].user_y_ofst + - params->ext_mem_param[RSZ_A].user_c_ofst; - /* set C address */ - rsz_set_c_address(rsz_base, val, rsz_start_add); - } - val = address + mem_param->flip_ofst_y + mem_param->user_y_ofst; - if (resize_no == RSZ_B) - val += params->ext_mem_param[RSZ_A].user_y_ofst + - params->ext_mem_param[RSZ_A].user_c_ofst; - /* set Y address */ - rsz_set_y_address(rsz_base, val, rsz_start_add); - } - /* resizer must be enabled */ - regw_rsz(rsz_base, params->rsz_en[resize_no], rsz_start_add); - - return 0; -} - -void -ipipe_set_lutdpc_regs(void __iomem *base_addr, void __iomem *isp5_base_addr, - struct vpfe_ipipe_lutdpc *dpc) -{ - u32 max_tbl_size = LUT_DPC_MAX_SIZE >> 1; - u32 lut_start_addr = DPC_TB0_START_ADDR; - u32 val; - u32 count; - - ipipe_clock_enable(base_addr); - regw_ip(base_addr, dpc->en, DPC_LUT_EN); - - if (dpc->en != 1) - return; - - val = LUTDPC_TBL_256_EN | (dpc->repl_white & 1); - regw_ip(base_addr, val, DPC_LUT_SEL); - regw_ip(base_addr, LUT_DPC_START_ADDR, DPC_LUT_ADR); - regw_ip(base_addr, dpc->dpc_size, DPC_LUT_SIZ & LUT_DPC_SIZE_MASK); - - for (count = 0; count < dpc->dpc_size; count++) { - if (count >= max_tbl_size) - lut_start_addr = DPC_TB1_START_ADDR; - val = (dpc->table[count].horz_pos & LUT_DPC_H_POS_MASK) | - ((dpc->table[count].vert_pos & LUT_DPC_V_POS_MASK) << - LUT_DPC_V_POS_SHIFT) | (dpc->table[count].method << - LUT_DPC_CORR_METH_SHIFT); - w_ip_table(isp5_base_addr, val, (lut_start_addr + - ((count % max_tbl_size) << 2))); - } -} - -static void -set_dpc_thresholds(void __iomem *base_addr, - struct vpfe_ipipe_otfdpc_2_0_cfg *dpc_thr) -{ - regw_ip(base_addr, dpc_thr->corr_thr.r & OTFDPC_DPC2_THR_MASK, - DPC_OTF_2C_THR_R); - regw_ip(base_addr, dpc_thr->corr_thr.gr & OTFDPC_DPC2_THR_MASK, - DPC_OTF_2C_THR_GR); - regw_ip(base_addr, dpc_thr->corr_thr.gb & OTFDPC_DPC2_THR_MASK, - DPC_OTF_2C_THR_GB); - regw_ip(base_addr, dpc_thr->corr_thr.b & OTFDPC_DPC2_THR_MASK, - DPC_OTF_2C_THR_B); - regw_ip(base_addr, dpc_thr->det_thr.r & OTFDPC_DPC2_THR_MASK, - DPC_OTF_2D_THR_R); - regw_ip(base_addr, dpc_thr->det_thr.gr & OTFDPC_DPC2_THR_MASK, - DPC_OTF_2D_THR_GR); - regw_ip(base_addr, dpc_thr->det_thr.gb & OTFDPC_DPC2_THR_MASK, - DPC_OTF_2D_THR_GB); - regw_ip(base_addr, dpc_thr->det_thr.b & OTFDPC_DPC2_THR_MASK, - DPC_OTF_2D_THR_B); -} - -void ipipe_set_otfdpc_regs(void __iomem *base_addr, - struct vpfe_ipipe_otfdpc *otfdpc) -{ - struct vpfe_ipipe_otfdpc_2_0_cfg *dpc_2_0 = &otfdpc->alg_cfg.dpc_2_0; - struct vpfe_ipipe_otfdpc_3_0_cfg *dpc_3_0 = &otfdpc->alg_cfg.dpc_3_0; - u32 val; - - ipipe_clock_enable(base_addr); - - regw_ip(base_addr, (otfdpc->en & 1), DPC_OTF_EN); - if (!otfdpc->en) - return; - - /* dpc enabled */ - val = (otfdpc->det_method << OTF_DET_METHOD_SHIFT) | otfdpc->alg; - regw_ip(base_addr, val, DPC_OTF_TYP); - - if (otfdpc->det_method == VPFE_IPIPE_DPC_OTF_MIN_MAX) { - /* ALG= 0, TYP = 0, DPC_OTF_2D_THR_[x]=0 - * DPC_OTF_2C_THR_[x] = Maximum thresohld - * MinMax method - */ - dpc_2_0->det_thr.r = dpc_2_0->det_thr.gb = - dpc_2_0->det_thr.gr = dpc_2_0->det_thr.b = 0; - set_dpc_thresholds(base_addr, dpc_2_0); - return; - } - /* MinMax2 */ - if (otfdpc->alg == VPFE_IPIPE_OTFDPC_2_0) { - set_dpc_thresholds(base_addr, dpc_2_0); - return; - } - regw_ip(base_addr, dpc_3_0->act_adj_shf & - OTF_DPC3_0_SHF_MASK, DPC_OTF_3_SHF); - /* Detection thresholds */ - regw_ip(base_addr, ((dpc_3_0->det_thr & OTF_DPC3_0_THR_MASK) << - OTF_DPC3_0_THR_SHIFT), DPC_OTF_3D_THR); - regw_ip(base_addr, dpc_3_0->det_slp & - OTF_DPC3_0_SLP_MASK, DPC_OTF_3D_SLP); - regw_ip(base_addr, dpc_3_0->det_thr_min & - OTF_DPC3_0_DET_MASK, DPC_OTF_3D_MIN); - regw_ip(base_addr, dpc_3_0->det_thr_max & - OTF_DPC3_0_DET_MASK, DPC_OTF_3D_MAX); - /* Correction thresholds */ - regw_ip(base_addr, ((dpc_3_0->corr_thr & OTF_DPC3_0_THR_MASK) << - OTF_DPC3_0_THR_SHIFT), DPC_OTF_3C_THR); - regw_ip(base_addr, dpc_3_0->corr_slp & - OTF_DPC3_0_SLP_MASK, DPC_OTF_3C_SLP); - regw_ip(base_addr, dpc_3_0->corr_thr_min & - OTF_DPC3_0_CORR_MASK, DPC_OTF_3C_MIN); - regw_ip(base_addr, dpc_3_0->corr_thr_max & - OTF_DPC3_0_CORR_MASK, DPC_OTF_3C_MAX); -} - -/* 2D Noise filter */ -void -ipipe_set_d2f_regs(void __iomem *base_addr, unsigned int id, - struct vpfe_ipipe_nf *noise_filter) -{ - - u32 offset = D2F_1ST; - int count; - u32 val; - - if (id == IPIPE_D2F_2ND) - offset = D2F_2ND; - - ipipe_clock_enable(base_addr); - regw_ip(base_addr, noise_filter->en & 1, offset + D2F_EN); - if (!noise_filter->en) - return; - - /*noise filter enabled */ - /* Combine all the fields to make D2F_CFG register of IPIPE */ - val = ((noise_filter->spread_val & D2F_SPR_VAL_MASK) << - D2F_SPR_VAL_SHIFT) | ((noise_filter->shft_val & - D2F_SHFT_VAL_MASK) << D2F_SHFT_VAL_SHIFT) | - (noise_filter->gr_sample_meth << D2F_SAMPLE_METH_SHIFT) | - ((noise_filter->apply_lsc_gain & 1) << - D2F_APPLY_LSC_GAIN_SHIFT) | D2F_USE_SPR_REG_VAL; - regw_ip(base_addr, val, offset + D2F_TYP); - - /* edge detection minimum */ - regw_ip(base_addr, noise_filter->edge_det_min_thr & - D2F_EDGE_DET_THR_MASK, offset + D2F_EDG_MIN); - - /* edge detection maximum */ - regw_ip(base_addr, noise_filter->edge_det_max_thr & - D2F_EDGE_DET_THR_MASK, offset + D2F_EDG_MAX); - - for (count = 0; count < VPFE_IPIPE_NF_STR_TABLE_SIZE; count++) - regw_ip(base_addr, - (noise_filter->str[count] & D2F_STR_VAL_MASK), - offset + D2F_STR + count * 4); - - for (count = 0; count < VPFE_IPIPE_NF_THR_TABLE_SIZE; count++) - regw_ip(base_addr, noise_filter->thr[count] & D2F_THR_VAL_MASK, - offset + D2F_THR + count * 4); -} - -#define IPIPE_U8Q5(decimal, integer) \ - (((decimal & 0x1f) | ((integer & 0x7) << 5))) - -/* Green Imbalance Correction */ -void ipipe_set_gic_regs(void __iomem *base_addr, struct vpfe_ipipe_gic *gic) -{ - u32 val; - - ipipe_clock_enable(base_addr); - regw_ip(base_addr, gic->en & 1, GIC_EN); - - if (!gic->en) - return; - - /*gic enabled */ - val = (gic->wt_fn_type << GIC_TYP_SHIFT) | - (gic->thr_sel << GIC_THR_SEL_SHIFT) | - ((gic->apply_lsc_gain & 1) << GIC_APPLY_LSC_GAIN_SHIFT); - regw_ip(base_addr, val, GIC_TYP); - - regw_ip(base_addr, gic->gain & GIC_GAIN_MASK, GIC_GAN); - - if (gic->gic_alg != VPFE_IPIPE_GIC_ALG_ADAPT_GAIN) { - /* Constant Gain. Set threshold to maximum */ - regw_ip(base_addr, GIC_THR_MASK, GIC_THR); - return; - } - - if (gic->thr_sel == VPFE_IPIPE_GIC_THR_REG) { - regw_ip(base_addr, gic->thr & GIC_THR_MASK, GIC_THR); - regw_ip(base_addr, gic->slope & GIC_SLOPE_MASK, GIC_SLP); - } else { - /* Use NF thresholds */ - val = IPIPE_U8Q5(gic->nf2_thr_gain.decimal, - gic->nf2_thr_gain.integer); - regw_ip(base_addr, val, GIC_NFGAN); - } -} - -#define IPIPE_U13Q9(decimal, integer) \ - (((decimal & 0x1ff) | ((integer & 0xf) << 9))) -/* White balance */ -void ipipe_set_wb_regs(void __iomem *base_addr, struct vpfe_ipipe_wb *wb) -{ - u32 val; - - ipipe_clock_enable(base_addr); - /* Ofsets. S12 */ - regw_ip(base_addr, wb->ofst_r & WB_OFFSET_MASK, WB2_OFT_R); - regw_ip(base_addr, wb->ofst_gr & WB_OFFSET_MASK, WB2_OFT_GR); - regw_ip(base_addr, wb->ofst_gb & WB_OFFSET_MASK, WB2_OFT_GB); - regw_ip(base_addr, wb->ofst_b & WB_OFFSET_MASK, WB2_OFT_B); - - /* Gains. U13Q9 */ - val = IPIPE_U13Q9(wb->gain_r.decimal, wb->gain_r.integer); - regw_ip(base_addr, val, WB2_WGN_R); - - val = IPIPE_U13Q9(wb->gain_gr.decimal, wb->gain_gr.integer); - regw_ip(base_addr, val, WB2_WGN_GR); - - val = IPIPE_U13Q9(wb->gain_gb.decimal, wb->gain_gb.integer); - regw_ip(base_addr, val, WB2_WGN_GB); - - val = IPIPE_U13Q9(wb->gain_b.decimal, wb->gain_b.integer); - regw_ip(base_addr, val, WB2_WGN_B); -} - -/* CFA */ -void ipipe_set_cfa_regs(void __iomem *base_addr, struct vpfe_ipipe_cfa *cfa) -{ - ipipe_clock_enable(base_addr); - - regw_ip(base_addr, cfa->alg, CFA_MODE); - regw_ip(base_addr, cfa->hpf_thr_2dir & CFA_HPF_THR_2DIR_MASK, - CFA_2DIR_HPF_THR); - regw_ip(base_addr, cfa->hpf_slp_2dir & CFA_HPF_SLOPE_2DIR_MASK, - CFA_2DIR_HPF_SLP); - regw_ip(base_addr, cfa->hp_mix_thr_2dir & CFA_HPF_MIX_THR_2DIR_MASK, - CFA_2DIR_MIX_THR); - regw_ip(base_addr, cfa->hp_mix_slope_2dir & CFA_HPF_MIX_SLP_2DIR_MASK, - CFA_2DIR_MIX_SLP); - regw_ip(base_addr, cfa->dir_thr_2dir & CFA_DIR_THR_2DIR_MASK, - CFA_2DIR_DIR_THR); - regw_ip(base_addr, cfa->dir_slope_2dir & CFA_DIR_SLP_2DIR_MASK, - CFA_2DIR_DIR_SLP); - regw_ip(base_addr, cfa->nd_wt_2dir & CFA_ND_WT_2DIR_MASK, - CFA_2DIR_NDWT); - regw_ip(base_addr, cfa->hue_fract_daa & CFA_DAA_HUE_FRA_MASK, - CFA_MONO_HUE_FRA); - regw_ip(base_addr, cfa->edge_thr_daa & CFA_DAA_EDG_THR_MASK, - CFA_MONO_EDG_THR); - regw_ip(base_addr, cfa->thr_min_daa & CFA_DAA_THR_MIN_MASK, - CFA_MONO_THR_MIN); - regw_ip(base_addr, cfa->thr_slope_daa & CFA_DAA_THR_SLP_MASK, - CFA_MONO_THR_SLP); - regw_ip(base_addr, cfa->slope_min_daa & CFA_DAA_SLP_MIN_MASK, - CFA_MONO_SLP_MIN); - regw_ip(base_addr, cfa->slope_slope_daa & CFA_DAA_SLP_SLP_MASK, - CFA_MONO_SLP_SLP); - regw_ip(base_addr, cfa->lp_wt_daa & CFA_DAA_LP_WT_MASK, - CFA_MONO_LPWT); -} - -void -ipipe_set_rgb2rgb_regs(void __iomem *base_addr, unsigned int id, - struct vpfe_ipipe_rgb2rgb *rgb) -{ - u32 offset_mask = RGB2RGB_1_OFST_MASK; - u32 offset = RGB1_MUL_BASE; - u32 integ_mask = 0xf; - u32 val; - - ipipe_clock_enable(base_addr); - - if (id == IPIPE_RGB2RGB_2) { - /* - * For second RGB module, gain integer is 3 bits instead - * of 4, offset has 11 bits insread of 13 - */ - offset = RGB2_MUL_BASE; - integ_mask = 0x7; - offset_mask = RGB2RGB_2_OFST_MASK; - } - /* Gains */ - val = (rgb->coef_rr.decimal & 0xff) | - ((rgb->coef_rr.integer & integ_mask) << 8); - regw_ip(base_addr, val, offset + RGB_MUL_RR); - val = (rgb->coef_gr.decimal & 0xff) | - ((rgb->coef_gr.integer & integ_mask) << 8); - regw_ip(base_addr, val, offset + RGB_MUL_GR); - val = (rgb->coef_br.decimal & 0xff) | - ((rgb->coef_br.integer & integ_mask) << 8); - regw_ip(base_addr, val, offset + RGB_MUL_BR); - val = (rgb->coef_rg.decimal & 0xff) | - ((rgb->coef_rg.integer & integ_mask) << 8); - regw_ip(base_addr, val, offset + RGB_MUL_RG); - val = (rgb->coef_gg.decimal & 0xff) | - ((rgb->coef_gg.integer & integ_mask) << 8); - regw_ip(base_addr, val, offset + RGB_MUL_GG); - val = (rgb->coef_bg.decimal & 0xff) | - ((rgb->coef_bg.integer & integ_mask) << 8); - regw_ip(base_addr, val, offset + RGB_MUL_BG); - val = (rgb->coef_rb.decimal & 0xff) | - ((rgb->coef_rb.integer & integ_mask) << 8); - regw_ip(base_addr, val, offset + RGB_MUL_RB); - val = (rgb->coef_gb.decimal & 0xff) | - ((rgb->coef_gb.integer & integ_mask) << 8); - regw_ip(base_addr, val, offset + RGB_MUL_GB); - val = (rgb->coef_bb.decimal & 0xff) | - ((rgb->coef_bb.integer & integ_mask) << 8); - regw_ip(base_addr, val, offset + RGB_MUL_BB); - - /* Offsets */ - regw_ip(base_addr, rgb->out_ofst_r & offset_mask, offset + RGB_OFT_OR); - regw_ip(base_addr, rgb->out_ofst_g & offset_mask, offset + RGB_OFT_OG); - regw_ip(base_addr, rgb->out_ofst_b & offset_mask, offset + RGB_OFT_OB); -} - -static void -ipipe_update_gamma_tbl(void __iomem *isp5_base_addr, - struct vpfe_ipipe_gamma_entry *table, int size, u32 addr) -{ - int count; - u32 val; - - for (count = 0; count < size; count++) { - val = table[count].slope & GAMMA_MASK; - val |= (table[count].offset & GAMMA_MASK) << GAMMA_SHIFT; - w_ip_table(isp5_base_addr, val, (addr + (count * 4))); - } -} - -void -ipipe_set_gamma_regs(void __iomem *base_addr, void __iomem *isp5_base_addr, - struct vpfe_ipipe_gamma *gamma) -{ - int table_size; - u32 val; - - ipipe_clock_enable(base_addr); - val = (gamma->bypass_r << GAMMA_BYPR_SHIFT) | - (gamma->bypass_b << GAMMA_BYPG_SHIFT) | - (gamma->bypass_g << GAMMA_BYPB_SHIFT) | - (gamma->tbl_sel << GAMMA_TBL_SEL_SHIFT) | - (gamma->tbl_size << GAMMA_TBL_SIZE_SHIFT); - - regw_ip(base_addr, val, GMM_CFG); - - if (gamma->tbl_sel != VPFE_IPIPE_GAMMA_TBL_RAM) - return; - - table_size = gamma->tbl_size; - - if (!gamma->bypass_r) - ipipe_update_gamma_tbl(isp5_base_addr, gamma->table_r, - table_size, GAMMA_R_START_ADDR); - if (!gamma->bypass_b) - ipipe_update_gamma_tbl(isp5_base_addr, gamma->table_b, - table_size, GAMMA_B_START_ADDR); - if (!gamma->bypass_g) - ipipe_update_gamma_tbl(isp5_base_addr, gamma->table_g, - table_size, GAMMA_G_START_ADDR); -} - -void -ipipe_set_3d_lut_regs(void __iomem *base_addr, void __iomem *isp5_base_addr, - struct vpfe_ipipe_3d_lut *lut_3d) -{ - struct vpfe_ipipe_3d_lut_entry *tbl; - u32 bnk_index; - u32 tbl_index; - u32 val; - u32 i; - - ipipe_clock_enable(base_addr); - regw_ip(base_addr, lut_3d->en, D3LUT_EN); - - if (!lut_3d->en) - return; - - /* valid table */ - tbl = lut_3d->table; - for (i = 0; i < VPFE_IPIPE_MAX_SIZE_3D_LUT; i++) { - /* - * Each entry has 0-9 (B), 10-19 (G) and - * 20-29 R values - */ - val = tbl[i].b & D3_LUT_ENTRY_MASK; - val |= (tbl[i].g & D3_LUT_ENTRY_MASK) << - D3_LUT_ENTRY_G_SHIFT; - val |= (tbl[i].r & D3_LUT_ENTRY_MASK) << - D3_LUT_ENTRY_R_SHIFT; - bnk_index = i % 4; - tbl_index = i >> 2; - tbl_index <<= 2; - if (bnk_index == 0) - w_ip_table(isp5_base_addr, val, - tbl_index + D3L_TB0_START_ADDR); - else if (bnk_index == 1) - w_ip_table(isp5_base_addr, val, - tbl_index + D3L_TB1_START_ADDR); - else if (bnk_index == 2) - w_ip_table(isp5_base_addr, val, - tbl_index + D3L_TB2_START_ADDR); - else - w_ip_table(isp5_base_addr, val, - tbl_index + D3L_TB3_START_ADDR); - } -} - -/* Lumina adjustments */ -void -ipipe_set_lum_adj_regs(void __iomem *base_addr, struct ipipe_lum_adj *lum_adj) -{ - u32 val; - - ipipe_clock_enable(base_addr); - - /* combine fields of YUV_ADJ to set brightness and contrast */ - val = lum_adj->contrast << LUM_ADJ_CONTR_SHIFT | - lum_adj->brightness << LUM_ADJ_BRIGHT_SHIFT; - regw_ip(base_addr, val, YUV_ADJ); -} - -inline u32 ipipe_s12q8(unsigned short decimal, short integer) -{ - return (decimal & 0xff) | ((integer & 0xf) << 8); -} - -void ipipe_set_rgb2ycbcr_regs(void __iomem *base_addr, - struct vpfe_ipipe_rgb2yuv *yuv) -{ - u32 val; - - /* S10Q8 */ - ipipe_clock_enable(base_addr); - val = ipipe_s12q8(yuv->coef_ry.decimal, yuv->coef_ry.integer); - regw_ip(base_addr, val, YUV_MUL_RY); - val = ipipe_s12q8(yuv->coef_gy.decimal, yuv->coef_gy.integer); - regw_ip(base_addr, val, YUV_MUL_GY); - val = ipipe_s12q8(yuv->coef_by.decimal, yuv->coef_by.integer); - regw_ip(base_addr, val, YUV_MUL_BY); - val = ipipe_s12q8(yuv->coef_rcb.decimal, yuv->coef_rcb.integer); - regw_ip(base_addr, val, YUV_MUL_RCB); - val = ipipe_s12q8(yuv->coef_gcb.decimal, yuv->coef_gcb.integer); - regw_ip(base_addr, val, YUV_MUL_GCB); - val = ipipe_s12q8(yuv->coef_bcb.decimal, yuv->coef_bcb.integer); - regw_ip(base_addr, val, YUV_MUL_BCB); - val = ipipe_s12q8(yuv->coef_rcr.decimal, yuv->coef_rcr.integer); - regw_ip(base_addr, val, YUV_MUL_RCR); - val = ipipe_s12q8(yuv->coef_gcr.decimal, yuv->coef_gcr.integer); - regw_ip(base_addr, val, YUV_MUL_GCR); - val = ipipe_s12q8(yuv->coef_bcr.decimal, yuv->coef_bcr.integer); - regw_ip(base_addr, val, YUV_MUL_BCR); - regw_ip(base_addr, yuv->out_ofst_y & RGB2YCBCR_OFST_MASK, YUV_OFT_Y); - regw_ip(base_addr, yuv->out_ofst_cb & RGB2YCBCR_OFST_MASK, YUV_OFT_CB); - regw_ip(base_addr, yuv->out_ofst_cr & RGB2YCBCR_OFST_MASK, YUV_OFT_CR); -} - -/* YUV 422 conversion */ -void -ipipe_set_yuv422_conv_regs(void __iomem *base_addr, - struct vpfe_ipipe_yuv422_conv *conv) -{ - u32 val; - - ipipe_clock_enable(base_addr); - - /* Combine all the fields to make YUV_PHS register of IPIPE */ - val = (conv->chrom_pos << 0) | (conv->en_chrom_lpf << 1); - regw_ip(base_addr, val, YUV_PHS); -} - -void -ipipe_set_gbce_regs(void __iomem *base_addr, void __iomem *isp5_base_addr, - struct vpfe_ipipe_gbce *gbce) -{ - unsigned int count; - u32 mask = GBCE_Y_VAL_MASK; - - if (gbce->type == VPFE_IPIPE_GBCE_GAIN_TBL) - mask = GBCE_GAIN_VAL_MASK; - - ipipe_clock_enable(base_addr); - regw_ip(base_addr, gbce->en & 1, GBCE_EN); - - if (!gbce->en) - return; - - regw_ip(base_addr, gbce->type, GBCE_TYP); - - for (count = 0; count < VPFE_IPIPE_MAX_SIZE_GBCE_LUT; count += 2) - w_ip_table(isp5_base_addr, ((gbce->table[count + 1] & mask) << - GBCE_ENTRY_SHIFT) | (gbce->table[count] & mask), - ((count/2) << 2) + GBCE_TB_START_ADDR); -} - -void -ipipe_set_ee_regs(void __iomem *base_addr, void __iomem *isp5_base_addr, - struct vpfe_ipipe_yee *ee) -{ - unsigned int count; - u32 val; - - ipipe_clock_enable(base_addr); - regw_ip(base_addr, ee->en, YEE_EN); - - if (!ee->en) - return; - - val = ee->en_halo_red & 1; - val |= ee->merge_meth << YEE_HALO_RED_EN_SHIFT; - regw_ip(base_addr, val, YEE_TYP); - - regw_ip(base_addr, ee->hpf_shft, YEE_SHF); - regw_ip(base_addr, ee->hpf_coef_00 & YEE_COEF_MASK, YEE_MUL_00); - regw_ip(base_addr, ee->hpf_coef_01 & YEE_COEF_MASK, YEE_MUL_01); - regw_ip(base_addr, ee->hpf_coef_02 & YEE_COEF_MASK, YEE_MUL_02); - regw_ip(base_addr, ee->hpf_coef_10 & YEE_COEF_MASK, YEE_MUL_10); - regw_ip(base_addr, ee->hpf_coef_11 & YEE_COEF_MASK, YEE_MUL_11); - regw_ip(base_addr, ee->hpf_coef_12 & YEE_COEF_MASK, YEE_MUL_12); - regw_ip(base_addr, ee->hpf_coef_20 & YEE_COEF_MASK, YEE_MUL_20); - regw_ip(base_addr, ee->hpf_coef_21 & YEE_COEF_MASK, YEE_MUL_21); - regw_ip(base_addr, ee->hpf_coef_22 & YEE_COEF_MASK, YEE_MUL_22); - regw_ip(base_addr, ee->yee_thr & YEE_THR_MASK, YEE_THR); - regw_ip(base_addr, ee->es_gain & YEE_ES_GAIN_MASK, YEE_E_GAN); - regw_ip(base_addr, ee->es_thr1 & YEE_ES_THR1_MASK, YEE_E_THR1); - regw_ip(base_addr, ee->es_thr2 & YEE_THR_MASK, YEE_E_THR2); - regw_ip(base_addr, ee->es_gain_grad & YEE_THR_MASK, YEE_G_GAN); - regw_ip(base_addr, ee->es_ofst_grad & YEE_THR_MASK, YEE_G_OFT); - - for (count = 0; count < VPFE_IPIPE_MAX_SIZE_YEE_LUT; count += 2) - w_ip_table(isp5_base_addr, ((ee->table[count + 1] & - YEE_ENTRY_MASK) << YEE_ENTRY_SHIFT) | - (ee->table[count] & YEE_ENTRY_MASK), - ((count/2) << 2) + YEE_TB_START_ADDR); -} - -/* Chromatic Artifact Correction. CAR */ -static void ipipe_set_mf(void __iomem *base_addr) -{ - /* typ to dynamic switch */ - regw_ip(base_addr, VPFE_IPIPE_CAR_DYN_SWITCH, CAR_TYP); - /* Set SW0 to maximum */ - regw_ip(base_addr, CAR_MF_THR, CAR_SW); -} - -static void -ipipe_set_gain_ctrl(void __iomem *base_addr, struct vpfe_ipipe_car *car) -{ - regw_ip(base_addr, VPFE_IPIPE_CAR_CHR_GAIN_CTRL, CAR_TYP); - regw_ip(base_addr, car->hpf, CAR_HPF_TYP); - regw_ip(base_addr, car->hpf_shft & CAR_HPF_SHIFT_MASK, CAR_HPF_SHF); - regw_ip(base_addr, car->hpf_thr, CAR_HPF_THR); - regw_ip(base_addr, car->gain1.gain, CAR_GN1_GAN); - regw_ip(base_addr, car->gain1.shft & CAR_GAIN1_SHFT_MASK, CAR_GN1_SHF); - regw_ip(base_addr, car->gain1.gain_min & CAR_GAIN_MIN_MASK, - CAR_GN1_MIN); - regw_ip(base_addr, car->gain2.gain, CAR_GN2_GAN); - regw_ip(base_addr, car->gain2.shft & CAR_GAIN2_SHFT_MASK, CAR_GN2_SHF); - regw_ip(base_addr, car->gain2.gain_min & CAR_GAIN_MIN_MASK, - CAR_GN2_MIN); -} - -void ipipe_set_car_regs(void __iomem *base_addr, struct vpfe_ipipe_car *car) -{ - u32 val; - - ipipe_clock_enable(base_addr); - regw_ip(base_addr, car->en, CAR_EN); - - if (!car->en) - return; - - switch (car->meth) { - case VPFE_IPIPE_CAR_MED_FLTR: - ipipe_set_mf(base_addr); - break; - - case VPFE_IPIPE_CAR_CHR_GAIN_CTRL: - ipipe_set_gain_ctrl(base_addr, car); - break; - - default: - /* Dynamic switch between MF and Gain Ctrl. */ - ipipe_set_mf(base_addr); - ipipe_set_gain_ctrl(base_addr, car); - /* Set the threshold for switching between - * the two Here we overwrite the MF SW0 value - */ - regw_ip(base_addr, VPFE_IPIPE_CAR_DYN_SWITCH, CAR_TYP); - val = car->sw1; - val <<= CAR_SW1_SHIFT; - val |= car->sw0; - regw_ip(base_addr, val, CAR_SW); - } -} - -/* Chromatic Gain Suppression */ -void ipipe_set_cgs_regs(void __iomem *base_addr, struct vpfe_ipipe_cgs *cgs) -{ - ipipe_clock_enable(base_addr); - regw_ip(base_addr, cgs->en, CGS_EN); - - if (!cgs->en) - return; - - /* Set the bright side parameters */ - regw_ip(base_addr, cgs->h_thr, CGS_GN1_H_THR); - regw_ip(base_addr, cgs->h_slope, CGS_GN1_H_GAN); - regw_ip(base_addr, cgs->h_shft & CAR_SHIFT_MASK, CGS_GN1_H_SHF); - regw_ip(base_addr, cgs->h_min, CGS_GN1_H_MIN); -} - -void rsz_src_enable(void __iomem *rsz_base, int enable) -{ - regw_rsz(rsz_base, enable, RSZ_SRC_EN); -} - -int rsz_enable(void __iomem *rsz_base, int rsz_id, int enable) -{ - if (rsz_id == RSZ_A) { - regw_rsz(rsz_base, enable, RSZ_EN_A); - /* We always enable RSZ_A. RSZ_B is enable upon request from - * application. So enable RSZ_SRC_EN along with RSZ_A - */ - regw_rsz(rsz_base, enable, RSZ_SRC_EN); - } else if (rsz_id == RSZ_B) { - regw_rsz(rsz_base, enable, RSZ_EN_B); - } else { - BUG(); - } - - return 0; -} diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.h b/drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.h deleted file mode 100644 index 16b6a14b7058..000000000000 --- a/drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.h +++ /dev/null @@ -1,556 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) 2012 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Contributors: - * Manjunath Hadli <manjunath.hadli@ti.com> - * Prabhakar Lad <prabhakar.lad@ti.com> - */ - -#ifndef _DAVINCI_VPFE_DM365_IPIPE_HW_H -#define _DAVINCI_VPFE_DM365_IPIPE_HW_H - -#include "vpfe_mc_capture.h" - -#define SET_LOW_ADDR 0x0000ffff -#define SET_HIGH_ADDR 0xffff0000 - -/* Below are the internal tables */ -#define DPC_TB0_START_ADDR 0x8000 -#define DPC_TB1_START_ADDR 0x8400 - -#define GAMMA_R_START_ADDR 0xa800 -#define GAMMA_G_START_ADDR 0xb000 -#define GAMMA_B_START_ADDR 0xb800 - -/* RAM table addresses for edge enhancement correction*/ -#define YEE_TB_START_ADDR 0x8800 - -/* RAM table address for GBC LUT */ -#define GBCE_TB_START_ADDR 0x9000 - -/* RAM table for 3D NF LUT */ -#define D3L_TB0_START_ADDR 0x9800 -#define D3L_TB1_START_ADDR 0x9c00 -#define D3L_TB2_START_ADDR 0xa000 -#define D3L_TB3_START_ADDR 0xa400 - -/* IPIPE Register Offsets from the base address */ -#define IPIPE_SRC_EN 0x0000 -#define IPIPE_SRC_MODE 0x0004 -#define IPIPE_SRC_FMT 0x0008 -#define IPIPE_SRC_COL 0x000c -#define IPIPE_SRC_VPS 0x0010 -#define IPIPE_SRC_VSZ 0x0014 -#define IPIPE_SRC_HPS 0x0018 -#define IPIPE_SRC_HSZ 0x001c - -#define IPIPE_SEL_SBU 0x0020 - -#define IPIPE_DMA_STA 0x0024 -#define IPIPE_GCK_MMR 0x0028 -#define IPIPE_GCK_PIX 0x002c -#define IPIPE_RESERVED0 0x0030 - -/* Defect Correction */ -#define DPC_LUT_EN 0x0034 -#define DPC_LUT_SEL 0x0038 -#define DPC_LUT_ADR 0x003c -#define DPC_LUT_SIZ 0x0040 -#define DPC_OTF_EN 0x0044 -#define DPC_OTF_TYP 0x0048 -#define DPC_OTF_2D_THR_R 0x004c -#define DPC_OTF_2D_THR_GR 0x0050 -#define DPC_OTF_2D_THR_GB 0x0054 -#define DPC_OTF_2D_THR_B 0x0058 -#define DPC_OTF_2C_THR_R 0x005c -#define DPC_OTF_2C_THR_GR 0x0060 -#define DPC_OTF_2C_THR_GB 0x0064 -#define DPC_OTF_2C_THR_B 0x0068 -#define DPC_OTF_3_SHF 0x006c -#define DPC_OTF_3D_THR 0x0070 -#define DPC_OTF_3D_SLP 0x0074 -#define DPC_OTF_3D_MIN 0x0078 -#define DPC_OTF_3D_MAX 0x007c -#define DPC_OTF_3C_THR 0x0080 -#define DPC_OTF_3C_SLP 0x0084 -#define DPC_OTF_3C_MIN 0x0088 -#define DPC_OTF_3C_MAX 0x008c - -/* Lense Shading Correction */ -#define LSC_VOFT 0x90 -#define LSC_VA2 0x94 -#define LSC_VA1 0x98 -#define LSC_VS 0x9c -#define LSC_HOFT 0xa0 -#define LSC_HA2 0xa4 -#define LSC_HA1 0xa8 -#define LSC_HS 0xac -#define LSC_GAIN_R 0xb0 -#define LSC_GAIN_GR 0xb4 -#define LSC_GAIN_GB 0xb8 -#define LSC_GAIN_B 0xbc -#define LSC_OFT_R 0xc0 -#define LSC_OFT_GR 0xc4 -#define LSC_OFT_GB 0xc8 -#define LSC_OFT_B 0xcc -#define LSC_SHF 0xd0 -#define LSC_MAX 0xd4 - -/* Noise Filter 1. Ofsets from start address given */ -#define D2F_1ST 0xd8 -#define D2F_EN 0x0 -#define D2F_TYP 0x4 -#define D2F_THR 0x8 -#define D2F_STR 0x28 -#define D2F_SPR 0x48 -#define D2F_EDG_MIN 0x68 -#define D2F_EDG_MAX 0x6c - -/* Noise Filter 2 */ -#define D2F_2ND 0x148 - -/* GIC */ -#define GIC_EN 0x1b8 -#define GIC_TYP 0x1bc -#define GIC_GAN 0x1c0 -#define GIC_NFGAN 0x1c4 -#define GIC_THR 0x1c8 -#define GIC_SLP 0x1cc - -/* White Balance */ -#define WB2_OFT_R 0x1d0 -#define WB2_OFT_GR 0x1d4 -#define WB2_OFT_GB 0x1d8 -#define WB2_OFT_B 0x1dc -#define WB2_WGN_R 0x1e0 -#define WB2_WGN_GR 0x1e4 -#define WB2_WGN_GB 0x1e8 -#define WB2_WGN_B 0x1ec - -/* CFA interpolation */ -#define CFA_MODE 0x1f0 -#define CFA_2DIR_HPF_THR 0x1f4 -#define CFA_2DIR_HPF_SLP 0x1f8 -#define CFA_2DIR_MIX_THR 0x1fc -#define CFA_2DIR_MIX_SLP 0x200 -#define CFA_2DIR_DIR_THR 0x204 -#define CFA_2DIR_DIR_SLP 0x208 -#define CFA_2DIR_NDWT 0x20c -#define CFA_MONO_HUE_FRA 0x210 -#define CFA_MONO_EDG_THR 0x214 -#define CFA_MONO_THR_MIN 0x218 -#define CFA_MONO_THR_SLP 0x21c -#define CFA_MONO_SLP_MIN 0x220 -#define CFA_MONO_SLP_SLP 0x224 -#define CFA_MONO_LPWT 0x228 - -/* RGB to RGB conversiona - 1st */ -#define RGB1_MUL_BASE 0x22c -/* Offsets from base */ -#define RGB_MUL_RR 0x0 -#define RGB_MUL_GR 0x4 -#define RGB_MUL_BR 0x8 -#define RGB_MUL_RG 0xc -#define RGB_MUL_GG 0x10 -#define RGB_MUL_BG 0x14 -#define RGB_MUL_RB 0x18 -#define RGB_MUL_GB 0x1c -#define RGB_MUL_BB 0x20 -#define RGB_OFT_OR 0x24 -#define RGB_OFT_OG 0x28 -#define RGB_OFT_OB 0x2c - -/* Gamma */ -#define GMM_CFG 0x25c - -/* RGB to RGB conversiona - 2nd */ -#define RGB2_MUL_BASE 0x260 - -/* 3D LUT */ -#define D3LUT_EN 0x290 - -/* RGB to YUV(YCbCr) conversion */ -#define YUV_ADJ 0x294 -#define YUV_MUL_RY 0x298 -#define YUV_MUL_GY 0x29c -#define YUV_MUL_BY 0x2a0 -#define YUV_MUL_RCB 0x2a4 -#define YUV_MUL_GCB 0x2a8 -#define YUV_MUL_BCB 0x2ac -#define YUV_MUL_RCR 0x2b0 -#define YUV_MUL_GCR 0x2b4 -#define YUV_MUL_BCR 0x2b8 -#define YUV_OFT_Y 0x2bc -#define YUV_OFT_CB 0x2c0 -#define YUV_OFT_CR 0x2c4 -#define YUV_PHS 0x2c8 - -/* Global Brightness and Contrast */ -#define GBCE_EN 0x2cc -#define GBCE_TYP 0x2d0 - -/* Edge Enhancer */ -#define YEE_EN 0x2d4 -#define YEE_TYP 0x2d8 -#define YEE_SHF 0x2dc -#define YEE_MUL_00 0x2e0 -#define YEE_MUL_01 0x2e4 -#define YEE_MUL_02 0x2e8 -#define YEE_MUL_10 0x2ec -#define YEE_MUL_11 0x2f0 -#define YEE_MUL_12 0x2f4 -#define YEE_MUL_20 0x2f8 -#define YEE_MUL_21 0x2fc -#define YEE_MUL_22 0x300 -#define YEE_THR 0x304 -#define YEE_E_GAN 0x308 -#define YEE_E_THR1 0x30c -#define YEE_E_THR2 0x310 -#define YEE_G_GAN 0x314 -#define YEE_G_OFT 0x318 - -/* Chroma Artifact Reduction */ -#define CAR_EN 0x31c -#define CAR_TYP 0x320 -#define CAR_SW 0x324 -#define CAR_HPF_TYP 0x328 -#define CAR_HPF_SHF 0x32c -#define CAR_HPF_THR 0x330 -#define CAR_GN1_GAN 0x334 -#define CAR_GN1_SHF 0x338 -#define CAR_GN1_MIN 0x33c -#define CAR_GN2_GAN 0x340 -#define CAR_GN2_SHF 0x344 -#define CAR_GN2_MIN 0x348 - -/* Chroma Gain Suppression */ -#define CGS_EN 0x34c -#define CGS_GN1_L_THR 0x350 -#define CGS_GN1_L_GAN 0x354 -#define CGS_GN1_L_SHF 0x358 -#define CGS_GN1_L_MIN 0x35c -#define CGS_GN1_H_THR 0x360 -#define CGS_GN1_H_GAN 0x364 -#define CGS_GN1_H_SHF 0x368 -#define CGS_GN1_H_MIN 0x36c -#define CGS_GN2_L_THR 0x370 -#define CGS_GN2_L_GAN 0x374 -#define CGS_GN2_L_SHF 0x378 -#define CGS_GN2_L_MIN 0x37c - -/* Resizer */ -#define RSZ_SRC_EN 0x0 -#define RSZ_SRC_MODE 0x4 -#define RSZ_SRC_FMT0 0x8 -#define RSZ_SRC_FMT1 0xc -#define RSZ_SRC_VPS 0x10 -#define RSZ_SRC_VSZ 0x14 -#define RSZ_SRC_HPS 0x18 -#define RSZ_SRC_HSZ 0x1c -#define RSZ_DMA_RZA 0x20 -#define RSZ_DMA_RZB 0x24 -#define RSZ_DMA_STA 0x28 -#define RSZ_GCK_MMR 0x2c -#define RSZ_RESERVED0 0x30 -#define RSZ_GCK_SDR 0x34 -#define RSZ_IRQ_RZA 0x38 -#define RSZ_IRQ_RZB 0x3c -#define RSZ_YUV_Y_MIN 0x40 -#define RSZ_YUV_Y_MAX 0x44 -#define RSZ_YUV_C_MIN 0x48 -#define RSZ_YUV_C_MAX 0x4c -#define RSZ_YUV_PHS 0x50 -#define RSZ_SEQ 0x54 - -/* Resizer Rescale Parameters */ -#define RSZ_EN_A 0x58 -#define RSZ_EN_B 0xe8 -/* - * offset of the registers to be added with base register of - * either RSZ0 or RSZ1 - */ -#define RSZ_MODE 0x4 -#define RSZ_420 0x8 -#define RSZ_I_VPS 0xc -#define RSZ_I_HPS 0x10 -#define RSZ_O_VSZ 0x14 -#define RSZ_O_HSZ 0x18 -#define RSZ_V_PHS_Y 0x1c -#define RSZ_V_PHS_C 0x20 -#define RSZ_V_DIF 0x24 -#define RSZ_V_TYP 0x28 -#define RSZ_V_LPF 0x2c -#define RSZ_H_PHS 0x30 -#define RSZ_H_PHS_ADJ 0x34 -#define RSZ_H_DIF 0x38 -#define RSZ_H_TYP 0x3c -#define RSZ_H_LPF 0x40 -#define RSZ_DWN_EN 0x44 -#define RSZ_DWN_AV 0x48 - -/* Resizer RGB Conversion Parameters */ -#define RSZ_RGB_EN 0x4c -#define RSZ_RGB_TYP 0x50 -#define RSZ_RGB_BLD 0x54 - -/* Resizer External Memory Parameters */ -#define RSZ_SDR_Y_BAD_H 0x58 -#define RSZ_SDR_Y_BAD_L 0x5c -#define RSZ_SDR_Y_SAD_H 0x60 -#define RSZ_SDR_Y_SAD_L 0x64 -#define RSZ_SDR_Y_OFT 0x68 -#define RSZ_SDR_Y_PTR_S 0x6c -#define RSZ_SDR_Y_PTR_E 0x70 -#define RSZ_SDR_C_BAD_H 0x74 -#define RSZ_SDR_C_BAD_L 0x78 -#define RSZ_SDR_C_SAD_H 0x7c -#define RSZ_SDR_C_SAD_L 0x80 -#define RSZ_SDR_C_OFT 0x84 -#define RSZ_SDR_C_PTR_S 0x88 -#define RSZ_SDR_C_PTR_E 0x8c - -/* Macro for resizer */ -#define RSZ_YUV_Y_MIN 0x40 -#define RSZ_YUV_Y_MAX 0x44 -#define RSZ_YUV_C_MIN 0x48 -#define RSZ_YUV_C_MAX 0x4c - -#define IPIPE_GCK_MMR_DEFAULT 1 -#define IPIPE_GCK_PIX_DEFAULT 0xe -#define RSZ_GCK_MMR_DEFAULT 1 -#define RSZ_GCK_SDR_DEFAULT 1 - -/* LUTDPC */ -#define LUTDPC_TBL_256_EN 0 -#define LUTDPC_INF_TBL_EN 1 -#define LUT_DPC_START_ADDR 0 -#define LUT_DPC_H_POS_MASK 0x1fff -#define LUT_DPC_V_POS_MASK 0x1fff -#define LUT_DPC_V_POS_SHIFT 13 -#define LUT_DPC_CORR_METH_SHIFT 26 -#define LUT_DPC_MAX_SIZE 256 -#define LUT_DPC_SIZE_MASK 0x3ff - -/* OTFDPC */ -#define OTFDPC_DPC2_THR_MASK 0xfff -#define OTF_DET_METHOD_SHIFT 1 -#define OTF_DPC3_0_SHF_MASK 3 -#define OTF_DPC3_0_THR_SHIFT 6 -#define OTF_DPC3_0_THR_MASK 0x3f -#define OTF_DPC3_0_SLP_MASK 0x3f -#define OTF_DPC3_0_DET_MASK 0xfff -#define OTF_DPC3_0_CORR_MASK 0xfff - -/* NF (D2F) */ -#define D2F_SPR_VAL_MASK 0x1f -#define D2F_SPR_VAL_SHIFT 0 -#define D2F_SHFT_VAL_MASK 3 -#define D2F_SHFT_VAL_SHIFT 5 -#define D2F_SAMPLE_METH_SHIFT 7 -#define D2F_APPLY_LSC_GAIN_SHIFT 8 -#define D2F_USE_SPR_REG_VAL 0 -#define D2F_STR_VAL_MASK 0x1f -#define D2F_THR_VAL_MASK 0x3ff -#define D2F_EDGE_DET_THR_MASK 0x7ff - -/* Green Imbalance Correction */ -#define GIC_TYP_SHIFT 0 -#define GIC_THR_SEL_SHIFT 1 -#define GIC_APPLY_LSC_GAIN_SHIFT 2 -#define GIC_GAIN_MASK 0xff -#define GIC_THR_MASK 0xfff -#define GIC_SLOPE_MASK 0xfff -#define GIC_NFGAN_INT_MASK 7 -#define GIC_NFGAN_DECI_MASK 0x1f - -/* WB */ -#define WB_OFFSET_MASK 0xfff -#define WB_GAIN_INT_MASK 0xf -#define WB_GAIN_DECI_MASK 0x1ff - -/* CFA */ -#define CFA_HPF_THR_2DIR_MASK 0x1fff -#define CFA_HPF_SLOPE_2DIR_MASK 0x3ff -#define CFA_HPF_MIX_THR_2DIR_MASK 0x1fff -#define CFA_HPF_MIX_SLP_2DIR_MASK 0x3ff -#define CFA_DIR_THR_2DIR_MASK 0x3ff -#define CFA_DIR_SLP_2DIR_MASK 0x7f -#define CFA_ND_WT_2DIR_MASK 0x3f -#define CFA_DAA_HUE_FRA_MASK 0x3f -#define CFA_DAA_EDG_THR_MASK 0xff -#define CFA_DAA_THR_MIN_MASK 0x3ff -#define CFA_DAA_THR_SLP_MASK 0x3ff -#define CFA_DAA_SLP_MIN_MASK 0x3ff -#define CFA_DAA_SLP_SLP_MASK 0x3ff -#define CFA_DAA_LP_WT_MASK 0x3f - -/* RGB2RGB */ -#define RGB2RGB_1_OFST_MASK 0x1fff -#define RGB2RGB_1_GAIN_INT_MASK 0xf -#define RGB2RGB_GAIN_DECI_MASK 0xff -#define RGB2RGB_2_OFST_MASK 0x7ff -#define RGB2RGB_2_GAIN_INT_MASK 0x7 - -/* Gamma */ -#define GAMMA_BYPR_SHIFT 0 -#define GAMMA_BYPG_SHIFT 1 -#define GAMMA_BYPB_SHIFT 2 -#define GAMMA_TBL_SEL_SHIFT 4 -#define GAMMA_TBL_SIZE_SHIFT 5 -#define GAMMA_MASK 0x3ff -#define GAMMA_SHIFT 10 - -/* 3D LUT */ -#define D3_LUT_ENTRY_MASK 0x3ff -#define D3_LUT_ENTRY_R_SHIFT 20 -#define D3_LUT_ENTRY_G_SHIFT 10 -#define D3_LUT_ENTRY_B_SHIFT 0 - -/* Lumina adj */ -#define LUM_ADJ_CONTR_SHIFT 0 -#define LUM_ADJ_BRIGHT_SHIFT 8 - -/* RGB2YCbCr */ -#define RGB2YCBCR_OFST_MASK 0x7ff -#define RGB2YCBCR_COEF_INT_MASK 0xf -#define RGB2YCBCR_COEF_DECI_MASK 0xff - -/* GBCE */ -#define GBCE_Y_VAL_MASK 0xff -#define GBCE_GAIN_VAL_MASK 0x3ff -#define GBCE_ENTRY_SHIFT 10 - -/* Edge Enhancements */ -#define YEE_HALO_RED_EN_SHIFT 1 -#define YEE_HPF_SHIFT_MASK 0xf -#define YEE_COEF_MASK 0x3ff -#define YEE_THR_MASK 0x3f -#define YEE_ES_GAIN_MASK 0xfff -#define YEE_ES_THR1_MASK 0xfff -#define YEE_ENTRY_SHIFT 9 -#define YEE_ENTRY_MASK 0x1ff - -/* CAR */ -#define CAR_MF_THR 0xff -#define CAR_SW1_SHIFT 8 -#define CAR_GAIN1_SHFT_MASK 7 -#define CAR_GAIN_MIN_MASK 0x1ff -#define CAR_GAIN2_SHFT_MASK 0xf -#define CAR_HPF_SHIFT_MASK 3 - -/* CGS */ -#define CAR_SHIFT_MASK 3 - -/* Resizer */ -#define RSZ_BYPASS_SHIFT 1 -#define RSZ_SRC_IMG_FMT_SHIFT 1 -#define RSZ_SRC_Y_C_SEL_SHIFT 2 -#define IPIPE_RSZ_VPS_MASK 0xffff -#define IPIPE_RSZ_HPS_MASK 0xffff -#define IPIPE_RSZ_VSZ_MASK 0x1fff -#define IPIPE_RSZ_HSZ_MASK 0x1fff -#define RSZ_HPS_MASK 0x1fff -#define RSZ_VPS_MASK 0x1fff -#define RSZ_O_HSZ_MASK 0x1fff -#define RSZ_O_VSZ_MASK 0x1fff -#define RSZ_V_PHS_MASK 0x3fff -#define RSZ_V_DIF_MASK 0x3fff - -#define RSZA_H_FLIP_SHIFT 0 -#define RSZA_V_FLIP_SHIFT 1 -#define RSZB_H_FLIP_SHIFT 2 -#define RSZB_V_FLIP_SHIFT 3 -#define RSZ_A 0 -#define RSZ_B 1 -#define RSZ_CEN_SHIFT 1 -#define RSZ_YEN_SHIFT 0 -#define RSZ_TYP_Y_SHIFT 0 -#define RSZ_TYP_C_SHIFT 1 -#define RSZ_LPF_INT_MASK 0x3f -#define RSZ_LPF_INT_C_SHIFT 6 -#define RSZ_H_PHS_MASK 0x3fff -#define RSZ_H_DIF_MASK 0x3fff -#define RSZ_DIFF_DOWN_THR 256 -#define RSZ_DWN_SCALE_AV_SZ_V_SHIFT 3 -#define RSZ_DWN_SCALE_AV_SZ_MASK 7 -#define RSZ_RGB_MSK1_SHIFT 2 -#define RSZ_RGB_MSK0_SHIFT 1 -#define RSZ_RGB_TYP_SHIFT 0 -#define RSZ_RGB_ALPHA_MASK 0xff - -static inline u32 regr_ip(void __iomem *addr, u32 offset) -{ - return readl(addr + offset); -} - -static inline void regw_ip(void __iomem *addr, u32 val, u32 offset) -{ - writel(val, addr + offset); -} - -static inline u32 w_ip_table(void __iomem *addr, u32 val, u32 offset) -{ - writel(val, addr + offset); - - return val; -} - -static inline u32 regr_rsz(void __iomem *addr, u32 offset) -{ - return readl(addr + offset); -} - -static inline u32 regw_rsz(void __iomem *addr, u32 val, u32 offset) -{ - writel(val, addr + offset); - - return val; -} - -int config_ipipe_hw(struct vpfe_ipipe_device *ipipe); -int resizer_set_outaddr(void __iomem *rsz_base, struct resizer_params *params, - int resize_no, unsigned int address); -int rsz_enable(void __iomem *rsz_base, int rsz_id, int enable); -void rsz_src_enable(void __iomem *rsz_base, int enable); -void rsz_set_in_pix_format(unsigned char y_c); -int config_rsz_hw(struct vpfe_resizer_device *resizer, - struct resizer_params *config); -void ipipe_set_d2f_regs(void __iomem *base_addr, unsigned int id, - struct vpfe_ipipe_nf *noise_filter); -void ipipe_set_rgb2rgb_regs(void __iomem *base_addr, unsigned int id, - struct vpfe_ipipe_rgb2rgb *rgb); -void ipipe_set_yuv422_conv_regs(void __iomem *base_addr, - struct vpfe_ipipe_yuv422_conv *conv); -void ipipe_set_lum_adj_regs(void __iomem *base_addr, - struct ipipe_lum_adj *lum_adj); -void ipipe_set_rgb2ycbcr_regs(void __iomem *base_addr, - struct vpfe_ipipe_rgb2yuv *yuv); -void ipipe_set_lutdpc_regs(void __iomem *base_addr, - void __iomem *isp5_base_addr, struct vpfe_ipipe_lutdpc *lutdpc); -void ipipe_set_otfdpc_regs(void __iomem *base_addr, - struct vpfe_ipipe_otfdpc *otfdpc); -void ipipe_set_3d_lut_regs(void __iomem *base_addr, - void __iomem *isp5_base_addr, struct vpfe_ipipe_3d_lut *lut_3d); -void ipipe_set_gamma_regs(void __iomem *base_addr, - void __iomem *isp5_base_addr, struct vpfe_ipipe_gamma *gamma); -void ipipe_set_ee_regs(void __iomem *base_addr, - void __iomem *isp5_base_addr, struct vpfe_ipipe_yee *ee); -void ipipe_set_gbce_regs(void __iomem *base_addr, - void __iomem *isp5_base_addr, struct vpfe_ipipe_gbce *gbce); -void ipipe_set_gic_regs(void __iomem *base_addr, struct vpfe_ipipe_gic *gic); -void ipipe_set_cfa_regs(void __iomem *base_addr, struct vpfe_ipipe_cfa *cfa); -void ipipe_set_car_regs(void __iomem *base_addr, struct vpfe_ipipe_car *car); -void ipipe_set_cgs_regs(void __iomem *base_addr, struct vpfe_ipipe_cgs *cgs); -void ipipe_set_wb_regs(void __iomem *base_addr, struct vpfe_ipipe_wb *wb); - -#endif /* _DAVINCI_VPFE_DM365_IPIPE_HW_H */ diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c deleted file mode 100644 index 51d4cd1bdb97..000000000000 --- a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c +++ /dev/null @@ -1,1070 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2012 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Contributors: - * Manjunath Hadli <manjunath.hadli@ti.com> - * Prabhakar Lad <prabhakar.lad@ti.com> - */ - -#include "dm365_ipipeif.h" -#include "vpfe_mc_capture.h" - -static const unsigned int ipipeif_input_fmts[] = { - MEDIA_BUS_FMT_UYVY8_2X8, - MEDIA_BUS_FMT_SGRBG12_1X12, - MEDIA_BUS_FMT_Y8_1X8, - MEDIA_BUS_FMT_UV8_1X8, - MEDIA_BUS_FMT_YDYUYDYV8_1X16, - MEDIA_BUS_FMT_SBGGR8_1X8, -}; - -static const unsigned int ipipeif_output_fmts[] = { - MEDIA_BUS_FMT_UYVY8_2X8, - MEDIA_BUS_FMT_SGRBG12_1X12, - MEDIA_BUS_FMT_Y8_1X8, - MEDIA_BUS_FMT_UV8_1X8, - MEDIA_BUS_FMT_YDYUYDYV8_1X16, - MEDIA_BUS_FMT_SBGGR8_1X8, - MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8, - MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8, -}; - -static int -ipipeif_get_pack_mode(u32 in_pix_fmt) -{ - switch (in_pix_fmt) { - case MEDIA_BUS_FMT_SBGGR8_1X8: - case MEDIA_BUS_FMT_Y8_1X8: - case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8: - case MEDIA_BUS_FMT_UV8_1X8: - return IPIPEIF_5_1_PACK_8_BIT; - - case MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8: - return IPIPEIF_5_1_PACK_8_BIT_A_LAW; - - case MEDIA_BUS_FMT_SGRBG12_1X12: - return IPIPEIF_5_1_PACK_16_BIT; - - case MEDIA_BUS_FMT_SBGGR12_1X12: - return IPIPEIF_5_1_PACK_12_BIT; - - default: - return IPIPEIF_5_1_PACK_16_BIT; - } -} - -static inline u32 ipipeif_read(void __iomem *addr, u32 offset) -{ - return readl(addr + offset); -} - -static inline void ipipeif_write(u32 val, void __iomem *addr, u32 offset) -{ - writel(val, addr + offset); -} - -static void ipipeif_config_dpc(void __iomem *addr, struct ipipeif_dpc *dpc) -{ - u32 val = 0; - - if (dpc->en) { - val = (dpc->en & 1) << IPIPEIF_DPC2_EN_SHIFT; - val |= dpc->thr & IPIPEIF_DPC2_THR_MASK; - } - ipipeif_write(val, addr, IPIPEIF_DPC2); -} - -#define IPIPEIF_MODE_CONTINUOUS 0 -#define IPIPEIF_MODE_ONE_SHOT 1 - -static int get_oneshot_mode(enum ipipeif_input_entity input) -{ - if (input == IPIPEIF_INPUT_MEMORY) - return IPIPEIF_MODE_ONE_SHOT; - if (input == IPIPEIF_INPUT_ISIF) - return IPIPEIF_MODE_CONTINUOUS; - - return -EINVAL; -} - -static int -ipipeif_get_cfg_src1(struct vpfe_ipipeif_device *ipipeif) -{ - struct v4l2_mbus_framefmt *informat; - - informat = &ipipeif->formats[IPIPEIF_PAD_SINK]; - if (ipipeif->input == IPIPEIF_INPUT_MEMORY && - (informat->code == MEDIA_BUS_FMT_Y8_1X8 || - informat->code == MEDIA_BUS_FMT_UV8_1X8)) - return IPIPEIF_CCDC; - - return IPIPEIF_SRC1_PARALLEL_PORT; -} - -static int -ipipeif_get_data_shift(struct vpfe_ipipeif_device *ipipeif) -{ - struct v4l2_mbus_framefmt *informat; - - informat = &ipipeif->formats[IPIPEIF_PAD_SINK]; - - switch (informat->code) { - case MEDIA_BUS_FMT_SGRBG12_1X12: - return IPIPEIF_5_1_BITS11_0; - - case MEDIA_BUS_FMT_Y8_1X8: - case MEDIA_BUS_FMT_UV8_1X8: - return IPIPEIF_5_1_BITS11_0; - - default: - return IPIPEIF_5_1_BITS7_0; - } -} - -static enum ipipeif_input_source -ipipeif_get_source(struct vpfe_ipipeif_device *ipipeif) -{ - struct v4l2_mbus_framefmt *informat; - - informat = &ipipeif->formats[IPIPEIF_PAD_SINK]; - if (ipipeif->input == IPIPEIF_INPUT_ISIF) - return IPIPEIF_CCDC; - - if (informat->code == MEDIA_BUS_FMT_UYVY8_2X8) - return IPIPEIF_SDRAM_YUV; - - return IPIPEIF_SDRAM_RAW; -} - -void vpfe_ipipeif_ss_buffer_isr(struct vpfe_ipipeif_device *ipipeif) -{ - struct vpfe_video_device *video_in = &ipipeif->video_in; - - if (ipipeif->input != IPIPEIF_INPUT_MEMORY) - return; - - spin_lock(&video_in->dma_queue_lock); - vpfe_video_process_buffer_complete(video_in); - video_in->state = VPFE_VIDEO_BUFFER_NOT_QUEUED; - vpfe_video_schedule_next_buffer(video_in); - spin_unlock(&video_in->dma_queue_lock); -} - -int vpfe_ipipeif_decimation_enabled(struct vpfe_device *vpfe_dev) -{ - struct vpfe_ipipeif_device *ipipeif = &vpfe_dev->vpfe_ipipeif; - - return ipipeif->config.decimation; -} - -int vpfe_ipipeif_get_rsz(struct vpfe_device *vpfe_dev) -{ - struct vpfe_ipipeif_device *ipipeif = &vpfe_dev->vpfe_ipipeif; - - return ipipeif->config.rsz; -} - -#define RD_DATA_15_2 0x7 - -/* - * ipipeif_hw_setup() - This function sets up IPIPEIF - * @sd: pointer to v4l2 subdev structure - * return -EINVAL or zero on success - */ -static int ipipeif_hw_setup(struct v4l2_subdev *sd) -{ - struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt *informat, *outformat; - struct ipipeif_params params = ipipeif->config; - enum ipipeif_input_source ipipeif_source; - u32 isif_port_if; - void __iomem *ipipeif_base_addr; - unsigned long val; - int data_shift; - int pack_mode; - int source1; - int tmp; - - ipipeif_base_addr = ipipeif->ipipeif_base_addr; - - /* Enable clock to IPIPEIF and IPIPE */ - vpss_enable_clock(VPSS_IPIPEIF_CLOCK, 1); - - informat = &ipipeif->formats[IPIPEIF_PAD_SINK]; - outformat = &ipipeif->formats[IPIPEIF_PAD_SOURCE]; - - /* Combine all the fields to make CFG1 register of IPIPEIF */ - tmp = val = get_oneshot_mode(ipipeif->input); - if (tmp < 0) { - dev_err(&sd->devnode->dev, "ipipeif: links setup required"); - return -EINVAL; - } - val <<= ONESHOT_SHIFT; - - ipipeif_source = ipipeif_get_source(ipipeif); - val |= ipipeif_source << INPSRC_SHIFT; - - val |= params.clock_select << CLKSEL_SHIFT; - val |= params.avg_filter << AVGFILT_SHIFT; - val |= params.decimation << DECIM_SHIFT; - - pack_mode = ipipeif_get_pack_mode(informat->code); - val |= pack_mode << PACK8IN_SHIFT; - - source1 = ipipeif_get_cfg_src1(ipipeif); - val |= source1 << INPSRC1_SHIFT; - - data_shift = ipipeif_get_data_shift(ipipeif); - if (ipipeif_source != IPIPEIF_SDRAM_YUV) - val |= data_shift << DATASFT_SHIFT; - else - val &= ~(RD_DATA_15_2 << DATASFT_SHIFT); - - ipipeif_write(val, ipipeif_base_addr, IPIPEIF_CFG1); - - switch (ipipeif_source) { - case IPIPEIF_CCDC: - ipipeif_write(ipipeif->gain, ipipeif_base_addr, IPIPEIF_GAIN); - break; - - case IPIPEIF_SDRAM_RAW: - case IPIPEIF_CCDC_DARKFM: - ipipeif_write(ipipeif->gain, ipipeif_base_addr, IPIPEIF_GAIN); - /* fall through */ - case IPIPEIF_SDRAM_YUV: - val |= data_shift << DATASFT_SHIFT; - ipipeif_write(params.ppln, ipipeif_base_addr, IPIPEIF_PPLN); - ipipeif_write(params.lpfr, ipipeif_base_addr, IPIPEIF_LPFR); - ipipeif_write(informat->width, ipipeif_base_addr, IPIPEIF_HNUM); - ipipeif_write(informat->height, - ipipeif_base_addr, IPIPEIF_VNUM); - break; - - default: - return -EINVAL; - } - - /*check if decimation is enable or not */ - if (params.decimation) - ipipeif_write(params.rsz, ipipeif_base_addr, IPIPEIF_RSZ); - - /* Setup sync alignment and initial rsz position */ - val = params.if_5_1.align_sync & 1; - val <<= IPIPEIF_INIRSZ_ALNSYNC_SHIFT; - val |= params.if_5_1.rsz_start & IPIPEIF_INIRSZ_MASK; - ipipeif_write(val, ipipeif_base_addr, IPIPEIF_INIRSZ); - isif_port_if = informat->code; - - if (isif_port_if == MEDIA_BUS_FMT_Y8_1X8) - isif_port_if = MEDIA_BUS_FMT_YUYV8_1X16; - else if (isif_port_if == MEDIA_BUS_FMT_UV8_1X8) - isif_port_if = MEDIA_BUS_FMT_SGRBG12_1X12; - - /* Enable DPCM decompression */ - switch (ipipeif_source) { - case IPIPEIF_SDRAM_RAW: - val = 0; - if (outformat->code == MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8) { - val = 1; - val |= (IPIPEIF_DPCM_8BIT_10BIT & 1) << - IPIPEIF_DPCM_BITS_SHIFT; - val |= (ipipeif->dpcm_predictor & 1) << - IPIPEIF_DPCM_PRED_SHIFT; - } - ipipeif_write(val, ipipeif_base_addr, IPIPEIF_DPCM); - - /* set DPC */ - ipipeif_config_dpc(ipipeif_base_addr, ¶ms.if_5_1.dpc); - - ipipeif_write(params.if_5_1.clip, - ipipeif_base_addr, IPIPEIF_OCLIP); - - /* fall through for SDRAM YUV mode */ - /* configure CFG2 */ - val = ipipeif_read(ipipeif_base_addr, IPIPEIF_CFG2); - switch (isif_port_if) { - case MEDIA_BUS_FMT_YUYV8_1X16: - case MEDIA_BUS_FMT_UYVY8_2X8: - case MEDIA_BUS_FMT_Y8_1X8: - clear_bit(IPIPEIF_CFG2_YUV8_SHIFT, &val); - set_bit(IPIPEIF_CFG2_YUV16_SHIFT, &val); - ipipeif_write(val, ipipeif_base_addr, IPIPEIF_CFG2); - break; - - default: - clear_bit(IPIPEIF_CFG2_YUV8_SHIFT, &val); - clear_bit(IPIPEIF_CFG2_YUV16_SHIFT, &val); - ipipeif_write(val, ipipeif_base_addr, IPIPEIF_CFG2); - break; - } - /* fall through */ - - case IPIPEIF_SDRAM_YUV: - /* Set clock divider */ - if (params.clock_select == IPIPEIF_SDRAM_CLK) { - val = ipipeif_read(ipipeif_base_addr, IPIPEIF_CLKDIV); - val |= (params.if_5_1.clk_div.m - 1) << - IPIPEIF_CLKDIV_M_SHIFT; - val |= (params.if_5_1.clk_div.n - 1); - ipipeif_write(val, ipipeif_base_addr, IPIPEIF_CLKDIV); - } - break; - - case IPIPEIF_CCDC: - case IPIPEIF_CCDC_DARKFM: - /* set DPC */ - ipipeif_config_dpc(ipipeif_base_addr, ¶ms.if_5_1.dpc); - - /* Set DF gain & threshold control */ - val = 0; - if (params.if_5_1.df_gain_en) { - val = params.if_5_1.df_gain_thr & - IPIPEIF_DF_GAIN_THR_MASK; - ipipeif_write(val, ipipeif_base_addr, IPIPEIF_DFSGTH); - val = (params.if_5_1.df_gain_en & 1) << - IPIPEIF_DF_GAIN_EN_SHIFT; - val |= params.if_5_1.df_gain & - IPIPEIF_DF_GAIN_MASK; - } - ipipeif_write(val, ipipeif_base_addr, IPIPEIF_DFSGVL); - /* configure CFG2 */ - val = VPFE_PINPOL_POSITIVE << IPIPEIF_CFG2_HDPOL_SHIFT; - val |= VPFE_PINPOL_POSITIVE << IPIPEIF_CFG2_VDPOL_SHIFT; - - switch (isif_port_if) { - case MEDIA_BUS_FMT_YUYV8_1X16: - case MEDIA_BUS_FMT_YUYV10_1X20: - clear_bit(IPIPEIF_CFG2_YUV8_SHIFT, &val); - set_bit(IPIPEIF_CFG2_YUV16_SHIFT, &val); - break; - - case MEDIA_BUS_FMT_YUYV8_2X8: - case MEDIA_BUS_FMT_UYVY8_2X8: - case MEDIA_BUS_FMT_Y8_1X8: - case MEDIA_BUS_FMT_YUYV10_2X10: - set_bit(IPIPEIF_CFG2_YUV8_SHIFT, &val); - set_bit(IPIPEIF_CFG2_YUV16_SHIFT, &val); - val |= IPIPEIF_CBCR_Y << IPIPEIF_CFG2_YUV8P_SHIFT; - break; - - default: - /* Bayer */ - ipipeif_write(params.if_5_1.clip, ipipeif_base_addr, - IPIPEIF_OCLIP); - } - ipipeif_write(val, ipipeif_base_addr, IPIPEIF_CFG2); - break; - - default: - return -EINVAL; - } - - return 0; -} - -static int -ipipeif_set_config(struct v4l2_subdev *sd, struct ipipeif_params *config) -{ - struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); - struct device *dev = ipipeif->subdev.v4l2_dev->dev; - - if (!config) { - dev_err(dev, "Invalid configuration pointer\n"); - return -EINVAL; - } - - ipipeif->config.clock_select = config->clock_select; - ipipeif->config.ppln = config->ppln; - ipipeif->config.lpfr = config->lpfr; - ipipeif->config.rsz = config->rsz; - ipipeif->config.decimation = config->decimation; - if (ipipeif->config.decimation && - (ipipeif->config.rsz < IPIPEIF_RSZ_MIN || - ipipeif->config.rsz > IPIPEIF_RSZ_MAX)) { - dev_err(dev, "rsz range is %d to %d\n", - IPIPEIF_RSZ_MIN, IPIPEIF_RSZ_MAX); - return -EINVAL; - } - - ipipeif->config.avg_filter = config->avg_filter; - - ipipeif->config.if_5_1.df_gain_thr = config->if_5_1.df_gain_thr; - ipipeif->config.if_5_1.df_gain = config->if_5_1.df_gain; - ipipeif->config.if_5_1.df_gain_en = config->if_5_1.df_gain_en; - - ipipeif->config.if_5_1.rsz_start = config->if_5_1.rsz_start; - ipipeif->config.if_5_1.align_sync = config->if_5_1.align_sync; - ipipeif->config.if_5_1.clip = config->if_5_1.clip; - - ipipeif->config.if_5_1.dpc.en = config->if_5_1.dpc.en; - ipipeif->config.if_5_1.dpc.thr = config->if_5_1.dpc.thr; - - ipipeif->config.if_5_1.clk_div.m = config->if_5_1.clk_div.m; - ipipeif->config.if_5_1.clk_div.n = config->if_5_1.clk_div.n; - - return 0; -} - -static int -ipipeif_get_config(struct v4l2_subdev *sd, void *arg) -{ - struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); - struct ipipeif_params *config = arg; - struct device *dev = ipipeif->subdev.v4l2_dev->dev; - - if (!arg) { - dev_err(dev, "Invalid configuration pointer\n"); - return -EINVAL; - } - - config->clock_select = ipipeif->config.clock_select; - config->ppln = ipipeif->config.ppln; - config->lpfr = ipipeif->config.lpfr; - config->rsz = ipipeif->config.rsz; - config->decimation = ipipeif->config.decimation; - config->avg_filter = ipipeif->config.avg_filter; - - config->if_5_1.df_gain_thr = ipipeif->config.if_5_1.df_gain_thr; - config->if_5_1.df_gain = ipipeif->config.if_5_1.df_gain; - config->if_5_1.df_gain_en = ipipeif->config.if_5_1.df_gain_en; - - config->if_5_1.rsz_start = ipipeif->config.if_5_1.rsz_start; - config->if_5_1.align_sync = ipipeif->config.if_5_1.align_sync; - config->if_5_1.clip = ipipeif->config.if_5_1.clip; - - config->if_5_1.dpc.en = ipipeif->config.if_5_1.dpc.en; - config->if_5_1.dpc.thr = ipipeif->config.if_5_1.dpc.thr; - - config->if_5_1.clk_div.m = ipipeif->config.if_5_1.clk_div.m; - config->if_5_1.clk_div.n = ipipeif->config.if_5_1.clk_div.n; - - return 0; -} - -/* - * ipipeif_ioctl() - Handle ipipeif module private ioctl's - * @sd: pointer to v4l2 subdev structure - * @cmd: configuration command - * @arg: configuration argument - */ -static long ipipeif_ioctl(struct v4l2_subdev *sd, - unsigned int cmd, void *arg) -{ - struct ipipeif_params *config = arg; - int ret = -ENOIOCTLCMD; - - switch (cmd) { - case VIDIOC_VPFE_IPIPEIF_S_CONFIG: - ret = ipipeif_set_config(sd, config); - break; - - case VIDIOC_VPFE_IPIPEIF_G_CONFIG: - ret = ipipeif_get_config(sd, arg); - break; - } - return ret; -} - -/* - * ipipeif_s_ctrl() - Handle set control subdev method - * @ctrl: pointer to v4l2 control structure - */ -static int ipipeif_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct vpfe_ipipeif_device *ipipeif = - container_of(ctrl->handler, struct vpfe_ipipeif_device, ctrls); - - switch (ctrl->id) { - case VPFE_CID_DPCM_PREDICTOR: - ipipeif->dpcm_predictor = ctrl->val; - break; - - case V4L2_CID_GAIN: - ipipeif->gain = ctrl->val; - break; - - default: - return -EINVAL; - } - - return 0; -} - -#define ENABLE_IPIPEIF 0x1 - -void vpfe_ipipeif_enable(struct vpfe_device *vpfe_dev) -{ - struct vpfe_ipipeif_device *ipipeif = &vpfe_dev->vpfe_ipipeif; - void __iomem *ipipeif_base_addr = ipipeif->ipipeif_base_addr; - unsigned char val; - - if (ipipeif->input != IPIPEIF_INPUT_MEMORY) - return; - - do { - val = ipipeif_read(ipipeif_base_addr, IPIPEIF_ENABLE); - } while (val & 0x1); - - ipipeif_write(ENABLE_IPIPEIF, ipipeif_base_addr, IPIPEIF_ENABLE); -} - -/* - * ipipeif_set_stream() - Enable/Disable streaming on ipipeif subdev - * @sd: pointer to v4l2 subdev structure - * @enable: 1 == Enable, 0 == Disable - */ -static int ipipeif_set_stream(struct v4l2_subdev *sd, int enable) -{ - struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); - struct vpfe_device *vpfe_dev = to_vpfe_device(ipipeif); - int ret = 0; - - if (!enable) - return ret; - - ret = ipipeif_hw_setup(sd); - if (!ret) - vpfe_ipipeif_enable(vpfe_dev); - - return ret; -} - -/* - * ipipeif_enum_mbus_code() - Handle pixel format enumeration - * @sd: pointer to v4l2 subdev structure - * @cfg: V4L2 subdev pad config - * @code: pointer to v4l2_subdev_mbus_code_enum structure - * return -EINVAL or zero on success - */ -static int ipipeif_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_mbus_code_enum *code) -{ - switch (code->pad) { - case IPIPEIF_PAD_SINK: - if (code->index >= ARRAY_SIZE(ipipeif_input_fmts)) - return -EINVAL; - - code->code = ipipeif_input_fmts[code->index]; - break; - - case IPIPEIF_PAD_SOURCE: - if (code->index >= ARRAY_SIZE(ipipeif_output_fmts)) - return -EINVAL; - - code->code = ipipeif_output_fmts[code->index]; - break; - - default: - return -EINVAL; - } - - return 0; -} - -/* - * ipipeif_get_format() - Handle get format by pads subdev method - * @sd: pointer to v4l2 subdev structure - * @cfg: V4L2 subdev pad config - * @fmt: pointer to v4l2 subdev format structure - */ -static int -ipipeif_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) -{ - struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); - - if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) - fmt->format = ipipeif->formats[fmt->pad]; - else - fmt->format = *(v4l2_subdev_get_try_format(sd, cfg, fmt->pad)); - - return 0; -} - -#define MIN_OUT_WIDTH 32 -#define MIN_OUT_HEIGHT 32 - -/* - * ipipeif_try_format() - Handle try format by pad subdev method - * @ipipeif: VPFE ipipeif device. - * @cfg: V4L2 subdev pad config - * @pad: pad num. - * @fmt: pointer to v4l2 format structure. - * @which : wanted subdev format - */ -static void -ipipeif_try_format(struct vpfe_ipipeif_device *ipipeif, - struct v4l2_subdev_pad_config *cfg, unsigned int pad, - struct v4l2_mbus_framefmt *fmt, - enum v4l2_subdev_format_whence which) -{ - unsigned int max_out_height; - unsigned int max_out_width; - unsigned int i; - - max_out_width = IPIPE_MAX_OUTPUT_WIDTH_A; - max_out_height = IPIPE_MAX_OUTPUT_HEIGHT_A; - - if (pad == IPIPEIF_PAD_SINK) { - for (i = 0; i < ARRAY_SIZE(ipipeif_input_fmts); i++) - if (fmt->code == ipipeif_input_fmts[i]) - break; - - /* If not found, use SBGGR10 as default */ - if (i >= ARRAY_SIZE(ipipeif_input_fmts)) - fmt->code = MEDIA_BUS_FMT_SGRBG12_1X12; - } else if (pad == IPIPEIF_PAD_SOURCE) { - for (i = 0; i < ARRAY_SIZE(ipipeif_output_fmts); i++) - if (fmt->code == ipipeif_output_fmts[i]) - break; - - /* If not found, use UYVY as default */ - if (i >= ARRAY_SIZE(ipipeif_output_fmts)) - fmt->code = MEDIA_BUS_FMT_UYVY8_2X8; - } - - fmt->width = clamp_t(u32, fmt->width, MIN_OUT_HEIGHT, max_out_width); - fmt->height = clamp_t(u32, fmt->height, MIN_OUT_WIDTH, max_out_height); -} - -static int -ipipeif_enum_frame_size(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_frame_size_enum *fse) -{ - struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt format; - - if (fse->index != 0) - return -EINVAL; - - format.code = fse->code; - format.width = 1; - format.height = 1; - ipipeif_try_format(ipipeif, cfg, fse->pad, &format, fse->which); - fse->min_width = format.width; - fse->min_height = format.height; - - if (format.code != fse->code) - return -EINVAL; - - format.code = fse->code; - format.width = -1; - format.height = -1; - ipipeif_try_format(ipipeif, cfg, fse->pad, &format, fse->which); - fse->max_width = format.width; - fse->max_height = format.height; - - return 0; -} - -/* - * __ipipeif_get_format() - helper function for getting ipipeif format - * @ipipeif: pointer to ipipeif private structure. - * @cfg: V4L2 subdev pad config - * @pad: pad number. - * @which: wanted subdev format. - * - */ -static struct v4l2_mbus_framefmt * -__ipipeif_get_format(struct vpfe_ipipeif_device *ipipeif, - struct v4l2_subdev_pad_config *cfg, unsigned int pad, - enum v4l2_subdev_format_whence which) -{ - if (which == V4L2_SUBDEV_FORMAT_TRY) - return v4l2_subdev_get_try_format(&ipipeif->subdev, cfg, pad); - - return &ipipeif->formats[pad]; -} - -/* - * ipipeif_set_format() - Handle set format by pads subdev method - * @sd: pointer to v4l2 subdev structure - * @cfg: V4L2 subdev pad config - * @fmt: pointer to v4l2 subdev format structure - * return -EINVAL or zero on success - */ -static int -ipipeif_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) -{ - struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt *format; - - format = __ipipeif_get_format(ipipeif, cfg, fmt->pad, fmt->which); - if (!format) - return -EINVAL; - - ipipeif_try_format(ipipeif, cfg, fmt->pad, &fmt->format, fmt->which); - *format = fmt->format; - - if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) - return 0; - - if (fmt->pad == IPIPEIF_PAD_SINK && - ipipeif->input != IPIPEIF_INPUT_NONE) - ipipeif->formats[fmt->pad] = fmt->format; - else if (fmt->pad == IPIPEIF_PAD_SOURCE && - ipipeif->output != IPIPEIF_OUTPUT_NONE) - ipipeif->formats[fmt->pad] = fmt->format; - else - return -EINVAL; - - return 0; -} - -static void ipipeif_set_default_config(struct vpfe_ipipeif_device *ipipeif) -{ -#define WIDTH_I 640 -#define HEIGHT_I 480 - - const struct ipipeif_params ipipeif_defaults = { - .clock_select = IPIPEIF_SDRAM_CLK, - .ppln = WIDTH_I + 8, - .lpfr = HEIGHT_I + 10, - .rsz = 16, /* resize ratio 16/rsz */ - .decimation = IPIPEIF_DECIMATION_OFF, - .avg_filter = IPIPEIF_AVG_OFF, - .if_5_1 = { - .clk_div = { - .m = 1, /* clock = sdram clock * (m/n) */ - .n = 6 - }, - .clip = 4095, - }, - }; - memcpy(&ipipeif->config, &ipipeif_defaults, - sizeof(struct ipipeif_params)); -} - -/* - * ipipeif_init_formats() - Initialize formats on all pads - * @sd: VPFE ipipeif V4L2 subdevice - * @fh: V4L2 subdev file handle - * - * Initialize all pad formats with default values. Try formats are initialized - * on the file handle. - */ -static int -ipipeif_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) -{ - struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); - struct v4l2_subdev_format format; - - memset(&format, 0, sizeof(format)); - format.pad = IPIPEIF_PAD_SINK; - format.which = V4L2_SUBDEV_FORMAT_TRY; - format.format.code = MEDIA_BUS_FMT_SGRBG12_1X12; - format.format.width = IPIPE_MAX_OUTPUT_WIDTH_A; - format.format.height = IPIPE_MAX_OUTPUT_HEIGHT_A; - ipipeif_set_format(sd, fh->pad, &format); - - memset(&format, 0, sizeof(format)); - format.pad = IPIPEIF_PAD_SOURCE; - format.which = V4L2_SUBDEV_FORMAT_TRY; - format.format.code = MEDIA_BUS_FMT_UYVY8_2X8; - format.format.width = IPIPE_MAX_OUTPUT_WIDTH_A; - format.format.height = IPIPE_MAX_OUTPUT_HEIGHT_A; - ipipeif_set_format(sd, fh->pad, &format); - - ipipeif_set_default_config(ipipeif); - - return 0; -} - -/* - * ipipeif_video_in_queue() - ipipeif video in queue - * @vpfe_dev: vpfe device pointer - * @addr: buffer address - */ -static int -ipipeif_video_in_queue(struct vpfe_device *vpfe_dev, unsigned long addr) -{ - struct vpfe_ipipeif_device *ipipeif = &vpfe_dev->vpfe_ipipeif; - void __iomem *ipipeif_base_addr = ipipeif->ipipeif_base_addr; - unsigned int adofs; - u32 val; - - if (ipipeif->input != IPIPEIF_INPUT_MEMORY) - return -EINVAL; - - switch (ipipeif->formats[IPIPEIF_PAD_SINK].code) { - case MEDIA_BUS_FMT_Y8_1X8: - case MEDIA_BUS_FMT_UV8_1X8: - case MEDIA_BUS_FMT_YDYUYDYV8_1X16: - adofs = ipipeif->formats[IPIPEIF_PAD_SINK].width; - break; - - default: - adofs = ipipeif->formats[IPIPEIF_PAD_SINK].width << 1; - break; - } - - /* adjust the line len to be a multiple of 32 */ - adofs += 31; - adofs &= ~0x1f; - val = (adofs >> 5) & IPIPEIF_ADOFS_LSB_MASK; - ipipeif_write(val, ipipeif_base_addr, IPIPEIF_ADOFS); - - /* lower sixteen bit */ - val = (addr >> IPIPEIF_ADDRL_SHIFT) & IPIPEIF_ADDRL_MASK; - ipipeif_write(val, ipipeif_base_addr, IPIPEIF_ADDRL); - - /* upper next seven bit */ - val = (addr >> IPIPEIF_ADDRU_SHIFT) & IPIPEIF_ADDRU_MASK; - ipipeif_write(val, ipipeif_base_addr, IPIPEIF_ADDRU); - - return 0; -} - -/* subdev core operations */ -static const struct v4l2_subdev_core_ops ipipeif_v4l2_core_ops = { - .ioctl = ipipeif_ioctl, -}; - -static const struct v4l2_ctrl_ops ipipeif_ctrl_ops = { - .s_ctrl = ipipeif_s_ctrl, -}; - -static const struct v4l2_ctrl_config vpfe_ipipeif_dpcm_pred = { - .ops = &ipipeif_ctrl_ops, - .id = VPFE_CID_DPCM_PREDICTOR, - .name = "DPCM Predictor", - .type = V4L2_CTRL_TYPE_INTEGER, - .min = 0, - .max = 1, - .step = 1, - .def = 0, -}; - -/* subdev file operations */ -static const struct v4l2_subdev_internal_ops ipipeif_v4l2_internal_ops = { - .open = ipipeif_init_formats, -}; - -/* subdev video operations */ -static const struct v4l2_subdev_video_ops ipipeif_v4l2_video_ops = { - .s_stream = ipipeif_set_stream, -}; - -/* subdev pad operations */ -static const struct v4l2_subdev_pad_ops ipipeif_v4l2_pad_ops = { - .enum_mbus_code = ipipeif_enum_mbus_code, - .enum_frame_size = ipipeif_enum_frame_size, - .get_fmt = ipipeif_get_format, - .set_fmt = ipipeif_set_format, -}; - -/* subdev operations */ -static const struct v4l2_subdev_ops ipipeif_v4l2_ops = { - .core = &ipipeif_v4l2_core_ops, - .video = &ipipeif_v4l2_video_ops, - .pad = &ipipeif_v4l2_pad_ops, -}; - -static const struct vpfe_video_operations video_in_ops = { - .queue = ipipeif_video_in_queue, -}; - -static int -ipipeif_link_setup(struct media_entity *entity, const struct media_pad *local, - const struct media_pad *remote, u32 flags) -{ - struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); - struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd); - struct vpfe_device *vpfe = to_vpfe_device(ipipeif); - unsigned int index = local->index; - - /* FIXME: this is actually a hack! */ - if (is_media_entity_v4l2_subdev(remote->entity)) - index |= 2 << 16; - - switch (index) { - case IPIPEIF_PAD_SINK: - /* Single shot mode */ - if (!(flags & MEDIA_LNK_FL_ENABLED)) { - ipipeif->input = IPIPEIF_INPUT_NONE; - break; - } - ipipeif->input = IPIPEIF_INPUT_MEMORY; - break; - - case IPIPEIF_PAD_SINK | 2 << 16: - /* read from isif */ - if (!(flags & MEDIA_LNK_FL_ENABLED)) { - ipipeif->input = IPIPEIF_INPUT_NONE; - break; - } - if (ipipeif->input != IPIPEIF_INPUT_NONE) - return -EBUSY; - - ipipeif->input = IPIPEIF_INPUT_ISIF; - break; - - case IPIPEIF_PAD_SOURCE | 2 << 16: - if (!(flags & MEDIA_LNK_FL_ENABLED)) { - ipipeif->output = IPIPEIF_OUTPUT_NONE; - break; - } - if (remote->entity == &vpfe->vpfe_ipipe.subdev.entity) - /* connencted to ipipe */ - ipipeif->output = IPIPEIF_OUTPUT_IPIPE; - else if (remote->entity == &vpfe->vpfe_resizer.crop_resizer.subdev.entity) - /* connected to resizer */ - ipipeif->output = IPIPEIF_OUTPUT_RESIZER; - else - return -EINVAL; - break; - - default: - return -EINVAL; - } - - return 0; -} - -static const struct media_entity_operations ipipeif_media_ops = { - .link_setup = ipipeif_link_setup, -}; - -/* - * vpfe_ipipeif_unregister_entities() - Unregister entity - * @ipipeif - pointer to ipipeif subdevice structure. - */ -void vpfe_ipipeif_unregister_entities(struct vpfe_ipipeif_device *ipipeif) -{ - /* unregister video device */ - vpfe_video_unregister(&ipipeif->video_in); - - /* unregister subdev */ - v4l2_device_unregister_subdev(&ipipeif->subdev); - /* cleanup entity */ - media_entity_cleanup(&ipipeif->subdev.entity); -} - -int -vpfe_ipipeif_register_entities(struct vpfe_ipipeif_device *ipipeif, - struct v4l2_device *vdev) -{ - struct vpfe_device *vpfe_dev = to_vpfe_device(ipipeif); - unsigned int flags; - int ret; - - /* Register the subdev */ - ret = v4l2_device_register_subdev(vdev, &ipipeif->subdev); - if (ret < 0) - return ret; - - ret = vpfe_video_register(&ipipeif->video_in, vdev); - if (ret) { - pr_err("Failed to register ipipeif video-in device\n"); - goto fail; - } - ipipeif->video_in.vpfe_dev = vpfe_dev; - - flags = 0; - ret = media_create_pad_link(&ipipeif->video_in.video_dev.entity, 0, - &ipipeif->subdev.entity, 0, flags); - if (ret < 0) - goto fail; - - return 0; -fail: - v4l2_device_unregister_subdev(&ipipeif->subdev); - - return ret; -} - -#define IPIPEIF_GAIN_HIGH 0x3ff -#define IPIPEIF_DEFAULT_GAIN 0x200 - -int vpfe_ipipeif_init(struct vpfe_ipipeif_device *ipipeif, - struct platform_device *pdev) -{ - struct v4l2_subdev *sd = &ipipeif->subdev; - struct media_pad *pads = &ipipeif->pads[0]; - struct media_entity *me = &sd->entity; - static resource_size_t res_len; - struct resource *res; - int ret; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 3); - if (!res) - return -ENOENT; - - res_len = resource_size(res); - res = request_mem_region(res->start, res_len, res->name); - if (!res) - return -EBUSY; - - ipipeif->ipipeif_base_addr = ioremap_nocache(res->start, res_len); - if (!ipipeif->ipipeif_base_addr) { - ret = -EBUSY; - goto fail; - } - - v4l2_subdev_init(sd, &ipipeif_v4l2_ops); - - sd->internal_ops = &ipipeif_v4l2_internal_ops; - strscpy(sd->name, "DAVINCI IPIPEIF", sizeof(sd->name)); - sd->grp_id = 1 << 16; /* group ID for davinci subdevs */ - - v4l2_set_subdevdata(sd, ipipeif); - - sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE; - pads[IPIPEIF_PAD_SINK].flags = MEDIA_PAD_FL_SINK; - pads[IPIPEIF_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; - ipipeif->input = IPIPEIF_INPUT_NONE; - ipipeif->output = IPIPEIF_OUTPUT_NONE; - me->ops = &ipipeif_media_ops; - - ret = media_entity_pads_init(me, IPIPEIF_NUM_PADS, pads); - if (ret) - goto fail; - - v4l2_ctrl_handler_init(&ipipeif->ctrls, 2); - v4l2_ctrl_new_std(&ipipeif->ctrls, &ipipeif_ctrl_ops, - V4L2_CID_GAIN, 0, - IPIPEIF_GAIN_HIGH, 1, IPIPEIF_DEFAULT_GAIN); - v4l2_ctrl_new_custom(&ipipeif->ctrls, &vpfe_ipipeif_dpcm_pred, NULL); - v4l2_ctrl_handler_setup(&ipipeif->ctrls); - sd->ctrl_handler = &ipipeif->ctrls; - - ipipeif->video_in.ops = &video_in_ops; - ipipeif->video_in.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - ret = vpfe_video_init(&ipipeif->video_in, "IPIPEIF"); - if (ret) { - pr_err("Failed to init IPIPEIF video-in device\n"); - goto fail; - } - ipipeif_set_default_config(ipipeif); - return 0; -fail: - release_mem_region(res->start, res_len); - return ret; -} - -void -vpfe_ipipeif_cleanup(struct vpfe_ipipeif_device *ipipeif, - struct platform_device *pdev) -{ - struct resource *res; - - v4l2_ctrl_handler_free(&ipipeif->ctrls); - iounmap(ipipeif->ipipeif_base_addr); - res = platform_get_resource(pdev, IORESOURCE_MEM, 3); - if (res) - release_mem_region(res->start, resource_size(res)); - -} diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.h b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.h deleted file mode 100644 index 4d126fc871f3..000000000000 --- a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.h +++ /dev/null @@ -1,228 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) 2012 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Contributors: - * Manjunath Hadli <manjunath.hadli@ti.com> - * Prabhakar Lad <prabhakar.lad@ti.com> - */ - -#ifndef _DAVINCI_VPFE_DM365_IPIPEIF_H -#define _DAVINCI_VPFE_DM365_IPIPEIF_H - -#include <linux/platform_device.h> - -#include <media/davinci/vpss.h> -#include <media/v4l2-ctrls.h> -#include <media/v4l2-subdev.h> - -#include "dm365_ipipeif_user.h" -#include "vpfe_video.h" - -/* IPIPE base specific types */ -enum ipipeif_data_shift { - IPIPEIF_BITS15_2 = 0, - IPIPEIF_BITS14_1 = 1, - IPIPEIF_BITS13_0 = 2, - IPIPEIF_BITS12_0 = 3, - IPIPEIF_BITS11_0 = 4, - IPIPEIF_BITS10_0 = 5, - IPIPEIF_BITS9_0 = 6, -}; - -enum ipipeif_clkdiv { - IPIPEIF_DIVIDE_HALF = 0, - IPIPEIF_DIVIDE_THIRD = 1, - IPIPEIF_DIVIDE_FOURTH = 2, - IPIPEIF_DIVIDE_FIFTH = 3, - IPIPEIF_DIVIDE_SIXTH = 4, - IPIPEIF_DIVIDE_EIGHTH = 5, - IPIPEIF_DIVIDE_SIXTEENTH = 6, - IPIPEIF_DIVIDE_THIRTY = 7, -}; - -enum ipipeif_pack_mode { - IPIPEIF_PACK_16_BIT = 0, - IPIPEIF_PACK_8_BIT = 1, -}; - -enum ipipeif_5_1_pack_mode { - IPIPEIF_5_1_PACK_16_BIT = 0, - IPIPEIF_5_1_PACK_8_BIT = 1, - IPIPEIF_5_1_PACK_8_BIT_A_LAW = 2, - IPIPEIF_5_1_PACK_12_BIT = 3 -}; - -enum ipipeif_input_source { - IPIPEIF_CCDC = 0, - IPIPEIF_SDRAM_RAW = 1, - IPIPEIF_CCDC_DARKFM = 2, - IPIPEIF_SDRAM_YUV = 3, -}; - -enum ipipeif_ialaw { - IPIPEIF_ALAW_OFF = 0, - IPIPEIF_ALAW_ON = 1, -}; - -enum ipipeif_input_src1 { - IPIPEIF_SRC1_PARALLEL_PORT = 0, - IPIPEIF_SRC1_SDRAM_RAW = 1, - IPIPEIF_SRC1_ISIF_DARKFM = 2, - IPIPEIF_SRC1_SDRAM_YUV = 3, -}; - -enum ipipeif_dfs_dir { - IPIPEIF_PORT_MINUS_SDRAM = 0, - IPIPEIF_SDRAM_MINUS_PORT = 1, -}; - -enum ipipeif_chroma_phase { - IPIPEIF_CBCR_Y = 0, - IPIPEIF_Y_CBCR = 1, -}; - -enum ipipeif_dpcm_type { - IPIPEIF_DPCM_8BIT_10BIT = 0, - IPIPEIF_DPCM_8BIT_12BIT = 1, -}; - -/* data shift for IPIPE 5.1 */ -enum ipipeif_5_1_data_shift { - IPIPEIF_5_1_BITS11_0 = 0, - IPIPEIF_5_1_BITS10_0 = 1, - IPIPEIF_5_1_BITS9_0 = 2, - IPIPEIF_5_1_BITS8_0 = 3, - IPIPEIF_5_1_BITS7_0 = 4, - IPIPEIF_5_1_BITS15_4 = 5, -}; - -#define IPIPEIF_PAD_SINK 0 -#define IPIPEIF_PAD_SOURCE 1 - -#define IPIPEIF_NUM_PADS 2 - -enum ipipeif_input_entity { - IPIPEIF_INPUT_NONE = 0, - IPIPEIF_INPUT_ISIF = 1, - IPIPEIF_INPUT_MEMORY = 2, -}; - -enum ipipeif_output_entity { - IPIPEIF_OUTPUT_NONE = 0, - IPIPEIF_OUTPUT_IPIPE = 1, - IPIPEIF_OUTPUT_RESIZER = 2, -}; - -struct vpfe_ipipeif_device { - struct v4l2_subdev subdev; - struct media_pad pads[IPIPEIF_NUM_PADS]; - struct v4l2_mbus_framefmt formats[IPIPEIF_NUM_PADS]; - enum ipipeif_input_entity input; - unsigned int output; - struct vpfe_video_device video_in; - struct v4l2_ctrl_handler ctrls; - void __iomem *ipipeif_base_addr; - struct ipipeif_params config; - int dpcm_predictor; - int gain; -}; - -/* IPIPEIF Register Offsets from the base address */ -#define IPIPEIF_ENABLE 0x00 -#define IPIPEIF_CFG1 0x04 -#define IPIPEIF_PPLN 0x08 -#define IPIPEIF_LPFR 0x0c -#define IPIPEIF_HNUM 0x10 -#define IPIPEIF_VNUM 0x14 -#define IPIPEIF_ADDRU 0x18 -#define IPIPEIF_ADDRL 0x1c -#define IPIPEIF_ADOFS 0x20 -#define IPIPEIF_RSZ 0x24 -#define IPIPEIF_GAIN 0x28 - -/* Below registers are available only on IPIPE 5.1 */ -#define IPIPEIF_DPCM 0x2c -#define IPIPEIF_CFG2 0x30 -#define IPIPEIF_INIRSZ 0x34 -#define IPIPEIF_OCLIP 0x38 -#define IPIPEIF_DTUDF 0x3c -#define IPIPEIF_CLKDIV 0x40 -#define IPIPEIF_DPC1 0x44 -#define IPIPEIF_DPC2 0x48 -#define IPIPEIF_DFSGVL 0x4c -#define IPIPEIF_DFSGTH 0x50 -#define IPIPEIF_RSZ3A 0x54 -#define IPIPEIF_INIRSZ3A 0x58 -#define IPIPEIF_RSZ_MIN 16 -#define IPIPEIF_RSZ_MAX 112 -#define IPIPEIF_RSZ_CONST 16 - -#define IPIPEIF_ADOFS_LSB_MASK 0x1ff -#define IPIPEIF_ADOFS_LSB_SHIFT 5 -#define IPIPEIF_ADOFS_MSB_MASK 0x200 -#define IPIPEIF_ADDRU_MASK 0x7ff -#define IPIPEIF_ADDRL_SHIFT 5 -#define IPIPEIF_ADDRL_MASK 0xffff -#define IPIPEIF_ADDRU_SHIFT 21 -#define IPIPEIF_ADDRMSB_SHIFT 31 -#define IPIPEIF_ADDRMSB_LEFT_SHIFT 10 - -/* CFG1 Masks and shifts */ -#define ONESHOT_SHIFT 0 -#define DECIM_SHIFT 1 -#define INPSRC_SHIFT 2 -#define CLKDIV_SHIFT 4 -#define AVGFILT_SHIFT 7 -#define PACK8IN_SHIFT 8 -#define IALAW_SHIFT 9 -#define CLKSEL_SHIFT 10 -#define DATASFT_SHIFT 11 -#define INPSRC1_SHIFT 14 - -/* DPC2 */ -#define IPIPEIF_DPC2_EN_SHIFT 12 -#define IPIPEIF_DPC2_THR_MASK 0xfff -/* Applicable for IPIPE 5.1 */ -#define IPIPEIF_DF_GAIN_EN_SHIFT 10 -#define IPIPEIF_DF_GAIN_MASK 0x3ff -#define IPIPEIF_DF_GAIN_THR_MASK 0xfff -/* DPCM */ -#define IPIPEIF_DPCM_BITS_SHIFT 2 -#define IPIPEIF_DPCM_PRED_SHIFT 1 -/* CFG2 */ -#define IPIPEIF_CFG2_HDPOL_SHIFT 1 -#define IPIPEIF_CFG2_VDPOL_SHIFT 2 -#define IPIPEIF_CFG2_YUV8_SHIFT 6 -#define IPIPEIF_CFG2_YUV16_SHIFT 3 -#define IPIPEIF_CFG2_YUV8P_SHIFT 7 - -/* INIRSZ */ -#define IPIPEIF_INIRSZ_ALNSYNC_SHIFT 13 -#define IPIPEIF_INIRSZ_MASK 0x1fff - -/* CLKDIV */ -#define IPIPEIF_CLKDIV_M_SHIFT 8 - -void vpfe_ipipeif_enable(struct vpfe_device *vpfe_dev); -void vpfe_ipipeif_ss_buffer_isr(struct vpfe_ipipeif_device *ipipeif); -int vpfe_ipipeif_decimation_enabled(struct vpfe_device *vpfe_dev); -int vpfe_ipipeif_get_rsz(struct vpfe_device *vpfe_dev); -void vpfe_ipipeif_cleanup(struct vpfe_ipipeif_device *ipipeif, - struct platform_device *pdev); -int vpfe_ipipeif_init(struct vpfe_ipipeif_device *ipipeif, - struct platform_device *pdev); -int vpfe_ipipeif_register_entities(struct vpfe_ipipeif_device *ipipeif, - struct v4l2_device *vdev); -void vpfe_ipipeif_unregister_entities(struct vpfe_ipipeif_device *ipipeif); - -#endif /* _DAVINCI_VPFE_DM365_IPIPEIF_H */ diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipeif_user.h b/drivers/staging/media/davinci_vpfe/dm365_ipipeif_user.h deleted file mode 100644 index 046dbdec67d8..000000000000 --- a/drivers/staging/media/davinci_vpfe/dm365_ipipeif_user.h +++ /dev/null @@ -1,90 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) 2012 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Contributors: - * Manjunath Hadli <manjunath.hadli@ti.com> - * Prabhakar Lad <prabhakar.lad@ti.com> - */ - -#ifndef _DAVINCI_VPFE_DM365_IPIPEIF_USER_H -#define _DAVINCI_VPFE_DM365_IPIPEIF_USER_H - -/* clockdiv for IPIPE 5.1 */ -struct ipipeif_5_1_clkdiv { - unsigned char m; - unsigned char n; -}; - -enum ipipeif_decimation { - IPIPEIF_DECIMATION_OFF, - IPIPEIF_DECIMATION_ON -}; - -/* DPC at the if for IPIPE 5.1 */ -struct ipipeif_dpc { - /* 0 - disable, 1 - enable */ - unsigned char en; - /* threshold */ - unsigned short thr; -}; - -enum ipipeif_clock { - IPIPEIF_PIXCEL_CLK, - IPIPEIF_SDRAM_CLK -}; - -enum ipipeif_avg_filter { - IPIPEIF_AVG_OFF, - IPIPEIF_AVG_ON -}; - -struct ipipeif_5_1 { - struct ipipeif_5_1_clkdiv clk_div; - /* Defect pixel correction */ - struct ipipeif_dpc dpc; - /* clipped to this value */ - unsigned short clip; - /* Align HSync and VSync to rsz_start */ - unsigned char align_sync; - /* resizer start position */ - unsigned int rsz_start; - /* DF gain enable */ - unsigned char df_gain_en; - /* DF gain value */ - unsigned short df_gain; - /* DF gain threshold value */ - unsigned short df_gain_thr; -}; - -struct ipipeif_params { - enum ipipeif_clock clock_select; - unsigned int ppln; - unsigned int lpfr; - unsigned char rsz; - enum ipipeif_decimation decimation; - enum ipipeif_avg_filter avg_filter; - /* IPIPE 5.1 */ - struct ipipeif_5_1 if_5_1; -}; - -/* - * Private IOCTL - * VIDIOC_VPFE_IPIPEIF_S_CONFIG: Set IPIEIF configuration - * VIDIOC_VPFE_IPIPEIF_G_CONFIG: Get IPIEIF configuration - */ -#define VIDIOC_VPFE_IPIPEIF_S_CONFIG \ - _IOWR('I', BASE_VIDIOC_PRIVATE + 1, struct ipipeif_params) -#define VIDIOC_VPFE_IPIPEIF_G_CONFIG \ - _IOWR('I', BASE_VIDIOC_PRIVATE + 2, struct ipipeif_params) - -#endif /* _DAVINCI_VPFE_DM365_IPIPEIF_USER_H */ diff --git a/drivers/staging/media/davinci_vpfe/dm365_isif.c b/drivers/staging/media/davinci_vpfe/dm365_isif.c deleted file mode 100644 index 05a997f7aa5d..000000000000 --- a/drivers/staging/media/davinci_vpfe/dm365_isif.c +++ /dev/null @@ -1,2097 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2012 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Contributors: - * Manjunath Hadli <manjunath.hadli@ti.com> - * Prabhakar Lad <prabhakar.lad@ti.com> - */ - -#include <linux/delay.h> -#include "dm365_isif.h" -#include "vpfe_mc_capture.h" - -#define MAX_WIDTH 4096 -#define MAX_HEIGHT 4096 - -static const unsigned int isif_fmts[] = { - MEDIA_BUS_FMT_YUYV8_2X8, - MEDIA_BUS_FMT_UYVY8_2X8, - MEDIA_BUS_FMT_YUYV8_1X16, - MEDIA_BUS_FMT_YUYV10_1X20, - MEDIA_BUS_FMT_SGRBG12_1X12, - MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8, - MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8, -}; - -#define ISIF_COLPTN_R_Ye 0x0 -#define ISIF_COLPTN_Gr_Cy 0x1 -#define ISIF_COLPTN_Gb_G 0x2 -#define ISIF_COLPTN_B_Mg 0x3 - -#define ISIF_CCOLP_CP01_0 0 -#define ISIF_CCOLP_CP03_2 2 -#define ISIF_CCOLP_CP05_4 4 -#define ISIF_CCOLP_CP07_6 6 -#define ISIF_CCOLP_CP11_0 8 -#define ISIF_CCOLP_CP13_2 10 -#define ISIF_CCOLP_CP15_4 12 -#define ISIF_CCOLP_CP17_6 14 - -static const u32 isif_sgrbg_pattern = - ISIF_COLPTN_Gr_Cy << ISIF_CCOLP_CP01_0 | - ISIF_COLPTN_R_Ye << ISIF_CCOLP_CP03_2 | - ISIF_COLPTN_B_Mg << ISIF_CCOLP_CP05_4 | - ISIF_COLPTN_Gb_G << ISIF_CCOLP_CP07_6 | - ISIF_COLPTN_Gr_Cy << ISIF_CCOLP_CP11_0 | - ISIF_COLPTN_R_Ye << ISIF_CCOLP_CP13_2 | - ISIF_COLPTN_B_Mg << ISIF_CCOLP_CP15_4 | - ISIF_COLPTN_Gb_G << ISIF_CCOLP_CP17_6; - -static const u32 isif_srggb_pattern = - ISIF_COLPTN_R_Ye << ISIF_CCOLP_CP01_0 | - ISIF_COLPTN_Gr_Cy << ISIF_CCOLP_CP03_2 | - ISIF_COLPTN_Gb_G << ISIF_CCOLP_CP05_4 | - ISIF_COLPTN_B_Mg << ISIF_CCOLP_CP07_6 | - ISIF_COLPTN_R_Ye << ISIF_CCOLP_CP11_0 | - ISIF_COLPTN_Gr_Cy << ISIF_CCOLP_CP13_2 | - ISIF_COLPTN_Gb_G << ISIF_CCOLP_CP15_4 | - ISIF_COLPTN_B_Mg << ISIF_CCOLP_CP17_6; - -static inline u32 isif_read(void __iomem *base_addr, u32 offset) -{ - return readl(base_addr + offset); -} - -static inline void isif_write(void __iomem *base_addr, u32 val, u32 offset) -{ - writel(val, base_addr + offset); -} - -static inline u32 isif_merge(void __iomem *base_addr, u32 mask, u32 val, - u32 offset) -{ - u32 new_val = (isif_read(base_addr, offset) & ~mask) | (val & mask); - - isif_write(base_addr, new_val, offset); - - return new_val; -} - -static void isif_enable_output_to_sdram(struct vpfe_isif_device *isif, int en) -{ - isif_merge(isif->isif_cfg.base_addr, ISIF_SYNCEN_WEN_MASK, - en << ISIF_SYNCEN_WEN_SHIFT, SYNCEN); -} - -static inline void -isif_regw_lin_tbl(struct vpfe_isif_device *isif, u32 val, u32 offset, int i) -{ - if (!i) - writel(val, isif->isif_cfg.linear_tbl0_addr + offset); - else - writel(val, isif->isif_cfg.linear_tbl1_addr + offset); -} - -static void isif_disable_all_modules(struct vpfe_isif_device *isif) -{ - /* disable BC */ - isif_write(isif->isif_cfg.base_addr, 0, CLAMPCFG); - /* disable vdfc */ - isif_write(isif->isif_cfg.base_addr, 0, DFCCTL); - /* disable CSC */ - isif_write(isif->isif_cfg.base_addr, 0, CSCCTL); - /* disable linearization */ - isif_write(isif->isif_cfg.base_addr, 0, LINCFG0); -} - -static void isif_enable(struct vpfe_isif_device *isif, int en) -{ - if (!en) - /* Before disable isif, disable all ISIF modules */ - isif_disable_all_modules(isif); - - /* - * wait for next VD. Assume lowest scan rate is 12 Hz. So - * 100 msec delay is good enough - */ - msleep(100); - isif_merge(isif->isif_cfg.base_addr, ISIF_SYNCEN_VDHDEN_MASK, - en, SYNCEN); -} - -/* - * ISIF helper functions - */ - -#define DM365_ISIF_MDFS_OFFSET 15 -#define DM365_ISIF_MDFS_MASK 0x1 - -/* get field id in isif hardware */ -enum v4l2_field vpfe_isif_get_fid(struct vpfe_device *vpfe_dev) -{ - struct vpfe_isif_device *isif = &vpfe_dev->vpfe_isif; - u32 field_status; - - field_status = isif_read(isif->isif_cfg.base_addr, MODESET); - return (field_status >> DM365_ISIF_MDFS_OFFSET) & - DM365_ISIF_MDFS_MASK; -} - -static int -isif_set_pixel_format(struct vpfe_isif_device *isif, unsigned int pixfmt) -{ - if (isif->formats[ISIF_PAD_SINK].code == MEDIA_BUS_FMT_SGRBG12_1X12) { - if (pixfmt == V4L2_PIX_FMT_SBGGR16) - isif->isif_cfg.data_pack = ISIF_PACK_16BIT; - else if ((pixfmt == V4L2_PIX_FMT_SGRBG10DPCM8) || - (pixfmt == V4L2_PIX_FMT_SGRBG10ALAW8)) - isif->isif_cfg.data_pack = ISIF_PACK_8BIT; - else - return -EINVAL; - - isif->isif_cfg.bayer.pix_fmt = ISIF_PIXFMT_RAW; - isif->isif_cfg.bayer.v4l2_pix_fmt = pixfmt; - } else { - if (pixfmt == V4L2_PIX_FMT_YUYV) - isif->isif_cfg.ycbcr.pix_order = ISIF_PIXORDER_YCBYCR; - else if (pixfmt == V4L2_PIX_FMT_UYVY) - isif->isif_cfg.ycbcr.pix_order = ISIF_PIXORDER_CBYCRY; - else - return -EINVAL; - - isif->isif_cfg.data_pack = ISIF_PACK_8BIT; - isif->isif_cfg.ycbcr.v4l2_pix_fmt = pixfmt; - } - - return 0; -} - -static int -isif_set_frame_format(struct vpfe_isif_device *isif, - enum isif_frmfmt frm_fmt) -{ - if (isif->formats[ISIF_PAD_SINK].code == MEDIA_BUS_FMT_SGRBG12_1X12) - isif->isif_cfg.bayer.frm_fmt = frm_fmt; - else - isif->isif_cfg.ycbcr.frm_fmt = frm_fmt; - - return 0; -} - -static int isif_set_image_window(struct vpfe_isif_device *isif) -{ - struct v4l2_rect *win = &isif->crop; - - if (isif->formats[ISIF_PAD_SINK].code == MEDIA_BUS_FMT_SGRBG12_1X12) { - isif->isif_cfg.bayer.win.top = win->top; - isif->isif_cfg.bayer.win.left = win->left; - isif->isif_cfg.bayer.win.width = win->width; - isif->isif_cfg.bayer.win.height = win->height; - return 0; - } - isif->isif_cfg.ycbcr.win.top = win->top; - isif->isif_cfg.ycbcr.win.left = win->left; - isif->isif_cfg.ycbcr.win.width = win->width; - isif->isif_cfg.ycbcr.win.height = win->height; - - return 0; -} - -static int -isif_set_buftype(struct vpfe_isif_device *isif, enum isif_buftype buf_type) -{ - if (isif->formats[ISIF_PAD_SINK].code == MEDIA_BUS_FMT_SGRBG12_1X12) - isif->isif_cfg.bayer.buf_type = buf_type; - else - isif->isif_cfg.ycbcr.buf_type = buf_type; - - return 0; -} - -/* configure format in isif hardware */ -static int -isif_config_format(struct vpfe_device *vpfe_dev, unsigned int pad) -{ - struct vpfe_isif_device *vpfe_isif = &vpfe_dev->vpfe_isif; - enum isif_frmfmt frm_fmt = ISIF_FRMFMT_INTERLACED; - struct v4l2_pix_format format; - int ret = 0; - - v4l2_fill_pix_format(&format, &vpfe_dev->vpfe_isif.formats[pad]); - mbus_to_pix(&vpfe_dev->vpfe_isif.formats[pad], &format); - - if (isif_set_pixel_format(vpfe_isif, format.pixelformat) < 0) { - v4l2_err(&vpfe_dev->v4l2_dev, - "Failed to set pixel format in isif\n"); - return -EINVAL; - } - - /* call for s_crop will override these values */ - vpfe_isif->crop.left = 0; - vpfe_isif->crop.top = 0; - vpfe_isif->crop.width = format.width; - vpfe_isif->crop.height = format.height; - - /* configure the image window */ - isif_set_image_window(vpfe_isif); - - switch (vpfe_dev->vpfe_isif.formats[pad].field) { - case V4L2_FIELD_INTERLACED: - /* do nothing, since it is default */ - ret = isif_set_buftype(vpfe_isif, ISIF_BUFTYPE_FLD_INTERLEAVED); - break; - - case V4L2_FIELD_NONE: - frm_fmt = ISIF_FRMFMT_PROGRESSIVE; - /* buffer type only applicable for interlaced scan */ - break; - - case V4L2_FIELD_SEQ_TB: - ret = isif_set_buftype(vpfe_isif, ISIF_BUFTYPE_FLD_SEPARATED); - break; - - default: - return -EINVAL; - } - - /* set the frame format */ - if (!ret) - ret = isif_set_frame_format(vpfe_isif, frm_fmt); - - return ret; -} - -/* - * isif_try_format() - Try video format on a pad - * @isif: VPFE isif device - * @cfg: V4L2 subdev pad config - * @fmt: pointer to v4l2 subdev format structure - */ -static void -isif_try_format(struct vpfe_isif_device *isif, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) -{ - unsigned int width = fmt->format.width; - unsigned int height = fmt->format.height; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(isif_fmts); i++) { - if (fmt->format.code == isif_fmts[i]) - break; - } - - /* If not found, use YUYV8_2x8 as default */ - if (i >= ARRAY_SIZE(isif_fmts)) - fmt->format.code = MEDIA_BUS_FMT_YUYV8_2X8; - - /* Clamp the size. */ - fmt->format.width = clamp_t(u32, width, 32, MAX_WIDTH); - fmt->format.height = clamp_t(u32, height, 32, MAX_HEIGHT); - - /* The data formatter truncates the number of horizontal output - * pixels to a multiple of 16. To avoid clipping data, allow - * callers to request an output size bigger than the input size - * up to the nearest multiple of 16. - */ - if (fmt->pad == ISIF_PAD_SOURCE) - fmt->format.width &= ~15; -} - -/* - * vpfe_isif_buffer_isr() - isif module non-progressive buffer scheduling isr - * @isif: Pointer to isif subdevice. - */ -void vpfe_isif_buffer_isr(struct vpfe_isif_device *isif) -{ - struct vpfe_device *vpfe_dev = to_vpfe_device(isif); - struct vpfe_video_device *video = &isif->video_out; - enum v4l2_field field; - int fid; - - if (!video->started) - return; - - field = video->fmt.fmt.pix.field; - - if (field == V4L2_FIELD_NONE) { - /* handle progressive frame capture */ - if (video->cur_frm != video->next_frm) - vpfe_video_process_buffer_complete(video); - return; - } - - /* interlaced or TB capture check which field we - * are in hardware - */ - fid = vpfe_isif_get_fid(vpfe_dev); - - /* switch the software maintained field id */ - video->field_id ^= 1; - if (fid == video->field_id) { - /* we are in-sync here,continue */ - if (fid == 0) { - /* - * One frame is just being captured. If the - * next frame is available, release the current - * frame and move on - */ - if (video->cur_frm != video->next_frm) - vpfe_video_process_buffer_complete(video); - /* - * based on whether the two fields are stored - * interleavely or separately in memory, - * reconfigure the ISIF memory address - */ - if (field == V4L2_FIELD_SEQ_TB) - vpfe_video_schedule_bottom_field(video); - return; - } - /* - * if one field is just being captured configure - * the next frame get the next frame from the - * empty queue if no frame is available hold on - * to the current buffer - */ - spin_lock(&video->dma_queue_lock); - if (!list_empty(&video->dma_queue) && - video->cur_frm == video->next_frm) - vpfe_video_schedule_next_buffer(video); - spin_unlock(&video->dma_queue_lock); - } else if (fid == 0) { - /* - * out of sync. Recover from any hardware out-of-sync. - * May loose one frame - */ - video->field_id = fid; - } -} - -/* - * vpfe_isif_vidint1_isr() - ISIF module progressive buffer scheduling isr - * @isif: Pointer to isif subdevice. - */ -void vpfe_isif_vidint1_isr(struct vpfe_isif_device *isif) -{ - struct vpfe_video_device *video = &isif->video_out; - - if (!video->started) - return; - - spin_lock(&video->dma_queue_lock); - if (video->fmt.fmt.pix.field == V4L2_FIELD_NONE && - !list_empty(&video->dma_queue) && video->cur_frm == video->next_frm) - vpfe_video_schedule_next_buffer(video); - - spin_unlock(&video->dma_queue_lock); -} - -/* - * VPFE video operations - */ - -static int isif_video_queue(struct vpfe_device *vpfe_dev, unsigned long addr) -{ - struct vpfe_isif_device *isif = &vpfe_dev->vpfe_isif; - - isif_write(isif->isif_cfg.base_addr, (addr >> 21) & - ISIF_CADU_BITS, CADU); - isif_write(isif->isif_cfg.base_addr, (addr >> 5) & - ISIF_CADL_BITS, CADL); - - return 0; -} - -static const struct vpfe_video_operations isif_video_ops = { - .queue = isif_video_queue, -}; - -/* - * V4L2 subdev operations - */ - -/* Parameter operations */ -static int isif_get_params(struct v4l2_subdev *sd, void *params) -{ - struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd); - - /* only raw module parameters can be set through the IOCTL */ - if (isif->formats[ISIF_PAD_SINK].code != MEDIA_BUS_FMT_SGRBG12_1X12) - return -EINVAL; - memcpy(params, &isif->isif_cfg.bayer.config_params, - sizeof(isif->isif_cfg.bayer.config_params)); - return 0; -} - -static int isif_validate_df_csc_params(const struct vpfe_isif_df_csc *df_csc) -{ - const struct vpfe_isif_color_space_conv *csc; - int err = -EINVAL; - int i; - - if (!df_csc->df_or_csc) { - /* csc configuration */ - csc = &df_csc->csc; - if (csc->en) { - for (i = 0; i < VPFE_ISIF_CSC_NUM_COEFF; i++) - if (csc->coeff[i].integer > - ISIF_CSC_COEF_INTEG_MASK || - csc->coeff[i].decimal > - ISIF_CSC_COEF_DECIMAL_MASK) { - pr_err("Invalid CSC coefficients\n"); - return err; - } - } - } - if (df_csc->start_pix > ISIF_DF_CSC_SPH_MASK) { - pr_err("Invalid df_csc start pix value\n"); - return err; - } - - if (df_csc->num_pixels > ISIF_DF_NUMPIX) { - pr_err("Invalid df_csc num pixels value\n"); - return err; - } - - if (df_csc->start_line > ISIF_DF_CSC_LNH_MASK) { - pr_err("Invalid df_csc start_line value\n"); - return err; - } - - if (df_csc->num_lines > ISIF_DF_NUMLINES) { - pr_err("Invalid df_csc num_lines value\n"); - return err; - } - - return 0; -} - -#define DM365_ISIF_MAX_VDFLSFT 4 -#define DM365_ISIF_MAX_VDFSLV 4095 -#define DM365_ISIF_MAX_DFCMEM0 0x1fff -#define DM365_ISIF_MAX_DFCMEM1 0x1fff - -static int isif_validate_dfc_params(const struct vpfe_isif_dfc *dfc) -{ - int err = -EINVAL; - int i; - - if (!dfc->en) - return 0; - - if (dfc->corr_whole_line > 1) { - pr_err("Invalid corr_whole_line value\n"); - return err; - } - - if (dfc->def_level_shift > DM365_ISIF_MAX_VDFLSFT) { - pr_err("Invalid def_level_shift value\n"); - return err; - } - - if (dfc->def_sat_level > DM365_ISIF_MAX_VDFSLV) { - pr_err("Invalid def_sat_level value\n"); - return err; - } - - if (!dfc->num_vdefects || - dfc->num_vdefects > VPFE_ISIF_VDFC_TABLE_SIZE) { - pr_err("Invalid num_vdefects value\n"); - return err; - } - - for (i = 0; i < VPFE_ISIF_VDFC_TABLE_SIZE; i++) { - if (dfc->table[i].pos_vert > DM365_ISIF_MAX_DFCMEM0) { - pr_err("Invalid pos_vert value\n"); - return err; - } - if (dfc->table[i].pos_horz > DM365_ISIF_MAX_DFCMEM1) { - pr_err("Invalid pos_horz value\n"); - return err; - } - } - - return 0; -} - -#define DM365_ISIF_MAX_CLVRV 0xfff -#define DM365_ISIF_MAX_CLDC 0x1fff -#define DM365_ISIF_MAX_CLHSH 0x1fff -#define DM365_ISIF_MAX_CLHSV 0x1fff -#define DM365_ISIF_MAX_CLVSH 0x1fff -#define DM365_ISIF_MAX_CLVSV 0x1fff -#define DM365_ISIF_MAX_HEIGHT_BLACK_REGION 0x1fff - -static int isif_validate_bclamp_params(const struct vpfe_isif_black_clamp *bclamp) -{ - int err = -EINVAL; - - if (bclamp->dc_offset > DM365_ISIF_MAX_CLDC) { - pr_err("Invalid bclamp dc_offset value\n"); - return err; - } - if (!bclamp->en) - return 0; - if (bclamp->horz.clamp_pix_limit > 1) { - pr_err("Invalid bclamp horz clamp_pix_limit value\n"); - return err; - } - if (bclamp->horz.win_count_calc < 1 || - bclamp->horz.win_count_calc > 32) { - pr_err("Invalid bclamp horz win_count_calc value\n"); - return err; - } - if (bclamp->horz.win_start_h_calc > DM365_ISIF_MAX_CLHSH) { - pr_err("Invalid bclamp win_start_v_calc value\n"); - return err; - } - - if (bclamp->horz.win_start_v_calc > DM365_ISIF_MAX_CLHSV) { - pr_err("Invalid bclamp win_start_v_calc value\n"); - return err; - } - if (bclamp->vert.reset_clamp_val > DM365_ISIF_MAX_CLVRV) { - pr_err("Invalid bclamp reset_clamp_val value\n"); - return err; - } - if (bclamp->vert.ob_v_sz_calc > DM365_ISIF_MAX_HEIGHT_BLACK_REGION) { - pr_err("Invalid bclamp ob_v_sz_calc value\n"); - return err; - } - if (bclamp->vert.ob_start_h > DM365_ISIF_MAX_CLVSH) { - pr_err("Invalid bclamp ob_start_h value\n"); - return err; - } - if (bclamp->vert.ob_start_v > DM365_ISIF_MAX_CLVSV) { - pr_err("Invalid bclamp ob_start_h value\n"); - return err; - } - return 0; -} - -static int -isif_validate_raw_params(const struct vpfe_isif_raw_config *params) -{ - int ret; - - ret = isif_validate_df_csc_params(¶ms->df_csc); - if (ret) - return ret; - ret = isif_validate_dfc_params(¶ms->dfc); - if (ret) - return ret; - return isif_validate_bclamp_params(¶ms->bclamp); -} - -static int isif_set_params(struct v4l2_subdev *sd, const struct vpfe_isif_raw_config *params) -{ - struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd); - int ret = -EINVAL; - - /* only raw module parameters can be set through the IOCTL */ - if (isif->formats[ISIF_PAD_SINK].code != MEDIA_BUS_FMT_SGRBG12_1X12) - return ret; - - if (!isif_validate_raw_params(params)) { - memcpy(&isif->isif_cfg.bayer.config_params, params, - sizeof(*params)); - ret = 0; - } - return ret; -} -/* - * isif_ioctl() - isif module private ioctl's - * @sd: VPFE isif V4L2 subdevice - * @cmd: ioctl command - * @arg: ioctl argument - * - * Return 0 on success or a negative error code otherwise. - */ -static long isif_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) -{ - switch (cmd) { - case VIDIOC_VPFE_ISIF_S_RAW_PARAMS: - return isif_set_params(sd, arg); - - case VIDIOC_VPFE_ISIF_G_RAW_PARAMS: - return isif_get_params(sd, arg); - - default: - return -ENOIOCTLCMD; - } -} - -static void isif_config_gain_offset(struct vpfe_isif_device *isif) -{ - struct vpfe_isif_gain_offsets_adj *gain_off_ptr = - &isif->isif_cfg.bayer.config_params.gain_offset; - void __iomem *base = isif->isif_cfg.base_addr; - u32 val; - - val = ((gain_off_ptr->gain_sdram_en & 1) << GAIN_SDRAM_EN_SHIFT) | - ((gain_off_ptr->gain_ipipe_en & 1) << GAIN_IPIPE_EN_SHIFT) | - ((gain_off_ptr->gain_h3a_en & 1) << GAIN_H3A_EN_SHIFT) | - ((gain_off_ptr->offset_sdram_en & 1) << OFST_SDRAM_EN_SHIFT) | - ((gain_off_ptr->offset_ipipe_en & 1) << OFST_IPIPE_EN_SHIFT) | - ((gain_off_ptr->offset_h3a_en & 1) << OFST_H3A_EN_SHIFT); - isif_merge(base, GAIN_OFFSET_EN_MASK, val, CGAMMAWD); - - isif_write(base, isif->isif_cfg.isif_gain_params.cr_gain, CRGAIN); - isif_write(base, isif->isif_cfg.isif_gain_params.cgr_gain, CGRGAIN); - isif_write(base, isif->isif_cfg.isif_gain_params.cgb_gain, CGBGAIN); - isif_write(base, isif->isif_cfg.isif_gain_params.cb_gain, CBGAIN); - isif_write(base, isif->isif_cfg.isif_gain_params.offset & OFFSET_MASK, - COFSTA); - -} - -static void isif_config_bclamp(struct vpfe_isif_device *isif, - struct vpfe_isif_black_clamp *bc) -{ - u32 val; - - /** - * DC Offset is always added to image data irrespective of bc enable - * status - */ - val = bc->dc_offset & ISIF_BC_DCOFFSET_MASK; - isif_write(isif->isif_cfg.base_addr, val, CLDCOFST); - - if (!bc->en) - return; - - val = (bc->bc_mode_color & ISIF_BC_MODE_COLOR_MASK) << - ISIF_BC_MODE_COLOR_SHIFT; - - /* Enable BC and horizontal clamp calculation parameters */ - val = val | 1 | ((bc->horz.mode & ISIF_HORZ_BC_MODE_MASK) << - ISIF_HORZ_BC_MODE_SHIFT); - - isif_write(isif->isif_cfg.base_addr, val, CLAMPCFG); - - if (bc->horz.mode != VPFE_ISIF_HORZ_BC_DISABLE) { - /* - * Window count for calculation - * Base window selection - * pixel limit - * Horizontal size of window - * vertical size of the window - * Horizontal start position of the window - * Vertical start position of the window - */ - val = (bc->horz.win_count_calc & ISIF_HORZ_BC_WIN_COUNT_MASK) | - ((bc->horz.base_win_sel_calc & 1) << - ISIF_HORZ_BC_WIN_SEL_SHIFT) | - ((bc->horz.clamp_pix_limit & 1) << - ISIF_HORZ_BC_PIX_LIMIT_SHIFT) | - ((bc->horz.win_h_sz_calc & - ISIF_HORZ_BC_WIN_H_SIZE_MASK) << - ISIF_HORZ_BC_WIN_H_SIZE_SHIFT) | - ((bc->horz.win_v_sz_calc & - ISIF_HORZ_BC_WIN_V_SIZE_MASK) << - ISIF_HORZ_BC_WIN_V_SIZE_SHIFT); - - isif_write(isif->isif_cfg.base_addr, val, CLHWIN0); - - val = bc->horz.win_start_h_calc & ISIF_HORZ_BC_WIN_START_H_MASK; - isif_write(isif->isif_cfg.base_addr, val, CLHWIN1); - - val = bc->horz.win_start_v_calc & ISIF_HORZ_BC_WIN_START_V_MASK; - isif_write(isif->isif_cfg.base_addr, val, CLHWIN2); - } - - /* vertical clamp calculation parameters */ - /* OB H Valid */ - val = bc->vert.ob_h_sz_calc & ISIF_VERT_BC_OB_H_SZ_MASK; - - /* Reset clamp value sel for previous line */ - val |= (bc->vert.reset_val_sel & ISIF_VERT_BC_RST_VAL_SEL_MASK) << - ISIF_VERT_BC_RST_VAL_SEL_SHIFT; - - /* Line average coefficient */ - val |= bc->vert.line_ave_coef << ISIF_VERT_BC_LINE_AVE_COEF_SHIFT; - isif_write(isif->isif_cfg.base_addr, val, CLVWIN0); - - /* Configured reset value */ - if (bc->vert.reset_val_sel == VPFE_ISIF_VERT_BC_USE_CONFIG_CLAMP_VAL) { - val = bc->vert.reset_clamp_val & ISIF_VERT_BC_RST_VAL_MASK; - isif_write(isif->isif_cfg.base_addr, val, CLVRV); - } - - /* Optical Black horizontal start position */ - val = bc->vert.ob_start_h & ISIF_VERT_BC_OB_START_HORZ_MASK; - isif_write(isif->isif_cfg.base_addr, val, CLVWIN1); - - /* Optical Black vertical start position */ - val = bc->vert.ob_start_v & ISIF_VERT_BC_OB_START_VERT_MASK; - isif_write(isif->isif_cfg.base_addr, val, CLVWIN2); - - val = bc->vert.ob_v_sz_calc & ISIF_VERT_BC_OB_VERT_SZ_MASK; - isif_write(isif->isif_cfg.base_addr, val, CLVWIN3); - - /* Vertical start position for BC subtraction */ - val = bc->vert_start_sub & ISIF_BC_VERT_START_SUB_V_MASK; - isif_write(isif->isif_cfg.base_addr, val, CLSV); -} - -/* This function will configure the window size to be capture in ISIF reg */ -static void -isif_setwin(struct vpfe_isif_device *isif, struct v4l2_rect *image_win, - enum isif_frmfmt frm_fmt, int ppc, int mode) -{ - int horz_nr_pixels; - int vert_nr_lines; - int horz_start; - int vert_start; - int mid_img; - - /* - * ppc - per pixel count. indicates how many pixels per cell - * output to SDRAM. example, for ycbcr, it is one y and one c, so 2. - * raw capture this is 1 - */ - horz_start = image_win->left << (ppc - 1); - horz_nr_pixels = (image_win->width << (ppc - 1)) - 1; - - /* Writing the horizontal info into the registers */ - isif_write(isif->isif_cfg.base_addr, - horz_start & START_PX_HOR_MASK, SPH); - isif_write(isif->isif_cfg.base_addr, - horz_nr_pixels & NUM_PX_HOR_MASK, LNH); - vert_start = image_win->top; - - if (frm_fmt == ISIF_FRMFMT_INTERLACED) { - vert_nr_lines = (image_win->height >> 1) - 1; - vert_start >>= 1; - /* To account for VD since line 0 doesn't have any data */ - vert_start += 1; - } else { - /* To account for VD since line 0 doesn't have any data */ - vert_start += 1; - vert_nr_lines = image_win->height - 1; - /* configure VDINT0 and VDINT1 */ - mid_img = vert_start + (image_win->height / 2); - isif_write(isif->isif_cfg.base_addr, mid_img, VDINT1); - } - - if (!mode) - isif_write(isif->isif_cfg.base_addr, 0, VDINT0); - else - isif_write(isif->isif_cfg.base_addr, vert_nr_lines, VDINT0); - isif_write(isif->isif_cfg.base_addr, - vert_start & START_VER_ONE_MASK, SLV0); - isif_write(isif->isif_cfg.base_addr, - vert_start & START_VER_TWO_MASK, SLV1); - isif_write(isif->isif_cfg.base_addr, - vert_nr_lines & NUM_LINES_VER, LNV); -} - -#define DM365_ISIF_DFCMWR_MEMORY_WRITE 1 -#define DM365_ISIF_DFCMRD_MEMORY_READ 0x2 - -static void -isif_config_dfc(struct vpfe_isif_device *isif, struct vpfe_isif_dfc *vdfc) -{ -#define DFC_WRITE_WAIT_COUNT 1000 - u32 count = DFC_WRITE_WAIT_COUNT; - u32 val; - int i; - - if (!vdfc->en) - return; - - /* Correction mode */ - val = (vdfc->corr_mode & ISIF_VDFC_CORR_MOD_MASK) << - ISIF_VDFC_CORR_MOD_SHIFT; - - /* Correct whole line or partial */ - if (vdfc->corr_whole_line) - val |= BIT(ISIF_VDFC_CORR_WHOLE_LN_SHIFT); - - /* level shift value */ - val |= (vdfc->def_level_shift & ISIF_VDFC_LEVEL_SHFT_MASK) << - ISIF_VDFC_LEVEL_SHFT_SHIFT; - - isif_write(isif->isif_cfg.base_addr, val, DFCCTL); - - /* Defect saturation level */ - val = vdfc->def_sat_level & ISIF_VDFC_SAT_LEVEL_MASK; - isif_write(isif->isif_cfg.base_addr, val, VDFSATLV); - - isif_write(isif->isif_cfg.base_addr, vdfc->table[0].pos_vert & - ISIF_VDFC_POS_MASK, DFCMEM0); - isif_write(isif->isif_cfg.base_addr, vdfc->table[0].pos_horz & - ISIF_VDFC_POS_MASK, DFCMEM1); - if (vdfc->corr_mode == VPFE_ISIF_VDFC_NORMAL || - vdfc->corr_mode == VPFE_ISIF_VDFC_HORZ_INTERPOL_IF_SAT) { - isif_write(isif->isif_cfg.base_addr, - vdfc->table[0].level_at_pos, DFCMEM2); - isif_write(isif->isif_cfg.base_addr, - vdfc->table[0].level_up_pixels, DFCMEM3); - isif_write(isif->isif_cfg.base_addr, - vdfc->table[0].level_low_pixels, DFCMEM4); - } - - val = isif_read(isif->isif_cfg.base_addr, DFCMEMCTL); - /* set DFCMARST and set DFCMWR */ - val |= BIT(ISIF_DFCMEMCTL_DFCMARST_SHIFT); - val |= 1; - isif_write(isif->isif_cfg.base_addr, val, DFCMEMCTL); - - while (count && (isif_read(isif->isif_cfg.base_addr, DFCMEMCTL) & 0x01)) - count--; - - val = isif_read(isif->isif_cfg.base_addr, DFCMEMCTL); - if (!count) { - pr_debug("defect table write timeout !!\n"); - return; - } - - for (i = 1; i < vdfc->num_vdefects; i++) { - isif_write(isif->isif_cfg.base_addr, vdfc->table[i].pos_vert & - ISIF_VDFC_POS_MASK, DFCMEM0); - - isif_write(isif->isif_cfg.base_addr, vdfc->table[i].pos_horz & - ISIF_VDFC_POS_MASK, DFCMEM1); - - if (vdfc->corr_mode == VPFE_ISIF_VDFC_NORMAL || - vdfc->corr_mode == VPFE_ISIF_VDFC_HORZ_INTERPOL_IF_SAT) { - isif_write(isif->isif_cfg.base_addr, - vdfc->table[i].level_at_pos, DFCMEM2); - isif_write(isif->isif_cfg.base_addr, - vdfc->table[i].level_up_pixels, DFCMEM3); - isif_write(isif->isif_cfg.base_addr, - vdfc->table[i].level_low_pixels, DFCMEM4); - } - val = isif_read(isif->isif_cfg.base_addr, DFCMEMCTL); - /* clear DFCMARST and set DFCMWR */ - val &= ~BIT(ISIF_DFCMEMCTL_DFCMARST_SHIFT); - val |= 1; - isif_write(isif->isif_cfg.base_addr, val, DFCMEMCTL); - - count = DFC_WRITE_WAIT_COUNT; - while (count && (isif_read(isif->isif_cfg.base_addr, - DFCMEMCTL) & 0x01)) - count--; - - val = isif_read(isif->isif_cfg.base_addr, DFCMEMCTL); - if (!count) { - pr_debug("defect table write timeout !!\n"); - return; - } - } - if (vdfc->num_vdefects < VPFE_ISIF_VDFC_TABLE_SIZE) { - /* Extra cycle needed */ - isif_write(isif->isif_cfg.base_addr, 0, DFCMEM0); - isif_write(isif->isif_cfg.base_addr, - DM365_ISIF_MAX_DFCMEM1, DFCMEM1); - isif_write(isif->isif_cfg.base_addr, - DM365_ISIF_DFCMWR_MEMORY_WRITE, DFCMEMCTL); - } - /* enable VDFC */ - isif_merge(isif->isif_cfg.base_addr, (1 << ISIF_VDFC_EN_SHIFT), - (1 << ISIF_VDFC_EN_SHIFT), DFCCTL); - - isif_merge(isif->isif_cfg.base_addr, (1 << ISIF_VDFC_EN_SHIFT), - (0 << ISIF_VDFC_EN_SHIFT), DFCCTL); - - isif_write(isif->isif_cfg.base_addr, 0x6, DFCMEMCTL); - for (i = 0; i < vdfc->num_vdefects; i++) { - count = DFC_WRITE_WAIT_COUNT; - while (count && - (isif_read(isif->isif_cfg.base_addr, DFCMEMCTL) & 0x2)) - count--; - val = isif_read(isif->isif_cfg.base_addr, DFCMEMCTL); - if (!count) { - pr_debug("defect table write timeout !!\n"); - return; - } - isif_write(isif->isif_cfg.base_addr, - DM365_ISIF_DFCMRD_MEMORY_READ, DFCMEMCTL); - } -} - -static void -isif_config_csc(struct vpfe_isif_device *isif, struct vpfe_isif_df_csc *df_csc) -{ - u32 val1; - u32 val2; - u32 i; - - if (!df_csc->csc.en) { - isif_write(isif->isif_cfg.base_addr, 0, CSCCTL); - return; - } - /* initialize all bits to 0 */ - val1 = 0; - for (i = 0; i < VPFE_ISIF_CSC_NUM_COEFF; i++) { - if ((i % 2) == 0) { - /* CSCM - LSB */ - val1 = ((df_csc->csc.coeff[i].integer & - ISIF_CSC_COEF_INTEG_MASK) << - ISIF_CSC_COEF_INTEG_SHIFT) | - ((df_csc->csc.coeff[i].decimal & - ISIF_CSC_COEF_DECIMAL_MASK)); - } else { - - /* CSCM - MSB */ - val2 = ((df_csc->csc.coeff[i].integer & - ISIF_CSC_COEF_INTEG_MASK) << - ISIF_CSC_COEF_INTEG_SHIFT) | - ((df_csc->csc.coeff[i].decimal & - ISIF_CSC_COEF_DECIMAL_MASK)); - val2 <<= ISIF_CSCM_MSB_SHIFT; - val2 |= val1; - isif_write(isif->isif_cfg.base_addr, val2, - (CSCM0 + ((i-1) << 1))); - } - } - /* program the active area */ - isif_write(isif->isif_cfg.base_addr, df_csc->start_pix & - ISIF_DF_CSC_SPH_MASK, FMTSPH); - /* - * one extra pixel as required for CSC. Actually number of - * pixel - 1 should be configured in this register. So we - * need to subtract 1 before writing to FMTSPH, but we will - * not do this since csc requires one extra pixel - */ - isif_write(isif->isif_cfg.base_addr, df_csc->num_pixels & - ISIF_DF_CSC_SPH_MASK, FMTLNH); - isif_write(isif->isif_cfg.base_addr, df_csc->start_line & - ISIF_DF_CSC_SPH_MASK, FMTSLV); - /* - * one extra line as required for CSC. See reason documented for - * num_pixels - */ - isif_write(isif->isif_cfg.base_addr, df_csc->num_lines & - ISIF_DF_CSC_SPH_MASK, FMTLNV); - /* Enable CSC */ - isif_write(isif->isif_cfg.base_addr, 1, CSCCTL); -} - -static void -isif_config_linearization(struct vpfe_isif_device *isif, - struct vpfe_isif_linearize *linearize) -{ - u32 val; - u32 i; - - if (!linearize->en) { - isif_write(isif->isif_cfg.base_addr, 0, LINCFG0); - return; - } - /* shift value for correction */ - val = (linearize->corr_shft & ISIF_LIN_CORRSFT_MASK) << - ISIF_LIN_CORRSFT_SHIFT; - /* enable */ - val |= 1; - isif_write(isif->isif_cfg.base_addr, val, LINCFG0); - /* Scale factor */ - val = (linearize->scale_fact.integer & 1) << - ISIF_LIN_SCALE_FACT_INTEG_SHIFT; - val |= linearize->scale_fact.decimal & ISIF_LIN_SCALE_FACT_DECIMAL_MASK; - isif_write(isif->isif_cfg.base_addr, val, LINCFG1); - - for (i = 0; i < VPFE_ISIF_LINEAR_TAB_SIZE; i++) { - val = linearize->table[i] & ISIF_LIN_ENTRY_MASK; - if (i%2) - isif_regw_lin_tbl(isif, val, ((i >> 1) << 2), 1); - else - isif_regw_lin_tbl(isif, val, ((i >> 1) << 2), 0); - } -} - -static void -isif_config_culling(struct vpfe_isif_device *isif, struct vpfe_isif_cul *cul) -{ - u32 val; - - /* Horizontal pattern */ - val = cul->hcpat_even << CULL_PAT_EVEN_LINE_SHIFT; - val |= cul->hcpat_odd; - isif_write(isif->isif_cfg.base_addr, val, CULH); - /* vertical pattern */ - isif_write(isif->isif_cfg.base_addr, cul->vcpat, CULV); - /* LPF */ - isif_merge(isif->isif_cfg.base_addr, ISIF_LPF_MASK << ISIF_LPF_SHIFT, - cul->en_lpf << ISIF_LPF_SHIFT, MODESET); -} - -static int isif_get_pix_fmt(u32 mbus_code) -{ - switch (mbus_code) { - case MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8: - case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8: - case MEDIA_BUS_FMT_SGRBG12_1X12: - return ISIF_PIXFMT_RAW; - - case MEDIA_BUS_FMT_YUYV8_2X8: - case MEDIA_BUS_FMT_UYVY8_2X8: - case MEDIA_BUS_FMT_YUYV10_2X10: - case MEDIA_BUS_FMT_Y8_1X8: - return ISIF_PIXFMT_YCBCR_8BIT; - - case MEDIA_BUS_FMT_YUYV8_1X16: - case MEDIA_BUS_FMT_YUYV10_1X20: - return ISIF_PIXFMT_YCBCR_16BIT; - - default: - break; - } - return -EINVAL; -} - -#define ISIF_INTERLACE_INVERSE_MODE 0x4b6d -#define ISIF_INTERLACE_NON_INVERSE_MODE 0x0b6d -#define ISIF_PROGRESSIVE_INVERSE_MODE 0x4000 -#define ISIF_PROGRESSIVE_NON_INVERSE_MODE 0x0000 - -static int isif_config_raw(struct v4l2_subdev *sd, int mode) -{ - struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd); - struct isif_params_raw *params = &isif->isif_cfg.bayer; - struct vpfe_isif_raw_config *module_params = - &isif->isif_cfg.bayer.config_params; - struct v4l2_mbus_framefmt *format; - int pix_fmt; - u32 val; - - format = &isif->formats[ISIF_PAD_SINK]; - - /* In case of user has set BT656IF earlier, it should be reset - * when configuring for raw input. - */ - isif_write(isif->isif_cfg.base_addr, 0, REC656IF); - /* Configure CCDCFG register - * Set CCD Not to swap input since input is RAW data - * Set FID detection function to Latch at V-Sync - * Set WENLOG - isif valid area - * Set TRGSEL - * Set EXTRG - * Packed to 8 or 16 bits - */ - val = ISIF_YCINSWP_RAW | ISIF_CCDCFG_FIDMD_LATCH_VSYNC | - ISIF_CCDCFG_WENLOG_AND | ISIF_CCDCFG_TRGSEL_WEN | - ISIF_CCDCFG_EXTRG_DISABLE | (isif->isif_cfg.data_pack & - ISIF_DATA_PACK_MASK); - isif_write(isif->isif_cfg.base_addr, val, CCDCFG); - - pix_fmt = isif_get_pix_fmt(format->code); - if (pix_fmt < 0) { - pr_debug("Invalid pix_fmt(input mode)\n"); - return -EINVAL; - } - /* - * Configure the vertical sync polarity(MODESET.VDPOL) - * Configure the horizontal sync polarity (MODESET.HDPOL) - * Configure frame id polarity (MODESET.FLDPOL) - * Configure data polarity - * Configure External WEN Selection - * Configure frame format(progressive or interlace) - * Configure pixel format (Input mode) - * Configure the data shift - */ - val = ISIF_VDHDOUT_INPUT | ((params->vd_pol & ISIF_VD_POL_MASK) << - ISIF_VD_POL_SHIFT) | ((params->hd_pol & ISIF_HD_POL_MASK) << - ISIF_HD_POL_SHIFT) | ((params->fid_pol & ISIF_FID_POL_MASK) << - ISIF_FID_POL_SHIFT) | ((ISIF_DATAPOL_NORMAL & - ISIF_DATAPOL_MASK) << ISIF_DATAPOL_SHIFT) | ((ISIF_EXWEN_DISABLE & - ISIF_EXWEN_MASK) << ISIF_EXWEN_SHIFT) | ((params->frm_fmt & - ISIF_FRM_FMT_MASK) << ISIF_FRM_FMT_SHIFT) | ((pix_fmt & - ISIF_INPUT_MASK) << ISIF_INPUT_SHIFT); - - /* currently only MEDIA_BUS_FMT_SGRBG12_1X12 is - * supported. shift appropriately depending on - * different MBUS fmt's added - */ - if (format->code == MEDIA_BUS_FMT_SGRBG12_1X12) - val |= ((VPFE_ISIF_NO_SHIFT & - ISIF_DATASFT_MASK) << ISIF_DATASFT_SHIFT); - - isif_write(isif->isif_cfg.base_addr, val, MODESET); - /* - * Configure GAMMAWD register - * CFA pattern setting - */ - val = (params->cfa_pat & ISIF_GAMMAWD_CFA_MASK) << - ISIF_GAMMAWD_CFA_SHIFT; - /* Gamma msb */ - if (params->v4l2_pix_fmt == V4L2_PIX_FMT_SGRBG10ALAW8) - val = val | ISIF_ALAW_ENABLE; - - val = val | ((params->data_msb & ISIF_ALAW_GAMA_WD_MASK) << - ISIF_ALAW_GAMA_WD_SHIFT); - - isif_write(isif->isif_cfg.base_addr, val, CGAMMAWD); - /* Configure DPCM compression settings */ - if (params->v4l2_pix_fmt == V4L2_PIX_FMT_SGRBG10DPCM8) { - val = BIT(ISIF_DPCM_EN_SHIFT); - val |= (params->dpcm_predictor & - ISIF_DPCM_PREDICTOR_MASK) << ISIF_DPCM_PREDICTOR_SHIFT; - } - isif_write(isif->isif_cfg.base_addr, val, MISC); - /* Configure Gain & Offset */ - isif_config_gain_offset(isif); - /* Configure Color pattern */ - if (format->code == MEDIA_BUS_FMT_SGRBG12_1X12) - val = isif_sgrbg_pattern; - else - /* default set to rggb */ - val = isif_srggb_pattern; - - isif_write(isif->isif_cfg.base_addr, val, CCOLP); - - /* Configure HSIZE register */ - val = (params->horz_flip_en & ISIF_HSIZE_FLIP_MASK) << - ISIF_HSIZE_FLIP_SHIFT; - - /* calculate line offset in 32 bytes based on pack value */ - if (isif->isif_cfg.data_pack == ISIF_PACK_8BIT) - val |= ((params->win.width + 31) >> 5) & ISIF_LINEOFST_MASK; - else if (isif->isif_cfg.data_pack == ISIF_PACK_12BIT) - val |= ((((params->win.width + (params->win.width >> 2)) + - 31) >> 5) & ISIF_LINEOFST_MASK); - else - val |= (((params->win.width * 2) + 31) >> 5) & - ISIF_LINEOFST_MASK; - isif_write(isif->isif_cfg.base_addr, val, HSIZE); - /* Configure SDOFST register */ - if (params->frm_fmt == ISIF_FRMFMT_INTERLACED) { - if (params->image_invert_en) - /* For interlace inverse mode */ - isif_write(isif->isif_cfg.base_addr, - ISIF_INTERLACE_INVERSE_MODE, SDOFST); - else - /* For interlace non inverse mode */ - isif_write(isif->isif_cfg.base_addr, - ISIF_INTERLACE_NON_INVERSE_MODE, SDOFST); - } else if (params->frm_fmt == ISIF_FRMFMT_PROGRESSIVE) { - if (params->image_invert_en) - isif_write(isif->isif_cfg.base_addr, - ISIF_PROGRESSIVE_INVERSE_MODE, SDOFST); - else - /* For progessive non inverse mode */ - isif_write(isif->isif_cfg.base_addr, - ISIF_PROGRESSIVE_NON_INVERSE_MODE, SDOFST); - } - /* Configure video window */ - isif_setwin(isif, ¶ms->win, params->frm_fmt, 1, mode); - /* Configure Black Clamp */ - isif_config_bclamp(isif, &module_params->bclamp); - /* Configure Vertical Defection Pixel Correction */ - isif_config_dfc(isif, &module_params->dfc); - if (!module_params->df_csc.df_or_csc) - /* Configure Color Space Conversion */ - isif_config_csc(isif, &module_params->df_csc); - - isif_config_linearization(isif, &module_params->linearize); - /* Configure Culling */ - isif_config_culling(isif, &module_params->culling); - /* Configure Horizontal and vertical offsets(DFC,LSC,Gain) */ - val = module_params->horz_offset & ISIF_DATA_H_OFFSET_MASK; - isif_write(isif->isif_cfg.base_addr, val, DATAHOFST); - - val = module_params->vert_offset & ISIF_DATA_V_OFFSET_MASK; - isif_write(isif->isif_cfg.base_addr, val, DATAVOFST); - - return 0; -} - -#define DM365_ISIF_HSIZE_MASK 0xffffffe0 -#define DM365_ISIF_SDOFST_2_LINES 0x00000249 - -/* This function will configure ISIF for YCbCr parameters. */ -static int isif_config_ycbcr(struct v4l2_subdev *sd, int mode) -{ - struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd); - struct isif_ycbcr_config *params = &isif->isif_cfg.ycbcr; - struct v4l2_mbus_framefmt *format; - int pix_fmt; - u32 modeset; - u32 ccdcfg; - - format = &isif->formats[ISIF_PAD_SINK]; - /* - * first reset the ISIF - * all registers have default values after reset - * This is important since we assume default values to be set in - * a lot of registers that we didn't touch - */ - /* start with all bits zero */ - ccdcfg = 0; - modeset = 0; - pix_fmt = isif_get_pix_fmt(format->code); - if (pix_fmt < 0) { - pr_debug("Invalid pix_fmt(input mode)\n"); - return -EINVAL; - } - /* configure pixel format or input mode */ - modeset = modeset | ((pix_fmt & ISIF_INPUT_MASK) << - ISIF_INPUT_SHIFT) | ((params->frm_fmt & ISIF_FRM_FMT_MASK) << - ISIF_FRM_FMT_SHIFT) | (((params->fid_pol & - ISIF_FID_POL_MASK) << ISIF_FID_POL_SHIFT)) | - (((params->hd_pol & ISIF_HD_POL_MASK) << ISIF_HD_POL_SHIFT)) | - (((params->vd_pol & ISIF_VD_POL_MASK) << ISIF_VD_POL_SHIFT)); - /* pack the data to 8-bit CCDCCFG */ - switch (format->code) { - case MEDIA_BUS_FMT_YUYV8_2X8: - case MEDIA_BUS_FMT_UYVY8_2X8: - if (pix_fmt != ISIF_PIXFMT_YCBCR_8BIT) { - pr_debug("Invalid pix_fmt(input mode)\n"); - return -EINVAL; - } - modeset |= ((VPFE_PINPOL_NEGATIVE & ISIF_VD_POL_MASK) << - ISIF_VD_POL_SHIFT); - isif_write(isif->isif_cfg.base_addr, 3, REC656IF); - ccdcfg = ccdcfg | ISIF_PACK_8BIT | ISIF_YCINSWP_YCBCR; - break; - - case MEDIA_BUS_FMT_YUYV10_2X10: - if (pix_fmt != ISIF_PIXFMT_YCBCR_8BIT) { - pr_debug("Invalid pix_fmt(input mode)\n"); - return -EINVAL; - } - /* setup BT.656, embedded sync */ - isif_write(isif->isif_cfg.base_addr, 3, REC656IF); - /* enable 10 bit mode in ccdcfg */ - ccdcfg = ccdcfg | ISIF_PACK_8BIT | ISIF_YCINSWP_YCBCR | - ISIF_BW656_ENABLE; - break; - - case MEDIA_BUS_FMT_YUYV10_1X20: - if (pix_fmt != ISIF_PIXFMT_YCBCR_16BIT) { - pr_debug("Invalid pix_fmt(input mode)\n"); - return -EINVAL; - } - isif_write(isif->isif_cfg.base_addr, 3, REC656IF); - break; - - case MEDIA_BUS_FMT_Y8_1X8: - ccdcfg |= ISIF_PACK_8BIT; - ccdcfg |= ISIF_YCINSWP_YCBCR; - if (pix_fmt != ISIF_PIXFMT_YCBCR_8BIT) { - pr_debug("Invalid pix_fmt(input mode)\n"); - return -EINVAL; - } - break; - - case MEDIA_BUS_FMT_YUYV8_1X16: - if (pix_fmt != ISIF_PIXFMT_YCBCR_16BIT) { - pr_debug("Invalid pix_fmt(input mode)\n"); - return -EINVAL; - } - break; - - default: - /* should never come here */ - pr_debug("Invalid interface type\n"); - return -EINVAL; - } - isif_write(isif->isif_cfg.base_addr, modeset, MODESET); - /* Set up pix order */ - ccdcfg |= (params->pix_order & ISIF_PIX_ORDER_MASK) << - ISIF_PIX_ORDER_SHIFT; - isif_write(isif->isif_cfg.base_addr, ccdcfg, CCDCFG); - /* configure video window */ - if (format->code == MEDIA_BUS_FMT_YUYV10_1X20 || - format->code == MEDIA_BUS_FMT_YUYV8_1X16) - isif_setwin(isif, ¶ms->win, params->frm_fmt, 1, mode); - else - isif_setwin(isif, ¶ms->win, params->frm_fmt, 2, mode); - - /* - * configure the horizontal line offset - * this is done by rounding up width to a multiple of 16 pixels - * and multiply by two to account for y:cb:cr 4:2:2 data - */ - isif_write(isif->isif_cfg.base_addr, - ((((params->win.width * 2) + 31) & - DM365_ISIF_HSIZE_MASK) >> 5), HSIZE); - - /* configure the memory line offset */ - if (params->frm_fmt == ISIF_FRMFMT_INTERLACED && - params->buf_type == ISIF_BUFTYPE_FLD_INTERLEAVED) - /* two fields are interleaved in memory */ - isif_write(isif->isif_cfg.base_addr, - DM365_ISIF_SDOFST_2_LINES, SDOFST); - return 0; -} - -static int isif_configure(struct v4l2_subdev *sd, int mode) -{ - struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt *format; - - format = &isif->formats[ISIF_PAD_SINK]; - - switch (format->code) { - case MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8: - case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8: - case MEDIA_BUS_FMT_SGRBG12_1X12: - return isif_config_raw(sd, mode); - - case MEDIA_BUS_FMT_YUYV8_2X8: - case MEDIA_BUS_FMT_UYVY8_2X8: - case MEDIA_BUS_FMT_YUYV10_2X10: - case MEDIA_BUS_FMT_Y8_1X8: - case MEDIA_BUS_FMT_YUYV8_1X16: - case MEDIA_BUS_FMT_YUYV10_1X20: - return isif_config_ycbcr(sd, mode); - - default: - break; - } - return -EINVAL; -} - -/* - * isif_set_stream() - Enable/Disable streaming on the ISIF module - * @sd: VPFE ISIF V4L2 subdevice - * @enable: Enable/disable stream - */ -static int isif_set_stream(struct v4l2_subdev *sd, int enable) -{ - struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd); - int ret; - - if (enable) { - ret = isif_configure(sd, - (isif->output == ISIF_OUTPUT_MEMORY) ? 0 : 1); - if (ret) - return ret; - if (isif->output == ISIF_OUTPUT_MEMORY) - isif_enable_output_to_sdram(isif, 1); - isif_enable(isif, 1); - } else { - isif_enable(isif, 0); - isif_enable_output_to_sdram(isif, 0); - } - - return 0; -} - -/* - * __isif_get_format() - helper function for getting isif format - * @isif: pointer to isif private structure. - * @pad: pad number. - * @cfg: V4L2 subdev pad config - * @which: wanted subdev format. - */ -static struct v4l2_mbus_framefmt * -__isif_get_format(struct vpfe_isif_device *isif, - struct v4l2_subdev_pad_config *cfg, unsigned int pad, - enum v4l2_subdev_format_whence which) -{ - if (which == V4L2_SUBDEV_FORMAT_TRY) - return v4l2_subdev_get_try_format(&isif->subdev, cfg, pad); - - return &isif->formats[pad]; -} - -/* - * isif_set_format() - set format on pad - * @sd : VPFE ISIF device - * @cfg : V4L2 subdev pad config - * @fmt : pointer to v4l2 subdev format structure - * - * Return 0 on success or -EINVAL if format or pad is invalid - */ -static int -isif_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) -{ - struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd); - struct vpfe_device *vpfe_dev = to_vpfe_device(isif); - struct v4l2_mbus_framefmt *format; - - format = __isif_get_format(isif, cfg, fmt->pad, fmt->which); - if (format == NULL) - return -EINVAL; - - isif_try_format(isif, cfg, fmt); - memcpy(format, &fmt->format, sizeof(*format)); - - if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) - return 0; - - if (fmt->pad == ISIF_PAD_SOURCE) - return isif_config_format(vpfe_dev, fmt->pad); - - return 0; -} - -/* - * isif_get_format() - Retrieve the video format on a pad - * @sd: VPFE ISIF V4L2 subdevice - * @cfg: V4L2 subdev pad config - * @fmt: pointer to v4l2 subdev format structure - * - * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond - * to the format type. - */ -static int -isif_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) -{ - struct vpfe_isif_device *vpfe_isif = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt *format; - - format = __isif_get_format(vpfe_isif, cfg, fmt->pad, fmt->which); - if (format == NULL) - return -EINVAL; - - memcpy(&fmt->format, format, sizeof(fmt->format)); - - return 0; -} - -/* - * isif_enum_frame_size() - enum frame sizes on pads - * @sd: VPFE isif V4L2 subdevice - * @cfg: V4L2 subdev pad config - * @code: pointer to v4l2_subdev_frame_size_enum structure - */ -static int -isif_enum_frame_size(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_frame_size_enum *fse) -{ - struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd); - struct v4l2_subdev_format format; - - if (fse->index != 0) - return -EINVAL; - - format.pad = fse->pad; - format.format.code = fse->code; - format.format.width = 1; - format.format.height = 1; - format.which = fse->which; - isif_try_format(isif, cfg, &format); - fse->min_width = format.format.width; - fse->min_height = format.format.height; - - if (format.format.code != fse->code) - return -EINVAL; - - format.pad = fse->pad; - format.format.code = fse->code; - format.format.width = -1; - format.format.height = -1; - format.which = fse->which; - isif_try_format(isif, cfg, &format); - fse->max_width = format.format.width; - fse->max_height = format.format.height; - - return 0; -} - -/* - * isif_enum_mbus_code() - enum mbus codes for pads - * @sd: VPFE isif V4L2 subdevice - * @cfg: V4L2 subdev pad config - * @code: pointer to v4l2_subdev_mbus_code_enum structure - */ -static int -isif_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_mbus_code_enum *code) -{ - switch (code->pad) { - case ISIF_PAD_SINK: - case ISIF_PAD_SOURCE: - if (code->index >= ARRAY_SIZE(isif_fmts)) - return -EINVAL; - code->code = isif_fmts[code->index]; - break; - - default: - return -EINVAL; - } - - return 0; -} - -/* - * isif_pad_set_selection() - set crop rectangle on pad - * @sd: VPFE isif V4L2 subdevice - * @cfg: V4L2 subdev pad config - * @code: pointer to v4l2_subdev_mbus_code_enum structure - * - * Return 0 on success, -EINVAL if pad is invalid - */ -static int -isif_pad_set_selection(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_selection *sel) -{ - struct vpfe_isif_device *vpfe_isif = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt *format; - - /* check whether it's a valid pad and target */ - if (sel->pad != ISIF_PAD_SINK || sel->target != V4L2_SEL_TGT_CROP) - return -EINVAL; - - format = __isif_get_format(vpfe_isif, cfg, sel->pad, sel->which); - if (format == NULL) - return -EINVAL; - - /* check wether crop rect is within limits */ - if (sel->r.top < 0 || sel->r.left < 0 || - (sel->r.left + sel->r.width > - vpfe_isif->formats[ISIF_PAD_SINK].width) || - (sel->r.top + sel->r.height > - vpfe_isif->formats[ISIF_PAD_SINK].height)) { - sel->r.left = 0; - sel->r.top = 0; - sel->r.width = format->width; - sel->r.height = format->height; - } - /* adjust the width to 16 pixel boundary */ - sel->r.width = (sel->r.width + 15) & ~0xf; - vpfe_isif->crop = sel->r; - if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) { - isif_set_image_window(vpfe_isif); - } else { - struct v4l2_rect *rect; - - rect = v4l2_subdev_get_try_crop(sd, cfg, ISIF_PAD_SINK); - memcpy(rect, &vpfe_isif->crop, sizeof(*rect)); - } - return 0; -} - -/* - * isif_pad_get_selection() - get crop rectangle on pad - * @sd: VPFE isif V4L2 subdevice - * @cfg: V4L2 subdev pad config - * @code: pointer to v4l2_subdev_mbus_code_enum structure - * - * Return 0 on success, -EINVAL if pad is invalid - */ -static int -isif_pad_get_selection(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_selection *sel) -{ - struct vpfe_isif_device *vpfe_isif = v4l2_get_subdevdata(sd); - - /* check whether it's a valid pad and target */ - if (sel->pad != ISIF_PAD_SINK || sel->target != V4L2_SEL_TGT_CROP) - return -EINVAL; - - if (sel->which == V4L2_SUBDEV_FORMAT_TRY) { - struct v4l2_rect *rect; - - rect = v4l2_subdev_get_try_crop(sd, cfg, ISIF_PAD_SINK); - memcpy(&sel->r, rect, sizeof(*rect)); - } else { - sel->r = vpfe_isif->crop; - } - - return 0; -} - -/* - * isif_init_formats() - Initialize formats on all pads - * @sd: VPFE isif V4L2 subdevice - * @fh: V4L2 subdev file handle - * - * Initialize all pad formats with default values. Try formats are initialized - * on the file handle. - */ -static int -isif_init_formats(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh) -{ - struct v4l2_subdev_format format; - struct v4l2_subdev_selection sel; - - memset(&format, 0, sizeof(format)); - format.pad = ISIF_PAD_SINK; - format.which = V4L2_SUBDEV_FORMAT_TRY; - format.format.code = MEDIA_BUS_FMT_SGRBG12_1X12; - format.format.width = MAX_WIDTH; - format.format.height = MAX_HEIGHT; - isif_set_format(sd, fh->pad, &format); - - memset(&format, 0, sizeof(format)); - format.pad = ISIF_PAD_SOURCE; - format.which = V4L2_SUBDEV_FORMAT_TRY; - format.format.code = MEDIA_BUS_FMT_SGRBG12_1X12; - format.format.width = MAX_WIDTH; - format.format.height = MAX_HEIGHT; - isif_set_format(sd, fh->pad, &format); - - memset(&sel, 0, sizeof(sel)); - sel.pad = ISIF_PAD_SINK; - sel.which = V4L2_SUBDEV_FORMAT_TRY; - sel.target = V4L2_SEL_TGT_CROP; - sel.r.width = MAX_WIDTH; - sel.r.height = MAX_HEIGHT; - isif_pad_set_selection(sd, fh->pad, &sel); - - return 0; -} - -/* subdev core operations */ -static const struct v4l2_subdev_core_ops isif_v4l2_core_ops = { - .ioctl = isif_ioctl, -}; - -/* subdev file operations */ -static const struct v4l2_subdev_internal_ops isif_v4l2_internal_ops = { - .open = isif_init_formats, -}; - -/* subdev video operations */ -static const struct v4l2_subdev_video_ops isif_v4l2_video_ops = { - .s_stream = isif_set_stream, -}; - -/* subdev pad operations */ -static const struct v4l2_subdev_pad_ops isif_v4l2_pad_ops = { - .enum_mbus_code = isif_enum_mbus_code, - .enum_frame_size = isif_enum_frame_size, - .get_fmt = isif_get_format, - .set_fmt = isif_set_format, - .set_selection = isif_pad_set_selection, - .get_selection = isif_pad_get_selection, -}; - -/* subdev operations */ -static const struct v4l2_subdev_ops isif_v4l2_ops = { - .core = &isif_v4l2_core_ops, - .video = &isif_v4l2_video_ops, - .pad = &isif_v4l2_pad_ops, -}; - -/* - * Media entity operations - */ - -/* - * isif_link_setup() - Setup isif connections - * @entity: isif media entity - * @local: Pad at the local end of the link - * @remote: Pad at the remote end of the link - * @flags: Link flags - * - * return -EINVAL or zero on success - */ -static int -isif_link_setup(struct media_entity *entity, const struct media_pad *local, - const struct media_pad *remote, u32 flags) -{ - struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); - struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd); - unsigned int index = local->index; - - /* FIXME: this is actually a hack! */ - if (is_media_entity_v4l2_subdev(remote->entity)) - index |= 2 << 16; - - switch (index) { - case ISIF_PAD_SINK | 2 << 16: - /* read from decoder/sensor */ - if (!(flags & MEDIA_LNK_FL_ENABLED)) { - isif->input = ISIF_INPUT_NONE; - break; - } - if (isif->input != ISIF_INPUT_NONE) - return -EBUSY; - isif->input = ISIF_INPUT_PARALLEL; - break; - - case ISIF_PAD_SOURCE: - /* write to memory */ - if (flags & MEDIA_LNK_FL_ENABLED) - isif->output = ISIF_OUTPUT_MEMORY; - else - isif->output = ISIF_OUTPUT_NONE; - break; - - case ISIF_PAD_SOURCE | 2 << 16: - if (flags & MEDIA_LNK_FL_ENABLED) - isif->output = ISIF_OUTPUT_IPIPEIF; - else - isif->output = ISIF_OUTPUT_NONE; - break; - - default: - return -EINVAL; - } - - return 0; -} -static const struct media_entity_operations isif_media_ops = { - .link_setup = isif_link_setup, -}; - -/* - * vpfe_isif_unregister_entities() - isif unregister entity - * @isif - pointer to isif subdevice structure. - */ -void vpfe_isif_unregister_entities(struct vpfe_isif_device *isif) -{ - vpfe_video_unregister(&isif->video_out); - /* unregister subdev */ - v4l2_device_unregister_subdev(&isif->subdev); - /* cleanup entity */ - media_entity_cleanup(&isif->subdev.entity); -} - -static void isif_restore_defaults(struct vpfe_isif_device *isif) -{ - enum vpss_ccdc_source_sel source = VPSS_CCDCIN; - int i; - - memset(&isif->isif_cfg.bayer.config_params, 0, - sizeof(struct vpfe_isif_raw_config)); - - isif->isif_cfg.bayer.config_params.linearize.corr_shft = - VPFE_ISIF_NO_SHIFT; - isif->isif_cfg.bayer.config_params.linearize.scale_fact.integer = 1; - isif->isif_cfg.bayer.config_params.culling.hcpat_odd = - ISIF_CULLING_HCAPT_ODD; - isif->isif_cfg.bayer.config_params.culling.hcpat_even = - ISIF_CULLING_HCAPT_EVEN; - isif->isif_cfg.bayer.config_params.culling.vcpat = ISIF_CULLING_VCAPT; - /* Enable clock to ISIF, IPIPEIF and BL */ - vpss_enable_clock(VPSS_CCDC_CLOCK, 1); - vpss_enable_clock(VPSS_IPIPEIF_CLOCK, 1); - vpss_enable_clock(VPSS_BL_CLOCK, 1); - - /* set all registers to default value */ - for (i = 0; i <= 0x1f8; i += 4) - isif_write(isif->isif_cfg.base_addr, 0, i); - /* no culling support */ - isif_write(isif->isif_cfg.base_addr, 0xffff, CULH); - isif_write(isif->isif_cfg.base_addr, 0xff, CULV); - - /* Set default offset and gain */ - isif_config_gain_offset(isif); - vpss_select_ccdc_source(source); -} - -/* - * vpfe_isif_register_entities() - isif register entity - * @isif - pointer to isif subdevice structure. - * @vdev: pointer to v4l2 device structure. - */ -int vpfe_isif_register_entities(struct vpfe_isif_device *isif, - struct v4l2_device *vdev) -{ - struct vpfe_device *vpfe_dev = to_vpfe_device(isif); - unsigned int flags; - int ret; - - /* Register the subdev */ - ret = v4l2_device_register_subdev(vdev, &isif->subdev); - if (ret < 0) - return ret; - - isif_restore_defaults(isif); - ret = vpfe_video_register(&isif->video_out, vdev); - if (ret) { - pr_err("Failed to register isif video out device\n"); - goto out_video_register; - } - isif->video_out.vpfe_dev = vpfe_dev; - flags = 0; - /* connect isif to video node */ - ret = media_create_pad_link(&isif->subdev.entity, 1, - &isif->video_out.video_dev.entity, - 0, flags); - if (ret < 0) - goto out_create_link; - return 0; -out_create_link: - vpfe_video_unregister(&isif->video_out); -out_video_register: - v4l2_device_unregister_subdev(&isif->subdev); - return ret; -} - -/* ------------------------------------------------------------------- - * V4L2 subdev control operations - */ - -static int vpfe_isif_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct vpfe_isif_device *isif = - container_of(ctrl->handler, struct vpfe_isif_device, ctrls); - struct isif_oper_config *config = &isif->isif_cfg; - - switch (ctrl->id) { - case VPFE_CID_DPCM_PREDICTOR: - config->bayer.dpcm_predictor = ctrl->val; - break; - - case VPFE_ISIF_CID_CRGAIN: - config->isif_gain_params.cr_gain = ctrl->val; - break; - - case VPFE_ISIF_CID_CGRGAIN: - config->isif_gain_params.cgr_gain = ctrl->val; - break; - - case VPFE_ISIF_CID_CGBGAIN: - config->isif_gain_params.cgb_gain = ctrl->val; - break; - - case VPFE_ISIF_CID_CBGAIN: - config->isif_gain_params.cb_gain = ctrl->val; - break; - - case VPFE_ISIF_CID_GAIN_OFFSET: - config->isif_gain_params.offset = ctrl->val; - break; - - default: - return -EINVAL; - } - return 0; -} - -static const struct v4l2_ctrl_ops vpfe_isif_ctrl_ops = { - .s_ctrl = vpfe_isif_s_ctrl, -}; - -static const struct v4l2_ctrl_config vpfe_isif_dpcm_pred = { - .ops = &vpfe_isif_ctrl_ops, - .id = VPFE_CID_DPCM_PREDICTOR, - .name = "DPCM Predictor", - .type = V4L2_CTRL_TYPE_INTEGER, - .min = 0, - .max = 1, - .step = 1, - .def = 0, -}; - -static const struct v4l2_ctrl_config vpfe_isif_crgain = { - .ops = &vpfe_isif_ctrl_ops, - .id = VPFE_ISIF_CID_CRGAIN, - .name = "CRGAIN", - .type = V4L2_CTRL_TYPE_INTEGER, - .min = 0, - .max = (1 << 12) - 1, - .step = 1, - .def = 0, -}; - -static const struct v4l2_ctrl_config vpfe_isif_cgrgain = { - .ops = &vpfe_isif_ctrl_ops, - .id = VPFE_ISIF_CID_CGRGAIN, - .name = "CGRGAIN", - .type = V4L2_CTRL_TYPE_INTEGER, - .min = 0, - .max = (1 << 12) - 1, - .step = 1, - .def = 0, -}; - -static const struct v4l2_ctrl_config vpfe_isif_cgbgain = { - .ops = &vpfe_isif_ctrl_ops, - .id = VPFE_ISIF_CID_CGBGAIN, - .name = "CGBGAIN", - .type = V4L2_CTRL_TYPE_INTEGER, - .min = 0, - .max = (1 << 12) - 1, - .step = 1, - .def = 0, -}; - -static const struct v4l2_ctrl_config vpfe_isif_cbgain = { - .ops = &vpfe_isif_ctrl_ops, - .id = VPFE_ISIF_CID_CBGAIN, - .name = "CBGAIN", - .type = V4L2_CTRL_TYPE_INTEGER, - .min = 0, - .max = (1 << 12) - 1, - .step = 1, - .def = 0, -}; - -static const struct v4l2_ctrl_config vpfe_isif_gain_offset = { - .ops = &vpfe_isif_ctrl_ops, - .id = VPFE_ISIF_CID_GAIN_OFFSET, - .name = "Gain Offset", - .type = V4L2_CTRL_TYPE_INTEGER, - .min = 0, - .max = (1 << 12) - 1, - .step = 1, - .def = 0, -}; - -static void isif_remove(struct vpfe_isif_device *isif, - struct platform_device *pdev) -{ - struct resource *res; - int i = 0; - - iounmap(isif->isif_cfg.base_addr); - iounmap(isif->isif_cfg.linear_tbl0_addr); - iounmap(isif->isif_cfg.linear_tbl1_addr); - - while (i < 3) { - res = platform_get_resource(pdev, IORESOURCE_MEM, i); - if (res) - release_mem_region(res->start, - resource_size(res)); - i++; - } -} - -static void isif_config_defaults(struct vpfe_isif_device *isif) -{ - isif->isif_cfg.ycbcr.v4l2_pix_fmt = V4L2_PIX_FMT_UYVY; - isif->isif_cfg.ycbcr.pix_fmt = ISIF_PIXFMT_YCBCR_8BIT; - isif->isif_cfg.ycbcr.frm_fmt = ISIF_FRMFMT_INTERLACED; - isif->isif_cfg.ycbcr.fid_pol = VPFE_PINPOL_POSITIVE; - isif->isif_cfg.ycbcr.vd_pol = VPFE_PINPOL_POSITIVE; - isif->isif_cfg.ycbcr.hd_pol = VPFE_PINPOL_POSITIVE; - isif->isif_cfg.ycbcr.pix_order = ISIF_PIXORDER_CBYCRY; - isif->isif_cfg.ycbcr.buf_type = ISIF_BUFTYPE_FLD_INTERLEAVED; - - isif->isif_cfg.bayer.v4l2_pix_fmt = V4L2_PIX_FMT_SGRBG10ALAW8; - isif->isif_cfg.bayer.pix_fmt = ISIF_PIXFMT_RAW; - isif->isif_cfg.bayer.frm_fmt = ISIF_FRMFMT_PROGRESSIVE; - isif->isif_cfg.bayer.fid_pol = VPFE_PINPOL_POSITIVE; - isif->isif_cfg.bayer.vd_pol = VPFE_PINPOL_POSITIVE; - isif->isif_cfg.bayer.hd_pol = VPFE_PINPOL_POSITIVE; - isif->isif_cfg.bayer.cfa_pat = ISIF_CFA_PAT_MOSAIC; - isif->isif_cfg.bayer.data_msb = ISIF_BIT_MSB_11; - isif->isif_cfg.data_pack = ISIF_PACK_8BIT; -} -/* - * vpfe_isif_init() - Initialize V4L2 subdev and media entity - * @isif: VPFE isif module - * @pdev: Pointer to platform device structure. - * Return 0 on success and a negative error code on failure. - */ -int vpfe_isif_init(struct vpfe_isif_device *isif, struct platform_device *pdev) -{ - struct v4l2_subdev *sd = &isif->subdev; - struct media_pad *pads = &isif->pads[0]; - struct media_entity *me = &sd->entity; - static resource_size_t res_len; - struct resource *res; - void __iomem *addr; - int status; - int i = 0; - - /* Get the ISIF base address, linearization table0 and table1 addr. */ - while (i < 3) { - res = platform_get_resource(pdev, IORESOURCE_MEM, i); - if (!res) { - status = -ENOENT; - goto fail_nobase_res; - } - res_len = resource_size(res); - res = request_mem_region(res->start, res_len, res->name); - if (!res) { - status = -EBUSY; - goto fail_nobase_res; - } - addr = ioremap_nocache(res->start, res_len); - if (!addr) { - status = -EBUSY; - goto fail_base_iomap; - } - switch (i) { - case 0: - /* ISIF base address */ - isif->isif_cfg.base_addr = addr; - break; - case 1: - /* ISIF linear tbl0 address */ - isif->isif_cfg.linear_tbl0_addr = addr; - break; - default: - /* ISIF linear tbl0 address */ - isif->isif_cfg.linear_tbl1_addr = addr; - break; - } - i++; - } - davinci_cfg_reg(DM365_VIN_CAM_WEN); - davinci_cfg_reg(DM365_VIN_CAM_VD); - davinci_cfg_reg(DM365_VIN_CAM_HD); - davinci_cfg_reg(DM365_VIN_YIN4_7_EN); - davinci_cfg_reg(DM365_VIN_YIN0_3_EN); - - /* queue ops */ - isif->video_out.ops = &isif_video_ops; - v4l2_subdev_init(sd, &isif_v4l2_ops); - sd->internal_ops = &isif_v4l2_internal_ops; - strscpy(sd->name, "DAVINCI ISIF", sizeof(sd->name)); - sd->grp_id = 1 << 16; /* group ID for davinci subdevs */ - v4l2_set_subdevdata(sd, isif); - sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE; - pads[ISIF_PAD_SINK].flags = MEDIA_PAD_FL_SINK; - pads[ISIF_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; - - isif->input = ISIF_INPUT_NONE; - isif->output = ISIF_OUTPUT_NONE; - me->ops = &isif_media_ops; - status = media_entity_pads_init(me, ISIF_PADS_NUM, pads); - if (status) - goto isif_fail; - isif->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - status = vpfe_video_init(&isif->video_out, "ISIF"); - if (status) { - pr_err("Failed to init isif-out video device\n"); - goto isif_fail; - } - v4l2_ctrl_handler_init(&isif->ctrls, 6); - v4l2_ctrl_new_custom(&isif->ctrls, &vpfe_isif_crgain, NULL); - v4l2_ctrl_new_custom(&isif->ctrls, &vpfe_isif_cgrgain, NULL); - v4l2_ctrl_new_custom(&isif->ctrls, &vpfe_isif_cgbgain, NULL); - v4l2_ctrl_new_custom(&isif->ctrls, &vpfe_isif_cbgain, NULL); - v4l2_ctrl_new_custom(&isif->ctrls, &vpfe_isif_gain_offset, NULL); - v4l2_ctrl_new_custom(&isif->ctrls, &vpfe_isif_dpcm_pred, NULL); - - v4l2_ctrl_handler_setup(&isif->ctrls); - sd->ctrl_handler = &isif->ctrls; - isif_config_defaults(isif); - return 0; -fail_base_iomap: - release_mem_region(res->start, res_len); - i--; -fail_nobase_res: - if (isif->isif_cfg.base_addr) - iounmap(isif->isif_cfg.base_addr); - if (isif->isif_cfg.linear_tbl0_addr) - iounmap(isif->isif_cfg.linear_tbl0_addr); - - while (i >= 0) { - res = platform_get_resource(pdev, IORESOURCE_MEM, i); - release_mem_region(res->start, res_len); - i--; - } - return status; -isif_fail: - v4l2_ctrl_handler_free(&isif->ctrls); - isif_remove(isif, pdev); - return status; -} - -/* - * vpfe_isif_cleanup - isif module cleanup - * @isif: pointer to isif subdevice - * @dev: pointer to platform device structure - */ -void -vpfe_isif_cleanup(struct vpfe_isif_device *isif, struct platform_device *pdev) -{ - isif_remove(isif, pdev); -} diff --git a/drivers/staging/media/davinci_vpfe/dm365_isif.h b/drivers/staging/media/davinci_vpfe/dm365_isif.h deleted file mode 100644 index 0e1fe472fb2b..000000000000 --- a/drivers/staging/media/davinci_vpfe/dm365_isif.h +++ /dev/null @@ -1,200 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) 2012 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Contributors: - * Manjunath Hadli <manjunath.hadli@ti.com> - * Prabhakar Lad <prabhakar.lad@ti.com> - */ - -#ifndef _DAVINCI_VPFE_DM365_ISIF_H -#define _DAVINCI_VPFE_DM365_ISIF_H - -#include <linux/platform_device.h> - -#include <mach/mux.h> - -#include <media/davinci/vpfe_types.h> -#include <media/v4l2-ctrls.h> -#include <media/v4l2-device.h> - -#include "davinci_vpfe_user.h" -#include "dm365_isif_regs.h" -#include "vpfe_video.h" - -#define ISIF_CULLING_HCAPT_ODD 0xff -#define ISIF_CULLING_HCAPT_EVEN 0xff -#define ISIF_CULLING_VCAPT 0xff - -#define ISIF_CADU_BITS 0x07ff -#define ISIF_CADL_BITS 0x0ffff - -enum isif_pixfmt { - ISIF_PIXFMT_RAW = 0, - ISIF_PIXFMT_YCBCR_16BIT = 1, - ISIF_PIXFMT_YCBCR_8BIT = 2, -}; - -enum isif_frmfmt { - ISIF_FRMFMT_PROGRESSIVE = 0, - ISIF_FRMFMT_INTERLACED = 1, -}; - -/* PIXEL ORDER IN MEMORY from LSB to MSB */ -/* only applicable for 8-bit input mode */ -enum isif_pixorder { - ISIF_PIXORDER_YCBYCR = 0, - ISIF_PIXORDER_CBYCRY = 1, -}; - -enum isif_buftype { - ISIF_BUFTYPE_FLD_INTERLEAVED = 0, - ISIF_BUFTYPE_FLD_SEPARATED = 1, -}; - -struct isif_ycbcr_config { - /* v4l2 pixel format */ - unsigned long v4l2_pix_fmt; - /* isif pixel format */ - enum isif_pixfmt pix_fmt; - /* isif frame format */ - enum isif_frmfmt frm_fmt; - /* isif crop window */ - struct v4l2_rect win; - /* field polarity */ - enum vpfe_pin_pol fid_pol; - /* interface VD polarity */ - enum vpfe_pin_pol vd_pol; - /* interface HD polarity */ - enum vpfe_pin_pol hd_pol; - /* isif pix order. Only used for ycbcr capture */ - enum isif_pixorder pix_order; - /* isif buffer type. Only used for ycbcr capture */ - enum isif_buftype buf_type; -}; - -enum isif_cfa_pattern { - ISIF_CFA_PAT_MOSAIC = 0, - ISIF_CFA_PAT_STRIPE = 1, -}; - -enum isif_data_msb { - /* MSB b15 */ - ISIF_BIT_MSB_15 = 0, - /* MSB b14 */ - ISIF_BIT_MSB_14 = 1, - /* MSB b13 */ - ISIF_BIT_MSB_13 = 2, - /* MSB b12 */ - ISIF_BIT_MSB_12 = 3, - /* MSB b11 */ - ISIF_BIT_MSB_11 = 4, - /* MSB b10 */ - ISIF_BIT_MSB_10 = 5, - /* MSB b9 */ - ISIF_BIT_MSB_9 = 6, - /* MSB b8 */ - ISIF_BIT_MSB_8 = 7, - /* MSB b7 */ - ISIF_BIT_MSB_7 = 8, -}; - -struct isif_params_raw { - /* v4l2 pixel format */ - unsigned long v4l2_pix_fmt; - /* isif pixel format */ - enum isif_pixfmt pix_fmt; - /* isif frame format */ - enum isif_frmfmt frm_fmt; - /* video window */ - struct v4l2_rect win; - /* field polarity */ - enum vpfe_pin_pol fid_pol; - /* interface VD polarity */ - enum vpfe_pin_pol vd_pol; - /* interface HD polarity */ - enum vpfe_pin_pol hd_pol; - /* buffer type. Applicable for interlaced mode */ - enum isif_buftype buf_type; - /* cfa pattern */ - enum isif_cfa_pattern cfa_pat; - /* Data MSB position */ - enum isif_data_msb data_msb; - /* Enable horizontal flip */ - unsigned char horz_flip_en; - /* Enable image invert vertically */ - unsigned char image_invert_en; - unsigned char dpcm_predictor; - struct vpfe_isif_raw_config config_params; -}; - -enum isif_data_pack { - ISIF_PACK_16BIT = 0, - ISIF_PACK_12BIT = 1, - ISIF_PACK_8BIT = 2, -}; - -struct isif_gain_values { - unsigned int cr_gain; - unsigned int cgr_gain; - unsigned int cgb_gain; - unsigned int cb_gain; - unsigned int offset; -}; - -struct isif_oper_config { - struct isif_ycbcr_config ycbcr; - struct isif_params_raw bayer; - enum isif_data_pack data_pack; - struct isif_gain_values isif_gain_params; - void __iomem *base_addr; - void __iomem *linear_tbl0_addr; - void __iomem *linear_tbl1_addr; -}; - -#define ISIF_PAD_SINK 0 -#define ISIF_PAD_SOURCE 1 - -#define ISIF_PADS_NUM 2 - -enum isif_input_entity { - ISIF_INPUT_NONE = 0, - ISIF_INPUT_PARALLEL = 1, -}; - -#define ISIF_OUTPUT_NONE (0) -#define ISIF_OUTPUT_MEMORY (1 << 0) -#define ISIF_OUTPUT_IPIPEIF (1 << 1) - -struct vpfe_isif_device { - struct v4l2_subdev subdev; - struct media_pad pads[ISIF_PADS_NUM]; - struct v4l2_mbus_framefmt formats[ISIF_PADS_NUM]; - enum isif_input_entity input; - unsigned int output; - struct v4l2_ctrl_handler ctrls; - struct v4l2_rect crop; - struct isif_oper_config isif_cfg; - struct vpfe_video_device video_out; -}; - -enum v4l2_field vpfe_isif_get_fid(struct vpfe_device *vpfe_dev); -void vpfe_isif_unregister_entities(struct vpfe_isif_device *isif); -int vpfe_isif_register_entities(struct vpfe_isif_device *isif, - struct v4l2_device *dev); -int vpfe_isif_init(struct vpfe_isif_device *isif, struct platform_device *pdev); -void vpfe_isif_cleanup(struct vpfe_isif_device *vpfe_isif, - struct platform_device *pdev); -void vpfe_isif_vidint1_isr(struct vpfe_isif_device *isif); -void vpfe_isif_buffer_isr(struct vpfe_isif_device *isif); - -#endif /* _DAVINCI_VPFE_DM365_ISIF_H */ diff --git a/drivers/staging/media/davinci_vpfe/dm365_isif_regs.h b/drivers/staging/media/davinci_vpfe/dm365_isif_regs.h deleted file mode 100644 index 6695680817b9..000000000000 --- a/drivers/staging/media/davinci_vpfe/dm365_isif_regs.h +++ /dev/null @@ -1,291 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) 2012 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Contributors: - * Manjunath Hadli <manjunath.hadli@ti.com> - * Prabhakar Lad <prabhakar.lad@ti.com> - */ - -#ifndef _DAVINCI_VPFE_DM365_ISIF_REGS_H -#define _DAVINCI_VPFE_DM365_ISIF_REGS_H - -/* ISIF registers relative offsets */ -#define SYNCEN 0x00 -#define MODESET 0x04 -#define HDW 0x08 -#define VDW 0x0c -#define PPLN 0x10 -#define LPFR 0x14 -#define SPH 0x18 -#define LNH 0x1c -#define SLV0 0x20 -#define SLV1 0x24 -#define LNV 0x28 -#define CULH 0x2c -#define CULV 0x30 -#define HSIZE 0x34 -#define SDOFST 0x38 -#define CADU 0x3c -#define CADL 0x40 -#define LINCFG0 0x44 -#define LINCFG1 0x48 -#define CCOLP 0x4c -#define CRGAIN 0x50 -#define CGRGAIN 0x54 -#define CGBGAIN 0x58 -#define CBGAIN 0x5c -#define COFSTA 0x60 -#define FLSHCFG0 0x64 -#define FLSHCFG1 0x68 -#define FLSHCFG2 0x6c -#define VDINT0 0x70 -#define VDINT1 0x74 -#define VDINT2 0x78 -#define MISC 0x7c -#define CGAMMAWD 0x80 -#define REC656IF 0x84 -#define CCDCFG 0x88 -/***************************************************** - * Defect Correction registers - *****************************************************/ -#define DFCCTL 0x8c -#define VDFSATLV 0x90 -#define DFCMEMCTL 0x94 -#define DFCMEM0 0x98 -#define DFCMEM1 0x9c -#define DFCMEM2 0xa0 -#define DFCMEM3 0xa4 -#define DFCMEM4 0xa8 -/**************************************************** - * Black Clamp registers - ****************************************************/ -#define CLAMPCFG 0xac -#define CLDCOFST 0xb0 -#define CLSV 0xb4 -#define CLHWIN0 0xb8 -#define CLHWIN1 0xbc -#define CLHWIN2 0xc0 -#define CLVRV 0xc4 -#define CLVWIN0 0xc8 -#define CLVWIN1 0xcc -#define CLVWIN2 0xd0 -#define CLVWIN3 0xd4 -/**************************************************** - * Lense Shading Correction - ****************************************************/ -#define DATAHOFST 0xd8 -#define DATAVOFST 0xdc -#define LSCHVAL 0xe0 -#define LSCVVAL 0xe4 -#define TWODLSCCFG 0xe8 -#define TWODLSCOFST 0xec -#define TWODLSCINI 0xf0 -#define TWODLSCGRBU 0xf4 -#define TWODLSCGRBL 0xf8 -#define TWODLSCGROF 0xfc -#define TWODLSCORBU 0x100 -#define TWODLSCORBL 0x104 -#define TWODLSCOROF 0x108 -#define TWODLSCIRQEN 0x10c -#define TWODLSCIRQST 0x110 -/**************************************************** - * Data formatter - ****************************************************/ -#define FMTCFG 0x114 -#define FMTPLEN 0x118 -#define FMTSPH 0x11c -#define FMTLNH 0x120 -#define FMTSLV 0x124 -#define FMTLNV 0x128 -#define FMTRLEN 0x12c -#define FMTHCNT 0x130 -#define FMTAPTR_BASE 0x134 -/* Below macro for addresses FMTAPTR0 - FMTAPTR15 */ -#define FMTAPTR(i) (FMTAPTR_BASE + (i * 4)) -#define FMTPGMVF0 0x174 -#define FMTPGMVF1 0x178 -#define FMTPGMAPU0 0x17c -#define FMTPGMAPU1 0x180 -#define FMTPGMAPS0 0x184 -#define FMTPGMAPS1 0x188 -#define FMTPGMAPS2 0x18c -#define FMTPGMAPS3 0x190 -#define FMTPGMAPS4 0x194 -#define FMTPGMAPS5 0x198 -#define FMTPGMAPS6 0x19c -#define FMTPGMAPS7 0x1a0 -/************************************************ - * Color Space Converter - ************************************************/ -#define CSCCTL 0x1a4 -#define CSCM0 0x1a8 -#define CSCM1 0x1ac -#define CSCM2 0x1b0 -#define CSCM3 0x1b4 -#define CSCM4 0x1b8 -#define CSCM5 0x1bc -#define CSCM6 0x1c0 -#define CSCM7 0x1c4 -#define OBWIN0 0x1c8 -#define OBWIN1 0x1cc -#define OBWIN2 0x1d0 -#define OBWIN3 0x1d4 -#define OBVAL0 0x1d8 -#define OBVAL1 0x1dc -#define OBVAL2 0x1e0 -#define OBVAL3 0x1e4 -#define OBVAL4 0x1e8 -#define OBVAL5 0x1ec -#define OBVAL6 0x1f0 -#define OBVAL7 0x1f4 -#define CLKCTL 0x1f8 - -/* Masks & Shifts below */ -#define START_PX_HOR_MASK 0x7fff -#define NUM_PX_HOR_MASK 0x7fff -#define START_VER_ONE_MASK 0x7fff -#define START_VER_TWO_MASK 0x7fff -#define NUM_LINES_VER 0x7fff - -/* gain - offset masks */ -#define OFFSET_MASK 0xfff -#define GAIN_SDRAM_EN_SHIFT 12 -#define GAIN_IPIPE_EN_SHIFT 13 -#define GAIN_H3A_EN_SHIFT 14 -#define OFST_SDRAM_EN_SHIFT 8 -#define OFST_IPIPE_EN_SHIFT 9 -#define OFST_H3A_EN_SHIFT 10 -#define GAIN_OFFSET_EN_MASK 0x7700 - -/* Culling */ -#define CULL_PAT_EVEN_LINE_SHIFT 8 - -/* CCDCFG register */ -#define ISIF_YCINSWP_RAW (0x00 << 4) -#define ISIF_YCINSWP_YCBCR (0x01 << 4) -#define ISIF_CCDCFG_FIDMD_LATCH_VSYNC (0x00 << 6) -#define ISIF_CCDCFG_WENLOG_AND (0x00 << 8) -#define ISIF_CCDCFG_TRGSEL_WEN (0x00 << 9) -#define ISIF_CCDCFG_EXTRG_DISABLE (0x00 << 10) -#define ISIF_LATCH_ON_VSYNC_DISABLE (0x01 << 15) -#define ISIF_LATCH_ON_VSYNC_ENABLE (0x00 << 15) -#define ISIF_DATA_PACK_MASK 0x03 -#define ISIF_PIX_ORDER_SHIFT 11 -#define ISIF_PIX_ORDER_MASK 0x01 -#define ISIF_BW656_ENABLE (0x01 << 5) - -/* MODESET registers */ -#define ISIF_VDHDOUT_INPUT (0x00 << 0) -#define ISIF_INPUT_MASK 0x03 -#define ISIF_INPUT_SHIFT 12 -#define ISIF_FID_POL_MASK 0x01 -#define ISIF_FID_POL_SHIFT 4 -#define ISIF_HD_POL_MASK 0x01 -#define ISIF_HD_POL_SHIFT 3 -#define ISIF_VD_POL_MASK 0x01 -#define ISIF_VD_POL_SHIFT 2 -#define ISIF_DATAPOL_NORMAL 0x00 -#define ISIF_DATAPOL_MASK 0x01 -#define ISIF_DATAPOL_SHIFT 6 -#define ISIF_EXWEN_DISABLE 0x00 -#define ISIF_EXWEN_MASK 0x01 -#define ISIF_EXWEN_SHIFT 5 -#define ISIF_FRM_FMT_MASK 0x01 -#define ISIF_FRM_FMT_SHIFT 7 -#define ISIF_DATASFT_MASK 0x07 -#define ISIF_DATASFT_SHIFT 8 -#define ISIF_LPF_SHIFT 14 -#define ISIF_LPF_MASK 0x1 - -/* GAMMAWD registers */ -#define ISIF_ALAW_GAMA_WD_MASK 0xf -#define ISIF_ALAW_GAMA_WD_SHIFT 1 -#define ISIF_ALAW_ENABLE 0x01 -#define ISIF_GAMMAWD_CFA_MASK 0x01 -#define ISIF_GAMMAWD_CFA_SHIFT 5 - -/* HSIZE registers */ -#define ISIF_HSIZE_FLIP_MASK 0x01 -#define ISIF_HSIZE_FLIP_SHIFT 12 -#define ISIF_LINEOFST_MASK 0xfff - -/* MISC registers */ -#define ISIF_DPCM_EN_SHIFT 12 -#define ISIF_DPCM_PREDICTOR_SHIFT 13 -#define ISIF_DPCM_PREDICTOR_MASK 1 - -/* Black clamp related */ -#define ISIF_BC_DCOFFSET_MASK 0x1fff -#define ISIF_BC_MODE_COLOR_MASK 1 -#define ISIF_BC_MODE_COLOR_SHIFT 4 -#define ISIF_HORZ_BC_MODE_MASK 3 -#define ISIF_HORZ_BC_MODE_SHIFT 1 -#define ISIF_HORZ_BC_WIN_COUNT_MASK 0x1f -#define ISIF_HORZ_BC_WIN_SEL_SHIFT 5 -#define ISIF_HORZ_BC_PIX_LIMIT_SHIFT 6 -#define ISIF_HORZ_BC_WIN_H_SIZE_MASK 3 -#define ISIF_HORZ_BC_WIN_H_SIZE_SHIFT 8 -#define ISIF_HORZ_BC_WIN_V_SIZE_MASK 3 -#define ISIF_HORZ_BC_WIN_V_SIZE_SHIFT 12 -#define ISIF_HORZ_BC_WIN_START_H_MASK 0x1fff -#define ISIF_HORZ_BC_WIN_START_V_MASK 0x1fff -#define ISIF_VERT_BC_OB_H_SZ_MASK 7 -#define ISIF_VERT_BC_RST_VAL_SEL_MASK 3 -#define ISIF_VERT_BC_RST_VAL_SEL_SHIFT 4 -#define ISIF_VERT_BC_LINE_AVE_COEF_SHIFT 8 -#define ISIF_VERT_BC_OB_START_HORZ_MASK 0x1fff -#define ISIF_VERT_BC_OB_START_VERT_MASK 0x1fff -#define ISIF_VERT_BC_OB_VERT_SZ_MASK 0x1fff -#define ISIF_VERT_BC_RST_VAL_MASK 0xfff -#define ISIF_BC_VERT_START_SUB_V_MASK 0x1fff - -/* VDFC registers */ -#define ISIF_VDFC_EN_SHIFT 4 -#define ISIF_VDFC_CORR_MOD_MASK 3 -#define ISIF_VDFC_CORR_MOD_SHIFT 5 -#define ISIF_VDFC_CORR_WHOLE_LN_SHIFT 7 -#define ISIF_VDFC_LEVEL_SHFT_MASK 7 -#define ISIF_VDFC_LEVEL_SHFT_SHIFT 8 -#define ISIF_VDFC_SAT_LEVEL_MASK 0xfff -#define ISIF_VDFC_POS_MASK 0x1fff -#define ISIF_DFCMEMCTL_DFCMARST_SHIFT 2 - -/* CSC registers */ -#define ISIF_CSC_COEF_INTEG_MASK 7 -#define ISIF_CSC_COEF_DECIMAL_MASK 0x1f -#define ISIF_CSC_COEF_INTEG_SHIFT 5 -#define ISIF_CSCM_MSB_SHIFT 8 -#define ISIF_DF_CSC_SPH_MASK 0x1fff -#define ISIF_DF_CSC_LNH_MASK 0x1fff -#define ISIF_DF_CSC_SLV_MASK 0x1fff -#define ISIF_DF_CSC_LNV_MASK 0x1fff -#define ISIF_DF_NUMLINES 0x7fff -#define ISIF_DF_NUMPIX 0x1fff - -/* Offsets for LSC/DFC/Gain */ -#define ISIF_DATA_H_OFFSET_MASK 0x1fff -#define ISIF_DATA_V_OFFSET_MASK 0x1fff - -/* Linearization */ -#define ISIF_LIN_CORRSFT_MASK 7 -#define ISIF_LIN_CORRSFT_SHIFT 4 -#define ISIF_LIN_SCALE_FACT_INTEG_SHIFT 10 -#define ISIF_LIN_SCALE_FACT_DECIMAL_MASK 0x3ff -#define ISIF_LIN_ENTRY_MASK 0x3ff - -/* masks and shifts*/ -#define ISIF_SYNCEN_VDHDEN_MASK (1 << 0) -#define ISIF_SYNCEN_WEN_MASK (1 << 1) -#define ISIF_SYNCEN_WEN_SHIFT 1 - -#endif /* _DAVINCI_VPFE_DM365_ISIF_REGS_H */ diff --git a/drivers/staging/media/davinci_vpfe/dm365_resizer.c b/drivers/staging/media/davinci_vpfe/dm365_resizer.c deleted file mode 100644 index 7adf1fae43f6..000000000000 --- a/drivers/staging/media/davinci_vpfe/dm365_resizer.c +++ /dev/null @@ -1,1995 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2012 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Contributors: - * Manjunath Hadli <manjunath.hadli@ti.com> - * Prabhakar Lad <prabhakar.lad@ti.com> - * - * - * Resizer allows upscaling or downscaling a image to a desired - * resolution. There are 2 resizer modules. both operating on the - * same input image, but can have different output resolution. - */ - -#include "dm365_ipipe_hw.h" -#include "dm365_resizer.h" - -#define MIN_IN_WIDTH 32 -#define MIN_IN_HEIGHT 32 -#define MAX_IN_WIDTH 4095 -#define MAX_IN_HEIGHT 4095 -#define MIN_OUT_WIDTH 16 -#define MIN_OUT_HEIGHT 2 - -static const unsigned int resizer_input_formats[] = { - MEDIA_BUS_FMT_UYVY8_2X8, - MEDIA_BUS_FMT_Y8_1X8, - MEDIA_BUS_FMT_UV8_1X8, - MEDIA_BUS_FMT_SGRBG12_1X12, -}; - -static const unsigned int resizer_output_formats[] = { - MEDIA_BUS_FMT_UYVY8_2X8, - MEDIA_BUS_FMT_Y8_1X8, - MEDIA_BUS_FMT_UV8_1X8, - MEDIA_BUS_FMT_YDYUYDYV8_1X16, - MEDIA_BUS_FMT_SGRBG12_1X12, -}; - -/* resizer_calculate_line_length() - This function calculates the line length of - * various image planes at the input and - * output. - */ -static void -resizer_calculate_line_length(u32 pix, int width, int height, - int *line_len, int *line_len_c) -{ - *line_len = 0; - *line_len_c = 0; - - if (pix == MEDIA_BUS_FMT_UYVY8_2X8 || - pix == MEDIA_BUS_FMT_SGRBG12_1X12) { - *line_len = width << 1; - } else { - *line_len = width; - *line_len_c = width; - } - - /* adjust the line len to be a multiple of 32 */ - *line_len += 31; - *line_len &= ~0x1f; - *line_len_c += 31; - *line_len_c &= ~0x1f; -} - -static inline int -resizer_validate_output_image_format(struct device *dev, - struct v4l2_mbus_framefmt *format, - int *in_line_len, int *in_line_len_c) -{ - if (format->code != MEDIA_BUS_FMT_UYVY8_2X8 && - format->code != MEDIA_BUS_FMT_Y8_1X8 && - format->code != MEDIA_BUS_FMT_UV8_1X8 && - format->code != MEDIA_BUS_FMT_YDYUYDYV8_1X16 && - format->code != MEDIA_BUS_FMT_SGRBG12_1X12) { - dev_err(dev, "Invalid Mbus format, %d\n", format->code); - return -EINVAL; - } - if (!format->width || !format->height) { - dev_err(dev, "invalid width or height\n"); - return -EINVAL; - } - resizer_calculate_line_length(format->code, format->width, - format->height, in_line_len, in_line_len_c); - return 0; -} - -static void -resizer_configure_passthru(struct vpfe_resizer_device *resizer, int bypass) -{ - struct resizer_params *param = &resizer->config; - - param->rsz_rsc_param[RSZ_A].cen = DISABLE; - param->rsz_rsc_param[RSZ_A].yen = DISABLE; - param->rsz_rsc_param[RSZ_A].v_phs_y = 0; - param->rsz_rsc_param[RSZ_A].v_phs_c = 0; - param->rsz_rsc_param[RSZ_A].v_dif = 256; - param->rsz_rsc_param[RSZ_A].v_lpf_int_y = 0; - param->rsz_rsc_param[RSZ_A].v_lpf_int_c = 0; - param->rsz_rsc_param[RSZ_A].h_phs = 0; - param->rsz_rsc_param[RSZ_A].h_dif = 256; - param->rsz_rsc_param[RSZ_A].h_lpf_int_y = 0; - param->rsz_rsc_param[RSZ_A].h_lpf_int_c = 0; - param->rsz_rsc_param[RSZ_A].dscale_en = DISABLE; - param->rsz2rgb[RSZ_A].rgb_en = DISABLE; - param->rsz_en[RSZ_A] = ENABLE; - param->rsz_en[RSZ_B] = DISABLE; - if (bypass) { - param->rsz_rsc_param[RSZ_A].i_vps = 0; - param->rsz_rsc_param[RSZ_A].i_hps = 0; - /* Raw Bypass */ - param->rsz_common.passthrough = BYPASS_ON; - } -} - -static void -configure_resizer_out_params(struct vpfe_resizer_device *resizer, int index, - void *output_spec, unsigned char partial, - unsigned int flag) -{ - struct resizer_params *param = &resizer->config; - struct v4l2_mbus_framefmt *outformat; - struct vpfe_rsz_output_spec *output; - - if (index == RSZ_A && - resizer->resizer_a.output == RESIZER_OUTPUT_NONE) { - param->rsz_en[index] = DISABLE; - return; - } - if (index == RSZ_B && - resizer->resizer_b.output == RESIZER_OUTPUT_NONE) { - param->rsz_en[index] = DISABLE; - return; - } - output = output_spec; - param->rsz_en[index] = ENABLE; - if (partial) { - param->rsz_rsc_param[index].h_flip = output->h_flip; - param->rsz_rsc_param[index].v_flip = output->v_flip; - param->rsz_rsc_param[index].v_typ_y = output->v_typ_y; - param->rsz_rsc_param[index].v_typ_c = output->v_typ_c; - param->rsz_rsc_param[index].v_lpf_int_y = - output->v_lpf_int_y; - param->rsz_rsc_param[index].v_lpf_int_c = - output->v_lpf_int_c; - param->rsz_rsc_param[index].h_typ_y = output->h_typ_y; - param->rsz_rsc_param[index].h_typ_c = output->h_typ_c; - param->rsz_rsc_param[index].h_lpf_int_y = - output->h_lpf_int_y; - param->rsz_rsc_param[index].h_lpf_int_c = - output->h_lpf_int_c; - param->rsz_rsc_param[index].dscale_en = - output->en_down_scale; - param->rsz_rsc_param[index].h_dscale_ave_sz = - output->h_dscale_ave_sz; - param->rsz_rsc_param[index].v_dscale_ave_sz = - output->v_dscale_ave_sz; - param->ext_mem_param[index].user_y_ofst = - (output->user_y_ofst + 31) & ~0x1f; - param->ext_mem_param[index].user_c_ofst = - (output->user_c_ofst + 31) & ~0x1f; - return; - } - - if (index == RSZ_A) - outformat = &resizer->resizer_a.formats[RESIZER_PAD_SOURCE]; - else - outformat = &resizer->resizer_b.formats[RESIZER_PAD_SOURCE]; - param->rsz_rsc_param[index].o_vsz = outformat->height - 1; - param->rsz_rsc_param[index].o_hsz = outformat->width - 1; - param->ext_mem_param[index].rsz_sdr_ptr_s_y = output->vst_y; - param->ext_mem_param[index].rsz_sdr_ptr_e_y = outformat->height; - param->ext_mem_param[index].rsz_sdr_ptr_s_c = output->vst_c; - param->ext_mem_param[index].rsz_sdr_ptr_e_c = outformat->height; - - if (!flag) - return; - /* update common parameters */ - param->rsz_rsc_param[index].h_flip = output->h_flip; - param->rsz_rsc_param[index].v_flip = output->v_flip; - param->rsz_rsc_param[index].v_typ_y = output->v_typ_y; - param->rsz_rsc_param[index].v_typ_c = output->v_typ_c; - param->rsz_rsc_param[index].v_lpf_int_y = output->v_lpf_int_y; - param->rsz_rsc_param[index].v_lpf_int_c = output->v_lpf_int_c; - param->rsz_rsc_param[index].h_typ_y = output->h_typ_y; - param->rsz_rsc_param[index].h_typ_c = output->h_typ_c; - param->rsz_rsc_param[index].h_lpf_int_y = output->h_lpf_int_y; - param->rsz_rsc_param[index].h_lpf_int_c = output->h_lpf_int_c; - param->rsz_rsc_param[index].dscale_en = output->en_down_scale; - param->rsz_rsc_param[index].h_dscale_ave_sz = output->h_dscale_ave_sz; - param->rsz_rsc_param[index].v_dscale_ave_sz = output->h_dscale_ave_sz; - param->ext_mem_param[index].user_y_ofst = - (output->user_y_ofst + 31) & ~0x1f; - param->ext_mem_param[index].user_c_ofst = - (output->user_c_ofst + 31) & ~0x1f; -} - -/* - * resizer_calculate_resize_ratios() - Calculates resize ratio for resizer - * A or B. This is called after setting - * the input size or output size. - * @resizer: Pointer to VPFE resizer subdevice. - * @index: index RSZ_A-resizer-A RSZ_B-resizer-B. - */ -static void -resizer_calculate_resize_ratios(struct vpfe_resizer_device *resizer, int index) -{ - struct resizer_params *param = &resizer->config; - struct v4l2_mbus_framefmt *informat, *outformat; - - informat = &resizer->crop_resizer.formats[RESIZER_CROP_PAD_SINK]; - - if (index == RSZ_A) - outformat = &resizer->resizer_a.formats[RESIZER_PAD_SOURCE]; - else - outformat = &resizer->resizer_b.formats[RESIZER_PAD_SOURCE]; - - if (outformat->field != V4L2_FIELD_INTERLACED) - param->rsz_rsc_param[index].v_dif = - ((informat->height) * 256) / (outformat->height); - else - param->rsz_rsc_param[index].v_dif = - ((informat->height >> 1) * 256) / (outformat->height); - param->rsz_rsc_param[index].h_dif = - ((informat->width) * 256) / (outformat->width); -} - -static void resizer_enable_422_420_conversion(struct resizer_params *param, - int index, bool en) -{ - param->rsz_rsc_param[index].cen = en; - param->rsz_rsc_param[index].yen = en; -} - -/* resizer_calculate_sdram_offsets() - This function calculates the offsets from - * start of buffer for the C plane when - * output format is YUV420SP. It also - * calculates the offsets from the start of - * the buffer when the image is flipped - * vertically or horizontally for ycbcr/y/c - * planes. - * @resizer: Pointer to resizer subdevice. - * @index: index RSZ_A-resizer-A RSZ_B-resizer-B. - */ -static int -resizer_calculate_sdram_offsets(struct vpfe_resizer_device *resizer, int index) -{ - struct resizer_params *param = &resizer->config; - struct v4l2_mbus_framefmt *outformat; - int bytesperpixel = 2; - int image_height; - int image_width; - int yuv_420 = 0; - int offset = 0; - - if (index == RSZ_A) - outformat = &resizer->resizer_a.formats[RESIZER_PAD_SOURCE]; - else - outformat = &resizer->resizer_b.formats[RESIZER_PAD_SOURCE]; - - image_height = outformat->height + 1; - image_width = outformat->width + 1; - param->ext_mem_param[index].c_offset = 0; - param->ext_mem_param[index].flip_ofst_y = 0; - param->ext_mem_param[index].flip_ofst_c = 0; - if (outformat->code == MEDIA_BUS_FMT_YDYUYDYV8_1X16) { - /* YUV 420 */ - yuv_420 = 1; - bytesperpixel = 1; - } - - if (param->rsz_rsc_param[index].h_flip) - /* width * bytesperpixel - 1 */ - offset = (image_width * bytesperpixel) - 1; - if (param->rsz_rsc_param[index].v_flip) - offset += (image_height - 1) * - param->ext_mem_param[index].rsz_sdr_oft_y; - param->ext_mem_param[index].flip_ofst_y = offset; - if (!yuv_420) - return 0; - offset = 0; - /* half height for c-plane */ - if (param->rsz_rsc_param[index].h_flip) - /* width * bytesperpixel - 1 */ - offset = image_width - 1; - if (param->rsz_rsc_param[index].v_flip) - offset += (((image_height >> 1) - 1) * - param->ext_mem_param[index].rsz_sdr_oft_c); - param->ext_mem_param[index].flip_ofst_c = offset; - param->ext_mem_param[index].c_offset = - param->ext_mem_param[index].rsz_sdr_oft_y * image_height; - return 0; -} - -static int resizer_configure_output_win(struct vpfe_resizer_device *resizer) -{ - struct resizer_params *param = &resizer->config; - struct vpfe_rsz_output_spec output_specs; - struct v4l2_mbus_framefmt *outformat; - int line_len_c; - int line_len; - int ret; - - outformat = &resizer->resizer_a.formats[RESIZER_PAD_SOURCE]; - - memset(&output_specs, 0x0, sizeof(struct vpfe_rsz_output_spec)); - output_specs.vst_y = param->user_config.vst; - if (outformat->code == MEDIA_BUS_FMT_YDYUYDYV8_1X16) - output_specs.vst_c = param->user_config.vst; - - configure_resizer_out_params(resizer, RSZ_A, &output_specs, 0, 0); - resizer_calculate_line_length(outformat->code, - param->rsz_rsc_param[0].o_hsz + 1, - param->rsz_rsc_param[0].o_vsz + 1, - &line_len, &line_len_c); - param->ext_mem_param[0].rsz_sdr_oft_y = line_len; - param->ext_mem_param[0].rsz_sdr_oft_c = line_len_c; - resizer_calculate_resize_ratios(resizer, RSZ_A); - if (param->rsz_en[RSZ_B]) - resizer_calculate_resize_ratios(resizer, RSZ_B); - - if (outformat->code == MEDIA_BUS_FMT_YDYUYDYV8_1X16) - resizer_enable_422_420_conversion(param, RSZ_A, ENABLE); - else - resizer_enable_422_420_conversion(param, RSZ_A, DISABLE); - - ret = resizer_calculate_sdram_offsets(resizer, RSZ_A); - if (!ret && param->rsz_en[RSZ_B]) - ret = resizer_calculate_sdram_offsets(resizer, RSZ_B); - - if (ret) - pr_err("Error in calculating sdram offsets\n"); - return ret; -} - -static int -resizer_calculate_down_scale_f_div_param(struct device *dev, - int input_width, int output_width, - struct resizer_scale_param *param) -{ - /* rsz = R, input_width = H, output width = h in the equation */ - unsigned int two_power; - unsigned int upper_h1; - unsigned int upper_h2; - unsigned int val1; - unsigned int val; - unsigned int rsz; - unsigned int h1; - unsigned int h2; - unsigned int o; - unsigned int n; - - upper_h1 = input_width >> 1; - n = param->h_dscale_ave_sz; - /* 2 ^ (scale+1) */ - two_power = 1 << (n + 1); - upper_h1 = (upper_h1 >> (n + 1)) << (n + 1); - upper_h2 = input_width - upper_h1; - if (upper_h2 % two_power) { - dev_err(dev, "frame halves to be a multiple of 2 power n+1\n"); - return -EINVAL; - } - two_power = 1 << n; - rsz = (input_width << 8) / output_width; - val = rsz * two_power; - val = ((upper_h1 << 8) / val) + 1; - if (!(val % 2)) { - h1 = val; - } else { - val = upper_h1 << 8; - val >>= n + 1; - val -= rsz >> 1; - val /= rsz << 1; - val <<= 1; - val += 2; - h1 = val; - } - o = 10 + (two_power << 2); - if (((input_width << 7) / rsz) % 2) - o += ((DIV_ROUND_UP(rsz, 1024) << 1) << n); - h2 = output_width - h1; - /* phi */ - val = (h1 * rsz) - (((upper_h1 - (o - 10)) / two_power) << 8); - /* skip */ - val1 = ((val - 1024) >> 9) << 1; - param->f_div.num_passes = MAX_PASSES; - param->f_div.pass[0].o_hsz = h1 - 1; - param->f_div.pass[0].i_hps = 0; - param->f_div.pass[0].h_phs = 0; - param->f_div.pass[0].src_hps = 0; - param->f_div.pass[0].src_hsz = upper_h1 + o; - param->f_div.pass[1].o_hsz = h2 - 1; - param->f_div.pass[1].i_hps = 10 + (val1 * two_power); - param->f_div.pass[1].h_phs = val - (val1 << 8); - param->f_div.pass[1].src_hps = upper_h1 - o; - param->f_div.pass[1].src_hsz = upper_h2 + o; - - return 0; -} - -static int -resizer_configure_common_in_params(struct vpfe_resizer_device *resizer) -{ - struct vpfe_device *vpfe_dev = to_vpfe_device(resizer); - struct resizer_params *param = &resizer->config; - struct vpfe_rsz_config_params *user_config; - struct v4l2_mbus_framefmt *informat; - - informat = &resizer->crop_resizer.formats[RESIZER_CROP_PAD_SINK]; - user_config = &resizer->config.user_config; - param->rsz_common.vps = param->user_config.vst; - param->rsz_common.hps = param->user_config.hst; - - if (vpfe_ipipeif_decimation_enabled(vpfe_dev)) - param->rsz_common.hsz = ((informat->width - 1) * - IPIPEIF_RSZ_CONST) / vpfe_ipipeif_get_rsz(vpfe_dev); - else - param->rsz_common.hsz = informat->width - 1; - - if (informat->field == V4L2_FIELD_INTERLACED) - param->rsz_common.vsz = (informat->height - 1) >> 1; - else - param->rsz_common.vsz = informat->height - 1; - - param->rsz_common.raw_flip = 0; - - if (resizer->crop_resizer.input == RESIZER_CROP_INPUT_IPIPEIF) - param->rsz_common.source = IPIPEIF_DATA; - else - param->rsz_common.source = IPIPE_DATA; - - switch (informat->code) { - case MEDIA_BUS_FMT_UYVY8_2X8: - param->rsz_common.src_img_fmt = RSZ_IMG_422; - param->rsz_common.raw_flip = 0; - break; - - case MEDIA_BUS_FMT_Y8_1X8: - param->rsz_common.src_img_fmt = RSZ_IMG_420; - /* Select y */ - param->rsz_common.y_c = 0; - param->rsz_common.raw_flip = 0; - break; - - case MEDIA_BUS_FMT_UV8_1X8: - param->rsz_common.src_img_fmt = RSZ_IMG_420; - /* Select y */ - param->rsz_common.y_c = 1; - param->rsz_common.raw_flip = 0; - break; - - case MEDIA_BUS_FMT_SGRBG12_1X12: - param->rsz_common.raw_flip = 1; - break; - - default: - param->rsz_common.src_img_fmt = RSZ_IMG_422; - param->rsz_common.source = IPIPE_DATA; - } - - param->rsz_common.yuv_y_min = user_config->yuv_y_min; - param->rsz_common.yuv_y_max = user_config->yuv_y_max; - param->rsz_common.yuv_c_min = user_config->yuv_c_min; - param->rsz_common.yuv_c_max = user_config->yuv_c_max; - param->rsz_common.out_chr_pos = user_config->out_chr_pos; - param->rsz_common.rsz_seq_crv = user_config->chroma_sample_even; - - return 0; -} -static int -resizer_configure_in_continuous_mode(struct vpfe_resizer_device *resizer) -{ - struct device *dev = resizer->crop_resizer.subdev.v4l2_dev->dev; - struct resizer_params *param = &resizer->config; - struct vpfe_rsz_config_params *cont_config; - int line_len_c; - int line_len; - int ret; - - if (resizer->resizer_a.output != RESIZER_OUTPUT_MEMORY) { - dev_err(dev, "enable resizer - Resizer-A\n"); - return -EINVAL; - } - - cont_config = &resizer->config.user_config; - param->rsz_en[RSZ_A] = ENABLE; - configure_resizer_out_params(resizer, RSZ_A, - &cont_config->output1, 1, 0); - param->rsz_en[RSZ_B] = DISABLE; - param->oper_mode = RESIZER_MODE_CONTINUOUS; - - if (resizer->resizer_b.output == RESIZER_OUTPUT_MEMORY) { - struct v4l2_mbus_framefmt *outformat2; - - param->rsz_en[RSZ_B] = ENABLE; - outformat2 = &resizer->resizer_b.formats[RESIZER_PAD_SOURCE]; - ret = resizer_validate_output_image_format(dev, outformat2, - &line_len, &line_len_c); - if (ret) - return ret; - param->ext_mem_param[RSZ_B].rsz_sdr_oft_y = line_len; - param->ext_mem_param[RSZ_B].rsz_sdr_oft_c = line_len_c; - configure_resizer_out_params(resizer, RSZ_B, - &cont_config->output2, 0, 1); - if (outformat2->code == MEDIA_BUS_FMT_YDYUYDYV8_1X16) - resizer_enable_422_420_conversion(param, - RSZ_B, ENABLE); - else - resizer_enable_422_420_conversion(param, - RSZ_B, DISABLE); - } - resizer_configure_common_in_params(resizer); - ret = resizer_configure_output_win(resizer); - if (ret) - return ret; - - param->rsz_common.passthrough = cont_config->bypass; - if (cont_config->bypass) - resizer_configure_passthru(resizer, 1); - - return 0; -} - -static inline int -resizer_validate_input_image_format(struct device *dev, - u32 pix, - int width, int height, int *line_len) -{ - int val; - - if (pix != MEDIA_BUS_FMT_UYVY8_2X8 && - pix != MEDIA_BUS_FMT_Y8_1X8 && - pix != MEDIA_BUS_FMT_UV8_1X8 && - pix != MEDIA_BUS_FMT_SGRBG12_1X12) { - dev_err(dev, - "resizer validate output: pix format not supported, %d\n", pix); - return -EINVAL; - } - - if (!width || !height) { - dev_err(dev, - "resizer validate input: invalid width or height\n"); - return -EINVAL; - } - - if (pix == MEDIA_BUS_FMT_UV8_1X8) - resizer_calculate_line_length(pix, width, - height, &val, line_len); - else - resizer_calculate_line_length(pix, width, - height, line_len, &val); - - return 0; -} - -static int -resizer_validate_decimation(struct device *dev, enum ipipeif_decimation dec_en, - unsigned char rsz, unsigned char frame_div_mode_en, - int width) -{ - if (dec_en && frame_div_mode_en) { - dev_err(dev, - "dec_en & frame_div_mode_en can not enabled simultaneously\n"); - return -EINVAL; - } - - if (frame_div_mode_en) { - dev_err(dev, "frame_div_mode mode not supported\n"); - return -EINVAL; - } - - if (!dec_en) - return 0; - - if (width <= VPFE_IPIPE_MAX_INPUT_WIDTH) { - dev_err(dev, - "image width to be more than %d for decimation\n", - VPFE_IPIPE_MAX_INPUT_WIDTH); - return -EINVAL; - } - - if (rsz < IPIPEIF_RSZ_MIN || rsz > IPIPEIF_RSZ_MAX) { - dev_err(dev, "rsz range is %d to %d\n", - IPIPEIF_RSZ_MIN, IPIPEIF_RSZ_MAX); - return -EINVAL; - } - - return 0; -} - -/* resizer_calculate_normal_f_div_param() - Algorithm to calculate the frame - * division parameters for resizer. - * in normal mode. - */ -static int -resizer_calculate_normal_f_div_param(struct device *dev, int input_width, - int output_width, struct resizer_scale_param *param) -{ - /* rsz = R, input_width = H, output width = h in the equation */ - unsigned int val1; - unsigned int rsz; - unsigned int val; - unsigned int h1; - unsigned int h2; - unsigned int o; - - if (output_width > input_width) { - dev_err(dev, "frame div mode is used for scale down only\n"); - return -EINVAL; - } - - rsz = (input_width << 8) / output_width; - val = rsz << 1; - val = ((input_width << 8) / val) + 1; - o = 14; - if (!(val % 2)) { - h1 = val; - } else { - val = input_width << 7; - val -= rsz >> 1; - val /= rsz << 1; - val <<= 1; - val += 2; - o += (DIV_ROUND_UP(rsz, 1024) << 1); - h1 = val; - } - h2 = output_width - h1; - /* phi */ - val = (h1 * rsz) - (((input_width >> 1) - o) << 8); - /* skip */ - val1 = ((val - 1024) >> 9) << 1; - param->f_div.num_passes = MAX_PASSES; - param->f_div.pass[0].o_hsz = h1 - 1; - param->f_div.pass[0].i_hps = 0; - param->f_div.pass[0].h_phs = 0; - param->f_div.pass[0].src_hps = 0; - param->f_div.pass[0].src_hsz = (input_width >> 2) + o; - param->f_div.pass[1].o_hsz = h2 - 1; - param->f_div.pass[1].i_hps = val1; - param->f_div.pass[1].h_phs = val - (val1 << 8); - param->f_div.pass[1].src_hps = (input_width >> 2) - o; - param->f_div.pass[1].src_hsz = (input_width >> 2) + o; - - return 0; -} - -static int -resizer_configure_in_single_shot_mode(struct vpfe_resizer_device *resizer) -{ - struct vpfe_rsz_config_params *config = &resizer->config.user_config; - struct device *dev = resizer->crop_resizer.subdev.v4l2_dev->dev; - struct vpfe_device *vpfe_dev = to_vpfe_device(resizer); - struct v4l2_mbus_framefmt *outformat1, *outformat2; - struct resizer_params *param = &resizer->config; - struct v4l2_mbus_framefmt *informat; - int decimation; - int line_len_c; - int line_len; - int rsz; - int ret; - - informat = &resizer->crop_resizer.formats[RESIZER_CROP_PAD_SINK]; - outformat1 = &resizer->resizer_a.formats[RESIZER_PAD_SOURCE]; - outformat2 = &resizer->resizer_b.formats[RESIZER_PAD_SOURCE]; - - decimation = vpfe_ipipeif_decimation_enabled(vpfe_dev); - rsz = vpfe_ipipeif_get_rsz(vpfe_dev); - if (decimation && param->user_config.frame_div_mode_en) { - dev_err(dev, - "dec_en & frame_div_mode_en cannot enabled simultaneously\n"); - return -EINVAL; - } - - ret = resizer_validate_decimation(dev, decimation, rsz, - param->user_config.frame_div_mode_en, informat->width); - if (ret) - return -EINVAL; - - ret = resizer_validate_input_image_format(dev, informat->code, - informat->width, informat->height, &line_len); - if (ret) - return -EINVAL; - - if (resizer->resizer_a.output != RESIZER_OUTPUT_NONE) { - param->rsz_en[RSZ_A] = ENABLE; - ret = resizer_validate_output_image_format(dev, outformat1, - &line_len, &line_len_c); - if (ret) - return ret; - param->ext_mem_param[RSZ_A].rsz_sdr_oft_y = line_len; - param->ext_mem_param[RSZ_A].rsz_sdr_oft_c = line_len_c; - configure_resizer_out_params(resizer, RSZ_A, - ¶m->user_config.output1, 0, 1); - - if (outformat1->code == MEDIA_BUS_FMT_SGRBG12_1X12) - param->rsz_common.raw_flip = 1; - else - param->rsz_common.raw_flip = 0; - - if (outformat1->code == MEDIA_BUS_FMT_YDYUYDYV8_1X16) - resizer_enable_422_420_conversion(param, - RSZ_A, ENABLE); - else - resizer_enable_422_420_conversion(param, - RSZ_A, DISABLE); - } - - if (resizer->resizer_b.output != RESIZER_OUTPUT_NONE) { - param->rsz_en[RSZ_B] = ENABLE; - ret = resizer_validate_output_image_format(dev, outformat2, - &line_len, &line_len_c); - if (ret) - return ret; - param->ext_mem_param[RSZ_B].rsz_sdr_oft_y = line_len; - param->ext_mem_param[RSZ_B].rsz_sdr_oft_c = line_len_c; - configure_resizer_out_params(resizer, RSZ_B, - ¶m->user_config.output2, 0, 1); - if (outformat2->code == MEDIA_BUS_FMT_YDYUYDYV8_1X16) - resizer_enable_422_420_conversion(param, - RSZ_B, ENABLE); - else - resizer_enable_422_420_conversion(param, - RSZ_B, DISABLE); - } - - resizer_configure_common_in_params(resizer); - if (resizer->resizer_a.output != RESIZER_OUTPUT_NONE) { - resizer_calculate_resize_ratios(resizer, RSZ_A); - resizer_calculate_sdram_offsets(resizer, RSZ_A); - /* Overriding resize ratio calculation */ - if (informat->code == MEDIA_BUS_FMT_UV8_1X8) { - param->rsz_rsc_param[RSZ_A].v_dif = - (((informat->height + 1) * 2) * 256) / - (param->rsz_rsc_param[RSZ_A].o_vsz + 1); - } - } - - if (resizer->resizer_b.output != RESIZER_OUTPUT_NONE) { - resizer_calculate_resize_ratios(resizer, RSZ_B); - resizer_calculate_sdram_offsets(resizer, RSZ_B); - /* Overriding resize ratio calculation */ - if (informat->code == MEDIA_BUS_FMT_UV8_1X8) { - param->rsz_rsc_param[RSZ_B].v_dif = - (((informat->height + 1) * 2) * 256) / - (param->rsz_rsc_param[RSZ_B].o_vsz + 1); - } - } - if (param->user_config.frame_div_mode_en && - param->rsz_en[RSZ_A]) { - if (!param->rsz_rsc_param[RSZ_A].dscale_en) - ret = resizer_calculate_normal_f_div_param(dev, - informat->width, - param->rsz_rsc_param[RSZ_A].o_vsz + 1, - ¶m->rsz_rsc_param[RSZ_A]); - else - ret = resizer_calculate_down_scale_f_div_param(dev, - informat->width, - param->rsz_rsc_param[RSZ_A].o_vsz + 1, - ¶m->rsz_rsc_param[RSZ_A]); - if (ret) - return -EINVAL; - } - if (param->user_config.frame_div_mode_en && - param->rsz_en[RSZ_B]) { - if (!param->rsz_rsc_param[RSZ_B].dscale_en) - ret = resizer_calculate_normal_f_div_param(dev, - informat->width, - param->rsz_rsc_param[RSZ_B].o_vsz + 1, - ¶m->rsz_rsc_param[RSZ_B]); - else - ret = resizer_calculate_down_scale_f_div_param(dev, - informat->width, - param->rsz_rsc_param[RSZ_B].o_vsz + 1, - ¶m->rsz_rsc_param[RSZ_B]); - if (ret) - return -EINVAL; - } - param->rsz_common.passthrough = config->bypass; - if (config->bypass) - resizer_configure_passthru(resizer, 1); - return 0; -} - -static void -resizer_set_default_configuration(struct vpfe_resizer_device *resizer) -{ -#define WIDTH_I 640 -#define HEIGHT_I 480 -#define WIDTH_O 640 -#define HEIGHT_O 480 - const struct resizer_params rsz_default_config = { - .oper_mode = RESIZER_MODE_ONE_SHOT, - .rsz_common = { - .vsz = HEIGHT_I - 1, - .hsz = WIDTH_I - 1, - .src_img_fmt = RSZ_IMG_422, - .raw_flip = 1, /* flip preserve Raw format */ - .source = IPIPE_DATA, - .passthrough = BYPASS_OFF, - .yuv_y_max = 255, - .yuv_c_max = 255, - .rsz_seq_crv = DISABLE, - .out_chr_pos = VPFE_IPIPE_YUV422_CHR_POS_COSITE, - }, - .rsz_rsc_param = { - { - .h_flip = DISABLE, - .v_flip = DISABLE, - .cen = DISABLE, - .yen = DISABLE, - .o_vsz = HEIGHT_O - 1, - .o_hsz = WIDTH_O - 1, - .v_dif = 256, - .v_typ_y = VPFE_RSZ_INTP_CUBIC, - .v_typ_c = VPFE_RSZ_INTP_CUBIC, - .h_dif = 256, - .h_typ_y = VPFE_RSZ_INTP_CUBIC, - .h_typ_c = VPFE_RSZ_INTP_CUBIC, - .h_dscale_ave_sz = - VPFE_IPIPE_DWN_SCALE_1_OVER_2, - .v_dscale_ave_sz = - VPFE_IPIPE_DWN_SCALE_1_OVER_2, - }, - { - .h_flip = DISABLE, - .v_flip = DISABLE, - .cen = DISABLE, - .yen = DISABLE, - .o_vsz = HEIGHT_O - 1, - .o_hsz = WIDTH_O - 1, - .v_dif = 256, - .v_typ_y = VPFE_RSZ_INTP_CUBIC, - .v_typ_c = VPFE_RSZ_INTP_CUBIC, - .h_dif = 256, - .h_typ_y = VPFE_RSZ_INTP_CUBIC, - .h_typ_c = VPFE_RSZ_INTP_CUBIC, - .h_dscale_ave_sz = - VPFE_IPIPE_DWN_SCALE_1_OVER_2, - .v_dscale_ave_sz = - VPFE_IPIPE_DWN_SCALE_1_OVER_2, - }, - }, - .rsz2rgb = { - { - .rgb_en = DISABLE - }, - { - .rgb_en = DISABLE - } - }, - .ext_mem_param = { - { - .rsz_sdr_oft_y = WIDTH_O << 1, - .rsz_sdr_ptr_e_y = HEIGHT_O, - .rsz_sdr_oft_c = WIDTH_O, - .rsz_sdr_ptr_e_c = HEIGHT_O >> 1, - }, - { - .rsz_sdr_oft_y = WIDTH_O << 1, - .rsz_sdr_ptr_e_y = HEIGHT_O, - .rsz_sdr_oft_c = WIDTH_O, - .rsz_sdr_ptr_e_c = HEIGHT_O, - }, - }, - .rsz_en[0] = ENABLE, - .rsz_en[1] = DISABLE, - .user_config = { - .output1 = { - .v_typ_y = VPFE_RSZ_INTP_CUBIC, - .v_typ_c = VPFE_RSZ_INTP_CUBIC, - .h_typ_y = VPFE_RSZ_INTP_CUBIC, - .h_typ_c = VPFE_RSZ_INTP_CUBIC, - .h_dscale_ave_sz = - VPFE_IPIPE_DWN_SCALE_1_OVER_2, - .v_dscale_ave_sz = - VPFE_IPIPE_DWN_SCALE_1_OVER_2, - }, - .output2 = { - .v_typ_y = VPFE_RSZ_INTP_CUBIC, - .v_typ_c = VPFE_RSZ_INTP_CUBIC, - .h_typ_y = VPFE_RSZ_INTP_CUBIC, - .h_typ_c = VPFE_RSZ_INTP_CUBIC, - .h_dscale_ave_sz = - VPFE_IPIPE_DWN_SCALE_1_OVER_2, - .v_dscale_ave_sz = - VPFE_IPIPE_DWN_SCALE_1_OVER_2, - }, - .yuv_y_max = 255, - .yuv_c_max = 255, - .out_chr_pos = VPFE_IPIPE_YUV422_CHR_POS_COSITE, - }, - }; - memcpy(&resizer->config, &rsz_default_config, - sizeof(struct resizer_params)); -} - -/* - * resizer_set_configuration() - set resizer config - * @resizer: vpfe resizer device pointer. - * @chan_config: resizer channel configuration. - */ -static int -resizer_set_configuration(struct vpfe_resizer_device *resizer, - struct vpfe_rsz_config *chan_config) -{ - if (!chan_config->config) - resizer_set_default_configuration(resizer); - else - if (copy_from_user(&resizer->config.user_config, - (void __user *)chan_config->config, - sizeof(struct vpfe_rsz_config_params))) - return -EFAULT; - - return 0; -} - -/* - * resizer_get_configuration() - get resizer config - * @resizer: vpfe resizer device pointer. - * @channel: image processor logical channel. - * @chan_config: resizer channel configuration. - */ -static int -resizer_get_configuration(struct vpfe_resizer_device *resizer, - struct vpfe_rsz_config *chan_config) -{ - struct device *dev = resizer->crop_resizer.subdev.v4l2_dev->dev; - - if (!chan_config->config) { - dev_err(dev, "Resizer channel invalid pointer\n"); - return -EINVAL; - } - - if (copy_to_user((void __user *)chan_config->config, - (void *)&resizer->config.user_config, - sizeof(struct vpfe_rsz_config_params))) { - dev_err(dev, "resizer_get_configuration: Error in copy to user\n"); - return -EFAULT; - } - - return 0; -} - -/* - * VPFE video operations - */ - -/* - * resizer_a_video_out_queue() - RESIZER-A video out queue - * @vpfe_dev: vpfe device pointer. - * @addr: buffer address. - */ -static int resizer_a_video_out_queue(struct vpfe_device *vpfe_dev, - unsigned long addr) -{ - struct vpfe_resizer_device *resizer = &vpfe_dev->vpfe_resizer; - - return resizer_set_outaddr(resizer->base_addr, - &resizer->config, RSZ_A, addr); -} - -/* - * resizer_b_video_out_queue() - RESIZER-B video out queue - * @vpfe_dev: vpfe device pointer. - * @addr: buffer address. - */ -static int resizer_b_video_out_queue(struct vpfe_device *vpfe_dev, - unsigned long addr) -{ - struct vpfe_resizer_device *resizer = &vpfe_dev->vpfe_resizer; - - return resizer_set_outaddr(resizer->base_addr, - &resizer->config, RSZ_B, addr); -} - -static const struct vpfe_video_operations resizer_a_video_ops = { - .queue = resizer_a_video_out_queue, -}; - -static const struct vpfe_video_operations resizer_b_video_ops = { - .queue = resizer_b_video_out_queue, -}; - -static void resizer_enable(struct vpfe_resizer_device *resizer, int en) -{ - struct vpfe_device *vpfe_dev = to_vpfe_device(resizer); - u16 ipipeif_sink = vpfe_dev->vpfe_ipipeif.input; - unsigned char val; - - if (resizer->crop_resizer.input == RESIZER_CROP_INPUT_NONE) - return; - - if (resizer->crop_resizer.input == RESIZER_CROP_INPUT_IPIPEIF && - ipipeif_sink == IPIPEIF_INPUT_MEMORY) { - do { - val = regr_rsz(resizer->base_addr, RSZ_SRC_EN); - } while (val); - - if (resizer->resizer_a.output != RESIZER_OUTPUT_NONE) { - do { - val = regr_rsz(resizer->base_addr, RSZ_A); - } while (val); - } - if (resizer->resizer_b.output != RESIZER_OUTPUT_NONE) { - do { - val = regr_rsz(resizer->base_addr, RSZ_B); - } while (val); - } - } - if (resizer->resizer_a.output != RESIZER_OUTPUT_NONE) - rsz_enable(resizer->base_addr, RSZ_A, en); - - if (resizer->resizer_b.output != RESIZER_OUTPUT_NONE) - rsz_enable(resizer->base_addr, RSZ_B, en); -} - - -/* - * resizer_ss_isr() - resizer module single-shot buffer scheduling isr - * @resizer: vpfe resizer device pointer. - */ -static void resizer_ss_isr(struct vpfe_resizer_device *resizer) -{ - struct vpfe_video_device *video_out = &resizer->resizer_a.video_out; - struct vpfe_video_device *video_out2 = &resizer->resizer_b.video_out; - struct vpfe_device *vpfe_dev = to_vpfe_device(resizer); - struct vpfe_pipeline *pipe = &video_out->pipe; - u16 ipipeif_sink = vpfe_dev->vpfe_ipipeif.input; - u32 val; - - if (ipipeif_sink != IPIPEIF_INPUT_MEMORY) - return; - - if (resizer->resizer_a.output == RESIZER_OUTPUT_MEMORY) { - val = vpss_dma_complete_interrupt(); - if (val != 0 && val != 2) - return; - } - - if (resizer->resizer_a.output == RESIZER_OUTPUT_MEMORY) { - spin_lock(&video_out->dma_queue_lock); - vpfe_video_process_buffer_complete(video_out); - video_out->state = VPFE_VIDEO_BUFFER_NOT_QUEUED; - vpfe_video_schedule_next_buffer(video_out); - spin_unlock(&video_out->dma_queue_lock); - } - - /* If resizer B is enabled */ - if (pipe->output_num > 1 && resizer->resizer_b.output == - RESIZER_OUTPUT_MEMORY) { - spin_lock(&video_out2->dma_queue_lock); - vpfe_video_process_buffer_complete(video_out2); - video_out2->state = VPFE_VIDEO_BUFFER_NOT_QUEUED; - vpfe_video_schedule_next_buffer(video_out2); - spin_unlock(&video_out2->dma_queue_lock); - } - - /* start HW if buffers are queued */ - if (vpfe_video_is_pipe_ready(pipe) && - resizer->resizer_a.output == RESIZER_OUTPUT_MEMORY) { - resizer_enable(resizer, 1); - vpfe_ipipe_enable(vpfe_dev, 1); - vpfe_ipipeif_enable(vpfe_dev); - } -} - -/* - * vpfe_resizer_buffer_isr() - resizer module buffer scheduling isr - * @resizer: vpfe resizer device pointer. - */ -void vpfe_resizer_buffer_isr(struct vpfe_resizer_device *resizer) -{ - struct vpfe_device *vpfe_dev = to_vpfe_device(resizer); - struct vpfe_video_device *video_out = &resizer->resizer_a.video_out; - struct vpfe_video_device *video_out2 = &resizer->resizer_b.video_out; - struct vpfe_pipeline *pipe = &resizer->resizer_a.video_out.pipe; - enum v4l2_field field; - int fid; - - if (!video_out->started) - return; - - if (resizer->crop_resizer.input == RESIZER_CROP_INPUT_NONE) - return; - - field = video_out->fmt.fmt.pix.field; - if (field == V4L2_FIELD_NONE) { - /* handle progressive frame capture */ - if (video_out->cur_frm != video_out->next_frm) { - vpfe_video_process_buffer_complete(video_out); - if (pipe->output_num > 1) - vpfe_video_process_buffer_complete(video_out2); - } - - video_out->skip_frame_count--; - if (!video_out->skip_frame_count) { - video_out->skip_frame_count = - video_out->skip_frame_count_init; - rsz_src_enable(resizer->base_addr, 1); - } else { - rsz_src_enable(resizer->base_addr, 0); - } - return; - } - - /* handle interlaced frame capture */ - fid = vpfe_isif_get_fid(vpfe_dev); - - /* switch the software maintained field id */ - video_out->field_id ^= 1; - if (fid == video_out->field_id) { - /* - * we are in-sync here,continue. - * One frame is just being captured. If the - * next frame is available, release the current - * frame and move on - */ - if (fid == 0 && video_out->cur_frm != video_out->next_frm) { - vpfe_video_process_buffer_complete(video_out); - if (pipe->output_num > 1) - vpfe_video_process_buffer_complete(video_out2); - } - } else if (fid == 0) { - /* - * out of sync. Recover from any hardware out-of-sync. - * May loose one frame - */ - video_out->field_id = fid; - } -} - -/* - * vpfe_resizer_dma_isr() - resizer module dma isr - * @resizer: vpfe resizer device pointer. - */ -void vpfe_resizer_dma_isr(struct vpfe_resizer_device *resizer) -{ - struct vpfe_video_device *video_out2 = &resizer->resizer_b.video_out; - struct vpfe_video_device *video_out = &resizer->resizer_a.video_out; - struct vpfe_device *vpfe_dev = to_vpfe_device(resizer); - struct vpfe_pipeline *pipe = &video_out->pipe; - int schedule_capture = 0; - enum v4l2_field field; - int fid; - - if (!video_out->started) - return; - - if (pipe->state == VPFE_PIPELINE_STREAM_SINGLESHOT) { - resizer_ss_isr(resizer); - return; - } - - field = video_out->fmt.fmt.pix.field; - if (field == V4L2_FIELD_NONE) { - if (!list_empty(&video_out->dma_queue) && - video_out->cur_frm == video_out->next_frm) - schedule_capture = 1; - } else { - fid = vpfe_isif_get_fid(vpfe_dev); - if (fid == video_out->field_id) { - /* we are in-sync here,continue */ - if (fid == 1 && !list_empty(&video_out->dma_queue) && - video_out->cur_frm == video_out->next_frm) - schedule_capture = 1; - } - } - - if (!schedule_capture) - return; - - spin_lock(&video_out->dma_queue_lock); - vpfe_video_schedule_next_buffer(video_out); - spin_unlock(&video_out->dma_queue_lock); - if (pipe->output_num > 1) { - spin_lock(&video_out2->dma_queue_lock); - vpfe_video_schedule_next_buffer(video_out2); - spin_unlock(&video_out2->dma_queue_lock); - } -} - -/* - * V4L2 subdev operations - */ - -/* - * resizer_ioctl() - Handle resizer module private ioctl's - * @sd: pointer to v4l2 subdev structure - * @cmd: configuration command - * @arg: configuration argument - */ -static long resizer_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) -{ - struct vpfe_resizer_device *resizer = v4l2_get_subdevdata(sd); - struct device *dev = resizer->crop_resizer.subdev.v4l2_dev->dev; - struct vpfe_rsz_config *user_config; - int ret = -ENOIOCTLCMD; - - if (&resizer->crop_resizer.subdev != sd) - return ret; - - switch (cmd) { - case VIDIOC_VPFE_RSZ_S_CONFIG: - user_config = arg; - ret = resizer_set_configuration(resizer, user_config); - break; - - case VIDIOC_VPFE_RSZ_G_CONFIG: - user_config = arg; - if (!user_config->config) { - dev_err(dev, "error in VIDIOC_VPFE_RSZ_G_CONFIG\n"); - return -EINVAL; - } - ret = resizer_get_configuration(resizer, user_config); - break; - } - return ret; -} - -static int resizer_do_hw_setup(struct vpfe_resizer_device *resizer) -{ - struct vpfe_device *vpfe_dev = to_vpfe_device(resizer); - u16 ipipeif_sink = vpfe_dev->vpfe_ipipeif.input; - u16 ipipeif_source = vpfe_dev->vpfe_ipipeif.output; - struct resizer_params *param = &resizer->config; - int ret = 0; - - if (resizer->resizer_a.output == RESIZER_OUTPUT_MEMORY || - resizer->resizer_b.output == RESIZER_OUTPUT_MEMORY) { - if (ipipeif_sink == IPIPEIF_INPUT_MEMORY && - ipipeif_source == IPIPEIF_OUTPUT_RESIZER) - ret = resizer_configure_in_single_shot_mode(resizer); - else - ret = resizer_configure_in_continuous_mode(resizer); - if (ret) - return ret; - ret = config_rsz_hw(resizer, param); - } - return ret; -} - -/* - * resizer_set_stream() - Enable/Disable streaming on resizer subdev - * @sd: pointer to v4l2 subdev structure - * @enable: 1 == Enable, 0 == Disable - */ -static int resizer_set_stream(struct v4l2_subdev *sd, int enable) -{ - struct vpfe_resizer_device *resizer = v4l2_get_subdevdata(sd); - - if (&resizer->crop_resizer.subdev != sd) - return 0; - - if (resizer->resizer_a.output != RESIZER_OUTPUT_MEMORY) - return 0; - - switch (enable) { - case 1: - if (resizer_do_hw_setup(resizer) < 0) - return -EINVAL; - resizer_enable(resizer, enable); - break; - - case 0: - resizer_enable(resizer, enable); - break; - } - - return 0; -} - -/* - * __resizer_get_format() - helper function for getting resizer format - * @sd: pointer to subdev. - * @cfg: V4L2 subdev pad config - * @pad: pad number. - * @which: wanted subdev format. - * Return wanted mbus frame format. - */ -static struct v4l2_mbus_framefmt * -__resizer_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, - unsigned int pad, enum v4l2_subdev_format_whence which) -{ - struct vpfe_resizer_device *resizer = v4l2_get_subdevdata(sd); - - if (which == V4L2_SUBDEV_FORMAT_TRY) - return v4l2_subdev_get_try_format(sd, cfg, pad); - if (&resizer->crop_resizer.subdev == sd) - return &resizer->crop_resizer.formats[pad]; - if (&resizer->resizer_a.subdev == sd) - return &resizer->resizer_a.formats[pad]; - if (&resizer->resizer_b.subdev == sd) - return &resizer->resizer_b.formats[pad]; - return NULL; -} - -/* - * resizer_try_format() - Handle try format by pad subdev method - * @sd: pointer to subdev. - * @cfg: V4L2 subdev pad config - * @pad: pad num. - * @fmt: pointer to v4l2 format structure. - * @which: wanted subdev format. - */ -static void -resizer_try_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, - unsigned int pad, struct v4l2_mbus_framefmt *fmt, - enum v4l2_subdev_format_whence which) -{ - struct vpfe_resizer_device *resizer = v4l2_get_subdevdata(sd); - unsigned int max_out_height; - unsigned int max_out_width; - unsigned int i; - - if ((&resizer->resizer_a.subdev == sd && pad == RESIZER_PAD_SINK) || - (&resizer->resizer_b.subdev == sd && pad == RESIZER_PAD_SINK) || - (&resizer->crop_resizer.subdev == sd && - (pad == RESIZER_CROP_PAD_SOURCE || - pad == RESIZER_CROP_PAD_SOURCE2 || pad == RESIZER_CROP_PAD_SINK))) { - for (i = 0; i < ARRAY_SIZE(resizer_input_formats); i++) { - if (fmt->code == resizer_input_formats[i]) - break; - } - /* If not found, use UYVY as default */ - if (i >= ARRAY_SIZE(resizer_input_formats)) - fmt->code = MEDIA_BUS_FMT_UYVY8_2X8; - - fmt->width = clamp_t(u32, fmt->width, MIN_IN_WIDTH, - MAX_IN_WIDTH); - fmt->height = clamp_t(u32, fmt->height, MIN_IN_HEIGHT, - MAX_IN_HEIGHT); - } else if (&resizer->resizer_a.subdev == sd && - pad == RESIZER_PAD_SOURCE) { - max_out_width = IPIPE_MAX_OUTPUT_WIDTH_A; - max_out_height = IPIPE_MAX_OUTPUT_HEIGHT_A; - - for (i = 0; i < ARRAY_SIZE(resizer_output_formats); i++) { - if (fmt->code == resizer_output_formats[i]) - break; - } - /* If not found, use UYVY as default */ - if (i >= ARRAY_SIZE(resizer_output_formats)) - fmt->code = MEDIA_BUS_FMT_UYVY8_2X8; - - fmt->width = clamp_t(u32, fmt->width, MIN_OUT_WIDTH, - max_out_width); - fmt->width &= ~15; - fmt->height = clamp_t(u32, fmt->height, MIN_OUT_HEIGHT, - max_out_height); - } else if (&resizer->resizer_b.subdev == sd && - pad == RESIZER_PAD_SOURCE) { - max_out_width = IPIPE_MAX_OUTPUT_WIDTH_B; - max_out_height = IPIPE_MAX_OUTPUT_HEIGHT_B; - - for (i = 0; i < ARRAY_SIZE(resizer_output_formats); i++) { - if (fmt->code == resizer_output_formats[i]) - break; - } - /* If not found, use UYVY as default */ - if (i >= ARRAY_SIZE(resizer_output_formats)) - fmt->code = MEDIA_BUS_FMT_UYVY8_2X8; - - fmt->width = clamp_t(u32, fmt->width, MIN_OUT_WIDTH, - max_out_width); - fmt->width &= ~15; - fmt->height = clamp_t(u32, fmt->height, MIN_OUT_HEIGHT, - max_out_height); - } -} - -/* - * resizer_set_format() - Handle set format by pads subdev method - * @sd: pointer to v4l2 subdev structure - * @cfg: V4L2 subdev pad config - * @fmt: pointer to v4l2 subdev format structure - * return -EINVAL or zero on success - */ -static int resizer_set_format(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) -{ - struct vpfe_resizer_device *resizer = v4l2_get_subdevdata(sd); - struct v4l2_mbus_framefmt *format; - - format = __resizer_get_format(sd, cfg, fmt->pad, fmt->which); - if (format == NULL) - return -EINVAL; - - resizer_try_format(sd, cfg, fmt->pad, &fmt->format, fmt->which); - *format = fmt->format; - - if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) - return 0; - - if (&resizer->crop_resizer.subdev == sd) { - if (fmt->pad == RESIZER_CROP_PAD_SINK) { - resizer->crop_resizer.formats[fmt->pad] = fmt->format; - } else if (fmt->pad == RESIZER_CROP_PAD_SOURCE && - resizer->crop_resizer.output == RESIZER_A) { - resizer->crop_resizer.formats[fmt->pad] = fmt->format; - resizer->crop_resizer. - formats[RESIZER_CROP_PAD_SOURCE2] = fmt->format; - } else if (fmt->pad == RESIZER_CROP_PAD_SOURCE2 && - resizer->crop_resizer.output2 == RESIZER_B) { - resizer->crop_resizer.formats[fmt->pad] = fmt->format; - resizer->crop_resizer. - formats[RESIZER_CROP_PAD_SOURCE] = fmt->format; - } else { - return -EINVAL; - } - } else if (&resizer->resizer_a.subdev == sd) { - if (fmt->pad == RESIZER_PAD_SINK) - resizer->resizer_a.formats[fmt->pad] = fmt->format; - else if (fmt->pad == RESIZER_PAD_SOURCE) - resizer->resizer_a.formats[fmt->pad] = fmt->format; - else - return -EINVAL; - } else if (&resizer->resizer_b.subdev == sd) { - if (fmt->pad == RESIZER_PAD_SINK) - resizer->resizer_b.formats[fmt->pad] = fmt->format; - else if (fmt->pad == RESIZER_PAD_SOURCE) - resizer->resizer_b.formats[fmt->pad] = fmt->format; - else - return -EINVAL; - } else { - return -EINVAL; - } - - return 0; -} - -/* - * resizer_get_format() - Retrieve the video format on a pad - * @sd: pointer to v4l2 subdev structure. - * @cfg: V4L2 subdev pad config - * @fmt: pointer to v4l2 subdev format structure - * return -EINVAL or zero on success - */ -static int resizer_get_format(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) -{ - struct v4l2_mbus_framefmt *format; - - format = __resizer_get_format(sd, cfg, fmt->pad, fmt->which); - if (format == NULL) - return -EINVAL; - - fmt->format = *format; - - return 0; -} - -/* - * resizer_enum_frame_size() - enum frame sizes on pads - * @sd: Pointer to subdevice. - * @cfg: V4L2 subdev pad config - * @code: pointer to v4l2_subdev_frame_size_enum structure. - */ -static int resizer_enum_frame_size(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_frame_size_enum *fse) -{ - struct v4l2_mbus_framefmt format; - - if (fse->index != 0) - return -EINVAL; - - format.code = fse->code; - format.width = 1; - format.height = 1; - resizer_try_format(sd, cfg, fse->pad, &format, fse->which); - fse->min_width = format.width; - fse->min_height = format.height; - - if (format.code != fse->code) - return -EINVAL; - - format.code = fse->code; - format.width = -1; - format.height = -1; - resizer_try_format(sd, cfg, fse->pad, &format, fse->which); - fse->max_width = format.width; - fse->max_height = format.height; - - return 0; -} - -/* - * resizer_enum_mbus_code() - enum mbus codes for pads - * @sd: Pointer to subdevice. - * @cfg: V4L2 subdev pad config - * @code: pointer to v4l2_subdev_mbus_code_enum structure - */ -static int resizer_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_mbus_code_enum *code) -{ - if (code->pad == RESIZER_PAD_SINK) { - if (code->index >= ARRAY_SIZE(resizer_input_formats)) - return -EINVAL; - - code->code = resizer_input_formats[code->index]; - } else if (code->pad == RESIZER_PAD_SOURCE) { - if (code->index >= ARRAY_SIZE(resizer_output_formats)) - return -EINVAL; - - code->code = resizer_output_formats[code->index]; - } - - return 0; -} - -/* - * resizer_init_formats() - Initialize formats on all pads - * @sd: Pointer to subdevice. - * @fh: V4L2 subdev file handle. - * - * Initialize all pad formats with default values. Try formats are - * initialized on the file handle. - */ -static int resizer_init_formats(struct v4l2_subdev *sd, - struct v4l2_subdev_fh *fh) -{ - __u32 which = V4L2_SUBDEV_FORMAT_TRY; - struct vpfe_resizer_device *resizer = v4l2_get_subdevdata(sd); - struct v4l2_subdev_format format; - - if (&resizer->crop_resizer.subdev == sd) { - memset(&format, 0, sizeof(format)); - format.pad = RESIZER_CROP_PAD_SINK; - format.which = which; - format.format.code = MEDIA_BUS_FMT_YUYV8_2X8; - format.format.width = MAX_IN_WIDTH; - format.format.height = MAX_IN_HEIGHT; - resizer_set_format(sd, fh->pad, &format); - - memset(&format, 0, sizeof(format)); - format.pad = RESIZER_CROP_PAD_SOURCE; - format.which = which; - format.format.code = MEDIA_BUS_FMT_UYVY8_2X8; - format.format.width = MAX_IN_WIDTH; - format.format.height = MAX_IN_WIDTH; - resizer_set_format(sd, fh->pad, &format); - - memset(&format, 0, sizeof(format)); - format.pad = RESIZER_CROP_PAD_SOURCE2; - format.which = which; - format.format.code = MEDIA_BUS_FMT_UYVY8_2X8; - format.format.width = MAX_IN_WIDTH; - format.format.height = MAX_IN_WIDTH; - resizer_set_format(sd, fh->pad, &format); - } else if (&resizer->resizer_a.subdev == sd) { - memset(&format, 0, sizeof(format)); - format.pad = RESIZER_PAD_SINK; - format.which = which; - format.format.code = MEDIA_BUS_FMT_YUYV8_2X8; - format.format.width = MAX_IN_WIDTH; - format.format.height = MAX_IN_HEIGHT; - resizer_set_format(sd, fh->pad, &format); - - memset(&format, 0, sizeof(format)); - format.pad = RESIZER_PAD_SOURCE; - format.which = which; - format.format.code = MEDIA_BUS_FMT_UYVY8_2X8; - format.format.width = IPIPE_MAX_OUTPUT_WIDTH_A; - format.format.height = IPIPE_MAX_OUTPUT_HEIGHT_A; - resizer_set_format(sd, fh->pad, &format); - } else if (&resizer->resizer_b.subdev == sd) { - memset(&format, 0, sizeof(format)); - format.pad = RESIZER_PAD_SINK; - format.which = which; - format.format.code = MEDIA_BUS_FMT_YUYV8_2X8; - format.format.width = MAX_IN_WIDTH; - format.format.height = MAX_IN_HEIGHT; - resizer_set_format(sd, fh->pad, &format); - - memset(&format, 0, sizeof(format)); - format.pad = RESIZER_PAD_SOURCE; - format.which = which; - format.format.code = MEDIA_BUS_FMT_UYVY8_2X8; - format.format.width = IPIPE_MAX_OUTPUT_WIDTH_B; - format.format.height = IPIPE_MAX_OUTPUT_HEIGHT_B; - resizer_set_format(sd, fh->pad, &format); - } - - return 0; -} - -/* subdev core operations */ -static const struct v4l2_subdev_core_ops resizer_v4l2_core_ops = { - .ioctl = resizer_ioctl, -}; - -/* subdev internal operations */ -static const struct v4l2_subdev_internal_ops resizer_v4l2_internal_ops = { - .open = resizer_init_formats, -}; - -/* subdev video operations */ -static const struct v4l2_subdev_video_ops resizer_v4l2_video_ops = { - .s_stream = resizer_set_stream, -}; - -/* subdev pad operations */ -static const struct v4l2_subdev_pad_ops resizer_v4l2_pad_ops = { - .enum_mbus_code = resizer_enum_mbus_code, - .enum_frame_size = resizer_enum_frame_size, - .get_fmt = resizer_get_format, - .set_fmt = resizer_set_format, -}; - -/* subdev operations */ -static const struct v4l2_subdev_ops resizer_v4l2_ops = { - .core = &resizer_v4l2_core_ops, - .video = &resizer_v4l2_video_ops, - .pad = &resizer_v4l2_pad_ops, -}; - -/* - * Media entity operations - */ - -/* - * resizer_link_setup() - Setup resizer connections - * @entity: Pointer to media entity structure - * @local: Pointer to local pad array - * @remote: Pointer to remote pad array - * @flags: Link flags - * return -EINVAL or zero on success - */ -static int resizer_link_setup(struct media_entity *entity, - const struct media_pad *local, - const struct media_pad *remote, u32 flags) -{ - struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); - struct vpfe_resizer_device *resizer = v4l2_get_subdevdata(sd); - struct vpfe_device *vpfe_dev = to_vpfe_device(resizer); - u16 ipipeif_source = vpfe_dev->vpfe_ipipeif.output; - u16 ipipe_source = vpfe_dev->vpfe_ipipe.output; - unsigned int index = local->index; - - /* FIXME: this is actually a hack! */ - if (is_media_entity_v4l2_subdev(remote->entity)) - index |= 2 << 16; - - if (&resizer->crop_resizer.subdev == sd) { - switch (index) { - case RESIZER_CROP_PAD_SINK | 2 << 16: - if (!(flags & MEDIA_LNK_FL_ENABLED)) { - resizer->crop_resizer.input = - RESIZER_CROP_INPUT_NONE; - break; - } - - if (resizer->crop_resizer.input != - RESIZER_CROP_INPUT_NONE) - return -EBUSY; - if (ipipeif_source == IPIPEIF_OUTPUT_RESIZER) - resizer->crop_resizer.input = - RESIZER_CROP_INPUT_IPIPEIF; - else if (ipipe_source == IPIPE_OUTPUT_RESIZER) - resizer->crop_resizer.input = - RESIZER_CROP_INPUT_IPIPE; - else - return -EINVAL; - break; - - case RESIZER_CROP_PAD_SOURCE | 2 << 16: - if (!(flags & MEDIA_LNK_FL_ENABLED)) { - resizer->crop_resizer.output = - RESIZER_CROP_OUTPUT_NONE; - break; - } - if (resizer->crop_resizer.output != - RESIZER_CROP_OUTPUT_NONE) - return -EBUSY; - resizer->crop_resizer.output = RESIZER_A; - break; - - case RESIZER_CROP_PAD_SOURCE2 | 2 << 16: - if (!(flags & MEDIA_LNK_FL_ENABLED)) { - resizer->crop_resizer.output2 = - RESIZER_CROP_OUTPUT_NONE; - break; - } - if (resizer->crop_resizer.output2 != - RESIZER_CROP_OUTPUT_NONE) - return -EBUSY; - resizer->crop_resizer.output2 = RESIZER_B; - break; - - default: - return -EINVAL; - } - } else if (&resizer->resizer_a.subdev == sd) { - switch (index) { - case RESIZER_PAD_SINK | 2 << 16: - if (!(flags & MEDIA_LNK_FL_ENABLED)) { - resizer->resizer_a.input = RESIZER_INPUT_NONE; - break; - } - if (resizer->resizer_a.input != RESIZER_INPUT_NONE) - return -EBUSY; - resizer->resizer_a.input = RESIZER_INPUT_CROP_RESIZER; - break; - - case RESIZER_PAD_SOURCE: - if (!(flags & MEDIA_LNK_FL_ENABLED)) { - resizer->resizer_a.output = RESIZER_OUTPUT_NONE; - break; - } - if (resizer->resizer_a.output != RESIZER_OUTPUT_NONE) - return -EBUSY; - resizer->resizer_a.output = RESIZER_OUTPUT_MEMORY; - break; - - default: - return -EINVAL; - } - } else if (&resizer->resizer_b.subdev == sd) { - switch (index) { - case RESIZER_PAD_SINK | 2 << 16: - if (!(flags & MEDIA_LNK_FL_ENABLED)) { - resizer->resizer_b.input = RESIZER_INPUT_NONE; - break; - } - if (resizer->resizer_b.input != RESIZER_INPUT_NONE) - return -EBUSY; - resizer->resizer_b.input = RESIZER_INPUT_CROP_RESIZER; - break; - - case RESIZER_PAD_SOURCE: - if (!(flags & MEDIA_LNK_FL_ENABLED)) { - resizer->resizer_b.output = RESIZER_OUTPUT_NONE; - break; - } - if (resizer->resizer_b.output != RESIZER_OUTPUT_NONE) - return -EBUSY; - resizer->resizer_b.output = RESIZER_OUTPUT_MEMORY; - break; - - default: - return -EINVAL; - } - } else { - return -EINVAL; - } - - return 0; -} - -static const struct media_entity_operations resizer_media_ops = { - .link_setup = resizer_link_setup, -}; - -/* - * vpfe_resizer_unregister_entities() - Unregister entity - * @vpfe_rsz - pointer to resizer subdevice structure. - */ -void vpfe_resizer_unregister_entities(struct vpfe_resizer_device *vpfe_rsz) -{ - /* unregister video devices */ - vpfe_video_unregister(&vpfe_rsz->resizer_a.video_out); - vpfe_video_unregister(&vpfe_rsz->resizer_b.video_out); - - /* unregister subdev */ - v4l2_device_unregister_subdev(&vpfe_rsz->crop_resizer.subdev); - v4l2_device_unregister_subdev(&vpfe_rsz->resizer_a.subdev); - v4l2_device_unregister_subdev(&vpfe_rsz->resizer_b.subdev); - /* cleanup entity */ - media_entity_cleanup(&vpfe_rsz->crop_resizer.subdev.entity); - media_entity_cleanup(&vpfe_rsz->resizer_a.subdev.entity); - media_entity_cleanup(&vpfe_rsz->resizer_b.subdev.entity); -} - -/* - * vpfe_resizer_register_entities() - Register entity - * @resizer - pointer to resizer device. - * @vdev: pointer to v4l2 device structure. - */ -int vpfe_resizer_register_entities(struct vpfe_resizer_device *resizer, - struct v4l2_device *vdev) -{ - struct vpfe_device *vpfe_dev = to_vpfe_device(resizer); - unsigned int flags = 0; - int ret; - - /* Register the crop resizer subdev */ - ret = v4l2_device_register_subdev(vdev, &resizer->crop_resizer.subdev); - if (ret < 0) { - pr_err("Failed to register crop resizer as v4l2-subdev\n"); - return ret; - } - /* Register Resizer-A subdev */ - ret = v4l2_device_register_subdev(vdev, &resizer->resizer_a.subdev); - if (ret < 0) { - pr_err("Failed to register resizer-a as v4l2-subdev\n"); - return ret; - } - /* Register Resizer-B subdev */ - ret = v4l2_device_register_subdev(vdev, &resizer->resizer_b.subdev); - if (ret < 0) { - pr_err("Failed to register resizer-b as v4l2-subdev\n"); - return ret; - } - /* Register video-out device for resizer-a */ - ret = vpfe_video_register(&resizer->resizer_a.video_out, vdev); - if (ret) { - pr_err("Failed to register RSZ-A video-out device\n"); - goto out_video_out2_register; - } - resizer->resizer_a.video_out.vpfe_dev = vpfe_dev; - - /* Register video-out device for resizer-b */ - ret = vpfe_video_register(&resizer->resizer_b.video_out, vdev); - if (ret) { - pr_err("Failed to register RSZ-B video-out device\n"); - goto out_video_out2_register; - } - resizer->resizer_b.video_out.vpfe_dev = vpfe_dev; - - /* create link between Resizer Crop----> Resizer A*/ - ret = media_create_pad_link(&resizer->crop_resizer.subdev.entity, 1, - &resizer->resizer_a.subdev.entity, - 0, flags); - if (ret < 0) - goto out_create_link; - - /* create link between Resizer Crop----> Resizer B*/ - ret = media_create_pad_link(&resizer->crop_resizer.subdev.entity, 2, - &resizer->resizer_b.subdev.entity, - 0, flags); - if (ret < 0) - goto out_create_link; - - /* create link between Resizer A ----> video out */ - ret = media_create_pad_link(&resizer->resizer_a.subdev.entity, 1, - &resizer->resizer_a.video_out.video_dev.entity, 0, flags); - if (ret < 0) - goto out_create_link; - - /* create link between Resizer B ----> video out */ - ret = media_create_pad_link(&resizer->resizer_b.subdev.entity, 1, - &resizer->resizer_b.video_out.video_dev.entity, 0, flags); - if (ret < 0) - goto out_create_link; - - return 0; - -out_create_link: - vpfe_video_unregister(&resizer->resizer_b.video_out); -out_video_out2_register: - vpfe_video_unregister(&resizer->resizer_a.video_out); - v4l2_device_unregister_subdev(&resizer->crop_resizer.subdev); - v4l2_device_unregister_subdev(&resizer->resizer_a.subdev); - v4l2_device_unregister_subdev(&resizer->resizer_b.subdev); - media_entity_cleanup(&resizer->crop_resizer.subdev.entity); - media_entity_cleanup(&resizer->resizer_a.subdev.entity); - media_entity_cleanup(&resizer->resizer_b.subdev.entity); - return ret; -} - -/* - * vpfe_resizer_init() - resizer device initialization. - * @vpfe_rsz - pointer to resizer device - * @pdev: platform device pointer. - */ -int vpfe_resizer_init(struct vpfe_resizer_device *vpfe_rsz, - struct platform_device *pdev) -{ - struct v4l2_subdev *sd = &vpfe_rsz->crop_resizer.subdev; - struct media_pad *pads = &vpfe_rsz->crop_resizer.pads[0]; - struct media_entity *me = &sd->entity; - resource_size_t res_len; - struct resource *res; - int ret; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 5); - if (!res) - return -ENOENT; - - res_len = resource_size(res); - res = request_mem_region(res->start, res_len, res->name); - if (!res) - return -EBUSY; - - vpfe_rsz->base_addr = ioremap_nocache(res->start, res_len); - if (!vpfe_rsz->base_addr) - return -EBUSY; - - v4l2_subdev_init(sd, &resizer_v4l2_ops); - sd->internal_ops = &resizer_v4l2_internal_ops; - strscpy(sd->name, "DAVINCI RESIZER CROP", sizeof(sd->name)); - sd->grp_id = 1 << 16; /* group ID for davinci subdevs */ - v4l2_set_subdevdata(sd, vpfe_rsz); - sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - - pads[RESIZER_CROP_PAD_SINK].flags = MEDIA_PAD_FL_SINK; - pads[RESIZER_CROP_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; - pads[RESIZER_CROP_PAD_SOURCE2].flags = MEDIA_PAD_FL_SOURCE; - - vpfe_rsz->crop_resizer.input = RESIZER_CROP_INPUT_NONE; - vpfe_rsz->crop_resizer.output = RESIZER_CROP_OUTPUT_NONE; - vpfe_rsz->crop_resizer.output2 = RESIZER_CROP_OUTPUT_NONE; - vpfe_rsz->crop_resizer.rsz_device = vpfe_rsz; - me->ops = &resizer_media_ops; - ret = media_entity_pads_init(me, RESIZER_CROP_PADS_NUM, pads); - if (ret) - return ret; - - sd = &vpfe_rsz->resizer_a.subdev; - pads = &vpfe_rsz->resizer_a.pads[0]; - me = &sd->entity; - - v4l2_subdev_init(sd, &resizer_v4l2_ops); - sd->internal_ops = &resizer_v4l2_internal_ops; - strscpy(sd->name, "DAVINCI RESIZER A", sizeof(sd->name)); - sd->grp_id = 1 << 16; /* group ID for davinci subdevs */ - v4l2_set_subdevdata(sd, vpfe_rsz); - sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - - pads[RESIZER_PAD_SINK].flags = MEDIA_PAD_FL_SINK; - pads[RESIZER_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; - - vpfe_rsz->resizer_a.input = RESIZER_INPUT_NONE; - vpfe_rsz->resizer_a.output = RESIZER_OUTPUT_NONE; - vpfe_rsz->resizer_a.rsz_device = vpfe_rsz; - me->ops = &resizer_media_ops; - ret = media_entity_pads_init(me, RESIZER_PADS_NUM, pads); - if (ret) - return ret; - - sd = &vpfe_rsz->resizer_b.subdev; - pads = &vpfe_rsz->resizer_b.pads[0]; - me = &sd->entity; - - v4l2_subdev_init(sd, &resizer_v4l2_ops); - sd->internal_ops = &resizer_v4l2_internal_ops; - strscpy(sd->name, "DAVINCI RESIZER B", sizeof(sd->name)); - sd->grp_id = 1 << 16; /* group ID for davinci subdevs */ - v4l2_set_subdevdata(sd, vpfe_rsz); - sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - - pads[RESIZER_PAD_SINK].flags = MEDIA_PAD_FL_SINK; - pads[RESIZER_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; - - vpfe_rsz->resizer_b.input = RESIZER_INPUT_NONE; - vpfe_rsz->resizer_b.output = RESIZER_OUTPUT_NONE; - vpfe_rsz->resizer_b.rsz_device = vpfe_rsz; - me->ops = &resizer_media_ops; - ret = media_entity_pads_init(me, RESIZER_PADS_NUM, pads); - if (ret) - return ret; - - vpfe_rsz->resizer_a.video_out.ops = &resizer_a_video_ops; - vpfe_rsz->resizer_a.video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - ret = vpfe_video_init(&vpfe_rsz->resizer_a.video_out, "RSZ-A"); - if (ret) { - pr_err("Failed to init RSZ video-out device\n"); - return ret; - } - vpfe_rsz->resizer_b.video_out.ops = &resizer_b_video_ops; - vpfe_rsz->resizer_b.video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - ret = vpfe_video_init(&vpfe_rsz->resizer_b.video_out, "RSZ-B"); - if (ret) { - pr_err("Failed to init RSZ video-out2 device\n"); - return ret; - } - memset(&vpfe_rsz->config, 0, sizeof(struct resizer_params)); - - return 0; -} - -void -vpfe_resizer_cleanup(struct vpfe_resizer_device *vpfe_rsz, - struct platform_device *pdev) -{ - struct resource *res; - - iounmap(vpfe_rsz->base_addr); - res = platform_get_resource(pdev, IORESOURCE_MEM, 5); - if (res) - release_mem_region(res->start, - resource_size(res)); -} diff --git a/drivers/staging/media/davinci_vpfe/dm365_resizer.h b/drivers/staging/media/davinci_vpfe/dm365_resizer.h deleted file mode 100644 index 5e31de96b2c9..000000000000 --- a/drivers/staging/media/davinci_vpfe/dm365_resizer.h +++ /dev/null @@ -1,241 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) 2012 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Contributors: - * Manjunath Hadli <manjunath.hadli@ti.com> - * Prabhakar Lad <prabhakar.lad@ti.com> - */ - -#ifndef _DAVINCI_VPFE_DM365_RESIZER_H -#define _DAVINCI_VPFE_DM365_RESIZER_H - -enum resizer_oper_mode { - RESIZER_MODE_CONTINUOUS = 0, - RESIZER_MODE_ONE_SHOT = 1, -}; - -struct f_div_pass { - unsigned int o_hsz; - unsigned int i_hps; - unsigned int h_phs; - unsigned int src_hps; - unsigned int src_hsz; -}; - -#define MAX_PASSES 2 - -struct f_div_param { - unsigned char en; - unsigned int num_passes; - struct f_div_pass pass[MAX_PASSES]; -}; - -/* Resizer Rescale Parameters*/ -struct resizer_scale_param { - bool h_flip; - bool v_flip; - bool cen; - bool yen; - unsigned short i_vps; - unsigned short i_hps; - unsigned short o_vsz; - unsigned short o_hsz; - unsigned short v_phs_y; - unsigned short v_phs_c; - unsigned short v_dif; - /* resize method - Luminance */ - enum vpfe_rsz_intp_t v_typ_y; - /* resize method - Chrominance */ - enum vpfe_rsz_intp_t v_typ_c; - /* vertical lpf intensity - Luminance */ - unsigned char v_lpf_int_y; - /* vertical lpf intensity - Chrominance */ - unsigned char v_lpf_int_c; - unsigned short h_phs; - unsigned short h_dif; - /* resize method - Luminance */ - enum vpfe_rsz_intp_t h_typ_y; - /* resize method - Chrominance */ - enum vpfe_rsz_intp_t h_typ_c; - /* horizontal lpf intensity - Luminance */ - unsigned char h_lpf_int_y; - /* horizontal lpf intensity - Chrominance */ - unsigned char h_lpf_int_c; - bool dscale_en; - enum vpfe_rsz_down_scale_ave_sz h_dscale_ave_sz; - enum vpfe_rsz_down_scale_ave_sz v_dscale_ave_sz; - /* store the calculated frame division parameter */ - struct f_div_param f_div; -}; - -enum resizer_rgb_t { - OUTPUT_32BIT, - OUTPUT_16BIT -}; - -enum resizer_rgb_msk_t { - NOMASK = 0, - MASKLAST2 = 1, -}; - -/* Resizer RGB Conversion Parameters */ -struct resizer_rgb { - bool rgb_en; - enum resizer_rgb_t rgb_typ; - enum resizer_rgb_msk_t rgb_msk0; - enum resizer_rgb_msk_t rgb_msk1; - unsigned int rgb_alpha_val; -}; - -/* Resizer External Memory Parameters */ -struct rsz_ext_mem_param { - unsigned int rsz_sdr_oft_y; - unsigned int rsz_sdr_ptr_s_y; - unsigned int rsz_sdr_ptr_e_y; - unsigned int rsz_sdr_oft_c; - unsigned int rsz_sdr_ptr_s_c; - unsigned int rsz_sdr_ptr_e_c; - /* offset to be added to buffer start when flipping for y/ycbcr */ - unsigned int flip_ofst_y; - /* offset to be added to buffer start when flipping for c */ - unsigned int flip_ofst_c; - /* c offset for YUV 420SP */ - unsigned int c_offset; - /* User Defined Y offset for YUV 420SP or YUV420ILE data */ - unsigned int user_y_ofst; - /* User Defined C offset for YUV 420SP data */ - unsigned int user_c_ofst; -}; - -enum rsz_data_source { - IPIPE_DATA, - IPIPEIF_DATA -}; - -enum rsz_src_img_fmt { - RSZ_IMG_422, - RSZ_IMG_420 -}; - -enum rsz_dpaths_bypass_t { - BYPASS_OFF = 0, - BYPASS_ON = 1, -}; - -struct rsz_common_params { - unsigned int vps; - unsigned int vsz; - unsigned int hps; - unsigned int hsz; - /* 420 or 422 */ - enum rsz_src_img_fmt src_img_fmt; - /* Y or C when src_fmt is 420, 0 - y, 1 - c */ - unsigned char y_c; - /* flip raw or ycbcr */ - unsigned char raw_flip; - /* IPIPE or IPIPEIF data */ - enum rsz_data_source source; - enum rsz_dpaths_bypass_t passthrough; - unsigned char yuv_y_min; - unsigned char yuv_y_max; - unsigned char yuv_c_min; - unsigned char yuv_c_max; - bool rsz_seq_crv; - enum vpfe_chr_pos out_chr_pos; -}; - -struct resizer_params { - enum resizer_oper_mode oper_mode; - struct rsz_common_params rsz_common; - struct resizer_scale_param rsz_rsc_param[2]; - struct resizer_rgb rsz2rgb[2]; - struct rsz_ext_mem_param ext_mem_param[2]; - bool rsz_en[2]; - struct vpfe_rsz_config_params user_config; -}; - -#define ENABLE 1 -#define DISABLE (!ENABLE) - -#define RESIZER_CROP_PAD_SINK 0 -#define RESIZER_CROP_PAD_SOURCE 1 -#define RESIZER_CROP_PAD_SOURCE2 2 - -#define RESIZER_CROP_PADS_NUM 3 - -enum resizer_crop_input_entity { - RESIZER_CROP_INPUT_NONE = 0, - RESIZER_CROP_INPUT_IPIPEIF = 1, - RESIZER_CROP_INPUT_IPIPE = 2, -}; - -enum resizer_crop_output_entity { - RESIZER_CROP_OUTPUT_NONE, - RESIZER_A, - RESIZER_B, -}; - -struct dm365_crop_resizer_device { - struct v4l2_subdev subdev; - struct media_pad pads[RESIZER_CROP_PADS_NUM]; - struct v4l2_mbus_framefmt formats[RESIZER_CROP_PADS_NUM]; - enum resizer_crop_input_entity input; - enum resizer_crop_output_entity output; - enum resizer_crop_output_entity output2; - struct vpfe_resizer_device *rsz_device; -}; - -#define RESIZER_PAD_SINK 0 -#define RESIZER_PAD_SOURCE 1 - -#define RESIZER_PADS_NUM 2 - -enum resizer_input_entity { - RESIZER_INPUT_NONE = 0, - RESIZER_INPUT_CROP_RESIZER = 1, -}; - -enum resizer_output_entity { - RESIZER_OUTPUT_NONE = 0, - RESIZER_OUTPUT_MEMORY = 1, -}; - -struct dm365_resizer_device { - struct v4l2_subdev subdev; - struct media_pad pads[RESIZER_PADS_NUM]; - struct v4l2_mbus_framefmt formats[RESIZER_PADS_NUM]; - enum resizer_input_entity input; - enum resizer_output_entity output; - struct vpfe_video_device video_out; - struct vpfe_resizer_device *rsz_device; -}; - -struct vpfe_resizer_device { - struct dm365_crop_resizer_device crop_resizer; - struct dm365_resizer_device resizer_a; - struct dm365_resizer_device resizer_b; - struct resizer_params config; - void __iomem *base_addr; -}; - -int vpfe_resizer_init(struct vpfe_resizer_device *vpfe_rsz, - struct platform_device *pdev); -int vpfe_resizer_register_entities(struct vpfe_resizer_device *vpfe_rsz, - struct v4l2_device *v4l2_dev); -void vpfe_resizer_unregister_entities(struct vpfe_resizer_device *vpfe_rsz); -void vpfe_resizer_cleanup(struct vpfe_resizer_device *vpfe_rsz, - struct platform_device *pdev); -void vpfe_resizer_buffer_isr(struct vpfe_resizer_device *resizer); -void vpfe_resizer_dma_isr(struct vpfe_resizer_device *resizer); - -#endif /* _DAVINCI_VPFE_DM365_RESIZER_H */ diff --git a/drivers/staging/media/davinci_vpfe/vpfe.h b/drivers/staging/media/davinci_vpfe/vpfe.h deleted file mode 100644 index 1f8e011fc162..000000000000 --- a/drivers/staging/media/davinci_vpfe/vpfe.h +++ /dev/null @@ -1,83 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) 2012 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Contributors: - * Manjunath Hadli <manjunath.hadli@ti.com> - * Prabhakar Lad <prabhakar.lad@ti.com> - */ - -#ifndef _VPFE_H -#define _VPFE_H - -#ifdef __KERNEL__ -#include <linux/v4l2-subdev.h> -#include <linux/clk.h> -#include <linux/i2c.h> - -#include <media/davinci/vpfe_types.h> - -#define CAPTURE_DRV_NAME "vpfe-capture" - -struct vpfe_route { - __u32 input; - __u32 output; -}; - -enum vpfe_subdev_id { - VPFE_SUBDEV_TVP5146 = 1, - VPFE_SUBDEV_MT9T031 = 2, - VPFE_SUBDEV_TVP7002 = 3, - VPFE_SUBDEV_MT9P031 = 4, -}; - -struct vpfe_ext_subdev_info { - /* v4l2 subdev */ - struct v4l2_subdev *subdev; - /* Sub device module name */ - char module_name[32]; - /* Sub device group id */ - int grp_id; - /* Number of inputs supported */ - int num_inputs; - /* inputs available at the sub device */ - struct v4l2_input *inputs; - /* Sub dev routing information for each input */ - struct vpfe_route *routes; - /* ccdc bus/interface configuration */ - struct vpfe_hw_if_param ccdc_if_params; - /* i2c subdevice board info */ - struct i2c_board_info board_info; - /* Is this a camera sub device ? */ - unsigned is_camera:1; - /* check if sub dev supports routing */ - unsigned can_route:1; - /* registered ? */ - unsigned registered:1; -}; - -struct vpfe_config { - /* Number of sub devices connected to vpfe */ - int num_subdevs; - /* information about each subdev */ - struct vpfe_ext_subdev_info *sub_devs; - /* evm card info */ - char *card_name; - /* setup function for the input path */ - int (*setup_input)(enum vpfe_subdev_id id); - /* number of clocks */ - int num_clocks; - /* clocks used for vpfe capture */ - char *clocks[]; -}; -#endif -#endif diff --git a/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c b/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c deleted file mode 100644 index 9dc28ffe38d5..000000000000 --- a/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c +++ /dev/null @@ -1,716 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2012 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Contributors: - * Manjunath Hadli <manjunath.hadli@ti.com> - * Prabhakar Lad <prabhakar.lad@ti.com> - * - * - * Driver name : VPFE Capture driver - * VPFE Capture driver allows applications to capture and stream video - * frames on DaVinci SoCs (DM6446, DM355 etc) from a YUV source such as - * TVP5146 or Raw Bayer RGB image data from an image sensor - * such as Microns' MT9T001, MT9T031 etc. - * - * These SoCs have, in common, a Video Processing Subsystem (VPSS) that - * consists of a Video Processing Front End (VPFE) for capturing - * video/raw image data and Video Processing Back End (VPBE) for displaying - * YUV data through an in-built analog encoder or Digital LCD port. This - * driver is for capture through VPFE. A typical EVM using these SoCs have - * following high level configuration. - * - * decoder(TVP5146/ YUV/ - * MT9T001) --> Raw Bayer RGB ---> MUX -> VPFE (CCDC/ISIF) - * data input | | - * V | - * SDRAM | - * V - * Image Processor - * | - * V - * SDRAM - * The data flow happens from a decoder connected to the VPFE over a - * YUV embedded (BT.656/BT.1120) or separate sync or raw bayer rgb interface - * and to the input of VPFE through an optional MUX (if more inputs are - * to be interfaced on the EVM). The input data is first passed through - * CCDC (CCD Controller, a.k.a Image Sensor Interface, ISIF). The CCDC - * does very little or no processing on YUV data and does pre-process Raw - * Bayer RGB data through modules such as Defect Pixel Correction (DFC) - * Color Space Conversion (CSC), data gain/offset etc. After this, data - * can be written to SDRAM or can be connected to the image processing - * block such as IPIPE (on DM355/DM365 only). - * - * Features supported - * - MMAP IO - * - USERPTR IO - * - Capture using TVP5146 over BT.656 - * - Support for interfacing decoders using sub device model - * - Work with DM365 or DM355 or DM6446 CCDC to do Raw Bayer - * RGB/YUV data capture to SDRAM. - * - Chaining of Image Processor - * - SINGLE-SHOT mode - */ - -#include <linux/interrupt.h> -#include <linux/module.h> -#include <linux/slab.h> - -#include "vpfe.h" -#include "vpfe_mc_capture.h" - -static bool debug; -static bool interface; - -module_param(interface, bool, 0444); -module_param(debug, bool, 0644); - -/* - * VPFE capture can be used for capturing video such as from TVP5146 or TVP7002 - * and for capture raw bayer data from camera sensors such as mt9p031. At this - * point there is problem in co-existence of mt9p031 and tvp5146 due to i2c - * address collision. So set the variable below from bootargs to do either video - * capture or camera capture. - * interface = 0 - video capture (from TVP514x or such), - * interface = 1 - Camera capture (from mt9p031 or such) - * Re-visit this when we fix the co-existence issue - */ -MODULE_PARM_DESC(interface, "interface 0-1 (default:0)"); -MODULE_PARM_DESC(debug, "Debug level 0-1"); - -MODULE_DESCRIPTION("VPFE Video for Linux Capture Driver"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Texas Instruments"); - -/* map mbus_fmt to pixelformat */ -void mbus_to_pix(const struct v4l2_mbus_framefmt *mbus, - struct v4l2_pix_format *pix) -{ - switch (mbus->code) { - case MEDIA_BUS_FMT_UYVY8_2X8: - pix->pixelformat = V4L2_PIX_FMT_UYVY; - pix->bytesperline = pix->width * 2; - break; - - case MEDIA_BUS_FMT_YUYV8_2X8: - pix->pixelformat = V4L2_PIX_FMT_YUYV; - pix->bytesperline = pix->width * 2; - break; - - case MEDIA_BUS_FMT_YUYV10_1X20: - pix->pixelformat = V4L2_PIX_FMT_UYVY; - pix->bytesperline = pix->width * 2; - break; - - case MEDIA_BUS_FMT_SGRBG12_1X12: - pix->pixelformat = V4L2_PIX_FMT_SBGGR16; - pix->bytesperline = pix->width * 2; - break; - - case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8: - pix->pixelformat = V4L2_PIX_FMT_SGRBG10DPCM8; - pix->bytesperline = pix->width; - break; - - case MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8: - pix->pixelformat = V4L2_PIX_FMT_SGRBG10ALAW8; - pix->bytesperline = pix->width; - break; - - case MEDIA_BUS_FMT_YDYUYDYV8_1X16: - pix->pixelformat = V4L2_PIX_FMT_NV12; - pix->bytesperline = pix->width; - break; - - case MEDIA_BUS_FMT_Y8_1X8: - pix->pixelformat = V4L2_PIX_FMT_GREY; - pix->bytesperline = pix->width; - break; - - case MEDIA_BUS_FMT_UV8_1X8: - pix->pixelformat = V4L2_PIX_FMT_UV8; - pix->bytesperline = pix->width; - break; - - default: - pr_err("Invalid mbus code set\n"); - } - /* pitch should be 32 bytes aligned */ - pix->bytesperline = ALIGN(pix->bytesperline, 32); - if (pix->pixelformat == V4L2_PIX_FMT_NV12) - pix->sizeimage = pix->bytesperline * pix->height + - ((pix->bytesperline * pix->height) >> 1); - else - pix->sizeimage = pix->bytesperline * pix->height; -} - -/* ISR for VINT0*/ -static irqreturn_t vpfe_isr(int irq, void *dev_id) -{ - struct vpfe_device *vpfe_dev = dev_id; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "%s\n", __func__); - vpfe_isif_buffer_isr(&vpfe_dev->vpfe_isif); - vpfe_resizer_buffer_isr(&vpfe_dev->vpfe_resizer); - return IRQ_HANDLED; -} - -/* vpfe_vdint1_isr() - isr handler for VINT1 interrupt */ -static irqreturn_t vpfe_vdint1_isr(int irq, void *dev_id) -{ - struct vpfe_device *vpfe_dev = dev_id; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "%s\n", __func__); - vpfe_isif_vidint1_isr(&vpfe_dev->vpfe_isif); - return IRQ_HANDLED; -} - -/* vpfe_imp_dma_isr() - ISR for ipipe dma completion */ -static irqreturn_t vpfe_imp_dma_isr(int irq, void *dev_id) -{ - struct vpfe_device *vpfe_dev = dev_id; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "%s\n", __func__); - vpfe_ipipeif_ss_buffer_isr(&vpfe_dev->vpfe_ipipeif); - vpfe_resizer_dma_isr(&vpfe_dev->vpfe_resizer); - return IRQ_HANDLED; -} - -/* - * vpfe_disable_clock() - Disable clocks for vpfe capture driver - * @vpfe_dev - ptr to vpfe capture device - * - * Disables clocks defined in vpfe configuration. The function - * assumes that at least one clock is to be defined which is - * true as of now. - */ -static void vpfe_disable_clock(struct vpfe_device *vpfe_dev) -{ - struct vpfe_config *vpfe_cfg = vpfe_dev->cfg; - int i; - - for (i = 0; i < vpfe_cfg->num_clocks; i++) { - clk_disable_unprepare(vpfe_dev->clks[i]); - clk_put(vpfe_dev->clks[i]); - } - kzfree(vpfe_dev->clks); - v4l2_info(vpfe_dev->pdev->driver, "vpfe capture clocks disabled\n"); -} - -/* - * vpfe_enable_clock() - Enable clocks for vpfe capture driver - * @vpfe_dev - ptr to vpfe capture device - * - * Enables clocks defined in vpfe configuration. The function - * assumes that at least one clock is to be defined which is - * true as of now. - */ -static int vpfe_enable_clock(struct vpfe_device *vpfe_dev) -{ - struct vpfe_config *vpfe_cfg = vpfe_dev->cfg; - int ret = -EFAULT; - int i; - - if (!vpfe_cfg->num_clocks) - return 0; - - vpfe_dev->clks = kcalloc(vpfe_cfg->num_clocks, - sizeof(*vpfe_dev->clks), GFP_KERNEL); - if (!vpfe_dev->clks) - return -ENOMEM; - - for (i = 0; i < vpfe_cfg->num_clocks; i++) { - if (vpfe_cfg->clocks[i] == NULL) { - v4l2_err(vpfe_dev->pdev->driver, - "clock %s is not defined in vpfe config\n", - vpfe_cfg->clocks[i]); - goto out; - } - - vpfe_dev->clks[i] = - clk_get(vpfe_dev->pdev, vpfe_cfg->clocks[i]); - if (IS_ERR(vpfe_dev->clks[i])) { - v4l2_err(vpfe_dev->pdev->driver, - "Failed to get clock %s\n", - vpfe_cfg->clocks[i]); - goto out; - } - - if (clk_prepare_enable(vpfe_dev->clks[i])) { - v4l2_err(vpfe_dev->pdev->driver, - "vpfe clock %s not enabled\n", - vpfe_cfg->clocks[i]); - goto out; - } - - v4l2_info(vpfe_dev->pdev->driver, "vpss clock %s enabled", - vpfe_cfg->clocks[i]); - } - - return 0; -out: - for (i = 0; i < vpfe_cfg->num_clocks; i++) - if (!IS_ERR(vpfe_dev->clks[i])) { - clk_disable_unprepare(vpfe_dev->clks[i]); - clk_put(vpfe_dev->clks[i]); - } - - v4l2_err(vpfe_dev->pdev->driver, "Failed to enable clocks\n"); - kzfree(vpfe_dev->clks); - - return ret; -} - -/* - * vpfe_detach_irq() - Detach IRQs for vpfe capture driver - * @vpfe_dev - ptr to vpfe capture device - * - * Detach all IRQs defined in vpfe configuration. - */ -static void vpfe_detach_irq(struct vpfe_device *vpfe_dev) -{ - free_irq(vpfe_dev->ccdc_irq0, vpfe_dev); - free_irq(vpfe_dev->ccdc_irq1, vpfe_dev); - free_irq(vpfe_dev->imp_dma_irq, vpfe_dev); -} - -/* - * vpfe_attach_irq() - Attach IRQs for vpfe capture driver - * @vpfe_dev - ptr to vpfe capture device - * - * Attach all IRQs defined in vpfe configuration. - */ -static int vpfe_attach_irq(struct vpfe_device *vpfe_dev) -{ - int ret; - - ret = request_irq(vpfe_dev->ccdc_irq0, vpfe_isr, 0, - "vpfe_capture0", vpfe_dev); - if (ret < 0) { - v4l2_err(&vpfe_dev->v4l2_dev, - "Error: requesting VINT0 interrupt\n"); - return ret; - } - - ret = request_irq(vpfe_dev->ccdc_irq1, vpfe_vdint1_isr, 0, - "vpfe_capture1", vpfe_dev); - if (ret < 0) { - v4l2_err(&vpfe_dev->v4l2_dev, - "Error: requesting VINT1 interrupt\n"); - free_irq(vpfe_dev->ccdc_irq0, vpfe_dev); - return ret; - } - - ret = request_irq(vpfe_dev->imp_dma_irq, vpfe_imp_dma_isr, - 0, "Imp_Sdram_Irq", vpfe_dev); - if (ret < 0) { - v4l2_err(&vpfe_dev->v4l2_dev, - "Error: requesting IMP IRQ interrupt\n"); - free_irq(vpfe_dev->ccdc_irq1, vpfe_dev); - free_irq(vpfe_dev->ccdc_irq0, vpfe_dev); - return ret; - } - - return 0; -} - -/* - * register_i2c_devices() - register all i2c v4l2 subdevs - * @vpfe_dev - ptr to vpfe capture device - * - * register all i2c v4l2 subdevs - */ -static int register_i2c_devices(struct vpfe_device *vpfe_dev) -{ - struct vpfe_ext_subdev_info *sdinfo; - struct vpfe_config *vpfe_cfg; - struct i2c_adapter *i2c_adap; - unsigned int num_subdevs; - int ret; - int i; - int k; - - vpfe_cfg = vpfe_dev->cfg; - i2c_adap = i2c_get_adapter(1); - num_subdevs = vpfe_cfg->num_subdevs; - vpfe_dev->sd = - kcalloc(num_subdevs, sizeof(struct v4l2_subdev *), - GFP_KERNEL); - if (!vpfe_dev->sd) - return -ENOMEM; - - for (i = 0, k = 0; i < num_subdevs; i++) { - sdinfo = &vpfe_cfg->sub_devs[i]; - /* - * register subdevices based on interface setting. Currently - * tvp5146 and mt9p031 cannot co-exists due to i2c address - * conflicts. So only one of them is registered. Re-visit this - * once we have support for i2c switch handling in i2c driver - * framework - */ - if (interface == sdinfo->is_camera) { - /* setup input path */ - if (vpfe_cfg->setup_input && - vpfe_cfg->setup_input(sdinfo->grp_id) < 0) { - ret = -EFAULT; - v4l2_info(&vpfe_dev->v4l2_dev, - "could not setup input for %s\n", - sdinfo->module_name); - goto probe_sd_out; - } - /* Load up the subdevice */ - vpfe_dev->sd[k] = - v4l2_i2c_new_subdev_board(&vpfe_dev->v4l2_dev, - i2c_adap, &sdinfo->board_info, - NULL); - if (vpfe_dev->sd[k]) { - v4l2_info(&vpfe_dev->v4l2_dev, - "v4l2 sub device %s registered\n", - sdinfo->module_name); - - vpfe_dev->sd[k]->grp_id = sdinfo->grp_id; - k++; - - sdinfo->registered = 1; - } - } else { - v4l2_info(&vpfe_dev->v4l2_dev, - "v4l2 sub device %s is not registered\n", - sdinfo->module_name); - } - } - vpfe_dev->num_ext_subdevs = k; - - return 0; - -probe_sd_out: - kzfree(vpfe_dev->sd); - - return ret; -} - -/* - * vpfe_register_entities() - register all v4l2 subdevs and media entities - * @vpfe_dev - ptr to vpfe capture device - * - * register all v4l2 subdevs, media entities, and creates links - * between entities - */ -static int vpfe_register_entities(struct vpfe_device *vpfe_dev) -{ - unsigned int flags = 0; - int ret; - int i; - - /* register i2c devices first */ - ret = register_i2c_devices(vpfe_dev); - if (ret) - return ret; - - /* register rest of the sub-devs */ - ret = vpfe_isif_register_entities(&vpfe_dev->vpfe_isif, - &vpfe_dev->v4l2_dev); - if (ret) - return ret; - - ret = vpfe_ipipeif_register_entities(&vpfe_dev->vpfe_ipipeif, - &vpfe_dev->v4l2_dev); - if (ret) - goto out_isif_register; - - ret = vpfe_ipipe_register_entities(&vpfe_dev->vpfe_ipipe, - &vpfe_dev->v4l2_dev); - if (ret) - goto out_ipipeif_register; - - ret = vpfe_resizer_register_entities(&vpfe_dev->vpfe_resizer, - &vpfe_dev->v4l2_dev); - if (ret) - goto out_ipipe_register; - - /* create links now, starting with external(i2c) entities */ - for (i = 0; i < vpfe_dev->num_ext_subdevs; i++) - /* - * if entity has no pads (ex: amplifier), - * can't establish link - */ - if (vpfe_dev->sd[i]->entity.num_pads) { - ret = media_create_pad_link(&vpfe_dev->sd[i]->entity, - 0, &vpfe_dev->vpfe_isif.subdev.entity, - 0, flags); - if (ret < 0) - goto out_resizer_register; - } - - ret = media_create_pad_link(&vpfe_dev->vpfe_isif.subdev.entity, 1, - &vpfe_dev->vpfe_ipipeif.subdev.entity, - 0, flags); - if (ret < 0) - goto out_resizer_register; - - ret = media_create_pad_link(&vpfe_dev->vpfe_ipipeif.subdev.entity, 1, - &vpfe_dev->vpfe_ipipe.subdev.entity, - 0, flags); - if (ret < 0) - goto out_resizer_register; - - ret = media_create_pad_link(&vpfe_dev->vpfe_ipipe.subdev.entity, - 1, &vpfe_dev->vpfe_resizer.crop_resizer.subdev.entity, - 0, flags); - if (ret < 0) - goto out_resizer_register; - - ret = media_create_pad_link(&vpfe_dev->vpfe_ipipeif.subdev.entity, 1, - &vpfe_dev->vpfe_resizer.crop_resizer.subdev.entity, - 0, flags); - if (ret < 0) - goto out_resizer_register; - - ret = v4l2_device_register_subdev_nodes(&vpfe_dev->v4l2_dev); - if (ret < 0) - goto out_resizer_register; - - return 0; - -out_resizer_register: - vpfe_resizer_unregister_entities(&vpfe_dev->vpfe_resizer); -out_ipipe_register: - vpfe_ipipe_unregister_entities(&vpfe_dev->vpfe_ipipe); -out_ipipeif_register: - vpfe_ipipeif_unregister_entities(&vpfe_dev->vpfe_ipipeif); -out_isif_register: - vpfe_isif_unregister_entities(&vpfe_dev->vpfe_isif); - - return ret; -} - -/* - * vpfe_unregister_entities() - unregister all v4l2 subdevs and media entities - * @vpfe_dev - ptr to vpfe capture device - * - * unregister all v4l2 subdevs and media entities - */ -static void vpfe_unregister_entities(struct vpfe_device *vpfe_dev) -{ - vpfe_isif_unregister_entities(&vpfe_dev->vpfe_isif); - vpfe_ipipeif_unregister_entities(&vpfe_dev->vpfe_ipipeif); - vpfe_ipipe_unregister_entities(&vpfe_dev->vpfe_ipipe); - vpfe_resizer_unregister_entities(&vpfe_dev->vpfe_resizer); -} - -/* - * vpfe_cleanup_modules() - cleanup all non-i2c v4l2 subdevs - * @vpfe_dev - ptr to vpfe capture device - * @pdev - pointer to platform device - * - * cleanup all v4l2 subdevs - */ -static void vpfe_cleanup_modules(struct vpfe_device *vpfe_dev, - struct platform_device *pdev) -{ - vpfe_isif_cleanup(&vpfe_dev->vpfe_isif, pdev); - vpfe_ipipeif_cleanup(&vpfe_dev->vpfe_ipipeif, pdev); - vpfe_ipipe_cleanup(&vpfe_dev->vpfe_ipipe, pdev); - vpfe_resizer_cleanup(&vpfe_dev->vpfe_resizer, pdev); -} - -/* - * vpfe_initialize_modules() - initialize all non-i2c v4l2 subdevs - * @vpfe_dev - ptr to vpfe capture device - * @pdev - pointer to platform device - * - * initialize all v4l2 subdevs and media entities - */ -static int vpfe_initialize_modules(struct vpfe_device *vpfe_dev, - struct platform_device *pdev) -{ - int ret; - - ret = vpfe_isif_init(&vpfe_dev->vpfe_isif, pdev); - if (ret) - return ret; - - ret = vpfe_ipipeif_init(&vpfe_dev->vpfe_ipipeif, pdev); - if (ret) - goto out_isif_init; - - ret = vpfe_ipipe_init(&vpfe_dev->vpfe_ipipe, pdev); - if (ret) - goto out_ipipeif_init; - - ret = vpfe_resizer_init(&vpfe_dev->vpfe_resizer, pdev); - if (ret) - goto out_ipipe_init; - - return 0; - -out_ipipe_init: - vpfe_ipipe_cleanup(&vpfe_dev->vpfe_ipipe, pdev); -out_ipipeif_init: - vpfe_ipipeif_cleanup(&vpfe_dev->vpfe_ipipeif, pdev); -out_isif_init: - vpfe_isif_cleanup(&vpfe_dev->vpfe_isif, pdev); - - return ret; -} - -/* - * vpfe_probe() : vpfe probe function - * @pdev: platform device pointer - * - * This function creates device entries by register itself to the V4L2 driver - * and initializes fields of each device objects - */ -static int vpfe_probe(struct platform_device *pdev) -{ - struct vpfe_device *vpfe_dev; - struct resource *res1; - int ret = -ENOMEM; - - vpfe_dev = kzalloc(sizeof(*vpfe_dev), GFP_KERNEL); - if (!vpfe_dev) - return ret; - - if (pdev->dev.platform_data == NULL) { - v4l2_err(pdev->dev.driver, "Unable to get vpfe config\n"); - ret = -ENOENT; - goto probe_free_dev_mem; - } - - vpfe_dev->cfg = pdev->dev.platform_data; - if (vpfe_dev->cfg->card_name == NULL || - vpfe_dev->cfg->sub_devs == NULL) { - v4l2_err(pdev->dev.driver, "null ptr in vpfe_cfg\n"); - ret = -ENOENT; - goto probe_free_dev_mem; - } - - /* Get VINT0 irq resource */ - res1 = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!res1) { - v4l2_err(pdev->dev.driver, - "Unable to get interrupt for VINT0\n"); - ret = -ENOENT; - goto probe_free_dev_mem; - } - vpfe_dev->ccdc_irq0 = res1->start; - - /* Get VINT1 irq resource */ - res1 = platform_get_resource(pdev, IORESOURCE_IRQ, 1); - if (!res1) { - v4l2_err(pdev->dev.driver, - "Unable to get interrupt for VINT1\n"); - ret = -ENOENT; - goto probe_free_dev_mem; - } - vpfe_dev->ccdc_irq1 = res1->start; - - /* Get DMA irq resource */ - res1 = platform_get_resource(pdev, IORESOURCE_IRQ, 2); - if (!res1) { - v4l2_err(pdev->dev.driver, - "Unable to get interrupt for DMA\n"); - ret = -ENOENT; - goto probe_free_dev_mem; - } - vpfe_dev->imp_dma_irq = res1->start; - - vpfe_dev->pdev = &pdev->dev; - - /* enable vpss clocks */ - ret = vpfe_enable_clock(vpfe_dev); - if (ret) - goto probe_free_dev_mem; - - ret = vpfe_initialize_modules(vpfe_dev, pdev); - if (ret) - goto probe_disable_clock; - - vpfe_dev->media_dev.dev = vpfe_dev->pdev; - strscpy((char *)&vpfe_dev->media_dev.model, "davinci-media", - sizeof(vpfe_dev->media_dev.model)); - - ret = media_device_register(&vpfe_dev->media_dev); - if (ret) { - v4l2_err(pdev->dev.driver, - "Unable to register media device.\n"); - goto probe_out_entities_cleanup; - } - - vpfe_dev->v4l2_dev.mdev = &vpfe_dev->media_dev; - ret = v4l2_device_register(&pdev->dev, &vpfe_dev->v4l2_dev); - if (ret) { - v4l2_err(pdev->dev.driver, "Unable to register v4l2 device.\n"); - goto probe_out_media_unregister; - } - - v4l2_info(&vpfe_dev->v4l2_dev, "v4l2 device registered\n"); - /* set the driver data in platform device */ - platform_set_drvdata(pdev, vpfe_dev); - /* register subdevs/entities */ - ret = vpfe_register_entities(vpfe_dev); - if (ret) - goto probe_out_v4l2_unregister; - - ret = vpfe_attach_irq(vpfe_dev); - if (ret) - goto probe_out_entities_unregister; - - return 0; - -probe_out_entities_unregister: - vpfe_unregister_entities(vpfe_dev); - kzfree(vpfe_dev->sd); -probe_out_v4l2_unregister: - v4l2_device_unregister(&vpfe_dev->v4l2_dev); -probe_out_media_unregister: - media_device_unregister(&vpfe_dev->media_dev); -probe_out_entities_cleanup: - vpfe_cleanup_modules(vpfe_dev, pdev); -probe_disable_clock: - vpfe_disable_clock(vpfe_dev); -probe_free_dev_mem: - kzfree(vpfe_dev); - - return ret; -} - -/* - * vpfe_remove : This function un-registers device from V4L2 driver - */ -static int vpfe_remove(struct platform_device *pdev) -{ - struct vpfe_device *vpfe_dev = platform_get_drvdata(pdev); - - v4l2_info(pdev->dev.driver, "%s\n", __func__); - - kzfree(vpfe_dev->sd); - vpfe_detach_irq(vpfe_dev); - vpfe_unregister_entities(vpfe_dev); - vpfe_cleanup_modules(vpfe_dev, pdev); - v4l2_device_unregister(&vpfe_dev->v4l2_dev); - media_device_unregister(&vpfe_dev->media_dev); - vpfe_disable_clock(vpfe_dev); - kzfree(vpfe_dev); - - return 0; -} - -static struct platform_driver vpfe_driver = { - .driver = { - .name = CAPTURE_DRV_NAME, - }, - .probe = vpfe_probe, - .remove = vpfe_remove, -}; - -module_platform_driver(vpfe_driver); diff --git a/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.h b/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.h deleted file mode 100644 index fe4a421b5dba..000000000000 --- a/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.h +++ /dev/null @@ -1,90 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) 2012 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Contributors: - * Manjunath Hadli <manjunath.hadli@ti.com> - * Prabhakar Lad <prabhakar.lad@ti.com> - */ - -#ifndef _DAVINCI_VPFE_MC_CAPTURE_H -#define _DAVINCI_VPFE_MC_CAPTURE_H - -#include "dm365_ipipe.h" -#include "dm365_ipipeif.h" -#include "dm365_isif.h" -#include "dm365_resizer.h" -#include "vpfe_video.h" - -#define VPFE_MAJOR_RELEASE 0 -#define VPFE_MINOR_RELEASE 0 -#define VPFE_BUILD 1 -#define VPFE_CAPTURE_VERSION_CODE ((VPFE_MAJOR_RELEASE << 16) | \ - (VPFE_MINOR_RELEASE << 8) | \ - VPFE_BUILD) - -/* IPIPE hardware limits */ -#define IPIPE_MAX_OUTPUT_WIDTH_A 2176 -#define IPIPE_MAX_OUTPUT_WIDTH_B 640 - -/* Based on max resolution supported. QXGA */ -#define IPIPE_MAX_OUTPUT_HEIGHT_A 1536 -/* Based on max resolution supported. VGA */ -#define IPIPE_MAX_OUTPUT_HEIGHT_B 480 - -#define to_vpfe_device(ptr_module) \ - container_of(ptr_module, struct vpfe_device, vpfe_##ptr_module) -#define to_device(ptr_module) \ - (to_vpfe_device(ptr_module)->dev) - -struct vpfe_device { - /* external registered sub devices */ - struct v4l2_subdev **sd; - /* number of registered external subdevs */ - unsigned int num_ext_subdevs; - /* vpfe cfg */ - struct vpfe_config *cfg; - /* clock ptrs for vpfe capture */ - struct clk **clks; - /* V4l2 device */ - struct v4l2_device v4l2_dev; - /* parent device */ - struct device *pdev; - /* IRQ number for DMA transfer completion at the image processor */ - unsigned int imp_dma_irq; - /* CCDC IRQs used when CCDC/ISIF output to SDRAM */ - unsigned int ccdc_irq0; - unsigned int ccdc_irq1; - /* media device */ - struct media_device media_dev; - /* ccdc subdevice */ - struct vpfe_isif_device vpfe_isif; - /* ipipeif subdevice */ - struct vpfe_ipipeif_device vpfe_ipipeif; - /* ipipe subdevice */ - struct vpfe_ipipe_device vpfe_ipipe; - /* resizer subdevice */ - struct vpfe_resizer_device vpfe_resizer; -}; - -/* File handle structure */ -struct vpfe_fh { - struct v4l2_fh vfh; - struct vpfe_video_device *video; - /* Indicates whether this file handle is doing IO */ - u8 io_allowed; -}; - -void mbus_to_pix(const struct v4l2_mbus_framefmt *mbus, - struct v4l2_pix_format *pix); - -#endif /* _DAVINCI_VPFE_MC_CAPTURE_H */ diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.c b/drivers/staging/media/davinci_vpfe/vpfe_video.c deleted file mode 100644 index ab6bc452d9f6..000000000000 --- a/drivers/staging/media/davinci_vpfe/vpfe_video.c +++ /dev/null @@ -1,1646 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2012 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Contributors: - * Manjunath Hadli <manjunath.hadli@ti.com> - * Prabhakar Lad <prabhakar.lad@ti.com> - */ - -#include <linux/module.h> -#include <linux/slab.h> - -#include <media/v4l2-ioctl.h> - -#include "vpfe.h" -#include "vpfe_mc_capture.h" - -static int debug; - -/* get v4l2 subdev pointer to external subdev which is active */ -static struct media_entity *vpfe_get_input_entity - (struct vpfe_video_device *video) -{ - struct vpfe_device *vpfe_dev = video->vpfe_dev; - struct media_pad *remote; - - remote = media_entity_remote_pad(&vpfe_dev->vpfe_isif.pads[0]); - if (!remote) { - pr_err("Invalid media connection to isif/ccdc\n"); - return NULL; - } - return remote->entity; -} - -/* updates external subdev(sensor/decoder) which is active */ -static int vpfe_update_current_ext_subdev(struct vpfe_video_device *video) -{ - struct vpfe_device *vpfe_dev = video->vpfe_dev; - struct vpfe_config *vpfe_cfg; - struct v4l2_subdev *subdev; - struct media_pad *remote; - int i; - - remote = media_entity_remote_pad(&vpfe_dev->vpfe_isif.pads[0]); - if (!remote) { - pr_err("Invalid media connection to isif/ccdc\n"); - return -EINVAL; - } - - subdev = media_entity_to_v4l2_subdev(remote->entity); - vpfe_cfg = vpfe_dev->pdev->platform_data; - for (i = 0; i < vpfe_cfg->num_subdevs; i++) { - if (!strcmp(vpfe_cfg->sub_devs[i].module_name, subdev->name)) { - video->current_ext_subdev = &vpfe_cfg->sub_devs[i]; - break; - } - } - - /* if user not linked decoder/sensor to isif/ccdc */ - if (i == vpfe_cfg->num_subdevs) { - pr_err("Invalid media chain connection to isif/ccdc\n"); - return -EINVAL; - } - /* find the v4l2 subdev pointer */ - for (i = 0; i < vpfe_dev->num_ext_subdevs; i++) { - if (!strcmp(video->current_ext_subdev->module_name, - vpfe_dev->sd[i]->name)) - video->current_ext_subdev->subdev = vpfe_dev->sd[i]; - } - return 0; -} - -/* get the subdev which is connected to the output video node */ -static struct v4l2_subdev * -vpfe_video_remote_subdev(struct vpfe_video_device *video, u32 *pad) -{ - struct media_pad *remote = media_entity_remote_pad(&video->pad); - - if (!remote || !is_media_entity_v4l2_subdev(remote->entity)) - return NULL; - if (pad) - *pad = remote->index; - return media_entity_to_v4l2_subdev(remote->entity); -} - -/* get the format set at output pad of the adjacent subdev */ -static int -__vpfe_video_get_format(struct vpfe_video_device *video, - struct v4l2_format *format) -{ - struct v4l2_subdev_format fmt; - struct v4l2_subdev *subdev; - struct media_pad *remote; - u32 pad; - int ret; - - subdev = vpfe_video_remote_subdev(video, &pad); - if (!subdev) - return -EINVAL; - - fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; - remote = media_entity_remote_pad(&video->pad); - fmt.pad = remote->index; - - ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt); - if (ret == -ENOIOCTLCMD) - return -EINVAL; - - format->type = video->type; - /* convert mbus_format to v4l2_format */ - v4l2_fill_pix_format(&format->fmt.pix, &fmt.format); - mbus_to_pix(&fmt.format, &format->fmt.pix); - - return 0; -} - -/* make a note of pipeline details */ -static int vpfe_prepare_pipeline(struct vpfe_video_device *video) -{ - struct media_graph graph; - struct media_entity *entity = &video->video_dev.entity; - struct media_device *mdev = entity->graph_obj.mdev; - struct vpfe_pipeline *pipe = &video->pipe; - struct vpfe_video_device *far_end = NULL; - int ret; - - pipe->input_num = 0; - pipe->output_num = 0; - - if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) - pipe->inputs[pipe->input_num++] = video; - else - pipe->outputs[pipe->output_num++] = video; - - mutex_lock(&mdev->graph_mutex); - ret = media_graph_walk_init(&graph, mdev); - if (ret) { - mutex_unlock(&mdev->graph_mutex); - return -ENOMEM; - } - media_graph_walk_start(&graph, entity); - while ((entity = media_graph_walk_next(&graph))) { - if (entity == &video->video_dev.entity) - continue; - if (!is_media_entity_v4l2_video_device(entity)) - continue; - far_end = to_vpfe_video(media_entity_to_video_device(entity)); - if (far_end->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) - pipe->inputs[pipe->input_num++] = far_end; - else - pipe->outputs[pipe->output_num++] = far_end; - } - media_graph_walk_cleanup(&graph); - mutex_unlock(&mdev->graph_mutex); - - return 0; -} - -/* update pipe state selected by user */ -static int vpfe_update_pipe_state(struct vpfe_video_device *video) -{ - struct vpfe_pipeline *pipe = &video->pipe; - int ret; - - ret = vpfe_prepare_pipeline(video); - if (ret) - return ret; - - /* - * Find out if there is any input video - * if yes, it is single shot. - */ - if (pipe->input_num == 0) { - pipe->state = VPFE_PIPELINE_STREAM_CONTINUOUS; - ret = vpfe_update_current_ext_subdev(video); - if (ret) { - pr_err("Invalid external subdev\n"); - return ret; - } - } else { - pipe->state = VPFE_PIPELINE_STREAM_SINGLESHOT; - } - video->initialized = 1; - video->skip_frame_count = 1; - video->skip_frame_count_init = 1; - return 0; -} - -/* checks whether pipeline is ready for enabling */ -int vpfe_video_is_pipe_ready(struct vpfe_pipeline *pipe) -{ - int i; - - for (i = 0; i < pipe->input_num; i++) - if (!pipe->inputs[i]->started || - pipe->inputs[i]->state != VPFE_VIDEO_BUFFER_QUEUED) - return 0; - for (i = 0; i < pipe->output_num; i++) - if (!pipe->outputs[i]->started || - pipe->outputs[i]->state != VPFE_VIDEO_BUFFER_QUEUED) - return 0; - return 1; -} - -/* - * Validate a pipeline by checking both ends of all links for format - * discrepancies. - * - * Return 0 if all formats match, or -EPIPE if at least one link is found with - * different formats on its two ends. - */ -static int vpfe_video_validate_pipeline(struct vpfe_pipeline *pipe) -{ - struct v4l2_subdev_format fmt_source; - struct v4l2_subdev_format fmt_sink; - struct v4l2_subdev *subdev; - struct media_pad *pad; - int ret; - - /* - * Should not matter if it is output[0] or 1 as - * the general ideas is to traverse backwards and - * the fact that the out video node always has the - * format of the connected pad. - */ - subdev = vpfe_video_remote_subdev(pipe->outputs[0], NULL); - if (!subdev) - return -EPIPE; - - while (1) { - /* Retrieve the sink format */ - pad = &subdev->entity.pads[0]; - if (!(pad->flags & MEDIA_PAD_FL_SINK)) - break; - - fmt_sink.which = V4L2_SUBDEV_FORMAT_ACTIVE; - fmt_sink.pad = pad->index; - ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, - &fmt_sink); - - if (ret < 0 && ret != -ENOIOCTLCMD) - return -EPIPE; - - /* Retrieve the source format */ - pad = media_entity_remote_pad(pad); - if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) - break; - - subdev = media_entity_to_v4l2_subdev(pad->entity); - - fmt_source.which = V4L2_SUBDEV_FORMAT_ACTIVE; - fmt_source.pad = pad->index; - ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt_source); - if (ret < 0 && ret != -ENOIOCTLCMD) - return -EPIPE; - - /* Check if the two ends match */ - if (fmt_source.format.code != fmt_sink.format.code || - fmt_source.format.width != fmt_sink.format.width || - fmt_source.format.height != fmt_sink.format.height) - return -EPIPE; - } - return 0; -} - -/* - * vpfe_pipeline_enable() - Enable streaming on a pipeline - * @vpfe_dev: vpfe device - * @pipe: vpfe pipeline - * - * Walk the entities chain starting at the pipeline output video node and start - * all modules in the chain in the given mode. - * - * Return 0 if successful, or the return value of the failed video::s_stream - * operation otherwise. - */ -static int vpfe_pipeline_enable(struct vpfe_pipeline *pipe) -{ - struct media_entity *entity; - struct v4l2_subdev *subdev; - struct media_device *mdev; - int ret; - - if (pipe->state == VPFE_PIPELINE_STREAM_CONTINUOUS) - entity = vpfe_get_input_entity(pipe->outputs[0]); - else - entity = &pipe->inputs[0]->video_dev.entity; - - mdev = entity->graph_obj.mdev; - mutex_lock(&mdev->graph_mutex); - ret = media_graph_walk_init(&pipe->graph, mdev); - if (ret) - goto out; - media_graph_walk_start(&pipe->graph, entity); - while ((entity = media_graph_walk_next(&pipe->graph))) { - - if (!is_media_entity_v4l2_subdev(entity)) - continue; - subdev = media_entity_to_v4l2_subdev(entity); - ret = v4l2_subdev_call(subdev, video, s_stream, 1); - if (ret < 0 && ret != -ENOIOCTLCMD) - break; - } -out: - if (ret) - media_graph_walk_cleanup(&pipe->graph); - mutex_unlock(&mdev->graph_mutex); - return ret; -} - -/* - * vpfe_pipeline_disable() - Disable streaming on a pipeline - * @vpfe_dev: vpfe device - * @pipe: VPFE pipeline - * - * Walk the entities chain starting at the pipeline output video node and stop - * all modules in the chain. - * - * Return 0 if all modules have been properly stopped, or -ETIMEDOUT if a module - * can't be stopped. - */ -static int vpfe_pipeline_disable(struct vpfe_pipeline *pipe) -{ - struct media_entity *entity; - struct v4l2_subdev *subdev; - struct media_device *mdev; - int ret = 0; - - if (pipe->state == VPFE_PIPELINE_STREAM_CONTINUOUS) - entity = vpfe_get_input_entity(pipe->outputs[0]); - else - entity = &pipe->inputs[0]->video_dev.entity; - - mdev = entity->graph_obj.mdev; - mutex_lock(&mdev->graph_mutex); - media_graph_walk_start(&pipe->graph, entity); - - while ((entity = media_graph_walk_next(&pipe->graph))) { - - if (!is_media_entity_v4l2_subdev(entity)) - continue; - subdev = media_entity_to_v4l2_subdev(entity); - ret = v4l2_subdev_call(subdev, video, s_stream, 0); - if (ret < 0 && ret != -ENOIOCTLCMD) - break; - } - mutex_unlock(&mdev->graph_mutex); - - media_graph_walk_cleanup(&pipe->graph); - return ret ? -ETIMEDOUT : 0; -} - -/* - * vpfe_pipeline_set_stream() - Enable/disable streaming on a pipeline - * @vpfe_dev: VPFE device - * @pipe: VPFE pipeline - * @state: Stream state (stopped or active) - * - * Set the pipeline to the given stream state. - * - * Return 0 if successful, or the return value of the failed video::s_stream - * operation otherwise. - */ -static int vpfe_pipeline_set_stream(struct vpfe_pipeline *pipe, - enum vpfe_pipeline_stream_state state) -{ - if (state == VPFE_PIPELINE_STREAM_STOPPED) - return vpfe_pipeline_disable(pipe); - - return vpfe_pipeline_enable(pipe); -} - -static int all_videos_stopped(struct vpfe_video_device *video) -{ - struct vpfe_pipeline *pipe = &video->pipe; - int i; - - for (i = 0; i < pipe->input_num; i++) - if (pipe->inputs[i]->started) - return 0; - for (i = 0; i < pipe->output_num; i++) - if (pipe->outputs[i]->started) - return 0; - return 1; -} - -/* - * vpfe_open() - open video device - * @file: file pointer - * - * initialize media pipeline state, allocate memory for file handle - * - * Return 0 if successful, or the return -ENODEV otherwise. - */ -static int vpfe_open(struct file *file) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_fh *handle; - - /* Allocate memory for the file handle object */ - handle = kzalloc(sizeof(struct vpfe_fh), GFP_KERNEL); - - if (!handle) - return -ENOMEM; - - v4l2_fh_init(&handle->vfh, &video->video_dev); - v4l2_fh_add(&handle->vfh); - - mutex_lock(&video->lock); - /* If decoder is not initialized. initialize it */ - if (!video->initialized && vpfe_update_pipe_state(video)) { - mutex_unlock(&video->lock); - v4l2_fh_del(&handle->vfh); - v4l2_fh_exit(&handle->vfh); - kfree(handle); - return -ENODEV; - } - /* Increment device users counter */ - video->usrs++; - /* Set io_allowed member to false */ - handle->io_allowed = 0; - handle->video = video; - file->private_data = &handle->vfh; - mutex_unlock(&video->lock); - - return 0; -} - -/* get the next buffer available from dma queue */ -static unsigned long -vpfe_video_get_next_buffer(struct vpfe_video_device *video) -{ - video->cur_frm = video->next_frm = - list_entry(video->dma_queue.next, - struct vpfe_cap_buffer, list); - - list_del(&video->next_frm->list); - video->next_frm->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE; - return vb2_dma_contig_plane_dma_addr(&video->next_frm->vb.vb2_buf, 0); -} - -/* schedule the next buffer which is available on dma queue */ -void vpfe_video_schedule_next_buffer(struct vpfe_video_device *video) -{ - struct vpfe_device *vpfe_dev = video->vpfe_dev; - unsigned long addr; - - if (list_empty(&video->dma_queue)) - return; - - video->next_frm = list_entry(video->dma_queue.next, - struct vpfe_cap_buffer, list); - - if (video->pipe.state == VPFE_PIPELINE_STREAM_SINGLESHOT) - video->cur_frm = video->next_frm; - - list_del(&video->next_frm->list); - video->next_frm->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE; - addr = vb2_dma_contig_plane_dma_addr(&video->next_frm->vb.vb2_buf, 0); - video->ops->queue(vpfe_dev, addr); - video->state = VPFE_VIDEO_BUFFER_QUEUED; -} - -/* schedule the buffer for capturing bottom field */ -void vpfe_video_schedule_bottom_field(struct vpfe_video_device *video) -{ - struct vpfe_device *vpfe_dev = video->vpfe_dev; - unsigned long addr; - - addr = vb2_dma_contig_plane_dma_addr(&video->cur_frm->vb.vb2_buf, 0); - addr += video->field_off; - video->ops->queue(vpfe_dev, addr); -} - -/* make buffer available for dequeue */ -void vpfe_video_process_buffer_complete(struct vpfe_video_device *video) -{ - struct vpfe_pipeline *pipe = &video->pipe; - - video->cur_frm->vb.vb2_buf.timestamp = ktime_get_ns(); - vb2_buffer_done(&video->cur_frm->vb.vb2_buf, VB2_BUF_STATE_DONE); - if (pipe->state == VPFE_PIPELINE_STREAM_CONTINUOUS) - video->cur_frm = video->next_frm; -} - -/* vpfe_stop_capture() - stop streaming */ -static void vpfe_stop_capture(struct vpfe_video_device *video) -{ - struct vpfe_pipeline *pipe = &video->pipe; - - video->started = 0; - - if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) - return; - if (all_videos_stopped(video)) - vpfe_pipeline_set_stream(pipe, - VPFE_PIPELINE_STREAM_STOPPED); -} - -/* - * vpfe_release() - release video device - * @file: file pointer - * - * deletes buffer queue, frees the buffers and the vpfe file handle - * - * Return 0 - */ -static int vpfe_release(struct file *file) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct v4l2_fh *vfh = file->private_data; - struct vpfe_device *vpfe_dev = video->vpfe_dev; - struct vpfe_fh *fh = container_of(vfh, struct vpfe_fh, vfh); - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_release\n"); - - /* Get the device lock */ - mutex_lock(&video->lock); - /* if this instance is doing IO */ - if (fh->io_allowed) { - if (video->started) { - vpfe_stop_capture(video); - /* - * mark pipe state as stopped in vpfe_release(), - * as app might call streamon() after streamoff() - * in which case driver has to start streaming. - */ - video->pipe.state = VPFE_PIPELINE_STREAM_STOPPED; - vb2_streamoff(&video->buffer_queue, - video->buffer_queue.type); - } - video->io_usrs = 0; - /* Free buffers allocated */ - vb2_queue_release(&video->buffer_queue); - } - /* Decrement device users counter */ - video->usrs--; - v4l2_fh_del(&fh->vfh); - v4l2_fh_exit(&fh->vfh); - /* If this is the last file handle */ - if (!video->usrs) - video->initialized = 0; - mutex_unlock(&video->lock); - file->private_data = NULL; - /* Free memory allocated to file handle object */ - v4l2_fh_del(vfh); - kzfree(fh); - return 0; -} - -/* - * vpfe_mmap() - It is used to map kernel space buffers - * into user spaces - */ -static int vpfe_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_mmap\n"); - return vb2_mmap(&video->buffer_queue, vma); -} - -/* - * vpfe_poll() - It is used for select/poll system call - */ -static __poll_t vpfe_poll(struct file *file, poll_table *wait) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_poll\n"); - if (video->started) - return vb2_poll(&video->buffer_queue, file, wait); - return 0; -} - -/* vpfe capture driver file operations */ -static const struct v4l2_file_operations vpfe_fops = { - .owner = THIS_MODULE, - .open = vpfe_open, - .release = vpfe_release, - .unlocked_ioctl = video_ioctl2, - .mmap = vpfe_mmap, - .poll = vpfe_poll -}; - -/* - * vpfe_querycap() - query capabilities of video device - * @file: file pointer - * @priv: void pointer - * @cap: pointer to v4l2_capability structure - * - * fills v4l2 capabilities structure - * - * Return 0 - */ -static int vpfe_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querycap\n"); - - cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT | - V4L2_CAP_STREAMING | V4L2_CAP_DEVICE_CAPS; - strscpy(cap->driver, CAPTURE_DRV_NAME, sizeof(cap->driver)); - strscpy(cap->bus_info, "VPFE", sizeof(cap->bus_info)); - strscpy(cap->card, vpfe_dev->cfg->card_name, sizeof(cap->card)); - - return 0; -} - -/* - * vpfe_g_fmt() - get the format which is active on video device - * @file: file pointer - * @priv: void pointer - * @fmt: pointer to v4l2_format structure - * - * fills v4l2 format structure with active format - * - * Return 0 - */ -static int vpfe_g_fmt(struct file *file, void *priv, - struct v4l2_format *fmt) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_fmt\n"); - /* Fill in the information about format */ - *fmt = video->fmt; - return 0; -} - -/* - * vpfe_enum_fmt() - enum formats supported on media chain - * @file: file pointer - * @priv: void pointer - * @fmt: pointer to v4l2_fmtdesc structure - * - * fills v4l2_fmtdesc structure with output format set on adjacent subdev, - * only one format is enumearted as subdevs are already configured - * - * Return 0 if successful, error code otherwise - */ -static int vpfe_enum_fmt(struct file *file, void *priv, - struct v4l2_fmtdesc *fmt) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - struct v4l2_subdev_format sd_fmt; - struct v4l2_mbus_framefmt mbus; - struct v4l2_subdev *subdev; - struct v4l2_format format; - struct media_pad *remote; - int ret; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_fmt\n"); - - /* - * since already subdev pad format is set, - * only one pixel format is available - */ - if (fmt->index > 0) { - v4l2_err(&vpfe_dev->v4l2_dev, "Invalid index\n"); - return -EINVAL; - } - /* get the remote pad */ - remote = media_entity_remote_pad(&video->pad); - if (!remote) { - v4l2_err(&vpfe_dev->v4l2_dev, - "invalid remote pad for video node\n"); - return -EINVAL; - } - /* get the remote subdev */ - subdev = vpfe_video_remote_subdev(video, NULL); - if (!subdev) { - v4l2_err(&vpfe_dev->v4l2_dev, - "invalid remote subdev for video node\n"); - return -EINVAL; - } - sd_fmt.pad = remote->index; - sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; - /* get output format of remote subdev */ - ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &sd_fmt); - if (ret) { - v4l2_err(&vpfe_dev->v4l2_dev, - "invalid remote subdev for video node\n"); - return ret; - } - /* convert to pix format */ - mbus.code = sd_fmt.format.code; - mbus_to_pix(&mbus, &format.fmt.pix); - /* copy the result */ - fmt->pixelformat = format.fmt.pix.pixelformat; - - return 0; -} - -/* - * vpfe_s_fmt() - set the format on video device - * @file: file pointer - * @priv: void pointer - * @fmt: pointer to v4l2_format structure - * - * validate and set the format on video device - * - * Return 0 on success, error code otherwise - */ -static int vpfe_s_fmt(struct file *file, void *priv, - struct v4l2_format *fmt) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - struct v4l2_format format; - int ret; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_fmt\n"); - /* If streaming is started, return error */ - if (video->started) { - v4l2_err(&vpfe_dev->v4l2_dev, "Streaming is started\n"); - return -EBUSY; - } - /* get adjacent subdev's output pad format */ - ret = __vpfe_video_get_format(video, &format); - if (ret) - return ret; - *fmt = format; - video->fmt = *fmt; - return 0; -} - -/* - * vpfe_try_fmt() - try the format on video device - * @file: file pointer - * @priv: void pointer - * @fmt: pointer to v4l2_format structure - * - * validate the format, update with correct format - * based on output format set on adjacent subdev - * - * Return 0 on success, error code otherwise - */ -static int vpfe_try_fmt(struct file *file, void *priv, - struct v4l2_format *fmt) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - struct v4l2_format format; - int ret; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_try_fmt\n"); - /* get adjacent subdev's output pad format */ - ret = __vpfe_video_get_format(video, &format); - if (ret) - return ret; - - *fmt = format; - return 0; -} - -/* - * vpfe_enum_input() - enum inputs supported on media chain - * @file: file pointer - * @priv: void pointer - * @fmt: pointer to v4l2_fmtdesc structure - * - * fills v4l2_input structure with input available on media chain, - * only one input is enumearted as media chain is setup by this time - * - * Return 0 if successful, -EINVAL is media chain is invalid - */ -static int vpfe_enum_input(struct file *file, void *priv, - struct v4l2_input *inp) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_ext_subdev_info *sdinfo = video->current_ext_subdev; - struct vpfe_device *vpfe_dev = video->vpfe_dev; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_input\n"); - /* enumerate from the subdev user has chosen through mc */ - if (inp->index < sdinfo->num_inputs) { - memcpy(inp, &sdinfo->inputs[inp->index], - sizeof(struct v4l2_input)); - return 0; - } - return -EINVAL; -} - -/* - * vpfe_g_input() - get index of the input which is active - * @file: file pointer - * @priv: void pointer - * @index: pointer to unsigned int - * - * set index with input index which is active - */ -static int vpfe_g_input(struct file *file, void *priv, unsigned int *index) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_input\n"); - - *index = video->current_input; - return 0; -} - -/* - * vpfe_s_input() - set input which is pointed by input index - * @file: file pointer - * @priv: void pointer - * @index: pointer to unsigned int - * - * set input on external subdev - * - * Return 0 on success, error code otherwise - */ -static int vpfe_s_input(struct file *file, void *priv, unsigned int index) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - struct vpfe_ext_subdev_info *sdinfo; - struct vpfe_route *route; - struct v4l2_input *inps; - u32 output; - u32 input; - int ret; - int i; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_input\n"); - - ret = mutex_lock_interruptible(&video->lock); - if (ret) - return ret; - /* - * If streaming is started return device busy - * error - */ - if (video->started) { - v4l2_err(&vpfe_dev->v4l2_dev, "Streaming is on\n"); - ret = -EBUSY; - goto unlock_out; - } - - sdinfo = video->current_ext_subdev; - if (!sdinfo->registered) { - ret = -EINVAL; - goto unlock_out; - } - if (vpfe_dev->cfg->setup_input && - vpfe_dev->cfg->setup_input(sdinfo->grp_id) < 0) { - ret = -EFAULT; - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, - "couldn't setup input for %s\n", - sdinfo->module_name); - goto unlock_out; - } - route = &sdinfo->routes[index]; - if (route && sdinfo->can_route) { - input = route->input; - output = route->output; - ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, - sdinfo->grp_id, video, - s_routing, input, output, 0); - if (ret) { - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, - "s_input:error in setting input in decoder\n"); - ret = -EINVAL; - goto unlock_out; - } - } - /* set standards set by subdev in video device */ - for (i = 0; i < sdinfo->num_inputs; i++) { - inps = &sdinfo->inputs[i]; - video->video_dev.tvnorms |= inps->std; - } - video->current_input = index; -unlock_out: - mutex_unlock(&video->lock); - return ret; -} - -/* - * vpfe_querystd() - query std which is being input on external subdev - * @file: file pointer - * @priv: void pointer - * @std_id: pointer to v4l2_std_id structure - * - * call external subdev through v4l2_device_call_until_err to - * get the std that is being active. - * - * Return 0 on success, error code otherwise - */ -static int vpfe_querystd(struct file *file, void *priv, v4l2_std_id *std_id) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - struct vpfe_ext_subdev_info *sdinfo; - int ret; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querystd\n"); - - ret = mutex_lock_interruptible(&video->lock); - sdinfo = video->current_ext_subdev; - if (ret) - return ret; - /* Call querystd function of decoder device */ - ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id, - video, querystd, std_id); - mutex_unlock(&video->lock); - return ret; -} - -/* - * vpfe_s_std() - set std on external subdev - * @file: file pointer - * @priv: void pointer - * @std_id: pointer to v4l2_std_id structure - * - * set std pointed by std_id on external subdev by calling it using - * v4l2_device_call_until_err - * - * Return 0 on success, error code otherwise - */ -static int vpfe_s_std(struct file *file, void *priv, v4l2_std_id std_id) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - struct vpfe_ext_subdev_info *sdinfo; - int ret; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_std\n"); - - /* Call decoder driver function to set the standard */ - ret = mutex_lock_interruptible(&video->lock); - if (ret) - return ret; - sdinfo = video->current_ext_subdev; - /* If streaming is started, return device busy error */ - if (video->started) { - v4l2_err(&vpfe_dev->v4l2_dev, "streaming is started\n"); - ret = -EBUSY; - goto unlock_out; - } - ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id, - video, s_std, std_id); - if (ret < 0) { - v4l2_err(&vpfe_dev->v4l2_dev, "Failed to set standard\n"); - video->stdid = V4L2_STD_UNKNOWN; - goto unlock_out; - } - video->stdid = std_id; -unlock_out: - mutex_unlock(&video->lock); - return ret; -} - -static int vpfe_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_std\n"); - *tvnorm = video->stdid; - return 0; -} - -/* - * vpfe_enum_dv_timings() - enumerate dv_timings which are supported by - * to external subdev - * @file: file pointer - * @priv: void pointer - * @timings: pointer to v4l2_enum_dv_timings structure - * - * enum dv_timings's which are supported by external subdev through - * v4l2_subdev_call - * - * Return 0 on success, error code otherwise - */ -static int -vpfe_enum_dv_timings(struct file *file, void *fh, - struct v4l2_enum_dv_timings *timings) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - struct v4l2_subdev *subdev = video->current_ext_subdev->subdev; - - timings->pad = 0; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_dv_timings\n"); - return v4l2_subdev_call(subdev, pad, enum_dv_timings, timings); -} - -/* - * vpfe_query_dv_timings() - query the dv_timings which is being input - * to external subdev - * @file: file pointer - * @priv: void pointer - * @timings: pointer to v4l2_dv_timings structure - * - * get dv_timings which is being input on external subdev through - * v4l2_subdev_call - * - * Return 0 on success, error code otherwise - */ -static int -vpfe_query_dv_timings(struct file *file, void *fh, - struct v4l2_dv_timings *timings) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - struct v4l2_subdev *subdev = video->current_ext_subdev->subdev; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_query_dv_timings\n"); - return v4l2_subdev_call(subdev, video, query_dv_timings, timings); -} - -/* - * vpfe_s_dv_timings() - set dv_timings on external subdev - * @file: file pointer - * @priv: void pointer - * @timings: pointer to v4l2_dv_timings structure - * - * set dv_timings pointed by timings on external subdev through - * v4l2_device_call_until_err, this configures amplifier also - * - * Return 0 on success, error code otherwise - */ -static int -vpfe_s_dv_timings(struct file *file, void *fh, - struct v4l2_dv_timings *timings) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_dv_timings\n"); - - video->stdid = V4L2_STD_UNKNOWN; - return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, - video->current_ext_subdev->grp_id, - video, s_dv_timings, timings); -} - -/* - * vpfe_g_dv_timings() - get dv_timings which is set on external subdev - * @file: file pointer - * @priv: void pointer - * @timings: pointer to v4l2_dv_timings structure - * - * get dv_timings which is set on external subdev through - * v4l2_subdev_call - * - * Return 0 on success, error code otherwise - */ -static int -vpfe_g_dv_timings(struct file *file, void *fh, - struct v4l2_dv_timings *timings) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - struct v4l2_subdev *subdev = video->current_ext_subdev->subdev; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_dv_timings\n"); - return v4l2_subdev_call(subdev, video, g_dv_timings, timings); -} - -/* - * Videobuf operations - */ -/* - * vpfe_buffer_queue_setup : Callback function for buffer setup. - * @vq: vb2_queue ptr - * @fmt: v4l2 format - * @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 nbuffers and buffer size - */ -static int -vpfe_buffer_queue_setup(struct vb2_queue *vq, - unsigned int *nbuffers, unsigned int *nplanes, - unsigned int sizes[], struct device *alloc_devs[]) -{ - struct vpfe_fh *fh = vb2_get_drv_priv(vq); - struct vpfe_video_device *video = fh->video; - struct vpfe_device *vpfe_dev = video->vpfe_dev; - unsigned long size; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_queue_setup\n"); - size = video->fmt.fmt.pix.sizeimage; - - if (vq->num_buffers + *nbuffers < 3) - *nbuffers = 3 - vq->num_buffers; - - *nplanes = 1; - sizes[0] = size; - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, - "nbuffers=%d, size=%lu\n", *nbuffers, size); - return 0; -} - -/* - * vpfe_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 vpfe_buffer_prepare(struct vb2_buffer *vb) -{ - struct vpfe_fh *fh = vb2_get_drv_priv(vb->vb2_queue); - struct vpfe_video_device *video = fh->video; - struct vpfe_device *vpfe_dev = video->vpfe_dev; - unsigned long addr; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_prepare\n"); - - /* Initialize buffer */ - vb2_set_plane_payload(vb, 0, video->fmt.fmt.pix.sizeimage); - if (vb2_plane_vaddr(vb, 0) && - vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) - return -EINVAL; - - addr = vb2_dma_contig_plane_dma_addr(vb, 0); - /* Make sure user addresses are aligned to 32 bytes */ - if (!ALIGN(addr, 32)) - return -EINVAL; - - return 0; -} - -static void vpfe_buffer_queue(struct vb2_buffer *vb) -{ - struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - /* Get the file handle object and device object */ - struct vpfe_fh *fh = vb2_get_drv_priv(vb->vb2_queue); - struct vpfe_video_device *video = fh->video; - struct vpfe_device *vpfe_dev = video->vpfe_dev; - struct vpfe_pipeline *pipe = &video->pipe; - struct vpfe_cap_buffer *buf = container_of(vbuf, - struct vpfe_cap_buffer, vb); - unsigned long flags; - unsigned long empty; - unsigned long addr; - - spin_lock_irqsave(&video->dma_queue_lock, flags); - empty = list_empty(&video->dma_queue); - /* add the buffer to the DMA queue */ - list_add_tail(&buf->list, &video->dma_queue); - spin_unlock_irqrestore(&video->dma_queue_lock, flags); - /* this case happens in case of single shot */ - if (empty && video->started && pipe->state == - VPFE_PIPELINE_STREAM_SINGLESHOT && - video->state == VPFE_VIDEO_BUFFER_NOT_QUEUED) { - spin_lock(&video->dma_queue_lock); - addr = vpfe_video_get_next_buffer(video); - video->ops->queue(vpfe_dev, addr); - - video->state = VPFE_VIDEO_BUFFER_QUEUED; - spin_unlock(&video->dma_queue_lock); - - /* enable h/w each time in single shot */ - if (vpfe_video_is_pipe_ready(pipe)) - vpfe_pipeline_set_stream(pipe, - VPFE_PIPELINE_STREAM_SINGLESHOT); - } -} - -/* vpfe_start_capture() - start streaming on all the subdevs */ -static int vpfe_start_capture(struct vpfe_video_device *video) -{ - struct vpfe_pipeline *pipe = &video->pipe; - int ret = 0; - - video->started = 1; - if (vpfe_video_is_pipe_ready(pipe)) - ret = vpfe_pipeline_set_stream(pipe, pipe->state); - - return ret; -} - -static int vpfe_start_streaming(struct vb2_queue *vq, unsigned int count) -{ - struct vpfe_fh *fh = vb2_get_drv_priv(vq); - struct vpfe_video_device *video = fh->video; - struct vpfe_device *vpfe_dev = video->vpfe_dev; - unsigned long addr; - int ret; - - ret = mutex_lock_interruptible(&video->lock); - if (ret) - goto streamoff; - - /* Get the next frame from the buffer queue */ - video->cur_frm = video->next_frm = - list_entry(video->dma_queue.next, struct vpfe_cap_buffer, list); - /* Remove buffer from the buffer queue */ - list_del(&video->cur_frm->list); - /* Mark state of the current frame to active */ - video->cur_frm->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE; - /* Initialize field_id and started member */ - video->field_id = 0; - addr = vb2_dma_contig_plane_dma_addr(&video->cur_frm->vb.vb2_buf, 0); - video->ops->queue(vpfe_dev, addr); - video->state = VPFE_VIDEO_BUFFER_QUEUED; - - ret = vpfe_start_capture(video); - if (ret) { - struct vpfe_cap_buffer *buf, *tmp; - - vb2_buffer_done(&video->cur_frm->vb.vb2_buf, - VB2_BUF_STATE_QUEUED); - list_for_each_entry_safe(buf, tmp, &video->dma_queue, list) { - list_del(&buf->list); - vb2_buffer_done(&buf->vb.vb2_buf, - VB2_BUF_STATE_QUEUED); - } - goto unlock_out; - } - - mutex_unlock(&video->lock); - - return ret; -unlock_out: - mutex_unlock(&video->lock); -streamoff: - ret = vb2_streamoff(&video->buffer_queue, video->buffer_queue.type); - return 0; -} - -static int vpfe_buffer_init(struct vb2_buffer *vb) -{ - struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - struct vpfe_cap_buffer *buf = container_of(vbuf, - struct vpfe_cap_buffer, vb); - - INIT_LIST_HEAD(&buf->list); - return 0; -} - -/* abort streaming and wait for last buffer */ -static void vpfe_stop_streaming(struct vb2_queue *vq) -{ - struct vpfe_fh *fh = vb2_get_drv_priv(vq); - struct vpfe_video_device *video = fh->video; - - /* release all active buffers */ - if (video->cur_frm == video->next_frm) { - vb2_buffer_done(&video->cur_frm->vb.vb2_buf, - VB2_BUF_STATE_ERROR); - } else { - if (video->cur_frm != NULL) - vb2_buffer_done(&video->cur_frm->vb.vb2_buf, - VB2_BUF_STATE_ERROR); - if (video->next_frm != NULL) - vb2_buffer_done(&video->next_frm->vb.vb2_buf, - VB2_BUF_STATE_ERROR); - } - - while (!list_empty(&video->dma_queue)) { - video->next_frm = list_entry(video->dma_queue.next, - struct vpfe_cap_buffer, list); - list_del(&video->next_frm->list); - vb2_buffer_done(&video->next_frm->vb.vb2_buf, - VB2_BUF_STATE_ERROR); - } -} - -static void vpfe_buf_cleanup(struct vb2_buffer *vb) -{ - struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - struct vpfe_fh *fh = vb2_get_drv_priv(vb->vb2_queue); - struct vpfe_video_device *video = fh->video; - struct vpfe_device *vpfe_dev = video->vpfe_dev; - struct vpfe_cap_buffer *buf = container_of(vbuf, - struct vpfe_cap_buffer, vb); - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buf_cleanup\n"); - if (vb->state == VB2_BUF_STATE_ACTIVE) - list_del_init(&buf->list); -} - -static const struct vb2_ops video_qops = { - .queue_setup = vpfe_buffer_queue_setup, - .buf_init = vpfe_buffer_init, - .buf_prepare = vpfe_buffer_prepare, - .start_streaming = vpfe_start_streaming, - .stop_streaming = vpfe_stop_streaming, - .buf_cleanup = vpfe_buf_cleanup, - .buf_queue = vpfe_buffer_queue, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, -}; - -/* - * vpfe_reqbufs() - supported REQBUF only once opening - * the device. - */ -static int vpfe_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *req_buf) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - struct vpfe_fh *fh = file->private_data; - struct vb2_queue *q; - int ret; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_reqbufs\n"); - - if (req_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && - req_buf->type != V4L2_BUF_TYPE_VIDEO_OUTPUT){ - v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buffer type\n"); - return -EINVAL; - } - - ret = mutex_lock_interruptible(&video->lock); - if (ret) - return ret; - - if (video->io_usrs != 0) { - v4l2_err(&vpfe_dev->v4l2_dev, "Only one IO user allowed\n"); - ret = -EBUSY; - goto unlock_out; - } - video->memory = req_buf->memory; - - /* Initialize videobuf2 queue as per the buffer type */ - q = &video->buffer_queue; - q->type = req_buf->type; - q->io_modes = VB2_MMAP | VB2_USERPTR; - q->drv_priv = fh; - q->min_buffers_needed = 1; - q->ops = &video_qops; - q->mem_ops = &vb2_dma_contig_memops; - q->buf_struct_size = sizeof(struct vpfe_cap_buffer); - q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - q->dev = vpfe_dev->pdev; - q->lock = &video->lock; - - ret = vb2_queue_init(q); - if (ret) { - v4l2_err(&vpfe_dev->v4l2_dev, "vb2_queue_init() failed\n"); - goto unlock_out; - } - - fh->io_allowed = 1; - video->io_usrs = 1; - INIT_LIST_HEAD(&video->dma_queue); - ret = vb2_reqbufs(&video->buffer_queue, req_buf); - -unlock_out: - mutex_unlock(&video->lock); - return ret; -} - -/* - * vpfe_querybuf() - query buffers for exchange - */ -static int vpfe_querybuf(struct file *file, void *priv, - struct v4l2_buffer *buf) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querybuf\n"); - - if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && - buf->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) { - v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n"); - return -EINVAL; - } - - if (video->memory != V4L2_MEMORY_MMAP) { - v4l2_err(&vpfe_dev->v4l2_dev, "Invalid memory\n"); - return -EINVAL; - } - - /* Call vb2_querybuf to get information */ - return vb2_querybuf(&video->buffer_queue, buf); -} - -/* - * vpfe_qbuf() - queue buffers for capture or processing - */ -static int vpfe_qbuf(struct file *file, void *priv, - struct v4l2_buffer *p) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - struct vpfe_fh *fh = file->private_data; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_qbuf\n"); - - if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && - p->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) { - v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n"); - return -EINVAL; - } - /* - * If this file handle is not allowed to do IO, - * return error - */ - if (!fh->io_allowed) { - v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n"); - return -EACCES; - } - - return vb2_qbuf(&video->buffer_queue, - video->video_dev.v4l2_dev->mdev, p); -} - -/* - * vpfe_dqbuf() - deque buffer which is done with processing - */ -static int vpfe_dqbuf(struct file *file, void *priv, - struct v4l2_buffer *buf) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_dqbuf\n"); - - if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && - buf->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) { - v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n"); - return -EINVAL; - } - - return vb2_dqbuf(&video->buffer_queue, - buf, (file->f_flags & O_NONBLOCK)); -} - -/* - * vpfe_streamon() - start streaming - * @file: file pointer - * @priv: void pointer - * @buf_type: enum v4l2_buf_type - * - * queue buffer onto hardware for capture/processing and - * start all the subdevs which are in media chain - * - * Return 0 on success, error code otherwise - */ -static int vpfe_streamon(struct file *file, void *priv, - enum v4l2_buf_type buf_type) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - struct vpfe_pipeline *pipe = &video->pipe; - struct vpfe_fh *fh = file->private_data; - int ret = -EINVAL; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_streamon\n"); - - if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE && - buf_type != V4L2_BUF_TYPE_VIDEO_OUTPUT) { - v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n"); - return ret; - } - /* If file handle is not allowed IO, return error */ - if (!fh->io_allowed) { - v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n"); - return -EACCES; - } - /* If buffer queue is empty, return error */ - if (list_empty(&video->buffer_queue.queued_list)) { - v4l2_err(&vpfe_dev->v4l2_dev, "buffer queue is empty\n"); - return -EIO; - } - /* Validate the pipeline */ - if (buf_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - ret = vpfe_video_validate_pipeline(pipe); - if (ret < 0) - return ret; - } - /* Call vb2_streamon to start streaming */ - return vb2_streamon(&video->buffer_queue, buf_type); -} - -/* - * vpfe_streamoff() - stop streaming - * @file: file pointer - * @priv: void pointer - * @buf_type: enum v4l2_buf_type - * - * stop all the subdevs which are in media chain - * - * Return 0 on success, error code otherwise - */ -static int vpfe_streamoff(struct file *file, void *priv, - enum v4l2_buf_type buf_type) -{ - struct vpfe_video_device *video = video_drvdata(file); - struct vpfe_device *vpfe_dev = video->vpfe_dev; - struct vpfe_fh *fh = file->private_data; - int ret = 0; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_streamoff\n"); - - if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE && - buf_type != V4L2_BUF_TYPE_VIDEO_OUTPUT) { - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "Invalid buf type\n"); - return -EINVAL; - } - - /* If io is allowed for this file handle, return error */ - if (!fh->io_allowed) { - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "fh->io_allowed\n"); - return -EACCES; - } - - /* If streaming is not started, return error */ - if (!video->started) { - v4l2_err(&vpfe_dev->v4l2_dev, "device is not started\n"); - return -EINVAL; - } - - ret = mutex_lock_interruptible(&video->lock); - if (ret) - return ret; - - vpfe_stop_capture(video); - ret = vb2_streamoff(&video->buffer_queue, buf_type); - mutex_unlock(&video->lock); - - return ret; -} - -/* vpfe capture ioctl operations */ -static const struct v4l2_ioctl_ops vpfe_ioctl_ops = { - .vidioc_querycap = vpfe_querycap, - .vidioc_g_fmt_vid_cap = vpfe_g_fmt, - .vidioc_s_fmt_vid_cap = vpfe_s_fmt, - .vidioc_try_fmt_vid_cap = vpfe_try_fmt, - .vidioc_enum_fmt_vid_cap = vpfe_enum_fmt, - .vidioc_g_fmt_vid_out = vpfe_g_fmt, - .vidioc_s_fmt_vid_out = vpfe_s_fmt, - .vidioc_try_fmt_vid_out = vpfe_try_fmt, - .vidioc_enum_fmt_vid_out = vpfe_enum_fmt, - .vidioc_enum_input = vpfe_enum_input, - .vidioc_g_input = vpfe_g_input, - .vidioc_s_input = vpfe_s_input, - .vidioc_querystd = vpfe_querystd, - .vidioc_s_std = vpfe_s_std, - .vidioc_g_std = vpfe_g_std, - .vidioc_enum_dv_timings = vpfe_enum_dv_timings, - .vidioc_query_dv_timings = vpfe_query_dv_timings, - .vidioc_s_dv_timings = vpfe_s_dv_timings, - .vidioc_g_dv_timings = vpfe_g_dv_timings, - .vidioc_reqbufs = vpfe_reqbufs, - .vidioc_querybuf = vpfe_querybuf, - .vidioc_qbuf = vpfe_qbuf, - .vidioc_dqbuf = vpfe_dqbuf, - .vidioc_streamon = vpfe_streamon, - .vidioc_streamoff = vpfe_streamoff, -}; - -/* VPFE video init function */ -int vpfe_video_init(struct vpfe_video_device *video, const char *name) -{ - const char *direction; - int ret; - - switch (video->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - direction = "output"; - video->pad.flags = MEDIA_PAD_FL_SINK; - video->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - break; - - case V4L2_BUF_TYPE_VIDEO_OUTPUT: - direction = "input"; - video->pad.flags = MEDIA_PAD_FL_SOURCE; - video->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - break; - - default: - return -EINVAL; - } - /* Initialize field of video device */ - mutex_init(&video->lock); - video->video_dev.release = video_device_release; - video->video_dev.fops = &vpfe_fops; - video->video_dev.ioctl_ops = &vpfe_ioctl_ops; - video->video_dev.minor = -1; - video->video_dev.tvnorms = 0; - video->video_dev.lock = &video->lock; - snprintf(video->video_dev.name, sizeof(video->video_dev.name), - "DAVINCI VIDEO %s %s", name, direction); - - spin_lock_init(&video->irqlock); - spin_lock_init(&video->dma_queue_lock); - ret = media_entity_pads_init(&video->video_dev.entity, - 1, &video->pad); - if (ret < 0) - return ret; - - video_set_drvdata(&video->video_dev, video); - - return 0; -} - -/* vpfe video device register function */ -int vpfe_video_register(struct vpfe_video_device *video, - struct v4l2_device *vdev) -{ - int ret; - - video->video_dev.v4l2_dev = vdev; - - if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - video->video_dev.device_caps = V4L2_CAP_VIDEO_CAPTURE; - else - video->video_dev.device_caps = V4L2_CAP_VIDEO_OUTPUT; - video->video_dev.device_caps |= V4L2_CAP_STREAMING; - ret = video_register_device(&video->video_dev, VFL_TYPE_GRABBER, -1); - if (ret < 0) - pr_err("%s: could not register video device (%d)\n", - __func__, ret); - return ret; -} - -/* vpfe video device unregister function */ -void vpfe_video_unregister(struct vpfe_video_device *video) -{ - if (video_is_registered(&video->video_dev)) { - video_unregister_device(&video->video_dev); - media_entity_cleanup(&video->video_dev.entity); - } -} diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.h b/drivers/staging/media/davinci_vpfe/vpfe_video.h deleted file mode 100644 index 5d01c4883ab4..000000000000 --- a/drivers/staging/media/davinci_vpfe/vpfe_video.h +++ /dev/null @@ -1,150 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) 2012 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Contributors: - * Manjunath Hadli <manjunath.hadli@ti.com> - * Prabhakar Lad <prabhakar.lad@ti.com> - */ - -#ifndef _DAVINCI_VPFE_VIDEO_H -#define _DAVINCI_VPFE_VIDEO_H - -#include <media/videobuf2-v4l2.h> -#include <media/videobuf2-dma-contig.h> - -struct vpfe_device; - -/* - * struct vpfe_video_operations - VPFE video operations - * @queue: Resume streaming when a buffer is queued. Called on VIDIOC_QBUF - * if there was no buffer previously queued. - */ -struct vpfe_video_operations { - int (*queue)(struct vpfe_device *vpfe_dev, unsigned long addr); -}; - -enum vpfe_pipeline_stream_state { - VPFE_PIPELINE_STREAM_STOPPED = 0, - VPFE_PIPELINE_STREAM_CONTINUOUS = 1, - VPFE_PIPELINE_STREAM_SINGLESHOT = 2, -}; - -enum vpfe_video_state { - /* indicates that buffer is not queued */ - VPFE_VIDEO_BUFFER_NOT_QUEUED = 0, - /* indicates that buffer is queued */ - VPFE_VIDEO_BUFFER_QUEUED = 1, -}; - -struct vpfe_pipeline { - /* media pipeline */ - struct media_pipeline *pipe; - struct media_graph graph; - /* state of the pipeline, continuous, - * single-shot or stopped - */ - enum vpfe_pipeline_stream_state state; - /* number of active input video entities */ - unsigned int input_num; - /* number of active output video entities */ - unsigned int output_num; - /* input video nodes in case of single-shot mode */ - struct vpfe_video_device *inputs[10]; - /* capturing video nodes */ - struct vpfe_video_device *outputs[10]; -}; - -#define to_vpfe_pipeline(__e) \ - container_of((__e)->pipe, struct vpfe_pipeline, pipe) - -#define to_vpfe_video(vdev) \ - container_of(vdev, struct vpfe_video_device, video_dev) - -struct vpfe_cap_buffer { - struct vb2_v4l2_buffer vb; - struct list_head list; -}; - -struct vpfe_video_device { - /* vpfe device */ - struct vpfe_device *vpfe_dev; - /* video dev */ - struct video_device video_dev; - /* media pad of video entity */ - struct media_pad pad; - /* video operations supported by video device */ - const struct vpfe_video_operations *ops; - /* type of the video buffers used by user */ - enum v4l2_buf_type type; - /* Indicates id of the field which is being captured */ - u32 field_id; - /* pipeline for which video device is part of */ - struct vpfe_pipeline pipe; - /* Indicates whether streaming started */ - u8 started; - /* Indicates state of the stream */ - unsigned int state; - /* current input at the sub device */ - int current_input; - /* - * This field keeps track of type of buffer exchange mechanism - * user has selected - */ - enum v4l2_memory memory; - /* number of open instances of the channel */ - u32 usrs; - /* flag to indicate whether decoder is initialized */ - u8 initialized; - /* skip frame count */ - u8 skip_frame_count; - /* skip frame count init value */ - u8 skip_frame_count_init; - /* time per frame for skipping */ - struct v4l2_fract timeperframe; - /* ptr to currently selected sub device */ - struct vpfe_ext_subdev_info *current_ext_subdev; - /* Pointer pointing to current vpfe_cap_buffer */ - struct vpfe_cap_buffer *cur_frm; - /* Pointer pointing to next vpfe_cap_buffer */ - struct vpfe_cap_buffer *next_frm; - /* Used to store pixel format */ - struct v4l2_format fmt; - struct vb2_queue buffer_queue; - /* Queue of filled frames */ - struct list_head dma_queue; - spinlock_t irqlock; - /* IRQ lock for DMA queue */ - spinlock_t dma_queue_lock; - /* lock used to serialize all video4linux ioctls */ - struct mutex lock; - /* number of users performing IO */ - u32 io_usrs; - /* Currently selected or default standard */ - v4l2_std_id stdid; - /* - * offset where second field starts from the starting of the - * buffer for field separated YCbCr formats - */ - u32 field_off; -}; - -int vpfe_video_is_pipe_ready(struct vpfe_pipeline *pipe); -void vpfe_video_unregister(struct vpfe_video_device *video); -int vpfe_video_register(struct vpfe_video_device *video, - struct v4l2_device *vdev); -int vpfe_video_init(struct vpfe_video_device *video, const char *name); -void vpfe_video_process_buffer_complete(struct vpfe_video_device *video); -void vpfe_video_schedule_bottom_field(struct vpfe_video_device *video); -void vpfe_video_schedule_next_buffer(struct vpfe_video_device *video); - -#endif /* _DAVINCI_VPFE_VIDEO_H */ |