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