* refactor GPU i2c bit-banging code to be correct using drm as reference
* add i2c locking code that represents common things we need to do before and after access git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42740 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -140,6 +140,8 @@ struct pll_info {
|
|||||||
|
|
||||||
struct ddc_info {
|
struct ddc_info {
|
||||||
bool valid;
|
bool valid;
|
||||||
|
bool hw_capable;
|
||||||
|
|
||||||
uint8 gpio_id;
|
uint8 gpio_id;
|
||||||
|
|
||||||
uint16 mask_scl_reg;
|
uint16 mask_scl_reg;
|
||||||
|
|||||||
@@ -277,35 +277,67 @@ radeon_gpu_irq_setup()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
lock_i2c(void* cookie, bool lock)
|
||||||
|
{
|
||||||
|
ddc_info *info = (ddc_info*)cookie;
|
||||||
|
|
||||||
|
uint32 buffer = 0;
|
||||||
|
|
||||||
|
if (info->hw_capable == true) {
|
||||||
|
// Switch GPIO pads to ddc mode
|
||||||
|
buffer = Read32(OUT, info->mask_scl_reg);
|
||||||
|
buffer &= ~(1 << 16);
|
||||||
|
Write32(OUT, info->mask_scl_reg, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear pins
|
||||||
|
buffer = Read32(OUT, info->gpio_a_scl_reg) & ~info->gpio_a_scl_shift;
|
||||||
|
Write32(OUT, info->gpio_a_scl_reg, buffer);
|
||||||
|
buffer = Read32(OUT, info->gpio_a_sda_reg) & ~info->gpio_a_sda_shift;
|
||||||
|
Write32(OUT, info->gpio_a_sda_reg, buffer);
|
||||||
|
|
||||||
|
// Set pins to input
|
||||||
|
buffer = Read32(OUT, info->gpio_en_scl_reg) & ~info->gpio_en_scl_shift;
|
||||||
|
Write32(OUT, info->gpio_en_scl_reg, buffer);
|
||||||
|
buffer = Read32(OUT, info->gpio_en_sda_reg) & ~info->gpio_en_sda_shift;
|
||||||
|
Write32(OUT, info->gpio_en_sda_reg, buffer);
|
||||||
|
|
||||||
|
// mask GPIO pins for software use
|
||||||
|
buffer = Read32(OUT, info->mask_scl_reg);
|
||||||
|
if (lock == true)
|
||||||
|
buffer |= info->mask_scl_shift;
|
||||||
|
else
|
||||||
|
buffer &= ~info->mask_scl_shift;
|
||||||
|
Write32(OUT, info->mask_scl_reg, buffer);
|
||||||
|
Read32(OUT, info->mask_scl_reg);
|
||||||
|
|
||||||
|
buffer = Read32(OUT, info->mask_sda_reg);
|
||||||
|
if (lock == true)
|
||||||
|
buffer |= info->mask_sda_shift;
|
||||||
|
else
|
||||||
|
buffer &= ~info->mask_sda_shift;
|
||||||
|
Write32(OUT, info->mask_sda_reg, buffer);
|
||||||
|
Read32(OUT, info->mask_sda_reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
get_i2c_signals(void* cookie, int* _clock, int* _data)
|
get_i2c_signals(void* cookie, int* _clock, int* _data)
|
||||||
{
|
{
|
||||||
ddc_info *info = (ddc_info*)cookie;
|
ddc_info *info = (ddc_info*)cookie;
|
||||||
|
|
||||||
// software only access
|
lock_i2c(cookie, true);
|
||||||
//uint32 scl_maskVal = Read32(OUT, info->mask_scl_reg);
|
uint32 scl = Read32(OUT, info->gpio_y_scl_reg) & info->gpio_y_scl_shift;
|
||||||
//uint32 sda_maskVal = Read32(OUT, info->mask_sda_reg);
|
uint32 sda = Read32(OUT, info->gpio_y_sda_reg) & info->gpio_y_sda_shift;
|
||||||
//Write32(OUT, info->mask_scl_reg, 1);
|
lock_i2c(cookie, false);
|
||||||
//Write32(OUT, info->mask_sda_reg, 1);
|
|
||||||
|
|
||||||
// set read mode
|
*_clock = (scl != 0);
|
||||||
uint32 scl_enVal = Read32(OUT, info->gpio_en_scl_reg);
|
*_data = (sda != 0);
|
||||||
uint32 sda_enVal = Read32(OUT, info->gpio_en_sda_reg);
|
|
||||||
Write32(OUT, info->gpio_en_scl_reg, 0);
|
|
||||||
Write32(OUT, info->gpio_en_sda_reg, 0);
|
|
||||||
|
|
||||||
*_clock = Read32(OUT, info->gpio_y_scl_reg);
|
|
||||||
*_data = Read32(OUT, info->gpio_y_sda_reg);
|
|
||||||
|
|
||||||
TRACE("%s: GPIO 0x%" B_PRIX8 ", clock: %d, data: %d\n",
|
TRACE("%s: GPIO 0x%" B_PRIX8 ", clock: %d, data: %d\n",
|
||||||
__func__, info->gpio_id, *_clock, *_data);
|
__func__, info->gpio_id, *_clock, *_data);
|
||||||
|
|
||||||
// restore previous settings
|
|
||||||
//Write32(OUT, info->mask_scl_reg, scl_maskVal);
|
|
||||||
//Write32(OUT, info->mask_sda_reg, sda_maskVal);
|
|
||||||
Write32(OUT, info->gpio_en_scl_reg, scl_enVal);
|
|
||||||
Write32(OUT, info->gpio_en_sda_reg, sda_enVal);
|
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,34 +347,22 @@ set_i2c_signals(void* cookie, int clock, int data)
|
|||||||
{
|
{
|
||||||
ddc_info* info = (ddc_info*)cookie;
|
ddc_info* info = (ddc_info*)cookie;
|
||||||
|
|
||||||
// software only access
|
lock_i2c(cookie, true);
|
||||||
uint32 scl_maskVal = Read32(OUT, info->mask_scl_reg);
|
uint32 scl = Read32(OUT, info->gpio_en_scl_reg)
|
||||||
uint32 sda_maskVal = Read32(OUT, info->mask_sda_reg);
|
& ~info->gpio_en_scl_shift;
|
||||||
Write32(OUT, info->mask_scl_reg, 1);
|
uint32 sda = Read32(OUT, info->gpio_en_sda_reg)
|
||||||
Write32(OUT, info->mask_sda_reg, 1);
|
& ~info->gpio_en_sda_shift;
|
||||||
|
|
||||||
// set write mode
|
scl |= clock ? 0 : info->gpio_en_scl_shift;
|
||||||
uint32 scl_enVal = Read32(OUT, info->gpio_en_scl_reg);
|
sda |= data ? 0 : info->gpio_en_sda_shift;
|
||||||
uint32 sda_enVal = Read32(OUT, info->gpio_en_sda_reg);
|
|
||||||
Write32(OUT, info->gpio_en_scl_reg, 1);
|
|
||||||
Write32(OUT, info->gpio_en_sda_reg, 1);
|
|
||||||
|
|
||||||
Write32(OUT, info->gpio_a_scl_reg, clock);
|
Write32(OUT, info->gpio_a_scl_reg, clock);
|
||||||
Write32(OUT, info->gpio_a_sda_reg, data);
|
Write32(OUT, info->gpio_a_sda_reg, data);
|
||||||
|
lock_i2c(cookie, false);
|
||||||
// read back to improve reliability?
|
|
||||||
Read32(OUT, info->gpio_a_scl_reg);
|
|
||||||
Read32(OUT, info->gpio_a_sda_reg);
|
|
||||||
|
|
||||||
TRACE("%s: GPIO 0x%" B_PRIX8 ", clock: %d, data: %d\n",
|
TRACE("%s: GPIO 0x%" B_PRIX8 ", clock: %d, data: %d\n",
|
||||||
__func__, info->gpio_id, clock, data);
|
__func__, info->gpio_id, clock, data);
|
||||||
|
|
||||||
// restore previous settings
|
|
||||||
Write32(OUT, info->mask_scl_reg, scl_maskVal);
|
|
||||||
Write32(OUT, info->mask_sda_reg, sda_maskVal);
|
|
||||||
Write32(OUT, info->gpio_en_scl_reg, scl_enVal);
|
|
||||||
Write32(OUT, info->gpio_en_sda_reg, sda_enVal);
|
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -417,6 +437,13 @@ radeon_gpu_i2c_setup(uint32 connector, uint8 gpio_id)
|
|||||||
|
|
||||||
// populate gpio information
|
// populate gpio information
|
||||||
gConnector[connector]->connector_ddc_info.valid = true;
|
gConnector[connector]->connector_ddc_info.valid = true;
|
||||||
|
|
||||||
|
// TODO : what is hw_capable?
|
||||||
|
if (gpio->sucI2cId.sbfAccess.bfHW_Capable)
|
||||||
|
gConnector[connector]->connector_ddc_info.hw_capable = true;
|
||||||
|
else
|
||||||
|
gConnector[connector]->connector_ddc_info.hw_capable = true;
|
||||||
|
|
||||||
gConnector[connector]->connector_ddc_info.gpio_id = gpio_id;
|
gConnector[connector]->connector_ddc_info.gpio_id = gpio_id;
|
||||||
|
|
||||||
// GPIO mask (Allows software to control the GPIO pad)
|
// GPIO mask (Allows software to control the GPIO pad)
|
||||||
|
|||||||
Reference in New Issue
Block a user