Commit fcec570b authored by Alex Deucher's avatar Alex Deucher Committed by Dave Airlie

drm/radeon/kms: add support for external tmds on legacy boards

This enables initialization of external tmds chips on pre-atom
and mac systems.  Macs are untested.  Also, some macs have single
link tmds chips while others have dual link tmds chips.  We need
to figure out which ones have which.

This gets external TMDS working on my RS485 and RV380.
Signed-off-by: default avatarAlex Deucher <alexdeucher@gmail.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 9b9fe724
This diff is collapsed.
......@@ -212,3 +212,59 @@ struct drm_encoder *radeon_best_encoder(struct drm_connector *connector)
{
return NULL;
}
void radeon_i2c_sw_get_byte(struct radeon_i2c_chan *i2c_bus,
u8 slave_addr,
u8 addr,
u8 *val)
{
u8 out_buf[2];
u8 in_buf[2];
struct i2c_msg msgs[] = {
{
.addr = slave_addr,
.flags = 0,
.len = 1,
.buf = out_buf,
},
{
.addr = slave_addr,
.flags = I2C_M_RD,
.len = 1,
.buf = in_buf,
}
};
out_buf[0] = addr;
out_buf[1] = 0;
if (i2c_transfer(&i2c_bus->adapter, msgs, 2) == 2) {
*val = in_buf[0];
DRM_DEBUG("val = 0x%02x\n", *val);
} else {
DRM_ERROR("i2c 0x%02x 0x%02x read failed\n",
addr, *val);
}
}
void radeon_i2c_sw_put_byte(struct radeon_i2c_chan *i2c_bus,
u8 slave_addr,
u8 addr,
u8 val)
{
uint8_t out_buf[2];
struct i2c_msg msg = {
.addr = slave_addr,
.flags = 0,
.len = 2,
.buf = out_buf,
};
out_buf[0] = addr;
out_buf[1] = val;
if (i2c_transfer(&i2c_bus->adapter, &msg, 1) != 1)
DRM_ERROR("i2c 0x%02x 0x%02x write failed\n",
addr, val);
}
......@@ -697,6 +697,8 @@ static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder,
/*if (mode->clock > 165000)
fp2_gen_cntl |= R300_FP2_DVO_DUAL_CHANNEL_EN;*/
}
if (!radeon_combios_external_tmds_setup(encoder))
radeon_external_tmds_setup(encoder);
}
if (radeon_crtc->crtc_id == 0) {
......@@ -724,6 +726,19 @@ static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder,
radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
}
static void radeon_ext_tmds_enc_destroy(struct drm_encoder *encoder)
{
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct radeon_encoder_ext_tmds *tmds = radeon_encoder->enc_priv;
if (tmds) {
if (tmds->i2c_bus)
radeon_i2c_destroy(tmds->i2c_bus);
}
kfree(radeon_encoder->enc_priv);
drm_encoder_cleanup(encoder);
kfree(radeon_encoder);
}
static const struct drm_encoder_helper_funcs radeon_legacy_tmds_ext_helper_funcs = {
.dpms = radeon_legacy_tmds_ext_dpms,
.mode_fixup = radeon_legacy_tmds_ext_mode_fixup,
......@@ -735,7 +750,7 @@ static const struct drm_encoder_helper_funcs radeon_legacy_tmds_ext_helper_funcs
static const struct drm_encoder_funcs radeon_legacy_tmds_ext_enc_funcs = {
.destroy = radeon_enc_destroy,
.destroy = radeon_ext_tmds_enc_destroy,
};
static bool radeon_legacy_tv_dac_mode_fixup(struct drm_encoder *encoder,
......@@ -1302,6 +1317,29 @@ static struct radeon_encoder_int_tmds *radeon_legacy_get_tmds_info(struct radeon
return tmds;
}
static struct radeon_encoder_ext_tmds *radeon_legacy_get_ext_tmds_info(struct radeon_encoder *encoder)
{
struct drm_device *dev = encoder->base.dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_encoder_ext_tmds *tmds = NULL;
bool ret;
if (rdev->is_atom_bios)
return NULL;
tmds = kzalloc(sizeof(struct radeon_encoder_ext_tmds), GFP_KERNEL);
if (!tmds)
return NULL;
ret = radeon_legacy_get_ext_tmds_info_from_combios(encoder, tmds);
if (ret == false)
radeon_legacy_get_ext_tmds_info_from_table(encoder, tmds);
return tmds;
}
void
radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t supported_device)
{
......@@ -1373,7 +1411,7 @@ radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t
drm_encoder_init(dev, encoder, &radeon_legacy_tmds_ext_enc_funcs, DRM_MODE_ENCODER_TMDS);
drm_encoder_helper_add(encoder, &radeon_legacy_tmds_ext_helper_funcs);
if (!rdev->is_atom_bios)
radeon_combios_get_ext_tmds_info(radeon_encoder);
radeon_encoder->enc_priv = radeon_legacy_get_ext_tmds_info(radeon_encoder);
break;
}
}
......@@ -184,6 +184,11 @@ enum radeon_connector_table {
CT_EMAC,
};
enum radeon_dvo_chip {
DVO_SIL164,
DVO_SIL1178,
};
struct radeon_mode_info {
struct atom_context *atom_context;
struct card_info *atom_card_info;
......@@ -275,6 +280,13 @@ struct radeon_encoder_int_tmds {
struct radeon_tmds_pll tmds_pll[4];
};
struct radeon_encoder_ext_tmds {
/* tmds over dvo */
struct radeon_i2c_chan *i2c_bus;
uint8_t slave_addr;
enum radeon_dvo_chip dvo_chip;
};
/* spread spectrum */
struct radeon_atom_ss {
uint16_t percentage;
......@@ -343,6 +355,14 @@ extern struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
struct radeon_i2c_bus_rec *rec,
const char *name);
extern void radeon_i2c_destroy(struct radeon_i2c_chan *i2c);
extern void radeon_i2c_sw_get_byte(struct radeon_i2c_chan *i2c_bus,
u8 slave_addr,
u8 addr,
u8 *val);
extern void radeon_i2c_sw_put_byte(struct radeon_i2c_chan *i2c,
u8 slave_addr,
u8 addr,
u8 val);
extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector);
extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
......@@ -392,12 +412,16 @@ extern bool radeon_atom_get_clock_info(struct drm_device *dev);
extern bool radeon_combios_get_clock_info(struct drm_device *dev);
extern struct radeon_encoder_atom_dig *
radeon_atombios_get_lvds_info(struct radeon_encoder *encoder);
bool radeon_atombios_get_tmds_info(struct radeon_encoder *encoder,
struct radeon_encoder_int_tmds *tmds);
bool radeon_legacy_get_tmds_info_from_combios(struct radeon_encoder *encoder,
struct radeon_encoder_int_tmds *tmds);
bool radeon_legacy_get_tmds_info_from_table(struct radeon_encoder *encoder,
struct radeon_encoder_int_tmds *tmds);
extern bool radeon_atombios_get_tmds_info(struct radeon_encoder *encoder,
struct radeon_encoder_int_tmds *tmds);
extern bool radeon_legacy_get_tmds_info_from_combios(struct radeon_encoder *encoder,
struct radeon_encoder_int_tmds *tmds);
extern bool radeon_legacy_get_tmds_info_from_table(struct radeon_encoder *encoder,
struct radeon_encoder_int_tmds *tmds);
extern bool radeon_legacy_get_ext_tmds_info_from_combios(struct radeon_encoder *encoder,
struct radeon_encoder_ext_tmds *tmds);
extern bool radeon_legacy_get_ext_tmds_info_from_table(struct radeon_encoder *encoder,
struct radeon_encoder_ext_tmds *tmds);
extern struct radeon_encoder_primary_dac *
radeon_atombios_get_primary_dac_info(struct radeon_encoder *encoder);
extern struct radeon_encoder_tv_dac *
......@@ -409,6 +433,8 @@ extern struct radeon_encoder_tv_dac *
radeon_combios_get_tv_dac_info(struct radeon_encoder *encoder);
extern struct radeon_encoder_primary_dac *
radeon_combios_get_primary_dac_info(struct radeon_encoder *encoder);
extern bool radeon_combios_external_tmds_setup(struct drm_encoder *encoder);
extern void radeon_external_tmds_setup(struct drm_encoder *encoder);
extern void radeon_combios_output_lock(struct drm_encoder *encoder, bool lock);
extern void radeon_combios_initialize_bios_scratch_regs(struct drm_device *dev);
extern void radeon_atom_output_lock(struct drm_encoder *encoder, bool lock);
......
......@@ -1051,20 +1051,25 @@
/* Multimedia I2C bus */
#define RADEON_I2C_CNTL_0 0x0090
#define RADEON_I2C_DONE (1<<0)
#define RADEON_I2C_NACK (1<<1)
#define RADEON_I2C_HALT (1<<2)
#define RADEON_I2C_SOFT_RST (1<<5)
#define RADEON_I2C_DRIVE_EN (1<<6)
#define RADEON_I2C_DRIVE_SEL (1<<7)
#define RADEON_I2C_START (1<<8)
#define RADEON_I2C_STOP (1<<9)
#define RADEON_I2C_RECEIVE (1<<10)
#define RADEON_I2C_ABORT (1<<11)
#define RADEON_I2C_GO (1<<12)
#define RADEON_I2C_DONE (1 << 0)
#define RADEON_I2C_NACK (1 << 1)
#define RADEON_I2C_HALT (1 << 2)
#define RADEON_I2C_SOFT_RST (1 << 5)
#define RADEON_I2C_DRIVE_EN (1 << 6)
#define RADEON_I2C_DRIVE_SEL (1 << 7)
#define RADEON_I2C_START (1 << 8)
#define RADEON_I2C_STOP (1 << 9)
#define RADEON_I2C_RECEIVE (1 << 10)
#define RADEON_I2C_ABORT (1 << 11)
#define RADEON_I2C_GO (1 << 12)
#define RADEON_I2C_PRESCALE_SHIFT 16
#define RADEON_I2C_CNTL_1 0x0094
#define RADEON_I2C_SEL (1<<16)
#define RADEON_I2C_EN (1<<17)
#define RADEON_I2C_DATA_COUNT_SHIFT 0
#define RADEON_I2C_ADDR_COUNT_SHIFT 4
#define RADEON_I2C_INTRA_BYTE_DELAY_SHIFT 8
#define RADEON_I2C_SEL (1 << 16)
#define RADEON_I2C_EN (1 << 17)
#define RADEON_I2C_TIME_LIMIT_SHIFT 24
#define RADEON_I2C_DATA 0x0098
#define RADEON_DVI_I2C_CNTL_0 0x02e0
......@@ -1072,7 +1077,7 @@
# define R200_SEL_DDC1 0 /* 0x60 - VGA_DDC */
# define R200_SEL_DDC2 1 /* 0x64 - DVI_DDC */
# define R200_SEL_DDC3 2 /* 0x68 - MONID_DDC */
#define RADEON_DVI_I2C_CNTL_1 0x02e4 /* ? */
#define RADEON_DVI_I2C_CNTL_1 0x02e4
#define RADEON_DVI_I2C_DATA 0x02e8
#define RADEON_INTERRUPT_LINE 0x0f3c /* PCI */
......@@ -1143,14 +1148,15 @@
# 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_LCD_GPIO_MASK 0x01a0
#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_GPIOPAD_MASK 0x0198
#define RADEON_GPIOPAD_A 0x019c
#define RADEON_MDGPIO_Y_REG 0x01b4
#define RADEON_MEM_ADDR_CONFIG 0x0148
#define RADEON_MEM_BASE 0x0f10 /* PCI */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment