1b2ce5617SAnders Roxell // SPDX-License-Identifier: GPL-2.0-only 2b2ce5617SAnders Roxell /* 3b2ce5617SAnders Roxell * Analog Devices ADV7511 HDMI Transmitter Device Driver 4b2ce5617SAnders Roxell * 5b2ce5617SAnders Roxell * Copyright 2013 Cisco Systems, Inc. and/or its affiliates. All rights reserved. 6b2ce5617SAnders Roxell */ 7b2ce5617SAnders Roxell 8b2ce5617SAnders Roxell /* 9b2ce5617SAnders Roxell * This file is named adv7511-v4l2.c so it doesn't conflict with the Analog 10b2ce5617SAnders Roxell * Device ADV7511 (config fragment CONFIG_DRM_I2C_ADV7511). 11b2ce5617SAnders Roxell */ 12b2ce5617SAnders Roxell 13b2ce5617SAnders Roxell 14b2ce5617SAnders Roxell #include <linux/kernel.h> 15b2ce5617SAnders Roxell #include <linux/module.h> 16b2ce5617SAnders Roxell #include <linux/slab.h> 17b2ce5617SAnders Roxell #include <linux/i2c.h> 18b2ce5617SAnders Roxell #include <linux/delay.h> 19b2ce5617SAnders Roxell #include <linux/videodev2.h> 20b2ce5617SAnders Roxell #include <linux/gpio.h> 21b2ce5617SAnders Roxell #include <linux/workqueue.h> 22b2ce5617SAnders Roxell #include <linux/hdmi.h> 23b2ce5617SAnders Roxell #include <linux/v4l2-dv-timings.h> 24b2ce5617SAnders Roxell #include <media/v4l2-device.h> 25b2ce5617SAnders Roxell #include <media/v4l2-common.h> 26b2ce5617SAnders Roxell #include <media/v4l2-ctrls.h> 27b2ce5617SAnders Roxell #include <media/v4l2-dv-timings.h> 28b2ce5617SAnders Roxell #include <media/i2c/adv7511.h> 29b2ce5617SAnders Roxell #include <media/cec.h> 30b2ce5617SAnders Roxell 31b2ce5617SAnders Roxell static int debug; 32b2ce5617SAnders Roxell module_param(debug, int, 0644); 33b2ce5617SAnders Roxell MODULE_PARM_DESC(debug, "debug level (0-2)"); 34b2ce5617SAnders Roxell 35b2ce5617SAnders Roxell MODULE_DESCRIPTION("Analog Devices ADV7511 HDMI Transmitter Device Driver"); 36b2ce5617SAnders Roxell MODULE_AUTHOR("Hans Verkuil"); 37b2ce5617SAnders Roxell MODULE_LICENSE("GPL v2"); 38b2ce5617SAnders Roxell 39b2ce5617SAnders Roxell #define MASK_ADV7511_EDID_RDY_INT 0x04 40b2ce5617SAnders Roxell #define MASK_ADV7511_MSEN_INT 0x40 41b2ce5617SAnders Roxell #define MASK_ADV7511_HPD_INT 0x80 42b2ce5617SAnders Roxell 43b2ce5617SAnders Roxell #define MASK_ADV7511_HPD_DETECT 0x40 44b2ce5617SAnders Roxell #define MASK_ADV7511_MSEN_DETECT 0x20 45b2ce5617SAnders Roxell #define MASK_ADV7511_EDID_RDY 0x10 46b2ce5617SAnders Roxell 47b2ce5617SAnders Roxell #define EDID_MAX_RETRIES (8) 48b2ce5617SAnders Roxell #define EDID_DELAY 250 49b2ce5617SAnders Roxell #define EDID_MAX_SEGM 8 50b2ce5617SAnders Roxell 51b2ce5617SAnders Roxell #define ADV7511_MAX_WIDTH 1920 52b2ce5617SAnders Roxell #define ADV7511_MAX_HEIGHT 1200 53b2ce5617SAnders Roxell #define ADV7511_MIN_PIXELCLOCK 20000000 54b2ce5617SAnders Roxell #define ADV7511_MAX_PIXELCLOCK 225000000 55b2ce5617SAnders Roxell 56b2ce5617SAnders Roxell #define ADV7511_MAX_ADDRS (3) 57b2ce5617SAnders Roxell 58b2ce5617SAnders Roxell /* 59b2ce5617SAnders Roxell ********************************************************************** 60b2ce5617SAnders Roxell * 61b2ce5617SAnders Roxell * Arrays with configuration parameters for the ADV7511 62b2ce5617SAnders Roxell * 63b2ce5617SAnders Roxell ********************************************************************** 64b2ce5617SAnders Roxell */ 65b2ce5617SAnders Roxell 66b2ce5617SAnders Roxell struct i2c_reg_value { 67b2ce5617SAnders Roxell unsigned char reg; 68b2ce5617SAnders Roxell unsigned char value; 69b2ce5617SAnders Roxell }; 70b2ce5617SAnders Roxell 71b2ce5617SAnders Roxell struct adv7511_state_edid { 72b2ce5617SAnders Roxell /* total number of blocks */ 73b2ce5617SAnders Roxell u32 blocks; 74b2ce5617SAnders Roxell /* Number of segments read */ 75b2ce5617SAnders Roxell u32 segments; 76b2ce5617SAnders Roxell u8 data[EDID_MAX_SEGM * 256]; 77b2ce5617SAnders Roxell /* Number of EDID read retries left */ 78b2ce5617SAnders Roxell unsigned read_retries; 79b2ce5617SAnders Roxell bool complete; 80b2ce5617SAnders Roxell }; 81b2ce5617SAnders Roxell 82b2ce5617SAnders Roxell struct adv7511_state { 83b2ce5617SAnders Roxell struct adv7511_platform_data pdata; 84b2ce5617SAnders Roxell struct v4l2_subdev sd; 85b2ce5617SAnders Roxell struct media_pad pad; 86b2ce5617SAnders Roxell struct v4l2_ctrl_handler hdl; 87b2ce5617SAnders Roxell int chip_revision; 88b2ce5617SAnders Roxell u8 i2c_edid_addr; 89b2ce5617SAnders Roxell u8 i2c_pktmem_addr; 90b2ce5617SAnders Roxell u8 i2c_cec_addr; 91b2ce5617SAnders Roxell 92b2ce5617SAnders Roxell struct i2c_client *i2c_cec; 93b2ce5617SAnders Roxell struct cec_adapter *cec_adap; 94b2ce5617SAnders Roxell u8 cec_addr[ADV7511_MAX_ADDRS]; 95b2ce5617SAnders Roxell u8 cec_valid_addrs; 96b2ce5617SAnders Roxell bool cec_enabled_adap; 97b2ce5617SAnders Roxell 98b2ce5617SAnders Roxell /* Is the adv7511 powered on? */ 99b2ce5617SAnders Roxell bool power_on; 100b2ce5617SAnders Roxell /* Did we receive hotplug and rx-sense signals? */ 101b2ce5617SAnders Roxell bool have_monitor; 102b2ce5617SAnders Roxell bool enabled_irq; 103b2ce5617SAnders Roxell /* timings from s_dv_timings */ 104b2ce5617SAnders Roxell struct v4l2_dv_timings dv_timings; 105b2ce5617SAnders Roxell u32 fmt_code; 106b2ce5617SAnders Roxell u32 colorspace; 107b2ce5617SAnders Roxell u32 ycbcr_enc; 108b2ce5617SAnders Roxell u32 quantization; 109b2ce5617SAnders Roxell u32 xfer_func; 110b2ce5617SAnders Roxell u32 content_type; 111b2ce5617SAnders Roxell /* controls */ 112b2ce5617SAnders Roxell struct v4l2_ctrl *hdmi_mode_ctrl; 113b2ce5617SAnders Roxell struct v4l2_ctrl *hotplug_ctrl; 114b2ce5617SAnders Roxell struct v4l2_ctrl *rx_sense_ctrl; 115b2ce5617SAnders Roxell struct v4l2_ctrl *have_edid0_ctrl; 116b2ce5617SAnders Roxell struct v4l2_ctrl *rgb_quantization_range_ctrl; 117b2ce5617SAnders Roxell struct v4l2_ctrl *content_type_ctrl; 118b2ce5617SAnders Roxell struct i2c_client *i2c_edid; 119b2ce5617SAnders Roxell struct i2c_client *i2c_pktmem; 120b2ce5617SAnders Roxell struct adv7511_state_edid edid; 121b2ce5617SAnders Roxell /* Running counter of the number of detected EDIDs (for debugging) */ 122b2ce5617SAnders Roxell unsigned edid_detect_counter; 123b2ce5617SAnders Roxell struct workqueue_struct *work_queue; 124b2ce5617SAnders Roxell struct delayed_work edid_handler; /* work entry */ 125b2ce5617SAnders Roxell }; 126b2ce5617SAnders Roxell 127b2ce5617SAnders Roxell static void adv7511_check_monitor_present_status(struct v4l2_subdev *sd); 128b2ce5617SAnders Roxell static bool adv7511_check_edid_status(struct v4l2_subdev *sd); 129b2ce5617SAnders Roxell static void adv7511_setup(struct v4l2_subdev *sd); 130b2ce5617SAnders Roxell static int adv7511_s_i2s_clock_freq(struct v4l2_subdev *sd, u32 freq); 131b2ce5617SAnders Roxell static int adv7511_s_clock_freq(struct v4l2_subdev *sd, u32 freq); 132b2ce5617SAnders Roxell 133b2ce5617SAnders Roxell 134b2ce5617SAnders Roxell static const struct v4l2_dv_timings_cap adv7511_timings_cap = { 135b2ce5617SAnders Roxell .type = V4L2_DV_BT_656_1120, 136b2ce5617SAnders Roxell /* keep this initialization for compatibility with GCC < 4.4.6 */ 137b2ce5617SAnders Roxell .reserved = { 0 }, 138b2ce5617SAnders Roxell V4L2_INIT_BT_TIMINGS(640, ADV7511_MAX_WIDTH, 350, ADV7511_MAX_HEIGHT, 139b2ce5617SAnders Roxell ADV7511_MIN_PIXELCLOCK, ADV7511_MAX_PIXELCLOCK, 140b2ce5617SAnders Roxell V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT | 141b2ce5617SAnders Roxell V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT, 142b2ce5617SAnders Roxell V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_REDUCED_BLANKING | 143b2ce5617SAnders Roxell V4L2_DV_BT_CAP_CUSTOM) 144b2ce5617SAnders Roxell }; 145b2ce5617SAnders Roxell 146b2ce5617SAnders Roxell static inline struct adv7511_state *get_adv7511_state(struct v4l2_subdev *sd) 147b2ce5617SAnders Roxell { 148b2ce5617SAnders Roxell return container_of(sd, struct adv7511_state, sd); 149b2ce5617SAnders Roxell } 150b2ce5617SAnders Roxell 151b2ce5617SAnders Roxell static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) 152b2ce5617SAnders Roxell { 153b2ce5617SAnders Roxell return &container_of(ctrl->handler, struct adv7511_state, hdl)->sd; 154b2ce5617SAnders Roxell } 155b2ce5617SAnders Roxell 156b2ce5617SAnders Roxell /* ------------------------ I2C ----------------------------------------------- */ 157b2ce5617SAnders Roxell 158b2ce5617SAnders Roxell static s32 adv_smbus_read_byte_data_check(struct i2c_client *client, 159b2ce5617SAnders Roxell u8 command, bool check) 160b2ce5617SAnders Roxell { 161b2ce5617SAnders Roxell union i2c_smbus_data data; 162b2ce5617SAnders Roxell 163b2ce5617SAnders Roxell if (!i2c_smbus_xfer(client->adapter, client->addr, client->flags, 164b2ce5617SAnders Roxell I2C_SMBUS_READ, command, 165b2ce5617SAnders Roxell I2C_SMBUS_BYTE_DATA, &data)) 166b2ce5617SAnders Roxell return data.byte; 167b2ce5617SAnders Roxell if (check) 168b2ce5617SAnders Roxell v4l_err(client, "error reading %02x, %02x\n", 169b2ce5617SAnders Roxell client->addr, command); 170b2ce5617SAnders Roxell return -1; 171b2ce5617SAnders Roxell } 172b2ce5617SAnders Roxell 173b2ce5617SAnders Roxell static s32 adv_smbus_read_byte_data(struct i2c_client *client, u8 command) 174b2ce5617SAnders Roxell { 175b2ce5617SAnders Roxell int i; 176b2ce5617SAnders Roxell for (i = 0; i < 3; i++) { 177b2ce5617SAnders Roxell int ret = adv_smbus_read_byte_data_check(client, command, true); 178b2ce5617SAnders Roxell if (ret >= 0) { 179b2ce5617SAnders Roxell if (i) 180b2ce5617SAnders Roxell v4l_err(client, "read ok after %d retries\n", i); 181b2ce5617SAnders Roxell return ret; 182b2ce5617SAnders Roxell } 183b2ce5617SAnders Roxell } 184b2ce5617SAnders Roxell v4l_err(client, "read failed\n"); 185b2ce5617SAnders Roxell return -1; 186b2ce5617SAnders Roxell } 187b2ce5617SAnders Roxell 188b2ce5617SAnders Roxell static int adv7511_rd(struct v4l2_subdev *sd, u8 reg) 189b2ce5617SAnders Roxell { 190b2ce5617SAnders Roxell struct i2c_client *client = v4l2_get_subdevdata(sd); 191b2ce5617SAnders Roxell 192b2ce5617SAnders Roxell return adv_smbus_read_byte_data(client, reg); 193b2ce5617SAnders Roxell } 194b2ce5617SAnders Roxell 195b2ce5617SAnders Roxell static int adv7511_wr(struct v4l2_subdev *sd, u8 reg, u8 val) 196b2ce5617SAnders Roxell { 197b2ce5617SAnders Roxell struct i2c_client *client = v4l2_get_subdevdata(sd); 198b2ce5617SAnders Roxell int ret; 199b2ce5617SAnders Roxell int i; 200b2ce5617SAnders Roxell 201b2ce5617SAnders Roxell for (i = 0; i < 3; i++) { 202b2ce5617SAnders Roxell ret = i2c_smbus_write_byte_data(client, reg, val); 203b2ce5617SAnders Roxell if (ret == 0) 204b2ce5617SAnders Roxell return 0; 205b2ce5617SAnders Roxell } 206b2ce5617SAnders Roxell v4l2_err(sd, "%s: i2c write error\n", __func__); 207b2ce5617SAnders Roxell return ret; 208b2ce5617SAnders Roxell } 209b2ce5617SAnders Roxell 210b2ce5617SAnders Roxell /* To set specific bits in the register, a clear-mask is given (to be AND-ed), 211b2ce5617SAnders Roxell and then the value-mask (to be OR-ed). */ 212b2ce5617SAnders Roxell static inline void adv7511_wr_and_or(struct v4l2_subdev *sd, u8 reg, u8 clr_mask, u8 val_mask) 213b2ce5617SAnders Roxell { 214b2ce5617SAnders Roxell adv7511_wr(sd, reg, (adv7511_rd(sd, reg) & clr_mask) | val_mask); 215b2ce5617SAnders Roxell } 216b2ce5617SAnders Roxell 217b2ce5617SAnders Roxell static int adv_smbus_read_i2c_block_data(struct i2c_client *client, 218b2ce5617SAnders Roxell u8 command, unsigned length, u8 *values) 219b2ce5617SAnders Roxell { 220b2ce5617SAnders Roxell union i2c_smbus_data data; 221b2ce5617SAnders Roxell int ret; 222b2ce5617SAnders Roxell 223b2ce5617SAnders Roxell if (length > I2C_SMBUS_BLOCK_MAX) 224b2ce5617SAnders Roxell length = I2C_SMBUS_BLOCK_MAX; 225b2ce5617SAnders Roxell data.block[0] = length; 226b2ce5617SAnders Roxell 227b2ce5617SAnders Roxell ret = i2c_smbus_xfer(client->adapter, client->addr, client->flags, 228b2ce5617SAnders Roxell I2C_SMBUS_READ, command, 229b2ce5617SAnders Roxell I2C_SMBUS_I2C_BLOCK_DATA, &data); 230b2ce5617SAnders Roxell memcpy(values, data.block + 1, length); 231b2ce5617SAnders Roxell return ret; 232b2ce5617SAnders Roxell } 233b2ce5617SAnders Roxell 234b2ce5617SAnders Roxell static void adv7511_edid_rd(struct v4l2_subdev *sd, uint16_t len, uint8_t *buf) 235b2ce5617SAnders Roxell { 236b2ce5617SAnders Roxell struct adv7511_state *state = get_adv7511_state(sd); 237b2ce5617SAnders Roxell int i; 238b2ce5617SAnders Roxell int err = 0; 239b2ce5617SAnders Roxell 240b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, "%s:\n", __func__); 241b2ce5617SAnders Roxell 242b2ce5617SAnders Roxell for (i = 0; !err && i < len; i += I2C_SMBUS_BLOCK_MAX) 243b2ce5617SAnders Roxell err = adv_smbus_read_i2c_block_data(state->i2c_edid, i, 244b2ce5617SAnders Roxell I2C_SMBUS_BLOCK_MAX, buf + i); 245b2ce5617SAnders Roxell if (err) 246b2ce5617SAnders Roxell v4l2_err(sd, "%s: i2c read error\n", __func__); 247b2ce5617SAnders Roxell } 248b2ce5617SAnders Roxell 249b2ce5617SAnders Roxell static inline int adv7511_cec_read(struct v4l2_subdev *sd, u8 reg) 250b2ce5617SAnders Roxell { 251b2ce5617SAnders Roxell struct adv7511_state *state = get_adv7511_state(sd); 252b2ce5617SAnders Roxell 253b2ce5617SAnders Roxell return i2c_smbus_read_byte_data(state->i2c_cec, reg); 254b2ce5617SAnders Roxell } 255b2ce5617SAnders Roxell 256b2ce5617SAnders Roxell static int adv7511_cec_write(struct v4l2_subdev *sd, u8 reg, u8 val) 257b2ce5617SAnders Roxell { 258b2ce5617SAnders Roxell struct adv7511_state *state = get_adv7511_state(sd); 259b2ce5617SAnders Roxell int ret; 260b2ce5617SAnders Roxell int i; 261b2ce5617SAnders Roxell 262b2ce5617SAnders Roxell for (i = 0; i < 3; i++) { 263b2ce5617SAnders Roxell ret = i2c_smbus_write_byte_data(state->i2c_cec, reg, val); 264b2ce5617SAnders Roxell if (ret == 0) 265b2ce5617SAnders Roxell return 0; 266b2ce5617SAnders Roxell } 267b2ce5617SAnders Roxell v4l2_err(sd, "%s: I2C Write Problem\n", __func__); 268b2ce5617SAnders Roxell return ret; 269b2ce5617SAnders Roxell } 270b2ce5617SAnders Roxell 271b2ce5617SAnders Roxell static inline int adv7511_cec_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, 272b2ce5617SAnders Roxell u8 val) 273b2ce5617SAnders Roxell { 274b2ce5617SAnders Roxell return adv7511_cec_write(sd, reg, (adv7511_cec_read(sd, reg) & mask) | val); 275b2ce5617SAnders Roxell } 276b2ce5617SAnders Roxell 277b2ce5617SAnders Roxell static int adv7511_pktmem_rd(struct v4l2_subdev *sd, u8 reg) 278b2ce5617SAnders Roxell { 279b2ce5617SAnders Roxell struct adv7511_state *state = get_adv7511_state(sd); 280b2ce5617SAnders Roxell 281b2ce5617SAnders Roxell return adv_smbus_read_byte_data(state->i2c_pktmem, reg); 282b2ce5617SAnders Roxell } 283b2ce5617SAnders Roxell 284b2ce5617SAnders Roxell static int adv7511_pktmem_wr(struct v4l2_subdev *sd, u8 reg, u8 val) 285b2ce5617SAnders Roxell { 286b2ce5617SAnders Roxell struct adv7511_state *state = get_adv7511_state(sd); 287b2ce5617SAnders Roxell int ret; 288b2ce5617SAnders Roxell int i; 289b2ce5617SAnders Roxell 290b2ce5617SAnders Roxell for (i = 0; i < 3; i++) { 291b2ce5617SAnders Roxell ret = i2c_smbus_write_byte_data(state->i2c_pktmem, reg, val); 292b2ce5617SAnders Roxell if (ret == 0) 293b2ce5617SAnders Roxell return 0; 294b2ce5617SAnders Roxell } 295b2ce5617SAnders Roxell v4l2_err(sd, "%s: i2c write error\n", __func__); 296b2ce5617SAnders Roxell return ret; 297b2ce5617SAnders Roxell } 298b2ce5617SAnders Roxell 299b2ce5617SAnders Roxell /* To set specific bits in the register, a clear-mask is given (to be AND-ed), 300b2ce5617SAnders Roxell and then the value-mask (to be OR-ed). */ 301b2ce5617SAnders Roxell static inline void adv7511_pktmem_wr_and_or(struct v4l2_subdev *sd, u8 reg, u8 clr_mask, u8 val_mask) 302b2ce5617SAnders Roxell { 303b2ce5617SAnders Roxell adv7511_pktmem_wr(sd, reg, (adv7511_pktmem_rd(sd, reg) & clr_mask) | val_mask); 304b2ce5617SAnders Roxell } 305b2ce5617SAnders Roxell 306b2ce5617SAnders Roxell static inline bool adv7511_have_hotplug(struct v4l2_subdev *sd) 307b2ce5617SAnders Roxell { 308b2ce5617SAnders Roxell return adv7511_rd(sd, 0x42) & MASK_ADV7511_HPD_DETECT; 309b2ce5617SAnders Roxell } 310b2ce5617SAnders Roxell 311b2ce5617SAnders Roxell static inline bool adv7511_have_rx_sense(struct v4l2_subdev *sd) 312b2ce5617SAnders Roxell { 313b2ce5617SAnders Roxell return adv7511_rd(sd, 0x42) & MASK_ADV7511_MSEN_DETECT; 314b2ce5617SAnders Roxell } 315b2ce5617SAnders Roxell 316b2ce5617SAnders Roxell static void adv7511_csc_conversion_mode(struct v4l2_subdev *sd, u8 mode) 317b2ce5617SAnders Roxell { 318b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x18, 0x9f, (mode & 0x3)<<5); 319b2ce5617SAnders Roxell } 320b2ce5617SAnders Roxell 321b2ce5617SAnders Roxell static void adv7511_csc_coeff(struct v4l2_subdev *sd, 322b2ce5617SAnders Roxell u16 A1, u16 A2, u16 A3, u16 A4, 323b2ce5617SAnders Roxell u16 B1, u16 B2, u16 B3, u16 B4, 324b2ce5617SAnders Roxell u16 C1, u16 C2, u16 C3, u16 C4) 325b2ce5617SAnders Roxell { 326b2ce5617SAnders Roxell /* A */ 327b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x18, 0xe0, A1>>8); 328b2ce5617SAnders Roxell adv7511_wr(sd, 0x19, A1); 329b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x1A, 0xe0, A2>>8); 330b2ce5617SAnders Roxell adv7511_wr(sd, 0x1B, A2); 331b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x1c, 0xe0, A3>>8); 332b2ce5617SAnders Roxell adv7511_wr(sd, 0x1d, A3); 333b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x1e, 0xe0, A4>>8); 334b2ce5617SAnders Roxell adv7511_wr(sd, 0x1f, A4); 335b2ce5617SAnders Roxell 336b2ce5617SAnders Roxell /* B */ 337b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x20, 0xe0, B1>>8); 338b2ce5617SAnders Roxell adv7511_wr(sd, 0x21, B1); 339b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x22, 0xe0, B2>>8); 340b2ce5617SAnders Roxell adv7511_wr(sd, 0x23, B2); 341b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x24, 0xe0, B3>>8); 342b2ce5617SAnders Roxell adv7511_wr(sd, 0x25, B3); 343b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x26, 0xe0, B4>>8); 344b2ce5617SAnders Roxell adv7511_wr(sd, 0x27, B4); 345b2ce5617SAnders Roxell 346b2ce5617SAnders Roxell /* C */ 347b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x28, 0xe0, C1>>8); 348b2ce5617SAnders Roxell adv7511_wr(sd, 0x29, C1); 349b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x2A, 0xe0, C2>>8); 350b2ce5617SAnders Roxell adv7511_wr(sd, 0x2B, C2); 351b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x2C, 0xe0, C3>>8); 352b2ce5617SAnders Roxell adv7511_wr(sd, 0x2D, C3); 353b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x2E, 0xe0, C4>>8); 354b2ce5617SAnders Roxell adv7511_wr(sd, 0x2F, C4); 355b2ce5617SAnders Roxell } 356b2ce5617SAnders Roxell 357b2ce5617SAnders Roxell static void adv7511_csc_rgb_full2limit(struct v4l2_subdev *sd, bool enable) 358b2ce5617SAnders Roxell { 359b2ce5617SAnders Roxell if (enable) { 360b2ce5617SAnders Roxell u8 csc_mode = 0; 361b2ce5617SAnders Roxell adv7511_csc_conversion_mode(sd, csc_mode); 362b2ce5617SAnders Roxell adv7511_csc_coeff(sd, 363b2ce5617SAnders Roxell 4096-564, 0, 0, 256, 364b2ce5617SAnders Roxell 0, 4096-564, 0, 256, 365b2ce5617SAnders Roxell 0, 0, 4096-564, 256); 366b2ce5617SAnders Roxell /* enable CSC */ 367b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x18, 0x7f, 0x80); 368b2ce5617SAnders Roxell /* AVI infoframe: Limited range RGB (16-235) */ 369b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x57, 0xf3, 0x04); 370b2ce5617SAnders Roxell } else { 371b2ce5617SAnders Roxell /* disable CSC */ 372b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x18, 0x7f, 0x0); 373b2ce5617SAnders Roxell /* AVI infoframe: Full range RGB (0-255) */ 374b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x57, 0xf3, 0x08); 375b2ce5617SAnders Roxell } 376b2ce5617SAnders Roxell } 377b2ce5617SAnders Roxell 378b2ce5617SAnders Roxell static void adv7511_set_rgb_quantization_mode(struct v4l2_subdev *sd, struct v4l2_ctrl *ctrl) 379b2ce5617SAnders Roxell { 380b2ce5617SAnders Roxell struct adv7511_state *state = get_adv7511_state(sd); 381b2ce5617SAnders Roxell 382b2ce5617SAnders Roxell /* Only makes sense for RGB formats */ 383b2ce5617SAnders Roxell if (state->fmt_code != MEDIA_BUS_FMT_RGB888_1X24) { 384b2ce5617SAnders Roxell /* so just keep quantization */ 385b2ce5617SAnders Roxell adv7511_csc_rgb_full2limit(sd, false); 386b2ce5617SAnders Roxell return; 387b2ce5617SAnders Roxell } 388b2ce5617SAnders Roxell 389b2ce5617SAnders Roxell switch (ctrl->val) { 390b2ce5617SAnders Roxell case V4L2_DV_RGB_RANGE_AUTO: 391b2ce5617SAnders Roxell /* automatic */ 392b2ce5617SAnders Roxell if (state->dv_timings.bt.flags & V4L2_DV_FL_IS_CE_VIDEO) { 393b2ce5617SAnders Roxell /* CE format, RGB limited range (16-235) */ 394b2ce5617SAnders Roxell adv7511_csc_rgb_full2limit(sd, true); 395b2ce5617SAnders Roxell } else { 396b2ce5617SAnders Roxell /* not CE format, RGB full range (0-255) */ 397b2ce5617SAnders Roxell adv7511_csc_rgb_full2limit(sd, false); 398b2ce5617SAnders Roxell } 399b2ce5617SAnders Roxell break; 400b2ce5617SAnders Roxell case V4L2_DV_RGB_RANGE_LIMITED: 401b2ce5617SAnders Roxell /* RGB limited range (16-235) */ 402b2ce5617SAnders Roxell adv7511_csc_rgb_full2limit(sd, true); 403b2ce5617SAnders Roxell break; 404b2ce5617SAnders Roxell case V4L2_DV_RGB_RANGE_FULL: 405b2ce5617SAnders Roxell /* RGB full range (0-255) */ 406b2ce5617SAnders Roxell adv7511_csc_rgb_full2limit(sd, false); 407b2ce5617SAnders Roxell break; 408b2ce5617SAnders Roxell } 409b2ce5617SAnders Roxell } 410b2ce5617SAnders Roxell 411b2ce5617SAnders Roxell /* ------------------------------ CTRL OPS ------------------------------ */ 412b2ce5617SAnders Roxell 413b2ce5617SAnders Roxell static int adv7511_s_ctrl(struct v4l2_ctrl *ctrl) 414b2ce5617SAnders Roxell { 415b2ce5617SAnders Roxell struct v4l2_subdev *sd = to_sd(ctrl); 416b2ce5617SAnders Roxell struct adv7511_state *state = get_adv7511_state(sd); 417b2ce5617SAnders Roxell 418b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, "%s: ctrl id: %d, ctrl->val %d\n", __func__, ctrl->id, ctrl->val); 419b2ce5617SAnders Roxell 420b2ce5617SAnders Roxell if (state->hdmi_mode_ctrl == ctrl) { 421b2ce5617SAnders Roxell /* Set HDMI or DVI-D */ 422b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0xaf, 0xfd, ctrl->val == V4L2_DV_TX_MODE_HDMI ? 0x02 : 0x00); 423b2ce5617SAnders Roxell return 0; 424b2ce5617SAnders Roxell } 425b2ce5617SAnders Roxell if (state->rgb_quantization_range_ctrl == ctrl) { 426b2ce5617SAnders Roxell adv7511_set_rgb_quantization_mode(sd, ctrl); 427b2ce5617SAnders Roxell return 0; 428b2ce5617SAnders Roxell } 429b2ce5617SAnders Roxell if (state->content_type_ctrl == ctrl) { 430b2ce5617SAnders Roxell u8 itc, cn; 431b2ce5617SAnders Roxell 432b2ce5617SAnders Roxell state->content_type = ctrl->val; 433b2ce5617SAnders Roxell itc = state->content_type != V4L2_DV_IT_CONTENT_TYPE_NO_ITC; 434b2ce5617SAnders Roxell cn = itc ? state->content_type : V4L2_DV_IT_CONTENT_TYPE_GRAPHICS; 435b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x57, 0x7f, itc << 7); 436b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x59, 0xcf, cn << 4); 437b2ce5617SAnders Roxell return 0; 438b2ce5617SAnders Roxell } 439b2ce5617SAnders Roxell 440b2ce5617SAnders Roxell return -EINVAL; 441b2ce5617SAnders Roxell } 442b2ce5617SAnders Roxell 443b2ce5617SAnders Roxell static const struct v4l2_ctrl_ops adv7511_ctrl_ops = { 444b2ce5617SAnders Roxell .s_ctrl = adv7511_s_ctrl, 445b2ce5617SAnders Roxell }; 446b2ce5617SAnders Roxell 447b2ce5617SAnders Roxell /* ---------------------------- CORE OPS ------------------------------------------- */ 448b2ce5617SAnders Roxell 449b2ce5617SAnders Roxell #ifdef CONFIG_VIDEO_ADV_DEBUG 450b2ce5617SAnders Roxell static void adv7511_inv_register(struct v4l2_subdev *sd) 451b2ce5617SAnders Roxell { 452b2ce5617SAnders Roxell struct adv7511_state *state = get_adv7511_state(sd); 453b2ce5617SAnders Roxell 454b2ce5617SAnders Roxell v4l2_info(sd, "0x000-0x0ff: Main Map\n"); 455b2ce5617SAnders Roxell if (state->i2c_cec) 456b2ce5617SAnders Roxell v4l2_info(sd, "0x100-0x1ff: CEC Map\n"); 457b2ce5617SAnders Roxell } 458b2ce5617SAnders Roxell 459b2ce5617SAnders Roxell static int adv7511_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) 460b2ce5617SAnders Roxell { 461b2ce5617SAnders Roxell struct adv7511_state *state = get_adv7511_state(sd); 462b2ce5617SAnders Roxell 463b2ce5617SAnders Roxell reg->size = 1; 464b2ce5617SAnders Roxell switch (reg->reg >> 8) { 465b2ce5617SAnders Roxell case 0: 466b2ce5617SAnders Roxell reg->val = adv7511_rd(sd, reg->reg & 0xff); 467b2ce5617SAnders Roxell break; 468b2ce5617SAnders Roxell case 1: 469b2ce5617SAnders Roxell if (state->i2c_cec) { 470b2ce5617SAnders Roxell reg->val = adv7511_cec_read(sd, reg->reg & 0xff); 471b2ce5617SAnders Roxell break; 472b2ce5617SAnders Roxell } 473*1771e9fbSGustavo A. R. Silva fallthrough; 474b2ce5617SAnders Roxell default: 475b2ce5617SAnders Roxell v4l2_info(sd, "Register %03llx not supported\n", reg->reg); 476b2ce5617SAnders Roxell adv7511_inv_register(sd); 477b2ce5617SAnders Roxell break; 478b2ce5617SAnders Roxell } 479b2ce5617SAnders Roxell return 0; 480b2ce5617SAnders Roxell } 481b2ce5617SAnders Roxell 482b2ce5617SAnders Roxell static int adv7511_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) 483b2ce5617SAnders Roxell { 484b2ce5617SAnders Roxell struct adv7511_state *state = get_adv7511_state(sd); 485b2ce5617SAnders Roxell 486b2ce5617SAnders Roxell switch (reg->reg >> 8) { 487b2ce5617SAnders Roxell case 0: 488b2ce5617SAnders Roxell adv7511_wr(sd, reg->reg & 0xff, reg->val & 0xff); 489b2ce5617SAnders Roxell break; 490b2ce5617SAnders Roxell case 1: 491b2ce5617SAnders Roxell if (state->i2c_cec) { 492b2ce5617SAnders Roxell adv7511_cec_write(sd, reg->reg & 0xff, reg->val & 0xff); 493b2ce5617SAnders Roxell break; 494b2ce5617SAnders Roxell } 495*1771e9fbSGustavo A. R. Silva fallthrough; 496b2ce5617SAnders Roxell default: 497b2ce5617SAnders Roxell v4l2_info(sd, "Register %03llx not supported\n", reg->reg); 498b2ce5617SAnders Roxell adv7511_inv_register(sd); 499b2ce5617SAnders Roxell break; 500b2ce5617SAnders Roxell } 501b2ce5617SAnders Roxell return 0; 502b2ce5617SAnders Roxell } 503b2ce5617SAnders Roxell #endif 504b2ce5617SAnders Roxell 505b2ce5617SAnders Roxell struct adv7511_cfg_read_infoframe { 506b2ce5617SAnders Roxell const char *desc; 507b2ce5617SAnders Roxell u8 present_reg; 508b2ce5617SAnders Roxell u8 present_mask; 509b2ce5617SAnders Roxell u8 header[3]; 510b2ce5617SAnders Roxell u16 payload_addr; 511b2ce5617SAnders Roxell }; 512b2ce5617SAnders Roxell 513b2ce5617SAnders Roxell static u8 hdmi_infoframe_checksum(u8 *ptr, size_t size) 514b2ce5617SAnders Roxell { 515b2ce5617SAnders Roxell u8 csum = 0; 516b2ce5617SAnders Roxell size_t i; 517b2ce5617SAnders Roxell 518b2ce5617SAnders Roxell /* compute checksum */ 519b2ce5617SAnders Roxell for (i = 0; i < size; i++) 520b2ce5617SAnders Roxell csum += ptr[i]; 521b2ce5617SAnders Roxell 522b2ce5617SAnders Roxell return 256 - csum; 523b2ce5617SAnders Roxell } 524b2ce5617SAnders Roxell 525b2ce5617SAnders Roxell static void log_infoframe(struct v4l2_subdev *sd, const struct adv7511_cfg_read_infoframe *cri) 526b2ce5617SAnders Roxell { 527b2ce5617SAnders Roxell struct i2c_client *client = v4l2_get_subdevdata(sd); 528b2ce5617SAnders Roxell struct device *dev = &client->dev; 529b2ce5617SAnders Roxell union hdmi_infoframe frame; 530b2ce5617SAnders Roxell u8 buffer[32]; 531b2ce5617SAnders Roxell u8 len; 532b2ce5617SAnders Roxell int i; 533b2ce5617SAnders Roxell 534b2ce5617SAnders Roxell if (!(adv7511_rd(sd, cri->present_reg) & cri->present_mask)) { 535b2ce5617SAnders Roxell v4l2_info(sd, "%s infoframe not transmitted\n", cri->desc); 536b2ce5617SAnders Roxell return; 537b2ce5617SAnders Roxell } 538b2ce5617SAnders Roxell 539b2ce5617SAnders Roxell memcpy(buffer, cri->header, sizeof(cri->header)); 540b2ce5617SAnders Roxell 541b2ce5617SAnders Roxell len = buffer[2]; 542b2ce5617SAnders Roxell 543b2ce5617SAnders Roxell if (len + 4 > sizeof(buffer)) { 544b2ce5617SAnders Roxell v4l2_err(sd, "%s: invalid %s infoframe length %d\n", __func__, cri->desc, len); 545b2ce5617SAnders Roxell return; 546b2ce5617SAnders Roxell } 547b2ce5617SAnders Roxell 548b2ce5617SAnders Roxell if (cri->payload_addr >= 0x100) { 549b2ce5617SAnders Roxell for (i = 0; i < len; i++) 550b2ce5617SAnders Roxell buffer[i + 4] = adv7511_pktmem_rd(sd, cri->payload_addr + i - 0x100); 551b2ce5617SAnders Roxell } else { 552b2ce5617SAnders Roxell for (i = 0; i < len; i++) 553b2ce5617SAnders Roxell buffer[i + 4] = adv7511_rd(sd, cri->payload_addr + i); 554b2ce5617SAnders Roxell } 555b2ce5617SAnders Roxell buffer[3] = 0; 556b2ce5617SAnders Roxell buffer[3] = hdmi_infoframe_checksum(buffer, len + 4); 557b2ce5617SAnders Roxell 558b2ce5617SAnders Roxell if (hdmi_infoframe_unpack(&frame, buffer, sizeof(buffer)) < 0) { 559b2ce5617SAnders Roxell v4l2_err(sd, "%s: unpack of %s infoframe failed\n", __func__, cri->desc); 560b2ce5617SAnders Roxell return; 561b2ce5617SAnders Roxell } 562b2ce5617SAnders Roxell 563b2ce5617SAnders Roxell hdmi_infoframe_log(KERN_INFO, dev, &frame); 564b2ce5617SAnders Roxell } 565b2ce5617SAnders Roxell 566b2ce5617SAnders Roxell static void adv7511_log_infoframes(struct v4l2_subdev *sd) 567b2ce5617SAnders Roxell { 568b2ce5617SAnders Roxell static const struct adv7511_cfg_read_infoframe cri[] = { 569b2ce5617SAnders Roxell { "AVI", 0x44, 0x10, { 0x82, 2, 13 }, 0x55 }, 570b2ce5617SAnders Roxell { "Audio", 0x44, 0x08, { 0x84, 1, 10 }, 0x73 }, 571b2ce5617SAnders Roxell { "SDP", 0x40, 0x40, { 0x83, 1, 25 }, 0x103 }, 572b2ce5617SAnders Roxell }; 573b2ce5617SAnders Roxell int i; 574b2ce5617SAnders Roxell 575b2ce5617SAnders Roxell for (i = 0; i < ARRAY_SIZE(cri); i++) 576b2ce5617SAnders Roxell log_infoframe(sd, &cri[i]); 577b2ce5617SAnders Roxell } 578b2ce5617SAnders Roxell 579b2ce5617SAnders Roxell static int adv7511_log_status(struct v4l2_subdev *sd) 580b2ce5617SAnders Roxell { 581b2ce5617SAnders Roxell struct adv7511_state *state = get_adv7511_state(sd); 582b2ce5617SAnders Roxell struct adv7511_state_edid *edid = &state->edid; 583b2ce5617SAnders Roxell int i; 584b2ce5617SAnders Roxell 585b2ce5617SAnders Roxell static const char * const states[] = { 586b2ce5617SAnders Roxell "in reset", 587b2ce5617SAnders Roxell "reading EDID", 588b2ce5617SAnders Roxell "idle", 589b2ce5617SAnders Roxell "initializing HDCP", 590b2ce5617SAnders Roxell "HDCP enabled", 591b2ce5617SAnders Roxell "initializing HDCP repeater", 592b2ce5617SAnders Roxell "6", "7", "8", "9", "A", "B", "C", "D", "E", "F" 593b2ce5617SAnders Roxell }; 594b2ce5617SAnders Roxell static const char * const errors[] = { 595b2ce5617SAnders Roxell "no error", 596b2ce5617SAnders Roxell "bad receiver BKSV", 597b2ce5617SAnders Roxell "Ri mismatch", 598b2ce5617SAnders Roxell "Pj mismatch", 599b2ce5617SAnders Roxell "i2c error", 600b2ce5617SAnders Roxell "timed out", 601b2ce5617SAnders Roxell "max repeater cascade exceeded", 602b2ce5617SAnders Roxell "hash check failed", 603b2ce5617SAnders Roxell "too many devices", 604b2ce5617SAnders Roxell "9", "A", "B", "C", "D", "E", "F" 605b2ce5617SAnders Roxell }; 606b2ce5617SAnders Roxell 607b2ce5617SAnders Roxell v4l2_info(sd, "power %s\n", state->power_on ? "on" : "off"); 608b2ce5617SAnders Roxell v4l2_info(sd, "%s hotplug, %s Rx Sense, %s EDID (%d block(s))\n", 609b2ce5617SAnders Roxell (adv7511_rd(sd, 0x42) & MASK_ADV7511_HPD_DETECT) ? "detected" : "no", 610b2ce5617SAnders Roxell (adv7511_rd(sd, 0x42) & MASK_ADV7511_MSEN_DETECT) ? "detected" : "no", 611b2ce5617SAnders Roxell edid->segments ? "found" : "no", 612b2ce5617SAnders Roxell edid->blocks); 613b2ce5617SAnders Roxell v4l2_info(sd, "%s output %s\n", 614b2ce5617SAnders Roxell (adv7511_rd(sd, 0xaf) & 0x02) ? 615b2ce5617SAnders Roxell "HDMI" : "DVI-D", 616b2ce5617SAnders Roxell (adv7511_rd(sd, 0xa1) & 0x3c) ? 617b2ce5617SAnders Roxell "disabled" : "enabled"); 618b2ce5617SAnders Roxell v4l2_info(sd, "state: %s, error: %s, detect count: %u, msk/irq: %02x/%02x\n", 619b2ce5617SAnders Roxell states[adv7511_rd(sd, 0xc8) & 0xf], 620b2ce5617SAnders Roxell errors[adv7511_rd(sd, 0xc8) >> 4], state->edid_detect_counter, 621b2ce5617SAnders Roxell adv7511_rd(sd, 0x94), adv7511_rd(sd, 0x96)); 622b2ce5617SAnders Roxell v4l2_info(sd, "RGB quantization: %s range\n", adv7511_rd(sd, 0x18) & 0x80 ? "limited" : "full"); 623b2ce5617SAnders Roxell if (adv7511_rd(sd, 0xaf) & 0x02) { 624b2ce5617SAnders Roxell /* HDMI only */ 625b2ce5617SAnders Roxell u8 manual_cts = adv7511_rd(sd, 0x0a) & 0x80; 626b2ce5617SAnders Roxell u32 N = (adv7511_rd(sd, 0x01) & 0xf) << 16 | 627b2ce5617SAnders Roxell adv7511_rd(sd, 0x02) << 8 | 628b2ce5617SAnders Roxell adv7511_rd(sd, 0x03); 629b2ce5617SAnders Roxell u8 vic_detect = adv7511_rd(sd, 0x3e) >> 2; 630b2ce5617SAnders Roxell u8 vic_sent = adv7511_rd(sd, 0x3d) & 0x3f; 631b2ce5617SAnders Roxell u32 CTS; 632b2ce5617SAnders Roxell 633b2ce5617SAnders Roxell if (manual_cts) 634b2ce5617SAnders Roxell CTS = (adv7511_rd(sd, 0x07) & 0xf) << 16 | 635b2ce5617SAnders Roxell adv7511_rd(sd, 0x08) << 8 | 636b2ce5617SAnders Roxell adv7511_rd(sd, 0x09); 637b2ce5617SAnders Roxell else 638b2ce5617SAnders Roxell CTS = (adv7511_rd(sd, 0x04) & 0xf) << 16 | 639b2ce5617SAnders Roxell adv7511_rd(sd, 0x05) << 8 | 640b2ce5617SAnders Roxell adv7511_rd(sd, 0x06); 641b2ce5617SAnders Roxell v4l2_info(sd, "CTS %s mode: N %d, CTS %d\n", 642b2ce5617SAnders Roxell manual_cts ? "manual" : "automatic", N, CTS); 643b2ce5617SAnders Roxell v4l2_info(sd, "VIC: detected %d, sent %d\n", 644b2ce5617SAnders Roxell vic_detect, vic_sent); 645b2ce5617SAnders Roxell adv7511_log_infoframes(sd); 646b2ce5617SAnders Roxell } 647b2ce5617SAnders Roxell if (state->dv_timings.type == V4L2_DV_BT_656_1120) 648b2ce5617SAnders Roxell v4l2_print_dv_timings(sd->name, "timings: ", 649b2ce5617SAnders Roxell &state->dv_timings, false); 650b2ce5617SAnders Roxell else 651b2ce5617SAnders Roxell v4l2_info(sd, "no timings set\n"); 652b2ce5617SAnders Roxell v4l2_info(sd, "i2c edid addr: 0x%x\n", state->i2c_edid_addr); 653b2ce5617SAnders Roxell 654b2ce5617SAnders Roxell if (state->i2c_cec == NULL) 655b2ce5617SAnders Roxell return 0; 656b2ce5617SAnders Roxell 657b2ce5617SAnders Roxell v4l2_info(sd, "i2c cec addr: 0x%x\n", state->i2c_cec_addr); 658b2ce5617SAnders Roxell 659b2ce5617SAnders Roxell v4l2_info(sd, "CEC: %s\n", state->cec_enabled_adap ? 660b2ce5617SAnders Roxell "enabled" : "disabled"); 661b2ce5617SAnders Roxell if (state->cec_enabled_adap) { 662b2ce5617SAnders Roxell for (i = 0; i < ADV7511_MAX_ADDRS; i++) { 663b2ce5617SAnders Roxell bool is_valid = state->cec_valid_addrs & (1 << i); 664b2ce5617SAnders Roxell 665b2ce5617SAnders Roxell if (is_valid) 666b2ce5617SAnders Roxell v4l2_info(sd, "CEC Logical Address: 0x%x\n", 667b2ce5617SAnders Roxell state->cec_addr[i]); 668b2ce5617SAnders Roxell } 669b2ce5617SAnders Roxell } 670b2ce5617SAnders Roxell v4l2_info(sd, "i2c pktmem addr: 0x%x\n", state->i2c_pktmem_addr); 671b2ce5617SAnders Roxell return 0; 672b2ce5617SAnders Roxell } 673b2ce5617SAnders Roxell 674b2ce5617SAnders Roxell /* Power up/down adv7511 */ 675b2ce5617SAnders Roxell static int adv7511_s_power(struct v4l2_subdev *sd, int on) 676b2ce5617SAnders Roxell { 677b2ce5617SAnders Roxell struct adv7511_state *state = get_adv7511_state(sd); 678b2ce5617SAnders Roxell const int retries = 20; 679b2ce5617SAnders Roxell int i; 680b2ce5617SAnders Roxell 681b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, "%s: power %s\n", __func__, on ? "on" : "off"); 682b2ce5617SAnders Roxell 683b2ce5617SAnders Roxell state->power_on = on; 684b2ce5617SAnders Roxell 685b2ce5617SAnders Roxell if (!on) { 686b2ce5617SAnders Roxell /* Power down */ 687b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x41, 0xbf, 0x40); 688b2ce5617SAnders Roxell return true; 689b2ce5617SAnders Roxell } 690b2ce5617SAnders Roxell 691b2ce5617SAnders Roxell /* Power up */ 692b2ce5617SAnders Roxell /* The adv7511 does not always come up immediately. 693b2ce5617SAnders Roxell Retry multiple times. */ 694b2ce5617SAnders Roxell for (i = 0; i < retries; i++) { 695b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x41, 0xbf, 0x0); 696b2ce5617SAnders Roxell if ((adv7511_rd(sd, 0x41) & 0x40) == 0) 697b2ce5617SAnders Roxell break; 698b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x41, 0xbf, 0x40); 699b2ce5617SAnders Roxell msleep(10); 700b2ce5617SAnders Roxell } 701b2ce5617SAnders Roxell if (i == retries) { 702b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, "%s: failed to powerup the adv7511!\n", __func__); 703b2ce5617SAnders Roxell adv7511_s_power(sd, 0); 704b2ce5617SAnders Roxell return false; 705b2ce5617SAnders Roxell } 706b2ce5617SAnders Roxell if (i > 1) 707b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, "%s: needed %d retries to powerup the adv7511\n", __func__, i); 708b2ce5617SAnders Roxell 709b2ce5617SAnders Roxell /* Reserved registers that must be set */ 710b2ce5617SAnders Roxell adv7511_wr(sd, 0x98, 0x03); 711b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x9a, 0xfe, 0x70); 712b2ce5617SAnders Roxell adv7511_wr(sd, 0x9c, 0x30); 713b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x9d, 0xfc, 0x01); 714b2ce5617SAnders Roxell adv7511_wr(sd, 0xa2, 0xa4); 715b2ce5617SAnders Roxell adv7511_wr(sd, 0xa3, 0xa4); 716b2ce5617SAnders Roxell adv7511_wr(sd, 0xe0, 0xd0); 717b2ce5617SAnders Roxell adv7511_wr(sd, 0xf9, 0x00); 718b2ce5617SAnders Roxell 719b2ce5617SAnders Roxell adv7511_wr(sd, 0x43, state->i2c_edid_addr); 720b2ce5617SAnders Roxell adv7511_wr(sd, 0x45, state->i2c_pktmem_addr); 721b2ce5617SAnders Roxell 722b2ce5617SAnders Roxell /* Set number of attempts to read the EDID */ 723b2ce5617SAnders Roxell adv7511_wr(sd, 0xc9, 0xf); 724b2ce5617SAnders Roxell return true; 725b2ce5617SAnders Roxell } 726b2ce5617SAnders Roxell 727b2ce5617SAnders Roxell #if IS_ENABLED(CONFIG_VIDEO_ADV7511_CEC) 728b2ce5617SAnders Roxell static int adv7511_cec_adap_enable(struct cec_adapter *adap, bool enable) 729b2ce5617SAnders Roxell { 730b2ce5617SAnders Roxell struct adv7511_state *state = cec_get_drvdata(adap); 731b2ce5617SAnders Roxell struct v4l2_subdev *sd = &state->sd; 732b2ce5617SAnders Roxell 733b2ce5617SAnders Roxell if (state->i2c_cec == NULL) 734b2ce5617SAnders Roxell return -EIO; 735b2ce5617SAnders Roxell 736b2ce5617SAnders Roxell if (!state->cec_enabled_adap && enable) { 737b2ce5617SAnders Roxell /* power up cec section */ 738b2ce5617SAnders Roxell adv7511_cec_write_and_or(sd, 0x4e, 0xfc, 0x01); 739b2ce5617SAnders Roxell /* legacy mode and clear all rx buffers */ 740b2ce5617SAnders Roxell adv7511_cec_write(sd, 0x4a, 0x00); 741b2ce5617SAnders Roxell adv7511_cec_write(sd, 0x4a, 0x07); 742b2ce5617SAnders Roxell adv7511_cec_write_and_or(sd, 0x11, 0xfe, 0); /* initially disable tx */ 743b2ce5617SAnders Roxell /* enabled irqs: */ 744b2ce5617SAnders Roxell /* tx: ready */ 745b2ce5617SAnders Roxell /* tx: arbitration lost */ 746b2ce5617SAnders Roxell /* tx: retry timeout */ 747b2ce5617SAnders Roxell /* rx: ready 1 */ 748b2ce5617SAnders Roxell if (state->enabled_irq) 749b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x95, 0xc0, 0x39); 750b2ce5617SAnders Roxell } else if (state->cec_enabled_adap && !enable) { 751b2ce5617SAnders Roxell if (state->enabled_irq) 752b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x95, 0xc0, 0x00); 753b2ce5617SAnders Roxell /* disable address mask 1-3 */ 754b2ce5617SAnders Roxell adv7511_cec_write_and_or(sd, 0x4b, 0x8f, 0x00); 755b2ce5617SAnders Roxell /* power down cec section */ 756b2ce5617SAnders Roxell adv7511_cec_write_and_or(sd, 0x4e, 0xfc, 0x00); 757b2ce5617SAnders Roxell state->cec_valid_addrs = 0; 758b2ce5617SAnders Roxell } 759b2ce5617SAnders Roxell state->cec_enabled_adap = enable; 760b2ce5617SAnders Roxell return 0; 761b2ce5617SAnders Roxell } 762b2ce5617SAnders Roxell 763b2ce5617SAnders Roxell static int adv7511_cec_adap_log_addr(struct cec_adapter *adap, u8 addr) 764b2ce5617SAnders Roxell { 765b2ce5617SAnders Roxell struct adv7511_state *state = cec_get_drvdata(adap); 766b2ce5617SAnders Roxell struct v4l2_subdev *sd = &state->sd; 767b2ce5617SAnders Roxell unsigned int i, free_idx = ADV7511_MAX_ADDRS; 768b2ce5617SAnders Roxell 769b2ce5617SAnders Roxell if (!state->cec_enabled_adap) 770b2ce5617SAnders Roxell return addr == CEC_LOG_ADDR_INVALID ? 0 : -EIO; 771b2ce5617SAnders Roxell 772b2ce5617SAnders Roxell if (addr == CEC_LOG_ADDR_INVALID) { 773b2ce5617SAnders Roxell adv7511_cec_write_and_or(sd, 0x4b, 0x8f, 0); 774b2ce5617SAnders Roxell state->cec_valid_addrs = 0; 775b2ce5617SAnders Roxell return 0; 776b2ce5617SAnders Roxell } 777b2ce5617SAnders Roxell 778b2ce5617SAnders Roxell for (i = 0; i < ADV7511_MAX_ADDRS; i++) { 779b2ce5617SAnders Roxell bool is_valid = state->cec_valid_addrs & (1 << i); 780b2ce5617SAnders Roxell 781b2ce5617SAnders Roxell if (free_idx == ADV7511_MAX_ADDRS && !is_valid) 782b2ce5617SAnders Roxell free_idx = i; 783b2ce5617SAnders Roxell if (is_valid && state->cec_addr[i] == addr) 784b2ce5617SAnders Roxell return 0; 785b2ce5617SAnders Roxell } 786b2ce5617SAnders Roxell if (i == ADV7511_MAX_ADDRS) { 787b2ce5617SAnders Roxell i = free_idx; 788b2ce5617SAnders Roxell if (i == ADV7511_MAX_ADDRS) 789b2ce5617SAnders Roxell return -ENXIO; 790b2ce5617SAnders Roxell } 791b2ce5617SAnders Roxell state->cec_addr[i] = addr; 792b2ce5617SAnders Roxell state->cec_valid_addrs |= 1 << i; 793b2ce5617SAnders Roxell 794b2ce5617SAnders Roxell switch (i) { 795b2ce5617SAnders Roxell case 0: 796b2ce5617SAnders Roxell /* enable address mask 0 */ 797b2ce5617SAnders Roxell adv7511_cec_write_and_or(sd, 0x4b, 0xef, 0x10); 798b2ce5617SAnders Roxell /* set address for mask 0 */ 799b2ce5617SAnders Roxell adv7511_cec_write_and_or(sd, 0x4c, 0xf0, addr); 800b2ce5617SAnders Roxell break; 801b2ce5617SAnders Roxell case 1: 802b2ce5617SAnders Roxell /* enable address mask 1 */ 803b2ce5617SAnders Roxell adv7511_cec_write_and_or(sd, 0x4b, 0xdf, 0x20); 804b2ce5617SAnders Roxell /* set address for mask 1 */ 805b2ce5617SAnders Roxell adv7511_cec_write_and_or(sd, 0x4c, 0x0f, addr << 4); 806b2ce5617SAnders Roxell break; 807b2ce5617SAnders Roxell case 2: 808b2ce5617SAnders Roxell /* enable address mask 2 */ 809b2ce5617SAnders Roxell adv7511_cec_write_and_or(sd, 0x4b, 0xbf, 0x40); 810b2ce5617SAnders Roxell /* set address for mask 1 */ 811b2ce5617SAnders Roxell adv7511_cec_write_and_or(sd, 0x4d, 0xf0, addr); 812b2ce5617SAnders Roxell break; 813b2ce5617SAnders Roxell } 814b2ce5617SAnders Roxell return 0; 815b2ce5617SAnders Roxell } 816b2ce5617SAnders Roxell 817b2ce5617SAnders Roxell static int adv7511_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, 818b2ce5617SAnders Roxell u32 signal_free_time, struct cec_msg *msg) 819b2ce5617SAnders Roxell { 820b2ce5617SAnders Roxell struct adv7511_state *state = cec_get_drvdata(adap); 821b2ce5617SAnders Roxell struct v4l2_subdev *sd = &state->sd; 822b2ce5617SAnders Roxell u8 len = msg->len; 823b2ce5617SAnders Roxell unsigned int i; 824b2ce5617SAnders Roxell 825b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, "%s: len %d\n", __func__, len); 826b2ce5617SAnders Roxell 827b2ce5617SAnders Roxell if (len > 16) { 828b2ce5617SAnders Roxell v4l2_err(sd, "%s: len exceeded 16 (%d)\n", __func__, len); 829b2ce5617SAnders Roxell return -EINVAL; 830b2ce5617SAnders Roxell } 831b2ce5617SAnders Roxell 832b2ce5617SAnders Roxell /* 833b2ce5617SAnders Roxell * The number of retries is the number of attempts - 1, but retry 834b2ce5617SAnders Roxell * at least once. It's not clear if a value of 0 is allowed, so 835b2ce5617SAnders Roxell * let's do at least one retry. 836b2ce5617SAnders Roxell */ 837b2ce5617SAnders Roxell adv7511_cec_write_and_or(sd, 0x12, ~0x70, max(1, attempts - 1) << 4); 838b2ce5617SAnders Roxell 839b2ce5617SAnders Roxell /* clear cec tx irq status */ 840b2ce5617SAnders Roxell adv7511_wr(sd, 0x97, 0x38); 841b2ce5617SAnders Roxell 842b2ce5617SAnders Roxell /* write data */ 843b2ce5617SAnders Roxell for (i = 0; i < len; i++) 844b2ce5617SAnders Roxell adv7511_cec_write(sd, i, msg->msg[i]); 845b2ce5617SAnders Roxell 846b2ce5617SAnders Roxell /* set length (data + header) */ 847b2ce5617SAnders Roxell adv7511_cec_write(sd, 0x10, len); 848b2ce5617SAnders Roxell /* start transmit, enable tx */ 849b2ce5617SAnders Roxell adv7511_cec_write(sd, 0x11, 0x01); 850b2ce5617SAnders Roxell return 0; 851b2ce5617SAnders Roxell } 852b2ce5617SAnders Roxell 853b2ce5617SAnders Roxell static void adv_cec_tx_raw_status(struct v4l2_subdev *sd, u8 tx_raw_status) 854b2ce5617SAnders Roxell { 855b2ce5617SAnders Roxell struct adv7511_state *state = get_adv7511_state(sd); 856b2ce5617SAnders Roxell 857b2ce5617SAnders Roxell if ((adv7511_cec_read(sd, 0x11) & 0x01) == 0) { 858b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, "%s: tx raw: tx disabled\n", __func__); 859b2ce5617SAnders Roxell return; 860b2ce5617SAnders Roxell } 861b2ce5617SAnders Roxell 862b2ce5617SAnders Roxell if (tx_raw_status & 0x10) { 863b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, 864b2ce5617SAnders Roxell "%s: tx raw: arbitration lost\n", __func__); 865b2ce5617SAnders Roxell cec_transmit_done(state->cec_adap, CEC_TX_STATUS_ARB_LOST, 866b2ce5617SAnders Roxell 1, 0, 0, 0); 867b2ce5617SAnders Roxell return; 868b2ce5617SAnders Roxell } 869b2ce5617SAnders Roxell if (tx_raw_status & 0x08) { 870b2ce5617SAnders Roxell u8 status; 871b2ce5617SAnders Roxell u8 nack_cnt; 872b2ce5617SAnders Roxell u8 low_drive_cnt; 873b2ce5617SAnders Roxell 874b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, "%s: tx raw: retry failed\n", __func__); 875b2ce5617SAnders Roxell /* 876b2ce5617SAnders Roxell * We set this status bit since this hardware performs 877b2ce5617SAnders Roxell * retransmissions. 878b2ce5617SAnders Roxell */ 879b2ce5617SAnders Roxell status = CEC_TX_STATUS_MAX_RETRIES; 880b2ce5617SAnders Roxell nack_cnt = adv7511_cec_read(sd, 0x14) & 0xf; 881b2ce5617SAnders Roxell if (nack_cnt) 882b2ce5617SAnders Roxell status |= CEC_TX_STATUS_NACK; 883b2ce5617SAnders Roxell low_drive_cnt = adv7511_cec_read(sd, 0x14) >> 4; 884b2ce5617SAnders Roxell if (low_drive_cnt) 885b2ce5617SAnders Roxell status |= CEC_TX_STATUS_LOW_DRIVE; 886b2ce5617SAnders Roxell cec_transmit_done(state->cec_adap, status, 887b2ce5617SAnders Roxell 0, nack_cnt, low_drive_cnt, 0); 888b2ce5617SAnders Roxell return; 889b2ce5617SAnders Roxell } 890b2ce5617SAnders Roxell if (tx_raw_status & 0x20) { 891b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, "%s: tx raw: ready ok\n", __func__); 892b2ce5617SAnders Roxell cec_transmit_done(state->cec_adap, CEC_TX_STATUS_OK, 0, 0, 0, 0); 893b2ce5617SAnders Roxell return; 894b2ce5617SAnders Roxell } 895b2ce5617SAnders Roxell } 896b2ce5617SAnders Roxell 897b2ce5617SAnders Roxell static const struct cec_adap_ops adv7511_cec_adap_ops = { 898b2ce5617SAnders Roxell .adap_enable = adv7511_cec_adap_enable, 899b2ce5617SAnders Roxell .adap_log_addr = adv7511_cec_adap_log_addr, 900b2ce5617SAnders Roxell .adap_transmit = adv7511_cec_adap_transmit, 901b2ce5617SAnders Roxell }; 902b2ce5617SAnders Roxell #endif 903b2ce5617SAnders Roxell 904b2ce5617SAnders Roxell /* Enable interrupts */ 905b2ce5617SAnders Roxell static void adv7511_set_isr(struct v4l2_subdev *sd, bool enable) 906b2ce5617SAnders Roxell { 907b2ce5617SAnders Roxell struct adv7511_state *state = get_adv7511_state(sd); 908b2ce5617SAnders Roxell u8 irqs = MASK_ADV7511_HPD_INT | MASK_ADV7511_MSEN_INT; 909b2ce5617SAnders Roxell u8 irqs_rd; 910b2ce5617SAnders Roxell int retries = 100; 911b2ce5617SAnders Roxell 912b2ce5617SAnders Roxell v4l2_dbg(2, debug, sd, "%s: %s\n", __func__, enable ? "enable" : "disable"); 913b2ce5617SAnders Roxell 914b2ce5617SAnders Roxell if (state->enabled_irq == enable) 915b2ce5617SAnders Roxell return; 916b2ce5617SAnders Roxell state->enabled_irq = enable; 917b2ce5617SAnders Roxell 918b2ce5617SAnders Roxell /* The datasheet says that the EDID ready interrupt should be 919b2ce5617SAnders Roxell disabled if there is no hotplug. */ 920b2ce5617SAnders Roxell if (!enable) 921b2ce5617SAnders Roxell irqs = 0; 922b2ce5617SAnders Roxell else if (adv7511_have_hotplug(sd)) 923b2ce5617SAnders Roxell irqs |= MASK_ADV7511_EDID_RDY_INT; 924b2ce5617SAnders Roxell 925b2ce5617SAnders Roxell /* 926b2ce5617SAnders Roxell * This i2c write can fail (approx. 1 in 1000 writes). But it 927b2ce5617SAnders Roxell * is essential that this register is correct, so retry it 928b2ce5617SAnders Roxell * multiple times. 929b2ce5617SAnders Roxell * 930b2ce5617SAnders Roxell * Note that the i2c write does not report an error, but the readback 931b2ce5617SAnders Roxell * clearly shows the wrong value. 932b2ce5617SAnders Roxell */ 933b2ce5617SAnders Roxell do { 934b2ce5617SAnders Roxell adv7511_wr(sd, 0x94, irqs); 935b2ce5617SAnders Roxell irqs_rd = adv7511_rd(sd, 0x94); 936b2ce5617SAnders Roxell } while (retries-- && irqs_rd != irqs); 937b2ce5617SAnders Roxell 938b2ce5617SAnders Roxell if (irqs_rd != irqs) 939b2ce5617SAnders Roxell v4l2_err(sd, "Could not set interrupts: hw failure?\n"); 940b2ce5617SAnders Roxell 941b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x95, 0xc0, 942b2ce5617SAnders Roxell (state->cec_enabled_adap && enable) ? 0x39 : 0x00); 943b2ce5617SAnders Roxell } 944b2ce5617SAnders Roxell 945b2ce5617SAnders Roxell /* Interrupt handler */ 946b2ce5617SAnders Roxell static int adv7511_isr(struct v4l2_subdev *sd, u32 status, bool *handled) 947b2ce5617SAnders Roxell { 948b2ce5617SAnders Roxell u8 irq_status; 949b2ce5617SAnders Roxell u8 cec_irq; 950b2ce5617SAnders Roxell 951b2ce5617SAnders Roxell /* disable interrupts to prevent a race condition */ 952b2ce5617SAnders Roxell adv7511_set_isr(sd, false); 953b2ce5617SAnders Roxell irq_status = adv7511_rd(sd, 0x96); 954b2ce5617SAnders Roxell cec_irq = adv7511_rd(sd, 0x97); 955b2ce5617SAnders Roxell /* clear detected interrupts */ 956b2ce5617SAnders Roxell adv7511_wr(sd, 0x96, irq_status); 957b2ce5617SAnders Roxell adv7511_wr(sd, 0x97, cec_irq); 958b2ce5617SAnders Roxell 959b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, "%s: irq 0x%x, cec-irq 0x%x\n", __func__, 960b2ce5617SAnders Roxell irq_status, cec_irq); 961b2ce5617SAnders Roxell 962b2ce5617SAnders Roxell if (irq_status & (MASK_ADV7511_HPD_INT | MASK_ADV7511_MSEN_INT)) 963b2ce5617SAnders Roxell adv7511_check_monitor_present_status(sd); 964b2ce5617SAnders Roxell if (irq_status & MASK_ADV7511_EDID_RDY_INT) 965b2ce5617SAnders Roxell adv7511_check_edid_status(sd); 966b2ce5617SAnders Roxell 967b2ce5617SAnders Roxell #if IS_ENABLED(CONFIG_VIDEO_ADV7511_CEC) 968b2ce5617SAnders Roxell if (cec_irq & 0x38) 969b2ce5617SAnders Roxell adv_cec_tx_raw_status(sd, cec_irq); 970b2ce5617SAnders Roxell 971b2ce5617SAnders Roxell if (cec_irq & 1) { 972b2ce5617SAnders Roxell struct adv7511_state *state = get_adv7511_state(sd); 973b2ce5617SAnders Roxell struct cec_msg msg; 974b2ce5617SAnders Roxell 975b2ce5617SAnders Roxell msg.len = adv7511_cec_read(sd, 0x25) & 0x1f; 976b2ce5617SAnders Roxell 977b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, "%s: cec msg len %d\n", __func__, 978b2ce5617SAnders Roxell msg.len); 979b2ce5617SAnders Roxell 980b2ce5617SAnders Roxell if (msg.len > 16) 981b2ce5617SAnders Roxell msg.len = 16; 982b2ce5617SAnders Roxell 983b2ce5617SAnders Roxell if (msg.len) { 984b2ce5617SAnders Roxell u8 i; 985b2ce5617SAnders Roxell 986b2ce5617SAnders Roxell for (i = 0; i < msg.len; i++) 987b2ce5617SAnders Roxell msg.msg[i] = adv7511_cec_read(sd, i + 0x15); 988b2ce5617SAnders Roxell 989b2ce5617SAnders Roxell adv7511_cec_write(sd, 0x4a, 0); /* toggle to re-enable rx 1 */ 990b2ce5617SAnders Roxell adv7511_cec_write(sd, 0x4a, 1); 991b2ce5617SAnders Roxell cec_received_msg(state->cec_adap, &msg); 992b2ce5617SAnders Roxell } 993b2ce5617SAnders Roxell } 994b2ce5617SAnders Roxell #endif 995b2ce5617SAnders Roxell 996b2ce5617SAnders Roxell /* enable interrupts */ 997b2ce5617SAnders Roxell adv7511_set_isr(sd, true); 998b2ce5617SAnders Roxell 999b2ce5617SAnders Roxell if (handled) 1000b2ce5617SAnders Roxell *handled = true; 1001b2ce5617SAnders Roxell return 0; 1002b2ce5617SAnders Roxell } 1003b2ce5617SAnders Roxell 1004b2ce5617SAnders Roxell static const struct v4l2_subdev_core_ops adv7511_core_ops = { 1005b2ce5617SAnders Roxell .log_status = adv7511_log_status, 1006b2ce5617SAnders Roxell #ifdef CONFIG_VIDEO_ADV_DEBUG 1007b2ce5617SAnders Roxell .g_register = adv7511_g_register, 1008b2ce5617SAnders Roxell .s_register = adv7511_s_register, 1009b2ce5617SAnders Roxell #endif 1010b2ce5617SAnders Roxell .s_power = adv7511_s_power, 1011b2ce5617SAnders Roxell .interrupt_service_routine = adv7511_isr, 1012b2ce5617SAnders Roxell }; 1013b2ce5617SAnders Roxell 1014b2ce5617SAnders Roxell /* ------------------------------ VIDEO OPS ------------------------------ */ 1015b2ce5617SAnders Roxell 1016b2ce5617SAnders Roxell /* Enable/disable adv7511 output */ 1017b2ce5617SAnders Roxell static int adv7511_s_stream(struct v4l2_subdev *sd, int enable) 1018b2ce5617SAnders Roxell { 1019b2ce5617SAnders Roxell struct adv7511_state *state = get_adv7511_state(sd); 1020b2ce5617SAnders Roxell 1021b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, "%s: %sable\n", __func__, (enable ? "en" : "dis")); 1022b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0xa1, ~0x3c, (enable ? 0 : 0x3c)); 1023b2ce5617SAnders Roxell if (enable) { 1024b2ce5617SAnders Roxell adv7511_check_monitor_present_status(sd); 1025b2ce5617SAnders Roxell } else { 1026b2ce5617SAnders Roxell adv7511_s_power(sd, 0); 1027b2ce5617SAnders Roxell state->have_monitor = false; 1028b2ce5617SAnders Roxell } 1029b2ce5617SAnders Roxell return 0; 1030b2ce5617SAnders Roxell } 1031b2ce5617SAnders Roxell 1032b2ce5617SAnders Roxell static int adv7511_s_dv_timings(struct v4l2_subdev *sd, 1033b2ce5617SAnders Roxell struct v4l2_dv_timings *timings) 1034b2ce5617SAnders Roxell { 1035b2ce5617SAnders Roxell struct adv7511_state *state = get_adv7511_state(sd); 1036b2ce5617SAnders Roxell struct v4l2_bt_timings *bt = &timings->bt; 1037b2ce5617SAnders Roxell u32 fps; 1038b2ce5617SAnders Roxell 1039b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, "%s:\n", __func__); 1040b2ce5617SAnders Roxell 1041b2ce5617SAnders Roxell /* quick sanity check */ 1042b2ce5617SAnders Roxell if (!v4l2_valid_dv_timings(timings, &adv7511_timings_cap, NULL, NULL)) 1043b2ce5617SAnders Roxell return -EINVAL; 1044b2ce5617SAnders Roxell 1045b2ce5617SAnders Roxell /* Fill the optional fields .standards and .flags in struct v4l2_dv_timings 1046b2ce5617SAnders Roxell if the format is one of the CEA or DMT timings. */ 1047b2ce5617SAnders Roxell v4l2_find_dv_timings_cap(timings, &adv7511_timings_cap, 0, NULL, NULL); 1048b2ce5617SAnders Roxell 1049b2ce5617SAnders Roxell /* save timings */ 1050b2ce5617SAnders Roxell state->dv_timings = *timings; 1051b2ce5617SAnders Roxell 1052b2ce5617SAnders Roxell /* set h/vsync polarities */ 1053b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x17, 0x9f, 1054b2ce5617SAnders Roxell ((bt->polarities & V4L2_DV_VSYNC_POS_POL) ? 0 : 0x40) | 1055b2ce5617SAnders Roxell ((bt->polarities & V4L2_DV_HSYNC_POS_POL) ? 0 : 0x20)); 1056b2ce5617SAnders Roxell 1057b2ce5617SAnders Roxell fps = (u32)bt->pixelclock / (V4L2_DV_BT_FRAME_WIDTH(bt) * V4L2_DV_BT_FRAME_HEIGHT(bt)); 1058b2ce5617SAnders Roxell switch (fps) { 1059b2ce5617SAnders Roxell case 24: 1060b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0xfb, 0xf9, 1 << 1); 1061b2ce5617SAnders Roxell break; 1062b2ce5617SAnders Roxell case 25: 1063b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0xfb, 0xf9, 2 << 1); 1064b2ce5617SAnders Roxell break; 1065b2ce5617SAnders Roxell case 30: 1066b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0xfb, 0xf9, 3 << 1); 1067b2ce5617SAnders Roxell break; 1068b2ce5617SAnders Roxell default: 1069b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0xfb, 0xf9, 0); 1070b2ce5617SAnders Roxell break; 1071b2ce5617SAnders Roxell } 1072b2ce5617SAnders Roxell 1073b2ce5617SAnders Roxell /* update quantization range based on new dv_timings */ 1074b2ce5617SAnders Roxell adv7511_set_rgb_quantization_mode(sd, state->rgb_quantization_range_ctrl); 1075b2ce5617SAnders Roxell 1076b2ce5617SAnders Roxell return 0; 1077b2ce5617SAnders Roxell } 1078b2ce5617SAnders Roxell 1079b2ce5617SAnders Roxell static int adv7511_g_dv_timings(struct v4l2_subdev *sd, 1080b2ce5617SAnders Roxell struct v4l2_dv_timings *timings) 1081b2ce5617SAnders Roxell { 1082b2ce5617SAnders Roxell struct adv7511_state *state = get_adv7511_state(sd); 1083b2ce5617SAnders Roxell 1084b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, "%s:\n", __func__); 1085b2ce5617SAnders Roxell 1086b2ce5617SAnders Roxell if (!timings) 1087b2ce5617SAnders Roxell return -EINVAL; 1088b2ce5617SAnders Roxell 1089b2ce5617SAnders Roxell *timings = state->dv_timings; 1090b2ce5617SAnders Roxell 1091b2ce5617SAnders Roxell return 0; 1092b2ce5617SAnders Roxell } 1093b2ce5617SAnders Roxell 1094b2ce5617SAnders Roxell static int adv7511_enum_dv_timings(struct v4l2_subdev *sd, 1095b2ce5617SAnders Roxell struct v4l2_enum_dv_timings *timings) 1096b2ce5617SAnders Roxell { 1097b2ce5617SAnders Roxell if (timings->pad != 0) 1098b2ce5617SAnders Roxell return -EINVAL; 1099b2ce5617SAnders Roxell 1100b2ce5617SAnders Roxell return v4l2_enum_dv_timings_cap(timings, &adv7511_timings_cap, NULL, NULL); 1101b2ce5617SAnders Roxell } 1102b2ce5617SAnders Roxell 1103b2ce5617SAnders Roxell static int adv7511_dv_timings_cap(struct v4l2_subdev *sd, 1104b2ce5617SAnders Roxell struct v4l2_dv_timings_cap *cap) 1105b2ce5617SAnders Roxell { 1106b2ce5617SAnders Roxell if (cap->pad != 0) 1107b2ce5617SAnders Roxell return -EINVAL; 1108b2ce5617SAnders Roxell 1109b2ce5617SAnders Roxell *cap = adv7511_timings_cap; 1110b2ce5617SAnders Roxell return 0; 1111b2ce5617SAnders Roxell } 1112b2ce5617SAnders Roxell 1113b2ce5617SAnders Roxell static const struct v4l2_subdev_video_ops adv7511_video_ops = { 1114b2ce5617SAnders Roxell .s_stream = adv7511_s_stream, 1115b2ce5617SAnders Roxell .s_dv_timings = adv7511_s_dv_timings, 1116b2ce5617SAnders Roxell .g_dv_timings = adv7511_g_dv_timings, 1117b2ce5617SAnders Roxell }; 1118b2ce5617SAnders Roxell 1119b2ce5617SAnders Roxell /* ------------------------------ AUDIO OPS ------------------------------ */ 1120b2ce5617SAnders Roxell static int adv7511_s_audio_stream(struct v4l2_subdev *sd, int enable) 1121b2ce5617SAnders Roxell { 1122b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, "%s: %sable\n", __func__, (enable ? "en" : "dis")); 1123b2ce5617SAnders Roxell 1124b2ce5617SAnders Roxell if (enable) 1125b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x4b, 0x3f, 0x80); 1126b2ce5617SAnders Roxell else 1127b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x4b, 0x3f, 0x40); 1128b2ce5617SAnders Roxell 1129b2ce5617SAnders Roxell return 0; 1130b2ce5617SAnders Roxell } 1131b2ce5617SAnders Roxell 1132b2ce5617SAnders Roxell static int adv7511_s_clock_freq(struct v4l2_subdev *sd, u32 freq) 1133b2ce5617SAnders Roxell { 1134b2ce5617SAnders Roxell u32 N; 1135b2ce5617SAnders Roxell 1136b2ce5617SAnders Roxell switch (freq) { 1137b2ce5617SAnders Roxell case 32000: N = 4096; break; 1138b2ce5617SAnders Roxell case 44100: N = 6272; break; 1139b2ce5617SAnders Roxell case 48000: N = 6144; break; 1140b2ce5617SAnders Roxell case 88200: N = 12544; break; 1141b2ce5617SAnders Roxell case 96000: N = 12288; break; 1142b2ce5617SAnders Roxell case 176400: N = 25088; break; 1143b2ce5617SAnders Roxell case 192000: N = 24576; break; 1144b2ce5617SAnders Roxell default: 1145b2ce5617SAnders Roxell return -EINVAL; 1146b2ce5617SAnders Roxell } 1147b2ce5617SAnders Roxell 1148b2ce5617SAnders Roxell /* Set N (used with CTS to regenerate the audio clock) */ 1149b2ce5617SAnders Roxell adv7511_wr(sd, 0x01, (N >> 16) & 0xf); 1150b2ce5617SAnders Roxell adv7511_wr(sd, 0x02, (N >> 8) & 0xff); 1151b2ce5617SAnders Roxell adv7511_wr(sd, 0x03, N & 0xff); 1152b2ce5617SAnders Roxell 1153b2ce5617SAnders Roxell return 0; 1154b2ce5617SAnders Roxell } 1155b2ce5617SAnders Roxell 1156b2ce5617SAnders Roxell static int adv7511_s_i2s_clock_freq(struct v4l2_subdev *sd, u32 freq) 1157b2ce5617SAnders Roxell { 1158b2ce5617SAnders Roxell u32 i2s_sf; 1159b2ce5617SAnders Roxell 1160b2ce5617SAnders Roxell switch (freq) { 1161b2ce5617SAnders Roxell case 32000: i2s_sf = 0x30; break; 1162b2ce5617SAnders Roxell case 44100: i2s_sf = 0x00; break; 1163b2ce5617SAnders Roxell case 48000: i2s_sf = 0x20; break; 1164b2ce5617SAnders Roxell case 88200: i2s_sf = 0x80; break; 1165b2ce5617SAnders Roxell case 96000: i2s_sf = 0xa0; break; 1166b2ce5617SAnders Roxell case 176400: i2s_sf = 0xc0; break; 1167b2ce5617SAnders Roxell case 192000: i2s_sf = 0xe0; break; 1168b2ce5617SAnders Roxell default: 1169b2ce5617SAnders Roxell return -EINVAL; 1170b2ce5617SAnders Roxell } 1171b2ce5617SAnders Roxell 1172b2ce5617SAnders Roxell /* Set sampling frequency for I2S audio to 48 kHz */ 1173b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x15, 0xf, i2s_sf); 1174b2ce5617SAnders Roxell 1175b2ce5617SAnders Roxell return 0; 1176b2ce5617SAnders Roxell } 1177b2ce5617SAnders Roxell 1178b2ce5617SAnders Roxell static int adv7511_s_routing(struct v4l2_subdev *sd, u32 input, u32 output, u32 config) 1179b2ce5617SAnders Roxell { 1180b2ce5617SAnders Roxell /* Only 2 channels in use for application */ 1181b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x73, 0xf8, 0x1); 1182b2ce5617SAnders Roxell /* Speaker mapping */ 1183b2ce5617SAnders Roxell adv7511_wr(sd, 0x76, 0x00); 1184b2ce5617SAnders Roxell 1185b2ce5617SAnders Roxell /* 16 bit audio word length */ 1186b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x14, 0xf0, 0x02); 1187b2ce5617SAnders Roxell 1188b2ce5617SAnders Roxell return 0; 1189b2ce5617SAnders Roxell } 1190b2ce5617SAnders Roxell 1191b2ce5617SAnders Roxell static const struct v4l2_subdev_audio_ops adv7511_audio_ops = { 1192b2ce5617SAnders Roxell .s_stream = adv7511_s_audio_stream, 1193b2ce5617SAnders Roxell .s_clock_freq = adv7511_s_clock_freq, 1194b2ce5617SAnders Roxell .s_i2s_clock_freq = adv7511_s_i2s_clock_freq, 1195b2ce5617SAnders Roxell .s_routing = adv7511_s_routing, 1196b2ce5617SAnders Roxell }; 1197b2ce5617SAnders Roxell 1198b2ce5617SAnders Roxell /* ---------------------------- PAD OPS ------------------------------------- */ 1199b2ce5617SAnders Roxell 1200b2ce5617SAnders Roxell static int adv7511_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) 1201b2ce5617SAnders Roxell { 1202b2ce5617SAnders Roxell struct adv7511_state *state = get_adv7511_state(sd); 1203b2ce5617SAnders Roxell 1204b2ce5617SAnders Roxell memset(edid->reserved, 0, sizeof(edid->reserved)); 1205b2ce5617SAnders Roxell 1206b2ce5617SAnders Roxell if (edid->pad != 0) 1207b2ce5617SAnders Roxell return -EINVAL; 1208b2ce5617SAnders Roxell 1209b2ce5617SAnders Roxell if (edid->start_block == 0 && edid->blocks == 0) { 1210b2ce5617SAnders Roxell edid->blocks = state->edid.segments * 2; 1211b2ce5617SAnders Roxell return 0; 1212b2ce5617SAnders Roxell } 1213b2ce5617SAnders Roxell 1214b2ce5617SAnders Roxell if (state->edid.segments == 0) 1215b2ce5617SAnders Roxell return -ENODATA; 1216b2ce5617SAnders Roxell 1217b2ce5617SAnders Roxell if (edid->start_block >= state->edid.segments * 2) 1218b2ce5617SAnders Roxell return -EINVAL; 1219b2ce5617SAnders Roxell 1220b2ce5617SAnders Roxell if (edid->start_block + edid->blocks > state->edid.segments * 2) 1221b2ce5617SAnders Roxell edid->blocks = state->edid.segments * 2 - edid->start_block; 1222b2ce5617SAnders Roxell 1223b2ce5617SAnders Roxell memcpy(edid->edid, &state->edid.data[edid->start_block * 128], 1224b2ce5617SAnders Roxell 128 * edid->blocks); 1225b2ce5617SAnders Roxell 1226b2ce5617SAnders Roxell return 0; 1227b2ce5617SAnders Roxell } 1228b2ce5617SAnders Roxell 1229b2ce5617SAnders Roxell static int adv7511_enum_mbus_code(struct v4l2_subdev *sd, 1230b2ce5617SAnders Roxell struct v4l2_subdev_pad_config *cfg, 1231b2ce5617SAnders Roxell struct v4l2_subdev_mbus_code_enum *code) 1232b2ce5617SAnders Roxell { 1233b2ce5617SAnders Roxell if (code->pad != 0) 1234b2ce5617SAnders Roxell return -EINVAL; 1235b2ce5617SAnders Roxell 1236b2ce5617SAnders Roxell switch (code->index) { 1237b2ce5617SAnders Roxell case 0: 1238b2ce5617SAnders Roxell code->code = MEDIA_BUS_FMT_RGB888_1X24; 1239b2ce5617SAnders Roxell break; 1240b2ce5617SAnders Roxell case 1: 1241b2ce5617SAnders Roxell code->code = MEDIA_BUS_FMT_YUYV8_1X16; 1242b2ce5617SAnders Roxell break; 1243b2ce5617SAnders Roxell case 2: 1244b2ce5617SAnders Roxell code->code = MEDIA_BUS_FMT_UYVY8_1X16; 1245b2ce5617SAnders Roxell break; 1246b2ce5617SAnders Roxell default: 1247b2ce5617SAnders Roxell return -EINVAL; 1248b2ce5617SAnders Roxell } 1249b2ce5617SAnders Roxell return 0; 1250b2ce5617SAnders Roxell } 1251b2ce5617SAnders Roxell 1252b2ce5617SAnders Roxell static void adv7511_fill_format(struct adv7511_state *state, 1253b2ce5617SAnders Roxell struct v4l2_mbus_framefmt *format) 1254b2ce5617SAnders Roxell { 1255b2ce5617SAnders Roxell format->width = state->dv_timings.bt.width; 1256b2ce5617SAnders Roxell format->height = state->dv_timings.bt.height; 1257b2ce5617SAnders Roxell format->field = V4L2_FIELD_NONE; 1258b2ce5617SAnders Roxell } 1259b2ce5617SAnders Roxell 1260b2ce5617SAnders Roxell static int adv7511_get_fmt(struct v4l2_subdev *sd, 1261b2ce5617SAnders Roxell struct v4l2_subdev_pad_config *cfg, 1262b2ce5617SAnders Roxell struct v4l2_subdev_format *format) 1263b2ce5617SAnders Roxell { 1264b2ce5617SAnders Roxell struct adv7511_state *state = get_adv7511_state(sd); 1265b2ce5617SAnders Roxell 1266b2ce5617SAnders Roxell if (format->pad != 0) 1267b2ce5617SAnders Roxell return -EINVAL; 1268b2ce5617SAnders Roxell 1269b2ce5617SAnders Roxell memset(&format->format, 0, sizeof(format->format)); 1270b2ce5617SAnders Roxell adv7511_fill_format(state, &format->format); 1271b2ce5617SAnders Roxell 1272b2ce5617SAnders Roxell if (format->which == V4L2_SUBDEV_FORMAT_TRY) { 1273b2ce5617SAnders Roxell struct v4l2_mbus_framefmt *fmt; 1274b2ce5617SAnders Roxell 1275b2ce5617SAnders Roxell fmt = v4l2_subdev_get_try_format(sd, cfg, format->pad); 1276b2ce5617SAnders Roxell format->format.code = fmt->code; 1277b2ce5617SAnders Roxell format->format.colorspace = fmt->colorspace; 1278b2ce5617SAnders Roxell format->format.ycbcr_enc = fmt->ycbcr_enc; 1279b2ce5617SAnders Roxell format->format.quantization = fmt->quantization; 1280b2ce5617SAnders Roxell format->format.xfer_func = fmt->xfer_func; 1281b2ce5617SAnders Roxell } else { 1282b2ce5617SAnders Roxell format->format.code = state->fmt_code; 1283b2ce5617SAnders Roxell format->format.colorspace = state->colorspace; 1284b2ce5617SAnders Roxell format->format.ycbcr_enc = state->ycbcr_enc; 1285b2ce5617SAnders Roxell format->format.quantization = state->quantization; 1286b2ce5617SAnders Roxell format->format.xfer_func = state->xfer_func; 1287b2ce5617SAnders Roxell } 1288b2ce5617SAnders Roxell 1289b2ce5617SAnders Roxell return 0; 1290b2ce5617SAnders Roxell } 1291b2ce5617SAnders Roxell 1292b2ce5617SAnders Roxell static int adv7511_set_fmt(struct v4l2_subdev *sd, 1293b2ce5617SAnders Roxell struct v4l2_subdev_pad_config *cfg, 1294b2ce5617SAnders Roxell struct v4l2_subdev_format *format) 1295b2ce5617SAnders Roxell { 1296b2ce5617SAnders Roxell struct adv7511_state *state = get_adv7511_state(sd); 1297b2ce5617SAnders Roxell /* 1298b2ce5617SAnders Roxell * Bitfield namings come the CEA-861-F standard, table 8 "Auxiliary 1299b2ce5617SAnders Roxell * Video Information (AVI) InfoFrame Format" 1300b2ce5617SAnders Roxell * 1301b2ce5617SAnders Roxell * c = Colorimetry 1302b2ce5617SAnders Roxell * ec = Extended Colorimetry 1303b2ce5617SAnders Roxell * y = RGB or YCbCr 1304b2ce5617SAnders Roxell * q = RGB Quantization Range 1305b2ce5617SAnders Roxell * yq = YCC Quantization Range 1306b2ce5617SAnders Roxell */ 1307b2ce5617SAnders Roxell u8 c = HDMI_COLORIMETRY_NONE; 1308b2ce5617SAnders Roxell u8 ec = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; 1309b2ce5617SAnders Roxell u8 y = HDMI_COLORSPACE_RGB; 1310b2ce5617SAnders Roxell u8 q = HDMI_QUANTIZATION_RANGE_DEFAULT; 1311b2ce5617SAnders Roxell u8 yq = HDMI_YCC_QUANTIZATION_RANGE_LIMITED; 1312b2ce5617SAnders Roxell u8 itc = state->content_type != V4L2_DV_IT_CONTENT_TYPE_NO_ITC; 1313b2ce5617SAnders Roxell u8 cn = itc ? state->content_type : V4L2_DV_IT_CONTENT_TYPE_GRAPHICS; 1314b2ce5617SAnders Roxell 1315b2ce5617SAnders Roxell if (format->pad != 0) 1316b2ce5617SAnders Roxell return -EINVAL; 1317b2ce5617SAnders Roxell switch (format->format.code) { 1318b2ce5617SAnders Roxell case MEDIA_BUS_FMT_UYVY8_1X16: 1319b2ce5617SAnders Roxell case MEDIA_BUS_FMT_YUYV8_1X16: 1320b2ce5617SAnders Roxell case MEDIA_BUS_FMT_RGB888_1X24: 1321b2ce5617SAnders Roxell break; 1322b2ce5617SAnders Roxell default: 1323b2ce5617SAnders Roxell return -EINVAL; 1324b2ce5617SAnders Roxell } 1325b2ce5617SAnders Roxell 1326b2ce5617SAnders Roxell adv7511_fill_format(state, &format->format); 1327b2ce5617SAnders Roxell if (format->which == V4L2_SUBDEV_FORMAT_TRY) { 1328b2ce5617SAnders Roxell struct v4l2_mbus_framefmt *fmt; 1329b2ce5617SAnders Roxell 1330b2ce5617SAnders Roxell fmt = v4l2_subdev_get_try_format(sd, cfg, format->pad); 1331b2ce5617SAnders Roxell fmt->code = format->format.code; 1332b2ce5617SAnders Roxell fmt->colorspace = format->format.colorspace; 1333b2ce5617SAnders Roxell fmt->ycbcr_enc = format->format.ycbcr_enc; 1334b2ce5617SAnders Roxell fmt->quantization = format->format.quantization; 1335b2ce5617SAnders Roxell fmt->xfer_func = format->format.xfer_func; 1336b2ce5617SAnders Roxell return 0; 1337b2ce5617SAnders Roxell } 1338b2ce5617SAnders Roxell 1339b2ce5617SAnders Roxell switch (format->format.code) { 1340b2ce5617SAnders Roxell case MEDIA_BUS_FMT_UYVY8_1X16: 1341b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x15, 0xf0, 0x01); 1342b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x16, 0x03, 0xb8); 1343b2ce5617SAnders Roxell y = HDMI_COLORSPACE_YUV422; 1344b2ce5617SAnders Roxell break; 1345b2ce5617SAnders Roxell case MEDIA_BUS_FMT_YUYV8_1X16: 1346b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x15, 0xf0, 0x01); 1347b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x16, 0x03, 0xbc); 1348b2ce5617SAnders Roxell y = HDMI_COLORSPACE_YUV422; 1349b2ce5617SAnders Roxell break; 1350b2ce5617SAnders Roxell case MEDIA_BUS_FMT_RGB888_1X24: 1351b2ce5617SAnders Roxell default: 1352b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x15, 0xf0, 0x00); 1353b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x16, 0x03, 0x00); 1354b2ce5617SAnders Roxell break; 1355b2ce5617SAnders Roxell } 1356b2ce5617SAnders Roxell state->fmt_code = format->format.code; 1357b2ce5617SAnders Roxell state->colorspace = format->format.colorspace; 1358b2ce5617SAnders Roxell state->ycbcr_enc = format->format.ycbcr_enc; 1359b2ce5617SAnders Roxell state->quantization = format->format.quantization; 1360b2ce5617SAnders Roxell state->xfer_func = format->format.xfer_func; 1361b2ce5617SAnders Roxell 1362b2ce5617SAnders Roxell switch (format->format.colorspace) { 1363b2ce5617SAnders Roxell case V4L2_COLORSPACE_OPRGB: 1364b2ce5617SAnders Roxell c = HDMI_COLORIMETRY_EXTENDED; 1365b2ce5617SAnders Roxell ec = y ? HDMI_EXTENDED_COLORIMETRY_OPYCC_601 : 1366b2ce5617SAnders Roxell HDMI_EXTENDED_COLORIMETRY_OPRGB; 1367b2ce5617SAnders Roxell break; 1368b2ce5617SAnders Roxell case V4L2_COLORSPACE_SMPTE170M: 1369b2ce5617SAnders Roxell c = y ? HDMI_COLORIMETRY_ITU_601 : HDMI_COLORIMETRY_NONE; 1370b2ce5617SAnders Roxell if (y && format->format.ycbcr_enc == V4L2_YCBCR_ENC_XV601) { 1371b2ce5617SAnders Roxell c = HDMI_COLORIMETRY_EXTENDED; 1372b2ce5617SAnders Roxell ec = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; 1373b2ce5617SAnders Roxell } 1374b2ce5617SAnders Roxell break; 1375b2ce5617SAnders Roxell case V4L2_COLORSPACE_REC709: 1376b2ce5617SAnders Roxell c = y ? HDMI_COLORIMETRY_ITU_709 : HDMI_COLORIMETRY_NONE; 1377b2ce5617SAnders Roxell if (y && format->format.ycbcr_enc == V4L2_YCBCR_ENC_XV709) { 1378b2ce5617SAnders Roxell c = HDMI_COLORIMETRY_EXTENDED; 1379b2ce5617SAnders Roxell ec = HDMI_EXTENDED_COLORIMETRY_XV_YCC_709; 1380b2ce5617SAnders Roxell } 1381b2ce5617SAnders Roxell break; 1382b2ce5617SAnders Roxell case V4L2_COLORSPACE_SRGB: 1383b2ce5617SAnders Roxell c = y ? HDMI_COLORIMETRY_EXTENDED : HDMI_COLORIMETRY_NONE; 1384b2ce5617SAnders Roxell ec = y ? HDMI_EXTENDED_COLORIMETRY_S_YCC_601 : 1385b2ce5617SAnders Roxell HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; 1386b2ce5617SAnders Roxell break; 1387b2ce5617SAnders Roxell case V4L2_COLORSPACE_BT2020: 1388b2ce5617SAnders Roxell c = HDMI_COLORIMETRY_EXTENDED; 1389b2ce5617SAnders Roxell if (y && format->format.ycbcr_enc == V4L2_YCBCR_ENC_BT2020_CONST_LUM) 1390b2ce5617SAnders Roxell ec = 5; /* Not yet available in hdmi.h */ 1391b2ce5617SAnders Roxell else 1392b2ce5617SAnders Roxell ec = 6; /* Not yet available in hdmi.h */ 1393b2ce5617SAnders Roxell break; 1394b2ce5617SAnders Roxell default: 1395b2ce5617SAnders Roxell break; 1396b2ce5617SAnders Roxell } 1397b2ce5617SAnders Roxell 1398b2ce5617SAnders Roxell /* 1399b2ce5617SAnders Roxell * CEA-861-F says that for RGB formats the YCC range must match the 1400b2ce5617SAnders Roxell * RGB range, although sources should ignore the YCC range. 1401b2ce5617SAnders Roxell * 1402b2ce5617SAnders Roxell * The RGB quantization range shouldn't be non-zero if the EDID doesn't 1403b2ce5617SAnders Roxell * have the Q bit set in the Video Capabilities Data Block, however this 1404b2ce5617SAnders Roxell * isn't checked at the moment. The assumption is that the application 1405b2ce5617SAnders Roxell * knows the EDID and can detect this. 1406b2ce5617SAnders Roxell * 1407b2ce5617SAnders Roxell * The same is true for the YCC quantization range: non-standard YCC 1408b2ce5617SAnders Roxell * quantization ranges should only be sent if the EDID has the YQ bit 1409b2ce5617SAnders Roxell * set in the Video Capabilities Data Block. 1410b2ce5617SAnders Roxell */ 1411b2ce5617SAnders Roxell switch (format->format.quantization) { 1412b2ce5617SAnders Roxell case V4L2_QUANTIZATION_FULL_RANGE: 1413b2ce5617SAnders Roxell q = y ? HDMI_QUANTIZATION_RANGE_DEFAULT : 1414b2ce5617SAnders Roxell HDMI_QUANTIZATION_RANGE_FULL; 1415b2ce5617SAnders Roxell yq = q ? q - 1 : HDMI_YCC_QUANTIZATION_RANGE_FULL; 1416b2ce5617SAnders Roxell break; 1417b2ce5617SAnders Roxell case V4L2_QUANTIZATION_LIM_RANGE: 1418b2ce5617SAnders Roxell q = y ? HDMI_QUANTIZATION_RANGE_DEFAULT : 1419b2ce5617SAnders Roxell HDMI_QUANTIZATION_RANGE_LIMITED; 1420b2ce5617SAnders Roxell yq = q ? q - 1 : HDMI_YCC_QUANTIZATION_RANGE_LIMITED; 1421b2ce5617SAnders Roxell break; 1422b2ce5617SAnders Roxell } 1423b2ce5617SAnders Roxell 1424b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x4a, 0xbf, 0); 1425b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x55, 0x9f, y << 5); 1426b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x56, 0x3f, c << 6); 1427b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x57, 0x83, (ec << 4) | (q << 2) | (itc << 7)); 1428b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x59, 0x0f, (yq << 6) | (cn << 4)); 1429b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x4a, 0xff, 1); 1430b2ce5617SAnders Roxell adv7511_set_rgb_quantization_mode(sd, state->rgb_quantization_range_ctrl); 1431b2ce5617SAnders Roxell 1432b2ce5617SAnders Roxell return 0; 1433b2ce5617SAnders Roxell } 1434b2ce5617SAnders Roxell 1435b2ce5617SAnders Roxell static const struct v4l2_subdev_pad_ops adv7511_pad_ops = { 1436b2ce5617SAnders Roxell .get_edid = adv7511_get_edid, 1437b2ce5617SAnders Roxell .enum_mbus_code = adv7511_enum_mbus_code, 1438b2ce5617SAnders Roxell .get_fmt = adv7511_get_fmt, 1439b2ce5617SAnders Roxell .set_fmt = adv7511_set_fmt, 1440b2ce5617SAnders Roxell .enum_dv_timings = adv7511_enum_dv_timings, 1441b2ce5617SAnders Roxell .dv_timings_cap = adv7511_dv_timings_cap, 1442b2ce5617SAnders Roxell }; 1443b2ce5617SAnders Roxell 1444b2ce5617SAnders Roxell /* --------------------- SUBDEV OPS --------------------------------------- */ 1445b2ce5617SAnders Roxell 1446b2ce5617SAnders Roxell static const struct v4l2_subdev_ops adv7511_ops = { 1447b2ce5617SAnders Roxell .core = &adv7511_core_ops, 1448b2ce5617SAnders Roxell .pad = &adv7511_pad_ops, 1449b2ce5617SAnders Roxell .video = &adv7511_video_ops, 1450b2ce5617SAnders Roxell .audio = &adv7511_audio_ops, 1451b2ce5617SAnders Roxell }; 1452b2ce5617SAnders Roxell 1453b2ce5617SAnders Roxell /* ----------------------------------------------------------------------- */ 1454b2ce5617SAnders Roxell static void adv7511_dbg_dump_edid(int lvl, int debug, struct v4l2_subdev *sd, int segment, u8 *buf) 1455b2ce5617SAnders Roxell { 1456b2ce5617SAnders Roxell if (debug >= lvl) { 1457b2ce5617SAnders Roxell int i, j; 1458b2ce5617SAnders Roxell v4l2_dbg(lvl, debug, sd, "edid segment %d\n", segment); 1459b2ce5617SAnders Roxell for (i = 0; i < 256; i += 16) { 1460b2ce5617SAnders Roxell u8 b[128]; 1461b2ce5617SAnders Roxell u8 *bp = b; 1462b2ce5617SAnders Roxell if (i == 128) 1463b2ce5617SAnders Roxell v4l2_dbg(lvl, debug, sd, "\n"); 1464b2ce5617SAnders Roxell for (j = i; j < i + 16; j++) { 1465b2ce5617SAnders Roxell sprintf(bp, "0x%02x, ", buf[j]); 1466b2ce5617SAnders Roxell bp += 6; 1467b2ce5617SAnders Roxell } 1468b2ce5617SAnders Roxell bp[0] = '\0'; 1469b2ce5617SAnders Roxell v4l2_dbg(lvl, debug, sd, "%s\n", b); 1470b2ce5617SAnders Roxell } 1471b2ce5617SAnders Roxell } 1472b2ce5617SAnders Roxell } 1473b2ce5617SAnders Roxell 1474b2ce5617SAnders Roxell static void adv7511_notify_no_edid(struct v4l2_subdev *sd) 1475b2ce5617SAnders Roxell { 1476b2ce5617SAnders Roxell struct adv7511_state *state = get_adv7511_state(sd); 1477b2ce5617SAnders Roxell struct adv7511_edid_detect ed; 1478b2ce5617SAnders Roxell 1479b2ce5617SAnders Roxell /* We failed to read the EDID, so send an event for this. */ 1480b2ce5617SAnders Roxell ed.present = false; 1481b2ce5617SAnders Roxell ed.segment = adv7511_rd(sd, 0xc4); 1482b2ce5617SAnders Roxell ed.phys_addr = CEC_PHYS_ADDR_INVALID; 1483b2ce5617SAnders Roxell cec_s_phys_addr(state->cec_adap, ed.phys_addr, false); 1484b2ce5617SAnders Roxell v4l2_subdev_notify(sd, ADV7511_EDID_DETECT, (void *)&ed); 1485b2ce5617SAnders Roxell v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, 0x0); 1486b2ce5617SAnders Roxell } 1487b2ce5617SAnders Roxell 1488b2ce5617SAnders Roxell static void adv7511_edid_handler(struct work_struct *work) 1489b2ce5617SAnders Roxell { 1490b2ce5617SAnders Roxell struct delayed_work *dwork = to_delayed_work(work); 1491b2ce5617SAnders Roxell struct adv7511_state *state = container_of(dwork, struct adv7511_state, edid_handler); 1492b2ce5617SAnders Roxell struct v4l2_subdev *sd = &state->sd; 1493b2ce5617SAnders Roxell 1494b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, "%s:\n", __func__); 1495b2ce5617SAnders Roxell 1496b2ce5617SAnders Roxell if (adv7511_check_edid_status(sd)) { 1497b2ce5617SAnders Roxell /* Return if we received the EDID. */ 1498b2ce5617SAnders Roxell return; 1499b2ce5617SAnders Roxell } 1500b2ce5617SAnders Roxell 1501b2ce5617SAnders Roxell if (adv7511_have_hotplug(sd)) { 1502b2ce5617SAnders Roxell /* We must retry reading the EDID several times, it is possible 1503b2ce5617SAnders Roxell * that initially the EDID couldn't be read due to i2c errors 1504b2ce5617SAnders Roxell * (DVI connectors are particularly prone to this problem). */ 1505b2ce5617SAnders Roxell if (state->edid.read_retries) { 1506b2ce5617SAnders Roxell state->edid.read_retries--; 1507b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, "%s: edid read failed\n", __func__); 1508b2ce5617SAnders Roxell state->have_monitor = false; 1509b2ce5617SAnders Roxell adv7511_s_power(sd, false); 1510b2ce5617SAnders Roxell adv7511_s_power(sd, true); 1511b2ce5617SAnders Roxell queue_delayed_work(state->work_queue, &state->edid_handler, EDID_DELAY); 1512b2ce5617SAnders Roxell return; 1513b2ce5617SAnders Roxell } 1514b2ce5617SAnders Roxell } 1515b2ce5617SAnders Roxell 1516b2ce5617SAnders Roxell /* We failed to read the EDID, so send an event for this. */ 1517b2ce5617SAnders Roxell adv7511_notify_no_edid(sd); 1518b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, "%s: no edid found\n", __func__); 1519b2ce5617SAnders Roxell } 1520b2ce5617SAnders Roxell 1521b2ce5617SAnders Roxell static void adv7511_audio_setup(struct v4l2_subdev *sd) 1522b2ce5617SAnders Roxell { 1523b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, "%s\n", __func__); 1524b2ce5617SAnders Roxell 1525b2ce5617SAnders Roxell adv7511_s_i2s_clock_freq(sd, 48000); 1526b2ce5617SAnders Roxell adv7511_s_clock_freq(sd, 48000); 1527b2ce5617SAnders Roxell adv7511_s_routing(sd, 0, 0, 0); 1528b2ce5617SAnders Roxell } 1529b2ce5617SAnders Roxell 1530b2ce5617SAnders Roxell /* Configure hdmi transmitter. */ 1531b2ce5617SAnders Roxell static void adv7511_setup(struct v4l2_subdev *sd) 1532b2ce5617SAnders Roxell { 1533b2ce5617SAnders Roxell struct adv7511_state *state = get_adv7511_state(sd); 1534b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, "%s\n", __func__); 1535b2ce5617SAnders Roxell 1536b2ce5617SAnders Roxell /* Input format: RGB 4:4:4 */ 1537b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x15, 0xf0, 0x0); 1538b2ce5617SAnders Roxell /* Output format: RGB 4:4:4 */ 1539b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x16, 0x7f, 0x0); 1540b2ce5617SAnders Roxell /* 1st order interpolation 4:2:2 -> 4:4:4 up conversion, Aspect ratio: 16:9 */ 1541b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x17, 0xf9, 0x06); 1542b2ce5617SAnders Roxell /* Disable pixel repetition */ 1543b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x3b, 0x9f, 0x0); 1544b2ce5617SAnders Roxell /* Disable CSC */ 1545b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x18, 0x7f, 0x0); 1546b2ce5617SAnders Roxell /* Output format: RGB 4:4:4, Active Format Information is valid, 1547b2ce5617SAnders Roxell * underscanned */ 1548b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x55, 0x9c, 0x12); 1549b2ce5617SAnders Roxell /* AVI Info frame packet enable, Audio Info frame disable */ 1550b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0x44, 0xe7, 0x10); 1551b2ce5617SAnders Roxell /* Colorimetry, Active format aspect ratio: same as picure. */ 1552b2ce5617SAnders Roxell adv7511_wr(sd, 0x56, 0xa8); 1553b2ce5617SAnders Roxell /* No encryption */ 1554b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0xaf, 0xed, 0x0); 1555b2ce5617SAnders Roxell 1556b2ce5617SAnders Roxell /* Positive clk edge capture for input video clock */ 1557b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0xba, 0x1f, 0x60); 1558b2ce5617SAnders Roxell 1559b2ce5617SAnders Roxell adv7511_audio_setup(sd); 1560b2ce5617SAnders Roxell 1561b2ce5617SAnders Roxell v4l2_ctrl_handler_setup(&state->hdl); 1562b2ce5617SAnders Roxell } 1563b2ce5617SAnders Roxell 1564b2ce5617SAnders Roxell static void adv7511_notify_monitor_detect(struct v4l2_subdev *sd) 1565b2ce5617SAnders Roxell { 1566b2ce5617SAnders Roxell struct adv7511_monitor_detect mdt; 1567b2ce5617SAnders Roxell struct adv7511_state *state = get_adv7511_state(sd); 1568b2ce5617SAnders Roxell 1569b2ce5617SAnders Roxell mdt.present = state->have_monitor; 1570b2ce5617SAnders Roxell v4l2_subdev_notify(sd, ADV7511_MONITOR_DETECT, (void *)&mdt); 1571b2ce5617SAnders Roxell } 1572b2ce5617SAnders Roxell 1573b2ce5617SAnders Roxell static void adv7511_check_monitor_present_status(struct v4l2_subdev *sd) 1574b2ce5617SAnders Roxell { 1575b2ce5617SAnders Roxell struct adv7511_state *state = get_adv7511_state(sd); 1576b2ce5617SAnders Roxell /* read hotplug and rx-sense state */ 1577b2ce5617SAnders Roxell u8 status = adv7511_rd(sd, 0x42); 1578b2ce5617SAnders Roxell 1579b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, "%s: status: 0x%x%s%s\n", 1580b2ce5617SAnders Roxell __func__, 1581b2ce5617SAnders Roxell status, 1582b2ce5617SAnders Roxell status & MASK_ADV7511_HPD_DETECT ? ", hotplug" : "", 1583b2ce5617SAnders Roxell status & MASK_ADV7511_MSEN_DETECT ? ", rx-sense" : ""); 1584b2ce5617SAnders Roxell 1585b2ce5617SAnders Roxell /* update read only ctrls */ 1586b2ce5617SAnders Roxell v4l2_ctrl_s_ctrl(state->hotplug_ctrl, adv7511_have_hotplug(sd) ? 0x1 : 0x0); 1587b2ce5617SAnders Roxell v4l2_ctrl_s_ctrl(state->rx_sense_ctrl, adv7511_have_rx_sense(sd) ? 0x1 : 0x0); 1588b2ce5617SAnders Roxell 1589b2ce5617SAnders Roxell if ((status & MASK_ADV7511_HPD_DETECT) && ((status & MASK_ADV7511_MSEN_DETECT) || state->edid.segments)) { 1590b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, "%s: hotplug and (rx-sense or edid)\n", __func__); 1591b2ce5617SAnders Roxell if (!state->have_monitor) { 1592b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, "%s: monitor detected\n", __func__); 1593b2ce5617SAnders Roxell state->have_monitor = true; 1594b2ce5617SAnders Roxell adv7511_set_isr(sd, true); 1595b2ce5617SAnders Roxell if (!adv7511_s_power(sd, true)) { 1596b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, "%s: monitor detected, powerup failed\n", __func__); 1597b2ce5617SAnders Roxell return; 1598b2ce5617SAnders Roxell } 1599b2ce5617SAnders Roxell adv7511_setup(sd); 1600b2ce5617SAnders Roxell adv7511_notify_monitor_detect(sd); 1601b2ce5617SAnders Roxell state->edid.read_retries = EDID_MAX_RETRIES; 1602b2ce5617SAnders Roxell queue_delayed_work(state->work_queue, &state->edid_handler, EDID_DELAY); 1603b2ce5617SAnders Roxell } 1604b2ce5617SAnders Roxell } else if (status & MASK_ADV7511_HPD_DETECT) { 1605b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, "%s: hotplug detected\n", __func__); 1606b2ce5617SAnders Roxell state->edid.read_retries = EDID_MAX_RETRIES; 1607b2ce5617SAnders Roxell queue_delayed_work(state->work_queue, &state->edid_handler, EDID_DELAY); 1608b2ce5617SAnders Roxell } else if (!(status & MASK_ADV7511_HPD_DETECT)) { 1609b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, "%s: hotplug not detected\n", __func__); 1610b2ce5617SAnders Roxell if (state->have_monitor) { 1611b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, "%s: monitor not detected\n", __func__); 1612b2ce5617SAnders Roxell state->have_monitor = false; 1613b2ce5617SAnders Roxell adv7511_notify_monitor_detect(sd); 1614b2ce5617SAnders Roxell } 1615b2ce5617SAnders Roxell adv7511_s_power(sd, false); 1616b2ce5617SAnders Roxell memset(&state->edid, 0, sizeof(struct adv7511_state_edid)); 1617b2ce5617SAnders Roxell adv7511_notify_no_edid(sd); 1618b2ce5617SAnders Roxell } 1619b2ce5617SAnders Roxell } 1620b2ce5617SAnders Roxell 1621b2ce5617SAnders Roxell static bool edid_block_verify_crc(u8 *edid_block) 1622b2ce5617SAnders Roxell { 1623b2ce5617SAnders Roxell u8 sum = 0; 1624b2ce5617SAnders Roxell int i; 1625b2ce5617SAnders Roxell 1626b2ce5617SAnders Roxell for (i = 0; i < 128; i++) 1627b2ce5617SAnders Roxell sum += edid_block[i]; 1628b2ce5617SAnders Roxell return sum == 0; 1629b2ce5617SAnders Roxell } 1630b2ce5617SAnders Roxell 1631b2ce5617SAnders Roxell static bool edid_verify_crc(struct v4l2_subdev *sd, u32 segment) 1632b2ce5617SAnders Roxell { 1633b2ce5617SAnders Roxell struct adv7511_state *state = get_adv7511_state(sd); 1634b2ce5617SAnders Roxell u32 blocks = state->edid.blocks; 1635b2ce5617SAnders Roxell u8 *data = state->edid.data; 1636b2ce5617SAnders Roxell 1637b2ce5617SAnders Roxell if (!edid_block_verify_crc(&data[segment * 256])) 1638b2ce5617SAnders Roxell return false; 1639b2ce5617SAnders Roxell if ((segment + 1) * 2 <= blocks) 1640b2ce5617SAnders Roxell return edid_block_verify_crc(&data[segment * 256 + 128]); 1641b2ce5617SAnders Roxell return true; 1642b2ce5617SAnders Roxell } 1643b2ce5617SAnders Roxell 1644b2ce5617SAnders Roxell static bool edid_verify_header(struct v4l2_subdev *sd, u32 segment) 1645b2ce5617SAnders Roxell { 1646b2ce5617SAnders Roxell static const u8 hdmi_header[] = { 1647b2ce5617SAnders Roxell 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 1648b2ce5617SAnders Roxell }; 1649b2ce5617SAnders Roxell struct adv7511_state *state = get_adv7511_state(sd); 1650b2ce5617SAnders Roxell u8 *data = state->edid.data; 1651b2ce5617SAnders Roxell 1652b2ce5617SAnders Roxell if (segment != 0) 1653b2ce5617SAnders Roxell return true; 1654b2ce5617SAnders Roxell return !memcmp(data, hdmi_header, sizeof(hdmi_header)); 1655b2ce5617SAnders Roxell } 1656b2ce5617SAnders Roxell 1657b2ce5617SAnders Roxell static bool adv7511_check_edid_status(struct v4l2_subdev *sd) 1658b2ce5617SAnders Roxell { 1659b2ce5617SAnders Roxell struct adv7511_state *state = get_adv7511_state(sd); 1660b2ce5617SAnders Roxell u8 edidRdy = adv7511_rd(sd, 0xc5); 1661b2ce5617SAnders Roxell 1662b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, "%s: edid ready (retries: %d)\n", 1663b2ce5617SAnders Roxell __func__, EDID_MAX_RETRIES - state->edid.read_retries); 1664b2ce5617SAnders Roxell 1665b2ce5617SAnders Roxell if (state->edid.complete) 1666b2ce5617SAnders Roxell return true; 1667b2ce5617SAnders Roxell 1668b2ce5617SAnders Roxell if (edidRdy & MASK_ADV7511_EDID_RDY) { 1669b2ce5617SAnders Roxell int segment = adv7511_rd(sd, 0xc4); 1670b2ce5617SAnders Roxell struct adv7511_edid_detect ed; 1671b2ce5617SAnders Roxell 1672b2ce5617SAnders Roxell if (segment >= EDID_MAX_SEGM) { 1673b2ce5617SAnders Roxell v4l2_err(sd, "edid segment number too big\n"); 1674b2ce5617SAnders Roxell return false; 1675b2ce5617SAnders Roxell } 1676b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, "%s: got segment %d\n", __func__, segment); 1677b2ce5617SAnders Roxell adv7511_edid_rd(sd, 256, &state->edid.data[segment * 256]); 1678b2ce5617SAnders Roxell adv7511_dbg_dump_edid(2, debug, sd, segment, &state->edid.data[segment * 256]); 1679b2ce5617SAnders Roxell if (segment == 0) { 1680b2ce5617SAnders Roxell state->edid.blocks = state->edid.data[0x7e] + 1; 1681b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, "%s: %d blocks in total\n", __func__, state->edid.blocks); 1682b2ce5617SAnders Roxell } 1683b2ce5617SAnders Roxell if (!edid_verify_crc(sd, segment) || 1684b2ce5617SAnders Roxell !edid_verify_header(sd, segment)) { 1685b2ce5617SAnders Roxell /* edid crc error, force reread of edid segment */ 1686b2ce5617SAnders Roxell v4l2_err(sd, "%s: edid crc or header error\n", __func__); 1687b2ce5617SAnders Roxell state->have_monitor = false; 1688b2ce5617SAnders Roxell adv7511_s_power(sd, false); 1689b2ce5617SAnders Roxell adv7511_s_power(sd, true); 1690b2ce5617SAnders Roxell return false; 1691b2ce5617SAnders Roxell } 1692b2ce5617SAnders Roxell /* one more segment read ok */ 1693b2ce5617SAnders Roxell state->edid.segments = segment + 1; 1694b2ce5617SAnders Roxell v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, 0x1); 1695b2ce5617SAnders Roxell if (((state->edid.data[0x7e] >> 1) + 1) > state->edid.segments) { 1696b2ce5617SAnders Roxell /* Request next EDID segment */ 1697b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, "%s: request segment %d\n", __func__, state->edid.segments); 1698b2ce5617SAnders Roxell adv7511_wr(sd, 0xc9, 0xf); 1699b2ce5617SAnders Roxell adv7511_wr(sd, 0xc4, state->edid.segments); 1700b2ce5617SAnders Roxell state->edid.read_retries = EDID_MAX_RETRIES; 1701b2ce5617SAnders Roxell queue_delayed_work(state->work_queue, &state->edid_handler, EDID_DELAY); 1702b2ce5617SAnders Roxell return false; 1703b2ce5617SAnders Roxell } 1704b2ce5617SAnders Roxell 1705b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, "%s: edid complete with %d segment(s)\n", __func__, state->edid.segments); 1706b2ce5617SAnders Roxell state->edid.complete = true; 1707b2ce5617SAnders Roxell ed.phys_addr = cec_get_edid_phys_addr(state->edid.data, 1708b2ce5617SAnders Roxell state->edid.segments * 256, 1709b2ce5617SAnders Roxell NULL); 1710b2ce5617SAnders Roxell /* report when we have all segments 1711b2ce5617SAnders Roxell but report only for segment 0 1712b2ce5617SAnders Roxell */ 1713b2ce5617SAnders Roxell ed.present = true; 1714b2ce5617SAnders Roxell ed.segment = 0; 1715b2ce5617SAnders Roxell state->edid_detect_counter++; 1716b2ce5617SAnders Roxell cec_s_phys_addr(state->cec_adap, ed.phys_addr, false); 1717b2ce5617SAnders Roxell v4l2_subdev_notify(sd, ADV7511_EDID_DETECT, (void *)&ed); 1718b2ce5617SAnders Roxell return ed.present; 1719b2ce5617SAnders Roxell } 1720b2ce5617SAnders Roxell 1721b2ce5617SAnders Roxell return false; 1722b2ce5617SAnders Roxell } 1723b2ce5617SAnders Roxell 1724b2ce5617SAnders Roxell static int adv7511_registered(struct v4l2_subdev *sd) 1725b2ce5617SAnders Roxell { 1726b2ce5617SAnders Roxell struct adv7511_state *state = get_adv7511_state(sd); 1727b2ce5617SAnders Roxell struct i2c_client *client = v4l2_get_subdevdata(sd); 1728b2ce5617SAnders Roxell int err; 1729b2ce5617SAnders Roxell 1730b2ce5617SAnders Roxell err = cec_register_adapter(state->cec_adap, &client->dev); 1731b2ce5617SAnders Roxell if (err) 1732b2ce5617SAnders Roxell cec_delete_adapter(state->cec_adap); 1733b2ce5617SAnders Roxell return err; 1734b2ce5617SAnders Roxell } 1735b2ce5617SAnders Roxell 1736b2ce5617SAnders Roxell static void adv7511_unregistered(struct v4l2_subdev *sd) 1737b2ce5617SAnders Roxell { 1738b2ce5617SAnders Roxell struct adv7511_state *state = get_adv7511_state(sd); 1739b2ce5617SAnders Roxell 1740b2ce5617SAnders Roxell cec_unregister_adapter(state->cec_adap); 1741b2ce5617SAnders Roxell } 1742b2ce5617SAnders Roxell 1743b2ce5617SAnders Roxell static const struct v4l2_subdev_internal_ops adv7511_int_ops = { 1744b2ce5617SAnders Roxell .registered = adv7511_registered, 1745b2ce5617SAnders Roxell .unregistered = adv7511_unregistered, 1746b2ce5617SAnders Roxell }; 1747b2ce5617SAnders Roxell 1748b2ce5617SAnders Roxell /* ----------------------------------------------------------------------- */ 1749b2ce5617SAnders Roxell /* Setup ADV7511 */ 1750b2ce5617SAnders Roxell static void adv7511_init_setup(struct v4l2_subdev *sd) 1751b2ce5617SAnders Roxell { 1752b2ce5617SAnders Roxell struct adv7511_state *state = get_adv7511_state(sd); 1753b2ce5617SAnders Roxell struct adv7511_state_edid *edid = &state->edid; 1754b2ce5617SAnders Roxell u32 cec_clk = state->pdata.cec_clk; 1755b2ce5617SAnders Roxell u8 ratio; 1756b2ce5617SAnders Roxell 1757b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, "%s\n", __func__); 1758b2ce5617SAnders Roxell 1759b2ce5617SAnders Roxell /* clear all interrupts */ 1760b2ce5617SAnders Roxell adv7511_wr(sd, 0x96, 0xff); 1761b2ce5617SAnders Roxell adv7511_wr(sd, 0x97, 0xff); 1762b2ce5617SAnders Roxell /* 1763b2ce5617SAnders Roxell * Stop HPD from resetting a lot of registers. 1764b2ce5617SAnders Roxell * It might leave the chip in a partly un-initialized state, 1765b2ce5617SAnders Roxell * in particular with regards to hotplug bounces. 1766b2ce5617SAnders Roxell */ 1767b2ce5617SAnders Roxell adv7511_wr_and_or(sd, 0xd6, 0x3f, 0xc0); 1768b2ce5617SAnders Roxell memset(edid, 0, sizeof(struct adv7511_state_edid)); 1769b2ce5617SAnders Roxell state->have_monitor = false; 1770b2ce5617SAnders Roxell adv7511_set_isr(sd, false); 1771b2ce5617SAnders Roxell adv7511_s_stream(sd, false); 1772b2ce5617SAnders Roxell adv7511_s_audio_stream(sd, false); 1773b2ce5617SAnders Roxell 1774b2ce5617SAnders Roxell if (state->i2c_cec == NULL) 1775b2ce5617SAnders Roxell return; 1776b2ce5617SAnders Roxell 1777b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, "%s: cec_clk %d\n", __func__, cec_clk); 1778b2ce5617SAnders Roxell 1779b2ce5617SAnders Roxell /* cec soft reset */ 1780b2ce5617SAnders Roxell adv7511_cec_write(sd, 0x50, 0x01); 1781b2ce5617SAnders Roxell adv7511_cec_write(sd, 0x50, 0x00); 1782b2ce5617SAnders Roxell 1783b2ce5617SAnders Roxell /* legacy mode */ 1784b2ce5617SAnders Roxell adv7511_cec_write(sd, 0x4a, 0x00); 1785b2ce5617SAnders Roxell adv7511_cec_write(sd, 0x4a, 0x07); 1786b2ce5617SAnders Roxell 1787b2ce5617SAnders Roxell if (cec_clk % 750000 != 0) 1788b2ce5617SAnders Roxell v4l2_err(sd, "%s: cec_clk %d, not multiple of 750 Khz\n", 1789b2ce5617SAnders Roxell __func__, cec_clk); 1790b2ce5617SAnders Roxell 1791b2ce5617SAnders Roxell ratio = (cec_clk / 750000) - 1; 1792b2ce5617SAnders Roxell adv7511_cec_write(sd, 0x4e, ratio << 2); 1793b2ce5617SAnders Roxell } 1794b2ce5617SAnders Roxell 1795b2ce5617SAnders Roxell static int adv7511_probe(struct i2c_client *client, const struct i2c_device_id *id) 1796b2ce5617SAnders Roxell { 1797b2ce5617SAnders Roxell struct adv7511_state *state; 1798b2ce5617SAnders Roxell struct adv7511_platform_data *pdata = client->dev.platform_data; 1799b2ce5617SAnders Roxell struct v4l2_ctrl_handler *hdl; 1800b2ce5617SAnders Roxell struct v4l2_subdev *sd; 1801b2ce5617SAnders Roxell u8 chip_id[2]; 1802b2ce5617SAnders Roxell int err = -EIO; 1803b2ce5617SAnders Roxell 1804b2ce5617SAnders Roxell /* Check if the adapter supports the needed features */ 1805b2ce5617SAnders Roxell if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 1806b2ce5617SAnders Roxell return -EIO; 1807b2ce5617SAnders Roxell 1808b2ce5617SAnders Roxell state = devm_kzalloc(&client->dev, sizeof(struct adv7511_state), GFP_KERNEL); 1809b2ce5617SAnders Roxell if (!state) 1810b2ce5617SAnders Roxell return -ENOMEM; 1811b2ce5617SAnders Roxell 1812b2ce5617SAnders Roxell /* Platform data */ 1813b2ce5617SAnders Roxell if (!pdata) { 1814b2ce5617SAnders Roxell v4l_err(client, "No platform data!\n"); 1815b2ce5617SAnders Roxell return -ENODEV; 1816b2ce5617SAnders Roxell } 1817b2ce5617SAnders Roxell memcpy(&state->pdata, pdata, sizeof(state->pdata)); 1818b2ce5617SAnders Roxell state->fmt_code = MEDIA_BUS_FMT_RGB888_1X24; 1819b2ce5617SAnders Roxell state->colorspace = V4L2_COLORSPACE_SRGB; 1820b2ce5617SAnders Roxell 1821b2ce5617SAnders Roxell sd = &state->sd; 1822b2ce5617SAnders Roxell 1823b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, "detecting adv7511 client on address 0x%x\n", 1824b2ce5617SAnders Roxell client->addr << 1); 1825b2ce5617SAnders Roxell 1826b2ce5617SAnders Roxell v4l2_i2c_subdev_init(sd, client, &adv7511_ops); 1827b2ce5617SAnders Roxell sd->internal_ops = &adv7511_int_ops; 1828b2ce5617SAnders Roxell 1829b2ce5617SAnders Roxell hdl = &state->hdl; 1830b2ce5617SAnders Roxell v4l2_ctrl_handler_init(hdl, 10); 1831b2ce5617SAnders Roxell /* add in ascending ID order */ 1832b2ce5617SAnders Roxell state->hdmi_mode_ctrl = v4l2_ctrl_new_std_menu(hdl, &adv7511_ctrl_ops, 1833b2ce5617SAnders Roxell V4L2_CID_DV_TX_MODE, V4L2_DV_TX_MODE_HDMI, 1834b2ce5617SAnders Roxell 0, V4L2_DV_TX_MODE_DVI_D); 1835b2ce5617SAnders Roxell state->hotplug_ctrl = v4l2_ctrl_new_std(hdl, NULL, 1836b2ce5617SAnders Roxell V4L2_CID_DV_TX_HOTPLUG, 0, 1, 0, 0); 1837b2ce5617SAnders Roxell state->rx_sense_ctrl = v4l2_ctrl_new_std(hdl, NULL, 1838b2ce5617SAnders Roxell V4L2_CID_DV_TX_RXSENSE, 0, 1, 0, 0); 1839b2ce5617SAnders Roxell state->have_edid0_ctrl = v4l2_ctrl_new_std(hdl, NULL, 1840b2ce5617SAnders Roxell V4L2_CID_DV_TX_EDID_PRESENT, 0, 1, 0, 0); 1841b2ce5617SAnders Roxell state->rgb_quantization_range_ctrl = 1842b2ce5617SAnders Roxell v4l2_ctrl_new_std_menu(hdl, &adv7511_ctrl_ops, 1843b2ce5617SAnders Roxell V4L2_CID_DV_TX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL, 1844b2ce5617SAnders Roxell 0, V4L2_DV_RGB_RANGE_AUTO); 1845b2ce5617SAnders Roxell state->content_type_ctrl = 1846b2ce5617SAnders Roxell v4l2_ctrl_new_std_menu(hdl, &adv7511_ctrl_ops, 1847b2ce5617SAnders Roxell V4L2_CID_DV_TX_IT_CONTENT_TYPE, V4L2_DV_IT_CONTENT_TYPE_NO_ITC, 1848b2ce5617SAnders Roxell 0, V4L2_DV_IT_CONTENT_TYPE_NO_ITC); 1849b2ce5617SAnders Roxell sd->ctrl_handler = hdl; 1850b2ce5617SAnders Roxell if (hdl->error) { 1851b2ce5617SAnders Roxell err = hdl->error; 1852b2ce5617SAnders Roxell goto err_hdl; 1853b2ce5617SAnders Roxell } 1854b2ce5617SAnders Roxell state->pad.flags = MEDIA_PAD_FL_SINK; 1855b2ce5617SAnders Roxell sd->entity.function = MEDIA_ENT_F_DV_ENCODER; 1856b2ce5617SAnders Roxell err = media_entity_pads_init(&sd->entity, 1, &state->pad); 1857b2ce5617SAnders Roxell if (err) 1858b2ce5617SAnders Roxell goto err_hdl; 1859b2ce5617SAnders Roxell 1860b2ce5617SAnders Roxell /* EDID and CEC i2c addr */ 1861b2ce5617SAnders Roxell state->i2c_edid_addr = state->pdata.i2c_edid << 1; 1862b2ce5617SAnders Roxell state->i2c_cec_addr = state->pdata.i2c_cec << 1; 1863b2ce5617SAnders Roxell state->i2c_pktmem_addr = state->pdata.i2c_pktmem << 1; 1864b2ce5617SAnders Roxell 1865b2ce5617SAnders Roxell state->chip_revision = adv7511_rd(sd, 0x0); 1866b2ce5617SAnders Roxell chip_id[0] = adv7511_rd(sd, 0xf5); 1867b2ce5617SAnders Roxell chip_id[1] = adv7511_rd(sd, 0xf6); 1868b2ce5617SAnders Roxell if (chip_id[0] != 0x75 || chip_id[1] != 0x11) { 1869b2ce5617SAnders Roxell v4l2_err(sd, "chip_id != 0x7511, read 0x%02x%02x\n", chip_id[0], 1870b2ce5617SAnders Roxell chip_id[1]); 1871b2ce5617SAnders Roxell err = -EIO; 1872b2ce5617SAnders Roxell goto err_entity; 1873b2ce5617SAnders Roxell } 1874b2ce5617SAnders Roxell 18759524da83SWolfram Sang state->i2c_edid = i2c_new_dummy_device(client->adapter, 1876b2ce5617SAnders Roxell state->i2c_edid_addr >> 1); 18779524da83SWolfram Sang if (IS_ERR(state->i2c_edid)) { 1878b2ce5617SAnders Roxell v4l2_err(sd, "failed to register edid i2c client\n"); 18799524da83SWolfram Sang err = PTR_ERR(state->i2c_edid); 1880b2ce5617SAnders Roxell goto err_entity; 1881b2ce5617SAnders Roxell } 1882b2ce5617SAnders Roxell 1883b2ce5617SAnders Roxell adv7511_wr(sd, 0xe1, state->i2c_cec_addr); 1884b2ce5617SAnders Roxell if (state->pdata.cec_clk < 3000000 || 1885b2ce5617SAnders Roxell state->pdata.cec_clk > 100000000) { 1886b2ce5617SAnders Roxell v4l2_err(sd, "%s: cec_clk %u outside range, disabling cec\n", 1887b2ce5617SAnders Roxell __func__, state->pdata.cec_clk); 1888b2ce5617SAnders Roxell state->pdata.cec_clk = 0; 1889b2ce5617SAnders Roxell } 1890b2ce5617SAnders Roxell 1891b2ce5617SAnders Roxell if (state->pdata.cec_clk) { 18929524da83SWolfram Sang state->i2c_cec = i2c_new_dummy_device(client->adapter, 1893b2ce5617SAnders Roxell state->i2c_cec_addr >> 1); 18949524da83SWolfram Sang if (IS_ERR(state->i2c_cec)) { 1895b2ce5617SAnders Roxell v4l2_err(sd, "failed to register cec i2c client\n"); 18969524da83SWolfram Sang err = PTR_ERR(state->i2c_cec); 1897b2ce5617SAnders Roxell goto err_unreg_edid; 1898b2ce5617SAnders Roxell } 1899b2ce5617SAnders Roxell adv7511_wr(sd, 0xe2, 0x00); /* power up cec section */ 1900b2ce5617SAnders Roxell } else { 1901b2ce5617SAnders Roxell adv7511_wr(sd, 0xe2, 0x01); /* power down cec section */ 1902b2ce5617SAnders Roxell } 1903b2ce5617SAnders Roxell 19049524da83SWolfram Sang state->i2c_pktmem = i2c_new_dummy_device(client->adapter, state->i2c_pktmem_addr >> 1); 19059524da83SWolfram Sang if (IS_ERR(state->i2c_pktmem)) { 1906b2ce5617SAnders Roxell v4l2_err(sd, "failed to register pktmem i2c client\n"); 19079524da83SWolfram Sang err = PTR_ERR(state->i2c_pktmem); 1908b2ce5617SAnders Roxell goto err_unreg_cec; 1909b2ce5617SAnders Roxell } 1910b2ce5617SAnders Roxell 1911b2ce5617SAnders Roxell state->work_queue = create_singlethread_workqueue(sd->name); 1912b2ce5617SAnders Roxell if (state->work_queue == NULL) { 1913b2ce5617SAnders Roxell v4l2_err(sd, "could not create workqueue\n"); 1914b2ce5617SAnders Roxell err = -ENOMEM; 1915b2ce5617SAnders Roxell goto err_unreg_pktmem; 1916b2ce5617SAnders Roxell } 1917b2ce5617SAnders Roxell 1918b2ce5617SAnders Roxell INIT_DELAYED_WORK(&state->edid_handler, adv7511_edid_handler); 1919b2ce5617SAnders Roxell 1920b2ce5617SAnders Roxell adv7511_init_setup(sd); 1921b2ce5617SAnders Roxell 1922b2ce5617SAnders Roxell #if IS_ENABLED(CONFIG_VIDEO_ADV7511_CEC) 1923b2ce5617SAnders Roxell state->cec_adap = cec_allocate_adapter(&adv7511_cec_adap_ops, 1924b2ce5617SAnders Roxell state, dev_name(&client->dev), CEC_CAP_DEFAULTS, 1925b2ce5617SAnders Roxell ADV7511_MAX_ADDRS); 1926b2ce5617SAnders Roxell err = PTR_ERR_OR_ZERO(state->cec_adap); 1927b2ce5617SAnders Roxell if (err) { 1928b2ce5617SAnders Roxell destroy_workqueue(state->work_queue); 1929b2ce5617SAnders Roxell goto err_unreg_pktmem; 1930b2ce5617SAnders Roxell } 1931b2ce5617SAnders Roxell #endif 1932b2ce5617SAnders Roxell 1933b2ce5617SAnders Roxell adv7511_set_isr(sd, true); 1934b2ce5617SAnders Roxell adv7511_check_monitor_present_status(sd); 1935b2ce5617SAnders Roxell 1936b2ce5617SAnders Roxell v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name, 1937b2ce5617SAnders Roxell client->addr << 1, client->adapter->name); 1938b2ce5617SAnders Roxell return 0; 1939b2ce5617SAnders Roxell 1940b2ce5617SAnders Roxell err_unreg_pktmem: 1941b2ce5617SAnders Roxell i2c_unregister_device(state->i2c_pktmem); 1942b2ce5617SAnders Roxell err_unreg_cec: 1943b2ce5617SAnders Roxell i2c_unregister_device(state->i2c_cec); 1944b2ce5617SAnders Roxell err_unreg_edid: 1945b2ce5617SAnders Roxell i2c_unregister_device(state->i2c_edid); 1946b2ce5617SAnders Roxell err_entity: 1947b2ce5617SAnders Roxell media_entity_cleanup(&sd->entity); 1948b2ce5617SAnders Roxell err_hdl: 1949b2ce5617SAnders Roxell v4l2_ctrl_handler_free(&state->hdl); 1950b2ce5617SAnders Roxell return err; 1951b2ce5617SAnders Roxell } 1952b2ce5617SAnders Roxell 1953b2ce5617SAnders Roxell /* ----------------------------------------------------------------------- */ 1954b2ce5617SAnders Roxell 1955b2ce5617SAnders Roxell static int adv7511_remove(struct i2c_client *client) 1956b2ce5617SAnders Roxell { 1957b2ce5617SAnders Roxell struct v4l2_subdev *sd = i2c_get_clientdata(client); 1958b2ce5617SAnders Roxell struct adv7511_state *state = get_adv7511_state(sd); 1959b2ce5617SAnders Roxell 1960b2ce5617SAnders Roxell state->chip_revision = -1; 1961b2ce5617SAnders Roxell 1962b2ce5617SAnders Roxell v4l2_dbg(1, debug, sd, "%s removed @ 0x%x (%s)\n", client->name, 1963b2ce5617SAnders Roxell client->addr << 1, client->adapter->name); 1964b2ce5617SAnders Roxell 1965b2ce5617SAnders Roxell adv7511_set_isr(sd, false); 1966b2ce5617SAnders Roxell adv7511_init_setup(sd); 1967b2ce5617SAnders Roxell cancel_delayed_work(&state->edid_handler); 1968b2ce5617SAnders Roxell i2c_unregister_device(state->i2c_edid); 1969b2ce5617SAnders Roxell i2c_unregister_device(state->i2c_cec); 1970b2ce5617SAnders Roxell i2c_unregister_device(state->i2c_pktmem); 1971b2ce5617SAnders Roxell destroy_workqueue(state->work_queue); 1972b2ce5617SAnders Roxell v4l2_device_unregister_subdev(sd); 1973b2ce5617SAnders Roxell media_entity_cleanup(&sd->entity); 1974b2ce5617SAnders Roxell v4l2_ctrl_handler_free(sd->ctrl_handler); 1975b2ce5617SAnders Roxell return 0; 1976b2ce5617SAnders Roxell } 1977b2ce5617SAnders Roxell 1978b2ce5617SAnders Roxell /* ----------------------------------------------------------------------- */ 1979b2ce5617SAnders Roxell 1980b2ce5617SAnders Roxell static const struct i2c_device_id adv7511_id[] = { 198125a3d6baSHans Verkuil { "adv7511-v4l2", 0 }, 1982b2ce5617SAnders Roxell { } 1983b2ce5617SAnders Roxell }; 1984b2ce5617SAnders Roxell MODULE_DEVICE_TABLE(i2c, adv7511_id); 1985b2ce5617SAnders Roxell 1986b2ce5617SAnders Roxell static struct i2c_driver adv7511_driver = { 1987b2ce5617SAnders Roxell .driver = { 198825a3d6baSHans Verkuil .name = "adv7511-v4l2", 1989b2ce5617SAnders Roxell }, 1990b2ce5617SAnders Roxell .probe = adv7511_probe, 1991b2ce5617SAnders Roxell .remove = adv7511_remove, 1992b2ce5617SAnders Roxell .id_table = adv7511_id, 1993b2ce5617SAnders Roxell }; 1994b2ce5617SAnders Roxell 1995b2ce5617SAnders Roxell module_i2c_driver(adv7511_driver); 1996