162306a36Sopenharmony_ci// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2020, The Linux Foundation. All rights reserved. 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci#include <linux/bits.h> 662306a36Sopenharmony_ci#include <linux/delay.h> 762306a36Sopenharmony_ci#include <linux/device.h> 862306a36Sopenharmony_ci#include <linux/err.h> 962306a36Sopenharmony_ci#include <linux/extcon.h> 1062306a36Sopenharmony_ci#include <linux/fs.h> 1162306a36Sopenharmony_ci#include <linux/gpio/consumer.h> 1262306a36Sopenharmony_ci#include <linux/i2c.h> 1362306a36Sopenharmony_ci#include <linux/interrupt.h> 1462306a36Sopenharmony_ci#include <linux/kernel.h> 1562306a36Sopenharmony_ci#include <linux/module.h> 1662306a36Sopenharmony_ci#include <linux/pm_runtime.h> 1762306a36Sopenharmony_ci#include <linux/regmap.h> 1862306a36Sopenharmony_ci#include <linux/regulator/consumer.h> 1962306a36Sopenharmony_ci#include <linux/types.h> 2062306a36Sopenharmony_ci#include <linux/wait.h> 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#include <crypto/hash.h> 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#include <drm/display/drm_dp_helper.h> 2562306a36Sopenharmony_ci#include <drm/display/drm_hdcp_helper.h> 2662306a36Sopenharmony_ci#include <drm/drm_atomic_helper.h> 2762306a36Sopenharmony_ci#include <drm/drm_bridge.h> 2862306a36Sopenharmony_ci#include <drm/drm_crtc.h> 2962306a36Sopenharmony_ci#include <drm/drm_edid.h> 3062306a36Sopenharmony_ci#include <drm/drm_print.h> 3162306a36Sopenharmony_ci#include <drm/drm_probe_helper.h> 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#include <sound/hdmi-codec.h> 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#define REG_IC_VER 0x04 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci#define REG_RESET_CTRL 0x05 3862306a36Sopenharmony_ci#define VIDEO_RESET BIT(0) 3962306a36Sopenharmony_ci#define AUDIO_RESET BIT(1) 4062306a36Sopenharmony_ci#define ALL_LOGIC_RESET BIT(2) 4162306a36Sopenharmony_ci#define AUX_RESET BIT(3) 4262306a36Sopenharmony_ci#define HDCP_RESET BIT(4) 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci#define INT_STATUS_01 0x06 4562306a36Sopenharmony_ci#define INT_MASK_01 0x09 4662306a36Sopenharmony_ci#define INT_HPD_CHANGE 0 4762306a36Sopenharmony_ci#define INT_RECEIVE_HPD_IRQ 1 4862306a36Sopenharmony_ci#define INT_SCDT_CHANGE 2 4962306a36Sopenharmony_ci#define INT_HDCP_FAIL 3 5062306a36Sopenharmony_ci#define INT_HDCP_DONE 4 5162306a36Sopenharmony_ci#define BIT_OFFSET(x) (((x) - INT_STATUS_01) * BITS_PER_BYTE) 5262306a36Sopenharmony_ci#define BIT_INT_HPD INT_HPD_CHANGE 5362306a36Sopenharmony_ci#define BIT_INT_HPD_IRQ INT_RECEIVE_HPD_IRQ 5462306a36Sopenharmony_ci#define BIT_INT_SCDT INT_SCDT_CHANGE 5562306a36Sopenharmony_ci#define BIT_INT_HDCP_FAIL INT_HDCP_FAIL 5662306a36Sopenharmony_ci#define BIT_INT_HDCP_DONE INT_HDCP_DONE 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci#define INT_STATUS_02 0x07 5962306a36Sopenharmony_ci#define INT_MASK_02 0x0A 6062306a36Sopenharmony_ci#define INT_AUX_CMD_FAIL 0 6162306a36Sopenharmony_ci#define INT_HDCP_KSV_CHECK 1 6262306a36Sopenharmony_ci#define INT_AUDIO_FIFO_ERROR 2 6362306a36Sopenharmony_ci#define BIT_INT_AUX_CMD_FAIL (BIT_OFFSET(0x07) + INT_AUX_CMD_FAIL) 6462306a36Sopenharmony_ci#define BIT_INT_HDCP_KSV_CHECK (BIT_OFFSET(0x07) + INT_HDCP_KSV_CHECK) 6562306a36Sopenharmony_ci#define BIT_INT_AUDIO_FIFO_ERROR (BIT_OFFSET(0x07) + INT_AUDIO_FIFO_ERROR) 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci#define INT_STATUS_03 0x08 6862306a36Sopenharmony_ci#define INT_MASK_03 0x0B 6962306a36Sopenharmony_ci#define INT_LINK_TRAIN_FAIL 4 7062306a36Sopenharmony_ci#define INT_VID_FIFO_ERROR 5 7162306a36Sopenharmony_ci#define INT_IO_LATCH_FIFO_OVERFLOW 7 7262306a36Sopenharmony_ci#define BIT_INT_LINK_TRAIN_FAIL (BIT_OFFSET(0x08) + INT_LINK_TRAIN_FAIL) 7362306a36Sopenharmony_ci#define BIT_INT_VID_FIFO_ERROR (BIT_OFFSET(0x08) + INT_VID_FIFO_ERROR) 7462306a36Sopenharmony_ci#define BIT_INT_IO_FIFO_OVERFLOW (BIT_OFFSET(0x08) + INT_IO_LATCH_FIFO_OVERFLOW) 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci#define REG_SYSTEM_STS 0x0D 7762306a36Sopenharmony_ci#define INT_STS BIT(0) 7862306a36Sopenharmony_ci#define HPD_STS BIT(1) 7962306a36Sopenharmony_ci#define VIDEO_STB BIT(2) 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci#define REG_LINK_TRAIN_STS 0x0E 8262306a36Sopenharmony_ci#define LINK_STATE_CR BIT(2) 8362306a36Sopenharmony_ci#define LINK_STATE_EQ BIT(3) 8462306a36Sopenharmony_ci#define LINK_STATE_NORP BIT(4) 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci#define REG_BANK_SEL 0x0F 8762306a36Sopenharmony_ci#define REG_CLK_CTRL0 0x10 8862306a36Sopenharmony_ci#define M_PCLK_DELAY 0x03 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci#define REG_AUX_OPT 0x11 9162306a36Sopenharmony_ci#define AUX_AUTO_RST BIT(0) 9262306a36Sopenharmony_ci#define AUX_FIX_FREQ BIT(3) 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci#define REG_DATA_CTRL0 0x12 9562306a36Sopenharmony_ci#define VIDEO_LATCH_EDGE BIT(4) 9662306a36Sopenharmony_ci#define ENABLE_PCLK_COUNTER BIT(7) 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci#define REG_PCLK_COUNTER_VALUE 0x13 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci#define REG_501_FIFO_CTRL 0x15 10162306a36Sopenharmony_ci#define RST_501_FIFO BIT(1) 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci#define REG_TRAIN_CTRL0 0x16 10462306a36Sopenharmony_ci#define FORCE_LBR BIT(0) 10562306a36Sopenharmony_ci#define LANE_COUNT_MASK 0x06 10662306a36Sopenharmony_ci#define LANE_SWAP BIT(3) 10762306a36Sopenharmony_ci#define SPREAD_AMP_5 BIT(4) 10862306a36Sopenharmony_ci#define FORCE_CR_DONE BIT(5) 10962306a36Sopenharmony_ci#define FORCE_EQ_DONE BIT(6) 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci#define REG_TRAIN_CTRL1 0x17 11262306a36Sopenharmony_ci#define AUTO_TRAIN BIT(0) 11362306a36Sopenharmony_ci#define MANUAL_TRAIN BIT(1) 11462306a36Sopenharmony_ci#define FORCE_RETRAIN BIT(2) 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci#define REG_AUX_CTRL 0x23 11762306a36Sopenharmony_ci#define CLR_EDID_FIFO BIT(0) 11862306a36Sopenharmony_ci#define AUX_USER_MODE BIT(1) 11962306a36Sopenharmony_ci#define AUX_NO_SEGMENT_WR BIT(6) 12062306a36Sopenharmony_ci#define AUX_EN_FIFO_READ BIT(7) 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci#define REG_AUX_ADR_0_7 0x24 12362306a36Sopenharmony_ci#define REG_AUX_ADR_8_15 0x25 12462306a36Sopenharmony_ci#define REG_AUX_ADR_16_19 0x26 12562306a36Sopenharmony_ci#define REG_AUX_OUT_DATA0 0x27 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci#define REG_AUX_CMD_REQ 0x2B 12862306a36Sopenharmony_ci#define AUX_BUSY BIT(5) 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci#define REG_AUX_DATA_0_7 0x2C 13162306a36Sopenharmony_ci#define REG_AUX_DATA_8_15 0x2D 13262306a36Sopenharmony_ci#define REG_AUX_DATA_16_23 0x2E 13362306a36Sopenharmony_ci#define REG_AUX_DATA_24_31 0x2F 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci#define REG_AUX_DATA_FIFO 0x2F 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci#define REG_AUX_ERROR_STS 0x9F 13862306a36Sopenharmony_ci#define M_AUX_REQ_FAIL 0x03 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci#define REG_HDCP_CTRL1 0x38 14162306a36Sopenharmony_ci#define HDCP_CP_ENABLE BIT(0) 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci#define REG_HDCP_TRIGGER 0x39 14462306a36Sopenharmony_ci#define HDCP_TRIGGER_START BIT(0) 14562306a36Sopenharmony_ci#define HDCP_TRIGGER_CPIRQ BIT(1) 14662306a36Sopenharmony_ci#define HDCP_TRIGGER_KSV_DONE BIT(4) 14762306a36Sopenharmony_ci#define HDCP_TRIGGER_KSV_FAIL BIT(5) 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci#define REG_HDCP_CTRL2 0x3A 15062306a36Sopenharmony_ci#define HDCP_AN_SEL BIT(0) 15162306a36Sopenharmony_ci#define HDCP_AN_GEN BIT(1) 15262306a36Sopenharmony_ci#define HDCP_HW_HPDIRQ_ACT BIT(2) 15362306a36Sopenharmony_ci#define HDCP_EN_M0_READ BIT(5) 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci#define REG_M0_0_7 0x4C 15662306a36Sopenharmony_ci#define REG_AN_0_7 0x4C 15762306a36Sopenharmony_ci#define REG_SP_CTRL0 0x58 15862306a36Sopenharmony_ci#define REG_IP_CTRL1 0x59 15962306a36Sopenharmony_ci#define REG_IP_CTRL2 0x5A 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci#define REG_LINK_DRV 0x5C 16262306a36Sopenharmony_ci#define DRV_HS BIT(1) 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci#define REG_DRV_LN_DATA_SEL 0x5D 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci#define REG_AUX 0x5E 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci#define REG_VID_BUS_CTRL0 0x60 16962306a36Sopenharmony_ci#define IN_DDR BIT(2) 17062306a36Sopenharmony_ci#define DDR_CD (0x01 << 6) 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci#define REG_VID_BUS_CTRL1 0x61 17362306a36Sopenharmony_ci#define TX_FIFO_RESET BIT(1) 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci#define REG_INPUT_CTRL 0xA0 17662306a36Sopenharmony_ci#define INPUT_HSYNC_POL BIT(0) 17762306a36Sopenharmony_ci#define INPUT_VSYNC_POL BIT(2) 17862306a36Sopenharmony_ci#define INPUT_INTERLACED BIT(4) 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci#define REG_INPUT_HTOTAL 0xA1 18162306a36Sopenharmony_ci#define REG_INPUT_HACTIVE_START 0xA3 18262306a36Sopenharmony_ci#define REG_INPUT_HACTIVE_WIDTH 0xA5 18362306a36Sopenharmony_ci#define REG_INPUT_HFRONT_PORCH 0xA7 18462306a36Sopenharmony_ci#define REG_INPUT_HSYNC_WIDTH 0xA9 18562306a36Sopenharmony_ci#define REG_INPUT_VTOTAL 0xAB 18662306a36Sopenharmony_ci#define REG_INPUT_VACTIVE_START 0xAD 18762306a36Sopenharmony_ci#define REG_INPUT_VACTIVE_WIDTH 0xAF 18862306a36Sopenharmony_ci#define REG_INPUT_VFRONT_PORCH 0xB1 18962306a36Sopenharmony_ci#define REG_INPUT_VSYNC_WIDTH 0xB3 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci#define REG_AUDIO_SRC_CTRL 0xB8 19262306a36Sopenharmony_ci#define M_AUDIO_I2S_EN 0x0F 19362306a36Sopenharmony_ci#define EN_I2S0 BIT(0) 19462306a36Sopenharmony_ci#define EN_I2S1 BIT(1) 19562306a36Sopenharmony_ci#define EN_I2S2 BIT(2) 19662306a36Sopenharmony_ci#define EN_I2S3 BIT(3) 19762306a36Sopenharmony_ci#define AUDIO_FIFO_RESET BIT(7) 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci#define REG_AUDIO_FMT 0xB9 20062306a36Sopenharmony_ci#define REG_AUDIO_FIFO_SEL 0xBA 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci#define REG_AUDIO_CTRL0 0xBB 20362306a36Sopenharmony_ci#define AUDIO_FULL_PKT BIT(4) 20462306a36Sopenharmony_ci#define AUDIO_16B_BOUND BIT(5) 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci#define REG_AUDIO_CTRL1 0xBC 20762306a36Sopenharmony_ci#define REG_AUDIO_INPUT_FREQ 0xBE 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci#define REG_IEC958_STS0 0xBF 21062306a36Sopenharmony_ci#define REG_IEC958_STS1 0xC0 21162306a36Sopenharmony_ci#define REG_IEC958_STS2 0xC1 21262306a36Sopenharmony_ci#define REG_IEC958_STS3 0xC2 21362306a36Sopenharmony_ci#define REG_IEC958_STS4 0xC3 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci#define REG_HPD_IRQ_TIME 0xC9 21662306a36Sopenharmony_ci#define REG_AUX_DEBUG_MODE 0xCA 21762306a36Sopenharmony_ci#define REG_AUX_OPT2 0xCB 21862306a36Sopenharmony_ci#define REG_HDCP_OPT 0xCE 21962306a36Sopenharmony_ci#define REG_USER_DRV_PRE 0xCF 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci#define REG_DATA_MUTE_CTRL 0xD3 22262306a36Sopenharmony_ci#define ENABLE_ENHANCED_FRAME BIT(0) 22362306a36Sopenharmony_ci#define ENABLE_AUTO_VIDEO_FIFO_RESET BIT(1) 22462306a36Sopenharmony_ci#define EN_VID_MUTE BIT(4) 22562306a36Sopenharmony_ci#define EN_AUD_MUTE BIT(5) 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci#define REG_TIME_STMP_CTRL 0xD4 22862306a36Sopenharmony_ci#define EN_ENHANCE_VID_STMP BIT(0) 22962306a36Sopenharmony_ci#define EN_ENHANCE_AUD_STMP BIT(2) 23062306a36Sopenharmony_ci#define M_STAMP_STEP 0x30 23162306a36Sopenharmony_ci#define EN_SSC_GAT BIT(6) 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci#define REG_INFOFRAME_CTRL 0xE8 23462306a36Sopenharmony_ci#define EN_AVI_PKT BIT(0) 23562306a36Sopenharmony_ci#define EN_AUD_PKT BIT(1) 23662306a36Sopenharmony_ci#define EN_MPG_PKT BIT(2) 23762306a36Sopenharmony_ci#define EN_GEN_PKT BIT(3) 23862306a36Sopenharmony_ci#define EN_VID_TIME_STMP BIT(4) 23962306a36Sopenharmony_ci#define EN_AUD_TIME_STMP BIT(5) 24062306a36Sopenharmony_ci#define EN_VID_CTRL_PKT (EN_AVI_PKT | EN_VID_TIME_STMP) 24162306a36Sopenharmony_ci#define EN_AUD_CTRL_PKT (EN_AUD_PKT | EN_AUD_TIME_STMP) 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci#define REG_AUDIO_N_0_7 0xDE 24462306a36Sopenharmony_ci#define REG_AUDIO_N_8_15 0xDF 24562306a36Sopenharmony_ci#define REG_AUDIO_N_16_23 0xE0 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci#define REG_AVI_INFO_DB1 0xE9 24862306a36Sopenharmony_ci#define REG_AVI_INFO_DB2 0xEA 24962306a36Sopenharmony_ci#define REG_AVI_INFO_DB3 0xEB 25062306a36Sopenharmony_ci#define REG_AVI_INFO_DB4 0xEC 25162306a36Sopenharmony_ci#define REG_AVI_INFO_DB5 0xED 25262306a36Sopenharmony_ci#define REG_AVI_INFO_SUM 0xF6 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci#define REG_AUD_INFOFRAM_DB1 0xF7 25562306a36Sopenharmony_ci#define REG_AUD_INFOFRAM_DB2 0xF8 25662306a36Sopenharmony_ci#define REG_AUD_INFOFRAM_DB3 0xF9 25762306a36Sopenharmony_ci#define REG_AUD_INFOFRAM_DB4 0xFA 25862306a36Sopenharmony_ci#define REG_AUD_INFOFRAM_SUM 0xFB 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci/* the following six registers are in bank1 */ 26162306a36Sopenharmony_ci#define REG_DRV_0_DB_800_MV 0x17E 26262306a36Sopenharmony_ci#define REG_PRE_0_DB_800_MV 0x17F 26362306a36Sopenharmony_ci#define REG_PRE_3P5_DB_800_MV 0x181 26462306a36Sopenharmony_ci#define REG_SSC_CTRL0 0x188 26562306a36Sopenharmony_ci#define REG_SSC_CTRL1 0x189 26662306a36Sopenharmony_ci#define REG_SSC_CTRL2 0x18A 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci#define RBR DP_LINK_BW_1_62 26962306a36Sopenharmony_ci#define HBR DP_LINK_BW_2_7 27062306a36Sopenharmony_ci#define HBR2 DP_LINK_BW_5_4 27162306a36Sopenharmony_ci#define HBR3 DP_LINK_BW_8_1 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci#define DPCD_V_1_1 0x11 27462306a36Sopenharmony_ci#define MISC_VERB 0xF0 27562306a36Sopenharmony_ci#define MISC_VERC 0x70 27662306a36Sopenharmony_ci#define I2S_INPUT_FORMAT_STANDARD 0 27762306a36Sopenharmony_ci#define I2S_INPUT_FORMAT_32BIT 1 27862306a36Sopenharmony_ci#define I2S_INPUT_LEFT_JUSTIFIED 0 27962306a36Sopenharmony_ci#define I2S_INPUT_RIGHT_JUSTIFIED 1 28062306a36Sopenharmony_ci#define I2S_DATA_1T_DELAY 0 28162306a36Sopenharmony_ci#define I2S_DATA_NO_DELAY 1 28262306a36Sopenharmony_ci#define I2S_WS_LEFT_CHANNEL 0 28362306a36Sopenharmony_ci#define I2S_WS_RIGHT_CHANNEL 1 28462306a36Sopenharmony_ci#define I2S_DATA_MSB_FIRST 0 28562306a36Sopenharmony_ci#define I2S_DATA_LSB_FIRST 1 28662306a36Sopenharmony_ci#define WORD_LENGTH_16BIT 0 28762306a36Sopenharmony_ci#define WORD_LENGTH_18BIT 1 28862306a36Sopenharmony_ci#define WORD_LENGTH_20BIT 2 28962306a36Sopenharmony_ci#define WORD_LENGTH_24BIT 3 29062306a36Sopenharmony_ci#define DEBUGFS_DIR_NAME "it6505-debugfs" 29162306a36Sopenharmony_ci#define READ_BUFFER_SIZE 400 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci/* Vendor option */ 29462306a36Sopenharmony_ci#define HDCP_DESIRED 1 29562306a36Sopenharmony_ci#define MAX_LANE_COUNT 4 29662306a36Sopenharmony_ci#define MAX_LINK_RATE HBR 29762306a36Sopenharmony_ci#define AUTO_TRAIN_RETRY 3 29862306a36Sopenharmony_ci#define MAX_HDCP_DOWN_STREAM_COUNT 10 29962306a36Sopenharmony_ci#define MAX_CR_LEVEL 0x03 30062306a36Sopenharmony_ci#define MAX_EQ_LEVEL 0x03 30162306a36Sopenharmony_ci#define AUX_WAIT_TIMEOUT_MS 15 30262306a36Sopenharmony_ci#define AUX_FIFO_MAX_SIZE 32 30362306a36Sopenharmony_ci#define PIXEL_CLK_DELAY 1 30462306a36Sopenharmony_ci#define PIXEL_CLK_INVERSE 0 30562306a36Sopenharmony_ci#define ADJUST_PHASE_THRESHOLD 80000 30662306a36Sopenharmony_ci#define DPI_PIXEL_CLK_MAX 95000 30762306a36Sopenharmony_ci#define HDCP_SHA1_FIFO_LEN (MAX_HDCP_DOWN_STREAM_COUNT * 5 + 10) 30862306a36Sopenharmony_ci#define DEFAULT_PWR_ON 0 30962306a36Sopenharmony_ci#define DEFAULT_DRV_HOLD 0 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci#define AUDIO_SELECT I2S 31262306a36Sopenharmony_ci#define AUDIO_TYPE LPCM 31362306a36Sopenharmony_ci#define AUDIO_SAMPLE_RATE SAMPLE_RATE_48K 31462306a36Sopenharmony_ci#define AUDIO_CHANNEL_COUNT 2 31562306a36Sopenharmony_ci#define I2S_INPUT_FORMAT I2S_INPUT_FORMAT_32BIT 31662306a36Sopenharmony_ci#define I2S_JUSTIFIED I2S_INPUT_LEFT_JUSTIFIED 31762306a36Sopenharmony_ci#define I2S_DATA_DELAY I2S_DATA_1T_DELAY 31862306a36Sopenharmony_ci#define I2S_WS_CHANNEL I2S_WS_LEFT_CHANNEL 31962306a36Sopenharmony_ci#define I2S_DATA_SEQUENCE I2S_DATA_MSB_FIRST 32062306a36Sopenharmony_ci#define AUDIO_WORD_LENGTH WORD_LENGTH_24BIT 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_cienum aux_cmd_type { 32362306a36Sopenharmony_ci CMD_AUX_NATIVE_READ = 0x0, 32462306a36Sopenharmony_ci CMD_AUX_NATIVE_WRITE = 0x5, 32562306a36Sopenharmony_ci CMD_AUX_I2C_EDID_READ = 0xB, 32662306a36Sopenharmony_ci}; 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_cienum aux_cmd_reply { 32962306a36Sopenharmony_ci REPLY_ACK, 33062306a36Sopenharmony_ci REPLY_NACK, 33162306a36Sopenharmony_ci REPLY_DEFER, 33262306a36Sopenharmony_ci}; 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_cienum link_train_status { 33562306a36Sopenharmony_ci LINK_IDLE, 33662306a36Sopenharmony_ci LINK_BUSY, 33762306a36Sopenharmony_ci LINK_OK, 33862306a36Sopenharmony_ci}; 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_cienum hdcp_state { 34162306a36Sopenharmony_ci HDCP_AUTH_IDLE, 34262306a36Sopenharmony_ci HDCP_AUTH_GOING, 34362306a36Sopenharmony_ci HDCP_AUTH_DONE, 34462306a36Sopenharmony_ci}; 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_cistruct it6505_platform_data { 34762306a36Sopenharmony_ci struct regulator *pwr18; 34862306a36Sopenharmony_ci struct regulator *ovdd; 34962306a36Sopenharmony_ci struct gpio_desc *gpiod_reset; 35062306a36Sopenharmony_ci}; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_cienum it6505_audio_select { 35362306a36Sopenharmony_ci I2S = 0, 35462306a36Sopenharmony_ci SPDIF, 35562306a36Sopenharmony_ci}; 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_cienum it6505_audio_sample_rate { 35862306a36Sopenharmony_ci SAMPLE_RATE_24K = 0x6, 35962306a36Sopenharmony_ci SAMPLE_RATE_32K = 0x3, 36062306a36Sopenharmony_ci SAMPLE_RATE_48K = 0x2, 36162306a36Sopenharmony_ci SAMPLE_RATE_96K = 0xA, 36262306a36Sopenharmony_ci SAMPLE_RATE_192K = 0xE, 36362306a36Sopenharmony_ci SAMPLE_RATE_44_1K = 0x0, 36462306a36Sopenharmony_ci SAMPLE_RATE_88_2K = 0x8, 36562306a36Sopenharmony_ci SAMPLE_RATE_176_4K = 0xC, 36662306a36Sopenharmony_ci}; 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_cienum it6505_audio_type { 36962306a36Sopenharmony_ci LPCM = 0, 37062306a36Sopenharmony_ci NLPCM, 37162306a36Sopenharmony_ci DSS, 37262306a36Sopenharmony_ci}; 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_cistruct it6505_audio_data { 37562306a36Sopenharmony_ci enum it6505_audio_select select; 37662306a36Sopenharmony_ci enum it6505_audio_sample_rate sample_rate; 37762306a36Sopenharmony_ci enum it6505_audio_type type; 37862306a36Sopenharmony_ci u8 word_length; 37962306a36Sopenharmony_ci u8 channel_count; 38062306a36Sopenharmony_ci u8 i2s_input_format; 38162306a36Sopenharmony_ci u8 i2s_justified; 38262306a36Sopenharmony_ci u8 i2s_data_delay; 38362306a36Sopenharmony_ci u8 i2s_ws_channel; 38462306a36Sopenharmony_ci u8 i2s_data_sequence; 38562306a36Sopenharmony_ci}; 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_cistruct it6505_audio_sample_rate_map { 38862306a36Sopenharmony_ci enum it6505_audio_sample_rate rate; 38962306a36Sopenharmony_ci int sample_rate_value; 39062306a36Sopenharmony_ci}; 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_cistruct it6505_drm_dp_link { 39362306a36Sopenharmony_ci unsigned char revision; 39462306a36Sopenharmony_ci unsigned int rate; 39562306a36Sopenharmony_ci unsigned int num_lanes; 39662306a36Sopenharmony_ci unsigned long capabilities; 39762306a36Sopenharmony_ci}; 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_cistruct debugfs_entries { 40062306a36Sopenharmony_ci char *name; 40162306a36Sopenharmony_ci const struct file_operations *fops; 40262306a36Sopenharmony_ci}; 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_cistruct it6505 { 40562306a36Sopenharmony_ci struct drm_dp_aux aux; 40662306a36Sopenharmony_ci struct drm_bridge bridge; 40762306a36Sopenharmony_ci struct device *dev; 40862306a36Sopenharmony_ci struct it6505_drm_dp_link link; 40962306a36Sopenharmony_ci struct it6505_platform_data pdata; 41062306a36Sopenharmony_ci /* 41162306a36Sopenharmony_ci * Mutex protects extcon and interrupt functions from interfering 41262306a36Sopenharmony_ci * each other. 41362306a36Sopenharmony_ci */ 41462306a36Sopenharmony_ci struct mutex extcon_lock; 41562306a36Sopenharmony_ci struct mutex mode_lock; /* used to bridge_detect */ 41662306a36Sopenharmony_ci struct mutex aux_lock; /* used to aux data transfers */ 41762306a36Sopenharmony_ci struct regmap *regmap; 41862306a36Sopenharmony_ci struct drm_display_mode source_output_mode; 41962306a36Sopenharmony_ci struct drm_display_mode video_info; 42062306a36Sopenharmony_ci struct notifier_block event_nb; 42162306a36Sopenharmony_ci struct extcon_dev *extcon; 42262306a36Sopenharmony_ci struct work_struct extcon_wq; 42362306a36Sopenharmony_ci int extcon_state; 42462306a36Sopenharmony_ci enum drm_connector_status connector_status; 42562306a36Sopenharmony_ci enum link_train_status link_state; 42662306a36Sopenharmony_ci struct work_struct link_works; 42762306a36Sopenharmony_ci u8 dpcd[DP_RECEIVER_CAP_SIZE]; 42862306a36Sopenharmony_ci u8 lane_count; 42962306a36Sopenharmony_ci u8 link_rate_bw_code; 43062306a36Sopenharmony_ci u8 sink_count; 43162306a36Sopenharmony_ci bool step_train; 43262306a36Sopenharmony_ci bool branch_device; 43362306a36Sopenharmony_ci bool enable_ssc; 43462306a36Sopenharmony_ci bool lane_swap_disabled; 43562306a36Sopenharmony_ci bool lane_swap; 43662306a36Sopenharmony_ci bool powered; 43762306a36Sopenharmony_ci bool hpd_state; 43862306a36Sopenharmony_ci u32 afe_setting; 43962306a36Sopenharmony_ci u32 max_dpi_pixel_clock; 44062306a36Sopenharmony_ci u32 max_lane_count; 44162306a36Sopenharmony_ci enum hdcp_state hdcp_status; 44262306a36Sopenharmony_ci struct delayed_work hdcp_work; 44362306a36Sopenharmony_ci struct work_struct hdcp_wait_ksv_list; 44462306a36Sopenharmony_ci struct completion extcon_completion; 44562306a36Sopenharmony_ci u8 auto_train_retry; 44662306a36Sopenharmony_ci bool hdcp_desired; 44762306a36Sopenharmony_ci bool is_repeater; 44862306a36Sopenharmony_ci u8 hdcp_down_stream_count; 44962306a36Sopenharmony_ci u8 bksvs[DRM_HDCP_KSV_LEN]; 45062306a36Sopenharmony_ci u8 sha1_input[HDCP_SHA1_FIFO_LEN]; 45162306a36Sopenharmony_ci bool enable_enhanced_frame; 45262306a36Sopenharmony_ci hdmi_codec_plugged_cb plugged_cb; 45362306a36Sopenharmony_ci struct device *codec_dev; 45462306a36Sopenharmony_ci struct delayed_work delayed_audio; 45562306a36Sopenharmony_ci struct it6505_audio_data audio; 45662306a36Sopenharmony_ci struct dentry *debugfs; 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci /* it6505 driver hold option */ 45962306a36Sopenharmony_ci bool enable_drv_hold; 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci struct edid *cached_edid; 46262306a36Sopenharmony_ci}; 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_cistruct it6505_step_train_para { 46562306a36Sopenharmony_ci u8 voltage_swing[MAX_LANE_COUNT]; 46662306a36Sopenharmony_ci u8 pre_emphasis[MAX_LANE_COUNT]; 46762306a36Sopenharmony_ci}; 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci/* 47062306a36Sopenharmony_ci * Vendor option afe settings for different platforms 47162306a36Sopenharmony_ci * 0: without FPC cable 47262306a36Sopenharmony_ci * 1: with FPC cable 47362306a36Sopenharmony_ci */ 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_cistatic const u8 afe_setting_table[][3] = { 47662306a36Sopenharmony_ci {0x82, 0x00, 0x45}, 47762306a36Sopenharmony_ci {0x93, 0x2A, 0x85} 47862306a36Sopenharmony_ci}; 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_cistatic const struct it6505_audio_sample_rate_map audio_sample_rate_map[] = { 48162306a36Sopenharmony_ci {SAMPLE_RATE_24K, 24000}, 48262306a36Sopenharmony_ci {SAMPLE_RATE_32K, 32000}, 48362306a36Sopenharmony_ci {SAMPLE_RATE_48K, 48000}, 48462306a36Sopenharmony_ci {SAMPLE_RATE_96K, 96000}, 48562306a36Sopenharmony_ci {SAMPLE_RATE_192K, 192000}, 48662306a36Sopenharmony_ci {SAMPLE_RATE_44_1K, 44100}, 48762306a36Sopenharmony_ci {SAMPLE_RATE_88_2K, 88200}, 48862306a36Sopenharmony_ci {SAMPLE_RATE_176_4K, 176400}, 48962306a36Sopenharmony_ci}; 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_cistatic const struct regmap_range it6505_bridge_volatile_ranges[] = { 49262306a36Sopenharmony_ci { .range_min = 0, .range_max = 0x1FF }, 49362306a36Sopenharmony_ci}; 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_cistatic const struct regmap_access_table it6505_bridge_volatile_table = { 49662306a36Sopenharmony_ci .yes_ranges = it6505_bridge_volatile_ranges, 49762306a36Sopenharmony_ci .n_yes_ranges = ARRAY_SIZE(it6505_bridge_volatile_ranges), 49862306a36Sopenharmony_ci}; 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_cistatic const struct regmap_range_cfg it6505_regmap_banks[] = { 50162306a36Sopenharmony_ci { 50262306a36Sopenharmony_ci .name = "it6505", 50362306a36Sopenharmony_ci .range_min = 0x00, 50462306a36Sopenharmony_ci .range_max = 0x1FF, 50562306a36Sopenharmony_ci .selector_reg = REG_BANK_SEL, 50662306a36Sopenharmony_ci .selector_mask = 0x1, 50762306a36Sopenharmony_ci .selector_shift = 0, 50862306a36Sopenharmony_ci .window_start = 0x00, 50962306a36Sopenharmony_ci .window_len = 0x100, 51062306a36Sopenharmony_ci }, 51162306a36Sopenharmony_ci}; 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_cistatic const struct regmap_config it6505_regmap_config = { 51462306a36Sopenharmony_ci .reg_bits = 8, 51562306a36Sopenharmony_ci .val_bits = 8, 51662306a36Sopenharmony_ci .volatile_table = &it6505_bridge_volatile_table, 51762306a36Sopenharmony_ci .cache_type = REGCACHE_NONE, 51862306a36Sopenharmony_ci .ranges = it6505_regmap_banks, 51962306a36Sopenharmony_ci .num_ranges = ARRAY_SIZE(it6505_regmap_banks), 52062306a36Sopenharmony_ci .max_register = 0x1FF, 52162306a36Sopenharmony_ci}; 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_cistatic int it6505_read(struct it6505 *it6505, unsigned int reg_addr) 52462306a36Sopenharmony_ci{ 52562306a36Sopenharmony_ci unsigned int value; 52662306a36Sopenharmony_ci int err; 52762306a36Sopenharmony_ci struct device *dev = it6505->dev; 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci if (!it6505->powered) 53062306a36Sopenharmony_ci return -ENODEV; 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ci err = regmap_read(it6505->regmap, reg_addr, &value); 53362306a36Sopenharmony_ci if (err < 0) { 53462306a36Sopenharmony_ci dev_err(dev, "read failed reg[0x%x] err: %d", reg_addr, err); 53562306a36Sopenharmony_ci return err; 53662306a36Sopenharmony_ci } 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci return value; 53962306a36Sopenharmony_ci} 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_cistatic int it6505_write(struct it6505 *it6505, unsigned int reg_addr, 54262306a36Sopenharmony_ci unsigned int reg_val) 54362306a36Sopenharmony_ci{ 54462306a36Sopenharmony_ci int err; 54562306a36Sopenharmony_ci struct device *dev = it6505->dev; 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci if (!it6505->powered) 54862306a36Sopenharmony_ci return -ENODEV; 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci err = regmap_write(it6505->regmap, reg_addr, reg_val); 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci if (err < 0) { 55362306a36Sopenharmony_ci dev_err(dev, "write failed reg[0x%x] = 0x%x err = %d", 55462306a36Sopenharmony_ci reg_addr, reg_val, err); 55562306a36Sopenharmony_ci return err; 55662306a36Sopenharmony_ci } 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci return 0; 55962306a36Sopenharmony_ci} 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_cistatic int it6505_set_bits(struct it6505 *it6505, unsigned int reg, 56262306a36Sopenharmony_ci unsigned int mask, unsigned int value) 56362306a36Sopenharmony_ci{ 56462306a36Sopenharmony_ci int err; 56562306a36Sopenharmony_ci struct device *dev = it6505->dev; 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ci if (!it6505->powered) 56862306a36Sopenharmony_ci return -ENODEV; 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci err = regmap_update_bits(it6505->regmap, reg, mask, value); 57162306a36Sopenharmony_ci if (err < 0) { 57262306a36Sopenharmony_ci dev_err(dev, "write reg[0x%x] = 0x%x mask = 0x%x failed err %d", 57362306a36Sopenharmony_ci reg, value, mask, err); 57462306a36Sopenharmony_ci return err; 57562306a36Sopenharmony_ci } 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci return 0; 57862306a36Sopenharmony_ci} 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_cistatic void it6505_debug_print(struct it6505 *it6505, unsigned int reg, 58162306a36Sopenharmony_ci const char *prefix) 58262306a36Sopenharmony_ci{ 58362306a36Sopenharmony_ci struct device *dev = it6505->dev; 58462306a36Sopenharmony_ci int val; 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci if (!drm_debug_enabled(DRM_UT_DRIVER)) 58762306a36Sopenharmony_ci return; 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci val = it6505_read(it6505, reg); 59062306a36Sopenharmony_ci if (val < 0) 59162306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "%s reg[%02x] read error (%d)", 59262306a36Sopenharmony_ci prefix, reg, val); 59362306a36Sopenharmony_ci else 59462306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "%s reg[%02x] = 0x%02x", prefix, reg, 59562306a36Sopenharmony_ci val); 59662306a36Sopenharmony_ci} 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_cistatic int it6505_dpcd_read(struct it6505 *it6505, unsigned long offset) 59962306a36Sopenharmony_ci{ 60062306a36Sopenharmony_ci u8 value; 60162306a36Sopenharmony_ci int ret; 60262306a36Sopenharmony_ci struct device *dev = it6505->dev; 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci ret = drm_dp_dpcd_readb(&it6505->aux, offset, &value); 60562306a36Sopenharmony_ci if (ret < 0) { 60662306a36Sopenharmony_ci dev_err(dev, "DPCD read failed [0x%lx] ret: %d", offset, ret); 60762306a36Sopenharmony_ci return ret; 60862306a36Sopenharmony_ci } 60962306a36Sopenharmony_ci return value; 61062306a36Sopenharmony_ci} 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_cistatic int it6505_dpcd_write(struct it6505 *it6505, unsigned long offset, 61362306a36Sopenharmony_ci u8 datain) 61462306a36Sopenharmony_ci{ 61562306a36Sopenharmony_ci int ret; 61662306a36Sopenharmony_ci struct device *dev = it6505->dev; 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci ret = drm_dp_dpcd_writeb(&it6505->aux, offset, datain); 61962306a36Sopenharmony_ci if (ret < 0) { 62062306a36Sopenharmony_ci dev_err(dev, "DPCD write failed [0x%lx] ret: %d", offset, ret); 62162306a36Sopenharmony_ci return ret; 62262306a36Sopenharmony_ci } 62362306a36Sopenharmony_ci return 0; 62462306a36Sopenharmony_ci} 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_cistatic int it6505_get_dpcd(struct it6505 *it6505, int offset, u8 *dpcd, int num) 62762306a36Sopenharmony_ci{ 62862306a36Sopenharmony_ci int ret; 62962306a36Sopenharmony_ci struct device *dev = it6505->dev; 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci ret = drm_dp_dpcd_read(&it6505->aux, offset, dpcd, num); 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci if (ret < 0) 63462306a36Sopenharmony_ci return ret; 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "ret = %d DPCD[0x%x] = 0x%*ph", ret, offset, 63762306a36Sopenharmony_ci num, dpcd); 63862306a36Sopenharmony_ci 63962306a36Sopenharmony_ci return 0; 64062306a36Sopenharmony_ci} 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_cistatic void it6505_dump(struct it6505 *it6505) 64362306a36Sopenharmony_ci{ 64462306a36Sopenharmony_ci unsigned int i, j; 64562306a36Sopenharmony_ci u8 regs[16]; 64662306a36Sopenharmony_ci struct device *dev = it6505->dev; 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci for (i = 0; i <= 0xff; i += 16) { 64962306a36Sopenharmony_ci for (j = 0; j < 16; j++) 65062306a36Sopenharmony_ci regs[j] = it6505_read(it6505, i + j); 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "[0x%02x] = %16ph", i, regs); 65362306a36Sopenharmony_ci } 65462306a36Sopenharmony_ci} 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_cistatic bool it6505_get_sink_hpd_status(struct it6505 *it6505) 65762306a36Sopenharmony_ci{ 65862306a36Sopenharmony_ci int reg_0d; 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci reg_0d = it6505_read(it6505, REG_SYSTEM_STS); 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci if (reg_0d < 0) 66362306a36Sopenharmony_ci return false; 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci return reg_0d & HPD_STS; 66662306a36Sopenharmony_ci} 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_cistatic int it6505_read_word(struct it6505 *it6505, unsigned int reg) 66962306a36Sopenharmony_ci{ 67062306a36Sopenharmony_ci int val0, val1; 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci val0 = it6505_read(it6505, reg); 67362306a36Sopenharmony_ci if (val0 < 0) 67462306a36Sopenharmony_ci return val0; 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_ci val1 = it6505_read(it6505, reg + 1); 67762306a36Sopenharmony_ci if (val1 < 0) 67862306a36Sopenharmony_ci return val1; 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci return (val1 << 8) | val0; 68162306a36Sopenharmony_ci} 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_cistatic void it6505_calc_video_info(struct it6505 *it6505) 68462306a36Sopenharmony_ci{ 68562306a36Sopenharmony_ci struct device *dev = it6505->dev; 68662306a36Sopenharmony_ci int hsync_pol, vsync_pol, interlaced; 68762306a36Sopenharmony_ci int htotal, hdes, hdew, hfph, hsyncw; 68862306a36Sopenharmony_ci int vtotal, vdes, vdew, vfph, vsyncw; 68962306a36Sopenharmony_ci int rddata, i, pclk, sum = 0; 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_ci usleep_range(10000, 15000); 69262306a36Sopenharmony_ci rddata = it6505_read(it6505, REG_INPUT_CTRL); 69362306a36Sopenharmony_ci hsync_pol = rddata & INPUT_HSYNC_POL; 69462306a36Sopenharmony_ci vsync_pol = (rddata & INPUT_VSYNC_POL) >> 2; 69562306a36Sopenharmony_ci interlaced = (rddata & INPUT_INTERLACED) >> 4; 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci htotal = it6505_read_word(it6505, REG_INPUT_HTOTAL) & 0x1FFF; 69862306a36Sopenharmony_ci hdes = it6505_read_word(it6505, REG_INPUT_HACTIVE_START) & 0x1FFF; 69962306a36Sopenharmony_ci hdew = it6505_read_word(it6505, REG_INPUT_HACTIVE_WIDTH) & 0x1FFF; 70062306a36Sopenharmony_ci hfph = it6505_read_word(it6505, REG_INPUT_HFRONT_PORCH) & 0x1FFF; 70162306a36Sopenharmony_ci hsyncw = it6505_read_word(it6505, REG_INPUT_HSYNC_WIDTH) & 0x1FFF; 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_ci vtotal = it6505_read_word(it6505, REG_INPUT_VTOTAL) & 0xFFF; 70462306a36Sopenharmony_ci vdes = it6505_read_word(it6505, REG_INPUT_VACTIVE_START) & 0xFFF; 70562306a36Sopenharmony_ci vdew = it6505_read_word(it6505, REG_INPUT_VACTIVE_WIDTH) & 0xFFF; 70662306a36Sopenharmony_ci vfph = it6505_read_word(it6505, REG_INPUT_VFRONT_PORCH) & 0xFFF; 70762306a36Sopenharmony_ci vsyncw = it6505_read_word(it6505, REG_INPUT_VSYNC_WIDTH) & 0xFFF; 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "hsync_pol:%d, vsync_pol:%d, interlaced:%d", 71062306a36Sopenharmony_ci hsync_pol, vsync_pol, interlaced); 71162306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "hactive_start:%d, vactive_start:%d", 71262306a36Sopenharmony_ci hdes, vdes); 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci for (i = 0; i < 3; i++) { 71562306a36Sopenharmony_ci it6505_set_bits(it6505, REG_DATA_CTRL0, ENABLE_PCLK_COUNTER, 71662306a36Sopenharmony_ci ENABLE_PCLK_COUNTER); 71762306a36Sopenharmony_ci usleep_range(10000, 15000); 71862306a36Sopenharmony_ci it6505_set_bits(it6505, REG_DATA_CTRL0, ENABLE_PCLK_COUNTER, 71962306a36Sopenharmony_ci 0x00); 72062306a36Sopenharmony_ci rddata = it6505_read_word(it6505, REG_PCLK_COUNTER_VALUE) & 72162306a36Sopenharmony_ci 0xFFF; 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ci sum += rddata; 72462306a36Sopenharmony_ci } 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci if (sum == 0) { 72762306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "calc video timing error"); 72862306a36Sopenharmony_ci return; 72962306a36Sopenharmony_ci } 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci sum /= 3; 73262306a36Sopenharmony_ci pclk = 13500 * 2048 / sum; 73362306a36Sopenharmony_ci it6505->video_info.clock = pclk; 73462306a36Sopenharmony_ci it6505->video_info.hdisplay = hdew; 73562306a36Sopenharmony_ci it6505->video_info.hsync_start = hdew + hfph; 73662306a36Sopenharmony_ci it6505->video_info.hsync_end = hdew + hfph + hsyncw; 73762306a36Sopenharmony_ci it6505->video_info.htotal = htotal; 73862306a36Sopenharmony_ci it6505->video_info.vdisplay = vdew; 73962306a36Sopenharmony_ci it6505->video_info.vsync_start = vdew + vfph; 74062306a36Sopenharmony_ci it6505->video_info.vsync_end = vdew + vfph + vsyncw; 74162306a36Sopenharmony_ci it6505->video_info.vtotal = vtotal; 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, DRM_MODE_FMT, 74462306a36Sopenharmony_ci DRM_MODE_ARG(&it6505->video_info)); 74562306a36Sopenharmony_ci} 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_cistatic int it6505_drm_dp_link_set_power(struct drm_dp_aux *aux, 74862306a36Sopenharmony_ci struct it6505_drm_dp_link *link, 74962306a36Sopenharmony_ci u8 mode) 75062306a36Sopenharmony_ci{ 75162306a36Sopenharmony_ci u8 value; 75262306a36Sopenharmony_ci int err; 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ci /* DP_SET_POWER register is only available on DPCD v1.1 and later */ 75562306a36Sopenharmony_ci if (link->revision < DPCD_V_1_1) 75662306a36Sopenharmony_ci return 0; 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_ci err = drm_dp_dpcd_readb(aux, DP_SET_POWER, &value); 75962306a36Sopenharmony_ci if (err < 0) 76062306a36Sopenharmony_ci return err; 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_ci value &= ~DP_SET_POWER_MASK; 76362306a36Sopenharmony_ci value |= mode; 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ci err = drm_dp_dpcd_writeb(aux, DP_SET_POWER, value); 76662306a36Sopenharmony_ci if (err < 0) 76762306a36Sopenharmony_ci return err; 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_ci if (mode == DP_SET_POWER_D0) { 77062306a36Sopenharmony_ci /* 77162306a36Sopenharmony_ci * According to the DP 1.1 specification, a "Sink Device must 77262306a36Sopenharmony_ci * exit the power saving state within 1 ms" (Section 2.5.3.1, 77362306a36Sopenharmony_ci * Table 5-52, "Sink Control Field" (register 0x600). 77462306a36Sopenharmony_ci */ 77562306a36Sopenharmony_ci usleep_range(1000, 2000); 77662306a36Sopenharmony_ci } 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_ci return 0; 77962306a36Sopenharmony_ci} 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_cistatic void it6505_clear_int(struct it6505 *it6505) 78262306a36Sopenharmony_ci{ 78362306a36Sopenharmony_ci it6505_write(it6505, INT_STATUS_01, 0xFF); 78462306a36Sopenharmony_ci it6505_write(it6505, INT_STATUS_02, 0xFF); 78562306a36Sopenharmony_ci it6505_write(it6505, INT_STATUS_03, 0xFF); 78662306a36Sopenharmony_ci} 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_cistatic void it6505_int_mask_enable(struct it6505 *it6505) 78962306a36Sopenharmony_ci{ 79062306a36Sopenharmony_ci it6505_write(it6505, INT_MASK_01, BIT(INT_HPD_CHANGE) | 79162306a36Sopenharmony_ci BIT(INT_RECEIVE_HPD_IRQ) | BIT(INT_SCDT_CHANGE) | 79262306a36Sopenharmony_ci BIT(INT_HDCP_FAIL) | BIT(INT_HDCP_DONE)); 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci it6505_write(it6505, INT_MASK_02, BIT(INT_AUX_CMD_FAIL) | 79562306a36Sopenharmony_ci BIT(INT_HDCP_KSV_CHECK) | BIT(INT_AUDIO_FIFO_ERROR)); 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_ci it6505_write(it6505, INT_MASK_03, BIT(INT_LINK_TRAIN_FAIL) | 79862306a36Sopenharmony_ci BIT(INT_VID_FIFO_ERROR) | BIT(INT_IO_LATCH_FIFO_OVERFLOW)); 79962306a36Sopenharmony_ci} 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_cistatic void it6505_int_mask_disable(struct it6505 *it6505) 80262306a36Sopenharmony_ci{ 80362306a36Sopenharmony_ci it6505_write(it6505, INT_MASK_01, 0x00); 80462306a36Sopenharmony_ci it6505_write(it6505, INT_MASK_02, 0x00); 80562306a36Sopenharmony_ci it6505_write(it6505, INT_MASK_03, 0x00); 80662306a36Sopenharmony_ci} 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_cistatic void it6505_lane_termination_on(struct it6505 *it6505) 80962306a36Sopenharmony_ci{ 81062306a36Sopenharmony_ci int regcf; 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_ci regcf = it6505_read(it6505, REG_USER_DRV_PRE); 81362306a36Sopenharmony_ci 81462306a36Sopenharmony_ci if (regcf == MISC_VERB) 81562306a36Sopenharmony_ci it6505_set_bits(it6505, REG_DRV_LN_DATA_SEL, 0x80, 0x00); 81662306a36Sopenharmony_ci 81762306a36Sopenharmony_ci if (regcf == MISC_VERC) { 81862306a36Sopenharmony_ci if (it6505->lane_swap) { 81962306a36Sopenharmony_ci switch (it6505->lane_count) { 82062306a36Sopenharmony_ci case 1: 82162306a36Sopenharmony_ci case 2: 82262306a36Sopenharmony_ci it6505_set_bits(it6505, REG_DRV_LN_DATA_SEL, 82362306a36Sopenharmony_ci 0x0C, 0x08); 82462306a36Sopenharmony_ci break; 82562306a36Sopenharmony_ci default: 82662306a36Sopenharmony_ci it6505_set_bits(it6505, REG_DRV_LN_DATA_SEL, 82762306a36Sopenharmony_ci 0x0C, 0x0C); 82862306a36Sopenharmony_ci break; 82962306a36Sopenharmony_ci } 83062306a36Sopenharmony_ci } else { 83162306a36Sopenharmony_ci switch (it6505->lane_count) { 83262306a36Sopenharmony_ci case 1: 83362306a36Sopenharmony_ci case 2: 83462306a36Sopenharmony_ci it6505_set_bits(it6505, REG_DRV_LN_DATA_SEL, 83562306a36Sopenharmony_ci 0x0C, 0x04); 83662306a36Sopenharmony_ci break; 83762306a36Sopenharmony_ci default: 83862306a36Sopenharmony_ci it6505_set_bits(it6505, REG_DRV_LN_DATA_SEL, 83962306a36Sopenharmony_ci 0x0C, 0x0C); 84062306a36Sopenharmony_ci break; 84162306a36Sopenharmony_ci } 84262306a36Sopenharmony_ci } 84362306a36Sopenharmony_ci } 84462306a36Sopenharmony_ci} 84562306a36Sopenharmony_ci 84662306a36Sopenharmony_cistatic void it6505_lane_termination_off(struct it6505 *it6505) 84762306a36Sopenharmony_ci{ 84862306a36Sopenharmony_ci int regcf; 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_ci regcf = it6505_read(it6505, REG_USER_DRV_PRE); 85162306a36Sopenharmony_ci 85262306a36Sopenharmony_ci if (regcf == MISC_VERB) 85362306a36Sopenharmony_ci it6505_set_bits(it6505, REG_DRV_LN_DATA_SEL, 0x80, 0x80); 85462306a36Sopenharmony_ci 85562306a36Sopenharmony_ci if (regcf == MISC_VERC) 85662306a36Sopenharmony_ci it6505_set_bits(it6505, REG_DRV_LN_DATA_SEL, 0x0C, 0x00); 85762306a36Sopenharmony_ci} 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_cistatic void it6505_lane_power_on(struct it6505 *it6505) 86062306a36Sopenharmony_ci{ 86162306a36Sopenharmony_ci it6505_set_bits(it6505, REG_LINK_DRV, 0xF1, 86262306a36Sopenharmony_ci (it6505->lane_swap ? 86362306a36Sopenharmony_ci GENMASK(7, 8 - it6505->lane_count) : 86462306a36Sopenharmony_ci GENMASK(3 + it6505->lane_count, 4)) | 86562306a36Sopenharmony_ci 0x01); 86662306a36Sopenharmony_ci} 86762306a36Sopenharmony_ci 86862306a36Sopenharmony_cistatic void it6505_lane_power_off(struct it6505 *it6505) 86962306a36Sopenharmony_ci{ 87062306a36Sopenharmony_ci it6505_set_bits(it6505, REG_LINK_DRV, 0xF0, 0x00); 87162306a36Sopenharmony_ci} 87262306a36Sopenharmony_ci 87362306a36Sopenharmony_cistatic void it6505_lane_off(struct it6505 *it6505) 87462306a36Sopenharmony_ci{ 87562306a36Sopenharmony_ci it6505_lane_power_off(it6505); 87662306a36Sopenharmony_ci it6505_lane_termination_off(it6505); 87762306a36Sopenharmony_ci} 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_cistatic void it6505_aux_termination_on(struct it6505 *it6505) 88062306a36Sopenharmony_ci{ 88162306a36Sopenharmony_ci int regcf; 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_ci regcf = it6505_read(it6505, REG_USER_DRV_PRE); 88462306a36Sopenharmony_ci 88562306a36Sopenharmony_ci if (regcf == MISC_VERB) 88662306a36Sopenharmony_ci it6505_lane_termination_on(it6505); 88762306a36Sopenharmony_ci 88862306a36Sopenharmony_ci if (regcf == MISC_VERC) 88962306a36Sopenharmony_ci it6505_set_bits(it6505, REG_DRV_LN_DATA_SEL, 0x80, 0x80); 89062306a36Sopenharmony_ci} 89162306a36Sopenharmony_ci 89262306a36Sopenharmony_cistatic void it6505_aux_power_on(struct it6505 *it6505) 89362306a36Sopenharmony_ci{ 89462306a36Sopenharmony_ci it6505_set_bits(it6505, REG_AUX, 0x02, 0x02); 89562306a36Sopenharmony_ci} 89662306a36Sopenharmony_ci 89762306a36Sopenharmony_cistatic void it6505_aux_on(struct it6505 *it6505) 89862306a36Sopenharmony_ci{ 89962306a36Sopenharmony_ci it6505_aux_power_on(it6505); 90062306a36Sopenharmony_ci it6505_aux_termination_on(it6505); 90162306a36Sopenharmony_ci} 90262306a36Sopenharmony_ci 90362306a36Sopenharmony_cistatic void it6505_aux_reset(struct it6505 *it6505) 90462306a36Sopenharmony_ci{ 90562306a36Sopenharmony_ci it6505_set_bits(it6505, REG_RESET_CTRL, AUX_RESET, AUX_RESET); 90662306a36Sopenharmony_ci it6505_set_bits(it6505, REG_RESET_CTRL, AUX_RESET, 0x00); 90762306a36Sopenharmony_ci} 90862306a36Sopenharmony_ci 90962306a36Sopenharmony_cistatic void it6505_reset_logic(struct it6505 *it6505) 91062306a36Sopenharmony_ci{ 91162306a36Sopenharmony_ci regmap_write(it6505->regmap, REG_RESET_CTRL, ALL_LOGIC_RESET); 91262306a36Sopenharmony_ci usleep_range(1000, 1500); 91362306a36Sopenharmony_ci} 91462306a36Sopenharmony_ci 91562306a36Sopenharmony_cistatic bool it6505_aux_op_finished(struct it6505 *it6505) 91662306a36Sopenharmony_ci{ 91762306a36Sopenharmony_ci int reg2b = it6505_read(it6505, REG_AUX_CMD_REQ); 91862306a36Sopenharmony_ci 91962306a36Sopenharmony_ci if (reg2b < 0) 92062306a36Sopenharmony_ci return false; 92162306a36Sopenharmony_ci 92262306a36Sopenharmony_ci return (reg2b & AUX_BUSY) == 0; 92362306a36Sopenharmony_ci} 92462306a36Sopenharmony_ci 92562306a36Sopenharmony_cistatic int it6505_aux_wait(struct it6505 *it6505) 92662306a36Sopenharmony_ci{ 92762306a36Sopenharmony_ci int status; 92862306a36Sopenharmony_ci unsigned long timeout; 92962306a36Sopenharmony_ci struct device *dev = it6505->dev; 93062306a36Sopenharmony_ci 93162306a36Sopenharmony_ci timeout = jiffies + msecs_to_jiffies(AUX_WAIT_TIMEOUT_MS) + 1; 93262306a36Sopenharmony_ci 93362306a36Sopenharmony_ci while (!it6505_aux_op_finished(it6505)) { 93462306a36Sopenharmony_ci if (time_after(jiffies, timeout)) { 93562306a36Sopenharmony_ci dev_err(dev, "Timed out waiting AUX to finish"); 93662306a36Sopenharmony_ci return -ETIMEDOUT; 93762306a36Sopenharmony_ci } 93862306a36Sopenharmony_ci usleep_range(1000, 2000); 93962306a36Sopenharmony_ci } 94062306a36Sopenharmony_ci 94162306a36Sopenharmony_ci status = it6505_read(it6505, REG_AUX_ERROR_STS); 94262306a36Sopenharmony_ci if (status < 0) { 94362306a36Sopenharmony_ci dev_err(dev, "Failed to read AUX channel: %d", status); 94462306a36Sopenharmony_ci return status; 94562306a36Sopenharmony_ci } 94662306a36Sopenharmony_ci 94762306a36Sopenharmony_ci return 0; 94862306a36Sopenharmony_ci} 94962306a36Sopenharmony_ci 95062306a36Sopenharmony_cistatic ssize_t it6505_aux_operation(struct it6505 *it6505, 95162306a36Sopenharmony_ci enum aux_cmd_type cmd, 95262306a36Sopenharmony_ci unsigned int address, u8 *buffer, 95362306a36Sopenharmony_ci size_t size, enum aux_cmd_reply *reply) 95462306a36Sopenharmony_ci{ 95562306a36Sopenharmony_ci int i, ret; 95662306a36Sopenharmony_ci bool aux_write_check = false; 95762306a36Sopenharmony_ci 95862306a36Sopenharmony_ci if (!it6505_get_sink_hpd_status(it6505)) 95962306a36Sopenharmony_ci return -EIO; 96062306a36Sopenharmony_ci 96162306a36Sopenharmony_ci /* set AUX user mode */ 96262306a36Sopenharmony_ci it6505_set_bits(it6505, REG_AUX_CTRL, AUX_USER_MODE, AUX_USER_MODE); 96362306a36Sopenharmony_ci 96462306a36Sopenharmony_ciaux_op_start: 96562306a36Sopenharmony_ci if (cmd == CMD_AUX_I2C_EDID_READ) { 96662306a36Sopenharmony_ci /* AUX EDID FIFO has max length of AUX_FIFO_MAX_SIZE bytes. */ 96762306a36Sopenharmony_ci size = min_t(size_t, size, AUX_FIFO_MAX_SIZE); 96862306a36Sopenharmony_ci /* Enable AUX FIFO read back and clear FIFO */ 96962306a36Sopenharmony_ci it6505_set_bits(it6505, REG_AUX_CTRL, 97062306a36Sopenharmony_ci AUX_EN_FIFO_READ | CLR_EDID_FIFO, 97162306a36Sopenharmony_ci AUX_EN_FIFO_READ | CLR_EDID_FIFO); 97262306a36Sopenharmony_ci 97362306a36Sopenharmony_ci it6505_set_bits(it6505, REG_AUX_CTRL, 97462306a36Sopenharmony_ci AUX_EN_FIFO_READ | CLR_EDID_FIFO, 97562306a36Sopenharmony_ci AUX_EN_FIFO_READ); 97662306a36Sopenharmony_ci } else { 97762306a36Sopenharmony_ci /* The DP AUX transmit buffer has 4 bytes. */ 97862306a36Sopenharmony_ci size = min_t(size_t, size, 4); 97962306a36Sopenharmony_ci it6505_set_bits(it6505, REG_AUX_CTRL, AUX_NO_SEGMENT_WR, 98062306a36Sopenharmony_ci AUX_NO_SEGMENT_WR); 98162306a36Sopenharmony_ci } 98262306a36Sopenharmony_ci 98362306a36Sopenharmony_ci /* Start Address[7:0] */ 98462306a36Sopenharmony_ci it6505_write(it6505, REG_AUX_ADR_0_7, (address >> 0) & 0xFF); 98562306a36Sopenharmony_ci /* Start Address[15:8] */ 98662306a36Sopenharmony_ci it6505_write(it6505, REG_AUX_ADR_8_15, (address >> 8) & 0xFF); 98762306a36Sopenharmony_ci /* WriteNum[3:0]+StartAdr[19:16] */ 98862306a36Sopenharmony_ci it6505_write(it6505, REG_AUX_ADR_16_19, 98962306a36Sopenharmony_ci ((address >> 16) & 0x0F) | ((size - 1) << 4)); 99062306a36Sopenharmony_ci 99162306a36Sopenharmony_ci if (cmd == CMD_AUX_NATIVE_WRITE) 99262306a36Sopenharmony_ci regmap_bulk_write(it6505->regmap, REG_AUX_OUT_DATA0, buffer, 99362306a36Sopenharmony_ci size); 99462306a36Sopenharmony_ci 99562306a36Sopenharmony_ci /* Aux Fire */ 99662306a36Sopenharmony_ci it6505_write(it6505, REG_AUX_CMD_REQ, cmd); 99762306a36Sopenharmony_ci 99862306a36Sopenharmony_ci ret = it6505_aux_wait(it6505); 99962306a36Sopenharmony_ci if (ret < 0) 100062306a36Sopenharmony_ci goto aux_op_err; 100162306a36Sopenharmony_ci 100262306a36Sopenharmony_ci ret = it6505_read(it6505, REG_AUX_ERROR_STS); 100362306a36Sopenharmony_ci if (ret < 0) 100462306a36Sopenharmony_ci goto aux_op_err; 100562306a36Sopenharmony_ci 100662306a36Sopenharmony_ci switch ((ret >> 6) & 0x3) { 100762306a36Sopenharmony_ci case 0: 100862306a36Sopenharmony_ci *reply = REPLY_ACK; 100962306a36Sopenharmony_ci break; 101062306a36Sopenharmony_ci case 1: 101162306a36Sopenharmony_ci *reply = REPLY_DEFER; 101262306a36Sopenharmony_ci ret = -EAGAIN; 101362306a36Sopenharmony_ci goto aux_op_err; 101462306a36Sopenharmony_ci case 2: 101562306a36Sopenharmony_ci *reply = REPLY_NACK; 101662306a36Sopenharmony_ci ret = -EIO; 101762306a36Sopenharmony_ci goto aux_op_err; 101862306a36Sopenharmony_ci case 3: 101962306a36Sopenharmony_ci ret = -ETIMEDOUT; 102062306a36Sopenharmony_ci goto aux_op_err; 102162306a36Sopenharmony_ci } 102262306a36Sopenharmony_ci 102362306a36Sopenharmony_ci /* Read back Native Write data */ 102462306a36Sopenharmony_ci if (cmd == CMD_AUX_NATIVE_WRITE) { 102562306a36Sopenharmony_ci aux_write_check = true; 102662306a36Sopenharmony_ci cmd = CMD_AUX_NATIVE_READ; 102762306a36Sopenharmony_ci goto aux_op_start; 102862306a36Sopenharmony_ci } 102962306a36Sopenharmony_ci 103062306a36Sopenharmony_ci if (cmd == CMD_AUX_I2C_EDID_READ) { 103162306a36Sopenharmony_ci for (i = 0; i < size; i++) { 103262306a36Sopenharmony_ci ret = it6505_read(it6505, REG_AUX_DATA_FIFO); 103362306a36Sopenharmony_ci if (ret < 0) 103462306a36Sopenharmony_ci goto aux_op_err; 103562306a36Sopenharmony_ci buffer[i] = ret; 103662306a36Sopenharmony_ci } 103762306a36Sopenharmony_ci } else { 103862306a36Sopenharmony_ci for (i = 0; i < size; i++) { 103962306a36Sopenharmony_ci ret = it6505_read(it6505, REG_AUX_DATA_0_7 + i); 104062306a36Sopenharmony_ci if (ret < 0) 104162306a36Sopenharmony_ci goto aux_op_err; 104262306a36Sopenharmony_ci 104362306a36Sopenharmony_ci if (aux_write_check && buffer[size - 1 - i] != ret) { 104462306a36Sopenharmony_ci ret = -EINVAL; 104562306a36Sopenharmony_ci goto aux_op_err; 104662306a36Sopenharmony_ci } 104762306a36Sopenharmony_ci 104862306a36Sopenharmony_ci buffer[size - 1 - i] = ret; 104962306a36Sopenharmony_ci } 105062306a36Sopenharmony_ci } 105162306a36Sopenharmony_ci 105262306a36Sopenharmony_ci ret = i; 105362306a36Sopenharmony_ci 105462306a36Sopenharmony_ciaux_op_err: 105562306a36Sopenharmony_ci if (cmd == CMD_AUX_I2C_EDID_READ) { 105662306a36Sopenharmony_ci /* clear AUX FIFO */ 105762306a36Sopenharmony_ci it6505_set_bits(it6505, REG_AUX_CTRL, 105862306a36Sopenharmony_ci AUX_EN_FIFO_READ | CLR_EDID_FIFO, 105962306a36Sopenharmony_ci AUX_EN_FIFO_READ | CLR_EDID_FIFO); 106062306a36Sopenharmony_ci it6505_set_bits(it6505, REG_AUX_CTRL, 106162306a36Sopenharmony_ci AUX_EN_FIFO_READ | CLR_EDID_FIFO, 0x00); 106262306a36Sopenharmony_ci } 106362306a36Sopenharmony_ci 106462306a36Sopenharmony_ci /* Leave AUX user mode */ 106562306a36Sopenharmony_ci it6505_set_bits(it6505, REG_AUX_CTRL, AUX_USER_MODE, 0); 106662306a36Sopenharmony_ci 106762306a36Sopenharmony_ci return ret; 106862306a36Sopenharmony_ci} 106962306a36Sopenharmony_ci 107062306a36Sopenharmony_cistatic ssize_t it6505_aux_do_transfer(struct it6505 *it6505, 107162306a36Sopenharmony_ci enum aux_cmd_type cmd, 107262306a36Sopenharmony_ci unsigned int address, u8 *buffer, 107362306a36Sopenharmony_ci size_t size, enum aux_cmd_reply *reply) 107462306a36Sopenharmony_ci{ 107562306a36Sopenharmony_ci int i, ret_size, ret = 0, request_size; 107662306a36Sopenharmony_ci 107762306a36Sopenharmony_ci mutex_lock(&it6505->aux_lock); 107862306a36Sopenharmony_ci for (i = 0; i < size; i += 4) { 107962306a36Sopenharmony_ci request_size = min((int)size - i, 4); 108062306a36Sopenharmony_ci ret_size = it6505_aux_operation(it6505, cmd, address + i, 108162306a36Sopenharmony_ci buffer + i, request_size, 108262306a36Sopenharmony_ci reply); 108362306a36Sopenharmony_ci if (ret_size < 0) { 108462306a36Sopenharmony_ci ret = ret_size; 108562306a36Sopenharmony_ci goto aux_op_err; 108662306a36Sopenharmony_ci } 108762306a36Sopenharmony_ci 108862306a36Sopenharmony_ci ret += ret_size; 108962306a36Sopenharmony_ci } 109062306a36Sopenharmony_ci 109162306a36Sopenharmony_ciaux_op_err: 109262306a36Sopenharmony_ci mutex_unlock(&it6505->aux_lock); 109362306a36Sopenharmony_ci return ret; 109462306a36Sopenharmony_ci} 109562306a36Sopenharmony_ci 109662306a36Sopenharmony_cistatic ssize_t it6505_aux_transfer(struct drm_dp_aux *aux, 109762306a36Sopenharmony_ci struct drm_dp_aux_msg *msg) 109862306a36Sopenharmony_ci{ 109962306a36Sopenharmony_ci struct it6505 *it6505 = container_of(aux, struct it6505, aux); 110062306a36Sopenharmony_ci u8 cmd; 110162306a36Sopenharmony_ci bool is_i2c = !(msg->request & DP_AUX_NATIVE_WRITE); 110262306a36Sopenharmony_ci int ret; 110362306a36Sopenharmony_ci enum aux_cmd_reply reply; 110462306a36Sopenharmony_ci 110562306a36Sopenharmony_ci /* IT6505 doesn't support arbitrary I2C read / write. */ 110662306a36Sopenharmony_ci if (is_i2c) 110762306a36Sopenharmony_ci return -EINVAL; 110862306a36Sopenharmony_ci 110962306a36Sopenharmony_ci switch (msg->request) { 111062306a36Sopenharmony_ci case DP_AUX_NATIVE_READ: 111162306a36Sopenharmony_ci cmd = CMD_AUX_NATIVE_READ; 111262306a36Sopenharmony_ci break; 111362306a36Sopenharmony_ci case DP_AUX_NATIVE_WRITE: 111462306a36Sopenharmony_ci cmd = CMD_AUX_NATIVE_WRITE; 111562306a36Sopenharmony_ci break; 111662306a36Sopenharmony_ci default: 111762306a36Sopenharmony_ci return -EINVAL; 111862306a36Sopenharmony_ci } 111962306a36Sopenharmony_ci 112062306a36Sopenharmony_ci ret = it6505_aux_do_transfer(it6505, cmd, msg->address, msg->buffer, 112162306a36Sopenharmony_ci msg->size, &reply); 112262306a36Sopenharmony_ci if (ret < 0) 112362306a36Sopenharmony_ci return ret; 112462306a36Sopenharmony_ci 112562306a36Sopenharmony_ci switch (reply) { 112662306a36Sopenharmony_ci case REPLY_ACK: 112762306a36Sopenharmony_ci msg->reply = DP_AUX_NATIVE_REPLY_ACK; 112862306a36Sopenharmony_ci break; 112962306a36Sopenharmony_ci case REPLY_NACK: 113062306a36Sopenharmony_ci msg->reply = DP_AUX_NATIVE_REPLY_NACK; 113162306a36Sopenharmony_ci break; 113262306a36Sopenharmony_ci case REPLY_DEFER: 113362306a36Sopenharmony_ci msg->reply = DP_AUX_NATIVE_REPLY_DEFER; 113462306a36Sopenharmony_ci break; 113562306a36Sopenharmony_ci } 113662306a36Sopenharmony_ci 113762306a36Sopenharmony_ci return ret; 113862306a36Sopenharmony_ci} 113962306a36Sopenharmony_ci 114062306a36Sopenharmony_cistatic int it6505_get_edid_block(void *data, u8 *buf, unsigned int block, 114162306a36Sopenharmony_ci size_t len) 114262306a36Sopenharmony_ci{ 114362306a36Sopenharmony_ci struct it6505 *it6505 = data; 114462306a36Sopenharmony_ci struct device *dev = it6505->dev; 114562306a36Sopenharmony_ci enum aux_cmd_reply reply; 114662306a36Sopenharmony_ci int offset, ret, aux_retry = 100; 114762306a36Sopenharmony_ci 114862306a36Sopenharmony_ci it6505_aux_reset(it6505); 114962306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "block number = %d", block); 115062306a36Sopenharmony_ci 115162306a36Sopenharmony_ci for (offset = 0; offset < EDID_LENGTH;) { 115262306a36Sopenharmony_ci ret = it6505_aux_do_transfer(it6505, CMD_AUX_I2C_EDID_READ, 115362306a36Sopenharmony_ci block * EDID_LENGTH + offset, 115462306a36Sopenharmony_ci buf + offset, 8, &reply); 115562306a36Sopenharmony_ci 115662306a36Sopenharmony_ci if (ret < 0 && ret != -EAGAIN) 115762306a36Sopenharmony_ci return ret; 115862306a36Sopenharmony_ci 115962306a36Sopenharmony_ci switch (reply) { 116062306a36Sopenharmony_ci case REPLY_ACK: 116162306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "[0x%02x]: %8ph", offset, 116262306a36Sopenharmony_ci buf + offset); 116362306a36Sopenharmony_ci offset += 8; 116462306a36Sopenharmony_ci aux_retry = 100; 116562306a36Sopenharmony_ci break; 116662306a36Sopenharmony_ci case REPLY_NACK: 116762306a36Sopenharmony_ci return -EIO; 116862306a36Sopenharmony_ci case REPLY_DEFER: 116962306a36Sopenharmony_ci msleep(20); 117062306a36Sopenharmony_ci if (!(--aux_retry)) 117162306a36Sopenharmony_ci return -EIO; 117262306a36Sopenharmony_ci } 117362306a36Sopenharmony_ci } 117462306a36Sopenharmony_ci 117562306a36Sopenharmony_ci return 0; 117662306a36Sopenharmony_ci} 117762306a36Sopenharmony_ci 117862306a36Sopenharmony_cistatic void it6505_variable_config(struct it6505 *it6505) 117962306a36Sopenharmony_ci{ 118062306a36Sopenharmony_ci it6505->link_rate_bw_code = HBR; 118162306a36Sopenharmony_ci it6505->lane_count = MAX_LANE_COUNT; 118262306a36Sopenharmony_ci it6505->link_state = LINK_IDLE; 118362306a36Sopenharmony_ci it6505->hdcp_desired = HDCP_DESIRED; 118462306a36Sopenharmony_ci it6505->auto_train_retry = AUTO_TRAIN_RETRY; 118562306a36Sopenharmony_ci it6505->audio.select = AUDIO_SELECT; 118662306a36Sopenharmony_ci it6505->audio.sample_rate = AUDIO_SAMPLE_RATE; 118762306a36Sopenharmony_ci it6505->audio.channel_count = AUDIO_CHANNEL_COUNT; 118862306a36Sopenharmony_ci it6505->audio.type = AUDIO_TYPE; 118962306a36Sopenharmony_ci it6505->audio.i2s_input_format = I2S_INPUT_FORMAT; 119062306a36Sopenharmony_ci it6505->audio.i2s_justified = I2S_JUSTIFIED; 119162306a36Sopenharmony_ci it6505->audio.i2s_data_delay = I2S_DATA_DELAY; 119262306a36Sopenharmony_ci it6505->audio.i2s_ws_channel = I2S_WS_CHANNEL; 119362306a36Sopenharmony_ci it6505->audio.i2s_data_sequence = I2S_DATA_SEQUENCE; 119462306a36Sopenharmony_ci it6505->audio.word_length = AUDIO_WORD_LENGTH; 119562306a36Sopenharmony_ci memset(it6505->sha1_input, 0, sizeof(it6505->sha1_input)); 119662306a36Sopenharmony_ci memset(it6505->bksvs, 0, sizeof(it6505->bksvs)); 119762306a36Sopenharmony_ci} 119862306a36Sopenharmony_ci 119962306a36Sopenharmony_cistatic int it6505_send_video_infoframe(struct it6505 *it6505, 120062306a36Sopenharmony_ci struct hdmi_avi_infoframe *frame) 120162306a36Sopenharmony_ci{ 120262306a36Sopenharmony_ci u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE]; 120362306a36Sopenharmony_ci int err; 120462306a36Sopenharmony_ci struct device *dev = it6505->dev; 120562306a36Sopenharmony_ci 120662306a36Sopenharmony_ci err = hdmi_avi_infoframe_pack(frame, buffer, sizeof(buffer)); 120762306a36Sopenharmony_ci if (err < 0) { 120862306a36Sopenharmony_ci dev_err(dev, "Failed to pack AVI infoframe: %d", err); 120962306a36Sopenharmony_ci return err; 121062306a36Sopenharmony_ci } 121162306a36Sopenharmony_ci 121262306a36Sopenharmony_ci err = it6505_set_bits(it6505, REG_INFOFRAME_CTRL, EN_AVI_PKT, 0x00); 121362306a36Sopenharmony_ci if (err) 121462306a36Sopenharmony_ci return err; 121562306a36Sopenharmony_ci 121662306a36Sopenharmony_ci err = regmap_bulk_write(it6505->regmap, REG_AVI_INFO_DB1, 121762306a36Sopenharmony_ci buffer + HDMI_INFOFRAME_HEADER_SIZE, 121862306a36Sopenharmony_ci frame->length); 121962306a36Sopenharmony_ci if (err) 122062306a36Sopenharmony_ci return err; 122162306a36Sopenharmony_ci 122262306a36Sopenharmony_ci err = it6505_set_bits(it6505, REG_INFOFRAME_CTRL, EN_AVI_PKT, 122362306a36Sopenharmony_ci EN_AVI_PKT); 122462306a36Sopenharmony_ci if (err) 122562306a36Sopenharmony_ci return err; 122662306a36Sopenharmony_ci 122762306a36Sopenharmony_ci return 0; 122862306a36Sopenharmony_ci} 122962306a36Sopenharmony_ci 123062306a36Sopenharmony_cistatic void it6505_get_extcon_property(struct it6505 *it6505) 123162306a36Sopenharmony_ci{ 123262306a36Sopenharmony_ci int err; 123362306a36Sopenharmony_ci union extcon_property_value property; 123462306a36Sopenharmony_ci struct device *dev = it6505->dev; 123562306a36Sopenharmony_ci 123662306a36Sopenharmony_ci if (it6505->extcon && !it6505->lane_swap_disabled) { 123762306a36Sopenharmony_ci err = extcon_get_property(it6505->extcon, EXTCON_DISP_DP, 123862306a36Sopenharmony_ci EXTCON_PROP_USB_TYPEC_POLARITY, 123962306a36Sopenharmony_ci &property); 124062306a36Sopenharmony_ci if (err) { 124162306a36Sopenharmony_ci dev_err(dev, "get property fail!"); 124262306a36Sopenharmony_ci return; 124362306a36Sopenharmony_ci } 124462306a36Sopenharmony_ci it6505->lane_swap = property.intval; 124562306a36Sopenharmony_ci } 124662306a36Sopenharmony_ci} 124762306a36Sopenharmony_ci 124862306a36Sopenharmony_cistatic void it6505_clk_phase_adjustment(struct it6505 *it6505, 124962306a36Sopenharmony_ci const struct drm_display_mode *mode) 125062306a36Sopenharmony_ci{ 125162306a36Sopenharmony_ci int clock = mode->clock; 125262306a36Sopenharmony_ci 125362306a36Sopenharmony_ci it6505_set_bits(it6505, REG_CLK_CTRL0, M_PCLK_DELAY, 125462306a36Sopenharmony_ci clock < ADJUST_PHASE_THRESHOLD ? PIXEL_CLK_DELAY : 0); 125562306a36Sopenharmony_ci it6505_set_bits(it6505, REG_DATA_CTRL0, VIDEO_LATCH_EDGE, 125662306a36Sopenharmony_ci PIXEL_CLK_INVERSE << 4); 125762306a36Sopenharmony_ci} 125862306a36Sopenharmony_ci 125962306a36Sopenharmony_cistatic void it6505_link_reset_step_train(struct it6505 *it6505) 126062306a36Sopenharmony_ci{ 126162306a36Sopenharmony_ci it6505_set_bits(it6505, REG_TRAIN_CTRL0, 126262306a36Sopenharmony_ci FORCE_CR_DONE | FORCE_EQ_DONE, 0x00); 126362306a36Sopenharmony_ci it6505_dpcd_write(it6505, DP_TRAINING_PATTERN_SET, 126462306a36Sopenharmony_ci DP_TRAINING_PATTERN_DISABLE); 126562306a36Sopenharmony_ci} 126662306a36Sopenharmony_ci 126762306a36Sopenharmony_cistatic void it6505_init(struct it6505 *it6505) 126862306a36Sopenharmony_ci{ 126962306a36Sopenharmony_ci it6505_write(it6505, REG_AUX_OPT, AUX_AUTO_RST | AUX_FIX_FREQ); 127062306a36Sopenharmony_ci it6505_write(it6505, REG_AUX_CTRL, AUX_NO_SEGMENT_WR); 127162306a36Sopenharmony_ci it6505_write(it6505, REG_HDCP_CTRL2, HDCP_AN_SEL | HDCP_HW_HPDIRQ_ACT); 127262306a36Sopenharmony_ci it6505_write(it6505, REG_VID_BUS_CTRL0, IN_DDR | DDR_CD); 127362306a36Sopenharmony_ci it6505_write(it6505, REG_VID_BUS_CTRL1, 0x01); 127462306a36Sopenharmony_ci it6505_write(it6505, REG_AUDIO_CTRL0, AUDIO_16B_BOUND); 127562306a36Sopenharmony_ci 127662306a36Sopenharmony_ci /* chip internal setting, don't modify */ 127762306a36Sopenharmony_ci it6505_write(it6505, REG_HPD_IRQ_TIME, 0xF5); 127862306a36Sopenharmony_ci it6505_write(it6505, REG_AUX_DEBUG_MODE, 0x4D); 127962306a36Sopenharmony_ci it6505_write(it6505, REG_AUX_OPT2, 0x17); 128062306a36Sopenharmony_ci it6505_write(it6505, REG_HDCP_OPT, 0x60); 128162306a36Sopenharmony_ci it6505_write(it6505, REG_DATA_MUTE_CTRL, 128262306a36Sopenharmony_ci EN_VID_MUTE | EN_AUD_MUTE | ENABLE_AUTO_VIDEO_FIFO_RESET); 128362306a36Sopenharmony_ci it6505_write(it6505, REG_TIME_STMP_CTRL, 128462306a36Sopenharmony_ci EN_SSC_GAT | EN_ENHANCE_VID_STMP | EN_ENHANCE_AUD_STMP); 128562306a36Sopenharmony_ci it6505_write(it6505, REG_INFOFRAME_CTRL, 0x00); 128662306a36Sopenharmony_ci it6505_write(it6505, REG_DRV_0_DB_800_MV, 128762306a36Sopenharmony_ci afe_setting_table[it6505->afe_setting][0]); 128862306a36Sopenharmony_ci it6505_write(it6505, REG_PRE_0_DB_800_MV, 128962306a36Sopenharmony_ci afe_setting_table[it6505->afe_setting][1]); 129062306a36Sopenharmony_ci it6505_write(it6505, REG_PRE_3P5_DB_800_MV, 129162306a36Sopenharmony_ci afe_setting_table[it6505->afe_setting][2]); 129262306a36Sopenharmony_ci it6505_write(it6505, REG_SSC_CTRL0, 0x9E); 129362306a36Sopenharmony_ci it6505_write(it6505, REG_SSC_CTRL1, 0x1C); 129462306a36Sopenharmony_ci it6505_write(it6505, REG_SSC_CTRL2, 0x42); 129562306a36Sopenharmony_ci} 129662306a36Sopenharmony_ci 129762306a36Sopenharmony_cistatic void it6505_video_disable(struct it6505 *it6505) 129862306a36Sopenharmony_ci{ 129962306a36Sopenharmony_ci it6505_set_bits(it6505, REG_DATA_MUTE_CTRL, EN_VID_MUTE, EN_VID_MUTE); 130062306a36Sopenharmony_ci it6505_set_bits(it6505, REG_INFOFRAME_CTRL, EN_VID_CTRL_PKT, 0x00); 130162306a36Sopenharmony_ci it6505_set_bits(it6505, REG_RESET_CTRL, VIDEO_RESET, VIDEO_RESET); 130262306a36Sopenharmony_ci} 130362306a36Sopenharmony_ci 130462306a36Sopenharmony_cistatic void it6505_video_reset(struct it6505 *it6505) 130562306a36Sopenharmony_ci{ 130662306a36Sopenharmony_ci it6505_link_reset_step_train(it6505); 130762306a36Sopenharmony_ci it6505_set_bits(it6505, REG_DATA_MUTE_CTRL, EN_VID_MUTE, EN_VID_MUTE); 130862306a36Sopenharmony_ci it6505_set_bits(it6505, REG_INFOFRAME_CTRL, EN_VID_CTRL_PKT, 0x00); 130962306a36Sopenharmony_ci it6505_set_bits(it6505, REG_RESET_CTRL, VIDEO_RESET, VIDEO_RESET); 131062306a36Sopenharmony_ci it6505_set_bits(it6505, REG_501_FIFO_CTRL, RST_501_FIFO, RST_501_FIFO); 131162306a36Sopenharmony_ci it6505_set_bits(it6505, REG_501_FIFO_CTRL, RST_501_FIFO, 0x00); 131262306a36Sopenharmony_ci it6505_set_bits(it6505, REG_RESET_CTRL, VIDEO_RESET, 0x00); 131362306a36Sopenharmony_ci} 131462306a36Sopenharmony_ci 131562306a36Sopenharmony_cistatic void it6505_update_video_parameter(struct it6505 *it6505, 131662306a36Sopenharmony_ci const struct drm_display_mode *mode) 131762306a36Sopenharmony_ci{ 131862306a36Sopenharmony_ci it6505_clk_phase_adjustment(it6505, mode); 131962306a36Sopenharmony_ci it6505_video_disable(it6505); 132062306a36Sopenharmony_ci} 132162306a36Sopenharmony_ci 132262306a36Sopenharmony_cistatic bool it6505_audio_input(struct it6505 *it6505) 132362306a36Sopenharmony_ci{ 132462306a36Sopenharmony_ci int reg05, regbe; 132562306a36Sopenharmony_ci 132662306a36Sopenharmony_ci reg05 = it6505_read(it6505, REG_RESET_CTRL); 132762306a36Sopenharmony_ci it6505_set_bits(it6505, REG_RESET_CTRL, AUDIO_RESET, 0x00); 132862306a36Sopenharmony_ci usleep_range(3000, 4000); 132962306a36Sopenharmony_ci regbe = it6505_read(it6505, REG_AUDIO_INPUT_FREQ); 133062306a36Sopenharmony_ci it6505_write(it6505, REG_RESET_CTRL, reg05); 133162306a36Sopenharmony_ci 133262306a36Sopenharmony_ci return regbe != 0xFF; 133362306a36Sopenharmony_ci} 133462306a36Sopenharmony_ci 133562306a36Sopenharmony_cistatic void it6505_setup_audio_channel_status(struct it6505 *it6505) 133662306a36Sopenharmony_ci{ 133762306a36Sopenharmony_ci enum it6505_audio_sample_rate sample_rate = it6505->audio.sample_rate; 133862306a36Sopenharmony_ci u8 audio_word_length_map[] = { 0x02, 0x04, 0x03, 0x0B }; 133962306a36Sopenharmony_ci 134062306a36Sopenharmony_ci /* Channel Status */ 134162306a36Sopenharmony_ci it6505_write(it6505, REG_IEC958_STS0, it6505->audio.type << 1); 134262306a36Sopenharmony_ci it6505_write(it6505, REG_IEC958_STS1, 0x00); 134362306a36Sopenharmony_ci it6505_write(it6505, REG_IEC958_STS2, 0x00); 134462306a36Sopenharmony_ci it6505_write(it6505, REG_IEC958_STS3, sample_rate); 134562306a36Sopenharmony_ci it6505_write(it6505, REG_IEC958_STS4, (~sample_rate << 4) | 134662306a36Sopenharmony_ci audio_word_length_map[it6505->audio.word_length]); 134762306a36Sopenharmony_ci} 134862306a36Sopenharmony_ci 134962306a36Sopenharmony_cistatic void it6505_setup_audio_format(struct it6505 *it6505) 135062306a36Sopenharmony_ci{ 135162306a36Sopenharmony_ci /* I2S MODE */ 135262306a36Sopenharmony_ci it6505_write(it6505, REG_AUDIO_FMT, 135362306a36Sopenharmony_ci (it6505->audio.word_length << 5) | 135462306a36Sopenharmony_ci (it6505->audio.i2s_data_sequence << 4) | 135562306a36Sopenharmony_ci (it6505->audio.i2s_ws_channel << 3) | 135662306a36Sopenharmony_ci (it6505->audio.i2s_data_delay << 2) | 135762306a36Sopenharmony_ci (it6505->audio.i2s_justified << 1) | 135862306a36Sopenharmony_ci it6505->audio.i2s_input_format); 135962306a36Sopenharmony_ci if (it6505->audio.select == SPDIF) { 136062306a36Sopenharmony_ci it6505_write(it6505, REG_AUDIO_FIFO_SEL, 0x00); 136162306a36Sopenharmony_ci /* 0x30 = 128*FS */ 136262306a36Sopenharmony_ci it6505_set_bits(it6505, REG_AUX_OPT, 0xF0, 0x30); 136362306a36Sopenharmony_ci } else { 136462306a36Sopenharmony_ci it6505_write(it6505, REG_AUDIO_FIFO_SEL, 0xE4); 136562306a36Sopenharmony_ci } 136662306a36Sopenharmony_ci 136762306a36Sopenharmony_ci it6505_write(it6505, REG_AUDIO_CTRL0, 0x20); 136862306a36Sopenharmony_ci it6505_write(it6505, REG_AUDIO_CTRL1, 0x00); 136962306a36Sopenharmony_ci} 137062306a36Sopenharmony_ci 137162306a36Sopenharmony_cistatic void it6505_enable_audio_source(struct it6505 *it6505) 137262306a36Sopenharmony_ci{ 137362306a36Sopenharmony_ci unsigned int audio_source_count; 137462306a36Sopenharmony_ci 137562306a36Sopenharmony_ci audio_source_count = BIT(DIV_ROUND_UP(it6505->audio.channel_count, 2)) 137662306a36Sopenharmony_ci - 1; 137762306a36Sopenharmony_ci 137862306a36Sopenharmony_ci audio_source_count |= it6505->audio.select << 4; 137962306a36Sopenharmony_ci 138062306a36Sopenharmony_ci it6505_write(it6505, REG_AUDIO_SRC_CTRL, audio_source_count); 138162306a36Sopenharmony_ci} 138262306a36Sopenharmony_ci 138362306a36Sopenharmony_cistatic void it6505_enable_audio_infoframe(struct it6505 *it6505) 138462306a36Sopenharmony_ci{ 138562306a36Sopenharmony_ci struct device *dev = it6505->dev; 138662306a36Sopenharmony_ci u8 audio_info_ca[] = { 0x00, 0x00, 0x01, 0x03, 0x07, 0x0B, 0x0F, 0x1F }; 138762306a36Sopenharmony_ci 138862306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "infoframe channel_allocation:0x%02x", 138962306a36Sopenharmony_ci audio_info_ca[it6505->audio.channel_count - 1]); 139062306a36Sopenharmony_ci 139162306a36Sopenharmony_ci it6505_write(it6505, REG_AUD_INFOFRAM_DB1, it6505->audio.channel_count 139262306a36Sopenharmony_ci - 1); 139362306a36Sopenharmony_ci it6505_write(it6505, REG_AUD_INFOFRAM_DB2, 0x00); 139462306a36Sopenharmony_ci it6505_write(it6505, REG_AUD_INFOFRAM_DB3, 139562306a36Sopenharmony_ci audio_info_ca[it6505->audio.channel_count - 1]); 139662306a36Sopenharmony_ci it6505_write(it6505, REG_AUD_INFOFRAM_DB4, 0x00); 139762306a36Sopenharmony_ci it6505_write(it6505, REG_AUD_INFOFRAM_SUM, 0x00); 139862306a36Sopenharmony_ci 139962306a36Sopenharmony_ci /* Enable Audio InfoFrame */ 140062306a36Sopenharmony_ci it6505_set_bits(it6505, REG_INFOFRAME_CTRL, EN_AUD_CTRL_PKT, 140162306a36Sopenharmony_ci EN_AUD_CTRL_PKT); 140262306a36Sopenharmony_ci} 140362306a36Sopenharmony_ci 140462306a36Sopenharmony_cistatic void it6505_disable_audio(struct it6505 *it6505) 140562306a36Sopenharmony_ci{ 140662306a36Sopenharmony_ci it6505_set_bits(it6505, REG_DATA_MUTE_CTRL, EN_AUD_MUTE, EN_AUD_MUTE); 140762306a36Sopenharmony_ci it6505_set_bits(it6505, REG_AUDIO_SRC_CTRL, M_AUDIO_I2S_EN, 0x00); 140862306a36Sopenharmony_ci it6505_set_bits(it6505, REG_INFOFRAME_CTRL, EN_AUD_CTRL_PKT, 0x00); 140962306a36Sopenharmony_ci it6505_set_bits(it6505, REG_RESET_CTRL, AUDIO_RESET, AUDIO_RESET); 141062306a36Sopenharmony_ci} 141162306a36Sopenharmony_ci 141262306a36Sopenharmony_cistatic void it6505_enable_audio(struct it6505 *it6505) 141362306a36Sopenharmony_ci{ 141462306a36Sopenharmony_ci struct device *dev = it6505->dev; 141562306a36Sopenharmony_ci int regbe; 141662306a36Sopenharmony_ci 141762306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "start"); 141862306a36Sopenharmony_ci it6505_disable_audio(it6505); 141962306a36Sopenharmony_ci 142062306a36Sopenharmony_ci it6505_setup_audio_channel_status(it6505); 142162306a36Sopenharmony_ci it6505_setup_audio_format(it6505); 142262306a36Sopenharmony_ci it6505_enable_audio_source(it6505); 142362306a36Sopenharmony_ci it6505_enable_audio_infoframe(it6505); 142462306a36Sopenharmony_ci 142562306a36Sopenharmony_ci it6505_write(it6505, REG_AUDIO_N_0_7, 0x00); 142662306a36Sopenharmony_ci it6505_write(it6505, REG_AUDIO_N_8_15, 0x80); 142762306a36Sopenharmony_ci it6505_write(it6505, REG_AUDIO_N_16_23, 0x00); 142862306a36Sopenharmony_ci 142962306a36Sopenharmony_ci it6505_set_bits(it6505, REG_AUDIO_SRC_CTRL, AUDIO_FIFO_RESET, 143062306a36Sopenharmony_ci AUDIO_FIFO_RESET); 143162306a36Sopenharmony_ci it6505_set_bits(it6505, REG_AUDIO_SRC_CTRL, AUDIO_FIFO_RESET, 0x00); 143262306a36Sopenharmony_ci it6505_set_bits(it6505, REG_RESET_CTRL, AUDIO_RESET, 0x00); 143362306a36Sopenharmony_ci regbe = it6505_read(it6505, REG_AUDIO_INPUT_FREQ); 143462306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "regbe:0x%02x audio input fs: %d.%d kHz", 143562306a36Sopenharmony_ci regbe, 6750 / regbe, (6750 % regbe) * 10 / regbe); 143662306a36Sopenharmony_ci it6505_set_bits(it6505, REG_DATA_MUTE_CTRL, EN_AUD_MUTE, 0x00); 143762306a36Sopenharmony_ci} 143862306a36Sopenharmony_ci 143962306a36Sopenharmony_cistatic bool it6505_use_step_train_check(struct it6505 *it6505) 144062306a36Sopenharmony_ci{ 144162306a36Sopenharmony_ci if (it6505->link.revision >= 0x12) 144262306a36Sopenharmony_ci return it6505->dpcd[DP_TRAINING_AUX_RD_INTERVAL] >= 0x01; 144362306a36Sopenharmony_ci 144462306a36Sopenharmony_ci return true; 144562306a36Sopenharmony_ci} 144662306a36Sopenharmony_ci 144762306a36Sopenharmony_cistatic void it6505_parse_link_capabilities(struct it6505 *it6505) 144862306a36Sopenharmony_ci{ 144962306a36Sopenharmony_ci struct device *dev = it6505->dev; 145062306a36Sopenharmony_ci struct it6505_drm_dp_link *link = &it6505->link; 145162306a36Sopenharmony_ci int bcaps; 145262306a36Sopenharmony_ci 145362306a36Sopenharmony_ci if (it6505->dpcd[0] == 0) { 145462306a36Sopenharmony_ci dev_err(dev, "DPCD is not initialized"); 145562306a36Sopenharmony_ci return; 145662306a36Sopenharmony_ci } 145762306a36Sopenharmony_ci 145862306a36Sopenharmony_ci memset(link, 0, sizeof(*link)); 145962306a36Sopenharmony_ci 146062306a36Sopenharmony_ci link->revision = it6505->dpcd[0]; 146162306a36Sopenharmony_ci link->rate = drm_dp_bw_code_to_link_rate(it6505->dpcd[1]); 146262306a36Sopenharmony_ci link->num_lanes = it6505->dpcd[2] & DP_MAX_LANE_COUNT_MASK; 146362306a36Sopenharmony_ci 146462306a36Sopenharmony_ci if (it6505->dpcd[2] & DP_ENHANCED_FRAME_CAP) 146562306a36Sopenharmony_ci link->capabilities = DP_ENHANCED_FRAME_CAP; 146662306a36Sopenharmony_ci 146762306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "DPCD Rev.: %d.%d", 146862306a36Sopenharmony_ci link->revision >> 4, link->revision & 0x0F); 146962306a36Sopenharmony_ci 147062306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "Sink max link rate: %d.%02d Gbps per lane", 147162306a36Sopenharmony_ci link->rate / 100000, link->rate / 1000 % 100); 147262306a36Sopenharmony_ci 147362306a36Sopenharmony_ci it6505->link_rate_bw_code = drm_dp_link_rate_to_bw_code(link->rate); 147462306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "link rate bw code:0x%02x", 147562306a36Sopenharmony_ci it6505->link_rate_bw_code); 147662306a36Sopenharmony_ci it6505->link_rate_bw_code = min_t(int, it6505->link_rate_bw_code, 147762306a36Sopenharmony_ci MAX_LINK_RATE); 147862306a36Sopenharmony_ci 147962306a36Sopenharmony_ci it6505->lane_count = link->num_lanes; 148062306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "Sink support %d lanes training", 148162306a36Sopenharmony_ci it6505->lane_count); 148262306a36Sopenharmony_ci it6505->lane_count = min_t(int, it6505->lane_count, 148362306a36Sopenharmony_ci it6505->max_lane_count); 148462306a36Sopenharmony_ci 148562306a36Sopenharmony_ci it6505->branch_device = drm_dp_is_branch(it6505->dpcd); 148662306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "Sink %sbranch device", 148762306a36Sopenharmony_ci it6505->branch_device ? "" : "Not "); 148862306a36Sopenharmony_ci 148962306a36Sopenharmony_ci it6505->enable_enhanced_frame = link->capabilities; 149062306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "Sink %sSupport Enhanced Framing", 149162306a36Sopenharmony_ci it6505->enable_enhanced_frame ? "" : "Not "); 149262306a36Sopenharmony_ci 149362306a36Sopenharmony_ci it6505->enable_ssc = (it6505->dpcd[DP_MAX_DOWNSPREAD] & 149462306a36Sopenharmony_ci DP_MAX_DOWNSPREAD_0_5); 149562306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "Maximum Down-Spread: %s, %ssupport SSC!", 149662306a36Sopenharmony_ci it6505->enable_ssc ? "0.5" : "0", 149762306a36Sopenharmony_ci it6505->enable_ssc ? "" : "Not "); 149862306a36Sopenharmony_ci 149962306a36Sopenharmony_ci it6505->step_train = it6505_use_step_train_check(it6505); 150062306a36Sopenharmony_ci if (it6505->step_train) 150162306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "auto train fail, will step train"); 150262306a36Sopenharmony_ci 150362306a36Sopenharmony_ci bcaps = it6505_dpcd_read(it6505, DP_AUX_HDCP_BCAPS); 150462306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "bcaps:0x%02x", bcaps); 150562306a36Sopenharmony_ci if (bcaps & DP_BCAPS_HDCP_CAPABLE) { 150662306a36Sopenharmony_ci it6505->is_repeater = (bcaps & DP_BCAPS_REPEATER_PRESENT); 150762306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "Support HDCP! Downstream is %s!", 150862306a36Sopenharmony_ci it6505->is_repeater ? "repeater" : 150962306a36Sopenharmony_ci "receiver"); 151062306a36Sopenharmony_ci } else { 151162306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "Sink not support HDCP!"); 151262306a36Sopenharmony_ci it6505->hdcp_desired = false; 151362306a36Sopenharmony_ci } 151462306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "HDCP %s", 151562306a36Sopenharmony_ci it6505->hdcp_desired ? "desired" : "undesired"); 151662306a36Sopenharmony_ci} 151762306a36Sopenharmony_ci 151862306a36Sopenharmony_cistatic void it6505_setup_ssc(struct it6505 *it6505) 151962306a36Sopenharmony_ci{ 152062306a36Sopenharmony_ci it6505_set_bits(it6505, REG_TRAIN_CTRL0, SPREAD_AMP_5, 152162306a36Sopenharmony_ci it6505->enable_ssc ? SPREAD_AMP_5 : 0x00); 152262306a36Sopenharmony_ci if (it6505->enable_ssc) { 152362306a36Sopenharmony_ci it6505_write(it6505, REG_SSC_CTRL0, 0x9E); 152462306a36Sopenharmony_ci it6505_write(it6505, REG_SSC_CTRL1, 0x1C); 152562306a36Sopenharmony_ci it6505_write(it6505, REG_SSC_CTRL2, 0x42); 152662306a36Sopenharmony_ci it6505_write(it6505, REG_SP_CTRL0, 0x07); 152762306a36Sopenharmony_ci it6505_write(it6505, REG_IP_CTRL1, 0x29); 152862306a36Sopenharmony_ci it6505_write(it6505, REG_IP_CTRL2, 0x03); 152962306a36Sopenharmony_ci /* Stamp Interrupt Step */ 153062306a36Sopenharmony_ci it6505_set_bits(it6505, REG_TIME_STMP_CTRL, M_STAMP_STEP, 153162306a36Sopenharmony_ci 0x10); 153262306a36Sopenharmony_ci it6505_dpcd_write(it6505, DP_DOWNSPREAD_CTRL, 153362306a36Sopenharmony_ci DP_SPREAD_AMP_0_5); 153462306a36Sopenharmony_ci } else { 153562306a36Sopenharmony_ci it6505_dpcd_write(it6505, DP_DOWNSPREAD_CTRL, 0x00); 153662306a36Sopenharmony_ci it6505_set_bits(it6505, REG_TIME_STMP_CTRL, M_STAMP_STEP, 153762306a36Sopenharmony_ci 0x00); 153862306a36Sopenharmony_ci } 153962306a36Sopenharmony_ci} 154062306a36Sopenharmony_ci 154162306a36Sopenharmony_cistatic inline void it6505_link_rate_setup(struct it6505 *it6505) 154262306a36Sopenharmony_ci{ 154362306a36Sopenharmony_ci it6505_set_bits(it6505, REG_TRAIN_CTRL0, FORCE_LBR, 154462306a36Sopenharmony_ci (it6505->link_rate_bw_code == RBR) ? FORCE_LBR : 0x00); 154562306a36Sopenharmony_ci it6505_set_bits(it6505, REG_LINK_DRV, DRV_HS, 154662306a36Sopenharmony_ci (it6505->link_rate_bw_code == RBR) ? 0x00 : DRV_HS); 154762306a36Sopenharmony_ci} 154862306a36Sopenharmony_ci 154962306a36Sopenharmony_cistatic void it6505_lane_count_setup(struct it6505 *it6505) 155062306a36Sopenharmony_ci{ 155162306a36Sopenharmony_ci it6505_get_extcon_property(it6505); 155262306a36Sopenharmony_ci it6505_set_bits(it6505, REG_TRAIN_CTRL0, LANE_SWAP, 155362306a36Sopenharmony_ci it6505->lane_swap ? LANE_SWAP : 0x00); 155462306a36Sopenharmony_ci it6505_set_bits(it6505, REG_TRAIN_CTRL0, LANE_COUNT_MASK, 155562306a36Sopenharmony_ci (it6505->lane_count - 1) << 1); 155662306a36Sopenharmony_ci} 155762306a36Sopenharmony_ci 155862306a36Sopenharmony_cistatic void it6505_link_training_setup(struct it6505 *it6505) 155962306a36Sopenharmony_ci{ 156062306a36Sopenharmony_ci struct device *dev = it6505->dev; 156162306a36Sopenharmony_ci 156262306a36Sopenharmony_ci if (it6505->enable_enhanced_frame) 156362306a36Sopenharmony_ci it6505_set_bits(it6505, REG_DATA_MUTE_CTRL, 156462306a36Sopenharmony_ci ENABLE_ENHANCED_FRAME, ENABLE_ENHANCED_FRAME); 156562306a36Sopenharmony_ci 156662306a36Sopenharmony_ci it6505_link_rate_setup(it6505); 156762306a36Sopenharmony_ci it6505_lane_count_setup(it6505); 156862306a36Sopenharmony_ci it6505_setup_ssc(it6505); 156962306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, 157062306a36Sopenharmony_ci "%s, %d lanes, %sable ssc, %sable enhanced frame", 157162306a36Sopenharmony_ci it6505->link_rate_bw_code != RBR ? "HBR" : "RBR", 157262306a36Sopenharmony_ci it6505->lane_count, 157362306a36Sopenharmony_ci it6505->enable_ssc ? "en" : "dis", 157462306a36Sopenharmony_ci it6505->enable_enhanced_frame ? "en" : "dis"); 157562306a36Sopenharmony_ci} 157662306a36Sopenharmony_ci 157762306a36Sopenharmony_cistatic bool it6505_link_start_auto_train(struct it6505 *it6505) 157862306a36Sopenharmony_ci{ 157962306a36Sopenharmony_ci int timeout = 500, link_training_state; 158062306a36Sopenharmony_ci bool state = false; 158162306a36Sopenharmony_ci 158262306a36Sopenharmony_ci mutex_lock(&it6505->aux_lock); 158362306a36Sopenharmony_ci it6505_set_bits(it6505, REG_TRAIN_CTRL0, 158462306a36Sopenharmony_ci FORCE_CR_DONE | FORCE_EQ_DONE, 0x00); 158562306a36Sopenharmony_ci it6505_write(it6505, REG_TRAIN_CTRL1, FORCE_RETRAIN); 158662306a36Sopenharmony_ci it6505_write(it6505, REG_TRAIN_CTRL1, AUTO_TRAIN); 158762306a36Sopenharmony_ci 158862306a36Sopenharmony_ci while (timeout > 0) { 158962306a36Sopenharmony_ci usleep_range(1000, 2000); 159062306a36Sopenharmony_ci link_training_state = it6505_read(it6505, REG_LINK_TRAIN_STS); 159162306a36Sopenharmony_ci 159262306a36Sopenharmony_ci if (link_training_state > 0 && 159362306a36Sopenharmony_ci (link_training_state & LINK_STATE_NORP)) { 159462306a36Sopenharmony_ci state = true; 159562306a36Sopenharmony_ci goto unlock; 159662306a36Sopenharmony_ci } 159762306a36Sopenharmony_ci 159862306a36Sopenharmony_ci timeout--; 159962306a36Sopenharmony_ci } 160062306a36Sopenharmony_ciunlock: 160162306a36Sopenharmony_ci mutex_unlock(&it6505->aux_lock); 160262306a36Sopenharmony_ci 160362306a36Sopenharmony_ci return state; 160462306a36Sopenharmony_ci} 160562306a36Sopenharmony_ci 160662306a36Sopenharmony_cistatic int it6505_drm_dp_link_configure(struct it6505 *it6505) 160762306a36Sopenharmony_ci{ 160862306a36Sopenharmony_ci u8 values[2]; 160962306a36Sopenharmony_ci int err; 161062306a36Sopenharmony_ci struct drm_dp_aux *aux = &it6505->aux; 161162306a36Sopenharmony_ci 161262306a36Sopenharmony_ci values[0] = it6505->link_rate_bw_code; 161362306a36Sopenharmony_ci values[1] = it6505->lane_count; 161462306a36Sopenharmony_ci 161562306a36Sopenharmony_ci if (it6505->enable_enhanced_frame) 161662306a36Sopenharmony_ci values[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; 161762306a36Sopenharmony_ci 161862306a36Sopenharmony_ci err = drm_dp_dpcd_write(aux, DP_LINK_BW_SET, values, sizeof(values)); 161962306a36Sopenharmony_ci if (err < 0) 162062306a36Sopenharmony_ci return err; 162162306a36Sopenharmony_ci 162262306a36Sopenharmony_ci return 0; 162362306a36Sopenharmony_ci} 162462306a36Sopenharmony_ci 162562306a36Sopenharmony_cistatic bool it6505_check_voltage_swing_max(u8 lane_voltage_swing_pre_emphasis) 162662306a36Sopenharmony_ci{ 162762306a36Sopenharmony_ci return ((lane_voltage_swing_pre_emphasis & 0x03) == MAX_CR_LEVEL); 162862306a36Sopenharmony_ci} 162962306a36Sopenharmony_ci 163062306a36Sopenharmony_cistatic bool it6505_check_pre_emphasis_max(u8 lane_voltage_swing_pre_emphasis) 163162306a36Sopenharmony_ci{ 163262306a36Sopenharmony_ci return ((lane_voltage_swing_pre_emphasis & 0x03) == MAX_EQ_LEVEL); 163362306a36Sopenharmony_ci} 163462306a36Sopenharmony_ci 163562306a36Sopenharmony_cistatic bool it6505_check_max_voltage_swing_reached(u8 *lane_voltage_swing, 163662306a36Sopenharmony_ci u8 lane_count) 163762306a36Sopenharmony_ci{ 163862306a36Sopenharmony_ci u8 i; 163962306a36Sopenharmony_ci 164062306a36Sopenharmony_ci for (i = 0; i < lane_count; i++) { 164162306a36Sopenharmony_ci if (lane_voltage_swing[i] & DP_TRAIN_MAX_SWING_REACHED) 164262306a36Sopenharmony_ci return true; 164362306a36Sopenharmony_ci } 164462306a36Sopenharmony_ci 164562306a36Sopenharmony_ci return false; 164662306a36Sopenharmony_ci} 164762306a36Sopenharmony_ci 164862306a36Sopenharmony_cistatic bool 164962306a36Sopenharmony_cistep_train_lane_voltage_para_set(struct it6505 *it6505, 165062306a36Sopenharmony_ci struct it6505_step_train_para 165162306a36Sopenharmony_ci *lane_voltage_pre_emphasis, 165262306a36Sopenharmony_ci u8 *lane_voltage_pre_emphasis_set) 165362306a36Sopenharmony_ci{ 165462306a36Sopenharmony_ci u8 *voltage_swing = lane_voltage_pre_emphasis->voltage_swing; 165562306a36Sopenharmony_ci u8 *pre_emphasis = lane_voltage_pre_emphasis->pre_emphasis; 165662306a36Sopenharmony_ci u8 i; 165762306a36Sopenharmony_ci 165862306a36Sopenharmony_ci for (i = 0; i < it6505->lane_count; i++) { 165962306a36Sopenharmony_ci voltage_swing[i] &= 0x03; 166062306a36Sopenharmony_ci lane_voltage_pre_emphasis_set[i] = voltage_swing[i]; 166162306a36Sopenharmony_ci if (it6505_check_voltage_swing_max(voltage_swing[i])) 166262306a36Sopenharmony_ci lane_voltage_pre_emphasis_set[i] |= 166362306a36Sopenharmony_ci DP_TRAIN_MAX_SWING_REACHED; 166462306a36Sopenharmony_ci 166562306a36Sopenharmony_ci pre_emphasis[i] &= 0x03; 166662306a36Sopenharmony_ci lane_voltage_pre_emphasis_set[i] |= pre_emphasis[i] 166762306a36Sopenharmony_ci << DP_TRAIN_PRE_EMPHASIS_SHIFT; 166862306a36Sopenharmony_ci if (it6505_check_pre_emphasis_max(pre_emphasis[i])) 166962306a36Sopenharmony_ci lane_voltage_pre_emphasis_set[i] |= 167062306a36Sopenharmony_ci DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; 167162306a36Sopenharmony_ci it6505_dpcd_write(it6505, DP_TRAINING_LANE0_SET + i, 167262306a36Sopenharmony_ci lane_voltage_pre_emphasis_set[i]); 167362306a36Sopenharmony_ci 167462306a36Sopenharmony_ci if (lane_voltage_pre_emphasis_set[i] != 167562306a36Sopenharmony_ci it6505_dpcd_read(it6505, DP_TRAINING_LANE0_SET + i)) 167662306a36Sopenharmony_ci return false; 167762306a36Sopenharmony_ci } 167862306a36Sopenharmony_ci 167962306a36Sopenharmony_ci return true; 168062306a36Sopenharmony_ci} 168162306a36Sopenharmony_ci 168262306a36Sopenharmony_cistatic bool 168362306a36Sopenharmony_ciit6505_step_cr_train(struct it6505 *it6505, 168462306a36Sopenharmony_ci struct it6505_step_train_para *lane_voltage_pre_emphasis) 168562306a36Sopenharmony_ci{ 168662306a36Sopenharmony_ci u8 loop_count = 0, i = 0, j; 168762306a36Sopenharmony_ci u8 link_status[DP_LINK_STATUS_SIZE] = { 0 }; 168862306a36Sopenharmony_ci u8 lane_level_config[MAX_LANE_COUNT] = { 0 }; 168962306a36Sopenharmony_ci int pre_emphasis_adjust = -1, voltage_swing_adjust = -1; 169062306a36Sopenharmony_ci const struct drm_dp_aux *aux = &it6505->aux; 169162306a36Sopenharmony_ci 169262306a36Sopenharmony_ci it6505_dpcd_write(it6505, DP_DOWNSPREAD_CTRL, 169362306a36Sopenharmony_ci it6505->enable_ssc ? DP_SPREAD_AMP_0_5 : 0x00); 169462306a36Sopenharmony_ci it6505_dpcd_write(it6505, DP_TRAINING_PATTERN_SET, 169562306a36Sopenharmony_ci DP_TRAINING_PATTERN_1); 169662306a36Sopenharmony_ci 169762306a36Sopenharmony_ci while (loop_count < 5 && i < 10) { 169862306a36Sopenharmony_ci i++; 169962306a36Sopenharmony_ci if (!step_train_lane_voltage_para_set(it6505, 170062306a36Sopenharmony_ci lane_voltage_pre_emphasis, 170162306a36Sopenharmony_ci lane_level_config)) 170262306a36Sopenharmony_ci continue; 170362306a36Sopenharmony_ci drm_dp_link_train_clock_recovery_delay(aux, it6505->dpcd); 170462306a36Sopenharmony_ci drm_dp_dpcd_read_link_status(&it6505->aux, link_status); 170562306a36Sopenharmony_ci 170662306a36Sopenharmony_ci if (drm_dp_clock_recovery_ok(link_status, it6505->lane_count)) { 170762306a36Sopenharmony_ci it6505_set_bits(it6505, REG_TRAIN_CTRL0, FORCE_CR_DONE, 170862306a36Sopenharmony_ci FORCE_CR_DONE); 170962306a36Sopenharmony_ci return true; 171062306a36Sopenharmony_ci } 171162306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(it6505->dev, "cr not done"); 171262306a36Sopenharmony_ci 171362306a36Sopenharmony_ci if (it6505_check_max_voltage_swing_reached(lane_level_config, 171462306a36Sopenharmony_ci it6505->lane_count)) 171562306a36Sopenharmony_ci goto cr_train_fail; 171662306a36Sopenharmony_ci 171762306a36Sopenharmony_ci for (j = 0; j < it6505->lane_count; j++) { 171862306a36Sopenharmony_ci lane_voltage_pre_emphasis->voltage_swing[j] = 171962306a36Sopenharmony_ci drm_dp_get_adjust_request_voltage(link_status, 172062306a36Sopenharmony_ci j) >> 172162306a36Sopenharmony_ci DP_TRAIN_VOLTAGE_SWING_SHIFT; 172262306a36Sopenharmony_ci lane_voltage_pre_emphasis->pre_emphasis[j] = 172362306a36Sopenharmony_ci drm_dp_get_adjust_request_pre_emphasis(link_status, 172462306a36Sopenharmony_ci j) >> 172562306a36Sopenharmony_ci DP_TRAIN_PRE_EMPHASIS_SHIFT; 172662306a36Sopenharmony_ci if (voltage_swing_adjust == 172762306a36Sopenharmony_ci lane_voltage_pre_emphasis->voltage_swing[j] && 172862306a36Sopenharmony_ci pre_emphasis_adjust == 172962306a36Sopenharmony_ci lane_voltage_pre_emphasis->pre_emphasis[j]) { 173062306a36Sopenharmony_ci loop_count++; 173162306a36Sopenharmony_ci continue; 173262306a36Sopenharmony_ci } 173362306a36Sopenharmony_ci 173462306a36Sopenharmony_ci voltage_swing_adjust = 173562306a36Sopenharmony_ci lane_voltage_pre_emphasis->voltage_swing[j]; 173662306a36Sopenharmony_ci pre_emphasis_adjust = 173762306a36Sopenharmony_ci lane_voltage_pre_emphasis->pre_emphasis[j]; 173862306a36Sopenharmony_ci loop_count = 0; 173962306a36Sopenharmony_ci 174062306a36Sopenharmony_ci if (voltage_swing_adjust + pre_emphasis_adjust > 174162306a36Sopenharmony_ci MAX_EQ_LEVEL) 174262306a36Sopenharmony_ci lane_voltage_pre_emphasis->voltage_swing[j] = 174362306a36Sopenharmony_ci MAX_EQ_LEVEL - 174462306a36Sopenharmony_ci lane_voltage_pre_emphasis 174562306a36Sopenharmony_ci ->pre_emphasis[j]; 174662306a36Sopenharmony_ci } 174762306a36Sopenharmony_ci } 174862306a36Sopenharmony_ci 174962306a36Sopenharmony_cicr_train_fail: 175062306a36Sopenharmony_ci it6505_dpcd_write(it6505, DP_TRAINING_PATTERN_SET, 175162306a36Sopenharmony_ci DP_TRAINING_PATTERN_DISABLE); 175262306a36Sopenharmony_ci 175362306a36Sopenharmony_ci return false; 175462306a36Sopenharmony_ci} 175562306a36Sopenharmony_ci 175662306a36Sopenharmony_cistatic bool 175762306a36Sopenharmony_ciit6505_step_eq_train(struct it6505 *it6505, 175862306a36Sopenharmony_ci struct it6505_step_train_para *lane_voltage_pre_emphasis) 175962306a36Sopenharmony_ci{ 176062306a36Sopenharmony_ci u8 loop_count = 0, i, link_status[DP_LINK_STATUS_SIZE] = { 0 }; 176162306a36Sopenharmony_ci u8 lane_level_config[MAX_LANE_COUNT] = { 0 }; 176262306a36Sopenharmony_ci const struct drm_dp_aux *aux = &it6505->aux; 176362306a36Sopenharmony_ci 176462306a36Sopenharmony_ci it6505_dpcd_write(it6505, DP_TRAINING_PATTERN_SET, 176562306a36Sopenharmony_ci DP_TRAINING_PATTERN_2); 176662306a36Sopenharmony_ci 176762306a36Sopenharmony_ci while (loop_count < 6) { 176862306a36Sopenharmony_ci loop_count++; 176962306a36Sopenharmony_ci 177062306a36Sopenharmony_ci if (!step_train_lane_voltage_para_set(it6505, 177162306a36Sopenharmony_ci lane_voltage_pre_emphasis, 177262306a36Sopenharmony_ci lane_level_config)) 177362306a36Sopenharmony_ci continue; 177462306a36Sopenharmony_ci 177562306a36Sopenharmony_ci drm_dp_link_train_channel_eq_delay(aux, it6505->dpcd); 177662306a36Sopenharmony_ci drm_dp_dpcd_read_link_status(&it6505->aux, link_status); 177762306a36Sopenharmony_ci 177862306a36Sopenharmony_ci if (!drm_dp_clock_recovery_ok(link_status, it6505->lane_count)) 177962306a36Sopenharmony_ci goto eq_train_fail; 178062306a36Sopenharmony_ci 178162306a36Sopenharmony_ci if (drm_dp_channel_eq_ok(link_status, it6505->lane_count)) { 178262306a36Sopenharmony_ci it6505_dpcd_write(it6505, DP_TRAINING_PATTERN_SET, 178362306a36Sopenharmony_ci DP_TRAINING_PATTERN_DISABLE); 178462306a36Sopenharmony_ci it6505_set_bits(it6505, REG_TRAIN_CTRL0, FORCE_EQ_DONE, 178562306a36Sopenharmony_ci FORCE_EQ_DONE); 178662306a36Sopenharmony_ci return true; 178762306a36Sopenharmony_ci } 178862306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(it6505->dev, "eq not done"); 178962306a36Sopenharmony_ci 179062306a36Sopenharmony_ci for (i = 0; i < it6505->lane_count; i++) { 179162306a36Sopenharmony_ci lane_voltage_pre_emphasis->voltage_swing[i] = 179262306a36Sopenharmony_ci drm_dp_get_adjust_request_voltage(link_status, 179362306a36Sopenharmony_ci i) >> 179462306a36Sopenharmony_ci DP_TRAIN_VOLTAGE_SWING_SHIFT; 179562306a36Sopenharmony_ci lane_voltage_pre_emphasis->pre_emphasis[i] = 179662306a36Sopenharmony_ci drm_dp_get_adjust_request_pre_emphasis(link_status, 179762306a36Sopenharmony_ci i) >> 179862306a36Sopenharmony_ci DP_TRAIN_PRE_EMPHASIS_SHIFT; 179962306a36Sopenharmony_ci 180062306a36Sopenharmony_ci if (lane_voltage_pre_emphasis->voltage_swing[i] + 180162306a36Sopenharmony_ci lane_voltage_pre_emphasis->pre_emphasis[i] > 180262306a36Sopenharmony_ci MAX_EQ_LEVEL) 180362306a36Sopenharmony_ci lane_voltage_pre_emphasis->voltage_swing[i] = 180462306a36Sopenharmony_ci 0x03 - lane_voltage_pre_emphasis 180562306a36Sopenharmony_ci ->pre_emphasis[i]; 180662306a36Sopenharmony_ci } 180762306a36Sopenharmony_ci } 180862306a36Sopenharmony_ci 180962306a36Sopenharmony_cieq_train_fail: 181062306a36Sopenharmony_ci it6505_dpcd_write(it6505, DP_TRAINING_PATTERN_SET, 181162306a36Sopenharmony_ci DP_TRAINING_PATTERN_DISABLE); 181262306a36Sopenharmony_ci return false; 181362306a36Sopenharmony_ci} 181462306a36Sopenharmony_ci 181562306a36Sopenharmony_cistatic bool it6505_link_start_step_train(struct it6505 *it6505) 181662306a36Sopenharmony_ci{ 181762306a36Sopenharmony_ci int err; 181862306a36Sopenharmony_ci struct it6505_step_train_para lane_voltage_pre_emphasis = { 181962306a36Sopenharmony_ci .voltage_swing = { 0 }, 182062306a36Sopenharmony_ci .pre_emphasis = { 0 }, 182162306a36Sopenharmony_ci }; 182262306a36Sopenharmony_ci 182362306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(it6505->dev, "start"); 182462306a36Sopenharmony_ci err = it6505_drm_dp_link_configure(it6505); 182562306a36Sopenharmony_ci 182662306a36Sopenharmony_ci if (err < 0) 182762306a36Sopenharmony_ci return false; 182862306a36Sopenharmony_ci if (!it6505_step_cr_train(it6505, &lane_voltage_pre_emphasis)) 182962306a36Sopenharmony_ci return false; 183062306a36Sopenharmony_ci if (!it6505_step_eq_train(it6505, &lane_voltage_pre_emphasis)) 183162306a36Sopenharmony_ci return false; 183262306a36Sopenharmony_ci return true; 183362306a36Sopenharmony_ci} 183462306a36Sopenharmony_ci 183562306a36Sopenharmony_cistatic bool it6505_get_video_status(struct it6505 *it6505) 183662306a36Sopenharmony_ci{ 183762306a36Sopenharmony_ci int reg_0d; 183862306a36Sopenharmony_ci 183962306a36Sopenharmony_ci reg_0d = it6505_read(it6505, REG_SYSTEM_STS); 184062306a36Sopenharmony_ci 184162306a36Sopenharmony_ci if (reg_0d < 0) 184262306a36Sopenharmony_ci return false; 184362306a36Sopenharmony_ci 184462306a36Sopenharmony_ci return reg_0d & VIDEO_STB; 184562306a36Sopenharmony_ci} 184662306a36Sopenharmony_ci 184762306a36Sopenharmony_cistatic void it6505_reset_hdcp(struct it6505 *it6505) 184862306a36Sopenharmony_ci{ 184962306a36Sopenharmony_ci it6505->hdcp_status = HDCP_AUTH_IDLE; 185062306a36Sopenharmony_ci /* Disable CP_Desired */ 185162306a36Sopenharmony_ci it6505_set_bits(it6505, REG_HDCP_CTRL1, HDCP_CP_ENABLE, 0x00); 185262306a36Sopenharmony_ci it6505_set_bits(it6505, REG_RESET_CTRL, HDCP_RESET, HDCP_RESET); 185362306a36Sopenharmony_ci} 185462306a36Sopenharmony_ci 185562306a36Sopenharmony_cistatic void it6505_start_hdcp(struct it6505 *it6505) 185662306a36Sopenharmony_ci{ 185762306a36Sopenharmony_ci struct device *dev = it6505->dev; 185862306a36Sopenharmony_ci 185962306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "start"); 186062306a36Sopenharmony_ci it6505_reset_hdcp(it6505); 186162306a36Sopenharmony_ci queue_delayed_work(system_wq, &it6505->hdcp_work, 186262306a36Sopenharmony_ci msecs_to_jiffies(2400)); 186362306a36Sopenharmony_ci} 186462306a36Sopenharmony_ci 186562306a36Sopenharmony_cistatic void it6505_stop_hdcp(struct it6505 *it6505) 186662306a36Sopenharmony_ci{ 186762306a36Sopenharmony_ci it6505_reset_hdcp(it6505); 186862306a36Sopenharmony_ci cancel_delayed_work(&it6505->hdcp_work); 186962306a36Sopenharmony_ci} 187062306a36Sopenharmony_ci 187162306a36Sopenharmony_cistatic bool it6505_hdcp_is_ksv_valid(u8 *ksv) 187262306a36Sopenharmony_ci{ 187362306a36Sopenharmony_ci int i, ones = 0; 187462306a36Sopenharmony_ci 187562306a36Sopenharmony_ci /* KSV has 20 1's and 20 0's */ 187662306a36Sopenharmony_ci for (i = 0; i < DRM_HDCP_KSV_LEN; i++) 187762306a36Sopenharmony_ci ones += hweight8(ksv[i]); 187862306a36Sopenharmony_ci if (ones != 20) 187962306a36Sopenharmony_ci return false; 188062306a36Sopenharmony_ci return true; 188162306a36Sopenharmony_ci} 188262306a36Sopenharmony_ci 188362306a36Sopenharmony_cistatic void it6505_hdcp_part1_auth(struct it6505 *it6505) 188462306a36Sopenharmony_ci{ 188562306a36Sopenharmony_ci struct device *dev = it6505->dev; 188662306a36Sopenharmony_ci u8 hdcp_bcaps; 188762306a36Sopenharmony_ci 188862306a36Sopenharmony_ci it6505_set_bits(it6505, REG_RESET_CTRL, HDCP_RESET, 0x00); 188962306a36Sopenharmony_ci /* Disable CP_Desired */ 189062306a36Sopenharmony_ci it6505_set_bits(it6505, REG_HDCP_CTRL1, HDCP_CP_ENABLE, 0x00); 189162306a36Sopenharmony_ci 189262306a36Sopenharmony_ci usleep_range(1000, 1500); 189362306a36Sopenharmony_ci hdcp_bcaps = it6505_dpcd_read(it6505, DP_AUX_HDCP_BCAPS); 189462306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "DPCD[0x68028]: 0x%02x", 189562306a36Sopenharmony_ci hdcp_bcaps); 189662306a36Sopenharmony_ci 189762306a36Sopenharmony_ci if (!hdcp_bcaps) 189862306a36Sopenharmony_ci return; 189962306a36Sopenharmony_ci 190062306a36Sopenharmony_ci /* clear the repeater List Chk Done and fail bit */ 190162306a36Sopenharmony_ci it6505_set_bits(it6505, REG_HDCP_TRIGGER, 190262306a36Sopenharmony_ci HDCP_TRIGGER_KSV_DONE | HDCP_TRIGGER_KSV_FAIL, 190362306a36Sopenharmony_ci 0x00); 190462306a36Sopenharmony_ci 190562306a36Sopenharmony_ci /* Enable An Generator */ 190662306a36Sopenharmony_ci it6505_set_bits(it6505, REG_HDCP_CTRL2, HDCP_AN_GEN, HDCP_AN_GEN); 190762306a36Sopenharmony_ci /* delay1ms(10);*/ 190862306a36Sopenharmony_ci usleep_range(10000, 15000); 190962306a36Sopenharmony_ci /* Stop An Generator */ 191062306a36Sopenharmony_ci it6505_set_bits(it6505, REG_HDCP_CTRL2, HDCP_AN_GEN, 0x00); 191162306a36Sopenharmony_ci 191262306a36Sopenharmony_ci it6505_set_bits(it6505, REG_HDCP_CTRL1, HDCP_CP_ENABLE, HDCP_CP_ENABLE); 191362306a36Sopenharmony_ci 191462306a36Sopenharmony_ci it6505_set_bits(it6505, REG_HDCP_TRIGGER, HDCP_TRIGGER_START, 191562306a36Sopenharmony_ci HDCP_TRIGGER_START); 191662306a36Sopenharmony_ci 191762306a36Sopenharmony_ci it6505->hdcp_status = HDCP_AUTH_GOING; 191862306a36Sopenharmony_ci} 191962306a36Sopenharmony_ci 192062306a36Sopenharmony_cistatic int it6505_sha1_digest(struct it6505 *it6505, u8 *sha1_input, 192162306a36Sopenharmony_ci unsigned int size, u8 *output_av) 192262306a36Sopenharmony_ci{ 192362306a36Sopenharmony_ci struct shash_desc *desc; 192462306a36Sopenharmony_ci struct crypto_shash *tfm; 192562306a36Sopenharmony_ci int err; 192662306a36Sopenharmony_ci struct device *dev = it6505->dev; 192762306a36Sopenharmony_ci 192862306a36Sopenharmony_ci tfm = crypto_alloc_shash("sha1", 0, 0); 192962306a36Sopenharmony_ci if (IS_ERR(tfm)) { 193062306a36Sopenharmony_ci dev_err(dev, "crypto_alloc_shash sha1 failed"); 193162306a36Sopenharmony_ci return PTR_ERR(tfm); 193262306a36Sopenharmony_ci } 193362306a36Sopenharmony_ci desc = kzalloc(sizeof(*desc) + crypto_shash_descsize(tfm), GFP_KERNEL); 193462306a36Sopenharmony_ci if (!desc) { 193562306a36Sopenharmony_ci crypto_free_shash(tfm); 193662306a36Sopenharmony_ci return -ENOMEM; 193762306a36Sopenharmony_ci } 193862306a36Sopenharmony_ci 193962306a36Sopenharmony_ci desc->tfm = tfm; 194062306a36Sopenharmony_ci err = crypto_shash_digest(desc, sha1_input, size, output_av); 194162306a36Sopenharmony_ci if (err) 194262306a36Sopenharmony_ci dev_err(dev, "crypto_shash_digest sha1 failed"); 194362306a36Sopenharmony_ci 194462306a36Sopenharmony_ci crypto_free_shash(tfm); 194562306a36Sopenharmony_ci kfree(desc); 194662306a36Sopenharmony_ci return err; 194762306a36Sopenharmony_ci} 194862306a36Sopenharmony_ci 194962306a36Sopenharmony_cistatic int it6505_setup_sha1_input(struct it6505 *it6505, u8 *sha1_input) 195062306a36Sopenharmony_ci{ 195162306a36Sopenharmony_ci struct device *dev = it6505->dev; 195262306a36Sopenharmony_ci u8 binfo[2]; 195362306a36Sopenharmony_ci int down_stream_count, i, err, msg_count = 0; 195462306a36Sopenharmony_ci 195562306a36Sopenharmony_ci err = it6505_get_dpcd(it6505, DP_AUX_HDCP_BINFO, binfo, 195662306a36Sopenharmony_ci ARRAY_SIZE(binfo)); 195762306a36Sopenharmony_ci 195862306a36Sopenharmony_ci if (err < 0) { 195962306a36Sopenharmony_ci dev_err(dev, "Read binfo value Fail"); 196062306a36Sopenharmony_ci return err; 196162306a36Sopenharmony_ci } 196262306a36Sopenharmony_ci 196362306a36Sopenharmony_ci down_stream_count = binfo[0] & 0x7F; 196462306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "binfo:0x%*ph", (int)ARRAY_SIZE(binfo), 196562306a36Sopenharmony_ci binfo); 196662306a36Sopenharmony_ci 196762306a36Sopenharmony_ci if ((binfo[0] & BIT(7)) || (binfo[1] & BIT(3))) { 196862306a36Sopenharmony_ci dev_err(dev, "HDCP max cascade device exceed"); 196962306a36Sopenharmony_ci return 0; 197062306a36Sopenharmony_ci } 197162306a36Sopenharmony_ci 197262306a36Sopenharmony_ci if (!down_stream_count || 197362306a36Sopenharmony_ci down_stream_count > MAX_HDCP_DOWN_STREAM_COUNT) { 197462306a36Sopenharmony_ci dev_err(dev, "HDCP down stream count Error %d", 197562306a36Sopenharmony_ci down_stream_count); 197662306a36Sopenharmony_ci return 0; 197762306a36Sopenharmony_ci } 197862306a36Sopenharmony_ci 197962306a36Sopenharmony_ci for (i = 0; i < down_stream_count; i++) { 198062306a36Sopenharmony_ci err = it6505_get_dpcd(it6505, DP_AUX_HDCP_KSV_FIFO + 198162306a36Sopenharmony_ci (i % 3) * DRM_HDCP_KSV_LEN, 198262306a36Sopenharmony_ci sha1_input + msg_count, 198362306a36Sopenharmony_ci DRM_HDCP_KSV_LEN); 198462306a36Sopenharmony_ci 198562306a36Sopenharmony_ci if (err < 0) 198662306a36Sopenharmony_ci return err; 198762306a36Sopenharmony_ci 198862306a36Sopenharmony_ci msg_count += 5; 198962306a36Sopenharmony_ci } 199062306a36Sopenharmony_ci 199162306a36Sopenharmony_ci it6505->hdcp_down_stream_count = down_stream_count; 199262306a36Sopenharmony_ci sha1_input[msg_count++] = binfo[0]; 199362306a36Sopenharmony_ci sha1_input[msg_count++] = binfo[1]; 199462306a36Sopenharmony_ci 199562306a36Sopenharmony_ci it6505_set_bits(it6505, REG_HDCP_CTRL2, HDCP_EN_M0_READ, 199662306a36Sopenharmony_ci HDCP_EN_M0_READ); 199762306a36Sopenharmony_ci 199862306a36Sopenharmony_ci err = regmap_bulk_read(it6505->regmap, REG_M0_0_7, 199962306a36Sopenharmony_ci sha1_input + msg_count, 8); 200062306a36Sopenharmony_ci 200162306a36Sopenharmony_ci it6505_set_bits(it6505, REG_HDCP_CTRL2, HDCP_EN_M0_READ, 0x00); 200262306a36Sopenharmony_ci 200362306a36Sopenharmony_ci if (err < 0) { 200462306a36Sopenharmony_ci dev_err(dev, " Warning, Read M value Fail"); 200562306a36Sopenharmony_ci return err; 200662306a36Sopenharmony_ci } 200762306a36Sopenharmony_ci 200862306a36Sopenharmony_ci msg_count += 8; 200962306a36Sopenharmony_ci 201062306a36Sopenharmony_ci return msg_count; 201162306a36Sopenharmony_ci} 201262306a36Sopenharmony_ci 201362306a36Sopenharmony_cistatic bool it6505_hdcp_part2_ksvlist_check(struct it6505 *it6505) 201462306a36Sopenharmony_ci{ 201562306a36Sopenharmony_ci struct device *dev = it6505->dev; 201662306a36Sopenharmony_ci u8 av[5][4], bv[5][4]; 201762306a36Sopenharmony_ci int i, err; 201862306a36Sopenharmony_ci 201962306a36Sopenharmony_ci i = it6505_setup_sha1_input(it6505, it6505->sha1_input); 202062306a36Sopenharmony_ci if (i <= 0) { 202162306a36Sopenharmony_ci dev_err(dev, "SHA-1 Input length error %d", i); 202262306a36Sopenharmony_ci return false; 202362306a36Sopenharmony_ci } 202462306a36Sopenharmony_ci 202562306a36Sopenharmony_ci it6505_sha1_digest(it6505, it6505->sha1_input, i, (u8 *)av); 202662306a36Sopenharmony_ci 202762306a36Sopenharmony_ci err = it6505_get_dpcd(it6505, DP_AUX_HDCP_V_PRIME(0), (u8 *)bv, 202862306a36Sopenharmony_ci sizeof(bv)); 202962306a36Sopenharmony_ci 203062306a36Sopenharmony_ci if (err < 0) { 203162306a36Sopenharmony_ci dev_err(dev, "Read V' value Fail"); 203262306a36Sopenharmony_ci return false; 203362306a36Sopenharmony_ci } 203462306a36Sopenharmony_ci 203562306a36Sopenharmony_ci for (i = 0; i < 5; i++) 203662306a36Sopenharmony_ci if (bv[i][3] != av[i][0] || bv[i][2] != av[i][1] || 203762306a36Sopenharmony_ci bv[i][1] != av[i][2] || bv[i][0] != av[i][3]) 203862306a36Sopenharmony_ci return false; 203962306a36Sopenharmony_ci 204062306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "V' all match!!"); 204162306a36Sopenharmony_ci return true; 204262306a36Sopenharmony_ci} 204362306a36Sopenharmony_ci 204462306a36Sopenharmony_cistatic void it6505_hdcp_wait_ksv_list(struct work_struct *work) 204562306a36Sopenharmony_ci{ 204662306a36Sopenharmony_ci struct it6505 *it6505 = container_of(work, struct it6505, 204762306a36Sopenharmony_ci hdcp_wait_ksv_list); 204862306a36Sopenharmony_ci struct device *dev = it6505->dev; 204962306a36Sopenharmony_ci unsigned int timeout = 5000; 205062306a36Sopenharmony_ci u8 bstatus = 0; 205162306a36Sopenharmony_ci bool ksv_list_check; 205262306a36Sopenharmony_ci 205362306a36Sopenharmony_ci timeout /= 20; 205462306a36Sopenharmony_ci while (timeout > 0) { 205562306a36Sopenharmony_ci if (!it6505_get_sink_hpd_status(it6505)) 205662306a36Sopenharmony_ci return; 205762306a36Sopenharmony_ci 205862306a36Sopenharmony_ci bstatus = it6505_dpcd_read(it6505, DP_AUX_HDCP_BSTATUS); 205962306a36Sopenharmony_ci 206062306a36Sopenharmony_ci if (bstatus & DP_BSTATUS_READY) 206162306a36Sopenharmony_ci break; 206262306a36Sopenharmony_ci 206362306a36Sopenharmony_ci msleep(20); 206462306a36Sopenharmony_ci timeout--; 206562306a36Sopenharmony_ci } 206662306a36Sopenharmony_ci 206762306a36Sopenharmony_ci if (timeout == 0) { 206862306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "timeout and ksv list wait failed"); 206962306a36Sopenharmony_ci goto timeout; 207062306a36Sopenharmony_ci } 207162306a36Sopenharmony_ci 207262306a36Sopenharmony_ci ksv_list_check = it6505_hdcp_part2_ksvlist_check(it6505); 207362306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "ksv list ready, ksv list check %s", 207462306a36Sopenharmony_ci ksv_list_check ? "pass" : "fail"); 207562306a36Sopenharmony_ci if (ksv_list_check) { 207662306a36Sopenharmony_ci it6505_set_bits(it6505, REG_HDCP_TRIGGER, 207762306a36Sopenharmony_ci HDCP_TRIGGER_KSV_DONE, HDCP_TRIGGER_KSV_DONE); 207862306a36Sopenharmony_ci return; 207962306a36Sopenharmony_ci } 208062306a36Sopenharmony_citimeout: 208162306a36Sopenharmony_ci it6505_set_bits(it6505, REG_HDCP_TRIGGER, 208262306a36Sopenharmony_ci HDCP_TRIGGER_KSV_DONE | HDCP_TRIGGER_KSV_FAIL, 208362306a36Sopenharmony_ci HDCP_TRIGGER_KSV_DONE | HDCP_TRIGGER_KSV_FAIL); 208462306a36Sopenharmony_ci} 208562306a36Sopenharmony_ci 208662306a36Sopenharmony_cistatic void it6505_hdcp_work(struct work_struct *work) 208762306a36Sopenharmony_ci{ 208862306a36Sopenharmony_ci struct it6505 *it6505 = container_of(work, struct it6505, 208962306a36Sopenharmony_ci hdcp_work.work); 209062306a36Sopenharmony_ci struct device *dev = it6505->dev; 209162306a36Sopenharmony_ci int ret; 209262306a36Sopenharmony_ci u8 link_status[DP_LINK_STATUS_SIZE] = { 0 }; 209362306a36Sopenharmony_ci 209462306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "start"); 209562306a36Sopenharmony_ci 209662306a36Sopenharmony_ci if (!it6505_get_sink_hpd_status(it6505)) 209762306a36Sopenharmony_ci return; 209862306a36Sopenharmony_ci 209962306a36Sopenharmony_ci ret = drm_dp_dpcd_read_link_status(&it6505->aux, link_status); 210062306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "ret: %d link_status: %*ph", ret, 210162306a36Sopenharmony_ci (int)sizeof(link_status), link_status); 210262306a36Sopenharmony_ci 210362306a36Sopenharmony_ci if (ret < 0 || !drm_dp_channel_eq_ok(link_status, it6505->lane_count) || 210462306a36Sopenharmony_ci !it6505_get_video_status(it6505)) { 210562306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "link train not done or no video"); 210662306a36Sopenharmony_ci return; 210762306a36Sopenharmony_ci } 210862306a36Sopenharmony_ci 210962306a36Sopenharmony_ci ret = it6505_get_dpcd(it6505, DP_AUX_HDCP_BKSV, it6505->bksvs, 211062306a36Sopenharmony_ci ARRAY_SIZE(it6505->bksvs)); 211162306a36Sopenharmony_ci if (ret < 0) { 211262306a36Sopenharmony_ci dev_err(dev, "fail to get bksv ret: %d", ret); 211362306a36Sopenharmony_ci it6505_set_bits(it6505, REG_HDCP_TRIGGER, 211462306a36Sopenharmony_ci HDCP_TRIGGER_KSV_FAIL, HDCP_TRIGGER_KSV_FAIL); 211562306a36Sopenharmony_ci } 211662306a36Sopenharmony_ci 211762306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "bksv = 0x%*ph", 211862306a36Sopenharmony_ci (int)ARRAY_SIZE(it6505->bksvs), it6505->bksvs); 211962306a36Sopenharmony_ci 212062306a36Sopenharmony_ci if (!it6505_hdcp_is_ksv_valid(it6505->bksvs)) { 212162306a36Sopenharmony_ci dev_err(dev, "Display Port bksv not valid"); 212262306a36Sopenharmony_ci it6505_set_bits(it6505, REG_HDCP_TRIGGER, 212362306a36Sopenharmony_ci HDCP_TRIGGER_KSV_FAIL, HDCP_TRIGGER_KSV_FAIL); 212462306a36Sopenharmony_ci } 212562306a36Sopenharmony_ci 212662306a36Sopenharmony_ci it6505_hdcp_part1_auth(it6505); 212762306a36Sopenharmony_ci} 212862306a36Sopenharmony_ci 212962306a36Sopenharmony_cistatic void it6505_show_hdcp_info(struct it6505 *it6505) 213062306a36Sopenharmony_ci{ 213162306a36Sopenharmony_ci struct device *dev = it6505->dev; 213262306a36Sopenharmony_ci int i; 213362306a36Sopenharmony_ci u8 *sha1 = it6505->sha1_input; 213462306a36Sopenharmony_ci 213562306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "hdcp_status: %d is_repeater: %d", 213662306a36Sopenharmony_ci it6505->hdcp_status, it6505->is_repeater); 213762306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "bksv = 0x%*ph", 213862306a36Sopenharmony_ci (int)ARRAY_SIZE(it6505->bksvs), it6505->bksvs); 213962306a36Sopenharmony_ci 214062306a36Sopenharmony_ci if (it6505->is_repeater) { 214162306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "hdcp_down_stream_count: %d", 214262306a36Sopenharmony_ci it6505->hdcp_down_stream_count); 214362306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "sha1_input: 0x%*ph", 214462306a36Sopenharmony_ci (int)ARRAY_SIZE(it6505->sha1_input), 214562306a36Sopenharmony_ci it6505->sha1_input); 214662306a36Sopenharmony_ci for (i = 0; i < it6505->hdcp_down_stream_count; i++) { 214762306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "KSV_%d = 0x%*ph", i, 214862306a36Sopenharmony_ci DRM_HDCP_KSV_LEN, sha1); 214962306a36Sopenharmony_ci sha1 += DRM_HDCP_KSV_LEN; 215062306a36Sopenharmony_ci } 215162306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "binfo: 0x%2ph M0: 0x%8ph", 215262306a36Sopenharmony_ci sha1, sha1 + 2); 215362306a36Sopenharmony_ci } 215462306a36Sopenharmony_ci} 215562306a36Sopenharmony_ci 215662306a36Sopenharmony_cistatic void it6505_stop_link_train(struct it6505 *it6505) 215762306a36Sopenharmony_ci{ 215862306a36Sopenharmony_ci it6505->link_state = LINK_IDLE; 215962306a36Sopenharmony_ci cancel_work_sync(&it6505->link_works); 216062306a36Sopenharmony_ci it6505_write(it6505, REG_TRAIN_CTRL1, FORCE_RETRAIN); 216162306a36Sopenharmony_ci} 216262306a36Sopenharmony_ci 216362306a36Sopenharmony_cistatic void it6505_link_train_ok(struct it6505 *it6505) 216462306a36Sopenharmony_ci{ 216562306a36Sopenharmony_ci struct device *dev = it6505->dev; 216662306a36Sopenharmony_ci 216762306a36Sopenharmony_ci it6505->link_state = LINK_OK; 216862306a36Sopenharmony_ci /* disalbe mute enable avi info frame */ 216962306a36Sopenharmony_ci it6505_set_bits(it6505, REG_DATA_MUTE_CTRL, EN_VID_MUTE, 0x00); 217062306a36Sopenharmony_ci it6505_set_bits(it6505, REG_INFOFRAME_CTRL, 217162306a36Sopenharmony_ci EN_VID_CTRL_PKT, EN_VID_CTRL_PKT); 217262306a36Sopenharmony_ci 217362306a36Sopenharmony_ci if (it6505_audio_input(it6505)) { 217462306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "Enable audio!"); 217562306a36Sopenharmony_ci it6505_enable_audio(it6505); 217662306a36Sopenharmony_ci } 217762306a36Sopenharmony_ci 217862306a36Sopenharmony_ci if (it6505->hdcp_desired) 217962306a36Sopenharmony_ci it6505_start_hdcp(it6505); 218062306a36Sopenharmony_ci} 218162306a36Sopenharmony_ci 218262306a36Sopenharmony_cistatic void it6505_link_step_train_process(struct it6505 *it6505) 218362306a36Sopenharmony_ci{ 218462306a36Sopenharmony_ci struct device *dev = it6505->dev; 218562306a36Sopenharmony_ci int ret, i, step_retry = 3; 218662306a36Sopenharmony_ci 218762306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "Start step train"); 218862306a36Sopenharmony_ci 218962306a36Sopenharmony_ci if (it6505->sink_count == 0) { 219062306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "it6505->sink_count:%d, force eq", 219162306a36Sopenharmony_ci it6505->sink_count); 219262306a36Sopenharmony_ci it6505_set_bits(it6505, REG_TRAIN_CTRL0, FORCE_EQ_DONE, 219362306a36Sopenharmony_ci FORCE_EQ_DONE); 219462306a36Sopenharmony_ci return; 219562306a36Sopenharmony_ci } 219662306a36Sopenharmony_ci 219762306a36Sopenharmony_ci if (!it6505->step_train) { 219862306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "not support step train"); 219962306a36Sopenharmony_ci return; 220062306a36Sopenharmony_ci } 220162306a36Sopenharmony_ci 220262306a36Sopenharmony_ci /* step training start here */ 220362306a36Sopenharmony_ci for (i = 0; i < step_retry; i++) { 220462306a36Sopenharmony_ci it6505_link_reset_step_train(it6505); 220562306a36Sopenharmony_ci ret = it6505_link_start_step_train(it6505); 220662306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "step train %s, retry:%d times", 220762306a36Sopenharmony_ci ret ? "pass" : "failed", i + 1); 220862306a36Sopenharmony_ci if (ret) { 220962306a36Sopenharmony_ci it6505_link_train_ok(it6505); 221062306a36Sopenharmony_ci return; 221162306a36Sopenharmony_ci } 221262306a36Sopenharmony_ci } 221362306a36Sopenharmony_ci 221462306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "training fail"); 221562306a36Sopenharmony_ci it6505->link_state = LINK_IDLE; 221662306a36Sopenharmony_ci it6505_video_reset(it6505); 221762306a36Sopenharmony_ci} 221862306a36Sopenharmony_ci 221962306a36Sopenharmony_cistatic void it6505_link_training_work(struct work_struct *work) 222062306a36Sopenharmony_ci{ 222162306a36Sopenharmony_ci struct it6505 *it6505 = container_of(work, struct it6505, link_works); 222262306a36Sopenharmony_ci struct device *dev = it6505->dev; 222362306a36Sopenharmony_ci int ret; 222462306a36Sopenharmony_ci 222562306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "it6505->sink_count: %d", 222662306a36Sopenharmony_ci it6505->sink_count); 222762306a36Sopenharmony_ci 222862306a36Sopenharmony_ci if (!it6505_get_sink_hpd_status(it6505)) 222962306a36Sopenharmony_ci return; 223062306a36Sopenharmony_ci 223162306a36Sopenharmony_ci it6505_link_training_setup(it6505); 223262306a36Sopenharmony_ci it6505_reset_hdcp(it6505); 223362306a36Sopenharmony_ci it6505_aux_reset(it6505); 223462306a36Sopenharmony_ci 223562306a36Sopenharmony_ci if (it6505->auto_train_retry < 1) { 223662306a36Sopenharmony_ci it6505_link_step_train_process(it6505); 223762306a36Sopenharmony_ci return; 223862306a36Sopenharmony_ci } 223962306a36Sopenharmony_ci 224062306a36Sopenharmony_ci ret = it6505_link_start_auto_train(it6505); 224162306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "auto train %s, auto_train_retry: %d", 224262306a36Sopenharmony_ci ret ? "pass" : "failed", it6505->auto_train_retry); 224362306a36Sopenharmony_ci it6505->auto_train_retry--; 224462306a36Sopenharmony_ci 224562306a36Sopenharmony_ci if (ret) { 224662306a36Sopenharmony_ci it6505_link_train_ok(it6505); 224762306a36Sopenharmony_ci return; 224862306a36Sopenharmony_ci } 224962306a36Sopenharmony_ci 225062306a36Sopenharmony_ci it6505_dump(it6505); 225162306a36Sopenharmony_ci} 225262306a36Sopenharmony_ci 225362306a36Sopenharmony_cistatic void it6505_plugged_status_to_codec(struct it6505 *it6505) 225462306a36Sopenharmony_ci{ 225562306a36Sopenharmony_ci enum drm_connector_status status = it6505->connector_status; 225662306a36Sopenharmony_ci 225762306a36Sopenharmony_ci if (it6505->plugged_cb && it6505->codec_dev) 225862306a36Sopenharmony_ci it6505->plugged_cb(it6505->codec_dev, 225962306a36Sopenharmony_ci status == connector_status_connected); 226062306a36Sopenharmony_ci} 226162306a36Sopenharmony_ci 226262306a36Sopenharmony_cistatic void it6505_remove_edid(struct it6505 *it6505) 226362306a36Sopenharmony_ci{ 226462306a36Sopenharmony_ci kfree(it6505->cached_edid); 226562306a36Sopenharmony_ci it6505->cached_edid = NULL; 226662306a36Sopenharmony_ci} 226762306a36Sopenharmony_ci 226862306a36Sopenharmony_cistatic int it6505_process_hpd_irq(struct it6505 *it6505) 226962306a36Sopenharmony_ci{ 227062306a36Sopenharmony_ci struct device *dev = it6505->dev; 227162306a36Sopenharmony_ci int ret, dpcd_sink_count, dp_irq_vector, bstatus; 227262306a36Sopenharmony_ci u8 link_status[DP_LINK_STATUS_SIZE]; 227362306a36Sopenharmony_ci 227462306a36Sopenharmony_ci if (!it6505_get_sink_hpd_status(it6505)) { 227562306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "HPD_IRQ HPD low"); 227662306a36Sopenharmony_ci it6505->sink_count = 0; 227762306a36Sopenharmony_ci return 0; 227862306a36Sopenharmony_ci } 227962306a36Sopenharmony_ci 228062306a36Sopenharmony_ci ret = it6505_dpcd_read(it6505, DP_SINK_COUNT); 228162306a36Sopenharmony_ci if (ret < 0) 228262306a36Sopenharmony_ci return ret; 228362306a36Sopenharmony_ci 228462306a36Sopenharmony_ci dpcd_sink_count = DP_GET_SINK_COUNT(ret); 228562306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "dpcd_sink_count: %d it6505->sink_count:%d", 228662306a36Sopenharmony_ci dpcd_sink_count, it6505->sink_count); 228762306a36Sopenharmony_ci 228862306a36Sopenharmony_ci if (it6505->branch_device && dpcd_sink_count != it6505->sink_count) { 228962306a36Sopenharmony_ci memset(it6505->dpcd, 0, sizeof(it6505->dpcd)); 229062306a36Sopenharmony_ci it6505->sink_count = dpcd_sink_count; 229162306a36Sopenharmony_ci it6505_reset_logic(it6505); 229262306a36Sopenharmony_ci it6505_int_mask_enable(it6505); 229362306a36Sopenharmony_ci it6505_init(it6505); 229462306a36Sopenharmony_ci it6505_remove_edid(it6505); 229562306a36Sopenharmony_ci return 0; 229662306a36Sopenharmony_ci } 229762306a36Sopenharmony_ci 229862306a36Sopenharmony_ci dp_irq_vector = it6505_dpcd_read(it6505, DP_DEVICE_SERVICE_IRQ_VECTOR); 229962306a36Sopenharmony_ci if (dp_irq_vector < 0) 230062306a36Sopenharmony_ci return dp_irq_vector; 230162306a36Sopenharmony_ci 230262306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "dp_irq_vector = 0x%02x", dp_irq_vector); 230362306a36Sopenharmony_ci 230462306a36Sopenharmony_ci if (dp_irq_vector & DP_CP_IRQ) { 230562306a36Sopenharmony_ci it6505_set_bits(it6505, REG_HDCP_TRIGGER, HDCP_TRIGGER_CPIRQ, 230662306a36Sopenharmony_ci HDCP_TRIGGER_CPIRQ); 230762306a36Sopenharmony_ci 230862306a36Sopenharmony_ci bstatus = it6505_dpcd_read(it6505, DP_AUX_HDCP_BSTATUS); 230962306a36Sopenharmony_ci if (bstatus < 0) 231062306a36Sopenharmony_ci return bstatus; 231162306a36Sopenharmony_ci 231262306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "Bstatus = 0x%02x", bstatus); 231362306a36Sopenharmony_ci } 231462306a36Sopenharmony_ci 231562306a36Sopenharmony_ci ret = drm_dp_dpcd_read_link_status(&it6505->aux, link_status); 231662306a36Sopenharmony_ci if (ret < 0) { 231762306a36Sopenharmony_ci dev_err(dev, "Fail to read link status ret: %d", ret); 231862306a36Sopenharmony_ci return ret; 231962306a36Sopenharmony_ci } 232062306a36Sopenharmony_ci 232162306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "link status = 0x%*ph", 232262306a36Sopenharmony_ci (int)ARRAY_SIZE(link_status), link_status); 232362306a36Sopenharmony_ci 232462306a36Sopenharmony_ci if (!drm_dp_channel_eq_ok(link_status, it6505->lane_count)) { 232562306a36Sopenharmony_ci it6505->auto_train_retry = AUTO_TRAIN_RETRY; 232662306a36Sopenharmony_ci it6505_video_reset(it6505); 232762306a36Sopenharmony_ci } 232862306a36Sopenharmony_ci 232962306a36Sopenharmony_ci return 0; 233062306a36Sopenharmony_ci} 233162306a36Sopenharmony_ci 233262306a36Sopenharmony_cistatic void it6505_irq_hpd(struct it6505 *it6505) 233362306a36Sopenharmony_ci{ 233462306a36Sopenharmony_ci struct device *dev = it6505->dev; 233562306a36Sopenharmony_ci int dp_sink_count; 233662306a36Sopenharmony_ci 233762306a36Sopenharmony_ci it6505->hpd_state = it6505_get_sink_hpd_status(it6505); 233862306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "hpd change interrupt, change to %s", 233962306a36Sopenharmony_ci it6505->hpd_state ? "high" : "low"); 234062306a36Sopenharmony_ci 234162306a36Sopenharmony_ci if (it6505->hpd_state) { 234262306a36Sopenharmony_ci wait_for_completion_timeout(&it6505->extcon_completion, 234362306a36Sopenharmony_ci msecs_to_jiffies(1000)); 234462306a36Sopenharmony_ci it6505_aux_on(it6505); 234562306a36Sopenharmony_ci if (it6505->dpcd[0] == 0) { 234662306a36Sopenharmony_ci it6505_get_dpcd(it6505, DP_DPCD_REV, it6505->dpcd, 234762306a36Sopenharmony_ci ARRAY_SIZE(it6505->dpcd)); 234862306a36Sopenharmony_ci it6505_variable_config(it6505); 234962306a36Sopenharmony_ci it6505_parse_link_capabilities(it6505); 235062306a36Sopenharmony_ci } 235162306a36Sopenharmony_ci it6505->auto_train_retry = AUTO_TRAIN_RETRY; 235262306a36Sopenharmony_ci 235362306a36Sopenharmony_ci it6505_drm_dp_link_set_power(&it6505->aux, &it6505->link, 235462306a36Sopenharmony_ci DP_SET_POWER_D0); 235562306a36Sopenharmony_ci dp_sink_count = it6505_dpcd_read(it6505, DP_SINK_COUNT); 235662306a36Sopenharmony_ci it6505->sink_count = DP_GET_SINK_COUNT(dp_sink_count); 235762306a36Sopenharmony_ci 235862306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "it6505->sink_count: %d", 235962306a36Sopenharmony_ci it6505->sink_count); 236062306a36Sopenharmony_ci 236162306a36Sopenharmony_ci it6505_lane_termination_on(it6505); 236262306a36Sopenharmony_ci it6505_lane_power_on(it6505); 236362306a36Sopenharmony_ci 236462306a36Sopenharmony_ci /* 236562306a36Sopenharmony_ci * for some dongle which issue HPD_irq 236662306a36Sopenharmony_ci * when sink count change from 0->1 236762306a36Sopenharmony_ci * it6505 not able to receive HPD_IRQ 236862306a36Sopenharmony_ci * if HW never go into trainig done 236962306a36Sopenharmony_ci */ 237062306a36Sopenharmony_ci 237162306a36Sopenharmony_ci if (it6505->branch_device && it6505->sink_count == 0) 237262306a36Sopenharmony_ci schedule_work(&it6505->link_works); 237362306a36Sopenharmony_ci 237462306a36Sopenharmony_ci if (!it6505_get_video_status(it6505)) 237562306a36Sopenharmony_ci it6505_video_reset(it6505); 237662306a36Sopenharmony_ci } else { 237762306a36Sopenharmony_ci memset(it6505->dpcd, 0, sizeof(it6505->dpcd)); 237862306a36Sopenharmony_ci it6505_remove_edid(it6505); 237962306a36Sopenharmony_ci 238062306a36Sopenharmony_ci if (it6505->hdcp_desired) 238162306a36Sopenharmony_ci it6505_stop_hdcp(it6505); 238262306a36Sopenharmony_ci 238362306a36Sopenharmony_ci it6505_video_disable(it6505); 238462306a36Sopenharmony_ci it6505_disable_audio(it6505); 238562306a36Sopenharmony_ci it6505_stop_link_train(it6505); 238662306a36Sopenharmony_ci it6505_lane_off(it6505); 238762306a36Sopenharmony_ci it6505_link_reset_step_train(it6505); 238862306a36Sopenharmony_ci } 238962306a36Sopenharmony_ci 239062306a36Sopenharmony_ci if (it6505->bridge.dev) 239162306a36Sopenharmony_ci drm_helper_hpd_irq_event(it6505->bridge.dev); 239262306a36Sopenharmony_ci} 239362306a36Sopenharmony_ci 239462306a36Sopenharmony_cistatic void it6505_irq_hpd_irq(struct it6505 *it6505) 239562306a36Sopenharmony_ci{ 239662306a36Sopenharmony_ci struct device *dev = it6505->dev; 239762306a36Sopenharmony_ci 239862306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "hpd_irq interrupt"); 239962306a36Sopenharmony_ci 240062306a36Sopenharmony_ci if (it6505_process_hpd_irq(it6505) < 0) 240162306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "process hpd_irq fail!"); 240262306a36Sopenharmony_ci} 240362306a36Sopenharmony_ci 240462306a36Sopenharmony_cistatic void it6505_irq_scdt(struct it6505 *it6505) 240562306a36Sopenharmony_ci{ 240662306a36Sopenharmony_ci struct device *dev = it6505->dev; 240762306a36Sopenharmony_ci bool data; 240862306a36Sopenharmony_ci 240962306a36Sopenharmony_ci data = it6505_get_video_status(it6505); 241062306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "video stable change interrupt, %s", 241162306a36Sopenharmony_ci data ? "stable" : "unstable"); 241262306a36Sopenharmony_ci it6505_calc_video_info(it6505); 241362306a36Sopenharmony_ci it6505_link_reset_step_train(it6505); 241462306a36Sopenharmony_ci 241562306a36Sopenharmony_ci if (data) 241662306a36Sopenharmony_ci schedule_work(&it6505->link_works); 241762306a36Sopenharmony_ci} 241862306a36Sopenharmony_ci 241962306a36Sopenharmony_cistatic void it6505_irq_hdcp_done(struct it6505 *it6505) 242062306a36Sopenharmony_ci{ 242162306a36Sopenharmony_ci struct device *dev = it6505->dev; 242262306a36Sopenharmony_ci 242362306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "hdcp done interrupt"); 242462306a36Sopenharmony_ci it6505->hdcp_status = HDCP_AUTH_DONE; 242562306a36Sopenharmony_ci it6505_show_hdcp_info(it6505); 242662306a36Sopenharmony_ci} 242762306a36Sopenharmony_ci 242862306a36Sopenharmony_cistatic void it6505_irq_hdcp_fail(struct it6505 *it6505) 242962306a36Sopenharmony_ci{ 243062306a36Sopenharmony_ci struct device *dev = it6505->dev; 243162306a36Sopenharmony_ci 243262306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "hdcp fail interrupt"); 243362306a36Sopenharmony_ci it6505->hdcp_status = HDCP_AUTH_IDLE; 243462306a36Sopenharmony_ci it6505_show_hdcp_info(it6505); 243562306a36Sopenharmony_ci it6505_start_hdcp(it6505); 243662306a36Sopenharmony_ci} 243762306a36Sopenharmony_ci 243862306a36Sopenharmony_cistatic void it6505_irq_aux_cmd_fail(struct it6505 *it6505) 243962306a36Sopenharmony_ci{ 244062306a36Sopenharmony_ci struct device *dev = it6505->dev; 244162306a36Sopenharmony_ci 244262306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "AUX PC Request Fail Interrupt"); 244362306a36Sopenharmony_ci} 244462306a36Sopenharmony_ci 244562306a36Sopenharmony_cistatic void it6505_irq_hdcp_ksv_check(struct it6505 *it6505) 244662306a36Sopenharmony_ci{ 244762306a36Sopenharmony_ci struct device *dev = it6505->dev; 244862306a36Sopenharmony_ci 244962306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "HDCP event Interrupt"); 245062306a36Sopenharmony_ci schedule_work(&it6505->hdcp_wait_ksv_list); 245162306a36Sopenharmony_ci} 245262306a36Sopenharmony_ci 245362306a36Sopenharmony_cistatic void it6505_irq_audio_fifo_error(struct it6505 *it6505) 245462306a36Sopenharmony_ci{ 245562306a36Sopenharmony_ci struct device *dev = it6505->dev; 245662306a36Sopenharmony_ci 245762306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "audio fifo error Interrupt"); 245862306a36Sopenharmony_ci 245962306a36Sopenharmony_ci if (it6505_audio_input(it6505)) 246062306a36Sopenharmony_ci it6505_enable_audio(it6505); 246162306a36Sopenharmony_ci} 246262306a36Sopenharmony_ci 246362306a36Sopenharmony_cistatic void it6505_irq_link_train_fail(struct it6505 *it6505) 246462306a36Sopenharmony_ci{ 246562306a36Sopenharmony_ci struct device *dev = it6505->dev; 246662306a36Sopenharmony_ci 246762306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "link training fail interrupt"); 246862306a36Sopenharmony_ci schedule_work(&it6505->link_works); 246962306a36Sopenharmony_ci} 247062306a36Sopenharmony_ci 247162306a36Sopenharmony_cistatic void it6505_irq_video_fifo_error(struct it6505 *it6505) 247262306a36Sopenharmony_ci{ 247362306a36Sopenharmony_ci struct device *dev = it6505->dev; 247462306a36Sopenharmony_ci 247562306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "video fifo overflow interrupt"); 247662306a36Sopenharmony_ci it6505->auto_train_retry = AUTO_TRAIN_RETRY; 247762306a36Sopenharmony_ci flush_work(&it6505->link_works); 247862306a36Sopenharmony_ci it6505_stop_hdcp(it6505); 247962306a36Sopenharmony_ci it6505_video_reset(it6505); 248062306a36Sopenharmony_ci} 248162306a36Sopenharmony_ci 248262306a36Sopenharmony_cistatic void it6505_irq_io_latch_fifo_overflow(struct it6505 *it6505) 248362306a36Sopenharmony_ci{ 248462306a36Sopenharmony_ci struct device *dev = it6505->dev; 248562306a36Sopenharmony_ci 248662306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "IO latch fifo overflow interrupt"); 248762306a36Sopenharmony_ci it6505->auto_train_retry = AUTO_TRAIN_RETRY; 248862306a36Sopenharmony_ci flush_work(&it6505->link_works); 248962306a36Sopenharmony_ci it6505_stop_hdcp(it6505); 249062306a36Sopenharmony_ci it6505_video_reset(it6505); 249162306a36Sopenharmony_ci} 249262306a36Sopenharmony_ci 249362306a36Sopenharmony_cistatic bool it6505_test_bit(unsigned int bit, const unsigned int *addr) 249462306a36Sopenharmony_ci{ 249562306a36Sopenharmony_ci return 1 & (addr[bit / BITS_PER_BYTE] >> (bit % BITS_PER_BYTE)); 249662306a36Sopenharmony_ci} 249762306a36Sopenharmony_ci 249862306a36Sopenharmony_cistatic irqreturn_t it6505_int_threaded_handler(int unused, void *data) 249962306a36Sopenharmony_ci{ 250062306a36Sopenharmony_ci struct it6505 *it6505 = data; 250162306a36Sopenharmony_ci struct device *dev = it6505->dev; 250262306a36Sopenharmony_ci static const struct { 250362306a36Sopenharmony_ci int bit; 250462306a36Sopenharmony_ci void (*handler)(struct it6505 *it6505); 250562306a36Sopenharmony_ci } irq_vec[] = { 250662306a36Sopenharmony_ci { BIT_INT_HPD, it6505_irq_hpd }, 250762306a36Sopenharmony_ci { BIT_INT_HPD_IRQ, it6505_irq_hpd_irq }, 250862306a36Sopenharmony_ci { BIT_INT_SCDT, it6505_irq_scdt }, 250962306a36Sopenharmony_ci { BIT_INT_HDCP_FAIL, it6505_irq_hdcp_fail }, 251062306a36Sopenharmony_ci { BIT_INT_HDCP_DONE, it6505_irq_hdcp_done }, 251162306a36Sopenharmony_ci { BIT_INT_AUX_CMD_FAIL, it6505_irq_aux_cmd_fail }, 251262306a36Sopenharmony_ci { BIT_INT_HDCP_KSV_CHECK, it6505_irq_hdcp_ksv_check }, 251362306a36Sopenharmony_ci { BIT_INT_AUDIO_FIFO_ERROR, it6505_irq_audio_fifo_error }, 251462306a36Sopenharmony_ci { BIT_INT_LINK_TRAIN_FAIL, it6505_irq_link_train_fail }, 251562306a36Sopenharmony_ci { BIT_INT_VID_FIFO_ERROR, it6505_irq_video_fifo_error }, 251662306a36Sopenharmony_ci { BIT_INT_IO_FIFO_OVERFLOW, it6505_irq_io_latch_fifo_overflow }, 251762306a36Sopenharmony_ci }; 251862306a36Sopenharmony_ci int int_status[3], i; 251962306a36Sopenharmony_ci 252062306a36Sopenharmony_ci if (it6505->enable_drv_hold || !it6505->powered) 252162306a36Sopenharmony_ci return IRQ_HANDLED; 252262306a36Sopenharmony_ci 252362306a36Sopenharmony_ci pm_runtime_get_sync(dev); 252462306a36Sopenharmony_ci 252562306a36Sopenharmony_ci int_status[0] = it6505_read(it6505, INT_STATUS_01); 252662306a36Sopenharmony_ci int_status[1] = it6505_read(it6505, INT_STATUS_02); 252762306a36Sopenharmony_ci int_status[2] = it6505_read(it6505, INT_STATUS_03); 252862306a36Sopenharmony_ci 252962306a36Sopenharmony_ci it6505_write(it6505, INT_STATUS_01, int_status[0]); 253062306a36Sopenharmony_ci it6505_write(it6505, INT_STATUS_02, int_status[1]); 253162306a36Sopenharmony_ci it6505_write(it6505, INT_STATUS_03, int_status[2]); 253262306a36Sopenharmony_ci 253362306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "reg06 = 0x%02x", int_status[0]); 253462306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "reg07 = 0x%02x", int_status[1]); 253562306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "reg08 = 0x%02x", int_status[2]); 253662306a36Sopenharmony_ci it6505_debug_print(it6505, REG_SYSTEM_STS, ""); 253762306a36Sopenharmony_ci 253862306a36Sopenharmony_ci if (it6505_test_bit(irq_vec[0].bit, (unsigned int *)int_status)) 253962306a36Sopenharmony_ci irq_vec[0].handler(it6505); 254062306a36Sopenharmony_ci 254162306a36Sopenharmony_ci if (it6505->hpd_state) { 254262306a36Sopenharmony_ci for (i = 1; i < ARRAY_SIZE(irq_vec); i++) { 254362306a36Sopenharmony_ci if (it6505_test_bit(irq_vec[i].bit, (unsigned int *)int_status)) 254462306a36Sopenharmony_ci irq_vec[i].handler(it6505); 254562306a36Sopenharmony_ci } 254662306a36Sopenharmony_ci } 254762306a36Sopenharmony_ci 254862306a36Sopenharmony_ci pm_runtime_put_sync(dev); 254962306a36Sopenharmony_ci 255062306a36Sopenharmony_ci return IRQ_HANDLED; 255162306a36Sopenharmony_ci} 255262306a36Sopenharmony_ci 255362306a36Sopenharmony_cistatic int it6505_poweron(struct it6505 *it6505) 255462306a36Sopenharmony_ci{ 255562306a36Sopenharmony_ci struct device *dev = it6505->dev; 255662306a36Sopenharmony_ci struct it6505_platform_data *pdata = &it6505->pdata; 255762306a36Sopenharmony_ci int err; 255862306a36Sopenharmony_ci 255962306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "it6505 start powered on"); 256062306a36Sopenharmony_ci 256162306a36Sopenharmony_ci if (it6505->powered) { 256262306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "it6505 already powered on"); 256362306a36Sopenharmony_ci return 0; 256462306a36Sopenharmony_ci } 256562306a36Sopenharmony_ci 256662306a36Sopenharmony_ci if (pdata->pwr18) { 256762306a36Sopenharmony_ci err = regulator_enable(pdata->pwr18); 256862306a36Sopenharmony_ci if (err) { 256962306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "Failed to enable VDD18: %d", 257062306a36Sopenharmony_ci err); 257162306a36Sopenharmony_ci return err; 257262306a36Sopenharmony_ci } 257362306a36Sopenharmony_ci } 257462306a36Sopenharmony_ci 257562306a36Sopenharmony_ci if (pdata->ovdd) { 257662306a36Sopenharmony_ci /* time interval between IVDD and OVDD at least be 1ms */ 257762306a36Sopenharmony_ci usleep_range(1000, 2000); 257862306a36Sopenharmony_ci err = regulator_enable(pdata->ovdd); 257962306a36Sopenharmony_ci if (err) { 258062306a36Sopenharmony_ci regulator_disable(pdata->pwr18); 258162306a36Sopenharmony_ci return err; 258262306a36Sopenharmony_ci } 258362306a36Sopenharmony_ci } 258462306a36Sopenharmony_ci /* time interval between OVDD and SYSRSTN at least be 10ms */ 258562306a36Sopenharmony_ci if (pdata->gpiod_reset) { 258662306a36Sopenharmony_ci usleep_range(10000, 20000); 258762306a36Sopenharmony_ci gpiod_set_value_cansleep(pdata->gpiod_reset, 0); 258862306a36Sopenharmony_ci usleep_range(1000, 2000); 258962306a36Sopenharmony_ci gpiod_set_value_cansleep(pdata->gpiod_reset, 1); 259062306a36Sopenharmony_ci usleep_range(10000, 20000); 259162306a36Sopenharmony_ci } 259262306a36Sopenharmony_ci 259362306a36Sopenharmony_ci it6505->powered = true; 259462306a36Sopenharmony_ci it6505_reset_logic(it6505); 259562306a36Sopenharmony_ci it6505_int_mask_enable(it6505); 259662306a36Sopenharmony_ci it6505_init(it6505); 259762306a36Sopenharmony_ci it6505_lane_off(it6505); 259862306a36Sopenharmony_ci 259962306a36Sopenharmony_ci return 0; 260062306a36Sopenharmony_ci} 260162306a36Sopenharmony_ci 260262306a36Sopenharmony_cistatic int it6505_poweroff(struct it6505 *it6505) 260362306a36Sopenharmony_ci{ 260462306a36Sopenharmony_ci struct device *dev = it6505->dev; 260562306a36Sopenharmony_ci struct it6505_platform_data *pdata = &it6505->pdata; 260662306a36Sopenharmony_ci int err; 260762306a36Sopenharmony_ci 260862306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "it6505 start power off"); 260962306a36Sopenharmony_ci 261062306a36Sopenharmony_ci if (!it6505->powered) { 261162306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "power had been already off"); 261262306a36Sopenharmony_ci return 0; 261362306a36Sopenharmony_ci } 261462306a36Sopenharmony_ci 261562306a36Sopenharmony_ci if (pdata->gpiod_reset) 261662306a36Sopenharmony_ci gpiod_set_value_cansleep(pdata->gpiod_reset, 0); 261762306a36Sopenharmony_ci 261862306a36Sopenharmony_ci if (pdata->pwr18) { 261962306a36Sopenharmony_ci err = regulator_disable(pdata->pwr18); 262062306a36Sopenharmony_ci if (err) 262162306a36Sopenharmony_ci return err; 262262306a36Sopenharmony_ci } 262362306a36Sopenharmony_ci 262462306a36Sopenharmony_ci if (pdata->ovdd) { 262562306a36Sopenharmony_ci err = regulator_disable(pdata->ovdd); 262662306a36Sopenharmony_ci if (err) 262762306a36Sopenharmony_ci return err; 262862306a36Sopenharmony_ci } 262962306a36Sopenharmony_ci 263062306a36Sopenharmony_ci it6505->powered = false; 263162306a36Sopenharmony_ci it6505->sink_count = 0; 263262306a36Sopenharmony_ci 263362306a36Sopenharmony_ci return 0; 263462306a36Sopenharmony_ci} 263562306a36Sopenharmony_ci 263662306a36Sopenharmony_cistatic enum drm_connector_status it6505_detect(struct it6505 *it6505) 263762306a36Sopenharmony_ci{ 263862306a36Sopenharmony_ci struct device *dev = it6505->dev; 263962306a36Sopenharmony_ci enum drm_connector_status status = connector_status_disconnected; 264062306a36Sopenharmony_ci int dp_sink_count; 264162306a36Sopenharmony_ci 264262306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "it6505->sink_count:%d powered:%d", 264362306a36Sopenharmony_ci it6505->sink_count, it6505->powered); 264462306a36Sopenharmony_ci 264562306a36Sopenharmony_ci mutex_lock(&it6505->mode_lock); 264662306a36Sopenharmony_ci 264762306a36Sopenharmony_ci if (!it6505->powered) 264862306a36Sopenharmony_ci goto unlock; 264962306a36Sopenharmony_ci 265062306a36Sopenharmony_ci if (it6505->enable_drv_hold) { 265162306a36Sopenharmony_ci status = it6505->hpd_state ? connector_status_connected : 265262306a36Sopenharmony_ci connector_status_disconnected; 265362306a36Sopenharmony_ci goto unlock; 265462306a36Sopenharmony_ci } 265562306a36Sopenharmony_ci 265662306a36Sopenharmony_ci if (it6505->hpd_state) { 265762306a36Sopenharmony_ci it6505_drm_dp_link_set_power(&it6505->aux, &it6505->link, 265862306a36Sopenharmony_ci DP_SET_POWER_D0); 265962306a36Sopenharmony_ci dp_sink_count = it6505_dpcd_read(it6505, DP_SINK_COUNT); 266062306a36Sopenharmony_ci it6505->sink_count = DP_GET_SINK_COUNT(dp_sink_count); 266162306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "it6505->sink_count:%d branch:%d", 266262306a36Sopenharmony_ci it6505->sink_count, it6505->branch_device); 266362306a36Sopenharmony_ci 266462306a36Sopenharmony_ci if (it6505->branch_device) { 266562306a36Sopenharmony_ci status = (it6505->sink_count != 0) ? 266662306a36Sopenharmony_ci connector_status_connected : 266762306a36Sopenharmony_ci connector_status_disconnected; 266862306a36Sopenharmony_ci } else { 266962306a36Sopenharmony_ci status = connector_status_connected; 267062306a36Sopenharmony_ci } 267162306a36Sopenharmony_ci } else { 267262306a36Sopenharmony_ci it6505->sink_count = 0; 267362306a36Sopenharmony_ci memset(it6505->dpcd, 0, sizeof(it6505->dpcd)); 267462306a36Sopenharmony_ci } 267562306a36Sopenharmony_ci 267662306a36Sopenharmony_ciunlock: 267762306a36Sopenharmony_ci if (it6505->connector_status != status) { 267862306a36Sopenharmony_ci it6505->connector_status = status; 267962306a36Sopenharmony_ci it6505_plugged_status_to_codec(it6505); 268062306a36Sopenharmony_ci } 268162306a36Sopenharmony_ci 268262306a36Sopenharmony_ci mutex_unlock(&it6505->mode_lock); 268362306a36Sopenharmony_ci 268462306a36Sopenharmony_ci return status; 268562306a36Sopenharmony_ci} 268662306a36Sopenharmony_ci 268762306a36Sopenharmony_cistatic int it6505_extcon_notifier(struct notifier_block *self, 268862306a36Sopenharmony_ci unsigned long event, void *ptr) 268962306a36Sopenharmony_ci{ 269062306a36Sopenharmony_ci struct it6505 *it6505 = container_of(self, struct it6505, event_nb); 269162306a36Sopenharmony_ci 269262306a36Sopenharmony_ci schedule_work(&it6505->extcon_wq); 269362306a36Sopenharmony_ci return NOTIFY_DONE; 269462306a36Sopenharmony_ci} 269562306a36Sopenharmony_ci 269662306a36Sopenharmony_cistatic void it6505_extcon_work(struct work_struct *work) 269762306a36Sopenharmony_ci{ 269862306a36Sopenharmony_ci struct it6505 *it6505 = container_of(work, struct it6505, extcon_wq); 269962306a36Sopenharmony_ci struct device *dev = it6505->dev; 270062306a36Sopenharmony_ci int state, ret; 270162306a36Sopenharmony_ci 270262306a36Sopenharmony_ci if (it6505->enable_drv_hold) 270362306a36Sopenharmony_ci return; 270462306a36Sopenharmony_ci 270562306a36Sopenharmony_ci mutex_lock(&it6505->extcon_lock); 270662306a36Sopenharmony_ci 270762306a36Sopenharmony_ci state = extcon_get_state(it6505->extcon, EXTCON_DISP_DP); 270862306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "EXTCON_DISP_DP = 0x%02x", state); 270962306a36Sopenharmony_ci 271062306a36Sopenharmony_ci if (state == it6505->extcon_state || unlikely(state < 0)) 271162306a36Sopenharmony_ci goto unlock; 271262306a36Sopenharmony_ci it6505->extcon_state = state; 271362306a36Sopenharmony_ci if (state) { 271462306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "start to power on"); 271562306a36Sopenharmony_ci msleep(100); 271662306a36Sopenharmony_ci ret = pm_runtime_get_sync(dev); 271762306a36Sopenharmony_ci 271862306a36Sopenharmony_ci /* 271962306a36Sopenharmony_ci * On system resume, extcon_work can be triggered before 272062306a36Sopenharmony_ci * pm_runtime_force_resume re-enables runtime power management. 272162306a36Sopenharmony_ci * Handling the error here to make sure the bridge is powered on. 272262306a36Sopenharmony_ci */ 272362306a36Sopenharmony_ci if (ret < 0) 272462306a36Sopenharmony_ci it6505_poweron(it6505); 272562306a36Sopenharmony_ci 272662306a36Sopenharmony_ci complete_all(&it6505->extcon_completion); 272762306a36Sopenharmony_ci } else { 272862306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "start to power off"); 272962306a36Sopenharmony_ci pm_runtime_put_sync(dev); 273062306a36Sopenharmony_ci reinit_completion(&it6505->extcon_completion); 273162306a36Sopenharmony_ci 273262306a36Sopenharmony_ci drm_helper_hpd_irq_event(it6505->bridge.dev); 273362306a36Sopenharmony_ci memset(it6505->dpcd, 0, sizeof(it6505->dpcd)); 273462306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "power off it6505 success!"); 273562306a36Sopenharmony_ci } 273662306a36Sopenharmony_ci 273762306a36Sopenharmony_ciunlock: 273862306a36Sopenharmony_ci mutex_unlock(&it6505->extcon_lock); 273962306a36Sopenharmony_ci} 274062306a36Sopenharmony_ci 274162306a36Sopenharmony_cistatic int it6505_use_notifier_module(struct it6505 *it6505) 274262306a36Sopenharmony_ci{ 274362306a36Sopenharmony_ci int ret; 274462306a36Sopenharmony_ci struct device *dev = it6505->dev; 274562306a36Sopenharmony_ci 274662306a36Sopenharmony_ci it6505->event_nb.notifier_call = it6505_extcon_notifier; 274762306a36Sopenharmony_ci INIT_WORK(&it6505->extcon_wq, it6505_extcon_work); 274862306a36Sopenharmony_ci ret = devm_extcon_register_notifier(it6505->dev, 274962306a36Sopenharmony_ci it6505->extcon, EXTCON_DISP_DP, 275062306a36Sopenharmony_ci &it6505->event_nb); 275162306a36Sopenharmony_ci if (ret) { 275262306a36Sopenharmony_ci dev_err(dev, "failed to register notifier for DP"); 275362306a36Sopenharmony_ci return ret; 275462306a36Sopenharmony_ci } 275562306a36Sopenharmony_ci 275662306a36Sopenharmony_ci schedule_work(&it6505->extcon_wq); 275762306a36Sopenharmony_ci 275862306a36Sopenharmony_ci return 0; 275962306a36Sopenharmony_ci} 276062306a36Sopenharmony_ci 276162306a36Sopenharmony_cistatic void it6505_remove_notifier_module(struct it6505 *it6505) 276262306a36Sopenharmony_ci{ 276362306a36Sopenharmony_ci if (it6505->extcon) { 276462306a36Sopenharmony_ci devm_extcon_unregister_notifier(it6505->dev, 276562306a36Sopenharmony_ci it6505->extcon, EXTCON_DISP_DP, 276662306a36Sopenharmony_ci &it6505->event_nb); 276762306a36Sopenharmony_ci 276862306a36Sopenharmony_ci flush_work(&it6505->extcon_wq); 276962306a36Sopenharmony_ci } 277062306a36Sopenharmony_ci} 277162306a36Sopenharmony_ci 277262306a36Sopenharmony_cistatic void __maybe_unused it6505_delayed_audio(struct work_struct *work) 277362306a36Sopenharmony_ci{ 277462306a36Sopenharmony_ci struct it6505 *it6505 = container_of(work, struct it6505, 277562306a36Sopenharmony_ci delayed_audio.work); 277662306a36Sopenharmony_ci 277762306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(it6505->dev, "start"); 277862306a36Sopenharmony_ci 277962306a36Sopenharmony_ci if (!it6505->powered) 278062306a36Sopenharmony_ci return; 278162306a36Sopenharmony_ci 278262306a36Sopenharmony_ci if (!it6505->enable_drv_hold) 278362306a36Sopenharmony_ci it6505_enable_audio(it6505); 278462306a36Sopenharmony_ci} 278562306a36Sopenharmony_ci 278662306a36Sopenharmony_cistatic int __maybe_unused it6505_audio_setup_hw_params(struct it6505 *it6505, 278762306a36Sopenharmony_ci struct hdmi_codec_params 278862306a36Sopenharmony_ci *params) 278962306a36Sopenharmony_ci{ 279062306a36Sopenharmony_ci struct device *dev = it6505->dev; 279162306a36Sopenharmony_ci int i = 0; 279262306a36Sopenharmony_ci 279362306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "%s %d Hz, %d bit, %d channels\n", __func__, 279462306a36Sopenharmony_ci params->sample_rate, params->sample_width, 279562306a36Sopenharmony_ci params->cea.channels); 279662306a36Sopenharmony_ci 279762306a36Sopenharmony_ci if (!it6505->bridge.encoder) 279862306a36Sopenharmony_ci return -ENODEV; 279962306a36Sopenharmony_ci 280062306a36Sopenharmony_ci if (params->cea.channels <= 1 || params->cea.channels > 8) { 280162306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "channel number: %d not support", 280262306a36Sopenharmony_ci it6505->audio.channel_count); 280362306a36Sopenharmony_ci return -EINVAL; 280462306a36Sopenharmony_ci } 280562306a36Sopenharmony_ci 280662306a36Sopenharmony_ci it6505->audio.channel_count = params->cea.channels; 280762306a36Sopenharmony_ci 280862306a36Sopenharmony_ci while (i < ARRAY_SIZE(audio_sample_rate_map) && 280962306a36Sopenharmony_ci params->sample_rate != 281062306a36Sopenharmony_ci audio_sample_rate_map[i].sample_rate_value) { 281162306a36Sopenharmony_ci i++; 281262306a36Sopenharmony_ci } 281362306a36Sopenharmony_ci if (i == ARRAY_SIZE(audio_sample_rate_map)) { 281462306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "sample rate: %d Hz not support", 281562306a36Sopenharmony_ci params->sample_rate); 281662306a36Sopenharmony_ci return -EINVAL; 281762306a36Sopenharmony_ci } 281862306a36Sopenharmony_ci it6505->audio.sample_rate = audio_sample_rate_map[i].rate; 281962306a36Sopenharmony_ci 282062306a36Sopenharmony_ci switch (params->sample_width) { 282162306a36Sopenharmony_ci case 16: 282262306a36Sopenharmony_ci it6505->audio.word_length = WORD_LENGTH_16BIT; 282362306a36Sopenharmony_ci break; 282462306a36Sopenharmony_ci case 18: 282562306a36Sopenharmony_ci it6505->audio.word_length = WORD_LENGTH_18BIT; 282662306a36Sopenharmony_ci break; 282762306a36Sopenharmony_ci case 20: 282862306a36Sopenharmony_ci it6505->audio.word_length = WORD_LENGTH_20BIT; 282962306a36Sopenharmony_ci break; 283062306a36Sopenharmony_ci case 24: 283162306a36Sopenharmony_ci case 32: 283262306a36Sopenharmony_ci it6505->audio.word_length = WORD_LENGTH_24BIT; 283362306a36Sopenharmony_ci break; 283462306a36Sopenharmony_ci default: 283562306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "wordlength: %d bit not support", 283662306a36Sopenharmony_ci params->sample_width); 283762306a36Sopenharmony_ci return -EINVAL; 283862306a36Sopenharmony_ci } 283962306a36Sopenharmony_ci 284062306a36Sopenharmony_ci return 0; 284162306a36Sopenharmony_ci} 284262306a36Sopenharmony_ci 284362306a36Sopenharmony_cistatic void __maybe_unused it6505_audio_shutdown(struct device *dev, void *data) 284462306a36Sopenharmony_ci{ 284562306a36Sopenharmony_ci struct it6505 *it6505 = dev_get_drvdata(dev); 284662306a36Sopenharmony_ci 284762306a36Sopenharmony_ci if (it6505->powered) 284862306a36Sopenharmony_ci it6505_disable_audio(it6505); 284962306a36Sopenharmony_ci} 285062306a36Sopenharmony_ci 285162306a36Sopenharmony_cistatic int __maybe_unused it6505_audio_hook_plugged_cb(struct device *dev, 285262306a36Sopenharmony_ci void *data, 285362306a36Sopenharmony_ci hdmi_codec_plugged_cb fn, 285462306a36Sopenharmony_ci struct device *codec_dev) 285562306a36Sopenharmony_ci{ 285662306a36Sopenharmony_ci struct it6505 *it6505 = data; 285762306a36Sopenharmony_ci 285862306a36Sopenharmony_ci it6505->plugged_cb = fn; 285962306a36Sopenharmony_ci it6505->codec_dev = codec_dev; 286062306a36Sopenharmony_ci it6505_plugged_status_to_codec(it6505); 286162306a36Sopenharmony_ci 286262306a36Sopenharmony_ci return 0; 286362306a36Sopenharmony_ci} 286462306a36Sopenharmony_ci 286562306a36Sopenharmony_cistatic inline struct it6505 *bridge_to_it6505(struct drm_bridge *bridge) 286662306a36Sopenharmony_ci{ 286762306a36Sopenharmony_ci return container_of(bridge, struct it6505, bridge); 286862306a36Sopenharmony_ci} 286962306a36Sopenharmony_ci 287062306a36Sopenharmony_cistatic int it6505_bridge_attach(struct drm_bridge *bridge, 287162306a36Sopenharmony_ci enum drm_bridge_attach_flags flags) 287262306a36Sopenharmony_ci{ 287362306a36Sopenharmony_ci struct it6505 *it6505 = bridge_to_it6505(bridge); 287462306a36Sopenharmony_ci struct device *dev = it6505->dev; 287562306a36Sopenharmony_ci int ret; 287662306a36Sopenharmony_ci 287762306a36Sopenharmony_ci if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) { 287862306a36Sopenharmony_ci DRM_ERROR("DRM_BRIDGE_ATTACH_NO_CONNECTOR must be supplied"); 287962306a36Sopenharmony_ci return -EINVAL; 288062306a36Sopenharmony_ci } 288162306a36Sopenharmony_ci 288262306a36Sopenharmony_ci if (!bridge->encoder) { 288362306a36Sopenharmony_ci dev_err(dev, "Parent encoder object not found"); 288462306a36Sopenharmony_ci return -ENODEV; 288562306a36Sopenharmony_ci } 288662306a36Sopenharmony_ci 288762306a36Sopenharmony_ci /* Register aux channel */ 288862306a36Sopenharmony_ci it6505->aux.drm_dev = bridge->dev; 288962306a36Sopenharmony_ci 289062306a36Sopenharmony_ci ret = drm_dp_aux_register(&it6505->aux); 289162306a36Sopenharmony_ci 289262306a36Sopenharmony_ci if (ret < 0) { 289362306a36Sopenharmony_ci dev_err(dev, "Failed to register aux: %d", ret); 289462306a36Sopenharmony_ci return ret; 289562306a36Sopenharmony_ci } 289662306a36Sopenharmony_ci 289762306a36Sopenharmony_ci if (it6505->extcon) { 289862306a36Sopenharmony_ci ret = it6505_use_notifier_module(it6505); 289962306a36Sopenharmony_ci if (ret < 0) { 290062306a36Sopenharmony_ci dev_err(dev, "use notifier module failed"); 290162306a36Sopenharmony_ci return ret; 290262306a36Sopenharmony_ci } 290362306a36Sopenharmony_ci } 290462306a36Sopenharmony_ci 290562306a36Sopenharmony_ci return 0; 290662306a36Sopenharmony_ci} 290762306a36Sopenharmony_ci 290862306a36Sopenharmony_cistatic void it6505_bridge_detach(struct drm_bridge *bridge) 290962306a36Sopenharmony_ci{ 291062306a36Sopenharmony_ci struct it6505 *it6505 = bridge_to_it6505(bridge); 291162306a36Sopenharmony_ci 291262306a36Sopenharmony_ci flush_work(&it6505->link_works); 291362306a36Sopenharmony_ci it6505_remove_notifier_module(it6505); 291462306a36Sopenharmony_ci} 291562306a36Sopenharmony_ci 291662306a36Sopenharmony_cistatic enum drm_mode_status 291762306a36Sopenharmony_ciit6505_bridge_mode_valid(struct drm_bridge *bridge, 291862306a36Sopenharmony_ci const struct drm_display_info *info, 291962306a36Sopenharmony_ci const struct drm_display_mode *mode) 292062306a36Sopenharmony_ci{ 292162306a36Sopenharmony_ci struct it6505 *it6505 = bridge_to_it6505(bridge); 292262306a36Sopenharmony_ci 292362306a36Sopenharmony_ci if (mode->flags & DRM_MODE_FLAG_INTERLACE) 292462306a36Sopenharmony_ci return MODE_NO_INTERLACE; 292562306a36Sopenharmony_ci 292662306a36Sopenharmony_ci if (mode->clock > it6505->max_dpi_pixel_clock) 292762306a36Sopenharmony_ci return MODE_CLOCK_HIGH; 292862306a36Sopenharmony_ci 292962306a36Sopenharmony_ci it6505->video_info.clock = mode->clock; 293062306a36Sopenharmony_ci 293162306a36Sopenharmony_ci return MODE_OK; 293262306a36Sopenharmony_ci} 293362306a36Sopenharmony_ci 293462306a36Sopenharmony_cistatic void it6505_bridge_atomic_enable(struct drm_bridge *bridge, 293562306a36Sopenharmony_ci struct drm_bridge_state *old_state) 293662306a36Sopenharmony_ci{ 293762306a36Sopenharmony_ci struct it6505 *it6505 = bridge_to_it6505(bridge); 293862306a36Sopenharmony_ci struct device *dev = it6505->dev; 293962306a36Sopenharmony_ci struct drm_atomic_state *state = old_state->base.state; 294062306a36Sopenharmony_ci struct hdmi_avi_infoframe frame; 294162306a36Sopenharmony_ci struct drm_crtc_state *crtc_state; 294262306a36Sopenharmony_ci struct drm_connector_state *conn_state; 294362306a36Sopenharmony_ci struct drm_display_mode *mode; 294462306a36Sopenharmony_ci struct drm_connector *connector; 294562306a36Sopenharmony_ci int ret; 294662306a36Sopenharmony_ci 294762306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "start"); 294862306a36Sopenharmony_ci 294962306a36Sopenharmony_ci connector = drm_atomic_get_new_connector_for_encoder(state, 295062306a36Sopenharmony_ci bridge->encoder); 295162306a36Sopenharmony_ci 295262306a36Sopenharmony_ci if (WARN_ON(!connector)) 295362306a36Sopenharmony_ci return; 295462306a36Sopenharmony_ci 295562306a36Sopenharmony_ci conn_state = drm_atomic_get_new_connector_state(state, connector); 295662306a36Sopenharmony_ci 295762306a36Sopenharmony_ci if (WARN_ON(!conn_state)) 295862306a36Sopenharmony_ci return; 295962306a36Sopenharmony_ci 296062306a36Sopenharmony_ci crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc); 296162306a36Sopenharmony_ci 296262306a36Sopenharmony_ci if (WARN_ON(!crtc_state)) 296362306a36Sopenharmony_ci return; 296462306a36Sopenharmony_ci 296562306a36Sopenharmony_ci mode = &crtc_state->adjusted_mode; 296662306a36Sopenharmony_ci 296762306a36Sopenharmony_ci if (WARN_ON(!mode)) 296862306a36Sopenharmony_ci return; 296962306a36Sopenharmony_ci 297062306a36Sopenharmony_ci ret = drm_hdmi_avi_infoframe_from_display_mode(&frame, 297162306a36Sopenharmony_ci connector, 297262306a36Sopenharmony_ci mode); 297362306a36Sopenharmony_ci if (ret) 297462306a36Sopenharmony_ci dev_err(dev, "Failed to setup AVI infoframe: %d", ret); 297562306a36Sopenharmony_ci 297662306a36Sopenharmony_ci it6505_update_video_parameter(it6505, mode); 297762306a36Sopenharmony_ci 297862306a36Sopenharmony_ci ret = it6505_send_video_infoframe(it6505, &frame); 297962306a36Sopenharmony_ci 298062306a36Sopenharmony_ci if (ret) 298162306a36Sopenharmony_ci dev_err(dev, "Failed to send AVI infoframe: %d", ret); 298262306a36Sopenharmony_ci 298362306a36Sopenharmony_ci it6505_int_mask_enable(it6505); 298462306a36Sopenharmony_ci it6505_video_reset(it6505); 298562306a36Sopenharmony_ci 298662306a36Sopenharmony_ci it6505_drm_dp_link_set_power(&it6505->aux, &it6505->link, 298762306a36Sopenharmony_ci DP_SET_POWER_D0); 298862306a36Sopenharmony_ci} 298962306a36Sopenharmony_ci 299062306a36Sopenharmony_cistatic void it6505_bridge_atomic_disable(struct drm_bridge *bridge, 299162306a36Sopenharmony_ci struct drm_bridge_state *old_state) 299262306a36Sopenharmony_ci{ 299362306a36Sopenharmony_ci struct it6505 *it6505 = bridge_to_it6505(bridge); 299462306a36Sopenharmony_ci struct device *dev = it6505->dev; 299562306a36Sopenharmony_ci 299662306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "start"); 299762306a36Sopenharmony_ci 299862306a36Sopenharmony_ci if (it6505->powered) { 299962306a36Sopenharmony_ci it6505_drm_dp_link_set_power(&it6505->aux, &it6505->link, 300062306a36Sopenharmony_ci DP_SET_POWER_D3); 300162306a36Sopenharmony_ci it6505_video_disable(it6505); 300262306a36Sopenharmony_ci } 300362306a36Sopenharmony_ci} 300462306a36Sopenharmony_ci 300562306a36Sopenharmony_cistatic void it6505_bridge_atomic_pre_enable(struct drm_bridge *bridge, 300662306a36Sopenharmony_ci struct drm_bridge_state *old_state) 300762306a36Sopenharmony_ci{ 300862306a36Sopenharmony_ci struct it6505 *it6505 = bridge_to_it6505(bridge); 300962306a36Sopenharmony_ci struct device *dev = it6505->dev; 301062306a36Sopenharmony_ci 301162306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "start"); 301262306a36Sopenharmony_ci 301362306a36Sopenharmony_ci pm_runtime_get_sync(dev); 301462306a36Sopenharmony_ci} 301562306a36Sopenharmony_ci 301662306a36Sopenharmony_cistatic void it6505_bridge_atomic_post_disable(struct drm_bridge *bridge, 301762306a36Sopenharmony_ci struct drm_bridge_state *old_state) 301862306a36Sopenharmony_ci{ 301962306a36Sopenharmony_ci struct it6505 *it6505 = bridge_to_it6505(bridge); 302062306a36Sopenharmony_ci struct device *dev = it6505->dev; 302162306a36Sopenharmony_ci 302262306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "start"); 302362306a36Sopenharmony_ci 302462306a36Sopenharmony_ci pm_runtime_put_sync(dev); 302562306a36Sopenharmony_ci} 302662306a36Sopenharmony_ci 302762306a36Sopenharmony_cistatic enum drm_connector_status 302862306a36Sopenharmony_ciit6505_bridge_detect(struct drm_bridge *bridge) 302962306a36Sopenharmony_ci{ 303062306a36Sopenharmony_ci struct it6505 *it6505 = bridge_to_it6505(bridge); 303162306a36Sopenharmony_ci 303262306a36Sopenharmony_ci return it6505_detect(it6505); 303362306a36Sopenharmony_ci} 303462306a36Sopenharmony_ci 303562306a36Sopenharmony_cistatic struct edid *it6505_bridge_get_edid(struct drm_bridge *bridge, 303662306a36Sopenharmony_ci struct drm_connector *connector) 303762306a36Sopenharmony_ci{ 303862306a36Sopenharmony_ci struct it6505 *it6505 = bridge_to_it6505(bridge); 303962306a36Sopenharmony_ci struct device *dev = it6505->dev; 304062306a36Sopenharmony_ci 304162306a36Sopenharmony_ci if (!it6505->cached_edid) { 304262306a36Sopenharmony_ci it6505->cached_edid = drm_do_get_edid(connector, it6505_get_edid_block, 304362306a36Sopenharmony_ci it6505); 304462306a36Sopenharmony_ci 304562306a36Sopenharmony_ci if (!it6505->cached_edid) { 304662306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "failed to get edid!"); 304762306a36Sopenharmony_ci return NULL; 304862306a36Sopenharmony_ci } 304962306a36Sopenharmony_ci } 305062306a36Sopenharmony_ci 305162306a36Sopenharmony_ci return drm_edid_duplicate(it6505->cached_edid); 305262306a36Sopenharmony_ci} 305362306a36Sopenharmony_ci 305462306a36Sopenharmony_cistatic const struct drm_bridge_funcs it6505_bridge_funcs = { 305562306a36Sopenharmony_ci .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, 305662306a36Sopenharmony_ci .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, 305762306a36Sopenharmony_ci .atomic_reset = drm_atomic_helper_bridge_reset, 305862306a36Sopenharmony_ci .attach = it6505_bridge_attach, 305962306a36Sopenharmony_ci .detach = it6505_bridge_detach, 306062306a36Sopenharmony_ci .mode_valid = it6505_bridge_mode_valid, 306162306a36Sopenharmony_ci .atomic_enable = it6505_bridge_atomic_enable, 306262306a36Sopenharmony_ci .atomic_disable = it6505_bridge_atomic_disable, 306362306a36Sopenharmony_ci .atomic_pre_enable = it6505_bridge_atomic_pre_enable, 306462306a36Sopenharmony_ci .atomic_post_disable = it6505_bridge_atomic_post_disable, 306562306a36Sopenharmony_ci .detect = it6505_bridge_detect, 306662306a36Sopenharmony_ci .get_edid = it6505_bridge_get_edid, 306762306a36Sopenharmony_ci}; 306862306a36Sopenharmony_ci 306962306a36Sopenharmony_cistatic __maybe_unused int it6505_bridge_resume(struct device *dev) 307062306a36Sopenharmony_ci{ 307162306a36Sopenharmony_ci struct it6505 *it6505 = dev_get_drvdata(dev); 307262306a36Sopenharmony_ci 307362306a36Sopenharmony_ci return it6505_poweron(it6505); 307462306a36Sopenharmony_ci} 307562306a36Sopenharmony_ci 307662306a36Sopenharmony_cistatic __maybe_unused int it6505_bridge_suspend(struct device *dev) 307762306a36Sopenharmony_ci{ 307862306a36Sopenharmony_ci struct it6505 *it6505 = dev_get_drvdata(dev); 307962306a36Sopenharmony_ci 308062306a36Sopenharmony_ci return it6505_poweroff(it6505); 308162306a36Sopenharmony_ci} 308262306a36Sopenharmony_ci 308362306a36Sopenharmony_cistatic const struct dev_pm_ops it6505_bridge_pm_ops = { 308462306a36Sopenharmony_ci SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) 308562306a36Sopenharmony_ci SET_RUNTIME_PM_OPS(it6505_bridge_suspend, it6505_bridge_resume, NULL) 308662306a36Sopenharmony_ci}; 308762306a36Sopenharmony_ci 308862306a36Sopenharmony_cistatic int it6505_init_pdata(struct it6505 *it6505) 308962306a36Sopenharmony_ci{ 309062306a36Sopenharmony_ci struct it6505_platform_data *pdata = &it6505->pdata; 309162306a36Sopenharmony_ci struct device *dev = it6505->dev; 309262306a36Sopenharmony_ci 309362306a36Sopenharmony_ci /* 1.0V digital core power regulator */ 309462306a36Sopenharmony_ci pdata->pwr18 = devm_regulator_get(dev, "pwr18"); 309562306a36Sopenharmony_ci if (IS_ERR(pdata->pwr18)) { 309662306a36Sopenharmony_ci dev_err(dev, "pwr18 regulator not found"); 309762306a36Sopenharmony_ci return PTR_ERR(pdata->pwr18); 309862306a36Sopenharmony_ci } 309962306a36Sopenharmony_ci 310062306a36Sopenharmony_ci pdata->ovdd = devm_regulator_get(dev, "ovdd"); 310162306a36Sopenharmony_ci if (IS_ERR(pdata->ovdd)) { 310262306a36Sopenharmony_ci dev_err(dev, "ovdd regulator not found"); 310362306a36Sopenharmony_ci return PTR_ERR(pdata->ovdd); 310462306a36Sopenharmony_ci } 310562306a36Sopenharmony_ci 310662306a36Sopenharmony_ci pdata->gpiod_reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); 310762306a36Sopenharmony_ci if (IS_ERR(pdata->gpiod_reset)) { 310862306a36Sopenharmony_ci dev_err(dev, "gpiod_reset gpio not found"); 310962306a36Sopenharmony_ci return PTR_ERR(pdata->gpiod_reset); 311062306a36Sopenharmony_ci } 311162306a36Sopenharmony_ci 311262306a36Sopenharmony_ci return 0; 311362306a36Sopenharmony_ci} 311462306a36Sopenharmony_ci 311562306a36Sopenharmony_cistatic int it6505_get_data_lanes_count(const struct device_node *endpoint, 311662306a36Sopenharmony_ci const unsigned int min, 311762306a36Sopenharmony_ci const unsigned int max) 311862306a36Sopenharmony_ci{ 311962306a36Sopenharmony_ci int ret; 312062306a36Sopenharmony_ci 312162306a36Sopenharmony_ci ret = of_property_count_u32_elems(endpoint, "data-lanes"); 312262306a36Sopenharmony_ci if (ret < 0) 312362306a36Sopenharmony_ci return ret; 312462306a36Sopenharmony_ci 312562306a36Sopenharmony_ci if (ret < min || ret > max) 312662306a36Sopenharmony_ci return -EINVAL; 312762306a36Sopenharmony_ci 312862306a36Sopenharmony_ci return ret; 312962306a36Sopenharmony_ci} 313062306a36Sopenharmony_ci 313162306a36Sopenharmony_cistatic void it6505_parse_dt(struct it6505 *it6505) 313262306a36Sopenharmony_ci{ 313362306a36Sopenharmony_ci struct device *dev = it6505->dev; 313462306a36Sopenharmony_ci struct device_node *np = dev->of_node, *ep = NULL; 313562306a36Sopenharmony_ci int len; 313662306a36Sopenharmony_ci u64 link_frequencies; 313762306a36Sopenharmony_ci u32 data_lanes[4]; 313862306a36Sopenharmony_ci u32 *afe_setting = &it6505->afe_setting; 313962306a36Sopenharmony_ci u32 *max_lane_count = &it6505->max_lane_count; 314062306a36Sopenharmony_ci u32 *max_dpi_pixel_clock = &it6505->max_dpi_pixel_clock; 314162306a36Sopenharmony_ci 314262306a36Sopenharmony_ci it6505->lane_swap_disabled = 314362306a36Sopenharmony_ci device_property_read_bool(dev, "no-laneswap"); 314462306a36Sopenharmony_ci 314562306a36Sopenharmony_ci if (it6505->lane_swap_disabled) 314662306a36Sopenharmony_ci it6505->lane_swap = false; 314762306a36Sopenharmony_ci 314862306a36Sopenharmony_ci if (device_property_read_u32(dev, "afe-setting", afe_setting) == 0) { 314962306a36Sopenharmony_ci if (*afe_setting >= ARRAY_SIZE(afe_setting_table)) { 315062306a36Sopenharmony_ci dev_err(dev, "afe setting error, use default"); 315162306a36Sopenharmony_ci *afe_setting = 0; 315262306a36Sopenharmony_ci } 315362306a36Sopenharmony_ci } else { 315462306a36Sopenharmony_ci *afe_setting = 0; 315562306a36Sopenharmony_ci } 315662306a36Sopenharmony_ci 315762306a36Sopenharmony_ci ep = of_graph_get_endpoint_by_regs(np, 1, 0); 315862306a36Sopenharmony_ci of_node_put(ep); 315962306a36Sopenharmony_ci 316062306a36Sopenharmony_ci if (ep) { 316162306a36Sopenharmony_ci len = it6505_get_data_lanes_count(ep, 1, 4); 316262306a36Sopenharmony_ci 316362306a36Sopenharmony_ci if (len > 0 && len != 3) { 316462306a36Sopenharmony_ci of_property_read_u32_array(ep, "data-lanes", 316562306a36Sopenharmony_ci data_lanes, len); 316662306a36Sopenharmony_ci *max_lane_count = len; 316762306a36Sopenharmony_ci } else { 316862306a36Sopenharmony_ci *max_lane_count = MAX_LANE_COUNT; 316962306a36Sopenharmony_ci dev_err(dev, "error data-lanes, use default"); 317062306a36Sopenharmony_ci } 317162306a36Sopenharmony_ci } else { 317262306a36Sopenharmony_ci *max_lane_count = MAX_LANE_COUNT; 317362306a36Sopenharmony_ci dev_err(dev, "error endpoint, use default"); 317462306a36Sopenharmony_ci } 317562306a36Sopenharmony_ci 317662306a36Sopenharmony_ci ep = of_graph_get_endpoint_by_regs(np, 0, 0); 317762306a36Sopenharmony_ci of_node_put(ep); 317862306a36Sopenharmony_ci 317962306a36Sopenharmony_ci if (ep) { 318062306a36Sopenharmony_ci len = of_property_read_variable_u64_array(ep, 318162306a36Sopenharmony_ci "link-frequencies", 318262306a36Sopenharmony_ci &link_frequencies, 0, 318362306a36Sopenharmony_ci 1); 318462306a36Sopenharmony_ci if (len >= 0) { 318562306a36Sopenharmony_ci do_div(link_frequencies, 1000); 318662306a36Sopenharmony_ci if (link_frequencies > 297000) { 318762306a36Sopenharmony_ci dev_err(dev, 318862306a36Sopenharmony_ci "max pixel clock error, use default"); 318962306a36Sopenharmony_ci *max_dpi_pixel_clock = DPI_PIXEL_CLK_MAX; 319062306a36Sopenharmony_ci } else { 319162306a36Sopenharmony_ci *max_dpi_pixel_clock = link_frequencies; 319262306a36Sopenharmony_ci } 319362306a36Sopenharmony_ci } else { 319462306a36Sopenharmony_ci dev_err(dev, "error link frequencies, use default"); 319562306a36Sopenharmony_ci *max_dpi_pixel_clock = DPI_PIXEL_CLK_MAX; 319662306a36Sopenharmony_ci } 319762306a36Sopenharmony_ci } else { 319862306a36Sopenharmony_ci dev_err(dev, "error endpoint, use default"); 319962306a36Sopenharmony_ci *max_dpi_pixel_clock = DPI_PIXEL_CLK_MAX; 320062306a36Sopenharmony_ci } 320162306a36Sopenharmony_ci 320262306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "using afe_setting: %u, max_lane_count: %u", 320362306a36Sopenharmony_ci it6505->afe_setting, it6505->max_lane_count); 320462306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "using max_dpi_pixel_clock: %u kHz", 320562306a36Sopenharmony_ci it6505->max_dpi_pixel_clock); 320662306a36Sopenharmony_ci} 320762306a36Sopenharmony_ci 320862306a36Sopenharmony_cistatic ssize_t receive_timing_debugfs_show(struct file *file, char __user *buf, 320962306a36Sopenharmony_ci size_t len, loff_t *ppos) 321062306a36Sopenharmony_ci{ 321162306a36Sopenharmony_ci struct it6505 *it6505 = file->private_data; 321262306a36Sopenharmony_ci struct drm_display_mode *vid; 321362306a36Sopenharmony_ci u8 read_buf[READ_BUFFER_SIZE]; 321462306a36Sopenharmony_ci u8 *str = read_buf, *end = read_buf + READ_BUFFER_SIZE; 321562306a36Sopenharmony_ci ssize_t ret, count; 321662306a36Sopenharmony_ci 321762306a36Sopenharmony_ci if (!it6505) 321862306a36Sopenharmony_ci return -ENODEV; 321962306a36Sopenharmony_ci 322062306a36Sopenharmony_ci it6505_calc_video_info(it6505); 322162306a36Sopenharmony_ci vid = &it6505->video_info; 322262306a36Sopenharmony_ci str += scnprintf(str, end - str, "---video timing---\n"); 322362306a36Sopenharmony_ci str += scnprintf(str, end - str, "PCLK:%d.%03dMHz\n", 322462306a36Sopenharmony_ci vid->clock / 1000, vid->clock % 1000); 322562306a36Sopenharmony_ci str += scnprintf(str, end - str, "HTotal:%d\n", vid->htotal); 322662306a36Sopenharmony_ci str += scnprintf(str, end - str, "HActive:%d\n", vid->hdisplay); 322762306a36Sopenharmony_ci str += scnprintf(str, end - str, "HFrontPorch:%d\n", 322862306a36Sopenharmony_ci vid->hsync_start - vid->hdisplay); 322962306a36Sopenharmony_ci str += scnprintf(str, end - str, "HSyncWidth:%d\n", 323062306a36Sopenharmony_ci vid->hsync_end - vid->hsync_start); 323162306a36Sopenharmony_ci str += scnprintf(str, end - str, "HBackPorch:%d\n", 323262306a36Sopenharmony_ci vid->htotal - vid->hsync_end); 323362306a36Sopenharmony_ci str += scnprintf(str, end - str, "VTotal:%d\n", vid->vtotal); 323462306a36Sopenharmony_ci str += scnprintf(str, end - str, "VActive:%d\n", vid->vdisplay); 323562306a36Sopenharmony_ci str += scnprintf(str, end - str, "VFrontPorch:%d\n", 323662306a36Sopenharmony_ci vid->vsync_start - vid->vdisplay); 323762306a36Sopenharmony_ci str += scnprintf(str, end - str, "VSyncWidth:%d\n", 323862306a36Sopenharmony_ci vid->vsync_end - vid->vsync_start); 323962306a36Sopenharmony_ci str += scnprintf(str, end - str, "VBackPorch:%d\n", 324062306a36Sopenharmony_ci vid->vtotal - vid->vsync_end); 324162306a36Sopenharmony_ci 324262306a36Sopenharmony_ci count = str - read_buf; 324362306a36Sopenharmony_ci ret = simple_read_from_buffer(buf, len, ppos, read_buf, count); 324462306a36Sopenharmony_ci 324562306a36Sopenharmony_ci return ret; 324662306a36Sopenharmony_ci} 324762306a36Sopenharmony_ci 324862306a36Sopenharmony_cistatic int force_power_on_off_debugfs_write(void *data, u64 value) 324962306a36Sopenharmony_ci{ 325062306a36Sopenharmony_ci struct it6505 *it6505 = data; 325162306a36Sopenharmony_ci 325262306a36Sopenharmony_ci if (!it6505) 325362306a36Sopenharmony_ci return -ENODEV; 325462306a36Sopenharmony_ci 325562306a36Sopenharmony_ci if (value) 325662306a36Sopenharmony_ci it6505_poweron(it6505); 325762306a36Sopenharmony_ci else 325862306a36Sopenharmony_ci it6505_poweroff(it6505); 325962306a36Sopenharmony_ci 326062306a36Sopenharmony_ci return 0; 326162306a36Sopenharmony_ci} 326262306a36Sopenharmony_ci 326362306a36Sopenharmony_cistatic int enable_drv_hold_debugfs_show(void *data, u64 *buf) 326462306a36Sopenharmony_ci{ 326562306a36Sopenharmony_ci struct it6505 *it6505 = data; 326662306a36Sopenharmony_ci 326762306a36Sopenharmony_ci if (!it6505) 326862306a36Sopenharmony_ci return -ENODEV; 326962306a36Sopenharmony_ci 327062306a36Sopenharmony_ci *buf = it6505->enable_drv_hold; 327162306a36Sopenharmony_ci 327262306a36Sopenharmony_ci return 0; 327362306a36Sopenharmony_ci} 327462306a36Sopenharmony_ci 327562306a36Sopenharmony_cistatic int enable_drv_hold_debugfs_write(void *data, u64 drv_hold) 327662306a36Sopenharmony_ci{ 327762306a36Sopenharmony_ci struct it6505 *it6505 = data; 327862306a36Sopenharmony_ci 327962306a36Sopenharmony_ci if (!it6505) 328062306a36Sopenharmony_ci return -ENODEV; 328162306a36Sopenharmony_ci 328262306a36Sopenharmony_ci it6505->enable_drv_hold = drv_hold; 328362306a36Sopenharmony_ci 328462306a36Sopenharmony_ci if (it6505->enable_drv_hold) { 328562306a36Sopenharmony_ci it6505_int_mask_disable(it6505); 328662306a36Sopenharmony_ci } else { 328762306a36Sopenharmony_ci it6505_clear_int(it6505); 328862306a36Sopenharmony_ci it6505_int_mask_enable(it6505); 328962306a36Sopenharmony_ci 329062306a36Sopenharmony_ci if (it6505->powered) { 329162306a36Sopenharmony_ci it6505->connector_status = 329262306a36Sopenharmony_ci it6505_get_sink_hpd_status(it6505) ? 329362306a36Sopenharmony_ci connector_status_connected : 329462306a36Sopenharmony_ci connector_status_disconnected; 329562306a36Sopenharmony_ci } else { 329662306a36Sopenharmony_ci it6505->connector_status = 329762306a36Sopenharmony_ci connector_status_disconnected; 329862306a36Sopenharmony_ci } 329962306a36Sopenharmony_ci } 330062306a36Sopenharmony_ci 330162306a36Sopenharmony_ci return 0; 330262306a36Sopenharmony_ci} 330362306a36Sopenharmony_ci 330462306a36Sopenharmony_cistatic const struct file_operations receive_timing_fops = { 330562306a36Sopenharmony_ci .owner = THIS_MODULE, 330662306a36Sopenharmony_ci .open = simple_open, 330762306a36Sopenharmony_ci .read = receive_timing_debugfs_show, 330862306a36Sopenharmony_ci .llseek = default_llseek, 330962306a36Sopenharmony_ci}; 331062306a36Sopenharmony_ci 331162306a36Sopenharmony_ciDEFINE_DEBUGFS_ATTRIBUTE(fops_force_power, NULL, 331262306a36Sopenharmony_ci force_power_on_off_debugfs_write, "%llu\n"); 331362306a36Sopenharmony_ci 331462306a36Sopenharmony_ciDEFINE_DEBUGFS_ATTRIBUTE(fops_enable_drv_hold, enable_drv_hold_debugfs_show, 331562306a36Sopenharmony_ci enable_drv_hold_debugfs_write, "%llu\n"); 331662306a36Sopenharmony_ci 331762306a36Sopenharmony_cistatic const struct debugfs_entries debugfs_entry[] = { 331862306a36Sopenharmony_ci { "receive_timing", &receive_timing_fops }, 331962306a36Sopenharmony_ci { "force_power_on_off", &fops_force_power }, 332062306a36Sopenharmony_ci { "enable_drv_hold", &fops_enable_drv_hold }, 332162306a36Sopenharmony_ci { NULL, NULL }, 332262306a36Sopenharmony_ci}; 332362306a36Sopenharmony_ci 332462306a36Sopenharmony_cistatic void debugfs_create_files(struct it6505 *it6505) 332562306a36Sopenharmony_ci{ 332662306a36Sopenharmony_ci int i = 0; 332762306a36Sopenharmony_ci 332862306a36Sopenharmony_ci while (debugfs_entry[i].name && debugfs_entry[i].fops) { 332962306a36Sopenharmony_ci debugfs_create_file(debugfs_entry[i].name, 0644, 333062306a36Sopenharmony_ci it6505->debugfs, it6505, 333162306a36Sopenharmony_ci debugfs_entry[i].fops); 333262306a36Sopenharmony_ci i++; 333362306a36Sopenharmony_ci } 333462306a36Sopenharmony_ci} 333562306a36Sopenharmony_ci 333662306a36Sopenharmony_cistatic void debugfs_init(struct it6505 *it6505) 333762306a36Sopenharmony_ci{ 333862306a36Sopenharmony_ci struct device *dev = it6505->dev; 333962306a36Sopenharmony_ci 334062306a36Sopenharmony_ci it6505->debugfs = debugfs_create_dir(DEBUGFS_DIR_NAME, NULL); 334162306a36Sopenharmony_ci 334262306a36Sopenharmony_ci if (IS_ERR(it6505->debugfs)) { 334362306a36Sopenharmony_ci dev_err(dev, "failed to create debugfs root"); 334462306a36Sopenharmony_ci return; 334562306a36Sopenharmony_ci } 334662306a36Sopenharmony_ci 334762306a36Sopenharmony_ci debugfs_create_files(it6505); 334862306a36Sopenharmony_ci} 334962306a36Sopenharmony_ci 335062306a36Sopenharmony_cistatic void it6505_debugfs_remove(struct it6505 *it6505) 335162306a36Sopenharmony_ci{ 335262306a36Sopenharmony_ci debugfs_remove_recursive(it6505->debugfs); 335362306a36Sopenharmony_ci} 335462306a36Sopenharmony_ci 335562306a36Sopenharmony_cistatic void it6505_shutdown(struct i2c_client *client) 335662306a36Sopenharmony_ci{ 335762306a36Sopenharmony_ci struct it6505 *it6505 = dev_get_drvdata(&client->dev); 335862306a36Sopenharmony_ci 335962306a36Sopenharmony_ci if (it6505->powered) 336062306a36Sopenharmony_ci it6505_lane_off(it6505); 336162306a36Sopenharmony_ci} 336262306a36Sopenharmony_ci 336362306a36Sopenharmony_cistatic int it6505_i2c_probe(struct i2c_client *client) 336462306a36Sopenharmony_ci{ 336562306a36Sopenharmony_ci struct it6505 *it6505; 336662306a36Sopenharmony_ci struct device *dev = &client->dev; 336762306a36Sopenharmony_ci struct extcon_dev *extcon; 336862306a36Sopenharmony_ci int err, intp_irq; 336962306a36Sopenharmony_ci 337062306a36Sopenharmony_ci it6505 = devm_kzalloc(&client->dev, sizeof(*it6505), GFP_KERNEL); 337162306a36Sopenharmony_ci if (!it6505) 337262306a36Sopenharmony_ci return -ENOMEM; 337362306a36Sopenharmony_ci 337462306a36Sopenharmony_ci mutex_init(&it6505->extcon_lock); 337562306a36Sopenharmony_ci mutex_init(&it6505->mode_lock); 337662306a36Sopenharmony_ci mutex_init(&it6505->aux_lock); 337762306a36Sopenharmony_ci 337862306a36Sopenharmony_ci it6505->bridge.of_node = client->dev.of_node; 337962306a36Sopenharmony_ci it6505->connector_status = connector_status_disconnected; 338062306a36Sopenharmony_ci it6505->dev = &client->dev; 338162306a36Sopenharmony_ci i2c_set_clientdata(client, it6505); 338262306a36Sopenharmony_ci 338362306a36Sopenharmony_ci /* get extcon device from DTS */ 338462306a36Sopenharmony_ci extcon = extcon_get_edev_by_phandle(dev, 0); 338562306a36Sopenharmony_ci if (PTR_ERR(extcon) == -EPROBE_DEFER) 338662306a36Sopenharmony_ci return -EPROBE_DEFER; 338762306a36Sopenharmony_ci if (IS_ERR(extcon)) { 338862306a36Sopenharmony_ci dev_err(dev, "can not get extcon device!"); 338962306a36Sopenharmony_ci return PTR_ERR(extcon); 339062306a36Sopenharmony_ci } 339162306a36Sopenharmony_ci 339262306a36Sopenharmony_ci it6505->extcon = extcon; 339362306a36Sopenharmony_ci 339462306a36Sopenharmony_ci it6505->regmap = devm_regmap_init_i2c(client, &it6505_regmap_config); 339562306a36Sopenharmony_ci if (IS_ERR(it6505->regmap)) { 339662306a36Sopenharmony_ci dev_err(dev, "regmap i2c init failed"); 339762306a36Sopenharmony_ci err = PTR_ERR(it6505->regmap); 339862306a36Sopenharmony_ci return err; 339962306a36Sopenharmony_ci } 340062306a36Sopenharmony_ci 340162306a36Sopenharmony_ci err = it6505_init_pdata(it6505); 340262306a36Sopenharmony_ci if (err) { 340362306a36Sopenharmony_ci dev_err(dev, "Failed to initialize pdata: %d", err); 340462306a36Sopenharmony_ci return err; 340562306a36Sopenharmony_ci } 340662306a36Sopenharmony_ci 340762306a36Sopenharmony_ci it6505_parse_dt(it6505); 340862306a36Sopenharmony_ci 340962306a36Sopenharmony_ci intp_irq = client->irq; 341062306a36Sopenharmony_ci 341162306a36Sopenharmony_ci if (!intp_irq) { 341262306a36Sopenharmony_ci dev_err(dev, "Failed to get INTP IRQ"); 341362306a36Sopenharmony_ci err = -ENODEV; 341462306a36Sopenharmony_ci return err; 341562306a36Sopenharmony_ci } 341662306a36Sopenharmony_ci 341762306a36Sopenharmony_ci err = devm_request_threaded_irq(&client->dev, intp_irq, NULL, 341862306a36Sopenharmony_ci it6505_int_threaded_handler, 341962306a36Sopenharmony_ci IRQF_TRIGGER_LOW | IRQF_ONESHOT, 342062306a36Sopenharmony_ci "it6505-intp", it6505); 342162306a36Sopenharmony_ci if (err) { 342262306a36Sopenharmony_ci dev_err(dev, "Failed to request INTP threaded IRQ: %d", err); 342362306a36Sopenharmony_ci return err; 342462306a36Sopenharmony_ci } 342562306a36Sopenharmony_ci 342662306a36Sopenharmony_ci INIT_WORK(&it6505->link_works, it6505_link_training_work); 342762306a36Sopenharmony_ci INIT_WORK(&it6505->hdcp_wait_ksv_list, it6505_hdcp_wait_ksv_list); 342862306a36Sopenharmony_ci INIT_DELAYED_WORK(&it6505->hdcp_work, it6505_hdcp_work); 342962306a36Sopenharmony_ci init_completion(&it6505->extcon_completion); 343062306a36Sopenharmony_ci memset(it6505->dpcd, 0, sizeof(it6505->dpcd)); 343162306a36Sopenharmony_ci it6505->powered = false; 343262306a36Sopenharmony_ci it6505->enable_drv_hold = DEFAULT_DRV_HOLD; 343362306a36Sopenharmony_ci 343462306a36Sopenharmony_ci if (DEFAULT_PWR_ON) 343562306a36Sopenharmony_ci it6505_poweron(it6505); 343662306a36Sopenharmony_ci 343762306a36Sopenharmony_ci DRM_DEV_DEBUG_DRIVER(dev, "it6505 device name: %s", dev_name(dev)); 343862306a36Sopenharmony_ci debugfs_init(it6505); 343962306a36Sopenharmony_ci pm_runtime_enable(dev); 344062306a36Sopenharmony_ci 344162306a36Sopenharmony_ci it6505->aux.name = "DP-AUX"; 344262306a36Sopenharmony_ci it6505->aux.dev = dev; 344362306a36Sopenharmony_ci it6505->aux.transfer = it6505_aux_transfer; 344462306a36Sopenharmony_ci drm_dp_aux_init(&it6505->aux); 344562306a36Sopenharmony_ci 344662306a36Sopenharmony_ci it6505->bridge.funcs = &it6505_bridge_funcs; 344762306a36Sopenharmony_ci it6505->bridge.type = DRM_MODE_CONNECTOR_DisplayPort; 344862306a36Sopenharmony_ci it6505->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID | 344962306a36Sopenharmony_ci DRM_BRIDGE_OP_HPD; 345062306a36Sopenharmony_ci drm_bridge_add(&it6505->bridge); 345162306a36Sopenharmony_ci 345262306a36Sopenharmony_ci return 0; 345362306a36Sopenharmony_ci} 345462306a36Sopenharmony_ci 345562306a36Sopenharmony_cistatic void it6505_i2c_remove(struct i2c_client *client) 345662306a36Sopenharmony_ci{ 345762306a36Sopenharmony_ci struct it6505 *it6505 = i2c_get_clientdata(client); 345862306a36Sopenharmony_ci 345962306a36Sopenharmony_ci drm_bridge_remove(&it6505->bridge); 346062306a36Sopenharmony_ci drm_dp_aux_unregister(&it6505->aux); 346162306a36Sopenharmony_ci it6505_debugfs_remove(it6505); 346262306a36Sopenharmony_ci it6505_poweroff(it6505); 346362306a36Sopenharmony_ci it6505_remove_edid(it6505); 346462306a36Sopenharmony_ci} 346562306a36Sopenharmony_ci 346662306a36Sopenharmony_cistatic const struct i2c_device_id it6505_id[] = { 346762306a36Sopenharmony_ci { "it6505", 0 }, 346862306a36Sopenharmony_ci { } 346962306a36Sopenharmony_ci}; 347062306a36Sopenharmony_ci 347162306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, it6505_id); 347262306a36Sopenharmony_ci 347362306a36Sopenharmony_cistatic const struct of_device_id it6505_of_match[] = { 347462306a36Sopenharmony_ci { .compatible = "ite,it6505" }, 347562306a36Sopenharmony_ci { } 347662306a36Sopenharmony_ci}; 347762306a36Sopenharmony_ci 347862306a36Sopenharmony_cistatic struct i2c_driver it6505_i2c_driver = { 347962306a36Sopenharmony_ci .driver = { 348062306a36Sopenharmony_ci .name = "it6505", 348162306a36Sopenharmony_ci .of_match_table = it6505_of_match, 348262306a36Sopenharmony_ci .pm = &it6505_bridge_pm_ops, 348362306a36Sopenharmony_ci }, 348462306a36Sopenharmony_ci .probe = it6505_i2c_probe, 348562306a36Sopenharmony_ci .remove = it6505_i2c_remove, 348662306a36Sopenharmony_ci .shutdown = it6505_shutdown, 348762306a36Sopenharmony_ci .id_table = it6505_id, 348862306a36Sopenharmony_ci}; 348962306a36Sopenharmony_ci 349062306a36Sopenharmony_cimodule_i2c_driver(it6505_i2c_driver); 349162306a36Sopenharmony_ci 349262306a36Sopenharmony_ciMODULE_AUTHOR("Allen Chen <allen.chen@ite.com.tw>"); 349362306a36Sopenharmony_ciMODULE_DESCRIPTION("IT6505 DisplayPort Transmitter driver"); 349462306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 3495