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 193*9fc41843SKuogee Hsieh /** 194*9fc41843SKuogee Hsieh * dp_catalog_aux_reset() - reset AUX controller 195*9fc41843SKuogee Hsieh * 196*9fc41843SKuogee Hsieh * @aux: DP catalog structure 197*9fc41843SKuogee Hsieh * 198*9fc41843SKuogee Hsieh * return: void 199*9fc41843SKuogee Hsieh * 200*9fc41843SKuogee Hsieh * This function reset AUX controller 201*9fc41843SKuogee Hsieh * 202*9fc41843SKuogee Hsieh * NOTE: reset AUX controller will also clear any pending HPD related interrupts 203*9fc41843SKuogee Hsieh * 204*9fc41843SKuogee 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 498*9fc41843SKuogee Hsieh /** 499*9fc41843SKuogee Hsieh * dp_catalog_ctrl_reset() - reset DP controller 500*9fc41843SKuogee Hsieh * 501*9fc41843SKuogee Hsieh * @dp_catalog: DP catalog structure 502*9fc41843SKuogee Hsieh * 503*9fc41843SKuogee Hsieh * return: void 504*9fc41843SKuogee Hsieh * 505*9fc41843SKuogee Hsieh * This function reset the DP controller 506*9fc41843SKuogee Hsieh * 507*9fc41843SKuogee Hsieh * NOTE: reset DP controller will also clear any pending HPD related interrupts 508*9fc41843SKuogee Hsieh * 509*9fc41843SKuogee 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 585220b856aSTanmay Shah /* enable HPD interrupts */ 586220b856aSTanmay Shah dp_catalog_hpd_config_intr(dp_catalog, 587220b856aSTanmay Shah DP_DP_HPD_PLUG_INT_MASK | DP_DP_IRQ_HPD_INT_MASK 5888ede2eccSKuogee Hsieh | DP_DP_HPD_UNPLUG_INT_MASK | DP_DP_HPD_REPLUG_INT_MASK, true); 589c943b494SChandan Uddaraju 590220b856aSTanmay Shah /* Configure REFTIMER and enable it */ 591220b856aSTanmay Shah reftimer |= DP_DP_HPD_REFTIMER_ENABLE; 592c943b494SChandan Uddaraju dp_write_aux(catalog, REG_DP_DP_HPD_REFTIMER, reftimer); 593220b856aSTanmay Shah 594c943b494SChandan Uddaraju /* Enable HPD */ 595220b856aSTanmay Shah dp_write_aux(catalog, REG_DP_DP_HPD_CTRL, DP_DP_HPD_CTRL_HPD_EN); 596c943b494SChandan Uddaraju } 597220b856aSTanmay Shah 598231a04fcSKuogee Hsieh u32 dp_catalog_link_is_connected(struct dp_catalog *dp_catalog) 59919e52bcbSKuogee Hsieh { 60019e52bcbSKuogee Hsieh struct dp_catalog_private *catalog = container_of(dp_catalog, 60119e52bcbSKuogee Hsieh struct dp_catalog_private, dp_catalog); 60219e52bcbSKuogee Hsieh u32 status; 60319e52bcbSKuogee Hsieh 60419e52bcbSKuogee Hsieh status = dp_read_aux(catalog, REG_DP_DP_HPD_INT_STATUS); 60519e52bcbSKuogee Hsieh status >>= DP_DP_HPD_STATE_STATUS_BITS_SHIFT; 60619e52bcbSKuogee Hsieh status &= DP_DP_HPD_STATE_STATUS_BITS_MASK; 60719e52bcbSKuogee Hsieh 60819e52bcbSKuogee Hsieh return status; 60919e52bcbSKuogee Hsieh } 61019e52bcbSKuogee Hsieh 611220b856aSTanmay Shah u32 dp_catalog_hpd_get_intr_status(struct dp_catalog *dp_catalog) 612220b856aSTanmay Shah { 613220b856aSTanmay Shah struct dp_catalog_private *catalog = container_of(dp_catalog, 614220b856aSTanmay Shah struct dp_catalog_private, dp_catalog); 615220b856aSTanmay Shah int isr = 0; 616220b856aSTanmay Shah 617220b856aSTanmay Shah isr = dp_read_aux(catalog, REG_DP_DP_HPD_INT_STATUS); 618220b856aSTanmay Shah dp_write_aux(catalog, REG_DP_DP_HPD_INT_ACK, 619220b856aSTanmay Shah (isr & DP_DP_HPD_INT_MASK)); 620220b856aSTanmay Shah 621220b856aSTanmay Shah return isr; 622c943b494SChandan Uddaraju } 623c943b494SChandan Uddaraju 624c943b494SChandan Uddaraju int dp_catalog_ctrl_get_interrupt(struct dp_catalog *dp_catalog) 625c943b494SChandan Uddaraju { 626c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 627c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 628c943b494SChandan Uddaraju u32 intr, intr_ack; 629c943b494SChandan Uddaraju 630c943b494SChandan Uddaraju intr = dp_read_ahb(catalog, REG_DP_INTR_STATUS2); 631c943b494SChandan Uddaraju intr &= ~DP_INTERRUPT_STATUS2_MASK; 632c943b494SChandan Uddaraju intr_ack = (intr & DP_INTERRUPT_STATUS2) 633c943b494SChandan Uddaraju << DP_INTERRUPT_STATUS_ACK_SHIFT; 634c943b494SChandan Uddaraju dp_write_ahb(catalog, REG_DP_INTR_STATUS2, 635c943b494SChandan Uddaraju intr_ack | DP_INTERRUPT_STATUS2_MASK); 636c943b494SChandan Uddaraju 637c943b494SChandan Uddaraju return intr; 638c943b494SChandan Uddaraju } 639c943b494SChandan Uddaraju 640c943b494SChandan Uddaraju void dp_catalog_ctrl_phy_reset(struct dp_catalog *dp_catalog) 641c943b494SChandan Uddaraju { 642c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 643c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 644c943b494SChandan Uddaraju 645c943b494SChandan Uddaraju dp_write_ahb(catalog, REG_DP_PHY_CTRL, 646937f941cSStephen Boyd DP_PHY_CTRL_SW_RESET | DP_PHY_CTRL_SW_RESET_PLL); 647c943b494SChandan Uddaraju usleep_range(1000, 1100); /* h/w recommended delay */ 648c943b494SChandan Uddaraju dp_write_ahb(catalog, REG_DP_PHY_CTRL, 0x0); 649c943b494SChandan Uddaraju } 650c943b494SChandan Uddaraju 651c943b494SChandan Uddaraju int dp_catalog_ctrl_update_vx_px(struct dp_catalog *dp_catalog, 652c943b494SChandan Uddaraju u8 v_level, u8 p_level) 653c943b494SChandan Uddaraju { 654c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 655c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 656937f941cSStephen Boyd struct dp_io *dp_io = catalog->io; 657937f941cSStephen Boyd struct phy *phy = dp_io->phy; 658937f941cSStephen Boyd struct phy_configure_opts_dp *opts_dp = &dp_io->phy_opts.dp; 659c943b494SChandan Uddaraju 660937f941cSStephen Boyd /* TODO: Update for all lanes instead of just first one */ 661937f941cSStephen Boyd opts_dp->voltage[0] = v_level; 662937f941cSStephen Boyd opts_dp->pre[0] = p_level; 663937f941cSStephen Boyd opts_dp->set_voltages = 1; 664937f941cSStephen Boyd phy_configure(phy, &dp_io->phy_opts); 665937f941cSStephen Boyd opts_dp->set_voltages = 0; 666c943b494SChandan Uddaraju 667c943b494SChandan Uddaraju return 0; 668c943b494SChandan Uddaraju } 669c943b494SChandan Uddaraju 670c943b494SChandan Uddaraju void dp_catalog_ctrl_send_phy_pattern(struct dp_catalog *dp_catalog, 671c943b494SChandan Uddaraju u32 pattern) 672c943b494SChandan Uddaraju { 673c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 674c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 675c943b494SChandan Uddaraju u32 value = 0x0; 676c943b494SChandan Uddaraju 677c943b494SChandan Uddaraju /* Make sure to clear the current pattern before starting a new one */ 678c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_STATE_CTRL, 0x0); 679c943b494SChandan Uddaraju 680c943b494SChandan Uddaraju switch (pattern) { 6818ede2eccSKuogee Hsieh case DP_PHY_TEST_PATTERN_D10_2: 682c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_STATE_CTRL, 683c943b494SChandan Uddaraju DP_STATE_CTRL_LINK_TRAINING_PATTERN1); 6848ede2eccSKuogee Hsieh break; 6858ede2eccSKuogee Hsieh case DP_PHY_TEST_PATTERN_ERROR_COUNT: 6868ede2eccSKuogee Hsieh value &= ~(1 << 16); 6878ede2eccSKuogee Hsieh dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, 6888ede2eccSKuogee Hsieh value); 6898ede2eccSKuogee Hsieh value |= SCRAMBLER_RESET_COUNT_VALUE; 6908ede2eccSKuogee Hsieh dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, 6918ede2eccSKuogee Hsieh value); 6928ede2eccSKuogee Hsieh dp_write_link(catalog, REG_DP_MAINLINK_LEVELS, 6938ede2eccSKuogee Hsieh DP_MAINLINK_SAFE_TO_EXIT_LEVEL_2); 6948ede2eccSKuogee Hsieh dp_write_link(catalog, REG_DP_STATE_CTRL, 6958ede2eccSKuogee Hsieh DP_STATE_CTRL_LINK_SYMBOL_ERR_MEASURE); 6968ede2eccSKuogee Hsieh break; 6978ede2eccSKuogee Hsieh case DP_PHY_TEST_PATTERN_PRBS7: 698c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_STATE_CTRL, 699c943b494SChandan Uddaraju DP_STATE_CTRL_LINK_PRBS7); 7008ede2eccSKuogee Hsieh break; 7018ede2eccSKuogee Hsieh case DP_PHY_TEST_PATTERN_80BIT_CUSTOM: 702c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_STATE_CTRL, 703c943b494SChandan Uddaraju DP_STATE_CTRL_LINK_TEST_CUSTOM_PATTERN); 704c943b494SChandan Uddaraju /* 00111110000011111000001111100000 */ 705c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG0, 706c943b494SChandan Uddaraju 0x3E0F83E0); 707c943b494SChandan Uddaraju /* 00001111100000111110000011111000 */ 708c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG1, 709c943b494SChandan Uddaraju 0x0F83E0F8); 710c943b494SChandan Uddaraju /* 1111100000111110 */ 711c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG2, 712c943b494SChandan Uddaraju 0x0000F83E); 7138ede2eccSKuogee Hsieh break; 7148ede2eccSKuogee Hsieh case DP_PHY_TEST_PATTERN_CP2520: 7158ede2eccSKuogee Hsieh value = dp_read_link(catalog, REG_DP_MAINLINK_CTRL); 7168ede2eccSKuogee Hsieh value &= ~DP_MAINLINK_CTRL_SW_BYPASS_SCRAMBLER; 7178ede2eccSKuogee Hsieh dp_write_link(catalog, REG_DP_MAINLINK_CTRL, value); 7188ede2eccSKuogee Hsieh 719c943b494SChandan Uddaraju value = DP_HBR2_ERM_PATTERN; 720c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, 721c943b494SChandan Uddaraju value); 722c943b494SChandan Uddaraju value |= SCRAMBLER_RESET_COUNT_VALUE; 723c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, 724c943b494SChandan Uddaraju value); 725c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_MAINLINK_LEVELS, 726c943b494SChandan Uddaraju DP_MAINLINK_SAFE_TO_EXIT_LEVEL_2); 727c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_STATE_CTRL, 728c943b494SChandan Uddaraju DP_STATE_CTRL_LINK_SYMBOL_ERR_MEASURE); 7298ede2eccSKuogee Hsieh value = dp_read_link(catalog, REG_DP_MAINLINK_CTRL); 7308ede2eccSKuogee Hsieh value |= DP_MAINLINK_CTRL_ENABLE; 7318ede2eccSKuogee Hsieh dp_write_link(catalog, REG_DP_MAINLINK_CTRL, value); 7328ede2eccSKuogee Hsieh break; 7338ede2eccSKuogee Hsieh case DP_PHY_TEST_PATTERN_SEL_MASK: 7348ede2eccSKuogee Hsieh dp_write_link(catalog, REG_DP_MAINLINK_CTRL, 7358ede2eccSKuogee Hsieh DP_MAINLINK_CTRL_ENABLE); 7368ede2eccSKuogee Hsieh dp_write_link(catalog, REG_DP_STATE_CTRL, 7378ede2eccSKuogee Hsieh DP_STATE_CTRL_LINK_TRAINING_PATTERN4); 7388ede2eccSKuogee Hsieh break; 739c943b494SChandan Uddaraju default: 740c943b494SChandan Uddaraju DRM_DEBUG_DP("No valid test pattern requested:0x%x\n", pattern); 7418ede2eccSKuogee Hsieh break; 742c943b494SChandan Uddaraju } 743c943b494SChandan Uddaraju } 744c943b494SChandan Uddaraju 745c943b494SChandan Uddaraju u32 dp_catalog_ctrl_read_phy_pattern(struct dp_catalog *dp_catalog) 746c943b494SChandan Uddaraju { 747c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 748c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 749c943b494SChandan Uddaraju 750c943b494SChandan Uddaraju return dp_read_link(catalog, REG_DP_MAINLINK_READY); 751c943b494SChandan Uddaraju } 752c943b494SChandan Uddaraju 753c943b494SChandan Uddaraju /* panel related catalog functions */ 754c943b494SChandan Uddaraju int dp_catalog_panel_timing_cfg(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 dp_write_link(catalog, REG_DP_TOTAL_HOR_VER, 760c943b494SChandan Uddaraju dp_catalog->total); 761c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_START_HOR_VER_FROM_SYNC, 762c943b494SChandan Uddaraju dp_catalog->sync_start); 763c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_HSYNC_VSYNC_WIDTH_POLARITY, 764c943b494SChandan Uddaraju dp_catalog->width_blanking); 765c943b494SChandan Uddaraju dp_write_link(catalog, REG_DP_ACTIVE_HOR_VER, dp_catalog->dp_active); 766c943b494SChandan Uddaraju return 0; 767c943b494SChandan Uddaraju } 768c943b494SChandan Uddaraju 769c943b494SChandan Uddaraju void dp_catalog_panel_tpg_enable(struct dp_catalog *dp_catalog, 770c943b494SChandan Uddaraju struct drm_display_mode *drm_mode) 771c943b494SChandan Uddaraju { 772c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 773c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 774c943b494SChandan Uddaraju u32 hsync_period, vsync_period; 775c943b494SChandan Uddaraju u32 display_v_start, display_v_end; 776c943b494SChandan Uddaraju u32 hsync_start_x, hsync_end_x; 777c943b494SChandan Uddaraju u32 v_sync_width; 778c943b494SChandan Uddaraju u32 hsync_ctl; 779c943b494SChandan Uddaraju u32 display_hctl; 780c943b494SChandan Uddaraju 781c943b494SChandan Uddaraju /* TPG config parameters*/ 782c943b494SChandan Uddaraju hsync_period = drm_mode->htotal; 783c943b494SChandan Uddaraju vsync_period = drm_mode->vtotal; 784c943b494SChandan Uddaraju 785c943b494SChandan Uddaraju display_v_start = ((drm_mode->vtotal - drm_mode->vsync_start) * 786c943b494SChandan Uddaraju hsync_period); 787c943b494SChandan Uddaraju display_v_end = ((vsync_period - (drm_mode->vsync_start - 788c943b494SChandan Uddaraju drm_mode->vdisplay)) 789c943b494SChandan Uddaraju * hsync_period) - 1; 790c943b494SChandan Uddaraju 791c943b494SChandan Uddaraju display_v_start += drm_mode->htotal - drm_mode->hsync_start; 792c943b494SChandan Uddaraju display_v_end -= (drm_mode->hsync_start - drm_mode->hdisplay); 793c943b494SChandan Uddaraju 794c943b494SChandan Uddaraju hsync_start_x = drm_mode->htotal - drm_mode->hsync_start; 795c943b494SChandan Uddaraju hsync_end_x = hsync_period - (drm_mode->hsync_start - 796c943b494SChandan Uddaraju drm_mode->hdisplay) - 1; 797c943b494SChandan Uddaraju 798c943b494SChandan Uddaraju v_sync_width = drm_mode->vsync_end - drm_mode->vsync_start; 799c943b494SChandan Uddaraju 800c943b494SChandan Uddaraju hsync_ctl = (hsync_period << 16) | 801c943b494SChandan Uddaraju (drm_mode->hsync_end - drm_mode->hsync_start); 802c943b494SChandan Uddaraju display_hctl = (hsync_end_x << 16) | hsync_start_x; 803c943b494SChandan Uddaraju 804c943b494SChandan Uddaraju 805c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_CONFIG, 0x0); 806c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_HSYNC_CTL, hsync_ctl); 807c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_VSYNC_PERIOD_F0, vsync_period * 808c943b494SChandan Uddaraju hsync_period); 809c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F0, v_sync_width * 810c943b494SChandan Uddaraju hsync_period); 811c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_VSYNC_PERIOD_F1, 0); 812c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F1, 0); 813c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_DISPLAY_HCTL, display_hctl); 814c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_HCTL, 0); 815c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_INTF_DISPLAY_V_START_F0, display_v_start); 816c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_DISPLAY_V_END_F0, display_v_end); 817c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_INTF_DISPLAY_V_START_F1, 0); 818c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_DISPLAY_V_END_F1, 0); 819c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_V_START_F0, 0); 820c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_V_END_F0, 0); 821c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_V_START_F1, 0); 822c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_V_END_F1, 0); 823c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_INTF_POLARITY_CTL, 0); 824c943b494SChandan Uddaraju 825c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_TPG_MAIN_CONTROL, 826c943b494SChandan Uddaraju DP_TPG_CHECKERED_RECT_PATTERN); 827c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_TPG_VIDEO_CONFIG, 828c943b494SChandan Uddaraju DP_TPG_VIDEO_CONFIG_BPP_8BIT | 829c943b494SChandan Uddaraju DP_TPG_VIDEO_CONFIG_RGB); 830c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_BIST_ENABLE, 831c943b494SChandan Uddaraju DP_BIST_ENABLE_DPBIST_EN); 832c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_TIMING_ENGINE_EN, 833c943b494SChandan Uddaraju DP_TIMING_ENGINE_EN_EN); 834c943b494SChandan Uddaraju DRM_DEBUG_DP("%s: enabled tpg\n", __func__); 835c943b494SChandan Uddaraju } 836c943b494SChandan Uddaraju 837c943b494SChandan Uddaraju void dp_catalog_panel_tpg_disable(struct dp_catalog *dp_catalog) 838c943b494SChandan Uddaraju { 839c943b494SChandan Uddaraju struct dp_catalog_private *catalog = container_of(dp_catalog, 840c943b494SChandan Uddaraju struct dp_catalog_private, dp_catalog); 841c943b494SChandan Uddaraju 842c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_TPG_MAIN_CONTROL, 0x0); 843c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_BIST_ENABLE, 0x0); 844c943b494SChandan Uddaraju dp_write_p0(catalog, MMSS_DP_TIMING_ENGINE_EN, 0x0); 845c943b494SChandan Uddaraju } 846c943b494SChandan Uddaraju 847c943b494SChandan Uddaraju struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_io *io) 848c943b494SChandan Uddaraju { 849c943b494SChandan Uddaraju struct dp_catalog_private *catalog; 850c943b494SChandan Uddaraju 851c943b494SChandan Uddaraju if (!io) { 852c943b494SChandan Uddaraju DRM_ERROR("invalid input\n"); 853c943b494SChandan Uddaraju return ERR_PTR(-EINVAL); 854c943b494SChandan Uddaraju } 855c943b494SChandan Uddaraju 856c943b494SChandan Uddaraju catalog = devm_kzalloc(dev, sizeof(*catalog), GFP_KERNEL); 857c943b494SChandan Uddaraju if (!catalog) 858c943b494SChandan Uddaraju return ERR_PTR(-ENOMEM); 859c943b494SChandan Uddaraju 860c943b494SChandan Uddaraju catalog->dev = dev; 861c943b494SChandan Uddaraju catalog->io = io; 862c943b494SChandan Uddaraju 863c943b494SChandan Uddaraju return &catalog->dp_catalog; 864c943b494SChandan Uddaraju } 865d13e36d7SAbhinav Kumar 866d13e36d7SAbhinav Kumar void dp_catalog_audio_get_header(struct dp_catalog *dp_catalog) 867d13e36d7SAbhinav Kumar { 868d13e36d7SAbhinav Kumar struct dp_catalog_private *catalog; 869d13e36d7SAbhinav Kumar u32 (*sdp_map)[DP_AUDIO_SDP_HEADER_MAX]; 870d13e36d7SAbhinav Kumar enum dp_catalog_audio_sdp_type sdp; 871d13e36d7SAbhinav Kumar enum dp_catalog_audio_header_type header; 872d13e36d7SAbhinav Kumar 873d13e36d7SAbhinav Kumar if (!dp_catalog) 874d13e36d7SAbhinav Kumar return; 875d13e36d7SAbhinav Kumar 876d13e36d7SAbhinav Kumar catalog = container_of(dp_catalog, 877d13e36d7SAbhinav Kumar struct dp_catalog_private, dp_catalog); 878d13e36d7SAbhinav Kumar 879d13e36d7SAbhinav Kumar sdp_map = catalog->audio_map; 880d13e36d7SAbhinav Kumar sdp = dp_catalog->sdp_type; 881d13e36d7SAbhinav Kumar header = dp_catalog->sdp_header; 882d13e36d7SAbhinav Kumar 883d13e36d7SAbhinav Kumar dp_catalog->audio_data = dp_read_link(catalog, 884d13e36d7SAbhinav Kumar sdp_map[sdp][header]); 885d13e36d7SAbhinav Kumar } 886d13e36d7SAbhinav Kumar 887d13e36d7SAbhinav Kumar void dp_catalog_audio_set_header(struct dp_catalog *dp_catalog) 888d13e36d7SAbhinav Kumar { 889d13e36d7SAbhinav Kumar struct dp_catalog_private *catalog; 890d13e36d7SAbhinav Kumar u32 (*sdp_map)[DP_AUDIO_SDP_HEADER_MAX]; 891d13e36d7SAbhinav Kumar enum dp_catalog_audio_sdp_type sdp; 892d13e36d7SAbhinav Kumar enum dp_catalog_audio_header_type header; 893d13e36d7SAbhinav Kumar u32 data; 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 data = dp_catalog->audio_data; 905d13e36d7SAbhinav Kumar 906d13e36d7SAbhinav Kumar dp_write_link(catalog, sdp_map[sdp][header], data); 907d13e36d7SAbhinav Kumar } 908d13e36d7SAbhinav Kumar 909d13e36d7SAbhinav Kumar void dp_catalog_audio_config_acr(struct dp_catalog *dp_catalog) 910d13e36d7SAbhinav Kumar { 911d13e36d7SAbhinav Kumar struct dp_catalog_private *catalog; 912d13e36d7SAbhinav Kumar u32 acr_ctrl, select; 913d13e36d7SAbhinav Kumar 914d13e36d7SAbhinav Kumar if (!dp_catalog) 915d13e36d7SAbhinav Kumar return; 916d13e36d7SAbhinav Kumar 917d13e36d7SAbhinav Kumar catalog = container_of(dp_catalog, 918d13e36d7SAbhinav Kumar struct dp_catalog_private, dp_catalog); 919d13e36d7SAbhinav Kumar 920d13e36d7SAbhinav Kumar select = dp_catalog->audio_data; 921d13e36d7SAbhinav Kumar acr_ctrl = select << 4 | BIT(31) | BIT(8) | BIT(14); 922d13e36d7SAbhinav Kumar 923d13e36d7SAbhinav Kumar DRM_DEBUG_DP("select = 0x%x, acr_ctrl = 0x%x\n", select, acr_ctrl); 924d13e36d7SAbhinav Kumar 925d13e36d7SAbhinav Kumar dp_write_link(catalog, MMSS_DP_AUDIO_ACR_CTRL, acr_ctrl); 926d13e36d7SAbhinav Kumar } 927d13e36d7SAbhinav Kumar 928d13e36d7SAbhinav Kumar void dp_catalog_audio_enable(struct dp_catalog *dp_catalog) 929d13e36d7SAbhinav Kumar { 930d13e36d7SAbhinav Kumar struct dp_catalog_private *catalog; 931d13e36d7SAbhinav Kumar bool enable; 932d13e36d7SAbhinav Kumar u32 audio_ctrl; 933d13e36d7SAbhinav Kumar 934d13e36d7SAbhinav Kumar if (!dp_catalog) 935d13e36d7SAbhinav Kumar return; 936d13e36d7SAbhinav Kumar 937d13e36d7SAbhinav Kumar catalog = container_of(dp_catalog, 938d13e36d7SAbhinav Kumar struct dp_catalog_private, dp_catalog); 939d13e36d7SAbhinav Kumar 940d13e36d7SAbhinav Kumar enable = !!dp_catalog->audio_data; 941d13e36d7SAbhinav Kumar audio_ctrl = dp_read_link(catalog, MMSS_DP_AUDIO_CFG); 942d13e36d7SAbhinav Kumar 943d13e36d7SAbhinav Kumar if (enable) 944d13e36d7SAbhinav Kumar audio_ctrl |= BIT(0); 945d13e36d7SAbhinav Kumar else 946d13e36d7SAbhinav Kumar audio_ctrl &= ~BIT(0); 947d13e36d7SAbhinav Kumar 948d13e36d7SAbhinav Kumar DRM_DEBUG_DP("dp_audio_cfg = 0x%x\n", audio_ctrl); 949d13e36d7SAbhinav Kumar 950d13e36d7SAbhinav Kumar dp_write_link(catalog, MMSS_DP_AUDIO_CFG, audio_ctrl); 951d13e36d7SAbhinav Kumar /* make sure audio engine is disabled */ 952d13e36d7SAbhinav Kumar wmb(); 953d13e36d7SAbhinav Kumar } 954d13e36d7SAbhinav Kumar 955d13e36d7SAbhinav Kumar void dp_catalog_audio_config_sdp(struct dp_catalog *dp_catalog) 956d13e36d7SAbhinav Kumar { 957d13e36d7SAbhinav Kumar struct dp_catalog_private *catalog; 958d13e36d7SAbhinav Kumar u32 sdp_cfg = 0; 959d13e36d7SAbhinav Kumar u32 sdp_cfg2 = 0; 960d13e36d7SAbhinav Kumar 961d13e36d7SAbhinav Kumar if (!dp_catalog) 962d13e36d7SAbhinav Kumar return; 963d13e36d7SAbhinav Kumar 964d13e36d7SAbhinav Kumar catalog = container_of(dp_catalog, 965d13e36d7SAbhinav Kumar struct dp_catalog_private, dp_catalog); 966d13e36d7SAbhinav Kumar 967d13e36d7SAbhinav Kumar sdp_cfg = dp_read_link(catalog, MMSS_DP_SDP_CFG); 968d13e36d7SAbhinav Kumar /* AUDIO_TIMESTAMP_SDP_EN */ 969d13e36d7SAbhinav Kumar sdp_cfg |= BIT(1); 970d13e36d7SAbhinav Kumar /* AUDIO_STREAM_SDP_EN */ 971d13e36d7SAbhinav Kumar sdp_cfg |= BIT(2); 972d13e36d7SAbhinav Kumar /* AUDIO_COPY_MANAGEMENT_SDP_EN */ 973d13e36d7SAbhinav Kumar sdp_cfg |= BIT(5); 974d13e36d7SAbhinav Kumar /* AUDIO_ISRC_SDP_EN */ 975d13e36d7SAbhinav Kumar sdp_cfg |= BIT(6); 976d13e36d7SAbhinav Kumar /* AUDIO_INFOFRAME_SDP_EN */ 977d13e36d7SAbhinav Kumar sdp_cfg |= BIT(20); 978d13e36d7SAbhinav Kumar 979d13e36d7SAbhinav Kumar DRM_DEBUG_DP("sdp_cfg = 0x%x\n", sdp_cfg); 980d13e36d7SAbhinav Kumar 981d13e36d7SAbhinav Kumar dp_write_link(catalog, MMSS_DP_SDP_CFG, sdp_cfg); 982d13e36d7SAbhinav Kumar 983d13e36d7SAbhinav Kumar sdp_cfg2 = dp_read_link(catalog, MMSS_DP_SDP_CFG2); 984d13e36d7SAbhinav Kumar /* IFRM_REGSRC -> Do not use reg values */ 985d13e36d7SAbhinav Kumar sdp_cfg2 &= ~BIT(0); 986d13e36d7SAbhinav Kumar /* AUDIO_STREAM_HB3_REGSRC-> Do not use reg values */ 987d13e36d7SAbhinav Kumar sdp_cfg2 &= ~BIT(1); 988d13e36d7SAbhinav Kumar 989d13e36d7SAbhinav Kumar DRM_DEBUG_DP("sdp_cfg2 = 0x%x\n", sdp_cfg2); 990d13e36d7SAbhinav Kumar 991d13e36d7SAbhinav Kumar dp_write_link(catalog, MMSS_DP_SDP_CFG2, sdp_cfg2); 992d13e36d7SAbhinav Kumar } 993d13e36d7SAbhinav Kumar 994d13e36d7SAbhinav Kumar void dp_catalog_audio_init(struct dp_catalog *dp_catalog) 995d13e36d7SAbhinav Kumar { 996d13e36d7SAbhinav Kumar struct dp_catalog_private *catalog; 997d13e36d7SAbhinav Kumar 998d13e36d7SAbhinav Kumar static u32 sdp_map[][DP_AUDIO_SDP_HEADER_MAX] = { 999d13e36d7SAbhinav Kumar { 1000d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_STREAM_0, 1001d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_STREAM_1, 1002d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_STREAM_1, 1003d13e36d7SAbhinav Kumar }, 1004d13e36d7SAbhinav Kumar { 1005d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_TIMESTAMP_0, 1006d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_TIMESTAMP_1, 1007d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_TIMESTAMP_1, 1008d13e36d7SAbhinav Kumar }, 1009d13e36d7SAbhinav Kumar { 1010d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_INFOFRAME_0, 1011d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_INFOFRAME_1, 1012d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_INFOFRAME_1, 1013d13e36d7SAbhinav Kumar }, 1014d13e36d7SAbhinav Kumar { 1015d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_COPYMANAGEMENT_0, 1016d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_COPYMANAGEMENT_1, 1017d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_COPYMANAGEMENT_1, 1018d13e36d7SAbhinav Kumar }, 1019d13e36d7SAbhinav Kumar { 1020d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_ISRC_0, 1021d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_ISRC_1, 1022d13e36d7SAbhinav Kumar MMSS_DP_AUDIO_ISRC_1, 1023d13e36d7SAbhinav Kumar }, 1024d13e36d7SAbhinav Kumar }; 1025d13e36d7SAbhinav Kumar 1026d13e36d7SAbhinav Kumar if (!dp_catalog) 1027d13e36d7SAbhinav Kumar return; 1028d13e36d7SAbhinav Kumar 1029d13e36d7SAbhinav Kumar catalog = container_of(dp_catalog, 1030d13e36d7SAbhinav Kumar struct dp_catalog_private, dp_catalog); 1031d13e36d7SAbhinav Kumar 1032d13e36d7SAbhinav Kumar catalog->audio_map = sdp_map; 1033d13e36d7SAbhinav Kumar } 1034d13e36d7SAbhinav Kumar 1035d13e36d7SAbhinav Kumar void dp_catalog_audio_sfe_level(struct dp_catalog *dp_catalog) 1036d13e36d7SAbhinav Kumar { 1037d13e36d7SAbhinav Kumar struct dp_catalog_private *catalog; 1038d13e36d7SAbhinav Kumar u32 mainlink_levels, safe_to_exit_level; 1039d13e36d7SAbhinav Kumar 1040d13e36d7SAbhinav Kumar if (!dp_catalog) 1041d13e36d7SAbhinav Kumar return; 1042d13e36d7SAbhinav Kumar 1043d13e36d7SAbhinav Kumar catalog = container_of(dp_catalog, 1044d13e36d7SAbhinav Kumar struct dp_catalog_private, dp_catalog); 1045d13e36d7SAbhinav Kumar 1046d13e36d7SAbhinav Kumar safe_to_exit_level = dp_catalog->audio_data; 1047d13e36d7SAbhinav Kumar mainlink_levels = dp_read_link(catalog, REG_DP_MAINLINK_LEVELS); 1048d13e36d7SAbhinav Kumar mainlink_levels &= 0xFE0; 1049d13e36d7SAbhinav Kumar mainlink_levels |= safe_to_exit_level; 1050d13e36d7SAbhinav Kumar 1051d13e36d7SAbhinav Kumar DRM_DEBUG_DP("mainlink_level = 0x%x, safe_to_exit_level = 0x%x\n", 1052d13e36d7SAbhinav Kumar mainlink_levels, safe_to_exit_level); 1053d13e36d7SAbhinav Kumar 1054d13e36d7SAbhinav Kumar dp_write_link(catalog, REG_DP_MAINLINK_LEVELS, mainlink_levels); 1055d13e36d7SAbhinav Kumar } 1056