* add i2c/ddc info storage to connector

* add edid info storage to display
* pass i2c/ddc information to common i2c code
* add code to read/write i2c/ddc
* i2c/ddc read/write code works 'in theory', needs tested
* detect monitors based on presence of edid on connector


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42718 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Alexander von Gluck IV 2011-09-06 23:00:07 +00:00
parent 440381c60f
commit b5fc0237e1
4 changed files with 109 additions and 51 deletions

View File

@ -138,16 +138,41 @@ struct pll_info {
};
struct ddc_info {
uint8 gpio_id;
uint16 mask_scl_reg;
uint16 mask_sda_reg;
uint16 mask_scl_shift;
uint16 mask_sda_shift;
uint16 gpio_en_scl_reg;
uint16 gpio_en_sda_reg;
uint16 gpio_en_scl_shift;
uint16 gpio_en_sda_shift;
uint16 gpio_y_scl_reg;
uint16 gpio_y_sda_reg;
uint16 gpio_y_scl_shift;
uint16 gpio_y_sda_shift;
uint16 gpio_a_scl_reg;
uint16 gpio_a_sda_reg;
uint16 gpio_a_scl_shift;
uint16 gpio_a_sda_shift;
};
typedef struct {
bool valid;
uint16 line_mux;
uint16 connector_flags;
uint32 connector_type;
uint16 connector_object_id;
i2c_bus connector_i2c;
uint32 encoder_type;
uint16 encoder_object_id;
// TODO struct radeon_i2c_bus_rec ddc_bus;
ddc_info connector_ddc_info;
i2c_bus connector_i2c;
// TODO struct radeon_hpd hpd;
} connector_info;
@ -162,6 +187,7 @@ typedef struct {
uint32 hfreq_max;
uint32 hfreq_min;
pll_info pll;
edid1_info *edid_info;
} display_info;

View File

@ -564,7 +564,7 @@ detect_connectors()
= (ATOM_I2C_ID_CONFIG_ACCESS *)
&i2c_record->sucI2cId;
// set up i2c bus for connector
// set up i2c gpio information for connector
radeon_gpu_i2c_setup(connector_index,
i2c_config->ucAccess);
break;
@ -633,7 +633,7 @@ detect_displays()
bool found = false;
switch(gConnector[id]->encoder_type) {
case VIDEO_ENCODER_DAC:
found = dac_sense(id);
found = radeon_gpu_read_edid(id, gDisplay[id]->edid_info);
break;
default:
found = false;

View File

@ -279,13 +279,12 @@ radeon_gpu_irq_setup()
static status_t
get_i2c_signals(void* cookie, int* _clock, int* _data)
{
#if 0
uint32 ioRegister = (uint32)cookie;
uint32 value = read32(ioRegister);
ddc_info *info = (ddc_info*)cookie;
*_clock = (value & I2C_CLOCK_VALUE_IN) != 0;
*_data = (value & I2C_DATA_VALUE_IN) != 0;
#endif
uint32 value = Read32(OUT, info->gpio_id);
*_clock = (value >> info->gpio_y_scl_shift) & 1;
*_data = (value >> info->gpio_y_sda_shift) & 1;
return B_OK;
}
@ -294,34 +293,45 @@ get_i2c_signals(void* cookie, int* _clock, int* _data)
static status_t
set_i2c_signals(void* cookie, int clock, int data)
{
#if 0
uint32 ioRegister = (uint32)cookie;
uint32 value = read32(OUT, ioRegister) & I2C_RESERVED;
ddc_info* info = (ddc_info*)cookie;
if (data != 0)
value |= I2C_DATA_DIRECTION_MASK;
else {
value |= I2C_DATA_DIRECTION_MASK
| I2C_DATA_DIRECTION_OUT
| I2C_DATA_VALUE_MASK;
}
uint32 value = Read32(OUT, info->gpio_id);
if (clock != 0)
value |= I2C_CLOCK_DIRECTION_MASK;
else
value |= I2C_CLOCK_DIRECTION_MASK
| I2C_CLOCK_DIRECTION_OUT
| I2C_CLOCK_VALUE_MASK;
value &= ~(info->gpio_a_scl_reg | info->gpio_a_sda_reg);
value &= ~(info->gpio_en_sda_reg | info->gpio_en_scl_reg);
value |= ((1 - clock) << info->gpio_en_scl_shift)
| ((1 - data) << info->gpio_en_sda_shift);
write32(OUT, ioRegister, value);
read32(OUT, ioRegister);
// make sure the PCI bus has flushed the write
#endif
Write32(OUT, info->gpio_id, value);
return B_OK;
}
bool
radeon_gpu_read_edid(uint32 connector, edid1_info *edid)
{
i2c_bus bus;
ddc2_init_timing(&bus);
bus.cookie = (void*)&gConnector[connector]->connector_ddc_info;
bus.set_signals = &set_i2c_signals;
bus.get_signals = &get_i2c_signals;
void *vdif;
size_t vdifLength;
if (ddc2_read_edid1(&bus, edid, &vdif, &vdifLength) != B_OK)
return false;
TRACE("%s: found edid monitor on connector #%" B_PRId32 "\n",
__func__, connector);
free(vdif);
return true;
}
status_t
radeon_gpu_i2c_setup(uint32 connector, uint8 gpio_id)
{
@ -349,33 +359,54 @@ radeon_gpu_i2c_setup(uint32 connector, uint8 gpio_id)
// TODO : if DCE 4 and i == 7 ... manual override for evergreen
// TODO : if DCE 3 and i == 4 ... manual override
if (gpio->sucI2cId.ucAccess == gpio_id) {
i2c_bus bus;
if (gpio->sucI2cId.ucAccess != gpio_id)
continue;
// successful lookup
TRACE("%s: successful i2c gpio lookup\n", __func__);
// successful lookup
TRACE("%s: found i2c gpio\n", __func__);
// pull registers for data and clock...
uint16 analogDataReg
= B_LENDIAN_TO_HOST_INT16(gpio->usDataA_RegisterIndex) * 4;
//uint16 analogClockReg
// = B_LENDIAN_TO_HOST_INT16(gpio->usClkA_RegisterIndex) * 4;
//uint16 digitalDataReg
// = B_LENDIAN_TO_HOST_INT16(gpio->usDataY_RegisterIndex) * 4;
//uint16 digitalClockReg
// = B_LENDIAN_TO_HOST_INT16(gpio->usClkY_RegisterIndex) * 4;
// populate cookie with analog data register
bus.cookie = (void*)analogDataReg;
bus.set_signals = &set_i2c_signals;
bus.get_signals = &get_i2c_signals;
// populate gpio information
gConnector[connector]->connector_ddc_info.gpio_id = gpio_id;
ddc2_init_timing(&bus);
// TODO : check for valid analog edid
// TODO : check for valid digital edid no results on analog
}
gConnector[connector]->connector_ddc_info.mask_scl_reg
= B_LENDIAN_TO_HOST_INT16(gpio->usClkMaskRegisterIndex) * 4;
gConnector[connector]->connector_ddc_info.mask_sda_reg
= B_LENDIAN_TO_HOST_INT16(gpio->usDataMaskRegisterIndex) * 4;
gConnector[connector]->connector_ddc_info.mask_scl_shift
= (1 << gpio->ucClkMaskShift);
gConnector[connector]->connector_ddc_info.mask_sda_shift
= (1 << gpio->ucDataMaskShift);
gConnector[connector]->connector_ddc_info.gpio_en_scl_reg
= B_LENDIAN_TO_HOST_INT16(gpio->usClkEnRegisterIndex) * 4;
gConnector[connector]->connector_ddc_info.gpio_en_sda_reg
= B_LENDIAN_TO_HOST_INT16(gpio->usDataEnRegisterIndex) * 4;
gConnector[connector]->connector_ddc_info.gpio_en_scl_shift
= (1 << gpio->ucClkEnShift);
gConnector[connector]->connector_ddc_info.gpio_en_sda_shift
= (1 << gpio->ucDataEnShift);
gConnector[connector]->connector_ddc_info.gpio_y_scl_reg
= B_LENDIAN_TO_HOST_INT16(gpio->usClkY_RegisterIndex) * 4;
gConnector[connector]->connector_ddc_info.gpio_y_sda_reg
= B_LENDIAN_TO_HOST_INT16(gpio->usDataY_RegisterIndex) * 4;
gConnector[connector]->connector_ddc_info.gpio_y_scl_shift
= (1 << gpio->ucClkY_Shift);
gConnector[connector]->connector_ddc_info.gpio_y_sda_shift
= (1 << gpio->ucDataY_Shift);
gConnector[connector]->connector_ddc_info.gpio_a_scl_reg
= B_LENDIAN_TO_HOST_INT16(gpio->usClkA_RegisterIndex) * 4;
gConnector[connector]->connector_ddc_info.gpio_a_sda_reg
= B_LENDIAN_TO_HOST_INT16(gpio->usDataA_RegisterIndex) * 4;
gConnector[connector]->connector_ddc_info.gpio_a_scl_shift
= (1 << gpio->ucClkA_Shift);
gConnector[connector]->connector_ddc_info.gpio_a_sda_shift
= (1 << gpio->ucDataA_Shift);
}
}
return B_OK;

View File

@ -168,6 +168,7 @@ void radeon_gpu_mc_resume();
uint32 radeon_gpu_mc_idlecheck();
status_t radeon_gpu_mc_setup();
status_t radeon_gpu_irq_setup();
bool radeon_gpu_read_edid(uint32 connector, edid1_info *edid);
status_t radeon_gpu_i2c_setup(uint32 connector, uint8 gpio_id);