// SPDX-License-Identifier: GPL-2.0-or-later /* Texas Instruments Triple 8-/10-BIT 165-/110-MSPS Video and Graphics * Digitizer with Horizontal PLL registers * * Copyright (C) 2009 Texas Instruments Inc * Author: Santiago Nunez-Corrales <[email protected]> * * This code is partially based upon the TVP5150 driver * written by Mauro Carvalho Chehab <[email protected]>, * the TVP514x driver written by Vaibhav Hiremath <[email protected]> * and the TVP7002 driver in the TI LSP 2.10.00.14. Revisions by * Muralidharan Karicheri and Snehaprabha Narnakaje (TI). */ #include <linux/delay.h> #include <linux/i2c.h> #include <linux/slab.h> #include <linux/videodev2.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_graph.h> #include <linux/v4l2-dv-timings.h> #include <media/i2c/tvp7002.h> #include <media/v4l2-async.h> #include <media/v4l2-device.h> #include <media/v4l2-common.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-fwnode.h> #include "tvp7002_reg.h" MODULE_DESCRIPTION(…) …; MODULE_AUTHOR(…) …; MODULE_LICENSE(…) …; /* I2C retry attempts */ #define I2C_RETRY_COUNT … /* End of registers */ #define TVP7002_EOR … /* Read write definition for registers */ #define TVP7002_READ … #define TVP7002_WRITE … #define TVP7002_RESERVED … /* Interlaced vs progressive mask and shift */ #define TVP7002_IP_SHIFT … #define TVP7002_INPR_MASK … /* Shift for CPL and LPF registers */ #define TVP7002_CL_SHIFT … #define TVP7002_CL_MASK … /* Debug functions */ static bool debug; module_param(debug, bool, 0644); MODULE_PARM_DESC(…) …; /* Structure for register values */ struct i2c_reg_value { … }; /* * Register default values (according to tvp7002 datasheet) * In the case of read-only registers, the value (0xff) is * never written. R/W functionality is controlled by the * writable bit in the register struct definition. */ static const struct i2c_reg_value tvp7002_init_default[] = …; /* Register parameters for 480P */ static const struct i2c_reg_value tvp7002_parms_480P[] = …; /* Register parameters for 576P */ static const struct i2c_reg_value tvp7002_parms_576P[] = …; /* Register parameters for 1080I60 */ static const struct i2c_reg_value tvp7002_parms_1080I60[] = …; /* Register parameters for 1080P60 */ static const struct i2c_reg_value tvp7002_parms_1080P60[] = …; /* Register parameters for 1080I50 */ static const struct i2c_reg_value tvp7002_parms_1080I50[] = …; /* Register parameters for 720P60 */ static const struct i2c_reg_value tvp7002_parms_720P60[] = …; /* Register parameters for 720P50 */ static const struct i2c_reg_value tvp7002_parms_720P50[] = …; /* Timings definition for handling device operation */ struct tvp7002_timings_definition { … }; /* Struct list for digital video timings */ static const struct tvp7002_timings_definition tvp7002_timings[] = …; #define NUM_TIMINGS … /* Device definition */ struct tvp7002 { … }; /* * to_tvp7002 - Obtain device handler TVP7002 * @sd: ptr to v4l2_subdev struct * * Returns device handler tvp7002. */ static inline struct tvp7002 *to_tvp7002(struct v4l2_subdev *sd) { … } static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) { … } /* * tvp7002_read - Read a value from a register in an TVP7002 * @sd: ptr to v4l2_subdev struct * @addr: TVP7002 register address * @dst: pointer to 8-bit destination * * Returns value read if successful, or non-zero (-1) otherwise. */ static int tvp7002_read(struct v4l2_subdev *sd, u8 addr, u8 *dst) { … } /* * tvp7002_read_err() - Read a register value with error code * @sd: pointer to standard V4L2 sub-device structure * @reg: destination register * @val: value to be read * @err: pointer to error value * * Read a value in a register and save error value in pointer. * Also update the register table if successful */ static inline void tvp7002_read_err(struct v4l2_subdev *sd, u8 reg, u8 *dst, int *err) { … } /* * tvp7002_write() - Write a value to a register in TVP7002 * @sd: ptr to v4l2_subdev struct * @addr: TVP7002 register address * @value: value to be written to the register * * Write a value to a register in an TVP7002 decoder device. * Returns zero if successful, or non-zero otherwise. */ static int tvp7002_write(struct v4l2_subdev *sd, u8 addr, u8 value) { … } /* * tvp7002_write_err() - Write a register value with error code * @sd: pointer to standard V4L2 sub-device structure * @reg: destination register * @val: value to be written * @err: pointer to error value * * Write a value in a register and save error value in pointer. * Also update the register table if successful */ static inline void tvp7002_write_err(struct v4l2_subdev *sd, u8 reg, u8 val, int *err) { … } /* * tvp7002_write_inittab() - Write initialization values * @sd: ptr to v4l2_subdev struct * @regs: ptr to i2c_reg_value struct * * Write initialization values. * Returns zero or -EINVAL if read operation fails. */ static int tvp7002_write_inittab(struct v4l2_subdev *sd, const struct i2c_reg_value *regs) { … } static int tvp7002_s_dv_timings(struct v4l2_subdev *sd, unsigned int pad, struct v4l2_dv_timings *dv_timings) { … } static int tvp7002_g_dv_timings(struct v4l2_subdev *sd, unsigned int pad, struct v4l2_dv_timings *dv_timings) { … } /* * tvp7002_s_ctrl() - Set a control * @ctrl: ptr to v4l2_ctrl struct * * Set a control in TVP7002 decoder device. * Returns zero when successful or -EINVAL if register access fails. */ static int tvp7002_s_ctrl(struct v4l2_ctrl *ctrl) { … } /* * tvp7002_query_dv() - query DV timings * @sd: pointer to standard V4L2 sub-device structure * @index: index into the tvp7002_timings array * * Returns the current DV timings detected by TVP7002. If no active input is * detected, returns -EINVAL */ static int tvp7002_query_dv(struct v4l2_subdev *sd, int *index) { … } static int tvp7002_query_dv_timings(struct v4l2_subdev *sd, unsigned int pad, struct v4l2_dv_timings *timings) { … } #ifdef CONFIG_VIDEO_ADV_DEBUG /* * tvp7002_g_register() - Get the value of a register * @sd: ptr to v4l2_subdev struct * @reg: ptr to v4l2_dbg_register struct * * Get the value of a TVP7002 decoder device register. * Returns zero when successful, -EINVAL if register read fails or * access to I2C client fails. */ static int tvp7002_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { … } /* * tvp7002_s_register() - set a control * @sd: ptr to v4l2_subdev struct * @reg: ptr to v4l2_dbg_register struct * * Get the value of a TVP7002 decoder device register. * Returns zero when successful, -EINVAL if register read fails. */ static int tvp7002_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { … } #endif /* * tvp7002_s_stream() - V4L2 decoder i/f handler for s_stream * @sd: pointer to standard V4L2 sub-device structure * @enable: streaming enable or disable * * Sets streaming to enable or disable, if possible. */ static int tvp7002_s_stream(struct v4l2_subdev *sd, int enable) { … } /* * tvp7002_log_status() - Print information about register settings * @sd: ptr to v4l2_subdev struct * * Log register values of a TVP7002 decoder device. * Returns zero or -EINVAL if read operation fails. */ static int tvp7002_log_status(struct v4l2_subdev *sd) { … } static int tvp7002_enum_dv_timings(struct v4l2_subdev *sd, struct v4l2_enum_dv_timings *timings) { … } static const struct v4l2_ctrl_ops tvp7002_ctrl_ops = …; /* * tvp7002_enum_mbus_code() - Enum supported digital video format on pad * @sd: pointer to standard V4L2 sub-device structure * @sd_state: V4L2 subdev state * @code: pointer to subdev enum mbus code struct * * Enumerate supported digital video formats for pad. */ static int tvp7002_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_mbus_code_enum *code) { … } /* * tvp7002_get_pad_format() - get video format on pad * @sd: pointer to standard V4L2 sub-device structure * @sd_state: V4L2 subdev state * @fmt: pointer to subdev format struct * * get video format for pad. */ static int tvp7002_get_pad_format(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *fmt) { … } /* * tvp7002_set_pad_format() - set video format on pad * @sd: pointer to standard V4L2 sub-device structure * @sd_state: V4L2 subdev state * @fmt: pointer to subdev format struct * * set video format for pad. */ static int tvp7002_set_pad_format(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *fmt) { … } /* V4L2 core operation handlers */ static const struct v4l2_subdev_core_ops tvp7002_core_ops = …; /* Specific video subsystem operation handlers */ static const struct v4l2_subdev_video_ops tvp7002_video_ops = …; /* media pad related operation handlers */ static const struct v4l2_subdev_pad_ops tvp7002_pad_ops = …; /* V4L2 top level operation handlers */ static const struct v4l2_subdev_ops tvp7002_ops = …; static struct tvp7002_config * tvp7002_get_pdata(struct i2c_client *client) { … } /* * tvp7002_probe - Probe a TVP7002 device * @c: ptr to i2c_client struct * @id: ptr to i2c_device_id struct * * Initialize the TVP7002 device * Returns zero when successful, -EINVAL if register read fails or * -EIO if i2c access is not available. */ static int tvp7002_probe(struct i2c_client *c) { … } /* * tvp7002_remove - Remove TVP7002 device support * @c: ptr to i2c_client struct * * Reset the TVP7002 device * Returns zero. */ static void tvp7002_remove(struct i2c_client *c) { … } /* I2C Device ID table */ static const struct i2c_device_id tvp7002_id[] = …; MODULE_DEVICE_TABLE(i2c, tvp7002_id); #if IS_ENABLED(CONFIG_OF) static const struct of_device_id tvp7002_of_match[] = …; MODULE_DEVICE_TABLE(of, tvp7002_of_match); #endif /* I2C driver data */ static struct i2c_driver tvp7002_driver = …; module_i2c_driver(…) …;