// SPDX-License-Identifier: GPL-2.0-only /* * ispccp2.c * * TI OMAP3 ISP - CCP2 module * * Copyright (C) 2010 Nokia Corporation * Copyright (C) 2010 Texas Instruments, Inc. * * Contacts: Laurent Pinchart <[email protected]> * Sakari Ailus <[email protected]> */ #include <linux/delay.h> #include <linux/device.h> #include <linux/mm.h> #include <linux/module.h> #include <linux/mutex.h> #include <linux/uaccess.h> #include <linux/regulator/consumer.h> #include "isp.h" #include "ispreg.h" #include "ispccp2.h" /* Number of LCX channels */ #define CCP2_LCx_CHANS_NUM … /* Max/Min size for CCP2 video port */ #define ISPCCP2_DAT_START_MIN … #define ISPCCP2_DAT_START_MAX … #define ISPCCP2_DAT_SIZE_MIN … #define ISPCCP2_DAT_SIZE_MAX … #define ISPCCP2_VPCLK_FRACDIV … #define ISPCCP2_LCx_CTRL_FORMAT_RAW8_DPCM10_VP … #define ISPCCP2_LCx_CTRL_FORMAT_RAW10_VP … /* Max/Min size for CCP2 memory channel */ #define ISPCCP2_LCM_HSIZE_COUNT_MIN … #define ISPCCP2_LCM_HSIZE_COUNT_MAX … #define ISPCCP2_LCM_HSIZE_SKIP_MIN … #define ISPCCP2_LCM_HSIZE_SKIP_MAX … #define ISPCCP2_LCM_VSIZE_MIN … #define ISPCCP2_LCM_VSIZE_MAX … #define ISPCCP2_LCM_HWORDS_MIN … #define ISPCCP2_LCM_HWORDS_MAX … #define ISPCCP2_LCM_CTRL_BURST_SIZE_32X … #define ISPCCP2_LCM_CTRL_READ_THROTTLE_FULL … #define ISPCCP2_LCM_CTRL_SRC_DECOMPR_DPCM10 … #define ISPCCP2_LCM_CTRL_SRC_FORMAT_RAW8 … #define ISPCCP2_LCM_CTRL_SRC_FORMAT_RAW10 … #define ISPCCP2_LCM_CTRL_DST_FORMAT_RAW10 … #define ISPCCP2_LCM_CTRL_DST_PORT_VP … #define ISPCCP2_LCM_CTRL_DST_PORT_MEM … /* Set only the required bits */ #define BIT_SET(var, shift, mask, val) … /* * ccp2_print_status - Print current CCP2 module register values. */ #define CCP2_PRINT_REGISTER(isp, name) … static void ccp2_print_status(struct isp_ccp2_device *ccp2) { … } /* * ccp2_reset - Reset the CCP2 * @ccp2: pointer to ISP CCP2 device */ static void ccp2_reset(struct isp_ccp2_device *ccp2) { … } /* * ccp2_pwr_cfg - Configure the power mode settings * @ccp2: pointer to ISP CCP2 device */ static void ccp2_pwr_cfg(struct isp_ccp2_device *ccp2) { … } /* * ccp2_if_enable - Enable CCP2 interface. * @ccp2: pointer to ISP CCP2 device * @enable: enable/disable flag */ static int ccp2_if_enable(struct isp_ccp2_device *ccp2, u8 enable) { … } /* * ccp2_mem_enable - Enable CCP2 memory interface. * @ccp2: pointer to ISP CCP2 device * @enable: enable/disable flag */ static void ccp2_mem_enable(struct isp_ccp2_device *ccp2, u8 enable) { … } /* * ccp2_phyif_config - Initialize CCP2 phy interface config * @ccp2: Pointer to ISP CCP2 device * @buscfg: CCP2 platform data * * Configure the CCP2 physical interface module from platform data. * * Returns -EIO if strobe is chosen in CSI1 mode, or 0 on success. */ static int ccp2_phyif_config(struct isp_ccp2_device *ccp2, const struct isp_ccp2_cfg *buscfg) { … } /* * ccp2_vp_config - Initialize CCP2 video port interface. * @ccp2: Pointer to ISP CCP2 device * @vpclk_div: Video port divisor * * Configure the CCP2 video port with the given clock divisor. The valid divisor * values depend on the ISP revision: * * - revision 1.0 and 2.0 1 to 4 * - revision 15.0 1 to 65536 * * The exact divisor value used might differ from the requested value, as ISP * revision 15.0 represent the divisor by 65536 divided by an integer. */ static void ccp2_vp_config(struct isp_ccp2_device *ccp2, unsigned int vpclk_div) { … } /* * ccp2_lcx_config - Initialize CCP2 logical channel interface. * @ccp2: Pointer to ISP CCP2 device * @config: Pointer to ISP LCx config structure. * * This will analyze the parameters passed by the interface config * and configure CSI1/CCP2 logical channel * */ static void ccp2_lcx_config(struct isp_ccp2_device *ccp2, struct isp_interface_lcx_config *config) { … } /* * ccp2_if_configure - Configure ccp2 with data from sensor * @ccp2: Pointer to ISP CCP2 device * * Return 0 on success or a negative error code */ static int ccp2_if_configure(struct isp_ccp2_device *ccp2) { … } static int ccp2_adjust_bandwidth(struct isp_ccp2_device *ccp2) { … } /* * ccp2_mem_configure - Initialize CCP2 memory input/output interface * @ccp2: Pointer to ISP CCP2 device * @config: Pointer to ISP mem interface config structure * * This will analyze the parameters passed by the interface config * structure, and configure the respective registers for proper * CSI1/CCP2 memory input. */ static void ccp2_mem_configure(struct isp_ccp2_device *ccp2, struct isp_interface_mem_config *config) { … } /* * ccp2_set_inaddr - Sets memory address of input frame. * @ccp2: Pointer to ISP CCP2 device * @addr: 32bit memory address aligned on 32byte boundary. * * Configures the memory address from which the input frame is to be read. */ static void ccp2_set_inaddr(struct isp_ccp2_device *ccp2, u32 addr) { … } /* ----------------------------------------------------------------------------- * Interrupt handling */ static void ccp2_isr_buffer(struct isp_ccp2_device *ccp2) { … } /* * omap3isp_ccp2_isr - Handle ISP CCP2 interrupts * @ccp2: Pointer to ISP CCP2 device * * This will handle the CCP2 interrupts */ void omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2) { … } /* ----------------------------------------------------------------------------- * V4L2 subdev operations */ static const unsigned int ccp2_fmts[] = …; /* * __ccp2_get_format - helper function for getting ccp2 format * @ccp2 : Pointer to ISP CCP2 device * @sd_state: V4L2 subdev state * @pad : pad number * @which : wanted subdev format * return format structure or NULL on error */ static struct v4l2_mbus_framefmt * __ccp2_get_format(struct isp_ccp2_device *ccp2, struct v4l2_subdev_state *sd_state, unsigned int pad, enum v4l2_subdev_format_whence which) { … } /* * ccp2_try_format - Handle try format by pad subdev method * @ccp2 : Pointer to ISP CCP2 device * @sd_state: V4L2 subdev state * @pad : pad num * @fmt : pointer to v4l2 mbus format structure * @which : wanted subdev format */ static void ccp2_try_format(struct isp_ccp2_device *ccp2, struct v4l2_subdev_state *sd_state, unsigned int pad, struct v4l2_mbus_framefmt *fmt, enum v4l2_subdev_format_whence which) { … } /* * ccp2_enum_mbus_code - Handle pixel format enumeration * @sd : pointer to v4l2 subdev structure * @sd_state: V4L2 subdev state * @code : pointer to v4l2_subdev_mbus_code_enum structure * return -EINVAL or zero on success */ static int ccp2_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_mbus_code_enum *code) { … } static int ccp2_enum_frame_size(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_frame_size_enum *fse) { … } /* * ccp2_get_format - Handle get format by pads subdev method * @sd : pointer to v4l2 subdev structure * @sd_state: V4L2 subdev state * @fmt : pointer to v4l2 subdev format structure * return -EINVAL or zero on success */ static int ccp2_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *fmt) { … } /* * ccp2_set_format - Handle set format by pads subdev method * @sd : pointer to v4l2 subdev structure * @sd_state: V4L2 subdev state * @fmt : pointer to v4l2 subdev format structure * returns zero */ static int ccp2_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *fmt) { … } /* * ccp2_init_formats - Initialize formats on all pads * @sd: ISP CCP2 V4L2 subdevice * @fh: V4L2 subdev file handle * * Initialize all pad formats with default values. If fh is not NULL, try * formats are initialized on the file handle. Otherwise active formats are * initialized on the device. */ static int ccp2_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { … } /* * ccp2_s_stream - Enable/Disable streaming on ccp2 subdev * @sd : pointer to v4l2 subdev structure * @enable: 1 == Enable, 0 == Disable * return zero */ static int ccp2_s_stream(struct v4l2_subdev *sd, int enable) { … } /* subdev video operations */ static const struct v4l2_subdev_video_ops ccp2_sd_video_ops = …; /* subdev pad operations */ static const struct v4l2_subdev_pad_ops ccp2_sd_pad_ops = …; /* subdev operations */ static const struct v4l2_subdev_ops ccp2_sd_ops = …; /* subdev internal operations */ static const struct v4l2_subdev_internal_ops ccp2_sd_internal_ops = …; /* -------------------------------------------------------------------------- * ISP ccp2 video device node */ /* * ccp2_video_queue - Queue video buffer. * @video : Pointer to isp video structure * @buffer: Pointer to isp_buffer structure * return -EIO or zero on success */ static int ccp2_video_queue(struct isp_video *video, struct isp_buffer *buffer) { … } static const struct isp_video_operations ccp2_video_ops = …; /* ----------------------------------------------------------------------------- * Media entity operations */ /* * ccp2_link_setup - Setup ccp2 connections. * @entity : Pointer to media entity structure * @local : Pointer to local pad array * @remote : Pointer to remote pad array * @flags : Link flags * return -EINVAL on error or zero on success */ static int ccp2_link_setup(struct media_entity *entity, const struct media_pad *local, const struct media_pad *remote, u32 flags) { … } /* media operations */ static const struct media_entity_operations ccp2_media_ops = …; /* * omap3isp_ccp2_unregister_entities - Unregister media entities: subdev * @ccp2: Pointer to ISP CCP2 device */ void omap3isp_ccp2_unregister_entities(struct isp_ccp2_device *ccp2) { … } /* * omap3isp_ccp2_register_entities - Register the subdev media entity * @ccp2: Pointer to ISP CCP2 device * @vdev: Pointer to v4l device * return negative error code or zero on success */ int omap3isp_ccp2_register_entities(struct isp_ccp2_device *ccp2, struct v4l2_device *vdev) { … } /* ----------------------------------------------------------------------------- * ISP ccp2 initialisation and cleanup */ /* * ccp2_init_entities - Initialize ccp2 subdev and media entity. * @ccp2: Pointer to ISP CCP2 device * return negative error code or zero on success */ static int ccp2_init_entities(struct isp_ccp2_device *ccp2) { … } /* * omap3isp_ccp2_init - CCP2 initialization. * @isp : Pointer to ISP device * return negative error code or zero on success */ int omap3isp_ccp2_init(struct isp_device *isp) { … } /* * omap3isp_ccp2_cleanup - CCP2 un-initialization * @isp : Pointer to ISP device */ void omap3isp_ccp2_cleanup(struct isp_device *isp) { … }