diff options
Diffstat (limited to 'drivers/gpu/drm/radeon')
53 files changed, 1309 insertions, 721 deletions
diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile index 09433534dc47..dbcbfe80aac0 100644 --- a/drivers/gpu/drm/radeon/Makefile +++ b/drivers/gpu/drm/radeon/Makefile @@ -72,7 +72,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \ radeon_cs.o radeon_bios.o radeon_benchmark.o r100.o r300.o r420.o \ rs400.o rs600.o rs690.o rv515.o r520.o r600.o rv770.o radeon_test.o \ r200.o radeon_legacy_tv.o r600_cs.o r600_blit_shaders.o \ - radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o \ + radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o dce3_1_afmt.o \ evergreen.o evergreen_cs.o evergreen_blit_shaders.o \ evergreen_hdmi.o radeon_trace_points.o ni.o cayman_blit_shaders.o \ atombios_encoders.o radeon_semaphore.o radeon_sa.o atombios_i2c.o si.o \ diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index e911898348f8..26c12a3fe430 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -557,6 +557,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, u32 adjusted_clock = mode->clock; int encoder_mode = atombios_get_encoder_mode(encoder); u32 dp_clock = mode->clock; + u32 clock = mode->clock; int bpc = radeon_crtc->bpc; bool is_duallink = radeon_dig_monitor_is_duallink(encoder, mode->clock); @@ -632,6 +633,24 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, radeon_crtc->pll_flags |= RADEON_PLL_USE_REF_DIV; } + /* adjust pll for deep color modes */ + if (encoder_mode == ATOM_ENCODER_MODE_HDMI) { + switch (bpc) { + case 8: + default: + break; + case 10: + clock = (clock * 5) / 4; + break; + case 12: + clock = (clock * 3) / 2; + break; + case 16: + clock = clock * 2; + break; + } + } + /* DCE3+ has an AdjustDisplayPll that will adjust the pixel clock * accordingly based on the encoder/transmitter to work around * special hw requirements. @@ -653,7 +672,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, switch (crev) { case 1: case 2: - args.v1.usPixelClock = cpu_to_le16(mode->clock / 10); + args.v1.usPixelClock = cpu_to_le16(clock / 10); args.v1.ucTransmitterID = radeon_encoder->encoder_id; args.v1.ucEncodeMode = encoder_mode; if (radeon_crtc->ss_enabled && radeon_crtc->ss.percentage) @@ -665,7 +684,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, adjusted_clock = le16_to_cpu(args.v1.usPixelClock) * 10; break; case 3: - args.v3.sInput.usPixelClock = cpu_to_le16(mode->clock / 10); + args.v3.sInput.usPixelClock = cpu_to_le16(clock / 10); args.v3.sInput.ucTransmitterID = radeon_encoder->encoder_id; args.v3.sInput.ucEncodeMode = encoder_mode; args.v3.sInput.ucDispPllConfig = 0; @@ -679,10 +698,6 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, args.v3.sInput.usPixelClock = cpu_to_le16(dp_clock / 10); } else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; - if (encoder_mode == ATOM_ENCODER_MODE_HDMI) - /* deep color support */ - args.v3.sInput.usPixelClock = - cpu_to_le16((mode->clock * bpc / 8) / 10); if (dig->coherent_mode) args.v3.sInput.ucDispPllConfig |= DISPPLL_CONFIG_COHERENT_MODE; @@ -862,14 +877,21 @@ static void atombios_crtc_program_pll(struct drm_crtc *crtc, args.v5.ucMiscInfo = 0; /* HDMI depth, etc. */ if (ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK)) args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_REF_DIV_SRC; - switch (bpc) { - case 8: - default: - args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_24BPP; - break; - case 10: - args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_30BPP; - break; + if (encoder_mode == ATOM_ENCODER_MODE_HDMI) { + switch (bpc) { + case 8: + default: + args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_24BPP; + break; + case 10: + /* yes this is correct, the atom define is wrong */ + args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_32BPP; + break; + case 12: + /* yes this is correct, the atom define is wrong */ + args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_30BPP; + break; + } } args.v5.ucTransmitterID = encoder_id; args.v5.ucEncoderMode = encoder_mode; @@ -884,20 +906,22 @@ static void atombios_crtc_program_pll(struct drm_crtc *crtc, args.v6.ucMiscInfo = 0; /* HDMI depth, etc. */ if (ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK)) args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_REF_DIV_SRC; - switch (bpc) { - case 8: - default: - args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_24BPP; - break; - case 10: - args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_30BPP; - break; - case 12: - args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_36BPP; - break; - case 16: - args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_48BPP; - break; + if (encoder_mode == ATOM_ENCODER_MODE_HDMI) { + switch (bpc) { + case 8: + default: + args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_24BPP; + break; + case 10: + args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_30BPP_V6; + break; + case 12: + args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_36BPP_V6; + break; + case 16: + args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_48BPP; + break; + } } args.v6.ucTransmitterID = encoder_id; args.v6.ucEncoderMode = encoder_mode; @@ -938,6 +962,9 @@ static bool atombios_crtc_prepare_pll(struct drm_crtc *crtc, struct drm_display_ struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; int dp_clock; + + /* Assign mode clock for hdmi deep color max clock limit check */ + radeon_connector->pixelclock_for_modeset = mode->clock; radeon_crtc->bpc = radeon_get_monitor_bpc(connector); switch (encoder_mode) { @@ -1019,10 +1046,17 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode struct radeon_encoder *radeon_encoder = to_radeon_encoder(radeon_crtc->encoder); u32 pll_clock = mode->clock; + u32 clock = mode->clock; u32 ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0; struct radeon_pll *pll; int encoder_mode = atombios_get_encoder_mode(radeon_crtc->encoder); + /* pass the actual clock to atombios_crtc_program_pll for DCE5,6 for HDMI */ + if (ASIC_IS_DCE5(rdev) && !ASIC_IS_DCE8(rdev) && + (encoder_mode == ATOM_ENCODER_MODE_HDMI) && + (radeon_crtc->bpc > 8)) + clock = radeon_crtc->adjusted_clock; + switch (radeon_crtc->pll_id) { case ATOM_PPLL1: pll = &rdev->clock.p1pll; @@ -1057,7 +1091,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode radeon_crtc->crtc_id, &radeon_crtc->ss); atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id, - encoder_mode, radeon_encoder->encoder_id, mode->clock, + encoder_mode, radeon_encoder->encoder_id, clock, ref_div, fb_div, frac_fb_div, post_div, radeon_crtc->bpc, radeon_crtc->ss_enabled, &radeon_crtc->ss); diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index 54e4f52549af..c5b1f2da3954 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -95,9 +95,12 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan, int index = GetIndexIntoMasterTable(COMMAND, ProcessAuxChannelTransaction); unsigned char *base; int recv_bytes; + int r = 0; memset(&args, 0, sizeof(args)); + mutex_lock(&chan->mutex); + base = (unsigned char *)(rdev->mode_info.atom_context->scratch + 1); radeon_atom_copy_swap(base, send, send_bytes, true); @@ -117,19 +120,22 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan, /* timeout */ if (args.v1.ucReplyStatus == 1) { DRM_DEBUG_KMS("dp_aux_ch timeout\n"); - return -ETIMEDOUT; + r = -ETIMEDOUT; + goto done; } /* flags not zero */ if (args.v1.ucReplyStatus == 2) { DRM_DEBUG_KMS("dp_aux_ch flags not zero\n"); - return -EBUSY; + r = -EBUSY; + goto done; } /* error */ if (args.v1.ucReplyStatus == 3) { DRM_DEBUG_KMS("dp_aux_ch error\n"); - return -EIO; + r = -EIO; + goto done; } recv_bytes = args.v1.ucDataOutLen; @@ -139,7 +145,11 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan, if (recv && recv_size) radeon_atom_copy_swap(recv, base + 16, recv_bytes, false); - return recv_bytes; + r = recv_bytes; +done: + mutex_unlock(&chan->mutex); + + return r; } #define BARE_ADDRESS_SIZE 3 @@ -212,11 +222,12 @@ void radeon_dp_aux_init(struct radeon_connector *radeon_connector) radeon_connector->ddc_bus->rec.hpd = radeon_connector->hpd.hpd; radeon_connector->ddc_bus->aux.dev = radeon_connector->base.kdev; radeon_connector->ddc_bus->aux.transfer = radeon_dp_aux_transfer; - ret = drm_dp_aux_register_i2c_bus(&radeon_connector->ddc_bus->aux); + + ret = drm_dp_aux_register(&radeon_connector->ddc_bus->aux); if (!ret) radeon_connector->ddc_bus->has_aux = true; - WARN(ret, "drm_dp_aux_register_i2c_bus() failed with error %d\n", ret); + WARN(ret, "drm_dp_aux_register() failed with error %d\n", ret); } /***** general DP utility functions *****/ @@ -281,6 +292,19 @@ static int dp_get_max_dp_pix_clock(int link_rate, /***** radeon specific DP functions *****/ +static int radeon_dp_get_max_link_rate(struct drm_connector *connector, + u8 dpcd[DP_DPCD_SIZE]) +{ + int max_link_rate; + + if (radeon_connector_is_dp12_capable(connector)) + max_link_rate = min(drm_dp_max_link_rate(dpcd), 540000); + else + max_link_rate = min(drm_dp_max_link_rate(dpcd), 270000); + + return max_link_rate; +} + /* First get the min lane# when low rate is used according to pixel clock * (prefer low rate), second check max lane# supported by DP panel, * if the max lane# < low rate lane# then use max lane# instead. @@ -290,7 +314,7 @@ static int radeon_dp_get_dp_lane_number(struct drm_connector *connector, int pix_clock) { int bpp = convert_bpc_to_bpp(radeon_get_monitor_bpc(connector)); - int max_link_rate = drm_dp_max_link_rate(dpcd); + int max_link_rate = radeon_dp_get_max_link_rate(connector, dpcd); int max_lane_num = drm_dp_max_lane_count(dpcd); int lane_num; int max_dp_pix_clock; @@ -328,7 +352,7 @@ static int radeon_dp_get_dp_link_clock(struct drm_connector *connector, return 540000; } - return drm_dp_max_link_rate(dpcd); + return radeon_dp_get_max_link_rate(connector, dpcd); } static u8 radeon_dp_encoder_service(struct radeon_device *rdev, diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index e6eb5097597f..2b2908440644 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -1884,8 +1884,11 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder) args.v2.ucEncodeMode = ATOM_ENCODER_MODE_CRT; else args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder); - } else + } else if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { + args.v2.ucEncodeMode = ATOM_ENCODER_MODE_LVDS; + } else { args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder); + } switch (radeon_encoder->encoder_id) { case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: diff --git a/drivers/gpu/drm/radeon/atombios_i2c.c b/drivers/gpu/drm/radeon/atombios_i2c.c index b5162c3b6111..9c570fb15b8c 100644 --- a/drivers/gpu/drm/radeon/atombios_i2c.c +++ b/drivers/gpu/drm/radeon/atombios_i2c.c @@ -43,15 +43,19 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan, int index = GetIndexIntoMasterTable(COMMAND, ProcessI2cChannelTransaction); unsigned char *base; u16 out = cpu_to_le16(0); + int r = 0; memset(&args, 0, sizeof(args)); + mutex_lock(&chan->mutex); + base = (unsigned char *)rdev->mode_info.atom_context->scratch; if (flags & HW_I2C_WRITE) { if (num > ATOM_MAX_HW_I2C_WRITE) { DRM_ERROR("hw i2c: tried to write too many bytes (%d vs 3)\n", num); - return -EINVAL; + r = -EINVAL; + goto done; } if (buf == NULL) args.ucRegIndex = 0; @@ -65,7 +69,8 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan, } else { if (num > ATOM_MAX_HW_I2C_READ) { DRM_ERROR("hw i2c: tried to read too many bytes (%d vs 255)\n", num); - return -EINVAL; + r = -EINVAL; + goto done; } args.ucRegIndex = 0; args.lpI2CDataOut = 0; @@ -82,13 +87,17 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan, /* error */ if (args.ucStatus != HW_ASSISTED_I2C_STATUS_SUCCESS) { DRM_DEBUG_KMS("hw_i2c error\n"); - return -EIO; + r = -EIO; + goto done; } if (!(flags & HW_I2C_WRITE)) radeon_atom_copy_swap(buf, base, num, false); - return 0; +done: + mutex_unlock(&chan->mutex); + + return r; } int radeon_atom_hw_i2c_xfer(struct i2c_adapter *i2c_adap, diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index d2fd98968085..dcd4518a9b08 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -80,6 +80,7 @@ extern int sumo_rlc_init(struct radeon_device *rdev); extern void si_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc); extern void si_rlc_reset(struct radeon_device *rdev); extern void si_init_uvd_internal_cg(struct radeon_device *rdev); +static u32 cik_get_cu_active_bitmap(struct radeon_device *rdev, u32 se, u32 sh); extern int cik_sdma_resume(struct radeon_device *rdev); extern void cik_sdma_enable(struct radeon_device *rdev, bool enable); extern void cik_sdma_fini(struct radeon_device *rdev); @@ -3257,7 +3258,7 @@ static void cik_gpu_init(struct radeon_device *rdev) u32 mc_shared_chmap, mc_arb_ramcfg; u32 hdp_host_path_cntl; u32 tmp; - int i, j; + int i, j, k; switch (rdev->family) { case CHIP_BONAIRE: @@ -3446,6 +3447,15 @@ static void cik_gpu_init(struct radeon_device *rdev) rdev->config.cik.max_sh_per_se, rdev->config.cik.max_backends_per_se); + for (i = 0; i < rdev->config.cik.max_shader_engines; i++) { + for (j = 0; j < rdev->config.cik.max_sh_per_se; j++) { + for (k = 0; k < rdev->config.cik.max_cu_per_sh; k++) { + rdev->config.cik.active_cus += + hweight32(cik_get_cu_active_bitmap(rdev, i, j)); + } + } + } + /* set HW defaults for 3D engine */ WREG32(CP_MEQ_THRESHOLDS, MEQ1_START(0x30) | MEQ2_START(0x60)); @@ -3698,7 +3708,7 @@ bool cik_semaphore_ring_emit(struct radeon_device *rdev, unsigned sel = emit_wait ? PACKET3_SEM_SEL_WAIT : PACKET3_SEM_SEL_SIGNAL; radeon_ring_write(ring, PACKET3(PACKET3_MEM_SEMAPHORE, 1)); - radeon_ring_write(ring, addr & 0xffffffff); + radeon_ring_write(ring, lower_32_bits(addr)); radeon_ring_write(ring, (upper_32_bits(addr) & 0xffff) | sel); return true; @@ -3818,7 +3828,7 @@ void cik_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); radeon_ring_write(ring, WRITE_DATA_DST_SEL(1)); radeon_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc); - radeon_ring_write(ring, upper_32_bits(ring->next_rptr_gpu_addr) & 0xffffffff); + radeon_ring_write(ring, upper_32_bits(ring->next_rptr_gpu_addr)); radeon_ring_write(ring, next_rptr); } @@ -5396,6 +5406,7 @@ static int cik_pcie_gart_enable(struct radeon_device *rdev) WREG32(MC_VM_MX_L1_TLB_CNTL, (0xA << 7) | ENABLE_L1_TLB | + ENABLE_L1_FRAGMENT_PROCESSING | SYSTEM_ACCESS_MODE_NOT_IN_SYS | ENABLE_ADVANCED_DRIVER_MODEL | SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU); @@ -5408,7 +5419,8 @@ static int cik_pcie_gart_enable(struct radeon_device *rdev) CONTEXT1_IDENTITY_ACCESS_MODE(1)); WREG32(VM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS | INVALIDATE_L2_CACHE); WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY | - L2_CACHE_BIGK_FRAGMENT_SIZE(6)); + BANK_SELECT(4) | + L2_CACHE_BIGK_FRAGMENT_SIZE(4)); /* setup context0 */ WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12); WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12); @@ -5444,6 +5456,7 @@ static int cik_pcie_gart_enable(struct radeon_device *rdev) (u32)(rdev->dummy_page.addr >> 12)); WREG32(VM_CONTEXT1_CNTL2, 4); WREG32(VM_CONTEXT1_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(1) | + PAGE_TABLE_BLOCK_SIZE(radeon_vm_block_size - 9) | RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT | RANGE_PROTECTION_FAULT_ENABLE_DEFAULT | DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT | @@ -7450,7 +7463,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[0])) - radeon_crtc_handle_flip(rdev, 0); + radeon_crtc_handle_vblank(rdev, 0); rdev->irq.stat_regs.cik.disp_int &= ~LB_D1_VBLANK_INTERRUPT; DRM_DEBUG("IH: D1 vblank\n"); } @@ -7476,7 +7489,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[1])) - radeon_crtc_handle_flip(rdev, 1); + radeon_crtc_handle_vblank(rdev, 1); rdev->irq.stat_regs.cik.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; DRM_DEBUG("IH: D2 vblank\n"); } @@ -7502,7 +7515,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[2])) - radeon_crtc_handle_flip(rdev, 2); + radeon_crtc_handle_vblank(rdev, 2); rdev->irq.stat_regs.cik.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; DRM_DEBUG("IH: D3 vblank\n"); } @@ -7528,7 +7541,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[3])) - radeon_crtc_handle_flip(rdev, 3); + radeon_crtc_handle_vblank(rdev, 3); rdev->irq.stat_regs.cik.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; DRM_DEBUG("IH: D4 vblank\n"); } @@ -7554,7 +7567,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[4])) - radeon_crtc_handle_flip(rdev, 4); + radeon_crtc_handle_vblank(rdev, 4); rdev->irq.stat_regs.cik.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; DRM_DEBUG("IH: D5 vblank\n"); } @@ -7580,7 +7593,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[5])) - radeon_crtc_handle_flip(rdev, 5); + radeon_crtc_handle_vblank(rdev, 5); rdev->irq.stat_regs.cik.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; DRM_DEBUG("IH: D6 vblank\n"); } diff --git a/drivers/gpu/drm/radeon/cik_sdma.c b/drivers/gpu/drm/radeon/cik_sdma.c index 72e464c79a88..8e9d0f1d858e 100644 --- a/drivers/gpu/drm/radeon/cik_sdma.c +++ b/drivers/gpu/drm/radeon/cik_sdma.c @@ -141,7 +141,7 @@ void cik_sdma_ring_ib_execute(struct radeon_device *rdev, next_rptr += 4; radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_WRITE, SDMA_WRITE_SUB_OPCODE_LINEAR, 0)); radeon_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc); - radeon_ring_write(ring, upper_32_bits(ring->next_rptr_gpu_addr) & 0xffffffff); + radeon_ring_write(ring, upper_32_bits(ring->next_rptr_gpu_addr)); radeon_ring_write(ring, 1); /* number of DWs to follow */ radeon_ring_write(ring, next_rptr); } @@ -151,7 +151,7 @@ void cik_sdma_ring_ib_execute(struct radeon_device *rdev, radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_NOP, 0, 0)); radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_INDIRECT_BUFFER, 0, extra_bits)); radeon_ring_write(ring, ib->gpu_addr & 0xffffffe0); /* base must be 32 byte aligned */ - radeon_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xffffffff); + radeon_ring_write(ring, upper_32_bits(ib->gpu_addr)); radeon_ring_write(ring, ib->length_dw); } @@ -203,8 +203,8 @@ void cik_sdma_fence_ring_emit(struct radeon_device *rdev, /* write the fence */ radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_FENCE, 0, 0)); - radeon_ring_write(ring, addr & 0xffffffff); - radeon_ring_write(ring, upper_32_bits(addr) & 0xffffffff); + radeon_ring_write(ring, lower_32_bits(addr)); + radeon_ring_write(ring, upper_32_bits(addr)); radeon_ring_write(ring, fence->seq); /* generate an interrupt */ radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_TRAP, 0, 0)); @@ -233,7 +233,7 @@ bool cik_sdma_semaphore_ring_emit(struct radeon_device *rdev, radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_SEMAPHORE, 0, extra_bits)); radeon_ring_write(ring, addr & 0xfffffff8); - radeon_ring_write(ring, upper_32_bits(addr) & 0xffffffff); + radeon_ring_write(ring, upper_32_bits(addr)); return true; } @@ -551,10 +551,10 @@ int cik_copy_dma(struct radeon_device *rdev, radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_COPY, SDMA_COPY_SUB_OPCODE_LINEAR, 0)); radeon_ring_write(ring, cur_size_in_bytes); radeon_ring_write(ring, 0); /* src/dst endian swap */ - radeon_ring_write(ring, src_offset & 0xffffffff); - radeon_ring_write(ring, upper_32_bits(src_offset) & 0xffffffff); - radeon_ring_write(ring, dst_offset & 0xffffffff); - radeon_ring_write(ring, upper_32_bits(dst_offset) & 0xffffffff); + radeon_ring_write(ring, lower_32_bits(src_offset)); + radeon_ring_write(ring, upper_32_bits(src_offset)); + radeon_ring_write(ring, lower_32_bits(dst_offset)); + radeon_ring_write(ring, upper_32_bits(dst_offset)); src_offset += cur_size_in_bytes; dst_offset += cur_size_in_bytes; } @@ -605,7 +605,7 @@ int cik_sdma_ring_test(struct radeon_device *rdev, } radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_WRITE, SDMA_WRITE_SUB_OPCODE_LINEAR, 0)); radeon_ring_write(ring, rdev->vram_scratch.gpu_addr & 0xfffffffc); - radeon_ring_write(ring, upper_32_bits(rdev->vram_scratch.gpu_addr) & 0xffffffff); + radeon_ring_write(ring, upper_32_bits(rdev->vram_scratch.gpu_addr)); radeon_ring_write(ring, 1); /* number of DWs to follow */ radeon_ring_write(ring, 0xDEADBEEF); radeon_ring_unlock_commit(rdev, ring); @@ -660,7 +660,7 @@ int cik_sdma_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) ib.ptr[0] = SDMA_PACKET(SDMA_OPCODE_WRITE, SDMA_WRITE_SUB_OPCODE_LINEAR, 0); ib.ptr[1] = rdev->vram_scratch.gpu_addr & 0xfffffffc; - ib.ptr[2] = upper_32_bits(rdev->vram_scratch.gpu_addr) & 0xffffffff; + ib.ptr[2] = upper_32_bits(rdev->vram_scratch.gpu_addr); ib.ptr[3] = 1; ib.ptr[4] = 0xDEADBEEF; ib.length_dw = 5; @@ -742,7 +742,26 @@ void cik_sdma_vm_set_page(struct radeon_device *rdev, trace_radeon_vm_set_page(pe, addr, count, incr, flags); - if (flags & R600_PTE_SYSTEM) { + if (flags == R600_PTE_GART) { + uint64_t src = rdev->gart.table_addr + (addr >> 12) * 8; + while (count) { + unsigned bytes = count * 8; + if (bytes > 0x1FFFF8) + bytes = 0x1FFFF8; + + ib->ptr[ib->length_dw++] = SDMA_PACKET(SDMA_OPCODE_COPY, SDMA_WRITE_SUB_OPCODE_LINEAR, 0); + ib->ptr[ib->length_dw++] = bytes; + ib->ptr[ib->length_dw++] = 0; /* src/dst endian swap */ + ib->ptr[ib->length_dw++] = lower_32_bits(src); + ib->ptr[ib->length_dw++] = upper_32_bits(src); + ib->ptr[ib->length_dw++] = lower_32_bits(pe); + ib->ptr[ib->length_dw++] = upper_32_bits(pe); + + pe += bytes; + src += bytes; + count -= bytes / 8; + } + } else if (flags & R600_PTE_SYSTEM) { while (count) { ndw = count * 2; if (ndw > 0xFFFFE) diff --git a/drivers/gpu/drm/radeon/cikd.h b/drivers/gpu/drm/radeon/cikd.h index dd7926394a8f..ae88660f34ea 100644 --- a/drivers/gpu/drm/radeon/cikd.h +++ b/drivers/gpu/drm/radeon/cikd.h @@ -482,6 +482,7 @@ #define READ_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 16) #define WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 18) #define WRITE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 19) +#define PAGE_TABLE_BLOCK_SIZE(x) (((x) & 0xF) << 24) #define VM_CONTEXT1_CNTL 0x1414 #define VM_CONTEXT0_CNTL2 0x1430 #define VM_CONTEXT1_CNTL2 0x1434 diff --git a/drivers/gpu/drm/radeon/clearstate_cayman.h b/drivers/gpu/drm/radeon/clearstate_cayman.h index aa908c55a513..e48a14037b76 100644 --- a/drivers/gpu/drm/radeon/clearstate_cayman.h +++ b/drivers/gpu/drm/radeon/clearstate_cayman.h @@ -1050,7 +1050,7 @@ static const struct cs_extent_def SECT_CONTEXT_defs[] = {SECT_CONTEXT_def_5, 0x0000a29e, 5 }, {SECT_CONTEXT_def_6, 0x0000a2a5, 56 }, {SECT_CONTEXT_def_7, 0x0000a2de, 290 }, - { 0, 0, 0 } + { NULL, 0, 0 } }; static const u32 SECT_CLEAR_def_1[] = { @@ -1061,7 +1061,7 @@ static const u32 SECT_CLEAR_def_1[] = static const struct cs_extent_def SECT_CLEAR_defs[] = { {SECT_CLEAR_def_1, 0x0000ffc0, 3 }, - { 0, 0, 0 } + { NULL, 0, 0 } }; static const u32 SECT_CTRLCONST_def_1[] = { @@ -1071,11 +1071,11 @@ static const u32 SECT_CTRLCONST_def_1[] = static const struct cs_extent_def SECT_CTRLCONST_defs[] = { {SECT_CTRLCONST_def_1, 0x0000f3fc, 2 }, - { 0, 0, 0 } + { NULL, 0, 0 } }; static const struct cs_section_def cayman_cs_data[] = { { SECT_CONTEXT_defs, SECT_CONTEXT }, { SECT_CLEAR_defs, SECT_CLEAR }, { SECT_CTRLCONST_defs, SECT_CTRLCONST }, - { 0, SECT_NONE } + { NULL, SECT_NONE } }; diff --git a/drivers/gpu/drm/radeon/clearstate_ci.h b/drivers/gpu/drm/radeon/clearstate_ci.h index c3982f9475fb..f55d06664e31 100644 --- a/drivers/gpu/drm/radeon/clearstate_ci.h +++ b/drivers/gpu/drm/radeon/clearstate_ci.h @@ -936,9 +936,9 @@ static const struct cs_extent_def ci_SECT_CONTEXT_defs[] = {ci_SECT_CONTEXT_def_5, 0x0000a2a0, 2 }, {ci_SECT_CONTEXT_def_6, 0x0000a2a3, 1 }, {ci_SECT_CONTEXT_def_7, 0x0000a2a5, 233 }, - { 0, 0, 0 } + { NULL, 0, 0 } }; static const struct cs_section_def ci_cs_data[] = { { ci_SECT_CONTEXT_defs, SECT_CONTEXT }, - { 0, SECT_NONE } + { NULL, SECT_NONE } }; diff --git a/drivers/gpu/drm/radeon/clearstate_si.h b/drivers/gpu/drm/radeon/clearstate_si.h index b994cb2a35a0..66e39cdb5cb0 100644 --- a/drivers/gpu/drm/radeon/clearstate_si.h +++ b/drivers/gpu/drm/radeon/clearstate_si.h @@ -933,9 +933,9 @@ static const struct cs_extent_def si_SECT_CONTEXT_defs[] = {si_SECT_CONTEXT_def_5, 0x0000a2a1, 1 }, {si_SECT_CONTEXT_def_6, 0x0000a2a3, 1 }, {si_SECT_CONTEXT_def_7, 0x0000a2a5, 233 }, - { 0, 0, 0 } + { NULL, 0, 0 } }; static const struct cs_section_def si_cs_data[] = { { si_SECT_CONTEXT_defs, SECT_CONTEXT }, - { 0, SECT_NONE } + { NULL, SECT_NONE } }; diff --git a/drivers/gpu/drm/radeon/dce3_1_afmt.c b/drivers/gpu/drm/radeon/dce3_1_afmt.c new file mode 100644 index 000000000000..51800e340a57 --- /dev/null +++ b/drivers/gpu/drm/radeon/dce3_1_afmt.c @@ -0,0 +1,244 @@ +/* + * Copyright 2013 Advanced Micro Devices, Inc. + * Copyright 2014 Rafał Miłecki + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include <linux/hdmi.h> +#include <drm/drmP.h> +#include "radeon.h" +#include "radeon_asic.h" +#include "r600d.h" + +static void dce3_2_afmt_write_speaker_allocation(struct drm_encoder *encoder) +{ + struct radeon_device *rdev = encoder->dev->dev_private; + struct drm_connector *connector; + struct radeon_connector *radeon_connector = NULL; + u32 tmp; + u8 *sadb; + int sad_count; + + list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) { + if (connector->encoder == encoder) { + radeon_connector = to_radeon_connector(connector); + break; + } + } + + if (!radeon_connector) { + DRM_ERROR("Couldn't find encoder's connector\n"); + return; + } + + sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb); + if (sad_count < 0) { + DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count); + return; + } + + /* program the speaker allocation */ + tmp = RREG32(AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER); + tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK); + /* set HDMI mode */ + tmp |= HDMI_CONNECTION; + if (sad_count) + tmp |= SPEAKER_ALLOCATION(sadb[0]); + else + tmp |= SPEAKER_ALLOCATION(5); /* stereo */ + WREG32(AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER, tmp); + + kfree(sadb); +} + +static void dce3_2_afmt_write_sad_regs(struct drm_encoder *encoder) +{ + struct radeon_device *rdev = encoder->dev->dev_private; + struct drm_connector *connector; + struct radeon_connector *radeon_connector = NULL; + struct cea_sad *sads; + int i, sad_count; + + static const u16 eld_reg_to_type[][2] = { + { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR0, HDMI_AUDIO_CODING_TYPE_PCM }, + { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR1, HDMI_AUDIO_CODING_TYPE_AC3 }, + { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR2, HDMI_AUDIO_CODING_TYPE_MPEG1 }, + { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR3, HDMI_AUDIO_CODING_TYPE_MP3 }, + { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR4, HDMI_AUDIO_CODING_TYPE_MPEG2 }, + { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR5, HDMI_AUDIO_CODING_TYPE_AAC_LC }, + { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR6, HDMI_AUDIO_CODING_TYPE_DTS }, + { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR7, HDMI_AUDIO_CODING_TYPE_ATRAC }, + { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR9, HDMI_AUDIO_CODING_TYPE_EAC3 }, + { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR10, HDMI_AUDIO_CODING_TYPE_DTS_HD }, + { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR11, HDMI_AUDIO_CODING_TYPE_MLP }, + { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR13, HDMI_AUDIO_CODING_TYPE_WMA_PRO }, + }; + + list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) { + if (connector->encoder == encoder) { + radeon_connector = to_radeon_connector(connector); + break; + } + } + + if (!radeon_connector) { + DRM_ERROR("Couldn't find encoder's connector\n"); + return; + } + + sad_count = drm_edid_to_sad(radeon_connector->edid, &sads); + if (sad_count < 0) { + DRM_ERROR("Couldn't read SADs: %d\n", sad_count); + return; + } + BUG_ON(!sads); + + for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) { + u32 value = 0; + u8 stereo_freqs = 0; + int max_channels = -1; + int j; + + for (j = 0; j < sad_count; j++) { + struct cea_sad *sad = &sads[j]; + + if (sad->format == eld_reg_to_type[i][1]) { + if (sad->channels > max_channels) { + value = MAX_CHANNELS(sad->channels) | + DESCRIPTOR_BYTE_2(sad->byte2) | + SUPPORTED_FREQUENCIES(sad->freq); + max_channels = sad->channels; + } + + if (sad->format == HDMI_AUDIO_CODING_TYPE_PCM) + stereo_freqs |= sad->freq; + else + break; + } + } + + value |= SUPPORTED_FREQUENCIES_STEREO(stereo_freqs); + + WREG32(eld_reg_to_type[i][0], value); + } + + kfree(sads); +} + +/* + * update the info frames with the data from the current display mode + */ +void dce3_1_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE]; + struct hdmi_avi_infoframe frame; + uint32_t offset; + ssize_t err; + + if (!dig || !dig->afmt) + return; + + /* Silent, r600_hdmi_enable will raise WARN for us */ + if (!dig->afmt->enabled) + return; + offset = dig->afmt->offset; + + /* disable audio prior to setting up hw */ + dig->afmt->pin = r600_audio_get_pin(rdev); + r600_audio_enable(rdev, dig->afmt->pin, false); + + r600_audio_set_dto(encoder, mode->clock); + + WREG32(HDMI0_VBI_PACKET_CONTROL + offset, + HDMI0_NULL_SEND); /* send null packets when required */ + + WREG32(HDMI0_AUDIO_CRC_CONTROL + offset, 0x1000); + + if (ASIC_IS_DCE32(rdev)) { + WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset, + HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */ + HDMI0_AUDIO_PACKETS_PER_LINE(3)); /* should be suffient for all audio modes and small enough for all hblanks */ + WREG32(AFMT_AUDIO_PACKET_CONTROL + offset, + AFMT_AUDIO_SAMPLE_SEND | /* send audio packets */ + AFMT_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */ + } else { + WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset, + HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */ + HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */ + HDMI0_AUDIO_PACKETS_PER_LINE(3) | /* should be suffient for all audio modes and small enough for all hblanks */ + HDMI0_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */ + } + + if (ASIC_IS_DCE32(rdev)) { + dce3_2_afmt_write_speaker_allocation(encoder); + dce3_2_afmt_write_sad_regs(encoder); + } + + WREG32(HDMI0_ACR_PACKET_CONTROL + offset, + HDMI0_ACR_SOURCE | /* select SW CTS value - XXX verify that hw CTS works on all families */ + HDMI0_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */ + + WREG32(HDMI0_VBI_PACKET_CONTROL + offset, + HDMI0_NULL_SEND | /* send null packets when required */ + HDMI0_GC_SEND | /* send general control packets */ + HDMI0_GC_CONT); /* send general control packets every frame */ + + /* TODO: HDMI0_AUDIO_INFO_UPDATE */ + WREG32(HDMI0_INFOFRAME_CONTROL0 + offset, + HDMI0_AVI_INFO_SEND | /* enable AVI info frames */ + HDMI0_AVI_INFO_CONT | /* send AVI info frames every frame/field */ + HDMI0_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */ + HDMI0_AUDIO_INFO_CONT); /* send audio info frames every frame/field */ + + WREG32(HDMI0_INFOFRAME_CONTROL1 + offset, + HDMI0_AVI_INFO_LINE(2) | /* anything other than 0 */ + HDMI0_AUDIO_INFO_LINE(2)); /* anything other than 0 */ + + WREG32(HDMI0_GC + offset, 0); /* unset HDMI0_GC_AVMUTE */ + + err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); + if (err < 0) { + DRM_ERROR("failed to setup AVI infoframe: %zd\n", err); + return; + } + + err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer)); + if (err < 0) { + DRM_ERROR("failed to pack AVI infoframe: %zd\n", err); + return; + } + + r600_hdmi_update_avi_infoframe(encoder, buffer, sizeof(buffer)); + r600_hdmi_update_ACR(encoder, mode->clock); + + /* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */ + WREG32(HDMI0_RAMP_CONTROL0 + offset, 0x00FFFFFF); + WREG32(HDMI0_RAMP_CONTROL1 + offset, 0x007FFFFF); + WREG32(HDMI0_RAMP_CONTROL2 + offset, 0x00000001); + WREG32(HDMI0_RAMP_CONTROL3 + offset, 0x00000001); + + r600_hdmi_audio_workaround(encoder); + + /* enable audio after to setting up hw */ + r600_audio_enable(rdev, dig->afmt->pin, true); +} diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 0f7a51a3694f..e2f605224e8c 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1301,36 +1301,6 @@ void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc) } /** - * radeon_irq_kms_pflip_irq_get - pre-pageflip callback. - * - * @rdev: radeon_device pointer - * @crtc: crtc to prepare for pageflip on - * - * Pre-pageflip callback (evergreen+). - * Enables the pageflip irq (vblank irq). - */ -void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc) -{ - /* enable the pflip int */ - radeon_irq_kms_pflip_irq_get(rdev, crtc); -} - -/** - * evergreen_post_page_flip - pos-pageflip callback. - * - * @rdev: radeon_device pointer - * @crtc: crtc to cleanup pageflip on - * - * Post-pageflip callback (evergreen+). - * Disables the pageflip irq (vblank irq). - */ -void evergreen_post_page_flip(struct radeon_device *rdev, int crtc) -{ - /* disable the pflip int */ - radeon_irq_kms_pflip_irq_put(rdev, crtc); -} - -/** * evergreen_page_flip - pageflip callback. * * @rdev: radeon_device pointer @@ -1343,7 +1313,7 @@ void evergreen_post_page_flip(struct radeon_device *rdev, int crtc) * double buffered update to take place. * Returns the current update pending status. */ -u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) +void evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; u32 tmp = RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset); @@ -1375,9 +1345,23 @@ u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) /* Unlock the lock, so double-buffering can take place inside vblank */ tmp &= ~EVERGREEN_GRPH_UPDATE_LOCK; WREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); +} + +/** + * evergreen_page_flip_pending - check if page flip is still pending + * + * @rdev: radeon_device pointer + * @crtc_id: crtc to check + * + * Returns the current update pending status. + */ +bool evergreen_page_flip_pending(struct radeon_device *rdev, int crtc_id) +{ + struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; /* Return current update_pending status: */ - return RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING; + return !!(RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & + EVERGREEN_GRPH_SURFACE_UPDATE_PENDING); } /* get temperature in millidegrees */ @@ -3353,6 +3337,18 @@ static void evergreen_gpu_init(struct radeon_device *rdev) disabled_rb_mask &= ~(1 << i); } + for (i = 0; i < rdev->config.evergreen.num_ses; i++) { + u32 simd_disable_bitmap; + + WREG32(GRBM_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_INDEX(i)); + WREG32(RLC_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_INDEX(i)); + simd_disable_bitmap = (RREG32(CC_GC_SHADER_PIPE_CONFIG) & 0xffff0000) >> 16; + simd_disable_bitmap |= 0xffffffff << rdev->config.evergreen.max_simds; + tmp <<= 16; + tmp |= simd_disable_bitmap; + } + rdev->config.evergreen.active_simds = hweight32(~tmp); + WREG32(GRBM_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_BROADCAST_WRITES); WREG32(RLC_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_BROADCAST_WRITES); @@ -4810,7 +4806,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[0])) - radeon_crtc_handle_flip(rdev, 0); + radeon_crtc_handle_vblank(rdev, 0); rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT; DRM_DEBUG("IH: D1 vblank\n"); } @@ -4836,7 +4832,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[1])) - radeon_crtc_handle_flip(rdev, 1); + radeon_crtc_handle_vblank(rdev, 1); rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; DRM_DEBUG("IH: D2 vblank\n"); } @@ -4862,7 +4858,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[2])) - radeon_crtc_handle_flip(rdev, 2); + radeon_crtc_handle_vblank(rdev, 2); rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; DRM_DEBUG("IH: D3 vblank\n"); } @@ -4888,7 +4884,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[3])) - radeon_crtc_handle_flip(rdev, 3); + radeon_crtc_handle_vblank(rdev, 3); rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; DRM_DEBUG("IH: D4 vblank\n"); } @@ -4914,7 +4910,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[4])) - radeon_crtc_handle_flip(rdev, 4); + radeon_crtc_handle_vblank(rdev, 4); rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; DRM_DEBUG("IH: D5 vblank\n"); } @@ -4940,7 +4936,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[5])) - radeon_crtc_handle_flip(rdev, 5); + radeon_crtc_handle_vblank(rdev, 5); rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; DRM_DEBUG("IH: D6 vblank\n"); } diff --git a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c index 05b0c95813fd..1ec0e6e83f9f 100644 --- a/drivers/gpu/drm/radeon/evergreen_hdmi.c +++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c @@ -293,10 +293,13 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE]; struct hdmi_avi_infoframe frame; uint32_t offset; ssize_t err; + uint32_t val; + int bpc = 8; if (!dig || !dig->afmt) return; @@ -306,6 +309,12 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode return; offset = dig->afmt->offset; + /* hdmi deep color mode general control packets setup, if bpc > 8 */ + if (encoder->crtc) { + struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); + bpc = radeon_crtc->bpc; + } + /* disable audio prior to setting up hw */ if (ASIC_IS_DCE6(rdev)) { dig->afmt->pin = dce6_audio_get_pin(rdev); @@ -322,6 +331,35 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode WREG32(AFMT_AUDIO_CRC_CONTROL + offset, 0x1000); + val = RREG32(HDMI_CONTROL + offset); + val &= ~HDMI_DEEP_COLOR_ENABLE; + val &= ~HDMI_DEEP_COLOR_DEPTH_MASK; + + switch (bpc) { + case 0: + case 6: + case 8: + case 16: + default: + DRM_DEBUG("%s: Disabling hdmi deep color for %d bpc.\n", + connector->name, bpc); + break; + case 10: + val |= HDMI_DEEP_COLOR_ENABLE; + val |= HDMI_DEEP_COLOR_DEPTH(HDMI_30BIT_DEEP_COLOR); + DRM_DEBUG("%s: Enabling hdmi deep color 30 for 10 bpc.\n", + connector->name); + break; + case 12: + val |= HDMI_DEEP_COLOR_ENABLE; + val |= HDMI_DEEP_COLOR_DEPTH(HDMI_36BIT_DEEP_COLOR); + DRM_DEBUG("%s: Enabling hdmi deep color 36 for 12 bpc.\n", + connector->name); + break; + } + + WREG32(HDMI_CONTROL + offset, val); + WREG32(HDMI_VBI_PACKET_CONTROL + offset, HDMI_NULL_SEND | /* send null packets when required */ HDMI_GC_SEND | /* send general control packets */ @@ -348,9 +386,13 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode /* fglrx clears sth in AFMT_AUDIO_PACKET_CONTROL2 here */ - WREG32(HDMI_ACR_PACKET_CONTROL + offset, - HDMI_ACR_SOURCE | /* select SW CTS value */ - HDMI_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */ + if (bpc > 8) + WREG32(HDMI_ACR_PACKET_CONTROL + offset, + HDMI_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */ + else + WREG32(HDMI_ACR_PACKET_CONTROL + offset, + HDMI_ACR_SOURCE | /* select SW CTS value */ + HDMI_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */ evergreen_hdmi_update_ACR(encoder, mode->clock); diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index f9c7963b3ee6..b066d6711b8d 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -517,10 +517,11 @@ # define HDMI_ERROR_ACK (1 << 8) # define HDMI_ERROR_MASK (1 << 9) # define HDMI_DEEP_COLOR_ENABLE (1 << 24) -# define HDMI_DEEP_COLOR_DEPTH (((x) & 3) << 28) +# define HDMI_DEEP_COLOR_DEPTH(x) (((x) & 3) << 28) # define HDMI_24BIT_DEEP_COLOR 0 # define HDMI_30BIT_DEEP_COLOR 1 # define HDMI_36BIT_DEEP_COLOR 2 +# define HDMI_DEEP_COLOR_DEPTH_MASK (3 << 28) #define HDMI_STATUS 0x7034 # define HDMI_ACTIVE_AVMUTE (1 << 0) # define HDMI_AUDIO_PACKET_ERROR (1 << 16) diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index d246e043421a..5a33ca681867 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -1057,6 +1057,18 @@ static void cayman_gpu_init(struct radeon_device *rdev) disabled_rb_mask &= ~(1 << i); } + for (i = 0; i < rdev->config.cayman.max_shader_engines; i++) { + u32 simd_disable_bitmap; + + WREG32(GRBM_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_INDEX(i)); + WREG32(RLC_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_INDEX(i)); + simd_disable_bitmap = (RREG32(CC_GC_SHADER_PIPE_CONFIG) & 0xffff0000) >> 16; + simd_disable_bitmap |= 0xffffffff << rdev->config.cayman.max_simds_per_se; + tmp <<= 16; + tmp |= simd_disable_bitmap; + } + rdev->config.cayman.active_simds = hweight32(~tmp); + WREG32(GRBM_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_BROADCAST_WRITES); WREG32(RLC_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_BROADCAST_WRITES); @@ -1228,12 +1240,14 @@ static int cayman_pcie_gart_enable(struct radeon_device *rdev) SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU); /* Setup L2 cache */ WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | + ENABLE_L2_FRAGMENT_PROCESSING | ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE | EFFECTIVE_L2_QUEUE_SIZE(7) | CONTEXT1_IDENTITY_ACCESS_MODE(1)); WREG32(VM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS | INVALIDATE_L2_CACHE); WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY | + BANK_SELECT(6) | L2_CACHE_BIGK_FRAGMENT_SIZE(6)); /* setup context0 */ WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12); @@ -1266,6 +1280,7 @@ static int cayman_pcie_gart_enable(struct radeon_device *rdev) (u32)(rdev->dummy_page.addr >> 12)); WREG32(VM_CONTEXT1_CNTL2, 4); WREG32(VM_CONTEXT1_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(1) | + PAGE_TABLE_BLOCK_SIZE(radeon_vm_block_size - 9) | RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT | RANGE_PROTECTION_FAULT_ENABLE_DEFAULT | DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT | @@ -1343,7 +1358,7 @@ void cayman_fence_ring_emit(struct radeon_device *rdev, /* EVENT_WRITE_EOP - flush caches, send int */ radeon_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE_EOP, 4)); radeon_ring_write(ring, EVENT_TYPE(CACHE_FLUSH_AND_INV_EVENT_TS) | EVENT_INDEX(5)); - radeon_ring_write(ring, addr & 0xffffffff); + radeon_ring_write(ring, lower_32_bits(addr)); radeon_ring_write(ring, (upper_32_bits(addr) & 0xff) | DATA_SEL(1) | INT_SEL(2)); radeon_ring_write(ring, fence->seq); radeon_ring_write(ring, 0); diff --git a/drivers/gpu/drm/radeon/nid.h b/drivers/gpu/drm/radeon/nid.h index d996033c243e..2e12e4d69253 100644 --- a/drivers/gpu/drm/radeon/nid.h +++ b/drivers/gpu/drm/radeon/nid.h @@ -128,6 +128,7 @@ #define READ_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 16) #define WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 18) #define WRITE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 19) +#define PAGE_TABLE_BLOCK_SIZE(x) (((x) & 0xF) << 24) #define VM_CONTEXT1_CNTL 0x1414 #define VM_CONTEXT0_CNTL2 0x1430 #define VM_CONTEXT1_CNTL2 0x1434 diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index b6c32640df20..1544efcf1c3a 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -142,36 +142,6 @@ void r100_wait_for_vblank(struct radeon_device *rdev, int crtc) } /** - * r100_pre_page_flip - pre-pageflip callback. - * - * @rdev: radeon_device pointer - * @crtc: crtc to prepare for pageflip on - * - * Pre-pageflip callback (r1xx-r4xx). - * Enables the pageflip irq (vblank irq). - */ -void r100_pre_page_flip(struct radeon_device *rdev, int crtc) -{ - /* enable the pflip int */ - radeon_irq_kms_pflip_irq_get(rdev, crtc); -} - -/** - * r100_post_page_flip - pos-pageflip callback. - * - * @rdev: radeon_device pointer - * @crtc: crtc to cleanup pageflip on - * - * Post-pageflip callback (r1xx-r4xx). - * Disables the pageflip irq (vblank irq). - */ -void r100_post_page_flip(struct radeon_device *rdev, int crtc) -{ - /* disable the pflip int */ - radeon_irq_kms_pflip_irq_put(rdev, crtc); -} - -/** * r100_page_flip - pageflip callback. * * @rdev: radeon_device pointer @@ -182,9 +152,8 @@ void r100_post_page_flip(struct radeon_device *rdev, int crtc) * During vblank we take the crtc lock and wait for the update_pending * bit to go high, when it does, we release the lock, and allow the * double buffered update to take place. - * Returns the current update pending status. */ -u32 r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) +void r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; u32 tmp = ((u32)crtc_base) | RADEON_CRTC_OFFSET__OFFSET_LOCK; @@ -206,8 +175,24 @@ u32 r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) tmp &= ~RADEON_CRTC_OFFSET__OFFSET_LOCK; WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp); +} + +/** + * r100_page_flip_pending - check if page flip is still pending + * + * @rdev: radeon_device pointer + * @crtc_id: crtc to check + * + * Check if the last pagefilp is still pending (r1xx-r4xx). + * Returns the current update pending status. + */ +bool r100_page_flip_pending(struct radeon_device *rdev, int crtc_id) +{ + struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; + /* Return current update_pending status: */ - return RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET; + return !!(RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & + RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET); } /** @@ -697,15 +682,11 @@ void r100_pci_gart_disable(struct radeon_device *rdev) WREG32(RADEON_AIC_HI_ADDR, 0); } -int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) +void r100_pci_gart_set_page(struct radeon_device *rdev, unsigned i, + uint64_t addr) { u32 *gtt = rdev->gart.ptr; - - if (i < 0 || i > rdev->gart.num_gpu_pages) { - return -EINVAL; - } gtt[i] = cpu_to_le32(lower_32_bits(addr)); - return 0; } void r100_pci_gart_fini(struct radeon_device *rdev) @@ -794,7 +775,7 @@ int r100_irq_process(struct radeon_device *rdev) wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[0])) - radeon_crtc_handle_flip(rdev, 0); + radeon_crtc_handle_vblank(rdev, 0); } if (status & RADEON_CRTC2_VBLANK_STAT) { if (rdev->irq.crtc_vblank_int[1]) { @@ -803,7 +784,7 @@ int r100_irq_process(struct radeon_device *rdev) wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[1])) - radeon_crtc_handle_flip(rdev, 1); + radeon_crtc_handle_vblank(rdev, 1); } if (status & RADEON_FP_DETECT_STAT) { queue_hotplug = true; diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 206caf9700b7..3c21d77a483d 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -72,13 +72,11 @@ void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev) #define R300_PTE_WRITEABLE (1 << 2) #define R300_PTE_READABLE (1 << 3) -int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) +void rv370_pcie_gart_set_page(struct radeon_device *rdev, unsigned i, + uint64_t addr) { void __iomem *ptr = rdev->gart.ptr; - if (i < 0 || i > rdev->gart.num_gpu_pages) { - return -EINVAL; - } addr = (lower_32_bits(addr) >> 8) | ((upper_32_bits(addr) & 0xff) << 24) | R300_PTE_WRITEABLE | R300_PTE_READABLE; @@ -86,7 +84,6 @@ int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) * on powerpc without HW swappers, it'll get swapped on way * into VRAM - so no need for cpu_to_le32 on VRAM tables */ writel(addr, ((void __iomem *)ptr) + (i * 4)); - return 0; } int rv370_pcie_gart_init(struct radeon_device *rdev) diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index bbc189fd3ddc..c66952d4b00c 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -1958,6 +1958,9 @@ static void r600_gpu_init(struct radeon_device *rdev) if (tmp < rdev->config.r600.max_simds) { rdev->config.r600.max_simds = tmp; } + tmp = rdev->config.r600.max_simds - + r600_count_pipe_bits((cc_gc_shader_pipe_config >> 16) & R6XX_MAX_SIMDS_MASK); + rdev->config.r600.active_simds = tmp; disabled_rb_mask = (RREG32(CC_RB_BACKEND_DISABLE) >> 16) & R6XX_MAX_BACKENDS_MASK; tmp = (tiling_config & PIPE_TILING__MASK) >> PIPE_TILING__SHIFT; @@ -2724,7 +2727,7 @@ void r600_fence_ring_emit(struct radeon_device *rdev, /* EVENT_WRITE_EOP - flush caches, send int */ radeon_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE_EOP, 4)); radeon_ring_write(ring, EVENT_TYPE(CACHE_FLUSH_AND_INV_EVENT_TS) | EVENT_INDEX(5)); - radeon_ring_write(ring, addr & 0xffffffff); + radeon_ring_write(ring, lower_32_bits(addr)); radeon_ring_write(ring, (upper_32_bits(addr) & 0xff) | DATA_SEL(1) | INT_SEL(2)); radeon_ring_write(ring, fence->seq); radeon_ring_write(ring, 0); @@ -2763,7 +2766,7 @@ bool r600_semaphore_ring_emit(struct radeon_device *rdev, sel |= PACKET3_SEM_WAIT_ON_SIGNAL; radeon_ring_write(ring, PACKET3(PACKET3_MEM_SEMAPHORE, 1)); - radeon_ring_write(ring, addr & 0xffffffff); + radeon_ring_write(ring, lower_32_bits(addr)); radeon_ring_write(ring, (upper_32_bits(addr) & 0xff) | sel); return true; @@ -2824,9 +2827,9 @@ int r600_copy_cpdma(struct radeon_device *rdev, if (size_in_bytes == 0) tmp |= PACKET3_CP_DMA_CP_SYNC; radeon_ring_write(ring, PACKET3(PACKET3_CP_DMA, 4)); - radeon_ring_write(ring, src_offset & 0xffffffff); + radeon_ring_write(ring, lower_32_bits(src_offset)); radeon_ring_write(ring, tmp); - radeon_ring_write(ring, dst_offset & 0xffffffff); + radeon_ring_write(ring, lower_32_bits(dst_offset)); radeon_ring_write(ring, upper_32_bits(dst_offset) & 0xff); radeon_ring_write(ring, cur_size_in_bytes); src_offset += cur_size_in_bytes; @@ -3876,7 +3879,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[0])) - radeon_crtc_handle_flip(rdev, 0); + radeon_crtc_handle_vblank(rdev, 0); rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VBLANK_INTERRUPT; DRM_DEBUG("IH: D1 vblank\n"); } @@ -3902,7 +3905,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[1])) - radeon_crtc_handle_flip(rdev, 1); + radeon_crtc_handle_vblank(rdev, 1); rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VBLANK_INTERRUPT; DRM_DEBUG("IH: D2 vblank\n"); } diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index 85a2bb28aed2..26ef8ced6f89 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c @@ -133,7 +133,7 @@ struct radeon_hdmi_acr r600_hdmi_acr(uint32_t clock) /* * update the N and CTS parameters for a given pixel clock rate */ -static void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock) +void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock) { struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; @@ -142,21 +142,33 @@ static void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock) struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; uint32_t offset = dig->afmt->offset; - WREG32(HDMI0_ACR_32_0 + offset, HDMI0_ACR_CTS_32(acr.cts_32khz)); - WREG32(HDMI0_ACR_32_1 + offset, acr.n_32khz); - - WREG32(HDMI0_ACR_44_0 + offset, HDMI0_ACR_CTS_44(acr.cts_44_1khz)); - WREG32(HDMI0_ACR_44_1 + offset, acr.n_44_1khz); - - WREG32(HDMI0_ACR_48_0 + offset, HDMI0_ACR_CTS_48(acr.cts_48khz)); - WREG32(HDMI0_ACR_48_1 + offset, acr.n_48khz); + WREG32_P(HDMI0_ACR_32_0 + offset, + HDMI0_ACR_CTS_32(acr.cts_32khz), + ~HDMI0_ACR_CTS_32_MASK); + WREG32_P(HDMI0_ACR_32_1 + offset, + HDMI0_ACR_N_32(acr.n_32khz), + ~HDMI0_ACR_N_32_MASK); + + WREG32_P(HDMI0_ACR_44_0 + offset, + HDMI0_ACR_CTS_44(acr.cts_44_1khz), + ~HDMI0_ACR_CTS_44_MASK); + WREG32_P(HDMI0_ACR_44_1 + offset, + HDMI0_ACR_N_44(acr.n_44_1khz), + ~HDMI0_ACR_N_44_MASK); + + WREG32_P(HDMI0_ACR_48_0 + offset, + HDMI0_ACR_CTS_48(acr.cts_48khz), + ~HDMI0_ACR_CTS_48_MASK); + WREG32_P(HDMI0_ACR_48_1 + offset, + HDMI0_ACR_N_48(acr.n_48khz), + ~HDMI0_ACR_N_48_MASK); } /* * build a HDMI Video Info Frame */ -static void r600_hdmi_update_avi_infoframe(struct drm_encoder *encoder, - void *buffer, size_t size) +void r600_hdmi_update_avi_infoframe(struct drm_encoder *encoder, void *buffer, + size_t size) { struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; @@ -231,7 +243,7 @@ int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder) /* * write the audio workaround status to the hardware */ -static void r600_hdmi_audio_workaround(struct drm_encoder *encoder) +void r600_hdmi_audio_workaround(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; @@ -250,7 +262,7 @@ static void r600_hdmi_audio_workaround(struct drm_encoder *encoder) value, ~HDMI0_AUDIO_TEST_EN); } -static void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock) +void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock) { struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; @@ -320,121 +332,6 @@ static void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock) } } -static void dce3_2_afmt_write_speaker_allocation(struct drm_encoder *encoder) -{ - struct radeon_device *rdev = encoder->dev->dev_private; - struct drm_connector *connector; - struct radeon_connector *radeon_connector = NULL; - u32 tmp; - u8 *sadb; - int sad_count; - - list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) { - if (connector->encoder == encoder) { - radeon_connector = to_radeon_connector(connector); - break; - } - } - - if (!radeon_connector) { - DRM_ERROR("Couldn't find encoder's connector\n"); - return; - } - - sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb); - if (sad_count < 0) { - DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count); - return; - } - - /* program the speaker allocation */ - tmp = RREG32(AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER); - tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK); - /* set HDMI mode */ - tmp |= HDMI_CONNECTION; - if (sad_count) - tmp |= SPEAKER_ALLOCATION(sadb[0]); - else - tmp |= SPEAKER_ALLOCATION(5); /* stereo */ - WREG32(AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER, tmp); - - kfree(sadb); -} - -static void dce3_2_afmt_write_sad_regs(struct drm_encoder *encoder) -{ - struct radeon_device *rdev = encoder->dev->dev_private; - struct drm_connector *connector; - struct radeon_connector *radeon_connector = NULL; - struct cea_sad *sads; - int i, sad_count; - - static const u16 eld_reg_to_type[][2] = { - { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR0, HDMI_AUDIO_CODING_TYPE_PCM }, - { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR1, HDMI_AUDIO_CODING_TYPE_AC3 }, - { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR2, HDMI_AUDIO_CODING_TYPE_MPEG1 }, - { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR3, HDMI_AUDIO_CODING_TYPE_MP3 }, - { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR4, HDMI_AUDIO_CODING_TYPE_MPEG2 }, - { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR5, HDMI_AUDIO_CODING_TYPE_AAC_LC }, - { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR6, HDMI_AUDIO_CODING_TYPE_DTS }, - { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR7, HDMI_AUDIO_CODING_TYPE_ATRAC }, - { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR9, HDMI_AUDIO_CODING_TYPE_EAC3 }, - { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR10, HDMI_AUDIO_CODING_TYPE_DTS_HD }, - { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR11, HDMI_AUDIO_CODING_TYPE_MLP }, - { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR13, HDMI_AUDIO_CODING_TYPE_WMA_PRO }, - }; - - list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) { - if (connector->encoder == encoder) { - radeon_connector = to_radeon_connector(connector); - break; - } - } - - if (!radeon_connector) { - DRM_ERROR("Couldn't find encoder's connector\n"); - return; - } - - sad_count = drm_edid_to_sad(radeon_connector->edid, &sads); - if (sad_count < 0) { - DRM_ERROR("Couldn't read SADs: %d\n", sad_count); - return; - } - BUG_ON(!sads); - - for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) { - u32 value = 0; - u8 stereo_freqs = 0; - int max_channels = -1; - int j; - - for (j = 0; j < sad_count; j++) { - struct cea_sad *sad = &sads[j]; - - if (sad->format == eld_reg_to_type[i][1]) { - if (sad->channels > max_channels) { - value = MAX_CHANNELS(sad->channels) | - DESCRIPTOR_BYTE_2(sad->byte2) | - SUPPORTED_FREQUENCIES(sad->freq); - max_channels = sad->channels; - } - - if (sad->format == HDMI_AUDIO_CODING_TYPE_PCM) - stereo_freqs |= sad->freq; - else - break; - } - } - - value |= SUPPORTED_FREQUENCIES_STEREO(stereo_freqs); - - WREG32(eld_reg_to_type[i][0], value); - } - - kfree(sads); -} - /* * update the info frames with the data from the current display mode */ @@ -447,6 +344,7 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE]; struct hdmi_avi_infoframe frame; uint32_t offset; + uint32_t acr_ctl; ssize_t err; if (!dig || !dig->afmt) @@ -463,52 +361,44 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod r600_audio_set_dto(encoder, mode->clock); - WREG32(HDMI0_VBI_PACKET_CONTROL + offset, - HDMI0_NULL_SEND); /* send null packets when required */ - - WREG32(HDMI0_AUDIO_CRC_CONTROL + offset, 0x1000); - - if (ASIC_IS_DCE32(rdev)) { - WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset, - HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */ - HDMI0_AUDIO_PACKETS_PER_LINE(3)); /* should be suffient for all audio modes and small enough for all hblanks */ - WREG32(AFMT_AUDIO_PACKET_CONTROL + offset, - AFMT_AUDIO_SAMPLE_SEND | /* send audio packets */ - AFMT_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */ - } else { - WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset, - HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */ - HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */ - HDMI0_AUDIO_PACKETS_PER_LINE(3) | /* should be suffient for all audio modes and small enough for all hblanks */ - HDMI0_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */ - } - - if (ASIC_IS_DCE32(rdev)) { - dce3_2_afmt_write_speaker_allocation(encoder); - dce3_2_afmt_write_sad_regs(encoder); - } - - WREG32(HDMI0_ACR_PACKET_CONTROL + offset, - HDMI0_ACR_SOURCE | /* select SW CTS value - XXX verify that hw CTS works on all families */ - HDMI0_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */ - - WREG32(HDMI0_VBI_PACKET_CONTROL + offset, - HDMI0_NULL_SEND | /* send null packets when required */ - HDMI0_GC_SEND | /* send general control packets */ - HDMI0_GC_CONT); /* send general control packets every frame */ - - /* TODO: HDMI0_AUDIO_INFO_UPDATE */ - WREG32(HDMI0_INFOFRAME_CONTROL0 + offset, - HDMI0_AVI_INFO_SEND | /* enable AVI info frames */ - HDMI0_AVI_INFO_CONT | /* send AVI info frames every frame/field */ - HDMI0_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */ - HDMI0_AUDIO_INFO_CONT); /* send audio info frames every frame/field */ - - WREG32(HDMI0_INFOFRAME_CONTROL1 + offset, - HDMI0_AVI_INFO_LINE(2) | /* anything other than 0 */ - HDMI0_AUDIO_INFO_LINE(2)); /* anything other than 0 */ - - WREG32(HDMI0_GC + offset, 0); /* unset HDMI0_GC_AVMUTE */ + WREG32_P(HDMI0_AUDIO_PACKET_CONTROL + offset, + HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */ + HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */ + HDMI0_AUDIO_PACKETS_PER_LINE(3) | /* should be suffient for all audio modes and small enough for all hblanks */ + HDMI0_60958_CS_UPDATE, /* allow 60958 channel status fields to be updated */ + ~(HDMI0_AUDIO_SAMPLE_SEND | + HDMI0_AUDIO_DELAY_EN_MASK | + HDMI0_AUDIO_PACKETS_PER_LINE_MASK | + HDMI0_60958_CS_UPDATE)); + + /* DCE 3.0 uses register that's normally for CRC_CONTROL */ + acr_ctl = ASIC_IS_DCE3(rdev) ? DCE3_HDMI0_ACR_PACKET_CONTROL : + HDMI0_ACR_PACKET_CONTROL; + WREG32_P(acr_ctl + offset, + HDMI0_ACR_SOURCE | /* select SW CTS value - XXX verify that hw CTS works on all families */ + HDMI0_ACR_AUTO_SEND, /* allow hw to sent ACR packets when required */ + ~(HDMI0_ACR_SOURCE | + HDMI0_ACR_AUTO_SEND)); + + WREG32_OR(HDMI0_VBI_PACKET_CONTROL + offset, + HDMI0_NULL_SEND | /* send null packets when required */ + HDMI0_GC_SEND | /* send general control packets */ + HDMI0_GC_CONT); /* send general control packets every frame */ + + WREG32_OR(HDMI0_INFOFRAME_CONTROL0 + offset, + HDMI0_AVI_INFO_SEND | /* enable AVI info frames */ + HDMI0_AVI_INFO_CONT | /* send AVI info frames every frame/field */ + HDMI0_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */ + HDMI0_AUDIO_INFO_UPDATE); /* required for audio info values to be updated */ + + WREG32_P(HDMI0_INFOFRAME_CONTROL1 + offset, + HDMI0_AVI_INFO_LINE(2) | /* anything other than 0 */ + HDMI0_AUDIO_INFO_LINE(2), /* anything other than 0 */ + ~(HDMI0_AVI_INFO_LINE_MASK | + HDMI0_AUDIO_INFO_LINE_MASK)); + + WREG32_AND(HDMI0_GC + offset, + ~HDMI0_GC_AVMUTE); /* unset HDMI0_GC_AVMUTE */ err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); if (err < 0) { @@ -523,22 +413,45 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod } r600_hdmi_update_avi_infoframe(encoder, buffer, sizeof(buffer)); + + /* fglrx duplicates INFOFRAME_CONTROL0 & INFOFRAME_CONTROL1 ops here */ + + WREG32_AND(HDMI0_GENERIC_PACKET_CONTROL + offset, + ~(HDMI0_GENERIC0_SEND | + HDMI0_GENERIC0_CONT | + HDMI0_GENERIC0_UPDATE | + HDMI0_GENERIC1_SEND | + HDMI0_GENERIC1_CONT | + HDMI0_GENERIC0_LINE_MASK | + HDMI0_GENERIC1_LINE_MASK)); + r600_hdmi_update_ACR(encoder, mode->clock); + WREG32_P(HDMI0_60958_0 + offset, + HDMI0_60958_CS_CHANNEL_NUMBER_L(1), + ~(HDMI0_60958_CS_CHANNEL_NUMBER_L_MASK | + HDMI0_60958_CS_CLOCK_ACCURACY_MASK)); + + WREG32_P(HDMI0_60958_1 + offset, + HDMI0_60958_CS_CHANNEL_NUMBER_R(2), + ~HDMI0_60958_CS_CHANNEL_NUMBER_R_MASK); + /* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */ WREG32(HDMI0_RAMP_CONTROL0 + offset, 0x00FFFFFF); WREG32(HDMI0_RAMP_CONTROL1 + offset, 0x007FFFFF); WREG32(HDMI0_RAMP_CONTROL2 + offset, 0x00000001); WREG32(HDMI0_RAMP_CONTROL3 + offset, 0x00000001); - r600_hdmi_audio_workaround(encoder); - /* enable audio after to setting up hw */ r600_audio_enable(rdev, dig->afmt->pin, true); } -/* - * update settings with current parameters from audio engine +/** + * r600_hdmi_update_audio_settings - Update audio infoframe + * + * @encoder: drm encoder + * + * Gets info about current audio stream and updates audio infoframe. */ void r600_hdmi_update_audio_settings(struct drm_encoder *encoder) { @@ -550,7 +463,7 @@ void r600_hdmi_update_audio_settings(struct drm_encoder *encoder) uint8_t buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AUDIO_INFOFRAME_SIZE]; struct hdmi_audio_infoframe frame; uint32_t offset; - uint32_t iec; + uint32_t value; ssize_t err; if (!dig->afmt || !dig->afmt->enabled) @@ -563,60 +476,6 @@ void r600_hdmi_update_audio_settings(struct drm_encoder *encoder) DRM_DEBUG("0x%02X IEC60958 status bits and 0x%02X category code\n", (int)audio.status_bits, (int)audio.category_code); - iec = 0; - if (audio.status_bits & AUDIO_STATUS_PROFESSIONAL) - iec |= 1 << 0; - if (audio.status_bits & AUDIO_STATUS_NONAUDIO) - iec |= 1 << 1; - if (audio.status_bits & AUDIO_STATUS_COPYRIGHT) - iec |= 1 << 2; - if (audio.status_bits & AUDIO_STATUS_EMPHASIS) - iec |= 1 << 3; - - iec |= HDMI0_60958_CS_CATEGORY_CODE(audio.category_code); - - switch (audio.rate) { - case 32000: - iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0x3); - break; - case 44100: - iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0x0); - break; - case 48000: - iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0x2); - break; - case 88200: - iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0x8); - break; - case 96000: - iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0xa); - break; - case 176400: - iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0xc); - break; - case 192000: - iec |= HDMI0_60958_CS_SAMPLING_FREQUENCY(0xe); - break; - } - - WREG32(HDMI0_60958_0 + offset, iec); - - iec = 0; - switch (audio.bits_per_sample) { - case 16: - iec |= HDMI0_60958_CS_WORD_LENGTH(0x2); - break; - case 20: - iec |= HDMI0_60958_CS_WORD_LENGTH(0x3); - break; - case 24: - iec |= HDMI0_60958_CS_WORD_LENGTH(0xb); - break; - } - if (audio.status_bits & AUDIO_STATUS_V) - iec |= 0x5 << 16; - WREG32_P(HDMI0_60958_1 + offset, iec, ~0x5000f); - err = hdmi_audio_infoframe_init(&frame); if (err < 0) { DRM_ERROR("failed to setup audio infoframe\n"); @@ -631,8 +490,22 @@ void r600_hdmi_update_audio_settings(struct drm_encoder *encoder) return; } + value = RREG32(HDMI0_AUDIO_PACKET_CONTROL + offset); + if (value & HDMI0_AUDIO_TEST_EN) + WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset, + value & ~HDMI0_AUDIO_TEST_EN); + + WREG32_OR(HDMI0_CONTROL + offset, + HDMI0_ERROR_ACK); + + WREG32_AND(HDMI0_INFOFRAME_CONTROL0 + offset, + ~HDMI0_AUDIO_INFO_SOURCE); + r600_hdmi_update_audio_infoframe(encoder, buffer, sizeof(buffer)); - r600_hdmi_audio_workaround(encoder); + + WREG32_OR(HDMI0_INFOFRAME_CONTROL0 + offset, + HDMI0_AUDIO_INFO_CONT | + HDMI0_AUDIO_INFO_UPDATE); } /* diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 37455f65107f..f94e7a9afe75 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -1029,15 +1029,18 @@ #define HDMI0_AUDIO_PACKET_CONTROL 0x7408 # define HDMI0_AUDIO_SAMPLE_SEND (1 << 0) # define HDMI0_AUDIO_DELAY_EN(x) (((x) & 3) << 4) +# define HDMI0_AUDIO_DELAY_EN_MASK (3 << 4) # define HDMI0_AUDIO_SEND_MAX_PACKETS (1 << 8) # define HDMI0_AUDIO_TEST_EN (1 << 12) # define HDMI0_AUDIO_PACKETS_PER_LINE(x) (((x) & 0x1f) << 16) +# define HDMI0_AUDIO_PACKETS_PER_LINE_MASK (0x1f << 16) # define HDMI0_AUDIO_CHANNEL_SWAP (1 << 24) # define HDMI0_60958_CS_UPDATE (1 << 26) # define HDMI0_AZ_FORMAT_WTRIG_MASK (1 << 28) # define HDMI0_AZ_FORMAT_WTRIG_ACK (1 << 29) #define HDMI0_AUDIO_CRC_CONTROL 0x740c # define HDMI0_AUDIO_CRC_EN (1 << 0) +#define DCE3_HDMI0_ACR_PACKET_CONTROL 0x740c #define HDMI0_VBI_PACKET_CONTROL 0x7410 # define HDMI0_NULL_SEND (1 << 0) # define HDMI0_GC_SEND (1 << 4) @@ -1054,7 +1057,9 @@ # define HDMI0_MPEG_INFO_UPDATE (1 << 10) #define HDMI0_INFOFRAME_CONTROL1 0x7418 # define HDMI0_AVI_INFO_LINE(x) (((x) & 0x3f) << 0) +# define HDMI0_AVI_INFO_LINE_MASK (0x3f << 0) # define HDMI0_AUDIO_INFO_LINE(x) (((x) & 0x3f) << 8) +# define HDMI0_AUDIO_INFO_LINE_MASK (0x3f << 8) # define HDMI0_MPEG_INFO_LINE(x) (((x) & 0x3f) << 16) #define HDMI0_GENERIC_PACKET_CONTROL 0x741c # define HDMI0_GENERIC0_SEND (1 << 0) @@ -1063,7 +1068,9 @@ # define HDMI0_GENERIC1_SEND (1 << 4) # define HDMI0_GENERIC1_CONT (1 << 5) # define HDMI0_GENERIC0_LINE(x) (((x) & 0x3f) << 16) +# define HDMI0_GENERIC0_LINE_MASK (0x3f << 16) # define HDMI0_GENERIC1_LINE(x) (((x) & 0x3f) << 24) +# define HDMI0_GENERIC1_LINE_MASK (0x3f << 24) #define HDMI0_GC 0x7428 # define HDMI0_GC_AVMUTE (1 << 0) #define HDMI0_AVI_INFO0 0x7454 @@ -1119,16 +1126,22 @@ #define HDMI0_GENERIC1_6 0x74a8 #define HDMI0_ACR_32_0 0x74ac # define HDMI0_ACR_CTS_32(x) (((x) & 0xfffff) << 12) +# define HDMI0_ACR_CTS_32_MASK (0xfffff << 12) #define HDMI0_ACR_32_1 0x74b0 # define HDMI0_ACR_N_32(x) (((x) & 0xfffff) << 0) +# define HDMI0_ACR_N_32_MASK (0xfffff << 0) #define HDMI0_ACR_44_0 0x74b4 # define HDMI0_ACR_CTS_44(x) (((x) & 0xfffff) << 12) +# define HDMI0_ACR_CTS_44_MASK (0xfffff << 12) #define HDMI0_ACR_44_1 0x74b8 # define HDMI0_ACR_N_44(x) (((x) & 0xfffff) << 0) +# define HDMI0_ACR_N_44_MASK (0xfffff << 0) #define HDMI0_ACR_48_0 0x74bc # define HDMI0_ACR_CTS_48(x) (((x) & 0xfffff) << 12) +# define HDMI0_ACR_CTS_48_MASK (0xfffff << 12) #define HDMI0_ACR_48_1 0x74c0 # define HDMI0_ACR_N_48(x) (((x) & 0xfffff) << 0) +# define HDMI0_ACR_N_48_MASK (0xfffff << 0) #define HDMI0_ACR_STATUS_0 0x74c4 #define HDMI0_ACR_STATUS_1 0x74c8 #define HDMI0_AUDIO_INFO0 0x74cc @@ -1148,14 +1161,17 @@ # define HDMI0_60958_CS_CATEGORY_CODE(x) (((x) & 0xff) << 8) # define HDMI0_60958_CS_SOURCE_NUMBER(x) (((x) & 0xf) << 16) # define HDMI0_60958_CS_CHANNEL_NUMBER_L(x) (((x) & 0xf) << 20) +# define HDMI0_60958_CS_CHANNEL_NUMBER_L_MASK (0xf << 20) # define HDMI0_60958_CS_SAMPLING_FREQUENCY(x) (((x) & 0xf) << 24) # define HDMI0_60958_CS_CLOCK_ACCURACY(x) (((x) & 3) << 28) +# define HDMI0_60958_CS_CLOCK_ACCURACY_MASK (3 << 28) #define HDMI0_60958_1 0x74d8 # define HDMI0_60958_CS_WORD_LENGTH(x) (((x) & 0xf) << 0) # define HDMI0_60958_CS_ORIGINAL_SAMPLING_FREQUENCY(x) (((x) & 0xf) << 4) # define HDMI0_60958_CS_VALID_L(x) (((x) & 1) << 16) # define HDMI0_60958_CS_VALID_R(x) (((x) & 1) << 18) # define HDMI0_60958_CS_CHANNEL_NUMBER_R(x) (((x) & 0xf) << 20) +# define HDMI0_60958_CS_CHANNEL_NUMBER_R_MASK (0xf << 20) #define HDMI0_ACR_PACKET_CONTROL 0x74dc # define HDMI0_ACR_SEND (1 << 0) # define HDMI0_ACR_CONT (1 << 1) @@ -1166,6 +1182,7 @@ # define HDMI0_ACR_48 3 # define HDMI0_ACR_SOURCE (1 << 8) /* 0 - hw; 1 - cts value */ # define HDMI0_ACR_AUTO_SEND (1 << 12) +#define DCE3_HDMI0_AUDIO_CRC_CONTROL 0x74dc #define HDMI0_RAMP_CONTROL0 0x74e0 # define HDMI0_RAMP_MAX_COUNT(x) (((x) & 0xffffff) << 0) #define HDMI0_RAMP_CONTROL1 0x74e4 diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 8149e7cf4303..4b0bbf88d5c0 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -100,6 +100,8 @@ extern int radeon_dpm; extern int radeon_aspm; extern int radeon_runtime_pm; extern int radeon_hard_reset; +extern int radeon_vm_size; +extern int radeon_vm_block_size; /* * Copy from radeon_drv.h so we don't have to include both and have conflicting @@ -676,14 +678,16 @@ void radeon_doorbell_free(struct radeon_device *rdev, u32 doorbell); * IRQS. */ -struct radeon_unpin_work { - struct work_struct work; - struct radeon_device *rdev; - int crtc_id; - struct radeon_fence *fence; +struct radeon_flip_work { + struct work_struct flip_work; + struct work_struct unpin_work; + struct radeon_device *rdev; + int crtc_id; + struct drm_framebuffer *fb; struct drm_pending_vblank_event *event; - struct radeon_bo *old_rbo; - u64 new_crtc_base; + struct radeon_bo *old_rbo; + struct radeon_bo *new_rbo; + struct radeon_fence *fence; }; struct r500_irq_stat_regs { @@ -835,13 +839,8 @@ struct radeon_mec { /* maximum number of VMIDs */ #define RADEON_NUM_VM 16 -/* defines number of bits in page table versus page directory, - * a page is 4KB so we have 12 bits offset, 9 bits in the page - * table and the remaining 19 bits are in the page directory */ -#define RADEON_VM_BLOCK_SIZE 9 - /* number of entries in page table */ -#define RADEON_VM_PTE_COUNT (1 << RADEON_VM_BLOCK_SIZE) +#define RADEON_VM_PTE_COUNT (1 << radeon_vm_block_size) /* PTBs (Page Table Blocks) need to be aligned to 32K */ #define RADEON_VM_PTB_ALIGN_SIZE 32768 @@ -854,6 +853,15 @@ struct radeon_mec { #define R600_PTE_READABLE (1 << 5) #define R600_PTE_WRITEABLE (1 << 6) +/* PTE (Page Table Entry) fragment field for different page sizes */ +#define R600_PTE_FRAG_4KB (0 << 7) +#define R600_PTE_FRAG_64KB (4 << 7) +#define R600_PTE_FRAG_256KB (6 << 7) + +/* flags used for GART page table entries on R600+ */ +#define R600_PTE_GART ( R600_PTE_VALID | R600_PTE_SYSTEM | R600_PTE_SNOOPED \ + | R600_PTE_READABLE | R600_PTE_WRITEABLE) + struct radeon_vm_pt { struct radeon_bo *bo; uint64_t addr; @@ -986,8 +994,8 @@ struct radeon_cs_reloc { struct radeon_bo *robj; struct ttm_validate_buffer tv; uint64_t gpu_offset; - unsigned domain; - unsigned alt_domain; + unsigned prefered_domains; + unsigned allowed_domains; uint32_t tiling_flags; uint32_t handle; }; @@ -1771,7 +1779,8 @@ struct radeon_asic { /* gart */ struct { void (*tlb_flush)(struct radeon_device *rdev); - int (*set_page)(struct radeon_device *rdev, int i, uint64_t addr); + void (*set_page)(struct radeon_device *rdev, unsigned i, + uint64_t addr); } gart; struct { int (*init)(struct radeon_device *rdev); @@ -1883,9 +1892,8 @@ struct radeon_asic { } dpm; /* pageflipping */ struct { - 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); + void (*page_flip)(struct radeon_device *rdev, int crtc, u64 crtc_base); + bool (*page_flip_pending)(struct radeon_device *rdev, int crtc); } pflip; }; @@ -1924,6 +1932,7 @@ struct r600_asic { unsigned tiling_group_size; unsigned tile_config; unsigned backend_map; + unsigned active_simds; }; struct rv770_asic { @@ -1949,6 +1958,7 @@ struct rv770_asic { unsigned tiling_group_size; unsigned tile_config; unsigned backend_map; + unsigned active_simds; }; struct evergreen_asic { @@ -1975,6 +1985,7 @@ struct evergreen_asic { unsigned tiling_group_size; unsigned tile_config; unsigned backend_map; + unsigned active_simds; }; struct cayman_asic { @@ -2013,6 +2024,7 @@ struct cayman_asic { unsigned multi_gpu_tile_size; unsigned tile_config; + unsigned active_simds; }; struct si_asic { @@ -2043,6 +2055,7 @@ struct si_asic { unsigned tile_config; uint32_t tile_mode_array[32]; + uint32_t active_cus; }; struct cik_asic { @@ -2074,6 +2087,7 @@ struct cik_asic { unsigned tile_config; uint32_t tile_mode_array[32]; uint32_t macrotile_mode_array[16]; + uint32_t active_cus; }; union radeon_asic_config { @@ -2745,9 +2759,8 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v); #define radeon_pm_finish(rdev) (rdev)->asic->pm.finish((rdev)) #define radeon_pm_init_profile(rdev) (rdev)->asic->pm.init_profile((rdev)) #define radeon_pm_get_dynpm_state(rdev) (rdev)->asic->pm.get_dynpm_state((rdev)) -#define radeon_pre_page_flip(rdev, crtc) (rdev)->asic->pflip.pre_page_flip((rdev), (crtc)) #define radeon_page_flip(rdev, crtc, base) (rdev)->asic->pflip.page_flip((rdev), (crtc), (base)) -#define radeon_post_page_flip(rdev, crtc) (rdev)->asic->pflip.post_page_flip((rdev), (crtc)) +#define radeon_page_flip_pending(rdev, crtc) (rdev)->asic->pflip.page_flip_pending((rdev), (crtc)) #define radeon_wait_for_vblank(rdev, crtc) (rdev)->asic->display.wait_for_vblank((rdev), (crtc)) #define radeon_mc_wait_for_idle(rdev) (rdev)->asic->mc_wait_for_idle((rdev)) #define radeon_get_xclk(rdev) (rdev)->asic->get_xclk((rdev)) diff --git a/drivers/gpu/drm/radeon/radeon_agp.c b/drivers/gpu/drm/radeon/radeon_agp.c index 42433344cb1b..a9297b2c3524 100644 --- a/drivers/gpu/drm/radeon/radeon_agp.c +++ b/drivers/gpu/drm/radeon/radeon_agp.c @@ -117,9 +117,6 @@ static struct radeon_agpmode_quirk radeon_agpmode_quirk_list[] = { /* ATI Host Bridge / RV280 [M9+] Needs AGPMode 1 (phoronix forum) */ { PCI_VENDOR_ID_ATI, 0xcbb2, PCI_VENDOR_ID_ATI, 0x5c61, PCI_VENDOR_ID_SONY, 0x8175, 1}, - /* HP Host Bridge / R300 [FireGL X1] Needs AGPMode 2 (fdo #7770) */ - { PCI_VENDOR_ID_HP, 0x122e, PCI_VENDOR_ID_ATI, 0x4e47, - PCI_VENDOR_ID_ATI, 0x0152, 2}, { 0, 0, 0, 0, 0, 0, 0 }, }; #endif diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index e5f0177bea1e..34b9aa9e3c06 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -248,9 +248,8 @@ static struct radeon_asic r100_asic = { .set_clock_gating = &radeon_legacy_set_clock_gating, }, .pflip = { - .pre_page_flip = &r100_pre_page_flip, .page_flip = &r100_page_flip, - .post_page_flip = &r100_post_page_flip, + .page_flip_pending = &r100_page_flip_pending, }, }; @@ -315,9 +314,8 @@ static struct radeon_asic r200_asic = { .set_clock_gating = &radeon_legacy_set_clock_gating, }, .pflip = { - .pre_page_flip = &r100_pre_page_flip, .page_flip = &r100_page_flip, - .post_page_flip = &r100_post_page_flip, + .page_flip_pending = &r100_page_flip_pending, }, }; @@ -396,9 +394,8 @@ static struct radeon_asic r300_asic = { .set_clock_gating = &radeon_legacy_set_clock_gating, }, .pflip = { - .pre_page_flip = &r100_pre_page_flip, .page_flip = &r100_page_flip, - .post_page_flip = &r100_post_page_flip, + .page_flip_pending = &r100_page_flip_pending, }, }; @@ -463,9 +460,8 @@ static struct radeon_asic r300_asic_pcie = { .set_clock_gating = &radeon_legacy_set_clock_gating, }, .pflip = { - .pre_page_flip = &r100_pre_page_flip, .page_flip = &r100_page_flip, - .post_page_flip = &r100_post_page_flip, + .page_flip_pending = &r100_page_flip_pending, }, }; @@ -530,9 +526,8 @@ static struct radeon_asic r420_asic = { .set_clock_gating = &radeon_atom_set_clock_gating, }, .pflip = { - .pre_page_flip = &r100_pre_page_flip, .page_flip = &r100_page_flip, - .post_page_flip = &r100_post_page_flip, + .page_flip_pending = &r100_page_flip_pending, }, }; @@ -597,9 +592,8 @@ static struct radeon_asic rs400_asic = { .set_clock_gating = &radeon_legacy_set_clock_gating, }, .pflip = { - .pre_page_flip = &r100_pre_page_flip, .page_flip = &r100_page_flip, - .post_page_flip = &r100_post_page_flip, + .page_flip_pending = &r100_page_flip_pending, }, }; @@ -666,9 +660,8 @@ static struct radeon_asic rs600_asic = { .set_clock_gating = &radeon_atom_set_clock_gating, }, .pflip = { - .pre_page_flip = &rs600_pre_page_flip, .page_flip = &rs600_page_flip, - .post_page_flip = &rs600_post_page_flip, + .page_flip_pending = &rs600_page_flip_pending, }, }; @@ -735,9 +728,8 @@ static struct radeon_asic rs690_asic = { .set_clock_gating = &radeon_atom_set_clock_gating, }, .pflip = { - .pre_page_flip = &rs600_pre_page_flip, .page_flip = &rs600_page_flip, - .post_page_flip = &rs600_post_page_flip, + .page_flip_pending = &rs600_page_flip_pending, }, }; @@ -802,9 +794,8 @@ static struct radeon_asic rv515_asic = { .set_clock_gating = &radeon_atom_set_clock_gating, }, .pflip = { - .pre_page_flip = &rs600_pre_page_flip, .page_flip = &rs600_page_flip, - .post_page_flip = &rs600_post_page_flip, + .page_flip_pending = &rs600_page_flip_pending, }, }; @@ -869,9 +860,8 @@ static struct radeon_asic r520_asic = { .set_clock_gating = &radeon_atom_set_clock_gating, }, .pflip = { - .pre_page_flip = &rs600_pre_page_flip, .page_flip = &rs600_page_flip, - .post_page_flip = &rs600_post_page_flip, + .page_flip_pending = &rs600_page_flip_pending, }, }; @@ -968,9 +958,8 @@ static struct radeon_asic r600_asic = { .get_temperature = &rv6xx_get_temp, }, .pflip = { - .pre_page_flip = &rs600_pre_page_flip, .page_flip = &rs600_page_flip, - .post_page_flip = &rs600_post_page_flip, + .page_flip_pending = &rs600_page_flip_pending, }, }; @@ -1059,9 +1048,8 @@ static struct radeon_asic rv6xx_asic = { .force_performance_level = &rv6xx_dpm_force_performance_level, }, .pflip = { - .pre_page_flip = &rs600_pre_page_flip, .page_flip = &rs600_page_flip, - .post_page_flip = &rs600_post_page_flip, + .page_flip_pending = &rs600_page_flip_pending, }, }; @@ -1150,9 +1138,8 @@ static struct radeon_asic rs780_asic = { .force_performance_level = &rs780_dpm_force_performance_level, }, .pflip = { - .pre_page_flip = &rs600_pre_page_flip, .page_flip = &rs600_page_flip, - .post_page_flip = &rs600_post_page_flip, + .page_flip_pending = &rs600_page_flip_pending, }, }; @@ -1201,7 +1188,7 @@ static struct radeon_asic rv770_asic = { .set_backlight_level = &atombios_set_backlight_level, .get_backlight_level = &atombios_get_backlight_level, .hdmi_enable = &r600_hdmi_enable, - .hdmi_setmode = &r600_hdmi_setmode, + .hdmi_setmode = &dce3_1_hdmi_setmode, }, .copy = { .blit = &r600_copy_cpdma, @@ -1256,9 +1243,8 @@ static struct radeon_asic rv770_asic = { .vblank_too_short = &rv770_dpm_vblank_too_short, }, .pflip = { - .pre_page_flip = &rs600_pre_page_flip, .page_flip = &rv770_page_flip, - .post_page_flip = &rs600_post_page_flip, + .page_flip_pending = &rv770_page_flip_pending, }, }; @@ -1375,9 +1361,8 @@ static struct radeon_asic evergreen_asic = { .vblank_too_short = &cypress_dpm_vblank_too_short, }, .pflip = { - .pre_page_flip = &evergreen_pre_page_flip, .page_flip = &evergreen_page_flip, - .post_page_flip = &evergreen_post_page_flip, + .page_flip_pending = &evergreen_page_flip_pending, }, }; @@ -1467,9 +1452,8 @@ static struct radeon_asic sumo_asic = { .force_performance_level = &sumo_dpm_force_performance_level, }, .pflip = { - .pre_page_flip = &evergreen_pre_page_flip, .page_flip = &evergreen_page_flip, - .post_page_flip = &evergreen_post_page_flip, + .page_flip_pending = &evergreen_page_flip_pending, }, }; @@ -1560,9 +1544,8 @@ static struct radeon_asic btc_asic = { .vblank_too_short = &btc_dpm_vblank_too_short, }, .pflip = { - .pre_page_flip = &evergreen_pre_page_flip, .page_flip = &evergreen_page_flip, - .post_page_flip = &evergreen_post_page_flip, + .page_flip_pending = &evergreen_page_flip_pending, }, }; @@ -1704,9 +1687,8 @@ static struct radeon_asic cayman_asic = { .vblank_too_short = &ni_dpm_vblank_too_short, }, .pflip = { - .pre_page_flip = &evergreen_pre_page_flip, .page_flip = &evergreen_page_flip, - .post_page_flip = &evergreen_post_page_flip, + .page_flip_pending = &evergreen_page_flip_pending, }, }; @@ -1805,9 +1787,8 @@ static struct radeon_asic trinity_asic = { .enable_bapm = &trinity_dpm_enable_bapm, }, .pflip = { - .pre_page_flip = &evergreen_pre_page_flip, .page_flip = &evergreen_page_flip, - .post_page_flip = &evergreen_post_page_flip, + .page_flip_pending = &evergreen_page_flip_pending, }, }; @@ -1936,9 +1917,8 @@ static struct radeon_asic si_asic = { .vblank_too_short = &ni_dpm_vblank_too_short, }, .pflip = { - .pre_page_flip = &evergreen_pre_page_flip, .page_flip = &evergreen_page_flip, - .post_page_flip = &evergreen_post_page_flip, + .page_flip_pending = &evergreen_page_flip_pending, }, }; @@ -2049,8 +2029,8 @@ static struct radeon_asic ci_asic = { .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, .dma = &cik_copy_dma, .dma_ring_index = R600_RING_TYPE_DMA_INDEX, - .copy = &cik_copy_cpdma, - .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX, + .copy = &cik_copy_dma, + .copy_ring_index = R600_RING_TYPE_DMA_INDEX, }, .surface = { .set_reg = r600_set_surface_reg, @@ -2099,9 +2079,8 @@ static struct radeon_asic ci_asic = { .powergate_uvd = &ci_dpm_powergate_uvd, }, .pflip = { - .pre_page_flip = &evergreen_pre_page_flip, .page_flip = &evergreen_page_flip, - .post_page_flip = &evergreen_post_page_flip, + .page_flip_pending = &evergreen_page_flip_pending, }, }; @@ -2204,9 +2183,8 @@ static struct radeon_asic kv_asic = { .enable_bapm = &kv_dpm_enable_bapm, }, .pflip = { - .pre_page_flip = &evergreen_pre_page_flip, .page_flip = &evergreen_page_flip, - .post_page_flip = &evergreen_post_page_flip, + .page_flip_pending = &evergreen_page_flip_pending, }, }; diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 3d55a3a39e82..01e7c0ad8f01 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -67,7 +67,8 @@ bool r100_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *cp); int r100_asic_reset(struct radeon_device *rdev); u32 r100_get_vblank_counter(struct radeon_device *rdev, int crtc); void r100_pci_gart_tlb_flush(struct radeon_device *rdev); -int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr); +void r100_pci_gart_set_page(struct radeon_device *rdev, unsigned i, + uint64_t addr); void r100_ring_start(struct radeon_device *rdev, struct radeon_ring *ring); int r100_irq_set(struct radeon_device *rdev); int r100_irq_process(struct radeon_device *rdev); @@ -135,9 +136,9 @@ extern void r100_pm_prepare(struct radeon_device *rdev); extern void r100_pm_finish(struct radeon_device *rdev); extern void r100_pm_init_profile(struct radeon_device *rdev); 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_page_flip(struct radeon_device *rdev, int crtc, + u64 crtc_base); +extern bool r100_page_flip_pending(struct radeon_device *rdev, int crtc); extern void r100_wait_for_vblank(struct radeon_device *rdev, int crtc); extern int r100_mc_wait_for_idle(struct radeon_device *rdev); @@ -171,7 +172,8 @@ extern void r300_fence_ring_emit(struct radeon_device *rdev, struct radeon_fence *fence); extern int r300_cs_parse(struct radeon_cs_parser *p); extern void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev); -extern int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr); +extern void rv370_pcie_gart_set_page(struct radeon_device *rdev, unsigned i, + uint64_t addr); extern void rv370_set_pcie_lanes(struct radeon_device *rdev, int lanes); extern int rv370_get_pcie_lanes(struct radeon_device *rdev); extern void r300_set_reg_safe(struct radeon_device *rdev); @@ -206,7 +208,8 @@ extern void rs400_fini(struct radeon_device *rdev); extern int rs400_suspend(struct radeon_device *rdev); extern int rs400_resume(struct radeon_device *rdev); void rs400_gart_tlb_flush(struct radeon_device *rdev); -int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr); +void rs400_gart_set_page(struct radeon_device *rdev, unsigned i, + uint64_t addr); uint32_t rs400_mc_rreg(struct radeon_device *rdev, uint32_t reg); void rs400_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); int rs400_gart_init(struct radeon_device *rdev); @@ -229,7 +232,8 @@ int rs600_irq_process(struct radeon_device *rdev); void rs600_irq_disable(struct radeon_device *rdev); u32 rs600_get_vblank_counter(struct radeon_device *rdev, int crtc); void rs600_gart_tlb_flush(struct radeon_device *rdev); -int rs600_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr); +void rs600_gart_set_page(struct radeon_device *rdev, unsigned i, + uint64_t addr); uint32_t rs600_mc_rreg(struct radeon_device *rdev, uint32_t reg); void rs600_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); void rs600_bandwidth_update(struct radeon_device *rdev); @@ -241,9 +245,9 @@ void rs600_hpd_set_polarity(struct radeon_device *rdev, extern void rs600_pm_misc(struct radeon_device *rdev); extern void rs600_pm_prepare(struct radeon_device *rdev); extern void rs600_pm_finish(struct radeon_device *rdev); -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); +extern void rs600_page_flip(struct radeon_device *rdev, int crtc, + u64 crtc_base); +extern bool rs600_page_flip_pending(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); extern int rs600_mc_wait_for_idle(struct radeon_device *rdev); @@ -387,6 +391,11 @@ void r600_rlc_stop(struct radeon_device *rdev); int r600_audio_init(struct radeon_device *rdev); struct r600_audio_pin r600_audio_status(struct radeon_device *rdev); void r600_audio_fini(struct radeon_device *rdev); +void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock); +void r600_hdmi_update_avi_infoframe(struct drm_encoder *encoder, void *buffer, + size_t size); +void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock); +void r600_hdmi_audio_workaround(struct drm_encoder *encoder); int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder); void r600_hdmi_update_audio_settings(struct drm_encoder *encoder); void r600_hdmi_enable(struct drm_encoder *encoder, bool enable); @@ -447,7 +456,8 @@ void rv770_fini(struct radeon_device *rdev); int rv770_suspend(struct radeon_device *rdev); int rv770_resume(struct radeon_device *rdev); void rv770_pm_misc(struct radeon_device *rdev); -u32 rv770_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); +void rv770_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); +bool rv770_page_flip_pending(struct radeon_device *rdev, int crtc); void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc); void r700_cp_stop(struct radeon_device *rdev); void r700_cp_fini(struct radeon_device *rdev); @@ -458,6 +468,8 @@ int rv770_copy_dma(struct radeon_device *rdev, u32 rv770_get_xclk(struct radeon_device *rdev); int rv770_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk); int rv770_get_temp(struct radeon_device *rdev); +/* hdmi */ +void dce3_1_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode); /* rv7xx pm */ int rv770_dpm_init(struct radeon_device *rdev); int rv770_dpm_enable(struct radeon_device *rdev); @@ -513,9 +525,9 @@ extern void sumo_pm_init_profile(struct radeon_device *rdev); extern void btc_pm_init_profile(struct radeon_device *rdev); int sumo_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk); int evergreen_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk); -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 evergreen_page_flip(struct radeon_device *rdev, int crtc, + u64 crtc_base); +extern bool evergreen_page_flip_pending(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_mc_wait_for_idle(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c index 9ab30976287d..6a03624fadaa 100644 --- a/drivers/gpu/drm/radeon/radeon_bios.c +++ b/drivers/gpu/drm/radeon/radeon_bios.c @@ -626,7 +626,7 @@ static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) vhdr->DeviceID != rdev->pdev->device) { DRM_INFO("ACPI VFCT table is not for this card\n"); goto out_unmap; - }; + } if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) { DRM_ERROR("ACPI VFCT image truncated\n"); diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index ea50e0ae7bf7..933c5c39654d 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -48,6 +48,7 @@ void radeon_connector_hotplug(struct drm_connector *connector) radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); /* if the connector is already off, don't turn it back on */ + /* FIXME: This access isn't protected by any locks. */ if (connector->dpms != DRM_MODE_DPMS_ON) return; @@ -100,6 +101,7 @@ int radeon_get_monitor_bpc(struct drm_connector *connector) struct radeon_connector *radeon_connector = to_radeon_connector(connector); struct radeon_connector_atom_dig *dig_connector; int bpc = 8; + int mode_clock, max_tmds_clock; switch (connector->connector_type) { case DRM_MODE_CONNECTOR_DVII: @@ -145,6 +147,61 @@ int radeon_get_monitor_bpc(struct drm_connector *connector) } break; } + + if (drm_detect_hdmi_monitor(radeon_connector->edid)) { + /* hdmi deep color only implemented on DCE4+ */ + if ((bpc > 8) && !ASIC_IS_DCE4(rdev)) { + DRM_DEBUG("%s: HDMI deep color %d bpc unsupported. Using 8 bpc.\n", + connector->name, bpc); + bpc = 8; + } + + /* + * Pre DCE-8 hw can't handle > 12 bpc, and more than 12 bpc doesn't make + * much sense without support for > 12 bpc framebuffers. RGB 4:4:4 at + * 12 bpc is always supported on hdmi deep color sinks, as this is + * required by the HDMI-1.3 spec. Clamp to a safe 12 bpc maximum. + */ + if (bpc > 12) { + DRM_DEBUG("%s: HDMI deep color %d bpc unsupported. Using 12 bpc.\n", + connector->name, bpc); + bpc = 12; + } + + /* Any defined maximum tmds clock limit we must not exceed? */ + if (connector->max_tmds_clock > 0) { + /* mode_clock is clock in kHz for mode to be modeset on this connector */ + mode_clock = radeon_connector->pixelclock_for_modeset; + + /* Maximum allowable input clock in kHz */ + max_tmds_clock = connector->max_tmds_clock * 1000; + + DRM_DEBUG("%s: hdmi mode dotclock %d kHz, max tmds input clock %d kHz.\n", + connector->name, mode_clock, max_tmds_clock); + + /* Check if bpc is within clock limit. Try to degrade gracefully otherwise */ + if ((bpc == 12) && (mode_clock * 3/2 > max_tmds_clock)) { + if ((connector->display_info.edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_30) && + (mode_clock * 5/4 <= max_tmds_clock)) + bpc = 10; + else + bpc = 8; + + DRM_DEBUG("%s: HDMI deep color 12 bpc exceeds max tmds clock. Using %d bpc.\n", + connector->name, bpc); + } + + if ((bpc == 10) && (mode_clock * 5/4 > max_tmds_clock)) { + bpc = 8; + DRM_DEBUG("%s: HDMI deep color 10 bpc exceeds max tmds clock. Using %d bpc.\n", + connector->name, bpc); + } + } + } + + DRM_DEBUG("%s: Display bpc=%d, returned bpc=%d\n", + connector->name, connector->display_info.bpc, bpc); + return bpc; } @@ -260,13 +317,17 @@ radeon_connector_analog_encoder_conflict_solve(struct drm_connector *connector, continue; if (priority == true) { - DRM_DEBUG_KMS("1: conflicting encoders switching off %s\n", drm_get_connector_name(conflict)); - DRM_DEBUG_KMS("in favor of %s\n", drm_get_connector_name(connector)); + DRM_DEBUG_KMS("1: conflicting encoders switching off %s\n", + conflict->name); + DRM_DEBUG_KMS("in favor of %s\n", + connector->name); conflict->status = connector_status_disconnected; radeon_connector_update_scratch_regs(conflict, connector_status_disconnected); } else { - DRM_DEBUG_KMS("2: conflicting encoders switching off %s\n", drm_get_connector_name(connector)); - DRM_DEBUG_KMS("in favor of %s\n", drm_get_connector_name(conflict)); + DRM_DEBUG_KMS("2: conflicting encoders switching off %s\n", + connector->name); + DRM_DEBUG_KMS("in favor of %s\n", + conflict->name); current_status = connector_status_disconnected; } break; @@ -787,7 +848,7 @@ radeon_vga_detect(struct drm_connector *connector, bool force) if (!radeon_connector->edid) { DRM_ERROR("%s: probed a monitor but no|invalid EDID\n", - drm_get_connector_name(connector)); + connector->name); ret = connector_status_connected; } else { radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL); @@ -1010,12 +1071,13 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) if (!radeon_connector->edid) { DRM_ERROR("%s: probed a monitor but no|invalid EDID\n", - drm_get_connector_name(connector)); + connector->name); /* rs690 seems to have a problem with connectors not existing and always * return a block of 0's. If we see this just stop polling on this output */ if ((rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) && radeon_connector->base.null_edid_counter) { ret = connector_status_disconnected; - DRM_ERROR("%s: detected RS690 floating bus bug, stopping ddc detect\n", drm_get_connector_name(connector)); + DRM_ERROR("%s: detected RS690 floating bus bug, stopping ddc detect\n", + connector->name); radeon_connector->ddc_bus = NULL; } else { ret = connector_status_connected; @@ -1387,7 +1449,7 @@ bool radeon_connector_is_dp12_capable(struct drm_connector *connector) struct radeon_device *rdev = dev->dev_private; if (ASIC_IS_DCE5(rdev) && - (rdev->clock.dp_extclk >= 53900) && + (rdev->clock.default_dispclk >= 53900) && radeon_connector_encoder_is_hbr2(connector)) { return true; } diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index 41ecf8a60611..71a143461478 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -140,10 +140,10 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p) if (p->ring == R600_RING_TYPE_UVD_INDEX && (i == 0 || drm_pci_device_is_agp(p->rdev->ddev))) { /* TODO: is this still needed for NI+ ? */ - p->relocs[i].domain = + p->relocs[i].prefered_domains = RADEON_GEM_DOMAIN_VRAM; - p->relocs[i].alt_domain = + p->relocs[i].allowed_domains = RADEON_GEM_DOMAIN_VRAM; /* prioritize this over any other relocation */ @@ -158,10 +158,10 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p) return -EINVAL; } - p->relocs[i].domain = domain; + p->relocs[i].prefered_domains = domain; if (domain == RADEON_GEM_DOMAIN_VRAM) domain |= RADEON_GEM_DOMAIN_GTT; - p->relocs[i].alt_domain = domain; + p->relocs[i].allowed_domains = domain; } p->relocs[i].tv.bo = &p->relocs[i].robj->tbo; diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 2cd144c378d6..03686fab842d 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1052,6 +1052,43 @@ static void radeon_check_arguments(struct radeon_device *rdev) radeon_agpmode = 0; break; } + + if (!radeon_check_pot_argument(radeon_vm_size)) { + dev_warn(rdev->dev, "VM size (%d) must be a power of 2\n", + radeon_vm_size); + radeon_vm_size = 4096; + } + + if (radeon_vm_size < 4) { + dev_warn(rdev->dev, "VM size (%d) to small, min is 4MB\n", + radeon_vm_size); + radeon_vm_size = 4096; + } + + /* + * Max GPUVM size for Cayman, SI and CI are 40 bits. + */ + if (radeon_vm_size > 1024*1024) { + dev_warn(rdev->dev, "VM size (%d) to large, max is 1TB\n", + radeon_vm_size); + radeon_vm_size = 4096; + } + + /* defines number of bits in page table versus page directory, + * a page is 4KB so we have 12 bits offset, minimum 9 bits in the + * page table and the remaining bits are in the page directory */ + if (radeon_vm_block_size < 9) { + dev_warn(rdev->dev, "VM page table size (%d) to small\n", + radeon_vm_block_size); + radeon_vm_block_size = 9; + } + + if (radeon_vm_block_size > 24 || + radeon_vm_size < (1ull << radeon_vm_block_size)) { + dev_warn(rdev->dev, "VM page table size (%d) to large\n", + radeon_vm_block_size); + radeon_vm_block_size = 9; + } } /** @@ -1126,12 +1163,13 @@ static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero static bool radeon_switcheroo_can_switch(struct pci_dev *pdev) { struct drm_device *dev = pci_get_drvdata(pdev); - bool can_switch; - spin_lock(&dev->count_lock); - can_switch = (dev->open_count == 0); - spin_unlock(&dev->count_lock); - return can_switch; + /* + * FIXME: open_count is protected by drm_global_mutex but that would lead to + * locking inversion with the driver load path. And the access here is + * completely racy anyway. So don't bother with locking for now. + */ + return dev->open_count == 0; } static const struct vga_switcheroo_client_ops radeon_switcheroo_ops = { @@ -1196,17 +1234,16 @@ int radeon_device_init(struct radeon_device *rdev, if (r) return r; + radeon_check_arguments(rdev); /* Adjust VM size here. - * Currently set to 4GB ((1 << 20) 4k pages). - * Max GPUVM size for cayman and SI is 40 bits. + * Max GPUVM size for cayman+ is 40 bits. */ - rdev->vm_manager.max_pfn = 1 << 20; + rdev->vm_manager.max_pfn = radeon_vm_size << 8; /* Set asic functions */ r = radeon_asic_init(rdev); if (r) return r; - radeon_check_arguments(rdev); /* all of the newer IGP chips have an internal gart * However some rs4xx report as AGP, so remove that here. diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 356b733caafe..5ed617056b9c 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -249,16 +249,21 @@ static void radeon_crtc_destroy(struct drm_crtc *crtc) struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); drm_crtc_cleanup(crtc); + destroy_workqueue(radeon_crtc->flip_queue); kfree(radeon_crtc); } -/* - * Handle unpin events outside the interrupt handler proper. +/** + * radeon_unpin_work_func - unpin old buffer object + * + * @__work - kernel work item + * + * Unpin the old frame buffer object outside of the interrupt handler */ static void radeon_unpin_work_func(struct work_struct *__work) { - struct radeon_unpin_work *work = - container_of(__work, struct radeon_unpin_work, work); + struct radeon_flip_work *work = + container_of(__work, struct radeon_flip_work, unpin_work); int r; /* unpin of the old buffer */ @@ -276,10 +281,10 @@ static void radeon_unpin_work_func(struct work_struct *__work) kfree(work); } -void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) +void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; - struct radeon_unpin_work *work; + struct radeon_flip_work *work; unsigned long flags; u32 update_pending; int vpos, hpos; @@ -289,24 +294,13 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) return; spin_lock_irqsave(&rdev->ddev->event_lock, flags); - work = radeon_crtc->unpin_work; - if (work == NULL || - (work->fence && !radeon_fence_signaled(work->fence))) { + work = radeon_crtc->flip_work; + if (work == NULL) { spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); return; } - /* New pageflip, or just completion of a previous one? */ - if (!radeon_crtc->deferred_flip_completion) { - /* do the flip (mmio) */ - update_pending = radeon_page_flip(rdev, crtc_id, work->new_crtc_base); - } else { - /* This is just a completion of a flip queued in crtc - * at last invocation. Make sure we go directly to - * completion routine. - */ - update_pending = 0; - radeon_crtc->deferred_flip_completion = 0; - } + + 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? @@ -324,19 +318,38 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) */ update_pending = 0; } - if (update_pending) { - /* crtc didn't flip in this target vblank interval, - * but flip is pending in crtc. It will complete it - * in next vblank interval, so complete the flip at - * next vblank irq. - */ - radeon_crtc->deferred_flip_completion = 1; + spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); + if (!update_pending) + radeon_crtc_handle_flip(rdev, crtc_id); +} + +/** + * radeon_crtc_handle_flip - page flip completed + * + * @rdev: radeon device pointer + * @crtc_id: crtc number this event is for + * + * Called when we are sure that a page flip for this crtc is completed. + */ +void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) +{ + struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; + struct radeon_flip_work *work; + unsigned long flags; + + /* this can happen at init */ + if (radeon_crtc == NULL) + return; + + spin_lock_irqsave(&rdev->ddev->event_lock, flags); + work = radeon_crtc->flip_work; + if (work == NULL) { spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); return; } - /* Pageflip (will be) certainly completed in this vblank. Clean up. */ - radeon_crtc->unpin_work = NULL; + /* Pageflip completed. Clean up. */ + radeon_crtc->flip_work = NULL; /* wakeup userspace */ if (work->event) @@ -344,86 +357,71 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); - drm_vblank_put(rdev->ddev, radeon_crtc->crtc_id); radeon_fence_unref(&work->fence); - radeon_post_page_flip(work->rdev, work->crtc_id); - schedule_work(&work->work); + radeon_irq_kms_pflip_irq_get(rdev, work->crtc_id); + queue_work(radeon_crtc->flip_queue, &work->unpin_work); } -static int radeon_crtc_page_flip(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct drm_pending_vblank_event *event, - uint32_t page_flip_flags) +/** + * radeon_flip_work_func - page flip framebuffer + * + * @work - kernel work item + * + * Wait for the buffer object to become idle and do the actual page flip + */ +static void radeon_flip_work_func(struct work_struct *__work) { - struct drm_device *dev = crtc->dev; - struct radeon_device *rdev = dev->dev_private; - struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); - struct radeon_framebuffer *old_radeon_fb; - struct radeon_framebuffer *new_radeon_fb; - struct drm_gem_object *obj; - struct radeon_bo *rbo; - struct radeon_unpin_work *work; - unsigned long flags; - u32 tiling_flags, pitch_pixels; - u64 base; - int r; + struct radeon_flip_work *work = + container_of(__work, struct radeon_flip_work, flip_work); + struct radeon_device *rdev = work->rdev; + struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[work->crtc_id]; - work = kzalloc(sizeof *work, GFP_KERNEL); - if (work == NULL) - return -ENOMEM; + struct drm_crtc *crtc = &radeon_crtc->base; + struct drm_framebuffer *fb = work->fb; - work->event = event; - work->rdev = rdev; - work->crtc_id = radeon_crtc->crtc_id; - old_radeon_fb = to_radeon_framebuffer(crtc->primary->fb); - new_radeon_fb = to_radeon_framebuffer(fb); - /* schedule unpin of the old buffer */ - obj = old_radeon_fb->obj; - /* take a reference to the old object */ - drm_gem_object_reference(obj); - rbo = gem_to_radeon_bo(obj); - work->old_rbo = rbo; - obj = new_radeon_fb->obj; - rbo = gem_to_radeon_bo(obj); + uint32_t tiling_flags, pitch_pixels; + uint64_t base; - spin_lock(&rbo->tbo.bdev->fence_lock); - if (rbo->tbo.sync_obj) - work->fence = radeon_fence_ref(rbo->tbo.sync_obj); - spin_unlock(&rbo->tbo.bdev->fence_lock); + unsigned long flags; + int r; - INIT_WORK(&work->work, radeon_unpin_work_func); + down_read(&rdev->exclusive_lock); + while (work->fence) { + r = radeon_fence_wait(work->fence, false); + if (r == -EDEADLK) { + up_read(&rdev->exclusive_lock); + r = radeon_gpu_reset(rdev); + down_read(&rdev->exclusive_lock); + } - /* We borrow the event spin lock for protecting unpin_work */ - spin_lock_irqsave(&dev->event_lock, flags); - if (radeon_crtc->unpin_work) { - DRM_DEBUG_DRIVER("flip queue: crtc already busy\n"); - r = -EBUSY; - goto unlock_free; + if (r) { + DRM_ERROR("failed to wait on page flip fence (%d)!\n", + r); + goto cleanup; + } else + radeon_fence_unref(&work->fence); } - radeon_crtc->unpin_work = work; - radeon_crtc->deferred_flip_completion = 0; - spin_unlock_irqrestore(&dev->event_lock, flags); /* pin the new buffer */ DRM_DEBUG_DRIVER("flip-ioctl() cur_fbo = %p, cur_bbo = %p\n", - work->old_rbo, rbo); + work->old_rbo, work->new_rbo); - r = radeon_bo_reserve(rbo, false); + r = radeon_bo_reserve(work->new_rbo, false); if (unlikely(r != 0)) { DRM_ERROR("failed to reserve new rbo buffer before flip\n"); - goto pflip_cleanup; + goto cleanup; } /* Only 27 bit offset for legacy CRTC */ - r = radeon_bo_pin_restricted(rbo, RADEON_GEM_DOMAIN_VRAM, + r = radeon_bo_pin_restricted(work->new_rbo, RADEON_GEM_DOMAIN_VRAM, ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27, &base); if (unlikely(r != 0)) { - radeon_bo_unreserve(rbo); + radeon_bo_unreserve(work->new_rbo); r = -EINVAL; DRM_ERROR("failed to pin new rbo buffer before flip\n"); - goto pflip_cleanup; + goto cleanup; } - radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL); - radeon_bo_unreserve(rbo); + radeon_bo_get_tiling_flags(work->new_rbo, &tiling_flags, NULL); + radeon_bo_unreserve(work->new_rbo); if (!ASIC_IS_AVIVO(rdev)) { /* crtc offset is from display base addr not FB location */ @@ -461,44 +459,91 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc, base &= ~7; } - spin_lock_irqsave(&dev->event_lock, flags); - work->new_crtc_base = base; - spin_unlock_irqrestore(&dev->event_lock, flags); + /* We borrow the event spin lock for protecting flip_work */ + spin_lock_irqsave(&crtc->dev->event_lock, flags); - /* update crtc fb */ - crtc->primary->fb = fb; + /* set the proper interrupt */ + radeon_irq_kms_pflip_irq_get(rdev, radeon_crtc->crtc_id); - r = drm_vblank_get(dev, radeon_crtc->crtc_id); - if (r) { - DRM_ERROR("failed to get vblank before flip\n"); - goto pflip_cleanup1; - } + /* do the flip (mmio) */ + radeon_page_flip(rdev, radeon_crtc->crtc_id, base); - /* set the proper interrupt */ - radeon_pre_page_flip(rdev, radeon_crtc->crtc_id); + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); + up_read(&rdev->exclusive_lock); - return 0; + return; -pflip_cleanup1: - if (unlikely(radeon_bo_reserve(rbo, false) != 0)) { - DRM_ERROR("failed to reserve new rbo in error path\n"); - goto pflip_cleanup; - } - if (unlikely(radeon_bo_unpin(rbo) != 0)) { - DRM_ERROR("failed to unpin new rbo in error path\n"); - } - radeon_bo_unreserve(rbo); - -pflip_cleanup: - spin_lock_irqsave(&dev->event_lock, flags); - radeon_crtc->unpin_work = NULL; -unlock_free: - spin_unlock_irqrestore(&dev->event_lock, flags); - drm_gem_object_unreference_unlocked(old_radeon_fb->obj); +cleanup: + drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base); radeon_fence_unref(&work->fence); kfree(work); + up_read(&rdev->exclusive_lock); +} - return r; +static int radeon_crtc_page_flip(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event, + uint32_t page_flip_flags) +{ + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct radeon_framebuffer *old_radeon_fb; + struct radeon_framebuffer *new_radeon_fb; + struct drm_gem_object *obj; + struct radeon_flip_work *work; + unsigned long flags; + + work = kzalloc(sizeof *work, GFP_KERNEL); + if (work == NULL) + return -ENOMEM; + + INIT_WORK(&work->flip_work, radeon_flip_work_func); + INIT_WORK(&work->unpin_work, radeon_unpin_work_func); + + work->rdev = rdev; + work->crtc_id = radeon_crtc->crtc_id; + work->fb = fb; + work->event = event; + + /* schedule unpin of the old buffer */ + old_radeon_fb = to_radeon_framebuffer(crtc->primary->fb); + obj = old_radeon_fb->obj; + + /* take a reference to the old object */ + drm_gem_object_reference(obj); + work->old_rbo = gem_to_radeon_bo(obj); + + new_radeon_fb = to_radeon_framebuffer(fb); + obj = new_radeon_fb->obj; + work->new_rbo = gem_to_radeon_bo(obj); + + spin_lock(&work->new_rbo->tbo.bdev->fence_lock); + if (work->new_rbo->tbo.sync_obj) + work->fence = radeon_fence_ref(work->new_rbo->tbo.sync_obj); + spin_unlock(&work->new_rbo->tbo.bdev->fence_lock); + + /* We borrow the event spin lock for protecting flip_work */ + spin_lock_irqsave(&crtc->dev->event_lock, flags); + + if (radeon_crtc->flip_work) { + DRM_DEBUG_DRIVER("flip queue: crtc already busy\n"); + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); + drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base); + radeon_fence_unref(&work->fence); + kfree(work); + return -EBUSY; + } + radeon_crtc->flip_work = work; + + /* update crtc fb */ + crtc->primary->fb = fb; + + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); + + queue_work(radeon_crtc->flip_queue, &work->flip_work); + + return 0; } static int @@ -568,6 +613,7 @@ static void radeon_crtc_init(struct drm_device *dev, int index) drm_mode_crtc_set_gamma_size(&radeon_crtc->base, 256); radeon_crtc->crtc_id = index; + radeon_crtc->flip_queue = create_singlethread_workqueue("radeon-crtc"); rdev->mode_info.crtcs[index] = radeon_crtc; if (rdev->family >= CHIP_BONAIRE) { @@ -661,7 +707,7 @@ static void radeon_print_display_setup(struct drm_device *dev) list_for_each_entry(connector, &dev->mode_config.connector_list, head) { radeon_connector = to_radeon_connector(connector); DRM_INFO("Connector %d:\n", i); - DRM_INFO(" %s\n", drm_get_connector_name(connector)); + DRM_INFO(" %s\n", connector->name); if (radeon_connector->hpd.hpd != RADEON_HPD_NONE) DRM_INFO(" %s\n", hpd_names[radeon_connector->hpd.hpd]); if (radeon_connector->ddc_bus) { diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index c00a2f585185..6e3017413386 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -81,9 +81,10 @@ * 2.37.0 - allow GS ring setup on r6xx/r7xx * 2.38.0 - RADEON_GEM_OP (GET_INITIAL_DOMAIN, SET_INITIAL_DOMAIN), * CIK: 1D and linear tiling modes contain valid PIPE_CONFIG + * 2.39.0 - Add INFO query for number of active CUs */ #define KMS_DRIVER_MAJOR 2 -#define KMS_DRIVER_MINOR 38 +#define KMS_DRIVER_MINOR 39 #define KMS_DRIVER_PATCHLEVEL 0 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); int radeon_driver_unload_kms(struct drm_device *dev); @@ -172,6 +173,8 @@ int radeon_dpm = -1; int radeon_aspm = -1; int radeon_runtime_pm = -1; int radeon_hard_reset = 0; +int radeon_vm_size = 4096; +int radeon_vm_block_size = 9; MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers"); module_param_named(no_wb, radeon_no_wb, int, 0444); @@ -239,6 +242,12 @@ module_param_named(runpm, radeon_runtime_pm, int, 0444); MODULE_PARM_DESC(hard_reset, "PCI config reset (1 = force enable, 0 = disable (default))"); module_param_named(hard_reset, radeon_hard_reset, int, 0444); +MODULE_PARM_DESC(vm_size, "VM address space size in megabytes (default 4GB)"); +module_param_named(vm_size, radeon_vm_size, int, 0444); + +MODULE_PARM_DESC(vm_block_size, "VM page table size in bits (default 9)"); +module_param_named(vm_block_size, radeon_vm_block_size, int, 0444); + static struct pci_device_id pciidlist[] = { radeon_PCI_IDS }; @@ -519,7 +528,6 @@ static struct drm_driver kms_driver = { DRIVER_USE_AGP | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM | DRIVER_PRIME | DRIVER_RENDER, - .dev_priv_size = 0, .load = radeon_driver_load_kms, .open = radeon_driver_open_kms, .preclose = radeon_driver_preclose_kms, diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index a77b1c13ea43..913787085dfa 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c @@ -819,15 +819,35 @@ static int radeon_debugfs_fence_info(struct seq_file *m, void *data) return 0; } +/** + * radeon_debugfs_gpu_reset - manually trigger a gpu reset + * + * Manually trigger a gpu reset at the next fence wait. + */ +static int radeon_debugfs_gpu_reset(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + struct radeon_device *rdev = dev->dev_private; + + down_read(&rdev->exclusive_lock); + seq_printf(m, "%d\n", rdev->needs_reset); + rdev->needs_reset = true; + up_read(&rdev->exclusive_lock); + + return 0; +} + static struct drm_info_list radeon_debugfs_fence_list[] = { {"radeon_fence_info", &radeon_debugfs_fence_info, 0, NULL}, + {"radeon_gpu_reset", &radeon_debugfs_gpu_reset, 0, NULL} }; #endif int radeon_debugfs_fence_init(struct radeon_device *rdev) { #if defined(CONFIG_DEBUG_FS) - return radeon_debugfs_add_files(rdev, radeon_debugfs_fence_list, 1); + return radeon_debugfs_add_files(rdev, radeon_debugfs_fence_list, 2); #else return 0; #endif diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c index 7b944142a9fd..add622008407 100644 --- a/drivers/gpu/drm/radeon/radeon_i2c.c +++ b/drivers/gpu/drm/radeon/radeon_i2c.c @@ -94,6 +94,8 @@ static int pre_xfer(struct i2c_adapter *i2c_adap) struct radeon_i2c_bus_rec *rec = &i2c->rec; uint32_t temp; + mutex_lock(&i2c->mutex); + /* RV410 appears to have a bug where the hw i2c in reset * holds the i2c port in a bad state - switch hw i2c away before * doing DDC - do this for all r200s/r300s/r400s for safety sake @@ -170,6 +172,8 @@ static void post_xfer(struct i2c_adapter *i2c_adap) temp = RREG32(rec->mask_data_reg) & ~rec->mask_data_mask; WREG32(rec->mask_data_reg, temp); temp = RREG32(rec->mask_data_reg); + + mutex_unlock(&i2c->mutex); } static int get_clock(void *i2c_priv) @@ -813,6 +817,8 @@ static int radeon_hw_i2c_xfer(struct i2c_adapter *i2c_adap, struct radeon_i2c_bus_rec *rec = &i2c->rec; int ret = 0; + mutex_lock(&i2c->mutex); + switch (rdev->family) { case CHIP_R100: case CHIP_RV100: @@ -879,6 +885,8 @@ static int radeon_hw_i2c_xfer(struct i2c_adapter *i2c_adap, break; } + mutex_unlock(&i2c->mutex); + return ret; } @@ -919,6 +927,7 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev, i2c->adapter.dev.parent = &dev->pdev->dev; i2c->dev = dev; i2c_set_adapdata(&i2c->adapter, i2c); + mutex_init(&i2c->mutex); if (rec->mm_i2c || (rec->hw_capable && radeon_hw_i2c && @@ -979,7 +988,7 @@ void radeon_i2c_destroy(struct radeon_i2c_chan *i2c) return; i2c_del_adapter(&i2c->adapter); if (i2c->has_aux) - drm_dp_aux_unregister_i2c_bus(&i2c->aux); + drm_dp_aux_unregister(&i2c->aux); kfree(i2c); } diff --git a/drivers/gpu/drm/radeon/radeon_ioc32.c b/drivers/gpu/drm/radeon/radeon_ioc32.c index bdb0f93e73bc..0b98ea134579 100644 --- a/drivers/gpu/drm/radeon/radeon_ioc32.c +++ b/drivers/gpu/drm/radeon/radeon_ioc32.c @@ -399,7 +399,7 @@ long radeon_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (nr < DRM_COMMAND_BASE) return drm_compat_ioctl(filp, cmd, arg); - if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(radeon_compat_ioctls)) + if (nr < DRM_COMMAND_BASE + ARRAY_SIZE(radeon_compat_ioctls)) fn = radeon_compat_ioctls[nr - DRM_COMMAND_BASE]; if (fn != NULL) diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c index 089c9ffb0aa9..16807afab362 100644 --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c @@ -287,7 +287,7 @@ int radeon_irq_kms_init(struct radeon_device *rdev) INIT_WORK(&rdev->reset_work, radeon_irq_reset_work_func); rdev->irq.installed = true; - r = drm_irq_install(rdev->ddev); + r = drm_irq_install(rdev->ddev, rdev->ddev->pdev->irq); if (r) { rdev->irq.installed = false; flush_work(&rdev->hotplug_work); diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index eaaedba04675..35d931881b4b 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -513,6 +513,22 @@ static int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file value_size = sizeof(uint64_t); value64 = atomic64_read(&rdev->gtt_usage); break; + case RADEON_INFO_ACTIVE_CU_COUNT: + if (rdev->family >= CHIP_BONAIRE) + *value = rdev->config.cik.active_cus; + else if (rdev->family >= CHIP_TAHITI) + *value = rdev->config.si.active_cus; + else if (rdev->family >= CHIP_CAYMAN) + *value = rdev->config.cayman.active_simds; + else if (rdev->family >= CHIP_CEDAR) + *value = rdev->config.evergreen.active_simds; + else if (rdev->family >= CHIP_RV770) + *value = rdev->config.rv770.active_simds; + else if (rdev->family >= CHIP_R600) + *value = rdev->config.r600.active_simds; + else + *value = 1; + break; default: DRM_DEBUG_KMS("Invalid request %d\n", info->request); return -EINVAL; @@ -859,4 +875,4 @@ const struct drm_ioctl_desc radeon_ioctls_kms[] = { DRM_IOCTL_DEF_DRV(RADEON_GEM_VA, radeon_gem_va_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(RADEON_GEM_OP, radeon_gem_op_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW), }; -int radeon_max_kms_ioctl = DRM_ARRAY_SIZE(radeon_ioctls_kms); +int radeon_max_kms_ioctl = ARRAY_SIZE(radeon_ioctls_kms); diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 6ddf31a2d34e..ad0e4b8cc7e3 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -191,6 +191,7 @@ struct radeon_i2c_chan { struct radeon_i2c_bus_rec rec; struct drm_dp_aux aux; bool has_aux; + struct mutex mutex; }; /* mostly for macs, but really any system without connector tables */ @@ -324,8 +325,8 @@ struct radeon_crtc { struct drm_display_mode native_mode; int pll_id; /* page flipping */ - struct radeon_unpin_work *unpin_work; - int deferred_flip_completion; + struct workqueue_struct *flip_queue; + struct radeon_flip_work *flip_work; /* pll sharing */ struct radeon_atom_ss ss; bool ss_enabled; @@ -505,6 +506,7 @@ struct radeon_connector { struct radeon_i2c_chan *router_bus; enum radeon_connector_audio audio; enum radeon_connector_dither dither; + int pixelclock_for_modeset; }; struct radeon_framebuffer { @@ -906,6 +908,7 @@ bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj) void radeon_fb_output_poll_changed(struct radeon_device *rdev); +void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id); void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id); int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled); diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 4faa4d6f9bb4..6c717b257d6d 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -446,7 +446,7 @@ int radeon_bo_list_validate(struct radeon_device *rdev, list_for_each_entry(lobj, head, tv.head) { bo = lobj->robj; if (!bo->pin_count) { - u32 domain = lobj->domain; + u32 domain = lobj->prefered_domains; u32 current_domain = radeon_mem_type_to_domain(bo->tbo.mem.mem_type); @@ -458,7 +458,7 @@ int radeon_bo_list_validate(struct radeon_device *rdev, * into account. We don't want to disallow buffer moves * completely. */ - if ((lobj->alt_domain & current_domain) != 0 && + if ((lobj->allowed_domains & current_domain) != 0 && (domain & current_domain) == 0 && /* will be moved */ bytes_moved > bytes_moved_threshold) { /* don't move it */ @@ -476,8 +476,9 @@ int radeon_bo_list_validate(struct radeon_device *rdev, initial_bytes_moved; if (unlikely(r)) { - if (r != -ERESTARTSYS && domain != lobj->alt_domain) { - domain = lobj->alt_domain; + if (r != -ERESTARTSYS && + domain != lobj->allowed_domains) { + domain = lobj->allowed_domains; goto retry; } ttm_eu_backoff_reservation(ticket, head); @@ -730,7 +731,7 @@ int radeon_bo_wait(struct radeon_bo *bo, u32 *mem_type, bool no_wait) { int r; - r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0); + r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, NULL); if (unlikely(r != 0)) return r; spin_lock(&bo->tbo.bdev->fence_lock); diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h index 9e7b25a0629d..5a873f31a171 100644 --- a/drivers/gpu/drm/radeon/radeon_object.h +++ b/drivers/gpu/drm/radeon/radeon_object.h @@ -65,7 +65,7 @@ static inline int radeon_bo_reserve(struct radeon_bo *bo, bool no_intr) { int r; - r = ttm_bo_reserve(&bo->tbo, !no_intr, false, false, 0); + r = ttm_bo_reserve(&bo->tbo, !no_intr, false, false, NULL); if (unlikely(r != 0)) { if (r != -ERESTARTSYS) dev_err(bo->rdev->dev, "%p reserve failed\n", bo); diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 2bdae61c0ac0..12c663e86ca1 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -984,6 +984,8 @@ void radeon_dpm_enable_uvd(struct radeon_device *rdev, bool enable) if (enable) { mutex_lock(&rdev->pm.mutex); rdev->pm.dpm.uvd_active = true; + /* disable this for now */ +#if 0 if ((rdev->pm.dpm.sd == 1) && (rdev->pm.dpm.hd == 0)) dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_SD; else if ((rdev->pm.dpm.sd == 2) && (rdev->pm.dpm.hd == 0)) @@ -993,6 +995,7 @@ void radeon_dpm_enable_uvd(struct radeon_device *rdev, bool enable) else if ((rdev->pm.dpm.sd == 0) && (rdev->pm.dpm.hd == 2)) dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_HD2; else +#endif dpm_state = POWER_STATE_TYPE_INTERNAL_UVD; rdev->pm.dpm.state = dpm_state; mutex_unlock(&rdev->pm.mutex); diff --git a/drivers/gpu/drm/radeon/radeon_state.c b/drivers/gpu/drm/radeon/radeon_state.c index 956ab7f14e16..23bb64fd775f 100644 --- a/drivers/gpu/drm/radeon/radeon_state.c +++ b/drivers/gpu/drm/radeon/radeon_state.c @@ -3054,7 +3054,7 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) value = 0; else - value = drm_dev_to_irq(dev); + value = dev->pdev->irq; break; case RADEON_PARAM_GART_BASE: value = dev_priv->gart_vm_start; @@ -3258,4 +3258,4 @@ struct drm_ioctl_desc radeon_ioctls[] = { DRM_IOCTL_DEF_DRV(RADEON_CS, r600_cs_legacy_ioctl, DRM_AUTH) }; -int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls); +int radeon_max_ioctl = ARRAY_SIZE(radeon_ioctls); diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c index 1b65ae2433cd..a4ad270e8261 100644 --- a/drivers/gpu/drm/radeon/radeon_uvd.c +++ b/drivers/gpu/drm/radeon/radeon_uvd.c @@ -812,7 +812,8 @@ void radeon_uvd_note_usage(struct radeon_device *rdev) (rdev->pm.dpm.hd != hd)) { rdev->pm.dpm.sd = sd; rdev->pm.dpm.hd = hd; - streams_changed = true; + /* disable this for now */ + /*streams_changed = true;*/ } } diff --git a/drivers/gpu/drm/radeon/radeon_vce.c b/drivers/gpu/drm/radeon/radeon_vce.c index 3971d968af6c..aa21c31a846c 100644 --- a/drivers/gpu/drm/radeon/radeon_vce.c +++ b/drivers/gpu/drm/radeon/radeon_vce.c @@ -66,6 +66,7 @@ int radeon_vce_init(struct radeon_device *rdev) case CHIP_BONAIRE: case CHIP_KAVERI: case CHIP_KABINI: + case CHIP_HAWAII: case CHIP_MULLINS: fw_name = FIRMWARE_BONAIRE; break; diff --git a/drivers/gpu/drm/radeon/radeon_vm.c b/drivers/gpu/drm/radeon/radeon_vm.c index c11b71d249e3..899d9126cad6 100644 --- a/drivers/gpu/drm/radeon/radeon_vm.c +++ b/drivers/gpu/drm/radeon/radeon_vm.c @@ -59,7 +59,7 @@ */ static unsigned radeon_vm_num_pdes(struct radeon_device *rdev) { - return rdev->vm_manager.max_pfn >> RADEON_VM_BLOCK_SIZE; + return rdev->vm_manager.max_pfn >> radeon_vm_block_size; } /** @@ -140,8 +140,8 @@ struct radeon_cs_reloc *radeon_vm_get_bos(struct radeon_device *rdev, /* add the vm page table to the list */ list[0].gobj = NULL; list[0].robj = vm->page_directory; - list[0].domain = RADEON_GEM_DOMAIN_VRAM; - list[0].alt_domain = RADEON_GEM_DOMAIN_VRAM; + list[0].prefered_domains = RADEON_GEM_DOMAIN_VRAM; + list[0].allowed_domains = RADEON_GEM_DOMAIN_VRAM; list[0].tv.bo = &vm->page_directory->tbo; list[0].tiling_flags = 0; list[0].handle = 0; @@ -153,8 +153,8 @@ struct radeon_cs_reloc *radeon_vm_get_bos(struct radeon_device *rdev, list[idx].gobj = NULL; list[idx].robj = vm->page_tables[i].bo; - list[idx].domain = RADEON_GEM_DOMAIN_VRAM; - list[idx].alt_domain = RADEON_GEM_DOMAIN_VRAM; + list[idx].prefered_domains = RADEON_GEM_DOMAIN_VRAM; + list[idx].allowed_domains = RADEON_GEM_DOMAIN_VRAM; list[idx].tv.bo = &list[idx].robj->tbo; list[idx].tiling_flags = 0; list[idx].handle = 0; @@ -474,8 +474,10 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev, bo_va->valid = false; list_move(&bo_va->vm_list, head); - soffset = (soffset / RADEON_GPU_PAGE_SIZE) >> RADEON_VM_BLOCK_SIZE; - eoffset = (eoffset / RADEON_GPU_PAGE_SIZE) >> RADEON_VM_BLOCK_SIZE; + soffset = (soffset / RADEON_GPU_PAGE_SIZE) >> radeon_vm_block_size; + eoffset = (eoffset / RADEON_GPU_PAGE_SIZE) >> radeon_vm_block_size; + + BUG_ON(eoffset >= radeon_vm_num_pdes(rdev)); if (eoffset > vm->max_pde_used) vm->max_pde_used = eoffset; @@ -583,10 +585,9 @@ static uint32_t radeon_vm_page_flags(uint32_t flags) int radeon_vm_update_page_directory(struct radeon_device *rdev, struct radeon_vm *vm) { - static const uint32_t incr = RADEON_VM_PTE_COUNT * 8; - struct radeon_bo *pd = vm->page_directory; uint64_t pd_addr = radeon_bo_gpu_offset(pd); + uint32_t incr = RADEON_VM_PTE_COUNT * 8; uint64_t last_pde = ~0, last_pt = ~0; unsigned count = 0, pt_idx, ndw; struct radeon_ib ib; @@ -660,6 +661,84 @@ int radeon_vm_update_page_directory(struct radeon_device *rdev, } /** + * radeon_vm_frag_ptes - add fragment information to PTEs + * + * @rdev: radeon_device pointer + * @ib: IB for the update + * @pe_start: first PTE to handle + * @pe_end: last PTE to handle + * @addr: addr those PTEs should point to + * @flags: hw mapping flags + * + * Global and local mutex must be locked! + */ +static void radeon_vm_frag_ptes(struct radeon_device *rdev, + struct radeon_ib *ib, + uint64_t pe_start, uint64_t pe_end, + uint64_t addr, uint32_t flags) +{ + /** + * The MC L1 TLB supports variable sized pages, based on a fragment + * field in the PTE. When this field is set to a non-zero value, page + * granularity is increased from 4KB to (1 << (12 + frag)). The PTE + * flags are considered valid for all PTEs within the fragment range + * and corresponding mappings are assumed to be physically contiguous. + * + * The L1 TLB can store a single PTE for the whole fragment, + * significantly increasing the space available for translation + * caching. This leads to large improvements in throughput when the + * TLB is under pressure. + * + * The L2 TLB distributes small and large fragments into two + * asymmetric partitions. The large fragment cache is significantly + * larger. Thus, we try to use large fragments wherever possible. + * Userspace can support this by aligning virtual base address and + * allocation size to the fragment size. + */ + + /* NI is optimized for 256KB fragments, SI and newer for 64KB */ + uint64_t frag_flags = rdev->family == CHIP_CAYMAN ? + R600_PTE_FRAG_256KB : R600_PTE_FRAG_64KB; + uint64_t frag_align = rdev->family == CHIP_CAYMAN ? 0x200 : 0x80; + + uint64_t frag_start = ALIGN(pe_start, frag_align); + uint64_t frag_end = pe_end & ~(frag_align - 1); + + unsigned count; + + /* system pages are non continuously */ + if ((flags & R600_PTE_SYSTEM) || !(flags & R600_PTE_VALID) || + (frag_start >= frag_end)) { + + count = (pe_end - pe_start) / 8; + radeon_asic_vm_set_page(rdev, ib, pe_start, addr, count, + RADEON_GPU_PAGE_SIZE, flags); + return; + } + + /* handle the 4K area at the beginning */ + if (pe_start != frag_start) { + count = (frag_start - pe_start) / 8; + radeon_asic_vm_set_page(rdev, ib, pe_start, addr, count, + RADEON_GPU_PAGE_SIZE, flags); + addr += RADEON_GPU_PAGE_SIZE * count; + } + + /* handle the area in the middle */ + count = (frag_end - frag_start) / 8; + radeon_asic_vm_set_page(rdev, ib, frag_start, addr, count, + RADEON_GPU_PAGE_SIZE, flags | frag_flags); + + /* handle the 4K area at the end */ + if (frag_end != pe_end) { + addr += RADEON_GPU_PAGE_SIZE * count; + count = (pe_end - frag_end) / 8; + radeon_asic_vm_set_page(rdev, ib, frag_end, addr, count, + RADEON_GPU_PAGE_SIZE, flags); + } +} + +/** * radeon_vm_update_ptes - make sure that page tables are valid * * @rdev: radeon_device pointer @@ -679,8 +758,7 @@ static void radeon_vm_update_ptes(struct radeon_device *rdev, uint64_t start, uint64_t end, uint64_t dst, uint32_t flags) { - static const uint64_t mask = RADEON_VM_PTE_COUNT - 1; - + uint64_t mask = RADEON_VM_PTE_COUNT - 1; uint64_t last_pte = ~0, last_dst = ~0; unsigned count = 0; uint64_t addr; @@ -690,7 +768,7 @@ static void radeon_vm_update_ptes(struct radeon_device *rdev, /* walk over the address space and update the page tables */ for (addr = start; addr < end; ) { - uint64_t pt_idx = addr >> RADEON_VM_BLOCK_SIZE; + uint64_t pt_idx = addr >> radeon_vm_block_size; struct radeon_bo *pt = vm->page_tables[pt_idx].bo; unsigned nptes; uint64_t pte; @@ -708,10 +786,9 @@ static void radeon_vm_update_ptes(struct radeon_device *rdev, if ((last_pte + 8 * count) != pte) { if (count) { - radeon_asic_vm_set_page(rdev, ib, last_pte, - last_dst, count, - RADEON_GPU_PAGE_SIZE, - flags); + radeon_vm_frag_ptes(rdev, ib, last_pte, + last_pte + 8 * count, + last_dst, flags); } count = nptes; @@ -726,9 +803,9 @@ static void radeon_vm_update_ptes(struct radeon_device *rdev, } if (count) { - radeon_asic_vm_set_page(rdev, ib, last_pte, - last_dst, count, - RADEON_GPU_PAGE_SIZE, flags); + radeon_vm_frag_ptes(rdev, ib, last_pte, + last_pte + 8 * count, + last_dst, flags); } } @@ -796,13 +873,13 @@ int radeon_vm_bo_update(struct radeon_device *rdev, /* padding, etc. */ ndw = 64; - if (RADEON_VM_BLOCK_SIZE > 11) + if (radeon_vm_block_size > 11) /* reserve space for one header for every 2k dwords */ ndw += (nptes >> 11) * 4; else /* reserve space for one header for every (1 << BLOCK_SIZE) entries */ - ndw += (nptes >> RADEON_VM_BLOCK_SIZE) * 4; + ndw += (nptes >> radeon_vm_block_size) * 4; /* reserve space for pte addresses */ ndw += nptes * 2; @@ -892,6 +969,8 @@ void radeon_vm_bo_invalidate(struct radeon_device *rdev, */ int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm) { + const unsigned align = min(RADEON_VM_PTB_ALIGN_SIZE, + RADEON_VM_PTE_COUNT * 8); unsigned pd_size, pd_entries, pts_size; int r; @@ -913,7 +992,7 @@ int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm) return -ENOMEM; } - r = radeon_bo_create(rdev, pd_size, RADEON_VM_PTB_ALIGN_SIZE, false, + r = radeon_bo_create(rdev, pd_size, align, false, RADEON_GEM_DOMAIN_VRAM, NULL, &vm->page_directory); if (r) diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c index 130d5cc50d43..a0f96decece3 100644 --- a/drivers/gpu/drm/radeon/rs400.c +++ b/drivers/gpu/drm/radeon/rs400.c @@ -212,21 +212,16 @@ void rs400_gart_fini(struct radeon_device *rdev) #define RS400_PTE_WRITEABLE (1 << 2) #define RS400_PTE_READABLE (1 << 3) -int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) +void rs400_gart_set_page(struct radeon_device *rdev, unsigned i, uint64_t addr) { uint32_t entry; u32 *gtt = rdev->gart.ptr; - if (i < 0 || i > rdev->gart.num_gpu_pages) { - return -EINVAL; - } - entry = (lower_32_bits(addr) & PAGE_MASK) | ((upper_32_bits(addr) & 0xff) << 4) | RS400_PTE_WRITEABLE | RS400_PTE_READABLE; entry = cpu_to_le32(entry); gtt[i] = entry; - return 0; } int rs400_mc_wait_for_idle(struct radeon_device *rdev) diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 72d3616de08e..d1a35cb1c91d 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -109,19 +109,7 @@ void avivo_wait_for_vblank(struct radeon_device *rdev, int crtc) } } -void rs600_pre_page_flip(struct radeon_device *rdev, int crtc) -{ - /* enable the pflip int */ - radeon_irq_kms_pflip_irq_get(rdev, crtc); -} - -void rs600_post_page_flip(struct radeon_device *rdev, int crtc) -{ - /* disable the pflip int */ - radeon_irq_kms_pflip_irq_put(rdev, crtc); -} - -u32 rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) +void rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset); @@ -148,9 +136,15 @@ u32 rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) /* Unlock the lock, so double-buffering can take place inside vblank */ tmp &= ~AVIVO_D1GRPH_UPDATE_LOCK; WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); +} + +bool rs600_page_flip_pending(struct radeon_device *rdev, int crtc_id) +{ + struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; /* Return current update_pending status: */ - return RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING; + return !!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & + AVIVO_D1GRPH_SURFACE_UPDATE_PENDING); } void avivo_program_fmt(struct drm_encoder *encoder) @@ -632,24 +626,16 @@ static void rs600_gart_fini(struct radeon_device *rdev) radeon_gart_table_vram_free(rdev); } -#define R600_PTE_VALID (1 << 0) -#define R600_PTE_SYSTEM (1 << 1) -#define R600_PTE_SNOOPED (1 << 2) -#define R600_PTE_READABLE (1 << 5) -#define R600_PTE_WRITEABLE (1 << 6) - -int rs600_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) +void rs600_gart_set_page(struct radeon_device *rdev, unsigned i, uint64_t addr) { void __iomem *ptr = (void *)rdev->gart.ptr; - if (i < 0 || i > rdev->gart.num_gpu_pages) { - return -EINVAL; - } addr = addr & 0xFFFFFFFFFFFFF000ULL; - addr |= R600_PTE_VALID | R600_PTE_SYSTEM | R600_PTE_SNOOPED; - addr |= R600_PTE_READABLE | R600_PTE_WRITEABLE; + if (addr == rdev->dummy_page.addr) + addr |= R600_PTE_SYSTEM | R600_PTE_SNOOPED; + else + addr |= R600_PTE_GART; writeq(addr, ptr + (i * 8)); - return 0; } int rs600_irq_set(struct radeon_device *rdev) @@ -787,7 +773,7 @@ int rs600_irq_process(struct radeon_device *rdev) wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[0])) - radeon_crtc_handle_flip(rdev, 0); + radeon_crtc_handle_vblank(rdev, 0); } if (G_007EDC_LB_D2_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { if (rdev->irq.crtc_vblank_int[1]) { @@ -796,7 +782,7 @@ int rs600_irq_process(struct radeon_device *rdev) wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[1])) - radeon_crtc_handle_flip(rdev, 1); + radeon_crtc_handle_vblank(rdev, 1); } if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { queue_hotplug = true; diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index fef310773aad..da8703d8d455 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -801,7 +801,7 @@ u32 rv770_get_xclk(struct radeon_device *rdev) return reference_clock; } -u32 rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) +void rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset); @@ -835,9 +835,15 @@ u32 rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) /* Unlock the lock, so double-buffering can take place inside vblank */ tmp &= ~AVIVO_D1GRPH_UPDATE_LOCK; WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); +} + +bool rv770_page_flip_pending(struct radeon_device *rdev, int crtc_id) +{ + struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; /* Return current update_pending status: */ - return RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING; + return !!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & + AVIVO_D1GRPH_SURFACE_UPDATE_PENDING); } /* get temperature in millidegrees */ @@ -1321,6 +1327,9 @@ static void rv770_gpu_init(struct radeon_device *rdev) if (tmp < rdev->config.rv770.max_simds) { rdev->config.rv770.max_simds = tmp; } + tmp = rdev->config.rv770.max_simds - + r600_count_pipe_bits((cc_gc_shader_pipe_config >> 16) & R7XX_MAX_SIMDS_MASK); + rdev->config.rv770.active_simds = tmp; switch (rdev->config.rv770.max_tile_pipes) { case 1: diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 22a63c98ba14..730cee2c34cf 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -71,6 +71,7 @@ MODULE_FIRMWARE("radeon/HAINAN_mc2.bin"); MODULE_FIRMWARE("radeon/HAINAN_rlc.bin"); MODULE_FIRMWARE("radeon/HAINAN_smc.bin"); +static u32 si_get_cu_active_bitmap(struct radeon_device *rdev, u32 se, u32 sh); static void si_pcie_gen3_enable(struct radeon_device *rdev); static void si_program_aspm(struct radeon_device *rdev); extern void sumo_rlc_fini(struct radeon_device *rdev); @@ -2900,7 +2901,7 @@ static void si_gpu_init(struct radeon_device *rdev) u32 sx_debug_1; u32 hdp_host_path_cntl; u32 tmp; - int i, j; + int i, j, k; switch (rdev->family) { case CHIP_TAHITI: @@ -3098,6 +3099,14 @@ static void si_gpu_init(struct radeon_device *rdev) rdev->config.si.max_sh_per_se, rdev->config.si.max_cu_per_sh); + for (i = 0; i < rdev->config.si.max_shader_engines; i++) { + for (j = 0; j < rdev->config.si.max_sh_per_se; j++) { + for (k = 0; k < rdev->config.si.max_cu_per_sh; k++) { + rdev->config.si.active_cus += + hweight32(si_get_cu_active_bitmap(rdev, i, j)); + } + } + } /* set HW defaults for 3D engine */ WREG32(CP_QUEUE_THRESHOLDS, (ROQ_IB1_START(0x16) | @@ -3186,7 +3195,7 @@ void si_fence_ring_emit(struct radeon_device *rdev, /* EVENT_WRITE_EOP - flush caches, send int */ radeon_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE_EOP, 4)); radeon_ring_write(ring, EVENT_TYPE(CACHE_FLUSH_AND_INV_TS_EVENT) | EVENT_INDEX(5)); - radeon_ring_write(ring, addr & 0xffffffff); + radeon_ring_write(ring, lower_32_bits(addr)); radeon_ring_write(ring, (upper_32_bits(addr) & 0xff) | DATA_SEL(1) | INT_SEL(2)); radeon_ring_write(ring, fence->seq); radeon_ring_write(ring, 0); @@ -3219,7 +3228,7 @@ void si_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); radeon_ring_write(ring, (1 << 8)); radeon_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc); - radeon_ring_write(ring, upper_32_bits(ring->next_rptr_gpu_addr) & 0xffffffff); + radeon_ring_write(ring, upper_32_bits(ring->next_rptr_gpu_addr)); radeon_ring_write(ring, next_rptr); } @@ -4044,18 +4053,21 @@ static int si_pcie_gart_enable(struct radeon_device *rdev) WREG32(MC_VM_MX_L1_TLB_CNTL, (0xA << 7) | ENABLE_L1_TLB | + ENABLE_L1_FRAGMENT_PROCESSING | SYSTEM_ACCESS_MODE_NOT_IN_SYS | ENABLE_ADVANCED_DRIVER_MODEL | SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU); /* Setup L2 cache */ WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | + ENABLE_L2_FRAGMENT_PROCESSING | ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE | EFFECTIVE_L2_QUEUE_SIZE(7) | CONTEXT1_IDENTITY_ACCESS_MODE(1)); WREG32(VM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS | INVALIDATE_L2_CACHE); WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY | - L2_CACHE_BIGK_FRAGMENT_SIZE(0)); + BANK_SELECT(4) | + L2_CACHE_BIGK_FRAGMENT_SIZE(4)); /* setup context0 */ WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12); WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12); @@ -4092,6 +4104,7 @@ static int si_pcie_gart_enable(struct radeon_device *rdev) (u32)(rdev->dummy_page.addr >> 12)); WREG32(VM_CONTEXT1_CNTL2, 4); WREG32(VM_CONTEXT1_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(1) | + PAGE_TABLE_BLOCK_SIZE(radeon_vm_block_size - 9) | RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT | RANGE_PROTECTION_FAULT_ENABLE_DEFAULT | DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT | @@ -6151,7 +6164,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[0])) - radeon_crtc_handle_flip(rdev, 0); + radeon_crtc_handle_vblank(rdev, 0); rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT; DRM_DEBUG("IH: D1 vblank\n"); } @@ -6177,7 +6190,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[1])) - radeon_crtc_handle_flip(rdev, 1); + radeon_crtc_handle_vblank(rdev, 1); rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; DRM_DEBUG("IH: D2 vblank\n"); } @@ -6203,7 +6216,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[2])) - radeon_crtc_handle_flip(rdev, 2); + radeon_crtc_handle_vblank(rdev, 2); rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; DRM_DEBUG("IH: D3 vblank\n"); } @@ -6229,7 +6242,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[3])) - radeon_crtc_handle_flip(rdev, 3); + radeon_crtc_handle_vblank(rdev, 3); rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; DRM_DEBUG("IH: D4 vblank\n"); } @@ -6255,7 +6268,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[4])) - radeon_crtc_handle_flip(rdev, 4); + radeon_crtc_handle_vblank(rdev, 4); rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; DRM_DEBUG("IH: D5 vblank\n"); } @@ -6281,7 +6294,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[5])) - radeon_crtc_handle_flip(rdev, 5); + radeon_crtc_handle_vblank(rdev, 5); rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; DRM_DEBUG("IH: D6 vblank\n"); } diff --git a/drivers/gpu/drm/radeon/si_dma.c b/drivers/gpu/drm/radeon/si_dma.c index de0ca070122f..e24c94b6d14d 100644 --- a/drivers/gpu/drm/radeon/si_dma.c +++ b/drivers/gpu/drm/radeon/si_dma.c @@ -79,7 +79,25 @@ void si_dma_vm_set_page(struct radeon_device *rdev, trace_radeon_vm_set_page(pe, addr, count, incr, flags); - if (flags & R600_PTE_SYSTEM) { + if (flags == R600_PTE_GART) { + uint64_t src = rdev->gart.table_addr + (addr >> 12) * 8; + while (count) { + unsigned bytes = count * 8; + if (bytes > 0xFFFF8) + bytes = 0xFFFF8; + + ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_COPY, + 1, 0, 0, bytes); + ib->ptr[ib->length_dw++] = lower_32_bits(pe); + ib->ptr[ib->length_dw++] = lower_32_bits(src); + ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff; + ib->ptr[ib->length_dw++] = upper_32_bits(src) & 0xff; + + pe += bytes; + src += bytes; + count -= bytes / 8; + } + } else if (flags & R600_PTE_SYSTEM) { while (count) { ndw = count * 2; if (ndw > 0xFFFFE) @@ -202,8 +220,8 @@ int si_copy_dma(struct radeon_device *rdev, cur_size_in_bytes = 0xFFFFF; size_in_bytes -= cur_size_in_bytes; radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_COPY, 1, 0, 0, cur_size_in_bytes)); - radeon_ring_write(ring, dst_offset & 0xffffffff); - radeon_ring_write(ring, src_offset & 0xffffffff); + radeon_ring_write(ring, lower_32_bits(dst_offset)); + radeon_ring_write(ring, lower_32_bits(src_offset)); radeon_ring_write(ring, upper_32_bits(dst_offset) & 0xff); radeon_ring_write(ring, upper_32_bits(src_offset) & 0xff); src_offset += cur_size_in_bytes; diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c index 9a3567bedaae..58918868f894 100644 --- a/drivers/gpu/drm/radeon/si_dpm.c +++ b/drivers/gpu/drm/radeon/si_dpm.c @@ -1948,6 +1948,10 @@ static void si_initialize_powertune_defaults(struct radeon_device *rdev) si_pi->cac_weights = cac_weights_cape_verde_pro; si_pi->dte_data = dte_data_cape_verde; break; + case 0x682C: + si_pi->cac_weights = cac_weights_cape_verde_pro; + si_pi->dte_data = dte_data_sun_xt; + break; case 0x6825: case 0x6827: si_pi->cac_weights = cac_weights_heathrow; @@ -1971,10 +1975,9 @@ static void si_initialize_powertune_defaults(struct radeon_device *rdev) si_pi->dte_data = dte_data_venus_xt; break; case 0x6823: - si_pi->cac_weights = cac_weights_chelsea_pro; - si_pi->dte_data = dte_data_venus_pro; - break; case 0x682B: + case 0x6822: + case 0x682A: si_pi->cac_weights = cac_weights_chelsea_pro; si_pi->dte_data = dte_data_venus_pro; break; @@ -1988,6 +1991,7 @@ static void si_initialize_powertune_defaults(struct radeon_device *rdev) case 0x6601: case 0x6621: case 0x6603: + case 0x6605: si_pi->cac_weights = cac_weights_mars_pro; si_pi->lcac_config = lcac_mars_pro; si_pi->cac_override = cac_override_oland; @@ -1998,6 +2002,7 @@ static void si_initialize_powertune_defaults(struct radeon_device *rdev) case 0x6600: case 0x6606: case 0x6620: + case 0x6604: si_pi->cac_weights = cac_weights_mars_xt; si_pi->lcac_config = lcac_mars_pro; si_pi->cac_override = cac_override_oland; @@ -2006,6 +2011,8 @@ static void si_initialize_powertune_defaults(struct radeon_device *rdev) update_dte_from_pl2 = true; break; case 0x6611: + case 0x6613: + case 0x6608: si_pi->cac_weights = cac_weights_oland_pro; si_pi->lcac_config = lcac_mars_pro; si_pi->cac_override = cac_override_oland; diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index 7321283602ce..fd414d34d885 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h @@ -362,6 +362,7 @@ #define READ_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 16) #define WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 18) #define WRITE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 19) +#define PAGE_TABLE_BLOCK_SIZE(x) (((x) & 0xF) << 24) #define VM_CONTEXT1_CNTL 0x1414 #define VM_CONTEXT0_CNTL2 0x1430 #define VM_CONTEXT1_CNTL2 0x1434 diff --git a/drivers/gpu/drm/radeon/uvd_v2_2.c b/drivers/gpu/drm/radeon/uvd_v2_2.c index d1771004cb52..8bfdadd56598 100644 --- a/drivers/gpu/drm/radeon/uvd_v2_2.c +++ b/drivers/gpu/drm/radeon/uvd_v2_2.c @@ -45,7 +45,7 @@ void uvd_v2_2_fence_emit(struct radeon_device *rdev, radeon_ring_write(ring, PACKET0(UVD_CONTEXT_ID, 0)); radeon_ring_write(ring, fence->seq); radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_DATA0, 0)); - radeon_ring_write(ring, addr & 0xffffffff); + radeon_ring_write(ring, lower_32_bits(addr)); radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_DATA1, 0)); radeon_ring_write(ring, upper_32_bits(addr) & 0xff); radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_CMD, 0)); |