coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
ps8640.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <delay.h>
4 #include <device/i2c_simple.h>
5 #include <edid.h>
6 #include <console/console.h>
7 #include <timer.h>
8 #include <dp_aux.h>
9 #include "ps8640.h"
10 
12 {
13  int ret;
14  u8 edid[EDID_LENGTH * 2];
15  int edid_size = EDID_LENGTH;
16 
20 
21  if (ret != 0) {
22  printk(BIOS_INFO, "Failed to read EDID.\n");
23  return -1;
24  }
25 
26  /* check if edid have extension flag, and read additional EDID data */
28  edid_size += EDID_LENGTH;
31  if (ret != 0) {
32  printk(BIOS_INFO, "Failed to read EDID ext block.\n");
33  return -1;
34  }
35  }
36 
37  if (decode_edid(edid, edid_size, out) != EDID_CONFORMANT) {
38  printk(BIOS_INFO, "Failed to decode EDID.\n");
39  return -1;
40  }
41 
42  return 0;
43 }
44 
46 {
47  u8 set_vdo_done;
48  struct stopwatch sw;
49 
50  mdelay(200);
52 
53  while (true) {
54  i2c_readb(bus, chip + 2, PAGE2_GPIO_H, &set_vdo_done);
55  if ((set_vdo_done & PS_GPIO9) == PS_GPIO9)
56  break;
57  if (stopwatch_expired(&sw)) {
58  printk(BIOS_INFO, "Failed to init ps8640.\n");
59  return -1;
60  }
61 
62  mdelay(20);
63  }
64 
65  mdelay(50);
66 
67  /*
68  * The Manufacturer Command Set (MCS) is a device dependent interface
69  * intended for factory programming of the display module default
70  * parameters. Once the display module is configured, the MCS shall be
71  * disabled by the manufacturer. Once disabled, all MCS commands are
72  * ignored by the display interface.
73  */
75  MCS_EN_SHIFT);
80 
81  return 0;
82 }
83 
85  uint8_t chip,
86  unsigned int target_reg,
87  unsigned int total_size,
88  enum aux_request request,
89  uint8_t *data)
90 {
91  int i;
93  uint8_t buf;
94  uint8_t reg;
95  int ret;
96 
97  if (target_reg & ~SWAUX_ADDR_MASK)
98  return CB_ERR;
99 
100  while (total_size) {
101  length = MIN(total_size, DP_AUX_MAX_PAYLOAD_BYTES);
102  total_size -= length;
103 
105  if (ret)
106  return CB_ERR;
107 
108  enum i2c_over_aux cmd = dp_get_aux_cmd(request, total_size);
110  (target_reg >> 16) | (cmd << 4)) ||
111  i2c_writeb(bus, chip, PAGE0_SWAUX_ADDR_15_8, target_reg >> 8) ||
112  i2c_writeb(bus, chip, PAGE0_SWAUX_ADDR_7_0, target_reg)) {
113  return CB_ERR;
114  }
115 
116  if (dp_aux_request_is_write(request)) {
117  reg = PAGE0_SWAUX_WDATA;
118  for (i = 0; i < length; i++) {
119  ret = i2c_writeb(bus, chip, reg++, *data++);
120  if (ret)
121  return CB_ERR;
122  }
123  } else {
124  if (length == 0)
126  else
128  }
129 
131  if (ret)
132  return CB_ERR;
133 
134  if (!wait_ms(100, !i2c_readb(bus, chip, PAGE0_SWAUX_CTRL, &buf) &&
135  !(buf & SWAUX_SEND)))
136  return CB_ERR;
137 
139  return CB_ERR;
140 
141  switch (buf & SWAUX_STATUS_MASK) {
142  case SWAUX_STATUS_NACK:
146  return CB_ERR;
147  case SWAUX_STATUS_ACKM:
148  length = buf & SWAUX_M_MASK;
149  break;
150  }
151 
152  if (length && !dp_aux_request_is_write(request)) {
153  reg = PAGE0_SWAUX_RDATA;
154  for (i = 0; i < length; i++) {
155  if (i2c_readb(bus, chip, reg++, &buf))
156  return CB_ERR;
157  *data++ = buf;
158  }
159  }
160  }
161 
162  return CB_SUCCESS;
163 }
164 
166 {
167  uint8_t val;
168 
171  DPCD_WRITE, &val);
172 
173  val = 0xff;
175  DPCD_WRITE, &val);
176 
179  DPCD_WRITE, &val);
180 }
#define MIN(a, b)
Definition: helpers.h:37
cb_err
coreboot error codes
Definition: cb_err.h:15
@ CB_ERR
Generic error code.
Definition: cb_err.h:17
@ CB_SUCCESS
Call completed successfully.
Definition: cb_err.h:16
#define printk(level,...)
Definition: stdlib.h:16
void mdelay(unsigned int msecs)
Definition: delay.c:2
int i2c_write_field(unsigned int bus, uint8_t chip, uint8_t reg, uint8_t data, uint8_t mask, uint8_t shift)
Definition: i2c.c:20
#define DP_BACKLIGHT_MODE_SET
Definition: dp_aux.h:35
#define DP_AUX_MAX_PAYLOAD_BYTES
Definition: dp_aux.h:42
#define DP_DISPLAY_CONTROL_REGISTER
Definition: dp_aux.h:38
bool dp_aux_request_is_write(enum aux_request request)
Definition: dp_aux.c:5
#define DP_BACKLIGHT_BRIGHTNESS_MSB
Definition: dp_aux.h:40
aux_request
Definition: dp_aux.h:25
@ DPCD_WRITE
Definition: dp_aux.h:27
enum i2c_over_aux dp_get_aux_cmd(enum aux_request request, uint32_t remaining_after_this)
Definition: dp_aux.c:17
#define DP_BACKLIGHT_ENABLE
Definition: dp_aux.h:39
i2c_over_aux
Definition: dp_aux.h:14
#define DP_BACKLIGHT_CONTROL_MODE_DPCD
Definition: dp_aux.h:37
@ EDID_EXTENSION_FLAG
Definition: dp_aux.h:11
@ EDID_I2C_ADDR
Definition: dp_aux.h:10
@ EDID_LENGTH
Definition: dp_aux.h:9
uint64_t length
Definition: fw_cfg_if.h:1
static struct tpm_chip chip
Definition: tis.c:17
static int i2c_writeb(unsigned int bus, uint8_t slave, uint8_t reg, uint8_t data)
Write a byte with one segment in one frame.
Definition: i2c_simple.h:131
static int i2c_readb(unsigned int bus, uint8_t slave, uint8_t reg, uint8_t *data)
Read a byte with two segments in one frame.
Definition: i2c_simple.h:109
static int i2c_read_bytes(unsigned int bus, uint8_t slave, uint8_t reg, uint8_t *data, int len)
Read multi-bytes with two segments in one frame.
Definition: i2c_simple.h:87
@ EDID_CONFORMANT
Definition: edid.h:90
int decode_edid(unsigned char *edid, int size, struct edid *out)
Definition: edid.c:1104
static int stopwatch_expired(struct stopwatch *sw)
Definition: timer.h:152
#define wait_ms(timeout_ms, condition)
Definition: timer.h:215
static void stopwatch_init_msecs_expire(struct stopwatch *sw, long ms)
Definition: timer.h:133
#define BIOS_INFO
BIOS_INFO - Expected events.
Definition: loglevel.h:113
static uint8_t * buf
Definition: uart.c:7
void ps8640_backlight_enable(uint8_t bus, uint8_t chip)
Definition: ps8640.c:165
int ps8640_init(uint8_t bus, uint8_t chip)
Definition: ps8640.c:45
int ps8640_get_edid(uint8_t bus, uint8_t chip, struct edid *out)
Definition: ps8640.c:11
static enum cb_err ps8640_bridge_aux_request(uint8_t bus, uint8_t chip, unsigned int target_reg, unsigned int total_size, enum aux_request request, uint8_t *data)
Definition: ps8640.c:84
@ PAGE0_SWAUX_WDATA
Definition: ps8640.h:36
@ PAGE0_SWAUX_STATUS
Definition: ps8640.h:40
@ PAGE0_AUXCH_CFG3
Definition: ps8640.h:27
@ PAGE0_SWAUX_ADDR_15_8
Definition: ps8640.h:30
@ SWAUX_STATUS_NACK
Definition: ps8640.h:43
@ SWAUX_SEND
Definition: ps8640.h:39
@ SWAUX_STATUS_INVALID
Definition: ps8640.h:46
@ SWAUX_STATUS_MASK
Definition: ps8640.h:42
@ PAGE0_SWAUX_RDATA
Definition: ps8640.h:37
@ SWAUX_ADDR_MASK
Definition: ps8640.h:32
@ PAGE0_SWAUX_CTRL
Definition: ps8640.h:38
@ SWAUX_M_MASK
Definition: ps8640.h:41
@ AUXCH_CFG3_RESET
Definition: ps8640.h:28
@ PAGE0_SWAUX_ADDR_23_16
Definition: ps8640.h:31
@ SWAUX_STATUS_ACKM
Definition: ps8640.h:45
@ PAGE0_SWAUX_ADDR_7_0
Definition: ps8640.h:29
@ PAGE0_SWAUX_LENGTH
Definition: ps8640.h:33
@ SWAUX_STATUS_TIMEOUT
Definition: ps8640.h:49
@ SWAUX_NO_PAYLOAD
Definition: ps8640.h:35
@ SWAUX_STATUS_I2C_NACK
Definition: ps8640.h:47
@ PAGE3_SET_ADD
Definition: ps8640.h:19
@ PAGE3_SET_VAL
Definition: ps8640.h:20
@ VDO_EN
Definition: ps8640.h:23
@ MCS_EN_SHIFT
Definition: ps8640.h:17
@ VDO_DIS
Definition: ps8640.h:22
@ PAGE2_I2C_BYPASS
Definition: ps8640.h:12
@ PAGE2_GPIO_H
Definition: ps8640.h:11
@ VDO_CTL_ADD
Definition: ps8640.h:21
@ I2C_BYPASS_EN
Definition: ps8640.h:14
@ PAGE2_MCS_EN
Definition: ps8640.h:16
@ MCS_EN_MASK
Definition: ps8640.h:18
@ PS_GPIO9
Definition: ps8640.h:13
unsigned int uint32_t
Definition: stdint.h:14
uint8_t u8
Definition: stdint.h:45
unsigned char uint8_t
Definition: stdint.h:8
Definition: device.h:76
Definition: edid.h:49
u8 val
Definition: sys.c:300