aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/radeon
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/radeon')
-rw-r--r--drivers/gpu/drm/radeon/r600_cp.c2
-rw-r--r--drivers/gpu/drm/radeon/r600_cs.c33
-rw-r--r--drivers/gpu/drm/radeon/radeon.h2
-rw-r--r--drivers/gpu/drm/radeon/radeon_atombios.c180
-rw-r--r--drivers/gpu/drm/radeon/radeon_clocks.c81
-rw-r--r--drivers/gpu/drm/radeon/radeon_combios.c388
-rw-r--r--drivers/gpu/drm/radeon/radeon_connectors.c45
-rw-r--r--drivers/gpu/drm/radeon/radeon_cs.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_cursor.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_device.c3
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c34
-rw-r--r--drivers/gpu/drm/radeon/radeon_gem.c12
-rw-r--r--drivers/gpu/drm/radeon/radeon_i2c.c82
-rw-r--r--drivers/gpu/drm/radeon/radeon_kms.c28
-rw-r--r--drivers/gpu/drm/radeon/radeon_mode.h24
-rw-r--r--drivers/gpu/drm/radeon/radeon_pm.c24
-rw-r--r--drivers/gpu/drm/radeon/reg_srcs/rv5151
17 files changed, 650 insertions, 293 deletions
diff --git a/drivers/gpu/drm/radeon/r600_cp.c b/drivers/gpu/drm/radeon/r600_cp.c
index 68e6f434930..4f4cd8b286d 100644
--- a/drivers/gpu/drm/radeon/r600_cp.c
+++ b/drivers/gpu/drm/radeon/r600_cp.c
@@ -200,7 +200,7 @@ int r600_page_table_init(struct drm_device *dev)
entry->pagelist[i], 0,
PAGE_SIZE,
PCI_DMA_BIDIRECTIONAL);
- if (entry->busaddr[i] == 0) {
+ if (pci_dma_mapping_error(dev->pdev, entry->busaddr[i])) {
DRM_ERROR("unable to map PCIGART pages!\n");
r600_page_table_cleanup(dev, gart_info);
goto done;
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c
index c3ea212e0c3..d8864949e38 100644
--- a/drivers/gpu/drm/radeon/r600_cs.c
+++ b/drivers/gpu/drm/radeon/r600_cs.c
@@ -133,6 +133,7 @@ static inline int r600_bpe_from_format(u32 *bpe, u32 format)
case V_038004_FMT_GB_GR:
case V_038004_FMT_BG_RG:
case V_038004_COLOR_INVALID:
+ default:
*bpe = 16;
return -EINVAL;
}
@@ -174,7 +175,7 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
dev_warn(p->dev, "FMASK or CMASK buffer are not supported by this kernel\n");
return -EINVAL;
}
- size = radeon_bo_size(track->cb_color_bo[i]);
+ size = radeon_bo_size(track->cb_color_bo[i]) - track->cb_color_bo_offset[i];
if (r600_bpe_from_format(&bpe, G_0280A0_FORMAT(track->cb_color_info[i]))) {
dev_warn(p->dev, "%s:%d cb invalid format %d for %d (0x%08X)\n",
__func__, __LINE__, G_0280A0_FORMAT(track->cb_color_info[i]),
@@ -327,7 +328,6 @@ static int r600_cs_track_check(struct radeon_cs_parser *p)
dev_warn(p->dev, "z/stencil buffer size not set\n");
return -EINVAL;
}
- printk_once(KERN_WARNING "You have old & broken userspace please consider updating mesa\n");
tmp = radeon_bo_size(track->db_bo) - track->db_offset;
tmp = (tmp / bpe) >> 6;
if (!tmp) {
@@ -882,8 +882,6 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx
return -EINVAL;
}
ib[idx] = track->cb_color_base_last[tmp];
- printk_once(KERN_WARNING "You have old & broken userspace "
- "please consider updating mesa & xf86-video-ati\n");
track->cb_color_frag_bo[tmp] = track->cb_color_bo[tmp];
} else {
r = r600_cs_packet_next_reloc(p, &reloc);
@@ -910,8 +908,6 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx
return -EINVAL;
}
ib[idx] = track->cb_color_base_last[tmp];
- printk_once(KERN_WARNING "You have old & broken userspace "
- "please consider updating mesa & xf86-video-ati\n");
track->cb_color_tile_bo[tmp] = track->cb_color_bo[tmp];
} else {
r = r600_cs_packet_next_reloc(p, &reloc);
@@ -938,7 +934,7 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx
return -EINVAL;
}
tmp = (reg - CB_COLOR0_BASE) / 4;
- track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx);
+ track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8;
ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
track->cb_color_base_last[tmp] = ib[idx];
track->cb_color_bo[tmp] = reloc->robj;
@@ -950,7 +946,7 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx
"0x%04X\n", reg);
return -EINVAL;
}
- track->db_offset = radeon_get_ib_value(p, idx);
+ track->db_offset = radeon_get_ib_value(p, idx) << 8;
ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
track->db_bo = reloc->robj;
break;
@@ -1055,10 +1051,10 @@ static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned nlevels
}
*l0_size = ALIGN((w0 * bpe), pitch_align) * h0 * d0;
*mipmap_size = offset;
- if (!blevel)
- *mipmap_size -= *l0_size;
if (!nlevels)
*mipmap_size = *l0_size;
+ if (!blevel)
+ *mipmap_size -= *l0_size;
}
/**
@@ -1165,14 +1161,14 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 i
(pitch_align * bpe),
&l0_size, &mipmap_size);
/* using get ib will give us the offset into the texture bo */
- word0 = radeon_get_ib_value(p, idx + 2);
+ word0 = radeon_get_ib_value(p, idx + 2) << 8;
if ((l0_size + word0) > radeon_bo_size(texture)) {
dev_warn(p->dev, "texture bo too small (%d %d %d %d -> %d have %ld)\n",
w0, h0, bpe, word0, l0_size, radeon_bo_size(texture));
return -EINVAL;
}
/* using get ib will give us the offset into the mipmap bo */
- word0 = radeon_get_ib_value(p, idx + 3);
+ word0 = radeon_get_ib_value(p, idx + 3) << 8;
if ((mipmap_size + word0) > radeon_bo_size(mipmap)) {
dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n",
w0, h0, bpe, blevel, nlevels, word0, mipmap_size, radeon_bo_size(texture));
@@ -1366,7 +1362,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
}
for (i = 0; i < (pkt->count / 7); i++) {
struct radeon_bo *texture, *mipmap;
- u32 size, offset;
+ u32 size, offset, base_offset, mip_offset;
switch (G__SQ_VTX_CONSTANT_TYPE(radeon_get_ib_value(p, idx+(i*7)+6+1))) {
case SQ_TEX_VTX_VALID_TEXTURE:
@@ -1376,7 +1372,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
DRM_ERROR("bad SET_RESOURCE\n");
return -EINVAL;
}
- ib[idx+1+(i*7)+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+ base_offset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1);
else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
@@ -1388,12 +1384,14 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
DRM_ERROR("bad SET_RESOURCE\n");
return -EINVAL;
}
- ib[idx+1+(i*7)+3] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+ mip_offset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
mipmap = reloc->robj;
r = r600_check_texture_resource(p, idx+(i*7)+1,
texture, mipmap, reloc->lobj.tiling_flags);
if (r)
return r;
+ ib[idx+1+(i*7)+2] += base_offset;
+ ib[idx+1+(i*7)+3] += mip_offset;
break;
case SQ_TEX_VTX_VALID_BUFFER:
/* vtx base */
@@ -1403,10 +1401,11 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
return -EINVAL;
}
offset = radeon_get_ib_value(p, idx+1+(i*7)+0);
- size = radeon_get_ib_value(p, idx+1+(i*7)+1);
+ size = radeon_get_ib_value(p, idx+1+(i*7)+1) + 1;
if (p->rdev && (size + offset) > radeon_bo_size(reloc->robj)) {
/* force size to size of the buffer */
- dev_warn(p->dev, "vbo resource seems too big for the bo\n");
+ dev_warn(p->dev, "vbo resource seems too big (%d) for the bo (%ld)\n",
+ size + offset, radeon_bo_size(reloc->robj));
ib[idx+1+(i*7)+1] = radeon_bo_size(reloc->robj);
}
ib[idx+1+(i*7)+0] += (u32)((reloc->lobj.gpu_offset) & 0xffffffff);
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 3cd1c470b77..3dfcfa3ca42 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -1100,6 +1100,8 @@ struct radeon_device {
struct notifier_block acpi_nb;
/* only one userspace can use Hyperz features at a time */
struct drm_file *hyperz_filp;
+ /* i2c buses */
+ struct radeon_i2c_chan *i2c_bus[RADEON_MAX_I2C_BUS];
};
int radeon_device_init(struct radeon_device *rdev,
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index 3bc2bcdf530..6d30868744e 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -48,7 +48,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,
- struct radeon_hpd *hpd);
+ struct radeon_hpd *hpd,
+ struct radeon_router *router);
/* from radeon_legacy_encoder.c */
extern void
@@ -114,7 +115,8 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_dev
i2c.i2c_id = gpio->sucI2cId.ucAccess;
- i2c.valid = true;
+ if (i2c.mask_clk_reg)
+ i2c.valid = true;
break;
}
}
@@ -123,6 +125,66 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_dev
return i2c;
}
+void radeon_atombios_i2c_init(struct radeon_device *rdev)
+{
+ struct atom_context *ctx = rdev->mode_info.atom_context;
+ 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;
+ uint16_t data_offset, size;
+ int i, num_indices;
+ char stmp[32];
+
+ memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec));
+
+ if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) {
+ i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset);
+
+ num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
+ sizeof(ATOM_GPIO_I2C_ASSIGMENT);
+
+ for (i = 0; i < num_indices; i++) {
+ gpio = &i2c_info->asGPIO_Info[i];
+ i2c.valid = false;
+ 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;
+
+ if (i2c.mask_clk_reg) {
+ i2c.valid = true;
+ sprintf(stmp, "0x%x", i2c.i2c_id);
+ rdev->i2c_bus[i] = radeon_i2c_create(rdev->ddev, &i2c, stmp);
+ }
+ }
+ }
+}
+
static inline struct radeon_gpio_rec radeon_lookup_gpio(struct radeon_device *rdev,
u8 id)
{
@@ -206,6 +268,7 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev,
uint16_t *line_mux,
struct radeon_hpd *hpd)
{
+ struct radeon_device *rdev = dev->dev_private;
/* Asus M2A-VM HDMI board lists the DVI port as HDMI */
if ((dev->pdev->device == 0x791e) &&
@@ -308,13 +371,22 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev,
}
}
- /* Acer laptop reports DVI-D as DVI-I */
+ /* Acer laptop reports DVI-D as DVI-I and hpd pins reversed */
if ((dev->pdev->device == 0x95c4) &&
(dev->pdev->subsystem_vendor == 0x1025) &&
(dev->pdev->subsystem_device == 0x013c)) {
+ struct radeon_gpio_rec gpio;
+
if ((*connector_type == DRM_MODE_CONNECTOR_DVII) &&
- (supported_device == ATOM_DEVICE_DFP1_SUPPORT))
+ (supported_device == ATOM_DEVICE_DFP1_SUPPORT)) {
+ gpio = radeon_lookup_gpio(rdev, 6);
+ *hpd = radeon_atom_get_hpd_info_from_gpio(rdev, &gpio);
*connector_type = DRM_MODE_CONNECTOR_DVID;
+ } else if ((*connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
+ (supported_device == ATOM_DEVICE_DFP1_SUPPORT)) {
+ gpio = radeon_lookup_gpio(rdev, 7);
+ *hpd = radeon_atom_get_hpd_info_from_gpio(rdev, &gpio);
+ }
}
/* XFX Pine Group device rv730 reports no VGA DDC lines
@@ -399,13 +471,15 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
u16 size, data_offset;
u8 frev, crev;
ATOM_CONNECTOR_OBJECT_TABLE *con_obj;
+ ATOM_OBJECT_TABLE *router_obj;
ATOM_DISPLAY_OBJECT_PATH_TABLE *path_obj;
ATOM_OBJECT_HEADER *obj_header;
- int i, j, path_size, device_support;
+ int i, j, k, path_size, device_support;
int connector_type;
u16 igp_lane_info, conn_id, connector_object_id;
bool linkb;
struct radeon_i2c_bus_rec ddc_bus;
+ struct radeon_router router;
struct radeon_gpio_rec gpio;
struct radeon_hpd hpd;
@@ -415,6 +489,8 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
if (crev < 2)
return false;
+ router.valid = false;
+
obj_header = (ATOM_OBJECT_HEADER *) (ctx->bios + data_offset);
path_obj = (ATOM_DISPLAY_OBJECT_PATH_TABLE *)
(ctx->bios + data_offset +
@@ -422,6 +498,9 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
con_obj = (ATOM_CONNECTOR_OBJECT_TABLE *)
(ctx->bios + data_offset +
le16_to_cpu(obj_header->usConnectorObjectTableOffset));
+ router_obj = (ATOM_OBJECT_TABLE *)
+ (ctx->bios + data_offset +
+ le16_to_cpu(obj_header->usRouterObjectTableOffset));
device_support = le16_to_cpu(obj_header->usDeviceSupport);
path_size = 0;
@@ -508,33 +587,86 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
if (connector_type == DRM_MODE_CONNECTOR_Unknown)
continue;
- for (j = 0; j < ((le16_to_cpu(path->usSize) - 8) / 2);
- j++) {
- uint8_t enc_obj_id, enc_obj_num, enc_obj_type;
+ for (j = 0; j < ((le16_to_cpu(path->usSize) - 8) / 2); j++) {
+ uint8_t grph_obj_id, grph_obj_num, grph_obj_type;
- enc_obj_id =
+ grph_obj_id =
(le16_to_cpu(path->usGraphicObjIds[j]) &
OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
- enc_obj_num =
+ grph_obj_num =
(le16_to_cpu(path->usGraphicObjIds[j]) &
ENUM_ID_MASK) >> ENUM_ID_SHIFT;
- enc_obj_type =
+ grph_obj_type =
(le16_to_cpu(path->usGraphicObjIds[j]) &
OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT;
- /* FIXME: add support for router objects */
- if (enc_obj_type == GRAPH_OBJECT_TYPE_ENCODER) {
- if (enc_obj_num == 2)
+ if (grph_obj_type == GRAPH_OBJECT_TYPE_ENCODER) {
+ if (grph_obj_num == 2)
linkb = true;
else
linkb = false;
radeon_add_atom_encoder(dev,
- enc_obj_id,
+ grph_obj_id,
le16_to_cpu
(path->
usDeviceTag));
+ } else if (grph_obj_type == GRAPH_OBJECT_TYPE_ROUTER) {
+ router.valid = false;
+ for (k = 0; k < router_obj->ucNumberOfObjects; k++) {
+ u16 router_obj_id = le16_to_cpu(router_obj->asObjects[j].usObjectID);
+ if (le16_to_cpu(path->usGraphicObjIds[j]) == router_obj_id) {
+ ATOM_COMMON_RECORD_HEADER *record = (ATOM_COMMON_RECORD_HEADER *)
+ (ctx->bios + data_offset +
+ le16_to_cpu(router_obj->asObjects[k].usRecordOffset));
+ ATOM_I2C_RECORD *i2c_record;
+ ATOM_I2C_ID_CONFIG_ACCESS *i2c_config;
+ ATOM_ROUTER_DDC_PATH_SELECT_RECORD *ddc_path;
+ ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *router_src_dst_table =
+ (ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *)
+ (ctx->bios + data_offset +
+ le16_to_cpu(router_obj->asObjects[k].usSrcDstTableOffset));
+ int enum_id;
+
+ router.router_id = router_obj_id;
+ for (enum_id = 0; enum_id < router_src_dst_table->ucNumberOfDst;
+ enum_id++) {
+ if (le16_to_cpu(path->usConnObjectId) ==
+ le16_to_cpu(router_src_dst_table->usDstObjectID[enum_id]))
+ break;
+ }
+
+ while (record->ucRecordType > 0 &&
+ record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) {
+ switch (record->ucRecordType) {
+ case ATOM_I2C_RECORD_TYPE:
+ i2c_record =
+ (ATOM_I2C_RECORD *)
+ record;
+ i2c_config =
+ (ATOM_I2C_ID_CONFIG_ACCESS *)
+ &i2c_record->sucI2cId;
+ router.i2c_info =
+ radeon_lookup_i2c_gpio(rdev,
+ i2c_config->
+ ucAccess);
+ router.i2c_addr = i2c_record->ucI2CAddr >> 1;
+ break;
+ case ATOM_ROUTER_DDC_PATH_SELECT_RECORD_TYPE:
+ ddc_path = (ATOM_ROUTER_DDC_PATH_SELECT_RECORD *)
+ record;
+ router.valid = true;
+ router.mux_type = ddc_path->ucMuxType;
+ router.mux_control_pin = ddc_path->ucMuxControlPin;
+ router.mux_state = ddc_path->ucMuxState[enum_id];
+ break;
+ }
+ record = (ATOM_COMMON_RECORD_HEADER *)
+ ((char *)record + record->ucRecordSize);
+ }
+ }
+ }
}
}
@@ -614,7 +746,8 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
connector_type, &ddc_bus,
linkb, igp_lane_info,
connector_object_id,
- &hpd);
+ &hpd,
+ &router);
}
}
@@ -691,6 +824,9 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
int i, j, max_device;
struct bios_connector *bios_connectors;
size_t bc_size = sizeof(*bios_connectors) * ATOM_MAX_SUPPORTED_DEVICE;
+ struct radeon_router router;
+
+ router.valid = false;
bios_connectors = kzalloc(bc_size, GFP_KERNEL);
if (!bios_connectors)
@@ -862,7 +998,8 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
&bios_connectors[i].ddc_bus,
false, 0,
connector_object_id,
- &bios_connectors[i].hpd);
+ &bios_connectors[i].hpd,
+ &router);
}
}
@@ -1521,7 +1658,7 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
thermal_controller_names[power_info->info.ucOverdriveThermalController],
power_info->info.ucOverdriveControllerAddress >> 1);
i2c_bus = radeon_lookup_i2c_gpio(rdev, power_info->info.ucOverdriveI2cLine);
- rdev->pm.i2c_bus = radeon_i2c_create(rdev->ddev, &i2c_bus, "Thermal");
+ rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus);
if (rdev->pm.i2c_bus) {
struct i2c_board_info info = { };
const char *name = thermal_controller_names[power_info->info.
@@ -1814,7 +1951,7 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
(controller->ucFanParameters &
ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
i2c_bus = radeon_lookup_i2c_gpio(rdev, controller->ucI2cLine);
- rdev->pm.i2c_bus = radeon_i2c_create(rdev->ddev, &i2c_bus, "Thermal");
+ rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus);
if (rdev->pm.i2c_bus) {
struct i2c_board_info info = { };
const char *name = pp_lib_thermal_controller_names[controller->ucType];
@@ -1927,6 +2064,11 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
rdev->pm.power_state[state_index].type =
POWER_STATE_TYPE_PERFORMANCE;
break;
+ case ATOM_PPLIB_CLASSIFICATION_UI_NONE:
+ if (misc2 & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE)
+ rdev->pm.power_state[state_index].type =
+ POWER_STATE_TYPE_PERFORMANCE;
+ break;
}
rdev->pm.power_state[state_index].flags = 0;
if (misc & ATOM_PPLIB_SINGLE_DISPLAY_ONLY)
diff --git a/drivers/gpu/drm/radeon/radeon_clocks.c b/drivers/gpu/drm/radeon/radeon_clocks.c
index f64936cc4dd..14448a740ba 100644
--- a/drivers/gpu/drm/radeon/radeon_clocks.c
+++ b/drivers/gpu/drm/radeon/radeon_clocks.c
@@ -91,6 +91,85 @@ uint32_t radeon_legacy_get_memory_clock(struct radeon_device *rdev)
return mclk;
}
+#ifdef CONFIG_OF
+/*
+ * Read XTAL (ref clock), SCLK and MCLK from Open Firmware device
+ * tree. Hopefully, ATI OF driver is kind enough to fill these
+ */
+static bool __devinit radeon_read_clocks_OF(struct drm_device *dev)
+{
+ struct radeon_device *rdev = dev->dev_private;
+ struct device_node *dp = rdev->pdev->dev.of_node;
+ const u32 *val;
+ struct radeon_pll *p1pll = &rdev->clock.p1pll;
+ struct radeon_pll *p2pll = &rdev->clock.p2pll;
+ struct radeon_pll *spll = &rdev->clock.spll;
+ struct radeon_pll *mpll = &rdev->clock.mpll;
+
+ if (dp == NULL)
+ return false;
+ val = of_get_property(dp, "ATY,RefCLK", NULL);
+ if (!val || !*val) {
+ printk(KERN_WARNING "radeonfb: No ATY,RefCLK property !\n");
+ return false;
+ }
+ p1pll->reference_freq = p2pll->reference_freq = (*val) / 10;
+ p1pll->reference_div = RREG32_PLL(RADEON_PPLL_REF_DIV) & 0x3ff;
+ if (p1pll->reference_div < 2)
+ p1pll->reference_div = 12;
+ p2pll->reference_div = p1pll->reference_div;
+
+ /* These aren't in the device-tree */
+ if (rdev->family >= CHIP_R420) {
+ p1pll->pll_in_min = 100;
+ p1pll->pll_in_max = 1350;
+ p1pll->pll_out_min = 20000;
+ p1pll->pll_out_max = 50000;
+ p2pll->pll_in_min = 100;
+ p2pll->pll_in_max = 1350;
+ p2pll->pll_out_min = 20000;
+ p2pll->pll_out_max = 50000;
+ } else {
+ p1pll->pll_in_min = 40;
+ p1pll->pll_in_max = 500;
+ p1pll->pll_out_min = 12500;
+ p1pll->pll_out_max = 35000;
+ p2pll->pll_in_min = 40;
+ p2pll->pll_in_max = 500;
+ p2pll->pll_out_min = 12500;
+ p2pll->pll_out_max = 35000;
+ }
+
+ spll->reference_freq = mpll->reference_freq = p1pll->reference_freq;
+ spll->reference_div = mpll->reference_div =
+ RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) &
+ RADEON_M_SPLL_REF_DIV_MASK;
+
+ val = of_get_property(dp, "ATY,SCLK", NULL);
+ if (val && *val)
+ rdev->clock.default_sclk = (*val) / 10;
+ else
+ rdev->clock.default_sclk =
+ radeon_legacy_get_engine_clock(rdev);
+
+ val = of_get_property(dp, "ATY,MCLK", NULL);
+ if (val && *val)
+ rdev->clock.default_mclk = (*val) / 10;
+ else
+ rdev->clock.default_mclk =
+ radeon_legacy_get_memory_clock(rdev);
+
+ DRM_INFO("Using device-tree clock info\n");
+
+ return true;
+}
+#else
+static bool __devinit radeon_read_clocks_OF(struct drm_device *dev)
+{
+ return false;
+}
+#endif /* CONFIG_OF */
+
void radeon_get_clock_info(struct drm_device *dev)
{
struct radeon_device *rdev = dev->dev_private;
@@ -105,6 +184,8 @@ void radeon_get_clock_info(struct drm_device *dev)
ret = radeon_atom_get_clock_info(dev);
else
ret = radeon_combios_get_clock_info(dev);
+ if (!ret)
+ ret = radeon_read_clocks_OF(dev);
if (ret) {
if (p1pll->reference_div < 2) {
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c
index 5e1474cde4b..885dcfac183 100644
--- a/drivers/gpu/drm/radeon/radeon_combios.c
+++ b/drivers/gpu/drm/radeon/radeon_combios.c
@@ -480,9 +480,66 @@ radeon_combios_get_hardcoded_edid(struct radeon_device *rdev)
}
static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rdev,
- int ddc_line)
+ enum radeon_combios_ddc ddc,
+ u32 clk_mask,
+ u32 data_mask)
{
struct radeon_i2c_bus_rec i2c;
+ int ddc_line = 0;
+
+ /* ddc id = mask reg
+ * DDC_NONE_DETECTED = none
+ * DDC_DVI = RADEON_GPIO_DVI_DDC
+ * DDC_VGA = RADEON_GPIO_VGA_DDC
+ * DDC_LCD = RADEON_GPIOPAD_MASK
+ * DDC_GPIO = RADEON_MDGPIO_MASK
+ * r1xx/r2xx
+ * DDC_MONID = RADEON_GPIO_MONID
+ * DDC_CRT2 = RADEON_GPIO_CRT2_DDC
+ * r3xx
+ * DDC_MONID = RADEON_GPIO_MONID
+ * DDC_CRT2 = RADEON_GPIO_DVI_DDC
+ * rs3xx/rs4xx
+ * DDC_MONID = RADEON_GPIOPAD_MASK
+ * DDC_CRT2 = RADEON_GPIO_MONID
+ */
+ switch (ddc) {
+ case DDC_NONE_DETECTED:
+ default:
+ ddc_line = 0;
+ break;
+ case DDC_DVI:
+ ddc_line = RADEON_GPIO_DVI_DDC;
+ break;
+ case DDC_VGA:
+ ddc_line = RADEON_GPIO_VGA_DDC;
+ break;
+ case DDC_LCD:
+ ddc_line = RADEON_GPIOPAD_MASK;
+ break;
+ case DDC_GPIO:
+ ddc_line = RADEON_MDGPIO_MASK;
+ break;
+ case DDC_MONID:
+ if (rdev->family == CHIP_RS300 ||
+ rdev->family == CHIP_RS400 ||
+ rdev->family == CHIP_RS480)
+ ddc_line = RADEON_GPIOPAD_MASK;
+ else
+ ddc_line = RADEON_GPIO_MONID;
+ break;
+ case DDC_CRT2:
+ if (rdev->family == CHIP_RS300 ||
+ rdev->family == CHIP_RS400 ||
+ rdev->family == CHIP_RS480)
+ ddc_line = RADEON_GPIO_MONID;
+ else if (rdev->family >= CHIP_R300) {
+ ddc_line = RADEON_GPIO_DVI_DDC;
+ ddc = DDC_DVI;
+ } else
+ ddc_line = RADEON_GPIO_CRT2_DDC;
+ break;
+ }
if (ddc_line == RADEON_GPIOPAD_MASK) {
i2c.mask_clk_reg = RADEON_GPIOPAD_MASK;
@@ -503,15 +560,6 @@ static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rde
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;
@@ -522,6 +570,26 @@ static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rde
i2c.y_data_reg = ddc_line;
}
+ if (clk_mask && data_mask) {
+ i2c.mask_clk_mask = clk_mask;
+ i2c.mask_data_mask = data_mask;
+ i2c.a_clk_mask = clk_mask;
+ i2c.a_data_mask = data_mask;
+ i2c.en_clk_mask = clk_mask;
+ i2c.en_data_mask = data_mask;
+ i2c.y_clk_mask = clk_mask;
+ i2c.y_data_mask = data_mask;
+ } 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;
+ }
+
switch (rdev->family) {
case CHIP_R100:
case CHIP_RV100:
@@ -599,7 +667,8 @@ static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rde
break;
}
i2c.mm_i2c = false;
- i2c.i2c_id = 0;
+
+ i2c.i2c_id = ddc;
i2c.hpd = RADEON_HPD_NONE;
if (ddc_line)
@@ -610,6 +679,62 @@ static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rde
return i2c;
}
+void radeon_combios_i2c_init(struct radeon_device *rdev)
+{
+ struct drm_device *dev = rdev->ddev;
+ struct radeon_i2c_bus_rec i2c;
+
+
+ i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0);
+ rdev->i2c_bus[0] = radeon_i2c_create(dev, &i2c, "DVI_DDC");
+
+ i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0);
+ rdev->i2c_bus[1] = radeon_i2c_create(dev, &i2c, "VGA_DDC");
+
+ i2c.valid = true;
+ i2c.hw_capable = true;
+ i2c.mm_i2c = true;
+ i2c.i2c_id = 0xa0;
+ rdev->i2c_bus[2] = radeon_i2c_create(dev, &i2c, "MM_I2C");
+
+ if (rdev->family == CHIP_RS300 ||
+ rdev->family == CHIP_RS400 ||
+ rdev->family == CHIP_RS480) {
+ u16 offset;
+ u8 id, blocks, clk, data;
+ int i;
+
+ i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0);
+ rdev->i2c_bus[3] = radeon_i2c_create(dev, &i2c, "MONID");
+
+ offset = combios_get_table_offset(dev, COMBIOS_I2C_INFO_TABLE);
+ if (offset) {
+ blocks = RBIOS8(offset + 2);
+ for (i = 0; i < blocks; i++) {
+ id = RBIOS8(offset + 3 + (i * 5) + 0);
+ if (id == 136) {
+ clk = RBIOS8(offset + 3 + (i * 5) + 3);
+ data = RBIOS8(offset + 3 + (i * 5) + 4);
+ i2c = combios_setup_i2c_bus(rdev, DDC_MONID,
+ clk, data);
+ rdev->i2c_bus[4] = radeon_i2c_create(dev, &i2c, "GPIOPAD_MASK");
+ break;
+ }
+ }
+ }
+
+ } else if (rdev->family >= CHIP_R300) {
+ i2c = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0);
+ rdev->i2c_bus[3] = radeon_i2c_create(dev, &i2c, "MONID");
+ } else {
+ i2c = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0);
+ rdev->i2c_bus[3] = radeon_i2c_create(dev, &i2c, "MONID");
+
+ i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0);
+ rdev->i2c_bus[4] = radeon_i2c_create(dev, &i2c, "CRT2_DDC");
+ }
+}
+
bool radeon_combios_get_clock_info(struct drm_device *dev)
{
struct radeon_device *rdev = dev->dev_private;
@@ -1247,8 +1372,8 @@ 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(rdev, RADEON_GPIO_MONID);
- tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO");
+ i2c_bus = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0);
+ tmds->i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus);
/* XXX some macs have duallink chips */
switch (rdev->mode_info.connector_table) {
@@ -1269,47 +1394,16 @@ bool radeon_legacy_get_ext_tmds_info_from_combios(struct radeon_encoder *encoder
struct drm_device *dev = encoder->base.dev;
struct radeon_device *rdev = dev->dev_private;
uint16_t offset;
- uint8_t ver, id, blocks, clk, data;
- int i;
+ uint8_t ver;
enum radeon_combios_ddc gpio;
struct radeon_i2c_bus_rec i2c_bus;
tmds->i2c_bus = NULL;
if (rdev->flags & RADEON_IS_IGP) {
- offset = combios_get_table_offset(dev, COMBIOS_I2C_INFO_TABLE);
- if (offset) {
- ver = RBIOS8(offset);
- DRM_INFO("GPIO Table revision: %d\n", ver);
- blocks = RBIOS8(offset + 2);
- for (i = 0; i < blocks; i++) {
- id = RBIOS8(offset + 3 + (i * 5) + 0);
- if (id == 136) {
- clk = RBIOS8(offset + 3 + (i * 5) + 3);
- data = RBIOS8(offset + 3 + (i * 5) + 4);
- i2c_bus.valid = true;
- i2c_bus.mask_clk_mask = (1 << clk);
- i2c_bus.mask_data_mask = (1 << data);
- i2c_bus.a_clk_mask = (1 << clk);
- i2c_bus.a_data_mask = (1 << data);
- i2c_bus.en_clk_mask = (1 << clk);
- i2c_bus.en_data_mask = (1 << data);
- i2c_bus.y_clk_mask = (1 << clk);
- i2c_bus.y_data_mask = (1 << data);
- i2c_bus.mask_clk_reg = RADEON_GPIOPAD_MASK;
- i2c_bus.mask_data_reg = RADEON_GPIOPAD_MASK;
- i2c_bus.a_clk_reg = RADEON_GPIOPAD_A;
- i2c_bus.a_data_reg = RADEON_GPIOPAD_A;
- i2c_bus.en_clk_reg = RADEON_GPIOPAD_EN;
- i2c_bus.en_data_reg = RADEON_GPIOPAD_EN;
- i2c_bus.y_clk_reg = RADEON_GPIOPAD_Y;
- i2c_bus.y_data_reg = RADEON_GPIOPAD_Y;
- tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO");
- tmds->dvo_chip = DVO_SIL164;
- tmds->slave_addr = 0x70 >> 1; /* 7 bit addressing */
- break;
- }
- }
- }
+ i2c_bus = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0);
+ tmds->i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus);
+ tmds->dvo_chip = DVO_SIL164;
+ tmds->slave_addr = 0x70 >> 1; /* 7 bit addressing */
} else {
offset = combios_get_table_offset(dev, COMBIOS_EXT_TMDS_INFO_TABLE);
if (offset) {
@@ -1318,37 +1412,15 @@ bool radeon_legacy_get_ext_tmds_info_from_combios(struct radeon_encoder *encoder
tmds->slave_addr = RBIOS8(offset + 4 + 2);
tmds->slave_addr >>= 1; /* 7 bit addressing */
gpio = RBIOS8(offset + 4 + 3);
- switch (gpio) {
- case DDC_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(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(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(rdev, RADEON_GPIO_MONID);
- else
- 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 */
+ if (gpio == DDC_LCD) {
+ /* MM i2c */
i2c_bus.valid = true;
i2c_bus.hw_capable = true;
i2c_bus.mm_i2c = true;