1 /* $NetBSD: anx_dp.c,v 1.2 2020/01/04 12:08:32 jmcneill Exp $ */ 2 3 /*- 4 * Copyright (c) 2019 Jonathan A. Kollasch <jakllsch@kollasch.net> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __KERNEL_RCSID(0, "$NetBSD: anx_dp.c,v 1.2 2020/01/04 12:08:32 jmcneill Exp $"); 31 32 #include <sys/param.h> 33 #include <sys/bus.h> 34 #include <sys/device.h> 35 #include <sys/intr.h> 36 #include <sys/systm.h> 37 #include <sys/kernel.h> 38 #include <sys/conf.h> 39 40 #include <dev/ic/anx_dp.h> 41 42 #if ANXDP_AUDIO 43 #include <dev/audio/audio_dai.h> 44 #endif 45 46 #include <drm/drmP.h> 47 #include <drm/drm_crtc.h> 48 #include <drm/drm_crtc_helper.h> 49 #include <drm/drm_dp_helper.h> 50 #include <drm/drm_edid.h> 51 52 #define ANXDP_DP_TX_VERSION 0x010 53 #define ANXDP_TX_SW_RESET 0x014 54 #define RESET_DP_TX __BIT(0) 55 #define ANXDP_FUNC_EN_1 0x018 56 #define MASTER_VID_FUNC_EN_N __BIT(7) 57 #define RK_VID_CAP_FUNC_EN_N __BIT(6) 58 #define SLAVE_VID_FUNC_EN_N __BIT(5) 59 #define RK_VID_FIFO_FUNC_EN_N __BIT(5) 60 #define AUD_FIFO_FUNC_EN_N __BIT(4) 61 #define AUD_FUNC_EN_N __BIT(3) 62 #define HDCP_FUNC_EN_N __BIT(2) 63 #define CRC_FUNC_EN_N __BIT(1) 64 #define SW_FUNC_EN_N __BIT(0) 65 #define ANXDP_FUNC_EN_2 0x01c 66 #define SSC_FUNC_EN_N __BIT(7) 67 #define AUX_FUNC_EN_N __BIT(2) 68 #define SERDES_FIFO_FUNC_EN_N __BIT(1) 69 #define LS_CLK_DOMAIN_FUNC_EN_N __BIT(0) 70 #define ANXDP_VIDEO_CTL_1 0x020 71 #define VIDEO_EN __BIT(7) 72 #define VIDEO_MUTE __BIT(6) 73 #define ANXDP_VIDEO_CTL_2 0x024 74 #define ANXDP_VIDEO_CTL_3 0x028 75 #define ANXDP_VIDEO_CTL_4 0x02c 76 #define ANXDP_VIDEO_CTL_8 0x03c 77 #define ANXDP_VIDEO_CTL_10 0x044 78 #define F_SEL __BIT(4) 79 #define SLAVE_I_SCAN_CFG __BIT(2) 80 #define SLAVE_VSYNC_P_CFG __BIT(1) 81 #define SLAVE_HSYNC_P_CFG __BIT(0) 82 #define ANXDP_PLL_REG_1 0x0fc 83 #define REF_CLK_24M __BIT(0) 84 #define RKANXDP_PD 0x12c 85 #define DP_INC_BG __BIT(7) 86 #define DP_EXP_PD __BIT(6) 87 #define DP_PHY_PD __BIT(5) 88 #define RK_AUX_PD __BIT(5) 89 #define AUX_PD __BIT(4) 90 #define RK_PLL_PD __BIT(4) 91 #define CHx_PD(x) __BIT(x) /* 0<=x<=3 */ 92 #define DP_ALL_PD __BITS(7,0) 93 #define ANXDP_LANE_MAP 0x35c 94 #define ANXDP_ANALOG_CTL_1 0x370 95 #define TX_TERMINAL_CTRL_50_OHM __BIT(4) 96 #define ANXDP_ANALOG_CTL_2 0x374 97 #define SEL_24M __BIT(3) 98 #define TX_DVDD_BIT_1_0625V 0x4 99 #define ANXDP_ANALOG_CTL_3 0x378 100 #define DRIVE_DVDD_BIT_1_0625V (0x4 << 5) 101 #define VCO_BIT_600_MICRO (0x5 << 0) 102 #define ANXDP_PLL_FILTER_CTL_1 0x37c 103 #define PD_RING_OSC __BIT(6) 104 #define AUX_TERMINAL_CTRL_50_OHM (2 << 4) 105 #define TX_CUR1_2X __BIT(2) 106 #define TX_CUR_16_MA 3 107 #define ANXDP_TX_AMP_TUNING_CTL 0x380 108 #define ANXDP_AUX_HW_RETRY_CTL 0x390 109 #define AUX_BIT_PERIOD_EXPECTED_DELAY(x) __SHIFTIN((x), __BITS(10,8)) 110 #define AUX_HW_RETRY_INTERVAL_600_US __SHIFTIN(0, __BITS(4,3)) 111 #define AUX_HW_RETRY_INTERVAL_800_US __SHIFTIN(1, __BITS(4,3)) 112 #define AUX_HW_RETRY_INTERVAL_1000_US __SHIFTIN(2, __BITS(4,3)) 113 #define AUX_HW_RETRY_INTERVAL_1800_US __SHIFTIN(3, __BITS(4,3)) 114 #define AUX_HW_RETRY_COUNT_SEL(x) __SHIFTIN((x), __BITS(2,0)) 115 #define ANXDP_COMMON_INT_STA_1 0x3c4 116 #define PLL_LOCK_CHG __BIT(6) 117 #define ANXDP_COMMON_INT_STA_2 0x3c8 118 #define ANXDP_COMMON_INT_STA_3 0x3cc 119 #define ANXDP_COMMON_INT_STA_4 0x3d0 120 #define ANXDP_DP_INT_STA 0x3dc 121 #define INT_HPD __BIT(6) 122 #define HW_TRAINING_FINISH __BIT(5) 123 #define RPLY_RECEIV __BIT(1) 124 #define AUX_ERR __BIT(0) 125 #define ANXDP_SYS_CTL_1 0x600 126 #define DET_STA __BIT(2) 127 #define FORCE_DET __BIT(1) 128 #define DET_CTRL __BIT(0) 129 #define ANXDP_SYS_CTL_2 0x604 130 #define ANXDP_SYS_CTL_3 0x608 131 #define HPD_STATUS __BIT(6) 132 #define F_HPD __BIT(5) 133 #define HPD_CTRL __BIT(4) 134 #define HDCP_RDY __BIT(3) 135 #define STRM_VALID __BIT(2) 136 #define F_VALID __BIT(1) 137 #define VALID_CTRL __BIT(0) 138 #define ANXDP_SYS_CTL_4 0x60c 139 #define ANXDP_PKT_SEND_CTL 0x640 140 #define ANXDP_HDCP_CTL 0x648 141 #define ANXDP_LINK_BW_SET 0x680 142 #define ANXDP_LANE_COUNT_SET 0x684 143 #define ANXDP_TRAINING_PTN_SET 0x688 144 #define SCRAMBLING_DISABLE __BIT(5) 145 #define SW_TRAINING_PATTERN_SET_PTN2 __SHIFTIN(2, __BITS(1,0)) 146 #define SW_TRAINING_PATTERN_SET_PTN1 __SHIFTIN(1, __BITS(1,0)) 147 #define ANXDP_LNx_LINK_TRAINING_CTL(x) (0x68c + 4 * (x)) /* 0 <= x <= 3 */ 148 #define MAX_PRE_REACH __BIT(5) 149 #define PRE_EMPHASIS_SET(x) __SHIFTIN((x), __BITS(4,3)) 150 #define MAX_DRIVE_REACH __BIT(2) 151 #define DRIVE_CURRENT_SET(x) __SHIFTIN((x), __BITS(1,0)) 152 #define ANXDP_DEBUG_CTL 0x6c0 153 #define PLL_LOCK __BIT(4) 154 #define F_PLL_LOCK __BIT(3) 155 #define PLL_LOCK_CTRL __BIT(2) 156 #define PN_INV __BIT(0) 157 #define ANXDP_LINK_DEBUG_CTL 0x6e0 158 #define ANXDP_PLL_CTL 0x71c 159 #define ANXDP_PHY_PD 0x720 160 #define ANXDP_PHY_TEST 0x724 161 #define MACRO_RST __BIT(5) 162 #define ANXDP_M_AUD_GEN_FILTER_TH 0x778 163 #define ANXDP_AUX_CH_STA 0x780 164 #define AUX_BUSY __BIT(4) 165 #define AUX_STATUS(x) __SHIFTOUT((x), __BITS(3,0)) 166 #define ANXDP_AUX_ERR_NUM 0x784 167 #define ANXDP_AUX_CH_DEFER_CTL 0x788 168 #define DEFER_CTRL_EN __BIT(7) 169 #define DEFER_COUNT(x) __SHIFTIN((x), __BITS(6,0)) 170 #define ANXDP_AUX_RX_COMM 0x78c 171 #define AUX_RX_COMM_I2C_DEFER __BIT(3) 172 #define AUX_RX_COMM_AUX_DEFER __BIT(1) 173 #define ANXDP_BUFFER_DATA_CTL 0x790 174 #define BUF_CLR __BIT(7) 175 #define BUF_DATA_COUNT(x) __SHIFTIN((x), __BITS(4,0)) 176 #define ANXDP_AUX_CH_CTL_1 0x794 177 #define AUX_LENGTH(x) __SHIFTIN((x) - 1, __BITS(7,4)) 178 #define AUX_TX_COMM(x) __SHIFTOUT(x, __BITS(3,0)) 179 #define AUX_TX_COMM_DP __BIT(3) 180 #define AUX_TX_COMM_MOT __BIT(2) 181 #define AUX_TX_COMM_READ __BIT(0) 182 #define ANXDP_AUX_ADDR_7_0 0x798 183 #define AUX_ADDR_7_0(x) (((x) >> 0) & 0xff) 184 #define ANXDP_AUX_ADDR_15_8 0x79c 185 #define AUX_ADDR_15_8(x) (((x) >> 8) & 0xff) 186 #define ANXDP_AUX_ADDR_19_16 0x7a0 187 #define AUX_ADDR_19_16(x) (((x) >> 16) & 0xf) 188 #define ANXDP_AUX_CH_CTL_2 0x7a4 189 #define ADDR_ONLY __BIT(1) 190 #define AUX_EN __BIT(0) 191 #define ANXDP_BUF_DATA(x) (0x7c0 + 4 * (x)) 192 #define ANXDP_SOC_GENERAL_CTL 0x800 193 #define AUDIO_MODE_SPDIF_MODE __BIT(8) 194 #define VIDEO_MODE_SLAVE_MODE __BIT(1) 195 #define ANXDP_CRC_CON 0x890 196 #define ANXDP_PLL_REG_2 0x9e4 197 #define ANXDP_PLL_REG_3 0x9e8 198 #define ANXDP_PLL_REG_4 0x9ec 199 #define ANXDP_PLL_REG_5 0xa00 200 201 #if ANXDP_AUDIO 202 enum anxdp_dai_mixer_ctrl { 203 ANXDP_DAI_OUTPUT_CLASS, 204 ANXDP_DAI_INPUT_CLASS, 205 206 ANXDP_DAI_OUTPUT_MASTER_VOLUME, 207 ANXDP_DAI_INPUT_DAC_VOLUME, 208 209 ANXDP_DAI_MIXER_CTRL_LAST 210 }; 211 212 static void 213 anxdp_audio_init(struct anxdp_softc *sc) 214 { 215 } 216 #endif 217 218 static inline const bool 219 isrockchip(struct anxdp_softc * const sc) 220 { 221 return (sc->sc_flags & ANXDP_FLAG_ROCKCHIP) != 0; 222 } 223 224 static enum drm_connector_status 225 anxdp_connector_detect(struct drm_connector *connector, bool force) 226 { 227 #if 0 228 struct anxdp_connector *anxdp_connector = to_anxdp_connector(connector); 229 struct anxdp_softc * const sc = anxdp_connector->sc; 230 231 /* XXX HPD */ 232 #endif 233 return connector_status_connected; 234 } 235 236 static void 237 anxdp_connector_destroy(struct drm_connector *connector) 238 { 239 drm_connector_unregister(connector); 240 drm_connector_cleanup(connector); 241 } 242 243 static const struct drm_connector_funcs anxdp_connector_funcs = { 244 .dpms = drm_helper_connector_dpms, 245 .detect = anxdp_connector_detect, 246 .fill_modes = drm_helper_probe_single_connector_modes, 247 .destroy = anxdp_connector_destroy, 248 }; 249 250 static void 251 anxdp_analog_power_up_all(struct anxdp_softc * const sc) 252 { 253 const bus_size_t pd_reg = isrockchip(sc) ? RKANXDP_PD : ANXDP_PHY_PD; 254 255 bus_space_write_4(sc->sc_bst, sc->sc_bsh, pd_reg, DP_ALL_PD); 256 delay(15); 257 bus_space_write_4(sc->sc_bst, sc->sc_bsh, pd_reg, 258 DP_ALL_PD & ~DP_INC_BG); 259 delay(15); 260 bus_space_write_4(sc->sc_bst, sc->sc_bsh, pd_reg, 0); 261 } 262 263 static int 264 anxdp_await_pll_lock(struct anxdp_softc * const sc) 265 { 266 u_int timeout; 267 268 for (timeout = 0; timeout < 100; timeout++) { 269 if ((bus_space_read_4(sc->sc_bst, sc->sc_bsh, ANXDP_DEBUG_CTL) & 270 PLL_LOCK) != 0) 271 return 0; 272 delay(20); 273 } 274 275 return ETIMEDOUT; 276 } 277 278 static void 279 anxdp_init_hpd(struct anxdp_softc * const sc) 280 { 281 uint32_t sc3; 282 283 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_COMMON_INT_STA_4, 0x7); 284 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_DP_INT_STA, INT_HPD); 285 286 sc3 = bus_space_read_4(sc->sc_bst, sc->sc_bsh, ANXDP_SYS_CTL_3); 287 sc3 &= ~(F_HPD | HPD_CTRL); 288 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_SYS_CTL_3, sc3); 289 290 sc3 = bus_space_read_4(sc->sc_bst, sc->sc_bsh, ANXDP_SYS_CTL_3); 291 sc3 |= F_HPD | HPD_CTRL; 292 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_SYS_CTL_3, sc3); 293 } 294 295 static void 296 anxdp_init_aux(struct anxdp_softc * const sc) 297 { 298 uint32_t fe2, pd, hrc; 299 const bus_size_t pd_reg = isrockchip(sc) ? RKANXDP_PD : ANXDP_PHY_PD; 300 const uint32_t pd_mask = isrockchip(sc) ? RK_AUX_PD : AUX_PD; 301 302 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_DP_INT_STA, 303 RPLY_RECEIV | AUX_ERR); 304 305 pd = bus_space_read_4(sc->sc_bst, sc->sc_bsh, pd_reg); 306 pd |= pd_mask; 307 bus_space_write_4(sc->sc_bst, sc->sc_bsh, pd_reg, pd); 308 309 delay(11); 310 311 pd = bus_space_read_4(sc->sc_bst, sc->sc_bsh, pd_reg); 312 pd &= ~pd_mask; 313 bus_space_write_4(sc->sc_bst, sc->sc_bsh, pd_reg, pd); 314 315 fe2 = bus_space_read_4(sc->sc_bst, sc->sc_bsh, ANXDP_FUNC_EN_2); 316 fe2 |= AUX_FUNC_EN_N; 317 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_FUNC_EN_2, fe2); 318 319 hrc = AUX_HW_RETRY_COUNT_SEL(0) | AUX_HW_RETRY_INTERVAL_600_US; 320 if (!isrockchip(sc)) 321 hrc |= AUX_BIT_PERIOD_EXPECTED_DELAY(3); 322 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_AUX_HW_RETRY_CTL, hrc); 323 324 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_AUX_CH_DEFER_CTL, 325 DEFER_CTRL_EN | DEFER_COUNT(1)); 326 327 fe2 = bus_space_read_4(sc->sc_bst, sc->sc_bsh, ANXDP_FUNC_EN_2); 328 fe2 &= ~AUX_FUNC_EN_N; 329 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_FUNC_EN_2, fe2); 330 } 331 332 static int 333 anxdp_connector_get_modes(struct drm_connector *connector) 334 { 335 struct anxdp_connector *anxdp_connector = to_anxdp_connector(connector); 336 struct anxdp_softc * const sc = anxdp_connector->sc; 337 struct edid *pedid = NULL; 338 int error; 339 340 pedid = drm_get_edid(connector, &sc->sc_dpaux.ddc); 341 342 #if ANXDP_AUDIO 343 if (pedid) { 344 anxdp_connector->monitor_audio = 345 drm_detect_monitor_audio(pedid); 346 } else { 347 anxdp_connector->monitor_audio = false; 348 } 349 350 #endif 351 drm_mode_connector_update_edid_property(connector, pedid); 352 if (pedid == NULL) 353 return 0; 354 355 error = drm_add_edid_modes(connector, pedid); 356 drm_edid_to_eld(connector, pedid); 357 358 if (pedid != NULL) 359 kfree(pedid); 360 361 return error; 362 } 363 364 static struct drm_encoder * 365 anxdp_connector_best_encoder(struct drm_connector *connector) 366 { 367 int enc_id = connector->encoder_ids[0]; 368 struct drm_mode_object *obj; 369 struct drm_encoder *encoder = NULL; 370 371 if (enc_id) { 372 obj = drm_mode_object_find(connector->dev, enc_id, 373 DRM_MODE_OBJECT_ENCODER); 374 if (obj == NULL) 375 return NULL; 376 encoder = obj_to_encoder(obj); 377 } 378 379 return encoder; 380 } 381 382 static const struct drm_connector_helper_funcs anxdp_connector_helper_funcs = { 383 .get_modes = anxdp_connector_get_modes, 384 .best_encoder = anxdp_connector_best_encoder, 385 }; 386 387 static int 388 anxdp_bridge_attach(struct drm_bridge *bridge) 389 { 390 struct anxdp_softc * const sc = bridge->driver_private; 391 struct anxdp_connector *anxdp_connector = &sc->sc_connector; 392 struct drm_connector *connector = &anxdp_connector->base; 393 int error; 394 395 anxdp_connector->sc = sc; 396 397 connector->polled = 398 DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT; 399 connector->interlace_allowed = 0; 400 connector->doublescan_allowed = 0; 401 402 drm_connector_init(bridge->dev, connector, &anxdp_connector_funcs, 403 connector->connector_type); 404 drm_connector_helper_add(connector, &anxdp_connector_helper_funcs); 405 406 error = drm_mode_connector_attach_encoder(connector, bridge->encoder); 407 if (error != 0) 408 return error; 409 410 return drm_connector_register(connector); 411 } 412 413 static void 414 anxdp_macro_reset(struct anxdp_softc * const sc) 415 { 416 uint32_t val; 417 418 val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, ANXDP_PHY_TEST); 419 val |= MACRO_RST; 420 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_PHY_TEST, val); 421 delay(10); 422 val &= ~MACRO_RST; 423 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_PHY_TEST, val); 424 } 425 426 static void 427 anxdp_link_start(struct anxdp_softc * const sc, struct drm_dp_link * const link) 428 { 429 uint8_t training[4]; 430 uint32_t val; 431 432 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_LINK_BW_SET, drm_dp_link_rate_to_bw_code(link->rate)); 433 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_LANE_COUNT_SET, link->num_lanes); 434 if (0 != drm_dp_link_configure(&sc->sc_dpaux, link)) 435 return; 436 437 for (u_int i = 0; i < link->num_lanes; i++) { 438 val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, 439 ANXDP_LNx_LINK_TRAINING_CTL(i)); 440 val &= ~(PRE_EMPHASIS_SET(3)|DRIVE_CURRENT_SET(3)); 441 val |= PRE_EMPHASIS_SET(0); 442 bus_space_write_4(sc->sc_bst, sc->sc_bsh, 443 ANXDP_LNx_LINK_TRAINING_CTL(i), val); 444 } 445 446 if (anxdp_await_pll_lock(sc) != 0) { 447 device_printf(sc->sc_dev, "PLL lock timeout\n"); 448 } 449 450 for (u_int i = 0; i < link->num_lanes; i++) { 451 training[i] = DP_TRAIN_PRE_EMPH_LEVEL_0 | 452 DP_TRAIN_VOLTAGE_SWING_LEVEL_0; 453 } 454 455 drm_dp_dpcd_write(&sc->sc_dpaux, DP_TRAINING_LANE0_SET, training, 456 link->num_lanes); 457 } 458 459 static void 460 anxdp_process_clock_recovery(struct anxdp_softc * const sc, 461 struct drm_dp_link * const link) 462 { 463 u_int i, tries; 464 uint8_t link_status[DP_LINK_STATUS_SIZE]; 465 uint8_t training[4]; 466 467 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_TRAINING_PTN_SET, 468 SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN1); 469 drm_dp_dpcd_writeb(&sc->sc_dpaux, DP_TRAINING_PATTERN_SET, 470 DP_LINK_SCRAMBLING_DISABLE | DP_TRAINING_PATTERN_1); 471 472 tries = 0; 473 again: 474 if (tries++ >= 10) { 475 device_printf(sc->sc_dev, "cr fail\n"); 476 return; 477 } 478 drm_dp_link_train_clock_recovery_delay(sc->sc_dpcd); 479 if (DP_LINK_STATUS_SIZE != 480 drm_dp_dpcd_read_link_status(&sc->sc_dpaux, link_status)) { 481 return; 482 } 483 if (!drm_dp_clock_recovery_ok(link_status, link->num_lanes)) { 484 goto cr_fail; 485 } 486 487 return; 488 489 cr_fail: 490 for (i = 0; i < link->num_lanes; i++) { 491 uint8_t vs, pe; 492 vs = drm_dp_get_adjust_request_voltage(link_status, i); 493 pe = drm_dp_get_adjust_request_pre_emphasis(link_status, i); 494 training[i] = vs | pe; 495 } 496 for (i = 0; i < link->num_lanes; i++) { 497 bus_space_write_4(sc->sc_bst, sc->sc_bsh, 498 ANXDP_LNx_LINK_TRAINING_CTL(i), training[i]); 499 } 500 drm_dp_dpcd_write(&sc->sc_dpaux, DP_TRAINING_LANE0_SET, training, 501 link->num_lanes); 502 goto again; 503 } 504 505 static void 506 anxdp_process_eq(struct anxdp_softc * const sc, struct drm_dp_link * const link) 507 { 508 u_int i, tries; 509 uint8_t link_status[DP_LINK_STATUS_SIZE]; 510 uint8_t training[4]; 511 512 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_TRAINING_PTN_SET, 513 SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN2); 514 drm_dp_dpcd_writeb(&sc->sc_dpaux, DP_TRAINING_PATTERN_SET, 515 DP_LINK_SCRAMBLING_DISABLE | DP_TRAINING_PATTERN_2); 516 517 tries = 0; 518 again: 519 if (tries++ >= 10) { 520 device_printf(sc->sc_dev, "eq fail\n"); 521 return; 522 } 523 drm_dp_link_train_channel_eq_delay(sc->sc_dpcd); 524 if (DP_LINK_STATUS_SIZE != 525 drm_dp_dpcd_read_link_status(&sc->sc_dpaux, link_status)) { 526 return; 527 } 528 if (!drm_dp_channel_eq_ok(link_status, link->num_lanes)) { 529 goto eq_fail; 530 } 531 532 return; 533 534 eq_fail: 535 for (i = 0; i < link->num_lanes; i++) { 536 uint8_t vs, pe; 537 vs = drm_dp_get_adjust_request_voltage(link_status, i); 538 pe = drm_dp_get_adjust_request_pre_emphasis(link_status, i); 539 training[i] = vs | pe; 540 } 541 for (i = 0; i < link->num_lanes; i++) { 542 bus_space_write_4(sc->sc_bst, sc->sc_bsh, 543 ANXDP_LNx_LINK_TRAINING_CTL(i), training[i]); 544 } 545 drm_dp_dpcd_write(&sc->sc_dpaux, DP_TRAINING_LANE0_SET, training, 546 link->num_lanes); 547 goto again; 548 } 549 550 static void 551 anxdp_train_link(struct anxdp_softc * const sc) 552 { 553 struct drm_dp_link link; 554 555 anxdp_macro_reset(sc); 556 557 if (0 != drm_dp_link_probe(&sc->sc_dpaux, &link)) { 558 device_printf(sc->sc_dev, "link probe failed\n"); 559 return; 560 } 561 if (0 != drm_dp_link_power_up(&sc->sc_dpaux, &link)) 562 return; 563 if (DP_RECEIVER_CAP_SIZE != drm_dp_dpcd_read(&sc->sc_dpaux, DP_DPCD_REV, 564 sc->sc_dpcd, DP_RECEIVER_CAP_SIZE)) 565 return; 566 567 anxdp_link_start(sc, &link); 568 anxdp_process_clock_recovery(sc, &link); 569 anxdp_process_eq(sc, &link); 570 571 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_TRAINING_PTN_SET, 0); 572 drm_dp_dpcd_writeb(&sc->sc_dpaux, DP_TRAINING_PATTERN_SET, 573 DP_TRAINING_PATTERN_DISABLE); 574 575 } 576 577 static void 578 anxdp_bringup(struct anxdp_softc * const sc) 579 { 580 uint32_t val; 581 582 val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, ANXDP_VIDEO_CTL_1); 583 val &= ~VIDEO_EN; 584 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_VIDEO_CTL_1, val); 585 586 val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, ANXDP_VIDEO_CTL_1); 587 val &= ~VIDEO_MUTE; 588 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_VIDEO_CTL_1, val); 589 590 val = SW_FUNC_EN_N; 591 if (isrockchip(sc)) { 592 val |= RK_VID_CAP_FUNC_EN_N | RK_VID_FIFO_FUNC_EN_N; 593 } else { 594 val |= MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N | 595 AUD_FIFO_FUNC_EN_N | AUD_FUNC_EN_N | HDCP_FUNC_EN_N; 596 } 597 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_FUNC_EN_1, val); 598 599 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_FUNC_EN_2, 600 SSC_FUNC_EN_N | AUX_FUNC_EN_N | SERDES_FIFO_FUNC_EN_N | 601 LS_CLK_DOMAIN_FUNC_EN_N); 602 603 delay(30); 604 605 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_M_AUD_GEN_FILTER_TH, 2); 606 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_SOC_GENERAL_CTL, 0x101); 607 608 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_TX_SW_RESET, 609 RESET_DP_TX); 610 611 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_ANALOG_CTL_1, 612 TX_TERMINAL_CTRL_50_OHM); 613 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_ANALOG_CTL_2, 614 SEL_24M | TX_DVDD_BIT_1_0625V); 615 if (isrockchip(sc)) { 616 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_PLL_REG_1, 617 REF_CLK_24M); 618 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_PLL_REG_2, 619 0x95); 620 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_PLL_REG_3, 621 0x40); 622 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_PLL_REG_4, 623 0x58); 624 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_PLL_REG_5, 625 0x22); 626 } 627 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_ANALOG_CTL_3, 628 DRIVE_DVDD_BIT_1_0625V | VCO_BIT_600_MICRO); 629 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_PLL_FILTER_CTL_1, 630 PD_RING_OSC | AUX_TERMINAL_CTRL_50_OHM | TX_CUR1_2X | TX_CUR_16_MA); 631 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_TX_AMP_TUNING_CTL, 0); 632 633 val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, ANXDP_FUNC_EN_1); 634 val &= ~SW_FUNC_EN_N; 635 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_FUNC_EN_1, val); 636 637 anxdp_analog_power_up_all(sc); 638 639 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_COMMON_INT_STA_1, 640 PLL_LOCK_CHG); 641 642 val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, ANXDP_DEBUG_CTL); 643 val &= ~(F_PLL_LOCK | PLL_LOCK_CTRL); 644 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_DEBUG_CTL, val); 645 646 if (anxdp_await_pll_lock(sc) != 0) { 647 device_printf(sc->sc_dev, "PLL lock timeout\n"); 648 } 649 650 val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, ANXDP_FUNC_EN_2); 651 val &= ~(SERDES_FIFO_FUNC_EN_N | LS_CLK_DOMAIN_FUNC_EN_N | 652 AUX_FUNC_EN_N); 653 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_FUNC_EN_2, val); 654 655 anxdp_init_hpd(sc); 656 anxdp_init_aux(sc); 657 } 658 659 static void 660 anxdp_bridge_enable(struct drm_bridge *bridge) 661 { 662 struct anxdp_softc * const sc = bridge->driver_private; 663 uint32_t val; 664 665 val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, ANXDP_FUNC_EN_1); 666 if (isrockchip(sc)) { 667 val &= ~(RK_VID_CAP_FUNC_EN_N | RK_VID_FIFO_FUNC_EN_N); 668 } else { 669 val &= ~(MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N); 670 val |= MASTER_VID_FUNC_EN_N; 671 } 672 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_FUNC_EN_1, val); 673 674 val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, ANXDP_VIDEO_CTL_10); 675 val &= ~(SLAVE_I_SCAN_CFG|SLAVE_VSYNC_P_CFG|SLAVE_HSYNC_P_CFG); 676 if ((sc->sc_curmode.flags & DRM_MODE_FLAG_INTERLACE) != 0) 677 val |= SLAVE_I_SCAN_CFG; 678 if ((sc->sc_curmode.flags & DRM_MODE_FLAG_NVSYNC) != 0) 679 val |= SLAVE_VSYNC_P_CFG; 680 if ((sc->sc_curmode.flags & DRM_MODE_FLAG_NHSYNC) != 0) 681 val |= SLAVE_HSYNC_P_CFG; 682 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_VIDEO_CTL_10, val); 683 684 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_SOC_GENERAL_CTL, 685 AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE); 686 687 anxdp_train_link(sc); 688 689 val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, ANXDP_VIDEO_CTL_1); 690 val |= VIDEO_EN; 691 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_VIDEO_CTL_1, val); 692 693 if (sc->sc_panel != NULL && 694 sc->sc_panel->funcs != NULL && 695 sc->sc_panel->funcs->enable != NULL) 696 sc->sc_panel->funcs->enable(sc->sc_panel); 697 #if ANXDP_AUDIO 698 699 if (sc->sc_connector.monitor_audio) 700 anxdp_audio_init(sc); 701 #endif 702 } 703 704 static void 705 anxdp_bridge_pre_enable(struct drm_bridge *bridge) 706 { 707 } 708 709 static void 710 anxdp_bridge_disable(struct drm_bridge *bridge) 711 { 712 } 713 714 static void 715 anxdp_bridge_post_disable(struct drm_bridge *bridge) 716 { 717 } 718 719 static void 720 anxdp_bridge_mode_set(struct drm_bridge *bridge, 721 struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) 722 { 723 struct anxdp_softc * const sc = bridge->driver_private; 724 725 sc->sc_curmode = *adjusted_mode; 726 } 727 728 static bool 729 anxdp_bridge_mode_fixup(struct drm_bridge *bridge, 730 const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) 731 { 732 return true; 733 } 734 735 static const struct drm_bridge_funcs anxdp_bridge_funcs = { 736 .attach = anxdp_bridge_attach, 737 .enable = anxdp_bridge_enable, 738 .pre_enable = anxdp_bridge_pre_enable, 739 .disable = anxdp_bridge_disable, 740 .post_disable = anxdp_bridge_post_disable, 741 .mode_set = anxdp_bridge_mode_set, 742 .mode_fixup = anxdp_bridge_mode_fixup, 743 }; 744 745 #if ANXDP_AUDIO 746 static int 747 anxdp_dai_set_format(audio_dai_tag_t dai, u_int format) 748 { 749 return 0; 750 } 751 752 static int 753 anxdp_dai_add_device(audio_dai_tag_t dai, audio_dai_tag_t aux) 754 { 755 /* Not supported */ 756 return 0; 757 } 758 759 static void 760 anxdp_audio_swvol_codec(audio_filter_arg_t *arg) 761 { 762 struct anxdp_softc * const sc = arg->context; 763 const aint_t *src; 764 aint_t *dst; 765 u_int sample_count; 766 u_int i; 767 768 src = arg->src; 769 dst = arg->dst; 770 sample_count = arg->count * arg->srcfmt->channels; 771 for (i = 0; i < sample_count; i++) { 772 aint2_t v = (aint2_t)(*src++); 773 v = v * sc->sc_swvol / 255; 774 *dst++ = (aint_t)v; 775 } 776 } 777 778 static int 779 anxdp_audio_set_format(void *priv, int setmode, 780 const audio_params_t *play, const audio_params_t *rec, 781 audio_filter_reg_t *pfil, audio_filter_reg_t *rfil) 782 { 783 struct anxdp_softc * const sc = priv; 784 785 pfil->codec = anxdp_audio_swvol_codec; 786 pfil->context = sc; 787 788 return 0; 789 } 790 791 static int 792 anxdp_audio_set_port(void *priv, mixer_ctrl_t *mc) 793 { 794 struct anxdp_softc * const sc = priv; 795 796 switch (mc->dev) { 797 case ANXDP_DAI_OUTPUT_MASTER_VOLUME: 798 case ANXDP_DAI_INPUT_DAC_VOLUME: 799 sc->sc_swvol = mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; 800 return 0; 801 default: 802 return ENXIO; 803 } 804 } 805 806 static int 807 anxdp_audio_get_port(void *priv, mixer_ctrl_t *mc) 808 { 809 struct anxdp_softc * const sc = priv; 810 811 switch (mc->dev) { 812 case ANXDP_DAI_OUTPUT_MASTER_VOLUME: 813 case ANXDP_DAI_INPUT_DAC_VOLUME: 814 mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = sc->sc_swvol; 815 mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = sc->sc_swvol; 816 return 0; 817 default: 818 return ENXIO; 819 } 820 } 821 822 static int 823 anxdp_audio_query_devinfo(void *priv, mixer_devinfo_t *di) 824 { 825 switch (di->index) { 826 case ANXDP_DAI_OUTPUT_CLASS: 827 di->mixer_class = di->index; 828 strcpy(di->label.name, AudioCoutputs); 829 di->type = AUDIO_MIXER_CLASS; 830 di->next = di->prev = AUDIO_MIXER_LAST; 831 return 0; 832 833 case ANXDP_DAI_INPUT_CLASS: 834 di->mixer_class = di->index; 835 strcpy(di->label.name, AudioCinputs); 836 di->type = AUDIO_MIXER_CLASS; 837 di->next = di->prev = AUDIO_MIXER_LAST; 838 return 0; 839 840 case ANXDP_DAI_OUTPUT_MASTER_VOLUME: 841 di->mixer_class = ANXDP_DAI_OUTPUT_CLASS; 842 strcpy(di->label.name, AudioNmaster); 843 di->un.v.delta = 1; 844 di->un.v.num_channels = 2; 845 strcpy(di->un.v.units.name, AudioNvolume); 846 di->type = AUDIO_MIXER_VALUE; 847 di->next = di->prev = AUDIO_MIXER_LAST; 848 return 0; 849 850 case ANXDP_DAI_INPUT_DAC_VOLUME: 851 di->mixer_class = ANXDP_DAI_INPUT_CLASS; 852 strcpy(di->label.name, AudioNdac); 853 di->un.v.delta = 1; 854 di->un.v.num_channels = 2; 855 strcpy(di->un.v.units.name, AudioNvolume); 856 di->type = AUDIO_MIXER_VALUE; 857 di->next = di->prev = AUDIO_MIXER_LAST; 858 return 0; 859 860 default: 861 return ENXIO; 862 } 863 } 864 865 static const struct audio_hw_if anxdp_dai_hw_if = { 866 .set_format = anxdp_audio_set_format, 867 .set_port = anxdp_audio_set_port, 868 .get_port = anxdp_audio_get_port, 869 .query_devinfo = anxdp_audio_query_devinfo, 870 }; 871 #endif 872 873 static ssize_t 874 anxdp_dp_aux_transfer(struct drm_dp_aux *dpaux, struct drm_dp_aux_msg *dpmsg) 875 { 876 struct anxdp_softc * const sc = container_of(dpaux, struct anxdp_softc, 877 sc_dpaux); 878 size_t loop_timeout = 0; 879 uint32_t val; 880 size_t i; 881 ssize_t ret = 0; 882 883 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_BUFFER_DATA_CTL, 884 BUF_CLR); 885 886 val = AUX_LENGTH(dpmsg->size); 887 if ((dpmsg->request & DP_AUX_I2C_MOT) != 0) 888 val |= AUX_TX_COMM_MOT; 889 890 switch (dpmsg->request & ~DP_AUX_I2C_MOT) { 891 case DP_AUX_I2C_WRITE: 892 break; 893 case DP_AUX_I2C_READ: 894 val |= AUX_TX_COMM_READ; 895 break; 896 case DP_AUX_NATIVE_WRITE: 897 val |= AUX_TX_COMM_DP; 898 break; 899 case DP_AUX_NATIVE_READ: 900 val |= AUX_TX_COMM_READ | AUX_TX_COMM_DP; 901 break; 902 } 903 904 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_AUX_CH_CTL_1, val); 905 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_AUX_ADDR_7_0, 906 AUX_ADDR_7_0(dpmsg->address)); 907 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_AUX_ADDR_15_8, 908 AUX_ADDR_15_8(dpmsg->address)); 909 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_AUX_ADDR_19_16, 910 AUX_ADDR_19_16(dpmsg->address)); 911 912 if (!(dpmsg->request & DP_AUX_I2C_READ)) { 913 for (i = 0; i < dpmsg->size; i++) { 914 bus_space_write_4(sc->sc_bst, sc->sc_bsh, 915 ANXDP_BUF_DATA(i), 916 ((const uint8_t *)(dpmsg->buffer))[i]); 917 ret++; 918 } 919 } 920 921 922 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_AUX_CH_CTL_2, 923 AUX_EN | ((dpmsg->size == 0) ? ADDR_ONLY : 0)); 924 925 loop_timeout = 0; 926 val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, ANXDP_AUX_CH_CTL_2); 927 while ((val & AUX_EN) != 0) { 928 if (++loop_timeout > 20000) { 929 ret = -ETIMEDOUT; 930 goto out; 931 } 932 delay(25); 933 val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, 934 ANXDP_AUX_CH_CTL_2); 935 } 936 937 loop_timeout = 0; 938 val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, ANXDP_DP_INT_STA); 939 while (!(val & RPLY_RECEIV)) { 940 if (++loop_timeout > 2000) { 941 ret = -ETIMEDOUT; 942 goto out; 943 } 944 delay(10); 945 val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, 946 ANXDP_DP_INT_STA); 947 } 948 949 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_DP_INT_STA, 950 RPLY_RECEIV); 951 952 val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, ANXDP_DP_INT_STA); 953 if ((val & AUX_ERR) != 0) { 954 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_DP_INT_STA, 955 AUX_ERR); 956 ret = -EREMOTEIO; 957 goto out; 958 } 959 960 val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, ANXDP_AUX_CH_STA); 961 if (AUX_STATUS(val) != 0) { 962 ret = -EREMOTEIO; 963 goto out; 964 } 965 966 if ((dpmsg->request & DP_AUX_I2C_READ)) { 967 for (i = 0; i < dpmsg->size; i++) { 968 val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, 969 ANXDP_BUF_DATA(i)); 970 ((uint8_t *)(dpmsg->buffer))[i] = val & 0xffU; 971 ret++; 972 } 973 } 974 975 val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, ANXDP_AUX_RX_COMM); 976 if (val == AUX_RX_COMM_AUX_DEFER) 977 dpmsg->reply = DP_AUX_NATIVE_REPLY_DEFER; 978 else if (val == AUX_RX_COMM_I2C_DEFER) 979 dpmsg->reply = DP_AUX_I2C_REPLY_DEFER; 980 else if ((dpmsg->request & ~DP_AUX_I2C_MOT) == DP_AUX_I2C_WRITE || 981 (dpmsg->request & ~DP_AUX_I2C_MOT) == DP_AUX_I2C_READ) 982 dpmsg->reply = DP_AUX_I2C_REPLY_ACK; 983 else if ((dpmsg->request & ~DP_AUX_I2C_MOT) == DP_AUX_NATIVE_WRITE || 984 (dpmsg->request & ~DP_AUX_I2C_MOT) == DP_AUX_NATIVE_READ) 985 dpmsg->reply = DP_AUX_NATIVE_REPLY_ACK; 986 987 out: 988 if (ret < 0) 989 anxdp_init_aux(sc); 990 991 return ret; 992 } 993 994 void 995 anxdp_dpms(struct anxdp_softc *sc, int mode) 996 { 997 switch (mode) { 998 case DRM_MODE_DPMS_ON: 999 pmf_event_inject(NULL, PMFE_DISPLAY_ON); 1000 break; 1001 case DRM_MODE_DPMS_STANDBY: 1002 case DRM_MODE_DPMS_SUSPEND: 1003 case DRM_MODE_DPMS_OFF: 1004 pmf_event_inject(NULL, PMFE_DISPLAY_OFF); 1005 break; 1006 } 1007 } 1008 1009 int 1010 anxdp_attach(struct anxdp_softc *sc) 1011 { 1012 #if ANXDP_AUDIO 1013 sc->sc_swvol = 255; 1014 1015 /* 1016 * Initialize audio DAI 1017 */ 1018 sc->sc_dai.dai_set_format = anxdp_dai_set_format; 1019 sc->sc_dai.dai_add_device = anxdp_dai_add_device; 1020 sc->sc_dai.dai_hw_if = &anxdp_dai_hw_if; 1021 sc->sc_dai.dai_dev = sc->sc_dev; 1022 sc->sc_dai.dai_priv = sc; 1023 #endif 1024 1025 sc->sc_dpaux.name = "DP Aux"; 1026 sc->sc_dpaux.transfer = anxdp_dp_aux_transfer; 1027 sc->sc_dpaux.dev = sc->sc_dev; 1028 if (drm_dp_aux_register(&sc->sc_dpaux) != 0) { 1029 device_printf(sc->sc_dev, "registering DP Aux failed\n"); 1030 } 1031 1032 anxdp_bringup(sc); 1033 1034 return 0; 1035 } 1036 1037 int 1038 anxdp_bind(struct anxdp_softc *sc, struct drm_encoder *encoder) 1039 { 1040 int error; 1041 1042 sc->sc_bridge.driver_private = sc; 1043 sc->sc_bridge.funcs = &anxdp_bridge_funcs; 1044 sc->sc_bridge.encoder = encoder; 1045 1046 error = drm_bridge_attach(encoder->dev, &sc->sc_bridge); 1047 if (error != 0) 1048 return EIO; 1049 1050 encoder->bridge = &sc->sc_bridge; 1051 1052 if (sc->sc_panel != NULL && sc->sc_panel->funcs != NULL && sc->sc_panel->funcs->prepare != NULL) 1053 sc->sc_panel->funcs->prepare(sc->sc_panel); 1054 1055 return 0; 1056 } 1057 1058 void anxdp0_dump(void); 1059 1060 void 1061 anxdp0_dump(void) 1062 { 1063 extern struct cfdriver anxdp_cd; 1064 struct anxdp_softc * const sc = device_lookup_private(&anxdp_cd, 0); 1065 size_t i; 1066 1067 if (sc == NULL) 1068 return; 1069 1070 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_SYS_CTL_1, 1071 bus_space_read_4(sc->sc_bst, sc->sc_bsh, ANXDP_SYS_CTL_1)); 1072 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_SYS_CTL_2, 1073 bus_space_read_4(sc->sc_bst, sc->sc_bsh, ANXDP_SYS_CTL_2)); 1074 bus_space_write_4(sc->sc_bst, sc->sc_bsh, ANXDP_SYS_CTL_3, 1075 bus_space_read_4(sc->sc_bst, sc->sc_bsh, ANXDP_SYS_CTL_3)); 1076 for (i = 0x000; i < 0xb00; i += 4) 1077 device_printf(sc->sc_dev, "%03zx 0x%08x\n", i, 1078 bus_space_read_4(sc->sc_bst, sc->sc_bsh, i)); 1079 } 1080