diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 1a816ea5122..c8dae3f9fa0 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -99,6 +99,25 @@ void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev) } } +void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc) +{ + struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; + int i; + + if (RREG32(EVERGREEN_CRTC_CONTROL + radeon_crtc->crtc_offset) & EVERGREEN_CRTC_MASTER_EN) { + for (i = 0; i < rdev->usec_timeout; i++) { + if (!(RREG32(EVERGREEN_CRTC_STATUS + radeon_crtc->crtc_offset) & EVERGREEN_CRTC_V_BLANK)) + break; + udelay(1); + } + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(EVERGREEN_CRTC_STATUS + radeon_crtc->crtc_offset) & EVERGREEN_CRTC_V_BLANK) + break; + udelay(1); + } + } +} + void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc) { /* enable the pflip int */ diff --git a/drivers/gpu/drm/radeon/evergreen_reg.h b/drivers/gpu/drm/radeon/evergreen_reg.h index 4215de95477..96c10b3991a 100644 --- a/drivers/gpu/drm/radeon/evergreen_reg.h +++ b/drivers/gpu/drm/radeon/evergreen_reg.h @@ -219,6 +219,7 @@ # define EVERGREEN_CRTC_MASTER_EN (1 << 0) # define EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE (1 << 24) #define EVERGREEN_CRTC_STATUS 0x6e8c +# define EVERGREEN_CRTC_V_BLANK (1 << 0) #define EVERGREEN_CRTC_STATUS_POSITION 0x6e90 #define EVERGREEN_MASTER_UPDATE_MODE 0x6ef8 #define EVERGREEN_CRTC_UPDATE_LOCK 0x6ed4 diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 99bb0064935..65fe8e092a1 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -65,6 +65,40 @@ MODULE_FIRMWARE(FIRMWARE_R520); #include "r100_track.h" +void r100_wait_for_vblank(struct radeon_device *rdev, int crtc) +{ + struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; + int i; + + if (radeon_crtc->crtc_id == 0) { + if (RREG32(RADEON_CRTC_GEN_CNTL) & RADEON_CRTC_EN) { + for (i = 0; i < rdev->usec_timeout; i++) { + if (!(RREG32(RADEON_CRTC_STATUS) & RADEON_CRTC_VBLANK_CUR)) + break; + udelay(1); + } + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(RADEON_CRTC_STATUS) & RADEON_CRTC_VBLANK_CUR) + break; + udelay(1); + } + } + } else { + if (RREG32(RADEON_CRTC2_GEN_CNTL) & RADEON_CRTC2_EN) { + for (i = 0; i < rdev->usec_timeout; i++) { + if (!(RREG32(RADEON_CRTC2_STATUS) & RADEON_CRTC2_VBLANK_CUR)) + break; + udelay(1); + } + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(RADEON_CRTC2_STATUS) & RADEON_CRTC2_VBLANK_CUR) + break; + udelay(1); + } + } + } +} + /* This files gather functions specifics to: * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 */ diff --git a/drivers/gpu/drm/radeon/r500_reg.h b/drivers/gpu/drm/radeon/r500_reg.h index 3bd8f1b1c60..ec576aaafb7 100644 --- a/drivers/gpu/drm/radeon/r500_reg.h +++ b/drivers/gpu/drm/radeon/r500_reg.h @@ -351,6 +351,8 @@ #define AVIVO_D1CRTC_BLANK_CONTROL 0x6084 #define AVIVO_D1CRTC_INTERLACE_CONTROL 0x6088 #define AVIVO_D1CRTC_INTERLACE_STATUS 0x608c +#define AVIVO_D1CRTC_STATUS 0x609c +# define AVIVO_D1CRTC_V_BLANK (1 << 0) #define AVIVO_D1CRTC_STATUS_POSITION 0x60a0 #define AVIVO_D1CRTC_FRAME_COUNT 0x60a4 #define AVIVO_D1CRTC_STEREO_CONTROL 0x60c4 diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 884e0d4b114..e19a430d344 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1204,6 +1204,8 @@ struct radeon_asic { void (*pre_page_flip)(struct radeon_device *rdev, int crtc); u32 (*page_flip)(struct radeon_device *rdev, int crtc, u64 crtc_base); void (*post_page_flip)(struct radeon_device *rdev, int crtc); + /* wait for vblank */ + void (*wait_for_vblank)(struct radeon_device *rdev, int crtc); }; /* @@ -1692,6 +1694,7 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v); #define radeon_pre_page_flip(rdev, crtc) rdev->asic->pre_page_flip((rdev), (crtc)) #define radeon_page_flip(rdev, crtc, base) rdev->asic->page_flip((rdev), (crtc), (base)) #define radeon_post_page_flip(rdev, crtc) rdev->asic->post_page_flip((rdev), (crtc)) +#define radeon_wait_for_vblank(rdev, crtc) rdev->asic->wait_for_vblank((rdev), (crtc)) /* Common functions */ /* AGP */ diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index 36a6192ce86..c6636085996 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -178,6 +178,7 @@ static struct radeon_asic r100_asic = { .pre_page_flip = &r100_pre_page_flip, .page_flip = &r100_page_flip, .post_page_flip = &r100_post_page_flip, + .wait_for_vblank = &r100_wait_for_vblank, }; static struct radeon_asic r200_asic = { @@ -229,6 +230,7 @@ static struct radeon_asic r200_asic = { .pre_page_flip = &r100_pre_page_flip, .page_flip = &r100_page_flip, .post_page_flip = &r100_post_page_flip, + .wait_for_vblank = &r100_wait_for_vblank, }; static struct radeon_asic r300_asic = { @@ -281,6 +283,7 @@ static struct radeon_asic r300_asic = { .pre_page_flip = &r100_pre_page_flip, .page_flip = &r100_page_flip, .post_page_flip = &r100_post_page_flip, + .wait_for_vblank = &r100_wait_for_vblank, }; static struct radeon_asic r300_asic_pcie = { @@ -332,6 +335,7 @@ static struct radeon_asic r300_asic_pcie = { .pre_page_flip = &r100_pre_page_flip, .page_flip = &r100_page_flip, .post_page_flip = &r100_post_page_flip, + .wait_for_vblank = &r100_wait_for_vblank, }; static struct radeon_asic r420_asic = { @@ -384,6 +388,7 @@ static struct radeon_asic r420_asic = { .pre_page_flip = &r100_pre_page_flip, .page_flip = &r100_page_flip, .post_page_flip = &r100_post_page_flip, + .wait_for_vblank = &r100_wait_for_vblank, }; static struct radeon_asic rs400_asic = { @@ -436,6 +441,7 @@ static struct radeon_asic rs400_asic = { .pre_page_flip = &r100_pre_page_flip, .page_flip = &r100_page_flip, .post_page_flip = &r100_post_page_flip, + .wait_for_vblank = &r100_wait_for_vblank, }; static struct radeon_asic rs600_asic = { @@ -488,6 +494,7 @@ static struct radeon_asic rs600_asic = { .pre_page_flip = &rs600_pre_page_flip, .page_flip = &rs600_page_flip, .post_page_flip = &rs600_post_page_flip, + .wait_for_vblank = &avivo_wait_for_vblank, }; static struct radeon_asic rs690_asic = { @@ -540,6 +547,7 @@ static struct radeon_asic rs690_asic = { .pre_page_flip = &rs600_pre_page_flip, .page_flip = &rs600_page_flip, .post_page_flip = &rs600_post_page_flip, + .wait_for_vblank = &avivo_wait_for_vblank, }; static struct radeon_asic rv515_asic = { @@ -592,6 +600,7 @@ static struct radeon_asic rv515_asic = { .pre_page_flip = &rs600_pre_page_flip, .page_flip = &rs600_page_flip, .post_page_flip = &rs600_post_page_flip, + .wait_for_vblank = &avivo_wait_for_vblank, }; static struct radeon_asic r520_asic = { @@ -644,6 +653,7 @@ static struct radeon_asic r520_asic = { .pre_page_flip = &rs600_pre_page_flip, .page_flip = &rs600_page_flip, .post_page_flip = &rs600_post_page_flip, + .wait_for_vblank = &avivo_wait_for_vblank, }; static struct radeon_asic r600_asic = { @@ -695,6 +705,7 @@ static struct radeon_asic r600_asic = { .pre_page_flip = &rs600_pre_page_flip, .page_flip = &rs600_page_flip, .post_page_flip = &rs600_post_page_flip, + .wait_for_vblank = &avivo_wait_for_vblank, }; static struct radeon_asic rs780_asic = { @@ -746,6 +757,7 @@ static struct radeon_asic rs780_asic = { .pre_page_flip = &rs600_pre_page_flip, .page_flip = &rs600_page_flip, .post_page_flip = &rs600_post_page_flip, + .wait_for_vblank = &avivo_wait_for_vblank, }; static struct radeon_asic rv770_asic = { @@ -797,6 +809,7 @@ static struct radeon_asic rv770_asic = { .pre_page_flip = &rs600_pre_page_flip, .page_flip = &rv770_page_flip, .post_page_flip = &rs600_post_page_flip, + .wait_for_vblank = &avivo_wait_for_vblank, }; static struct radeon_asic evergreen_asic = { @@ -848,6 +861,7 @@ static struct radeon_asic evergreen_asic = { .pre_page_flip = &evergreen_pre_page_flip, .page_flip = &evergreen_page_flip, .post_page_flip = &evergreen_post_page_flip, + .wait_for_vblank = &dce4_wait_for_vblank, }; static struct radeon_asic sumo_asic = { @@ -899,6 +913,7 @@ static struct radeon_asic sumo_asic = { .pre_page_flip = &evergreen_pre_page_flip, .page_flip = &evergreen_page_flip, .post_page_flip = &evergreen_post_page_flip, + .wait_for_vblank = &dce4_wait_for_vblank, }; static struct radeon_asic btc_asic = { @@ -950,6 +965,7 @@ static struct radeon_asic btc_asic = { .pre_page_flip = &evergreen_pre_page_flip, .page_flip = &evergreen_page_flip, .post_page_flip = &evergreen_post_page_flip, + .wait_for_vblank = &dce4_wait_for_vblank, }; static const struct radeon_vm_funcs cayman_vm_funcs = { @@ -1024,6 +1040,7 @@ static struct radeon_asic cayman_asic = { .pre_page_flip = &evergreen_pre_page_flip, .page_flip = &evergreen_page_flip, .post_page_flip = &evergreen_post_page_flip, + .wait_for_vblank = &dce4_wait_for_vblank, }; int radeon_asic_init(struct radeon_device *rdev) diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 6304aef0d9b..d9df84f9ebb 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -139,6 +139,7 @@ extern void r100_pm_get_dynpm_state(struct radeon_device *rdev); extern void r100_pre_page_flip(struct radeon_device *rdev, int crtc); extern u32 r100_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); extern void r100_post_page_flip(struct radeon_device *rdev, int crtc); +extern void r100_wait_for_vblank(struct radeon_device *rdev, int crtc); /* * r200,rv250,rs300,rv280 @@ -236,7 +237,7 @@ extern void rs600_pre_page_flip(struct radeon_device *rdev, int crtc); extern u32 rs600_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); extern void rs600_post_page_flip(struct radeon_device *rdev, int crtc); void rs600_set_safe_registers(struct radeon_device *rdev); - +extern void avivo_wait_for_vblank(struct radeon_device *rdev, int crtc); /* * rs690,rs740 @@ -423,6 +424,7 @@ extern void sumo_pm_init_profile(struct radeon_device *rdev); extern void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc); extern u32 evergreen_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); extern void evergreen_post_page_flip(struct radeon_device *rdev, int crtc); +extern void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc); void evergreen_disable_interrupt_state(struct radeon_device *rdev); int evergreen_blit_init(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/radeon_reg.h b/drivers/gpu/drm/radeon/radeon_reg.h index b4ce8645570..50986341128 100644 --- a/drivers/gpu/drm/radeon/radeon_reg.h +++ b/drivers/gpu/drm/radeon/radeon_reg.h @@ -539,9 +539,11 @@ #define RADEON_CRTC2_PITCH 0x032c #define RADEON_CRTC_STATUS 0x005c +# define RADEON_CRTC_VBLANK_CUR (1 << 0) # define RADEON_CRTC_VBLANK_SAVE (1 << 1) # define RADEON_CRTC_VBLANK_SAVE_CLEAR (1 << 1) #define RADEON_CRTC2_STATUS 0x03fc +# define RADEON_CRTC2_VBLANK_CUR (1 << 0) # define RADEON_CRTC2_VBLANK_SAVE (1 << 1) # define RADEON_CRTC2_VBLANK_SAVE_CLEAR (1 << 1) #define RADEON_CRTC_V_SYNC_STRT_WID 0x020c diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index ec46eb45e34..fdb56b44dcd 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -46,6 +46,25 @@ void rs600_gpu_init(struct radeon_device *rdev); int rs600_mc_wait_for_idle(struct radeon_device *rdev); +void avivo_wait_for_vblank(struct radeon_device *rdev, int crtc) +{ + struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; + int i; + + if (RREG32(AVIVO_D1CRTC_CONTROL + radeon_crtc->crtc_offset) & AVIVO_CRTC_EN) { + for (i = 0; i < rdev->usec_timeout; i++) { + if (!(RREG32(AVIVO_D1CRTC_STATUS + radeon_crtc->crtc_offset) & AVIVO_D1CRTC_V_BLANK)) + break; + udelay(1); + } + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(AVIVO_D1CRTC_STATUS + radeon_crtc->crtc_offset) & AVIVO_D1CRTC_V_BLANK) + break; + udelay(1); + } + } +} + void rs600_pre_page_flip(struct radeon_device *rdev, int crtc) { /* enable the pflip int */