1c943b494SChandan Uddaraju // SPDX-License-Identifier: GPL-2.0-only 2c943b494SChandan Uddaraju /* 3c943b494SChandan Uddaraju * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. 4c943b494SChandan Uddaraju */ 5c943b494SChandan Uddaraju 6c943b494SChandan Uddaraju #define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__ 7c943b494SChandan Uddaraju 8c943b494SChandan Uddaraju #include <linux/delay.h> 9c943b494SChandan Uddaraju #include <linux/iopoll.h> 10937f941cSStephen Boyd #include <linux/phy/phy.h> 11937f941cSStephen Boyd #include <linux/phy/phy-dp.h> 12c943b494SChandan Uddaraju #include <linux/rational.h> 135b529e8dSThomas Zimmermann #include <drm/dp/drm_dp_helper.h> 14937f941cSStephen Boyd #include <drm/drm_print.h> 15c943b494SChandan Uddaraju 16c943b494SChandan Uddaraju #include "dp_catalog.h" 17c943b494SChandan Uddaraju #include "dp_reg.h" 18c943b494SChandan Uddaraju 19c943b494SChandan Uddaraju #define POLLING_SLEEP_US 1000 20c943b494SChandan Uddaraju #define POLLING_TIMEOUT_US 10000 21c943b494SChandan Uddaraju 22c943b494SChandan Uddaraju #define SCRAMBLER_RESET_COUNT_VALUE 0xFC 23c943b494SChandan Uddaraju 24c943b494SChandan Uddaraju #define DP_INTERRUPT_STATUS_ACK_SHIFT 1 25c943b494SChandan Uddaraju #define DP_INTERRUPT_STATUS_MASK_SHIFT 2 26c943b494SChandan Uddaraju 27757a2f36SKuogee Hsieh #define DP_INTF_CONFIG_DATABUS_WIDEN BIT(4) 28757a2f36SKuogee Hsieh 29c943b494SChandan Uddaraju #define DP_INTERRUPT_STATUS1 \ 30c943b494SChandan Uddaraju (DP_INTR_AUX_I2C_DONE| \ 31c943b494SChandan Uddaraju DP_INTR_WRONG_ADDR | DP_INTR_TIMEOUT | \ 32c943b494SChandan Uddaraju DP_INTR_NACK_DEFER | DP_INTR_WRONG_DATA_CNT | \ 33c943b494SChandan Uddaraju DP_INTR_I2C_NACK | DP_INTR_I2C_DEFER | \ 34c943b494SChandan Uddaraju DP_INTR_PLL_UNLOCKED | DP_INTR_AUX_ERROR) 35c943b494SChandan Uddaraju 36c943b494SChandan Uddaraju #define DP_INTERRUPT_STATUS1_ACK \ 37c943b494SChandan Uddaraju (DP_INTERRUPT_STATUS1 << DP_INTERRUPT_STATUS_ACK_SHIFT) 38c943b494SChandan Uddaraju #define DP_INTERRUPT_STATUS1_MASK \ 39c943b494SChandan Uddaraju (DP_INTERRUPT_STATUS1 << DP_INTERRUPT_STATUS_MASK_SHIFT) 40c943b494SChandan Uddaraju 41c943b494SChandan Uddaraju #define DP_INTERRUPT_STATUS2 \ 42c943b494SChandan Uddaraju (DP_INTR_READY_FOR_VIDEO | DP_INTR_IDLE_PATTERN_SENT | \ 43c943b494SChandan Uddaraju DP_INTR_FRAME_END | DP_INTR_CRC_UPDATED) 44c943b494SChandan Uddaraju 45c943b494SChandan Uddaraju #define DP_INTERRUPT_STATUS2_ACK \ 46c943b494SChandan Uddaraju (DP_INTERRUPT_STATUS2 << DP_INTERRUPT_STATUS_ACK_SHIFT) 47c943b494SChandan Uddaraju #define DP_INTERRUPT_STATUS2_MASK \ 48c943b494SChandan Uddaraju (DP_INTERRUPT_STATUS2 << DP_INTERRUPT_STATUS_MASK_SHIFT) 49c943b494SChandan Uddaraju 50c943b494SChandan Uddaraju struct dp_catalog_private { 51c943b494SChandan Uddaraju struct device *dev; 52*202aceacSKuogee Hsieh struct drm_device *drm_dev; 53c943b494SChandan Uddaraju struct dp_io *io; 54d13e36d7SAbhinav Kumar u32 (*audio_map)[DP_AUDIO_SDP_HEADER_MAX]; 55c943b494SChandan Uddaraju struct dp_catalog dp_catalog; 56c943b494SChandan Uddaraju u8 aux_lut_cfg_index[PHY_AUX_CFG_MAX]; 57c943b494SChandan Uddaraju }; 58c943b494SChandan Uddaraju 590f6090f3SAbhinav Kumar void dp_catalog_snapshot(struct dp_catalog *dp_catalog, struct msm_disp_state *disp_state) 600f6090f3SAbhinav Kumar { 610f6090f3SAbhinav Kumar struct dp_catalog_private *catalog = container_of(dp_catalog, 620f6090f3SAbhinav Kumar struct dp_catalog_private, dp_catalog); 63060c160fSBjorn Andersson struct dss_io_data *dss = &catalog->io->dp_controller; 640f6090f3SAbhinav Kumar 65060c160fSBjorn Andersson msm_disp_snapshot_add_block(disp_state, dss->ahb.len, dss->ahb.base, "dp_ahb"); 66060c160fSBjorn Andersson msm_disp_snapshot_add_block(disp_state, dss->aux.len, dss->aux.base, "dp_aux"); 67060c160fSBjorn Andersson msm_disp_snapshot_add_block(disp_state, dss->link.len, dss->link.base, "dp_link"); 68060c160fSBjorn Andersson msm_disp_snapshot_add_block(disp_state, dss->p0.len, dss->p0.base, "dp_p0"); 690f6090f3SAbhinav Kumar } 700f6090f3SAbhinav Kumar 71c943b494SChandan Uddaraju static inline u32 dp_read_aux(struct dp_catalog_private *catalog, u32 offset) 72c943b494SChandan Uddaraju { 73060c160fSBjorn Andersson return readl_relaxed(catalog->io->dp_controller.aux.base + offset); 74c943b494SChandan Uddaraju } 75c943b494SChandan Uddaraju 76c943b494SChandan Uddaraju static inline void dp_write_aux(struct dp_catalog_private *catalog, 77c943b494SChandan Uddaraju u32 offset, u32 data) 78c943b494SChandan Uddaraju { 79c943b494SChandan Uddaraju /* 80c943b494SChandan Uddaraju * To make sure aux reg writes happens before any other operation, 81c943b494SChandan Uddaraju * this function uses writel() instread of writel_relaxed() 82c943b494SChandan Uddaraju */ 83060c160fSBjorn Andersson writel(data, catalog->io->dp_controller.aux.base + offset); 84c943b494SChandan Uddaraju } 85c943b494SChandan Uddaraju 86757a2f36SKuogee Hsieh static inline u32 dp_read_ahb(const struct dp_catalog_private *catalog, u32 offset) 87c943b494SChandan Uddaraju { 88060c160fSBjorn Andersson return readl_relaxed(catalog->io->dp_controller.ahb.base + offset); 89c943b494SChandan Uddaraju } 90c943b494SChandan Uddaraju 91c943b494SChandan Uddaraju static inline void dp_write_ahb(struct dp_catalog_private *catalog, 92c943b494SChandan Uddaraju u32 offset, u32 data) 93c943b494SChandan Uddaraju { 94c943b494SChandan Uddaraju /* 95c943b494SChandan Uddaraju * To make sure phy reg writes happens before any other operation, 96c943b494SChandan Uddaraju * this function uses writel() instread of writel_relaxed() 97c943b494SChandan Uddaraju */ 98060c160fSBjorn Andersson writel(data, catalog->io->dp_controller.ahb.base + offset); 99c943b494SChandan Uddaraju } 100c943b494SChandan Uddaraju 101c943b494SChandan Uddaraju static inline void dp_write_p0(struct dp_catalog_private *catalog, 102c943b494SChandan Uddaraju u32 offset, u32 data) 103c943b494SChandan Uddaraju { 104c943b494SChandan Uddaraju /* 105c943b494SChandan Uddaraju * To make sure interface reg writes happens before any other operation, 106c943b494SChandan Uddaraju * this function uses writel() instread of writel_relaxed() 107c943b494SChandan Uddaraju */ 108060c160fSBjorn Andersson writel(data, catalog->io->dp_controller.p0.base + offset); 109c943b494SChandan Uddaraju } 110c943b494SChandan Uddaraju 111c943b494SChandan Uddaraju static inline u32 dp_read_p0(struct dp_catalog_private *catalog, 112c943b494SChandan Uddaraju u32 offset) 113c943b494SChandan Uddaraju { 114c943b494SChandan Uddaraju /* 115c943b494SChandan Uddaraju * To make sure interface reg writes happens before any other operation, 116c943b494SChandan Uddaraju * this function uses writel() instread of writel_relaxed() 117c943b494SChandan Uddaraju */ 118060c160fSBjorn Andersson return readl_relaxed(catalog->io->dp_controller.p0.base + offset); 119c943b494SChandan Uddaraju } 120c943b494SChandan Uddaraju 121c943b494SChandan Uddaraju static inline u32 dp_read_link(struct dp_catalog_private *catalog, u32 offset) 122c943b494SChandan Uddaraju { 123060c160fSBjorn Andersson return readl_relaxed(catalog->io->dp_controller.link.base + offset); 124c943b494SChandan Uddaraju } 125c943b494SChandan Uddaraju 126c943b494SChandan Uddaraju static inline void dp_write_link(struct dp_catalog_private *catalog, 127c943b494SChandan Uddaraju u32 offset, u32 data) 128c943b494SChandan Uddaraju { 129c943b494SChandan Uddaraju /* 130c943b494SChandan Uddaraju * To make sure link reg writes happens before any other operation, 131c943b494SChandan Uddaraju * this function uses writel() instread of writel_relaxed() 132c943b494SChandan Uddaraju */ 133060c160fSBjorn Andersson writel(data, catalog->io->dp_controller.link.base + offset); 134c943b494SChandan Uddaraju } 135c943b494SChandan Uddaraju 136c943b494SChandan Uddaraju /* aux related catalog functions */ 137c943b494SChandan Uddaraju u32 dp_catalog_aux_read_data(struct dp_catalog *dp_catalog) 138c943b494SChandan Uddaraju { 139c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 140c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 141c943b494SChandan Uddaraju 142c943b494SChandan Uddaraju return dp_read_aux(catalog, REG_DP_AUX_DATA); 143c943b494SChandan Uddaraju } 144c943b494SChandan Uddaraju 145c943b494SChandan Uddaraju int dp_catalog_aux_write_data(struct dp_catalog *dp_catalog) 146c943b494SChandan Uddaraju { 147c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 148c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 149c943b494SChandan Uddaraju 150c943b494SChandan Uddaraju dp_write_aux(catalog, REG_DP_AUX_DATA, dp_catalog->aux_data); 151c943b494SChandan Uddaraju return 0; 152c943b494SChandan Uddaraju } 153c943b494SChandan Uddaraju 154c943b494SChandan Uddaraju int dp_catalog_aux_write_trans(struct dp_catalog *dp_catalog) 155c943b494SChandan Uddaraju { 156c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 157c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 158c943b494SChandan Uddaraju 159c943b494SChandan Uddaraju dp_write_aux(catalog, REG_DP_AUX_TRANS_CTRL, dp_catalog->aux_data); 160c943b494SChandan Uddaraju return 0; 161c943b494SChandan Uddaraju } 162c943b494SChandan Uddaraju 163c943b494SChandan Uddaraju int dp_catalog_aux_clear_trans(struct dp_catalog *dp_catalog, bool read) 164c943b494SChandan Uddaraju { 165c943b494SChandan Uddaraju u32 data; 166c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 167c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 168c943b494SChandan Uddaraju 169c943b494SChandan Uddaraju if (read) { 170c943b494SChandan Uddaraju data = dp_read_aux(catalog, REG_DP_AUX_TRANS_CTRL); 171c943b494SChandan Uddaraju data &= ~DP_AUX_TRANS_CTRL_GO; 172c943b494SChandan Uddaraju dp_write_aux(catalog, REG_DP_AUX_TRANS_CTRL, data); 173c943b494SChandan Uddaraju } else { 174c943b494SChandan Uddaraju dp_write_aux(catalog, REG_DP_AUX_TRANS_CTRL, 0); 175c943b494SChandan Uddaraju } 176c943b494SChandan Uddaraju return 0; 177c943b494SChandan Uddaraju } 178c943b494SChandan Uddaraju 179c943b494SChandan Uddaraju int dp_catalog_aux_clear_hw_interrupts(struct dp_catalog *dp_catalog) 180c943b494SChandan Uddaraju { 181c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 182c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 183c943b494SChandan Uddaraju 184c943b494SChandan Uddaraju dp_read_aux(catalog, REG_DP_PHY_AUX_INTERRUPT_STATUS); 185c943b494SChandan Uddaraju dp_write_aux(catalog, REG_DP_PHY_AUX_INTERRUPT_CLEAR, 0x1f); 186c943b494SChandan Uddaraju dp_write_aux(catalog, REG_DP_PHY_AUX_INTERRUPT_CLEAR, 0x9f); 187c943b494SChandan Uddaraju dp_write_aux(catalog, REG_DP_PHY_AUX_INTERRUPT_CLEAR, 0); 188c943b494SChandan Uddaraju return 0; 189c943b494SChandan Uddaraju } 190c943b494SChandan Uddaraju 1919fc41843SKuogee Hsieh /** 1929fc41843SKuogee Hsieh * dp_catalog_aux_reset() - reset AUX controller 1939fc41843SKuogee Hsieh * 1942eb4bfc0SLee Jones * @dp_catalog: DP catalog structure 1959fc41843SKuogee Hsieh * 1969fc41843SKuogee Hsieh * return: void 1979fc41843SKuogee Hsieh * 1989fc41843SKuogee Hsieh * This function reset AUX controller 1999fc41843SKuogee Hsieh * 2009fc41843SKuogee Hsieh * NOTE: reset AUX controller will also clear any pending HPD related interrupts 2019fc41843SKuogee Hsieh * 2029fc41843SKuogee Hsieh */ 203c943b494SChandan Uddaraju void dp_catalog_aux_reset(struct dp_catalog *dp_catalog) 204c943b494SChandan Uddaraju { 205c943b494SChandan Uddaraju u32 aux_ctrl; 206c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 207c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 208c943b494SChandan Uddaraju 209c943b494SChandan Uddaraju aux_ctrl = dp_read_aux(catalog, REG_DP_AUX_CTRL); 210c943b494SChandan Uddaraju 211c943b494SChandan Uddaraju aux_ctrl |= DP_AUX_CTRL_RESET; 212c943b494SChandan Uddaraju dp_write_aux(catalog, REG_DP_AUX_CTRL, aux_ctrl); 213c943b494SChandan Uddaraju usleep_range(1000, 1100); /* h/w recommended delay */ 214c943b494SChandan Uddaraju 215c943b494SChandan Uddaraju aux_ctrl &= ~DP_AUX_CTRL_RESET; 216c943b494SChandan Uddaraju dp_write_aux(catalog, REG_DP_AUX_CTRL, aux_ctrl); 217c943b494SChandan Uddaraju } 218c943b494SChandan Uddaraju 219c943b494SChandan Uddaraju void dp_catalog_aux_enable(struct dp_catalog *dp_catalog, bool enable) 220c943b494SChandan Uddaraju { 221c943b494SChandan Uddaraju u32 aux_ctrl; 222c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 223c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 224c943b494SChandan Uddaraju 225c943b494SChandan Uddaraju aux_ctrl = dp_read_aux(catalog, REG_DP_AUX_CTRL); 226c943b494SChandan Uddaraju 227c943b494SChandan Uddaraju if (enable) { 228c943b494SChandan Uddaraju dp_write_aux(catalog, REG_DP_TIMEOUT_COUNT, 0xffff); 229c943b494SChandan Uddaraju dp_write_aux(catalog, REG_DP_AUX_LIMITS, 0xffff); 230c943b494SChandan Uddaraju aux_ctrl |= DP_AUX_CTRL_ENABLE; 231c943b494SChandan Uddaraju } else { 232c943b494SChandan Uddaraju aux_ctrl &= ~DP_AUX_CTRL_ENABLE; 233c943b494SChandan Uddaraju } 234c943b494SChandan Uddaraju 235c943b494SChandan Uddaraju dp_write_aux(catalog, REG_DP_AUX_CTRL, aux_ctrl); 236c943b494SChandan Uddaraju } 237c943b494SChandan Uddaraju 238937f941cSStephen Boyd void dp_catalog_aux_update_cfg(struct dp_catalog *dp_catalog) 239c943b494SChandan Uddaraju { 240c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 241c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 242937f941cSStephen Boyd struct dp_io *dp_io = catalog->io; 243937f941cSStephen Boyd struct phy *phy = dp_io->phy; 244c943b494SChandan Uddaraju 245937f941cSStephen Boyd phy_calibrate(phy); 246c943b494SChandan Uddaraju } 247c943b494SChandan Uddaraju 248c943b494SChandan Uddaraju static void dump_regs(void __iomem *base, int len) 249c943b494SChandan Uddaraju { 250c943b494SChandan Uddaraju int i; 251c943b494SChandan Uddaraju u32 x0, x4, x8, xc; 252c943b494SChandan Uddaraju u32 addr_off = 0; 253c943b494SChandan Uddaraju 254c943b494SChandan Uddaraju len = DIV_ROUND_UP(len, 16); 255c943b494SChandan Uddaraju for (i = 0; i < len; i++) { 256c943b494SChandan Uddaraju x0 = readl_relaxed(base + addr_off); 257c943b494SChandan Uddaraju x4 = readl_relaxed(base + addr_off + 0x04); 258c943b494SChandan Uddaraju x8 = readl_relaxed(base + addr_off + 0x08); 259c943b494SChandan Uddaraju xc = readl_relaxed(base + addr_off + 0x0c); 260c943b494SChandan Uddaraju 261c943b494SChandan Uddaraju pr_info("%08x: %08x %08x %08x %08x", addr_off, x0, x4, x8, xc); 262c943b494SChandan Uddaraju addr_off += 16; 263c943b494SChandan Uddaraju } 264c943b494SChandan Uddaraju } 265c943b494SChandan Uddaraju 266c943b494SChandan Uddaraju void dp_catalog_dump_regs(struct dp_catalog *dp_catalog) 267c943b494SChandan Uddaraju { 268c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 269c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 270060c160fSBjorn Andersson struct dss_io_data *io = &catalog->io->dp_controller; 271c943b494SChandan Uddaraju 272c943b494SChandan Uddaraju pr_info("AHB regs\n"); 273060c160fSBjorn Andersson dump_regs(io->ahb.base, io->ahb.len); 274c943b494SChandan Uddaraju 275c943b494SChandan Uddaraju pr_info("AUXCLK regs\n"); 276060c160fSBjorn Andersson dump_regs(io->aux.base, io->aux.len); 277c943b494SChandan Uddaraju 278c943b494SChandan Uddaraju pr_info("LCLK regs\n"); 279060c160fSBjorn Andersson dump_regs(io->link.base, io->link.len); 280c943b494SChandan Uddaraju 281c943b494SChandan Uddaraju pr_info("P0CLK regs\n"); 282060c160fSBjorn Andersson dump_regs(io->p0.base, io->p0.len); 283c943b494SChandan Uddaraju } 284c943b494SChandan Uddaraju 28524c7861bSStephen Boyd u32 dp_catalog_aux_get_irq(struct dp_catalog *dp_catalog) 286c943b494SChandan Uddaraju { 287c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 288c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 289c943b494SChandan Uddaraju u32 intr, intr_ack; 290c943b494SChandan Uddaraju 291c943b494SChandan Uddaraju intr = dp_read_ahb(catalog, REG_DP_INTR_STATUS); 292c943b494SChandan Uddaraju intr &= ~DP_INTERRUPT_STATUS1_MASK; 293c943b494SChandan Uddaraju intr_ack = (intr & DP_INTERRUPT_STATUS1) 294c943b494SChandan Uddaraju << DP_INTERRUPT_STATUS_ACK_SHIFT; 295c943b494SChandan Uddaraju dp_write_ahb(catalog, REG_DP_INTR_STATUS, intr_ack | 296c943b494SChandan Uddaraju DP_INTERRUPT_STATUS1_MASK); 297c943b494SChandan Uddaraju 298c943b494SChandan Uddaraju return intr; 299c943b494SChandan Uddaraju 300c943b494SChandan Uddaraju } 301c943b494SChandan Uddaraju 302c943b494SChandan Uddaraju /* controller related catalog functions */ 303c943b494SChandan Uddaraju void dp_catalog_ctrl_update_transfer_unit(struct dp_catalog *dp_catalog, 304c943b494SChandan Uddaraju u32 dp_tu, u32 valid_boundary, 305c943b494SChandan Uddaraju u32 valid_boundary2) 306c943b494SChandan Uddaraju { 307c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 308c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 309c943b494SChandan Uddaraju 310c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_VALID_BOUNDARY, valid_boundary); 311c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_TU, dp_tu); 312c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_VALID_BOUNDARY_2, valid_boundary2); 313c943b494SChandan Uddaraju } 314c943b494SChandan Uddaraju 315c943b494SChandan Uddaraju void dp_catalog_ctrl_state_ctrl(struct dp_catalog *dp_catalog, u32 state) 316c943b494SChandan Uddaraju { 317c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 318c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 319c943b494SChandan Uddaraju 320c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_STATE_CTRL, state); 321c943b494SChandan Uddaraju } 322c943b494SChandan Uddaraju 323c943b494SChandan Uddaraju void dp_catalog_ctrl_config_ctrl(struct dp_catalog *dp_catalog, u32 cfg) 324c943b494SChandan Uddaraju { 325c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 326c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 327c943b494SChandan Uddaraju 328*202aceacSKuogee Hsieh drm_dbg_dp(catalog->drm_dev, "DP_CONFIGURATION_CTRL=0x%x\n", cfg); 329c943b494SChandan Uddaraju 330c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_CONFIGURATION_CTRL, cfg); 331c943b494SChandan Uddaraju } 332c943b494SChandan Uddaraju 333c943b494SChandan Uddaraju void dp_catalog_ctrl_lane_mapping(struct dp_catalog *dp_catalog) 334c943b494SChandan Uddaraju { 335c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 336c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 337c943b494SChandan Uddaraju u32 ln_0 = 0, ln_1 = 1, ln_2 = 2, ln_3 = 3; /* One-to-One mapping */ 338c943b494SChandan Uddaraju u32 ln_mapping; 339c943b494SChandan Uddaraju 340c943b494SChandan Uddaraju ln_mapping = ln_0 << LANE0_MAPPING_SHIFT; 341c943b494SChandan Uddaraju ln_mapping |= ln_1 << LANE1_MAPPING_SHIFT; 342c943b494SChandan Uddaraju ln_mapping |= ln_2 << LANE2_MAPPING_SHIFT; 343c943b494SChandan Uddaraju ln_mapping |= ln_3 << LANE3_MAPPING_SHIFT; 344c943b494SChandan Uddaraju 345c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_LOGICAL2PHYSICAL_LANE_MAPPING, 346c943b494SChandan Uddaraju ln_mapping); 347c943b494SChandan Uddaraju } 348c943b494SChandan Uddaraju 349c943b494SChandan Uddaraju void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog *dp_catalog, 350c943b494SChandan Uddaraju bool enable) 351c943b494SChandan Uddaraju { 352c943b494SChandan Uddaraju u32 mainlink_ctrl; 353c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 354c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 355c943b494SChandan Uddaraju 356*202aceacSKuogee Hsieh drm_dbg_dp(catalog->drm_dev, "enable=%d\n", enable); 357c943b494SChandan Uddaraju if (enable) { 358c943b494SChandan Uddaraju /* 359c943b494SChandan Uddaraju * To make sure link reg writes happens before other operation, 360c943b494SChandan Uddaraju * dp_write_link() function uses writel() 361c943b494SChandan Uddaraju */ 3628ede2eccSKuogee Hsieh mainlink_ctrl = dp_read_link(catalog, REG_DP_MAINLINK_CTRL); 3638ede2eccSKuogee Hsieh 3648ede2eccSKuogee Hsieh mainlink_ctrl &= ~(DP_MAINLINK_CTRL_RESET | 365c943b494SChandan Uddaraju DP_MAINLINK_CTRL_ENABLE); 3668ede2eccSKuogee Hsieh dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl); 3678ede2eccSKuogee Hsieh 3688ede2eccSKuogee Hsieh mainlink_ctrl |= DP_MAINLINK_CTRL_RESET; 3698ede2eccSKuogee Hsieh dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl); 3708ede2eccSKuogee Hsieh 3718ede2eccSKuogee Hsieh mainlink_ctrl &= ~DP_MAINLINK_CTRL_RESET; 3728ede2eccSKuogee Hsieh dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl); 3738ede2eccSKuogee Hsieh 3748ede2eccSKuogee Hsieh mainlink_ctrl |= (DP_MAINLINK_CTRL_ENABLE | 3758ede2eccSKuogee Hsieh DP_MAINLINK_FB_BOUNDARY_SEL); 3768ede2eccSKuogee Hsieh dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl); 377c943b494SChandan Uddaraju } else { 378c943b494SChandan Uddaraju mainlink_ctrl = dp_read_link(catalog, REG_DP_MAINLINK_CTRL); 379c943b494SChandan Uddaraju mainlink_ctrl &= ~DP_MAINLINK_CTRL_ENABLE; 380c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl); 381c943b494SChandan Uddaraju } 382c943b494SChandan Uddaraju } 383c943b494SChandan Uddaraju 384c943b494SChandan Uddaraju void dp_catalog_ctrl_config_misc(struct dp_catalog *dp_catalog, 385c943b494SChandan Uddaraju u32 colorimetry_cfg, 386c943b494SChandan Uddaraju u32 test_bits_depth) 387c943b494SChandan Uddaraju { 388c943b494SChandan Uddaraju u32 misc_val; 389c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 390c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 391c943b494SChandan Uddaraju 392c943b494SChandan Uddaraju misc_val = dp_read_link(catalog, REG_DP_MISC1_MISC0); 393c943b494SChandan Uddaraju 394c943b494SChandan Uddaraju /* clear bpp bits */ 395c943b494SChandan Uddaraju misc_val &= ~(0x07 << DP_MISC0_TEST_BITS_DEPTH_SHIFT); 396c943b494SChandan Uddaraju misc_val |= colorimetry_cfg << DP_MISC0_COLORIMETRY_CFG_SHIFT; 397c943b494SChandan Uddaraju misc_val |= test_bits_depth << DP_MISC0_TEST_BITS_DEPTH_SHIFT; 398c943b494SChandan Uddaraju /* Configure clock to synchronous mode */ 399c943b494SChandan Uddaraju misc_val |= DP_MISC0_SYNCHRONOUS_CLK; 400c943b494SChandan Uddaraju 401*202aceacSKuogee Hsieh drm_dbg_dp(catalog->drm_dev, "misc settings = 0x%x\n", misc_val); 402c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_MISC1_MISC0, misc_val); 403c943b494SChandan Uddaraju } 404c943b494SChandan Uddaraju 405c943b494SChandan Uddaraju void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog, 406c943b494SChandan Uddaraju u32 rate, u32 stream_rate_khz, 407c943b494SChandan Uddaraju bool fixed_nvid) 408c943b494SChandan Uddaraju { 409c943b494SChandan Uddaraju u32 pixel_m, pixel_n; 410937f941cSStephen Boyd u32 mvid, nvid, pixel_div = 0, dispcc_input_rate; 411c943b494SChandan Uddaraju u32 const nvid_fixed = DP_LINK_CONSTANT_N_VALUE; 412c943b494SChandan Uddaraju u32 const link_rate_hbr2 = 540000; 413c943b494SChandan Uddaraju u32 const link_rate_hbr3 = 810000; 414c943b494SChandan Uddaraju unsigned long den, num; 415c943b494SChandan Uddaraju 416c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 417c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 418c943b494SChandan Uddaraju 419937f941cSStephen Boyd if (rate == link_rate_hbr3) 420c943b494SChandan Uddaraju pixel_div = 6; 421937f941cSStephen Boyd else if (rate == 1620000 || rate == 270000) 422c943b494SChandan Uddaraju pixel_div = 2; 423937f941cSStephen Boyd else if (rate == link_rate_hbr2) 424c943b494SChandan Uddaraju pixel_div = 4; 425c943b494SChandan Uddaraju else 426c943b494SChandan Uddaraju DRM_ERROR("Invalid pixel mux divider\n"); 427c943b494SChandan Uddaraju 428c943b494SChandan Uddaraju dispcc_input_rate = (rate * 10) / pixel_div; 429c943b494SChandan Uddaraju 430c943b494SChandan Uddaraju rational_best_approximation(dispcc_input_rate, stream_rate_khz, 431c943b494SChandan Uddaraju (unsigned long)(1 << 16) - 1, 432c943b494SChandan Uddaraju (unsigned long)(1 << 16) - 1, &den, &num); 433c943b494SChandan Uddaraju 434c943b494SChandan Uddaraju den = ~(den - num); 435c943b494SChandan Uddaraju den = den & 0xFFFF; 436c943b494SChandan Uddaraju pixel_m = num; 437c943b494SChandan Uddaraju pixel_n = den; 438c943b494SChandan Uddaraju 439c943b494SChandan Uddaraju mvid = (pixel_m & 0xFFFF) * 5; 440c943b494SChandan Uddaraju nvid = (0xFFFF & (~pixel_n)) + (pixel_m & 0xFFFF); 441c943b494SChandan Uddaraju 442c943b494SChandan Uddaraju if (nvid < nvid_fixed) { 443c943b494SChandan Uddaraju u32 temp; 444c943b494SChandan Uddaraju 445c943b494SChandan Uddaraju temp = (nvid_fixed / nvid) * nvid; 446c943b494SChandan Uddaraju mvid = (nvid_fixed / nvid) * mvid; 447c943b494SChandan Uddaraju nvid = temp; 448c943b494SChandan Uddaraju } 449c943b494SChandan Uddaraju 450c943b494SChandan Uddaraju if (link_rate_hbr2 == rate) 451c943b494SChandan Uddaraju nvid *= 2; 452c943b494SChandan Uddaraju 453c943b494SChandan Uddaraju if (link_rate_hbr3 == rate) 454c943b494SChandan Uddaraju nvid *= 3; 455c943b494SChandan Uddaraju 456*202aceacSKuogee Hsieh drm_dbg_dp(catalog->drm_dev, "mvid=0x%x, nvid=0x%x\n", mvid, nvid); 457c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_SOFTWARE_MVID, mvid); 458c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_SOFTWARE_NVID, nvid); 459c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_DSC_DTO, 0x0); 460c943b494SChandan Uddaraju } 461c943b494SChandan Uddaraju 46295665325SKuogee Hsieh int dp_catalog_ctrl_set_pattern_state_bit(struct dp_catalog *dp_catalog, 46395665325SKuogee Hsieh u32 state_bit) 464c943b494SChandan Uddaraju { 465c943b494SChandan Uddaraju int bit, ret; 466c943b494SChandan Uddaraju u32 data; 467c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 468c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 469c943b494SChandan Uddaraju 47095665325SKuogee Hsieh bit = BIT(state_bit - 1); 471*202aceacSKuogee Hsieh drm_dbg_dp(catalog->drm_dev, "hw: bit=%d train=%d\n", bit, state_bit); 4728ede2eccSKuogee Hsieh dp_catalog_ctrl_state_ctrl(dp_catalog, bit); 473c943b494SChandan Uddaraju 47495665325SKuogee Hsieh bit = BIT(state_bit - 1) << DP_MAINLINK_READY_LINK_TRAINING_SHIFT; 475c943b494SChandan Uddaraju 476c943b494SChandan Uddaraju /* Poll for mainlink ready status */ 477060c160fSBjorn Andersson ret = readx_poll_timeout(readl, catalog->io->dp_controller.link.base + 478c943b494SChandan Uddaraju REG_DP_MAINLINK_READY, 479c943b494SChandan Uddaraju data, data & bit, 480c943b494SChandan Uddaraju POLLING_SLEEP_US, POLLING_TIMEOUT_US); 481c943b494SChandan Uddaraju if (ret < 0) { 48295665325SKuogee Hsieh DRM_ERROR("set state_bit for link_train=%d failed\n", state_bit); 483c943b494SChandan Uddaraju return ret; 484c943b494SChandan Uddaraju } 485c943b494SChandan Uddaraju return 0; 486c943b494SChandan Uddaraju } 487c943b494SChandan Uddaraju 4889fc41843SKuogee Hsieh /** 489757a2f36SKuogee Hsieh * dp_catalog_hw_revision() - retrieve DP hw revision 490757a2f36SKuogee Hsieh * 491757a2f36SKuogee Hsieh * @dp_catalog: DP catalog structure 492757a2f36SKuogee Hsieh * 493757a2f36SKuogee Hsieh * Return: DP controller hw revision 494757a2f36SKuogee Hsieh * 495757a2f36SKuogee Hsieh */ 496757a2f36SKuogee Hsieh u32 dp_catalog_hw_revision(const struct dp_catalog *dp_catalog) 497757a2f36SKuogee Hsieh { 498757a2f36SKuogee Hsieh const struct dp_catalog_private *catalog = container_of(dp_catalog, 499757a2f36SKuogee Hsieh struct dp_catalog_private, dp_catalog); 500757a2f36SKuogee Hsieh 501757a2f36SKuogee Hsieh return dp_read_ahb(catalog, REG_DP_HW_VERSION); 502757a2f36SKuogee Hsieh } 503757a2f36SKuogee Hsieh 504757a2f36SKuogee Hsieh /** 5059fc41843SKuogee Hsieh * dp_catalog_ctrl_reset() - reset DP controller 5069fc41843SKuogee Hsieh * 5079fc41843SKuogee Hsieh * @dp_catalog: DP catalog structure 5089fc41843SKuogee Hsieh * 5099fc41843SKuogee Hsieh * return: void 5109fc41843SKuogee Hsieh * 5119fc41843SKuogee Hsieh * This function reset the DP controller 5129fc41843SKuogee Hsieh * 5139fc41843SKuogee Hsieh * NOTE: reset DP controller will also clear any pending HPD related interrupts 5149fc41843SKuogee Hsieh * 5159fc41843SKuogee Hsieh */ 516c943b494SChandan Uddaraju void dp_catalog_ctrl_reset(struct dp_catalog *dp_catalog) 517c943b494SChandan Uddaraju { 518c943b494SChandan Uddaraju u32 sw_reset; 519c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 520c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 521c943b494SChandan Uddaraju 522c943b494SChandan Uddaraju sw_reset = dp_read_ahb(catalog, REG_DP_SW_RESET); 523c943b494SChandan Uddaraju 524c943b494SChandan Uddaraju sw_reset |= DP_SW_RESET; 525c943b494SChandan Uddaraju dp_write_ahb(catalog, REG_DP_SW_RESET, sw_reset); 526c943b494SChandan Uddaraju usleep_range(1000, 1100); /* h/w recommended delay */ 527c943b494SChandan Uddaraju 528c943b494SChandan Uddaraju sw_reset &= ~DP_SW_RESET; 529c943b494SChandan Uddaraju dp_write_ahb(catalog, REG_DP_SW_RESET, sw_reset); 530c943b494SChandan Uddaraju } 531c943b494SChandan Uddaraju 532c943b494SChandan Uddaraju bool dp_catalog_ctrl_mainlink_ready(struct dp_catalog *dp_catalog) 533c943b494SChandan Uddaraju { 534c943b494SChandan Uddaraju u32 data; 535c943b494SChandan Uddaraju int ret; 536c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 537c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 538c943b494SChandan Uddaraju 539c943b494SChandan Uddaraju /* Poll for mainlink ready status */ 540060c160fSBjorn Andersson ret = readl_poll_timeout(catalog->io->dp_controller.link.base + 541c943b494SChandan Uddaraju REG_DP_MAINLINK_READY, 542c943b494SChandan Uddaraju data, data & DP_MAINLINK_READY_FOR_VIDEO, 543c943b494SChandan Uddaraju POLLING_SLEEP_US, POLLING_TIMEOUT_US); 544c943b494SChandan Uddaraju if (ret < 0) { 545c943b494SChandan Uddaraju DRM_ERROR("mainlink not ready\n"); 546c943b494SChandan Uddaraju return false; 547c943b494SChandan Uddaraju } 548c943b494SChandan Uddaraju 549c943b494SChandan Uddaraju return true; 550c943b494SChandan Uddaraju } 551c943b494SChandan Uddaraju 552c943b494SChandan Uddaraju void dp_catalog_ctrl_enable_irq(struct dp_catalog *dp_catalog, 553c943b494SChandan Uddaraju bool enable) 554c943b494SChandan Uddaraju { 555c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 556c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 557c943b494SChandan Uddaraju 558c943b494SChandan Uddaraju if (enable) { 559c943b494SChandan Uddaraju dp_write_ahb(catalog, REG_DP_INTR_STATUS, 560c943b494SChandan Uddaraju DP_INTERRUPT_STATUS1_MASK); 561c943b494SChandan Uddaraju dp_write_ahb(catalog, REG_DP_INTR_STATUS2, 562c943b494SChandan Uddaraju DP_INTERRUPT_STATUS2_MASK); 563c943b494SChandan Uddaraju } else { 564c943b494SChandan Uddaraju dp_write_ahb(catalog, REG_DP_INTR_STATUS, 0x00); 565c943b494SChandan Uddaraju dp_write_ahb(catalog, REG_DP_INTR_STATUS2, 0x00); 566c943b494SChandan Uddaraju } 567c943b494SChandan Uddaraju } 568c943b494SChandan Uddaraju 569220b856aSTanmay Shah void dp_catalog_hpd_config_intr(struct dp_catalog *dp_catalog, 570220b856aSTanmay Shah u32 intr_mask, bool en) 571c943b494SChandan Uddaraju { 572c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 573c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 574c943b494SChandan Uddaraju 575220b856aSTanmay Shah u32 config = dp_read_aux(catalog, REG_DP_DP_HPD_INT_MASK); 576220b856aSTanmay Shah 577220b856aSTanmay Shah config = (en ? config | intr_mask : config & ~intr_mask); 578220b856aSTanmay Shah 579*202aceacSKuogee Hsieh drm_dbg_dp(catalog->drm_dev, "intr_mask=%#x config=%#x\n", 580*202aceacSKuogee Hsieh intr_mask, config); 581220b856aSTanmay Shah dp_write_aux(catalog, REG_DP_DP_HPD_INT_MASK, 582220b856aSTanmay Shah config & DP_DP_HPD_INT_MASK); 583220b856aSTanmay Shah } 584220b856aSTanmay Shah 585220b856aSTanmay Shah void dp_catalog_ctrl_hpd_config(struct dp_catalog *dp_catalog) 586220b856aSTanmay Shah { 587220b856aSTanmay Shah struct dp_catalog_private *catalog = container_of(dp_catalog, 588220b856aSTanmay Shah struct dp_catalog_private, dp_catalog); 589220b856aSTanmay Shah 590c943b494SChandan Uddaraju u32 reftimer = dp_read_aux(catalog, REG_DP_DP_HPD_REFTIMER); 591c943b494SChandan Uddaraju 592f21c8a27SKuogee Hsieh /* enable HPD plug and unplug interrupts */ 593220b856aSTanmay Shah dp_catalog_hpd_config_intr(dp_catalog, 594f21c8a27SKuogee Hsieh DP_DP_HPD_PLUG_INT_MASK | DP_DP_HPD_UNPLUG_INT_MASK, true); 595c943b494SChandan Uddaraju 596220b856aSTanmay Shah /* Configure REFTIMER and enable it */ 597220b856aSTanmay Shah reftimer |= DP_DP_HPD_REFTIMER_ENABLE; 598c943b494SChandan Uddaraju dp_write_aux(catalog, REG_DP_DP_HPD_REFTIMER, reftimer); 599220b856aSTanmay Shah 600c943b494SChandan Uddaraju /* Enable HPD */ 601220b856aSTanmay Shah dp_write_aux(catalog, REG_DP_DP_HPD_CTRL, DP_DP_HPD_CTRL_HPD_EN); 602c943b494SChandan Uddaraju } 603220b856aSTanmay Shah 604231a04fcSKuogee Hsieh u32 dp_catalog_link_is_connected(struct dp_catalog *dp_catalog) 60519e52bcbSKuogee Hsieh { 60619e52bcbSKuogee Hsieh struct dp_catalog_private *catalog = container_of(dp_catalog, 60719e52bcbSKuogee Hsieh struct dp_catalog_private, dp_catalog); 60819e52bcbSKuogee Hsieh u32 status; 60919e52bcbSKuogee Hsieh 61019e52bcbSKuogee Hsieh status = dp_read_aux(catalog, REG_DP_DP_HPD_INT_STATUS); 611*202aceacSKuogee Hsieh drm_dbg_dp(catalog->drm_dev, "aux status: %#x\n", status); 61219e52bcbSKuogee Hsieh status >>= DP_DP_HPD_STATE_STATUS_BITS_SHIFT; 61319e52bcbSKuogee Hsieh status &= DP_DP_HPD_STATE_STATUS_BITS_MASK; 61419e52bcbSKuogee Hsieh 61519e52bcbSKuogee Hsieh return status; 61619e52bcbSKuogee Hsieh } 61719e52bcbSKuogee Hsieh 618220b856aSTanmay Shah u32 dp_catalog_hpd_get_intr_status(struct dp_catalog *dp_catalog) 619220b856aSTanmay Shah { 620220b856aSTanmay Shah struct dp_catalog_private *catalog = container_of(dp_catalog, 621220b856aSTanmay Shah struct dp_catalog_private, dp_catalog); 622220b856aSTanmay Shah int isr = 0; 623220b856aSTanmay Shah 624220b856aSTanmay Shah isr = dp_read_aux(catalog, REG_DP_DP_HPD_INT_STATUS); 625220b856aSTanmay Shah dp_write_aux(catalog, REG_DP_DP_HPD_INT_ACK, 626220b856aSTanmay Shah (isr & DP_DP_HPD_INT_MASK)); 627220b856aSTanmay Shah 628220b856aSTanmay Shah return isr; 629c943b494SChandan Uddaraju } 630c943b494SChandan Uddaraju 631c943b494SChandan Uddaraju int dp_catalog_ctrl_get_interrupt(struct dp_catalog *dp_catalog) 632c943b494SChandan Uddaraju { 633c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 634c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 635c943b494SChandan Uddaraju u32 intr, intr_ack; 636c943b494SChandan Uddaraju 637c943b494SChandan Uddaraju intr = dp_read_ahb(catalog, REG_DP_INTR_STATUS2); 638c943b494SChandan Uddaraju intr &= ~DP_INTERRUPT_STATUS2_MASK; 639c943b494SChandan Uddaraju intr_ack = (intr & DP_INTERRUPT_STATUS2) 640c943b494SChandan Uddaraju << DP_INTERRUPT_STATUS_ACK_SHIFT; 641c943b494SChandan Uddaraju dp_write_ahb(catalog, REG_DP_INTR_STATUS2, 642c943b494SChandan Uddaraju intr_ack | DP_INTERRUPT_STATUS2_MASK); 643c943b494SChandan Uddaraju 644c943b494SChandan Uddaraju return intr; 645c943b494SChandan Uddaraju } 646c943b494SChandan Uddaraju 647c943b494SChandan Uddaraju void dp_catalog_ctrl_phy_reset(struct dp_catalog *dp_catalog) 648c943b494SChandan Uddaraju { 649c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 650c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 651c943b494SChandan Uddaraju 652c943b494SChandan Uddaraju dp_write_ahb(catalog, REG_DP_PHY_CTRL, 653937f941cSStephen Boyd DP_PHY_CTRL_SW_RESET | DP_PHY_CTRL_SW_RESET_PLL); 654c943b494SChandan Uddaraju usleep_range(1000, 1100); /* h/w recommended delay */ 655c943b494SChandan Uddaraju dp_write_ahb(catalog, REG_DP_PHY_CTRL, 0x0); 656c943b494SChandan Uddaraju } 657c943b494SChandan Uddaraju 658c943b494SChandan Uddaraju int dp_catalog_ctrl_update_vx_px(struct dp_catalog *dp_catalog, 659c943b494SChandan Uddaraju u8 v_level, u8 p_level) 660c943b494SChandan Uddaraju { 661c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 662c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 663937f941cSStephen Boyd struct dp_io *dp_io = catalog->io; 664937f941cSStephen Boyd struct phy *phy = dp_io->phy; 665937f941cSStephen Boyd struct phy_configure_opts_dp *opts_dp = &dp_io->phy_opts.dp; 666c943b494SChandan Uddaraju 667937f941cSStephen Boyd /* TODO: Update for all lanes instead of just first one */ 668937f941cSStephen Boyd opts_dp->voltage[0] = v_level; 669937f941cSStephen Boyd opts_dp->pre[0] = p_level; 670937f941cSStephen Boyd opts_dp->set_voltages = 1; 671937f941cSStephen Boyd phy_configure(phy, &dp_io->phy_opts); 672937f941cSStephen Boyd opts_dp->set_voltages = 0; 673c943b494SChandan Uddaraju 674c943b494SChandan Uddaraju return 0; 675c943b494SChandan Uddaraju } 676c943b494SChandan Uddaraju 677c943b494SChandan Uddaraju void dp_catalog_ctrl_send_phy_pattern(struct dp_catalog *dp_catalog, 678c943b494SChandan Uddaraju u32 pattern) 679c943b494SChandan Uddaraju { 680c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 681c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 682c943b494SChandan Uddaraju u32 value = 0x0; 683c943b494SChandan Uddaraju 684c943b494SChandan Uddaraju /* Make sure to clear the current pattern before starting a new one */ 685c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_STATE_CTRL, 0x0); 686c943b494SChandan Uddaraju 687*202aceacSKuogee Hsieh drm_dbg_dp(catalog->drm_dev, "pattern: %#x\n", pattern); 688c943b494SChandan Uddaraju switch (pattern) { 6898ede2eccSKuogee Hsieh case DP_PHY_TEST_PATTERN_D10_2: 690c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_STATE_CTRL, 691c943b494SChandan Uddaraju DP_STATE_CTRL_LINK_TRAINING_PATTERN1); 6928ede2eccSKuogee Hsieh break; 6938ede2eccSKuogee Hsieh case DP_PHY_TEST_PATTERN_ERROR_COUNT: 6948ede2eccSKuogee Hsieh value &= ~(1 << 16); 6958ede2eccSKuogee Hsieh dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, 6968ede2eccSKuogee Hsieh value); 6978ede2eccSKuogee Hsieh value |= SCRAMBLER_RESET_COUNT_VALUE; 6988ede2eccSKuogee Hsieh dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, 6998ede2eccSKuogee Hsieh value); 7008ede2eccSKuogee Hsieh dp_write_link(catalog, REG_DP_MAINLINK_LEVELS, 7018ede2eccSKuogee Hsieh DP_MAINLINK_SAFE_TO_EXIT_LEVEL_2); 7028ede2eccSKuogee Hsieh dp_write_link(catalog, REG_DP_STATE_CTRL, 7038ede2eccSKuogee Hsieh DP_STATE_CTRL_LINK_SYMBOL_ERR_MEASURE); 7048ede2eccSKuogee Hsieh break; 7058ede2eccSKuogee Hsieh case DP_PHY_TEST_PATTERN_PRBS7: 706c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_STATE_CTRL, 707c943b494SChandan Uddaraju DP_STATE_CTRL_LINK_PRBS7); 7088ede2eccSKuogee Hsieh break; 7098ede2eccSKuogee Hsieh case DP_PHY_TEST_PATTERN_80BIT_CUSTOM: 710c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_STATE_CTRL, 711c943b494SChandan Uddaraju DP_STATE_CTRL_LINK_TEST_CUSTOM_PATTERN); 712c943b494SChandan Uddaraju /* 00111110000011111000001111100000 */ 713c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG0, 714c943b494SChandan Uddaraju 0x3E0F83E0); 715c943b494SChandan Uddaraju /* 00001111100000111110000011111000 */ 716c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG1, 717c943b494SChandan Uddaraju 0x0F83E0F8); 718c943b494SChandan Uddaraju /* 1111100000111110 */ 719c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG2, 720c943b494SChandan Uddaraju 0x0000F83E); 7218ede2eccSKuogee Hsieh break; 7228ede2eccSKuogee Hsieh case DP_PHY_TEST_PATTERN_CP2520: 7238ede2eccSKuogee Hsieh value = dp_read_link(catalog, REG_DP_MAINLINK_CTRL); 7248ede2eccSKuogee Hsieh value &= ~DP_MAINLINK_CTRL_SW_BYPASS_SCRAMBLER; 7258ede2eccSKuogee Hsieh dp_write_link(catalog, REG_DP_MAINLINK_CTRL, value); 7268ede2eccSKuogee Hsieh 727c943b494SChandan Uddaraju value = DP_HBR2_ERM_PATTERN; 728c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, 729c943b494SChandan Uddaraju value); 730c943b494SChandan Uddaraju value |= SCRAMBLER_RESET_COUNT_VALUE; 731c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, 732c943b494SChandan Uddaraju value); 733c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_MAINLINK_LEVELS, 734c943b494SChandan Uddaraju DP_MAINLINK_SAFE_TO_EXIT_LEVEL_2); 735c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_STATE_CTRL, 736c943b494SChandan Uddaraju DP_STATE_CTRL_LINK_SYMBOL_ERR_MEASURE); 7378ede2eccSKuogee Hsieh value = dp_read_link(catalog, REG_DP_MAINLINK_CTRL); 7388ede2eccSKuogee Hsieh value |= DP_MAINLINK_CTRL_ENABLE; 7398ede2eccSKuogee Hsieh dp_write_link(catalog, REG_DP_MAINLINK_CTRL, value); 7408ede2eccSKuogee Hsieh break; 7418ede2eccSKuogee Hsieh case DP_PHY_TEST_PATTERN_SEL_MASK: 7428ede2eccSKuogee Hsieh dp_write_link(catalog, REG_DP_MAINLINK_CTRL, 7438ede2eccSKuogee Hsieh DP_MAINLINK_CTRL_ENABLE); 7448ede2eccSKuogee Hsieh dp_write_link(catalog, REG_DP_STATE_CTRL, 7458ede2eccSKuogee Hsieh DP_STATE_CTRL_LINK_TRAINING_PATTERN4); 7468ede2eccSKuogee Hsieh break; 747c943b494SChandan Uddaraju default: 748*202aceacSKuogee Hsieh drm_dbg_dp(catalog->drm_dev, 749*202aceacSKuogee Hsieh "No valid test pattern requested: %#x\n", pattern); 7508ede2eccSKuogee Hsieh break; 751c943b494SChandan Uddaraju } 752c943b494SChandan Uddaraju } 753c943b494SChandan Uddaraju 754c943b494SChandan Uddaraju u32 dp_catalog_ctrl_read_phy_pattern(struct dp_catalog *dp_catalog) 755c943b494SChandan Uddaraju { 756c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 757c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 758c943b494SChandan Uddaraju 759c943b494SChandan Uddaraju return dp_read_link(catalog, REG_DP_MAINLINK_READY); 760c943b494SChandan Uddaraju } 761c943b494SChandan Uddaraju 762c943b494SChandan Uddaraju /* panel related catalog functions */ 763c943b494SChandan Uddaraju int dp_catalog_panel_timing_cfg(struct dp_catalog *dp_catalog) 764c943b494SChandan Uddaraju { 765c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 766c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 767757a2f36SKuogee Hsieh u32 reg; 768c943b494SChandan Uddaraju 769c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_TOTAL_HOR_VER, 770c943b494SChandan Uddaraju dp_catalog->total); 771c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_START_HOR_VER_FROM_SYNC, 772c943b494SChandan Uddaraju dp_catalog->sync_start); 773c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_HSYNC_VSYNC_WIDTH_POLARITY, 774c943b494SChandan Uddaraju dp_catalog->width_blanking); 775c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_ACTIVE_HOR_VER, dp_catalog->dp_active); 776757a2f36SKuogee Hsieh 777757a2f36SKuogee Hsieh reg = dp_read_p0(catalog, MMSS_DP_INTF_CONFIG); 778757a2f36SKuogee Hsieh 779757a2f36SKuogee Hsieh if (dp_catalog->wide_bus_en) 780757a2f36SKuogee Hsieh reg |= DP_INTF_CONFIG_DATABUS_WIDEN; 781757a2f36SKuogee Hsieh else 782757a2f36SKuogee Hsieh reg &= ~DP_INTF_CONFIG_DATABUS_WIDEN; 783757a2f36SKuogee Hsieh 784757a2f36SKuogee Hsieh 785757a2f36SKuogee Hsieh DRM_DEBUG_DP("wide_bus_en=%d reg=%#x\n", dp_catalog->wide_bus_en, reg); 786757a2f36SKuogee Hsieh 787757a2f36SKuogee Hsieh dp_write_p0(catalog, MMSS_DP_INTF_CONFIG, reg); 788c943b494SChandan Uddaraju return 0; 789c943b494SChandan Uddaraju } 790c943b494SChandan Uddaraju 791c943b494SChandan Uddaraju void dp_catalog_panel_tpg_enable(struct dp_catalog *dp_catalog, 792c943b494SChandan Uddaraju struct drm_display_mode *drm_mode) 793c943b494SChandan Uddaraju { 794c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 795c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 796c943b494SChandan Uddaraju u32 hsync_period, vsync_period; 797c943b494SChandan Uddaraju u32 display_v_start, display_v_end; 798c943b494SChandan Uddaraju u32 hsync_start_x, hsync_end_x; 799c943b494SChandan Uddaraju u32 v_sync_width; 800c943b494SChandan Uddaraju u32 hsync_ctl; 801c943b494SChandan Uddaraju u32 display_hctl; 802c943b494SChandan Uddaraju 803c943b494SChandan Uddaraju /* TPG config parameters*/ 804c943b494SChandan Uddaraju hsync_period = drm_mode->htotal; 805c943b494SChandan Uddaraju vsync_period = drm_mode->vtotal; 806c943b494SChandan Uddaraju 807c943b494SChandan Uddaraju display_v_start = ((drm_mode->vtotal - drm_mode->vsync_start) * 808c943b494SChandan Uddaraju hsync_period); 809c943b494SChandan Uddaraju display_v_end = ((vsync_period - (drm_mode->vsync_start - 810c943b494SChandan Uddaraju drm_mode->vdisplay)) 811c943b494SChandan Uddaraju * hsync_period) - 1; 812c943b494SChandan Uddaraju 813c943b494SChandan Uddaraju display_v_start += drm_mode->htotal - drm_mode->hsync_start; 814c943b494SChandan Uddaraju display_v_end -= (drm_mode->hsync_start - drm_mode->hdisplay); 815c943b494SChandan Uddaraju 816c943b494SChandan Uddaraju hsync_start_x = drm_mode->htotal - drm_mode->hsync_start; 817c943b494SChandan Uddaraju hsync_end_x = hsync_period - (drm_mode->hsync_start - 818c943b494SChandan Uddaraju drm_mode->hdisplay) - 1; 819c943b494SChandan Uddaraju 820c943b494SChandan Uddaraju v_sync_width = drm_mode->vsync_end - drm_mode->vsync_start; 821c943b494SChandan Uddaraju 822c943b494SChandan Uddaraju hsync_ctl = (hsync_period << 16) | 823c943b494SChandan Uddaraju (drm_mode->hsync_end - drm_mode->hsync_start); 824c943b494SChandan Uddaraju display_hctl = (hsync_end_x << 16) | hsync_start_x; 825c943b494SChandan Uddaraju 826c943b494SChandan Uddaraju 827c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_CONFIG, 0x0); 828c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_HSYNC_CTL, hsync_ctl); 829c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_VSYNC_PERIOD_F0, vsync_period * 830c943b494SChandan Uddaraju hsync_period); 831c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F0, v_sync_width * 832c943b494SChandan Uddaraju hsync_period); 833c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_VSYNC_PERIOD_F1, 0); 834c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F1, 0); 835c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_DISPLAY_HCTL, display_hctl); 836c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_HCTL, 0); 837c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_INTF_DISPLAY_V_START_F0, display_v_start); 838c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_DISPLAY_V_END_F0, display_v_end); 839c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_INTF_DISPLAY_V_START_F1, 0); 840c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_DISPLAY_V_END_F1, 0); 841c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_V_START_F0, 0); 842c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_V_END_F0, 0); 843c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_V_START_F1, 0); 844c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_V_END_F1, 0); 845c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_POLARITY_CTL, 0); 846c943b494SChandan Uddaraju 847c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_TPG_MAIN_CONTROL, 848c943b494SChandan Uddaraju DP_TPG_CHECKERED_RECT_PATTERN); 849c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_TPG_VIDEO_CONFIG, 850c943b494SChandan Uddaraju DP_TPG_VIDEO_CONFIG_BPP_8BIT | 851c943b494SChandan Uddaraju DP_TPG_VIDEO_CONFIG_RGB); 852c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_BIST_ENABLE, 853c943b494SChandan Uddaraju DP_BIST_ENABLE_DPBIST_EN); 854c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_TIMING_ENGINE_EN, 855c943b494SChandan Uddaraju DP_TIMING_ENGINE_EN_EN); 856*202aceacSKuogee Hsieh drm_dbg_dp(catalog->drm_dev, "%s: enabled tpg\n", __func__); 857c943b494SChandan Uddaraju } 858c943b494SChandan Uddaraju 859c943b494SChandan Uddaraju void dp_catalog_panel_tpg_disable(struct dp_catalog *dp_catalog) 860c943b494SChandan Uddaraju { 861c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 862c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 863c943b494SChandan Uddaraju 864c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_TPG_MAIN_CONTROL, 0x0); 865c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_BIST_ENABLE, 0x0); 866c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_TIMING_ENGINE_EN, 0x0); 867c943b494SChandan Uddaraju } 868c943b494SChandan Uddaraju 869c943b494SChandan Uddaraju struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_io *io) 870c943b494SChandan Uddaraju { 871c943b494SChandan Uddaraju struct dp_catalog_private *catalog; 872c943b494SChandan Uddaraju 873c943b494SChandan Uddaraju if (!io) { 874c943b494SChandan Uddaraju DRM_ERROR("invalid input\n"); 875c943b494SChandan Uddaraju return ERR_PTR(-EINVAL); 876c943b494SChandan Uddaraju } 877c943b494SChandan Uddaraju 878c943b494SChandan Uddaraju catalog = devm_kzalloc(dev, sizeof(*catalog), GFP_KERNEL); 879c943b494SChandan Uddaraju if (!catalog) 880c943b494SChandan Uddaraju return ERR_PTR(-ENOMEM); 881c943b494SChandan Uddaraju 882c943b494SChandan Uddaraju catalog->dev = dev; 883c943b494SChandan Uddaraju catalog->io = io; 884c943b494SChandan Uddaraju 885c943b494SChandan Uddaraju return &catalog->dp_catalog; 886c943b494SChandan Uddaraju } 887d13e36d7SAbhinav Kumar 888d13e36d7SAbhinav Kumar void dp_catalog_audio_get_header(struct dp_catalog *dp_catalog) 889d13e36d7SAbhinav Kumar { 890d13e36d7SAbhinav Kumar struct dp_catalog_private *catalog; 891d13e36d7SAbhinav Kumar u32 (*sdp_map)[DP_AUDIO_SDP_HEADER_MAX]; 892d13e36d7SAbhinav Kumar enum dp_catalog_audio_sdp_type sdp; 893d13e36d7SAbhinav Kumar enum dp_catalog_audio_header_type header; 894d13e36d7SAbhinav Kumar 895d13e36d7SAbhinav Kumar if (!dp_catalog) 896d13e36d7SAbhinav Kumar return; 897d13e36d7SAbhinav Kumar 898d13e36d7SAbhinav Kumar catalog = container_of(dp_catalog, 899d13e36d7SAbhinav Kumar struct dp_catalog_private, dp_catalog); 900d13e36d7SAbhinav Kumar 901d13e36d7SAbhinav Kumar sdp_map = catalog->audio_map; 902d13e36d7SAbhinav Kumar sdp = dp_catalog->sdp_type; 903d13e36d7SAbhinav Kumar header = dp_catalog->sdp_header; 904d13e36d7SAbhinav Kumar 905d13e36d7SAbhinav Kumar dp_catalog->audio_data = dp_read_link(catalog, 906d13e36d7SAbhinav Kumar sdp_map[sdp][header]); 907d13e36d7SAbhinav Kumar } 908d13e36d7SAbhinav Kumar 909d13e36d7SAbhinav Kumar void dp_catalog_audio_set_header(struct dp_catalog *dp_catalog) 910d13e36d7SAbhinav Kumar { 911d13e36d7SAbhinav Kumar struct dp_catalog_private *catalog; 912d13e36d7SAbhinav Kumar u32 (*sdp_map)[DP_AUDIO_SDP_HEADER_MAX]; 913d13e36d7SAbhinav Kumar enum dp_catalog_audio_sdp_type sdp; 914d13e36d7SAbhinav Kumar enum dp_catalog_audio_header_type header; 915d13e36d7SAbhinav Kumar u32 data; 916d13e36d7SAbhinav Kumar 917d13e36d7SAbhinav Kumar if (!dp_catalog) 918d13e36d7SAbhinav Kumar return; 919d13e36d7SAbhinav Kumar 920d13e36d7SAbhinav Kumar catalog = container_of(dp_catalog, 921d13e36d7SAbhinav Kumar struct dp_catalog_private, dp_catalog); 922d13e36d7SAbhinav Kumar 923d13e36d7SAbhinav Kumar sdp_map = catalog->audio_map; 924d13e36d7SAbhinav Kumar sdp = dp_catalog->sdp_type; 925d13e36d7SAbhinav Kumar header = dp_catalog->sdp_header; 926d13e36d7SAbhinav Kumar data = dp_catalog->audio_data; 927d13e36d7SAbhinav Kumar 928d13e36d7SAbhinav Kumar dp_write_link(catalog, sdp_map[sdp][header], data); 929d13e36d7SAbhinav Kumar } 930d13e36d7SAbhinav Kumar 931d13e36d7SAbhinav Kumar void dp_catalog_audio_config_acr(struct dp_catalog *dp_catalog) 932d13e36d7SAbhinav Kumar { 933d13e36d7SAbhinav Kumar struct dp_catalog_private *catalog; 934d13e36d7SAbhinav Kumar u32 acr_ctrl, select; 935d13e36d7SAbhinav Kumar 936d13e36d7SAbhinav Kumar if (!dp_catalog) 937d13e36d7SAbhinav Kumar return; 938d13e36d7SAbhinav Kumar 939d13e36d7SAbhinav Kumar catalog = container_of(dp_catalog, 940d13e36d7SAbhinav Kumar struct dp_catalog_private, dp_catalog); 941d13e36d7SAbhinav Kumar 942d13e36d7SAbhinav Kumar select = dp_catalog->audio_data; 943d13e36d7SAbhinav Kumar acr_ctrl = select << 4 | BIT(31) | BIT(8) | BIT(14); 944d13e36d7SAbhinav Kumar 945*202aceacSKuogee Hsieh drm_dbg_dp(catalog->drm_dev, "select: %#x, acr_ctrl: %#x\n", 946*202aceacSKuogee Hsieh select, acr_ctrl); 947d13e36d7SAbhinav Kumar 948d13e36d7SAbhinav Kumar dp_write_link(catalog, MMSS_DP_AUDIO_ACR_CTRL, acr_ctrl); 949d13e36d7SAbhinav Kumar } 950d13e36d7SAbhinav Kumar 951d13e36d7SAbhinav Kumar void dp_catalog_audio_enable(struct dp_catalog *dp_catalog) 952d13e36d7SAbhinav Kumar { 953d13e36d7SAbhinav Kumar struct dp_catalog_private *catalog; 954d13e36d7SAbhinav Kumar bool enable; 955d13e36d7SAbhinav Kumar u32 audio_ctrl; 956d13e36d7SAbhinav Kumar 957d13e36d7SAbhinav Kumar if (!dp_catalog) 958d13e36d7SAbhinav Kumar return; 959d13e36d7SAbhinav Kumar 960d13e36d7SAbhinav Kumar catalog = container_of(dp_catalog, 961d13e36d7SAbhinav Kumar struct dp_catalog_private, dp_catalog); 962d13e36d7SAbhinav Kumar 963d13e36d7SAbhinav Kumar enable = !!dp_catalog->audio_data; 964d13e36d7SAbhinav Kumar audio_ctrl = dp_read_link(catalog, MMSS_DP_AUDIO_CFG); 965d13e36d7SAbhinav Kumar 966d13e36d7SAbhinav Kumar if (enable) 967d13e36d7SAbhinav Kumar audio_ctrl |= BIT(0); 968d13e36d7SAbhinav Kumar else 969d13e36d7SAbhinav Kumar audio_ctrl &= ~BIT(0); 970d13e36d7SAbhinav Kumar 971*202aceacSKuogee Hsieh drm_dbg_dp(catalog->drm_dev, "dp_audio_cfg = 0x%x\n", audio_ctrl); 972d13e36d7SAbhinav Kumar 973d13e36d7SAbhinav Kumar dp_write_link(catalog, MMSS_DP_AUDIO_CFG, audio_ctrl); 974d13e36d7SAbhinav Kumar /* make sure audio engine is disabled */ 975d13e36d7SAbhinav Kumar wmb(); 976d13e36d7SAbhinav Kumar } 977d13e36d7SAbhinav Kumar 978d13e36d7SAbhinav Kumar void dp_catalog_audio_config_sdp(struct dp_catalog *dp_catalog) 979d13e36d7SAbhinav Kumar { 980d13e36d7SAbhinav Kumar struct dp_catalog_private *catalog; 981d13e36d7SAbhinav Kumar u32 sdp_cfg = 0; 982d13e36d7SAbhinav Kumar u32 sdp_cfg2 = 0; 983d13e36d7SAbhinav Kumar 984d13e36d7SAbhinav Kumar if (!dp_catalog) 985d13e36d7SAbhinav Kumar return; 986d13e36d7SAbhinav Kumar 987d13e36d7SAbhinav Kumar catalog = container_of(dp_catalog, 988d13e36d7SAbhinav Kumar struct dp_catalog_private, dp_catalog); 989d13e36d7SAbhinav Kumar 990d13e36d7SAbhinav Kumar sdp_cfg = dp_read_link(catalog, MMSS_DP_SDP_CFG); 991d13e36d7SAbhinav Kumar /* AUDIO_TIMESTAMP_SDP_EN */ 992d13e36d7SAbhinav Kumar sdp_cfg |= BIT(1); 993d13e36d7SAbhinav Kumar /* AUDIO_STREAM_SDP_EN */ 994d13e36d7SAbhinav Kumar sdp_cfg |= BIT(2); 995d13e36d7SAbhinav Kumar /* AUDIO_COPY_MANAGEMENT_SDP_EN */ 996d13e36d7SAbhinav Kumar sdp_cfg |= BIT(5); 997d13e36d7SAbhinav Kumar /* AUDIO_ISRC_SDP_EN */ 998d13e36d7SAbhinav Kumar sdp_cfg |= BIT(6); 999d13e36d7SAbhinav Kumar /* AUDIO_INFOFRAME_SDP_EN */ 1000d13e36d7SAbhinav Kumar sdp_cfg |= BIT(20); 1001d13e36d7SAbhinav Kumar 1002*202aceacSKuogee Hsieh drm_dbg_dp(catalog->drm_dev, "sdp_cfg = 0x%x\n", sdp_cfg); 1003d13e36d7SAbhinav Kumar 1004d13e36d7SAbhinav Kumar dp_write_link(catalog, MMSS_DP_SDP_CFG, sdp_cfg); 1005d13e36d7SAbhinav Kumar 1006d13e36d7SAbhinav Kumar sdp_cfg2 = dp_read_link(catalog, MMSS_DP_SDP_CFG2); 1007d13e36d7SAbhinav Kumar /* IFRM_REGSRC -> Do not use reg values */ 1008d13e36d7SAbhinav Kumar sdp_cfg2 &= ~BIT(0); 1009d13e36d7SAbhinav Kumar /* AUDIO_STREAM_HB3_REGSRC-> Do not use reg values */ 1010d13e36d7SAbhinav Kumar sdp_cfg2 &= ~BIT(1); 1011d13e36d7SAbhinav Kumar 1012*202aceacSKuogee Hsieh drm_dbg_dp(catalog->drm_dev, "sdp_cfg2 = 0x%x\n", sdp_cfg2); 1013d13e36d7SAbhinav Kumar 1014d13e36d7SAbhinav Kumar dp_write_link(catalog, MMSS_DP_SDP_CFG2, sdp_cfg2); 1015d13e36d7SAbhinav Kumar } 1016d13e36d7SAbhinav Kumar 1017d13e36d7SAbhinav Kumar void dp_catalog_audio_init(struct dp_catalog *dp_catalog) 1018d13e36d7SAbhinav Kumar { 1019d13e36d7SAbhinav Kumar struct dp_catalog_private *catalog; 1020d13e36d7SAbhinav Kumar 1021d13e36d7SAbhinav Kumar static u32 sdp_map[][DP_AUDIO_SDP_HEADER_MAX] = { 1022d13e36d7SAbhinav Kumar { 1023d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_STREAM_0, 1024d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_STREAM_1, 1025d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_STREAM_1, 1026d13e36d7SAbhinav Kumar }, 1027d13e36d7SAbhinav Kumar { 1028d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_TIMESTAMP_0, 1029d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_TIMESTAMP_1, 1030d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_TIMESTAMP_1, 1031d13e36d7SAbhinav Kumar }, 1032d13e36d7SAbhinav Kumar { 1033d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_INFOFRAME_0, 1034d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_INFOFRAME_1, 1035d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_INFOFRAME_1, 1036d13e36d7SAbhinav Kumar }, 1037d13e36d7SAbhinav Kumar { 1038d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_COPYMANAGEMENT_0, 1039d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_COPYMANAGEMENT_1, 1040d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_COPYMANAGEMENT_1, 1041d13e36d7SAbhinav Kumar }, 1042d13e36d7SAbhinav Kumar { 1043d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_ISRC_0, 1044d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_ISRC_1, 1045d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_ISRC_1, 1046d13e36d7SAbhinav Kumar }, 1047d13e36d7SAbhinav Kumar }; 1048d13e36d7SAbhinav Kumar 1049d13e36d7SAbhinav Kumar if (!dp_catalog) 1050d13e36d7SAbhinav Kumar return; 1051d13e36d7SAbhinav Kumar 1052d13e36d7SAbhinav Kumar catalog = container_of(dp_catalog, 1053d13e36d7SAbhinav Kumar struct dp_catalog_private, dp_catalog); 1054d13e36d7SAbhinav Kumar 1055d13e36d7SAbhinav Kumar catalog->audio_map = sdp_map; 1056d13e36d7SAbhinav Kumar } 1057d13e36d7SAbhinav Kumar 1058d13e36d7SAbhinav Kumar void dp_catalog_audio_sfe_level(struct dp_catalog *dp_catalog) 1059d13e36d7SAbhinav Kumar { 1060d13e36d7SAbhinav Kumar struct dp_catalog_private *catalog; 1061d13e36d7SAbhinav Kumar u32 mainlink_levels, safe_to_exit_level; 1062d13e36d7SAbhinav Kumar 1063d13e36d7SAbhinav Kumar if (!dp_catalog) 1064d13e36d7SAbhinav Kumar return; 1065d13e36d7SAbhinav Kumar 1066d13e36d7SAbhinav Kumar catalog = container_of(dp_catalog, 1067d13e36d7SAbhinav Kumar struct dp_catalog_private, dp_catalog); 1068d13e36d7SAbhinav Kumar 1069d13e36d7SAbhinav Kumar safe_to_exit_level = dp_catalog->audio_data; 1070d13e36d7SAbhinav Kumar mainlink_levels = dp_read_link(catalog, REG_DP_MAINLINK_LEVELS); 1071d13e36d7SAbhinav Kumar mainlink_levels &= 0xFE0; 1072d13e36d7SAbhinav Kumar mainlink_levels |= safe_to_exit_level; 1073d13e36d7SAbhinav Kumar 1074*202aceacSKuogee Hsieh drm_dbg_dp(catalog->drm_dev, 1075*202aceacSKuogee Hsieh "mainlink_level = 0x%x, safe_to_exit_level = 0x%x\n", 1076d13e36d7SAbhinav Kumar mainlink_levels, safe_to_exit_level); 1077d13e36d7SAbhinav Kumar 1078d13e36d7SAbhinav Kumar dp_write_link(catalog, REG_DP_MAINLINK_LEVELS, mainlink_levels); 1079d13e36d7SAbhinav Kumar } 1080