drm/nouveau: bios parser fixes for eDP boards

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
Ben Skeggs 2010-04-20 02:28:37 +10:00
Родитель 90af89b93c
Коммит 25908b7797
1 изменённых файлов: 124 добавлений и 0 удалений

Просмотреть файл

@ -26,6 +26,7 @@
#define NV_DEBUG_NOTRACE
#include "nouveau_drv.h"
#include "nouveau_hw.h"
#include "nouveau_encoder.h"
/* these defines are made up */
#define NV_CIO_CRE_44_HEADA 0x0
@ -1066,6 +1067,126 @@ init_io_flag_condition(struct nvbios *bios, uint16_t offset,
return 2;
}
static int
init_dp_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
{
/*
* INIT_DP_CONDITION opcode: 0x3A ('')
*
* offset (8 bit): opcode
* offset + 1 (8 bit): "sub" opcode
* offset + 2 (8 bit): unknown
*
*/
struct bit_displayport_encoder_table *dpe = NULL;
struct dcb_entry *dcb = bios->display.output;
struct drm_device *dev = bios->dev;
uint8_t cond = bios->data[offset + 1];
int dummy;
BIOSLOG(bios, "0x%04X: subop 0x%02X\n", offset, cond);
if (!iexec->execute)
return 3;
dpe = nouveau_bios_dp_table(dev, dcb, &dummy);
if (!dpe) {
NV_ERROR(dev, "0x%04X: INIT_3A: no encoder table!!\n", offset);
return -EINVAL;
}
switch (cond) {
case 0:
{
struct dcb_connector_table_entry *ent =
&bios->dcb.connector.entry[dcb->connector];
if (ent->type != DCB_CONNECTOR_eDP)
iexec->execute = false;
}
break;
case 1:
case 2:
if (!(dpe->unknown & cond))
iexec->execute = false;
break;
case 5:
{
struct nouveau_i2c_chan *auxch;
int ret;
auxch = nouveau_i2c_find(dev, bios->display.output->i2c_index);
if (!auxch)
return -ENODEV;
ret = nouveau_dp_auxch(auxch, 9, 0xd, &cond, 1);
if (ret)
return ret;
if (cond & 1)
iexec->execute = false;
}
break;
default:
NV_WARN(dev, "0x%04X: unknown INIT_3A op: %d\n", offset, cond);
break;
}
if (iexec->execute)
BIOSLOG(bios, "0x%04X: continuing to execute\n", offset);
else
BIOSLOG(bios, "0x%04X: skipping following commands\n", offset);
return 3;
}
static int
init_op_3b(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
{
/*
* INIT_3B opcode: 0x3B ('')
*
* offset (8 bit): opcode
* offset + 1 (8 bit): crtc index
*
*/
uint8_t or = ffs(bios->display.output->or) - 1;
uint8_t index = bios->data[offset + 1];
uint8_t data;
if (!iexec->execute)
return 2;
data = bios_idxprt_rd(bios, 0x3d4, index);
bios_idxprt_wr(bios, 0x3d4, index, data & ~(1 << or));
return 2;
}
static int
init_op_3c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
{
/*
* INIT_3C opcode: 0x3C ('')
*
* offset (8 bit): opcode
* offset + 1 (8 bit): crtc index
*
*/
uint8_t or = ffs(bios->display.output->or) - 1;
uint8_t index = bios->data[offset + 1];
uint8_t data;
if (!iexec->execute)
return 2;
data = bios_idxprt_rd(bios, 0x3d4, index);
bios_idxprt_wr(bios, 0x3d4, index, data | (1 << or));
return 2;
}
static int
init_idx_addr_latched(struct nvbios *bios, uint16_t offset,
struct init_exec *iexec)
@ -2934,6 +3055,9 @@ static struct init_tbl_entry itbl_entry[] = {
{ "INIT_COPY" , 0x37, init_copy },
{ "INIT_NOT" , 0x38, init_not },
{ "INIT_IO_FLAG_CONDITION" , 0x39, init_io_flag_condition },
{ "INIT_DP_CONDITION" , 0x3A, init_dp_condition },
{ "INIT_OP_3B" , 0x3B, init_op_3b },
{ "INIT_OP_3C" , 0x3C, init_op_3c },
{ "INIT_INDEX_ADDRESS_LATCHED" , 0x49, init_idx_addr_latched },
{ "INIT_IO_RESTRICT_PLL2" , 0x4A, init_io_restrict_pll2 },
{ "INIT_PLL2" , 0x4B, init_pll2 },