Commit 6a93cb25 authored by Alex Deucher's avatar Alex Deucher Committed by Dave Airlie

drm/radeon/kms: i2c reorg

- keep the atom i2c id in the i2c rec
- fix gpio regs for GPIO and MDGPIO on pre-avivo chips
- track whether the i2c line is hw capable
- track whether the i2c line uses the multimedia i2c block
Signed-off-by: default avatarAlex Deucher <alexdeucher@gmail.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 1a66c95a
...@@ -52,7 +52,7 @@ bool radeon_process_aux_ch(struct radeon_i2c_chan *chan, u8 *req_bytes, ...@@ -52,7 +52,7 @@ bool radeon_process_aux_ch(struct radeon_i2c_chan *chan, u8 *req_bytes,
args.lpAuxRequest = 0; args.lpAuxRequest = 0;
args.lpDataOut = 16; args.lpDataOut = 16;
args.ucDataOutLen = 0; args.ucDataOutLen = 0;
args.ucChannelID = chan->i2c_id; args.ucChannelID = chan->rec.i2c_id;
args.ucDelay = delay / 10; args.ucDelay = delay / 10;
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
...@@ -60,7 +60,7 @@ bool radeon_process_aux_ch(struct radeon_i2c_chan *chan, u8 *req_bytes, ...@@ -60,7 +60,7 @@ bool radeon_process_aux_ch(struct radeon_i2c_chan *chan, u8 *req_bytes,
if (args.ucReplyStatus) { if (args.ucReplyStatus) {
DRM_ERROR("failed to get auxch %02x%02x %02x %02x 0x%02x %02x\n", DRM_ERROR("failed to get auxch %02x%02x %02x %02x 0x%02x %02x\n",
req_bytes[1], req_bytes[0], req_bytes[2], req_bytes[3], req_bytes[1], req_bytes[0], req_bytes[2], req_bytes[3],
chan->i2c_id, args.ucReplyStatus); chan->rec.i2c_id, args.ucReplyStatus);
return false; return false;
} }
...@@ -102,7 +102,7 @@ int radeon_dp_getsinktype(struct radeon_connector *radeon_connector) ...@@ -102,7 +102,7 @@ int radeon_dp_getsinktype(struct radeon_connector *radeon_connector)
struct radeon_device *rdev = dev->dev_private; struct radeon_device *rdev = dev->dev_private;
return radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_GET_SINK_TYPE, 0, return radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_GET_SINK_TYPE, 0,
radeon_dig_connector->uc_i2c_id, 0); radeon_dig_connector->dp_i2c_bus->rec.i2c_id, 0);
} }
union dig_transmitter_control { union dig_transmitter_control {
......
...@@ -47,7 +47,7 @@ radeon_add_atom_connector(struct drm_device *dev, ...@@ -47,7 +47,7 @@ radeon_add_atom_connector(struct drm_device *dev,
int connector_type, int connector_type,
struct radeon_i2c_bus_rec *i2c_bus, struct radeon_i2c_bus_rec *i2c_bus,
bool linkb, uint32_t igp_lane_info, bool linkb, uint32_t igp_lane_info,
uint16_t connector_object_id, uint8_t uc_i2c_id); uint16_t connector_object_id);
/* from radeon_legacy_encoder.c */ /* from radeon_legacy_encoder.c */
extern void extern void
...@@ -65,7 +65,7 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_gpio(struct drm_device *de ...@@ -65,7 +65,7 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_gpio(struct drm_device *de
{ {
struct radeon_device *rdev = dev->dev_private; struct radeon_device *rdev = dev->dev_private;
struct atom_context *ctx = rdev->mode_info.atom_context; 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; struct radeon_i2c_bus_rec i2c;
int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info); int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info);
struct _ATOM_GPIO_I2C_INFO *i2c_info; struct _ATOM_GPIO_I2C_INFO *i2c_info;
...@@ -78,24 +78,37 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_gpio(struct drm_device *de ...@@ -78,24 +78,37 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_gpio(struct drm_device *de
i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset); 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_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4;
i2c.mask_data_reg = le16_to_cpu(gpio.usDataMaskRegisterIndex) * 4; i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4;
i2c.en_clk_reg = le16_to_cpu(gpio.usClkEnRegisterIndex) * 4; i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4;
i2c.en_data_reg = le16_to_cpu(gpio.usDataEnRegisterIndex) * 4; i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4;
i2c.y_clk_reg = le16_to_cpu(gpio.usClkY_RegisterIndex) * 4; i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4;
i2c.y_data_reg = le16_to_cpu(gpio.usDataY_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_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4;
i2c.a_data_reg = le16_to_cpu(gpio.usDataA_RegisterIndex) * 4; i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4;
i2c.mask_clk_mask = (1 << gpio.ucClkMaskShift); i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift);
i2c.mask_data_mask = (1 << gpio.ucDataMaskShift); i2c.mask_data_mask = (1 << gpio->ucDataMaskShift);
i2c.en_clk_mask = (1 << gpio.ucClkEnShift); i2c.en_clk_mask = (1 << gpio->ucClkEnShift);
i2c.en_data_mask = (1 << gpio.ucDataEnShift); i2c.en_data_mask = (1 << gpio->ucDataEnShift);
i2c.y_clk_mask = (1 << gpio.ucClkY_Shift); i2c.y_clk_mask = (1 << gpio->ucClkY_Shift);
i2c.y_data_mask = (1 << gpio.ucDataY_Shift); i2c.y_data_mask = (1 << gpio->ucDataY_Shift);
i2c.a_clk_mask = (1 << gpio.ucClkA_Shift); i2c.a_clk_mask = (1 << gpio->ucClkA_Shift);
i2c.a_data_mask = (1 << gpio.ucDataA_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.valid = true; i2c.valid = true;
return i2c; return i2c;
...@@ -276,7 +289,6 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) ...@@ -276,7 +289,6 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
uint16_t igp_lane_info, conn_id, connector_object_id; uint16_t igp_lane_info, conn_id, connector_object_id;
bool linkb; bool linkb;
struct radeon_i2c_bus_rec ddc_bus; struct radeon_i2c_bus_rec ddc_bus;
ATOM_I2C_ID_CONFIG_ACCESS i2c_id;
atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset); atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset);
if (data_offset == 0) if (data_offset == 0)
...@@ -302,7 +314,6 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) ...@@ -302,7 +314,6 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
path = (ATOM_DISPLAY_OBJECT_PATH *) addr; path = (ATOM_DISPLAY_OBJECT_PATH *) addr;
path_size += le16_to_cpu(path->usSize); path_size += le16_to_cpu(path->usSize);
linkb = false; linkb = false;
i2c_id.ucAccess = 0;
if (device_support & le16_to_cpu(path->usDeviceTag)) { if (device_support & le16_to_cpu(path->usDeviceTag)) {
uint8_t con_obj_id, con_obj_num, con_obj_type; uint8_t con_obj_id, con_obj_num, con_obj_type;
...@@ -431,7 +442,6 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) ...@@ -431,7 +442,6 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
i2c_record = i2c_record =
(ATOM_I2C_RECORD (ATOM_I2C_RECORD
*) record; *) record;
i2c_id.sbfAccess = i2c_record->sucI2cId;
line_mux = line_mux =
i2c_record-> i2c_record->
sucI2cId. sucI2cId.
...@@ -474,7 +484,7 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) ...@@ -474,7 +484,7 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
usDeviceTag), usDeviceTag),
connector_type, &ddc_bus, connector_type, &ddc_bus,
linkb, igp_lane_info, linkb, igp_lane_info,
connector_object_id, i2c_id.ucAccess); connector_object_id);
} }
} }
...@@ -693,7 +703,7 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct ...@@ -693,7 +703,7 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
connector_type, connector_type,
&bios_connectors[i].ddc_bus, &bios_connectors[i].ddc_bus,
false, 0, false, 0,
connector_object_id, 0); connector_object_id);
} }
} }
......
This diff is collapsed.
...@@ -952,7 +952,7 @@ radeon_add_atom_connector(struct drm_device *dev, ...@@ -952,7 +952,7 @@ radeon_add_atom_connector(struct drm_device *dev,
struct radeon_i2c_bus_rec *i2c_bus, struct radeon_i2c_bus_rec *i2c_bus,
bool linkb, bool linkb,
uint32_t igp_lane_info, uint32_t igp_lane_info,
uint16_t connector_object_id, uint8_t uc_i2c_id) uint16_t connector_object_id)
{ {
struct radeon_device *rdev = dev->dev_private; struct radeon_device *rdev = dev->dev_private;
struct drm_connector *connector; struct drm_connector *connector;
...@@ -1083,8 +1083,7 @@ radeon_add_atom_connector(struct drm_device *dev, ...@@ -1083,8 +1083,7 @@ radeon_add_atom_connector(struct drm_device *dev,
if (ret) if (ret)
goto failed; goto failed;
/* add DP i2c bus */ /* add DP i2c bus */
radeon_dig_connector->uc_i2c_id = uc_i2c_id; radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch");
radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, "DP-auxch", true, uc_i2c_id);
if (i2c_bus->valid) { if (i2c_bus->valid) {
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DP"); radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DP");
if (!radeon_connector->ddc_bus) if (!radeon_connector->ddc_bus)
......
...@@ -69,6 +69,7 @@ void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state) ...@@ -69,6 +69,7 @@ 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 * 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 * doing DDC - do this for all r200s/r300s/r400s for safety sake
*/ */
if (rec->hw_capable) {
if ((rdev->family >= CHIP_R200) && !ASIC_IS_AVIVO(rdev)) { if ((rdev->family >= CHIP_R200) && !ASIC_IS_AVIVO(rdev)) {
if (rec->a_clk_reg == RADEON_GPIO_MONID) { if (rec->a_clk_reg == RADEON_GPIO_MONID) {
WREG32(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST | WREG32(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST |
...@@ -78,6 +79,7 @@ void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state) ...@@ -78,6 +79,7 @@ void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state)
R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3))); R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3)));
} }
} }
}
/* clear the output pin values */ /* clear the output pin values */
temp = RREG32(rec->a_clk_reg) & ~rec->a_clk_mask; temp = RREG32(rec->a_clk_reg) & ~rec->a_clk_mask;
...@@ -86,6 +88,12 @@ void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state) ...@@ -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; temp = RREG32(rec->a_data_reg) & ~rec->a_data_mask;
WREG32(rec->a_data_reg, temp); 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 */ /* mask the gpio pins for software use */
temp = RREG32(rec->mask_clk_reg); temp = RREG32(rec->mask_clk_reg);
...@@ -199,7 +207,8 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev, ...@@ -199,7 +207,8 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
} }
struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev, struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev,
const char *name, bool dp, u8 i2c_id) struct radeon_i2c_bus_rec *rec,
const char *name)
{ {
struct radeon_i2c_chan *i2c; struct radeon_i2c_chan *i2c;
int ret; int ret;
...@@ -208,7 +217,7 @@ struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev, ...@@ -208,7 +217,7 @@ struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev,
if (i2c == NULL) if (i2c == NULL)
return NULL; return NULL;
i2c->i2c_id = i2c_id; i2c->rec = *rec;
i2c->adapter.owner = THIS_MODULE; i2c->adapter.owner = THIS_MODULE;
i2c->dev = dev; i2c->dev = dev;
i2c_set_adapdata(&i2c->adapter, i2c); i2c_set_adapdata(&i2c->adapter, i2c);
......
...@@ -106,6 +106,13 @@ enum radeon_tv_std { ...@@ -106,6 +106,13 @@ enum radeon_tv_std {
*/ */
struct radeon_i2c_bus_rec { struct radeon_i2c_bus_rec {
bool valid; 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_clk_reg;
uint32_t mask_data_reg; uint32_t mask_data_reg;
uint32_t a_clk_reg; uint32_t a_clk_reg;
...@@ -172,7 +179,6 @@ struct radeon_i2c_chan { ...@@ -172,7 +179,6 @@ struct radeon_i2c_chan {
struct i2c_algo_bit_data bit; struct i2c_algo_bit_data bit;
} algo; } algo;
struct radeon_i2c_bus_rec rec; struct radeon_i2c_bus_rec rec;
uint8_t i2c_id;
}; };
/* mostly for macs, but really any system without connector tables */ /* mostly for macs, but really any system without connector tables */
...@@ -333,7 +339,6 @@ struct radeon_encoder { ...@@ -333,7 +339,6 @@ struct radeon_encoder {
struct radeon_connector_atom_dig { struct radeon_connector_atom_dig {
uint32_t igp_lane_info; uint32_t igp_lane_info;
bool linkb; bool linkb;
uint16_t uc_i2c_id;
struct radeon_i2c_chan *dp_i2c_bus; struct radeon_i2c_chan *dp_i2c_bus;
u8 dpcd[8]; u8 dpcd[8];
}; };
...@@ -352,8 +357,6 @@ struct radeon_connector { ...@@ -352,8 +357,6 @@ struct radeon_connector {
void *con_priv; void *con_priv;
bool dac_load_detect; bool dac_load_detect;
uint16_t connector_object_id; uint16_t connector_object_id;
/* need to keep this for display port */
//
}; };
struct radeon_framebuffer { struct radeon_framebuffer {
...@@ -362,12 +365,13 @@ struct radeon_framebuffer { ...@@ -362,12 +365,13 @@ struct radeon_framebuffer {
}; };
extern int radeon_dp_getsinktype(struct radeon_connector *radeon_connector); extern int radeon_dp_getsinktype(struct radeon_connector *radeon_connector);
extern void radeon_dp_getdpcd(struct radeon_connector *connector); extern void radeon_dp_getdpcd(struct radeon_connector *radeon_connector);
extern int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, extern int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
uint8_t write_byte, uint8_t *read_byte); uint8_t write_byte, uint8_t *read_byte);
extern struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev, extern struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev,
const char *name, bool dp, u8 i2c_id); struct radeon_i2c_bus_rec *rec,
const char *name);
extern struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev, extern struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
struct radeon_i2c_bus_rec *rec, struct radeon_i2c_bus_rec *rec,
const char *name); const char *name);
......
...@@ -1148,16 +1148,16 @@ ...@@ -1148,16 +1148,16 @@
# define RADEON_IO_MCLK_MAX_DYN_STOP_LAT (1 << 13) # define RADEON_IO_MCLK_MAX_DYN_STOP_LAT (1 << 13)
# define RADEON_MC_MCLK_DYN_ENABLE (1 << 14) # define RADEON_MC_MCLK_DYN_ENABLE (1 << 14)
# define RADEON_IO_MCLK_DYN_ENABLE (1 << 15) # define RADEON_IO_MCLK_DYN_ENABLE (1 << 15)
#define RADEON_GPIOPAD_MASK 0x0198 #define RADEON_GPIOPAD_MASK 0x0198
#define RADEON_GPIOPAD_A 0x019c #define RADEON_GPIOPAD_A 0x019c
#define RADEON_GPIOPAD_EN 0x01a0 #define RADEON_GPIOPAD_EN 0x01a0
#define RADEON_GPIOPAD_Y 0x01a4 #define RADEON_GPIOPAD_Y 0x01a4
#define RADEON_LCD_GPIO_MASK 0x01a0 #define RADEON_MDGPIO_MASK 0x01a8
#define RADEON_LCD_GPIO_Y_REG 0x01a4 #define RADEON_MDGPIO_A 0x01ac
#define RADEON_MDGPIO_A_REG 0x01ac #define RADEON_MDGPIO_EN 0x01b0
#define RADEON_MDGPIO_EN_REG 0x01b0 #define RADEON_MDGPIO_Y 0x01b4
#define RADEON_MDGPIO_MASK 0x0198
#define RADEON_MDGPIO_Y_REG 0x01b4
#define RADEON_MEM_ADDR_CONFIG 0x0148 #define RADEON_MEM_ADDR_CONFIG 0x0148
#define RADEON_MEM_BASE 0x0f10 /* PCI */ #define RADEON_MEM_BASE 0x0f10 /* PCI */
#define RADEON_MEM_CNTL 0x0140 #define RADEON_MEM_CNTL 0x0140
......
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