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