forked from Minki/linux
Merge remote branch 'korg/drm-radeon-dp' into drm-linus
This merges the radeon KMS DisplayPort and hotplug detect support. Tested on RV635 DP card with a Dell 2408 monitor. Conflicts: drivers/gpu/drm/drm_fb_helper.c
This commit is contained in:
commit
7b0a9e8302
@ -49,7 +49,7 @@ radeon-y += radeon_device.o radeon_kms.o \
|
||||
radeon_cs.o radeon_bios.o radeon_benchmark.o r100.o r300.o r420.o \
|
||||
rs400.o rs600.o rs690.o rv515.o r520.o r600.o rv770.o radeon_test.o \
|
||||
r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \
|
||||
r600_blit_kms.o radeon_pm.o
|
||||
r600_blit_kms.o radeon_pm.o atombios_dp.o
|
||||
|
||||
radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
|
||||
|
||||
|
@ -263,10 +263,10 @@ static uint32_t atom_get_src_int(atom_exec_context *ctx, uint8_t attr,
|
||||
case ATOM_ARG_FB:
|
||||
idx = U8(*ptr);
|
||||
(*ptr)++;
|
||||
val = gctx->scratch[((gctx->fb_base + idx) / 4)];
|
||||
if (print)
|
||||
DEBUG("FB[0x%02X]", idx);
|
||||
printk(KERN_INFO "FB access is not implemented.\n");
|
||||
return 0;
|
||||
break;
|
||||
case ATOM_ARG_IMM:
|
||||
switch (align) {
|
||||
case ATOM_SRC_DWORD:
|
||||
@ -488,9 +488,9 @@ static void atom_put_dst(atom_exec_context *ctx, int arg, uint8_t attr,
|
||||
case ATOM_ARG_FB:
|
||||
idx = U8(*ptr);
|
||||
(*ptr)++;
|
||||
gctx->scratch[((gctx->fb_base + idx) / 4)] = val;
|
||||
DEBUG("FB[0x%02X]", idx);
|
||||
printk(KERN_INFO "FB access is not implemented.\n");
|
||||
return;
|
||||
break;
|
||||
case ATOM_ARG_PLL:
|
||||
idx = U8(*ptr);
|
||||
(*ptr)++;
|
||||
@ -1214,3 +1214,28 @@ void atom_parse_cmd_header(struct atom_context *ctx, int index, uint8_t * frev,
|
||||
*crev = CU8(idx + 3);
|
||||
return;
|
||||
}
|
||||
|
||||
int atom_allocate_fb_scratch(struct atom_context *ctx)
|
||||
{
|
||||
int index = GetIndexIntoMasterTable(DATA, VRAM_UsageByFirmware);
|
||||
uint16_t data_offset;
|
||||
int usage_bytes;
|
||||
struct _ATOM_VRAM_USAGE_BY_FIRMWARE *firmware_usage;
|
||||
|
||||
atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset);
|
||||
|
||||
firmware_usage = (struct _ATOM_VRAM_USAGE_BY_FIRMWARE *)(ctx->bios + data_offset);
|
||||
|
||||
DRM_DEBUG("atom firmware requested %08x %dkb\n",
|
||||
firmware_usage->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware,
|
||||
firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb);
|
||||
|
||||
usage_bytes = firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb * 1024;
|
||||
if (usage_bytes == 0)
|
||||
usage_bytes = 20 * 1024;
|
||||
/* allocate some scratch memory */
|
||||
ctx->scratch = kzalloc(usage_bytes, GFP_KERNEL);
|
||||
if (!ctx->scratch)
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
@ -132,6 +132,7 @@ struct atom_context {
|
||||
uint8_t shift;
|
||||
int cs_equal, cs_above;
|
||||
int io_mode;
|
||||
uint32_t *scratch;
|
||||
};
|
||||
|
||||
extern int atom_debug;
|
||||
@ -142,6 +143,7 @@ int atom_asic_init(struct atom_context *);
|
||||
void atom_destroy(struct atom_context *);
|
||||
void atom_parse_data_header(struct atom_context *ctx, int index, uint16_t *size, uint8_t *frev, uint8_t *crev, uint16_t *data_start);
|
||||
void atom_parse_cmd_header(struct atom_context *ctx, int index, uint8_t *frev, uint8_t *crev);
|
||||
int atom_allocate_fb_scratch(struct atom_context *ctx);
|
||||
#include "atom-types.h"
|
||||
#include "atombios.h"
|
||||
#include "ObjectID.h"
|
||||
|
@ -2680,7 +2680,7 @@ typedef struct _ATOM_I2C_RECORD {
|
||||
typedef struct _ATOM_HPD_INT_RECORD {
|
||||
ATOM_COMMON_RECORD_HEADER sheader;
|
||||
UCHAR ucHPDIntGPIOID; /* Corresponding block in GPIO_PIN_INFO table gives the pin info */
|
||||
UCHAR ucPluggged_PinState;
|
||||
UCHAR ucPlugged_PinState;
|
||||
} ATOM_HPD_INT_RECORD;
|
||||
|
||||
typedef struct _ATOM_OUTPUT_PROTECTION_RECORD {
|
||||
|
790
drivers/gpu/drm/radeon/atombios_dp.c
Normal file
790
drivers/gpu/drm/radeon/atombios_dp.c
Normal file
@ -0,0 +1,790 @@
|
||||
/*
|
||||
* Copyright 2007-8 Advanced Micro Devices, Inc.
|
||||
* Copyright 2008 Red Hat Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: Dave Airlie
|
||||
* Alex Deucher
|
||||
*/
|
||||
#include "drmP.h"
|
||||
#include "radeon_drm.h"
|
||||
#include "radeon.h"
|
||||
|
||||
#include "atom.h"
|
||||
#include "atom-bits.h"
|
||||
#include "drm_dp_helper.h"
|
||||
|
||||
/* move these to drm_dp_helper.c/h */
|
||||
#define DP_LINK_CONFIGURATION_SIZE 9
|
||||
#define DP_LINK_STATUS_SIZE 6
|
||||
#define DP_DPCD_SIZE 8
|
||||
|
||||
static char *voltage_names[] = {
|
||||
"0.4V", "0.6V", "0.8V", "1.2V"
|
||||
};
|
||||
static char *pre_emph_names[] = {
|
||||
"0dB", "3.5dB", "6dB", "9.5dB"
|
||||
};
|
||||
|
||||
static const int dp_clocks[] = {
|
||||
54000, /* 1 lane, 1.62 Ghz */
|
||||
90000, /* 1 lane, 2.70 Ghz */
|
||||
108000, /* 2 lane, 1.62 Ghz */
|
||||
180000, /* 2 lane, 2.70 Ghz */
|
||||
216000, /* 4 lane, 1.62 Ghz */
|
||||
360000, /* 4 lane, 2.70 Ghz */
|
||||
};
|
||||
|
||||
static const int num_dp_clocks = sizeof(dp_clocks) / sizeof(int);
|
||||
|
||||
/* common helper functions */
|
||||
static int dp_lanes_for_mode_clock(u8 dpcd[DP_DPCD_SIZE], int mode_clock)
|
||||
{
|
||||
int i;
|
||||
u8 max_link_bw;
|
||||
u8 max_lane_count;
|
||||
|
||||
if (!dpcd)
|
||||
return 0;
|
||||
|
||||
max_link_bw = dpcd[DP_MAX_LINK_RATE];
|
||||
max_lane_count = dpcd[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK;
|
||||
|
||||
switch (max_link_bw) {
|
||||
case DP_LINK_BW_1_62:
|
||||
default:
|
||||
for (i = 0; i < num_dp_clocks; i++) {
|
||||
if (i % 2)
|
||||
continue;
|
||||
switch (max_lane_count) {
|
||||
case 1:
|
||||
if (i > 1)
|
||||
return 0;
|
||||
break;
|
||||
case 2:
|
||||
if (i > 3)
|
||||
return 0;
|
||||
break;
|
||||
case 4:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (dp_clocks[i] > mode_clock) {
|
||||
if (i < 2)
|
||||
return 1;
|
||||
else if (i < 4)
|
||||
return 2;
|
||||
else
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DP_LINK_BW_2_7:
|
||||
for (i = 0; i < num_dp_clocks; i++) {
|
||||
switch (max_lane_count) {
|
||||
case 1:
|
||||
if (i > 1)
|
||||
return 0;
|
||||
break;
|
||||
case 2:
|
||||
if (i > 3)
|
||||
return 0;
|
||||
break;
|
||||
case 4:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (dp_clocks[i] > mode_clock) {
|
||||
if (i < 2)
|
||||
return 1;
|
||||
else if (i < 4)
|
||||
return 2;
|
||||
else
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dp_link_clock_for_mode_clock(u8 dpcd[DP_DPCD_SIZE], int mode_clock)
|
||||
{
|
||||
int i;
|
||||
u8 max_link_bw;
|
||||
u8 max_lane_count;
|
||||
|
||||
if (!dpcd)
|
||||
return 0;
|
||||
|
||||
max_link_bw = dpcd[DP_MAX_LINK_RATE];
|
||||
max_lane_count = dpcd[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK;
|
||||
|
||||
switch (max_link_bw) {
|
||||
case DP_LINK_BW_1_62:
|
||||
default:
|
||||
for (i = 0; i < num_dp_clocks; i++) {
|
||||
if (i % 2)
|
||||
continue;
|
||||
switch (max_lane_count) {
|
||||
case 1:
|
||||
if (i > 1)
|
||||
return 0;
|
||||
break;
|
||||
case 2:
|
||||
if (i > 3)
|
||||
return 0;
|
||||
break;
|
||||
case 4:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (dp_clocks[i] > mode_clock)
|
||||
return 162000;
|
||||
}
|
||||
break;
|
||||
case DP_LINK_BW_2_7:
|
||||
for (i = 0; i < num_dp_clocks; i++) {
|
||||
switch (max_lane_count) {
|
||||
case 1:
|
||||
if (i > 1)
|
||||
return 0;
|
||||
break;
|
||||
case 2:
|
||||
if (i > 3)
|
||||
return 0;
|
||||
break;
|
||||
case 4:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (dp_clocks[i] > mode_clock)
|
||||
return (i % 2) ? 270000 : 162000;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dp_mode_valid(u8 dpcd[DP_DPCD_SIZE], int mode_clock)
|
||||
{
|
||||
int lanes = dp_lanes_for_mode_clock(dpcd, mode_clock);
|
||||
int bw = dp_lanes_for_mode_clock(dpcd, mode_clock);
|
||||
|
||||
if ((lanes == 0) || (bw == 0))
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static u8 dp_link_status(u8 link_status[DP_LINK_STATUS_SIZE], int r)
|
||||
{
|
||||
return link_status[r - DP_LANE0_1_STATUS];
|
||||
}
|
||||
|
||||
static u8 dp_get_lane_status(u8 link_status[DP_LINK_STATUS_SIZE],
|
||||
int lane)
|
||||
{
|
||||
int i = DP_LANE0_1_STATUS + (lane >> 1);
|
||||
int s = (lane & 1) * 4;
|
||||
u8 l = dp_link_status(link_status, i);
|
||||
return (l >> s) & 0xf;
|
||||
}
|
||||
|
||||
static bool dp_clock_recovery_ok(u8 link_status[DP_LINK_STATUS_SIZE],
|
||||
int lane_count)
|
||||
{
|
||||
int lane;
|
||||
u8 lane_status;
|
||||
|
||||
for (lane = 0; lane < lane_count; lane++) {
|
||||
lane_status = dp_get_lane_status(link_status, lane);
|
||||
if ((lane_status & DP_LANE_CR_DONE) == 0)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool dp_channel_eq_ok(u8 link_status[DP_LINK_STATUS_SIZE],
|
||||
int lane_count)
|
||||
{
|
||||
u8 lane_align;
|
||||
u8 lane_status;
|
||||
int lane;
|
||||
|
||||
lane_align = dp_link_status(link_status,
|
||||
DP_LANE_ALIGN_STATUS_UPDATED);
|
||||
if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0)
|
||||
return false;
|
||||
for (lane = 0; lane < lane_count; lane++) {
|
||||
lane_status = dp_get_lane_status(link_status, lane);
|
||||
if ((lane_status & DP_CHANNEL_EQ_BITS) != DP_CHANNEL_EQ_BITS)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static u8 dp_get_adjust_request_voltage(uint8_t link_status[DP_LINK_STATUS_SIZE],
|
||||
int lane)
|
||||
|
||||
{
|
||||
int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
|
||||
int s = ((lane & 1) ?
|
||||
DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT :
|
||||
DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT);
|
||||
u8 l = dp_link_status(link_status, i);
|
||||
|
||||
return ((l >> s) & 0x3) << DP_TRAIN_VOLTAGE_SWING_SHIFT;
|
||||
}
|
||||
|
||||
static u8 dp_get_adjust_request_pre_emphasis(uint8_t link_status[DP_LINK_STATUS_SIZE],
|
||||
int lane)
|
||||
{
|
||||
int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
|
||||
int s = ((lane & 1) ?
|
||||
DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT :
|
||||
DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT);
|
||||
u8 l = dp_link_status(link_status, i);
|
||||
|
||||
return ((l >> s) & 0x3) << DP_TRAIN_PRE_EMPHASIS_SHIFT;
|
||||
}
|
||||
|
||||
/* XXX fix me -- chip specific */
|
||||
#define DP_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_1200
|
||||
static u8 dp_pre_emphasis_max(u8 voltage_swing)
|
||||
{
|
||||
switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
|
||||
case DP_TRAIN_VOLTAGE_SWING_400:
|
||||
return DP_TRAIN_PRE_EMPHASIS_6;
|
||||
case DP_TRAIN_VOLTAGE_SWING_600:
|
||||
return DP_TRAIN_PRE_EMPHASIS_6;
|
||||
case DP_TRAIN_VOLTAGE_SWING_800:
|
||||
return DP_TRAIN_PRE_EMPHASIS_3_5;
|
||||
case DP_TRAIN_VOLTAGE_SWING_1200:
|
||||
default:
|
||||
return DP_TRAIN_PRE_EMPHASIS_0;
|
||||
}
|
||||
}
|
||||
|
||||
static void dp_get_adjust_train(u8 link_status[DP_LINK_STATUS_SIZE],
|
||||
int lane_count,
|
||||
u8 train_set[4])
|
||||
{
|
||||
u8 v = 0;
|
||||
u8 p = 0;
|
||||
int lane;
|
||||
|
||||
for (lane = 0; lane < lane_count; lane++) {
|
||||
u8 this_v = dp_get_adjust_request_voltage(link_status, lane);
|
||||
u8 this_p = dp_get_adjust_request_pre_emphasis(link_status, lane);
|
||||
|
||||
DRM_DEBUG("requested signal parameters: lane %d voltage %s pre_emph %s\n",
|
||||
lane,
|
||||
voltage_names[this_v >> DP_TRAIN_VOLTAGE_SWING_SHIFT],
|
||||
pre_emph_names[this_p >> DP_TRAIN_PRE_EMPHASIS_SHIFT]);
|
||||
|
||||
if (this_v > v)
|
||||
v = this_v;
|
||||
if (this_p > p)
|
||||
p = this_p;
|
||||
}
|
||||
|
||||
if (v >= DP_VOLTAGE_MAX)
|
||||
v = DP_VOLTAGE_MAX | DP_TRAIN_MAX_SWING_REACHED;
|
||||
|
||||
if (p >= dp_pre_emphasis_max(v))
|
||||
p = dp_pre_emphasis_max(v) | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
|
||||
|
||||
DRM_DEBUG("using signal parameters: voltage %s pre_emph %s\n",
|
||||
voltage_names[(v & DP_TRAIN_VOLTAGE_SWING_MASK) >> DP_TRAIN_VOLTAGE_SWING_SHIFT],
|
||||
pre_emph_names[(p & DP_TRAIN_PRE_EMPHASIS_MASK) >> DP_TRAIN_PRE_EMPHASIS_SHIFT]);
|
||||
|
||||
for (lane = 0; lane < 4; lane++)
|
||||
train_set[lane] = v | p;
|
||||
}
|
||||
|
||||
|
||||
/* radeon aux chan functions */
|
||||
bool radeon_process_aux_ch(struct radeon_i2c_chan *chan, u8 *req_bytes,
|
||||
int num_bytes, u8 *read_byte,
|
||||
u8 read_buf_len, u8 delay)
|
||||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION args;
|
||||
int index = GetIndexIntoMasterTable(COMMAND, ProcessAuxChannelTransaction);
|
||||
unsigned char *base;
|
||||
|
||||
memset(&args, 0, sizeof(args));
|
||||
|
||||
base = (unsigned char *)rdev->mode_info.atom_context->scratch;
|
||||
|
||||
memcpy(base, req_bytes, num_bytes);
|
||||
|
||||
args.lpAuxRequest = 0;
|
||||
args.lpDataOut = 16;
|
||||
args.ucDataOutLen = 0;
|
||||
args.ucChannelID = chan->rec.i2c_id;
|
||||
args.ucDelay = delay / 10;
|
||||
|
||||
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
|
||||
|
||||
if (args.ucReplyStatus) {
|
||||
DRM_DEBUG("failed to get auxch %02x%02x %02x %02x 0x%02x %02x\n",
|
||||
req_bytes[1], req_bytes[0], req_bytes[2], req_bytes[3],
|
||||
chan->rec.i2c_id, args.ucReplyStatus);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (args.ucDataOutLen && read_byte && read_buf_len) {
|
||||
if (read_buf_len < args.ucDataOutLen) {
|
||||
DRM_ERROR("Buffer to small for return answer %d %d\n",
|
||||
read_buf_len, args.ucDataOutLen);
|
||||
return false;
|
||||
}
|
||||
{
|
||||
int len = min(read_buf_len, args.ucDataOutLen);
|
||||
memcpy(read_byte, base + 16, len);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool radeon_dp_aux_native_write(struct radeon_connector *radeon_connector, uint16_t address,
|
||||
uint8_t send_bytes, uint8_t *send)
|
||||
{
|
||||
struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv;
|
||||
u8 msg[20];
|
||||
u8 msg_len, dp_msg_len;
|
||||
bool ret;
|
||||
|
||||
dp_msg_len = 4;
|
||||
msg[0] = address;
|
||||
msg[1] = address >> 8;
|
||||
msg[2] = AUX_NATIVE_WRITE << 4;
|
||||
dp_msg_len += send_bytes;
|
||||
msg[3] = (dp_msg_len << 4) | (send_bytes - 1);
|
||||
|
||||
if (send_bytes > 16)
|
||||
return false;
|
||||
|
||||
memcpy(&msg[4], send, send_bytes);
|
||||
msg_len = 4 + send_bytes;
|
||||
ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus, msg, msg_len, NULL, 0, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool radeon_dp_aux_native_read(struct radeon_connector *radeon_connector, uint16_t address,
|
||||
uint8_t delay, uint8_t expected_bytes,
|
||||
uint8_t *read_p)
|
||||
{
|
||||
struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv;
|
||||
u8 msg[20];
|
||||
u8 msg_len, dp_msg_len;
|
||||
bool ret = false;
|
||||
msg_len = 4;
|
||||
dp_msg_len = 4;
|
||||
msg[0] = address;
|
||||
msg[1] = address >> 8;
|
||||
msg[2] = AUX_NATIVE_READ << 4;
|
||||
msg[3] = (dp_msg_len) << 4;
|
||||
msg[3] |= expected_bytes - 1;
|
||||
|
||||
ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus, msg, msg_len, read_p, expected_bytes, delay);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* radeon dp functions */
|
||||
static u8 radeon_dp_encoder_service(struct radeon_device *rdev, int action, int dp_clock,
|
||||
uint8_t ucconfig, uint8_t lane_num)
|
||||
{
|
||||
DP_ENCODER_SERVICE_PARAMETERS args;
|
||||
int index = GetIndexIntoMasterTable(COMMAND, DPEncoderService);
|
||||
|
||||
memset(&args, 0, sizeof(args));
|
||||
args.ucLinkClock = dp_clock / 10;
|
||||
args.ucConfig = ucconfig;
|
||||
args.ucAction = action;
|
||||
args.ucLaneNum = lane_num;
|
||||
args.ucStatus = 0;
|
||||
|
||||
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
|
||||
return args.ucStatus;
|
||||
}
|
||||
|
||||
u8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector)
|
||||
{
|
||||
struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv;
|
||||
struct drm_device *dev = radeon_connector->base.dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
|
||||
return radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_GET_SINK_TYPE, 0,
|
||||
dig_connector->dp_i2c_bus->rec.i2c_id, 0);
|
||||
}
|
||||
|
||||
bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector)
|
||||
{
|
||||
struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv;
|
||||
u8 msg[25];
|
||||
int ret;
|
||||
|
||||
ret = radeon_dp_aux_native_read(radeon_connector, DP_DPCD_REV, 0, 8, msg);
|
||||
if (ret) {
|
||||
memcpy(dig_connector->dpcd, msg, 8);
|
||||
{
|
||||
int i;
|
||||
DRM_DEBUG("DPCD: ");
|
||||
for (i = 0; i < 8; i++)
|
||||
DRM_DEBUG("%02x ", msg[i]);
|
||||
DRM_DEBUG("\n");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
dig_connector->dpcd[0] = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
void radeon_dp_set_link_config(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
struct radeon_connector *radeon_connector;
|
||||
struct radeon_connector_atom_dig *dig_connector;
|
||||
|
||||
if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort)
|
||||
return;
|
||||
|
||||
radeon_connector = to_radeon_connector(connector);
|
||||
if (!radeon_connector->con_priv)
|
||||
return;
|
||||
dig_connector = radeon_connector->con_priv;
|
||||
|
||||
dig_connector->dp_clock =
|
||||
dp_link_clock_for_mode_clock(dig_connector->dpcd, mode->clock);
|
||||
dig_connector->dp_lane_count =
|
||||
dp_lanes_for_mode_clock(dig_connector->dpcd, mode->clock);
|
||||
}
|
||||
|
||||
int radeon_dp_mode_valid_helper(struct radeon_connector *radeon_connector,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv;
|
||||
|
||||
return dp_mode_valid(dig_connector->dpcd, mode->clock);
|
||||
}
|
||||
|
||||
static bool atom_dp_get_link_status(struct radeon_connector *radeon_connector,
|
||||
u8 link_status[DP_LINK_STATUS_SIZE])
|
||||
{
|
||||
int ret;
|
||||
ret = radeon_dp_aux_native_read(radeon_connector, DP_LANE0_1_STATUS, 100,
|
||||
DP_LINK_STATUS_SIZE, link_status);
|
||||
if (!ret) {
|
||||
DRM_ERROR("displayport link status failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
DRM_DEBUG("link status %02x %02x %02x %02x %02x %02x\n",
|
||||
link_status[0], link_status[1], link_status[2],
|
||||
link_status[3], link_status[4], link_status[5]);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector)
|
||||
{
|
||||
struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv;
|
||||
u8 link_status[DP_LINK_STATUS_SIZE];
|
||||
|
||||
if (!atom_dp_get_link_status(radeon_connector, link_status))
|
||||
return false;
|
||||
if (dp_channel_eq_ok(link_status, dig_connector->dp_lane_count))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void dp_set_power(struct radeon_connector *radeon_connector, u8 power_state)
|
||||
{
|
||||
struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv;
|
||||
|
||||
if (dig_connector->dpcd[0] >= 0x11) {
|
||||
radeon_dp_aux_native_write(radeon_connector, DP_SET_POWER, 1,
|
||||
&power_state);
|
||||
}
|
||||
}
|
||||
|
||||
static void dp_set_downspread(struct radeon_connector *radeon_connector, u8 downspread)
|
||||
{
|
||||
radeon_dp_aux_native_write(radeon_connector, DP_DOWNSPREAD_CTRL, 1,
|
||||
&downspread);
|
||||
}
|
||||
|
||||
static void dp_set_link_bw_lanes(struct radeon_connector *radeon_connector,
|
||||
u8 link_configuration[DP_LINK_CONFIGURATION_SIZE])
|
||||
{
|
||||
radeon_dp_aux_native_write(radeon_connector, DP_LINK_BW_SET, 2,
|
||||
link_configuration);
|
||||
}
|
||||
|
||||
static void dp_update_dpvs_emph(struct radeon_connector *radeon_connector,
|
||||
struct drm_encoder *encoder,
|
||||
u8 train_set[4])
|
||||
{
|
||||
struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dig_connector->dp_lane_count; i++)
|
||||
atombios_dig_transmitter_setup(encoder,
|
||||
ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH,
|
||||
i, train_set[i]);
|
||||
|
||||
radeon_dp_aux_native_write(radeon_connector, DP_TRAINING_LANE0_SET,
|
||||
dig_connector->dp_lane_count, train_set);
|
||||
}
|
||||
|
||||
static void dp_set_training(struct radeon_connector *radeon_connector,
|
||||
u8 training)
|
||||
{
|
||||
radeon_dp_aux_native_write(radeon_connector, DP_TRAINING_PATTERN_SET,
|
||||
1, &training);
|
||||
}
|
||||
|
||||
void dp_link_train(struct drm_encoder *encoder,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
struct radeon_encoder_atom_dig *dig;
|
||||
struct radeon_connector *radeon_connector;
|
||||
struct radeon_connector_atom_dig *dig_connector;
|
||||
int enc_id = 0;
|
||||
bool clock_recovery, channel_eq;
|
||||
u8 link_status[DP_LINK_STATUS_SIZE];
|
||||
u8 link_configuration[DP_LINK_CONFIGURATION_SIZE];
|
||||
u8 tries, voltage;
|
||||
u8 train_set[4];
|
||||
int i;
|
||||
|
||||
if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort)
|
||||
return;
|
||||
|
||||
if (!radeon_encoder->enc_priv)
|
||||
return;
|
||||
dig = radeon_encoder->enc_priv;
|
||||
|
||||
radeon_connector = to_radeon_connector(connector);
|
||||
if (!radeon_connector->con_priv)
|
||||
return;
|
||||
dig_connector = radeon_connector->con_priv;
|
||||
|
||||
if (ASIC_IS_DCE32(rdev)) {
|
||||
if (dig->dig_block)
|
||||
enc_id |= ATOM_DP_CONFIG_DIG2_ENCODER;
|
||||
else
|
||||
enc_id |= ATOM_DP_CONFIG_DIG1_ENCODER;
|
||||
if (dig_connector->linkb)
|
||||
enc_id |= ATOM_DP_CONFIG_LINK_B;
|
||||
else
|
||||
enc_id |= ATOM_DP_CONFIG_LINK_A;
|
||||
} else {
|
||||
if (dig_connector->linkb)
|
||||
enc_id |= ATOM_DP_CONFIG_DIG2_ENCODER | ATOM_DP_CONFIG_LINK_B;
|
||||
else
|
||||
enc_id |= ATOM_DP_CONFIG_DIG1_ENCODER | ATOM_DP_CONFIG_LINK_A;
|
||||
}
|
||||
|
||||
memset(link_configuration, 0, DP_LINK_CONFIGURATION_SIZE);
|
||||
if (dig_connector->dp_clock == 270000)
|
||||
link_configuration[0] = DP_LINK_BW_2_7;
|
||||
else
|
||||
link_configuration[0] = DP_LINK_BW_1_62;
|
||||
link_configuration[1] = dig_connector->dp_lane_count;
|
||||
if (dig_connector->dpcd[0] >= 0x11)
|
||||
link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
|
||||
|
||||
/* power up the sink */
|
||||
dp_set_power(radeon_connector, DP_SET_POWER_D0);
|
||||
/* disable the training pattern on the sink */
|
||||
dp_set_training(radeon_connector, DP_TRAINING_PATTERN_DISABLE);
|
||||
/* set link bw and lanes on the sink */
|
||||
dp_set_link_bw_lanes(radeon_connector, link_configuration);
|
||||
/* disable downspread on the sink */
|
||||
dp_set_downspread(radeon_connector, 0);
|
||||
/* start training on the source */
|
||||
radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_START,
|
||||
dig_connector->dp_clock, enc_id, 0);
|
||||
/* set training pattern 1 on the source */
|
||||
radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_PATTERN_SEL,
|
||||
dig_connector->dp_clock, enc_id, 0);
|
||||
|
||||
/* set initial vs/emph */
|
||||
memset(train_set, 0, 4);
|
||||
udelay(400);
|
||||
/* set training pattern 1 on the sink */
|
||||
dp_set_training(radeon_connector, DP_TRAINING_PATTERN_1);
|
||||
|
||||
dp_update_dpvs_emph(radeon_connector, encoder, train_set);
|
||||
|
||||
/* clock recovery loop */
|
||||
clock_recovery = false;
|
||||
tries = 0;
|
||||
voltage = 0xff;
|
||||
for (;;) {
|
||||
udelay(100);
|
||||
if (!atom_dp_get_link_status(radeon_connector, link_status))
|
||||
break;
|
||||
|
||||
if (dp_clock_recovery_ok(link_status, dig_connector->dp_lane_count)) {
|
||||
clock_recovery = true;
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < dig_connector->dp_lane_count; i++) {
|
||||
if ((train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
|
||||
break;
|
||||
}
|
||||
if (i == dig_connector->dp_lane_count) {
|
||||
DRM_ERROR("clock recovery reached max voltage\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if ((train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) {
|
||||
++tries;
|
||||
if (tries == 5) {
|
||||
DRM_ERROR("clock recovery tried 5 times\n");
|
||||
break;
|
||||
}
|
||||
} else
|
||||
tries = 0;
|
||||
|
||||
voltage = train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
|
||||
|
||||
/* Compute new train_set as requested by sink */
|
||||
dp_get_adjust_train(link_status, dig_connector->dp_lane_count, train_set);
|
||||
dp_update_dpvs_emph(radeon_connector, encoder, train_set);
|
||||
}
|
||||
if (!clock_recovery)
|
||||
DRM_ERROR("clock recovery failed\n");
|
||||
else
|
||||
DRM_DEBUG("clock recovery at voltage %d pre-emphasis %d\n",
|
||||
train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK,
|
||||
(train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK) >>
|
||||
DP_TRAIN_PRE_EMPHASIS_SHIFT);
|
||||
|
||||
|
||||
/* set training pattern 2 on the sink */
|
||||
dp_set_training(radeon_connector, DP_TRAINING_PATTERN_2);
|
||||
/* set training pattern 2 on the source */
|
||||
radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_PATTERN_SEL,
|
||||
dig_connector->dp_clock, enc_id, 1);
|
||||
|
||||
/* channel equalization loop */
|
||||
tries = 0;
|
||||
channel_eq = false;
|
||||
for (;;) {
|
||||
udelay(400);
|
||||
if (!atom_dp_get_link_status(radeon_connector, link_status))
|
||||
break;
|
||||
|
||||
if (dp_channel_eq_ok(link_status, dig_connector->dp_lane_count)) {
|
||||
channel_eq = true;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Try 5 times */
|
||||
if (tries > 5) {
|
||||
DRM_ERROR("channel eq failed: 5 tries\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/* Compute new train_set as requested by sink */
|
||||
dp_get_adjust_train(link_status, dig_connector->dp_lane_count, train_set);
|
||||
dp_update_dpvs_emph(radeon_connector, encoder, train_set);
|
||||
|
||||
tries++;
|
||||
}
|
||||
|
||||
if (!channel_eq)
|
||||
DRM_ERROR("channel eq failed\n");
|
||||
else
|
||||
DRM_DEBUG("channel eq at voltage %d pre-emphasis %d\n",
|
||||
train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK,
|
||||
(train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK)
|
||||
>> DP_TRAIN_PRE_EMPHASIS_SHIFT);
|
||||
|
||||
/* disable the training pattern on the sink */
|
||||
dp_set_training(radeon_connector, DP_TRAINING_PATTERN_DISABLE);
|
||||
|
||||
radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_COMPLETE,
|
||||
dig_connector->dp_clock, enc_id, 0);
|
||||
}
|
||||
|
||||
int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
|
||||
uint8_t write_byte, uint8_t *read_byte)
|
||||
{
|
||||
struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
|
||||
struct radeon_i2c_chan *auxch = (struct radeon_i2c_chan *)adapter;
|
||||
int ret = 0;
|
||||
uint16_t address = algo_data->address;
|
||||
uint8_t msg[5];
|
||||
uint8_t reply[2];
|
||||
int msg_len, dp_msg_len;
|
||||
int reply_bytes;
|
||||
|
||||
/* Set up the command byte */
|
||||
if (mode & MODE_I2C_READ)
|
||||
msg[2] = AUX_I2C_READ << 4;
|
||||
else
|
||||
msg[2] = AUX_I2C_WRITE << 4;
|
||||
|
||||
if (!(mode & MODE_I2C_STOP))
|
||||
msg[2] |= AUX_I2C_MOT << 4;
|
||||
|
||||
msg[0] = address;
|
||||
msg[1] = address >> 8;
|
||||
|
||||
reply_bytes = 1;
|
||||
|
||||
msg_len = 4;
|
||||
dp_msg_len = 3;
|
||||
switch (mode) {
|
||||
case MODE_I2C_WRITE:
|
||||
msg[4] = write_byte;
|
||||
msg_len++;
|
||||
dp_msg_len += 2;
|
||||
break;
|
||||
case MODE_I2C_READ:
|
||||
dp_msg_len += 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
msg[3] = (dp_msg_len) << 4;
|
||||
ret = radeon_process_aux_ch(auxch, msg, msg_len, reply, reply_bytes, 0);
|
||||
|
||||
if (ret) {
|
||||
if (read_byte)
|
||||
*read_byte = reply[0];
|
||||
return reply_bytes;
|
||||
}
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
@ -65,6 +65,95 @@ MODULE_FIRMWARE(FIRMWARE_R520);
|
||||
* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280
|
||||
*/
|
||||
|
||||
/* hpd for digital panel detect/disconnect */
|
||||
bool r100_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd)
|
||||
{
|
||||
bool connected = false;
|
||||
|
||||
switch (hpd) {
|
||||
case RADEON_HPD_1:
|
||||
if (RREG32(RADEON_FP_GEN_CNTL) & RADEON_FP_DETECT_SENSE)
|
||||
connected = true;
|
||||
break;
|
||||
case RADEON_HPD_2:
|
||||
if (RREG32(RADEON_FP2_GEN_CNTL) & RADEON_FP2_DETECT_SENSE)
|
||||
connected = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return connected;
|
||||
}
|
||||
|
||||
void r100_hpd_set_polarity(struct radeon_device *rdev,
|
||||
enum radeon_hpd_id hpd)
|
||||
{
|
||||
u32 tmp;
|
||||
bool connected = r100_hpd_sense(rdev, hpd);
|
||||
|
||||
switch (hpd) {
|
||||
case RADEON_HPD_1:
|
||||
tmp = RREG32(RADEON_FP_GEN_CNTL);
|
||||
if (connected)
|
||||
tmp &= ~RADEON_FP_DETECT_INT_POL;
|
||||
else
|
||||
tmp |= RADEON_FP_DETECT_INT_POL;
|
||||
WREG32(RADEON_FP_GEN_CNTL, tmp);
|
||||
break;
|
||||
case RADEON_HPD_2:
|
||||
tmp = RREG32(RADEON_FP2_GEN_CNTL);
|
||||
if (connected)
|
||||
tmp &= ~RADEON_FP2_DETECT_INT_POL;
|
||||
else
|
||||
tmp |= RADEON_FP2_DETECT_INT_POL;
|
||||
WREG32(RADEON_FP2_GEN_CNTL, tmp);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void r100_hpd_init(struct radeon_device *rdev)
|
||||
{
|
||||
struct drm_device *dev = rdev->ddev;
|
||||
struct drm_connector *connector;
|
||||
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
|
||||
switch (radeon_connector->hpd.hpd) {
|
||||
case RADEON_HPD_1:
|
||||
rdev->irq.hpd[0] = true;
|
||||
break;
|
||||
case RADEON_HPD_2:
|
||||
rdev->irq.hpd[1] = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
r100_irq_set(rdev);
|
||||
}
|
||||
|
||||
void r100_hpd_fini(struct radeon_device *rdev)
|
||||
{
|
||||
struct drm_device *dev = rdev->ddev;
|
||||
struct drm_connector *connector;
|
||||
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
|
||||
switch (radeon_connector->hpd.hpd) {
|
||||
case RADEON_HPD_1:
|
||||
rdev->irq.hpd[0] = false;
|
||||
break;
|
||||
case RADEON_HPD_2:
|
||||
rdev->irq.hpd[1] = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* PCI GART
|
||||
*/
|
||||
@ -163,6 +252,12 @@ int r100_irq_set(struct radeon_device *rdev)
|
||||
if (rdev->irq.crtc_vblank_int[1]) {
|
||||
tmp |= RADEON_CRTC2_VBLANK_MASK;
|
||||
}
|
||||
if (rdev->irq.hpd[0]) {
|
||||
tmp |= RADEON_FP_DETECT_MASK;
|
||||
}
|
||||
if (rdev->irq.hpd[1]) {
|
||||
tmp |= RADEON_FP2_DETECT_MASK;
|
||||
}
|
||||
WREG32(RADEON_GEN_INT_CNTL, tmp);
|
||||
return 0;
|
||||
}
|
||||
@ -181,8 +276,9 @@ void r100_irq_disable(struct radeon_device *rdev)
|
||||
static inline uint32_t r100_irq_ack(struct radeon_device *rdev)
|
||||
{
|
||||
uint32_t irqs = RREG32(RADEON_GEN_INT_STATUS);
|
||||
uint32_t irq_mask = RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT |
|
||||
RADEON_CRTC2_VBLANK_STAT;
|
||||
uint32_t irq_mask = RADEON_SW_INT_TEST |
|
||||
RADEON_CRTC_VBLANK_STAT | RADEON_CRTC2_VBLANK_STAT |
|
||||
RADEON_FP_DETECT_STAT | RADEON_FP2_DETECT_STAT;
|
||||
|
||||
if (irqs) {
|
||||
WREG32(RADEON_GEN_INT_STATUS, irqs);
|
||||
@ -193,6 +289,7 @@ static inline uint32_t r100_irq_ack(struct radeon_device *rdev)
|
||||
int r100_irq_process(struct radeon_device *rdev)
|
||||
{
|
||||
uint32_t status, msi_rearm;
|
||||
bool queue_hotplug = false;
|
||||
|
||||
status = r100_irq_ack(rdev);
|
||||
if (!status) {
|
||||
@ -213,8 +310,18 @@ int r100_irq_process(struct radeon_device *rdev)
|
||||
if (status & RADEON_CRTC2_VBLANK_STAT) {
|
||||
drm_handle_vblank(rdev->ddev, 1);
|
||||
}
|
||||
if (status & RADEON_FP_DETECT_STAT) {
|
||||
queue_hotplug = true;
|
||||
DRM_DEBUG("HPD1\n");
|
||||
}
|
||||
if (status & RADEON_FP2_DETECT_STAT) {
|
||||
queue_hotplug = true;
|
||||
DRM_DEBUG("HPD2\n");
|
||||
}
|
||||
status = r100_irq_ack(rdev);
|
||||
}
|
||||
if (queue_hotplug)
|
||||
queue_work(rdev->wq, &rdev->hotplug_work);
|
||||
if (rdev->msi_enabled) {
|
||||
switch (rdev->family) {
|
||||
case CHIP_RS400:
|
||||
|
@ -716,6 +716,8 @@
|
||||
|
||||
#define AVIVO_DVOA_BIT_DEPTH_CONTROL 0x7988
|
||||
|
||||
#define AVIVO_DC_GPIO_HPD_A 0x7e94
|
||||
|
||||
#define AVIVO_GPIO_0 0x7e30
|
||||
#define AVIVO_GPIO_1 0x7e40
|
||||
#define AVIVO_GPIO_2 0x7e50
|
||||
|
@ -74,6 +74,281 @@ int r600_mc_wait_for_idle(struct radeon_device *rdev);
|
||||
void r600_gpu_init(struct radeon_device *rdev);
|
||||
void r600_fini(struct radeon_device *rdev);
|
||||
|
||||
/* hpd for digital panel detect/disconnect */
|
||||
bool r600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd)
|
||||
{
|
||||
bool connected = false;
|
||||
|
||||
if (ASIC_IS_DCE3(rdev)) {
|
||||
switch (hpd) {
|
||||
case RADEON_HPD_1:
|
||||
if (RREG32(DC_HPD1_INT_STATUS) & DC_HPDx_SENSE)
|
||||
connected = true;
|
||||
break;
|
||||
case RADEON_HPD_2:
|
||||
if (RREG32(DC_HPD2_INT_STATUS) & DC_HPDx_SENSE)
|
||||
connected = true;
|
||||
break;
|
||||
case RADEON_HPD_3:
|
||||
if (RREG32(DC_HPD3_INT_STATUS) & DC_HPDx_SENSE)
|
||||
connected = true;
|
||||
break;
|
||||
case RADEON_HPD_4:
|
||||
if (RREG32(DC_HPD4_INT_STATUS) & DC_HPDx_SENSE)
|
||||
connected = true;
|
||||
break;
|
||||
/* DCE 3.2 */
|
||||
case RADEON_HPD_5:
|
||||
if (RREG32(DC_HPD5_INT_STATUS) & DC_HPDx_SENSE)
|
||||
connected = true;
|
||||
break;
|
||||
case RADEON_HPD_6:
|
||||
if (RREG32(DC_HPD6_INT_STATUS) & DC_HPDx_SENSE)
|
||||
connected = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (hpd) {
|
||||
case RADEON_HPD_1:
|
||||
if (RREG32(DC_HOT_PLUG_DETECT1_INT_STATUS) & DC_HOT_PLUG_DETECTx_SENSE)
|
||||
connected = true;
|
||||
break;
|
||||
case RADEON_HPD_2:
|
||||
if (RREG32(DC_HOT_PLUG_DETECT2_INT_STATUS) & DC_HOT_PLUG_DETECTx_SENSE)
|
||||
connected = true;
|
||||
break;
|
||||
case RADEON_HPD_3:
|
||||
if (RREG32(DC_HOT_PLUG_DETECT3_INT_STATUS) & DC_HOT_PLUG_DETECTx_SENSE)
|
||||
connected = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return connected;
|
||||
}
|
||||
|
||||
void r600_hpd_set_polarity(struct radeon_device *rdev,
|
||||
enum radeon_hpd_id hpd)
|
||||
{
|
||||
u32 tmp;
|
||||
bool connected = r600_hpd_sense(rdev, hpd);
|
||||
|
||||
if (ASIC_IS_DCE3(rdev)) {
|
||||
switch (hpd) {
|
||||
case RADEON_HPD_1:
|
||||
tmp = RREG32(DC_HPD1_INT_CONTROL);
|
||||
if (connected)
|
||||
tmp &= ~DC_HPDx_INT_POLARITY;
|
||||
else
|
||||
tmp |= DC_HPDx_INT_POLARITY;
|
||||
WREG32(DC_HPD1_INT_CONTROL, tmp);
|
||||
break;
|
||||
case RADEON_HPD_2:
|
||||
tmp = RREG32(DC_HPD2_INT_CONTROL);
|
||||
if (connected)
|
||||
tmp &= ~DC_HPDx_INT_POLARITY;
|
||||
else
|
||||
tmp |= DC_HPDx_INT_POLARITY;
|
||||
WREG32(DC_HPD2_INT_CONTROL, tmp);
|
||||
break;
|
||||
case RADEON_HPD_3:
|
||||
tmp = RREG32(DC_HPD3_INT_CONTROL);
|
||||
if (connected)
|
||||
tmp &= ~DC_HPDx_INT_POLARITY;
|
||||
else
|
||||
tmp |= DC_HPDx_INT_POLARITY;
|
||||
WREG32(DC_HPD3_INT_CONTROL, tmp);
|
||||
break;
|
||||
case RADEON_HPD_4:
|
||||
tmp = RREG32(DC_HPD4_INT_CONTROL);
|
||||
if (connected)
|
||||
tmp &= ~DC_HPDx_INT_POLARITY;
|
||||
else
|
||||
tmp |= DC_HPDx_INT_POLARITY;
|
||||
WREG32(DC_HPD4_INT_CONTROL, tmp);
|
||||
break;
|
||||
case RADEON_HPD_5:
|
||||
tmp = RREG32(DC_HPD5_INT_CONTROL);
|
||||
if (connected)
|
||||
tmp &= ~DC_HPDx_INT_POLARITY;
|
||||
else
|
||||
tmp |= DC_HPDx_INT_POLARITY;
|
||||
WREG32(DC_HPD5_INT_CONTROL, tmp);
|
||||
break;
|
||||
/* DCE 3.2 */
|
||||
case RADEON_HPD_6:
|
||||
tmp = RREG32(DC_HPD6_INT_CONTROL);
|
||||
if (connected)
|
||||
tmp &= ~DC_HPDx_INT_POLARITY;
|
||||
else
|
||||
tmp |= DC_HPDx_INT_POLARITY;
|
||||
WREG32(DC_HPD6_INT_CONTROL, tmp);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (hpd) {
|
||||
case RADEON_HPD_1:
|
||||
tmp = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL);
|
||||
if (connected)
|
||||
tmp &= ~DC_HOT_PLUG_DETECTx_INT_POLARITY;
|
||||
else
|
||||
tmp |= DC_HOT_PLUG_DETECTx_INT_POLARITY;
|
||||
WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp);
|
||||
break;
|
||||
case RADEON_HPD_2:
|
||||
tmp = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL);
|
||||
if (connected)
|
||||
tmp &= ~DC_HOT_PLUG_DETECTx_INT_POLARITY;
|
||||
else
|
||||
tmp |= DC_HOT_PLUG_DETECTx_INT_POLARITY;
|
||||
WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp);
|
||||
break;
|
||||
case RADEON_HPD_3:
|
||||
tmp = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL);
|
||||
if (connected)
|
||||
tmp &= ~DC_HOT_PLUG_DETECTx_INT_POLARITY;
|
||||
else
|
||||
tmp |= DC_HOT_PLUG_DETECTx_INT_POLARITY;
|
||||
WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, tmp);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void r600_hpd_init(struct radeon_device *rdev)
|
||||
{
|
||||
struct drm_device *dev = rdev->ddev;
|
||||
struct drm_connector *connector;
|
||||
|
||||
if (ASIC_IS_DCE3(rdev)) {
|
||||
u32 tmp = DC_HPDx_CONNECTION_TIMER(0x9c4) | DC_HPDx_RX_INT_TIMER(0xfa);
|
||||
if (ASIC_IS_DCE32(rdev))
|
||||
tmp |= DC_HPDx_EN;
|
||||
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
|
||||
switch (radeon_connector->hpd.hpd) {
|
||||
case RADEON_HPD_1:
|
||||
WREG32(DC_HPD1_CONTROL, tmp);
|
||||
rdev->irq.hpd[0] = true;
|
||||
break;
|
||||
case RADEON_HPD_2:
|
||||
WREG32(DC_HPD2_CONTROL, tmp);
|
||||
rdev->irq.hpd[1] = true;
|
||||
break;
|
||||
case RADEON_HPD_3:
|
||||
WREG32(DC_HPD3_CONTROL, tmp);
|
||||
rdev->irq.hpd[2] = true;
|
||||
break;
|
||||
case RADEON_HPD_4:
|
||||
WREG32(DC_HPD4_CONTROL, tmp);
|
||||
rdev->irq.hpd[3] = true;
|
||||
break;
|
||||
/* DCE 3.2 */
|
||||
case RADEON_HPD_5:
|
||||
WREG32(DC_HPD5_CONTROL, tmp);
|
||||
rdev->irq.hpd[4] = true;
|
||||
break;
|
||||
case RADEON_HPD_6:
|
||||
WREG32(DC_HPD6_CONTROL, tmp);
|
||||
rdev->irq.hpd[5] = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
|
||||
switch (radeon_connector->hpd.hpd) {
|
||||
case RADEON_HPD_1:
|
||||
WREG32(DC_HOT_PLUG_DETECT1_CONTROL, DC_HOT_PLUG_DETECTx_EN);
|
||||
rdev->irq.hpd[0] = true;
|
||||
break;
|
||||
case RADEON_HPD_2:
|
||||
WREG32(DC_HOT_PLUG_DETECT2_CONTROL, DC_HOT_PLUG_DETECTx_EN);
|
||||
rdev->irq.hpd[1] = true;
|
||||
break;
|
||||
case RADEON_HPD_3:
|
||||
WREG32(DC_HOT_PLUG_DETECT3_CONTROL, DC_HOT_PLUG_DETECTx_EN);
|
||||
rdev->irq.hpd[2] = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
r600_irq_set(rdev);
|
||||
}
|
||||
|
||||
void r600_hpd_fini(struct radeon_device *rdev)
|
||||
{
|
||||
struct drm_device *dev = rdev->ddev;
|
||||
struct drm_connector *connector;
|
||||
|
||||
if (ASIC_IS_DCE3(rdev)) {
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
|
||||
switch (radeon_connector->hpd.hpd) {
|
||||
case RADEON_HPD_1:
|
||||
WREG32(DC_HPD1_CONTROL, 0);
|
||||
rdev->irq.hpd[0] = false;
|
||||
break;
|
||||
case RADEON_HPD_2:
|
||||
WREG32(DC_HPD2_CONTROL, 0);
|
||||
rdev->irq.hpd[1] = false;
|
||||
break;
|
||||
case RADEON_HPD_3:
|
||||
WREG32(DC_HPD3_CONTROL, 0);
|
||||
rdev->irq.hpd[2] = false;
|
||||
break;
|
||||
case RADEON_HPD_4:
|
||||
WREG32(DC_HPD4_CONTROL, 0);
|
||||
rdev->irq.hpd[3] = false;
|
||||
break;
|
||||
/* DCE 3.2 */
|
||||
case RADEON_HPD_5:
|
||||
WREG32(DC_HPD5_CONTROL, 0);
|
||||
rdev->irq.hpd[4] = false;
|
||||
break;
|
||||
case RADEON_HPD_6:
|
||||
WREG32(DC_HPD6_CONTROL, 0);
|
||||
rdev->irq.hpd[5] = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
|
||||
switch (radeon_connector->hpd.hpd) {
|
||||
case RADEON_HPD_1:
|
||||
WREG32(DC_HOT_PLUG_DETECT1_CONTROL, 0);
|
||||
rdev->irq.hpd[0] = false;
|
||||
break;
|
||||
case RADEON_HPD_2:
|
||||
WREG32(DC_HOT_PLUG_DETECT2_CONTROL, 0);
|
||||
rdev->irq.hpd[1] = false;
|
||||
break;
|
||||
case RADEON_HPD_3:
|
||||
WREG32(DC_HOT_PLUG_DETECT3_CONTROL, 0);
|
||||
rdev->irq.hpd[2] = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* R600 PCIE GART
|
||||
*/
|
||||
@ -2060,6 +2335,42 @@ static void r600_disable_interrupts(struct radeon_device *rdev)
|
||||
rdev->ih.rptr = 0;
|
||||
}
|
||||
|
||||
static void r600_disable_interrupt_state(struct radeon_device *rdev)
|
||||
{
|
||||
u32 tmp;
|
||||
|
||||
WREG32(CP_INT_CNTL, 0);
|
||||
WREG32(GRBM_INT_CNTL, 0);
|
||||
WREG32(DxMODE_INT_MASK, 0);
|
||||
if (ASIC_IS_DCE3(rdev)) {
|
||||
WREG32(DCE3_DACA_AUTODETECT_INT_CONTROL, 0);
|
||||
WREG32(DCE3_DACB_AUTODETECT_INT_CONTROL, 0);
|
||||
tmp = RREG32(DC_HPD1_INT_CONTROL) & DC_HPDx_INT_POLARITY;
|
||||
WREG32(DC_HPD1_INT_CONTROL, tmp);
|
||||
tmp = RREG32(DC_HPD2_INT_CONTROL) & DC_HPDx_INT_POLARITY;
|
||||
WREG32(DC_HPD2_INT_CONTROL, tmp);
|
||||
tmp = RREG32(DC_HPD3_INT_CONTROL) & DC_HPDx_INT_POLARITY;
|
||||
WREG32(DC_HPD3_INT_CONTROL, tmp);
|
||||
tmp = RREG32(DC_HPD4_INT_CONTROL) & DC_HPDx_INT_POLARITY;
|
||||
WREG32(DC_HPD4_INT_CONTROL, tmp);
|
||||
if (ASIC_IS_DCE32(rdev)) {
|
||||
tmp = RREG32(DC_HPD5_INT_CONTROL) & DC_HPDx_INT_POLARITY;
|
||||
WREG32(DC_HPD5_INT_CONTROL, 0);
|
||||
tmp = RREG32(DC_HPD6_INT_CONTROL) & DC_HPDx_INT_POLARITY;
|
||||
WREG32(DC_HPD6_INT_CONTROL, 0);
|
||||
}
|
||||
} else {
|
||||
WREG32(DACA_AUTODETECT_INT_CONTROL, 0);
|
||||
WREG32(DACB_AUTODETECT_INT_CONTROL, 0);
|
||||
tmp = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL) & DC_HOT_PLUG_DETECTx_INT_POLARITY;
|
||||
WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, 0);
|
||||
tmp = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL) & DC_HOT_PLUG_DETECTx_INT_POLARITY;
|
||||
WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, 0);
|
||||
tmp = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL) & DC_HOT_PLUG_DETECTx_INT_POLARITY;
|
||||
WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
int r600_irq_init(struct radeon_device *rdev)
|
||||
{
|
||||
int ret = 0;
|
||||
@ -2122,9 +2433,7 @@ int r600_irq_init(struct radeon_device *rdev)
|
||||
WREG32(IH_CNTL, ih_cntl);
|
||||
|
||||
/* force the active interrupt state to all disabled */
|
||||
WREG32(CP_INT_CNTL, 0);
|
||||
WREG32(GRBM_INT_CNTL, 0);
|
||||
WREG32(DxMODE_INT_MASK, 0);
|
||||
r600_disable_interrupt_state(rdev);
|
||||
|
||||
/* enable irqs */
|
||||
r600_enable_interrupts(rdev);
|
||||
@ -2141,13 +2450,29 @@ void r600_irq_fini(struct radeon_device *rdev)
|
||||
|
||||
int r600_irq_set(struct radeon_device *rdev)
|
||||
{
|
||||
uint32_t cp_int_cntl = CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE;
|
||||
uint32_t mode_int = 0;
|
||||
u32 cp_int_cntl = CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE;
|
||||
u32 mode_int = 0;
|
||||
u32 hpd1, hpd2, hpd3, hpd4 = 0, hpd5 = 0, hpd6 = 0;
|
||||
|
||||
/* don't enable anything if the ih is disabled */
|
||||
if (!rdev->ih.enabled)
|
||||
return 0;
|
||||
|
||||
if (ASIC_IS_DCE3(rdev)) {
|
||||
hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN;
|
||||
hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~DC_HPDx_INT_EN;
|
||||
hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~DC_HPDx_INT_EN;
|
||||
hpd4 = RREG32(DC_HPD4_INT_CONTROL) & ~DC_HPDx_INT_EN;
|
||||
if (ASIC_IS_DCE32(rdev)) {
|
||||
hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~DC_HPDx_INT_EN;
|
||||
hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN;
|
||||
}
|
||||
} else {
|
||||
hpd1 = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL) & ~DC_HPDx_INT_EN;
|
||||
hpd2 = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL) & ~DC_HPDx_INT_EN;
|
||||
hpd3 = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL) & ~DC_HPDx_INT_EN;
|
||||
}
|
||||
|
||||
if (rdev->irq.sw_int) {
|
||||
DRM_DEBUG("r600_irq_set: sw int\n");
|
||||
cp_int_cntl |= RB_INT_ENABLE;
|
||||
@ -2160,39 +2485,137 @@ int r600_irq_set(struct radeon_device *rdev)
|
||||
DRM_DEBUG("r600_irq_set: vblank 1\n");
|
||||
mode_int |= D2MODE_VBLANK_INT_MASK;
|
||||
}
|
||||
if (rdev->irq.hpd[0]) {
|
||||
DRM_DEBUG("r600_irq_set: hpd 1\n");
|
||||
hpd1 |= DC_HPDx_INT_EN;
|
||||
}
|
||||
if (rdev->irq.hpd[1]) {
|
||||
DRM_DEBUG("r600_irq_set: hpd 2\n");
|
||||
hpd2 |= DC_HPDx_INT_EN;
|
||||
}
|
||||
if (rdev->irq.hpd[2]) {
|
||||
DRM_DEBUG("r600_irq_set: hpd 3\n");
|
||||
hpd3 |= DC_HPDx_INT_EN;
|
||||
}
|
||||
if (rdev->irq.hpd[3]) {
|
||||
DRM_DEBUG("r600_irq_set: hpd 4\n");
|
||||
hpd4 |= DC_HPDx_INT_EN;
|
||||
}
|
||||
if (rdev->irq.hpd[4]) {
|
||||
DRM_DEBUG("r600_irq_set: hpd 5\n");
|
||||
hpd5 |= DC_HPDx_INT_EN;
|
||||
}
|
||||
if (rdev->irq.hpd[5]) {
|
||||
DRM_DEBUG("r600_irq_set: hpd 6\n");
|
||||
hpd6 |= DC_HPDx_INT_EN;
|
||||
}
|
||||
|
||||
WREG32(CP_INT_CNTL, cp_int_cntl);
|
||||
WREG32(DxMODE_INT_MASK, mode_int);
|
||||
if (ASIC_IS_DCE3(rdev)) {
|
||||
WREG32(DC_HPD1_INT_CONTROL, hpd1);
|
||||
WREG32(DC_HPD2_INT_CONTROL, hpd2);
|
||||
WREG32(DC_HPD3_INT_CONTROL, hpd3);
|
||||
WREG32(DC_HPD4_INT_CONTROL, hpd4);
|
||||
if (ASIC_IS_DCE32(rdev)) {
|
||||
WREG32(DC_HPD5_INT_CONTROL, hpd5);
|
||||
WREG32(DC_HPD6_INT_CONTROL, hpd6);
|
||||
}
|
||||
} else {
|
||||
WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, hpd1);
|
||||
WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, hpd2);
|
||||
WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, hpd3);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void r600_irq_ack(struct radeon_device *rdev, u32 disp_int)
|
||||
static inline void r600_irq_ack(struct radeon_device *rdev,
|
||||
u32 *disp_int,
|
||||
u32 *disp_int_cont,
|
||||
u32 *disp_int_cont2)
|
||||
{
|
||||
u32 tmp;
|
||||
|
||||
if (disp_int & LB_D1_VBLANK_INTERRUPT)
|
||||
if (ASIC_IS_DCE3(rdev)) {
|
||||
*disp_int = RREG32(DCE3_DISP_INTERRUPT_STATUS);
|
||||
*disp_int_cont = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE);
|
||||
*disp_int_cont2 = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE2);
|
||||
} else {
|
||||
*disp_int = RREG32(DISP_INTERRUPT_STATUS);
|
||||
*disp_int_cont = RREG32(DISP_INTERRUPT_STATUS_CONTINUE);
|
||||
*disp_int_cont2 = 0;
|
||||
}
|
||||
|
||||
if (*disp_int & LB_D1_VBLANK_INTERRUPT)
|
||||
WREG32(D1MODE_VBLANK_STATUS, DxMODE_VBLANK_ACK);
|
||||
if (disp_int & LB_D1_VLINE_INTERRUPT)
|
||||
if (*disp_int & LB_D1_VLINE_INTERRUPT)
|
||||
WREG32(D1MODE_VLINE_STATUS, DxMODE_VLINE_ACK);
|
||||
if (disp_int & LB_D2_VBLANK_INTERRUPT)
|
||||
if (*disp_int & LB_D2_VBLANK_INTERRUPT)
|
||||
WREG32(D2MODE_VBLANK_STATUS, DxMODE_VBLANK_ACK);
|
||||
if (disp_int & LB_D2_VLINE_INTERRUPT)
|
||||
if (*disp_int & LB_D2_VLINE_INTERRUPT)
|
||||
WREG32(D2MODE_VLINE_STATUS, DxMODE_VLINE_ACK);
|
||||
|
||||
if (*disp_int & DC_HPD1_INTERRUPT) {
|
||||
if (ASIC_IS_DCE3(rdev)) {
|
||||
tmp = RREG32(DC_HPD1_INT_CONTROL);
|
||||
tmp |= DC_HPDx_INT_ACK;
|
||||
WREG32(DC_HPD1_INT_CONTROL, tmp);
|
||||
} else {
|
||||
tmp = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL);
|
||||
tmp |= DC_HPDx_INT_ACK;
|
||||
WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp);
|
||||
}
|
||||
}
|
||||
if (*disp_int & DC_HPD2_INTERRUPT) {
|
||||
if (ASIC_IS_DCE3(rdev)) {
|
||||
tmp = RREG32(DC_HPD2_INT_CONTROL);
|
||||
tmp |= DC_HPDx_INT_ACK;
|
||||
WREG32(DC_HPD2_INT_CONTROL, tmp);
|
||||
} else {
|
||||
tmp = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL);
|
||||
tmp |= DC_HPDx_INT_ACK;
|
||||
WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp);
|
||||
}
|
||||
}
|
||||
if (*disp_int_cont & DC_HPD3_INTERRUPT) {
|
||||
if (ASIC_IS_DCE3(rdev)) {
|
||||
tmp = RREG32(DC_HPD3_INT_CONTROL);
|
||||
tmp |= DC_HPDx_INT_ACK;
|
||||
WREG32(DC_HPD3_INT_CONTROL, tmp);
|
||||
} else {
|
||||
tmp = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL);
|
||||
tmp |= DC_HPDx_INT_ACK;
|
||||
WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, tmp);
|
||||
}
|
||||
}
|
||||
if (*disp_int_cont & DC_HPD4_INTERRUPT) {
|
||||
tmp = RREG32(DC_HPD4_INT_CONTROL);
|
||||
tmp |= DC_HPDx_INT_ACK;
|
||||
WREG32(DC_HPD4_INT_CONTROL, tmp);
|
||||
}
|
||||
if (ASIC_IS_DCE32(rdev)) {
|
||||
if (*disp_int_cont2 & DC_HPD5_INTERRUPT) {
|
||||
tmp = RREG32(DC_HPD5_INT_CONTROL);
|
||||
tmp |= DC_HPDx_INT_ACK;
|
||||
WREG32(DC_HPD5_INT_CONTROL, tmp);
|
||||
}
|
||||
if (*disp_int_cont2 & DC_HPD6_INTERRUPT) {
|
||||
tmp = RREG32(DC_HPD5_INT_CONTROL);
|
||||
tmp |= DC_HPDx_INT_ACK;
|
||||
WREG32(DC_HPD6_INT_CONTROL, tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void r600_irq_disable(struct radeon_device *rdev)
|
||||
{
|
||||
u32 disp_int;
|
||||
u32 disp_int, disp_int_cont, disp_int_cont2;
|
||||
|
||||
r600_disable_interrupts(rdev);
|
||||
/* Wait and acknowledge irq */
|
||||
mdelay(1);
|
||||
if (ASIC_IS_DCE3(rdev))
|
||||
disp_int = RREG32(DCE3_DISP_INTERRUPT_STATUS);
|
||||
else
|
||||
disp_int = RREG32(DISP_INTERRUPT_STATUS);
|
||||
r600_irq_ack(rdev, disp_int);
|
||||
r600_irq_ack(rdev, &disp_int, &disp_int_cont, &disp_int_cont2);
|
||||
r600_disable_interrupt_state(rdev);
|
||||
}
|
||||
|
||||
static inline u32 r600_get_ih_wptr(struct radeon_device *rdev)
|
||||
@ -2249,8 +2672,9 @@ int r600_irq_process(struct radeon_device *rdev)
|
||||
u32 rptr = rdev->ih.rptr;
|
||||
u32 src_id, src_data;
|
||||
u32 last_entry = rdev->ih.ring_size - 16;
|
||||
u32 ring_index, disp_int;
|
||||
u32 ring_index, disp_int, disp_int_cont, disp_int_cont2;
|
||||
unsigned long flags;
|
||||
bool queue_hotplug = false;
|
||||
|
||||
DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr);
|
||||
|
||||
@ -2267,11 +2691,7 @@ int r600_irq_process(struct radeon_device *rdev)
|
||||
|
||||
restart_ih:
|
||||
/* display interrupts */
|
||||
if (ASIC_IS_DCE3(rdev))
|
||||
disp_int = RREG32(DCE3_DISP_INTERRUPT_STATUS);
|
||||
else
|
||||
disp_int = RREG32(DISP_INTERRUPT_STATUS);
|
||||
r600_irq_ack(rdev, disp_int);
|
||||
r600_irq_ack(rdev, &disp_int, &disp_int_cont, &disp_int_cont2);
|
||||
|
||||
rdev->ih.wptr = wptr;
|
||||
while (rptr != wptr) {
|
||||
@ -2321,6 +2741,55 @@ restart_ih:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 19: /* HPD/DAC hotplug */
|
||||
switch (src_data) {
|
||||
case 0:
|
||||
if (disp_int & DC_HPD1_INTERRUPT) {
|
||||
disp_int &= ~DC_HPD1_INTERRUPT;
|
||||
queue_hotplug = true;
|
||||
DRM_DEBUG("IH: HPD1\n");
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (disp_int & DC_HPD2_INTERRUPT) {
|
||||
disp_int &= ~DC_HPD2_INTERRUPT;
|
||||
queue_hotplug = true;
|
||||
DRM_DEBUG("IH: HPD2\n");
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (disp_int_cont & DC_HPD3_INTERRUPT) {
|
||||
disp_int_cont &= ~DC_HPD3_INTERRUPT;
|
||||
queue_hotplug = true;
|
||||
DRM_DEBUG("IH: HPD3\n");
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
if (disp_int_cont & DC_HPD4_INTERRUPT) {
|
||||
disp_int_cont &= ~DC_HPD4_INTERRUPT;
|
||||
queue_hotplug = true;
|
||||
DRM_DEBUG("IH: HPD4\n");
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
if (disp_int_cont2 & DC_HPD5_INTERRUPT) {
|
||||
disp_int_cont &= ~DC_HPD5_INTERRUPT;
|
||||
queue_hotplug = true;
|
||||
DRM_DEBUG("IH: HPD5\n");
|
||||
}
|
||||
break;
|
||||
case 12:
|
||||
if (disp_int_cont2 & DC_HPD6_INTERRUPT) {
|
||||
disp_int_cont &= ~DC_HPD6_INTERRUPT;
|
||||
queue_hotplug = true;
|
||||
DRM_DEBUG("IH: HPD6\n");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 176: /* CP_INT in ring buffer */
|
||||
case 177: /* CP_INT in IB1 */
|
||||
case 178: /* CP_INT in IB2 */
|
||||
@ -2345,6 +2814,8 @@ restart_ih:
|
||||
wptr = r600_get_ih_wptr(rdev);
|
||||
if (wptr != rdev->ih.wptr)
|
||||
goto restart_ih;
|
||||
if (queue_hotplug)
|
||||
queue_work(rdev->wq, &rdev->hotplug_work);
|
||||
rdev->ih.rptr = rptr;
|
||||
WREG32(IH_RB_RPTR, rdev->ih.rptr);
|
||||
spin_unlock_irqrestore(&rdev->ih.lock, flags);
|
||||
|
@ -558,6 +558,7 @@
|
||||
# define DC_HOT_PLUG_DETECT2_INTERRUPT (1 << 19)
|
||||
# define DC_I2C_SW_DONE_INTERRUPT (1 << 20)
|
||||
# define DC_I2C_HW_DONE_INTERRUPT (1 << 21)
|
||||
#define DISP_INTERRUPT_STATUS_CONTINUE 0x7ee8
|
||||
#define DCE3_DISP_INTERRUPT_STATUS_CONTINUE 0x7de8
|
||||
# define DC_HPD4_INTERRUPT (1 << 14)
|
||||
# define DC_HPD4_RX_INTERRUPT (1 << 15)
|
||||
@ -590,6 +591,18 @@
|
||||
# define DC_HPD6_INTERRUPT (1 << 21)
|
||||
# define DC_HPD6_RX_INTERRUPT (1 << 22)
|
||||
|
||||
#define DACA_AUTO_DETECT_CONTROL 0x7828
|
||||
#define DACB_AUTO_DETECT_CONTROL 0x7a28
|
||||
#define DCE3_DACA_AUTO_DETECT_CONTROL 0x7028
|
||||
#define DCE3_DACB_AUTO_DETECT_CONTROL 0x7128
|
||||
# define DACx_AUTODETECT_MODE(x) ((x) << 0)
|
||||
# define DACx_AUTODETECT_MODE_NONE 0
|
||||
# define DACx_AUTODETECT_MODE_CONNECT 1
|
||||
# define DACx_AUTODETECT_MODE_DISCONNECT 2
|
||||
# define DACx_AUTODETECT_FRAME_TIME_COUNTER(x) ((x) << 8)
|
||||
/* bit 18 = R/C, 17 = G/Y, 16 = B/Comp */
|
||||
# define DACx_AUTODETECT_CHECK_MASK(x) ((x) << 16)
|
||||
|
||||
#define DCE3_DACA_AUTODETECT_INT_CONTROL 0x7038
|
||||
#define DCE3_DACB_AUTODETECT_INT_CONTROL 0x7138
|
||||
#define DACA_AUTODETECT_INT_CONTROL 0x7838
|
||||
@ -597,23 +610,62 @@
|
||||
# define DACx_AUTODETECT_ACK (1 << 0)
|
||||
# define DACx_AUTODETECT_INT_ENABLE (1 << 16)
|
||||
|
||||
#define DC_HOT_PLUG_DETECT1_CONTROL 0x7d00
|
||||
#define DC_HOT_PLUG_DETECT2_CONTROL 0x7d10
|
||||
#define DC_HOT_PLUG_DETECT3_CONTROL 0x7d24
|
||||
# define DC_HOT_PLUG_DETECTx_EN (1 << 0)
|
||||
|
||||
#define DC_HOT_PLUG_DETECT1_INT_STATUS 0x7d04
|
||||
#define DC_HOT_PLUG_DETECT2_INT_STATUS 0x7d14
|
||||
#define DC_HOT_PLUG_DETECT3_INT_STATUS 0x7d28
|
||||
# define DC_HOT_PLUG_DETECTx_INT_STATUS (1 << 0)
|
||||
# define DC_HOT_PLUG_DETECTx_SENSE (1 << 1)
|
||||
|
||||
/* DCE 3.0 */
|
||||
#define DC_HPD1_INT_STATUS 0x7d00
|
||||
#define DC_HPD2_INT_STATUS 0x7d0c
|
||||
#define DC_HPD3_INT_STATUS 0x7d18
|
||||
#define DC_HPD4_INT_STATUS 0x7d24
|
||||
/* DCE 3.2 */
|
||||
#define DC_HPD5_INT_STATUS 0x7dc0
|
||||
#define DC_HPD6_INT_STATUS 0x7df4
|
||||
# define DC_HPDx_INT_STATUS (1 << 0)
|
||||
# define DC_HPDx_SENSE (1 << 1)
|
||||
# define DC_HPDx_RX_INT_STATUS (1 << 8)
|
||||
|
||||
#define DC_HOT_PLUG_DETECT1_INT_CONTROL 0x7d08
|
||||
#define DC_HOT_PLUG_DETECT2_INT_CONTROL 0x7d18
|
||||
#define DC_HOT_PLUG_DETECT3_INT_CONTROL 0x7d2c
|
||||
# define DC_HOT_PLUG_DETECTx_INT_ACK (1 << 0)
|
||||
# define DC_HOT_PLUG_DETECTx_INT_POLARITY (1 << 8)
|
||||
# define DC_HOT_PLUG_DETECTx_INT_EN (1 << 16)
|
||||
/* DCE 3.2 */
|
||||
/* DCE 3.0 */
|
||||
#define DC_HPD1_INT_CONTROL 0x7d04
|
||||
#define DC_HPD2_INT_CONTROL 0x7d10
|
||||
#define DC_HPD3_INT_CONTROL 0x7d1c
|
||||
#define DC_HPD4_INT_CONTROL 0x7d28
|
||||
/* DCE 3.2 */
|
||||
#define DC_HPD5_INT_CONTROL 0x7dc4
|
||||
#define DC_HPD6_INT_CONTROL 0x7df8
|
||||
# define DC_HPDx_INT_ACK (1 << 0)
|
||||
# define DC_HPDx_INT_POLARITY (1 << 8)
|
||||
# define DC_HPDx_INT_EN (1 << 16)
|
||||
# define DC_HPDx_RX_INT_ACK (1 << 20)
|
||||
# define DC_HPDx_RX_INT_EN (1 << 24)
|
||||
|
||||
/* DCE 3.0 */
|
||||
#define DC_HPD1_CONTROL 0x7d08
|
||||
#define DC_HPD2_CONTROL 0x7d14
|
||||
#define DC_HPD3_CONTROL 0x7d20
|
||||
#define DC_HPD4_CONTROL 0x7d2c
|
||||
/* DCE 3.2 */
|
||||
#define DC_HPD5_CONTROL 0x7dc8
|
||||
#define DC_HPD6_CONTROL 0x7dfc
|
||||
# define DC_HPDx_CONNECTION_TIMER(x) ((x) << 0)
|
||||
# define DC_HPDx_RX_INT_TIMER(x) ((x) << 16)
|
||||
/* DCE 3.2 */
|
||||
# define DC_HPDx_EN (1 << 28)
|
||||
|
||||
/*
|
||||
* PM4
|
||||
*/
|
||||
|
@ -339,6 +339,8 @@ struct radeon_irq {
|
||||
bool sw_int;
|
||||
/* FIXME: use a define max crtc rather than hardcode it */
|
||||
bool crtc_vblank_int[2];
|
||||
/* FIXME: use defines for max hpd/dacs */
|
||||
bool hpd[6];
|
||||
spinlock_t sw_lock;
|
||||
int sw_refcount;
|
||||
};
|
||||
@ -647,6 +649,10 @@ struct radeon_asic {
|
||||
int (*clear_surface_reg)(struct radeon_device *rdev, int reg);
|
||||
void (*bandwidth_update)(struct radeon_device *rdev);
|
||||
void (*hdp_flush)(struct radeon_device *rdev);
|
||||
void (*hpd_init)(struct radeon_device *rdev);
|
||||
void (*hpd_fini)(struct radeon_device *rdev);
|
||||
bool (*hpd_sense)(struct radeon_device *rdev, enum radeon_hpd_id hpd);
|
||||
void (*hpd_set_polarity)(struct radeon_device *rdev, enum radeon_hpd_id hpd);
|
||||
};
|
||||
|
||||
/*
|
||||
@ -803,6 +809,8 @@ struct radeon_device {
|
||||
struct r600_blit r600_blit;
|
||||
int msi_enabled; /* msi enabled */
|
||||
struct r600_ih ih; /* r6/700 interrupt ring */
|
||||
struct workqueue_struct *wq;
|
||||
struct work_struct hotplug_work;
|
||||
};
|
||||
|
||||
int radeon_device_init(struct radeon_device *rdev,
|
||||
@ -986,6 +994,10 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v)
|
||||
#define radeon_clear_surface_reg(rdev, r) ((rdev)->asic->clear_surface_reg((rdev), (r)))
|
||||
#define radeon_bandwidth_update(rdev) (rdev)->asic->bandwidth_update((rdev))
|
||||
#define radeon_hdp_flush(rdev) (rdev)->asic->hdp_flush((rdev))
|
||||
#define radeon_hpd_init(rdev) (rdev)->asic->hpd_init((rdev))
|
||||
#define radeon_hpd_fini(rdev) (rdev)->asic->hpd_fini((rdev))
|
||||
#define radeon_hpd_sense(rdev, hpd) (rdev)->asic->hpd_sense((rdev), (hpd))
|
||||
#define radeon_hpd_set_polarity(rdev, hpd) (rdev)->asic->hpd_set_polarity((rdev), (hpd))
|
||||
|
||||
/* Common functions */
|
||||
extern int radeon_gart_table_vram_pin(struct radeon_device *rdev);
|
||||
|
@ -77,6 +77,11 @@ void r100_bandwidth_update(struct radeon_device *rdev);
|
||||
void r100_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
|
||||
int r100_ring_test(struct radeon_device *rdev);
|
||||
void r100_hdp_flush(struct radeon_device *rdev);
|
||||
void r100_hpd_init(struct radeon_device *rdev);
|
||||
void r100_hpd_fini(struct radeon_device *rdev);
|
||||
bool r100_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd);
|
||||
void r100_hpd_set_polarity(struct radeon_device *rdev,
|
||||
enum radeon_hpd_id hpd);
|
||||
|
||||
static struct radeon_asic r100_asic = {
|
||||
.init = &r100_init,
|
||||
@ -109,6 +114,10 @@ static struct radeon_asic r100_asic = {
|
||||
.clear_surface_reg = r100_clear_surface_reg,
|
||||
.bandwidth_update = &r100_bandwidth_update,
|
||||
.hdp_flush = &r100_hdp_flush,
|
||||
.hpd_init = &r100_hpd_init,
|
||||
.hpd_fini = &r100_hpd_fini,
|
||||
.hpd_sense = &r100_hpd_sense,
|
||||
.hpd_set_polarity = &r100_hpd_set_polarity,
|
||||
};
|
||||
|
||||
|
||||
@ -165,6 +174,10 @@ static struct radeon_asic r300_asic = {
|
||||
.clear_surface_reg = r100_clear_surface_reg,
|
||||
.bandwidth_update = &r100_bandwidth_update,
|
||||
.hdp_flush = &r100_hdp_flush,
|
||||
.hpd_init = &r100_hpd_init,
|
||||
.hpd_fini = &r100_hpd_fini,
|
||||
.hpd_sense = &r100_hpd_sense,
|
||||
.hpd_set_polarity = &r100_hpd_set_polarity,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -205,6 +218,10 @@ static struct radeon_asic r420_asic = {
|
||||
.clear_surface_reg = r100_clear_surface_reg,
|
||||
.bandwidth_update = &r100_bandwidth_update,
|
||||
.hdp_flush = &r100_hdp_flush,
|
||||
.hpd_init = &r100_hpd_init,
|
||||
.hpd_fini = &r100_hpd_fini,
|
||||
.hpd_sense = &r100_hpd_sense,
|
||||
.hpd_set_polarity = &r100_hpd_set_polarity,
|
||||
};
|
||||
|
||||
|
||||
@ -250,6 +267,10 @@ static struct radeon_asic rs400_asic = {
|
||||
.clear_surface_reg = r100_clear_surface_reg,
|
||||
.bandwidth_update = &r100_bandwidth_update,
|
||||
.hdp_flush = &r100_hdp_flush,
|
||||
.hpd_init = &r100_hpd_init,
|
||||
.hpd_fini = &r100_hpd_fini,
|
||||
.hpd_sense = &r100_hpd_sense,
|
||||
.hpd_set_polarity = &r100_hpd_set_polarity,
|
||||
};
|
||||
|
||||
|
||||
@ -268,6 +289,12 @@ int rs600_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr);
|
||||
uint32_t rs600_mc_rreg(struct radeon_device *rdev, uint32_t reg);
|
||||
void rs600_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
|
||||
void rs600_bandwidth_update(struct radeon_device *rdev);
|
||||
void rs600_hpd_init(struct radeon_device *rdev);
|
||||
void rs600_hpd_fini(struct radeon_device *rdev);
|
||||
bool rs600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd);
|
||||
void rs600_hpd_set_polarity(struct radeon_device *rdev,
|
||||
enum radeon_hpd_id hpd);
|
||||
|
||||
static struct radeon_asic rs600_asic = {
|
||||
.init = &rs600_init,
|
||||
.fini = &rs600_fini,
|
||||
@ -297,6 +324,10 @@ static struct radeon_asic rs600_asic = {
|
||||
.set_clock_gating = &radeon_atom_set_clock_gating,
|
||||
.bandwidth_update = &rs600_bandwidth_update,
|
||||
.hdp_flush = &r100_hdp_flush,
|
||||
.hpd_init = &rs600_hpd_init,
|
||||
.hpd_fini = &rs600_hpd_fini,
|
||||
.hpd_sense = &rs600_hpd_sense,
|
||||
.hpd_set_polarity = &rs600_hpd_set_polarity,
|
||||
};
|
||||
|
||||
|
||||
@ -341,6 +372,10 @@ static struct radeon_asic rs690_asic = {
|
||||
.clear_surface_reg = r100_clear_surface_reg,
|
||||
.bandwidth_update = &rs690_bandwidth_update,
|
||||
.hdp_flush = &r100_hdp_flush,
|
||||
.hpd_init = &rs600_hpd_init,
|
||||
.hpd_fini = &rs600_hpd_fini,
|
||||
.hpd_sense = &rs600_hpd_sense,
|
||||
.hpd_set_polarity = &rs600_hpd_set_polarity,
|
||||
};
|
||||
|
||||
|
||||
@ -389,6 +424,10 @@ static struct radeon_asic rv515_asic = {
|
||||
.clear_surface_reg = r100_clear_surface_reg,
|
||||
.bandwidth_update = &rv515_bandwidth_update,
|
||||
.hdp_flush = &r100_hdp_flush,
|
||||
.hpd_init = &rs600_hpd_init,
|
||||
.hpd_fini = &rs600_hpd_fini,
|
||||
.hpd_sense = &rs600_hpd_sense,
|
||||
.hpd_set_polarity = &rs600_hpd_set_polarity,
|
||||
};
|
||||
|
||||
|
||||
@ -428,6 +467,10 @@ static struct radeon_asic r520_asic = {
|
||||
.clear_surface_reg = r100_clear_surface_reg,
|
||||
.bandwidth_update = &rv515_bandwidth_update,
|
||||
.hdp_flush = &r100_hdp_flush,
|
||||
.hpd_init = &rs600_hpd_init,
|
||||
.hpd_fini = &rs600_hpd_fini,
|
||||
.hpd_sense = &rs600_hpd_sense,
|
||||
.hpd_set_polarity = &rs600_hpd_set_polarity,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -465,6 +508,11 @@ int r600_copy_blit(struct radeon_device *rdev,
|
||||
uint64_t src_offset, uint64_t dst_offset,
|
||||
unsigned num_pages, struct radeon_fence *fence);
|
||||
void r600_hdp_flush(struct radeon_device *rdev);
|
||||
void r600_hpd_init(struct radeon_device *rdev);
|
||||
void r600_hpd_fini(struct radeon_device *rdev);
|
||||
bool r600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd);
|
||||
void r600_hpd_set_polarity(struct radeon_device *rdev,
|
||||
enum radeon_hpd_id hpd);
|
||||
|
||||
static struct radeon_asic r600_asic = {
|
||||
.init = &r600_init,
|
||||
@ -496,6 +544,10 @@ static struct radeon_asic r600_asic = {
|
||||
.clear_surface_reg = r600_clear_surface_reg,
|
||||
.bandwidth_update = &rv515_bandwidth_update,
|
||||
.hdp_flush = &r600_hdp_flush,
|
||||
.hpd_init = &r600_hpd_init,
|
||||
.hpd_fini = &r600_hpd_fini,
|
||||
.hpd_sense = &r600_hpd_sense,
|
||||
.hpd_set_polarity = &r600_hpd_set_polarity,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -537,6 +589,10 @@ static struct radeon_asic rv770_asic = {
|
||||
.clear_surface_reg = r600_clear_surface_reg,
|
||||
.bandwidth_update = &rv515_bandwidth_update,
|
||||
.hdp_flush = &r600_hdp_flush,
|
||||
.hpd_init = &r600_hpd_init,
|
||||
.hpd_fini = &r600_hpd_fini,
|
||||
.hpd_sense = &r600_hpd_sense,
|
||||
.hpd_set_polarity = &r600_hpd_set_polarity,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -47,7 +47,8 @@ radeon_add_atom_connector(struct drm_device *dev,
|
||||
int connector_type,
|
||||
struct radeon_i2c_bus_rec *i2c_bus,
|
||||
bool linkb, uint32_t igp_lane_info,
|
||||
uint16_t connector_object_id);
|
||||
uint16_t connector_object_id,
|
||||
struct radeon_hpd *hpd);
|
||||
|
||||
/* from radeon_legacy_encoder.c */
|
||||
extern void
|
||||
@ -60,12 +61,11 @@ union atom_supported_devices {
|
||||
struct _ATOM_SUPPORTED_DEVICES_INFO_2d1 info_2d1;
|
||||
};
|
||||
|
||||
static inline struct radeon_i2c_bus_rec radeon_lookup_gpio(struct drm_device
|
||||
*dev, uint8_t id)
|
||||
static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_device *rdev,
|
||||
uint8_t id)
|
||||
{
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct atom_context *ctx = rdev->mode_info.atom_context;
|
||||
ATOM_GPIO_I2C_ASSIGMENT gpio;
|
||||
ATOM_GPIO_I2C_ASSIGMENT *gpio;
|
||||
struct radeon_i2c_bus_rec i2c;
|
||||
int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info);
|
||||
struct _ATOM_GPIO_I2C_INFO *i2c_info;
|
||||
@ -78,34 +78,116 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_gpio(struct drm_device
|
||||
|
||||
i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset);
|
||||
|
||||
gpio = i2c_info->asGPIO_Info[id];
|
||||
gpio = &i2c_info->asGPIO_Info[id];
|
||||
|
||||
i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4;
|
||||
i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4;
|
||||
i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4;
|
||||
i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4;
|
||||
i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4;
|
||||
i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4;
|
||||
i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4;
|
||||
i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4;
|
||||
i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift);
|
||||
i2c.mask_data_mask = (1 << gpio->ucDataMaskShift);
|
||||
i2c.en_clk_mask = (1 << gpio->ucClkEnShift);
|
||||
i2c.en_data_mask = (1 << gpio->ucDataEnShift);
|
||||
i2c.y_clk_mask = (1 << gpio->ucClkY_Shift);
|
||||
i2c.y_data_mask = (1 << gpio->ucDataY_Shift);
|
||||
i2c.a_clk_mask = (1 << gpio->ucClkA_Shift);
|
||||
i2c.a_data_mask = (1 << gpio->ucDataA_Shift);
|
||||
|
||||
if (gpio->sucI2cId.sbfAccess.bfHW_Capable)
|
||||
i2c.hw_capable = true;
|
||||
else
|
||||
i2c.hw_capable = false;
|
||||
|
||||
if (gpio->sucI2cId.ucAccess == 0xa0)
|
||||
i2c.mm_i2c = true;
|
||||
else
|
||||
i2c.mm_i2c = false;
|
||||
|
||||
i2c.i2c_id = gpio->sucI2cId.ucAccess;
|
||||
|
||||
i2c.mask_clk_reg = le16_to_cpu(gpio.usClkMaskRegisterIndex) * 4;
|
||||
i2c.mask_data_reg = le16_to_cpu(gpio.usDataMaskRegisterIndex) * 4;
|
||||
i2c.en_clk_reg = le16_to_cpu(gpio.usClkEnRegisterIndex) * 4;
|
||||
i2c.en_data_reg = le16_to_cpu(gpio.usDataEnRegisterIndex) * 4;
|
||||
i2c.y_clk_reg = le16_to_cpu(gpio.usClkY_RegisterIndex) * 4;
|
||||
i2c.y_data_reg = le16_to_cpu(gpio.usDataY_RegisterIndex) * 4;
|
||||
i2c.a_clk_reg = le16_to_cpu(gpio.usClkA_RegisterIndex) * 4;
|
||||
i2c.a_data_reg = le16_to_cpu(gpio.usDataA_RegisterIndex) * 4;
|
||||
i2c.mask_clk_mask = (1 << gpio.ucClkMaskShift);
|
||||
i2c.mask_data_mask = (1 << gpio.ucDataMaskShift);
|
||||
i2c.en_clk_mask = (1 << gpio.ucClkEnShift);
|
||||
i2c.en_data_mask = (1 << gpio.ucDataEnShift);
|
||||
i2c.y_clk_mask = (1 << gpio.ucClkY_Shift);
|
||||
i2c.y_data_mask = (1 << gpio.ucDataY_Shift);
|
||||
i2c.a_clk_mask = (1 << gpio.ucClkA_Shift);
|
||||
i2c.a_data_mask = (1 << gpio.ucDataA_Shift);
|
||||
i2c.valid = true;
|
||||
|
||||
return i2c;
|
||||
}
|
||||
|
||||
static inline struct radeon_gpio_rec radeon_lookup_gpio(struct radeon_device *rdev,
|
||||
u8 id)
|
||||
{
|
||||
struct atom_context *ctx = rdev->mode_info.atom_context;
|
||||
struct radeon_gpio_rec gpio;
|
||||
int index = GetIndexIntoMasterTable(DATA, GPIO_Pin_LUT);
|
||||
struct _ATOM_GPIO_PIN_LUT *gpio_info;
|
||||
ATOM_GPIO_PIN_ASSIGNMENT *pin;
|
||||
u16 data_offset, size;
|
||||
int i, num_indices;
|
||||
|
||||
memset(&gpio, 0, sizeof(struct radeon_gpio_rec));
|
||||
gpio.valid = false;
|
||||
|
||||
atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset);
|
||||
|
||||
gpio_info = (struct _ATOM_GPIO_PIN_LUT *)(ctx->bios + data_offset);
|
||||
|
||||
num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / sizeof(ATOM_GPIO_PIN_ASSIGNMENT);
|
||||
|
||||
for (i = 0; i < num_indices; i++) {
|
||||
pin = &gpio_info->asGPIO_Pin[i];
|
||||
if (id == pin->ucGPIO_ID) {
|
||||
gpio.id = pin->ucGPIO_ID;
|
||||
gpio.reg = pin->usGpioPin_AIndex * 4;
|
||||
gpio.mask = (1 << pin->ucGpioPinBitShift);
|
||||
gpio.valid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return gpio;
|
||||
}
|
||||
|
||||
static struct radeon_hpd radeon_atom_get_hpd_info_from_gpio(struct radeon_device *rdev,
|
||||
struct radeon_gpio_rec *gpio)
|
||||
{
|
||||
struct radeon_hpd hpd;
|
||||
hpd.gpio = *gpio;
|
||||
if (gpio->reg == AVIVO_DC_GPIO_HPD_A) {
|
||||
switch(gpio->mask) {
|
||||
case (1 << 0):
|
||||
hpd.hpd = RADEON_HPD_1;
|
||||
break;
|
||||
case (1 << 8):
|
||||
hpd.hpd = RADEON_HPD_2;
|
||||
break;
|
||||
case (1 << 16):
|
||||
hpd.hpd = RADEON_HPD_3;
|
||||
break;
|
||||
case (1 << 24):
|
||||
hpd.hpd = RADEON_HPD_4;
|
||||
break;
|
||||
case (1 << 26):
|
||||
hpd.hpd = RADEON_HPD_5;
|
||||
break;
|
||||
case (1 << 28):
|
||||
hpd.hpd = RADEON_HPD_6;
|
||||
break;
|
||||
default:
|
||||
hpd.hpd = RADEON_HPD_NONE;
|
||||
break;
|
||||
}
|
||||
} else
|
||||
hpd.hpd = RADEON_HPD_NONE;
|
||||
return hpd;
|
||||
}
|
||||
|
||||
static bool radeon_atom_apply_quirks(struct drm_device *dev,
|
||||
uint32_t supported_device,
|
||||
int *connector_type,
|
||||
struct radeon_i2c_bus_rec *i2c_bus,
|
||||
uint16_t *line_mux)
|
||||
uint16_t *line_mux,
|
||||
struct radeon_hpd *hpd)
|
||||
{
|
||||
|
||||
/* Asus M2A-VM HDMI board lists the DVI port as HDMI */
|
||||
@ -266,16 +348,18 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
|
||||
struct radeon_mode_info *mode_info = &rdev->mode_info;
|
||||
struct atom_context *ctx = mode_info->atom_context;
|
||||
int index = GetIndexIntoMasterTable(DATA, Object_Header);
|
||||
uint16_t size, data_offset;
|
||||
uint8_t frev, crev, line_mux = 0;
|
||||
u16 size, data_offset;
|
||||
u8 frev, crev;
|
||||
ATOM_CONNECTOR_OBJECT_TABLE *con_obj;
|
||||
ATOM_DISPLAY_OBJECT_PATH_TABLE *path_obj;
|
||||
ATOM_OBJECT_HEADER *obj_header;
|
||||
int i, j, path_size, device_support;
|
||||
int connector_type;
|
||||
uint16_t igp_lane_info, conn_id, connector_object_id;
|
||||
u16 igp_lane_info, conn_id, connector_object_id;
|
||||
bool linkb;
|
||||
struct radeon_i2c_bus_rec ddc_bus;
|
||||
struct radeon_gpio_rec gpio;
|
||||
struct radeon_hpd hpd;
|
||||
|
||||
atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset);
|
||||
|
||||
@ -302,7 +386,6 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
|
||||
path = (ATOM_DISPLAY_OBJECT_PATH *) addr;
|
||||
path_size += le16_to_cpu(path->usSize);
|
||||
linkb = false;
|
||||
|
||||
if (device_support & le16_to_cpu(path->usDeviceTag)) {
|
||||
uint8_t con_obj_id, con_obj_num, con_obj_type;
|
||||
|
||||
@ -403,10 +486,9 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
|
||||
}
|
||||
}
|
||||
|
||||
/* look up gpio for ddc */
|
||||
/* look up gpio for ddc, hpd */
|
||||
if ((le16_to_cpu(path->usDeviceTag) &
|
||||
(ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
|
||||
== 0) {
|
||||
(ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) == 0) {
|
||||
for (j = 0; j < con_obj->ucNumberOfObjects; j++) {
|
||||
if (le16_to_cpu(path->usConnObjectId) ==
|
||||
le16_to_cpu(con_obj->asObjects[j].
|
||||
@ -420,21 +502,31 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
|
||||
asObjects[j].
|
||||
usRecordOffset));
|
||||
ATOM_I2C_RECORD *i2c_record;
|
||||
ATOM_HPD_INT_RECORD *hpd_record;
|
||||
hpd.hpd = RADEON_HPD_NONE;
|
||||
|
||||
while (record->ucRecordType > 0
|
||||
&& record->
|
||||
ucRecordType <=
|
||||
ATOM_MAX_OBJECT_RECORD_NUMBER) {
|
||||
switch (record->
|
||||
ucRecordType) {
|
||||
switch (record->ucRecordType) {
|
||||
case ATOM_I2C_RECORD_TYPE:
|
||||
i2c_record =
|
||||
(ATOM_I2C_RECORD
|
||||
*) record;
|
||||
line_mux =
|
||||
i2c_record->
|
||||
sucI2cId.
|
||||
bfI2C_LineMux;
|
||||
(ATOM_I2C_RECORD *)
|
||||
record;
|
||||
ddc_bus = radeon_lookup_i2c_gpio(rdev,
|
||||
i2c_record->
|
||||
sucI2cId.
|
||||
bfI2C_LineMux);
|
||||
break;
|
||||
case ATOM_HPD_INT_RECORD_TYPE:
|
||||
hpd_record =
|
||||
(ATOM_HPD_INT_RECORD *)
|
||||
record;
|
||||
gpio = radeon_lookup_gpio(rdev,
|
||||
hpd_record->ucHPDIntGPIOID);
|
||||
hpd = radeon_atom_get_hpd_info_from_gpio(rdev, &gpio);
|
||||
hpd.plugged_state = hpd_record->ucPlugged_PinState;
|
||||
break;
|
||||
}
|
||||
record =
|
||||
@ -447,24 +539,16 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else
|
||||
line_mux = 0;
|
||||
|
||||
if ((le16_to_cpu(path->usDeviceTag) ==
|
||||
ATOM_DEVICE_TV1_SUPPORT)
|
||||
|| (le16_to_cpu(path->usDeviceTag) ==
|
||||
ATOM_DEVICE_TV2_SUPPORT)
|
||||
|| (le16_to_cpu(path->usDeviceTag) ==
|
||||
ATOM_DEVICE_CV_SUPPORT))
|
||||
} else {
|
||||
hpd.hpd = RADEON_HPD_NONE;
|
||||
ddc_bus.valid = false;
|
||||
else
|
||||
ddc_bus = radeon_lookup_gpio(dev, line_mux);
|
||||
}
|
||||
|
||||
conn_id = le16_to_cpu(path->usConnObjectId);
|
||||
|
||||
if (!radeon_atom_apply_quirks
|
||||
(dev, le16_to_cpu(path->usDeviceTag), &connector_type,
|
||||
&ddc_bus, &conn_id))
|
||||
&ddc_bus, &conn_id, &hpd))
|
||||
continue;
|
||||
|
||||
radeon_add_atom_connector(dev,
|
||||
@ -473,7 +557,8 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
|
||||
usDeviceTag),
|
||||
connector_type, &ddc_bus,
|
||||
linkb, igp_lane_info,
|
||||
connector_object_id);
|
||||
connector_object_id,
|
||||
&hpd);
|
||||
|
||||
}
|
||||
}
|
||||
@ -528,6 +613,7 @@ struct bios_connector {
|
||||
uint16_t devices;
|
||||
int connector_type;
|
||||
struct radeon_i2c_bus_rec ddc_bus;
|
||||
struct radeon_hpd hpd;
|
||||
};
|
||||
|
||||
bool radeon_get_atom_connector_info_from_supported_devices_table(struct
|
||||
@ -543,7 +629,7 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
|
||||
uint16_t device_support;
|
||||
uint8_t dac;
|
||||
union atom_supported_devices *supported_devices;
|
||||
int i, j;
|
||||
int i, j, max_device;
|
||||
struct bios_connector bios_connectors[ATOM_MAX_SUPPORTED_DEVICE];
|
||||
|
||||
atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset);
|
||||
@ -553,7 +639,12 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
|
||||
|
||||
device_support = le16_to_cpu(supported_devices->info.usDeviceSupport);
|
||||
|
||||
for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) {
|
||||
if (frev > 1)
|
||||
max_device = ATOM_MAX_SUPPORTED_DEVICE;
|
||||
else
|
||||
max_device = ATOM_MAX_SUPPORTED_DEVICE_INFO;
|
||||
|
||||
for (i = 0; i < max_device; i++) {
|
||||
ATOM_CONNECTOR_INFO_I2C ci =
|
||||
supported_devices->info.asConnInfo[i];
|
||||
|
||||
@ -608,8 +699,30 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
|
||||
bios_connectors[i].line_mux = 52;
|
||||
} else
|
||||
bios_connectors[i].ddc_bus =
|
||||
radeon_lookup_gpio(dev,
|
||||
bios_connectors[i].line_mux);
|
||||
radeon_lookup_i2c_gpio(rdev,
|
||||
bios_connectors[i].line_mux);
|
||||
|
||||
if ((crev > 1) && (frev > 1)) {
|
||||
u8 isb = supported_devices->info_2d1.asIntSrcInfo[i].ucIntSrcBitmap;
|
||||
switch (isb) {
|
||||
case 0x4:
|
||||
bios_connectors[i].hpd.hpd = RADEON_HPD_1;
|
||||
break;
|
||||
case 0xa:
|
||||
bios_connectors[i].hpd.hpd = RADEON_HPD_2;
|
||||
break;
|
||||
default:
|
||||
bios_connectors[i].hpd.hpd = RADEON_HPD_NONE;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (i == ATOM_DEVICE_DFP1_INDEX)
|
||||
bios_connectors[i].hpd.hpd = RADEON_HPD_1;
|
||||
else if (i == ATOM_DEVICE_DFP2_INDEX)
|
||||
bios_connectors[i].hpd.hpd = RADEON_HPD_2;
|
||||
else
|
||||
bios_connectors[i].hpd.hpd = RADEON_HPD_NONE;
|
||||
}
|
||||
|
||||
/* Always set the connector type to VGA for CRT1/CRT2. if they are
|
||||
* shared with a DVI port, we'll pick up the DVI connector when we
|
||||
@ -621,7 +734,8 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
|
||||
|
||||
if (!radeon_atom_apply_quirks
|
||||
(dev, (1 << i), &bios_connectors[i].connector_type,
|
||||
&bios_connectors[i].ddc_bus, &bios_connectors[i].line_mux))
|
||||
&bios_connectors[i].ddc_bus, &bios_connectors[i].line_mux,
|
||||
&bios_connectors[i].hpd))
|
||||
continue;
|
||||
|
||||
bios_connectors[i].valid = true;
|
||||
@ -643,9 +757,9 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
|
||||
}
|
||||
|
||||
/* combine shared connectors */
|
||||
for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) {
|
||||
for (i = 0; i < max_device; i++) {
|
||||
if (bios_connectors[i].valid) {
|
||||
for (j = 0; j < ATOM_MAX_SUPPORTED_DEVICE; j++) {
|
||||
for (j = 0; j < max_device; j++) {
|
||||
if (bios_connectors[j].valid && (i != j)) {
|
||||
if (bios_connectors[i].line_mux ==
|
||||
bios_connectors[j].line_mux) {
|
||||
@ -669,6 +783,10 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
|
||||
bios_connectors[i].
|
||||
connector_type =
|
||||
DRM_MODE_CONNECTOR_DVII;
|
||||
if (bios_connectors[j].devices &
|
||||
(ATOM_DEVICE_DFP_SUPPORT))
|
||||
bios_connectors[i].hpd =
|
||||
bios_connectors[j].hpd;
|
||||
bios_connectors[j].
|
||||
valid = false;
|
||||
}
|
||||
@ -679,7 +797,7 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
|
||||
}
|
||||
|
||||
/* add the connectors */
|
||||
for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) {
|
||||
for (i = 0; i < max_device; i++) {
|
||||
if (bios_connectors[i].valid) {
|
||||
uint16_t connector_object_id =
|
||||
atombios_get_connector_object_id(dev,
|
||||
@ -692,7 +810,8 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
|
||||
connector_type,
|
||||
&bios_connectors[i].ddc_bus,
|
||||
false, 0,
|
||||
connector_object_id);
|
||||
connector_object_id,
|
||||
&bios_connectors[i].hpd);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,8 @@ radeon_add_legacy_connector(struct drm_device *dev,
|
||||
uint32_t supported_device,
|
||||
int connector_type,
|
||||
struct radeon_i2c_bus_rec *i2c_bus,
|
||||
uint16_t connector_object_id);
|
||||
uint16_t connector_object_id,
|
||||
struct radeon_hpd *hpd);
|
||||
|
||||
/* from radeon_legacy_encoder.c */
|
||||
extern void
|
||||
@ -442,29 +443,39 @@ static uint16_t combios_get_table_offset(struct drm_device *dev,
|
||||
|
||||
}
|
||||
|
||||
struct radeon_i2c_bus_rec combios_setup_i2c_bus(int ddc_line)
|
||||
static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rdev,
|
||||
int ddc_line)
|
||||
{
|
||||
struct radeon_i2c_bus_rec i2c;
|
||||
|
||||
i2c.mask_clk_mask = RADEON_GPIO_EN_1;
|
||||
i2c.mask_data_mask = RADEON_GPIO_EN_0;
|
||||
i2c.a_clk_mask = RADEON_GPIO_A_1;
|
||||
i2c.a_data_mask = RADEON_GPIO_A_0;
|
||||
i2c.en_clk_mask = RADEON_GPIO_EN_1;
|
||||
i2c.en_data_mask = RADEON_GPIO_EN_0;
|
||||
i2c.y_clk_mask = RADEON_GPIO_Y_1;
|
||||
i2c.y_data_mask = RADEON_GPIO_Y_0;
|
||||
if ((ddc_line == RADEON_LCD_GPIO_MASK) ||
|
||||
(ddc_line == RADEON_MDGPIO_EN_REG)) {
|
||||
i2c.mask_clk_reg = ddc_line;
|
||||
i2c.mask_data_reg = ddc_line;
|
||||
i2c.a_clk_reg = ddc_line;
|
||||
i2c.a_data_reg = ddc_line;
|
||||
i2c.en_clk_reg = ddc_line;
|
||||
i2c.en_data_reg = ddc_line;
|
||||
i2c.y_clk_reg = ddc_line + 4;
|
||||
i2c.y_data_reg = ddc_line + 4;
|
||||
if (ddc_line == RADEON_GPIOPAD_MASK) {
|
||||
i2c.mask_clk_reg = RADEON_GPIOPAD_MASK;
|
||||
i2c.mask_data_reg = RADEON_GPIOPAD_MASK;
|
||||
i2c.a_clk_reg = RADEON_GPIOPAD_A;
|
||||
i2c.a_data_reg = RADEON_GPIOPAD_A;
|
||||
i2c.en_clk_reg = RADEON_GPIOPAD_EN;
|
||||
i2c.en_data_reg = RADEON_GPIOPAD_EN;
|
||||
i2c.y_clk_reg = RADEON_GPIOPAD_Y;
|
||||
i2c.y_data_reg = RADEON_GPIOPAD_Y;
|
||||
} else if (ddc_line == RADEON_MDGPIO_MASK) {
|
||||
i2c.mask_clk_reg = RADEON_MDGPIO_MASK;
|
||||
i2c.mask_data_reg = RADEON_MDGPIO_MASK;
|
||||
i2c.a_clk_reg = RADEON_MDGPIO_A;
|
||||
i2c.a_data_reg = RADEON_MDGPIO_A;
|
||||
i2c.en_clk_reg = RADEON_MDGPIO_EN;
|
||||
i2c.en_data_reg = RADEON_MDGPIO_EN;
|
||||
i2c.y_clk_reg = RADEON_MDGPIO_Y;
|
||||
i2c.y_data_reg = RADEON_MDGPIO_Y;
|
||||
} else {
|
||||
i2c.mask_clk_mask = RADEON_GPIO_EN_1;
|
||||
i2c.mask_data_mask = RADEON_GPIO_EN_0;
|
||||
i2c.a_clk_mask = RADEON_GPIO_A_1;
|
||||
i2c.a_data_mask = RADEON_GPIO_A_0;
|
||||
i2c.en_clk_mask = RADEON_GPIO_EN_1;
|
||||
i2c.en_data_mask = RADEON_GPIO_EN_0;
|
||||
i2c.y_clk_mask = RADEON_GPIO_Y_1;
|
||||
i2c.y_data_mask = RADEON_GPIO_Y_0;
|
||||
|
||||
i2c.mask_clk_reg = ddc_line;
|
||||
i2c.mask_data_reg = ddc_line;
|
||||
i2c.a_clk_reg = ddc_line;
|
||||
@ -475,6 +486,28 @@ struct radeon_i2c_bus_rec combios_setup_i2c_bus(int ddc_line)
|
||||
i2c.y_data_reg = ddc_line;
|
||||
}
|
||||
|
||||
if (rdev->family < CHIP_R200)
|
||||
i2c.hw_capable = false;
|
||||
else {
|
||||
switch (ddc_line) {
|
||||
case RADEON_GPIO_VGA_DDC:
|
||||
case RADEON_GPIO_DVI_DDC:
|
||||
i2c.hw_capable = true;
|
||||
break;
|
||||
case RADEON_GPIO_MONID:
|
||||
/* hw i2c on RADEON_GPIO_MONID doesn't seem to work
|
||||
* reliably on some pre-r4xx hardware; not sure why.
|
||||
*/
|
||||
i2c.hw_capable = false;
|
||||
break;
|
||||
default:
|
||||
i2c.hw_capable = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
i2c.mm_i2c = false;
|
||||
i2c.i2c_id = 0;
|
||||
|
||||
if (ddc_line)
|
||||
i2c.valid = true;
|
||||
else
|
||||
@ -1077,7 +1110,7 @@ bool radeon_legacy_get_ext_tmds_info_from_table(struct radeon_encoder *encoder,
|
||||
struct radeon_i2c_bus_rec i2c_bus;
|
||||
|
||||
/* default for macs */
|
||||
i2c_bus = combios_setup_i2c_bus(RADEON_GPIO_MONID);
|
||||
i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID);
|
||||
tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO");
|
||||
|
||||
/* XXX some macs have duallink chips */
|
||||
@ -1153,23 +1186,23 @@ bool radeon_legacy_get_ext_tmds_info_from_combios(struct radeon_encoder *encoder
|
||||
gpio = RBIOS8(offset + 4 + 3);
|
||||
switch (gpio) {
|
||||
case DDC_MONID:
|
||||
i2c_bus = combios_setup_i2c_bus(RADEON_GPIO_MONID);
|
||||
i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID);
|
||||
tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO");
|
||||
break;
|
||||
case DDC_DVI:
|
||||
i2c_bus = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
|
||||
i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC);
|
||||
tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO");
|
||||
break;
|
||||
case DDC_VGA:
|
||||
i2c_bus = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
|
||||
i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
|
||||
tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO");
|
||||
break;
|
||||
case DDC_CRT2:
|
||||
/* R3xx+ chips don't have GPIO_CRT2_DDC gpio pad */
|
||||
if (rdev->family >= CHIP_R300)
|
||||
i2c_bus = combios_setup_i2c_bus(RADEON_GPIO_MONID);
|
||||
i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID);
|
||||
else
|
||||
i2c_bus = combios_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
|
||||
i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC);
|
||||
tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO");
|
||||
break;
|
||||
case DDC_LCD: /* MM i2c */
|
||||
@ -1194,6 +1227,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
|
||||
{
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct radeon_i2c_bus_rec ddc_i2c;
|
||||
struct radeon_hpd hpd;
|
||||
|
||||
rdev->mode_info.connector_table = radeon_connector_table;
|
||||
if (rdev->mode_info.connector_table == CT_NONE) {
|
||||
@ -1254,7 +1288,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
|
||||
/* these are the most common settings */
|
||||
if (rdev->flags & RADEON_SINGLE_CRTC) {
|
||||
/* VGA - primary dac */
|
||||
ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
|
||||
ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
|
||||
hpd.hpd = RADEON_HPD_NONE;
|
||||
radeon_add_legacy_encoder(dev,
|
||||
radeon_get_encoder_id(dev,
|
||||
ATOM_DEVICE_CRT1_SUPPORT,
|
||||
@ -1264,10 +1299,12 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
|
||||
ATOM_DEVICE_CRT1_SUPPORT,
|
||||
DRM_MODE_CONNECTOR_VGA,
|
||||
&ddc_i2c,
|
||||
CONNECTOR_OBJECT_ID_VGA);
|
||||
CONNECTOR_OBJECT_ID_VGA,
|
||||
&hpd);
|
||||
} else if (rdev->flags & RADEON_IS_MOBILITY) {
|
||||
/* LVDS */
|
||||
ddc_i2c = combios_setup_i2c_bus(RADEON_LCD_GPIO_MASK);
|
||||
ddc_i2c = combios_setup_i2c_bus(rdev, 0);
|
||||
hpd.hpd = RADEON_HPD_NONE;
|
||||
radeon_add_legacy_encoder(dev,
|
||||
radeon_get_encoder_id(dev,
|
||||
ATOM_DEVICE_LCD1_SUPPORT,
|
||||
@ -1277,10 +1314,12 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
|
||||
ATOM_DEVICE_LCD1_SUPPORT,
|
||||
DRM_MODE_CONNECTOR_LVDS,
|
||||
&ddc_i2c,
|
||||
CONNECTOR_OBJECT_ID_LVDS);
|
||||
CONNECTOR_OBJECT_ID_LVDS,
|
||||
&hpd);
|
||||
|
||||
/* VGA - primary dac */
|
||||
ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
|
||||
ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
|
||||
hpd.hpd = RADEON_HPD_NONE;
|
||||
radeon_add_legacy_encoder(dev,
|
||||
radeon_get_encoder_id(dev,
|
||||
ATOM_DEVICE_CRT1_SUPPORT,
|
||||
@ -1290,10 +1329,12 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
|
||||
ATOM_DEVICE_CRT1_SUPPORT,
|
||||
DRM_MODE_CONNECTOR_VGA,
|
||||
&ddc_i2c,
|
||||
CONNECTOR_OBJECT_ID_VGA);
|
||||
CONNECTOR_OBJECT_ID_VGA,
|
||||
&hpd);
|
||||
} else {
|
||||
/* DVI-I - tv dac, int tmds */
|
||||
ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
|
||||
ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC);
|
||||
hpd.hpd = RADEON_HPD_1;
|
||||
radeon_add_legacy_encoder(dev,
|
||||
radeon_get_encoder_id(dev,
|
||||
ATOM_DEVICE_DFP1_SUPPORT,
|
||||
@ -1309,10 +1350,12 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
|
||||
ATOM_DEVICE_CRT2_SUPPORT,
|
||||
DRM_MODE_CONNECTOR_DVII,
|
||||
&ddc_i2c,
|
||||
CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I);
|
||||
CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I,
|
||||
&hpd);
|
||||
|
||||
/* VGA - primary dac */
|
||||
ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
|
||||
ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
|
||||
hpd.hpd = RADEON_HPD_NONE;
|
||||
radeon_add_legacy_encoder(dev,
|
||||
radeon_get_encoder_id(dev,
|
||||
ATOM_DEVICE_CRT1_SUPPORT,
|
||||
@ -1322,11 +1365,14 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
|
||||
ATOM_DEVICE_CRT1_SUPPORT,
|
||||
DRM_MODE_CONNECTOR_VGA,
|
||||
&ddc_i2c,
|
||||
CONNECTOR_OBJECT_ID_VGA);
|
||||
CONNECTOR_OBJECT_ID_VGA,
|
||||
&hpd);
|
||||
}
|
||||
|
||||
if (rdev->family != CHIP_R100 && rdev->family != CHIP_R200) {
|
||||
/* TV - tv dac */
|
||||
ddc_i2c.valid = false;
|
||||
hpd.hpd = RADEON_HPD_NONE;
|
||||
radeon_add_legacy_encoder(dev,
|
||||
radeon_get_encoder_id(dev,
|
||||
ATOM_DEVICE_TV1_SUPPORT,
|
||||
@ -1336,14 +1382,16 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
|
||||
ATOM_DEVICE_TV1_SUPPORT,
|
||||
DRM_MODE_CONNECTOR_SVIDEO,
|
||||
&ddc_i2c,
|
||||
CONNECTOR_OBJECT_ID_SVIDEO);
|
||||
CONNECTOR_OBJECT_ID_SVIDEO,
|
||||
&hpd);
|
||||
}
|
||||
break;
|
||||
case CT_IBOOK:
|
||||
DRM_INFO("Connector Table: %d (ibook)\n",
|
||||
rdev->mode_info.connector_table);
|
||||
/* LVDS */
|
||||
ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
|
||||
ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC);
|
||||
hpd.hpd = RADEON_HPD_NONE;
|
||||
radeon_add_legacy_encoder(dev,
|
||||
radeon_get_encoder_id(dev,
|
||||
ATOM_DEVICE_LCD1_SUPPORT,
|
||||
@ -1351,9 +1399,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
|
||||
ATOM_DEVICE_LCD1_SUPPORT);
|
||||
radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT,
|
||||
DRM_MODE_CONNECTOR_LVDS, &ddc_i2c,
|
||||
CONNECTOR_OBJECT_ID_LVDS);
|
||||
CONNECTOR_OBJECT_ID_LVDS,
|
||||
&hpd);
|
||||
/* VGA - TV DAC */
|
||||
ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
|
||||
ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
|
||||
hpd.hpd = RADEON_HPD_NONE;
|
||||
radeon_add_legacy_encoder(dev,
|
||||
radeon_get_encoder_id(dev,
|
||||
ATOM_DEVICE_CRT2_SUPPORT,
|
||||
@ -1361,8 +1411,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
|
||||
ATOM_DEVICE_CRT2_SUPPORT);
|
||||
radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT2_SUPPORT,
|
||||
DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
|
||||
CONNECTOR_OBJECT_ID_VGA);
|
||||
CONNECTOR_OBJECT_ID_VGA,
|
||||
&hpd);
|
||||
/* TV - TV DAC */
|
||||
ddc_i2c.valid = false;
|
||||
hpd.hpd = RADEON_HPD_NONE;
|
||||
radeon_add_legacy_encoder(dev,
|
||||
radeon_get_encoder_id(dev,
|
||||
ATOM_DEVICE_TV1_SUPPORT,
|
||||
@ -1371,13 +1424,15 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
|
||||
radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
|
||||
DRM_MODE_CONNECTOR_SVIDEO,
|
||||
&ddc_i2c,
|
||||
CONNECTOR_OBJECT_ID_SVIDEO);
|
||||
CONNECTOR_OBJECT_ID_SVIDEO,
|
||||
&hpd);
|
||||
break;
|
||||
case CT_POWERBOOK_EXTERNAL:
|
||||
DRM_INFO("Connector Table: %d (powerbook external tmds)\n",
|
||||
rdev->mode_info.connector_table);
|
||||
/* LVDS */
|
||||
ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
|
||||
ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC);
|
||||
hpd.hpd = RADEON_HPD_NONE;
|
||||
radeon_add_legacy_encoder(dev,
|
||||
radeon_get_encoder_id(dev,
|
||||
ATOM_DEVICE_LCD1_SUPPORT,
|
||||
@ -1385,9 +1440,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
|
||||
ATOM_DEVICE_LCD1_SUPPORT);
|
||||
radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT,
|
||||
DRM_MODE_CONNECTOR_LVDS, &ddc_i2c,
|
||||
CONNECTOR_OBJECT_ID_LVDS);
|
||||
CONNECTOR_OBJECT_ID_LVDS,
|
||||
&hpd);
|
||||
/* DVI-I - primary dac, ext tmds */
|
||||
ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
|
||||
ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
|
||||
hpd.hpd = RADEON_HPD_2; /* ??? */
|
||||
radeon_add_legacy_encoder(dev,
|
||||
radeon_get_encoder_id(dev,
|
||||
ATOM_DEVICE_DFP2_SUPPORT,
|
||||
@ -1403,8 +1460,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
|
||||
ATOM_DEVICE_DFP2_SUPPORT |
|
||||
ATOM_DEVICE_CRT1_SUPPORT,
|
||||
DRM_MODE_CONNECTOR_DVII, &ddc_i2c,
|
||||
CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I);
|
||||
CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I,
|
||||
&hpd);
|
||||
/* TV - TV DAC */
|
||||
ddc_i2c.valid = false;
|
||||
hpd.hpd = RADEON_HPD_NONE;
|
||||
radeon_add_legacy_encoder(dev,
|
||||
radeon_get_encoder_id(dev,
|
||||
ATOM_DEVICE_TV1_SUPPORT,
|
||||
@ -1413,13 +1473,15 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
|
||||
radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
|
||||
DRM_MODE_CONNECTOR_SVIDEO,
|
||||
&ddc_i2c,
|
||||
CONNECTOR_OBJECT_ID_SVIDEO);
|
||||
CONNECTOR_OBJECT_ID_SVIDEO,
|
||||
&hpd);
|
||||
break;
|
||||
case CT_POWERBOOK_INTERNAL:
|
||||
DRM_INFO("Connector Table: %d (powerbook internal tmds)\n",
|
||||
rdev->mode_info.connector_table);
|
||||
/* LVDS */
|
||||
ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
|
||||
ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC);
|
||||
hpd.hpd = RADEON_HPD_NONE;
|
||||
radeon_add_legacy_encoder(dev,
|
||||
radeon_get_encoder_id(dev,
|
||||
ATOM_DEVICE_LCD1_SUPPORT,
|
||||
@ -1427,9 +1489,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
|
||||
ATOM_DEVICE_LCD1_SUPPORT);
|
||||
radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT,
|
||||
DRM_MODE_CONNECTOR_LVDS, &ddc_i2c,
|
||||
CONNECTOR_OBJECT_ID_LVDS);
|
||||
CONNECTOR_OBJECT_ID_LVDS,
|
||||
&hpd);
|
||||
/* DVI-I - primary dac, int tmds */
|
||||
ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
|
||||
ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
|
||||
hpd.hpd = RADEON_HPD_1; /* ??? */
|
||||
radeon_add_legacy_encoder(dev,
|
||||
radeon_get_encoder_id(dev,
|
||||
ATOM_DEVICE_DFP1_SUPPORT,
|
||||
@ -1444,8 +1508,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
|
||||
ATOM_DEVICE_DFP1_SUPPORT |
|
||||
ATOM_DEVICE_CRT1_SUPPORT,
|
||||
DRM_MODE_CONNECTOR_DVII, &ddc_i2c,
|
||||
CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I);
|
||||
CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I,
|
||||
&hpd);
|
||||
/* TV - TV DAC */
|
||||
ddc_i2c.valid = false;
|
||||
hpd.hpd = RADEON_HPD_NONE;
|
||||
radeon_add_legacy_encoder(dev,
|
||||
radeon_get_encoder_id(dev,
|
||||
ATOM_DEVICE_TV1_SUPPORT,
|
||||
@ -1454,13 +1521,15 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
|
||||
radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
|
||||
DRM_MODE_CONNECTOR_SVIDEO,
|
||||
&ddc_i2c,
|
||||
CONNECTOR_OBJECT_ID_SVIDEO);
|
||||
CONNECTOR_OBJECT_ID_SVIDEO,
|
||||
&hpd);
|
||||
break;
|
||||
case CT_POWERBOOK_VGA:
|
||||
DRM_INFO("Connector Table: %d (powerbook vga)\n",
|
||||
rdev->mode_info.connector_table);
|
||||
/* LVDS */
|
||||
ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
|
||||
ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC);
|
||||
hpd.hpd = RADEON_HPD_NONE;
|
||||
radeon_add_legacy_encoder(dev,
|
||||
radeon_get_encoder_id(dev,
|
||||
ATOM_DEVICE_LCD1_SUPPORT,
|
||||
@ -1468,9 +1537,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
|
||||
ATOM_DEVICE_LCD1_SUPPORT);
|
||||
radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT,
|
||||
DRM_MODE_CONNECTOR_LVDS, &ddc_i2c,
|
||||
CONNECTOR_OBJECT_ID_LVDS);
|
||||
CONNECTOR_OBJECT_ID_LVDS,
|
||||
&hpd);
|
||||
/* VGA - primary dac */
|
||||
ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
|
||||
ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
|
||||
hpd.hpd = RADEON_HPD_NONE;
|
||||
radeon_add_legacy_encoder(dev,
|
||||
radeon_get_encoder_id(dev,
|
||||
ATOM_DEVICE_CRT1_SUPPORT,
|
||||
@ -1478,8 +1549,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
|
||||
ATOM_DEVICE_CRT1_SUPPORT);
|
||||
radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT1_SUPPORT,
|
||||
DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
|
||||
CONNECTOR_OBJECT_ID_VGA);
|
||||
CONNECTOR_OBJECT_ID_VGA,
|
||||
&hpd);
|
||||
/* TV - TV DAC */
|
||||
ddc_i2c.valid = false;
|
||||
hpd.hpd = RADEON_HPD_NONE;
|
||||
radeon_add_legacy_encoder(dev,
|
||||
radeon_get_encoder_id(dev,
|
||||
ATOM_DEVICE_TV1_SUPPORT,
|
||||
@ -1488,13 +1562,15 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
|
||||
radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
|
||||
DRM_MODE_CONNECTOR_SVIDEO,
|
||||
&ddc_i2c,
|
||||
CONNECTOR_OBJECT_ID_SVIDEO);
|
||||
CONNECTOR_OBJECT_ID_SVIDEO,
|
||||
&hpd);
|
||||
break;
|
||||
case CT_MINI_EXTERNAL:
|
||||
DRM_INFO("Connector Table: %d (mini external tmds)\n",
|
||||
rdev->mode_info.connector_table);
|
||||
/* DVI-I - tv dac, ext tmds */
|
||||
ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
|
||||
ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC);
|
||||
hpd.hpd = RADEON_HPD_2; /* ??? */
|
||||
radeon_add_legacy_encoder(dev,
|
||||
radeon_get_encoder_id(dev,
|
||||
ATOM_DEVICE_DFP2_SUPPORT,
|
||||
@ -1510,8 +1586,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
|
||||
ATOM_DEVICE_DFP2_SUPPORT |
|
||||
ATOM_DEVICE_CRT2_SUPPORT,
|
||||
DRM_MODE_CONNECTOR_DVII, &ddc_i2c,
|
||||
CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I);
|
||||
CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I,
|
||||
&hpd);
|
||||
/* TV - TV DAC */
|
||||
ddc_i2c.valid = false;
|
||||
hpd.hpd = RADEON_HPD_NONE;
|
||||
radeon_add_legacy_encoder(dev,
|
||||
radeon_get_encoder_id(dev,
|
||||
ATOM_DEVICE_TV1_SUPPORT,
|
||||
@ -1520,13 +1599,15 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
|
||||
radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_TV1_SUPPORT,
|
||||
DRM_MODE_CONNECTOR_SVIDEO,
|
||||
&ddc_i2c,
|
||||
CONNECTOR_OBJECT_ID_SVIDEO);
|
||||
CONNECTOR_OBJECT_ID_SVIDEO,
|
||||
&hpd);
|
||||
break;
|
||||
case CT_MINI_INTERNAL:
|
||||
DRM_INFO("Connector Table: %d (mini internal tmds)\n",
|
||||
rdev->mode_info.connector_table);
|
||||
/* DVI-I - tv dac, int tmds */
|
||||
ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
|
||||
ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC);
|
||||
hpd.hpd = RADEON_HPD_1; /* ??? */
|
||||
radeon_add_legacy_encoder(dev,
|
||||
radeon_get_encoder_id(dev,
|
||||
ATOM_DEVICE_DFP1_SUPPORT,
|
||||
@ -1541,8 +1622,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
|
||||
ATOM_DEVICE_DFP1_SUPPORT |
|
||||
ATOM_DEVICE_CRT2_SUPPORT,
|
||||
DRM_MODE_CONNECTOR_DVII, &ddc_i2c,
|
||||
CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I);
|
||||
CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I,
|
||||
&hpd);
|
||||
/* TV - TV DAC */
|
||||
ddc_i2c.valid = false;
|
||||
hpd.hpd = RADEON_HPD_NONE;
|
||||
radeon_add_legacy_encoder(dev,
|
||||
radeon_get_encoder_id(dev,
|
||||
ATOM_DEVICE_TV1_SUPPORT,
|
||||
@ -1551,13 +1635,15 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
|
||||
radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_TV1_SUPPORT,
|
||||
DRM_MODE_CONNECTOR_SVIDEO,
|
||||
&ddc_i2c,
|
||||
CONNECTOR_OBJECT_ID_SVIDEO);
|
||||
CONNECTOR_OBJECT_ID_SVIDEO,
|
||||
&hpd);
|
||||
break;
|
||||
case CT_IMAC_G5_ISIGHT:
|
||||
DRM_INFO("Connector Table: %d (imac g5 isight)\n",
|
||||
rdev->mode_info.connector_table);
|
||||
/* DVI-D - int tmds */
|
||||
ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_MONID);
|
||||
ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID);
|
||||
hpd.hpd = RADEON_HPD_1; /* ??? */
|
||||
radeon_add_legacy_encoder(dev,
|
||||
radeon_get_encoder_id(dev,
|
||||
ATOM_DEVICE_DFP1_SUPPORT,
|
||||
@ -1565,9 +1651,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
|
||||
ATOM_DEVICE_DFP1_SUPPORT);
|
||||
radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_DFP1_SUPPORT,
|
||||
DRM_MODE_CONNECTOR_DVID, &ddc_i2c,
|
||||
CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D);
|
||||
CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D,
|
||||
&hpd);
|
||||
/* VGA - tv dac */
|
||||
ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
|
||||
ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC);
|
||||
hpd.hpd = RADEON_HPD_NONE;
|
||||
radeon_add_legacy_encoder(dev,
|
||||
radeon_get_encoder_id(dev,
|
||||
ATOM_DEVICE_CRT2_SUPPORT,
|
||||
@ -1575,8 +1663,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
|
||||
ATOM_DEVICE_CRT2_SUPPORT);
|
||||
radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT2_SUPPORT,
|
||||
DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
|
||||
CONNECTOR_OBJECT_ID_VGA);
|
||||
CONNECTOR_OBJECT_ID_VGA,
|
||||
&hpd);
|
||||
/* TV - TV DAC */
|
||||
ddc_i2c.valid = false;
|
||||
hpd.hpd = RADEON_HPD_NONE;
|
||||
radeon_add_legacy_encoder(dev,
|
||||
radeon_get_encoder_id(dev,
|
||||
ATOM_DEVICE_TV1_SUPPORT,
|
||||
@ -1585,13 +1676,15 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
|
||||
radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
|
||||
DRM_MODE_CONNECTOR_SVIDEO,
|
||||
&ddc_i2c,
|
||||
CONNECTOR_OBJECT_ID_SVIDEO);
|
||||
CONNECTOR_OBJECT_ID_SVIDEO,
|
||||
&hpd);
|
||||
break;
|
||||
case CT_EMAC:
|
||||
DRM_INFO("Connector Table: %d (emac)\n",
|
||||
rdev->mode_info.connector_table);
|
||||
/* VGA - primary dac */
|
||||
ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
|
||||
ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
|
||||
hpd.hpd = RADEON_HPD_NONE;
|
||||
radeon_add_legacy_encoder(dev,
|
||||
radeon_get_encoder_id(dev,
|
||||
ATOM_DEVICE_CRT1_SUPPORT,
|
||||
@ -1599,9 +1692,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
|
||||
ATOM_DEVICE_CRT1_SUPPORT);
|
||||
radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_CRT1_SUPPORT,
|
||||
DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
|
||||
CONNECTOR_OBJECT_ID_VGA);
|
||||
CONNECTOR_OBJECT_ID_VGA,
|
||||
&hpd);
|
||||
/* VGA - tv dac */
|
||||
ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
|
||||
ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC);
|
||||
hpd.hpd = RADEON_HPD_NONE;
|
||||
radeon_add_legacy_encoder(dev,
|
||||
radeon_get_encoder_id(dev,
|
||||
ATOM_DEVICE_CRT2_SUPPORT,
|
||||
@ -1609,8 +1704,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
|
||||
ATOM_DEVICE_CRT2_SUPPORT);
|
||||
radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT2_SUPPORT,
|
||||
DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
|
||||
CONNECTOR_OBJECT_ID_VGA);
|
||||
CONNECTOR_OBJECT_ID_VGA,
|
||||
&hpd);
|
||||
/* TV - TV DAC */
|
||||
ddc_i2c.valid = false;
|
||||
hpd.hpd = RADEON_HPD_NONE;
|
||||
radeon_add_legacy_encoder(dev,
|
||||
radeon_get_encoder_id(dev,
|
||||
ATOM_DEVICE_TV1_SUPPORT,
|
||||
@ -1619,7 +1717,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
|
||||
radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
|
||||
DRM_MODE_CONNECTOR_SVIDEO,
|
||||
&ddc_i2c,
|
||||
CONNECTOR_OBJECT_ID_SVIDEO);
|
||||
CONNECTOR_OBJECT_ID_SVIDEO,
|
||||
&hpd);
|
||||
break;
|
||||
default:
|
||||
DRM_INFO("Connector table: %d (invalid)\n",
|
||||
@ -1636,7 +1735,8 @@ static bool radeon_apply_legacy_quirks(struct drm_device *dev,
|
||||
int bios_index,
|
||||
enum radeon_combios_connector
|
||||
*legacy_connector,
|
||||
struct radeon_i2c_bus_rec *ddc_i2c)
|
||||
struct radeon_i2c_bus_rec *ddc_i2c,
|
||||
struct radeon_hpd *hpd)
|
||||
{
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
|
||||
@ -1644,11 +1744,11 @@ static bool radeon_apply_legacy_quirks(struct drm_device *dev,
|
||||
if ((rdev->family == CHIP_RS400 ||
|
||||
rdev->family == CHIP_RS480) &&
|
||||
ddc_i2c->mask_clk_reg == RADEON_GPIO_CRT2_DDC)
|
||||
*ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_MONID);
|
||||
*ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID);
|
||||
else if ((rdev->family == CHIP_RS400 ||
|
||||
rdev->family == CHIP_RS480) &&
|
||||
ddc_i2c->mask_clk_reg == RADEON_GPIO_MONID) {
|
||||
ddc_i2c->valid = true;
|
||||
*ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIOPAD_MASK);
|
||||
ddc_i2c->mask_clk_mask = (0x20 << 8);
|
||||
ddc_i2c->mask_data_mask = 0x80;
|
||||
ddc_i2c->a_clk_mask = (0x20 << 8);
|
||||
@ -1657,20 +1757,12 @@ static bool radeon_apply_legacy_quirks(struct drm_device *dev,
|
||||
ddc_i2c->en_data_mask = 0x80;
|
||||
ddc_i2c->y_clk_mask = (0x20 << 8);
|
||||
ddc_i2c->y_data_mask = 0x80;
|
||||
ddc_i2c->mask_clk_reg = RADEON_GPIOPAD_MASK;
|
||||
ddc_i2c->mask_data_reg = RADEON_GPIOPAD_MASK;
|
||||
ddc_i2c->a_clk_reg = RADEON_GPIOPAD_A;
|
||||
ddc_i2c->a_data_reg = RADEON_GPIOPAD_A;
|
||||
ddc_i2c->en_clk_reg = RADEON_GPIOPAD_EN;
|
||||
ddc_i2c->en_data_reg = RADEON_GPIOPAD_EN;
|
||||
ddc_i2c->y_clk_reg = RADEON_GPIOPAD_Y;
|
||||
ddc_i2c->y_data_reg = RADEON_GPIOPAD_Y;
|
||||
}
|
||||
|
||||
/* R3xx+ chips don't have GPIO_CRT2_DDC gpio pad */
|
||||
if ((rdev->family >= CHIP_R300) &&
|
||||
ddc_i2c->mask_clk_reg == RADEON_GPIO_CRT2_DDC)
|
||||
*ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
|
||||
*ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC);
|
||||
|
||||
/* Certain IBM chipset RN50s have a BIOS reporting two VGAs,
|
||||
one with VGA DDC and one with CRT2 DDC. - kill the CRT2 DDC one */
|
||||
@ -1768,6 +1860,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
|
||||
enum radeon_combios_connector connector;
|
||||
int i = 0;
|
||||
struct radeon_i2c_bus_rec ddc_i2c;
|
||||
struct radeon_hpd hpd;
|
||||
|
||||
if (rdev->bios == NULL)
|
||||
return false;
|
||||
@ -1788,26 +1881,40 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
|
||||
switch (ddc_type) {
|
||||
case DDC_MONID:
|
||||
ddc_i2c =
|
||||
combios_setup_i2c_bus(RADEON_GPIO_MONID);
|
||||
combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID);
|
||||
break;
|
||||
case DDC_DVI:
|
||||
ddc_i2c =
|
||||
combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
|
||||
combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC);
|
||||
break;
|
||||
case DDC_VGA:
|
||||
ddc_i2c =
|
||||
combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
|
||||
combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
|
||||
break;
|
||||
case DDC_CRT2:
|
||||
ddc_i2c =
|
||||
combios_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
|
||||
combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (connector) {
|
||||
case CONNECTOR_PROPRIETARY_LEGACY:
|
||||
case CONNECTOR_DVI_I_LEGACY:
|
||||
case CONNECTOR_DVI_D_LEGACY:
|
||||
if ((tmp >> 4) & 0x1)
|
||||
hpd.hpd = RADEON_HPD_2;
|
||||
else
|
||||
hpd.hpd = RADEON_HPD_1;
|
||||
break;
|
||||
default:
|
||||
hpd.hpd = RADEON_HPD_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!radeon_apply_legacy_quirks(dev, i, &connector,
|
||||
&ddc_i2c))
|
||||
&ddc_i2c, &hpd))
|
||||
continue;
|
||||
|
||||
switch (connector) {
|
||||
@ -1824,7 +1931,8 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
|
||||
legacy_connector_convert
|
||||
[connector],
|
||||
&ddc_i2c,
|
||||
CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D);
|
||||
CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D,
|
||||
&hpd);
|
||||
break;
|
||||
case CONNECTOR_CRT_LEGACY:
|
||||
if (tmp & 0x1) {
|
||||
@ -1850,7 +1958,8 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
|
||||
legacy_connector_convert
|
||||
[connector],
|
||||
&ddc_i2c,
|
||||
CONNECTOR_OBJECT_ID_VGA);
|
||||
CONNECTOR_OBJECT_ID_VGA,
|
||||
&hpd);
|
||||
break;
|
||||
case CONNECTOR_DVI_I_LEGACY:
|
||||
devices = 0;
|
||||
@ -1896,7 +2005,8 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
|
||||
legacy_connector_convert
|
||||
[connector],
|
||||
&ddc_i2c,
|
||||
connector_object_id);
|
||||
connector_object_id,
|
||||
&hpd);
|
||||
break;
|
||||
case CONNECTOR_DVI_D_LEGACY:
|
||||
if ((tmp >> 4) & 0x1) {
|
||||
@ -1914,7 +2024,8 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
|
||||
legacy_connector_convert
|
||||
[connector],
|
||||
&ddc_i2c,
|
||||
connector_object_id);
|
||||
connector_object_id,
|
||||
&hpd);
|
||||
break;
|
||||
case CONNECTOR_CTV_LEGACY:
|
||||
case CONNECTOR_STV_LEGACY:
|
||||
@ -1929,7 +2040,8 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
|
||||
legacy_connector_convert
|
||||
[connector],
|
||||
&ddc_i2c,
|
||||
CONNECTOR_OBJECT_ID_SVIDEO);
|
||||
CONNECTOR_OBJECT_ID_SVIDEO,
|
||||
&hpd);
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unknown connector type: %d\n",
|
||||
@ -1955,14 +2067,16 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
|
||||
0),
|
||||
ATOM_DEVICE_DFP1_SUPPORT);
|
||||
|
||||
ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
|
||||
ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC);
|
||||
hpd.hpd = RADEON_HPD_NONE;
|
||||
radeon_add_legacy_connector(dev,
|
||||
0,
|
||||
ATOM_DEVICE_CRT1_SUPPORT |
|
||||
ATOM_DEVICE_DFP1_SUPPORT,
|
||||
DRM_MODE_CONNECTOR_DVII,
|
||||
&ddc_i2c,
|
||||
CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I);
|
||||
CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I,
|
||||
&hpd);
|
||||
} else {
|
||||
uint16_t crt_info =
|
||||
combios_get_table_offset(dev, COMBIOS_CRT_INFO_TABLE);
|
||||
@ -1973,13 +2087,15 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
|
||||
ATOM_DEVICE_CRT1_SUPPORT,
|
||||
1),
|
||||
ATOM_DEVICE_CRT1_SUPPORT);
|
||||
ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
|
||||
ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
|
||||
hpd.hpd = RADEON_HPD_NONE;
|
||||
radeon_add_legacy_connector(dev,
|
||||
0,
|
||||
ATOM_DEVICE_CRT1_SUPPORT,
|
||||
DRM_MODE_CONNECTOR_VGA,
|
||||
&ddc_i2c,
|
||||
CONNECTOR_OBJECT_ID_VGA);
|
||||
CONNECTOR_OBJECT_ID_VGA,
|
||||
&hpd);
|
||||
} else {
|
||||
DRM_DEBUG("No connector info found\n");
|
||||
return false;
|
||||
@ -2007,27 +2123,27 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
|
||||
case DDC_MONID:
|
||||
ddc_i2c =
|
||||
combios_setup_i2c_bus
|
||||
(RADEON_GPIO_MONID);
|
||||
(rdev, RADEON_GPIO_MONID);
|
||||
break;
|
||||
case DDC_DVI:
|
||||
ddc_i2c =
|
||||
combios_setup_i2c_bus
|
||||
(RADEON_GPIO_DVI_DDC);
|
||||
(rdev, RADEON_GPIO_DVI_DDC);
|
||||
break;
|
||||
case DDC_VGA:
|
||||
ddc_i2c =
|
||||
combios_setup_i2c_bus
|
||||
(RADEON_GPIO_VGA_DDC);
|
||||
(rdev, RADEON_GPIO_VGA_DDC);
|
||||
break;
|
||||
case DDC_CRT2:
|
||||
ddc_i2c =
|
||||
combios_setup_i2c_bus
|
||||
(RADEON_GPIO_CRT2_DDC);
|
||||
(rdev, RADEON_GPIO_CRT2_DDC);
|
||||
break;
|
||||
case DDC_LCD:
|
||||
ddc_i2c =
|
||||
combios_setup_i2c_bus
|
||||
(RADEON_LCD_GPIO_MASK);
|
||||
(rdev, RADEON_GPIOPAD_MASK);
|
||||
ddc_i2c.mask_clk_mask =
|
||||
RBIOS32(lcd_ddc_info + 3);
|
||||
ddc_i2c.mask_data_mask =
|
||||
@ -2048,7 +2164,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
|
||||
case DDC_GPIO:
|
||||
ddc_i2c =
|
||||
combios_setup_i2c_bus
|
||||
(RADEON_MDGPIO_EN_REG);
|
||||
(rdev, RADEON_MDGPIO_MASK);
|
||||
ddc_i2c.mask_clk_mask =
|
||||
RBIOS32(lcd_ddc_info + 3);
|
||||
ddc_i2c.mask_data_mask =
|
||||
@ -2074,12 +2190,14 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
|
||||
} else
|
||||
ddc_i2c.valid = false;
|
||||
|
||||
hpd.hpd = RADEON_HPD_NONE;
|
||||
radeon_add_legacy_connector(dev,
|
||||
5,
|
||||
ATOM_DEVICE_LCD1_SUPPORT,
|
||||
DRM_MODE_CONNECTOR_LVDS,
|
||||
&ddc_i2c,
|
||||
CONNECTOR_OBJECT_ID_LVDS);
|
||||
CONNECTOR_OBJECT_ID_LVDS,
|
||||
&hpd);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2090,6 +2208,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
|
||||
if (tv_info) {
|
||||
if (RBIOS8(tv_info + 6) == 'T') {
|
||||
if (radeon_apply_legacy_tv_quirks(dev)) {
|
||||
hpd.hpd = RADEON_HPD_NONE;
|
||||
radeon_add_legacy_encoder(dev,
|
||||
radeon_get_encoder_id
|
||||
(dev,
|
||||
@ -2100,7 +2219,8 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
|
||||
ATOM_DEVICE_TV1_SUPPORT,
|
||||
DRM_MODE_CONNECTOR_SVIDEO,
|
||||
&ddc_i2c,
|
||||
CONNECTOR_OBJECT_ID_SVIDEO);
|
||||
CONNECTOR_OBJECT_ID_SVIDEO,
|
||||
&hpd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +40,26 @@ radeon_atombios_connected_scratch_regs(struct drm_connector *connector,
|
||||
struct drm_encoder *encoder,
|
||||
bool connected);
|
||||
|
||||
void radeon_connector_hotplug(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
|
||||
|
||||
if (radeon_connector->hpd.hpd != RADEON_HPD_NONE)
|
||||
radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
|
||||
|
||||
if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) {
|
||||
if (radeon_dp_getsinktype(radeon_connector) == CONNECTOR_OBJECT_ID_DISPLAYPORT) {
|
||||
if (radeon_dp_needs_link_train(radeon_connector)) {
|
||||
if (connector->encoder)
|
||||
dp_link_train(connector->encoder, connector);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void radeon_property_change_mode(struct drm_encoder *encoder)
|
||||
{
|
||||
struct drm_crtc *crtc = encoder->crtc;
|
||||
@ -896,6 +916,91 @@ struct drm_connector_funcs radeon_dvi_connector_funcs = {
|
||||
.force = radeon_dvi_force,
|
||||
};
|
||||
|
||||
static void radeon_dp_connector_destroy(struct drm_connector *connector)
|
||||
{
|
||||
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
|
||||
struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
|
||||
|
||||
if (radeon_connector->ddc_bus)
|
||||
radeon_i2c_destroy(radeon_connector->ddc_bus);
|
||||
if (radeon_connector->edid)
|
||||
kfree(radeon_connector->edid);
|
||||
if (radeon_dig_connector->dp_i2c_bus)
|
||||
radeon_i2c_destroy(radeon_dig_connector->dp_i2c_bus);
|
||||
kfree(radeon_connector->con_priv);
|
||||
drm_sysfs_connector_remove(connector);
|
||||
drm_connector_cleanup(connector);
|
||||
kfree(connector);
|
||||
}
|
||||
|
||||
static int radeon_dp_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
|
||||
int ret;
|
||||
|
||||
ret = radeon_ddc_get_modes(radeon_connector);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static enum drm_connector_status radeon_dp_detect(struct drm_connector *connector)
|
||||
{
|
||||
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
|
||||
enum drm_connector_status ret = connector_status_disconnected;
|
||||
struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
|
||||
u8 sink_type;
|
||||
|
||||
if (radeon_connector->edid) {
|
||||
kfree(radeon_connector->edid);
|
||||
radeon_connector->edid = NULL;
|
||||
}
|
||||
|
||||
sink_type = radeon_dp_getsinktype(radeon_connector);
|
||||
if (sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) {
|
||||
if (radeon_dp_getdpcd(radeon_connector)) {
|
||||
radeon_dig_connector->dp_sink_type = sink_type;
|
||||
ret = connector_status_connected;
|
||||
}
|
||||
} else {
|
||||
radeon_i2c_do_lock(radeon_connector->ddc_bus, 1);
|
||||
if (radeon_ddc_probe(radeon_connector)) {
|
||||
radeon_dig_connector->dp_sink_type = sink_type;
|
||||
ret = connector_status_connected;
|
||||
}
|
||||
radeon_i2c_do_lock(radeon_connector->ddc_bus, 0);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int radeon_dp_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
|
||||
struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
|
||||
|
||||
/* XXX check mode bandwidth */
|
||||
|
||||
if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT)
|
||||
return radeon_dp_mode_valid_helper(radeon_connector, mode);
|
||||
else
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
struct drm_connector_helper_funcs radeon_dp_connector_helper_funcs = {
|
||||
.get_modes = radeon_dp_get_modes,
|
||||
.mode_valid = radeon_dp_mode_valid,
|
||||
.best_encoder = radeon_dvi_encoder,
|
||||
};
|
||||
|
||||
struct drm_connector_funcs radeon_dp_connector_funcs = {
|
||||
.dpms = drm_helper_connector_dpms,
|
||||
.detect = radeon_dp_detect,
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.set_property = radeon_connector_set_property,
|
||||
.destroy = radeon_dp_connector_destroy,
|
||||
.force = radeon_dvi_force,
|
||||
};
|
||||
|
||||
void
|
||||
radeon_add_atom_connector(struct drm_device *dev,
|
||||
uint32_t connector_id,
|
||||
@ -904,7 +1009,8 @@ radeon_add_atom_connector(struct drm_device *dev,
|
||||
struct radeon_i2c_bus_rec *i2c_bus,
|
||||
bool linkb,
|
||||
uint32_t igp_lane_info,
|
||||
uint16_t connector_object_id)
|
||||
uint16_t connector_object_id,
|
||||
struct radeon_hpd *hpd)
|
||||
{
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct drm_connector *connector;
|
||||
@ -944,6 +1050,7 @@ radeon_add_atom_connector(struct drm_device *dev,
|
||||
radeon_connector->devices = supported_device;
|
||||
radeon_connector->shared_ddc = shared_ddc;
|
||||
radeon_connector->connector_object_id = connector_object_id;
|
||||
radeon_connector->hpd = *hpd;
|
||||
switch (connector_type) {
|
||||
case DRM_MODE_CONNECTOR_VGA:
|
||||
drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
|
||||
@ -1030,10 +1137,12 @@ radeon_add_atom_connector(struct drm_device *dev,
|
||||
radeon_dig_connector->linkb = linkb;
|
||||
radeon_dig_connector->igp_lane_info = igp_lane_info;
|
||||
radeon_connector->con_priv = radeon_dig_connector;
|
||||
drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type);
|
||||
ret = drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
|
||||
drm_connector_init(dev, &radeon_connector->base, &radeon_dp_connector_funcs, connector_type);
|
||||
ret = drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs);
|
||||
if (ret)
|
||||
goto failed;
|
||||
/* add DP i2c bus */
|
||||
radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch");
|
||||
if (i2c_bus->valid) {
|
||||
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DP");
|
||||
if (!radeon_connector->ddc_bus)
|
||||
@ -1099,7 +1208,8 @@ radeon_add_legacy_connector(struct drm_device *dev,
|
||||
uint32_t supported_device,
|
||||
int connector_type,
|
||||
struct radeon_i2c_bus_rec *i2c_bus,
|
||||
uint16_t connector_object_id)
|
||||
uint16_t connector_object_id,
|
||||
struct radeon_hpd *hpd)
|
||||
{
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct drm_connector *connector;
|
||||
@ -1129,6 +1239,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
|
||||
radeon_connector->connector_id = connector_id;
|
||||
radeon_connector->devices = supported_device;
|
||||
radeon_connector->connector_object_id = connector_object_id;
|
||||
radeon_connector->hpd = *hpd;
|
||||
switch (connector_type) {
|
||||
case DRM_MODE_CONNECTOR_VGA:
|
||||
drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
|
||||
|
@ -481,11 +481,13 @@ int radeon_atombios_init(struct radeon_device *rdev)
|
||||
|
||||
rdev->mode_info.atom_context = atom_parse(atom_card_info, rdev->bios);
|
||||
radeon_atom_initialize_bios_scratch_regs(rdev->ddev);
|
||||
atom_allocate_fb_scratch(rdev->mode_info.atom_context);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void radeon_atombios_fini(struct radeon_device *rdev)
|
||||
{
|
||||
kfree(rdev->mode_info.atom_context->scratch);
|
||||
kfree(rdev->mode_info.atom_context);
|
||||
kfree(rdev->mode_info.atom_card_info);
|
||||
}
|
||||
@ -568,6 +570,11 @@ int radeon_device_init(struct radeon_device *rdev,
|
||||
rwlock_init(&rdev->fence_drv.lock);
|
||||
INIT_LIST_HEAD(&rdev->gem.objects);
|
||||
|
||||
/* setup workqueue */
|
||||
rdev->wq = create_workqueue("radeon");
|
||||
if (rdev->wq == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Set asic functions */
|
||||
r = radeon_asic_init(rdev);
|
||||
if (r) {
|
||||
@ -641,6 +648,7 @@ void radeon_device_fini(struct radeon_device *rdev)
|
||||
DRM_INFO("radeon: finishing device.\n");
|
||||
rdev->shutdown = true;
|
||||
radeon_fini(rdev);
|
||||
destroy_workqueue(rdev->wq);
|
||||
vga_client_register(rdev->pdev, NULL, NULL, NULL);
|
||||
iounmap(rdev->rmmio);
|
||||
rdev->rmmio = NULL;
|
||||
@ -687,6 +695,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
|
||||
radeon_save_bios_scratch_regs(rdev);
|
||||
|
||||
radeon_suspend(rdev);
|
||||
radeon_hpd_fini(rdev);
|
||||
/* evict remaining vram memory */
|
||||
radeon_bo_evict_vram(rdev);
|
||||
|
||||
@ -721,6 +730,8 @@ int radeon_resume_kms(struct drm_device *dev)
|
||||
fb_set_suspend(rdev->fbdev_info, 0);
|
||||
release_console_sem();
|
||||
|
||||
/* reset hpd state */
|
||||
radeon_hpd_init(rdev);
|
||||
/* blat the mode back in */
|
||||
drm_helper_resume_force_mode(dev);
|
||||
return 0;
|
||||
|
@ -250,6 +250,16 @@ static const char *connector_names[13] = {
|
||||
"HDMI-B",
|
||||
};
|
||||
|
||||
static const char *hpd_names[7] = {
|
||||
"NONE",
|
||||
"HPD1",
|
||||
"HPD2",
|
||||
"HPD3",
|
||||
"HPD4",
|
||||
"HPD5",
|
||||
"HPD6",
|
||||
};
|
||||
|
||||
static void radeon_print_display_setup(struct drm_device *dev)
|
||||
{
|
||||
struct drm_connector *connector;
|
||||
@ -264,6 +274,8 @@ static void radeon_print_display_setup(struct drm_device *dev)
|
||||
radeon_connector = to_radeon_connector(connector);
|
||||
DRM_INFO("Connector %d:\n", i);
|
||||
DRM_INFO(" %s\n", connector_names[connector->connector_type]);
|
||||
if (radeon_connector->hpd.hpd != RADEON_HPD_NONE)
|
||||
DRM_INFO(" %s\n", hpd_names[radeon_connector->hpd.hpd]);
|
||||
if (radeon_connector->ddc_bus)
|
||||
DRM_INFO(" DDC: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
|
||||
radeon_connector->ddc_bus->rec.mask_clk_reg,
|
||||
@ -337,6 +349,11 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) {
|
||||
struct radeon_connector_atom_dig *dig = radeon_connector->con_priv;
|
||||
if (dig->dp_i2c_bus)
|
||||
radeon_connector->edid = drm_get_edid(&radeon_connector->base, &dig->dp_i2c_bus->adapter);
|
||||
}
|
||||
if (!radeon_connector->ddc_bus)
|
||||
return -1;
|
||||
if (!radeon_connector->edid) {
|
||||
@ -724,6 +741,8 @@ int radeon_modeset_init(struct radeon_device *rdev)
|
||||
if (!ret) {
|
||||
return ret;
|
||||
}
|
||||
/* initialize hpd */
|
||||
radeon_hpd_init(rdev);
|
||||
drm_helper_initial_config(rdev->ddev);
|
||||
return 0;
|
||||
}
|
||||
@ -731,6 +750,7 @@ int radeon_modeset_init(struct radeon_device *rdev)
|
||||
void radeon_modeset_fini(struct radeon_device *rdev)
|
||||
{
|
||||
if (rdev->mode_info.mode_config_initialized) {
|
||||
radeon_hpd_fini(rdev);
|
||||
drm_mode_config_cleanup(rdev->ddev);
|
||||
rdev->mode_info.mode_config_initialized = false;
|
||||
}
|
||||
|
@ -250,6 +250,12 @@ static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
|
||||
}
|
||||
}
|
||||
|
||||
if (ASIC_IS_DCE3(rdev) &&
|
||||
(radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT))) {
|
||||
struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
|
||||
radeon_dp_set_link_config(connector, mode);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -554,6 +560,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
|
||||
{
|
||||
struct drm_connector *connector;
|
||||
struct radeon_connector *radeon_connector;
|
||||
struct radeon_connector_atom_dig *radeon_dig_connector;
|
||||
|
||||
connector = radeon_get_connector_for_encoder(encoder);
|
||||
if (!connector)
|
||||
@ -583,10 +590,10 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
|
||||
return ATOM_ENCODER_MODE_LVDS;
|
||||
break;
|
||||
case DRM_MODE_CONNECTOR_DisplayPort:
|
||||
/*if (radeon_output->MonType == MT_DP)
|
||||
return ATOM_ENCODER_MODE_DP;
|
||||
else*/
|
||||
if (drm_detect_hdmi_monitor(radeon_connector->edid))
|
||||
radeon_dig_connector = radeon_connector->con_priv;
|
||||
if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT)
|
||||
return ATOM_ENCODER_MODE_DP;
|
||||
else if (drm_detect_hdmi_monitor(radeon_connector->edid))
|
||||
return ATOM_ENCODER_MODE_HDMI;
|
||||
else
|
||||
return ATOM_ENCODER_MODE_DVI;
|
||||
@ -605,6 +612,30 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* DIG Encoder/Transmitter Setup
|
||||
*
|
||||
* DCE 3.0/3.1
|
||||
* - 2 DIG transmitter blocks. UNIPHY (links A and B) and LVTMA.
|
||||
* Supports up to 3 digital outputs
|
||||
* - 2 DIG encoder blocks.
|
||||
* DIG1 can drive UNIPHY link A or link B
|
||||
* DIG2 can drive UNIPHY link B or LVTMA
|
||||
*
|
||||
* DCE 3.2
|
||||
* - 3 DIG transmitter blocks. UNIPHY0/1/2 (links A and B).
|
||||
* Supports up to 5 digital outputs
|
||||
* - 2 DIG encoder blocks.
|
||||
* DIG1/2 can drive UNIPHY0/1/2 link A or link B
|
||||
*
|
||||
* Routing
|
||||
* crtc -> dig encoder -> UNIPHY/LVTMA (1 or 2 links)
|
||||
* Examples:
|
||||
* crtc0 -> dig2 -> LVTMA links A+B -> TMDS/HDMI
|
||||
* crtc1 -> dig1 -> UNIPHY0 link B -> DP
|
||||
* crtc0 -> dig1 -> UNIPHY2 link A -> LVDS
|
||||
* crtc1 -> dig2 -> UNIPHY1 link B+A -> TMDS/HDMI
|
||||
*/
|
||||
static void
|
||||
atombios_dig_encoder_setup(struct drm_encoder *encoder, int action)
|
||||
{
|
||||
@ -646,10 +677,17 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action)
|
||||
} else {
|
||||
switch (radeon_encoder->encoder_id) {
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
|
||||
index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
|
||||
/* XXX doesn't really matter which dig encoder we pick as long as it's
|
||||
* not already in use
|
||||
*/
|
||||
if (dig_connector->linkb)
|
||||
index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
|
||||
else
|
||||
index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
|
||||
num = 1;
|
||||
break;
|
||||
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
|
||||
/* Only dig2 encoder can drive LVTMA */
|
||||
index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
|
||||
num = 2;
|
||||
break;
|
||||
@ -684,19 +722,22 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action)
|
||||
}
|
||||
}
|
||||
|
||||
if (radeon_encoder->pixel_clock > 165000) {
|
||||
args.ucConfig |= ATOM_ENCODER_CONFIG_LINKA_B;
|
||||
args.ucLaneNum = 8;
|
||||
} else {
|
||||
if (dig_connector->linkb)
|
||||
args.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
|
||||
else
|
||||
args.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
|
||||
args.ucLaneNum = 4;
|
||||
}
|
||||
|
||||
args.ucEncoderMode = atombios_get_encoder_mode(encoder);
|
||||
|
||||
if (args.ucEncoderMode == ATOM_ENCODER_MODE_DP) {
|
||||
if (dig_connector->dp_clock == 270000)
|
||||
args.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
|
||||
args.ucLaneNum = dig_connector->dp_lane_count;
|
||||
} else if (radeon_encoder->pixel_clock > 165000)
|
||||
args.ucLaneNum = 8;
|
||||
else
|
||||
args.ucLaneNum = 4;
|
||||
|
||||
if (dig_connector->linkb)
|
||||
args.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
|
||||
else
|
||||
args.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
|
||||
|
||||
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
|
||||
|
||||
}
|
||||
@ -706,8 +747,8 @@ union dig_transmitter_control {
|
||||
DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2;
|
||||
};
|
||||
|
||||
static void
|
||||
atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action)
|
||||
void
|
||||
atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
@ -719,6 +760,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action)
|
||||
struct drm_connector *connector;
|
||||
struct radeon_connector *radeon_connector;
|
||||
struct radeon_connector_atom_dig *dig_connector;
|
||||
bool is_dp = false;
|
||||
|
||||
connector = radeon_get_connector_for_encoder(encoder);
|
||||
if (!connector)
|
||||
@ -736,6 +778,9 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action)
|
||||
|
||||
dig_connector = radeon_connector->con_priv;
|
||||
|
||||
if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP)
|
||||
is_dp = true;
|
||||
|
||||
memset(&args, 0, sizeof(args));
|
||||
|
||||
if (ASIC_IS_DCE32(rdev))
|
||||
@ -756,17 +801,23 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action)
|
||||
args.v1.ucAction = action;
|
||||
if (action == ATOM_TRANSMITTER_ACTION_INIT) {
|
||||
args.v1.usInitInfo = radeon_connector->connector_object_id;
|
||||
} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
|
||||
args.v1.asMode.ucLaneSel = lane_num;
|
||||
args.v1.asMode.ucLaneSet = lane_set;
|
||||
} else {
|
||||
if (radeon_encoder->pixel_clock > 165000)
|
||||
if (is_dp)
|
||||
args.v1.usPixelClock =
|
||||
cpu_to_le16(dig_connector->dp_clock / 10);
|
||||
else if (radeon_encoder->pixel_clock > 165000)
|
||||
args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
|
||||
else
|
||||
args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
|
||||
}
|
||||
if (ASIC_IS_DCE32(rdev)) {
|
||||
if (radeon_encoder->pixel_clock > 165000)
|
||||
args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
|
||||
if (dig->dig_block)
|
||||
args.v2.acConfig.ucEncoderSel = 1;
|
||||
if (dig_connector->linkb)
|
||||
args.v2.acConfig.ucLinkSel = 1;
|
||||
|
||||
switch (radeon_encoder->encoder_id) {
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
|
||||
@ -783,7 +834,9 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action)
|
||||
break;
|
||||
}
|
||||
|
||||
if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
|
||||
if (is_dp)
|
||||
args.v2.acConfig.fCoherentMode = 1;
|
||||
else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
|
||||
if (dig->coherent_mode)
|
||||
args.v2.acConfig.fCoherentMode = 1;
|
||||
}
|
||||
@ -792,17 +845,20 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action)
|
||||
|
||||
switch (radeon_encoder->encoder_id) {
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
|
||||
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
|
||||
/* XXX doesn't really matter which dig encoder we pick as long as it's
|
||||
* not already in use
|
||||
*/
|
||||
if (dig_connector->linkb)
|
||||
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
|
||||
else
|
||||
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
|
||||
if (rdev->flags & RADEON_IS_IGP) {
|
||||
if (radeon_encoder->pixel_clock > 165000) {
|
||||
args.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK |
|
||||
ATOM_TRANSMITTER_CONFIG_LINKA_B);
|
||||
if (dig_connector->igp_lane_info & 0x3)
|
||||
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7;
|
||||
else if (dig_connector->igp_lane_info & 0xc)
|
||||
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15;
|
||||
} else {
|
||||
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA;
|
||||
if (dig_connector->igp_lane_info & 0x1)
|
||||
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
|
||||
else if (dig_connector->igp_lane_info & 0x2)
|
||||
@ -812,35 +868,25 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action)
|
||||
else if (dig_connector->igp_lane_info & 0x8)
|
||||
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15;
|
||||
}
|
||||
} else {
|
||||
if (radeon_encoder->pixel_clock > 165000)
|
||||
args.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK |
|
||||
ATOM_TRANSMITTER_CONFIG_LINKA_B |
|
||||
ATOM_TRANSMITTER_CONFIG_LANE_0_7);
|
||||
else {
|
||||
if (dig_connector->linkb)
|
||||
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB | ATOM_TRANSMITTER_CONFIG_LANE_0_3;
|
||||
else
|
||||
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA | ATOM_TRANSMITTER_CONFIG_LANE_0_3;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
|
||||
/* Only dig2 encoder can drive LVTMA */
|
||||
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
|
||||
if (radeon_encoder->pixel_clock > 165000)
|
||||
args.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK |
|
||||
ATOM_TRANSMITTER_CONFIG_LINKA_B |
|
||||
ATOM_TRANSMITTER_CONFIG_LANE_0_7);
|
||||
else {
|
||||
if (dig_connector->linkb)
|
||||
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB | ATOM_TRANSMITTER_CONFIG_LANE_0_3;
|
||||
else
|
||||
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA | ATOM_TRANSMITTER_CONFIG_LANE_0_3;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
|
||||
if (radeon_encoder->pixel_clock > 165000)
|
||||
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK;
|
||||
|
||||
if (dig_connector->linkb)
|
||||
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB;
|
||||
else
|
||||
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA;
|
||||
|
||||
if (is_dp)
|
||||
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
|
||||
else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
|
||||
if (dig->coherent_mode)
|
||||
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
|
||||
}
|
||||
@ -950,12 +996,16 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
|
||||
if (is_dig) {
|
||||
switch (mode) {
|
||||
case DRM_MODE_DPMS_ON:
|
||||
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT);
|
||||
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
|
||||
{
|
||||
struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
|
||||
dp_link_train(encoder, connector);
|
||||
}
|
||||
break;
|
||||
case DRM_MODE_DPMS_STANDBY:
|
||||
case DRM_MODE_DPMS_SUSPEND:
|
||||
case DRM_MODE_DPMS_OFF:
|
||||
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT);
|
||||
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@ -1057,13 +1107,33 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder)
|
||||
args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
|
||||
else
|
||||
args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
|
||||
} else
|
||||
args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
|
||||
} else {
|
||||
struct drm_connector *connector;
|
||||
struct radeon_connector *radeon_connector;
|
||||
struct radeon_connector_atom_dig *dig_connector;
|
||||
|
||||
connector = radeon_get_connector_for_encoder(encoder);
|
||||
if (!connector)
|
||||
return;
|
||||
radeon_connector = to_radeon_connector(connector);
|
||||
if (!radeon_connector->con_priv)
|
||||
return;
|
||||
dig_connector = radeon_connector->con_priv;
|
||||
|
||||
/* XXX doesn't really matter which dig encoder we pick as long as it's
|
||||
* not already in use
|
||||
*/
|
||||
if (dig_connector->linkb)
|
||||
args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
|
||||
else
|
||||
args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
|
||||
}
|
||||
break;
|
||||
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
|
||||
args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID;
|
||||
break;
|
||||
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
|
||||
/* Only dig2 encoder can drive LVTMA */
|
||||
args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
|
||||
break;
|
||||
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
|
||||
@ -1136,11 +1206,14 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
|
||||
|
||||
if (radeon_encoder->enc_priv) {
|
||||
struct radeon_encoder_atom_dig *dig;
|
||||
if (radeon_encoder->active_device &
|
||||
(ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) {
|
||||
if (radeon_encoder->enc_priv) {
|
||||
struct radeon_encoder_atom_dig *dig;
|
||||
|
||||
dig = radeon_encoder->enc_priv;
|
||||
dig->dig_block = radeon_crtc->crtc_id;
|
||||
dig = radeon_encoder->enc_priv;
|
||||
dig->dig_block = radeon_crtc->crtc_id;
|
||||
}
|
||||
}
|
||||
radeon_encoder->pixel_clock = adjusted_mode->clock;
|
||||
|
||||
@ -1166,14 +1239,14 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
|
||||
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
|
||||
/* disable the encoder and transmitter */
|
||||
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE);
|
||||
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
|
||||
atombios_dig_encoder_setup(encoder, ATOM_DISABLE);
|
||||
|
||||
/* setup and enable the encoder and transmitter */
|
||||
atombios_dig_encoder_setup(encoder, ATOM_ENABLE);
|
||||
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT);
|
||||
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP);
|
||||
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE);
|
||||
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0);
|
||||
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
|
||||
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
|
||||
break;
|
||||
case ENCODER_OBJECT_ID_INTERNAL_DDI:
|
||||
atombios_ddia_setup(encoder, ATOM_ENABLE);
|
||||
|
@ -69,13 +69,15 @@ void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state)
|
||||
* holds the i2c port in a bad state - switch hw i2c away before
|
||||
* doing DDC - do this for all r200s/r300s/r400s for safety sake
|
||||
*/
|
||||
if ((rdev->family >= CHIP_R200) && !ASIC_IS_AVIVO(rdev)) {
|
||||
if (rec->a_clk_reg == RADEON_GPIO_MONID) {
|
||||
WREG32(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST |
|
||||
R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1)));
|
||||
} else {
|
||||
WREG32(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST |
|
||||
R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3)));
|
||||
if (rec->hw_capable) {
|
||||
if ((rdev->family >= CHIP_R200) && !ASIC_IS_AVIVO(rdev)) {
|
||||
if (rec->a_clk_reg == RADEON_GPIO_MONID) {
|
||||
WREG32(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST |
|
||||
R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1)));
|
||||
} else {
|
||||
WREG32(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST |
|
||||
R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -86,6 +88,12 @@ void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state)
|
||||
temp = RREG32(rec->a_data_reg) & ~rec->a_data_mask;
|
||||
WREG32(rec->a_data_reg, temp);
|
||||
|
||||
/* set the pins to input */
|
||||
temp = RREG32(rec->en_clk_reg) & ~rec->en_clk_mask;
|
||||
WREG32(rec->en_clk_reg, temp);
|
||||
|
||||
temp = RREG32(rec->en_data_reg) & ~rec->en_data_mask;
|
||||
WREG32(rec->en_data_reg, temp);
|
||||
|
||||
/* mask the gpio pins for software use */
|
||||
temp = RREG32(rec->mask_clk_reg);
|
||||
@ -172,20 +180,19 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
|
||||
return NULL;
|
||||
|
||||
i2c->adapter.owner = THIS_MODULE;
|
||||
i2c->adapter.algo_data = &i2c->algo;
|
||||
i2c->dev = dev;
|
||||
i2c->algo.setsda = set_data;
|
||||
i2c->algo.setscl = set_clock;
|
||||
i2c->algo.getsda = get_data;
|
||||
i2c->algo.getscl = get_clock;
|
||||
i2c->algo.udelay = 20;
|
||||
i2c_set_adapdata(&i2c->adapter, i2c);
|
||||
i2c->adapter.algo_data = &i2c->algo.bit;
|
||||
i2c->algo.bit.setsda = set_data;
|
||||
i2c->algo.bit.setscl = set_clock;
|
||||
i2c->algo.bit.getsda = get_data;
|
||||
i2c->algo.bit.getscl = get_clock;
|
||||
i2c->algo.bit.udelay = 20;
|
||||
/* vesa says 2.2 ms is enough, 1 jiffy doesn't seem to always
|
||||
* make this, 2 jiffies is a lot more reliable */
|
||||
i2c->algo.timeout = 2;
|
||||
i2c->algo.data = i2c;
|
||||
i2c->algo.bit.timeout = 2;
|
||||
i2c->algo.bit.data = i2c;
|
||||
i2c->rec = *rec;
|
||||
i2c_set_adapdata(&i2c->adapter, i2c);
|
||||
|
||||
ret = i2c_bit_add_bus(&i2c->adapter);
|
||||
if (ret) {
|
||||
DRM_INFO("Failed to register i2c %s\n", name);
|
||||
@ -199,6 +206,38 @@ out_free:
|
||||
|
||||
}
|
||||
|
||||
struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev,
|
||||
struct radeon_i2c_bus_rec *rec,
|
||||
const char *name)
|
||||
{
|
||||
struct radeon_i2c_chan *i2c;
|
||||
int ret;
|
||||
|
||||
i2c = kzalloc(sizeof(struct radeon_i2c_chan), GFP_KERNEL);
|
||||
if (i2c == NULL)
|
||||
return NULL;
|
||||
|
||||
i2c->rec = *rec;
|
||||
i2c->adapter.owner = THIS_MODULE;
|
||||
i2c->dev = dev;
|
||||
i2c_set_adapdata(&i2c->adapter, i2c);
|
||||
i2c->adapter.algo_data = &i2c->algo.dp;
|
||||
i2c->algo.dp.aux_ch = radeon_dp_i2c_aux_ch;
|
||||
i2c->algo.dp.address = 0;
|
||||
ret = i2c_dp_aux_add_bus(&i2c->adapter);
|
||||
if (ret) {
|
||||
DRM_INFO("Failed to register i2c %s\n", name);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
return i2c;
|
||||
out_free:
|
||||
kfree(i2c);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void radeon_i2c_destroy(struct radeon_i2c_chan *i2c)
|
||||
{
|
||||
if (!i2c)
|
||||
|
@ -39,11 +39,32 @@ irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS)
|
||||
return radeon_irq_process(rdev);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle hotplug events outside the interrupt handler proper.
|
||||
*/
|
||||
static void radeon_hotplug_work_func(struct work_struct *work)
|
||||
{
|
||||
struct radeon_device *rdev = container_of(work, struct radeon_device,
|
||||
hotplug_work);
|
||||
struct drm_device *dev = rdev->ddev;
|
||||
struct drm_mode_config *mode_config = &dev->mode_config;
|
||||
struct drm_connector *connector;
|
||||
|
||||
if (mode_config->num_connector) {
|
||||
list_for_each_entry(connector, &mode_config->connector_list, head)
|
||||
radeon_connector_hotplug(connector);
|
||||
}
|
||||
/* Just fire off a uevent and let userspace tell us what to do */
|
||||
drm_sysfs_hotplug_event(dev);
|
||||
}
|
||||
|
||||
void radeon_driver_irq_preinstall_kms(struct drm_device *dev)
|
||||
{
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
unsigned i;
|
||||
|
||||
INIT_WORK(&rdev->hotplug_work, radeon_hotplug_work_func);
|
||||
|
||||
/* Disable *all* interrupts */
|
||||
rdev->irq.sw_int = false;
|
||||
for (i = 0; i < 2; i++) {
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include <drm_crtc.h>
|
||||
#include <drm_mode.h>
|
||||
#include <drm_edid.h>
|
||||
#include <drm_dp_helper.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-id.h>
|
||||
#include <linux/i2c-algo-bit.h>
|
||||
@ -105,6 +106,13 @@ enum radeon_tv_std {
|
||||
*/
|
||||
struct radeon_i2c_bus_rec {
|
||||
bool valid;
|
||||
/* id used by atom */
|
||||
uint8_t i2c_id;
|
||||
/* can be used with hw i2c engine */
|
||||
bool hw_capable;
|
||||
/* uses multi-media i2c engine */
|
||||
bool mm_i2c;
|
||||
/* regs and bits */
|
||||
uint32_t mask_clk_reg;
|
||||
uint32_t mask_data_reg;
|
||||
uint32_t a_clk_reg;
|
||||
@ -164,9 +172,12 @@ struct radeon_pll {
|
||||
};
|
||||
|
||||
struct radeon_i2c_chan {
|
||||
struct drm_device *dev;
|
||||
struct i2c_adapter adapter;
|
||||
struct i2c_algo_bit_data algo;
|
||||
struct drm_device *dev;
|
||||
union {
|
||||
struct i2c_algo_dp_aux_data dp;
|
||||
struct i2c_algo_bit_data bit;
|
||||
} algo;
|
||||
struct radeon_i2c_bus_rec rec;
|
||||
};
|
||||
|
||||
@ -328,6 +339,35 @@ struct radeon_encoder {
|
||||
struct radeon_connector_atom_dig {
|
||||
uint32_t igp_lane_info;
|
||||
bool linkb;
|
||||
/* displayport */
|
||||
struct radeon_i2c_chan *dp_i2c_bus;
|
||||
u8 dpcd[8];
|
||||
u8 dp_sink_type;
|
||||
int dp_clock;
|
||||
int dp_lane_count;
|
||||
};
|
||||
|
||||
struct radeon_gpio_rec {
|
||||
bool valid;
|
||||
u8 id;
|
||||
u32 reg;
|
||||
u32 mask;
|
||||
};
|
||||
|
||||
enum radeon_hpd_id {
|
||||
RADEON_HPD_NONE = 0,
|
||||
RADEON_HPD_1,
|
||||
RADEON_HPD_2,
|
||||
RADEON_HPD_3,
|
||||
RADEON_HPD_4,
|
||||
RADEON_HPD_5,
|
||||
RADEON_HPD_6,
|
||||
};
|
||||
|
||||
struct radeon_hpd {
|
||||
enum radeon_hpd_id hpd;
|
||||
u8 plugged_state;
|
||||
struct radeon_gpio_rec gpio;
|
||||
};
|
||||
|
||||
struct radeon_connector {
|
||||
@ -344,6 +384,7 @@ struct radeon_connector {
|
||||
void *con_priv;
|
||||
bool dac_load_detect;
|
||||
uint16_t connector_object_id;
|
||||
struct radeon_hpd hpd;
|
||||
};
|
||||
|
||||
struct radeon_framebuffer {
|
||||
@ -351,6 +392,25 @@ struct radeon_framebuffer {
|
||||
struct drm_gem_object *obj;
|
||||
};
|
||||
|
||||
extern void radeon_connector_hotplug(struct drm_connector *connector);
|
||||
extern bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector);
|
||||
extern int radeon_dp_mode_valid_helper(struct radeon_connector *radeon_connector,
|
||||
struct drm_display_mode *mode);
|
||||
extern void radeon_dp_set_link_config(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode);
|
||||
extern void dp_link_train(struct drm_encoder *encoder,
|
||||
struct drm_connector *connector);
|
||||
extern u8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector);
|
||||
extern bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector);
|
||||
extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder,
|
||||
int action, uint8_t lane_num,
|
||||
uint8_t lane_set);
|
||||
extern int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
|
||||
uint8_t write_byte, uint8_t *read_byte);
|
||||
|
||||
extern struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev,
|
||||
struct radeon_i2c_bus_rec *rec,
|
||||
const char *name);
|
||||
extern struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
|
||||
struct radeon_i2c_bus_rec *rec,
|
||||
const char *name);
|
||||
|
@ -887,6 +887,7 @@
|
||||
# define RADEON_FP_PANEL_FORMAT (1 << 3)
|
||||
# define RADEON_FP_EN_TMDS (1 << 7)
|
||||
# define RADEON_FP_DETECT_SENSE (1 << 8)
|
||||
# define RADEON_FP_DETECT_INT_POL (1 << 9)
|
||||
# define R200_FP_SOURCE_SEL_MASK (3 << 10)
|
||||
# define R200_FP_SOURCE_SEL_CRTC1 (0 << 10)
|
||||
# define R200_FP_SOURCE_SEL_CRTC2 (1 << 10)
|
||||
@ -894,6 +895,7 @@
|
||||
# define R200_FP_SOURCE_SEL_TRANS (3 << 10)
|
||||
# define RADEON_FP_SEL_CRTC1 (0 << 13)
|
||||
# define RADEON_FP_SEL_CRTC2 (1 << 13)
|
||||
# define R300_HPD_SEL(x) ((x) << 13)
|
||||
# define RADEON_FP_CRTC_DONT_SHADOW_HPAR (1 << 15)
|
||||
# define RADEON_FP_CRTC_DONT_SHADOW_VPAR (1 << 16)
|
||||
# define RADEON_FP_CRTC_DONT_SHADOW_HEND (1 << 17)
|
||||
@ -909,6 +911,7 @@
|
||||
# define RADEON_FP2_ON (1 << 2)
|
||||
# define RADEON_FP2_PANEL_FORMAT (1 << 3)
|
||||
# define RADEON_FP2_DETECT_SENSE (1 << 8)
|
||||
# define RADEON_FP2_DETECT_INT_POL (1 << 9)
|
||||
# define R200_FP2_SOURCE_SEL_MASK (3 << 10)
|
||||
# define R200_FP2_SOURCE_SEL_CRTC1 (0 << 10)
|
||||
# define R200_FP2_SOURCE_SEL_CRTC2 (1 << 10)
|
||||
@ -988,14 +991,20 @@
|
||||
|
||||
#define RADEON_GEN_INT_CNTL 0x0040
|
||||
# define RADEON_CRTC_VBLANK_MASK (1 << 0)
|
||||
# define RADEON_FP_DETECT_MASK (1 << 4)
|
||||
# define RADEON_CRTC2_VBLANK_MASK (1 << 9)
|
||||
# define RADEON_FP2_DETECT_MASK (1 << 10)
|
||||
# define RADEON_SW_INT_ENABLE (1 << 25)
|
||||
#define RADEON_GEN_INT_STATUS 0x0044
|
||||
# define AVIVO_DISPLAY_INT_STATUS (1 << 0)
|
||||
# define RADEON_CRTC_VBLANK_STAT (1 << 0)
|
||||
# define RADEON_CRTC_VBLANK_STAT_ACK (1 << 0)
|
||||
# define RADEON_FP_DETECT_STAT (1 << 4)
|
||||
# define RADEON_FP_DETECT_STAT_ACK (1 << 4)
|
||||
# define RADEON_CRTC2_VBLANK_STAT (1 << 9)
|
||||
# define RADEON_CRTC2_VBLANK_STAT_ACK (1 << 9)
|
||||
# define RADEON_FP2_DETECT_STAT (1 << 10)
|
||||
# define RADEON_FP2_DETECT_STAT_ACK (1 << 10)
|
||||
# define RADEON_SW_INT_FIRE (1 << 26)
|
||||
# define RADEON_SW_INT_TEST (1 << 25)
|
||||
# define RADEON_SW_INT_TEST_ACK (1 << 25)
|
||||
@ -1148,16 +1157,16 @@
|
||||
# define RADEON_IO_MCLK_MAX_DYN_STOP_LAT (1 << 13)
|
||||
# define RADEON_MC_MCLK_DYN_ENABLE (1 << 14)
|
||||
# define RADEON_IO_MCLK_DYN_ENABLE (1 << 15)
|
||||
|
||||
#define RADEON_GPIOPAD_MASK 0x0198
|
||||
#define RADEON_GPIOPAD_A 0x019c
|
||||
#define RADEON_GPIOPAD_EN 0x01a0
|
||||
#define RADEON_GPIOPAD_Y 0x01a4
|
||||
#define RADEON_LCD_GPIO_MASK 0x01a0
|
||||
#define RADEON_LCD_GPIO_Y_REG 0x01a4
|
||||
#define RADEON_MDGPIO_A_REG 0x01ac
|
||||
#define RADEON_MDGPIO_EN_REG 0x01b0
|
||||
#define RADEON_MDGPIO_MASK 0x0198
|
||||
#define RADEON_MDGPIO_Y_REG 0x01b4
|
||||
#define RADEON_MDGPIO_MASK 0x01a8
|
||||
#define RADEON_MDGPIO_A 0x01ac
|
||||
#define RADEON_MDGPIO_EN 0x01b0
|
||||
#define RADEON_MDGPIO_Y 0x01b4
|
||||
|
||||
#define RADEON_MEM_ADDR_CONFIG 0x0148
|
||||
#define RADEON_MEM_BASE 0x0f10 /* PCI */
|
||||
#define RADEON_MEM_CNTL 0x0140
|
||||
|
@ -60,6 +60,107 @@ int rs600_mc_init(struct radeon_device *rdev)
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* hpd for digital panel detect/disconnect */
|
||||
bool rs600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd)
|
||||
{
|
||||
u32 tmp;
|
||||
bool connected = false;
|
||||
|
||||
switch (hpd) {
|
||||
case RADEON_HPD_1:
|
||||
tmp = RREG32(R_007D04_DC_HOT_PLUG_DETECT1_INT_STATUS);
|
||||
if (G_007D04_DC_HOT_PLUG_DETECT1_SENSE(tmp))
|
||||
connected = true;
|
||||
break;
|
||||
case RADEON_HPD_2:
|
||||
tmp = RREG32(R_007D14_DC_HOT_PLUG_DETECT2_INT_STATUS);
|
||||
if (G_007D14_DC_HOT_PLUG_DETECT2_SENSE(tmp))
|
||||
connected = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return connected;
|
||||
}
|
||||
|
||||
void rs600_hpd_set_polarity(struct radeon_device *rdev,
|
||||
enum radeon_hpd_id hpd)
|
||||
{
|
||||
u32 tmp;
|
||||
bool connected = rs600_hpd_sense(rdev, hpd);
|
||||
|
||||
switch (hpd) {
|
||||
case RADEON_HPD_1:
|
||||
tmp = RREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL);
|
||||
if (connected)
|
||||
tmp &= ~S_007D08_DC_HOT_PLUG_DETECT1_INT_POLARITY(1);
|
||||
else
|
||||
tmp |= S_007D08_DC_HOT_PLUG_DETECT1_INT_POLARITY(1);
|
||||
WREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp);
|
||||
break;
|
||||
case RADEON_HPD_2:
|
||||
tmp = RREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL);
|
||||
if (connected)
|
||||
tmp &= ~S_007D18_DC_HOT_PLUG_DETECT2_INT_POLARITY(1);
|
||||
else
|
||||
tmp |= S_007D18_DC_HOT_PLUG_DETECT2_INT_POLARITY(1);
|
||||
WREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void rs600_hpd_init(struct radeon_device *rdev)
|
||||
{
|
||||
struct drm_device *dev = rdev->ddev;
|
||||
struct drm_connector *connector;
|
||||
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
|
||||
switch (radeon_connector->hpd.hpd) {
|
||||
case RADEON_HPD_1:
|
||||
WREG32(R_007D00_DC_HOT_PLUG_DETECT1_CONTROL,
|
||||
S_007D00_DC_HOT_PLUG_DETECT1_EN(1));
|
||||
rdev->irq.hpd[0] = true;
|
||||
break;
|
||||
case RADEON_HPD_2:
|
||||
WREG32(R_007D10_DC_HOT_PLUG_DETECT2_CONTROL,
|
||||
S_007D10_DC_HOT_PLUG_DETECT2_EN(1));
|
||||
rdev->irq.hpd[1] = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
rs600_irq_set(rdev);
|
||||
}
|
||||
|
||||
void rs600_hpd_fini(struct radeon_device *rdev)
|
||||
{
|
||||
struct drm_device *dev = rdev->ddev;
|
||||
struct drm_connector *connector;
|
||||
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
|
||||
switch (radeon_connector->hpd.hpd) {
|
||||
case RADEON_HPD_1:
|
||||
WREG32(R_007D00_DC_HOT_PLUG_DETECT1_CONTROL,
|
||||
S_007D00_DC_HOT_PLUG_DETECT1_EN(0));
|
||||
rdev->irq.hpd[0] = false;
|
||||
break;
|
||||
case RADEON_HPD_2:
|
||||
WREG32(R_007D10_DC_HOT_PLUG_DETECT2_CONTROL,
|
||||
S_007D10_DC_HOT_PLUG_DETECT2_EN(0));
|
||||
rdev->irq.hpd[1] = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* GART.
|
||||
*/
|
||||
@ -209,6 +310,10 @@ int rs600_irq_set(struct radeon_device *rdev)
|
||||
{
|
||||
uint32_t tmp = 0;
|
||||
uint32_t mode_int = 0;
|
||||
u32 hpd1 = RREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL) &
|
||||
~S_007D08_DC_HOT_PLUG_DETECT1_INT_EN(1);
|
||||
u32 hpd2 = RREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL) &
|
||||
~S_007D18_DC_HOT_PLUG_DETECT2_INT_EN(1);
|
||||
|
||||
if (rdev->irq.sw_int) {
|
||||
tmp |= S_000040_SW_INT_EN(1);
|
||||
@ -219,8 +324,16 @@ int rs600_irq_set(struct radeon_device *rdev)
|
||||
if (rdev->irq.crtc_vblank_int[1]) {
|
||||
mode_int |= S_006540_D2MODE_VBLANK_INT_MASK(1);
|
||||
}
|
||||
if (rdev->irq.hpd[0]) {
|
||||
hpd1 |= S_007D08_DC_HOT_PLUG_DETECT1_INT_EN(1);
|
||||
}
|
||||
if (rdev->irq.hpd[1]) {
|
||||
hpd2 |= S_007D18_DC_HOT_PLUG_DETECT2_INT_EN(1);
|
||||
}
|
||||
WREG32(R_000040_GEN_INT_CNTL, tmp);
|
||||
WREG32(R_006540_DxMODE_INT_MASK, mode_int);
|
||||
WREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL, hpd1);
|
||||
WREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL, hpd2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -228,6 +341,7 @@ static inline uint32_t rs600_irq_ack(struct radeon_device *rdev, u32 *r500_disp_
|
||||
{
|
||||
uint32_t irqs = RREG32(R_000044_GEN_INT_STATUS);
|
||||
uint32_t irq_mask = ~C_000044_SW_INT;
|
||||
u32 tmp;
|
||||
|
||||
if (G_000044_DISPLAY_INT_STAT(irqs)) {
|
||||
*r500_disp_int = RREG32(R_007EDC_DISP_INTERRUPT_STATUS);
|
||||
@ -239,6 +353,16 @@ static inline uint32_t rs600_irq_ack(struct radeon_device *rdev, u32 *r500_disp_
|
||||
WREG32(R_006D34_D2MODE_VBLANK_STATUS,
|
||||
S_006D34_D2MODE_VBLANK_ACK(1));
|
||||
}
|
||||
if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(*r500_disp_int)) {
|
||||
tmp = RREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL);
|
||||
tmp |= S_007D08_DC_HOT_PLUG_DETECT1_INT_ACK(1);
|
||||
WREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp);
|
||||
}
|
||||
if (G_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(*r500_disp_int)) {
|
||||
tmp = RREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL);
|
||||
tmp |= S_007D18_DC_HOT_PLUG_DETECT2_INT_ACK(1);
|
||||
WREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp);
|
||||
}
|
||||
} else {
|
||||
*r500_disp_int = 0;
|
||||
}
|
||||
@ -264,6 +388,7 @@ int rs600_irq_process(struct radeon_device *rdev)
|
||||
{
|
||||
uint32_t status, msi_rearm;
|
||||
uint32_t r500_disp_int;
|
||||
bool queue_hotplug = false;
|
||||
|
||||
status = rs600_irq_ack(rdev, &r500_disp_int);
|
||||
if (!status && !r500_disp_int) {
|
||||
@ -278,8 +403,18 @@ int rs600_irq_process(struct radeon_device *rdev)
|
||||
drm_handle_vblank(rdev->ddev, 0);
|
||||
if (G_007EDC_LB_D2_VBLANK_INTERRUPT(r500_disp_int))
|
||||
drm_handle_vblank(rdev->ddev, 1);
|
||||
if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(r500_disp_int)) {
|
||||
queue_hotplug = true;
|
||||
DRM_DEBUG("HPD1\n");
|
||||
}
|
||||
if (G_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(r500_disp_int)) {
|
||||
queue_hotplug = true;
|
||||
DRM_DEBUG("HPD2\n");
|
||||
}
|
||||
status = rs600_irq_ack(rdev, &r500_disp_int);
|
||||
}
|
||||
if (queue_hotplug)
|
||||
queue_work(rdev->wq, &rdev->hotplug_work);
|
||||
if (rdev->msi_enabled) {
|
||||
switch (rdev->family) {
|
||||
case CHIP_RS600:
|
||||
|
@ -30,27 +30,12 @@
|
||||
|
||||
/* Registers */
|
||||
#define R_000040_GEN_INT_CNTL 0x000040
|
||||
#define S_000040_DISPLAY_INT_STATUS(x) (((x) & 0x1) << 0)
|
||||
#define G_000040_DISPLAY_INT_STATUS(x) (((x) >> 0) & 0x1)
|
||||
#define C_000040_DISPLAY_INT_STATUS 0xFFFFFFFE
|
||||
#define S_000040_DMA_VIPH0_INT_EN(x) (((x) & 0x1) << 12)
|
||||
#define G_000040_DMA_VIPH0_INT_EN(x) (((x) >> 12) & 0x1)
|
||||
#define C_000040_DMA_VIPH0_INT_EN 0xFFFFEFFF
|
||||
#define S_000040_CRTC2_VSYNC(x) (((x) & 0x1) << 6)
|
||||
#define G_000040_CRTC2_VSYNC(x) (((x) >> 6) & 0x1)
|
||||
#define C_000040_CRTC2_VSYNC 0xFFFFFFBF
|
||||
#define S_000040_SNAPSHOT2(x) (((x) & 0x1) << 7)
|
||||
#define G_000040_SNAPSHOT2(x) (((x) >> 7) & 0x1)
|
||||
#define C_000040_SNAPSHOT2 0xFFFFFF7F
|
||||
#define S_000040_CRTC2_VBLANK(x) (((x) & 0x1) << 9)
|
||||
#define G_000040_CRTC2_VBLANK(x) (((x) >> 9) & 0x1)
|
||||
#define C_000040_CRTC2_VBLANK 0xFFFFFDFF
|
||||
#define S_000040_FP2_DETECT(x) (((x) & 0x1) << 10)
|
||||
#define G_000040_FP2_DETECT(x) (((x) >> 10) & 0x1)
|
||||
#define C_000040_FP2_DETECT 0xFFFFFBFF
|
||||
#define S_000040_VSYNC_DIFF_OVER_LIMIT(x) (((x) & 0x1) << 11)
|
||||
#define G_000040_VSYNC_DIFF_OVER_LIMIT(x) (((x) >> 11) & 0x1)
|
||||
#define C_000040_VSYNC_DIFF_OVER_LIMIT 0xFFFFF7FF
|
||||
#define S_000040_SCRATCH_INT_MASK(x) (((x) & 0x1) << 18)
|
||||
#define G_000040_SCRATCH_INT_MASK(x) (((x) >> 18) & 0x1)
|
||||
#define C_000040_SCRATCH_INT_MASK 0xFFFBFFFF
|
||||
#define S_000040_GUI_IDLE_MASK(x) (((x) & 0x1) << 19)
|
||||
#define G_000040_GUI_IDLE_MASK(x) (((x) >> 19) & 0x1)
|
||||
#define C_000040_GUI_IDLE_MASK 0xFFF7FFFF
|
||||
#define S_000040_DMA_VIPH1_INT_EN(x) (((x) & 0x1) << 13)
|
||||
#define G_000040_DMA_VIPH1_INT_EN(x) (((x) >> 13) & 0x1)
|
||||
#define C_000040_DMA_VIPH1_INT_EN 0xFFFFDFFF
|
||||
@ -370,7 +355,90 @@
|
||||
#define S_007EDC_LB_D2_VBLANK_INTERRUPT(x) (((x) & 0x1) << 5)
|
||||
#define G_007EDC_LB_D2_VBLANK_INTERRUPT(x) (((x) >> 5) & 0x1)
|
||||
#define C_007EDC_LB_D2_VBLANK_INTERRUPT 0xFFFFFFDF
|
||||
|
||||
#define S_007EDC_DACA_AUTODETECT_INTERRUPT(x) (((x) & 0x1) << 16)
|
||||
#define G_007EDC_DACA_AUTODETECT_INTERRUPT(x) (((x) >> 16) & 0x1)
|
||||
#define C_007EDC_DACA_AUTODETECT_INTERRUPT 0xFFFEFFFF
|
||||
#define S_007EDC_DACB_AUTODETECT_INTERRUPT(x) (((x) & 0x1) << 17)
|
||||
#define G_007EDC_DACB_AUTODETECT_INTERRUPT(x) (((x) >> 17) & 0x1)
|
||||
#define C_007EDC_DACB_AUTODETECT_INTERRUPT 0xFFFDFFFF
|
||||
#define S_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(x) (((x) & 0x1) << 18)
|
||||
#define G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(x) (((x) >> 18) & 0x1)
|
||||
#define C_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT 0xFFFBFFFF
|
||||
#define S_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(x) (((x) & 0x1) << 19)
|
||||
#define G_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(x) (((x) >> 19) & 0x1)
|
||||
#define C_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT 0xFFF7FFFF
|
||||
#define R_007828_DACA_AUTODETECT_CONTROL 0x007828
|
||||
#define S_007828_DACA_AUTODETECT_MODE(x) (((x) & 0x3) << 0)
|
||||
#define G_007828_DACA_AUTODETECT_MODE(x) (((x) >> 0) & 0x3)
|
||||
#define C_007828_DACA_AUTODETECT_MODE 0xFFFFFFFC
|
||||
#define S_007828_DACA_AUTODETECT_FRAME_TIME_COUNTER(x) (((x) & 0xff) << 8)
|
||||
#define G_007828_DACA_AUTODETECT_FRAME_TIME_COUNTER(x) (((x) >> 8) & 0xff)
|
||||
#define C_007828_DACA_AUTODETECT_FRAME_TIME_COUNTER 0xFFFF00FF
|
||||
#define S_007828_DACA_AUTODETECT_CHECK_MASK(x) (((x) & 0x3) << 16)
|
||||
#define G_007828_DACA_AUTODETECT_CHECK_MASK(x) (((x) >> 16) & 0x3)
|
||||
#define C_007828_DACA_AUTODETECT_CHECK_MASK 0xFFFCFFFF
|
||||
#define R_007838_DACA_AUTODETECT_INT_CONTROL 0x007838
|
||||
#define S_007838_DACA_AUTODETECT_ACK(x) (((x) & 0x1) << 0)
|
||||
#define C_007838_DACA_DACA_AUTODETECT_ACK 0xFFFFFFFE
|
||||
#define S_007838_DACA_AUTODETECT_INT_ENABLE(x) (((x) & 0x1) << 16)
|
||||
#define G_007838_DACA_AUTODETECT_INT_ENABLE(x) (((x) >> 16) & 0x1)
|
||||
#define C_007838_DACA_AUTODETECT_INT_ENABLE 0xFFFCFFFF
|
||||
#define R_007A28_DACB_AUTODETECT_CONTROL 0x007A28
|
||||
#define S_007A28_DACB_AUTODETECT_MODE(x) (((x) & 0x3) << 0)
|
||||
#define G_007A28_DACB_AUTODETECT_MODE(x) (((x) >> 0) & 0x3)
|
||||
#define C_007A28_DACB_AUTODETECT_MODE 0xFFFFFFFC
|
||||
#define S_007A28_DACB_AUTODETECT_FRAME_TIME_COUNTER(x) (((x) & 0xff) << 8)
|
||||
#define G_007A28_DACB_AUTODETECT_FRAME_TIME_COUNTER(x) (((x) >> 8) & 0xff)
|
||||
#define C_007A28_DACB_AUTODETECT_FRAME_TIME_COUNTER 0xFFFF00FF
|
||||
#define S_007A28_DACB_AUTODETECT_CHECK_MASK(x) (((x) & 0x3) << 16)
|
||||
#define G_007A28_DACB_AUTODETECT_CHECK_MASK(x) (((x) >> 16) & 0x3)
|
||||
#define C_007A28_DACB_AUTODETECT_CHECK_MASK 0xFFFCFFFF
|
||||
#define R_007A38_DACB_AUTODETECT_INT_CONTROL 0x007A38
|
||||
#define S_007A38_DACB_AUTODETECT_ACK(x) (((x) & 0x1) << 0)
|
||||
#define C_007A38_DACB_DACA_AUTODETECT_ACK 0xFFFFFFFE
|
||||
#define S_007A38_DACB_AUTODETECT_INT_ENABLE(x) (((x) & 0x1) << 16)
|
||||
#define G_007A38_DACB_AUTODETECT_INT_ENABLE(x) (((x) >> 16) & 0x1)
|
||||
#define C_007A38_DACB_AUTODETECT_INT_ENABLE 0xFFFCFFFF
|
||||
#define R_007D00_DC_HOT_PLUG_DETECT1_CONTROL 0x007D00
|
||||
#define S_007D00_DC_HOT_PLUG_DETECT1_EN(x) (((x) & 0x1) << 0)
|
||||
#define G_007D00_DC_HOT_PLUG_DETECT1_EN(x) (((x) >> 0) & 0x1)
|
||||
#define C_007D00_DC_HOT_PLUG_DETECT1_EN 0xFFFFFFFE
|
||||
#define R_007D04_DC_HOT_PLUG_DETECT1_INT_STATUS 0x007D04
|
||||
#define S_007D04_DC_HOT_PLUG_DETECT1_INT_STATUS(x) (((x) & 0x1) << 0)
|
||||
#define G_007D04_DC_HOT_PLUG_DETECT1_INT_STATUS(x) (((x) >> 0) & 0x1)
|
||||
#define C_007D04_DC_HOT_PLUG_DETECT1_INT_STATUS 0xFFFFFFFE
|
||||
#define S_007D04_DC_HOT_PLUG_DETECT1_SENSE(x) (((x) & 0x1) << 1)
|
||||
#define G_007D04_DC_HOT_PLUG_DETECT1_SENSE(x) (((x) >> 1) & 0x1)
|
||||
#define C_007D04_DC_HOT_PLUG_DETECT1_SENSE 0xFFFFFFFD
|
||||
#define R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL 0x007D08
|
||||
#define S_007D08_DC_HOT_PLUG_DETECT1_INT_ACK(x) (((x) & 0x1) << 0)
|
||||
#define C_007D08_DC_HOT_PLUG_DETECT1_INT_ACK 0xFFFFFFFE
|
||||
#define S_007D08_DC_HOT_PLUG_DETECT1_INT_POLARITY(x) (((x) & 0x1) << 8)
|
||||
#define G_007D08_DC_HOT_PLUG_DETECT1_INT_POLARITY(x) (((x) >> 8) & 0x1)
|
||||
#define C_007D08_DC_HOT_PLUG_DETECT1_INT_POLARITY 0xFFFFFEFF
|
||||
#define S_007D08_DC_HOT_PLUG_DETECT1_INT_EN(x) (((x) & 0x1) << 16)
|
||||
#define G_007D08_DC_HOT_PLUG_DETECT1_INT_EN(x) (((x) >> 16) & 0x1)
|
||||
#define C_007D08_DC_HOT_PLUG_DETECT1_INT_EN 0xFFFEFFFF
|
||||
#define R_007D10_DC_HOT_PLUG_DETECT2_CONTROL 0x007D10
|
||||
#define S_007D10_DC_HOT_PLUG_DETECT2_EN(x) (((x) & 0x1) << 0)
|
||||
#define G_007D10_DC_HOT_PLUG_DETECT2_EN(x) (((x) >> 0) & 0x1)
|
||||
#define C_007D10_DC_HOT_PLUG_DETECT2_EN 0xFFFFFFFE
|
||||
#define R_007D14_DC_HOT_PLUG_DETECT2_INT_STATUS 0x007D14
|
||||
#define S_007D14_DC_HOT_PLUG_DETECT2_INT_STATUS(x) (((x) & 0x1) << 0)
|
||||
#define G_007D14_DC_HOT_PLUG_DETECT2_INT_STATUS(x) (((x) >> 0) & 0x1)
|
||||
#define C_007D14_DC_HOT_PLUG_DETECT2_INT_STATUS 0xFFFFFFFE
|
||||
#define S_007D14_DC_HOT_PLUG_DETECT2_SENSE(x) (((x) & 0x1) << 1)
|
||||
#define G_007D14_DC_HOT_PLUG_DETECT2_SENSE(x) (((x) >> 1) & 0x1)
|
||||
#define C_007D14_DC_HOT_PLUG_DETECT2_SENSE 0xFFFFFFFD
|
||||
#define R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL 0x007D18
|
||||
#define S_007D18_DC_HOT_PLUG_DETECT2_INT_ACK(x) (((x) & 0x1) << 0)
|
||||
#define C_007D18_DC_HOT_PLUG_DETECT2_INT_ACK 0xFFFFFFFE
|
||||
#define S_007D18_DC_HOT_PLUG_DETECT2_INT_POLARITY(x) (((x) & 0x1) << 8)
|
||||
#define G_007D18_DC_HOT_PLUG_DETECT2_INT_POLARITY(x) (((x) >> 8) & 0x1)
|
||||
#define C_007D18_DC_HOT_PLUG_DETECT2_INT_POLARITY 0xFFFFFEFF
|
||||
#define S_007D18_DC_HOT_PLUG_DETECT2_INT_EN(x) (((x) & 0x1) << 16)
|
||||
#define G_007D18_DC_HOT_PLUG_DETECT2_INT_EN(x) (((x) >> 16) & 0x1)
|
||||
#define C_007D18_DC_HOT_PLUG_DETECT2_INT_EN 0xFFFEFFFF
|
||||
|
||||
/* MC registers */
|
||||
#define R_000000_MC_STATUS 0x000000
|
||||
|
@ -43,16 +43,41 @@
|
||||
#define AUX_I2C_REPLY_MASK (0x3 << 6)
|
||||
|
||||
/* AUX CH addresses */
|
||||
#define DP_LINK_BW_SET 0x100
|
||||
/* DPCD */
|
||||
#define DP_DPCD_REV 0x000
|
||||
|
||||
#define DP_MAX_LINK_RATE 0x001
|
||||
|
||||
#define DP_MAX_LANE_COUNT 0x002
|
||||
# define DP_MAX_LANE_COUNT_MASK 0x1f
|
||||
# define DP_ENHANCED_FRAME_CAP (1 << 7)
|
||||
|
||||
#define DP_MAX_DOWNSPREAD 0x003
|
||||
# define DP_NO_AUX_HANDSHAKE_LINK_TRAINING (1 << 6)
|
||||
|
||||
#define DP_NORP 0x004
|
||||
|
||||
#define DP_DOWNSTREAMPORT_PRESENT 0x005
|
||||
# define DP_DWN_STRM_PORT_PRESENT (1 << 0)
|
||||
# define DP_DWN_STRM_PORT_TYPE_MASK 0x06
|
||||
/* 00b = DisplayPort */
|
||||
/* 01b = Analog */
|
||||
/* 10b = TMDS or HDMI */
|
||||
/* 11b = Other */
|
||||
# define DP_FORMAT_CONVERSION (1 << 3)
|
||||
|
||||
#define DP_MAIN_LINK_CHANNEL_CODING 0x006
|
||||
|
||||
/* link configuration */
|
||||
#define DP_LINK_BW_SET 0x100
|
||||
# define DP_LINK_BW_1_62 0x06
|
||||
# define DP_LINK_BW_2_7 0x0a
|
||||
|
||||
#define DP_LANE_COUNT_SET 0x101
|
||||
#define DP_LANE_COUNT_SET 0x101
|
||||
# define DP_LANE_COUNT_MASK 0x0f
|
||||
# define DP_LANE_COUNT_ENHANCED_FRAME_EN (1 << 7)
|
||||
|
||||
#define DP_TRAINING_PATTERN_SET 0x102
|
||||
|
||||
#define DP_TRAINING_PATTERN_SET 0x102
|
||||
# define DP_TRAINING_PATTERN_DISABLE 0
|
||||
# define DP_TRAINING_PATTERN_1 1
|
||||
# define DP_TRAINING_PATTERN_2 2
|
||||
@ -102,11 +127,14 @@
|
||||
|
||||
#define DP_LANE0_1_STATUS 0x202
|
||||
#define DP_LANE2_3_STATUS 0x203
|
||||
|
||||
# define DP_LANE_CR_DONE (1 << 0)
|
||||
# define DP_LANE_CHANNEL_EQ_DONE (1 << 1)
|
||||
# define DP_LANE_SYMBOL_LOCKED (1 << 2)
|
||||
|
||||
#define DP_CHANNEL_EQ_BITS (DP_LANE_CR_DONE | \
|
||||
DP_LANE_CHANNEL_EQ_DONE | \
|
||||
DP_LANE_SYMBOL_LOCKED)
|
||||
|
||||
#define DP_LANE_ALIGN_STATUS_UPDATED 0x204
|
||||
|
||||
#define DP_INTERLANE_ALIGN_DONE (1 << 0)
|
||||
@ -120,15 +148,18 @@
|
||||
|
||||
#define DP_ADJUST_REQUEST_LANE0_1 0x206
|
||||
#define DP_ADJUST_REQUEST_LANE2_3 0x207
|
||||
# define DP_ADJUST_VOLTAGE_SWING_LANE0_MASK 0x03
|
||||
# define DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT 0
|
||||
# define DP_ADJUST_PRE_EMPHASIS_LANE0_MASK 0x0c
|
||||
# define DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT 2
|
||||
# define DP_ADJUST_VOLTAGE_SWING_LANE1_MASK 0x30
|
||||
# define DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT 4
|
||||
# define DP_ADJUST_PRE_EMPHASIS_LANE1_MASK 0xc0
|
||||
# define DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT 6
|
||||
|
||||
#define DP_ADJUST_VOLTAGE_SWING_LANE0_MASK 0x03
|
||||
#define DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT 0
|
||||
#define DP_ADJUST_PRE_EMPHASIS_LANE0_MASK 0x0c
|
||||
#define DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT 2
|
||||
#define DP_ADJUST_VOLTAGE_SWING_LANE1_MASK 0x30
|
||||
#define DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT 4
|
||||
#define DP_ADJUST_PRE_EMPHASIS_LANE1_MASK 0xc0
|
||||
#define DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT 6
|
||||
#define DP_SET_POWER 0x600
|
||||
# define DP_SET_POWER_D0 0x1
|
||||
# define DP_SET_POWER_D3 0x2
|
||||
|
||||
#define MODE_I2C_START 1
|
||||
#define MODE_I2C_WRITE 2
|
||||
|
Loading…
Reference in New Issue
Block a user