^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * adv7604 - Analog Devices ADV7604 video decoder driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright 2012 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * References (c = chapter, p = page):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * REF_01 - Analog devices, ADV7604, Register Settings Recommendations,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Revision 2.5, June 2010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * REF_02 - Analog devices, Register map documentation, Documentation of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * the register maps, Software manual, Rev. F, June 2010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * REF_03 - Analog devices, ADV7604, Hardware Manual, Rev. F, August 2010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/gpio/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/hdmi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/of_graph.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/v4l2-dv-timings.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/videodev2.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/workqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <media/i2c/adv7604.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <media/cec.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <media/v4l2-ctrls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <media/v4l2-device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <media/v4l2-event.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <media/v4l2-dv-timings.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <media/v4l2-fwnode.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static int debug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) module_param(debug, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) MODULE_PARM_DESC(debug, "debug level (0-2)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) MODULE_DESCRIPTION("Analog Devices ADV7604 video decoder driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) MODULE_AUTHOR("Mats Randgaard <mats.randgaard@cisco.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /* ADV7604 system clock frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define ADV76XX_FSC (28636360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define ADV76XX_RGB_OUT (1 << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define ADV76XX_OP_FORMAT_SEL_8BIT (0 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define ADV7604_OP_FORMAT_SEL_10BIT (1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define ADV76XX_OP_FORMAT_SEL_12BIT (2 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define ADV76XX_OP_MODE_SEL_SDR_422 (0 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define ADV7604_OP_MODE_SEL_DDR_422 (1 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define ADV76XX_OP_MODE_SEL_SDR_444 (2 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define ADV7604_OP_MODE_SEL_DDR_444 (3 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define ADV76XX_OP_MODE_SEL_SDR_422_2X (4 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define ADV7604_OP_MODE_SEL_ADI_CM (5 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define ADV76XX_OP_CH_SEL_GBR (0 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define ADV76XX_OP_CH_SEL_GRB (1 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define ADV76XX_OP_CH_SEL_BGR (2 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define ADV76XX_OP_CH_SEL_RGB (3 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define ADV76XX_OP_CH_SEL_BRG (4 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define ADV76XX_OP_CH_SEL_RBG (5 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define ADV76XX_OP_SWAP_CB_CR (1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define ADV76XX_MAX_ADDRS (3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) enum adv76xx_type {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) ADV7604,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) ADV7611,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) ADV7612,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) struct adv76xx_reg_seq {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) unsigned int reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) struct adv76xx_format_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) u32 code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) u8 op_ch_sel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) bool rgb_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) bool swap_cb_cr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) u8 op_format_sel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) struct adv76xx_cfg_read_infoframe {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) const char *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) u8 present_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) u8 head_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) u8 payload_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct adv76xx_chip_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) enum adv76xx_type type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) bool has_afe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) unsigned int max_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) unsigned int num_dv_ports;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) unsigned int edid_enable_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) unsigned int edid_status_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) unsigned int lcf_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) unsigned int cable_det_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) unsigned int tdms_lock_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) unsigned int fmt_change_digital_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) unsigned int cp_csc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) unsigned int cec_irq_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) unsigned int cec_rx_enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) unsigned int cec_rx_enable_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) bool cec_irq_swap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) const struct adv76xx_format_info *formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) unsigned int nformats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) void (*set_termination)(struct v4l2_subdev *sd, bool enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) void (*setup_irqs)(struct v4l2_subdev *sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) unsigned int (*read_hdmi_pixelclock)(struct v4l2_subdev *sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) unsigned int (*read_cable_det)(struct v4l2_subdev *sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) /* 0 = AFE, 1 = HDMI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) const struct adv76xx_reg_seq *recommended_settings[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) unsigned int num_recommended_settings[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) unsigned long page_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) /* Masks for timings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) unsigned int linewidth_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) unsigned int field0_height_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) unsigned int field1_height_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) unsigned int hfrontporch_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) unsigned int hsync_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) unsigned int hbackporch_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) unsigned int field0_vfrontporch_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) unsigned int field1_vfrontporch_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) unsigned int field0_vsync_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) unsigned int field1_vsync_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) unsigned int field0_vbackporch_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) unsigned int field1_vbackporch_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) **********************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * Arrays with configuration parameters for the ADV7604
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) **********************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) struct adv76xx_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) const struct adv76xx_chip_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) struct adv76xx_platform_data pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) struct gpio_desc *hpd_gpio[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) struct gpio_desc *reset_gpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) struct v4l2_subdev sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) struct media_pad pads[ADV76XX_PAD_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) unsigned int source_pad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) struct v4l2_ctrl_handler hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) enum adv76xx_pad selected_input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) struct v4l2_dv_timings timings;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) const struct adv76xx_format_info *format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) u8 edid[256];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) u32 present;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) unsigned blocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) } edid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) u16 spa_port_a[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) struct v4l2_fract aspect_ratio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) u32 rgb_quantization_range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) struct delayed_work delayed_work_enable_hotplug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) bool restart_stdi_once;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) /* CEC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) struct cec_adapter *cec_adap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) u8 cec_addr[ADV76XX_MAX_ADDRS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) u8 cec_valid_addrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) bool cec_enabled_adap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) /* i2c clients */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) struct i2c_client *i2c_clients[ADV76XX_PAGE_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) /* Regmaps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) struct regmap *regmap[ADV76XX_PAGE_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) /* controls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) struct v4l2_ctrl *detect_tx_5v_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) struct v4l2_ctrl *analog_sampling_phase_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) struct v4l2_ctrl *free_run_color_manual_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) struct v4l2_ctrl *free_run_color_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) struct v4l2_ctrl *rgb_quantization_range_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) static bool adv76xx_has_afe(struct adv76xx_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) return state->info->has_afe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) /* Unsupported timings. This device cannot support 720p30. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) static const struct v4l2_dv_timings adv76xx_timings_exceptions[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) V4L2_DV_BT_CEA_1280X720P30,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) static bool adv76xx_check_dv_timings(const struct v4l2_dv_timings *t, void *hdl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) for (i = 0; adv76xx_timings_exceptions[i].bt.width; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (v4l2_match_dv_timings(t, adv76xx_timings_exceptions + i, 0, false))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) struct adv76xx_video_standards {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) struct v4l2_dv_timings timings;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) u8 vid_std;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) u8 v_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) /* sorted by number of lines */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) static const struct adv76xx_video_standards adv7604_prim_mode_comp[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) /* { V4L2_DV_BT_CEA_720X480P59_94, 0x0a, 0x00 }, TODO flickering */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) { V4L2_DV_BT_CEA_720X576P50, 0x0b, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) { V4L2_DV_BT_CEA_1280X720P50, 0x19, 0x01 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) { V4L2_DV_BT_CEA_1280X720P60, 0x19, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) { V4L2_DV_BT_CEA_1920X1080P24, 0x1e, 0x04 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) { V4L2_DV_BT_CEA_1920X1080P25, 0x1e, 0x03 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) { V4L2_DV_BT_CEA_1920X1080P30, 0x1e, 0x02 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) { V4L2_DV_BT_CEA_1920X1080P50, 0x1e, 0x01 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) { V4L2_DV_BT_CEA_1920X1080P60, 0x1e, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) /* TODO add 1920x1080P60_RB (CVT timing) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) /* sorted by number of lines */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) static const struct adv76xx_video_standards adv7604_prim_mode_gr[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) { V4L2_DV_BT_DMT_640X480P60, 0x08, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) { V4L2_DV_BT_DMT_640X480P72, 0x09, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) { V4L2_DV_BT_DMT_640X480P75, 0x0a, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) { V4L2_DV_BT_DMT_640X480P85, 0x0b, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) { V4L2_DV_BT_DMT_800X600P56, 0x00, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) { V4L2_DV_BT_DMT_800X600P60, 0x01, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) { V4L2_DV_BT_DMT_800X600P72, 0x02, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) { V4L2_DV_BT_DMT_800X600P75, 0x03, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) { V4L2_DV_BT_DMT_800X600P85, 0x04, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) { V4L2_DV_BT_DMT_1024X768P60, 0x0c, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) { V4L2_DV_BT_DMT_1024X768P70, 0x0d, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) { V4L2_DV_BT_DMT_1024X768P75, 0x0e, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) { V4L2_DV_BT_DMT_1024X768P85, 0x0f, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) { V4L2_DV_BT_DMT_1280X1024P60, 0x05, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) { V4L2_DV_BT_DMT_1280X1024P75, 0x06, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) { V4L2_DV_BT_DMT_1360X768P60, 0x12, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) { V4L2_DV_BT_DMT_1366X768P60, 0x13, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) { V4L2_DV_BT_DMT_1400X1050P60, 0x14, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) { V4L2_DV_BT_DMT_1400X1050P75, 0x15, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) { V4L2_DV_BT_DMT_1600X1200P60, 0x16, 0x00 }, /* TODO not tested */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) /* TODO add 1600X1200P60_RB (not a DMT timing) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) { V4L2_DV_BT_DMT_1680X1050P60, 0x18, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) { V4L2_DV_BT_DMT_1920X1200P60_RB, 0x19, 0x00 }, /* TODO not tested */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) /* sorted by number of lines */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) static const struct adv76xx_video_standards adv76xx_prim_mode_hdmi_comp[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) { V4L2_DV_BT_CEA_720X480P59_94, 0x0a, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) { V4L2_DV_BT_CEA_720X576P50, 0x0b, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) { V4L2_DV_BT_CEA_1280X720P50, 0x13, 0x01 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) { V4L2_DV_BT_CEA_1280X720P60, 0x13, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) { V4L2_DV_BT_CEA_1920X1080P24, 0x1e, 0x04 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) { V4L2_DV_BT_CEA_1920X1080P25, 0x1e, 0x03 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) { V4L2_DV_BT_CEA_1920X1080P30, 0x1e, 0x02 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) { V4L2_DV_BT_CEA_1920X1080P50, 0x1e, 0x01 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) { V4L2_DV_BT_CEA_1920X1080P60, 0x1e, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) /* sorted by number of lines */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) static const struct adv76xx_video_standards adv76xx_prim_mode_hdmi_gr[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) { V4L2_DV_BT_DMT_640X480P60, 0x08, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) { V4L2_DV_BT_DMT_640X480P72, 0x09, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) { V4L2_DV_BT_DMT_640X480P75, 0x0a, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) { V4L2_DV_BT_DMT_640X480P85, 0x0b, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) { V4L2_DV_BT_DMT_800X600P56, 0x00, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) { V4L2_DV_BT_DMT_800X600P60, 0x01, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) { V4L2_DV_BT_DMT_800X600P72, 0x02, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) { V4L2_DV_BT_DMT_800X600P75, 0x03, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) { V4L2_DV_BT_DMT_800X600P85, 0x04, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) { V4L2_DV_BT_DMT_1024X768P60, 0x0c, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) { V4L2_DV_BT_DMT_1024X768P70, 0x0d, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) { V4L2_DV_BT_DMT_1024X768P75, 0x0e, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) { V4L2_DV_BT_DMT_1024X768P85, 0x0f, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) { V4L2_DV_BT_DMT_1280X1024P60, 0x05, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) { V4L2_DV_BT_DMT_1280X1024P75, 0x06, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) static const struct v4l2_event adv76xx_ev_fmt = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) .type = V4L2_EVENT_SOURCE_CHANGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) /* ----------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) static inline struct adv76xx_state *to_state(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return container_of(sd, struct adv76xx_state, sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) static inline unsigned htotal(const struct v4l2_bt_timings *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) return V4L2_DV_BT_FRAME_WIDTH(t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) static inline unsigned vtotal(const struct v4l2_bt_timings *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) return V4L2_DV_BT_FRAME_HEIGHT(t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) /* ----------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) static int adv76xx_read_check(struct adv76xx_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) int client_page, u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) struct i2c_client *client = state->i2c_clients[client_page];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) err = regmap_read(state->regmap[client_page], reg, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) v4l_err(client, "error reading %02x, %02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) client->addr, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) /* adv76xx_write_block(): Write raw data with a maximum of I2C_SMBUS_BLOCK_MAX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) * size to one or more registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) * A value of zero will be returned on success, a negative errno will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) * be returned in error cases.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) static int adv76xx_write_block(struct adv76xx_state *state, int client_page,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) unsigned int init_reg, const void *val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) size_t val_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) struct regmap *regmap = state->regmap[client_page];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) if (val_len > I2C_SMBUS_BLOCK_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) val_len = I2C_SMBUS_BLOCK_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) return regmap_raw_write(regmap, init_reg, val, val_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) /* ----------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) static inline int io_read(struct v4l2_subdev *sd, u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) return adv76xx_read_check(state, ADV76XX_PAGE_IO, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) static inline int io_write(struct v4l2_subdev *sd, u8 reg, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) return regmap_write(state->regmap[ADV76XX_PAGE_IO], reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) static inline int io_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) return io_write(sd, reg, (io_read(sd, reg) & ~mask) | val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) static inline int avlink_read(struct v4l2_subdev *sd, u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) return adv76xx_read_check(state, ADV7604_PAGE_AVLINK, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) static inline int avlink_write(struct v4l2_subdev *sd, u8 reg, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return regmap_write(state->regmap[ADV7604_PAGE_AVLINK], reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) static inline int cec_read(struct v4l2_subdev *sd, u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) return adv76xx_read_check(state, ADV76XX_PAGE_CEC, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) static inline int cec_write(struct v4l2_subdev *sd, u8 reg, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) return regmap_write(state->regmap[ADV76XX_PAGE_CEC], reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) static inline int cec_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) return cec_write(sd, reg, (cec_read(sd, reg) & ~mask) | val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) static inline int infoframe_read(struct v4l2_subdev *sd, u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) return adv76xx_read_check(state, ADV76XX_PAGE_INFOFRAME, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) static inline int infoframe_write(struct v4l2_subdev *sd, u8 reg, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) return regmap_write(state->regmap[ADV76XX_PAGE_INFOFRAME], reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) static inline int afe_read(struct v4l2_subdev *sd, u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) return adv76xx_read_check(state, ADV76XX_PAGE_AFE, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) static inline int afe_write(struct v4l2_subdev *sd, u8 reg, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) return regmap_write(state->regmap[ADV76XX_PAGE_AFE], reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) static inline int rep_read(struct v4l2_subdev *sd, u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) return adv76xx_read_check(state, ADV76XX_PAGE_REP, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) static inline int rep_write(struct v4l2_subdev *sd, u8 reg, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) return regmap_write(state->regmap[ADV76XX_PAGE_REP], reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) static inline int rep_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) return rep_write(sd, reg, (rep_read(sd, reg) & ~mask) | val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) static inline int edid_read(struct v4l2_subdev *sd, u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) return adv76xx_read_check(state, ADV76XX_PAGE_EDID, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) static inline int edid_write(struct v4l2_subdev *sd, u8 reg, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) return regmap_write(state->regmap[ADV76XX_PAGE_EDID], reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) static inline int edid_write_block(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) unsigned int total_len, const u8 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) int len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) v4l2_dbg(2, debug, sd, "%s: write EDID block (%d byte)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) __func__, total_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) while (!err && i < total_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) len = (total_len - i) > I2C_SMBUS_BLOCK_MAX ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) I2C_SMBUS_BLOCK_MAX :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) (total_len - i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) err = adv76xx_write_block(state, ADV76XX_PAGE_EDID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) i, val + i, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) i += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) static void adv76xx_set_hpd(struct adv76xx_state *state, unsigned int hpd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) for (i = 0; i < state->info->num_dv_ports; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) gpiod_set_value_cansleep(state->hpd_gpio[i], hpd & BIT(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) v4l2_subdev_notify(&state->sd, ADV76XX_HOTPLUG, &hpd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) static void adv76xx_delayed_work_enable_hotplug(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) struct delayed_work *dwork = to_delayed_work(work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) struct adv76xx_state *state = container_of(dwork, struct adv76xx_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) delayed_work_enable_hotplug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) struct v4l2_subdev *sd = &state->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) v4l2_dbg(2, debug, sd, "%s: enable hotplug\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) adv76xx_set_hpd(state, state->edid.present);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) static inline int hdmi_read(struct v4l2_subdev *sd, u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) return adv76xx_read_check(state, ADV76XX_PAGE_HDMI, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) static u16 hdmi_read16(struct v4l2_subdev *sd, u8 reg, u16 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) return ((hdmi_read(sd, reg) << 8) | hdmi_read(sd, reg + 1)) & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) static inline int hdmi_write(struct v4l2_subdev *sd, u8 reg, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) return regmap_write(state->regmap[ADV76XX_PAGE_HDMI], reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) static inline int hdmi_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) return hdmi_write(sd, reg, (hdmi_read(sd, reg) & ~mask) | val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) static inline int test_write(struct v4l2_subdev *sd, u8 reg, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) return regmap_write(state->regmap[ADV76XX_PAGE_TEST], reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) static inline int cp_read(struct v4l2_subdev *sd, u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) return adv76xx_read_check(state, ADV76XX_PAGE_CP, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) static u16 cp_read16(struct v4l2_subdev *sd, u8 reg, u16 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) return ((cp_read(sd, reg) << 8) | cp_read(sd, reg + 1)) & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) static inline int cp_write(struct v4l2_subdev *sd, u8 reg, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) return regmap_write(state->regmap[ADV76XX_PAGE_CP], reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) static inline int cp_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) return cp_write(sd, reg, (cp_read(sd, reg) & ~mask) | val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) static inline int vdp_read(struct v4l2_subdev *sd, u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) return adv76xx_read_check(state, ADV7604_PAGE_VDP, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) static inline int vdp_write(struct v4l2_subdev *sd, u8 reg, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) return regmap_write(state->regmap[ADV7604_PAGE_VDP], reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) #define ADV76XX_REG(page, offset) (((page) << 8) | (offset))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) #define ADV76XX_REG_SEQ_TERM 0xffff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) #ifdef CONFIG_VIDEO_ADV_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) static int adv76xx_read_reg(struct v4l2_subdev *sd, unsigned int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) unsigned int page = reg >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) if (page >= ADV76XX_PAGE_MAX || !(BIT(page) & state->info->page_mask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) reg &= 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) err = regmap_read(state->regmap[page], reg, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) return err ? err : val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) static int adv76xx_write_reg(struct v4l2_subdev *sd, unsigned int reg, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) unsigned int page = reg >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (page >= ADV76XX_PAGE_MAX || !(BIT(page) & state->info->page_mask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) reg &= 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) return regmap_write(state->regmap[page], reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) static void adv76xx_write_reg_seq(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) const struct adv76xx_reg_seq *reg_seq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) for (i = 0; reg_seq[i].reg != ADV76XX_REG_SEQ_TERM; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) adv76xx_write_reg(sd, reg_seq[i].reg, reg_seq[i].val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) /* -----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) * Format helpers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) static const struct adv76xx_format_info adv7604_formats[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) { MEDIA_BUS_FMT_RGB888_1X24, ADV76XX_OP_CH_SEL_RGB, true, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) ADV76XX_OP_MODE_SEL_SDR_444 | ADV76XX_OP_FORMAT_SEL_8BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) { MEDIA_BUS_FMT_YUYV8_2X8, ADV76XX_OP_CH_SEL_RGB, false, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) ADV76XX_OP_MODE_SEL_SDR_422 | ADV76XX_OP_FORMAT_SEL_8BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) { MEDIA_BUS_FMT_YVYU8_2X8, ADV76XX_OP_CH_SEL_RGB, false, true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) ADV76XX_OP_MODE_SEL_SDR_422 | ADV76XX_OP_FORMAT_SEL_8BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) { MEDIA_BUS_FMT_YUYV10_2X10, ADV76XX_OP_CH_SEL_RGB, false, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) ADV76XX_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_10BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) { MEDIA_BUS_FMT_YVYU10_2X10, ADV76XX_OP_CH_SEL_RGB, false, true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) ADV76XX_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_10BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) { MEDIA_BUS_FMT_YUYV12_2X12, ADV76XX_OP_CH_SEL_RGB, false, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) ADV76XX_OP_MODE_SEL_SDR_422 | ADV76XX_OP_FORMAT_SEL_12BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) { MEDIA_BUS_FMT_YVYU12_2X12, ADV76XX_OP_CH_SEL_RGB, false, true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) ADV76XX_OP_MODE_SEL_SDR_422 | ADV76XX_OP_FORMAT_SEL_12BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) { MEDIA_BUS_FMT_UYVY8_1X16, ADV76XX_OP_CH_SEL_RBG, false, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV76XX_OP_FORMAT_SEL_8BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) { MEDIA_BUS_FMT_VYUY8_1X16, ADV76XX_OP_CH_SEL_RBG, false, true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV76XX_OP_FORMAT_SEL_8BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) { MEDIA_BUS_FMT_YUYV8_1X16, ADV76XX_OP_CH_SEL_RGB, false, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV76XX_OP_FORMAT_SEL_8BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) { MEDIA_BUS_FMT_YVYU8_1X16, ADV76XX_OP_CH_SEL_RGB, false, true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV76XX_OP_FORMAT_SEL_8BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) { MEDIA_BUS_FMT_UYVY10_1X20, ADV76XX_OP_CH_SEL_RBG, false, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) { MEDIA_BUS_FMT_VYUY10_1X20, ADV76XX_OP_CH_SEL_RBG, false, true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) { MEDIA_BUS_FMT_YUYV10_1X20, ADV76XX_OP_CH_SEL_RGB, false, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) { MEDIA_BUS_FMT_YVYU10_1X20, ADV76XX_OP_CH_SEL_RGB, false, true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) { MEDIA_BUS_FMT_UYVY12_1X24, ADV76XX_OP_CH_SEL_RBG, false, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV76XX_OP_FORMAT_SEL_12BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) { MEDIA_BUS_FMT_VYUY12_1X24, ADV76XX_OP_CH_SEL_RBG, false, true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV76XX_OP_FORMAT_SEL_12BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) { MEDIA_BUS_FMT_YUYV12_1X24, ADV76XX_OP_CH_SEL_RGB, false, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV76XX_OP_FORMAT_SEL_12BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) { MEDIA_BUS_FMT_YVYU12_1X24, ADV76XX_OP_CH_SEL_RGB, false, true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV76XX_OP_FORMAT_SEL_12BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) static const struct adv76xx_format_info adv7611_formats[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) { MEDIA_BUS_FMT_RGB888_1X24, ADV76XX_OP_CH_SEL_RGB, true, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) ADV76XX_OP_MODE_SEL_SDR_444 | ADV76XX_OP_FORMAT_SEL_8BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) { MEDIA_BUS_FMT_YUYV8_2X8, ADV76XX_OP_CH_SEL_RGB, false, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) ADV76XX_OP_MODE_SEL_SDR_422 | ADV76XX_OP_FORMAT_SEL_8BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) { MEDIA_BUS_FMT_YVYU8_2X8, ADV76XX_OP_CH_SEL_RGB, false, true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) ADV76XX_OP_MODE_SEL_SDR_422 | ADV76XX_OP_FORMAT_SEL_8BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) { MEDIA_BUS_FMT_YUYV12_2X12, ADV76XX_OP_CH_SEL_RGB, false, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) ADV76XX_OP_MODE_SEL_SDR_422 | ADV76XX_OP_FORMAT_SEL_12BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) { MEDIA_BUS_FMT_YVYU12_2X12, ADV76XX_OP_CH_SEL_RGB, false, true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) ADV76XX_OP_MODE_SEL_SDR_422 | ADV76XX_OP_FORMAT_SEL_12BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) { MEDIA_BUS_FMT_UYVY8_1X16, ADV76XX_OP_CH_SEL_RBG, false, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV76XX_OP_FORMAT_SEL_8BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) { MEDIA_BUS_FMT_VYUY8_1X16, ADV76XX_OP_CH_SEL_RBG, false, true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV76XX_OP_FORMAT_SEL_8BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) { MEDIA_BUS_FMT_YUYV8_1X16, ADV76XX_OP_CH_SEL_RGB, false, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV76XX_OP_FORMAT_SEL_8BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) { MEDIA_BUS_FMT_YVYU8_1X16, ADV76XX_OP_CH_SEL_RGB, false, true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV76XX_OP_FORMAT_SEL_8BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) { MEDIA_BUS_FMT_UYVY12_1X24, ADV76XX_OP_CH_SEL_RBG, false, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV76XX_OP_FORMAT_SEL_12BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) { MEDIA_BUS_FMT_VYUY12_1X24, ADV76XX_OP_CH_SEL_RBG, false, true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV76XX_OP_FORMAT_SEL_12BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) { MEDIA_BUS_FMT_YUYV12_1X24, ADV76XX_OP_CH_SEL_RGB, false, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV76XX_OP_FORMAT_SEL_12BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) { MEDIA_BUS_FMT_YVYU12_1X24, ADV76XX_OP_CH_SEL_RGB, false, true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV76XX_OP_FORMAT_SEL_12BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) static const struct adv76xx_format_info adv7612_formats[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) { MEDIA_BUS_FMT_RGB888_1X24, ADV76XX_OP_CH_SEL_RGB, true, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) ADV76XX_OP_MODE_SEL_SDR_444 | ADV76XX_OP_FORMAT_SEL_8BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) { MEDIA_BUS_FMT_YUYV8_2X8, ADV76XX_OP_CH_SEL_RGB, false, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) ADV76XX_OP_MODE_SEL_SDR_422 | ADV76XX_OP_FORMAT_SEL_8BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) { MEDIA_BUS_FMT_YVYU8_2X8, ADV76XX_OP_CH_SEL_RGB, false, true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) ADV76XX_OP_MODE_SEL_SDR_422 | ADV76XX_OP_FORMAT_SEL_8BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) { MEDIA_BUS_FMT_UYVY8_1X16, ADV76XX_OP_CH_SEL_RBG, false, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV76XX_OP_FORMAT_SEL_8BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) { MEDIA_BUS_FMT_VYUY8_1X16, ADV76XX_OP_CH_SEL_RBG, false, true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV76XX_OP_FORMAT_SEL_8BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) { MEDIA_BUS_FMT_YUYV8_1X16, ADV76XX_OP_CH_SEL_RGB, false, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV76XX_OP_FORMAT_SEL_8BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) { MEDIA_BUS_FMT_YVYU8_1X16, ADV76XX_OP_CH_SEL_RGB, false, true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV76XX_OP_FORMAT_SEL_8BIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) static const struct adv76xx_format_info *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) adv76xx_format_info(struct adv76xx_state *state, u32 code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) for (i = 0; i < state->info->nformats; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) if (state->info->formats[i].code == code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) return &state->info->formats[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) /* ----------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) static inline bool is_analog_input(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) return state->selected_input == ADV7604_PAD_VGA_RGB ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) state->selected_input == ADV7604_PAD_VGA_COMP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) static inline bool is_digital_input(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) return state->selected_input == ADV76XX_PAD_HDMI_PORT_A ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) state->selected_input == ADV7604_PAD_HDMI_PORT_B ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) state->selected_input == ADV7604_PAD_HDMI_PORT_C ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) state->selected_input == ADV7604_PAD_HDMI_PORT_D;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) static const struct v4l2_dv_timings_cap adv7604_timings_cap_analog = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) .type = V4L2_DV_BT_656_1120,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) /* keep this initialization for compatibility with GCC < 4.4.6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) .reserved = { 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) V4L2_INIT_BT_TIMINGS(640, 1920, 350, 1200, 25000000, 170000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_REDUCED_BLANKING |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) V4L2_DV_BT_CAP_CUSTOM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) static const struct v4l2_dv_timings_cap adv76xx_timings_cap_digital = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) .type = V4L2_DV_BT_656_1120,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) /* keep this initialization for compatibility with GCC < 4.4.6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) .reserved = { 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) V4L2_INIT_BT_TIMINGS(640, 1920, 350, 1200, 25000000, 225000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_REDUCED_BLANKING |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) V4L2_DV_BT_CAP_CUSTOM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) * Return the DV timings capabilities for the requested sink pad. As a special
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) * case, pad value -1 returns the capabilities for the currently selected input.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) static const struct v4l2_dv_timings_cap *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) adv76xx_get_dv_timings_cap(struct v4l2_subdev *sd, int pad)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) if (pad == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) pad = state->selected_input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) switch (pad) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) case ADV76XX_PAD_HDMI_PORT_A:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) case ADV7604_PAD_HDMI_PORT_B:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) case ADV7604_PAD_HDMI_PORT_C:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) case ADV7604_PAD_HDMI_PORT_D:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) return &adv76xx_timings_cap_digital;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) case ADV7604_PAD_VGA_RGB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) case ADV7604_PAD_VGA_COMP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) return &adv7604_timings_cap_analog;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) /* ----------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) #ifdef CONFIG_VIDEO_ADV_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) static void adv76xx_inv_register(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) v4l2_info(sd, "0x000-0x0ff: IO Map\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) v4l2_info(sd, "0x100-0x1ff: AVLink Map\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) v4l2_info(sd, "0x200-0x2ff: CEC Map\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) v4l2_info(sd, "0x300-0x3ff: InfoFrame Map\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) v4l2_info(sd, "0x400-0x4ff: ESDP Map\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) v4l2_info(sd, "0x500-0x5ff: DPP Map\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) v4l2_info(sd, "0x600-0x6ff: AFE Map\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) v4l2_info(sd, "0x700-0x7ff: Repeater Map\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) v4l2_info(sd, "0x800-0x8ff: EDID Map\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) v4l2_info(sd, "0x900-0x9ff: HDMI Map\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) v4l2_info(sd, "0xa00-0xaff: Test Map\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) v4l2_info(sd, "0xb00-0xbff: CP Map\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) v4l2_info(sd, "0xc00-0xcff: VDP Map\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) static int adv76xx_g_register(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) struct v4l2_dbg_register *reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) ret = adv76xx_read_reg(sd, reg->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) v4l2_info(sd, "Register %03llx not supported\n", reg->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) adv76xx_inv_register(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) reg->size = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) reg->val = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) static int adv76xx_s_register(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) const struct v4l2_dbg_register *reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) ret = adv76xx_write_reg(sd, reg->reg, reg->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) v4l2_info(sd, "Register %03llx not supported\n", reg->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) adv76xx_inv_register(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) static unsigned int adv7604_read_cable_det(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) u8 value = io_read(sd, 0x6f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) return ((value & 0x10) >> 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) | ((value & 0x08) >> 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) | ((value & 0x04) << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) | ((value & 0x02) << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) static unsigned int adv7611_read_cable_det(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) u8 value = io_read(sd, 0x6f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) return value & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) static unsigned int adv7612_read_cable_det(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) /* Reads CABLE_DET_A_RAW. For input B support, need to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) * account for bit 7 [MSB] of 0x6a (ie. CABLE_DET_B_RAW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) u8 value = io_read(sd, 0x6f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) return value & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) static int adv76xx_s_detect_tx_5v_ctrl(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) const struct adv76xx_chip_info *info = state->info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) u16 cable_det = info->read_cable_det(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) return v4l2_ctrl_s_ctrl(state->detect_tx_5v_ctrl, cable_det);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) static int find_and_set_predefined_video_timings(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) u8 prim_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) const struct adv76xx_video_standards *predef_vid_timings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) const struct v4l2_dv_timings *timings)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) for (i = 0; predef_vid_timings[i].timings.bt.width; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) if (!v4l2_match_dv_timings(timings, &predef_vid_timings[i].timings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) is_digital_input(sd) ? 250000 : 1000000, false))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) io_write(sd, 0x00, predef_vid_timings[i].vid_std); /* video std */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) io_write(sd, 0x01, (predef_vid_timings[i].v_freq << 4) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) prim_mode); /* v_freq and prim mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) static int configure_predefined_video_timings(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) struct v4l2_dv_timings *timings)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) v4l2_dbg(1, debug, sd, "%s", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) if (adv76xx_has_afe(state)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) /* reset to default values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) io_write(sd, 0x16, 0x43);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) io_write(sd, 0x17, 0x5a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) /* disable embedded syncs for auto graphics mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) cp_write_clr_set(sd, 0x81, 0x10, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) cp_write(sd, 0x8f, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) cp_write(sd, 0x90, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) cp_write(sd, 0xa2, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) cp_write(sd, 0xa3, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) cp_write(sd, 0xa4, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) cp_write(sd, 0xa5, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) cp_write(sd, 0xa6, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) cp_write(sd, 0xa7, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) cp_write(sd, 0xab, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) cp_write(sd, 0xac, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) if (is_analog_input(sd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) err = find_and_set_predefined_video_timings(sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) 0x01, adv7604_prim_mode_comp, timings);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) err = find_and_set_predefined_video_timings(sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) 0x02, adv7604_prim_mode_gr, timings);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) } else if (is_digital_input(sd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) err = find_and_set_predefined_video_timings(sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) 0x05, adv76xx_prim_mode_hdmi_comp, timings);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) err = find_and_set_predefined_video_timings(sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) 0x06, adv76xx_prim_mode_hdmi_gr, timings);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) v4l2_dbg(2, debug, sd, "%s: Unknown port %d selected\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) __func__, state->selected_input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) err = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) static void configure_custom_video_timings(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) const struct v4l2_bt_timings *bt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) u32 width = htotal(bt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) u32 height = vtotal(bt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) u16 cp_start_sav = bt->hsync + bt->hbackporch - 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) u16 cp_start_eav = width - bt->hfrontporch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) u16 cp_start_vbi = height - bt->vfrontporch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) u16 cp_end_vbi = bt->vsync + bt->vbackporch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) u16 ch1_fr_ll = (((u32)bt->pixelclock / 100) > 0) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) ((width * (ADV76XX_FSC / 100)) / ((u32)bt->pixelclock / 100)) : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) const u8 pll[2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) 0xc0 | ((width >> 8) & 0x1f),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) width & 0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) v4l2_dbg(2, debug, sd, "%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) if (is_analog_input(sd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) /* auto graphics */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) io_write(sd, 0x00, 0x07); /* video std */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) io_write(sd, 0x01, 0x02); /* prim mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) /* enable embedded syncs for auto graphics mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) cp_write_clr_set(sd, 0x81, 0x10, 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) /* Should only be set in auto-graphics mode [REF_02, p. 91-92] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) /* setup PLL_DIV_MAN_EN and PLL_DIV_RATIO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) /* IO-map reg. 0x16 and 0x17 should be written in sequence */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) if (regmap_raw_write(state->regmap[ADV76XX_PAGE_IO],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 0x16, pll, 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) v4l2_err(sd, "writing to reg 0x16 and 0x17 failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) /* active video - horizontal timing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) cp_write(sd, 0xa2, (cp_start_sav >> 4) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) cp_write(sd, 0xa3, ((cp_start_sav & 0x0f) << 4) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) ((cp_start_eav >> 8) & 0x0f));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) cp_write(sd, 0xa4, cp_start_eav & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) /* active video - vertical timing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) cp_write(sd, 0xa5, (cp_start_vbi >> 4) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) cp_write(sd, 0xa6, ((cp_start_vbi & 0xf) << 4) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) ((cp_end_vbi >> 8) & 0xf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) cp_write(sd, 0xa7, cp_end_vbi & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) } else if (is_digital_input(sd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) /* set default prim_mode/vid_std for HDMI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) according to [REF_03, c. 4.2] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) io_write(sd, 0x00, 0x02); /* video std */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) io_write(sd, 0x01, 0x06); /* prim mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) v4l2_dbg(2, debug, sd, "%s: Unknown port %d selected\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) __func__, state->selected_input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) cp_write(sd, 0x8f, (ch1_fr_ll >> 8) & 0x7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) cp_write(sd, 0x90, ch1_fr_ll & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) cp_write(sd, 0xab, (height >> 4) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) cp_write(sd, 0xac, (height & 0x0f) << 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) static void adv76xx_set_offset(struct v4l2_subdev *sd, bool auto_offset, u16 offset_a, u16 offset_b, u16 offset_c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) u8 offset_buf[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) if (auto_offset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) offset_a = 0x3ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) offset_b = 0x3ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) offset_c = 0x3ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) v4l2_dbg(2, debug, sd, "%s: %s offset: a = 0x%x, b = 0x%x, c = 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) __func__, auto_offset ? "Auto" : "Manual",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) offset_a, offset_b, offset_c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) offset_buf[0] = (cp_read(sd, 0x77) & 0xc0) | ((offset_a & 0x3f0) >> 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) offset_buf[1] = ((offset_a & 0x00f) << 4) | ((offset_b & 0x3c0) >> 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) offset_buf[2] = ((offset_b & 0x03f) << 2) | ((offset_c & 0x300) >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) offset_buf[3] = offset_c & 0x0ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) /* Registers must be written in this order with no i2c access in between */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) if (regmap_raw_write(state->regmap[ADV76XX_PAGE_CP],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) 0x77, offset_buf, 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) v4l2_err(sd, "%s: i2c error writing to CP reg 0x77, 0x78, 0x79, 0x7a\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) static void adv76xx_set_gain(struct v4l2_subdev *sd, bool auto_gain, u16 gain_a, u16 gain_b, u16 gain_c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) u8 gain_buf[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) u8 gain_man = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) u8 agc_mode_man = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) if (auto_gain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) gain_man = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) agc_mode_man = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) gain_a = 0x100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) gain_b = 0x100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) gain_c = 0x100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) v4l2_dbg(2, debug, sd, "%s: %s gain: a = 0x%x, b = 0x%x, c = 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) __func__, auto_gain ? "Auto" : "Manual",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) gain_a, gain_b, gain_c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) gain_buf[0] = ((gain_man << 7) | (agc_mode_man << 6) | ((gain_a & 0x3f0) >> 4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) gain_buf[1] = (((gain_a & 0x00f) << 4) | ((gain_b & 0x3c0) >> 6));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) gain_buf[2] = (((gain_b & 0x03f) << 2) | ((gain_c & 0x300) >> 8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) gain_buf[3] = ((gain_c & 0x0ff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) /* Registers must be written in this order with no i2c access in between */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) if (regmap_raw_write(state->regmap[ADV76XX_PAGE_CP],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) 0x73, gain_buf, 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) v4l2_err(sd, "%s: i2c error writing to CP reg 0x73, 0x74, 0x75, 0x76\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) static void set_rgb_quantization_range(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) bool rgb_output = io_read(sd, 0x02) & 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) bool hdmi_signal = hdmi_read(sd, 0x05) & 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) u8 y = HDMI_COLORSPACE_RGB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) if (hdmi_signal && (io_read(sd, 0x60) & 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) y = infoframe_read(sd, 0x01) >> 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) v4l2_dbg(2, debug, sd, "%s: RGB quantization range: %d, RGB out: %d, HDMI: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) __func__, state->rgb_quantization_range,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) rgb_output, hdmi_signal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) adv76xx_set_gain(sd, true, 0x0, 0x0, 0x0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) adv76xx_set_offset(sd, true, 0x0, 0x0, 0x0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) io_write_clr_set(sd, 0x02, 0x04, rgb_output ? 0 : 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) switch (state->rgb_quantization_range) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) case V4L2_DV_RGB_RANGE_AUTO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) if (state->selected_input == ADV7604_PAD_VGA_RGB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) /* Receiving analog RGB signal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) * Set RGB full range (0-255) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) io_write_clr_set(sd, 0x02, 0xf0, 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) if (state->selected_input == ADV7604_PAD_VGA_COMP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) /* Receiving analog YPbPr signal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) * Set automode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) io_write_clr_set(sd, 0x02, 0xf0, 0xf0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) if (hdmi_signal) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) /* Receiving HDMI signal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) * Set automode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) io_write_clr_set(sd, 0x02, 0xf0, 0xf0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) /* Receiving DVI-D signal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) * ADV7604 selects RGB limited range regardless of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) * input format (CE/IT) in automatic mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) if (state->timings.bt.flags & V4L2_DV_FL_IS_CE_VIDEO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) /* RGB limited range (16-235) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) io_write_clr_set(sd, 0x02, 0xf0, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) /* RGB full range (0-255) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) io_write_clr_set(sd, 0x02, 0xf0, 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) if (is_digital_input(sd) && rgb_output) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) adv76xx_set_offset(sd, false, 0x40, 0x40, 0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) adv76xx_set_gain(sd, false, 0xe0, 0xe0, 0xe0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) adv76xx_set_offset(sd, false, 0x70, 0x70, 0x70);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) case V4L2_DV_RGB_RANGE_LIMITED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) if (state->selected_input == ADV7604_PAD_VGA_COMP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) /* YCrCb limited range (16-235) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) io_write_clr_set(sd, 0x02, 0xf0, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) if (y != HDMI_COLORSPACE_RGB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) /* RGB limited range (16-235) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) io_write_clr_set(sd, 0x02, 0xf0, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) case V4L2_DV_RGB_RANGE_FULL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) if (state->selected_input == ADV7604_PAD_VGA_COMP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) /* YCrCb full range (0-255) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) io_write_clr_set(sd, 0x02, 0xf0, 0x60);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) if (y != HDMI_COLORSPACE_RGB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) /* RGB full range (0-255) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) io_write_clr_set(sd, 0x02, 0xf0, 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) if (is_analog_input(sd) || hdmi_signal)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) /* Adjust gain/offset for DVI-D signals only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) if (rgb_output) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) adv76xx_set_offset(sd, false, 0x40, 0x40, 0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) adv76xx_set_gain(sd, false, 0xe0, 0xe0, 0xe0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) adv76xx_set_offset(sd, false, 0x70, 0x70, 0x70);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) static int adv76xx_s_ctrl(struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) struct v4l2_subdev *sd =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) &container_of(ctrl->handler, struct adv76xx_state, hdl)->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) switch (ctrl->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) case V4L2_CID_BRIGHTNESS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) cp_write(sd, 0x3c, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) case V4L2_CID_CONTRAST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) cp_write(sd, 0x3a, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) case V4L2_CID_SATURATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) cp_write(sd, 0x3b, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) case V4L2_CID_HUE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) cp_write(sd, 0x3d, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) case V4L2_CID_DV_RX_RGB_RANGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) state->rgb_quantization_range = ctrl->val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) set_rgb_quantization_range(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) case V4L2_CID_ADV_RX_ANALOG_SAMPLING_PHASE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) if (!adv76xx_has_afe(state))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) /* Set the analog sampling phase. This is needed to find the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) best sampling phase for analog video: an application or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) driver has to try a number of phases and analyze the picture
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) quality before settling on the best performing phase. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) afe_write(sd, 0xc8, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) case V4L2_CID_ADV_RX_FREE_RUN_COLOR_MANUAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) /* Use the default blue color for free running mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) or supply your own. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) cp_write_clr_set(sd, 0xbf, 0x04, ctrl->val << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) case V4L2_CID_ADV_RX_FREE_RUN_COLOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) cp_write(sd, 0xc0, (ctrl->val & 0xff0000) >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) cp_write(sd, 0xc1, (ctrl->val & 0x00ff00) >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) cp_write(sd, 0xc2, (u8)(ctrl->val & 0x0000ff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) static int adv76xx_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) struct v4l2_subdev *sd =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) &container_of(ctrl->handler, struct adv76xx_state, hdl)->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) if (ctrl->id == V4L2_CID_DV_RX_IT_CONTENT_TYPE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) ctrl->val = V4L2_DV_IT_CONTENT_TYPE_NO_ITC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) if ((io_read(sd, 0x60) & 1) && (infoframe_read(sd, 0x03) & 0x80))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) ctrl->val = (infoframe_read(sd, 0x05) >> 4) & 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) /* ----------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) static inline bool no_power(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) /* Entire chip or CP powered off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) return io_read(sd, 0x0c) & 0x24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) static inline bool no_signal_tmds(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) return !(io_read(sd, 0x6a) & (0x10 >> state->selected_input));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) static inline bool no_lock_tmds(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) const struct adv76xx_chip_info *info = state->info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) return (io_read(sd, 0x6a) & info->tdms_lock_mask) != info->tdms_lock_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) static inline bool is_hdmi(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) return hdmi_read(sd, 0x05) & 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) static inline bool no_lock_sspd(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) * Chips without a AFE don't expose registers for the SSPD, so just assume
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) * that we have a lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) if (adv76xx_has_afe(state))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) /* TODO channel 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) return ((cp_read(sd, 0xb5) & 0xd0) != 0xd0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) static inline bool no_lock_stdi(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) /* TODO channel 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) return !(cp_read(sd, 0xb1) & 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) static inline bool no_signal(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) bool ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) ret = no_power(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) ret |= no_lock_stdi(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) ret |= no_lock_sspd(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) if (is_digital_input(sd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) ret |= no_lock_tmds(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) ret |= no_signal_tmds(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) static inline bool no_lock_cp(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) if (!adv76xx_has_afe(state))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) /* CP has detected a non standard number of lines on the incoming
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) video compared to what it is configured to receive by s_dv_timings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) return io_read(sd, 0x12) & 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) static inline bool in_free_run(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) return cp_read(sd, 0xff) & 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) static int adv76xx_g_input_status(struct v4l2_subdev *sd, u32 *status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) *status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) *status |= no_power(sd) ? V4L2_IN_ST_NO_POWER : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) *status |= no_signal(sd) ? V4L2_IN_ST_NO_SIGNAL : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) if (!in_free_run(sd) && no_lock_cp(sd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) *status |= is_digital_input(sd) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) V4L2_IN_ST_NO_SYNC : V4L2_IN_ST_NO_H_LOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) v4l2_dbg(1, debug, sd, "%s: status = 0x%x\n", __func__, *status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) /* ----------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) struct stdi_readback {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) u16 bl, lcf, lcvs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) u8 hs_pol, vs_pol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) bool interlaced;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) static int stdi2dv_timings(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) struct stdi_readback *stdi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) struct v4l2_dv_timings *timings)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) u32 hfreq = (ADV76XX_FSC * 8) / stdi->bl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) u32 pix_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) for (i = 0; v4l2_dv_timings_presets[i].bt.width; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) const struct v4l2_bt_timings *bt = &v4l2_dv_timings_presets[i].bt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) if (!v4l2_valid_dv_timings(&v4l2_dv_timings_presets[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) adv76xx_get_dv_timings_cap(sd, -1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) adv76xx_check_dv_timings, NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) if (vtotal(bt) != stdi->lcf + 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) if (bt->vsync != stdi->lcvs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) pix_clk = hfreq * htotal(bt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) if ((pix_clk < bt->pixelclock + 1000000) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) (pix_clk > bt->pixelclock - 1000000)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) *timings = v4l2_dv_timings_presets[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) if (v4l2_detect_cvt(stdi->lcf + 1, hfreq, stdi->lcvs, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) (stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) (stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) false, timings))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) if (v4l2_detect_gtf(stdi->lcf + 1, hfreq, stdi->lcvs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) (stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) (stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) false, state->aspect_ratio, timings))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) v4l2_dbg(2, debug, sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) "%s: No format candidate found for lcvs = %d, lcf=%d, bl = %d, %chsync, %cvsync\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) __func__, stdi->lcvs, stdi->lcf, stdi->bl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) stdi->hs_pol, stdi->vs_pol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) static int read_stdi(struct v4l2_subdev *sd, struct stdi_readback *stdi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) const struct adv76xx_chip_info *info = state->info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) u8 polarity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) if (no_lock_stdi(sd) || no_lock_sspd(sd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) v4l2_dbg(2, debug, sd, "%s: STDI and/or SSPD not locked\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) /* read STDI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) stdi->bl = cp_read16(sd, 0xb1, 0x3fff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) stdi->lcf = cp_read16(sd, info->lcf_reg, 0x7ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) stdi->lcvs = cp_read(sd, 0xb3) >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) stdi->interlaced = io_read(sd, 0x12) & 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) if (adv76xx_has_afe(state)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) /* read SSPD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) polarity = cp_read(sd, 0xb5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) if ((polarity & 0x03) == 0x01) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) stdi->hs_pol = polarity & 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) ? (polarity & 0x08 ? '+' : '-') : 'x';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) stdi->vs_pol = polarity & 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) ? (polarity & 0x20 ? '+' : '-') : 'x';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) stdi->hs_pol = 'x';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) stdi->vs_pol = 'x';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) polarity = hdmi_read(sd, 0x05);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) stdi->hs_pol = polarity & 0x20 ? '+' : '-';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) stdi->vs_pol = polarity & 0x10 ? '+' : '-';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) if (no_lock_stdi(sd) || no_lock_sspd(sd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) v4l2_dbg(2, debug, sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) "%s: signal lost during readout of STDI/SSPD\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) if (stdi->lcf < 239 || stdi->bl < 8 || stdi->bl == 0x3fff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) v4l2_dbg(2, debug, sd, "%s: invalid signal\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) memset(stdi, 0, sizeof(struct stdi_readback));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) v4l2_dbg(2, debug, sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) "%s: lcf (frame height - 1) = %d, bl = %d, lcvs (vsync) = %d, %chsync, %cvsync, %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) __func__, stdi->lcf, stdi->bl, stdi->lcvs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) stdi->hs_pol, stdi->vs_pol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) stdi->interlaced ? "interlaced" : "progressive");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) static int adv76xx_enum_dv_timings(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) struct v4l2_enum_dv_timings *timings)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) if (timings->pad >= state->source_pad)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) return v4l2_enum_dv_timings_cap(timings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) adv76xx_get_dv_timings_cap(sd, timings->pad),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) adv76xx_check_dv_timings, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) static int adv76xx_dv_timings_cap(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) struct v4l2_dv_timings_cap *cap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) unsigned int pad = cap->pad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) if (cap->pad >= state->source_pad)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) *cap = *adv76xx_get_dv_timings_cap(sd, pad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) cap->pad = pad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) /* Fill the optional fields .standards and .flags in struct v4l2_dv_timings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) if the format is listed in adv76xx_timings[] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) static void adv76xx_fill_optional_dv_timings_fields(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) struct v4l2_dv_timings *timings)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) v4l2_find_dv_timings_cap(timings, adv76xx_get_dv_timings_cap(sd, -1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) is_digital_input(sd) ? 250000 : 1000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) adv76xx_check_dv_timings, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) static unsigned int adv7604_read_hdmi_pixelclock(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) int a, b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) a = hdmi_read(sd, 0x06);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) b = hdmi_read(sd, 0x3b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) if (a < 0 || b < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) return a * 1000000 + ((b & 0x30) >> 4) * 250000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) static unsigned int adv7611_read_hdmi_pixelclock(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) int a, b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) a = hdmi_read(sd, 0x51);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) b = hdmi_read(sd, 0x52);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) if (a < 0 || b < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) return ((a << 1) | (b >> 7)) * 1000000 + (b & 0x7f) * 1000000 / 128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) static unsigned int adv76xx_read_hdmi_pixelclock(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) const struct adv76xx_chip_info *info = state->info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) unsigned int freq, bits_per_channel, pixelrepetition;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) freq = info->read_hdmi_pixelclock(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) if (is_hdmi(sd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) /* adjust for deep color mode and pixel repetition */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) bits_per_channel = ((hdmi_read(sd, 0x0b) & 0x60) >> 4) + 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) pixelrepetition = (hdmi_read(sd, 0x05) & 0x0f) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) freq = freq * 8 / bits_per_channel / pixelrepetition;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) return freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) static int adv76xx_query_dv_timings(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) struct v4l2_dv_timings *timings)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) const struct adv76xx_chip_info *info = state->info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) struct v4l2_bt_timings *bt = &timings->bt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) struct stdi_readback stdi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) if (!timings)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) memset(timings, 0, sizeof(struct v4l2_dv_timings));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) if (no_signal(sd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) state->restart_stdi_once = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) v4l2_dbg(1, debug, sd, "%s: no valid signal\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) return -ENOLINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) /* read STDI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) if (read_stdi(sd, &stdi)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) v4l2_dbg(1, debug, sd, "%s: STDI/SSPD not locked\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) return -ENOLINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) bt->interlaced = stdi.interlaced ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) V4L2_DV_INTERLACED : V4L2_DV_PROGRESSIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) if (is_digital_input(sd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) bool hdmi_signal = hdmi_read(sd, 0x05) & 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) u8 vic = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) u32 w, h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) w = hdmi_read16(sd, 0x07, info->linewidth_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) h = hdmi_read16(sd, 0x09, info->field0_height_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) if (hdmi_signal && (io_read(sd, 0x60) & 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) vic = infoframe_read(sd, 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) if (vic && v4l2_find_dv_timings_cea861_vic(timings, vic) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) bt->width == w && bt->height == h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) timings->type = V4L2_DV_BT_656_1120;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) bt->width = w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) bt->height = h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) bt->pixelclock = adv76xx_read_hdmi_pixelclock(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) bt->hfrontporch = hdmi_read16(sd, 0x20, info->hfrontporch_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) bt->hsync = hdmi_read16(sd, 0x22, info->hsync_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) bt->hbackporch = hdmi_read16(sd, 0x24, info->hbackporch_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) bt->vfrontporch = hdmi_read16(sd, 0x2a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) info->field0_vfrontporch_mask) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) bt->vsync = hdmi_read16(sd, 0x2e, info->field0_vsync_mask) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) bt->vbackporch = hdmi_read16(sd, 0x32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) info->field0_vbackporch_mask) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) bt->polarities = ((hdmi_read(sd, 0x05) & 0x10) ? V4L2_DV_VSYNC_POS_POL : 0) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) ((hdmi_read(sd, 0x05) & 0x20) ? V4L2_DV_HSYNC_POS_POL : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) if (bt->interlaced == V4L2_DV_INTERLACED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) bt->height += hdmi_read16(sd, 0x0b,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) info->field1_height_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) bt->il_vfrontporch = hdmi_read16(sd, 0x2c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) info->field1_vfrontporch_mask) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) bt->il_vsync = hdmi_read16(sd, 0x30,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) info->field1_vsync_mask) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) bt->il_vbackporch = hdmi_read16(sd, 0x34,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) info->field1_vbackporch_mask) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) adv76xx_fill_optional_dv_timings_fields(sd, timings);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) /* find format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) * Since LCVS values are inaccurate [REF_03, p. 275-276],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) * stdi2dv_timings() is called with lcvs +-1 if the first attempt fails.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) if (!stdi2dv_timings(sd, &stdi, timings))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) stdi.lcvs += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) v4l2_dbg(1, debug, sd, "%s: lcvs + 1 = %d\n", __func__, stdi.lcvs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) if (!stdi2dv_timings(sd, &stdi, timings))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) stdi.lcvs -= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) v4l2_dbg(1, debug, sd, "%s: lcvs - 1 = %d\n", __func__, stdi.lcvs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) if (stdi2dv_timings(sd, &stdi, timings)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) * The STDI block may measure wrong values, especially
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) * for lcvs and lcf. If the driver can not find any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) * valid timing, the STDI block is restarted to measure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) * the video timings again. The function will return an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) * error, but the restart of STDI will generate a new
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) * STDI interrupt and the format detection process will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) * restart.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) if (state->restart_stdi_once) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) v4l2_dbg(1, debug, sd, "%s: restart STDI\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) /* TODO restart STDI for Sync Channel 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) /* enter one-shot mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) cp_write_clr_set(sd, 0x86, 0x06, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) /* trigger STDI restart */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) cp_write_clr_set(sd, 0x86, 0x06, 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) /* reset to continuous mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) cp_write_clr_set(sd, 0x86, 0x06, 0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) state->restart_stdi_once = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) return -ENOLINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) v4l2_dbg(1, debug, sd, "%s: format not supported\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) return -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) state->restart_stdi_once = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) if (no_signal(sd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) v4l2_dbg(1, debug, sd, "%s: signal lost during readout\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) memset(timings, 0, sizeof(struct v4l2_dv_timings));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) return -ENOLINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) if ((is_analog_input(sd) && bt->pixelclock > 170000000) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) (is_digital_input(sd) && bt->pixelclock > 225000000)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) v4l2_dbg(1, debug, sd, "%s: pixelclock out of range %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) __func__, (u32)bt->pixelclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) return -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) if (debug > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) v4l2_print_dv_timings(sd->name, "adv76xx_query_dv_timings: ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) timings, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) static int adv76xx_s_dv_timings(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) struct v4l2_dv_timings *timings)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) struct v4l2_bt_timings *bt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) if (!timings)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) if (v4l2_match_dv_timings(&state->timings, timings, 0, false)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) v4l2_dbg(1, debug, sd, "%s: no change\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) bt = &timings->bt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) if (!v4l2_valid_dv_timings(timings, adv76xx_get_dv_timings_cap(sd, -1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) adv76xx_check_dv_timings, NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) return -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) adv76xx_fill_optional_dv_timings_fields(sd, timings);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) state->timings = *timings;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) cp_write_clr_set(sd, 0x91, 0x40, bt->interlaced ? 0x40 : 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) /* Use prim_mode and vid_std when available */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) err = configure_predefined_video_timings(sd, timings);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) /* custom settings when the video format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) does not have prim_mode/vid_std */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) configure_custom_video_timings(sd, bt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) set_rgb_quantization_range(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) if (debug > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) v4l2_print_dv_timings(sd->name, "adv76xx_s_dv_timings: ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) timings, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) static int adv76xx_g_dv_timings(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) struct v4l2_dv_timings *timings)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) *timings = state->timings;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) static void adv7604_set_termination(struct v4l2_subdev *sd, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) hdmi_write(sd, 0x01, enable ? 0x00 : 0x78);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) static void adv7611_set_termination(struct v4l2_subdev *sd, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) hdmi_write(sd, 0x83, enable ? 0xfe : 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) static void enable_input(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) if (is_analog_input(sd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) io_write(sd, 0x15, 0xb0); /* Disable Tristate of Pins (no audio) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) } else if (is_digital_input(sd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) hdmi_write_clr_set(sd, 0x00, 0x03, state->selected_input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) state->info->set_termination(sd, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) io_write(sd, 0x15, 0xa0); /* Disable Tristate of Pins */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) hdmi_write_clr_set(sd, 0x1a, 0x10, 0x00); /* Unmute audio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) v4l2_dbg(2, debug, sd, "%s: Unknown port %d selected\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) __func__, state->selected_input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) static void disable_input(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) hdmi_write_clr_set(sd, 0x1a, 0x10, 0x10); /* Mute audio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) msleep(16); /* 512 samples with >= 32 kHz sample rate [REF_03, c. 7.16.10] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) io_write(sd, 0x15, 0xbe); /* Tristate all outputs from video core */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) state->info->set_termination(sd, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) static void select_input(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) const struct adv76xx_chip_info *info = state->info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) if (is_analog_input(sd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) adv76xx_write_reg_seq(sd, info->recommended_settings[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) afe_write(sd, 0x00, 0x08); /* power up ADC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) afe_write(sd, 0x01, 0x06); /* power up Analog Front End */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) afe_write(sd, 0xc8, 0x00); /* phase control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) } else if (is_digital_input(sd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) hdmi_write(sd, 0x00, state->selected_input & 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) adv76xx_write_reg_seq(sd, info->recommended_settings[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) if (adv76xx_has_afe(state)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) afe_write(sd, 0x00, 0xff); /* power down ADC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) afe_write(sd, 0x01, 0xfe); /* power down Analog Front End */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) afe_write(sd, 0xc8, 0x40); /* phase control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) cp_write(sd, 0x3e, 0x00); /* CP core pre-gain control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) cp_write(sd, 0xc3, 0x39); /* CP coast control. Graphics mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) cp_write(sd, 0x40, 0x80); /* CP core pre-gain control. Graphics mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) v4l2_dbg(2, debug, sd, "%s: Unknown port %d selected\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) __func__, state->selected_input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) static int adv76xx_s_routing(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) u32 input, u32 output, u32 config)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) v4l2_dbg(2, debug, sd, "%s: input %d, selected input %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) __func__, input, state->selected_input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) if (input == state->selected_input)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) if (input > state->info->max_port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) state->selected_input = input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) disable_input(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) select_input(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) enable_input(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) v4l2_subdev_notify_event(sd, &adv76xx_ev_fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) static int adv76xx_enum_mbus_code(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) struct v4l2_subdev_mbus_code_enum *code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) if (code->index >= state->info->nformats)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) code->code = state->info->formats[code->index].code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) static void adv76xx_fill_format(struct adv76xx_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) struct v4l2_mbus_framefmt *format)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) memset(format, 0, sizeof(*format));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) format->width = state->timings.bt.width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) format->height = state->timings.bt.height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) format->field = V4L2_FIELD_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) format->colorspace = V4L2_COLORSPACE_SRGB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) if (state->timings.bt.flags & V4L2_DV_FL_IS_CE_VIDEO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) format->colorspace = (state->timings.bt.height <= 576) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) V4L2_COLORSPACE_SMPTE170M : V4L2_COLORSPACE_REC709;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) * Compute the op_ch_sel value required to obtain on the bus the component order
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) * corresponding to the selected format taking into account bus reordering
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) * applied by the board at the output of the device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) * The following table gives the op_ch_value from the format component order
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) * (expressed as op_ch_sel value in column) and the bus reordering (expressed as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) * adv76xx_bus_order value in row).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) * | GBR(0) GRB(1) BGR(2) RGB(3) BRG(4) RBG(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) * ----------+-------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) * RGB (NOP) | GBR GRB BGR RGB BRG RBG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) * GRB (1-2) | BGR RGB GBR GRB RBG BRG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) * RBG (2-3) | GRB GBR BRG RBG BGR RGB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) * BGR (1-3) | RBG BRG RGB BGR GRB GBR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) * BRG (ROR) | BRG RBG GRB GBR RGB BGR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) * GBR (ROL) | RGB BGR RBG BRG GBR GRB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) static unsigned int adv76xx_op_ch_sel(struct adv76xx_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) #define _SEL(a,b,c,d,e,f) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) ADV76XX_OP_CH_SEL_##a, ADV76XX_OP_CH_SEL_##b, ADV76XX_OP_CH_SEL_##c, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) ADV76XX_OP_CH_SEL_##d, ADV76XX_OP_CH_SEL_##e, ADV76XX_OP_CH_SEL_##f }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) #define _BUS(x) [ADV7604_BUS_ORDER_##x]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) static const unsigned int op_ch_sel[6][6] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) _BUS(RGB) /* NOP */ = _SEL(GBR, GRB, BGR, RGB, BRG, RBG),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) _BUS(GRB) /* 1-2 */ = _SEL(BGR, RGB, GBR, GRB, RBG, BRG),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) _BUS(RBG) /* 2-3 */ = _SEL(GRB, GBR, BRG, RBG, BGR, RGB),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) _BUS(BGR) /* 1-3 */ = _SEL(RBG, BRG, RGB, BGR, GRB, GBR),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) _BUS(BRG) /* ROR */ = _SEL(BRG, RBG, GRB, GBR, RGB, BGR),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) _BUS(GBR) /* ROL */ = _SEL(RGB, BGR, RBG, BRG, GBR, GRB),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) return op_ch_sel[state->pdata.bus_order][state->format->op_ch_sel >> 5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) static void adv76xx_setup_format(struct adv76xx_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) struct v4l2_subdev *sd = &state->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) io_write_clr_set(sd, 0x02, 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) state->format->rgb_out ? ADV76XX_RGB_OUT : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) io_write(sd, 0x03, state->format->op_format_sel |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) state->pdata.op_format_mode_sel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) io_write_clr_set(sd, 0x04, 0xe0, adv76xx_op_ch_sel(state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) io_write_clr_set(sd, 0x05, 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) state->format->swap_cb_cr ? ADV76XX_OP_SWAP_CB_CR : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) set_rgb_quantization_range(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) static int adv76xx_get_format(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) struct v4l2_subdev_format *format)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) if (format->pad != state->source_pad)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) adv76xx_fill_format(state, &format->format);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) struct v4l2_mbus_framefmt *fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) fmt = v4l2_subdev_get_try_format(sd, cfg, format->pad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) format->format.code = fmt->code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) format->format.code = state->format->code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) static int adv76xx_get_selection(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) struct v4l2_subdev_selection *sel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) /* Only CROP, CROP_DEFAULT and CROP_BOUNDS are supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) if (sel->target > V4L2_SEL_TGT_CROP_BOUNDS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) sel->r.left = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) sel->r.top = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) sel->r.width = state->timings.bt.width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) sel->r.height = state->timings.bt.height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) static int adv76xx_set_format(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) struct v4l2_subdev_format *format)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) const struct adv76xx_format_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) if (format->pad != state->source_pad)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) info = adv76xx_format_info(state, format->format.code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) if (!info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) info = adv76xx_format_info(state, MEDIA_BUS_FMT_YUYV8_2X8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) adv76xx_fill_format(state, &format->format);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) format->format.code = info->code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) struct v4l2_mbus_framefmt *fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) fmt = v4l2_subdev_get_try_format(sd, cfg, format->pad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) fmt->code = format->format.code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) state->format = info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) adv76xx_setup_format(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) #if IS_ENABLED(CONFIG_VIDEO_ADV7604_CEC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) static void adv76xx_cec_tx_raw_status(struct v4l2_subdev *sd, u8 tx_raw_status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) if ((cec_read(sd, 0x11) & 0x01) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) v4l2_dbg(1, debug, sd, "%s: tx raw: tx disabled\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) if (tx_raw_status & 0x02) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) v4l2_dbg(1, debug, sd, "%s: tx raw: arbitration lost\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) cec_transmit_done(state->cec_adap, CEC_TX_STATUS_ARB_LOST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) 1, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) if (tx_raw_status & 0x04) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) u8 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) u8 nack_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) u8 low_drive_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) v4l2_dbg(1, debug, sd, "%s: tx raw: retry failed\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) * We set this status bit since this hardware performs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) * retransmissions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) status = CEC_TX_STATUS_MAX_RETRIES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) nack_cnt = cec_read(sd, 0x14) & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) if (nack_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) status |= CEC_TX_STATUS_NACK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) low_drive_cnt = cec_read(sd, 0x14) >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) if (low_drive_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) status |= CEC_TX_STATUS_LOW_DRIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) cec_transmit_done(state->cec_adap, status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) 0, nack_cnt, low_drive_cnt, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) if (tx_raw_status & 0x01) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) v4l2_dbg(1, debug, sd, "%s: tx raw: ready ok\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) cec_transmit_done(state->cec_adap, CEC_TX_STATUS_OK, 0, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) static void adv76xx_cec_isr(struct v4l2_subdev *sd, bool *handled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) const struct adv76xx_chip_info *info = state->info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) u8 cec_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) /* cec controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) cec_irq = io_read(sd, info->cec_irq_status) & 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) if (!cec_irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) v4l2_dbg(1, debug, sd, "%s: cec: irq 0x%x\n", __func__, cec_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) adv76xx_cec_tx_raw_status(sd, cec_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) if (cec_irq & 0x08) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) struct cec_msg msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) msg.len = cec_read(sd, 0x25) & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) if (msg.len > 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) msg.len = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) if (msg.len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) u8 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) for (i = 0; i < msg.len; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) msg.msg[i] = cec_read(sd, i + 0x15);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) cec_write(sd, info->cec_rx_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) info->cec_rx_enable_mask); /* re-enable rx */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) cec_received_msg(state->cec_adap, &msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) if (info->cec_irq_swap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) * Note: the bit order is swapped between 0x4d and 0x4e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) * on adv7604
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) cec_irq = ((cec_irq & 0x08) >> 3) | ((cec_irq & 0x04) >> 1) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) ((cec_irq & 0x02) << 1) | ((cec_irq & 0x01) << 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) io_write(sd, info->cec_irq_status + 1, cec_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) if (handled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) *handled = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) static int adv76xx_cec_adap_enable(struct cec_adapter *adap, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) struct adv76xx_state *state = cec_get_drvdata(adap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) const struct adv76xx_chip_info *info = state->info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) struct v4l2_subdev *sd = &state->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) if (!state->cec_enabled_adap && enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) cec_write_clr_set(sd, 0x2a, 0x01, 0x01); /* power up cec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) cec_write(sd, 0x2c, 0x01); /* cec soft reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) cec_write_clr_set(sd, 0x11, 0x01, 0); /* initially disable tx */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) /* enabled irqs: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) /* tx: ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) /* tx: arbitration lost */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) /* tx: retry timeout */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) /* rx: ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) io_write_clr_set(sd, info->cec_irq_status + 3, 0x0f, 0x0f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) cec_write(sd, info->cec_rx_enable, info->cec_rx_enable_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) } else if (state->cec_enabled_adap && !enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) /* disable cec interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) io_write_clr_set(sd, info->cec_irq_status + 3, 0x0f, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) /* disable address mask 1-3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) cec_write_clr_set(sd, 0x27, 0x70, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) /* power down cec section */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) cec_write_clr_set(sd, 0x2a, 0x01, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) state->cec_valid_addrs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) state->cec_enabled_adap = enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) adv76xx_s_detect_tx_5v_ctrl(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) static int adv76xx_cec_adap_log_addr(struct cec_adapter *adap, u8 addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) struct adv76xx_state *state = cec_get_drvdata(adap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) struct v4l2_subdev *sd = &state->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) unsigned int i, free_idx = ADV76XX_MAX_ADDRS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) if (!state->cec_enabled_adap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) return addr == CEC_LOG_ADDR_INVALID ? 0 : -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) if (addr == CEC_LOG_ADDR_INVALID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) cec_write_clr_set(sd, 0x27, 0x70, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) state->cec_valid_addrs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) for (i = 0; i < ADV76XX_MAX_ADDRS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) bool is_valid = state->cec_valid_addrs & (1 << i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) if (free_idx == ADV76XX_MAX_ADDRS && !is_valid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) free_idx = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) if (is_valid && state->cec_addr[i] == addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) if (i == ADV76XX_MAX_ADDRS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) i = free_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) if (i == ADV76XX_MAX_ADDRS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) state->cec_addr[i] = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) state->cec_valid_addrs |= 1 << i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) switch (i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) /* enable address mask 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) cec_write_clr_set(sd, 0x27, 0x10, 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) /* set address for mask 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) cec_write_clr_set(sd, 0x28, 0x0f, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) /* enable address mask 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) cec_write_clr_set(sd, 0x27, 0x20, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) /* set address for mask 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) cec_write_clr_set(sd, 0x28, 0xf0, addr << 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) /* enable address mask 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) cec_write_clr_set(sd, 0x27, 0x40, 0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) /* set address for mask 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) cec_write_clr_set(sd, 0x29, 0x0f, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) static int adv76xx_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) u32 signal_free_time, struct cec_msg *msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) struct adv76xx_state *state = cec_get_drvdata(adap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) struct v4l2_subdev *sd = &state->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) u8 len = msg->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) * The number of retries is the number of attempts - 1, but retry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) * at least once. It's not clear if a value of 0 is allowed, so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) * let's do at least one retry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) cec_write_clr_set(sd, 0x12, 0x70, max(1, attempts - 1) << 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) if (len > 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) v4l2_err(sd, "%s: len exceeded 16 (%d)\n", __func__, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) /* write data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) for (i = 0; i < len; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) cec_write(sd, i, msg->msg[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) /* set length (data + header) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) cec_write(sd, 0x10, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) /* start transmit, enable tx */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) cec_write(sd, 0x11, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) static const struct cec_adap_ops adv76xx_cec_adap_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) .adap_enable = adv76xx_cec_adap_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) .adap_log_addr = adv76xx_cec_adap_log_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) .adap_transmit = adv76xx_cec_adap_transmit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) static int adv76xx_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) const struct adv76xx_chip_info *info = state->info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) const u8 irq_reg_0x43 = io_read(sd, 0x43);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) const u8 irq_reg_0x6b = io_read(sd, 0x6b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) const u8 irq_reg_0x70 = io_read(sd, 0x70);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) u8 fmt_change_digital;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) u8 fmt_change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) u8 tx_5v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) if (irq_reg_0x43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) io_write(sd, 0x44, irq_reg_0x43);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) if (irq_reg_0x70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) io_write(sd, 0x71, irq_reg_0x70);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) if (irq_reg_0x6b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) io_write(sd, 0x6c, irq_reg_0x6b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) v4l2_dbg(2, debug, sd, "%s: ", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) /* format change */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) fmt_change = irq_reg_0x43 & 0x98;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) fmt_change_digital = is_digital_input(sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210) ? irq_reg_0x6b & info->fmt_change_digital_mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) if (fmt_change || fmt_change_digital) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) v4l2_dbg(1, debug, sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) "%s: fmt_change = 0x%x, fmt_change_digital = 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) __func__, fmt_change, fmt_change_digital);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) v4l2_subdev_notify_event(sd, &adv76xx_ev_fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) if (handled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) *handled = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) /* HDMI/DVI mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) if (irq_reg_0x6b & 0x01) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) v4l2_dbg(1, debug, sd, "%s: irq %s mode\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) (io_read(sd, 0x6a) & 0x01) ? "HDMI" : "DVI");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) set_rgb_quantization_range(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) if (handled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) *handled = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) #if IS_ENABLED(CONFIG_VIDEO_ADV7604_CEC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) /* cec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234) adv76xx_cec_isr(sd, handled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) /* tx 5v detect */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) tx_5v = irq_reg_0x70 & info->cable_det_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) if (tx_5v) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) v4l2_dbg(1, debug, sd, "%s: tx_5v: 0x%x\n", __func__, tx_5v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) adv76xx_s_detect_tx_5v_ctrl(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) if (handled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) *handled = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) static irqreturn_t adv76xx_irq_handler(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) struct adv76xx_state *state = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) bool handled = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) adv76xx_isr(&state->sd, 0, &handled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) return handled ? IRQ_HANDLED : IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) static int adv76xx_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) u8 *data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) memset(edid->reserved, 0, sizeof(edid->reserved));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) switch (edid->pad) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) case ADV76XX_PAD_HDMI_PORT_A:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) case ADV7604_PAD_HDMI_PORT_B:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) case ADV7604_PAD_HDMI_PORT_C:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) case ADV7604_PAD_HDMI_PORT_D:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) if (state->edid.present & (1 << edid->pad))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271) data = state->edid.edid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) if (edid->start_block == 0 && edid->blocks == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) edid->blocks = data ? state->edid.blocks : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) return -ENODATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) if (edid->start_block >= state->edid.blocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) if (edid->start_block + edid->blocks > state->edid.blocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) edid->blocks = state->edid.blocks - edid->start_block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) memcpy(edid->edid, data + edid->start_block * 128, edid->blocks * 128);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) static int adv76xx_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) const struct adv76xx_chip_info *info = state->info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) unsigned int spa_loc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) u16 pa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) memset(edid->reserved, 0, sizeof(edid->reserved));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) if (edid->pad > ADV7604_PAD_HDMI_PORT_D)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) if (edid->start_block != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) if (edid->blocks == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) /* Disable hotplug and I2C access to EDID RAM from DDC port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) state->edid.present &= ~(1 << edid->pad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) adv76xx_set_hpd(state, state->edid.present);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315) rep_write_clr_set(sd, info->edid_enable_reg, 0x0f, state->edid.present);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) /* Fall back to a 16:9 aspect ratio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) state->aspect_ratio.numerator = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) state->aspect_ratio.denominator = 9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) if (!state->edid.present) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) state->edid.blocks = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323) cec_phys_addr_invalidate(state->cec_adap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326) v4l2_dbg(2, debug, sd, "%s: clear EDID pad %d, edid.present = 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) __func__, edid->pad, state->edid.present);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330) if (edid->blocks > 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) edid->blocks = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332) return -E2BIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) pa = v4l2_get_edid_phys_addr(edid->edid, edid->blocks * 128, &spa_loc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) err = v4l2_phys_addr_validate(pa, &pa, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) v4l2_dbg(2, debug, sd, "%s: write EDID pad %d, edid.present = 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) __func__, edid->pad, state->edid.present);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) /* Disable hotplug and I2C access to EDID RAM from DDC port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) cancel_delayed_work_sync(&state->delayed_work_enable_hotplug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) adv76xx_set_hpd(state, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345) rep_write_clr_set(sd, info->edid_enable_reg, 0x0f, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) * Return an error if no location of the source physical address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) * was found.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351) if (spa_loc == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) switch (edid->pad) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355) case ADV76XX_PAD_HDMI_PORT_A:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) state->spa_port_a[0] = edid->edid[spa_loc];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357) state->spa_port_a[1] = edid->edid[spa_loc + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359) case ADV7604_PAD_HDMI_PORT_B:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360) rep_write(sd, 0x70, edid->edid[spa_loc]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) rep_write(sd, 0x71, edid->edid[spa_loc + 1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363) case ADV7604_PAD_HDMI_PORT_C:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364) rep_write(sd, 0x72, edid->edid[spa_loc]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) rep_write(sd, 0x73, edid->edid[spa_loc + 1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367) case ADV7604_PAD_HDMI_PORT_D:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) rep_write(sd, 0x74, edid->edid[spa_loc]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369) rep_write(sd, 0x75, edid->edid[spa_loc + 1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) if (info->type == ADV7604) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376) rep_write(sd, 0x76, spa_loc & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377) rep_write_clr_set(sd, 0x77, 0x40, (spa_loc & 0x100) >> 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) /* ADV7612 Software Manual Rev. A, p. 15 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380) rep_write(sd, 0x70, spa_loc & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381) rep_write_clr_set(sd, 0x71, 0x01, (spa_loc & 0x100) >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384) edid->edid[spa_loc] = state->spa_port_a[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385) edid->edid[spa_loc + 1] = state->spa_port_a[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387) memcpy(state->edid.edid, edid->edid, 128 * edid->blocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388) state->edid.blocks = edid->blocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389) state->aspect_ratio = v4l2_calc_aspect_ratio(edid->edid[0x15],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) edid->edid[0x16]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391) state->edid.present |= 1 << edid->pad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393) err = edid_write_block(sd, 128 * edid->blocks, state->edid.edid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395) v4l2_err(sd, "error %d writing edid pad %d\n", err, edid->pad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399) /* adv76xx calculates the checksums and enables I2C access to internal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400) EDID RAM from DDC port. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401) rep_write_clr_set(sd, info->edid_enable_reg, 0x0f, state->edid.present);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403) for (i = 0; i < 1000; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404) if (rep_read(sd, info->edid_status_reg) & state->edid.present)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406) mdelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) if (i == 1000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409) v4l2_err(sd, "error enabling edid (0x%x)\n", state->edid.present);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412) cec_s_phys_addr(state->cec_adap, pa, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414) /* enable hotplug after 100 ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415) schedule_delayed_work(&state->delayed_work_enable_hotplug, HZ / 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419) /*********** avi info frame CEA-861-E **************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421) static const struct adv76xx_cfg_read_infoframe adv76xx_cri[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422) { "AVI", 0x01, 0xe0, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423) { "Audio", 0x02, 0xe3, 0x1c },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424) { "SDP", 0x04, 0xe6, 0x2a },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425) { "Vendor", 0x10, 0xec, 0x54 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428) static int adv76xx_read_infoframe(struct v4l2_subdev *sd, int index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429) union hdmi_infoframe *frame)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431) uint8_t buffer[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432) u8 len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435) if (!(io_read(sd, 0x60) & adv76xx_cri[index].present_mask)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436) v4l2_info(sd, "%s infoframe not received\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437) adv76xx_cri[index].desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) for (i = 0; i < 3; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442) buffer[i] = infoframe_read(sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443) adv76xx_cri[index].head_addr + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445) len = buffer[2] + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447) if (len + 3 > sizeof(buffer)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) v4l2_err(sd, "%s: invalid %s infoframe length %d\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449) adv76xx_cri[index].desc, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453) for (i = 0; i < len; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454) buffer[i + 3] = infoframe_read(sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455) adv76xx_cri[index].payload_addr + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457) if (hdmi_infoframe_unpack(frame, buffer, len + 3) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458) v4l2_err(sd, "%s: unpack of %s infoframe failed\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459) adv76xx_cri[index].desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2465) static void adv76xx_log_infoframes(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2466) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2467) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2469) if (!is_hdmi(sd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2470) v4l2_info(sd, "receive DVI-D signal, no infoframes\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2471) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2474) for (i = 0; i < ARRAY_SIZE(adv76xx_cri); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2475) union hdmi_infoframe frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2476) struct i2c_client *client = v4l2_get_subdevdata(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2478) if (adv76xx_read_infoframe(sd, i, &frame))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2479) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2480) hdmi_infoframe_log(KERN_INFO, &client->dev, &frame);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2484) static int adv76xx_log_status(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2485) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2486) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2487) const struct adv76xx_chip_info *info = state->info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2488) struct v4l2_dv_timings timings;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2489) struct stdi_readback stdi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2490) u8 reg_io_0x02 = io_read(sd, 0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2491) u8 edid_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2492) u8 cable_det;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2494) static const char * const csc_coeff_sel_rb[16] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2495) "bypassed", "YPbPr601 -> RGB", "reserved", "YPbPr709 -> RGB",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2496) "reserved", "RGB -> YPbPr601", "reserved", "RGB -> YPbPr709",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2497) "reserved", "YPbPr709 -> YPbPr601", "YPbPr601 -> YPbPr709",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2498) "reserved", "reserved", "reserved", "reserved", "manual"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2499) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2500) static const char * const input_color_space_txt[16] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2501) "RGB limited range (16-235)", "RGB full range (0-255)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2502) "YCbCr Bt.601 (16-235)", "YCbCr Bt.709 (16-235)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2503) "xvYCC Bt.601", "xvYCC Bt.709",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2504) "YCbCr Bt.601 (0-255)", "YCbCr Bt.709 (0-255)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2505) "invalid", "invalid", "invalid", "invalid", "invalid",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2506) "invalid", "invalid", "automatic"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2507) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2508) static const char * const hdmi_color_space_txt[16] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2509) "RGB limited range (16-235)", "RGB full range (0-255)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2510) "YCbCr Bt.601 (16-235)", "YCbCr Bt.709 (16-235)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2511) "xvYCC Bt.601", "xvYCC Bt.709",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2512) "YCbCr Bt.601 (0-255)", "YCbCr Bt.709 (0-255)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2513) "sYCC", "opYCC 601", "opRGB", "invalid", "invalid",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2514) "invalid", "invalid", "invalid"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2515) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2516) static const char * const rgb_quantization_range_txt[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2517) "Automatic",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2518) "RGB limited range (16-235)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2519) "RGB full range (0-255)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2520) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2521) static const char * const deep_color_mode_txt[4] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2522) "8-bits per channel",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2523) "10-bits per channel",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2524) "12-bits per channel",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2525) "16-bits per channel (not supported)"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2526) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2528) v4l2_info(sd, "-----Chip status-----\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2529) v4l2_info(sd, "Chip power: %s\n", no_power(sd) ? "off" : "on");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2530) edid_enabled = rep_read(sd, info->edid_status_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2531) v4l2_info(sd, "EDID enabled port A: %s, B: %s, C: %s, D: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2532) ((edid_enabled & 0x01) ? "Yes" : "No"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2533) ((edid_enabled & 0x02) ? "Yes" : "No"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2534) ((edid_enabled & 0x04) ? "Yes" : "No"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2535) ((edid_enabled & 0x08) ? "Yes" : "No"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2536) v4l2_info(sd, "CEC: %s\n", state->cec_enabled_adap ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2537) "enabled" : "disabled");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2538) if (state->cec_enabled_adap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2539) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2541) for (i = 0; i < ADV76XX_MAX_ADDRS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2542) bool is_valid = state->cec_valid_addrs & (1 << i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2544) if (is_valid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2545) v4l2_info(sd, "CEC Logical Address: 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2546) state->cec_addr[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2550) v4l2_info(sd, "-----Signal status-----\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2551) cable_det = info->read_cable_det(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2552) v4l2_info(sd, "Cable detected (+5V power) port A: %s, B: %s, C: %s, D: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2553) ((cable_det & 0x01) ? "Yes" : "No"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2554) ((cable_det & 0x02) ? "Yes" : "No"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2555) ((cable_det & 0x04) ? "Yes" : "No"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2556) ((cable_det & 0x08) ? "Yes" : "No"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2557) v4l2_info(sd, "TMDS signal detected: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2558) no_signal_tmds(sd) ? "false" : "true");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2559) v4l2_info(sd, "TMDS signal locked: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2560) no_lock_tmds(sd) ? "false" : "true");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2561) v4l2_info(sd, "SSPD locked: %s\n", no_lock_sspd(sd) ? "false" : "true");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2562) v4l2_info(sd, "STDI locked: %s\n", no_lock_stdi(sd) ? "false" : "true");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2563) v4l2_info(sd, "CP locked: %s\n", no_lock_cp(sd) ? "false" : "true");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2564) v4l2_info(sd, "CP free run: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2565) (in_free_run(sd)) ? "on" : "off");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2566) v4l2_info(sd, "Prim-mode = 0x%x, video std = 0x%x, v_freq = 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2567) io_read(sd, 0x01) & 0x0f, io_read(sd, 0x00) & 0x3f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2568) (io_read(sd, 0x01) & 0x70) >> 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2570) v4l2_info(sd, "-----Video Timings-----\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2571) if (read_stdi(sd, &stdi))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2572) v4l2_info(sd, "STDI: not locked\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2573) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2574) v4l2_info(sd, "STDI: lcf (frame height - 1) = %d, bl = %d, lcvs (vsync) = %d, %s, %chsync, %cvsync\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2575) stdi.lcf, stdi.bl, stdi.lcvs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2576) stdi.interlaced ? "interlaced" : "progressive",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2577) stdi.hs_pol, stdi.vs_pol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2578) if (adv76xx_query_dv_timings(sd, &timings))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2579) v4l2_info(sd, "No video detected\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2580) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2581) v4l2_print_dv_timings(sd->name, "Detected format: ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2582) &timings, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2583) v4l2_print_dv_timings(sd->name, "Configured format: ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2584) &state->timings, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2586) if (no_signal(sd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2587) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2589) v4l2_info(sd, "-----Color space-----\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2590) v4l2_info(sd, "RGB quantization range ctrl: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2591) rgb_quantization_range_txt[state->rgb_quantization_range]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2592) v4l2_info(sd, "Input color space: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2593) input_color_space_txt[reg_io_0x02 >> 4]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2594) v4l2_info(sd, "Output color space: %s %s, alt-gamma %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2595) (reg_io_0x02 & 0x02) ? "RGB" : "YCbCr",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2596) (((reg_io_0x02 >> 2) & 0x01) ^ (reg_io_0x02 & 0x01)) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2597) "(16-235)" : "(0-255)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2598) (reg_io_0x02 & 0x08) ? "enabled" : "disabled");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2599) v4l2_info(sd, "Color space conversion: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2600) csc_coeff_sel_rb[cp_read(sd, info->cp_csc) >> 4]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2602) if (!is_digital_input(sd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2603) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2605) v4l2_info(sd, "-----%s status-----\n", is_hdmi(sd) ? "HDMI" : "DVI-D");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2606) v4l2_info(sd, "Digital video port selected: %c\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2607) (hdmi_read(sd, 0x00) & 0x03) + 'A');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2608) v4l2_info(sd, "HDCP encrypted content: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2609) (hdmi_read(sd, 0x05) & 0x40) ? "true" : "false");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2610) v4l2_info(sd, "HDCP keys read: %s%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2611) (hdmi_read(sd, 0x04) & 0x20) ? "yes" : "no",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2612) (hdmi_read(sd, 0x04) & 0x10) ? "ERROR" : "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2613) if (is_hdmi(sd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2614) bool audio_pll_locked = hdmi_read(sd, 0x04) & 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2615) bool audio_sample_packet_detect = hdmi_read(sd, 0x18) & 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2616) bool audio_mute = io_read(sd, 0x65) & 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2618) v4l2_info(sd, "Audio: pll %s, samples %s, %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2619) audio_pll_locked ? "locked" : "not locked",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2620) audio_sample_packet_detect ? "detected" : "not detected",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2621) audio_mute ? "muted" : "enabled");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2622) if (audio_pll_locked && audio_sample_packet_detect) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2623) v4l2_info(sd, "Audio format: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2624) (hdmi_read(sd, 0x07) & 0x20) ? "multi-channel" : "stereo");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2626) v4l2_info(sd, "Audio CTS: %u\n", (hdmi_read(sd, 0x5b) << 12) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2627) (hdmi_read(sd, 0x5c) << 8) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2628) (hdmi_read(sd, 0x5d) & 0xf0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2629) v4l2_info(sd, "Audio N: %u\n", ((hdmi_read(sd, 0x5d) & 0x0f) << 16) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2630) (hdmi_read(sd, 0x5e) << 8) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2631) hdmi_read(sd, 0x5f));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2632) v4l2_info(sd, "AV Mute: %s\n", (hdmi_read(sd, 0x04) & 0x40) ? "on" : "off");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2634) v4l2_info(sd, "Deep color mode: %s\n", deep_color_mode_txt[(hdmi_read(sd, 0x0b) & 0x60) >> 5]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2635) v4l2_info(sd, "HDMI colorspace: %s\n", hdmi_color_space_txt[hdmi_read(sd, 0x53) & 0xf]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2637) adv76xx_log_infoframes(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2640) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2643) static int adv76xx_subscribe_event(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2644) struct v4l2_fh *fh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2645) struct v4l2_event_subscription *sub)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2646) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2647) switch (sub->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2648) case V4L2_EVENT_SOURCE_CHANGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2649) return v4l2_src_change_event_subdev_subscribe(sd, fh, sub);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2650) case V4L2_EVENT_CTRL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2651) return v4l2_ctrl_subdev_subscribe_event(sd, fh, sub);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2652) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2653) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2654) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2655) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2657) static int adv76xx_registered(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2658) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2659) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2660) struct i2c_client *client = v4l2_get_subdevdata(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2661) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2663) err = cec_register_adapter(state->cec_adap, &client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2664) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2665) cec_delete_adapter(state->cec_adap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2666) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2667) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2669) static void adv76xx_unregistered(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2670) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2671) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2673) cec_unregister_adapter(state->cec_adap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2674) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2676) /* ----------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2678) static const struct v4l2_ctrl_ops adv76xx_ctrl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2679) .s_ctrl = adv76xx_s_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2680) .g_volatile_ctrl = adv76xx_g_volatile_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2681) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2683) static const struct v4l2_subdev_core_ops adv76xx_core_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2684) .log_status = adv76xx_log_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2685) .interrupt_service_routine = adv76xx_isr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2686) .subscribe_event = adv76xx_subscribe_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2687) .unsubscribe_event = v4l2_event_subdev_unsubscribe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2688) #ifdef CONFIG_VIDEO_ADV_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2689) .g_register = adv76xx_g_register,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2690) .s_register = adv76xx_s_register,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2691) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2692) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2694) static const struct v4l2_subdev_video_ops adv76xx_video_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2695) .s_routing = adv76xx_s_routing,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2696) .g_input_status = adv76xx_g_input_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2697) .s_dv_timings = adv76xx_s_dv_timings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2698) .g_dv_timings = adv76xx_g_dv_timings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2699) .query_dv_timings = adv76xx_query_dv_timings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2700) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2702) static const struct v4l2_subdev_pad_ops adv76xx_pad_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2703) .enum_mbus_code = adv76xx_enum_mbus_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2704) .get_selection = adv76xx_get_selection,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2705) .get_fmt = adv76xx_get_format,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2706) .set_fmt = adv76xx_set_format,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2707) .get_edid = adv76xx_get_edid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2708) .set_edid = adv76xx_set_edid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2709) .dv_timings_cap = adv76xx_dv_timings_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2710) .enum_dv_timings = adv76xx_enum_dv_timings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2711) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2713) static const struct v4l2_subdev_ops adv76xx_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2714) .core = &adv76xx_core_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2715) .video = &adv76xx_video_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2716) .pad = &adv76xx_pad_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2717) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2719) static const struct v4l2_subdev_internal_ops adv76xx_int_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2720) .registered = adv76xx_registered,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2721) .unregistered = adv76xx_unregistered,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2722) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2724) /* -------------------------- custom ctrls ---------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2726) static const struct v4l2_ctrl_config adv7604_ctrl_analog_sampling_phase = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2727) .ops = &adv76xx_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2728) .id = V4L2_CID_ADV_RX_ANALOG_SAMPLING_PHASE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2729) .name = "Analog Sampling Phase",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2730) .type = V4L2_CTRL_TYPE_INTEGER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2731) .min = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2732) .max = 0x1f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2733) .step = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2734) .def = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2735) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2737) static const struct v4l2_ctrl_config adv76xx_ctrl_free_run_color_manual = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2738) .ops = &adv76xx_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2739) .id = V4L2_CID_ADV_RX_FREE_RUN_COLOR_MANUAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2740) .name = "Free Running Color, Manual",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2741) .type = V4L2_CTRL_TYPE_BOOLEAN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2742) .min = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2743) .max = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2744) .step = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2745) .def = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2746) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2748) static const struct v4l2_ctrl_config adv76xx_ctrl_free_run_color = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2749) .ops = &adv76xx_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2750) .id = V4L2_CID_ADV_RX_FREE_RUN_COLOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2751) .name = "Free Running Color",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2752) .type = V4L2_CTRL_TYPE_INTEGER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2753) .min = 0x0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2754) .max = 0xffffff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2755) .step = 0x1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2756) .def = 0x0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2757) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2759) /* ----------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2761) struct adv76xx_register_map {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2762) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2763) u8 default_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2764) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2766) static const struct adv76xx_register_map adv76xx_default_addresses[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2767) [ADV76XX_PAGE_IO] = { "main", 0x4c },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2768) [ADV7604_PAGE_AVLINK] = { "avlink", 0x42 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2769) [ADV76XX_PAGE_CEC] = { "cec", 0x40 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2770) [ADV76XX_PAGE_INFOFRAME] = { "infoframe", 0x3e },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2771) [ADV7604_PAGE_ESDP] = { "esdp", 0x38 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2772) [ADV7604_PAGE_DPP] = { "dpp", 0x3c },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2773) [ADV76XX_PAGE_AFE] = { "afe", 0x26 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2774) [ADV76XX_PAGE_REP] = { "rep", 0x32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2775) [ADV76XX_PAGE_EDID] = { "edid", 0x36 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2776) [ADV76XX_PAGE_HDMI] = { "hdmi", 0x34 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2777) [ADV76XX_PAGE_TEST] = { "test", 0x30 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2778) [ADV76XX_PAGE_CP] = { "cp", 0x22 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2779) [ADV7604_PAGE_VDP] = { "vdp", 0x24 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2780) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2782) static int adv76xx_core_init(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2783) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2784) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2785) const struct adv76xx_chip_info *info = state->info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2786) struct adv76xx_platform_data *pdata = &state->pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2788) hdmi_write(sd, 0x48,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2789) (pdata->disable_pwrdnb ? 0x80 : 0) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2790) (pdata->disable_cable_det_rst ? 0x40 : 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2792) disable_input(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2794) if (pdata->default_input >= 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2795) pdata->default_input < state->source_pad) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2796) state->selected_input = pdata->default_input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2797) select_input(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2798) enable_input(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2799) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2801) /* power */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2802) io_write(sd, 0x0c, 0x42); /* Power up part and power down VDP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2803) io_write(sd, 0x0b, 0x44); /* Power down ESDP block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2804) cp_write(sd, 0xcf, 0x01); /* Power down macrovision */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2806) /* video format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2807) io_write_clr_set(sd, 0x02, 0x0f, pdata->alt_gamma << 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2808) io_write_clr_set(sd, 0x05, 0x0e, pdata->blank_data << 3 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2809) pdata->insert_av_codes << 2 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2810) pdata->replicate_av_codes << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2811) adv76xx_setup_format(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2813) cp_write(sd, 0x69, 0x30); /* Enable CP CSC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2815) /* VS, HS polarities */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2816) io_write(sd, 0x06, 0xa0 | pdata->inv_vs_pol << 2 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2817) pdata->inv_hs_pol << 1 | pdata->inv_llc_pol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2819) /* Adjust drive strength */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2820) io_write(sd, 0x14, 0x40 | pdata->dr_str_data << 4 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2821) pdata->dr_str_clk << 2 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2822) pdata->dr_str_sync);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2824) cp_write(sd, 0xba, (pdata->hdmi_free_run_mode << 1) | 0x01); /* HDMI free run */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2825) cp_write(sd, 0xf3, 0xdc); /* Low threshold to enter/exit free run mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2826) cp_write(sd, 0xf9, 0x23); /* STDI ch. 1 - LCVS change threshold -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2827) ADI recommended setting [REF_01, c. 2.3.3] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2828) cp_write(sd, 0x45, 0x23); /* STDI ch. 2 - LCVS change threshold -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2829) ADI recommended setting [REF_01, c. 2.3.3] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2830) cp_write(sd, 0xc9, 0x2d); /* use prim_mode and vid_std as free run resolution
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2831) for digital formats */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2833) /* HDMI audio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2834) hdmi_write_clr_set(sd, 0x15, 0x03, 0x03); /* Mute on FIFO over-/underflow [REF_01, c. 1.2.18] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2835) hdmi_write_clr_set(sd, 0x1a, 0x0e, 0x08); /* Wait 1 s before unmute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2836) hdmi_write_clr_set(sd, 0x68, 0x06, 0x06); /* FIFO reset on over-/underflow [REF_01, c. 1.2.19] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2838) /* TODO from platform data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2839) afe_write(sd, 0xb5, 0x01); /* Setting MCLK to 256Fs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2841) if (adv76xx_has_afe(state)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2842) afe_write(sd, 0x02, pdata->ain_sel); /* Select analog input muxing mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2843) io_write_clr_set(sd, 0x30, 1 << 4, pdata->output_bus_lsb_to_msb << 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2844) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2846) /* interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2847) io_write(sd, 0x40, 0xc0 | pdata->int1_config); /* Configure INT1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2848) io_write(sd, 0x46, 0x98); /* Enable SSPD, STDI and CP unlocked interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2849) io_write(sd, 0x6e, info->fmt_change_digital_mask); /* Enable V_LOCKED and DE_REGEN_LCK interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2850) io_write(sd, 0x73, info->cable_det_mask); /* Enable cable detection (+5v) interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2851) info->setup_irqs(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2853) return v4l2_ctrl_handler_setup(sd->ctrl_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2854) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2856) static void adv7604_setup_irqs(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2857) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2858) io_write(sd, 0x41, 0xd7); /* STDI irq for any change, disable INT2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2859) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2861) static void adv7611_setup_irqs(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2862) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2863) io_write(sd, 0x41, 0xd0); /* STDI irq for any change, disable INT2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2864) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2866) static void adv7612_setup_irqs(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2867) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2868) io_write(sd, 0x41, 0xd0); /* disable INT2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2869) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2871) static void adv76xx_unregister_clients(struct adv76xx_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2872) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2873) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2875) for (i = 1; i < ARRAY_SIZE(state->i2c_clients); ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2876) i2c_unregister_device(state->i2c_clients[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2877) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2879) static struct i2c_client *adv76xx_dummy_client(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2880) unsigned int page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2881) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2882) struct i2c_client *client = v4l2_get_subdevdata(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2883) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2884) struct adv76xx_platform_data *pdata = &state->pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2885) unsigned int io_reg = 0xf2 + page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2886) struct i2c_client *new_client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2888) if (pdata && pdata->i2c_addresses[page])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2889) new_client = i2c_new_dummy_device(client->adapter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2890) pdata->i2c_addresses[page]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2891) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2892) new_client = i2c_new_ancillary_device(client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2893) adv76xx_default_addresses[page].name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2894) adv76xx_default_addresses[page].default_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2896) if (!IS_ERR(new_client))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2897) io_write(sd, io_reg, new_client->addr << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2899) return new_client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2900) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2902) static const struct adv76xx_reg_seq adv7604_recommended_settings_afe[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2903) /* reset ADI recommended settings for HDMI: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2904) /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2905) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x0d), 0x04 }, /* HDMI filter optimization */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2906) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x0d), 0x04 }, /* HDMI filter optimization */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2907) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x3d), 0x00 }, /* DDC bus active pull-up control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2908) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x3e), 0x74 }, /* TMDS PLL optimization */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2909) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x4e), 0x3b }, /* TMDS PLL optimization */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2910) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x57), 0x74 }, /* TMDS PLL optimization */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2911) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x58), 0x63 }, /* TMDS PLL optimization */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2912) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x8d), 0x18 }, /* equaliser */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2913) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x8e), 0x34 }, /* equaliser */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2914) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x93), 0x88 }, /* equaliser */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2915) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x94), 0x2e }, /* equaliser */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2916) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x96), 0x00 }, /* enable automatic EQ changing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2918) /* set ADI recommended settings for digitizer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2919) /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 17. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2920) { ADV76XX_REG(ADV76XX_PAGE_AFE, 0x12), 0x7b }, /* ADC noise shaping filter controls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2921) { ADV76XX_REG(ADV76XX_PAGE_AFE, 0x0c), 0x1f }, /* CP core gain controls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2922) { ADV76XX_REG(ADV76XX_PAGE_CP, 0x3e), 0x04 }, /* CP core pre-gain control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2923) { ADV76XX_REG(ADV76XX_PAGE_CP, 0xc3), 0x39 }, /* CP coast control. Graphics mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2924) { ADV76XX_REG(ADV76XX_PAGE_CP, 0x40), 0x5c }, /* CP core pre-gain control. Graphics mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2926) { ADV76XX_REG_SEQ_TERM, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2927) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2929) static const struct adv76xx_reg_seq adv7604_recommended_settings_hdmi[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2930) /* set ADI recommended settings for HDMI: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2931) /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2932) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x0d), 0x84 }, /* HDMI filter optimization */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2933) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x3d), 0x10 }, /* DDC bus active pull-up control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2934) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x3e), 0x39 }, /* TMDS PLL optimization */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2935) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x4e), 0x3b }, /* TMDS PLL optimization */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2936) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x57), 0xb6 }, /* TMDS PLL optimization */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2937) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x58), 0x03 }, /* TMDS PLL optimization */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2938) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x8d), 0x18 }, /* equaliser */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2939) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x8e), 0x34 }, /* equaliser */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2940) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x93), 0x8b }, /* equaliser */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2941) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x94), 0x2d }, /* equaliser */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2942) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x96), 0x01 }, /* enable automatic EQ changing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2944) /* reset ADI recommended settings for digitizer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2945) /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 17. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2946) { ADV76XX_REG(ADV76XX_PAGE_AFE, 0x12), 0xfb }, /* ADC noise shaping filter controls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2947) { ADV76XX_REG(ADV76XX_PAGE_AFE, 0x0c), 0x0d }, /* CP core gain controls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2949) { ADV76XX_REG_SEQ_TERM, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2950) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2952) static const struct adv76xx_reg_seq adv7611_recommended_settings_hdmi[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2953) /* ADV7611 Register Settings Recommendations Rev 1.5, May 2014 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2954) { ADV76XX_REG(ADV76XX_PAGE_CP, 0x6c), 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2955) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x9b), 0x03 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2956) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x6f), 0x08 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2957) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x85), 0x1f },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2958) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x87), 0x70 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2959) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x57), 0xda },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2960) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x58), 0x01 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2961) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x03), 0x98 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2962) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x4c), 0x44 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2963) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x8d), 0x04 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2964) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x8e), 0x1e },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2966) { ADV76XX_REG_SEQ_TERM, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2967) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2969) static const struct adv76xx_reg_seq adv7612_recommended_settings_hdmi[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2970) { ADV76XX_REG(ADV76XX_PAGE_CP, 0x6c), 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2971) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x9b), 0x03 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2972) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x6f), 0x08 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2973) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x85), 0x1f },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2974) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x87), 0x70 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2975) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x57), 0xda },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2976) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x58), 0x01 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2977) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x03), 0x98 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2978) { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x4c), 0x44 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2979) { ADV76XX_REG_SEQ_TERM, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2980) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2982) static const struct adv76xx_chip_info adv76xx_chip_info[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2983) [ADV7604] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2984) .type = ADV7604,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2985) .has_afe = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2986) .max_port = ADV7604_PAD_VGA_COMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2987) .num_dv_ports = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2988) .edid_enable_reg = 0x77,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2989) .edid_status_reg = 0x7d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2990) .lcf_reg = 0xb3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2991) .tdms_lock_mask = 0xe0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2992) .cable_det_mask = 0x1e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2993) .fmt_change_digital_mask = 0xc1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2994) .cp_csc = 0xfc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2995) .cec_irq_status = 0x4d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2996) .cec_rx_enable = 0x26,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2997) .cec_rx_enable_mask = 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2998) .cec_irq_swap = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2999) .formats = adv7604_formats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3000) .nformats = ARRAY_SIZE(adv7604_formats),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3001) .set_termination = adv7604_set_termination,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3002) .setup_irqs = adv7604_setup_irqs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3003) .read_hdmi_pixelclock = adv7604_read_hdmi_pixelclock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3004) .read_cable_det = adv7604_read_cable_det,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3005) .recommended_settings = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3006) [0] = adv7604_recommended_settings_afe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3007) [1] = adv7604_recommended_settings_hdmi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3008) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3009) .num_recommended_settings = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3010) [0] = ARRAY_SIZE(adv7604_recommended_settings_afe),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3011) [1] = ARRAY_SIZE(adv7604_recommended_settings_hdmi),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3012) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3013) .page_mask = BIT(ADV76XX_PAGE_IO) | BIT(ADV7604_PAGE_AVLINK) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3014) BIT(ADV76XX_PAGE_CEC) | BIT(ADV76XX_PAGE_INFOFRAME) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3015) BIT(ADV7604_PAGE_ESDP) | BIT(ADV7604_PAGE_DPP) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3016) BIT(ADV76XX_PAGE_AFE) | BIT(ADV76XX_PAGE_REP) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3017) BIT(ADV76XX_PAGE_EDID) | BIT(ADV76XX_PAGE_HDMI) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3018) BIT(ADV76XX_PAGE_TEST) | BIT(ADV76XX_PAGE_CP) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3019) BIT(ADV7604_PAGE_VDP),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3020) .linewidth_mask = 0xfff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3021) .field0_height_mask = 0xfff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3022) .field1_height_mask = 0xfff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3023) .hfrontporch_mask = 0x3ff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3024) .hsync_mask = 0x3ff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3025) .hbackporch_mask = 0x3ff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3026) .field0_vfrontporch_mask = 0x1fff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3027) .field0_vsync_mask = 0x1fff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3028) .field0_vbackporch_mask = 0x1fff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3029) .field1_vfrontporch_mask = 0x1fff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3030) .field1_vsync_mask = 0x1fff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3031) .field1_vbackporch_mask = 0x1fff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3032) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3033) [ADV7611] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3034) .type = ADV7611,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3035) .has_afe = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3036) .max_port = ADV76XX_PAD_HDMI_PORT_A,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3037) .num_dv_ports = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3038) .edid_enable_reg = 0x74,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3039) .edid_status_reg = 0x76,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3040) .lcf_reg = 0xa3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3041) .tdms_lock_mask = 0x43,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3042) .cable_det_mask = 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3043) .fmt_change_digital_mask = 0x03,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3044) .cp_csc = 0xf4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3045) .cec_irq_status = 0x93,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3046) .cec_rx_enable = 0x2c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3047) .cec_rx_enable_mask = 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3048) .formats = adv7611_formats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3049) .nformats = ARRAY_SIZE(adv7611_formats),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3050) .set_termination = adv7611_set_termination,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3051) .setup_irqs = adv7611_setup_irqs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3052) .read_hdmi_pixelclock = adv7611_read_hdmi_pixelclock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3053) .read_cable_det = adv7611_read_cable_det,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3054) .recommended_settings = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3055) [1] = adv7611_recommended_settings_hdmi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3056) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3057) .num_recommended_settings = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3058) [1] = ARRAY_SIZE(adv7611_recommended_settings_hdmi),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3059) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3060) .page_mask = BIT(ADV76XX_PAGE_IO) | BIT(ADV76XX_PAGE_CEC) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3061) BIT(ADV76XX_PAGE_INFOFRAME) | BIT(ADV76XX_PAGE_AFE) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3062) BIT(ADV76XX_PAGE_REP) | BIT(ADV76XX_PAGE_EDID) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3063) BIT(ADV76XX_PAGE_HDMI) | BIT(ADV76XX_PAGE_CP),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3064) .linewidth_mask = 0x1fff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3065) .field0_height_mask = 0x1fff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3066) .field1_height_mask = 0x1fff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3067) .hfrontporch_mask = 0x1fff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3068) .hsync_mask = 0x1fff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3069) .hbackporch_mask = 0x1fff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3070) .field0_vfrontporch_mask = 0x3fff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3071) .field0_vsync_mask = 0x3fff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3072) .field0_vbackporch_mask = 0x3fff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3073) .field1_vfrontporch_mask = 0x3fff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3074) .field1_vsync_mask = 0x3fff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3075) .field1_vbackporch_mask = 0x3fff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3076) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3077) [ADV7612] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3078) .type = ADV7612,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3079) .has_afe = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3080) .max_port = ADV76XX_PAD_HDMI_PORT_A, /* B not supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3081) .num_dv_ports = 1, /* normally 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3082) .edid_enable_reg = 0x74,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3083) .edid_status_reg = 0x76,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3084) .lcf_reg = 0xa3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3085) .tdms_lock_mask = 0x43,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3086) .cable_det_mask = 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3087) .fmt_change_digital_mask = 0x03,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3088) .cp_csc = 0xf4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3089) .cec_irq_status = 0x93,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3090) .cec_rx_enable = 0x2c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3091) .cec_rx_enable_mask = 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3092) .formats = adv7612_formats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3093) .nformats = ARRAY_SIZE(adv7612_formats),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3094) .set_termination = adv7611_set_termination,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3095) .setup_irqs = adv7612_setup_irqs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3096) .read_hdmi_pixelclock = adv7611_read_hdmi_pixelclock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3097) .read_cable_det = adv7612_read_cable_det,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3098) .recommended_settings = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3099) [1] = adv7612_recommended_settings_hdmi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3100) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3101) .num_recommended_settings = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3102) [1] = ARRAY_SIZE(adv7612_recommended_settings_hdmi),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3103) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3104) .page_mask = BIT(ADV76XX_PAGE_IO) | BIT(ADV76XX_PAGE_CEC) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3105) BIT(ADV76XX_PAGE_INFOFRAME) | BIT(ADV76XX_PAGE_AFE) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3106) BIT(ADV76XX_PAGE_REP) | BIT(ADV76XX_PAGE_EDID) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3107) BIT(ADV76XX_PAGE_HDMI) | BIT(ADV76XX_PAGE_CP),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3108) .linewidth_mask = 0x1fff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3109) .field0_height_mask = 0x1fff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3110) .field1_height_mask = 0x1fff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3111) .hfrontporch_mask = 0x1fff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3112) .hsync_mask = 0x1fff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3113) .hbackporch_mask = 0x1fff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3114) .field0_vfrontporch_mask = 0x3fff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3115) .field0_vsync_mask = 0x3fff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3116) .field0_vbackporch_mask = 0x3fff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3117) .field1_vfrontporch_mask = 0x3fff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3118) .field1_vsync_mask = 0x3fff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3119) .field1_vbackporch_mask = 0x3fff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3120) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3121) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3123) static const struct i2c_device_id adv76xx_i2c_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3124) { "adv7604", (kernel_ulong_t)&adv76xx_chip_info[ADV7604] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3125) { "adv7611", (kernel_ulong_t)&adv76xx_chip_info[ADV7611] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3126) { "adv7612", (kernel_ulong_t)&adv76xx_chip_info[ADV7612] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3127) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3128) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3129) MODULE_DEVICE_TABLE(i2c, adv76xx_i2c_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3131) static const struct of_device_id adv76xx_of_id[] __maybe_unused = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3132) { .compatible = "adi,adv7611", .data = &adv76xx_chip_info[ADV7611] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3133) { .compatible = "adi,adv7612", .data = &adv76xx_chip_info[ADV7612] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3134) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3135) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3136) MODULE_DEVICE_TABLE(of, adv76xx_of_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3138) static int adv76xx_parse_dt(struct adv76xx_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3140) struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3141) struct device_node *endpoint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3142) struct device_node *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3143) unsigned int flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3144) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3145) u32 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3147) np = state->i2c_clients[ADV76XX_PAGE_IO]->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3149) /* Parse the endpoint. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3150) endpoint = of_graph_get_next_endpoint(np, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3151) if (!endpoint)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3152) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3154) ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint), &bus_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3155) of_node_put(endpoint);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3156) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3157) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3159) if (!of_property_read_u32(np, "default-input", &v))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3160) state->pdata.default_input = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3161) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3162) state->pdata.default_input = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3164) flags = bus_cfg.bus.parallel.flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3166) if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3167) state->pdata.inv_hs_pol = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3169) if (flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3170) state->pdata.inv_vs_pol = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3172) if (flags & V4L2_MBUS_PCLK_SAMPLE_RISING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3173) state->pdata.inv_llc_pol = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3175) if (bus_cfg.bus_type == V4L2_MBUS_BT656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3176) state->pdata.insert_av_codes = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3178) /* Disable the interrupt for now as no DT-based board uses it. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3179) state->pdata.int1_config = ADV76XX_INT1_CONFIG_ACTIVE_HIGH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3181) /* Hardcode the remaining platform data fields. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3182) state->pdata.disable_pwrdnb = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3183) state->pdata.disable_cable_det_rst = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3184) state->pdata.blank_data = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3185) state->pdata.op_format_mode_sel = ADV7604_OP_FORMAT_MODE0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3186) state->pdata.bus_order = ADV7604_BUS_ORDER_RGB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3187) state->pdata.dr_str_data = ADV76XX_DR_STR_MEDIUM_HIGH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3188) state->pdata.dr_str_clk = ADV76XX_DR_STR_MEDIUM_HIGH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3189) state->pdata.dr_str_sync = ADV76XX_DR_STR_MEDIUM_HIGH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3191) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3194) static const struct regmap_config adv76xx_regmap_cnf[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3195) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3196) .name = "io",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3197) .reg_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3198) .val_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3200) .max_register = 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3201) .cache_type = REGCACHE_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3202) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3203) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3204) .name = "avlink",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3205) .reg_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3206) .val_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3208) .max_register = 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3209) .cache_type = REGCACHE_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3210) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3211) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3212) .name = "cec",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3213) .reg_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3214) .val_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3216) .max_register = 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3217) .cache_type = REGCACHE_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3218) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3220) .name = "infoframe",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3221) .reg_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3222) .val_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3224) .max_register = 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3225) .cache_type = REGCACHE_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3226) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3227) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3228) .name = "esdp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3229) .reg_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3230) .val_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3232) .max_register = 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3233) .cache_type = REGCACHE_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3234) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3236) .name = "epp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3237) .reg_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3238) .val_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3240) .max_register = 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3241) .cache_type = REGCACHE_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3242) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3244) .name = "afe",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3245) .reg_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3246) .val_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3248) .max_register = 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3249) .cache_type = REGCACHE_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3250) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3251) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3252) .name = "rep",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3253) .reg_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3254) .val_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3256) .max_register = 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3257) .cache_type = REGCACHE_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3258) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3260) .name = "edid",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3261) .reg_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3262) .val_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3264) .max_register = 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3265) .cache_type = REGCACHE_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3266) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3268) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3269) .name = "hdmi",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3270) .reg_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3271) .val_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3273) .max_register = 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3274) .cache_type = REGCACHE_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3275) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3277) .name = "test",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3278) .reg_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3279) .val_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3281) .max_register = 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3282) .cache_type = REGCACHE_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3283) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3284) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3285) .name = "cp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3286) .reg_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3287) .val_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3289) .max_register = 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3290) .cache_type = REGCACHE_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3291) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3292) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3293) .name = "vdp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3294) .reg_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3295) .val_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3297) .max_register = 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3298) .cache_type = REGCACHE_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3299) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3300) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3302) static int configure_regmap(struct adv76xx_state *state, int region)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3303) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3304) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3306) if (!state->i2c_clients[region])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3307) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3309) state->regmap[region] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3310) devm_regmap_init_i2c(state->i2c_clients[region],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3311) &adv76xx_regmap_cnf[region]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3313) if (IS_ERR(state->regmap[region])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3314) err = PTR_ERR(state->regmap[region]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3315) v4l_err(state->i2c_clients[region],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3316) "Error initializing regmap %d with error %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3317) region, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3318) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3321) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3324) static int configure_regmaps(struct adv76xx_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3325) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3326) int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3328) for (i = ADV7604_PAGE_AVLINK ; i < ADV76XX_PAGE_MAX; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3329) err = configure_regmap(state, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3330) if (err && (err != -ENODEV))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3331) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3333) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3336) static void adv76xx_reset(struct adv76xx_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3337) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3338) if (state->reset_gpio) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3339) /* ADV76XX can be reset by a low reset pulse of minimum 5 ms. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3340) gpiod_set_value_cansleep(state->reset_gpio, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3341) usleep_range(5000, 10000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3342) gpiod_set_value_cansleep(state->reset_gpio, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3343) /* It is recommended to wait 5 ms after the low pulse before */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3344) /* an I2C write is performed to the ADV76XX. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3345) usleep_range(5000, 10000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3349) static int adv76xx_probe(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3350) const struct i2c_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3351) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3352) static const struct v4l2_dv_timings cea640x480 =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3353) V4L2_DV_BT_CEA_640X480P59_94;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3354) struct adv76xx_state *state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3355) struct v4l2_ctrl_handler *hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3356) struct v4l2_ctrl *ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3357) struct v4l2_subdev *sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3358) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3359) unsigned int val, val2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3360) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3362) /* Check if the adapter supports the needed features */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3363) if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3364) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3365) v4l_dbg(1, debug, client, "detecting adv76xx client on address 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3366) client->addr << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3368) state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3369) if (!state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3370) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3372) state->i2c_clients[ADV76XX_PAGE_IO] = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3374) /* initialize variables */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3375) state->restart_stdi_once = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3376) state->selected_input = ~0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3378) if (IS_ENABLED(CONFIG_OF) && client->dev.of_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3379) const struct of_device_id *oid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3381) oid = of_match_node(adv76xx_of_id, client->dev.of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3382) state->info = oid->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3384) err = adv76xx_parse_dt(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3385) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3386) v4l_err(client, "DT parsing error\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3387) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3389) } else if (client->dev.platform_data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3390) struct adv76xx_platform_data *pdata = client->dev.platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3392) state->info = (const struct adv76xx_chip_info *)id->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3393) state->pdata = *pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3394) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3395) v4l_err(client, "No platform data!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3396) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3399) /* Request GPIOs. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3400) for (i = 0; i < state->info->num_dv_ports; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3401) state->hpd_gpio[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3402) devm_gpiod_get_index_optional(&client->dev, "hpd", i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3403) GPIOD_OUT_LOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3404) if (IS_ERR(state->hpd_gpio[i]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3405) return PTR_ERR(state->hpd_gpio[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3407) if (state->hpd_gpio[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3408) v4l_info(client, "Handling HPD %u GPIO\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3410) state->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3411) GPIOD_OUT_HIGH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3412) if (IS_ERR(state->reset_gpio))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3413) return PTR_ERR(state->reset_gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3415) adv76xx_reset(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3417) state->timings = cea640x480;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3418) state->format = adv76xx_format_info(state, MEDIA_BUS_FMT_YUYV8_2X8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3420) sd = &state->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3421) v4l2_i2c_subdev_init(sd, client, &adv76xx_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3422) snprintf(sd->name, sizeof(sd->name), "%s %d-%04x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3423) id->name, i2c_adapter_id(client->adapter),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3424) client->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3425) sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3426) sd->internal_ops = &adv76xx_int_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3428) /* Configure IO Regmap region */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3429) err = configure_regmap(state, ADV76XX_PAGE_IO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3431) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3432) v4l2_err(sd, "Error configuring IO regmap region\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3433) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3436) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3437) * Verify that the chip is present. On ADV7604 the RD_INFO register only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3438) * identifies the revision, while on ADV7611 it identifies the model as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3439) * well. Use the HDMI slave address on ADV7604 and RD_INFO on ADV7611.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3440) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3441) switch (state->info->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3442) case ADV7604:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3443) err = regmap_read(state->regmap[ADV76XX_PAGE_IO], 0xfb, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3444) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3445) v4l2_err(sd, "Error %d reading IO Regmap\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3446) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3447) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3448) if (val != 0x68) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3449) v4l2_err(sd, "not an adv7604 on address 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3450) client->addr << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3451) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3453) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3454) case ADV7611:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3455) case ADV7612:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3456) err = regmap_read(state->regmap[ADV76XX_PAGE_IO],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3457) 0xea,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3458) &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3459) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3460) v4l2_err(sd, "Error %d reading IO Regmap\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3461) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3463) val2 = val << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3464) err = regmap_read(state->regmap[ADV76XX_PAGE_IO],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3465) 0xeb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3466) &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3467) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3468) v4l2_err(sd, "Error %d reading IO Regmap\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3469) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3471) val |= val2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3472) if ((state->info->type == ADV7611 && val != 0x2051) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3473) (state->info->type == ADV7612 && val != 0x2041)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3474) v4l2_err(sd, "not an adv761x on address 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3475) client->addr << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3476) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3478) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3481) /* control handlers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3482) hdl = &state->hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3483) v4l2_ctrl_handler_init(hdl, adv76xx_has_afe(state) ? 9 : 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3485) v4l2_ctrl_new_std(hdl, &adv76xx_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3486) V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3487) v4l2_ctrl_new_std(hdl, &adv76xx_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3488) V4L2_CID_CONTRAST, 0, 255, 1, 128);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3489) v4l2_ctrl_new_std(hdl, &adv76xx_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3490) V4L2_CID_SATURATION, 0, 255, 1, 128);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3491) v4l2_ctrl_new_std(hdl, &adv76xx_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3492) V4L2_CID_HUE, 0, 128, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3493) ctrl = v4l2_ctrl_new_std_menu(hdl, &adv76xx_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3494) V4L2_CID_DV_RX_IT_CONTENT_TYPE, V4L2_DV_IT_CONTENT_TYPE_NO_ITC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3495) 0, V4L2_DV_IT_CONTENT_TYPE_NO_ITC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3496) if (ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3497) ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3499) state->detect_tx_5v_ctrl = v4l2_ctrl_new_std(hdl, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3500) V4L2_CID_DV_RX_POWER_PRESENT, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3501) (1 << state->info->num_dv_ports) - 1, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3502) state->rgb_quantization_range_ctrl =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3503) v4l2_ctrl_new_std_menu(hdl, &adv76xx_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3504) V4L2_CID_DV_RX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3505) 0, V4L2_DV_RGB_RANGE_AUTO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3507) /* custom controls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3508) if (adv76xx_has_afe(state))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3509) state->analog_sampling_phase_ctrl =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3510) v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_analog_sampling_phase, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3511) state->free_run_color_manual_ctrl =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3512) v4l2_ctrl_new_custom(hdl, &adv76xx_ctrl_free_run_color_manual, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3513) state->free_run_color_ctrl =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3514) v4l2_ctrl_new_custom(hdl, &adv76xx_ctrl_free_run_color, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3516) sd->ctrl_handler = hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3517) if (hdl->error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3518) err = hdl->error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3519) goto err_hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3521) if (adv76xx_s_detect_tx_5v_ctrl(sd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3522) err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3523) goto err_hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3526) for (i = 1; i < ADV76XX_PAGE_MAX; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3527) struct i2c_client *dummy_client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3529) if (!(BIT(i) & state->info->page_mask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3530) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3532) dummy_client = adv76xx_dummy_client(sd, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3533) if (IS_ERR(dummy_client)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3534) err = PTR_ERR(dummy_client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3535) v4l2_err(sd, "failed to create i2c client %u\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3536) goto err_i2c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3539) state->i2c_clients[i] = dummy_client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3542) INIT_DELAYED_WORK(&state->delayed_work_enable_hotplug,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3543) adv76xx_delayed_work_enable_hotplug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3545) state->source_pad = state->info->num_dv_ports
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3546) + (state->info->has_afe ? 2 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3547) for (i = 0; i < state->source_pad; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3548) state->pads[i].flags = MEDIA_PAD_FL_SINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3549) state->pads[state->source_pad].flags = MEDIA_PAD_FL_SOURCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3550) sd->entity.function = MEDIA_ENT_F_DV_DECODER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3552) err = media_entity_pads_init(&sd->entity, state->source_pad + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3553) state->pads);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3554) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3555) goto err_work_queues;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3557) /* Configure regmaps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3558) err = configure_regmaps(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3559) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3560) goto err_entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3562) err = adv76xx_core_init(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3563) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3564) goto err_entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3566) if (client->irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3567) err = devm_request_threaded_irq(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3568) client->irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3569) NULL, adv76xx_irq_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3570) IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3571) client->name, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3572) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3573) goto err_entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3576) #if IS_ENABLED(CONFIG_VIDEO_ADV7604_CEC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3577) state->cec_adap = cec_allocate_adapter(&adv76xx_cec_adap_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3578) state, dev_name(&client->dev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3579) CEC_CAP_DEFAULTS, ADV76XX_MAX_ADDRS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3580) err = PTR_ERR_OR_ZERO(state->cec_adap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3581) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3582) goto err_entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3583) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3585) v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3586) client->addr << 1, client->adapter->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3588) err = v4l2_async_register_subdev(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3589) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3590) goto err_entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3592) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3594) err_entity:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3595) media_entity_cleanup(&sd->entity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3596) err_work_queues:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3597) cancel_delayed_work(&state->delayed_work_enable_hotplug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3598) err_i2c:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3599) adv76xx_unregister_clients(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3600) err_hdl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3601) v4l2_ctrl_handler_free(hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3602) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3603) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3605) /* ----------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3607) static int adv76xx_remove(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3608) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3609) struct v4l2_subdev *sd = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3610) struct adv76xx_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3612) /* disable interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3613) io_write(sd, 0x40, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3614) io_write(sd, 0x41, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3615) io_write(sd, 0x46, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3616) io_write(sd, 0x6e, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3617) io_write(sd, 0x73, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3619) cancel_delayed_work_sync(&state->delayed_work_enable_hotplug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3620) v4l2_async_unregister_subdev(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3621) media_entity_cleanup(&sd->entity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3622) adv76xx_unregister_clients(to_state(sd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3623) v4l2_ctrl_handler_free(sd->ctrl_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3624) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3627) /* ----------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3629) static struct i2c_driver adv76xx_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3630) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3631) .name = "adv7604",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3632) .of_match_table = of_match_ptr(adv76xx_of_id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3633) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3634) .probe = adv76xx_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3635) .remove = adv76xx_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3636) .id_table = adv76xx_i2c_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3637) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3639) module_i2c_driver(adv76xx_driver);