234,7 → 234,7 |
"INTERNAL_UNIPHY2", |
}; |
|
static const char *connector_names[13] = { |
static const char *connector_names[15] = { |
"Unknown", |
"VGA", |
"DVI-I", |
248,8 → 248,20 |
"DisplayPort", |
"HDMI-A", |
"HDMI-B", |
"TV", |
"eDP", |
}; |
|
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,16 → 276,27 |
radeon_connector = to_radeon_connector(connector); |
DRM_INFO("Connector %d:\n", i); |
DRM_INFO(" %s\n", connector_names[connector->connector_type]); |
if (radeon_connector->ddc_bus) |
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, |
radeon_connector->ddc_bus->rec.mask_data_reg, |
radeon_connector->ddc_bus->rec.a_clk_reg, |
radeon_connector->ddc_bus->rec.a_data_reg, |
radeon_connector->ddc_bus->rec.put_clk_reg, |
radeon_connector->ddc_bus->rec.put_data_reg, |
radeon_connector->ddc_bus->rec.get_clk_reg, |
radeon_connector->ddc_bus->rec.get_data_reg); |
radeon_connector->ddc_bus->rec.en_clk_reg, |
radeon_connector->ddc_bus->rec.en_data_reg, |
radeon_connector->ddc_bus->rec.y_clk_reg, |
radeon_connector->ddc_bus->rec.y_data_reg); |
} else { |
if (connector->connector_type == DRM_MODE_CONNECTOR_VGA || |
connector->connector_type == DRM_MODE_CONNECTOR_DVII || |
connector->connector_type == DRM_MODE_CONNECTOR_DVID || |
connector->connector_type == DRM_MODE_CONNECTOR_DVIA || |
connector->connector_type == DRM_MODE_CONNECTOR_HDMIA || |
connector->connector_type == DRM_MODE_CONNECTOR_HDMIB) |
DRM_INFO(" DDC: no ddc bus - possible BIOS bug - please report to xorg-driver-ati@lists.x.org\n"); |
} |
DRM_INFO(" Encoders:\n"); |
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
radeon_encoder = to_radeon_encoder(encoder); |
317,13 → 340,17 |
ret = radeon_get_atom_connector_info_from_object_table(dev); |
else |
ret = radeon_get_atom_connector_info_from_supported_devices_table(dev); |
} else |
} else { |
ret = radeon_get_legacy_connector_info_from_bios(dev); |
if (ret == false) |
ret = radeon_get_legacy_connector_info_from_table(dev); |
} |
} else { |
if (!ASIC_IS_AVIVO(rdev)) |
ret = radeon_get_legacy_connector_info_from_table(dev); |
} |
if (ret) { |
radeon_setup_encoder_clones(dev); |
radeon_print_display_setup(dev); |
list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head) |
radeon_ddc_dump(drm_connector); |
336,12 → 363,19 |
{ |
int ret = 0; |
|
if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) || |
(radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) { |
struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; |
if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT || |
dig->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) && 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) { |
radeon_i2c_do_lock(radeon_connector, 1); |
radeon_i2c_do_lock(radeon_connector->ddc_bus, 1); |
radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter); |
radeon_i2c_do_lock(radeon_connector, 0); |
radeon_i2c_do_lock(radeon_connector->ddc_bus, 0); |
} |
|
if (radeon_connector->edid) { |
361,9 → 395,9 |
|
if (!radeon_connector->ddc_bus) |
return -1; |
radeon_i2c_do_lock(radeon_connector, 1); |
radeon_i2c_do_lock(radeon_connector->ddc_bus, 1); |
edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter); |
radeon_i2c_do_lock(radeon_connector, 0); |
radeon_i2c_do_lock(radeon_connector->ddc_bus, 0); |
if (edid) { |
kfree(edid); |
} |
386,11 → 420,12 |
uint32_t *fb_div_p, |
uint32_t *frac_fb_div_p, |
uint32_t *ref_div_p, |
uint32_t *post_div_p, |
int flags) |
uint32_t *post_div_p) |
{ |
uint32_t min_ref_div = pll->min_ref_div; |
uint32_t max_ref_div = pll->max_ref_div; |
uint32_t min_post_div = pll->min_post_div; |
uint32_t max_post_div = pll->max_post_div; |
uint32_t min_fractional_feed_div = 0; |
uint32_t max_fractional_feed_div = 0; |
uint32_t best_vco = pll->best_vco; |
406,7 → 441,7 |
DRM_DEBUG("PLL freq %llu %u %u\n", freq, pll->min_ref_div, pll->max_ref_div); |
freq = freq * 1000; |
|
if (flags & RADEON_PLL_USE_REF_DIV) |
if (pll->flags & RADEON_PLL_USE_REF_DIV) |
min_ref_div = max_ref_div = pll->reference_div; |
else { |
while (min_ref_div < max_ref_div-1) { |
421,19 → 456,22 |
} |
} |
|
if (flags & RADEON_PLL_USE_FRAC_FB_DIV) { |
if (pll->flags & RADEON_PLL_USE_POST_DIV) |
min_post_div = max_post_div = pll->post_div; |
|
if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) { |
min_fractional_feed_div = pll->min_frac_feedback_div; |
max_fractional_feed_div = pll->max_frac_feedback_div; |
} |
|
for (post_div = pll->min_post_div; post_div <= pll->max_post_div; ++post_div) { |
for (post_div = min_post_div; post_div <= max_post_div; ++post_div) { |
uint32_t ref_div; |
|
if ((flags & RADEON_PLL_NO_ODD_POST_DIV) && (post_div & 1)) |
if ((pll->flags & RADEON_PLL_NO_ODD_POST_DIV) && (post_div & 1)) |
continue; |
|
/* legacy radeons only have a few post_divs */ |
if (flags & RADEON_PLL_LEGACY) { |
if (pll->flags & RADEON_PLL_LEGACY) { |
if ((post_div == 5) || |
(post_div == 7) || |
(post_div == 9) || |
480,7 → 518,7 |
tmp += (uint64_t)pll->reference_freq * 1000 * frac_feedback_div; |
current_freq = radeon_div(tmp, ref_div * post_div); |
|
if (flags & RADEON_PLL_PREFER_CLOSEST_LOWER) { |
if (pll->flags & RADEON_PLL_PREFER_CLOSEST_LOWER) { |
error = freq - current_freq; |
error = error < 0 ? 0xffffffff : error; |
} else |
507,12 → 545,12 |
best_freq = current_freq; |
best_error = error; |
best_vco_diff = vco_diff; |
} else if (((flags & RADEON_PLL_PREFER_LOW_REF_DIV) && (ref_div < best_ref_div)) || |
((flags & RADEON_PLL_PREFER_HIGH_REF_DIV) && (ref_div > best_ref_div)) || |
((flags & RADEON_PLL_PREFER_LOW_FB_DIV) && (feedback_div < best_feedback_div)) || |
((flags & RADEON_PLL_PREFER_HIGH_FB_DIV) && (feedback_div > best_feedback_div)) || |
((flags & RADEON_PLL_PREFER_LOW_POST_DIV) && (post_div < best_post_div)) || |
((flags & RADEON_PLL_PREFER_HIGH_POST_DIV) && (post_div > best_post_div))) { |
} else if (((pll->flags & RADEON_PLL_PREFER_LOW_REF_DIV) && (ref_div < best_ref_div)) || |
((pll->flags & RADEON_PLL_PREFER_HIGH_REF_DIV) && (ref_div > best_ref_div)) || |
((pll->flags & RADEON_PLL_PREFER_LOW_FB_DIV) && (feedback_div < best_feedback_div)) || |
((pll->flags & RADEON_PLL_PREFER_HIGH_FB_DIV) && (feedback_div > best_feedback_div)) || |
((pll->flags & RADEON_PLL_PREFER_LOW_POST_DIV) && (post_div < best_post_div)) || |
((pll->flags & RADEON_PLL_PREFER_HIGH_POST_DIV) && (post_div > best_post_div))) { |
best_post_div = post_div; |
best_ref_div = ref_div; |
best_feedback_div = feedback_div; |
542,6 → 580,97 |
*post_div_p = best_post_div; |
} |
|
void radeon_compute_pll_avivo(struct radeon_pll *pll, |
uint64_t freq, |
uint32_t *dot_clock_p, |
uint32_t *fb_div_p, |
uint32_t *frac_fb_div_p, |
uint32_t *ref_div_p, |
uint32_t *post_div_p) |
{ |
fixed20_12 m, n, frac_n, p, f_vco, f_pclk, best_freq; |
fixed20_12 pll_out_max, pll_out_min; |
fixed20_12 pll_in_max, pll_in_min; |
fixed20_12 reference_freq; |
fixed20_12 error, ffreq, a, b; |
|
pll_out_max.full = rfixed_const(pll->pll_out_max); |
pll_out_min.full = rfixed_const(pll->pll_out_min); |
pll_in_max.full = rfixed_const(pll->pll_in_max); |
pll_in_min.full = rfixed_const(pll->pll_in_min); |
reference_freq.full = rfixed_const(pll->reference_freq); |
do_div(freq, 10); |
ffreq.full = rfixed_const(freq); |
error.full = rfixed_const(100 * 100); |
|
/* max p */ |
p.full = rfixed_div(pll_out_max, ffreq); |
p.full = rfixed_floor(p); |
|
/* min m */ |
m.full = rfixed_div(reference_freq, pll_in_max); |
m.full = rfixed_ceil(m); |
|
while (1) { |
n.full = rfixed_div(ffreq, reference_freq); |
n.full = rfixed_mul(n, m); |
n.full = rfixed_mul(n, p); |
|
f_vco.full = rfixed_div(n, m); |
f_vco.full = rfixed_mul(f_vco, reference_freq); |
|
f_pclk.full = rfixed_div(f_vco, p); |
|
if (f_pclk.full > ffreq.full) |
error.full = f_pclk.full - ffreq.full; |
else |
error.full = ffreq.full - f_pclk.full; |
error.full = rfixed_div(error, f_pclk); |
a.full = rfixed_const(100 * 100); |
error.full = rfixed_mul(error, a); |
|
a.full = rfixed_mul(m, p); |
a.full = rfixed_div(n, a); |
best_freq.full = rfixed_mul(reference_freq, a); |
|
if (rfixed_trunc(error) < 25) |
break; |
|
a.full = rfixed_const(1); |
m.full = m.full + a.full; |
a.full = rfixed_div(reference_freq, m); |
if (a.full >= pll_in_min.full) |
continue; |
|
m.full = rfixed_div(reference_freq, pll_in_max); |
m.full = rfixed_ceil(m); |
a.full= rfixed_const(1); |
p.full = p.full - a.full; |
a.full = rfixed_mul(p, ffreq); |
if (a.full >= pll_out_min.full) |
continue; |
else { |
DRM_ERROR("Unable to find pll dividers\n"); |
break; |
} |
} |
|
a.full = rfixed_const(10); |
b.full = rfixed_mul(n, a); |
|
frac_n.full = rfixed_floor(n); |
frac_n.full = rfixed_mul(frac_n, a); |
frac_n.full = b.full - frac_n.full; |
|
*dot_clock_p = rfixed_trunc(best_freq); |
*fb_div_p = rfixed_trunc(n); |
*frac_fb_div_p = rfixed_trunc(frac_n); |
*ref_div_p = rfixed_trunc(m); |
*post_div_p = rfixed_trunc(p); |
|
DRM_DEBUG("%u %d.%d, %d, %d\n", *dot_clock_p * 10, *fb_div_p, *frac_fb_div_p, *ref_div_p, *post_div_p); |
} |
|
static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb) |
{ |
struct radeon_framebuffer *radeon_fb = to_radeon_framebuffer(fb); |
632,7 → 761,7 |
{ TV_STD_SECAM, "secam" }, |
}; |
|
int radeon_modeset_create_props(struct radeon_device *rdev) |
static int radeon_modeset_create_props(struct radeon_device *rdev) |
{ |
int i, sz; |
|
645,7 → 774,7 |
return -ENOMEM; |
|
rdev->mode_info.coherent_mode_property->values[0] = 0; |
rdev->mode_info.coherent_mode_property->values[0] = 1; |
rdev->mode_info.coherent_mode_property->values[1] = 1; |
} |
|
if (!ASIC_IS_AVIVO(rdev)) { |
669,7 → 798,7 |
if (!rdev->mode_info.load_detect_property) |
return -ENOMEM; |
rdev->mode_info.load_detect_property->values[0] = 0; |
rdev->mode_info.load_detect_property->values[0] = 1; |
rdev->mode_info.load_detect_property->values[1] = 1; |
|
drm_mode_create_scaling_mode_property(rdev->ddev); |
|
726,6 → 855,8 |
if (!ret) { |
return ret; |
} |
/* initialize hpd */ |
radeon_hpd_init(rdev); |
drm_helper_initial_config(rdev->ddev); |
return 0; |
} |
733,6 → 864,7 |
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; |
} |
753,7 → 885,15 |
if (encoder->crtc != crtc) |
continue; |
if (first) { |
/* set scaling */ |
if (radeon_encoder->rmx_type == RMX_OFF) |
radeon_crtc->rmx_type = RMX_OFF; |
else if (mode->hdisplay < radeon_encoder->native_mode.hdisplay || |
mode->vdisplay < radeon_encoder->native_mode.vdisplay) |
radeon_crtc->rmx_type = radeon_encoder->rmx_type; |
else |
radeon_crtc->rmx_type = RMX_OFF; |
/* copy native mode */ |
memcpy(&radeon_crtc->native_mode, |
&radeon_encoder->native_mode, |
sizeof(struct drm_display_mode)); |