Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 6103 → Rev 6104

/drivers/video/drm/radeon/radeon_display.c
30,26 → 30,13
#include "atom.h"
#include <asm/div64.h>
 
#include <linux/pm_runtime.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_plane_helper.h>
#include <drm/drm_edid.h>
 
/* Greatest common divisor */
unsigned long gcd(unsigned long a, unsigned long b)
{
unsigned long r;
#include <linux/gcd.h>
 
if (a < b)
swap(a, b);
 
if (!b)
return a;
while ((r = a % b) != 0) {
a = b;
b = r;
}
return b;
}
 
static void avivo_crtc_load_lut(struct drm_crtc *crtc)
{
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
167,7 → 154,7
(NI_GRPH_REGAMMA_MODE(NI_REGAMMA_BYPASS) |
NI_OVL_REGAMMA_MODE(NI_REGAMMA_BYPASS)));
WREG32(NI_OUTPUT_CSC_CONTROL + radeon_crtc->crtc_offset,
(NI_OUTPUT_CSC_GRPH_MODE(NI_OUTPUT_CSC_BYPASS) |
(NI_OUTPUT_CSC_GRPH_MODE(radeon_crtc->output_csc) |
NI_OUTPUT_CSC_OVL_MODE(NI_OUTPUT_CSC_BYPASS)));
/* XXX match this to the depth of the crtc fmt block, move to modeset? */
WREG32(0x6940 + radeon_crtc->crtc_offset, 0);
267,6 → 254,65
kfree(radeon_crtc);
}
 
void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id)
{
struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
unsigned long flags;
u32 update_pending;
int vpos, hpos;
 
/* can happen during initialization */
if (radeon_crtc == NULL)
return;
 
/* Skip the pageflip completion check below (based on polling) on
* asics which reliably support hw pageflip completion irqs. pflip
* irqs are a reliable and race-free method of handling pageflip
* completion detection. A use_pflipirq module parameter < 2 allows
* to override this in case of asics with faulty pflip irqs.
* A module parameter of 0 would only use this polling based path,
* a parameter of 1 would use pflip irq only as a backup to this
* path, as in Linux 3.16.
*/
if ((radeon_use_pflipirq == 2) && ASIC_IS_DCE4(rdev))
return;
 
spin_lock_irqsave(&rdev->ddev->event_lock, flags);
if (radeon_crtc->flip_status != RADEON_FLIP_SUBMITTED) {
DRM_DEBUG_DRIVER("radeon_crtc->flip_status = %d != "
"RADEON_FLIP_SUBMITTED(%d)\n",
radeon_crtc->flip_status,
RADEON_FLIP_SUBMITTED);
spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
return;
}
 
update_pending = radeon_page_flip_pending(rdev, crtc_id);
 
/* Has the pageflip already completed in crtc, or is it certain
* to complete in this vblank?
*/
if (update_pending &&
(DRM_SCANOUTPOS_VALID & radeon_get_crtc_scanoutpos(rdev->ddev,
crtc_id,
USE_REAL_VBLANKSTART,
&vpos, &hpos, NULL, NULL,
&rdev->mode_info.crtcs[crtc_id]->base.hwmode)) &&
((vpos >= (99 * rdev->mode_info.crtcs[crtc_id]->base.hwmode.crtc_vdisplay)/100) ||
(vpos < 0 && !ASIC_IS_AVIVO(rdev)))) {
/* crtc didn't flip in this target vblank interval,
* but flip is pending in crtc. Based on the current
* scanout position we know that the current frame is
* (nearly) complete and the flip will (likely)
* complete before the start of the next frame.
*/
update_pending = 0;
}
spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
// if (!update_pending)
// radeon_crtc_handle_flip(rdev, crtc_id);
}
 
static int
radeon_crtc_set_config(struct drm_mode_set *set)
{
632,6 → 678,9
if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV &&
pll->flags & RADEON_PLL_USE_REF_DIV)
ref_div_max = pll->reference_div;
else if (pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP)
/* fix for problems on RS880 */
ref_div_max = min(pll->max_ref_div, 7u);
else
ref_div_max = pll->max_ref_div;
 
1016,6 → 1065,13
{ RADEON_FMT_DITHER_ENABLE, "on" },
};
 
static struct drm_prop_enum_list radeon_output_csc_enum_list[] =
{ { RADEON_OUTPUT_CSC_BYPASS, "bypass" },
{ RADEON_OUTPUT_CSC_TVRGB, "tvrgb" },
{ RADEON_OUTPUT_CSC_YCBCR601, "ycbcr601" },
{ RADEON_OUTPUT_CSC_YCBCR709, "ycbcr709" },
};
 
static int radeon_modeset_create_props(struct radeon_device *rdev)
{
int sz;
1078,6 → 1134,12
"dither",
radeon_dither_enum_list, sz);
 
sz = ARRAY_SIZE(radeon_output_csc_enum_list);
rdev->mode_info.output_csc_property =
drm_property_create_enum(rdev->ddev, 0,
"output_csc",
radeon_output_csc_enum_list, sz);
 
return 0;
}
 
1408,8 → 1470,10
* unknown small number of scanlines wrt. real scanout position.
*
*/
int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int flags,
int *vpos, int *hpos, void *stime, void *etime)
int radeon_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
unsigned int flags, int *vpos, int *hpos,
ktime_t *stime, ktime_t *etime,
const struct drm_display_mode *mode)
{
u32 stat_crtc = 0, vbl = 0, position = 0;
int vbl_start, vbl_end, vtotal, ret = 0;
1417,8 → 1481,14
 
struct radeon_device *rdev = dev->dev_private;
 
/* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */
 
/* Get optional system timestamp before query. */
if (stime)
*stime = ktime_get();
 
if (ASIC_IS_DCE4(rdev)) {
if (crtc == 0) {
if (pipe == 0) {
vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END +
EVERGREEN_CRTC0_REGISTER_OFFSET);
position = RREG32(EVERGREEN_CRTC_STATUS_POSITION +
1425,7 → 1495,7
EVERGREEN_CRTC0_REGISTER_OFFSET);
ret |= DRM_SCANOUTPOS_VALID;
}
if (crtc == 1) {
if (pipe == 1) {
vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END +
EVERGREEN_CRTC1_REGISTER_OFFSET);
position = RREG32(EVERGREEN_CRTC_STATUS_POSITION +
1432,7 → 1502,7
EVERGREEN_CRTC1_REGISTER_OFFSET);
ret |= DRM_SCANOUTPOS_VALID;
}
if (crtc == 2) {
if (pipe == 2) {
vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END +
EVERGREEN_CRTC2_REGISTER_OFFSET);
position = RREG32(EVERGREEN_CRTC_STATUS_POSITION +
1439,7 → 1509,7
EVERGREEN_CRTC2_REGISTER_OFFSET);
ret |= DRM_SCANOUTPOS_VALID;
}
if (crtc == 3) {
if (pipe == 3) {
vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END +
EVERGREEN_CRTC3_REGISTER_OFFSET);
position = RREG32(EVERGREEN_CRTC_STATUS_POSITION +
1446,7 → 1516,7
EVERGREEN_CRTC3_REGISTER_OFFSET);
ret |= DRM_SCANOUTPOS_VALID;
}
if (crtc == 4) {
if (pipe == 4) {
vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END +
EVERGREEN_CRTC4_REGISTER_OFFSET);
position = RREG32(EVERGREEN_CRTC_STATUS_POSITION +
1453,7 → 1523,7
EVERGREEN_CRTC4_REGISTER_OFFSET);
ret |= DRM_SCANOUTPOS_VALID;
}
if (crtc == 5) {
if (pipe == 5) {
vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END +
EVERGREEN_CRTC5_REGISTER_OFFSET);
position = RREG32(EVERGREEN_CRTC_STATUS_POSITION +
1461,12 → 1531,12
ret |= DRM_SCANOUTPOS_VALID;
}
} else if (ASIC_IS_AVIVO(rdev)) {
if (crtc == 0) {
if (pipe == 0) {
vbl = RREG32(AVIVO_D1CRTC_V_BLANK_START_END);
position = RREG32(AVIVO_D1CRTC_STATUS_POSITION);
ret |= DRM_SCANOUTPOS_VALID;
}
if (crtc == 1) {
if (pipe == 1) {
vbl = RREG32(AVIVO_D2CRTC_V_BLANK_START_END);
position = RREG32(AVIVO_D2CRTC_STATUS_POSITION);
ret |= DRM_SCANOUTPOS_VALID;
1473,7 → 1543,7
}
} else {
/* Pre-AVIVO: Different encoding of scanout pos and vblank interval. */
if (crtc == 0) {
if (pipe == 0) {
/* Assume vbl_end == 0, get vbl_start from
* upper 16 bits.
*/
1487,7 → 1557,7
 
ret |= DRM_SCANOUTPOS_VALID;
}
if (crtc == 1) {
if (pipe == 1) {
vbl = (RREG32(RADEON_CRTC2_V_TOTAL_DISP) &
RADEON_CRTC_V_DISP) >> RADEON_CRTC_V_DISP_SHIFT;
position = (RREG32(RADEON_CRTC2_VLINE_CRNT_VLINE) >> 16) & RADEON_CRTC_V_TOTAL;
1499,6 → 1569,12
}
}
 
/* Get optional system timestamp after query. */
if (etime)
*etime = ktime_get();
 
/* preempt_enable_rt() should go right here in PREEMPT_RT patchset. */
 
/* Decode into vertical and horizontal scanout position. */
*vpos = position & 0x1fff;
*hpos = (position >> 16) & 0x1fff;
1512,7 → 1588,7
}
else {
/* No: Fake something reasonable which gives at least ok results. */
vbl_start = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vdisplay;
vbl_start = mode->crtc_vdisplay;
vbl_end = 0;
}
 
1528,7 → 1604,7
 
/* Inside "upper part" of vblank area? Apply corrective offset if so: */
if (in_vbl && (*vpos >= vbl_start)) {
vtotal = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vtotal;
vtotal = mode->crtc_vtotal;
*vpos = *vpos - vtotal;
}
 
1550,8 → 1626,8
* We only do this if DRM_CALLED_FROM_VBLIRQ.
*/
if ((flags & DRM_CALLED_FROM_VBLIRQ) && !in_vbl) {
vbl_start = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vdisplay;
vtotal = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vtotal;
vbl_start = mode->crtc_vdisplay;
vtotal = mode->crtc_vtotal;
 
if (vbl_start - *vpos < vtotal / 100) {
*vpos -= vtotal;