linux/drivers/media/i2c/adv7604.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * adv7604 - Analog Devices ADV7604 video decoder driver
 *
 * Copyright 2012 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
 *
 */

/*
 * References (c = chapter, p = page):
 * REF_01 - Analog devices, ADV7604, Register Settings Recommendations,
 *		Revision 2.5, June 2010
 * REF_02 - Analog devices, Register map documentation, Documentation of
 *		the register maps, Software manual, Rev. F, June 2010
 * REF_03 - Analog devices, ADV7604, Hardware Manual, Rev. F, August 2010
 */

#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/hdmi.h>
#include <linux/i2c.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_graph.h>
#include <linux/slab.h>
#include <linux/v4l2-dv-timings.h>
#include <linux/videodev2.h>
#include <linux/workqueue.h>
#include <linux/regmap.h>
#include <linux/interrupt.h>

#include <media/i2c/adv7604.h>
#include <media/cec.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-event.h>
#include <media/v4l2-dv-timings.h>
#include <media/v4l2-fwnode.h>

static int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC();

MODULE_DESCRIPTION();
MODULE_AUTHOR();
MODULE_AUTHOR();
MODULE_LICENSE();

/* ADV7604 system clock frequency */
#define ADV76XX_FSC

#define ADV76XX_RGB_OUT

#define ADV76XX_OP_FORMAT_SEL_8BIT
#define ADV7604_OP_FORMAT_SEL_10BIT
#define ADV76XX_OP_FORMAT_SEL_12BIT

#define ADV76XX_OP_MODE_SEL_SDR_422
#define ADV7604_OP_MODE_SEL_DDR_422
#define ADV76XX_OP_MODE_SEL_SDR_444
#define ADV7604_OP_MODE_SEL_DDR_444
#define ADV76XX_OP_MODE_SEL_SDR_422_2X
#define ADV7604_OP_MODE_SEL_ADI_CM

#define ADV76XX_OP_CH_SEL_GBR
#define ADV76XX_OP_CH_SEL_GRB
#define ADV76XX_OP_CH_SEL_BGR
#define ADV76XX_OP_CH_SEL_RGB
#define ADV76XX_OP_CH_SEL_BRG
#define ADV76XX_OP_CH_SEL_RBG

#define ADV76XX_OP_SWAP_CB_CR

#define ADV76XX_MAX_ADDRS

#define ADV76XX_MAX_EDID_BLOCKS

enum adv76xx_type {};

struct adv76xx_reg_seq {};

struct adv76xx_format_info {};

struct adv76xx_cfg_read_infoframe {};

struct adv76xx_chip_info {};

/*
 **********************************************************************
 *
 *  Arrays with configuration parameters for the ADV7604
 *
 **********************************************************************
 */

struct adv76xx_state {};

static bool adv76xx_has_afe(struct adv76xx_state *state)
{}

/* Unsupported timings. This device cannot support 720p30. */
static const struct v4l2_dv_timings adv76xx_timings_exceptions[] =;

static bool adv76xx_check_dv_timings(const struct v4l2_dv_timings *t, void *hdl)
{}

struct adv76xx_video_standards {};

/* sorted by number of lines */
static const struct adv76xx_video_standards adv7604_prim_mode_comp[] =;

/* sorted by number of lines */
static const struct adv76xx_video_standards adv7604_prim_mode_gr[] =;

/* sorted by number of lines */
static const struct adv76xx_video_standards adv76xx_prim_mode_hdmi_comp[] =;

/* sorted by number of lines */
static const struct adv76xx_video_standards adv76xx_prim_mode_hdmi_gr[] =;

static const struct v4l2_event adv76xx_ev_fmt =;

/* ----------------------------------------------------------------------- */

static inline struct adv76xx_state *to_state(struct v4l2_subdev *sd)
{}

static inline unsigned htotal(const struct v4l2_bt_timings *t)
{}

static inline unsigned vtotal(const struct v4l2_bt_timings *t)
{}

/* ----------------------------------------------------------------------- */

static int adv76xx_read_check(struct adv76xx_state *state,
			     int client_page, u8 reg)
{}

/* adv76xx_write_block(): Write raw data with a maximum of I2C_SMBUS_BLOCK_MAX
 * size to one or more registers.
 *
 * A value of zero will be returned on success, a negative errno will
 * be returned in error cases.
 */
static int adv76xx_write_block(struct adv76xx_state *state, int client_page,
			      unsigned int init_reg, const void *val,
			      size_t val_len)
{}

/* ----------------------------------------------------------------------- */

static inline int io_read(struct v4l2_subdev *sd, u8 reg)
{}

static inline int io_write(struct v4l2_subdev *sd, u8 reg, u8 val)
{}

static inline int io_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask,
				   u8 val)
{}

static inline int __always_unused avlink_read(struct v4l2_subdev *sd, u8 reg)
{}

static inline int __always_unused avlink_write(struct v4l2_subdev *sd, u8 reg, u8 val)
{}

static inline int cec_read(struct v4l2_subdev *sd, u8 reg)
{}

static inline int cec_write(struct v4l2_subdev *sd, u8 reg, u8 val)
{}

static inline int cec_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask,
				   u8 val)
{}

static inline int infoframe_read(struct v4l2_subdev *sd, u8 reg)
{}

static inline int __always_unused infoframe_write(struct v4l2_subdev *sd, u8 reg, u8 val)
{}

static inline int __always_unused afe_read(struct v4l2_subdev *sd, u8 reg)
{}

static inline int afe_write(struct v4l2_subdev *sd, u8 reg, u8 val)
{}

static inline int rep_read(struct v4l2_subdev *sd, u8 reg)
{}

static inline int rep_write(struct v4l2_subdev *sd, u8 reg, u8 val)
{}

static inline int rep_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
{}

static inline int __always_unused edid_read(struct v4l2_subdev *sd, u8 reg)
{}

static inline int __always_unused edid_write(struct v4l2_subdev *sd, u8 reg, u8 val)
{}

static inline int edid_write_block(struct v4l2_subdev *sd,
					unsigned int total_len, const u8 *val)
{}

static void adv76xx_set_hpd(struct adv76xx_state *state, unsigned int hpd)
{}

static void adv76xx_delayed_work_enable_hotplug(struct work_struct *work)
{}

static inline int hdmi_read(struct v4l2_subdev *sd, u8 reg)
{}

static u16 hdmi_read16(struct v4l2_subdev *sd, u8 reg, u16 mask)
{}

static inline int hdmi_write(struct v4l2_subdev *sd, u8 reg, u8 val)
{}

static inline int hdmi_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
{}

static inline int __always_unused test_write(struct v4l2_subdev *sd, u8 reg, u8 val)
{}

static inline int cp_read(struct v4l2_subdev *sd, u8 reg)
{}

static u16 cp_read16(struct v4l2_subdev *sd, u8 reg, u16 mask)
{}

static inline int cp_write(struct v4l2_subdev *sd, u8 reg, u8 val)
{}

static inline int cp_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
{}

static inline int __always_unused vdp_read(struct v4l2_subdev *sd, u8 reg)
{}

static inline int __always_unused vdp_write(struct v4l2_subdev *sd, u8 reg, u8 val)
{}

#define ADV76XX_REG(page, offset)
#define ADV76XX_REG_SEQ_TERM

#ifdef CONFIG_VIDEO_ADV_DEBUG
static int adv76xx_read_reg(struct v4l2_subdev *sd, unsigned int reg)
{}
#endif

static int adv76xx_write_reg(struct v4l2_subdev *sd, unsigned int reg, u8 val)
{}

static void adv76xx_write_reg_seq(struct v4l2_subdev *sd,
				  const struct adv76xx_reg_seq *reg_seq)
{}

/* -----------------------------------------------------------------------------
 * Format helpers
 */

static const struct adv76xx_format_info adv7604_formats[] =;

static const struct adv76xx_format_info adv7611_formats[] =;

static const struct adv76xx_format_info adv7612_formats[] =;

static const struct adv76xx_format_info *
adv76xx_format_info(struct adv76xx_state *state, u32 code)
{}

/* ----------------------------------------------------------------------- */

static inline bool is_analog_input(struct v4l2_subdev *sd)
{}

static inline bool is_digital_input(struct v4l2_subdev *sd)
{}

static const struct v4l2_dv_timings_cap adv7604_timings_cap_analog =;

static const struct v4l2_dv_timings_cap adv76xx_timings_cap_digital =;

/*
 * Return the DV timings capabilities for the requested sink pad. As a special
 * case, pad value -1 returns the capabilities for the currently selected input.
 */
static const struct v4l2_dv_timings_cap *
adv76xx_get_dv_timings_cap(struct v4l2_subdev *sd, int pad)
{}


/* ----------------------------------------------------------------------- */

#ifdef CONFIG_VIDEO_ADV_DEBUG
static void adv76xx_inv_register(struct v4l2_subdev *sd)
{}

static int adv76xx_g_register(struct v4l2_subdev *sd,
					struct v4l2_dbg_register *reg)
{}

static int adv76xx_s_register(struct v4l2_subdev *sd,
					const struct v4l2_dbg_register *reg)
{}
#endif

static unsigned int adv7604_read_cable_det(struct v4l2_subdev *sd)
{}

static unsigned int adv7611_read_cable_det(struct v4l2_subdev *sd)
{}

static unsigned int adv7612_read_cable_det(struct v4l2_subdev *sd)
{}

static int adv76xx_s_detect_tx_5v_ctrl(struct v4l2_subdev *sd)
{}

static int find_and_set_predefined_video_timings(struct v4l2_subdev *sd,
		u8 prim_mode,
		const struct adv76xx_video_standards *predef_vid_timings,
		const struct v4l2_dv_timings *timings)
{}

static int configure_predefined_video_timings(struct v4l2_subdev *sd,
		struct v4l2_dv_timings *timings)
{}

static void configure_custom_video_timings(struct v4l2_subdev *sd,
		const struct v4l2_bt_timings *bt)
{}

static void adv76xx_set_offset(struct v4l2_subdev *sd, bool auto_offset, u16 offset_a, u16 offset_b, u16 offset_c)
{}

static void adv76xx_set_gain(struct v4l2_subdev *sd, bool auto_gain, u16 gain_a, u16 gain_b, u16 gain_c)
{}

static void set_rgb_quantization_range(struct v4l2_subdev *sd)
{}

static int adv76xx_s_ctrl(struct v4l2_ctrl *ctrl)
{}

static int adv76xx_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
{}

/* ----------------------------------------------------------------------- */

static inline bool no_power(struct v4l2_subdev *sd)
{}

static inline bool no_signal_tmds(struct v4l2_subdev *sd)
{}

static inline bool no_lock_tmds(struct v4l2_subdev *sd)
{}

static inline bool is_hdmi(struct v4l2_subdev *sd)
{}

static inline bool no_lock_sspd(struct v4l2_subdev *sd)
{}

static inline bool no_lock_stdi(struct v4l2_subdev *sd)
{}

static inline bool no_signal(struct v4l2_subdev *sd)
{}

static inline bool no_lock_cp(struct v4l2_subdev *sd)
{}

static inline bool in_free_run(struct v4l2_subdev *sd)
{}

static int adv76xx_g_input_status(struct v4l2_subdev *sd, u32 *status)
{}

/* ----------------------------------------------------------------------- */

struct stdi_readback {};

static int stdi2dv_timings(struct v4l2_subdev *sd,
		struct stdi_readback *stdi,
		struct v4l2_dv_timings *timings)
{}


static int read_stdi(struct v4l2_subdev *sd, struct stdi_readback *stdi)
{}

static int adv76xx_enum_dv_timings(struct v4l2_subdev *sd,
			struct v4l2_enum_dv_timings *timings)
{}

static int adv76xx_dv_timings_cap(struct v4l2_subdev *sd,
			struct v4l2_dv_timings_cap *cap)
{}

/* Fill the optional fields .standards and .flags in struct v4l2_dv_timings
   if the format is listed in adv76xx_timings[] */
static void adv76xx_fill_optional_dv_timings_fields(struct v4l2_subdev *sd,
		struct v4l2_dv_timings *timings)
{}

static unsigned int adv7604_read_hdmi_pixelclock(struct v4l2_subdev *sd)
{}

static unsigned int adv7611_read_hdmi_pixelclock(struct v4l2_subdev *sd)
{}

static unsigned int adv76xx_read_hdmi_pixelclock(struct v4l2_subdev *sd)
{}

static int adv76xx_query_dv_timings(struct v4l2_subdev *sd, unsigned int pad,
				    struct v4l2_dv_timings *timings)
{}

static int adv76xx_s_dv_timings(struct v4l2_subdev *sd, unsigned int pad,
				struct v4l2_dv_timings *timings)
{}

static int adv76xx_g_dv_timings(struct v4l2_subdev *sd, unsigned int pad,
				struct v4l2_dv_timings *timings)
{}

static void adv7604_set_termination(struct v4l2_subdev *sd, bool enable)
{}

static void adv7611_set_termination(struct v4l2_subdev *sd, bool enable)
{}

static void enable_input(struct v4l2_subdev *sd)
{}

static void disable_input(struct v4l2_subdev *sd)
{}

static void select_input(struct v4l2_subdev *sd)
{}

static int adv76xx_s_routing(struct v4l2_subdev *sd,
		u32 input, u32 output, u32 config)
{}

static int adv76xx_enum_mbus_code(struct v4l2_subdev *sd,
				  struct v4l2_subdev_state *sd_state,
				  struct v4l2_subdev_mbus_code_enum *code)
{}

static void adv76xx_fill_format(struct adv76xx_state *state,
				struct v4l2_mbus_framefmt *format)
{}

/*
 * Compute the op_ch_sel value required to obtain on the bus the component order
 * corresponding to the selected format taking into account bus reordering
 * applied by the board at the output of the device.
 *
 * The following table gives the op_ch_value from the format component order
 * (expressed as op_ch_sel value in column) and the bus reordering (expressed as
 * adv76xx_bus_order value in row).
 *
 *           |	GBR(0)	GRB(1)	BGR(2)	RGB(3)	BRG(4)	RBG(5)
 * ----------+-------------------------------------------------
 * RGB (NOP) |	GBR	GRB	BGR	RGB	BRG	RBG
 * GRB (1-2) |	BGR	RGB	GBR	GRB	RBG	BRG
 * RBG (2-3) |	GRB	GBR	BRG	RBG	BGR	RGB
 * BGR (1-3) |	RBG	BRG	RGB	BGR	GRB	GBR
 * BRG (ROR) |	BRG	RBG	GRB	GBR	RGB	BGR
 * GBR (ROL) |	RGB	BGR	RBG	BRG	GBR	GRB
 */
static unsigned int adv76xx_op_ch_sel(struct adv76xx_state *state)
{}

static void adv76xx_setup_format(struct adv76xx_state *state)
{}

static int adv76xx_get_format(struct v4l2_subdev *sd,
			      struct v4l2_subdev_state *sd_state,
			      struct v4l2_subdev_format *format)
{}

static int adv76xx_get_selection(struct v4l2_subdev *sd,
				 struct v4l2_subdev_state *sd_state,
				 struct v4l2_subdev_selection *sel)
{}

static int adv76xx_set_format(struct v4l2_subdev *sd,
			      struct v4l2_subdev_state *sd_state,
			      struct v4l2_subdev_format *format)
{}

#if IS_ENABLED(CONFIG_VIDEO_ADV7604_CEC)
static void adv76xx_cec_tx_raw_status(struct v4l2_subdev *sd, u8 tx_raw_status)
{}

static void adv76xx_cec_isr(struct v4l2_subdev *sd, bool *handled)
{}

static int adv76xx_cec_adap_enable(struct cec_adapter *adap, bool enable)
{}

static int adv76xx_cec_adap_log_addr(struct cec_adapter *adap, u8 addr)
{}

static int adv76xx_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
				     u32 signal_free_time, struct cec_msg *msg)
{}

static const struct cec_adap_ops adv76xx_cec_adap_ops =;
#endif

static int adv76xx_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
{}

static irqreturn_t adv76xx_irq_handler(int irq, void *dev_id)
{}

static int adv76xx_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
{}

static int adv76xx_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
{}

/*********** avi info frame CEA-861-E **************/

static const struct adv76xx_cfg_read_infoframe adv76xx_cri[] =;

static int adv76xx_read_infoframe(struct v4l2_subdev *sd, int index,
				  union hdmi_infoframe *frame)
{}

static void adv76xx_log_infoframes(struct v4l2_subdev *sd)
{}

static int adv76xx_log_status(struct v4l2_subdev *sd)
{}

static int adv76xx_subscribe_event(struct v4l2_subdev *sd,
				   struct v4l2_fh *fh,
				   struct v4l2_event_subscription *sub)
{}

static int adv76xx_registered(struct v4l2_subdev *sd)
{}

static void adv76xx_unregistered(struct v4l2_subdev *sd)
{}

/* ----------------------------------------------------------------------- */

static const struct v4l2_ctrl_ops adv76xx_ctrl_ops =;

static const struct v4l2_subdev_core_ops adv76xx_core_ops =;

static const struct v4l2_subdev_video_ops adv76xx_video_ops =;

static const struct v4l2_subdev_pad_ops adv76xx_pad_ops =;

static const struct v4l2_subdev_ops adv76xx_ops =;

static const struct v4l2_subdev_internal_ops adv76xx_int_ops =;

/* -------------------------- custom ctrls ---------------------------------- */

static const struct v4l2_ctrl_config adv7604_ctrl_analog_sampling_phase =;

static const struct v4l2_ctrl_config adv76xx_ctrl_free_run_color_manual =;

static const struct v4l2_ctrl_config adv76xx_ctrl_free_run_color =;

/* ----------------------------------------------------------------------- */

struct adv76xx_register_map {};

static const struct adv76xx_register_map adv76xx_default_addresses[] =;

static int adv76xx_core_init(struct v4l2_subdev *sd)
{}

static void adv7604_setup_irqs(struct v4l2_subdev *sd)
{}

static void adv7611_setup_irqs(struct v4l2_subdev *sd)
{}

static void adv7612_setup_irqs(struct v4l2_subdev *sd)
{}

static void adv76xx_unregister_clients(struct adv76xx_state *state)
{}

static struct i2c_client *adv76xx_dummy_client(struct v4l2_subdev *sd,
					       unsigned int page)
{}

static const struct adv76xx_reg_seq adv7604_recommended_settings_afe[] =;

static const struct adv76xx_reg_seq adv7604_recommended_settings_hdmi[] =;

static const struct adv76xx_reg_seq adv7611_recommended_settings_hdmi[] =;

static const struct adv76xx_reg_seq adv7612_recommended_settings_hdmi[] =;

static const struct adv76xx_chip_info adv76xx_chip_info[] =;

static const struct i2c_device_id adv76xx_i2c_id[] =;
MODULE_DEVICE_TABLE(i2c, adv76xx_i2c_id);

static const struct of_device_id adv76xx_of_id[] __maybe_unused =;
MODULE_DEVICE_TABLE(of, adv76xx_of_id);

static int adv76xx_parse_dt(struct adv76xx_state *state)
{}

static const struct regmap_config adv76xx_regmap_cnf[] =;

static int configure_regmap(struct adv76xx_state *state, int region)
{}

static int configure_regmaps(struct adv76xx_state *state)
{}

static void adv76xx_reset(struct adv76xx_state *state)
{}

static int adv76xx_probe(struct i2c_client *client)
{}

/* ----------------------------------------------------------------------- */

static void adv76xx_remove(struct i2c_client *client)
{}

/* ----------------------------------------------------------------------- */

static struct i2c_driver adv76xx_driver =;

module_i2c_driver();