Create connector source file, move connector bus calls into it
* this will help break apart some of the sources * display bus communications really don't belong with GPU operations * rename functions to better describe their actions
This commit is contained in:
@@ -12,8 +12,9 @@ UsePrivateHeaders [ FDirName graphics common ] ;
|
||||
Addon radeon_hd.accelerant :
|
||||
accelerant.cpp
|
||||
atom.cpp
|
||||
create_display_modes.cpp
|
||||
bios.cpp
|
||||
connector.cpp
|
||||
create_display_modes.cpp
|
||||
display.cpp
|
||||
encoder.cpp
|
||||
engine.cpp
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "accelerant.h"
|
||||
|
||||
#include "bios.h"
|
||||
#include "connector.h"
|
||||
#include "display.h"
|
||||
#include "gpu.h"
|
||||
#include "pll.h"
|
||||
@@ -252,7 +253,7 @@ radeon_init_accelerant(int device)
|
||||
radeon_init_bios(gInfo->rom);
|
||||
|
||||
// detect GPIO pins
|
||||
radeon_gpu_gpio_setup();
|
||||
gpio_probe();
|
||||
|
||||
// detect physical connectors
|
||||
status = detect_connectors();
|
||||
|
||||
@@ -0,0 +1,357 @@
|
||||
/*
|
||||
* Copyright 2006-2011, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander von Gluck, [email protected]
|
||||
*/
|
||||
|
||||
|
||||
#include "accelerant_protos.h"
|
||||
#include "accelerant.h"
|
||||
#include "bios.h"
|
||||
#include "connector.h"
|
||||
#include "gpu.h"
|
||||
#include "utility.h"
|
||||
|
||||
#include <Debug.h>
|
||||
|
||||
|
||||
#undef TRACE
|
||||
|
||||
#define TRACE_CONNECTOR
|
||||
#ifdef TRACE_CONNECTOR
|
||||
# define TRACE(x...) _sPrintf("radeon_hd: " x)
|
||||
#else
|
||||
# define TRACE(x...) ;
|
||||
#endif
|
||||
|
||||
#define ERROR(x...) _sPrintf("radeon_hd: " x)
|
||||
|
||||
|
||||
static void
|
||||
gpio_lock_i2c(void* cookie, bool lock)
|
||||
{
|
||||
gpio_info *info = (gpio_info*)cookie;
|
||||
radeon_shared_info &sinfo = *gInfo->shared_info;
|
||||
|
||||
uint32 buffer = 0;
|
||||
|
||||
if (lock == true) {
|
||||
// hw_capable and > DCE3
|
||||
if (info->hw_capable == true
|
||||
&& sinfo.dceMajor >= 3) {
|
||||
// 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->a_scl_reg) & ~info->a_scl_mask;
|
||||
Write32(OUT, info->a_scl_reg, buffer);
|
||||
buffer = Read32(OUT, info->a_sda_reg) & ~info->a_sda_mask;
|
||||
Write32(OUT, info->a_sda_reg, buffer);
|
||||
}
|
||||
|
||||
// Set pins to input
|
||||
buffer = Read32(OUT, info->en_scl_reg) & ~info->en_scl_mask;
|
||||
Write32(OUT, info->en_scl_reg, buffer);
|
||||
buffer = Read32(OUT, info->en_sda_reg) & ~info->en_sda_mask;
|
||||
Write32(OUT, info->en_sda_reg, buffer);
|
||||
|
||||
// mask GPIO pins for software use
|
||||
buffer = Read32(OUT, info->mask_scl_reg);
|
||||
if (lock == true) {
|
||||
buffer |= info->mask_scl_mask;
|
||||
} else {
|
||||
buffer &= ~info->mask_scl_mask;
|
||||
}
|
||||
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_mask;
|
||||
} else {
|
||||
buffer &= ~info->mask_sda_mask;
|
||||
}
|
||||
Write32(OUT, info->mask_sda_reg, buffer);
|
||||
Read32(OUT, info->mask_sda_reg);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
gpio_get_i2c_bit(void* cookie, int* _clock, int* _data)
|
||||
{
|
||||
gpio_info *info = (gpio_info*)cookie;
|
||||
|
||||
uint32 scl = Read32(OUT, info->y_scl_reg)
|
||||
& info->y_scl_mask;
|
||||
uint32 sda = Read32(OUT, info->y_sda_reg)
|
||||
& info->y_sda_mask;
|
||||
|
||||
*_clock = (scl != 0);
|
||||
*_data = (sda != 0);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
gpio_set_i2c_bit(void* cookie, int clock, int data)
|
||||
{
|
||||
gpio_info* info = (gpio_info*)cookie;
|
||||
|
||||
uint32 scl = Read32(OUT, info->en_scl_reg)
|
||||
& ~info->en_scl_mask;
|
||||
scl |= clock ? 0 : info->en_scl_mask;
|
||||
Write32(OUT, info->en_scl_reg, scl);
|
||||
Read32(OUT, info->en_scl_reg);
|
||||
|
||||
uint32 sda = Read32(OUT, info->en_sda_reg)
|
||||
& ~info->en_sda_mask;
|
||||
sda |= data ? 0 : info->en_sda_mask;
|
||||
Write32(OUT, info->en_sda_reg, sda);
|
||||
Read32(OUT, info->en_sda_reg);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
connector_read_edid(uint32 connector, edid1_info *edid)
|
||||
{
|
||||
// ensure things are sane
|
||||
uint32 gpioID = gConnector[connector]->gpioID;
|
||||
if (gGPIOInfo[gpioID]->valid == false)
|
||||
return false;
|
||||
|
||||
if (gConnector[connector]->type == VIDEO_CONNECTOR_LVDS) {
|
||||
// we should call connector_read_edid_lvds at some point
|
||||
ERROR("%s: LCD panel detected (LVDS), sending VESA EDID!\n",
|
||||
__func__);
|
||||
memcpy(edid, &gInfo->shared_info->edid_info, sizeof(struct edid1_info));
|
||||
return true;
|
||||
}
|
||||
|
||||
i2c_bus bus;
|
||||
|
||||
ddc2_init_timing(&bus);
|
||||
bus.cookie = (void*)gGPIOInfo[gpioID];
|
||||
bus.set_signals = &gpio_set_i2c_bit;
|
||||
bus.get_signals = &gpio_get_i2c_bit;
|
||||
|
||||
gpio_lock_i2c(bus.cookie, true);
|
||||
status_t edid_result = ddc2_read_edid1(&bus, edid, NULL, NULL);
|
||||
gpio_lock_i2c(bus.cookie, false);
|
||||
|
||||
if (edid_result != B_OK)
|
||||
return false;
|
||||
|
||||
TRACE("%s: found edid monitor on connector #%" B_PRId32 "\n",
|
||||
__func__, connector);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
bool
|
||||
connector_read_edid_lvds(uint32 connector, edid1_info *edid)
|
||||
{
|
||||
uint8 dceMajor;
|
||||
uint8 dceMinor;
|
||||
int index = GetIndexIntoMasterTable(DATA, LVDS_Info);
|
||||
uint16 offset;
|
||||
|
||||
if (atom_parse_data_header(gAtomContexg, index, NULL,
|
||||
&dceMajor, &dceMinor, &offset) == B_OK) {
|
||||
lvdsInfo = (union lvds_info *)(gAtomContext->bios + offset);
|
||||
|
||||
display_timing timing;
|
||||
// Pixel Clock
|
||||
timing.pixel_clock
|
||||
= B_LENDIAN_TO_HOST_INT16(lvdsInfo->info.sLCDTiming.usPixClk) * 10;
|
||||
// Horizontal
|
||||
timing.h_display
|
||||
= B_LENDIAN_TO_HOST_INT16(lvdsInfo->info.sLCDTiming.usHActive);
|
||||
timing.h_total = timing.h_display + B_LENDIAN_TO_HOST_INT16(
|
||||
lvdsInfo->info.sLCDTiming.usHBlanking_Time);
|
||||
timing.h_sync_start = timing.h_display
|
||||
+ B_LENDIAN_TO_HOST_INT16(lvdsInfo->info.sLCDTiming.usHSyncOffset);
|
||||
timing.h_sync_end = timing.h_sync_start
|
||||
+ B_LENDIAN_TO_HOST_INT16(lvdsInfo->info.sLCDTiming.usHSyncWidth);
|
||||
// Vertical
|
||||
timing.v_display
|
||||
= B_LENDIAN_TO_HOST_INT16(lvdsInfo->info.sLCDTiming.usVActive);
|
||||
timing.v_total = timing.v_display + B_LENDIAN_TO_HOST_INT16(
|
||||
lvdsInfo->info.sLCDTiming.usVBlanking_Time);
|
||||
timing.v_sync_start = timing.v_display
|
||||
+ B_LENDIAN_TO_HOST_INT16(lvdsInfo->info.sLCDTiming.usVSyncOffset);
|
||||
timing.v_sync_end = timing.v_sync_start
|
||||
+ B_LENDIAN_TO_HOST_INT16(lvdsInfo->info.sLCDTiming.usVSyncWidth);
|
||||
|
||||
#if 0
|
||||
// Who cares.
|
||||
uint32 powerDelay
|
||||
= B_LENDIAN_TO_HOST_INT16(lvdsInfo->info.usOffDelayInMs);
|
||||
uint32 lcdMisc = lvdsInfo->info.ucLVDS_Misc;
|
||||
#endif
|
||||
|
||||
uint16 flags = B_LENDIAN_TO_HOST_INT16(
|
||||
lvdsInfo->info.sLCDTiming.susModeMiscInfo.usAccess);
|
||||
|
||||
if ((flags & ATOM_VSYNC_POLARITY) == 0)
|
||||
timing.flags |= B_POSITIVE_VSYNC;
|
||||
if ((flags & ATOM_HSYNC_POLARITY) == 0)
|
||||
timing.flags |= B_POSITIVE_HSYNC;
|
||||
|
||||
// Extra flags
|
||||
if ((flags & ATOM_INTERLACE) != 0)
|
||||
timing.flags |= B_TIMING_INTERLACED;
|
||||
|
||||
#if 0
|
||||
// We don't use these timing flags at the moment
|
||||
if ((flags & ATOM_COMPOSITESYNC) != 0)
|
||||
timing.flags |= MODE_FLAG_CSYNC;
|
||||
if ((flags & ATOM_DOUBLE_CLOCK_MODE) != 0)
|
||||
timing.flags |= MODE_FLAG_DBLSCAN;
|
||||
#endif
|
||||
|
||||
// TODO: generate a fake EDID with information above
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
status_t
|
||||
connector_attach_gpio(uint32 id, uint8 hw_line)
|
||||
{
|
||||
gConnector[id]->gpioID = 0;
|
||||
for (uint32 i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) {
|
||||
if (gGPIOInfo[i]->hw_line != hw_line)
|
||||
continue;
|
||||
gConnector[id]->gpioID = i;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
TRACE("%s: couldn't find GPIO for connector %" B_PRIu32 "\n",
|
||||
__func__, id);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
gpio_probe()
|
||||
{
|
||||
radeon_shared_info &info = *gInfo->shared_info;
|
||||
|
||||
int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info);
|
||||
|
||||
uint8 tableMajor;
|
||||
uint8 tableMinor;
|
||||
uint16 tableOffset;
|
||||
uint16 tableSize;
|
||||
|
||||
if (atom_parse_data_header(gAtomContext, index, &tableSize,
|
||||
&tableMajor, &tableMinor, &tableOffset) != B_OK) {
|
||||
ERROR("%s: could't read GPIO_I2C_Info table from AtomBIOS index %d!\n",
|
||||
__func__, index);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
struct _ATOM_GPIO_I2C_INFO *i2c_info
|
||||
= (struct _ATOM_GPIO_I2C_INFO *)(gAtomContext->bios + tableOffset);
|
||||
|
||||
uint32 numIndices = (tableSize - sizeof(ATOM_COMMON_TABLE_HEADER))
|
||||
/ sizeof(ATOM_GPIO_I2C_ASSIGMENT);
|
||||
|
||||
if (numIndices > ATOM_MAX_SUPPORTED_DEVICE) {
|
||||
ERROR("%s: ERROR: AtomBIOS contains more GPIO_Info items then I"
|
||||
"was prepared for! (seen: %" B_PRIu32 "; max: %" B_PRIu32 ")\n",
|
||||
__func__, numIndices, (uint32)ATOM_MAX_SUPPORTED_DEVICE);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < numIndices; i++) {
|
||||
ATOM_GPIO_I2C_ASSIGMENT *gpio = &i2c_info->asGPIO_Info[i];
|
||||
|
||||
if (info.dceMajor >= 3) {
|
||||
if (i == 4 && B_LENDIAN_TO_HOST_INT16(gpio->usClkMaskRegisterIndex)
|
||||
== 0x1fda && gpio->sucI2cId.ucAccess == 0x94) {
|
||||
gpio->sucI2cId.ucAccess = 0x14;
|
||||
TRACE("%s: BUG: GPIO override for DCE 3 occured\n", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
if (info.dceMajor >= 4) {
|
||||
if (i == 7 && B_LENDIAN_TO_HOST_INT16(gpio->usClkMaskRegisterIndex)
|
||||
== 0x1936 && gpio->sucI2cId.ucAccess == 0) {
|
||||
gpio->sucI2cId.ucAccess = 0x97;
|
||||
gpio->ucDataMaskShift = 8;
|
||||
gpio->ucDataEnShift = 8;
|
||||
gpio->ucDataY_Shift = 8;
|
||||
gpio->ucDataA_Shift = 8;
|
||||
TRACE("%s: BUG: GPIO override for DCE 4 occured\n", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
// populate gpio information
|
||||
gGPIOInfo[i]->hw_line
|
||||
= gpio->sucI2cId.ucAccess;
|
||||
gGPIOInfo[i]->hw_capable
|
||||
= (gpio->sucI2cId.sbfAccess.bfHW_Capable) ? true : false;
|
||||
|
||||
// GPIO mask (Allows software to control the GPIO pad)
|
||||
// 0 = chip access; 1 = only software;
|
||||
gGPIOInfo[i]->mask_scl_reg
|
||||
= B_LENDIAN_TO_HOST_INT16(gpio->usClkMaskRegisterIndex) * 4;
|
||||
gGPIOInfo[i]->mask_sda_reg
|
||||
= B_LENDIAN_TO_HOST_INT16(gpio->usDataMaskRegisterIndex) * 4;
|
||||
gGPIOInfo[i]->mask_scl_mask
|
||||
= (1 << gpio->ucClkMaskShift);
|
||||
gGPIOInfo[i]->mask_sda_mask
|
||||
= (1 << gpio->ucDataMaskShift);
|
||||
|
||||
// GPIO output / write (A) enable
|
||||
// 0 = GPIO input (Y); 1 = GPIO output (A);
|
||||
gGPIOInfo[i]->en_scl_reg
|
||||
= B_LENDIAN_TO_HOST_INT16(gpio->usClkEnRegisterIndex) * 4;
|
||||
gGPIOInfo[i]->en_sda_reg
|
||||
= B_LENDIAN_TO_HOST_INT16(gpio->usDataEnRegisterIndex) * 4;
|
||||
gGPIOInfo[i]->en_scl_mask
|
||||
= (1 << gpio->ucClkEnShift);
|
||||
gGPIOInfo[i]->en_sda_mask
|
||||
= (1 << gpio->ucDataEnShift);
|
||||
|
||||
// GPIO output / write (A)
|
||||
gGPIOInfo[i]->a_scl_reg
|
||||
= B_LENDIAN_TO_HOST_INT16(gpio->usClkA_RegisterIndex) * 4;
|
||||
gGPIOInfo[i]->a_sda_reg
|
||||
= B_LENDIAN_TO_HOST_INT16(gpio->usDataA_RegisterIndex) * 4;
|
||||
gGPIOInfo[i]->a_scl_mask
|
||||
= (1 << gpio->ucClkA_Shift);
|
||||
gGPIOInfo[i]->a_sda_mask
|
||||
= (1 << gpio->ucDataA_Shift);
|
||||
|
||||
// GPIO input / read (Y)
|
||||
gGPIOInfo[i]->y_scl_reg
|
||||
= B_LENDIAN_TO_HOST_INT16(gpio->usClkY_RegisterIndex) * 4;
|
||||
gGPIOInfo[i]->y_sda_reg
|
||||
= B_LENDIAN_TO_HOST_INT16(gpio->usDataY_RegisterIndex) * 4;
|
||||
gGPIOInfo[i]->y_scl_mask
|
||||
= (1 << gpio->ucClkY_Shift);
|
||||
gGPIOInfo[i]->y_sda_mask
|
||||
= (1 << gpio->ucDataY_Shift);
|
||||
|
||||
// ensure data is valid
|
||||
gGPIOInfo[i]->valid = (gGPIOInfo[i]->mask_scl_reg) ? true : false;
|
||||
|
||||
TRACE("%s: GPIO @ %" B_PRIu32 ", valid: %s, hw_line: 0x%" B_PRIX32 "\n",
|
||||
__func__, i, gGPIOInfo[i]->valid ? "true" : "false",
|
||||
gGPIOInfo[i]->hw_line);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright 2006-2011, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander von Gluck, [email protected]
|
||||
*/
|
||||
#ifndef RADEON_HD_CONNECTOR_H
|
||||
#define RADEON_HD_CONNECTOR_H
|
||||
|
||||
status_t gpio_probe();
|
||||
status_t connector_attach_gpio(uint32 id, uint8 hw_line);
|
||||
bool connector_read_edid(uint32 connector, edid1_info *edid);
|
||||
|
||||
#endif
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "accelerant_protos.h"
|
||||
#include "accelerant.h"
|
||||
#include "bios.h"
|
||||
#include "connector.h"
|
||||
#include "display.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
@@ -322,7 +323,7 @@ detect_connectors_legacy()
|
||||
gConnector[connectorIndex]->encoder.isExternal
|
||||
= encoder_is_external(encoderID);
|
||||
|
||||
radeon_gpu_i2c_attach(connectorIndex, ci.sucI2cId.ucAccess);
|
||||
connector_attach_gpio(connectorIndex, ci.sucI2cId.ucAccess);
|
||||
|
||||
pll_limit_probe(&gConnector[connectorIndex]->encoder.pll);
|
||||
|
||||
@@ -558,7 +559,7 @@ detect_connectors()
|
||||
= (ATOM_I2C_ID_CONFIG_ACCESS *)
|
||||
&i2c_record->sucI2cId;
|
||||
// attach i2c gpio information for connector
|
||||
radeon_gpu_i2c_attach(connectorIndex,
|
||||
connector_attach_gpio(connectorIndex,
|
||||
i2c_config->ucAccess);
|
||||
break;
|
||||
case ATOM_HPD_INT_RECORD_TYPE:
|
||||
@@ -625,7 +626,7 @@ detect_displays()
|
||||
if (displayIndex >= MAX_DISPLAY)
|
||||
continue;
|
||||
|
||||
if (radeon_gpu_read_edid(id, &gDisplay[displayIndex]->edid_info)) {
|
||||
if (connector_read_edid(id, &gDisplay[displayIndex]->edid_info)) {
|
||||
|
||||
if (gConnector[id]->encoder.type == VIDEO_ENCODER_TVDAC
|
||||
|| gConnector[id]->encoder.type == VIDEO_ENCODER_DAC) {
|
||||
|
||||
@@ -523,331 +523,3 @@ radeon_gpu_irq_setup()
|
||||
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
lock_i2c(void* cookie, bool lock)
|
||||
{
|
||||
gpio_info *info = (gpio_info*)cookie;
|
||||
radeon_shared_info &sinfo = *gInfo->shared_info;
|
||||
|
||||
uint32 buffer = 0;
|
||||
|
||||
if (lock == true) {
|
||||
// hw_capable and > DCE3
|
||||
if (info->hw_capable == true
|
||||
&& sinfo.dceMajor >= 3) {
|
||||
// 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->a_scl_reg) & ~info->a_scl_mask;
|
||||
Write32(OUT, info->a_scl_reg, buffer);
|
||||
buffer = Read32(OUT, info->a_sda_reg) & ~info->a_sda_mask;
|
||||
Write32(OUT, info->a_sda_reg, buffer);
|
||||
}
|
||||
|
||||
// Set pins to input
|
||||
buffer = Read32(OUT, info->en_scl_reg) & ~info->en_scl_mask;
|
||||
Write32(OUT, info->en_scl_reg, buffer);
|
||||
buffer = Read32(OUT, info->en_sda_reg) & ~info->en_sda_mask;
|
||||
Write32(OUT, info->en_sda_reg, buffer);
|
||||
|
||||
// mask GPIO pins for software use
|
||||
buffer = Read32(OUT, info->mask_scl_reg);
|
||||
if (lock == true) {
|
||||
buffer |= info->mask_scl_mask;
|
||||
} else {
|
||||
buffer &= ~info->mask_scl_mask;
|
||||
}
|
||||
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_mask;
|
||||
} else {
|
||||
buffer &= ~info->mask_sda_mask;
|
||||
}
|
||||
Write32(OUT, info->mask_sda_reg, buffer);
|
||||
Read32(OUT, info->mask_sda_reg);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
get_i2c_signals(void* cookie, int* _clock, int* _data)
|
||||
{
|
||||
gpio_info *info = (gpio_info*)cookie;
|
||||
|
||||
uint32 scl = Read32(OUT, info->y_scl_reg)
|
||||
& info->y_scl_mask;
|
||||
uint32 sda = Read32(OUT, info->y_sda_reg)
|
||||
& info->y_sda_mask;
|
||||
|
||||
*_clock = (scl != 0);
|
||||
*_data = (sda != 0);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
set_i2c_signals(void* cookie, int clock, int data)
|
||||
{
|
||||
gpio_info* info = (gpio_info*)cookie;
|
||||
|
||||
uint32 scl = Read32(OUT, info->en_scl_reg)
|
||||
& ~info->en_scl_mask;
|
||||
scl |= clock ? 0 : info->en_scl_mask;
|
||||
Write32(OUT, info->en_scl_reg, scl);
|
||||
Read32(OUT, info->en_scl_reg);
|
||||
|
||||
uint32 sda = Read32(OUT, info->en_sda_reg)
|
||||
& ~info->en_sda_mask;
|
||||
sda |= data ? 0 : info->en_sda_mask;
|
||||
Write32(OUT, info->en_sda_reg, sda);
|
||||
Read32(OUT, info->en_sda_reg);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
radeon_gpu_read_edid(uint32 connector, edid1_info *edid)
|
||||
{
|
||||
// ensure things are sane
|
||||
uint32 gpioID = gConnector[connector]->gpioID;
|
||||
if (gGPIOInfo[gpioID]->valid == false)
|
||||
return false;
|
||||
|
||||
if (gConnector[connector]->type == VIDEO_CONNECTOR_LVDS) {
|
||||
// we should call radeon_gpu_read_edid_lvds at some point
|
||||
ERROR("%s: LCD panel detected (LVDS), sending VESA EDID!\n",
|
||||
__func__);
|
||||
memcpy(edid, &gInfo->shared_info->edid_info, sizeof(struct edid1_info));
|
||||
return true;
|
||||
}
|
||||
|
||||
i2c_bus bus;
|
||||
|
||||
ddc2_init_timing(&bus);
|
||||
bus.cookie = (void*)gGPIOInfo[gpioID];
|
||||
bus.set_signals = &set_i2c_signals;
|
||||
bus.get_signals = &get_i2c_signals;
|
||||
|
||||
lock_i2c(bus.cookie, true);
|
||||
status_t edid_result = ddc2_read_edid1(&bus, edid, NULL, NULL);
|
||||
lock_i2c(bus.cookie, false);
|
||||
|
||||
if (edid_result != B_OK)
|
||||
return false;
|
||||
|
||||
TRACE("%s: found edid monitor on connector #%" B_PRId32 "\n",
|
||||
__func__, connector);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
bool
|
||||
radeon_gpu_read_edid_lvds(uint32 connector, edid1_info *edid)
|
||||
{
|
||||
uint8 dceMajor;
|
||||
uint8 dceMinor;
|
||||
int index = GetIndexIntoMasterTable(DATA, LVDS_Info);
|
||||
uint16 offset;
|
||||
|
||||
if (atom_parse_data_header(gAtomContexg, index, NULL,
|
||||
&dceMajor, &dceMinor, &offset) == B_OK) {
|
||||
lvdsInfo = (union lvds_info *)(gAtomContext->bios + offset);
|
||||
|
||||
display_timing timing;
|
||||
// Pixel Clock
|
||||
timing.pixel_clock
|
||||
= B_LENDIAN_TO_HOST_INT16(lvdsInfo->info.sLCDTiming.usPixClk) * 10;
|
||||
// Horizontal
|
||||
timing.h_display
|
||||
= B_LENDIAN_TO_HOST_INT16(lvdsInfo->info.sLCDTiming.usHActive);
|
||||
timing.h_total = timing.h_display + B_LENDIAN_TO_HOST_INT16(
|
||||
lvdsInfo->info.sLCDTiming.usHBlanking_Time);
|
||||
timing.h_sync_start = timing.h_display
|
||||
+ B_LENDIAN_TO_HOST_INT16(lvdsInfo->info.sLCDTiming.usHSyncOffset);
|
||||
timing.h_sync_end = timing.h_sync_start
|
||||
+ B_LENDIAN_TO_HOST_INT16(lvdsInfo->info.sLCDTiming.usHSyncWidth);
|
||||
// Vertical
|
||||
timing.v_display
|
||||
= B_LENDIAN_TO_HOST_INT16(lvdsInfo->info.sLCDTiming.usVActive);
|
||||
timing.v_total = timing.v_display + B_LENDIAN_TO_HOST_INT16(
|
||||
lvdsInfo->info.sLCDTiming.usVBlanking_Time);
|
||||
timing.v_sync_start = timing.v_display
|
||||
+ B_LENDIAN_TO_HOST_INT16(lvdsInfo->info.sLCDTiming.usVSyncOffset);
|
||||
timing.v_sync_end = timing.v_sync_start
|
||||
+ B_LENDIAN_TO_HOST_INT16(lvdsInfo->info.sLCDTiming.usVSyncWidth);
|
||||
|
||||
#if 0
|
||||
// Who cares.
|
||||
uint32 powerDelay
|
||||
= B_LENDIAN_TO_HOST_INT16(lvdsInfo->info.usOffDelayInMs);
|
||||
uint32 lcdMisc = lvdsInfo->info.ucLVDS_Misc;
|
||||
#endif
|
||||
|
||||
uint16 flags = B_LENDIAN_TO_HOST_INT16(
|
||||
lvdsInfo->info.sLCDTiming.susModeMiscInfo.usAccess);
|
||||
|
||||
if ((flags & ATOM_VSYNC_POLARITY) == 0)
|
||||
timing.flags |= B_POSITIVE_VSYNC;
|
||||
if ((flags & ATOM_HSYNC_POLARITY) == 0)
|
||||
timing.flags |= B_POSITIVE_HSYNC;
|
||||
|
||||
// Extra flags
|
||||
if ((flags & ATOM_INTERLACE) != 0)
|
||||
timing.flags |= B_TIMING_INTERLACED;
|
||||
|
||||
#if 0
|
||||
// We don't use these timing flags at the moment
|
||||
if ((flags & ATOM_COMPOSITESYNC) != 0)
|
||||
timing.flags |= MODE_FLAG_CSYNC;
|
||||
if ((flags & ATOM_DOUBLE_CLOCK_MODE) != 0)
|
||||
timing.flags |= MODE_FLAG_DBLSCAN;
|
||||
#endif
|
||||
|
||||
// TODO: generate a fake EDID with information above
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
status_t
|
||||
radeon_gpu_i2c_attach(uint32 id, uint8 hw_line)
|
||||
{
|
||||
gConnector[id]->gpioID = 0;
|
||||
for (uint32 i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) {
|
||||
if (gGPIOInfo[i]->hw_line != hw_line)
|
||||
continue;
|
||||
gConnector[id]->gpioID = i;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
TRACE("%s: couldn't find GPIO for connector %" B_PRIu32 "\n",
|
||||
__func__, id);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
radeon_gpu_gpio_setup()
|
||||
{
|
||||
radeon_shared_info &info = *gInfo->shared_info;
|
||||
|
||||
int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info);
|
||||
|
||||
uint8 tableMajor;
|
||||
uint8 tableMinor;
|
||||
uint16 tableOffset;
|
||||
uint16 tableSize;
|
||||
|
||||
if (atom_parse_data_header(gAtomContext, index, &tableSize,
|
||||
&tableMajor, &tableMinor, &tableOffset) != B_OK) {
|
||||
ERROR("%s: could't read GPIO_I2C_Info table from AtomBIOS index %d!\n",
|
||||
__func__, index);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
struct _ATOM_GPIO_I2C_INFO *i2c_info
|
||||
= (struct _ATOM_GPIO_I2C_INFO *)(gAtomContext->bios + tableOffset);
|
||||
|
||||
uint32 numIndices = (tableSize - sizeof(ATOM_COMMON_TABLE_HEADER))
|
||||
/ sizeof(ATOM_GPIO_I2C_ASSIGMENT);
|
||||
|
||||
if (numIndices > ATOM_MAX_SUPPORTED_DEVICE) {
|
||||
ERROR("%s: ERROR: AtomBIOS contains more GPIO_Info items then I"
|
||||
"was prepared for! (seen: %" B_PRIu32 "; max: %" B_PRIu32 ")\n",
|
||||
__func__, numIndices, (uint32)ATOM_MAX_SUPPORTED_DEVICE);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < numIndices; i++) {
|
||||
ATOM_GPIO_I2C_ASSIGMENT *gpio = &i2c_info->asGPIO_Info[i];
|
||||
|
||||
if (info.dceMajor >= 3) {
|
||||
if (i == 4 && B_LENDIAN_TO_HOST_INT16(gpio->usClkMaskRegisterIndex)
|
||||
== 0x1fda && gpio->sucI2cId.ucAccess == 0x94) {
|
||||
gpio->sucI2cId.ucAccess = 0x14;
|
||||
TRACE("%s: BUG: GPIO override for DCE 3 occured\n", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
if (info.dceMajor >= 4) {
|
||||
if (i == 7 && B_LENDIAN_TO_HOST_INT16(gpio->usClkMaskRegisterIndex)
|
||||
== 0x1936 && gpio->sucI2cId.ucAccess == 0) {
|
||||
gpio->sucI2cId.ucAccess = 0x97;
|
||||
gpio->ucDataMaskShift = 8;
|
||||
gpio->ucDataEnShift = 8;
|
||||
gpio->ucDataY_Shift = 8;
|
||||
gpio->ucDataA_Shift = 8;
|
||||
TRACE("%s: BUG: GPIO override for DCE 4 occured\n", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
// populate gpio information
|
||||
gGPIOInfo[i]->hw_line
|
||||
= gpio->sucI2cId.ucAccess;
|
||||
gGPIOInfo[i]->hw_capable
|
||||
= (gpio->sucI2cId.sbfAccess.bfHW_Capable) ? true : false;
|
||||
|
||||
// GPIO mask (Allows software to control the GPIO pad)
|
||||
// 0 = chip access; 1 = only software;
|
||||
gGPIOInfo[i]->mask_scl_reg
|
||||
= B_LENDIAN_TO_HOST_INT16(gpio->usClkMaskRegisterIndex) * 4;
|
||||
gGPIOInfo[i]->mask_sda_reg
|
||||
= B_LENDIAN_TO_HOST_INT16(gpio->usDataMaskRegisterIndex) * 4;
|
||||
gGPIOInfo[i]->mask_scl_mask
|
||||
= (1 << gpio->ucClkMaskShift);
|
||||
gGPIOInfo[i]->mask_sda_mask
|
||||
= (1 << gpio->ucDataMaskShift);
|
||||
|
||||
// GPIO output / write (A) enable
|
||||
// 0 = GPIO input (Y); 1 = GPIO output (A);
|
||||
gGPIOInfo[i]->en_scl_reg
|
||||
= B_LENDIAN_TO_HOST_INT16(gpio->usClkEnRegisterIndex) * 4;
|
||||
gGPIOInfo[i]->en_sda_reg
|
||||
= B_LENDIAN_TO_HOST_INT16(gpio->usDataEnRegisterIndex) * 4;
|
||||
gGPIOInfo[i]->en_scl_mask
|
||||
= (1 << gpio->ucClkEnShift);
|
||||
gGPIOInfo[i]->en_sda_mask
|
||||
= (1 << gpio->ucDataEnShift);
|
||||
|
||||
// GPIO output / write (A)
|
||||
gGPIOInfo[i]->a_scl_reg
|
||||
= B_LENDIAN_TO_HOST_INT16(gpio->usClkA_RegisterIndex) * 4;
|
||||
gGPIOInfo[i]->a_sda_reg
|
||||
= B_LENDIAN_TO_HOST_INT16(gpio->usDataA_RegisterIndex) * 4;
|
||||
gGPIOInfo[i]->a_scl_mask
|
||||
= (1 << gpio->ucClkA_Shift);
|
||||
gGPIOInfo[i]->a_sda_mask
|
||||
= (1 << gpio->ucDataA_Shift);
|
||||
|
||||
// GPIO input / read (Y)
|
||||
gGPIOInfo[i]->y_scl_reg
|
||||
= B_LENDIAN_TO_HOST_INT16(gpio->usClkY_RegisterIndex) * 4;
|
||||
gGPIOInfo[i]->y_sda_reg
|
||||
= B_LENDIAN_TO_HOST_INT16(gpio->usDataY_RegisterIndex) * 4;
|
||||
gGPIOInfo[i]->y_scl_mask
|
||||
= (1 << gpio->ucClkY_Shift);
|
||||
gGPIOInfo[i]->y_sda_mask
|
||||
= (1 << gpio->ucDataY_Shift);
|
||||
|
||||
// ensure data is valid
|
||||
gGPIOInfo[i]->valid = (gGPIOInfo[i]->mask_scl_reg) ? true : false;
|
||||
|
||||
TRACE("%s: GPIO @ %" B_PRIu32 ", valid: %s, hw_line: 0x%" B_PRIX32 "\n",
|
||||
__func__, i, gGPIOInfo[i]->valid ? "true" : "false",
|
||||
gGPIOInfo[i]->hw_line);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -176,9 +176,6 @@ void radeon_gpu_mc_resume(struct gpu_state *gpuState);
|
||||
uint32 radeon_gpu_mc_idlecheck();
|
||||
status_t radeon_gpu_mc_setup();
|
||||
status_t radeon_gpu_irq_setup();
|
||||
status_t radeon_gpu_gpio_setup();
|
||||
status_t radeon_gpu_i2c_attach(uint32 id, uint8 hw_line);
|
||||
bool radeon_gpu_read_edid(uint32 connector, edid1_info *edid);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user