Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7ed220d7 authored by Michel Dänzer's avatar Michel Dänzer Committed by Dave Airlie
Browse files

drm/radeon/kms: Fix up vertical blank interrupt support.



Fixes 3D apps timing out in the WAIT_VBLANK ioctl.

AVIVO bits compile-tested only.

Signed-off-by: default avatarMichel Dänzer <daenzer@vmware.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 3f8befec
Loading
Loading
Loading
Loading
+66 −0
Original line number Original line Diff line number Diff line
@@ -253,6 +253,72 @@ void r100_mc_fini(struct radeon_device *rdev)
}
}




/*
 * Interrupts
 */
int r100_irq_set(struct radeon_device *rdev)
{
	uint32_t tmp = 0;

	if (rdev->irq.sw_int) {
		tmp |= RADEON_SW_INT_ENABLE;
	}
	if (rdev->irq.crtc_vblank_int[0]) {
		tmp |= RADEON_CRTC_VBLANK_MASK;
	}
	if (rdev->irq.crtc_vblank_int[1]) {
		tmp |= RADEON_CRTC2_VBLANK_MASK;
	}
	WREG32(RADEON_GEN_INT_CNTL, tmp);
	return 0;
}

static inline uint32_t r100_irq_ack(struct radeon_device *rdev)
{
	uint32_t irqs = RREG32(RADEON_GEN_INT_STATUS);
	uint32_t irq_mask = RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT |
		RADEON_CRTC2_VBLANK_STAT;

	if (irqs) {
		WREG32(RADEON_GEN_INT_STATUS, irqs);
	}
	return irqs & irq_mask;
}

int r100_irq_process(struct radeon_device *rdev)
{
	uint32_t status;

	status = r100_irq_ack(rdev);
	if (!status) {
		return IRQ_NONE;
	}
	while (status) {
		/* SW interrupt */
		if (status & RADEON_SW_INT_TEST) {
			radeon_fence_process(rdev);
		}
		/* Vertical blank interrupts */
		if (status & RADEON_CRTC_VBLANK_STAT) {
			drm_handle_vblank(rdev->ddev, 0);
		}
		if (status & RADEON_CRTC2_VBLANK_STAT) {
			drm_handle_vblank(rdev->ddev, 1);
		}
		status = r100_irq_ack(rdev);
	}
	return IRQ_HANDLED;
}

u32 r100_get_vblank_counter(struct radeon_device *rdev, int crtc)
{
	if (crtc == 0)
		return RREG32(RADEON_CRTC_CRNT_FRAME);
	else
		return RREG32(RADEON_CRTC2_CRNT_FRAME);
}


/*
/*
 * Fence emission
 * Fence emission
 */
 */
+12 −4
Original line number Original line Diff line number Diff line
@@ -350,6 +350,7 @@
#define AVIVO_D1CRTC_BLANK_CONTROL                              0x6084
#define AVIVO_D1CRTC_BLANK_CONTROL                              0x6084
#define AVIVO_D1CRTC_INTERLACE_CONTROL                          0x6088
#define AVIVO_D1CRTC_INTERLACE_CONTROL                          0x6088
#define AVIVO_D1CRTC_INTERLACE_STATUS                           0x608c
#define AVIVO_D1CRTC_INTERLACE_STATUS                           0x608c
#define AVIVO_D1CRTC_FRAME_COUNT                                0x60a4
#define AVIVO_D1CRTC_STEREO_CONTROL                             0x60c4
#define AVIVO_D1CRTC_STEREO_CONTROL                             0x60c4


/* master controls */
/* master controls */
@@ -438,14 +439,15 @@
#       define AVIVO_DC_LB_DISP1_END_ADR_SHIFT  4
#       define AVIVO_DC_LB_DISP1_END_ADR_SHIFT  4
#       define AVIVO_DC_LB_DISP1_END_ADR_MASK   0x7ff
#       define AVIVO_DC_LB_DISP1_END_ADR_MASK   0x7ff


#define R500_DxMODE_INT_MASK 0x6540
#define R500_D1MODE_INT_MASK (1<<0)
#define R500_D2MODE_INT_MASK (1<<8)

#define AVIVO_D1MODE_DATA_FORMAT                0x6528
#define AVIVO_D1MODE_DATA_FORMAT                0x6528
#       define AVIVO_D1MODE_INTERLEAVE_EN       (1 << 0)
#       define AVIVO_D1MODE_INTERLEAVE_EN       (1 << 0)
#define AVIVO_D1MODE_DESKTOP_HEIGHT             0x652C
#define AVIVO_D1MODE_DESKTOP_HEIGHT             0x652C
#define AVIVO_D1MODE_VBLANK_STATUS              0x6534
#       define AVIVO_VBLANK_ACK                 (1 << 4)
#define AVIVO_D1MODE_VLINE_START_END            0x6538
#define AVIVO_D1MODE_VLINE_START_END            0x6538
#define AVIVO_DxMODE_INT_MASK                   0x6540
#       define AVIVO_D1MODE_INT_MASK            (1 << 0)
#       define AVIVO_D2MODE_INT_MASK            (1 << 8)
#define AVIVO_D1MODE_VIEWPORT_START             0x6580
#define AVIVO_D1MODE_VIEWPORT_START             0x6580
#define AVIVO_D1MODE_VIEWPORT_SIZE              0x6584
#define AVIVO_D1MODE_VIEWPORT_SIZE              0x6584
#define AVIVO_D1MODE_EXT_OVERSCAN_LEFT_RIGHT    0x6588
#define AVIVO_D1MODE_EXT_OVERSCAN_LEFT_RIGHT    0x6588
@@ -475,6 +477,7 @@
#define AVIVO_D2CRTC_BLANK_CONTROL                              0x6884
#define AVIVO_D2CRTC_BLANK_CONTROL                              0x6884
#define AVIVO_D2CRTC_INTERLACE_CONTROL                          0x6888
#define AVIVO_D2CRTC_INTERLACE_CONTROL                          0x6888
#define AVIVO_D2CRTC_INTERLACE_STATUS                           0x688c
#define AVIVO_D2CRTC_INTERLACE_STATUS                           0x688c
#define AVIVO_D2CRTC_FRAME_COUNT                                0x68a4
#define AVIVO_D2CRTC_STEREO_CONTROL                             0x68c4
#define AVIVO_D2CRTC_STEREO_CONTROL                             0x68c4


#define AVIVO_D2GRPH_ENABLE                                     0x6900
#define AVIVO_D2GRPH_ENABLE                                     0x6900
@@ -497,6 +500,7 @@
#define AVIVO_D2CUR_SIZE                        0x6c10
#define AVIVO_D2CUR_SIZE                        0x6c10
#define AVIVO_D2CUR_POSITION                    0x6c14
#define AVIVO_D2CUR_POSITION                    0x6c14


#define AVIVO_D2MODE_VBLANK_STATUS              0x6d34
#define AVIVO_D2MODE_VLINE_START_END            0x6d38
#define AVIVO_D2MODE_VLINE_START_END            0x6d38
#define AVIVO_D2MODE_VIEWPORT_START             0x6d80
#define AVIVO_D2MODE_VIEWPORT_START             0x6d80
#define AVIVO_D2MODE_VIEWPORT_SIZE              0x6d84
#define AVIVO_D2MODE_VIEWPORT_SIZE              0x6d84
@@ -748,4 +752,8 @@
#	define AVIVO_I2C_EN							(1 << 0)
#	define AVIVO_I2C_EN							(1 << 0)
#	define AVIVO_I2C_RESET						(1 << 8)
#	define AVIVO_I2C_RESET						(1 << 8)


#define AVIVO_DISP_INTERRUPT_STATUS                             0x7edc
#       define AVIVO_D1_VBLANK_INTERRUPT                        (1 << 4)
#       define AVIVO_D2_VBLANK_INTERRUPT                        (1 << 5)

#endif
#endif
+2 −0
Original line number Original line Diff line number Diff line
@@ -574,6 +574,7 @@ struct radeon_asic {
	void (*ring_start)(struct radeon_device *rdev);
	void (*ring_start)(struct radeon_device *rdev);
	int (*irq_set)(struct radeon_device *rdev);
	int (*irq_set)(struct radeon_device *rdev);
	int (*irq_process)(struct radeon_device *rdev);
	int (*irq_process)(struct radeon_device *rdev);
	u32 (*get_vblank_counter)(struct radeon_device *rdev, int crtc);
	void (*fence_ring_emit)(struct radeon_device *rdev, struct radeon_fence *fence);
	void (*fence_ring_emit)(struct radeon_device *rdev, struct radeon_fence *fence);
	int (*cs_parse)(struct radeon_cs_parser *p);
	int (*cs_parse)(struct radeon_cs_parser *p);
	int (*copy_blit)(struct radeon_device *rdev,
	int (*copy_blit)(struct radeon_device *rdev,
@@ -862,6 +863,7 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v)
#define radeon_ring_start(rdev) (rdev)->asic->ring_start((rdev))
#define radeon_ring_start(rdev) (rdev)->asic->ring_start((rdev))
#define radeon_irq_set(rdev) (rdev)->asic->irq_set((rdev))
#define radeon_irq_set(rdev) (rdev)->asic->irq_set((rdev))
#define radeon_irq_process(rdev) (rdev)->asic->irq_process((rdev))
#define radeon_irq_process(rdev) (rdev)->asic->irq_process((rdev))
#define radeon_get_vblank_counter(rdev, crtc) (rdev)->asic->get_vblank_counter((rdev), (crtc))
#define radeon_fence_ring_emit(rdev, fence) (rdev)->asic->fence_ring_emit((rdev), (fence))
#define radeon_fence_ring_emit(rdev, fence) (rdev)->asic->fence_ring_emit((rdev), (fence))
#define radeon_copy_blit(rdev, s, d, np, f) (rdev)->asic->copy_blit((rdev), (s), (d), (np), (f))
#define radeon_copy_blit(rdev, s, d, np, f) (rdev)->asic->copy_blit((rdev), (s), (d), (np), (f))
#define radeon_copy_dma(rdev, s, d, np, f) (rdev)->asic->copy_dma((rdev), (s), (d), (np), (f))
#define radeon_copy_dma(rdev, s, d, np, f) (rdev)->asic->copy_dma((rdev), (s), (d), (np), (f))
+17 −6
Original line number Original line Diff line number Diff line
@@ -49,6 +49,7 @@ void r100_vram_info(struct radeon_device *rdev);
int r100_gpu_reset(struct radeon_device *rdev);
int r100_gpu_reset(struct radeon_device *rdev);
int r100_mc_init(struct radeon_device *rdev);
int r100_mc_init(struct radeon_device *rdev);
void r100_mc_fini(struct radeon_device *rdev);
void r100_mc_fini(struct radeon_device *rdev);
u32 r100_get_vblank_counter(struct radeon_device *rdev, int crtc);
int r100_wb_init(struct radeon_device *rdev);
int r100_wb_init(struct radeon_device *rdev);
void r100_wb_fini(struct radeon_device *rdev);
void r100_wb_fini(struct radeon_device *rdev);
int r100_gart_enable(struct radeon_device *rdev);
int r100_gart_enable(struct radeon_device *rdev);
@@ -96,6 +97,7 @@ static struct radeon_asic r100_asic = {
	.ring_start = &r100_ring_start,
	.ring_start = &r100_ring_start,
	.irq_set = &r100_irq_set,
	.irq_set = &r100_irq_set,
	.irq_process = &r100_irq_process,
	.irq_process = &r100_irq_process,
	.get_vblank_counter = &r100_get_vblank_counter,
	.fence_ring_emit = &r100_fence_ring_emit,
	.fence_ring_emit = &r100_fence_ring_emit,
	.cs_parse = &r100_cs_parse,
	.cs_parse = &r100_cs_parse,
	.copy_blit = &r100_copy_blit,
	.copy_blit = &r100_copy_blit,
@@ -156,6 +158,7 @@ static struct radeon_asic r300_asic = {
	.ring_start = &r300_ring_start,
	.ring_start = &r300_ring_start,
	.irq_set = &r100_irq_set,
	.irq_set = &r100_irq_set,
	.irq_process = &r100_irq_process,
	.irq_process = &r100_irq_process,
	.get_vblank_counter = &r100_get_vblank_counter,
	.fence_ring_emit = &r300_fence_ring_emit,
	.fence_ring_emit = &r300_fence_ring_emit,
	.cs_parse = &r300_cs_parse,
	.cs_parse = &r300_cs_parse,
	.copy_blit = &r100_copy_blit,
	.copy_blit = &r100_copy_blit,
@@ -196,6 +199,7 @@ static struct radeon_asic r420_asic = {
	.ring_start = &r300_ring_start,
	.ring_start = &r300_ring_start,
	.irq_set = &r100_irq_set,
	.irq_set = &r100_irq_set,
	.irq_process = &r100_irq_process,
	.irq_process = &r100_irq_process,
	.get_vblank_counter = &r100_get_vblank_counter,
	.fence_ring_emit = &r300_fence_ring_emit,
	.fence_ring_emit = &r300_fence_ring_emit,
	.cs_parse = &r300_cs_parse,
	.cs_parse = &r300_cs_parse,
	.copy_blit = &r100_copy_blit,
	.copy_blit = &r100_copy_blit,
@@ -243,6 +247,7 @@ static struct radeon_asic rs400_asic = {
	.ring_start = &r300_ring_start,
	.ring_start = &r300_ring_start,
	.irq_set = &r100_irq_set,
	.irq_set = &r100_irq_set,
	.irq_process = &r100_irq_process,
	.irq_process = &r100_irq_process,
	.get_vblank_counter = &r100_get_vblank_counter,
	.fence_ring_emit = &r300_fence_ring_emit,
	.fence_ring_emit = &r300_fence_ring_emit,
	.cs_parse = &r300_cs_parse,
	.cs_parse = &r300_cs_parse,
	.copy_blit = &r100_copy_blit,
	.copy_blit = &r100_copy_blit,
@@ -266,6 +271,8 @@ void rs600_vram_info(struct radeon_device *rdev);
int rs600_mc_init(struct radeon_device *rdev);
int rs600_mc_init(struct radeon_device *rdev);
void rs600_mc_fini(struct radeon_device *rdev);
void rs600_mc_fini(struct radeon_device *rdev);
int rs600_irq_set(struct radeon_device *rdev);
int rs600_irq_set(struct radeon_device *rdev);
int rs600_irq_process(struct radeon_device *rdev);
u32 rs600_get_vblank_counter(struct radeon_device *rdev, int crtc);
int rs600_gart_enable(struct radeon_device *rdev);
int rs600_gart_enable(struct radeon_device *rdev);
void rs600_gart_disable(struct radeon_device *rdev);
void rs600_gart_disable(struct radeon_device *rdev);
void rs600_gart_tlb_flush(struct radeon_device *rdev);
void rs600_gart_tlb_flush(struct radeon_device *rdev);
@@ -291,7 +298,8 @@ static struct radeon_asic rs600_asic = {
	.cp_disable = &r100_cp_disable,
	.cp_disable = &r100_cp_disable,
	.ring_start = &r300_ring_start,
	.ring_start = &r300_ring_start,
	.irq_set = &rs600_irq_set,
	.irq_set = &rs600_irq_set,
	.irq_process = &r100_irq_process,
	.irq_process = &rs600_irq_process,
	.get_vblank_counter = &rs600_get_vblank_counter,
	.fence_ring_emit = &r300_fence_ring_emit,
	.fence_ring_emit = &r300_fence_ring_emit,
	.cs_parse = &r300_cs_parse,
	.cs_parse = &r300_cs_parse,
	.copy_blit = &r100_copy_blit,
	.copy_blit = &r100_copy_blit,
@@ -334,7 +342,8 @@ static struct radeon_asic rs690_asic = {
	.cp_disable = &r100_cp_disable,
	.cp_disable = &r100_cp_disable,
	.ring_start = &r300_ring_start,
	.ring_start = &r300_ring_start,
	.irq_set = &rs600_irq_set,
	.irq_set = &rs600_irq_set,
	.irq_process = &r100_irq_process,
	.irq_process = &rs600_irq_process,
	.get_vblank_counter = &rs600_get_vblank_counter,
	.fence_ring_emit = &r300_fence_ring_emit,
	.fence_ring_emit = &r300_fence_ring_emit,
	.cs_parse = &r300_cs_parse,
	.cs_parse = &r300_cs_parse,
	.copy_blit = &r100_copy_blit,
	.copy_blit = &r100_copy_blit,
@@ -382,8 +391,9 @@ static struct radeon_asic rv515_asic = {
	.cp_fini = &r100_cp_fini,
	.cp_fini = &r100_cp_fini,
	.cp_disable = &r100_cp_disable,
	.cp_disable = &r100_cp_disable,
	.ring_start = &rv515_ring_start,
	.ring_start = &rv515_ring_start,
	.irq_set = &r100_irq_set,
	.irq_set = &rs600_irq_set,
	.irq_process = &r100_irq_process,
	.irq_process = &rs600_irq_process,
	.get_vblank_counter = &rs600_get_vblank_counter,
	.fence_ring_emit = &r300_fence_ring_emit,
	.fence_ring_emit = &r300_fence_ring_emit,
	.cs_parse = &r300_cs_parse,
	.cs_parse = &r300_cs_parse,
	.copy_blit = &r100_copy_blit,
	.copy_blit = &r100_copy_blit,
@@ -424,8 +434,9 @@ static struct radeon_asic r520_asic = {
	.cp_fini = &r100_cp_fini,
	.cp_fini = &r100_cp_fini,
	.cp_disable = &r100_cp_disable,
	.cp_disable = &r100_cp_disable,
	.ring_start = &rv515_ring_start,
	.ring_start = &rv515_ring_start,
	.irq_set = &r100_irq_set,
	.irq_set = &rs600_irq_set,
	.irq_process = &r100_irq_process,
	.irq_process = &rs600_irq_process,
	.get_vblank_counter = &rs600_get_vblank_counter,
	.fence_ring_emit = &r300_fence_ring_emit,
	.fence_ring_emit = &r300_fence_ring_emit,
	.cs_parse = &r300_cs_parse,
	.cs_parse = &r300_cs_parse,
	.copy_blit = &r100_copy_blit,
	.copy_blit = &r100_copy_blit,
+0 −54
Original line number Original line Diff line number Diff line
@@ -32,60 +32,6 @@
#include "radeon.h"
#include "radeon.h"
#include "atom.h"
#include "atom.h"


static inline uint32_t r100_irq_ack(struct radeon_device *rdev)
{
	uint32_t irqs = RREG32(RADEON_GEN_INT_STATUS);
	uint32_t irq_mask = RADEON_SW_INT_TEST;

	if (irqs) {
		WREG32(RADEON_GEN_INT_STATUS, irqs);
	}
	return irqs & irq_mask;
}

int r100_irq_set(struct radeon_device *rdev)
{
	uint32_t tmp = 0;

	if (rdev->irq.sw_int) {
		tmp |= RADEON_SW_INT_ENABLE;
	}
	/* Todo go through CRTC and enable vblank int or not */
	WREG32(RADEON_GEN_INT_CNTL, tmp);
	return 0;
}

int r100_irq_process(struct radeon_device *rdev)
{
	uint32_t status;

	status = r100_irq_ack(rdev);
	if (!status) {
		return IRQ_NONE;
	}
	while (status) {
		/* SW interrupt */
		if (status & RADEON_SW_INT_TEST) {
			radeon_fence_process(rdev);
		}
		status = r100_irq_ack(rdev);
	}
	return IRQ_HANDLED;
}

int rs600_irq_set(struct radeon_device *rdev)
{
	uint32_t tmp = 0;

	if (rdev->irq.sw_int) {
		tmp |= RADEON_SW_INT_ENABLE;
	}
	WREG32(RADEON_GEN_INT_CNTL, tmp);
	/* Todo go through CRTC and enable vblank int or not */
	WREG32(R500_DxMODE_INT_MASK, 0);
	return 0;
}

irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS)
irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS)
{
{
	struct drm_device *dev = (struct drm_device *) arg;
	struct drm_device *dev = (struct drm_device *) arg;
Loading