aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorMarcin Koƛcielnicki <koriakin@0x04.net>2010-07-03 22:47:16 -0400
committerBen Skeggs <bskeggs@redhat.com>2010-08-05 18:35:50 -0400
commitb715d64028ea90bcb67b3823ae1cc908a4ae0bc6 (patch)
tree0725debf2f98cb2709805e011d2f818c9e50b9a1 /drivers/gpu
parente3a1924f3e5aeabdb1a1ae1a87b4097e48b7f2c5 (diff)
drm/nouveau: implement init table opcodex 0x5e and 0x9a
Signed-off-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Marcin Koƛcielnicki <koriakin@0x04.net>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bios.c123
1 files changed, 123 insertions, 0 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
index 6dd00ffa63a0..8f1f16276f03 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
@@ -2020,6 +2020,64 @@ init_sub_direct(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
2020} 2020}
2021 2021
2022static int 2022static int
2023init_i2c_if(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
2024{
2025 /*
2026 * INIT_I2C_IF opcode: 0x5E ('^')
2027 *
2028 * offset (8 bit): opcode
2029 * offset + 1 (8 bit): DCB I2C table entry index
2030 * offset + 2 (8 bit): I2C slave address
2031 * offset + 3 (8 bit): I2C register
2032 * offset + 4 (8 bit): mask
2033 * offset + 5 (8 bit): data
2034 *
2035 * Read the register given by "I2C register" on the device addressed
2036 * by "I2C slave address" on the I2C bus given by "DCB I2C table
2037 * entry index". Compare the result AND "mask" to "data".
2038 * If they're not equal, skip subsequent opcodes until condition is
2039 * inverted (INIT_NOT), or we hit INIT_RESUME
2040 */
2041
2042 uint8_t i2c_index = bios->data[offset + 1];
2043 uint8_t i2c_address = bios->data[offset + 2] >> 1;
2044 uint8_t reg = bios->data[offset + 3];
2045 uint8_t mask = bios->data[offset + 4];
2046 uint8_t data = bios->data[offset + 5];
2047 struct nouveau_i2c_chan *chan;
2048 union i2c_smbus_data val;
2049 int ret;
2050
2051 /* no execute check by design */
2052
2053 BIOSLOG(bios, "0x%04X: DCBI2CIndex: 0x%02X, I2CAddress: 0x%02X\n",
2054 offset, i2c_index, i2c_address);
2055
2056 chan = init_i2c_device_find(bios->dev, i2c_index);
2057 if (!chan)
2058 return -ENODEV;
2059
2060 ret = i2c_smbus_xfer(&chan->adapter, i2c_address, 0,
2061 I2C_SMBUS_READ, reg,
2062 I2C_SMBUS_BYTE_DATA, &val);
2063 if (ret < 0) {
2064 BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X, Value: [no device], "
2065 "Mask: 0x%02X, Data: 0x%02X\n",
2066 offset, reg, mask, data);
2067 iexec->execute = 0;
2068 return 6;
2069 }
2070
2071 BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X, Value: 0x%02X, "
2072 "Mask: 0x%02X, Data: 0x%02X\n",
2073 offset, reg, val.byte, mask, data);
2074
2075 iexec->execute = ((val.byte & mask) == data);
2076
2077 return 6;
2078}
2079
2080static int
2023init_copy_nv_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) 2081init_copy_nv_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
2024{ 2082{
2025 /* 2083 /*
@@ -3517,6 +3575,69 @@ init_zm_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
3517 return len; 3575 return len;
3518} 3576}
3519 3577
3578static int
3579init_i2c_long_if(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
3580{
3581 /*
3582 * INIT_I2C_LONG_IF opcode: 0x9A ('')
3583 *
3584 * offset (8 bit): opcode
3585 * offset + 1 (8 bit): DCB I2C table entry index
3586 * offset + 2 (8 bit): I2C slave address
3587 * offset + 3 (16 bit): I2C register
3588 * offset + 5 (8 bit): mask
3589 * offset + 6 (8 bit): data
3590 *
3591 * Read the register given by "I2C register" on the device addressed
3592 * by "I2C slave address" on the I2C bus given by "DCB I2C table
3593 * entry index". Compare the result AND "mask" to "data".
3594 * If they're not equal, skip subsequent opcodes until condition is
3595 * inverted (INIT_NOT), or we hit INIT_RESUME
3596 */
3597
3598 uint8_t i2c_index = bios->data[offset + 1];
3599 uint8_t i2c_address = bios->data[offset + 2] >> 1;
3600 uint8_t reglo = bios->data[offset + 3];
3601 uint8_t reghi = bios->data[offset + 4];
3602 uint8_t mask = bios->data[offset + 5];
3603 uint8_t data = bios->data[offset + 6];
3604 struct nouveau_i2c_chan *chan;
3605 uint8_t buf0[2] = { reghi, reglo };
3606 uint8_t buf1[1];
3607 struct i2c_msg msg[2] = {
3608 { i2c_address, 0, 1, buf0 },
3609 { i2c_address, I2C_M_RD, 1, buf1 },
3610 };
3611 int ret;
3612
3613 /* no execute check by design */
3614
3615 BIOSLOG(bios, "0x%04X: DCBI2CIndex: 0x%02X, I2CAddress: 0x%02X\n",
3616 offset, i2c_index, i2c_address);
3617
3618 chan = init_i2c_device_find(bios->dev, i2c_index);
3619 if (!chan)
3620 return -ENODEV;
3621
3622
3623 ret = i2c_transfer(&chan->adapter, msg, 2);
3624 if (ret < 0) {
3625 BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X:0x%02X, Value: [no device], "
3626 "Mask: 0x%02X, Data: 0x%02X\n",
3627 offset, reghi, reglo, mask, data);
3628 iexec->execute = 0;
3629 return 7;
3630 }
3631
3632 BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X:0x%02X, Value: 0x%02X, "
3633 "Mask: 0x%02X, Data: 0x%02X\n",
3634 offset, reghi, reglo, buf1[0], mask, data);
3635
3636 iexec->execute = ((buf1[0] & mask) == data);
3637
3638 return 7;
3639}
3640
3520static struct init_tbl_entry itbl_entry[] = { 3641static struct init_tbl_entry itbl_entry[] = {
3521 /* command name , id , length , offset , mult , command handler */ 3642 /* command name , id , length , offset , mult , command handler */
3522 /* INIT_PROG (0x31, 15, 10, 4) removed due to no example of use */ 3643 /* INIT_PROG (0x31, 15, 10, 4) removed due to no example of use */
@@ -3547,6 +3668,7 @@ static struct init_tbl_entry itbl_entry[] = {
3547 { "INIT_ZM_REG_SEQUENCE" , 0x58, init_zm_reg_sequence }, 3668 { "INIT_ZM_REG_SEQUENCE" , 0x58, init_zm_reg_sequence },
3548 /* INIT_INDIRECT_REG (0x5A, 7, 0, 0) removed due to no example of use */ 3669 /* INIT_INDIRECT_REG (0x5A, 7, 0, 0) removed due to no example of use */
3549 { "INIT_SUB_DIRECT" , 0x5B, init_sub_direct }, 3670 { "INIT_SUB_DIRECT" , 0x5B, init_sub_direct },
3671 { "INIT_I2C_IF" , 0x5E, init_i2c_if },
3550 { "INIT_COPY_NV_REG" , 0x5F, init_copy_nv_reg }, 3672 { "INIT_COPY_NV_REG" , 0x5F, init_copy_nv_reg },
3551 { "INIT_ZM_INDEX_IO" , 0x62, init_zm_index_io }, 3673 { "INIT_ZM_INDEX_IO" , 0x62, init_zm_index_io },
3552 { "INIT_COMPUTE_MEM" , 0x63, init_compute_mem }, 3674 { "INIT_COMPUTE_MEM" , 0x63, init_compute_mem },
@@ -3580,6 +3702,7 @@ static struct init_tbl_entry itbl_entry[] = {
3580 { "INIT_97" , 0x97, init_97 }, 3702 { "INIT_97" , 0x97, init_97 },
3581 { "INIT_AUXCH" , 0x98, init_auxch }, 3703 { "INIT_AUXCH" , 0x98, init_auxch },
3582 { "INIT_ZM_AUXCH" , 0x99, init_zm_auxch }, 3704 { "INIT_ZM_AUXCH" , 0x99, init_zm_auxch },
3705 { "INIT_I2C_LONG_IF" , 0x9A, init_i2c_long_if },
3583 { NULL , 0 , NULL } 3706 { NULL , 0 , NULL }
3584}; 3707};
3585 3708