// SPDX-License-Identifier: GPL-2.0-only /* * drivers/media/i2c/tvp514x.c * * TI TVP5146/47 decoder driver * * Copyright (C) 2008 Texas Instruments Inc * Author: Vaibhav Hiremath <[email protected]> * * Contributors: * Sivaraj R <[email protected]> * Brijesh R Jadav <[email protected]> * Hardik Shah <[email protected]> * Manjunath Hadli <[email protected]> * Karicheri Muralidharan <[email protected]> * Prabhakar Lad <[email protected]> */ #include <linux/delay.h> #include <linux/i2c.h> #include <linux/mod_devicetable.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_graph.h> #include <linux/slab.h> #include <linux/v4l2-mediabus.h> #include <linux/videodev2.h> #include <media/i2c/tvp514x.h> #include <media/media-entity.h> #include <media/v4l2-async.h> #include <media/v4l2-common.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-fwnode.h> #include <media/v4l2-mediabus.h> #include "tvp514x_regs.h" /* Private macros for TVP */ #define I2C_RETRY_COUNT … #define LOCK_RETRY_COUNT … #define LOCK_RETRY_DELAY … /* Debug functions */ static bool debug; module_param(debug, bool, 0644); MODULE_PARM_DESC(…) …; MODULE_AUTHOR(…) …; MODULE_DESCRIPTION(…) …; MODULE_LICENSE(…) …; /* enum tvp514x_std - enum for supported standards */ enum tvp514x_std { … }; /** * struct tvp514x_std_info - Structure to store standard information * @width: Line width in pixels * @height:Number of active lines * @video_std: Value to write in REG_VIDEO_STD register * @standard: v4l2 standard structure information */ struct tvp514x_std_info { … }; static struct tvp514x_reg tvp514x_reg_list_default[0x40]; static int tvp514x_s_stream(struct v4l2_subdev *sd, int enable); /** * struct tvp514x_decoder - TVP5146/47 decoder object * @sd: Subdevice Slave handle * @hdl: embedded &struct v4l2_ctrl_handler * @tvp514x_regs: copy of hw's regs with preset values. * @pdata: Board specific * @ver: Chip version * @streaming: TVP5146/47 decoder streaming - enabled or disabled. * @pix: Current pixel format * @num_fmts: Number of formats * @fmt_list: Format list * @current_std: Current standard * @num_stds: Number of standards * @std_list: Standards list * @input: Input routing at chip level * @output: Output routing at chip level * @pad: subdev media pad associated with the decoder * @format: media bus frame format * @int_seq: driver's register init sequence */ struct tvp514x_decoder { … }; /* TVP514x default register values */ static struct tvp514x_reg tvp514x_reg_list_default[] = …; /* * List of image formats supported by TVP5146/47 decoder * Currently we are using 8 bit mode only, but can be * extended to 10/20 bit mode. */ static const struct v4l2_fmtdesc tvp514x_fmt_list[] = …; /* * Supported standards - * * Currently supports two standards only, need to add support for rest of the * modes, like SECAM, etc... */ static const struct tvp514x_std_info tvp514x_std_list[] = …; static inline struct tvp514x_decoder *to_decoder(struct v4l2_subdev *sd) { … } static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) { … } /** * tvp514x_read_reg() - Read a value from a register in an TVP5146/47. * @sd: ptr to v4l2_subdev struct * @reg: TVP5146/47 register address * * Returns value read if successful, or non-zero (-1) otherwise. */ static int tvp514x_read_reg(struct v4l2_subdev *sd, u8 reg) { … } /** * dump_reg() - dump the register content of TVP5146/47. * @sd: ptr to v4l2_subdev struct * @reg: TVP5146/47 register address */ static void dump_reg(struct v4l2_subdev *sd, u8 reg) { … } /** * tvp514x_write_reg() - Write a value to a register in TVP5146/47 * @sd: ptr to v4l2_subdev struct * @reg: TVP5146/47 register address * @val: value to be written to the register * * Write a value to a register in an TVP5146/47 decoder device. * Returns zero if successful, or non-zero otherwise. */ static int tvp514x_write_reg(struct v4l2_subdev *sd, u8 reg, u8 val) { … } /** * tvp514x_write_regs() : Initializes a list of TVP5146/47 registers * @sd: ptr to v4l2_subdev struct * @reglist: list of TVP5146/47 registers and values * * Initializes a list of TVP5146/47 registers:- * if token is TOK_TERM, then entire write operation terminates * if token is TOK_DELAY, then a delay of 'val' msec is introduced * if token is TOK_SKIP, then the register write is skipped * if token is TOK_WRITE, then the register write is performed * Returns zero if successful, or non-zero otherwise. */ static int tvp514x_write_regs(struct v4l2_subdev *sd, const struct tvp514x_reg reglist[]) { … } /** * tvp514x_query_current_std() : Query the current standard detected by TVP5146/47 * @sd: ptr to v4l2_subdev struct * * Returns the current standard detected by TVP5146/47, STD_INVALID if there is no * standard detected. */ static enum tvp514x_std tvp514x_query_current_std(struct v4l2_subdev *sd) { … } /* TVP5146/47 register dump function */ static void tvp514x_reg_dump(struct v4l2_subdev *sd) { … } /** * tvp514x_configure() - Configure the TVP5146/47 registers * @sd: ptr to v4l2_subdev struct * @decoder: ptr to tvp514x_decoder structure * * Returns zero if successful, or non-zero otherwise. */ static int tvp514x_configure(struct v4l2_subdev *sd, struct tvp514x_decoder *decoder) { … } /** * tvp514x_detect() - Detect if an tvp514x is present, and if so which revision. * @sd: pointer to standard V4L2 sub-device structure * @decoder: pointer to tvp514x_decoder structure * * A device is considered to be detected if the chip ID (LSB and MSB) * registers match the expected values. * Any value of the rom version register is accepted. * Returns ENODEV error number if no device is detected, or zero * if a device is detected. */ static int tvp514x_detect(struct v4l2_subdev *sd, struct tvp514x_decoder *decoder) { … } /** * tvp514x_querystd() - V4L2 decoder interface handler for querystd * @sd: pointer to standard V4L2 sub-device structure * @std_id: standard V4L2 std_id ioctl enum * * Returns the current standard detected by TVP5146/47. If no active input is * detected then *std_id is set to 0 and the function returns 0. */ static int tvp514x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id) { … } /** * tvp514x_s_std() - V4L2 decoder interface handler for s_std * @sd: pointer to standard V4L2 sub-device structure * @std_id: standard V4L2 v4l2_std_id ioctl enum * * If std_id is supported, sets the requested standard. Otherwise, returns * -EINVAL */ static int tvp514x_s_std(struct v4l2_subdev *sd, v4l2_std_id std_id) { … } /** * tvp514x_s_routing() - V4L2 decoder interface handler for s_routing * @sd: pointer to standard V4L2 sub-device structure * @input: input selector for routing the signal * @output: output selector for routing the signal * @config: config value. Not used * * If index is valid, selects the requested input. Otherwise, returns -EINVAL if * the input is not supported or there is no active signal present in the * selected input. */ static int tvp514x_s_routing(struct v4l2_subdev *sd, u32 input, u32 output, u32 config) { … } /** * tvp514x_s_ctrl() - V4L2 decoder interface handler for s_ctrl * @ctrl: pointer to v4l2_ctrl structure * * If the requested control is supported, sets the control's current * value in HW. Otherwise, returns -EINVAL if the control is not supported. */ static int tvp514x_s_ctrl(struct v4l2_ctrl *ctrl) { … } static int tvp514x_get_frame_interval(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_frame_interval *ival) { … } static int tvp514x_set_frame_interval(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_frame_interval *ival) { … } /** * tvp514x_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 tvp514x_s_stream(struct v4l2_subdev *sd, int enable) { … } static const struct v4l2_ctrl_ops tvp514x_ctrl_ops = …; /** * tvp514x_enum_mbus_code() - V4L2 decoder interface handler for enum_mbus_code * @sd: pointer to standard V4L2 sub-device structure * @sd_state: subdev state * @code: pointer to v4l2_subdev_mbus_code_enum structure * * Enumertaes mbus codes supported */ static int tvp514x_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_mbus_code_enum *code) { … } /** * tvp514x_get_pad_format() - V4L2 decoder interface handler for get pad format * @sd: pointer to standard V4L2 sub-device structure * @sd_state: subdev state * @format: pointer to v4l2_subdev_format structure * * Retrieves pad format which is active or tried based on requirement */ static int tvp514x_get_pad_format(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *format) { … } /** * tvp514x_set_pad_format() - V4L2 decoder interface handler for set pad format * @sd: pointer to standard V4L2 sub-device structure * @sd_state: subdev state * @fmt: pointer to v4l2_subdev_format structure * * Set pad format for the output pad */ static int tvp514x_set_pad_format(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *fmt) { … } static const struct v4l2_subdev_video_ops tvp514x_video_ops = …; static const struct v4l2_subdev_pad_ops tvp514x_pad_ops = …; static const struct v4l2_subdev_ops tvp514x_ops = …; static const struct tvp514x_decoder tvp514x_dev = …; static struct tvp514x_platform_data * tvp514x_get_pdata(struct i2c_client *client) { … } /** * tvp514x_probe() - decoder driver i2c probe handler * @client: i2c driver client device structure * * Register decoder as an i2c client device and V4L2 * device. */ static int tvp514x_probe(struct i2c_client *client) { … } /** * tvp514x_remove() - decoder driver i2c remove handler * @client: i2c driver client device structure * * Unregister decoder as an i2c client device and V4L2 * device. Complement of tvp514x_probe(). */ static void tvp514x_remove(struct i2c_client *client) { … } /* TVP5146 Init/Power on Sequence */ static const struct tvp514x_reg tvp5146_init_reg_seq[] = …; /* TVP5147 Init/Power on Sequence */ static const struct tvp514x_reg tvp5147_init_reg_seq[] = …; /* TVP5146M2/TVP5147M1 Init/Power on Sequence */ static const struct tvp514x_reg tvp514xm_init_reg_seq[] = …; /* * I2C Device Table - * * name - Name of the actual device/chip. * driver_data - Driver data */ static const struct i2c_device_id tvp514x_id[] = …; MODULE_DEVICE_TABLE(i2c, tvp514x_id); static const struct of_device_id tvp514x_of_match[] = …; MODULE_DEVICE_TABLE(of, tvp514x_of_match); static struct i2c_driver tvp514x_driver = …; module_i2c_driver(…) …;