ati: add edid support.

Read EDID blob via i2c, store in VBE_edid.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
Gerd Hoffmann 2019-03-18 15:43:53 +01:00
parent a307d0adc5
commit 588eb12163
1 changed files with 114 additions and 0 deletions

View File

@ -19,6 +19,8 @@
#define MM_DATA 0x0004
#define CRTC_GEN_CNTL 0x0050
#define CRTC_EXT_CNTL 0x0054
#define GPIO_VGA_DDC 0x0060
#define GPIO_DVI_DDC 0x0064
#define CRTC_H_TOTAL_DISP 0x0200
#define CRTC_V_TOTAL_DISP 0x0208
#define CRTC_OFFSET 0x0224
@ -106,6 +108,20 @@ static inline void ati_write(u32 reg, u32 val)
}
}
static inline u32 ati_read(u32 reg)
{
u32 io_addr = GET_GLOBAL(ati_io_addr);
u32 val;
if (reg < 0x100) {
val = inl(io_addr + reg);
} else {
outl(reg, io_addr + MM_INDEX);
reg = inl(io_addr + MM_DATA);
}
return val;
}
static void ati_clear(u32 offset, u32 size)
{
u8 data[64];
@ -180,6 +196,97 @@ ati_set_mode(struct vgamode_s *vmode_g, int flags)
return stdvga_set_mode(vmode_g, flags);
}
/****************************************************************
* edid
****************************************************************/
static void
ati_i2c_set_scl_sda(int scl, int sda)
{
u32 data = 0;
if (!scl)
data |= (1 << 17);
if (!sda)
data |= (1 << 16);
ati_write(GPIO_DVI_DDC, data);
}
static int
ati_i2c_get_sda(void)
{
u32 data = ati_read(GPIO_DVI_DDC);
return data & (1 << 8) ? 1 : 0;
}
static void ati_i2c_start(void)
{
ati_i2c_set_scl_sda(1, 1);
ati_i2c_set_scl_sda(1, 0);
ati_i2c_set_scl_sda(0, 0);
}
static void ati_i2c_ack(void)
{
ati_i2c_set_scl_sda(0, 0);
ati_i2c_set_scl_sda(1, 0);
ati_i2c_set_scl_sda(0, 0);
}
static void ati_i2c_stop(void)
{
ati_i2c_set_scl_sda(0, 0);
ati_i2c_set_scl_sda(1, 0);
ati_i2c_set_scl_sda(1, 1);
}
static void ati_i2c_send_byte(u8 byte)
{
int i, bit;
for (i = 0; i < 8; i++) {
bit = (1 << (7-i)) & byte ? 1 : 0;
ati_i2c_set_scl_sda(0, bit);
ati_i2c_set_scl_sda(1, bit);
ati_i2c_set_scl_sda(0, bit);
}
}
static u8 ati_i2c_recv_byte(void)
{
u8 byte = 0;
int i, bit;
for (i = 0; i < 8; i++) {
ati_i2c_set_scl_sda(0, 1);
ati_i2c_set_scl_sda(1, 1);
bit = ati_i2c_get_sda();
ati_i2c_set_scl_sda(0, 1);
if (bit)
byte |= (1 << (7-i));
}
return byte;
}
static void ati_i2c_edid(void)
{
u8 byte;
int i;
dprintf(1, "ati: reading edid blob\n");
ati_i2c_start();
ati_i2c_send_byte(0x50 << 1 | 1);
ati_i2c_ack();
for (i = 0; i < 128; i++) {
byte = ati_i2c_recv_byte();
ati_i2c_ack();
SET_VGA(VBE_edid[i], byte);
}
ati_i2c_stop();
}
/****************************************************************
* init
****************************************************************/
@ -241,5 +348,12 @@ ati_setup(void)
}
}
u16 device = pci_config_readw(bdf, PCI_DEVICE_ID);
switch (device) {
case 0x5159:
ati_i2c_edid();
break;
}
return 0;
}