uboot/board/gdsys/common/dp501.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2012
   4 * Dirk Eibach,  Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
   5 */
   6
   7/* Parade Technologies Inc. DP501 DisplayPort DVI/HDMI Transmitter */
   8
   9#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
  10
  11#include <common.h>
  12#include <asm/io.h>
  13#include <errno.h>
  14#include <i2c.h>
  15
  16#define DP501_I2C_ADDR 0x08
  17
  18#ifdef CONFIG_SYS_DP501_I2C
  19int dp501_i2c[] = CONFIG_SYS_DP501_I2C;
  20#endif
  21
  22#ifdef CONFIG_SYS_DP501_BASE
  23int dp501_base[] = CONFIG_SYS_DP501_BASE;
  24#endif
  25
  26static void dp501_setbits(u8 addr, u8 reg, u8 mask)
  27{
  28        u8 val;
  29
  30        val = i2c_reg_read(addr, reg);
  31        setbits_8(&val, mask);
  32        i2c_reg_write(addr, reg, val);
  33}
  34
  35static void dp501_clrbits(u8 addr, u8 reg, u8 mask)
  36{
  37        u8 val;
  38
  39        val = i2c_reg_read(addr, reg);
  40        clrbits_8(&val, mask);
  41        i2c_reg_write(addr, reg, val);
  42}
  43
  44static int dp501_detect_cable_adapter(u8 addr)
  45{
  46        u8 val = i2c_reg_read(addr, 0x00);
  47
  48        return !(val & 0x04);
  49}
  50
  51static void dp501_link_training(u8 addr)
  52{
  53        u8 val;
  54        u8 link_bw;
  55        u8 max_lane_cnt;
  56        u8 lane_cnt;
  57
  58        val = i2c_reg_read(addr, 0x51);
  59        if (val >= 0x0a)
  60                link_bw = 0x0a;
  61        else
  62                link_bw = 0x06;
  63        if (link_bw != val)
  64                printf("DP sink supports %d Mbps link rate, set to %d Mbps\n",
  65                       val * 270, link_bw * 270);
  66        i2c_reg_write(addr, 0x5d, link_bw); /* set link_bw */
  67        val = i2c_reg_read(addr, 0x52);
  68        max_lane_cnt = val & 0x1f;
  69        if (max_lane_cnt >= 4)
  70                lane_cnt = 4;
  71        else
  72                lane_cnt = max_lane_cnt;
  73        if (lane_cnt != max_lane_cnt)
  74                printf("DP sink supports %d lanes, set to %d lanes\n",
  75                       max_lane_cnt, lane_cnt);
  76        i2c_reg_write(addr, 0x5e, lane_cnt | (val & 0x80)); /* set lane_cnt */
  77        val = i2c_reg_read(addr, 0x53);
  78        i2c_reg_write(addr, 0x5c, val); /* set downspread_ctl */
  79
  80        i2c_reg_write(addr, 0x5f, 0x0d); /* start training */
  81}
  82
  83void dp501_powerup(u8 addr)
  84{
  85        dp501_clrbits(addr, 0x0a, 0x30); /* power on encoder */
  86        dp501_setbits(addr, 0x0a, 0x0e); /* block HDCP and MCCS on I2C bride*/
  87        i2c_reg_write(addr, 0x27, 0x30); /* Hardware auto detect DVO timing */
  88        dp501_setbits(addr, 0x72, 0x80); /* DPCD read enable */
  89        dp501_setbits(addr, 0x30, 0x20); /* RS polynomial select */
  90        i2c_reg_write(addr, 0x71, 0x20); /* Enable Aux burst write */
  91        dp501_setbits(addr, 0x78, 0x30); /* Disable HPD2 IRQ */
  92        dp501_clrbits(addr, 0x2f, 0x40); /* Link FIFO reset selection */
  93        dp501_clrbits(addr, 0x60, 0x20); /* Enable scrambling */
  94
  95#ifdef CONFIG_SYS_DP501_VCAPCTRL0
  96        i2c_reg_write(addr, 0x24, CONFIG_SYS_DP501_VCAPCTRL0);
  97#else
  98        i2c_reg_write(addr, 0x24, 0xc0); /* SDR mode 0, ext. H/VSYNC */
  99#endif
 100
 101#ifdef CONFIG_SYS_DP501_DIFFERENTIAL
 102        i2c_reg_write(addr + 2, 0x24, 0x10); /* clock input differential */
 103        i2c_reg_write(addr + 2, 0x25, 0x04);
 104        i2c_reg_write(addr + 2, 0x26, 0x10);
 105#else
 106        i2c_reg_write(addr + 2, 0x24, 0x02); /* clock input single ended */
 107#endif
 108
 109        i2c_reg_write(addr + 2, 0x1a, 0x04); /* SPDIF input method TTL */
 110
 111        i2c_reg_write(addr + 2, 0x00, 0x18); /* driving strength */
 112        i2c_reg_write(addr + 2, 0x03, 0x06); /* driving strength */
 113        i2c_reg_write(addr, 0x2c, 0x00); /* configure N value */
 114        i2c_reg_write(addr, 0x2d, 0x00); /* configure N value */
 115        i2c_reg_write(addr, 0x2e, 0x0c); /* configure N value */
 116        i2c_reg_write(addr, 0x76, 0xff); /* clear all interrupt */
 117        dp501_setbits(addr, 0x78, 0x03); /* clear all interrupt */
 118        i2c_reg_write(addr, 0x75, 0xf8); /* aux channel reset */
 119        i2c_reg_write(addr, 0x75, 0x00); /* clear aux channel reset */
 120        i2c_reg_write(addr, 0x87, 0x7f); /* set retry counter as 7
 121                                            retry interval 400us */
 122
 123        if (dp501_detect_cable_adapter(addr)) {
 124                printf("DVI/HDMI cable adapter detected\n");
 125                i2c_reg_write(addr, 0x5e, 0x04); /* enable 4 channel */
 126                dp501_clrbits(addr, 0x00, 0x08); /* DVI/HDMI HDCP operation */
 127        } else {
 128                printf("no DVI/HDMI cable adapter detected\n");
 129                dp501_setbits(addr, 0x00, 0x08); /* for DP HDCP operation */
 130
 131                dp501_link_training(addr);
 132        }
 133}
 134
 135void dp501_powerdown(u8 addr)
 136{
 137        dp501_setbits(addr, 0x0a, 0x30); /* power down encoder, standby mode */
 138}
 139
 140
 141int dp501_probe(unsigned screen, bool power)
 142{
 143#ifdef CONFIG_SYS_DP501_BASE
 144        uint8_t dp501_addr = dp501_base[screen];
 145#else
 146        uint8_t dp501_addr = DP501_I2C_ADDR;
 147#endif
 148
 149#ifdef CONFIG_SYS_DP501_I2C
 150        i2c_set_bus_num(dp501_i2c[screen]);
 151#endif
 152
 153        if (i2c_probe(dp501_addr))
 154                return -1;
 155
 156        dp501_powerup(dp501_addr);
 157
 158        return 0;
 159}
 160
 161#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
 162