1 /* SPDX-License-Identifier: GPL-2.0-only */
4 #include <device/i2c_simple.h>
6 #include <console/console.h>
11 int ps8640_get_edid(uint8_t bus
, uint8_t chip
, struct edid
*out
)
14 u8 edid
[EDID_LENGTH
* 2];
15 int edid_size
= EDID_LENGTH
;
17 i2c_writeb(bus
, chip
+ 2, PAGE2_I2C_BYPASS
,
18 EDID_I2C_ADDR
| I2C_BYPASS_EN
);
19 ret
= i2c_read_bytes(bus
, EDID_I2C_ADDR
, 0, edid
, EDID_LENGTH
);
22 printk(BIOS_INFO
, "Failed to read EDID.\n");
26 /* check if edid have extension flag, and read additional EDID data */
27 if (edid
[EDID_EXTENSION_FLAG
]) {
28 edid_size
+= EDID_LENGTH
;
29 ret
= i2c_read_bytes(bus
, EDID_I2C_ADDR
, EDID_LENGTH
,
30 &edid
[EDID_LENGTH
], EDID_LENGTH
);
32 printk(BIOS_INFO
, "Failed to read EDID ext block.\n");
37 if (decode_edid(edid
, edid_size
, out
) != EDID_CONFORMANT
) {
38 printk(BIOS_INFO
, "Failed to decode EDID.\n");
45 int ps8640_init(uint8_t bus
, uint8_t chip
)
51 stopwatch_init_msecs_expire(&sw
, 200);
54 i2c_readb(bus
, chip
+ 2, PAGE2_GPIO_H
, &set_vdo_done
);
55 if ((set_vdo_done
& PS_GPIO9
) == PS_GPIO9
)
57 if (stopwatch_expired(&sw
)) {
58 printk(BIOS_INFO
, "Failed to init ps8640.\n");
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.
74 i2c_write_field(bus
, chip
+ 2, PAGE2_MCS_EN
, 0x0, MCS_EN_MASK
,
76 i2c_writeb(bus
, chip
+ 3, PAGE3_SET_ADD
, VDO_CTL_ADD
);
77 i2c_writeb(bus
, chip
+ 3, PAGE3_SET_VAL
, VDO_DIS
);
78 i2c_writeb(bus
, chip
+ 3, PAGE3_SET_ADD
, VDO_CTL_ADD
);
79 i2c_writeb(bus
, chip
+ 3, PAGE3_SET_VAL
, VDO_EN
);
84 static enum cb_err
ps8640_bridge_aux_request(uint8_t bus
,
86 unsigned int target_reg
,
87 unsigned int total_size
,
88 enum aux_request request
,
97 if (target_reg
& ~SWAUX_ADDR_MASK
)
101 length
= MIN(total_size
, DP_AUX_MAX_PAYLOAD_BYTES
);
102 total_size
-= length
;
104 ret
= i2c_writeb(bus
, chip
, PAGE0_AUXCH_CFG3
, AUXCH_CFG3_RESET
);
108 enum i2c_over_aux cmd
= dp_get_aux_cmd(request
, total_size
);
109 if (i2c_writeb(bus
, chip
, PAGE0_SWAUX_ADDR_23_16
,
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
)) {
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
++);
125 i2c_writeb(bus
, chip
, PAGE0_SWAUX_LENGTH
, SWAUX_NO_PAYLOAD
);
127 i2c_writeb(bus
, chip
, PAGE0_SWAUX_LENGTH
, length
- 1);
130 ret
= i2c_writeb(bus
, chip
, PAGE0_SWAUX_CTRL
, SWAUX_SEND
);
134 if (!wait_ms(100, !i2c_readb(bus
, chip
, PAGE0_SWAUX_CTRL
, &buf
) &&
135 !(buf
& SWAUX_SEND
)))
138 if (i2c_readb(bus
, chip
, PAGE0_SWAUX_STATUS
, &buf
))
141 switch (buf
& SWAUX_STATUS_MASK
) {
142 case SWAUX_STATUS_NACK
:
143 case SWAUX_STATUS_I2C_NACK
:
144 case SWAUX_STATUS_INVALID
:
145 case SWAUX_STATUS_TIMEOUT
:
147 case SWAUX_STATUS_ACKM
:
148 length
= buf
& SWAUX_M_MASK
;
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
))
165 void ps8640_backlight_enable(uint8_t bus
, uint8_t chip
)
169 val
= DP_BACKLIGHT_CONTROL_MODE_DPCD
;
170 ps8640_bridge_aux_request(bus
, chip
, DP_BACKLIGHT_MODE_SET
, 1,
174 ps8640_bridge_aux_request(bus
, chip
, DP_BACKLIGHT_BRIGHTNESS_MSB
, 1,
177 val
= DP_BACKLIGHT_ENABLE
;
178 ps8640_bridge_aux_request(bus
, chip
, DP_DISPLAY_CONTROL_REGISTER
, 1,