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> 13c943b494SChandan Uddaraju #include <drm/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 27c943b494SChandan Uddaraju #define MSM_DP_CONTROLLER_AHB_OFFSET 0x0000 28c943b494SChandan Uddaraju #define MSM_DP_CONTROLLER_AHB_SIZE 0x0200 29c943b494SChandan Uddaraju #define MSM_DP_CONTROLLER_AUX_OFFSET 0x0200 30c943b494SChandan Uddaraju #define MSM_DP_CONTROLLER_AUX_SIZE 0x0200 31c943b494SChandan Uddaraju #define MSM_DP_CONTROLLER_LINK_OFFSET 0x0400 32c943b494SChandan Uddaraju #define MSM_DP_CONTROLLER_LINK_SIZE 0x0C00 33c943b494SChandan Uddaraju #define MSM_DP_CONTROLLER_P0_OFFSET 0x1000 34c943b494SChandan Uddaraju #define MSM_DP_CONTROLLER_P0_SIZE 0x0400 35c943b494SChandan Uddaraju 36c943b494SChandan Uddaraju #define DP_INTERRUPT_STATUS1 \ 37c943b494SChandan Uddaraju (DP_INTR_AUX_I2C_DONE| \ 38c943b494SChandan Uddaraju DP_INTR_WRONG_ADDR | DP_INTR_TIMEOUT | \ 39c943b494SChandan Uddaraju DP_INTR_NACK_DEFER | DP_INTR_WRONG_DATA_CNT | \ 40c943b494SChandan Uddaraju DP_INTR_I2C_NACK | DP_INTR_I2C_DEFER | \ 41c943b494SChandan Uddaraju DP_INTR_PLL_UNLOCKED | DP_INTR_AUX_ERROR) 42c943b494SChandan Uddaraju 43c943b494SChandan Uddaraju #define DP_INTERRUPT_STATUS1_ACK \ 44c943b494SChandan Uddaraju (DP_INTERRUPT_STATUS1 << DP_INTERRUPT_STATUS_ACK_SHIFT) 45c943b494SChandan Uddaraju #define DP_INTERRUPT_STATUS1_MASK \ 46c943b494SChandan Uddaraju (DP_INTERRUPT_STATUS1 << DP_INTERRUPT_STATUS_MASK_SHIFT) 47c943b494SChandan Uddaraju 48c943b494SChandan Uddaraju #define DP_INTERRUPT_STATUS2 \ 49c943b494SChandan Uddaraju (DP_INTR_READY_FOR_VIDEO | DP_INTR_IDLE_PATTERN_SENT | \ 50c943b494SChandan Uddaraju DP_INTR_FRAME_END | DP_INTR_CRC_UPDATED) 51c943b494SChandan Uddaraju 52c943b494SChandan Uddaraju #define DP_INTERRUPT_STATUS2_ACK \ 53c943b494SChandan Uddaraju (DP_INTERRUPT_STATUS2 << DP_INTERRUPT_STATUS_ACK_SHIFT) 54c943b494SChandan Uddaraju #define DP_INTERRUPT_STATUS2_MASK \ 55c943b494SChandan Uddaraju (DP_INTERRUPT_STATUS2 << DP_INTERRUPT_STATUS_MASK_SHIFT) 56c943b494SChandan Uddaraju 57c943b494SChandan Uddaraju struct dp_catalog_private { 58c943b494SChandan Uddaraju struct device *dev; 59c943b494SChandan Uddaraju struct dp_io *io; 60d13e36d7SAbhinav Kumar u32 (*audio_map)[DP_AUDIO_SDP_HEADER_MAX]; 61c943b494SChandan Uddaraju struct dp_catalog dp_catalog; 62c943b494SChandan Uddaraju u8 aux_lut_cfg_index[PHY_AUX_CFG_MAX]; 63c943b494SChandan Uddaraju }; 64c943b494SChandan Uddaraju 65c943b494SChandan Uddaraju static inline u32 dp_read_aux(struct dp_catalog_private *catalog, u32 offset) 66c943b494SChandan Uddaraju { 67c943b494SChandan Uddaraju offset += MSM_DP_CONTROLLER_AUX_OFFSET; 68c943b494SChandan Uddaraju return readl_relaxed(catalog->io->dp_controller.base + offset); 69c943b494SChandan Uddaraju } 70c943b494SChandan Uddaraju 71c943b494SChandan Uddaraju static inline void dp_write_aux(struct dp_catalog_private *catalog, 72c943b494SChandan Uddaraju u32 offset, u32 data) 73c943b494SChandan Uddaraju { 74c943b494SChandan Uddaraju offset += MSM_DP_CONTROLLER_AUX_OFFSET; 75c943b494SChandan Uddaraju /* 76c943b494SChandan Uddaraju * To make sure aux reg writes happens before any other operation, 77c943b494SChandan Uddaraju * this function uses writel() instread of writel_relaxed() 78c943b494SChandan Uddaraju */ 79c943b494SChandan Uddaraju writel(data, catalog->io->dp_controller.base + offset); 80c943b494SChandan Uddaraju } 81c943b494SChandan Uddaraju 82c943b494SChandan Uddaraju static inline u32 dp_read_ahb(struct dp_catalog_private *catalog, u32 offset) 83c943b494SChandan Uddaraju { 84c943b494SChandan Uddaraju offset += MSM_DP_CONTROLLER_AHB_OFFSET; 85c943b494SChandan Uddaraju return readl_relaxed(catalog->io->dp_controller.base + offset); 86c943b494SChandan Uddaraju } 87c943b494SChandan Uddaraju 88c943b494SChandan Uddaraju static inline void dp_write_ahb(struct dp_catalog_private *catalog, 89c943b494SChandan Uddaraju u32 offset, u32 data) 90c943b494SChandan Uddaraju { 91c943b494SChandan Uddaraju offset += MSM_DP_CONTROLLER_AHB_OFFSET; 92c943b494SChandan Uddaraju /* 93c943b494SChandan Uddaraju * To make sure phy reg writes happens before any other operation, 94c943b494SChandan Uddaraju * this function uses writel() instread of writel_relaxed() 95c943b494SChandan Uddaraju */ 96c943b494SChandan Uddaraju writel(data, catalog->io->dp_controller.base + offset); 97c943b494SChandan Uddaraju } 98c943b494SChandan Uddaraju 99c943b494SChandan Uddaraju static inline void dp_write_p0(struct dp_catalog_private *catalog, 100c943b494SChandan Uddaraju u32 offset, u32 data) 101c943b494SChandan Uddaraju { 102c943b494SChandan Uddaraju offset += MSM_DP_CONTROLLER_P0_OFFSET; 103c943b494SChandan Uddaraju /* 104c943b494SChandan Uddaraju * To make sure interface reg writes happens before any other operation, 105c943b494SChandan Uddaraju * this function uses writel() instread of writel_relaxed() 106c943b494SChandan Uddaraju */ 107c943b494SChandan Uddaraju writel(data, catalog->io->dp_controller.base + offset); 108c943b494SChandan Uddaraju } 109c943b494SChandan Uddaraju 110c943b494SChandan Uddaraju static inline u32 dp_read_p0(struct dp_catalog_private *catalog, 111c943b494SChandan Uddaraju u32 offset) 112c943b494SChandan Uddaraju { 113c943b494SChandan Uddaraju offset += MSM_DP_CONTROLLER_P0_OFFSET; 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 */ 118c943b494SChandan Uddaraju return readl_relaxed(catalog->io->dp_controller.base + offset); 119c943b494SChandan Uddaraju } 120c943b494SChandan Uddaraju 121c943b494SChandan Uddaraju static inline u32 dp_read_link(struct dp_catalog_private *catalog, u32 offset) 122c943b494SChandan Uddaraju { 123c943b494SChandan Uddaraju offset += MSM_DP_CONTROLLER_LINK_OFFSET; 124c943b494SChandan Uddaraju return readl_relaxed(catalog->io->dp_controller.base + offset); 125c943b494SChandan Uddaraju } 126c943b494SChandan Uddaraju 127c943b494SChandan Uddaraju static inline void dp_write_link(struct dp_catalog_private *catalog, 128c943b494SChandan Uddaraju u32 offset, u32 data) 129c943b494SChandan Uddaraju { 130c943b494SChandan Uddaraju offset += MSM_DP_CONTROLLER_LINK_OFFSET; 131c943b494SChandan Uddaraju /* 132c943b494SChandan Uddaraju * To make sure link reg writes happens before any other operation, 133c943b494SChandan Uddaraju * this function uses writel() instread of writel_relaxed() 134c943b494SChandan Uddaraju */ 135c943b494SChandan Uddaraju writel(data, catalog->io->dp_controller.base + offset); 136c943b494SChandan Uddaraju } 137c943b494SChandan Uddaraju 138c943b494SChandan Uddaraju /* aux related catalog functions */ 139c943b494SChandan Uddaraju u32 dp_catalog_aux_read_data(struct dp_catalog *dp_catalog) 140c943b494SChandan Uddaraju { 141c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 142c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 143c943b494SChandan Uddaraju 144c943b494SChandan Uddaraju return dp_read_aux(catalog, REG_DP_AUX_DATA); 145c943b494SChandan Uddaraju } 146c943b494SChandan Uddaraju 147c943b494SChandan Uddaraju int dp_catalog_aux_write_data(struct dp_catalog *dp_catalog) 148c943b494SChandan Uddaraju { 149c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 150c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 151c943b494SChandan Uddaraju 152c943b494SChandan Uddaraju dp_write_aux(catalog, REG_DP_AUX_DATA, dp_catalog->aux_data); 153c943b494SChandan Uddaraju return 0; 154c943b494SChandan Uddaraju } 155c943b494SChandan Uddaraju 156c943b494SChandan Uddaraju int dp_catalog_aux_write_trans(struct dp_catalog *dp_catalog) 157c943b494SChandan Uddaraju { 158c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 159c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 160c943b494SChandan Uddaraju 161c943b494SChandan Uddaraju dp_write_aux(catalog, REG_DP_AUX_TRANS_CTRL, dp_catalog->aux_data); 162c943b494SChandan Uddaraju return 0; 163c943b494SChandan Uddaraju } 164c943b494SChandan Uddaraju 165c943b494SChandan Uddaraju int dp_catalog_aux_clear_trans(struct dp_catalog *dp_catalog, bool read) 166c943b494SChandan Uddaraju { 167c943b494SChandan Uddaraju u32 data; 168c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 169c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 170c943b494SChandan Uddaraju 171c943b494SChandan Uddaraju if (read) { 172c943b494SChandan Uddaraju data = dp_read_aux(catalog, REG_DP_AUX_TRANS_CTRL); 173c943b494SChandan Uddaraju data &= ~DP_AUX_TRANS_CTRL_GO; 174c943b494SChandan Uddaraju dp_write_aux(catalog, REG_DP_AUX_TRANS_CTRL, data); 175c943b494SChandan Uddaraju } else { 176c943b494SChandan Uddaraju dp_write_aux(catalog, REG_DP_AUX_TRANS_CTRL, 0); 177c943b494SChandan Uddaraju } 178c943b494SChandan Uddaraju return 0; 179c943b494SChandan Uddaraju } 180c943b494SChandan Uddaraju 181c943b494SChandan Uddaraju int dp_catalog_aux_clear_hw_interrupts(struct dp_catalog *dp_catalog) 182c943b494SChandan Uddaraju { 183c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 184c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 185c943b494SChandan Uddaraju 186c943b494SChandan Uddaraju dp_read_aux(catalog, REG_DP_PHY_AUX_INTERRUPT_STATUS); 187c943b494SChandan Uddaraju dp_write_aux(catalog, REG_DP_PHY_AUX_INTERRUPT_CLEAR, 0x1f); 188c943b494SChandan Uddaraju dp_write_aux(catalog, REG_DP_PHY_AUX_INTERRUPT_CLEAR, 0x9f); 189c943b494SChandan Uddaraju dp_write_aux(catalog, REG_DP_PHY_AUX_INTERRUPT_CLEAR, 0); 190c943b494SChandan Uddaraju return 0; 191c943b494SChandan Uddaraju } 192c943b494SChandan Uddaraju 1939fc41843SKuogee Hsieh /** 1949fc41843SKuogee Hsieh * dp_catalog_aux_reset() - reset AUX controller 1959fc41843SKuogee Hsieh * 1969fc41843SKuogee Hsieh * @aux: DP catalog structure 1979fc41843SKuogee Hsieh * 1989fc41843SKuogee Hsieh * return: void 1999fc41843SKuogee Hsieh * 2009fc41843SKuogee Hsieh * This function reset AUX controller 2019fc41843SKuogee Hsieh * 2029fc41843SKuogee Hsieh * NOTE: reset AUX controller will also clear any pending HPD related interrupts 2039fc41843SKuogee Hsieh * 2049fc41843SKuogee Hsieh */ 205c943b494SChandan Uddaraju void dp_catalog_aux_reset(struct dp_catalog *dp_catalog) 206c943b494SChandan Uddaraju { 207c943b494SChandan Uddaraju u32 aux_ctrl; 208c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 209c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 210c943b494SChandan Uddaraju 211c943b494SChandan Uddaraju aux_ctrl = dp_read_aux(catalog, REG_DP_AUX_CTRL); 212c943b494SChandan Uddaraju 213c943b494SChandan Uddaraju aux_ctrl |= DP_AUX_CTRL_RESET; 214c943b494SChandan Uddaraju dp_write_aux(catalog, REG_DP_AUX_CTRL, aux_ctrl); 215c943b494SChandan Uddaraju usleep_range(1000, 1100); /* h/w recommended delay */ 216c943b494SChandan Uddaraju 217c943b494SChandan Uddaraju aux_ctrl &= ~DP_AUX_CTRL_RESET; 218c943b494SChandan Uddaraju dp_write_aux(catalog, REG_DP_AUX_CTRL, aux_ctrl); 219c943b494SChandan Uddaraju } 220c943b494SChandan Uddaraju 221c943b494SChandan Uddaraju void dp_catalog_aux_enable(struct dp_catalog *dp_catalog, bool enable) 222c943b494SChandan Uddaraju { 223c943b494SChandan Uddaraju u32 aux_ctrl; 224c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 225c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 226c943b494SChandan Uddaraju 227c943b494SChandan Uddaraju aux_ctrl = dp_read_aux(catalog, REG_DP_AUX_CTRL); 228c943b494SChandan Uddaraju 229c943b494SChandan Uddaraju if (enable) { 230c943b494SChandan Uddaraju dp_write_aux(catalog, REG_DP_TIMEOUT_COUNT, 0xffff); 231c943b494SChandan Uddaraju dp_write_aux(catalog, REG_DP_AUX_LIMITS, 0xffff); 232c943b494SChandan Uddaraju aux_ctrl |= DP_AUX_CTRL_ENABLE; 233c943b494SChandan Uddaraju } else { 234c943b494SChandan Uddaraju aux_ctrl &= ~DP_AUX_CTRL_ENABLE; 235c943b494SChandan Uddaraju } 236c943b494SChandan Uddaraju 237c943b494SChandan Uddaraju dp_write_aux(catalog, REG_DP_AUX_CTRL, aux_ctrl); 238c943b494SChandan Uddaraju } 239c943b494SChandan Uddaraju 240937f941cSStephen Boyd void dp_catalog_aux_update_cfg(struct dp_catalog *dp_catalog) 241c943b494SChandan Uddaraju { 242c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 243c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 244937f941cSStephen Boyd struct dp_io *dp_io = catalog->io; 245937f941cSStephen Boyd struct phy *phy = dp_io->phy; 246c943b494SChandan Uddaraju 247937f941cSStephen Boyd phy_calibrate(phy); 248c943b494SChandan Uddaraju } 249c943b494SChandan Uddaraju 250c943b494SChandan Uddaraju static void dump_regs(void __iomem *base, int len) 251c943b494SChandan Uddaraju { 252c943b494SChandan Uddaraju int i; 253c943b494SChandan Uddaraju u32 x0, x4, x8, xc; 254c943b494SChandan Uddaraju u32 addr_off = 0; 255c943b494SChandan Uddaraju 256c943b494SChandan Uddaraju len = DIV_ROUND_UP(len, 16); 257c943b494SChandan Uddaraju for (i = 0; i < len; i++) { 258c943b494SChandan Uddaraju x0 = readl_relaxed(base + addr_off); 259c943b494SChandan Uddaraju x4 = readl_relaxed(base + addr_off + 0x04); 260c943b494SChandan Uddaraju x8 = readl_relaxed(base + addr_off + 0x08); 261c943b494SChandan Uddaraju xc = readl_relaxed(base + addr_off + 0x0c); 262c943b494SChandan Uddaraju 263c943b494SChandan Uddaraju pr_info("%08x: %08x %08x %08x %08x", addr_off, x0, x4, x8, xc); 264c943b494SChandan Uddaraju addr_off += 16; 265c943b494SChandan Uddaraju } 266c943b494SChandan Uddaraju } 267c943b494SChandan Uddaraju 268c943b494SChandan Uddaraju void dp_catalog_dump_regs(struct dp_catalog *dp_catalog) 269c943b494SChandan Uddaraju { 270c943b494SChandan Uddaraju u32 offset, len; 271c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 272c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 273c943b494SChandan Uddaraju 274c943b494SChandan Uddaraju pr_info("AHB regs\n"); 275c943b494SChandan Uddaraju offset = MSM_DP_CONTROLLER_AHB_OFFSET; 276c943b494SChandan Uddaraju len = MSM_DP_CONTROLLER_AHB_SIZE; 277c943b494SChandan Uddaraju dump_regs(catalog->io->dp_controller.base + offset, len); 278c943b494SChandan Uddaraju 279c943b494SChandan Uddaraju pr_info("AUXCLK regs\n"); 280c943b494SChandan Uddaraju offset = MSM_DP_CONTROLLER_AUX_OFFSET; 281c943b494SChandan Uddaraju len = MSM_DP_CONTROLLER_AUX_SIZE; 282c943b494SChandan Uddaraju dump_regs(catalog->io->dp_controller.base + offset, len); 283c943b494SChandan Uddaraju 284c943b494SChandan Uddaraju pr_info("LCLK regs\n"); 285c943b494SChandan Uddaraju offset = MSM_DP_CONTROLLER_LINK_OFFSET; 286c943b494SChandan Uddaraju len = MSM_DP_CONTROLLER_LINK_SIZE; 287c943b494SChandan Uddaraju dump_regs(catalog->io->dp_controller.base + offset, len); 288c943b494SChandan Uddaraju 289c943b494SChandan Uddaraju pr_info("P0CLK regs\n"); 290c943b494SChandan Uddaraju offset = MSM_DP_CONTROLLER_P0_OFFSET; 291c943b494SChandan Uddaraju len = MSM_DP_CONTROLLER_P0_SIZE; 292c943b494SChandan Uddaraju dump_regs(catalog->io->dp_controller.base + offset, len); 293c943b494SChandan Uddaraju } 294c943b494SChandan Uddaraju 295c943b494SChandan Uddaraju int dp_catalog_aux_get_irq(struct dp_catalog *dp_catalog) 296c943b494SChandan Uddaraju { 297c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 298c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 299c943b494SChandan Uddaraju u32 intr, intr_ack; 300c943b494SChandan Uddaraju 301c943b494SChandan Uddaraju intr = dp_read_ahb(catalog, REG_DP_INTR_STATUS); 302c943b494SChandan Uddaraju intr &= ~DP_INTERRUPT_STATUS1_MASK; 303c943b494SChandan Uddaraju intr_ack = (intr & DP_INTERRUPT_STATUS1) 304c943b494SChandan Uddaraju << DP_INTERRUPT_STATUS_ACK_SHIFT; 305c943b494SChandan Uddaraju dp_write_ahb(catalog, REG_DP_INTR_STATUS, intr_ack | 306c943b494SChandan Uddaraju DP_INTERRUPT_STATUS1_MASK); 307c943b494SChandan Uddaraju 308c943b494SChandan Uddaraju return intr; 309c943b494SChandan Uddaraju 310c943b494SChandan Uddaraju } 311c943b494SChandan Uddaraju 312c943b494SChandan Uddaraju /* controller related catalog functions */ 313c943b494SChandan Uddaraju void dp_catalog_ctrl_update_transfer_unit(struct dp_catalog *dp_catalog, 314c943b494SChandan Uddaraju u32 dp_tu, u32 valid_boundary, 315c943b494SChandan Uddaraju u32 valid_boundary2) 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_VALID_BOUNDARY, valid_boundary); 321c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_TU, dp_tu); 322c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_VALID_BOUNDARY_2, valid_boundary2); 323c943b494SChandan Uddaraju } 324c943b494SChandan Uddaraju 325c943b494SChandan Uddaraju void dp_catalog_ctrl_state_ctrl(struct dp_catalog *dp_catalog, u32 state) 326c943b494SChandan Uddaraju { 327c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 328c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 329c943b494SChandan Uddaraju 330c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_STATE_CTRL, state); 331c943b494SChandan Uddaraju } 332c943b494SChandan Uddaraju 333c943b494SChandan Uddaraju void dp_catalog_ctrl_config_ctrl(struct dp_catalog *dp_catalog, u32 cfg) 334c943b494SChandan Uddaraju { 335c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 336c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 337c943b494SChandan Uddaraju 338c943b494SChandan Uddaraju DRM_DEBUG_DP("DP_CONFIGURATION_CTRL=0x%x\n", cfg); 339c943b494SChandan Uddaraju 340c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_CONFIGURATION_CTRL, cfg); 341c943b494SChandan Uddaraju } 342c943b494SChandan Uddaraju 343c943b494SChandan Uddaraju void dp_catalog_ctrl_lane_mapping(struct dp_catalog *dp_catalog) 344c943b494SChandan Uddaraju { 345c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 346c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 347c943b494SChandan Uddaraju u32 ln_0 = 0, ln_1 = 1, ln_2 = 2, ln_3 = 3; /* One-to-One mapping */ 348c943b494SChandan Uddaraju u32 ln_mapping; 349c943b494SChandan Uddaraju 350c943b494SChandan Uddaraju ln_mapping = ln_0 << LANE0_MAPPING_SHIFT; 351c943b494SChandan Uddaraju ln_mapping |= ln_1 << LANE1_MAPPING_SHIFT; 352c943b494SChandan Uddaraju ln_mapping |= ln_2 << LANE2_MAPPING_SHIFT; 353c943b494SChandan Uddaraju ln_mapping |= ln_3 << LANE3_MAPPING_SHIFT; 354c943b494SChandan Uddaraju 355c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_LOGICAL2PHYSICAL_LANE_MAPPING, 356c943b494SChandan Uddaraju ln_mapping); 357c943b494SChandan Uddaraju } 358c943b494SChandan Uddaraju 359c943b494SChandan Uddaraju void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog *dp_catalog, 360c943b494SChandan Uddaraju bool enable) 361c943b494SChandan Uddaraju { 362c943b494SChandan Uddaraju u32 mainlink_ctrl; 363c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 364c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 365c943b494SChandan Uddaraju 366c943b494SChandan Uddaraju if (enable) { 367c943b494SChandan Uddaraju /* 368c943b494SChandan Uddaraju * To make sure link reg writes happens before other operation, 369c943b494SChandan Uddaraju * dp_write_link() function uses writel() 370c943b494SChandan Uddaraju */ 3718ede2eccSKuogee Hsieh mainlink_ctrl = dp_read_link(catalog, REG_DP_MAINLINK_CTRL); 3728ede2eccSKuogee Hsieh 3738ede2eccSKuogee Hsieh mainlink_ctrl &= ~(DP_MAINLINK_CTRL_RESET | 374c943b494SChandan Uddaraju DP_MAINLINK_CTRL_ENABLE); 3758ede2eccSKuogee Hsieh dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl); 3768ede2eccSKuogee Hsieh 3778ede2eccSKuogee Hsieh mainlink_ctrl |= DP_MAINLINK_CTRL_RESET; 3788ede2eccSKuogee Hsieh dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl); 3798ede2eccSKuogee Hsieh 3808ede2eccSKuogee Hsieh mainlink_ctrl &= ~DP_MAINLINK_CTRL_RESET; 3818ede2eccSKuogee Hsieh dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl); 3828ede2eccSKuogee Hsieh 3838ede2eccSKuogee Hsieh mainlink_ctrl |= (DP_MAINLINK_CTRL_ENABLE | 3848ede2eccSKuogee Hsieh DP_MAINLINK_FB_BOUNDARY_SEL); 3858ede2eccSKuogee Hsieh dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl); 386c943b494SChandan Uddaraju } else { 387c943b494SChandan Uddaraju mainlink_ctrl = dp_read_link(catalog, REG_DP_MAINLINK_CTRL); 388c943b494SChandan Uddaraju mainlink_ctrl &= ~DP_MAINLINK_CTRL_ENABLE; 389c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl); 390c943b494SChandan Uddaraju } 391c943b494SChandan Uddaraju } 392c943b494SChandan Uddaraju 393c943b494SChandan Uddaraju void dp_catalog_ctrl_config_misc(struct dp_catalog *dp_catalog, 394c943b494SChandan Uddaraju u32 colorimetry_cfg, 395c943b494SChandan Uddaraju u32 test_bits_depth) 396c943b494SChandan Uddaraju { 397c943b494SChandan Uddaraju u32 misc_val; 398c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 399c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 400c943b494SChandan Uddaraju 401c943b494SChandan Uddaraju misc_val = dp_read_link(catalog, REG_DP_MISC1_MISC0); 402c943b494SChandan Uddaraju 403c943b494SChandan Uddaraju /* clear bpp bits */ 404c943b494SChandan Uddaraju misc_val &= ~(0x07 << DP_MISC0_TEST_BITS_DEPTH_SHIFT); 405c943b494SChandan Uddaraju misc_val |= colorimetry_cfg << DP_MISC0_COLORIMETRY_CFG_SHIFT; 406c943b494SChandan Uddaraju misc_val |= test_bits_depth << DP_MISC0_TEST_BITS_DEPTH_SHIFT; 407c943b494SChandan Uddaraju /* Configure clock to synchronous mode */ 408c943b494SChandan Uddaraju misc_val |= DP_MISC0_SYNCHRONOUS_CLK; 409c943b494SChandan Uddaraju 410c943b494SChandan Uddaraju DRM_DEBUG_DP("misc settings = 0x%x\n", misc_val); 411c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_MISC1_MISC0, misc_val); 412c943b494SChandan Uddaraju } 413c943b494SChandan Uddaraju 414c943b494SChandan Uddaraju void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog, 415c943b494SChandan Uddaraju u32 rate, u32 stream_rate_khz, 416c943b494SChandan Uddaraju bool fixed_nvid) 417c943b494SChandan Uddaraju { 418c943b494SChandan Uddaraju u32 pixel_m, pixel_n; 419937f941cSStephen Boyd u32 mvid, nvid, pixel_div = 0, dispcc_input_rate; 420c943b494SChandan Uddaraju u32 const nvid_fixed = DP_LINK_CONSTANT_N_VALUE; 421c943b494SChandan Uddaraju u32 const link_rate_hbr2 = 540000; 422c943b494SChandan Uddaraju u32 const link_rate_hbr3 = 810000; 423c943b494SChandan Uddaraju unsigned long den, num; 424c943b494SChandan Uddaraju 425c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 426c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 427c943b494SChandan Uddaraju 428937f941cSStephen Boyd if (rate == link_rate_hbr3) 429c943b494SChandan Uddaraju pixel_div = 6; 430937f941cSStephen Boyd else if (rate == 1620000 || rate == 270000) 431c943b494SChandan Uddaraju pixel_div = 2; 432937f941cSStephen Boyd else if (rate == link_rate_hbr2) 433c943b494SChandan Uddaraju pixel_div = 4; 434c943b494SChandan Uddaraju else 435c943b494SChandan Uddaraju DRM_ERROR("Invalid pixel mux divider\n"); 436c943b494SChandan Uddaraju 437c943b494SChandan Uddaraju dispcc_input_rate = (rate * 10) / pixel_div; 438c943b494SChandan Uddaraju 439c943b494SChandan Uddaraju rational_best_approximation(dispcc_input_rate, stream_rate_khz, 440c943b494SChandan Uddaraju (unsigned long)(1 << 16) - 1, 441c943b494SChandan Uddaraju (unsigned long)(1 << 16) - 1, &den, &num); 442c943b494SChandan Uddaraju 443c943b494SChandan Uddaraju den = ~(den - num); 444c943b494SChandan Uddaraju den = den & 0xFFFF; 445c943b494SChandan Uddaraju pixel_m = num; 446c943b494SChandan Uddaraju pixel_n = den; 447c943b494SChandan Uddaraju 448c943b494SChandan Uddaraju mvid = (pixel_m & 0xFFFF) * 5; 449c943b494SChandan Uddaraju nvid = (0xFFFF & (~pixel_n)) + (pixel_m & 0xFFFF); 450c943b494SChandan Uddaraju 451c943b494SChandan Uddaraju if (nvid < nvid_fixed) { 452c943b494SChandan Uddaraju u32 temp; 453c943b494SChandan Uddaraju 454c943b494SChandan Uddaraju temp = (nvid_fixed / nvid) * nvid; 455c943b494SChandan Uddaraju mvid = (nvid_fixed / nvid) * mvid; 456c943b494SChandan Uddaraju nvid = temp; 457c943b494SChandan Uddaraju } 458c943b494SChandan Uddaraju 459c943b494SChandan Uddaraju if (link_rate_hbr2 == rate) 460c943b494SChandan Uddaraju nvid *= 2; 461c943b494SChandan Uddaraju 462c943b494SChandan Uddaraju if (link_rate_hbr3 == rate) 463c943b494SChandan Uddaraju nvid *= 3; 464c943b494SChandan Uddaraju 465c943b494SChandan Uddaraju DRM_DEBUG_DP("mvid=0x%x, nvid=0x%x\n", mvid, nvid); 466c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_SOFTWARE_MVID, mvid); 467c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_SOFTWARE_NVID, nvid); 468c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_DSC_DTO, 0x0); 469c943b494SChandan Uddaraju } 470c943b494SChandan Uddaraju 471c943b494SChandan Uddaraju int dp_catalog_ctrl_set_pattern(struct dp_catalog *dp_catalog, 472c943b494SChandan Uddaraju u32 pattern) 473c943b494SChandan Uddaraju { 474c943b494SChandan Uddaraju int bit, ret; 475c943b494SChandan Uddaraju u32 data; 476c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 477c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 478c943b494SChandan Uddaraju 479c943b494SChandan Uddaraju bit = BIT(pattern - 1); 480c943b494SChandan Uddaraju DRM_DEBUG_DP("hw: bit=%d train=%d\n", bit, pattern); 4818ede2eccSKuogee Hsieh dp_catalog_ctrl_state_ctrl(dp_catalog, bit); 482c943b494SChandan Uddaraju 483c943b494SChandan Uddaraju bit = BIT(pattern - 1) << DP_MAINLINK_READY_LINK_TRAINING_SHIFT; 484c943b494SChandan Uddaraju 485c943b494SChandan Uddaraju /* Poll for mainlink ready status */ 486c943b494SChandan Uddaraju ret = readx_poll_timeout(readl, catalog->io->dp_controller.base + 487c943b494SChandan Uddaraju MSM_DP_CONTROLLER_LINK_OFFSET + 488c943b494SChandan Uddaraju REG_DP_MAINLINK_READY, 489c943b494SChandan Uddaraju data, data & bit, 490c943b494SChandan Uddaraju POLLING_SLEEP_US, POLLING_TIMEOUT_US); 491c943b494SChandan Uddaraju if (ret < 0) { 492c943b494SChandan Uddaraju DRM_ERROR("set pattern for link_train=%d failed\n", pattern); 493c943b494SChandan Uddaraju return ret; 494c943b494SChandan Uddaraju } 495c943b494SChandan Uddaraju return 0; 496c943b494SChandan Uddaraju } 497c943b494SChandan Uddaraju 4989fc41843SKuogee Hsieh /** 4999fc41843SKuogee Hsieh * dp_catalog_ctrl_reset() - reset DP controller 5009fc41843SKuogee Hsieh * 5019fc41843SKuogee Hsieh * @dp_catalog: DP catalog structure 5029fc41843SKuogee Hsieh * 5039fc41843SKuogee Hsieh * return: void 5049fc41843SKuogee Hsieh * 5059fc41843SKuogee Hsieh * This function reset the DP controller 5069fc41843SKuogee Hsieh * 5079fc41843SKuogee Hsieh * NOTE: reset DP controller will also clear any pending HPD related interrupts 5089fc41843SKuogee Hsieh * 5099fc41843SKuogee Hsieh */ 510c943b494SChandan Uddaraju void dp_catalog_ctrl_reset(struct dp_catalog *dp_catalog) 511c943b494SChandan Uddaraju { 512c943b494SChandan Uddaraju u32 sw_reset; 513c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 514c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 515c943b494SChandan Uddaraju 516c943b494SChandan Uddaraju sw_reset = dp_read_ahb(catalog, REG_DP_SW_RESET); 517c943b494SChandan Uddaraju 518c943b494SChandan Uddaraju sw_reset |= DP_SW_RESET; 519c943b494SChandan Uddaraju dp_write_ahb(catalog, REG_DP_SW_RESET, sw_reset); 520c943b494SChandan Uddaraju usleep_range(1000, 1100); /* h/w recommended delay */ 521c943b494SChandan Uddaraju 522c943b494SChandan Uddaraju sw_reset &= ~DP_SW_RESET; 523c943b494SChandan Uddaraju dp_write_ahb(catalog, REG_DP_SW_RESET, sw_reset); 524c943b494SChandan Uddaraju } 525c943b494SChandan Uddaraju 526c943b494SChandan Uddaraju bool dp_catalog_ctrl_mainlink_ready(struct dp_catalog *dp_catalog) 527c943b494SChandan Uddaraju { 528c943b494SChandan Uddaraju u32 data; 529c943b494SChandan Uddaraju int ret; 530c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 531c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 532c943b494SChandan Uddaraju 533c943b494SChandan Uddaraju /* Poll for mainlink ready status */ 534c943b494SChandan Uddaraju ret = readl_poll_timeout(catalog->io->dp_controller.base + 535c943b494SChandan Uddaraju MSM_DP_CONTROLLER_LINK_OFFSET + 536c943b494SChandan Uddaraju REG_DP_MAINLINK_READY, 537c943b494SChandan Uddaraju data, data & DP_MAINLINK_READY_FOR_VIDEO, 538c943b494SChandan Uddaraju POLLING_SLEEP_US, POLLING_TIMEOUT_US); 539c943b494SChandan Uddaraju if (ret < 0) { 540c943b494SChandan Uddaraju DRM_ERROR("mainlink not ready\n"); 541c943b494SChandan Uddaraju return false; 542c943b494SChandan Uddaraju } 543c943b494SChandan Uddaraju 544c943b494SChandan Uddaraju return true; 545c943b494SChandan Uddaraju } 546c943b494SChandan Uddaraju 547c943b494SChandan Uddaraju void dp_catalog_ctrl_enable_irq(struct dp_catalog *dp_catalog, 548c943b494SChandan Uddaraju bool enable) 549c943b494SChandan Uddaraju { 550c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 551c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 552c943b494SChandan Uddaraju 553c943b494SChandan Uddaraju if (enable) { 554c943b494SChandan Uddaraju dp_write_ahb(catalog, REG_DP_INTR_STATUS, 555c943b494SChandan Uddaraju DP_INTERRUPT_STATUS1_MASK); 556c943b494SChandan Uddaraju dp_write_ahb(catalog, REG_DP_INTR_STATUS2, 557c943b494SChandan Uddaraju DP_INTERRUPT_STATUS2_MASK); 558c943b494SChandan Uddaraju } else { 559c943b494SChandan Uddaraju dp_write_ahb(catalog, REG_DP_INTR_STATUS, 0x00); 560c943b494SChandan Uddaraju dp_write_ahb(catalog, REG_DP_INTR_STATUS2, 0x00); 561c943b494SChandan Uddaraju } 562c943b494SChandan Uddaraju } 563c943b494SChandan Uddaraju 564220b856aSTanmay Shah void dp_catalog_hpd_config_intr(struct dp_catalog *dp_catalog, 565220b856aSTanmay Shah u32 intr_mask, bool en) 566c943b494SChandan Uddaraju { 567c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 568c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 569c943b494SChandan Uddaraju 570220b856aSTanmay Shah u32 config = dp_read_aux(catalog, REG_DP_DP_HPD_INT_MASK); 571220b856aSTanmay Shah 572220b856aSTanmay Shah config = (en ? config | intr_mask : config & ~intr_mask); 573220b856aSTanmay Shah 574220b856aSTanmay Shah dp_write_aux(catalog, REG_DP_DP_HPD_INT_MASK, 575220b856aSTanmay Shah config & DP_DP_HPD_INT_MASK); 576220b856aSTanmay Shah } 577220b856aSTanmay Shah 578220b856aSTanmay Shah void dp_catalog_ctrl_hpd_config(struct dp_catalog *dp_catalog) 579220b856aSTanmay Shah { 580220b856aSTanmay Shah struct dp_catalog_private *catalog = container_of(dp_catalog, 581220b856aSTanmay Shah struct dp_catalog_private, dp_catalog); 582220b856aSTanmay Shah 583c943b494SChandan Uddaraju u32 reftimer = dp_read_aux(catalog, REG_DP_DP_HPD_REFTIMER); 584c943b494SChandan Uddaraju 585*f21c8a27SKuogee Hsieh /* enable HPD plug and unplug interrupts */ 586220b856aSTanmay Shah dp_catalog_hpd_config_intr(dp_catalog, 587*f21c8a27SKuogee Hsieh DP_DP_HPD_PLUG_INT_MASK | DP_DP_HPD_UNPLUG_INT_MASK, true); 588c943b494SChandan Uddaraju 589220b856aSTanmay Shah /* Configure REFTIMER and enable it */ 590220b856aSTanmay Shah reftimer |= DP_DP_HPD_REFTIMER_ENABLE; 591c943b494SChandan Uddaraju dp_write_aux(catalog, REG_DP_DP_HPD_REFTIMER, reftimer); 592220b856aSTanmay Shah 593c943b494SChandan Uddaraju /* Enable HPD */ 594220b856aSTanmay Shah dp_write_aux(catalog, REG_DP_DP_HPD_CTRL, DP_DP_HPD_CTRL_HPD_EN); 595c943b494SChandan Uddaraju } 596220b856aSTanmay Shah 597231a04fcSKuogee Hsieh u32 dp_catalog_link_is_connected(struct dp_catalog *dp_catalog) 59819e52bcbSKuogee Hsieh { 59919e52bcbSKuogee Hsieh struct dp_catalog_private *catalog = container_of(dp_catalog, 60019e52bcbSKuogee Hsieh struct dp_catalog_private, dp_catalog); 60119e52bcbSKuogee Hsieh u32 status; 60219e52bcbSKuogee Hsieh 60319e52bcbSKuogee Hsieh status = dp_read_aux(catalog, REG_DP_DP_HPD_INT_STATUS); 60419e52bcbSKuogee Hsieh status >>= DP_DP_HPD_STATE_STATUS_BITS_SHIFT; 60519e52bcbSKuogee Hsieh status &= DP_DP_HPD_STATE_STATUS_BITS_MASK; 60619e52bcbSKuogee Hsieh 60719e52bcbSKuogee Hsieh return status; 60819e52bcbSKuogee Hsieh } 60919e52bcbSKuogee Hsieh 610220b856aSTanmay Shah u32 dp_catalog_hpd_get_intr_status(struct dp_catalog *dp_catalog) 611220b856aSTanmay Shah { 612220b856aSTanmay Shah struct dp_catalog_private *catalog = container_of(dp_catalog, 613220b856aSTanmay Shah struct dp_catalog_private, dp_catalog); 614220b856aSTanmay Shah int isr = 0; 615220b856aSTanmay Shah 616220b856aSTanmay Shah isr = dp_read_aux(catalog, REG_DP_DP_HPD_INT_STATUS); 617220b856aSTanmay Shah dp_write_aux(catalog, REG_DP_DP_HPD_INT_ACK, 618220b856aSTanmay Shah (isr & DP_DP_HPD_INT_MASK)); 619220b856aSTanmay Shah 620220b856aSTanmay Shah return isr; 621c943b494SChandan Uddaraju } 622c943b494SChandan Uddaraju 623c943b494SChandan Uddaraju int dp_catalog_ctrl_get_interrupt(struct dp_catalog *dp_catalog) 624c943b494SChandan Uddaraju { 625c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 626c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 627c943b494SChandan Uddaraju u32 intr, intr_ack; 628c943b494SChandan Uddaraju 629c943b494SChandan Uddaraju intr = dp_read_ahb(catalog, REG_DP_INTR_STATUS2); 630c943b494SChandan Uddaraju intr &= ~DP_INTERRUPT_STATUS2_MASK; 631c943b494SChandan Uddaraju intr_ack = (intr & DP_INTERRUPT_STATUS2) 632c943b494SChandan Uddaraju << DP_INTERRUPT_STATUS_ACK_SHIFT; 633c943b494SChandan Uddaraju dp_write_ahb(catalog, REG_DP_INTR_STATUS2, 634c943b494SChandan Uddaraju intr_ack | DP_INTERRUPT_STATUS2_MASK); 635c943b494SChandan Uddaraju 636c943b494SChandan Uddaraju return intr; 637c943b494SChandan Uddaraju } 638c943b494SChandan Uddaraju 639c943b494SChandan Uddaraju void dp_catalog_ctrl_phy_reset(struct dp_catalog *dp_catalog) 640c943b494SChandan Uddaraju { 641c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 642c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 643c943b494SChandan Uddaraju 644c943b494SChandan Uddaraju dp_write_ahb(catalog, REG_DP_PHY_CTRL, 645937f941cSStephen Boyd DP_PHY_CTRL_SW_RESET | DP_PHY_CTRL_SW_RESET_PLL); 646c943b494SChandan Uddaraju usleep_range(1000, 1100); /* h/w recommended delay */ 647c943b494SChandan Uddaraju dp_write_ahb(catalog, REG_DP_PHY_CTRL, 0x0); 648c943b494SChandan Uddaraju } 649c943b494SChandan Uddaraju 650c943b494SChandan Uddaraju int dp_catalog_ctrl_update_vx_px(struct dp_catalog *dp_catalog, 651c943b494SChandan Uddaraju u8 v_level, u8 p_level) 652c943b494SChandan Uddaraju { 653c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 654c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 655937f941cSStephen Boyd struct dp_io *dp_io = catalog->io; 656937f941cSStephen Boyd struct phy *phy = dp_io->phy; 657937f941cSStephen Boyd struct phy_configure_opts_dp *opts_dp = &dp_io->phy_opts.dp; 658c943b494SChandan Uddaraju 659937f941cSStephen Boyd /* TODO: Update for all lanes instead of just first one */ 660937f941cSStephen Boyd opts_dp->voltage[0] = v_level; 661937f941cSStephen Boyd opts_dp->pre[0] = p_level; 662937f941cSStephen Boyd opts_dp->set_voltages = 1; 663937f941cSStephen Boyd phy_configure(phy, &dp_io->phy_opts); 664937f941cSStephen Boyd opts_dp->set_voltages = 0; 665c943b494SChandan Uddaraju 666c943b494SChandan Uddaraju return 0; 667c943b494SChandan Uddaraju } 668c943b494SChandan Uddaraju 669c943b494SChandan Uddaraju void dp_catalog_ctrl_send_phy_pattern(struct dp_catalog *dp_catalog, 670c943b494SChandan Uddaraju u32 pattern) 671c943b494SChandan Uddaraju { 672c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 673c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 674c943b494SChandan Uddaraju u32 value = 0x0; 675c943b494SChandan Uddaraju 676c943b494SChandan Uddaraju /* Make sure to clear the current pattern before starting a new one */ 677c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_STATE_CTRL, 0x0); 678c943b494SChandan Uddaraju 679c943b494SChandan Uddaraju switch (pattern) { 6808ede2eccSKuogee Hsieh case DP_PHY_TEST_PATTERN_D10_2: 681c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_STATE_CTRL, 682c943b494SChandan Uddaraju DP_STATE_CTRL_LINK_TRAINING_PATTERN1); 6838ede2eccSKuogee Hsieh break; 6848ede2eccSKuogee Hsieh case DP_PHY_TEST_PATTERN_ERROR_COUNT: 6858ede2eccSKuogee Hsieh value &= ~(1 << 16); 6868ede2eccSKuogee Hsieh dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, 6878ede2eccSKuogee Hsieh value); 6888ede2eccSKuogee Hsieh value |= SCRAMBLER_RESET_COUNT_VALUE; 6898ede2eccSKuogee Hsieh dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, 6908ede2eccSKuogee Hsieh value); 6918ede2eccSKuogee Hsieh dp_write_link(catalog, REG_DP_MAINLINK_LEVELS, 6928ede2eccSKuogee Hsieh DP_MAINLINK_SAFE_TO_EXIT_LEVEL_2); 6938ede2eccSKuogee Hsieh dp_write_link(catalog, REG_DP_STATE_CTRL, 6948ede2eccSKuogee Hsieh DP_STATE_CTRL_LINK_SYMBOL_ERR_MEASURE); 6958ede2eccSKuogee Hsieh break; 6968ede2eccSKuogee Hsieh case DP_PHY_TEST_PATTERN_PRBS7: 697c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_STATE_CTRL, 698c943b494SChandan Uddaraju DP_STATE_CTRL_LINK_PRBS7); 6998ede2eccSKuogee Hsieh break; 7008ede2eccSKuogee Hsieh case DP_PHY_TEST_PATTERN_80BIT_CUSTOM: 701c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_STATE_CTRL, 702c943b494SChandan Uddaraju DP_STATE_CTRL_LINK_TEST_CUSTOM_PATTERN); 703c943b494SChandan Uddaraju /* 00111110000011111000001111100000 */ 704c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG0, 705c943b494SChandan Uddaraju 0x3E0F83E0); 706c943b494SChandan Uddaraju /* 00001111100000111110000011111000 */ 707c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG1, 708c943b494SChandan Uddaraju 0x0F83E0F8); 709c943b494SChandan Uddaraju /* 1111100000111110 */ 710c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG2, 711c943b494SChandan Uddaraju 0x0000F83E); 7128ede2eccSKuogee Hsieh break; 7138ede2eccSKuogee Hsieh case DP_PHY_TEST_PATTERN_CP2520: 7148ede2eccSKuogee Hsieh value = dp_read_link(catalog, REG_DP_MAINLINK_CTRL); 7158ede2eccSKuogee Hsieh value &= ~DP_MAINLINK_CTRL_SW_BYPASS_SCRAMBLER; 7168ede2eccSKuogee Hsieh dp_write_link(catalog, REG_DP_MAINLINK_CTRL, value); 7178ede2eccSKuogee Hsieh 718c943b494SChandan Uddaraju value = DP_HBR2_ERM_PATTERN; 719c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, 720c943b494SChandan Uddaraju value); 721c943b494SChandan Uddaraju value |= SCRAMBLER_RESET_COUNT_VALUE; 722c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, 723c943b494SChandan Uddaraju value); 724c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_MAINLINK_LEVELS, 725c943b494SChandan Uddaraju DP_MAINLINK_SAFE_TO_EXIT_LEVEL_2); 726c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_STATE_CTRL, 727c943b494SChandan Uddaraju DP_STATE_CTRL_LINK_SYMBOL_ERR_MEASURE); 7288ede2eccSKuogee Hsieh value = dp_read_link(catalog, REG_DP_MAINLINK_CTRL); 7298ede2eccSKuogee Hsieh value |= DP_MAINLINK_CTRL_ENABLE; 7308ede2eccSKuogee Hsieh dp_write_link(catalog, REG_DP_MAINLINK_CTRL, value); 7318ede2eccSKuogee Hsieh break; 7328ede2eccSKuogee Hsieh case DP_PHY_TEST_PATTERN_SEL_MASK: 7338ede2eccSKuogee Hsieh dp_write_link(catalog, REG_DP_MAINLINK_CTRL, 7348ede2eccSKuogee Hsieh DP_MAINLINK_CTRL_ENABLE); 7358ede2eccSKuogee Hsieh dp_write_link(catalog, REG_DP_STATE_CTRL, 7368ede2eccSKuogee Hsieh DP_STATE_CTRL_LINK_TRAINING_PATTERN4); 7378ede2eccSKuogee Hsieh break; 738c943b494SChandan Uddaraju default: 739c943b494SChandan Uddaraju DRM_DEBUG_DP("No valid test pattern requested:0x%x\n", pattern); 7408ede2eccSKuogee Hsieh break; 741c943b494SChandan Uddaraju } 742c943b494SChandan Uddaraju } 743c943b494SChandan Uddaraju 744c943b494SChandan Uddaraju u32 dp_catalog_ctrl_read_phy_pattern(struct dp_catalog *dp_catalog) 745c943b494SChandan Uddaraju { 746c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 747c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 748c943b494SChandan Uddaraju 749c943b494SChandan Uddaraju return dp_read_link(catalog, REG_DP_MAINLINK_READY); 750c943b494SChandan Uddaraju } 751c943b494SChandan Uddaraju 752c943b494SChandan Uddaraju /* panel related catalog functions */ 753c943b494SChandan Uddaraju int dp_catalog_panel_timing_cfg(struct dp_catalog *dp_catalog) 754c943b494SChandan Uddaraju { 755c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 756c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 757c943b494SChandan Uddaraju 758c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_TOTAL_HOR_VER, 759c943b494SChandan Uddaraju dp_catalog->total); 760c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_START_HOR_VER_FROM_SYNC, 761c943b494SChandan Uddaraju dp_catalog->sync_start); 762c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_HSYNC_VSYNC_WIDTH_POLARITY, 763c943b494SChandan Uddaraju dp_catalog->width_blanking); 764c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_ACTIVE_HOR_VER, dp_catalog->dp_active); 765c943b494SChandan Uddaraju return 0; 766c943b494SChandan Uddaraju } 767c943b494SChandan Uddaraju 768c943b494SChandan Uddaraju void dp_catalog_panel_tpg_enable(struct dp_catalog *dp_catalog, 769c943b494SChandan Uddaraju struct drm_display_mode *drm_mode) 770c943b494SChandan Uddaraju { 771c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 772c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 773c943b494SChandan Uddaraju u32 hsync_period, vsync_period; 774c943b494SChandan Uddaraju u32 display_v_start, display_v_end; 775c943b494SChandan Uddaraju u32 hsync_start_x, hsync_end_x; 776c943b494SChandan Uddaraju u32 v_sync_width; 777c943b494SChandan Uddaraju u32 hsync_ctl; 778c943b494SChandan Uddaraju u32 display_hctl; 779c943b494SChandan Uddaraju 780c943b494SChandan Uddaraju /* TPG config parameters*/ 781c943b494SChandan Uddaraju hsync_period = drm_mode->htotal; 782c943b494SChandan Uddaraju vsync_period = drm_mode->vtotal; 783c943b494SChandan Uddaraju 784c943b494SChandan Uddaraju display_v_start = ((drm_mode->vtotal - drm_mode->vsync_start) * 785c943b494SChandan Uddaraju hsync_period); 786c943b494SChandan Uddaraju display_v_end = ((vsync_period - (drm_mode->vsync_start - 787c943b494SChandan Uddaraju drm_mode->vdisplay)) 788c943b494SChandan Uddaraju * hsync_period) - 1; 789c943b494SChandan Uddaraju 790c943b494SChandan Uddaraju display_v_start += drm_mode->htotal - drm_mode->hsync_start; 791c943b494SChandan Uddaraju display_v_end -= (drm_mode->hsync_start - drm_mode->hdisplay); 792c943b494SChandan Uddaraju 793c943b494SChandan Uddaraju hsync_start_x = drm_mode->htotal - drm_mode->hsync_start; 794c943b494SChandan Uddaraju hsync_end_x = hsync_period - (drm_mode->hsync_start - 795c943b494SChandan Uddaraju drm_mode->hdisplay) - 1; 796c943b494SChandan Uddaraju 797c943b494SChandan Uddaraju v_sync_width = drm_mode->vsync_end - drm_mode->vsync_start; 798c943b494SChandan Uddaraju 799c943b494SChandan Uddaraju hsync_ctl = (hsync_period << 16) | 800c943b494SChandan Uddaraju (drm_mode->hsync_end - drm_mode->hsync_start); 801c943b494SChandan Uddaraju display_hctl = (hsync_end_x << 16) | hsync_start_x; 802c943b494SChandan Uddaraju 803c943b494SChandan Uddaraju 804c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_CONFIG, 0x0); 805c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_HSYNC_CTL, hsync_ctl); 806c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_VSYNC_PERIOD_F0, vsync_period * 807c943b494SChandan Uddaraju hsync_period); 808c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F0, v_sync_width * 809c943b494SChandan Uddaraju hsync_period); 810c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_VSYNC_PERIOD_F1, 0); 811c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F1, 0); 812c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_DISPLAY_HCTL, display_hctl); 813c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_HCTL, 0); 814c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_INTF_DISPLAY_V_START_F0, display_v_start); 815c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_DISPLAY_V_END_F0, display_v_end); 816c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_INTF_DISPLAY_V_START_F1, 0); 817c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_DISPLAY_V_END_F1, 0); 818c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_V_START_F0, 0); 819c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_V_END_F0, 0); 820c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_V_START_F1, 0); 821c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_V_END_F1, 0); 822c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_POLARITY_CTL, 0); 823c943b494SChandan Uddaraju 824c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_TPG_MAIN_CONTROL, 825c943b494SChandan Uddaraju DP_TPG_CHECKERED_RECT_PATTERN); 826c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_TPG_VIDEO_CONFIG, 827c943b494SChandan Uddaraju DP_TPG_VIDEO_CONFIG_BPP_8BIT | 828c943b494SChandan Uddaraju DP_TPG_VIDEO_CONFIG_RGB); 829c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_BIST_ENABLE, 830c943b494SChandan Uddaraju DP_BIST_ENABLE_DPBIST_EN); 831c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_TIMING_ENGINE_EN, 832c943b494SChandan Uddaraju DP_TIMING_ENGINE_EN_EN); 833c943b494SChandan Uddaraju DRM_DEBUG_DP("%s: enabled tpg\n", __func__); 834c943b494SChandan Uddaraju } 835c943b494SChandan Uddaraju 836c943b494SChandan Uddaraju void dp_catalog_panel_tpg_disable(struct dp_catalog *dp_catalog) 837c943b494SChandan Uddaraju { 838c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 839c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 840c943b494SChandan Uddaraju 841c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_TPG_MAIN_CONTROL, 0x0); 842c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_BIST_ENABLE, 0x0); 843c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_TIMING_ENGINE_EN, 0x0); 844c943b494SChandan Uddaraju } 845c943b494SChandan Uddaraju 846c943b494SChandan Uddaraju struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_io *io) 847c943b494SChandan Uddaraju { 848c943b494SChandan Uddaraju struct dp_catalog_private *catalog; 849c943b494SChandan Uddaraju 850c943b494SChandan Uddaraju if (!io) { 851c943b494SChandan Uddaraju DRM_ERROR("invalid input\n"); 852c943b494SChandan Uddaraju return ERR_PTR(-EINVAL); 853c943b494SChandan Uddaraju } 854c943b494SChandan Uddaraju 855c943b494SChandan Uddaraju catalog = devm_kzalloc(dev, sizeof(*catalog), GFP_KERNEL); 856c943b494SChandan Uddaraju if (!catalog) 857c943b494SChandan Uddaraju return ERR_PTR(-ENOMEM); 858c943b494SChandan Uddaraju 859c943b494SChandan Uddaraju catalog->dev = dev; 860c943b494SChandan Uddaraju catalog->io = io; 861c943b494SChandan Uddaraju 862c943b494SChandan Uddaraju return &catalog->dp_catalog; 863c943b494SChandan Uddaraju } 864d13e36d7SAbhinav Kumar 865d13e36d7SAbhinav Kumar void dp_catalog_audio_get_header(struct dp_catalog *dp_catalog) 866d13e36d7SAbhinav Kumar { 867d13e36d7SAbhinav Kumar struct dp_catalog_private *catalog; 868d13e36d7SAbhinav Kumar u32 (*sdp_map)[DP_AUDIO_SDP_HEADER_MAX]; 869d13e36d7SAbhinav Kumar enum dp_catalog_audio_sdp_type sdp; 870d13e36d7SAbhinav Kumar enum dp_catalog_audio_header_type header; 871d13e36d7SAbhinav Kumar 872d13e36d7SAbhinav Kumar if (!dp_catalog) 873d13e36d7SAbhinav Kumar return; 874d13e36d7SAbhinav Kumar 875d13e36d7SAbhinav Kumar catalog = container_of(dp_catalog, 876d13e36d7SAbhinav Kumar struct dp_catalog_private, dp_catalog); 877d13e36d7SAbhinav Kumar 878d13e36d7SAbhinav Kumar sdp_map = catalog->audio_map; 879d13e36d7SAbhinav Kumar sdp = dp_catalog->sdp_type; 880d13e36d7SAbhinav Kumar header = dp_catalog->sdp_header; 881d13e36d7SAbhinav Kumar 882d13e36d7SAbhinav Kumar dp_catalog->audio_data = dp_read_link(catalog, 883d13e36d7SAbhinav Kumar sdp_map[sdp][header]); 884d13e36d7SAbhinav Kumar } 885d13e36d7SAbhinav Kumar 886d13e36d7SAbhinav Kumar void dp_catalog_audio_set_header(struct dp_catalog *dp_catalog) 887d13e36d7SAbhinav Kumar { 888d13e36d7SAbhinav Kumar struct dp_catalog_private *catalog; 889d13e36d7SAbhinav Kumar u32 (*sdp_map)[DP_AUDIO_SDP_HEADER_MAX]; 890d13e36d7SAbhinav Kumar enum dp_catalog_audio_sdp_type sdp; 891d13e36d7SAbhinav Kumar enum dp_catalog_audio_header_type header; 892d13e36d7SAbhinav Kumar u32 data; 893d13e36d7SAbhinav Kumar 894d13e36d7SAbhinav Kumar if (!dp_catalog) 895d13e36d7SAbhinav Kumar return; 896d13e36d7SAbhinav Kumar 897d13e36d7SAbhinav Kumar catalog = container_of(dp_catalog, 898d13e36d7SAbhinav Kumar struct dp_catalog_private, dp_catalog); 899d13e36d7SAbhinav Kumar 900d13e36d7SAbhinav Kumar sdp_map = catalog->audio_map; 901d13e36d7SAbhinav Kumar sdp = dp_catalog->sdp_type; 902d13e36d7SAbhinav Kumar header = dp_catalog->sdp_header; 903d13e36d7SAbhinav Kumar data = dp_catalog->audio_data; 904d13e36d7SAbhinav Kumar 905d13e36d7SAbhinav Kumar dp_write_link(catalog, sdp_map[sdp][header], data); 906d13e36d7SAbhinav Kumar } 907d13e36d7SAbhinav Kumar 908d13e36d7SAbhinav Kumar void dp_catalog_audio_config_acr(struct dp_catalog *dp_catalog) 909d13e36d7SAbhinav Kumar { 910d13e36d7SAbhinav Kumar struct dp_catalog_private *catalog; 911d13e36d7SAbhinav Kumar u32 acr_ctrl, select; 912d13e36d7SAbhinav Kumar 913d13e36d7SAbhinav Kumar if (!dp_catalog) 914d13e36d7SAbhinav Kumar return; 915d13e36d7SAbhinav Kumar 916d13e36d7SAbhinav Kumar catalog = container_of(dp_catalog, 917d13e36d7SAbhinav Kumar struct dp_catalog_private, dp_catalog); 918d13e36d7SAbhinav Kumar 919d13e36d7SAbhinav Kumar select = dp_catalog->audio_data; 920d13e36d7SAbhinav Kumar acr_ctrl = select << 4 | BIT(31) | BIT(8) | BIT(14); 921d13e36d7SAbhinav Kumar 922d13e36d7SAbhinav Kumar DRM_DEBUG_DP("select = 0x%x, acr_ctrl = 0x%x\n", select, acr_ctrl); 923d13e36d7SAbhinav Kumar 924d13e36d7SAbhinav Kumar dp_write_link(catalog, MMSS_DP_AUDIO_ACR_CTRL, acr_ctrl); 925d13e36d7SAbhinav Kumar } 926d13e36d7SAbhinav Kumar 927d13e36d7SAbhinav Kumar void dp_catalog_audio_enable(struct dp_catalog *dp_catalog) 928d13e36d7SAbhinav Kumar { 929d13e36d7SAbhinav Kumar struct dp_catalog_private *catalog; 930d13e36d7SAbhinav Kumar bool enable; 931d13e36d7SAbhinav Kumar u32 audio_ctrl; 932d13e36d7SAbhinav Kumar 933d13e36d7SAbhinav Kumar if (!dp_catalog) 934d13e36d7SAbhinav Kumar return; 935d13e36d7SAbhinav Kumar 936d13e36d7SAbhinav Kumar catalog = container_of(dp_catalog, 937d13e36d7SAbhinav Kumar struct dp_catalog_private, dp_catalog); 938d13e36d7SAbhinav Kumar 939d13e36d7SAbhinav Kumar enable = !!dp_catalog->audio_data; 940d13e36d7SAbhinav Kumar audio_ctrl = dp_read_link(catalog, MMSS_DP_AUDIO_CFG); 941d13e36d7SAbhinav Kumar 942d13e36d7SAbhinav Kumar if (enable) 943d13e36d7SAbhinav Kumar audio_ctrl |= BIT(0); 944d13e36d7SAbhinav Kumar else 945d13e36d7SAbhinav Kumar audio_ctrl &= ~BIT(0); 946d13e36d7SAbhinav Kumar 947d13e36d7SAbhinav Kumar DRM_DEBUG_DP("dp_audio_cfg = 0x%x\n", audio_ctrl); 948d13e36d7SAbhinav Kumar 949d13e36d7SAbhinav Kumar dp_write_link(catalog, MMSS_DP_AUDIO_CFG, audio_ctrl); 950d13e36d7SAbhinav Kumar /* make sure audio engine is disabled */ 951d13e36d7SAbhinav Kumar wmb(); 952d13e36d7SAbhinav Kumar } 953d13e36d7SAbhinav Kumar 954d13e36d7SAbhinav Kumar void dp_catalog_audio_config_sdp(struct dp_catalog *dp_catalog) 955d13e36d7SAbhinav Kumar { 956d13e36d7SAbhinav Kumar struct dp_catalog_private *catalog; 957d13e36d7SAbhinav Kumar u32 sdp_cfg = 0; 958d13e36d7SAbhinav Kumar u32 sdp_cfg2 = 0; 959d13e36d7SAbhinav Kumar 960d13e36d7SAbhinav Kumar if (!dp_catalog) 961d13e36d7SAbhinav Kumar return; 962d13e36d7SAbhinav Kumar 963d13e36d7SAbhinav Kumar catalog = container_of(dp_catalog, 964d13e36d7SAbhinav Kumar struct dp_catalog_private, dp_catalog); 965d13e36d7SAbhinav Kumar 966d13e36d7SAbhinav Kumar sdp_cfg = dp_read_link(catalog, MMSS_DP_SDP_CFG); 967d13e36d7SAbhinav Kumar /* AUDIO_TIMESTAMP_SDP_EN */ 968d13e36d7SAbhinav Kumar sdp_cfg |= BIT(1); 969d13e36d7SAbhinav Kumar /* AUDIO_STREAM_SDP_EN */ 970d13e36d7SAbhinav Kumar sdp_cfg |= BIT(2); 971d13e36d7SAbhinav Kumar /* AUDIO_COPY_MANAGEMENT_SDP_EN */ 972d13e36d7SAbhinav Kumar sdp_cfg |= BIT(5); 973d13e36d7SAbhinav Kumar /* AUDIO_ISRC_SDP_EN */ 974d13e36d7SAbhinav Kumar sdp_cfg |= BIT(6); 975d13e36d7SAbhinav Kumar /* AUDIO_INFOFRAME_SDP_EN */ 976d13e36d7SAbhinav Kumar sdp_cfg |= BIT(20); 977d13e36d7SAbhinav Kumar 978d13e36d7SAbhinav Kumar DRM_DEBUG_DP("sdp_cfg = 0x%x\n", sdp_cfg); 979d13e36d7SAbhinav Kumar 980d13e36d7SAbhinav Kumar dp_write_link(catalog, MMSS_DP_SDP_CFG, sdp_cfg); 981d13e36d7SAbhinav Kumar 982d13e36d7SAbhinav Kumar sdp_cfg2 = dp_read_link(catalog, MMSS_DP_SDP_CFG2); 983d13e36d7SAbhinav Kumar /* IFRM_REGSRC -> Do not use reg values */ 984d13e36d7SAbhinav Kumar sdp_cfg2 &= ~BIT(0); 985d13e36d7SAbhinav Kumar /* AUDIO_STREAM_HB3_REGSRC-> Do not use reg values */ 986d13e36d7SAbhinav Kumar sdp_cfg2 &= ~BIT(1); 987d13e36d7SAbhinav Kumar 988d13e36d7SAbhinav Kumar DRM_DEBUG_DP("sdp_cfg2 = 0x%x\n", sdp_cfg2); 989d13e36d7SAbhinav Kumar 990d13e36d7SAbhinav Kumar dp_write_link(catalog, MMSS_DP_SDP_CFG2, sdp_cfg2); 991d13e36d7SAbhinav Kumar } 992d13e36d7SAbhinav Kumar 993d13e36d7SAbhinav Kumar void dp_catalog_audio_init(struct dp_catalog *dp_catalog) 994d13e36d7SAbhinav Kumar { 995d13e36d7SAbhinav Kumar struct dp_catalog_private *catalog; 996d13e36d7SAbhinav Kumar 997d13e36d7SAbhinav Kumar static u32 sdp_map[][DP_AUDIO_SDP_HEADER_MAX] = { 998d13e36d7SAbhinav Kumar { 999d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_STREAM_0, 1000d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_STREAM_1, 1001d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_STREAM_1, 1002d13e36d7SAbhinav Kumar }, 1003d13e36d7SAbhinav Kumar { 1004d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_TIMESTAMP_0, 1005d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_TIMESTAMP_1, 1006d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_TIMESTAMP_1, 1007d13e36d7SAbhinav Kumar }, 1008d13e36d7SAbhinav Kumar { 1009d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_INFOFRAME_0, 1010d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_INFOFRAME_1, 1011d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_INFOFRAME_1, 1012d13e36d7SAbhinav Kumar }, 1013d13e36d7SAbhinav Kumar { 1014d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_COPYMANAGEMENT_0, 1015d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_COPYMANAGEMENT_1, 1016d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_COPYMANAGEMENT_1, 1017d13e36d7SAbhinav Kumar }, 1018d13e36d7SAbhinav Kumar { 1019d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_ISRC_0, 1020d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_ISRC_1, 1021d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_ISRC_1, 1022d13e36d7SAbhinav Kumar }, 1023d13e36d7SAbhinav Kumar }; 1024d13e36d7SAbhinav Kumar 1025d13e36d7SAbhinav Kumar if (!dp_catalog) 1026d13e36d7SAbhinav Kumar return; 1027d13e36d7SAbhinav Kumar 1028d13e36d7SAbhinav Kumar catalog = container_of(dp_catalog, 1029d13e36d7SAbhinav Kumar struct dp_catalog_private, dp_catalog); 1030d13e36d7SAbhinav Kumar 1031d13e36d7SAbhinav Kumar catalog->audio_map = sdp_map; 1032d13e36d7SAbhinav Kumar } 1033d13e36d7SAbhinav Kumar 1034d13e36d7SAbhinav Kumar void dp_catalog_audio_sfe_level(struct dp_catalog *dp_catalog) 1035d13e36d7SAbhinav Kumar { 1036d13e36d7SAbhinav Kumar struct dp_catalog_private *catalog; 1037d13e36d7SAbhinav Kumar u32 mainlink_levels, safe_to_exit_level; 1038d13e36d7SAbhinav Kumar 1039d13e36d7SAbhinav Kumar if (!dp_catalog) 1040d13e36d7SAbhinav Kumar return; 1041d13e36d7SAbhinav Kumar 1042d13e36d7SAbhinav Kumar catalog = container_of(dp_catalog, 1043d13e36d7SAbhinav Kumar struct dp_catalog_private, dp_catalog); 1044d13e36d7SAbhinav Kumar 1045d13e36d7SAbhinav Kumar safe_to_exit_level = dp_catalog->audio_data; 1046d13e36d7SAbhinav Kumar mainlink_levels = dp_read_link(catalog, REG_DP_MAINLINK_LEVELS); 1047d13e36d7SAbhinav Kumar mainlink_levels &= 0xFE0; 1048d13e36d7SAbhinav Kumar mainlink_levels |= safe_to_exit_level; 1049d13e36d7SAbhinav Kumar 1050d13e36d7SAbhinav Kumar DRM_DEBUG_DP("mainlink_level = 0x%x, safe_to_exit_level = 0x%x\n", 1051d13e36d7SAbhinav Kumar mainlink_levels, safe_to_exit_level); 1052d13e36d7SAbhinav Kumar 1053d13e36d7SAbhinav Kumar dp_write_link(catalog, REG_DP_MAINLINK_LEVELS, mainlink_levels); 1054d13e36d7SAbhinav Kumar } 1055