#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(…) …;
#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 { … };
struct adv76xx_state { … };
static bool adv76xx_has_afe(struct adv76xx_state *state)
{ … }
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 { … };
static const struct adv76xx_video_standards adv7604_prim_mode_comp[] = …;
static const struct adv76xx_video_standards adv7604_prim_mode_gr[] = …;
static const struct adv76xx_video_standards adv76xx_prim_mode_hdmi_comp[] = …;
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)
{ … }
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)
{ … }
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 = …;
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)
{ … }
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)
{ … }
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)
{ … }
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 = …;
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(…) …;