* 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
+28 -2
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 { typedef struct {
bool valid; bool valid;
uint16 line_mux; uint16 line_mux;
uint16 connector_flags; uint16 connector_flags;
uint32 connector_type; uint32 connector_type;
uint16 connector_object_id; uint16 connector_object_id;
i2c_bus connector_i2c;
uint32 encoder_type; uint32 encoder_type;
uint16 encoder_object_id; 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; // TODO struct radeon_hpd hpd;
} connector_info; } connector_info;
@@ -162,6 +187,7 @@ typedef struct {
uint32 hfreq_max; uint32 hfreq_max;
uint32 hfreq_min; uint32 hfreq_min;
pll_info pll; pll_info pll;
edid1_info *edid_info;
} display_info; } display_info;
@@ -564,7 +564,7 @@ detect_connectors()
= (ATOM_I2C_ID_CONFIG_ACCESS *) = (ATOM_I2C_ID_CONFIG_ACCESS *)
&i2c_record->sucI2cId; &i2c_record->sucI2cId;
// set up i2c bus for connector // set up i2c gpio information for connector
radeon_gpu_i2c_setup(connector_index, radeon_gpu_i2c_setup(connector_index,
i2c_config->ucAccess); i2c_config->ucAccess);
break; break;
@@ -633,7 +633,7 @@ detect_displays()
bool found = false; bool found = false;
switch(gConnector[id]->encoder_type) { switch(gConnector[id]->encoder_type) {
case VIDEO_ENCODER_DAC: case VIDEO_ENCODER_DAC:
found = dac_sense(id); found = radeon_gpu_read_edid(id, gDisplay[id]->edid_info);
break; break;
default: default:
found = false; found = false;
+78 -47
View File
@@ -279,13 +279,12 @@ radeon_gpu_irq_setup()
static status_t static status_t
get_i2c_signals(void* cookie, int* _clock, int* _data) get_i2c_signals(void* cookie, int* _clock, int* _data)
{ {
#if 0 ddc_info *info = (ddc_info*)cookie;
uint32 ioRegister = (uint32)cookie;
uint32 value = read32(ioRegister);
*_clock = (value & I2C_CLOCK_VALUE_IN) != 0; uint32 value = Read32(OUT, info->gpio_id);
*_data = (value & I2C_DATA_VALUE_IN) != 0;
#endif *_clock = (value >> info->gpio_y_scl_shift) & 1;
*_data = (value >> info->gpio_y_sda_shift) & 1;
return B_OK; return B_OK;
} }
@@ -294,34 +293,45 @@ get_i2c_signals(void* cookie, int* _clock, int* _data)
static status_t static status_t
set_i2c_signals(void* cookie, int clock, int data) set_i2c_signals(void* cookie, int clock, int data)
{ {
#if 0 ddc_info* info = (ddc_info*)cookie;
uint32 ioRegister = (uint32)cookie;
uint32 value = read32(OUT, ioRegister) & I2C_RESERVED;
if (data != 0) uint32 value = Read32(OUT, info->gpio_id);
value |= I2C_DATA_DIRECTION_MASK;
else {
value |= I2C_DATA_DIRECTION_MASK
| I2C_DATA_DIRECTION_OUT
| I2C_DATA_VALUE_MASK;
}
if (clock != 0) value &= ~(info->gpio_a_scl_reg | info->gpio_a_sda_reg);
value |= I2C_CLOCK_DIRECTION_MASK; value &= ~(info->gpio_en_sda_reg | info->gpio_en_scl_reg);
else value |= ((1 - clock) << info->gpio_en_scl_shift)
value |= I2C_CLOCK_DIRECTION_MASK | ((1 - data) << info->gpio_en_sda_shift);
| I2C_CLOCK_DIRECTION_OUT
| I2C_CLOCK_VALUE_MASK;
write32(OUT, ioRegister, value); Write32(OUT, info->gpio_id, value);
read32(OUT, ioRegister);
// make sure the PCI bus has flushed the write
#endif
return B_OK; 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 status_t
radeon_gpu_i2c_setup(uint32 connector, uint8 gpio_id) 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 4 and i == 7 ... manual override for evergreen
// TODO : if DCE 3 and i == 4 ... manual override // TODO : if DCE 3 and i == 4 ... manual override
if (gpio->sucI2cId.ucAccess == gpio_id) { if (gpio->sucI2cId.ucAccess != gpio_id)
i2c_bus bus; continue;
// successful lookup // successful lookup
TRACE("%s: successful i2c gpio lookup\n", __func__); TRACE("%s: found i2c gpio\n", __func__);
// pull registers for data and clock...
uint16 analogDataReg // populate gpio information
gConnector[connector]->connector_ddc_info.gpio_id = gpio_id;
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; = B_LENDIAN_TO_HOST_INT16(gpio->usDataA_RegisterIndex) * 4;
//uint16 analogClockReg gConnector[connector]->connector_ddc_info.gpio_a_scl_shift
// = B_LENDIAN_TO_HOST_INT16(gpio->usClkA_RegisterIndex) * 4; = (1 << gpio->ucClkA_Shift);
//uint16 digitalDataReg gConnector[connector]->connector_ddc_info.gpio_a_sda_shift
// = B_LENDIAN_TO_HOST_INT16(gpio->usDataY_RegisterIndex) * 4; = (1 << gpio->ucDataA_Shift);
//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;
ddc2_init_timing(&bus);
// TODO : check for valid analog edid
// TODO : check for valid digital edid no results on analog
}
} }
} }
return B_OK; return B_OK;
+1
View File
@@ -168,6 +168,7 @@ void radeon_gpu_mc_resume();
uint32 radeon_gpu_mc_idlecheck(); uint32 radeon_gpu_mc_idlecheck();
status_t radeon_gpu_mc_setup(); status_t radeon_gpu_mc_setup();
status_t radeon_gpu_irq_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); status_t radeon_gpu_i2c_setup(uint32 connector, uint8 gpio_id);