diff options
Diffstat (limited to 'drivers/gpu/drm/radeon')
28 files changed, 2296 insertions, 1076 deletions
diff --git a/drivers/gpu/drm/radeon/Kconfig b/drivers/gpu/drm/radeon/Kconfig index 9746fee59f5..ea92bbe3ed3 100644 --- a/drivers/gpu/drm/radeon/Kconfig +++ b/drivers/gpu/drm/radeon/Kconfig @@ -28,11 +28,4 @@ config DRM_RADEON_KMS The kernel will also perform security check on command stream provided by the user, we want to catch and forbid any illegal use of the GPU such as DMA into random system memory or into memory - not owned by the process supplying the command stream. This part - of the code is still incomplete and this why we propose that patch - as a staging driver addition, future security might forbid current - experimental userspace to run. - - This code support the following hardware : R1XX,R2XX,R3XX,R4XX,R5XX - (radeon up to X1950). Works is underway to provide support for R6XX, - R7XX and newer hardware (radeon from HD2XXX to HD4XXX). + not owned by the process supplying the command stream. diff --git a/drivers/gpu/drm/radeon/atom.c b/drivers/gpu/drm/radeon/atom.c index 7bd74568909..ebdb0fdb834 100644 --- a/drivers/gpu/drm/radeon/atom.c +++ b/drivers/gpu/drm/radeon/atom.c @@ -652,12 +652,12 @@ static void atom_op_compare(atom_exec_context *ctx, int *ptr, int arg) static void atom_op_delay(atom_exec_context *ctx, int *ptr, int arg) { - uint8_t count = U8((*ptr)++); + unsigned count = U8((*ptr)++); SDEBUG(" count: %d\n", count); if (arg == ATOM_UNIT_MICROSEC) udelay(count); else - schedule_timeout_uninterruptible(msecs_to_jiffies(count)); + msleep(count); } static void atom_op_div(atom_exec_context *ctx, int *ptr, int arg) diff --git a/drivers/gpu/drm/radeon/atombios.h b/drivers/gpu/drm/radeon/atombios.h index 7fd88497b93..49611e2365d 100644 --- a/drivers/gpu/drm/radeon/atombios.h +++ b/drivers/gpu/drm/radeon/atombios.h @@ -726,6 +726,7 @@ typedef struct _DIG_ENCODER_CONTROL_PARAMETERS_V2 #define ATOM_ENCODER_CMD_DP_VIDEO_ON 0x0d #define ATOM_ENCODER_CMD_QUERY_DP_LINK_TRAINING_STATUS 0x0e #define ATOM_ENCODER_CMD_SETUP 0x0f +#define ATOM_ENCODER_CMD_SETUP_PANEL_MODE 0x10 // ucStatus #define ATOM_ENCODER_STATUS_LINK_TRAINING_COMPLETE 0x10 @@ -765,13 +766,19 @@ typedef struct _DIG_ENCODER_CONTROL_PARAMETERS_V3 USHORT usPixelClock; // in 10KHz; for bios convenient ATOM_DIG_ENCODER_CONFIG_V3 acConfig; UCHAR ucAction; - UCHAR ucEncoderMode; + union { + UCHAR ucEncoderMode; // =0: DP encoder // =1: LVDS encoder // =2: DVI encoder // =3: HDMI encoder // =4: SDVO encoder // =5: DP audio + UCHAR ucPanelMode; // only valid when ucAction == ATOM_ENCODER_CMD_SETUP_PANEL_MODE + // =0: external DP + // =1: internal DP2 + // =0x11: internal DP1 for NutMeg/Travis DP translator + }; UCHAR ucLaneNum; // how many lanes to enable UCHAR ucBitPerColor; // only valid for DP mode when ucAction = ATOM_ENCODER_CMD_SETUP UCHAR ucReserved; @@ -816,13 +823,19 @@ typedef struct _DIG_ENCODER_CONTROL_PARAMETERS_V4 UCHAR ucConfig; }; UCHAR ucAction; - UCHAR ucEncoderMode; + union { + UCHAR ucEncoderMode; // =0: DP encoder // =1: LVDS encoder // =2: DVI encoder // =3: HDMI encoder // =4: SDVO encoder // =5: DP audio + UCHAR ucPanelMode; // only valid when ucAction == ATOM_ENCODER_CMD_SETUP_PANEL_MODE + // =0: external DP + // =1: internal DP2 + // =0x11: internal DP1 for NutMeg/Travis DP translator + }; UCHAR ucLaneNum; // how many lanes to enable UCHAR ucBitPerColor; // only valid for DP mode when ucAction = ATOM_ENCODER_CMD_SETUP UCHAR ucHPD_ID; // HPD ID (1-6). =0 means to skip HDP programming. New comparing to previous version @@ -836,6 +849,11 @@ typedef struct _DIG_ENCODER_CONTROL_PARAMETERS_V4 #define PANEL_12BIT_PER_COLOR 0x04 #define PANEL_16BIT_PER_COLOR 0x05 +//define ucPanelMode +#define DP_PANEL_MODE_EXTERNAL_DP_MODE 0x00 +#define DP_PANEL_MODE_INTERNAL_DP2_MODE 0x01 +#define DP_PANEL_MODE_INTERNAL_DP1_MODE 0x11 + /****************************************************************************/ // Structures used by UNIPHYTransmitterControlTable // LVTMATransmitterControlTable diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 529a3a70473..84a69e7fa11 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -420,7 +420,7 @@ static void atombios_crtc_program_ss(struct drm_crtc *crtc, if (ASIC_IS_DCE5(rdev)) { args.v3.usSpreadSpectrumAmountFrac = cpu_to_le16(0); - args.v3.ucSpreadSpectrumType = ss->type; + args.v3.ucSpreadSpectrumType = ss->type & ATOM_SS_CENTRE_SPREAD_MODE_MASK; switch (pll_id) { case ATOM_PPLL1: args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_P1PLL; @@ -440,10 +440,12 @@ static void atombios_crtc_program_ss(struct drm_crtc *crtc, case ATOM_PPLL_INVALID: return; } - args.v2.ucEnable = enable; + args.v3.ucEnable = enable; + if ((ss->percentage == 0) || (ss->type & ATOM_EXTERNAL_SS_MASK)) + args.v3.ucEnable = ATOM_DISABLE; } else if (ASIC_IS_DCE4(rdev)) { args.v2.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage); - args.v2.ucSpreadSpectrumType = ss->type; + args.v2.ucSpreadSpectrumType = ss->type & ATOM_SS_CENTRE_SPREAD_MODE_MASK; switch (pll_id) { case ATOM_PPLL1: args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_P1PLL; @@ -464,32 +466,36 @@ static void atombios_crtc_program_ss(struct drm_crtc *crtc, return; } args.v2.ucEnable = enable; + if ((ss->percentage == 0) || (ss->type & ATOM_EXTERNAL_SS_MASK)) + args.v2.ucEnable = ATOM_DISABLE; } else if (ASIC_IS_DCE3(rdev)) { args.v1.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage); - args.v1.ucSpreadSpectrumType = ss->type; + args.v1.ucSpreadSpectrumType = ss->type & ATOM_SS_CENTRE_SPREAD_MODE_MASK; args.v1.ucSpreadSpectrumStep = ss->step; args.v1.ucSpreadSpectrumDelay = ss->delay; args.v1.ucSpreadSpectrumRange = ss->range; args.v1.ucPpll = pll_id; args.v1.ucEnable = enable; } else if (ASIC_IS_AVIVO(rdev)) { - if (enable == ATOM_DISABLE) { + if ((enable == ATOM_DISABLE) || (ss->percentage == 0) || + (ss->type & ATOM_EXTERNAL_SS_MASK)) { atombios_disable_ss(crtc); return; } args.lvds_ss_2.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage); - args.lvds_ss_2.ucSpreadSpectrumType = ss->type; + args.lvds_ss_2.ucSpreadSpectrumType = ss->type & ATOM_SS_CENTRE_SPREAD_MODE_MASK; args.lvds_ss_2.ucSpreadSpectrumStep = ss->step; args.lvds_ss_2.ucSpreadSpectrumDelay = ss->delay; args.lvds_ss_2.ucSpreadSpectrumRange = ss->range; args.lvds_ss_2.ucEnable = enable; } else { - if (enable == ATOM_DISABLE) { + if ((enable == ATOM_DISABLE) || (ss->percentage == 0) || + (ss->type & ATOM_EXTERNAL_SS_MASK)) { atombios_disable_ss(crtc); return; } args.lvds_ss.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage); - args.lvds_ss.ucSpreadSpectrumType = ss->type; + args.lvds_ss.ucSpreadSpectrumType = ss->type & ATOM_SS_CENTRE_SPREAD_MODE_MASK; args.lvds_ss.ucSpreadSpectrumStepSize_Delay = (ss->step & 3) << 2; args.lvds_ss.ucSpreadSpectrumStepSize_Delay |= (ss->delay & 7) << 4; args.lvds_ss.ucEnable = enable; @@ -512,6 +518,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, struct radeon_device *rdev = dev->dev_private; struct drm_encoder *encoder = NULL; struct radeon_encoder *radeon_encoder = NULL; + struct drm_connector *connector = NULL; u32 adjusted_clock = mode->clock; int encoder_mode = 0; u32 dp_clock = mode->clock; @@ -546,9 +553,12 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { if (encoder->crtc == crtc) { radeon_encoder = to_radeon_encoder(encoder); + connector = radeon_get_connector_for_encoder(encoder); + if (connector) + bpc = connector->display_info.bpc; encoder_mode = atombios_get_encoder_mode(encoder); - if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) { - struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); + if ((radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) || + radeon_encoder_is_dp_bridge(encoder)) { if (connector) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); struct radeon_connector_atom_dig *dig_connector = @@ -612,7 +622,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, args.v1.usPixelClock = cpu_to_le16(mode->clock / 10); args.v1.ucTransmitterID = radeon_encoder->encoder_id; args.v1.ucEncodeMode = encoder_mode; - if (ss_enabled) + if (ss_enabled && ss->percentage) args.v1.ucConfig |= ADJUST_DISPLAY_CONFIG_SS_ENABLE; @@ -625,10 +635,11 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, args.v3.sInput.ucTransmitterID = radeon_encoder->encoder_id; args.v3.sInput.ucEncodeMode = encoder_mode; args.v3.sInput.ucDispPllConfig = 0; - if (ss_enabled) + if (ss_enabled && ss->percentage) args.v3.sInput.ucDispPllConfig |= DISPPLL_CONFIG_SS_ENABLE; - if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { + if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT) || + radeon_encoder_is_dp_bridge(encoder)) { struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; if (encoder_mode == ATOM_ENCODER_MODE_DP) { args.v3.sInput.ucDispPllConfig |= @@ -754,7 +765,10 @@ static void atombios_crtc_program_pll(struct drm_crtc *crtc, u32 ref_div, u32 fb_div, u32 frac_fb_div, - u32 post_div) + u32 post_div, + int bpc, + bool ss_enabled, + struct radeon_atom_ss *ss) { struct drm_device *dev = crtc->dev; struct radeon_device *rdev = dev->dev_private; @@ -801,6 +815,8 @@ static void atombios_crtc_program_pll(struct drm_crtc *crtc, args.v3.ucPostDiv = post_div; args.v3.ucPpll = pll_id; args.v3.ucMiscInfo = (pll_id << 2); + if (ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK)) + args.v3.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC; args.v3.ucTransmitterId = encoder_id; args.v3.ucEncoderMode = encoder_mode; break; @@ -812,6 +828,17 @@ static void atombios_crtc_program_pll(struct drm_crtc *crtc, args.v5.ulFbDivDecFrac = cpu_to_le32(frac_fb_div * 100000); args.v5.ucPostDiv = post_div; 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; + } args.v5.ucTransmitterID = encoder_id; args.v5.ucEncoderMode = encoder_mode; args.v5.ucPpll = pll_id; @@ -824,6 +851,23 @@ static void atombios_crtc_program_pll(struct drm_crtc *crtc, args.v6.ulFbDivDecFrac = cpu_to_le32(frac_fb_div * 100000); args.v6.ucPostDiv = post_div; 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; + } args.v6.ucTransmitterID = encoder_id; args.v6.ucEncoderMode = encoder_mode; args.v6.ucPpll = pll_id; @@ -855,6 +899,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode int encoder_mode = 0; struct radeon_atom_ss ss; bool ss_enabled = false; + int bpc = 8; list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { if (encoder->crtc == crtc) { @@ -891,41 +936,30 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; int dp_clock; + bpc = connector->display_info.bpc; switch (encoder_mode) { case ATOM_ENCODER_MODE_DP: /* DP/eDP */ dp_clock = dig_connector->dp_clock / 10; - if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) { - if (ASIC_IS_DCE4(rdev)) - ss_enabled = - radeon_atombios_get_asic_ss_info(rdev, &ss, - dig->lcd_ss_id, - dp_clock); - else + if (ASIC_IS_DCE4(rdev)) + ss_enabled = + radeon_atombios_get_asic_ss_info(rdev, &ss, + ASIC_INTERNAL_SS_ON_DP, + dp_clock); + else { + if (dp_clock == 16200) { ss_enabled = radeon_atombios_get_ppll_ss_info(rdev, &ss, - dig->lcd_ss_id); - } else { - if (ASIC_IS_DCE4(rdev)) - ss_enabled = - radeon_atombios_get_asic_ss_info(rdev, &ss, - ASIC_INTERNAL_SS_ON_DP, - dp_clock); - else { - if (dp_clock == 16200) { - ss_enabled = - radeon_atombios_get_ppll_ss_info(rdev, &ss, - ATOM_DP_SS_ID2); - if (!ss_enabled) - ss_enabled = - radeon_atombios_get_ppll_ss_info(rdev, &ss, - ATOM_DP_SS_ID1); - } else + ATOM_DP_SS_ID2); + if (!ss_enabled) ss_enabled = radeon_atombios_get_ppll_ss_info(rdev, &ss, ATOM_DP_SS_ID1); - } + } else + ss_enabled = + radeon_atombios_get_ppll_ss_info(rdev, &ss, + ATOM_DP_SS_ID1); } break; case ATOM_ENCODER_MODE_LVDS: @@ -974,7 +1008,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id, encoder_mode, radeon_encoder->encoder_id, mode->clock, - ref_div, fb_div, frac_fb_div, post_div); + ref_div, fb_div, frac_fb_div, post_div, bpc, ss_enabled, &ss); if (ss_enabled) { /* calculate ss amount and step size */ @@ -982,7 +1016,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode u32 step_size; u32 amount = (((fb_div * 10) + frac_fb_div) * ss.percentage) / 10000; ss.amount = (amount / 10) & ATOM_PPLL_SS_AMOUNT_V2_FBDIV_MASK; - ss.amount |= ((amount - (ss.amount * 10)) << ATOM_PPLL_SS_AMOUNT_V2_NFRAC_SHIFT) & + ss.amount |= ((amount - (amount / 10)) << ATOM_PPLL_SS_AMOUNT_V2_NFRAC_SHIFT) & ATOM_PPLL_SS_AMOUNT_V2_NFRAC_MASK; if (ss.type & ATOM_PPLL_SS_TYPE_V2_CENTRE_SPREAD) step_size = (4 * amount * ref_div * (ss.rate * 2048)) / @@ -1011,7 +1045,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, uint64_t fb_location; uint32_t fb_format, fb_pitch_pixels, tiling_flags; u32 fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_NONE); - u32 tmp; + u32 tmp, viewport_w, viewport_h; int r; /* no fb bound */ @@ -1137,8 +1171,10 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, y &= ~1; WREG32(EVERGREEN_VIEWPORT_START + radeon_crtc->crtc_offset, (x << 16) | y); + viewport_w = crtc->mode.hdisplay; + viewport_h = (crtc->mode.vdisplay + 1) & ~1; WREG32(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset, - (crtc->mode.hdisplay << 16) | crtc->mode.vdisplay); + (viewport_w << 16) | viewport_h); /* pageflip setup */ /* make sure flip is at vb rather than hb */ @@ -1179,7 +1215,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, uint64_t fb_location; uint32_t fb_format, fb_pitch_pixels, tiling_flags; u32 fb_swap = R600_D1GRPH_SWAP_ENDIAN_NONE; - u32 tmp; + u32 tmp, viewport_w, viewport_h; int r; /* no fb bound */ @@ -1304,8 +1340,10 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, y &= ~1; WREG32(AVIVO_D1MODE_VIEWPORT_START + radeon_crtc->crtc_offset, (x << 16) | y); + viewport_w = crtc->mode.hdisplay; + viewport_h = (crtc->mode.vdisplay + 1) & ~1; WREG32(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset, - (crtc->mode.hdisplay << 16) | crtc->mode.vdisplay); + (viewport_w << 16) | viewport_h); /* pageflip setup */ /* make sure flip is at vb rather than hb */ @@ -1395,11 +1433,19 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) uint32_t pll_in_use = 0; if (ASIC_IS_DCE4(rdev)) { - /* if crtc is driving DP and we have an ext clock, use that */ list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) { if (test_encoder->crtc && (test_encoder->crtc == crtc)) { + /* in DP mode, the DP ref clock can come from PPLL, DCPLL, or ext clock, + * depending on the asic: + * DCE4: PPLL or ext clock + * DCE5: DCPLL or ext clock + * + * Setting ATOM_PPLL_INVALID will cause SetPixelClock to skip + * PPLL/DCPLL programming and only program the DP DTO for the + * crtc virtual pixel clock. + */ if (atombios_get_encoder_mode(test_encoder) == ATOM_ENCODER_MODE_DP) { - if (rdev->clock.dp_extclk) + if (ASIC_IS_DCE5(rdev) || rdev->clock.dp_extclk) return ATOM_PPLL_INVALID; } } @@ -1515,6 +1561,8 @@ static void atombios_crtc_commit(struct drm_crtc *crtc) static void atombios_crtc_disable(struct drm_crtc *crtc) { struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct radeon_atom_ss ss; + atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); switch (radeon_crtc->pll_id) { @@ -1522,7 +1570,7 @@ static void atombios_crtc_disable(struct drm_crtc *crtc) case ATOM_PPLL2: /* disable the ppll */ atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id, - 0, 0, ATOM_DISABLE, 0, 0, 0, 0); + 0, 0, ATOM_DISABLE, 0, 0, 0, 0, 0, false, &ss); break; default: break; diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index 695de9a3850..8c0f9e36ff8 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -43,158 +43,242 @@ static char *pre_emph_names[] = { "0dB", "3.5dB", "6dB", "9.5dB" }; -static const int dp_clocks[] = { - 54000, /* 1 lane, 1.62 Ghz */ - 90000, /* 1 lane, 2.70 Ghz */ - 108000, /* 2 lane, 1.62 Ghz */ - 180000, /* 2 lane, 2.70 Ghz */ - 216000, /* 4 lane, 1.62 Ghz */ - 360000, /* 4 lane, 2.70 Ghz */ +/***** radeon AUX functions *****/ +union aux_channel_transaction { + PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION v1; + PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS_V2 v2; }; -static const int num_dp_clocks = sizeof(dp_clocks) / sizeof(int); +static int radeon_process_aux_ch(struct radeon_i2c_chan *chan, + u8 *send, int send_bytes, + u8 *recv, int recv_size, + u8 delay, u8 *ack) +{ + struct drm_device *dev = chan->dev; + struct radeon_device *rdev = dev->dev_private; + union aux_channel_transaction args; + int index = GetIndexIntoMasterTable(COMMAND, ProcessAuxChannelTransaction); + unsigned char *base; + int recv_bytes; + + memset(&args, 0, sizeof(args)); -/* common helper functions */ -static int dp_lanes_for_mode_clock(u8 dpcd[DP_DPCD_SIZE], int mode_clock) + base = (unsigned char *)rdev->mode_info.atom_context->scratch; + + memcpy(base, send, send_bytes); + + args.v1.lpAuxRequest = 0; + args.v1.lpDataOut = 16; + args.v1.ucDataOutLen = 0; + args.v1.ucChannelID = chan->rec.i2c_id; + args.v1.ucDelay = delay / 10; + if (ASIC_IS_DCE4(rdev)) + args.v2.ucHPD_ID = chan->rec.hpd; + + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + + *ack = args.v1.ucReplyStatus; + + /* timeout */ + if (args.v1.ucReplyStatus == 1) { + DRM_DEBUG_KMS("dp_aux_ch timeout\n"); + return -ETIMEDOUT; + } + + /* flags not zero */ + if (args.v1.ucReplyStatus == 2) { + DRM_DEBUG_KMS("dp_aux_ch flags not zero\n"); + return -EBUSY; + } + + /* error */ + if (args.v1.ucReplyStatus == 3) { + DRM_DEBUG_KMS("dp_aux_ch error\n"); + return -EIO; + } + + recv_bytes = args.v1.ucDataOutLen; + if (recv_bytes > recv_size) + recv_bytes = recv_size; + + if (recv && recv_size) + memcpy(recv, base + 16, recv_bytes); + + return recv_bytes; +} + +static int radeon_dp_aux_native_write(struct radeon_connector *radeon_connector, + u16 address, u8 *send, u8 send_bytes, u8 delay) { - int i; - u8 max_link_bw; - u8 max_lane_count; + struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; + int ret; + u8 msg[20]; + int msg_bytes = send_bytes + 4; + u8 ack; - if (!dpcd) - return 0; + if (send_bytes > 16) + return -1; - max_link_bw = dpcd[DP_MAX_LINK_RATE]; - max_lane_count = dpcd[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK; + msg[0] = address; + msg[1] = address >> 8; + msg[2] = AUX_NATIVE_WRITE << 4; + msg[3] = (msg_bytes << 4) | (send_bytes - 1); + memcpy(&msg[4], send, send_bytes); - switch (max_link_bw) { - case DP_LINK_BW_1_62: - default: - for (i = 0; i < num_dp_clocks; i++) { - if (i % 2) - continue; - switch (max_lane_count) { - case 1: - if (i > 1) - return 0; - break; - case 2: - if (i > 3) - return 0; - break; - case 4: - default: - break; - } - if (dp_clocks[i] > mode_clock) { - if (i < 2) - return 1; - else if (i < 4) - return 2; - else - return 4; - } - } - break; - case DP_LINK_BW_2_7: - for (i = 0; i < num_dp_clocks; i++) { - switch (max_lane_count) { - case 1: - if (i > 1) - return 0; - break; - case 2: - if (i > 3) - return 0; - break; - case 4: - default: - break; - } - if (dp_clocks[i] > mode_clock) { - if (i < 2) - return 1; - else if (i < 4) - return 2; - else - return 4; - } - } - break; + while (1) { + ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus, + msg, msg_bytes, NULL, 0, delay, &ack); + if (ret < 0) + return ret; + if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) + break; + else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) + udelay(400); + else + return -EIO; } - return 0; + return send_bytes; } -static int dp_link_clock_for_mode_clock(u8 dpcd[DP_DPCD_SIZE], int mode_clock) +static int radeon_dp_aux_native_read(struct radeon_connector *radeon_connector, + u16 address, u8 *recv, int recv_bytes, u8 delay) { - int i; - u8 max_link_bw; - u8 max_lane_count; + struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; + u8 msg[4]; + int msg_bytes = 4; + u8 ack; + int ret; - if (!dpcd) - return 0; + msg[0] = address; + msg[1] = address >> 8; + msg[2] = AUX_NATIVE_READ << 4; + msg[3] = (msg_bytes << 4) | (recv_bytes - 1); + + while (1) { + ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus, + msg, msg_bytes, recv, recv_bytes, delay, &ack); + if (ret == 0) + return -EPROTO; + if (ret < 0) + return ret; + if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) + return ret; + else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) + udelay(400); + else + return -EIO; + } +} - max_link_bw = dpcd[DP_MAX_LINK_RATE]; - max_lane_count = dpcd[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK; +static void radeon_write_dpcd_reg(struct radeon_connector *radeon_connector, + u16 reg, u8 val) +{ + radeon_dp_aux_native_write(radeon_connector, reg, &val, 1, 0); +} - switch (max_link_bw) { - case DP_LINK_BW_1_62: +static u8 radeon_read_dpcd_reg(struct radeon_connector *radeon_connector, + u16 reg) +{ + u8 val = 0; + + radeon_dp_aux_native_read(radeon_connector, reg, &val, 1, 0); + + return val; +} + +int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, + u8 write_byte, u8 *read_byte) +{ + struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; + struct radeon_i2c_chan *auxch = (struct radeon_i2c_chan *)adapter; + u16 address = algo_data->address; + u8 msg[5]; + u8 reply[2]; + unsigned retry; + int msg_bytes; + int reply_bytes = 1; + int ret; + u8 ack; + + /* Set up the command byte */ + if (mode & MODE_I2C_READ) + msg[2] = AUX_I2C_READ << 4; + else + msg[2] = AUX_I2C_WRITE << 4; + + if (!(mode & MODE_I2C_STOP)) + msg[2] |= AUX_I2C_MOT << 4; + + msg[0] = address; + msg[1] = address >> 8; + + switch (mode) { + case MODE_I2C_WRITE: + msg_bytes = 5; + msg[3] = msg_bytes << 4; + msg[4] = write_byte; + break; + case MODE_I2C_READ: + msg_bytes = 4; + msg[3] = msg_bytes << 4; + break; default: - for (i = 0; i < num_dp_clocks; i++) { - if (i % 2) - continue; - switch (max_lane_count) { - case 1: - if (i > 1) - return 0; - break; - case 2: - if (i > 3) - return 0; - break; - case 4: - default: - break; - } - if (dp_clocks[i] > mode_clock) - return 162000; - } + msg_bytes = 4; + msg[3] = 3 << 4; break; - case DP_LINK_BW_2_7: - for (i = 0; i < num_dp_clocks; i++) { - switch (max_lane_count) { - case 1: - if (i > 1) - return 0; - break; - case 2: - if (i > 3) - return 0; - break; - case 4: - default: - break; - } - if (dp_clocks[i] > mode_clock) - return (i % 2) ? 270000 : 162000; - } } - return 0; -} + for (retry = 0; retry < 4; retry++) { + ret = radeon_process_aux_ch(auxch, + msg, msg_bytes, reply, reply_bytes, 0, &ack); + if (ret < 0) { + DRM_DEBUG_KMS("aux_ch failed %d\n", ret); + return ret; + } -int dp_mode_valid(u8 dpcd[DP_DPCD_SIZE], int mode_clock) -{ - int lanes = dp_lanes_for_mode_clock(dpcd, mode_clock); - int dp_clock = dp_link_clock_for_mode_clock(dpcd, mode_clock); + switch (ack & AUX_NATIVE_REPLY_MASK) { + case AUX_NATIVE_REPLY_ACK: + /* I2C-over-AUX Reply field is only valid + * when paired with AUX ACK. + */ + break; + case AUX_NATIVE_REPLY_NACK: + DRM_DEBUG_KMS("aux_ch native nack\n"); + return -EREMOTEIO; + case AUX_NATIVE_REPLY_DEFER: + DRM_DEBUG_KMS("aux_ch native defer\n"); + udelay(400); + continue; + default: + DRM_ERROR("aux_ch invalid native reply 0x%02x\n", ack); + return -EREMOTEIO; + } - if ((lanes == 0) || (dp_clock == 0)) - return MODE_CLOCK_HIGH; + switch (ack & AUX_I2C_REPLY_MASK) { + case AUX_I2C_REPLY_ACK: + if (mode == MODE_I2C_READ) + *read_byte = reply[0]; + return ret; + case AUX_I2C_REPLY_NACK: + DRM_DEBUG_KMS("aux_i2c nack\n"); + return -EREMOTEIO; + case AUX_I2C_REPLY_DEFER: + DRM_DEBUG_KMS("aux_i2c defer\n"); + udelay(400); + break; + default: + DRM_ERROR("aux_i2c invalid reply 0x%02x\n", ack); + return -EREMOTEIO; + } + } - return MODE_OK; + DRM_ERROR("aux i2c too many retries, giving up\n"); + return -EREMOTEIO; } +/***** general DP utility functions *****/ + static u8 dp_link_status(u8 link_status[DP_LINK_STATUS_SIZE], int r) { return link_status[r - DP_LANE0_1_STATUS]; @@ -242,7 +326,7 @@ static bool dp_channel_eq_ok(u8 link_status[DP_LINK_STATUS_SIZE], return true; } -static u8 dp_get_adjust_request_voltage(uint8_t link_status[DP_LINK_STATUS_SIZE], +static u8 dp_get_adjust_request_voltage(u8 link_status[DP_LINK_STATUS_SIZE], int lane) { @@ -255,7 +339,7 @@ static u8 dp_get_adjust_request_voltage(uint8_t link_status[DP_LINK_STATUS_SIZE] return ((l >> s) & 0x3) << DP_TRAIN_VOLTAGE_SWING_SHIFT; } -static u8 dp_get_adjust_request_pre_emphasis(uint8_t link_status[DP_LINK_STATUS_SIZE], +static u8 dp_get_adjust_request_pre_emphasis(u8 link_status[DP_LINK_STATUS_SIZE], int lane) { int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1); @@ -267,22 +351,8 @@ static u8 dp_get_adjust_request_pre_emphasis(uint8_t link_status[DP_LINK_STATUS_ return ((l >> s) & 0x3) << DP_TRAIN_PRE_EMPHASIS_SHIFT; } -/* XXX fix me -- chip specific */ #define DP_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_1200 -static u8 dp_pre_emphasis_max(u8 voltage_swing) -{ - switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { - case DP_TRAIN_VOLTAGE_SWING_400: - return DP_TRAIN_PRE_EMPHASIS_6; - case DP_TRAIN_VOLTAGE_SWING_600: - return DP_TRAIN_PRE_EMPHASIS_6; - case DP_TRAIN_VOLTAGE_SWING_800: - return DP_TRAIN_PRE_EMPHASIS_3_5; - case DP_TRAIN_VOLTAGE_SWING_1200: - default: - return DP_TRAIN_PRE_EMPHASIS_0; - } -} +#define DP_PRE_EMPHASIS_MAX DP_TRAIN_PRE_EMPHASIS_9_5 static void dp_get_adjust_train(u8 link_status[DP_LINK_STATUS_SIZE], int lane_count, @@ -308,10 +378,10 @@ static void dp_get_adjust_train(u8 link_status[DP_LINK_STATUS_SIZE], } if (v >= DP_VOLTAGE_MAX) - v = DP_VOLTAGE_MAX | DP_TRAIN_MAX_SWING_REACHED; + v |= DP_TRAIN_MAX_SWING_REACHED; - if (p >= dp_pre_emphasis_max(v)) - p = dp_pre_emphasis_max(v) | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; + if (p >= DP_PRE_EMPHASIS_MAX) + p |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; DRM_DEBUG_KMS("using signal parameters: voltage %s pre_emph %s\n", voltage_names[(v & DP_TRAIN_VOLTAGE_SWING_MASK) >> DP_TRAIN_VOLTAGE_SWING_SHIFT], @@ -321,110 +391,109 @@ static void dp_get_adjust_train(u8 link_status[DP_LINK_STATUS_SIZE], train_set[lane] = v | p; } -union aux_channel_transaction { - PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION v1; - PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS_V2 v2; -}; - -/* radeon aux chan functions */ -bool radeon_process_aux_ch(struct radeon_i2c_chan *chan, u8 *req_bytes, - int num_bytes, u8 *read_byte, - u8 read_buf_len, u8 delay) +/* convert bits per color to bits per pixel */ +/* get bpc from the EDID */ +static int convert_bpc_to_bpp(int bpc) { - struct drm_device *dev = chan->dev; - struct radeon_device *rdev = dev->dev_private; - union aux_channel_transaction args; - int index = GetIndexIntoMasterTable(COMMAND, ProcessAuxChannelTransaction); - unsigned char *base; - int retry_count = 0; - - memset(&args, 0, sizeof(args)); - - base = (unsigned char *)rdev->mode_info.atom_context->scratch; - -retry: - memcpy(base, req_bytes, num_bytes); - - args.v1.lpAuxRequest = 0; - args.v1.lpDataOut = 16; - args.v1.ucDataOutLen = 0; - args.v1.ucChannelID = chan->rec.i2c_id; - args.v1.ucDelay = delay / 10; - if (ASIC_IS_DCE4(rdev)) - args.v2.ucHPD_ID = chan->rec.hpd; + if (bpc == 0) + return 24; + else + return bpc * 3; +} - atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); +/* get the max pix clock supported by the link rate and lane num */ +static int dp_get_max_dp_pix_clock(int link_rate, + int lane_num, + int bpp) +{ + return (link_rate * lane_num * 8) / bpp; +} - if (args.v1.ucReplyStatus && !args.v1.ucDataOutLen) { - if (args.v1.ucReplyStatus == 0x20 && retry_count++ < 10) - goto retry; - DRM_DEBUG_KMS("failed to get auxch %02x%02x %02x %02x 0x%02x %02x after %d retries\n", - req_bytes[1], req_bytes[0], req_bytes[2], req_bytes[3], - chan->rec.i2c_id, args.v1.ucReplyStatus, retry_count); - return false; +static int dp_get_max_link_rate(u8 dpcd[DP_DPCD_SIZE]) +{ + switch (dpcd[DP_MAX_LINK_RATE]) { + case DP_LINK_BW_1_62: + default: + return 162000; + case DP_LINK_BW_2_7: + return 270000; + case DP_LINK_BW_5_4: + return 540000; } +} - if (args.v1.ucDataOutLen && read_byte && read_buf_len) { - if (read_buf_len < args.v1.ucDataOutLen) { - DRM_ERROR("Buffer to small for return answer %d %d\n", - read_buf_len, args.v1.ucDataOutLen); - return false; - } - { - int len = min(read_buf_len, args.v1.ucDataOutLen); - memcpy(read_byte, base + 16, len); - } - } - return true; +static u8 dp_get_max_lane_number(u8 dpcd[DP_DPCD_SIZE]) +{ + return dpcd[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK; } -bool radeon_dp_aux_native_write(struct radeon_connector *radeon_connector, uint16_t address, - uint8_t send_bytes, uint8_t *send) +static u8 dp_get_dp_link_rate_coded(int link_rate) { - struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; - u8 msg[20]; - u8 msg_len, dp_msg_len; - bool ret; + switch (link_rate) { + case 162000: + default: + return DP_LINK_BW_1_62; + case 270000: + return DP_LINK_BW_2_7; + case 540000: + return DP_LINK_BW_5_4; + } +} - dp_msg_len = 4; - msg[0] = address; - msg[1] = address >> 8; - msg[2] = AUX_NATIVE_WRITE << 4; - dp_msg_len += send_bytes; - msg[3] = (dp_msg_len << 4) | (send_bytes - 1); +/***** radeon specific DP functions *****/ - if (send_bytes > 16) - return false; +/* 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. + */ +static int radeon_dp_get_dp_lane_number(struct drm_connector *connector, + u8 dpcd[DP_DPCD_SIZE], + int pix_clock) +{ + int bpp = convert_bpc_to_bpp(connector->display_info.bpc); + int max_link_rate = dp_get_max_link_rate(dpcd); + int max_lane_num = dp_get_max_lane_number(dpcd); + int lane_num; + int max_dp_pix_clock; + + for (lane_num = 1; lane_num < max_lane_num; lane_num <<= 1) { + max_dp_pix_clock = dp_get_max_dp_pix_clock(max_link_rate, lane_num, bpp); + if (pix_clock <= max_dp_pix_clock) + break; + } - memcpy(&msg[4], send, send_bytes); - msg_len = 4 + send_bytes; - ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus, msg, msg_len, NULL, 0, 0); - return ret; + return lane_num; } -bool radeon_dp_aux_native_read(struct radeon_connector *radeon_connector, uint16_t address, - uint8_t delay, uint8_t expected_bytes, - uint8_t *read_p) +static int radeon_dp_get_dp_link_clock(struct drm_connector *connector, + u8 dpcd[DP_DPCD_SIZE], + int pix_clock) { - struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; - u8 msg[20]; - u8 msg_len, dp_msg_len; - bool ret = false; - msg_len = 4; - dp_msg_len = 4; - msg[0] = address; - msg[1] = address >> 8; - msg[2] = AUX_NATIVE_READ << 4; - msg[3] = (dp_msg_len) << 4; - msg[3] |= expected_bytes - 1; + int bpp = convert_bpc_to_bpp(connector->display_info.bpc); + int lane_num, max_pix_clock; + + if (radeon_connector_encoder_is_dp_bridge(connector)) + return 270000; + + lane_num = radeon_dp_get_dp_lane_number(connector, dpcd, pix_clock); + max_pix_clock = dp_get_max_dp_pix_clock(162000, lane_num, bpp); + if (pix_clock <= max_pix_clock) + return 162000; + max_pix_clock = dp_get_max_dp_pix_clock(270000, lane_num, bpp); + if (pix_clock <= max_pix_clock) + return 270000; + if (radeon_connector_is_dp12_capable(connector)) { + max_pix_clock = dp_get_max_dp_pix_clock(540000, lane_num, bpp); + if (pix_clock <= max_pix_clock) + return 540000; + } - ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus, msg, msg_len, read_p, expected_bytes, delay); - return ret; + return dp_get_max_link_rate(dpcd); } -/* radeon dp functions */ -static u8 radeon_dp_encoder_service(struct radeon_device *rdev, int action, int dp_clock, - uint8_t ucconfig, uint8_t lane_num) +static u8 radeon_dp_encoder_service(struct radeon_device *rdev, + int action, int dp_clock, + u8 ucconfig, u8 lane_num) { DP_ENCODER_SERVICE_PARAMETERS args; int index = GetIndexIntoMasterTable(COMMAND, DPEncoderService); @@ -454,60 +523,86 @@ bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector) { struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; u8 msg[25]; - int ret; + int ret, i; - ret = radeon_dp_aux_native_read(radeon_connector, DP_DPCD_REV, 0, 8, msg); - if (ret) { + ret = radeon_dp_aux_native_read(radeon_connector, DP_DPCD_REV, msg, 8, 0); + if (ret > 0) { memcpy(dig_connector->dpcd, msg, 8); - { - int i; - DRM_DEBUG_KMS("DPCD: "); - for (i = 0; i < 8; i++) - DRM_DEBUG_KMS("%02x ", msg[i]); - DRM_DEBUG_KMS("\n"); - } + DRM_DEBUG_KMS("DPCD: "); + for (i = 0; i < 8; i++) + DRM_DEBUG_KMS("%02x ", msg[i]); + DRM_DEBUG_KMS("\n"); return true; } dig_connector->dpcd[0] = 0; return false; } +static void radeon_dp_set_panel_mode(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + int panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; + + if (!ASIC_IS_DCE4(rdev)) + return; + + if (radeon_connector_encoder_is_dp_bridge(connector)) + panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE; + + atombios_dig_encoder_setup(encoder, + ATOM_ENCODER_CMD_SETUP_PANEL_MODE, + panel_mode); +} + void radeon_dp_set_link_config(struct drm_connector *connector, struct drm_display_mode *mode) { - struct radeon_connector *radeon_connector; + struct radeon_connector *radeon_connector = to_radeon_connector(connector); struct radeon_connector_atom_dig *dig_connector; - if ((connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort) && - (connector->connector_type != DRM_MODE_CONNECTOR_eDP)) - return; - - radeon_connector = to_radeon_connector(connector); if (!radeon_connector->con_priv) return; dig_connector = radeon_connector->con_priv; - dig_connector->dp_clock = - dp_link_clock_for_mode_clock(dig_connector->dpcd, mode->clock); - dig_connector->dp_lane_count = - dp_lanes_for_mode_clock(dig_connector->dpcd, mode->clock); + if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || + (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) { + dig_connector->dp_clock = + radeon_dp_get_dp_link_clock(connector, dig_connector->dpcd, mode->clock); + dig_connector->dp_lane_count = + radeon_dp_get_dp_lane_number(connector, dig_connector->dpcd, mode->clock); + } } -int radeon_dp_mode_valid_helper(struct radeon_connector *radeon_connector, +int radeon_dp_mode_valid_helper(struct drm_connector *connector, struct drm_display_mode *mode) { - struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + struct radeon_connector_atom_dig *dig_connector; + int dp_clock; + + if (!radeon_connector->con_priv) + return MODE_CLOCK_HIGH; + dig_connector = radeon_connector->con_priv; + + dp_clock = + radeon_dp_get_dp_link_clock(connector, dig_connector->dpcd, mode->clock); + + if ((dp_clock == 540000) && + (!radeon_connector_is_dp12_capable(connector))) + return MODE_CLOCK_HIGH; - return dp_mode_valid(dig_connector->dpcd, mode->clock); + return MODE_OK; } -static bool atom_dp_get_link_status(struct radeon_connector *radeon_connector, - u8 link_status[DP_LINK_STATUS_SIZE]) +static bool radeon_dp_get_link_status(struct radeon_connector *radeon_connector, + u8 link_status[DP_LINK_STATUS_SIZE]) { int ret; - ret = radeon_dp_aux_native_read(radeon_connector, DP_LANE0_1_STATUS, 100, - DP_LINK_STATUS_SIZE, link_status); - if (!ret) { + ret = radeon_dp_aux_native_read(radeon_connector, DP_LANE0_1_STATUS, + link_status, DP_LINK_STATUS_SIZE, 100); + if (ret <= 0) { DRM_ERROR("displayport link status failed\n"); return false; } @@ -518,292 +613,309 @@ static bool atom_dp_get_link_status(struct radeon_connector *radeon_connector, return true; } -bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector) -{ - struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; +struct radeon_dp_link_train_info { + struct radeon_device *rdev; + struct drm_encoder *encoder; + struct drm_connector *connector; + struct radeon_connector *radeon_connector; + int enc_id; + int dp_clock; + int dp_lane_count; + int rd_interval; + bool tp3_supported; + u8 dpcd[8]; + u8 train_set[4]; u8 link_status[DP_LINK_STATUS_SIZE]; + u8 tries; +}; - if (!atom_dp_get_link_status(radeon_connector, link_status)) - return false; - if (dp_channel_eq_ok(link_status, dig_connector->dp_lane_count)) - return false; - return true; +static void radeon_dp_update_vs_emph(struct radeon_dp_link_train_info *dp_info) +{ + /* set the initial vs/emph on the source */ + atombios_dig_transmitter_setup(dp_info->encoder, + ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH, + 0, dp_info->train_set[0]); /* sets all lanes at once */ + + /* set the vs/emph on the sink */ + radeon_dp_aux_native_write(dp_info->radeon_connector, DP_TRAINING_LANE0_SET, + dp_info->train_set, dp_info->dp_lane_count, 0); } -static void dp_set_power(struct radeon_connector *radeon_connector, u8 power_state) +static void radeon_dp_set_tp(struct radeon_dp_link_train_info *dp_info, int tp) { - struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; + int rtp = 0; - if (dig_connector->dpcd[0] >= 0x11) { - radeon_dp_aux_native_write(radeon_connector, DP_SET_POWER, 1, - &power_state); + /* set training pattern on the source */ + if (ASIC_IS_DCE4(dp_info->rdev)) { + switch (tp) { + case DP_TRAINING_PATTERN_1: + rtp = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1; + break; + case DP_TRAINING_PATTERN_2: + rtp = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN2; + break; + case DP_TRAINING_PATTERN_3: + rtp = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN3; + break; + } + atombios_dig_encoder_setup(dp_info->encoder, rtp, 0); + } else { + switch (tp) { + case DP_TRAINING_PATTERN_1: + rtp = 0; + break; + case DP_TRAINING_PATTERN_2: + rtp = 1; + break; + } + radeon_dp_encoder_service(dp_info->rdev, ATOM_DP_ACTION_TRAINING_PATTERN_SEL, + dp_info->dp_clock, dp_info->enc_id, rtp); } -} -static void dp_set_downspread(struct radeon_connector *radeon_connector, u8 downspread) -{ - radeon_dp_aux_native_write(radeon_connector, DP_DOWNSPREAD_CTRL, 1, - &downspread); + /* enable training pattern on the sink */ + radeon_write_dpcd_reg(dp_info->radeon_connector, DP_TRAINING_PATTERN_SET, tp); } -static void dp_set_link_bw_lanes(struct radeon_connector *radeon_connector, - u8 link_configuration[DP_LINK_CONFIGURATION_SIZE]) +static int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info) { - radeon_dp_aux_native_write(radeon_connector, DP_LINK_BW_SET, 2, - link_configuration); -} + u8 tmp; -static void dp_update_dpvs_emph(struct radeon_connector *radeon_connector, - struct drm_encoder *encoder, - u8 train_set[4]) -{ - struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; - int i; + /* power up the sink */ + if (dp_info->dpcd[0] >= 0x11) + radeon_write_dpcd_reg(dp_info->radeon_connector, + DP_SET_POWER, DP_SET_POWER_D0); + + /* possibly enable downspread on the sink */ + if (dp_info->dpcd[3] & 0x1) + radeon_write_dpcd_reg(dp_info->radeon_connector, + DP_DOWNSPREAD_CTRL, DP_SPREAD_AMP_0_5); + else + radeon_write_dpcd_reg(dp_info->radeon_connector, + DP_DOWNSPREAD_CTRL, 0); - for (i = 0; i < dig_connector->dp_lane_count; i++) - atombios_dig_transmitter_setup(encoder, - ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH, - i, train_set[i]); + radeon_dp_set_panel_mode(dp_info->encoder, dp_info->connector); - radeon_dp_aux_native_write(radeon_connector, DP_TRAINING_LANE0_SET, - dig_connector->dp_lane_count, train_set); -} + /* set the lane count on the sink */ + tmp = dp_info->dp_lane_count; + if (dp_info->dpcd[0] >= 0x11) + tmp |= DP_LANE_COUNT_ENHANCED_FRAME_EN; + radeon_write_dpcd_reg(dp_info->radeon_connector, DP_LANE_COUNT_SET, tmp); -static void dp_set_training(struct radeon_connector *radeon_connector, - u8 training) -{ - radeon_dp_aux_native_write(radeon_connector, DP_TRAINING_PATTERN_SET, - 1, &training); -} + /* set the link rate on the sink */ + tmp = dp_get_dp_link_rate_coded(dp_info->dp_clock); + radeon_write_dpcd_reg(dp_info->radeon_connector, DP_LINK_BW_SET, tmp); -void dp_link_train(struct drm_encoder *encoder, - struct drm_connector *connector) -{ - 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; - struct radeon_connector *radeon_connector; - struct radeon_connector_atom_dig *dig_connector; - int enc_id = 0; - bool clock_recovery, channel_eq; - u8 link_status[DP_LINK_STATUS_SIZE]; - u8 link_configuration[DP_LINK_CONFIGURATION_SIZE]; - u8 tries, voltage; - u8 train_set[4]; - int i; + /* start training on the source */ + if (ASIC_IS_DCE4(dp_info->rdev)) + atombios_dig_encoder_setup(dp_info->encoder, + ATOM_ENCODER_CMD_DP_LINK_TRAINING_START, 0); + else + radeon_dp_encoder_service(dp_info->rdev, ATOM_DP_ACTION_TRAINING_START, + dp_info->dp_clock, dp_info->enc_id, 0); - if ((connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort) && - (connector->connector_type != DRM_MODE_CONNECTOR_eDP)) - return; + /* disable the training pattern on the sink */ + radeon_write_dpcd_reg(dp_info->radeon_connector, + DP_TRAINING_PATTERN_SET, + DP_TRAINING_PATTERN_DISABLE); - if (!radeon_encoder->enc_priv) - return; - dig = radeon_encoder->enc_priv; + return 0; +} - radeon_connector = to_radeon_connector(connector); - if (!radeon_connector->con_priv) - return; - dig_connector = radeon_connector->con_priv; +static int radeon_dp_link_train_finish(struct radeon_dp_link_train_info *dp_info) +{ + udelay(400); - if (dig->dig_encoder) - enc_id |= ATOM_DP_CONFIG_DIG2_ENCODER; - else - enc_id |= ATOM_DP_CONFIG_DIG1_ENCODER; - if (dig->linkb) - enc_id |= ATOM_DP_CONFIG_LINK_B; - else - enc_id |= ATOM_DP_CONFIG_LINK_A; + /* disable the training pattern on the sink */ + radeon_write_dpcd_reg(dp_info->radeon_connector, + DP_TRAINING_PATTERN_SET, + DP_TRAINING_PATTERN_DISABLE); - memset(link_configuration, 0, DP_LINK_CONFIGURATION_SIZE); - if (dig_connector->dp_clock == 270000) - link_configuration[0] = DP_LINK_BW_2_7; + /* disable the training pattern on the source */ + if (ASIC_IS_DCE4(dp_info->rdev)) + atombios_dig_encoder_setup(dp_info->encoder, + ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE, 0); else - link_configuration[0] = DP_LINK_BW_1_62; - link_configuration[1] = dig_connector->dp_lane_count; - if (dig_connector->dpcd[0] >= 0x11) - link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; + radeon_dp_encoder_service(dp_info->rdev, ATOM_DP_ACTION_TRAINING_COMPLETE, + dp_info->dp_clock, dp_info->enc_id, 0); - /* power up the sink */ - dp_set_power(radeon_connector, DP_SET_POWER_D0); - /* disable the training pattern on the sink */ - dp_set_training(radeon_connector, DP_TRAINING_PATTERN_DISABLE); - /* set link bw and lanes on the sink */ - dp_set_link_bw_lanes(radeon_connector, link_configuration); - /* disable downspread on the sink */ - dp_set_downspread(radeon_connector, 0); - if (ASIC_IS_DCE4(rdev)) { - /* start training on the source */ - atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_LINK_TRAINING_START); - /* set training pattern 1 on the source */ - atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1); - } else { - /* start training on the source */ - radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_START, - dig_connector->dp_clock, enc_id, 0); - /* set training pattern 1 on the source */ - radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_PATTERN_SEL, - dig_connector->dp_clock, enc_id, 0); - } + return 0; +} - /* set initial vs/emph */ - memset(train_set, 0, 4); - udelay(400); - /* set training pattern 1 on the sink */ - dp_set_training(radeon_connector, DP_TRAINING_PATTERN_1); +static int radeon_dp_link_train_cr(struct radeon_dp_link_train_info *dp_info) +{ + bool clock_recovery; + u8 voltage; + int i; - dp_update_dpvs_emph(radeon_connector, encoder, train_set); + radeon_dp_set_tp(dp_info, DP_TRAINING_PATTERN_1); + memset(dp_info->train_set, 0, 4); + radeon_dp_update_vs_emph(dp_info); + + udelay(400); /* clock recovery loop */ clock_recovery = false; - tries = 0; + dp_info->tries = 0; voltage = 0xff; - for (;;) { - udelay(100); - if (!atom_dp_get_link_status(radeon_connector, link_status)) + while (1) { + if (dp_info->rd_interval == 0) + udelay(100); + else + mdelay(dp_info->rd_interval * 4); + + if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) break; - if (dp_clock_recovery_ok(link_status, dig_connector->dp_lane_count)) { + if (dp_clock_recovery_ok(dp_info->link_status, dp_info->dp_lane_count)) { clock_recovery = true; break; } - for (i = 0; i < dig_connector->dp_lane_count; i++) { - if ((train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) + for (i = 0; i < dp_info->dp_lane_count; i++) { + if ((dp_info->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) break; } - if (i == dig_connector->dp_lane_count) { + if (i == dp_info->dp_lane_count) { DRM_ERROR("clock recovery reached max voltage\n"); break; } - if ((train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { - ++tries; - if (tries == 5) { + if ((dp_info->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { + ++dp_info->tries; + if (dp_info->tries == 5) { DRM_ERROR("clock recovery tried 5 times\n"); break; } } else - tries = 0; + dp_info->tries = 0; - voltage = train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; + voltage = dp_info->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; /* Compute new train_set as requested by sink */ - dp_get_adjust_train(link_status, dig_connector->dp_lane_count, train_set); - dp_update_dpvs_emph(radeon_connector, encoder, train_set); + dp_get_adjust_train(dp_info->link_status, dp_info->dp_lane_count, dp_info->train_set); + + radeon_dp_update_vs_emph(dp_info); } - if (!clock_recovery) + if (!clock_recovery) { DRM_ERROR("clock recovery failed\n"); - else + return -1; + } else { DRM_DEBUG_KMS("clock recovery at voltage %d pre-emphasis %d\n", - train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK, - (train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK) >> + dp_info->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK, + (dp_info->train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK) >> DP_TRAIN_PRE_EMPHASIS_SHIFT); + return 0; + } +} +static int radeon_dp_link_train_ce(struct radeon_dp_link_train_info *dp_info) +{ + bool channel_eq; - /* set training pattern 2 on the sink */ - dp_set_training(radeon_connector, DP_TRAINING_PATTERN_2); - /* set training pattern 2 on the source */ - if (ASIC_IS_DCE4(rdev)) - atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN2); + if (dp_info->tp3_supported) + radeon_dp_set_tp(dp_info, DP_TRAINING_PATTERN_3); else - radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_PATTERN_SEL, - dig_connector->dp_clock, enc_id, 1); + radeon_dp_set_tp(dp_info, DP_TRAINING_PATTERN_2); /* channel equalization loop */ - tries = 0; + dp_info->tries = 0; channel_eq = false; - for (;;) { - udelay(400); - if (!atom_dp_get_link_status(radeon_connector, link_status)) + while (1) { + if (dp_info->rd_interval == 0) + udelay(400); + else + mdelay(dp_info->rd_interval * 4); + + if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) break; - if (dp_channel_eq_ok(link_status, dig_connector->dp_lane_count)) { + if (dp_channel_eq_ok(dp_info->link_status, dp_info->dp_lane_count)) { channel_eq = true; break; } /* Try 5 times */ - if (tries > 5) { + if (dp_info->tries > 5) { DRM_ERROR("channel eq failed: 5 tries\n"); break; } /* Compute new train_set as requested by sink */ - dp_get_adjust_train(link_status, dig_connector->dp_lane_count, train_set); - dp_update_dpvs_emph(radeon_connector, encoder, train_set); + dp_get_adjust_train(dp_info->link_status, dp_info->dp_lane_count, dp_info->train_set); - tries++; + radeon_dp_update_vs_emph(dp_info); + dp_info->tries++; } - if (!channel_eq) + if (!channel_eq) { DRM_ERROR("channel eq failed\n"); - else + return -1; + } else { DRM_DEBUG_KMS("channel eq at voltage %d pre-emphasis %d\n", - train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK, - (train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK) + dp_info->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK, + (dp_info->train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK) >> DP_TRAIN_PRE_EMPHASIS_SHIFT); - - /* disable the training pattern on the sink */ - dp_set_training(radeon_connector, DP_TRAINING_PATTERN_DISABLE); - - /* disable the training pattern on the source */ - if (ASIC_IS_DCE4(rdev)) - atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE); - else - radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_COMPLETE, - dig_connector->dp_clock, enc_id, 0); + return 0; + } } -int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, - uint8_t write_byte, uint8_t *read_byte) +void radeon_dp_link_train(struct drm_encoder *encoder, + struct drm_connector *connector) { - struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; - struct radeon_i2c_chan *auxch = (struct radeon_i2c_chan *)adapter; - int ret = 0; - uint16_t address = algo_data->address; - uint8_t msg[5]; - uint8_t reply[2]; - int msg_len, dp_msg_len; - int reply_bytes; - - /* Set up the command byte */ - if (mode & MODE_I2C_READ) - msg[2] = AUX_I2C_READ << 4; - else - msg[2] = AUX_I2C_WRITE << 4; - - if (!(mode & MODE_I2C_STOP)) - msg[2] |= AUX_I2C_MOT << 4; + 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; + struct radeon_connector *radeon_connector; + struct radeon_connector_atom_dig *dig_connector; + struct radeon_dp_link_train_info dp_info; + u8 tmp; - msg[0] = address; - msg[1] = address >> 8; + if (!radeon_encoder->enc_priv) + return; + dig = radeon_encoder->enc_priv; - reply_bytes = 1; + radeon_connector = to_radeon_connector(connector); + if (!radeon_connector->con_priv) + return; + dig_connector = radeon_connector->con_priv; - msg_len = 4; - dp_msg_len = 3; - switch (mode) { - case MODE_I2C_WRITE: - msg[4] = write_byte; - msg_len++; - dp_msg_len += 2; - break; - case MODE_I2C_READ: - dp_msg_len += 1; - break; - default: - break; - } + if ((dig_connector->dp_sink_type != CONNECTOR_OBJECT_ID_DISPLAYPORT) && + (dig_connector->dp_sink_type != CONNECTOR_OBJECT_ID_eDP)) + return; - msg[3] = (dp_msg_len) << 4; - ret = radeon_process_aux_ch(auxch, msg, msg_len, reply, reply_bytes, 0); + dp_info.enc_id = 0; + if (dig->dig_encoder) + dp_info.enc_id |= ATOM_DP_CONFIG_DIG2_ENCODER; + else + dp_info.enc_id |= ATOM_DP_CONFIG_DIG1_ENCODER; + if (dig->linkb) + dp_info.enc_id |= ATOM_DP_CONFIG_LINK_B; + else + dp_info.enc_id |= ATOM_DP_CONFIG_LINK_A; - if (ret) { - if (read_byte) - *read_byte = reply[0]; - return reply_bytes; - } - return -EREMOTEIO; + dp_info.rd_interval = radeon_read_dpcd_reg(radeon_connector, DP_TRAINING_AUX_RD_INTERVAL); + tmp = radeon_read_dpcd_reg(radeon_connector, DP_MAX_LANE_COUNT); + if (ASIC_IS_DCE5(rdev) && (tmp & DP_TPS3_SUPPORTED)) + dp_info.tp3_supported = true; + else + dp_info.tp3_supported = false; + + memcpy(dp_info.dpcd, dig_connector->dpcd, 8); + dp_info.rdev = rdev; + dp_info.encoder = encoder; + dp_info.connector = connector; + dp_info.radeon_connector = radeon_connector; + dp_info.dp_lane_count = dig_connector->dp_lane_count; + dp_info.dp_clock = dig_connector->dp_clock; + + if (radeon_dp_link_train_init(&dp_info)) + goto done; + if (radeon_dp_link_train_cr(&dp_info)) + goto done; + if (radeon_dp_link_train_ce(&dp_info)) + goto done; +done: + if (radeon_dp_link_train_finish(&dp_info)) + return; } - diff --git a/drivers/gpu/drm/radeon/cayman_blit_shaders.c b/drivers/gpu/drm/radeon/cayman_blit_shaders.c index e148ab04b80..7b4eeb7b4a8 100644 --- a/drivers/gpu/drm/radeon/cayman_blit_shaders.c +++ b/drivers/gpu/drm/radeon/cayman_blit_shaders.c @@ -39,17 +39,335 @@ const u32 cayman_default_state[] = { - /* XXX fill in additional blit state */ + 0xc0066900, + 0x00000000, + 0x00000060, /* DB_RENDER_CONTROL */ + 0x00000000, /* DB_COUNT_CONTROL */ + 0x00000000, /* DB_DEPTH_VIEW */ + 0x0000002a, /* DB_RENDER_OVERRIDE */ + 0x00000000, /* DB_RENDER_OVERRIDE2 */ + 0x00000000, /* DB_HTILE_DATA_BASE */ 0xc0026900, - 0x00000316, - 0x0000000e, /* VGT_VERTEX_REUSE_BLOCK_CNTL */ - 0x00000010, /* */ + 0x0000000a, + 0x00000000, /* DB_STENCIL_CLEAR */ + 0x00000000, /* DB_DEPTH_CLEAR */ + + 0xc0036900, + 0x0000000f, + 0x00000000, /* DB_DEPTH_INFO */ + 0x00000000, /* DB_Z_INFO */ + 0x00000000, /* DB_STENCIL_INFO */ + + 0xc0016900, + 0x00000080, + 0x00000000, /* PA_SC_WINDOW_OFFSET */ + + 0xc00d6900, + 0x00000083, + 0x0000ffff, /* PA_SC_CLIPRECT_RULE */ + 0x00000000, /* PA_SC_CLIPRECT_0_TL */ + 0x20002000, /* PA_SC_CLIPRECT_0_BR */ + 0x00000000, + 0x20002000, + 0x00000000, + 0x20002000, + 0x00000000, + 0x20002000, + 0xaaaaaaaa, /* PA_SC_EDGERULE */ + 0x00000000, /* PA_SU_HARDWARE_SCREEN_OFFSET */ + 0x0000000f, /* CB_TARGET_MASK */ + 0x0000000f, /* CB_SHADER_MASK */ + + 0xc0226900, + 0x00000094, + 0x80000000, /* PA_SC_VPORT_SCISSOR_0_TL */ + 0x20002000, /* PA_SC_VPORT_SCISSOR_0_BR */ + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x80000000, + 0x20002000, + 0x00000000, /* PA_SC_VPORT_ZMIN_0 */ + 0x3f800000, /* PA_SC_VPORT_ZMAX_0 */ + + 0xc0016900, + 0x000000d4, + 0x00000000, /* SX_MISC */ 0xc0026900, 0x000000d9, 0x00000000, /* CP_RINGID */ 0x00000000, /* CP_VMID */ + + 0xc0096900, + 0x00000100, + 0x00ffffff, /* VGT_MAX_VTX_INDX */ + 0x00000000, /* VGT_MIN_VTX_INDX */ + 0x00000000, /* VGT_INDX_OFFSET */ + 0x00000000, /* VGT_MULTI_PRIM_IB_RESET_INDX */ + 0x00000000, /* SX_ALPHA_TEST_CONTROL */ + 0x00000000, /* CB_BLEND_RED */ + 0x00000000, /* CB_BLEND_GREEN */ + 0x00000000, /* CB_BLEND_BLUE */ + 0x00000000, /* CB_BLEND_ALPHA */ + + 0xc0016900, + 0x00000187, + 0x00000100, /* SPI_VS_OUT_ID_0 */ + + 0xc0026900, + 0x00000191, + 0x00000100, /* SPI_PS_INPUT_CNTL_0 */ + 0x00000101, /* SPI_PS_INPUT_CNTL_1 */ + + 0xc0016900, + 0x000001b1, + 0x00000000, /* SPI_VS_OUT_CONFIG */ + + 0xc0106900, + 0x000001b3, + 0x20000001, /* SPI_PS_IN_CONTROL_0 */ + 0x00000000, /* SPI_PS_IN_CONTROL_1 */ + 0x00000000, /* SPI_INTERP_CONTROL_0 */ + 0x00000000, /* SPI_INPUT_Z */ + 0x00000000, /* SPI_FOG_CNTL */ + 0x00100000, /* SPI_BARYC_CNTL */ + 0x00000000, /* SPI_PS_IN_CONTROL_2 */ + 0x00000000, /* SPI_COMPUTE_INPUT_CNTL */ + 0x00000000, /* SPI_COMPUTE_NUM_THREAD_X */ + 0x00000000, /* SPI_COMPUTE_NUM_THREAD_Y */ + 0x00000000, /* SPI_COMPUTE_NUM_THREAD_Z */ + 0x00000000, /* SPI_GPR_MGMT */ + 0x00000000, /* SPI_LDS_MGMT */ + 0x00000000, /* SPI_STACK_MGMT */ + 0x00000000, /* SPI_WAVE_MGMT_1 */ + 0x00000000, /* SPI_WAVE_MGMT_2 */ + + 0xc0016900, + 0x000001e0, + 0x00000000, /* CB_BLEND0_CONTROL */ + + 0xc00e6900, + 0x00000200, + 0x00000000, /* DB_DEPTH_CONTROL */ + 0x00000000, /* DB_EQAA */ + 0x00cc0010, /* CB_COLOR_CONTROL */ + 0x00000210, /* DB_SHADER_CONTROL */ + 0x00010000, /* PA_CL_CLIP_CNTL */ + 0x00000004, /* PA_SU_SC_MODE_CNTL */ + 0x00000100, /* PA_CL_VTE_CNTL */ + 0x00000000, /* PA_CL_VS_OUT_CNTL */ + 0x00000000, /* PA_CL_NANINF_CNTL */ + 0x00000000, /* PA_SU_LINE_STIPPLE_CNTL */ + 0x00000000, /* PA_SU_LINE_STIPPLE_SCALE */ + 0x00000000, /* PA_SU_PRIM_FILTER_CNTL */ + 0x00000000, /* */ + 0x00000000, /* */ + + 0xc0026900, + 0x00000229, + 0x00000000, /* SQ_PGM_START_FS */ + 0x00000000, + + 0xc0016900, + 0x0000023b, + 0x00000000, /* SQ_LDS_ALLOC_PS */ + + 0xc0066900, + 0x00000240, + 0x00000000, /* SQ_ESGS_RING_ITEMSIZE */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + + 0xc0046900, + 0x00000247, + 0x00000000, /* SQ_GS_VERT_ITEMSIZE */ + 0x00000000, + 0x00000000, + 0x00000000, + + 0xc0116900, + 0x00000280, + 0x00000000, /* PA_SU_POINT_SIZE */ + 0x00000000, /* PA_SU_POINT_MINMAX */ + 0x00000008, /* PA_SU_LINE_CNTL */ + 0x00000000, /* PA_SC_LINE_STIPPLE */ + 0x00000000, /* VGT_OUTPUT_PATH_CNTL */ + 0x00000000, /* VGT_HOS_CNTL */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, /* VGT_GS_MODE */ + + 0xc0026900, + 0x00000292, + 0x00000000, /* PA_SC_MODE_CNTL_0 */ + 0x00000000, /* PA_SC_MODE_CNTL_1 */ + + 0xc0016900, + 0x000002a1, + 0x00000000, /* VGT_PRIMITIVEID_EN */ + + 0xc0016900, + 0x000002a5, + 0x00000000, /* VGT_MULTI_PRIM_IB_RESET_EN */ + + 0xc0026900, + 0x000002a8, + 0x00000000, /* VGT_INSTANCE_STEP_RATE_0 */ + 0x00000000, + + 0xc0026900, + 0x000002ad, + 0x00000000, /* VGT_REUSE_OFF */ + 0x00000000, + + 0xc0016900, + 0x000002d5, + 0x00000000, /* VGT_SHADER_STAGES_EN */ + + 0xc0016900, + 0x000002dc, + 0x0000aa00, /* DB_ALPHA_TO_MASK */ + + 0xc0066900, + 0x000002de, + 0x00000000, /* PA_SU_POLY_OFFSET_DB_FMT_CNTL */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + + 0xc0026900, + 0x000002e5, + 0x00000000, /* VGT_STRMOUT_CONFIG */ + 0x00000000, + + 0xc01b6900, + 0x000002f5, + 0x76543210, /* PA_SC_CENTROID_PRIORITY_0 */ + 0xfedcba98, /* PA_SC_CENTROID_PRIORITY_1 */ + 0x00000000, /* PA_SC_LINE_CNTL */ + 0x00000000, /* PA_SC_AA_CONFIG */ + 0x00000005, /* PA_SU_VTX_CNTL */ + 0x3f800000, /* PA_CL_GB_VERT_CLIP_ADJ */ + 0x3f800000, /* PA_CL_GB_VERT_DISC_ADJ */ + 0x3f800000, /* PA_CL_GB_HORZ_CLIP_ADJ */ + 0x3f800000, /* PA_CL_GB_HORZ_DISC_ADJ */ + 0x00000000, /* PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0 */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xffffffff, /* PA_SC_AA_MASK_X0Y0_X1Y0 */ + 0xffffffff, + + 0xc0026900, + 0x00000316, + 0x0000000e, /* VGT_VERTEX_REUSE_BLOCK_CNTL */ + 0x00000010, /* */ +}; + +const u32 cayman_vs[] = +{ + 0x00000004, + 0x80400400, + 0x0000a03c, + 0x95000688, + 0x00004000, + 0x15000688, + 0x00000000, + 0x88000000, + 0x04000000, + 0x67961001, +#ifdef __BIG_ENDIAN + 0x00020000, +#else + 0x00000000, +#endif + 0x00000000, + 0x04000000, + 0x67961000, +#ifdef __BIG_ENDIAN + 0x00020008, +#else + 0x00000008, +#endif + 0x00000000, +}; + +const u32 cayman_ps[] = +{ + 0x00000004, + 0xa00c0000, + 0x00000008, + 0x80400000, + 0x00000000, + 0x95000688, + 0x00000000, + 0x88000000, + 0x00380400, + 0x00146b10, + 0x00380000, + 0x20146b10, + 0x00380400, + 0x40146b00, + 0x80380000, + 0x60146b00, + 0x00000010, + 0x000d1000, + 0xb0800000, + 0x00000000, }; +const u32 cayman_ps_size = ARRAY_SIZE(cayman_ps); +const u32 cayman_vs_size = ARRAY_SIZE(cayman_vs); const u32 cayman_default_size = ARRAY_SIZE(cayman_default_state); diff --git a/drivers/gpu/drm/radeon/cayman_blit_shaders.h b/drivers/gpu/drm/radeon/cayman_blit_shaders.h index 33b75e5d0fa..f5d0e9a6026 100644 --- a/drivers/gpu/drm/radeon/cayman_blit_shaders.h +++ b/drivers/gpu/drm/radeon/cayman_blit_shaders.h @@ -25,8 +25,11 @@ #ifndef CAYMAN_BLIT_SHADERS_H #define CAYMAN_BLIT_SHADERS_H +extern const u32 cayman_ps[]; +extern const u32 cayman_vs[]; extern const u32 cayman_default_state[]; +extern const u32 cayman_ps_size, cayman_vs_size; extern const u32 cayman_default_size; #endif diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 9073e3bfb08..98ea597bc76 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -88,21 +88,39 @@ u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) /* get temperature in millidegrees */ int evergreen_get_temp(struct radeon_device *rdev) { - u32 temp = (RREG32(CG_MULT_THERMAL_STATUS) & ASIC_T_MASK) >> - ASIC_T_SHIFT; - u32 actual_temp = 0; - - if (temp & 0x400) - actual_temp = -256; - else if (temp & 0x200) - actual_temp = 255; - else if (temp & 0x100) { - actual_temp = temp & 0x1ff; - actual_temp |= ~0x1ff; - } else - actual_temp = temp & 0xff; + u32 temp, toffset, actual_temp = 0; + + if (rdev->family == CHIP_JUNIPER) { + toffset = (RREG32(CG_THERMAL_CTRL) & TOFFSET_MASK) >> + TOFFSET_SHIFT; + temp = (RREG32(CG_TS0_STATUS) & TS0_ADC_DOUT_MASK) >> + TS0_ADC_DOUT_SHIFT; + + if (toffset & 0x100) + actual_temp = temp / 2 - (0x200 - toffset); + else + actual_temp = temp / 2 + toffset; + + actual_temp = actual_temp * 1000; + + } else { + temp = (RREG32(CG_MULT_THERMAL_STATUS) & ASIC_T_MASK) >> + ASIC_T_SHIFT; - return (actual_temp * 1000) / 2; + if (temp & 0x400) + actual_temp = -256; + else if (temp & 0x200) + actual_temp = 255; + else if (temp & 0x100) { + actual_temp = temp & 0x1ff; + actual_temp |= ~0x1ff; + } else + actual_temp = temp & 0xff; + + actual_temp = (actual_temp * 1000) / 2; + } + + return actual_temp; } int sumo_get_temp(struct radeon_device *rdev) @@ -1415,6 +1433,8 @@ static u32 evergreen_get_tile_pipe_to_backend_map(struct radeon_device *rdev, case CHIP_CEDAR: case CHIP_REDWOOD: case CHIP_PALM: + case CHIP_SUMO: + case CHIP_SUMO2: case CHIP_TURKS: case CHIP_CAICOS: force_no_swizzle = false; @@ -1544,6 +1564,8 @@ static void evergreen_program_channel_remap(struct radeon_device *rdev) case CHIP_REDWOOD: case CHIP_CEDAR: case CHIP_PALM: + case CHIP_SUMO: + case CHIP_SUMO2: case CHIP_TURKS: case CHIP_CAICOS: default: @@ -1578,7 +1600,7 @@ static void evergreen_gpu_init(struct radeon_device *rdev) u32 sq_stack_resource_mgmt_2; u32 sq_stack_resource_mgmt_3; u32 vgt_cache_invalidation; - u32 hdp_host_path_cntl; + u32 hdp_host_path_cntl, tmp; int i, j, num_shader_engines, ps_thread_count; switch (rdev->family) { @@ -1689,6 +1711,54 @@ static void evergreen_gpu_init(struct radeon_device *rdev) rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; break; + case CHIP_SUMO: + rdev->config.evergreen.num_ses = 1; + rdev->config.evergreen.max_pipes = 4; + rdev->config.evergreen.max_tile_pipes = 2; + if (rdev->pdev->device == 0x9648) + rdev->config.evergreen.max_simds = 3; + else if ((rdev->pdev->device == 0x9647) || + (rdev->pdev->device == 0x964a)) + rdev->config.evergreen.max_simds = 4; + else + rdev->config.evergreen.max_simds = 5; + rdev->config.evergreen.max_backends = 2 * rdev->config.evergreen.num_ses; + rdev->config.evergreen.max_gprs = 256; + rdev->config.evergreen.max_threads = 248; + rdev->config.evergreen.max_gs_threads = 32; + rdev->config.evergreen.max_stack_entries = 256; + rdev->config.evergreen.sx_num_of_sets = 4; + rdev->config.evergreen.sx_max_export_size = 256; + rdev->config.evergreen.sx_max_export_pos_size = 64; + rdev->config.evergreen.sx_max_export_smx_size = 192; + rdev->config.evergreen.max_hw_contexts = 8; + rdev->config.evergreen.sq_num_cf_insts = 2; + + rdev->config.evergreen.sc_prim_fifo_size = 0x40; + rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; + rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; + break; + case CHIP_SUMO2: + rdev->config.evergreen.num_ses = 1; + rdev->config.evergreen.max_pipes = 4; + rdev->config.evergreen.max_tile_pipes = 4; + rdev->config.evergreen.max_simds = 2; + rdev->config.evergreen.max_backends = 1 * rdev->config.evergreen.num_ses; + rdev->config.evergreen.max_gprs = 256; + rdev->config.evergreen.max_threads = 248; + rdev->config.evergreen.max_gs_threads = 32; + rdev->config.evergreen.max_stack_entries = 512; + rdev->config.evergreen.sx_num_of_sets = 4; + rdev->config.evergreen.sx_max_export_size = 256; + rdev->config.evergreen.sx_max_export_pos_size = 64; + rdev->config.evergreen.sx_max_export_smx_size = 192; + rdev->config.evergreen.max_hw_contexts = 8; + rdev->config.evergreen.sq_num_cf_insts = 2; + + rdev->config.evergreen.sc_prim_fifo_size = 0x40; + rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; + rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; + break; case CHIP_BARTS: rdev->config.evergreen.num_ses = 2; rdev->config.evergreen.max_pipes = 4; @@ -1936,8 +2006,12 @@ static void evergreen_gpu_init(struct radeon_device *rdev) rdev->config.evergreen.tile_config |= (3 << 0); break; } - rdev->config.evergreen.tile_config |= - ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4; + /* num banks is 8 on all fusion asics */ + if (rdev->flags & RADEON_IS_IGP) + rdev->config.evergreen.tile_config |= 8 << 4; + else + rdev->config.evergreen.tile_config |= + ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4; rdev->config.evergreen.tile_config |= ((mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT) << 8; rdev->config.evergreen.tile_config |= @@ -2035,6 +2109,8 @@ static void evergreen_gpu_init(struct radeon_device *rdev) switch (rdev->family) { case CHIP_CEDAR: case CHIP_PALM: + case CHIP_SUMO: + case CHIP_SUMO2: case CHIP_CAICOS: /* no vertex cache */ sq_config &= ~VC_ENABLE; @@ -2056,6 +2132,8 @@ static void evergreen_gpu_init(struct radeon_device *rdev) switch (rdev->family) { case CHIP_CEDAR: case CHIP_PALM: + case CHIP_SUMO: + case CHIP_SUMO2: ps_thread_count = 96; break; default: @@ -2095,6 +2173,8 @@ static void evergreen_gpu_init(struct radeon_device *rdev) switch (rdev->family) { case CHIP_CEDAR: case CHIP_PALM: + case CHIP_SUMO: + case CHIP_SUMO2: case CHIP_CAICOS: vgt_cache_invalidation = CACHE_INVALIDATION(TC_ONLY); break; @@ -2141,6 +2221,10 @@ static void evergreen_gpu_init(struct radeon_device *rdev) for (i = SQ_ALU_CONST_BUFFER_SIZE_HS_0; i < 0x29000; i += 4) WREG32(i, 0); + tmp = RREG32(HDP_MISC_CNTL); + tmp |= HDP_FLUSH_INVALIDATE_CACHE; + WREG32(HDP_MISC_CNTL, tmp); + hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL); WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl); diff --git a/drivers/gpu/drm/radeon/evergreen_blit_kms.c b/drivers/gpu/drm/radeon/evergreen_blit_kms.c index ba06a69c6de..57f3bc17b87 100644 --- a/drivers/gpu/drm/radeon/evergreen_blit_kms.c +++ b/drivers/gpu/drm/radeon/evergreen_blit_kms.c @@ -31,6 +31,7 @@ #include "evergreend.h" #include "evergreen_blit_shaders.h" +#include "cayman_blit_shaders.h" #define DI_PT_RECTLIST 0x11 #define DI_INDEX_SIZE_16_BIT 0x0 @@ -152,6 +153,8 @@ set_vtx_resource(struct radeon_device *rdev, u64 gpu_addr) if ((rdev->family == CHIP_CEDAR) || (rdev->family == CHIP_PALM) || + (rdev->family == CHIP_SUMO) || + (rdev->family == CHIP_SUMO2) || (rdev->family == CHIP_CAICOS)) cp_set_surface_sync(rdev, PACKET3_TC_ACTION_ENA, 48, gpu_addr); @@ -199,6 +202,16 @@ static void set_scissors(struct radeon_device *rdev, int x1, int y1, int x2, int y2) { + /* workaround some hw bugs */ + if (x2 == 0) + x1 = 1; + if (y2 == 0) + y1 = 1; + if (rdev->family == CHIP_CAYMAN) { + if ((x2 == 1) && (y2 == 1)) + x2 = 2; + } + radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 2)); radeon_ring_write(rdev, (PA_SC_SCREEN_SCISSOR_TL - PACKET3_SET_CONTEXT_REG_START) >> 2); radeon_ring_write(rdev, (x1 << 0) | (y1 << 16)); @@ -255,238 +268,284 @@ set_default_state(struct radeon_device *rdev) u64 gpu_addr; int dwords; - switch (rdev->family) { - case CHIP_CEDAR: - default: - num_ps_gprs = 93; - num_vs_gprs = 46; - num_temp_gprs = 4; - num_gs_gprs = 31; - num_es_gprs = 31; - num_hs_gprs = 23; - num_ls_gprs = 23; - num_ps_threads = 96; - num_vs_threads = 16; - num_gs_threads = 16; - num_es_threads = 16; - num_hs_threads = 16; - num_ls_threads = 16; - num_ps_stack_entries = 42; - num_vs_stack_entries = 42; - num_gs_stack_entries = 42; - num_es_stack_entries = 42; - num_hs_stack_entries = 42; - num_ls_stack_entries = 42; - break; - case CHIP_REDWOOD: - num_ps_gprs = 93; - num_vs_gprs = 46; - num_temp_gprs = 4; - num_gs_gprs = 31; - num_es_gprs = 31; - num_hs_gprs = 23; - num_ls_gprs = 23; - num_ps_threads = 128; - num_vs_threads = 20; - num_gs_threads = 20; - num_es_threads = 20; - num_hs_threads = 20; - num_ls_threads = 20; - num_ps_stack_entries = 42; - num_vs_stack_entries = 42; - num_gs_stack_entries = 42; - num_es_stack_entries = 42; - num_hs_stack_entries = 42; - num_ls_stack_entries = 42; - break; - case CHIP_JUNIPER: - num_ps_gprs = 93; - num_vs_gprs = 46; - num_temp_gprs = 4; - num_gs_gprs = 31; - num_es_gprs = 31; - num_hs_gprs = 23; - num_ls_gprs = 23; - num_ps_threads = 128; - num_vs_threads = 20; - num_gs_threads = 20; - num_es_threads = 20; - num_hs_threads = 20; - num_ls_threads = 20; - num_ps_stack_entries = 85; - num_vs_stack_entries = 85; - num_gs_stack_entries = 85; - num_es_stack_entries = 85; - num_hs_stack_entries = 85; - num_ls_stack_entries = 85; - break; - case CHIP_CYPRESS: - case CHIP_HEMLOCK: - num_ps_gprs = 93; - num_vs_gprs = 46; - num_temp_gprs = 4; - num_gs_gprs = 31; - num_es_gprs = 31; - num_hs_gprs = 23; - num_ls_gprs = 23; - num_ps_threads = 128; - num_vs_threads = 20; - num_gs_threads = 20; - num_es_threads = 20; - num_hs_threads = 20; - num_ls_threads = 20; - num_ps_stack_entries = 85; - num_vs_stack_entries = 85; - num_gs_stack_entries = 85; - num_es_stack_entries = 85; - num_hs_stack_entries = 85; - num_ls_stack_entries = 85; - break; - case CHIP_PALM: - num_ps_gprs = 93; - num_vs_gprs = 46; - num_temp_gprs = 4; - num_gs_gprs = 31; - num_es_gprs = 31; - num_hs_gprs = 23; - num_ls_gprs = 23; - num_ps_threads = 96; - num_vs_threads = 16; - num_gs_threads = 16; - num_es_threads = 16; - num_hs_threads = 16; - num_ls_threads = 16; - num_ps_stack_entries = 42; - num_vs_stack_entries = 42; - num_gs_stack_entries = 42; - num_es_stack_entries = 42; - num_hs_stack_entries = 42; - num_ls_stack_entries = 42; - break; - case CHIP_BARTS: - num_ps_gprs = 93; - num_vs_gprs = 46; - num_temp_gprs = 4; - num_gs_gprs = 31; - num_es_gprs = 31; - num_hs_gprs = 23; - num_ls_gprs = 23; - num_ps_threads = 128; - num_vs_threads = 20; - num_gs_threads = 20; - num_es_threads = 20; - num_hs_threads = 20; - num_ls_threads = 20; - num_ps_stack_entries = 85; - num_vs_stack_entries = 85; - num_gs_stack_entries = 85; - num_es_stack_entries = 85; - num_hs_stack_entries = 85; - num_ls_stack_entries = 85; - break; - case CHIP_TURKS: - num_ps_gprs = 93; - num_vs_gprs = 46; - num_temp_gprs = 4; - num_gs_gprs = 31; - num_es_gprs = 31; - num_hs_gprs = 23; - num_ls_gprs = 23; - num_ps_threads = 128; - num_vs_threads = 20; - num_gs_threads = 20; - num_es_threads = 20; - num_hs_threads = 20; - num_ls_threads = 20; - num_ps_stack_entries = 42; - num_vs_stack_entries = 42; - num_gs_stack_entries = 42; - num_es_stack_entries = 42; - num_hs_stack_entries = 42; - num_ls_stack_entries = 42; - break; - case CHIP_CAICOS: - num_ps_gprs = 93; - num_vs_gprs = 46; - num_temp_gprs = 4; - num_gs_gprs = 31; - num_es_gprs = 31; - num_hs_gprs = 23; - num_ls_gprs = 23; - num_ps_threads = 128; - num_vs_threads = 10; - num_gs_threads = 10; - num_es_threads = 10; - num_hs_threads = 10; - num_ls_threads = 10; - num_ps_stack_entries = 42; - num_vs_stack_entries = 42; - num_gs_stack_entries = 42; - num_es_stack_entries = 42; - num_hs_stack_entries = 42; - num_ls_stack_entries = 42; - break; - } - - if ((rdev->family == CHIP_CEDAR) || - (rdev->family == CHIP_PALM) || - (rdev->family == CHIP_CAICOS)) - sq_config = 0; - else - sq_config = VC_ENABLE; - - sq_config |= (EXPORT_SRC_C | - CS_PRIO(0) | - LS_PRIO(0) | - HS_PRIO(0) | - PS_PRIO(0) | - VS_PRIO(1) | - GS_PRIO(2) | - ES_PRIO(3)); - - sq_gpr_resource_mgmt_1 = (NUM_PS_GPRS(num_ps_gprs) | - NUM_VS_GPRS(num_vs_gprs) | - NUM_CLAUSE_TEMP_GPRS(num_temp_gprs)); - sq_gpr_resource_mgmt_2 = (NUM_GS_GPRS(num_gs_gprs) | - NUM_ES_GPRS(num_es_gprs)); - sq_gpr_resource_mgmt_3 = (NUM_HS_GPRS(num_hs_gprs) | - NUM_LS_GPRS(num_ls_gprs)); - sq_thread_resource_mgmt = (NUM_PS_THREADS(num_ps_threads) | - NUM_VS_THREADS(num_vs_threads) | - NUM_GS_THREADS(num_gs_threads) | - NUM_ES_THREADS(num_es_threads)); - sq_thread_resource_mgmt_2 = (NUM_HS_THREADS(num_hs_threads) | - NUM_LS_THREADS(num_ls_threads)); - sq_stack_resource_mgmt_1 = (NUM_PS_STACK_ENTRIES(num_ps_stack_entries) | - NUM_VS_STACK_ENTRIES(num_vs_stack_entries)); - sq_stack_resource_mgmt_2 = (NUM_GS_STACK_ENTRIES(num_gs_stack_entries) | - NUM_ES_STACK_ENTRIES(num_es_stack_entries)); - sq_stack_resource_mgmt_3 = (NUM_HS_STACK_ENTRIES(num_hs_stack_entries) | - NUM_LS_STACK_ENTRIES(num_ls_stack_entries)); - /* set clear context state */ radeon_ring_write(rdev, PACKET3(PACKET3_CLEAR_STATE, 0)); radeon_ring_write(rdev, 0); - /* disable dyn gprs */ - radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1)); - radeon_ring_write(rdev, (SQ_DYN_GPR_CNTL_PS_FLUSH_REQ - PACKET3_SET_CONFIG_REG_START) >> 2); - radeon_ring_write(rdev, 0); + if (rdev->family < CHIP_CAYMAN) { + switch (rdev->family) { + case CHIP_CEDAR: + default: + num_ps_gprs = 93; + num_vs_gprs = 46; + num_temp_gprs = 4; + num_gs_gprs = 31; + num_es_gprs = 31; + num_hs_gprs = 23; + num_ls_gprs = 23; + num_ps_threads = 96; + num_vs_threads = 16; + num_gs_threads = 16; + num_es_threads = 16; + num_hs_threads = 16; + num_ls_threads = 16; + num_ps_stack_entries = 42; + num_vs_stack_entries = 42; + num_gs_stack_entries = 42; + num_es_stack_entries = 42; + num_hs_stack_entries = 42; + num_ls_stack_entries = 42; + break; + case CHIP_REDWOOD: + num_ps_gprs = 93; + num_vs_gprs = 46; + num_temp_gprs = 4; + num_gs_gprs = 31; + num_es_gprs = 31; + num_hs_gprs = 23; + num_ls_gprs = 23; + num_ps_threads = 128; + num_vs_threads = 20; + num_gs_threads = 20; + num_es_threads = 20; + num_hs_threads = 20; + num_ls_threads = 20; + num_ps_stack_entries = 42; + num_vs_stack_entries = 42; + num_gs_stack_entries = 42; + num_es_stack_entries = 42; + num_hs_stack_entries = 42; + num_ls_stack_entries = 42; + break; + case CHIP_JUNIPER: + num_ps_gprs = 93; + num_vs_gprs = 46; + num_temp_gprs = 4; + num_gs_gprs = 31; + num_es_gprs = 31; + num_hs_gprs = 23; + num_ls_gprs = 23; + num_ps_threads = 128; + num_vs_threads = 20; + num_gs_threads = 20; + num_es_threads = 20; + num_hs_threads = 20; + num_ls_threads = 20; + num_ps_stack_entries = 85; + num_vs_stack_entries = 85; + num_gs_stack_entries = 85; + num_es_stack_entries = 85; + num_hs_stack_entries = 85; + num_ls_stack_entries = 85; + break; + case CHIP_CYPRESS: + case CHIP_HEMLOCK: + num_ps_gprs = 93; + num_vs_gprs = 46; + num_temp_gprs = 4; + num_gs_gprs = 31; + num_es_gprs = 31; + num_hs_gprs = 23; + num_ls_gprs = 23; + num_ps_threads = 128; + num_vs_threads = 20; + num_gs_threads = 20; + num_es_threads = 20; + num_hs_threads = 20; + num_ls_threads = 20; + num_ps_stack_entries = 85; + num_vs_stack_entries = 85; + num_gs_stack_entries = 85; + num_es_stack_entries = 85; + num_hs_stack_entries = 85; + num_ls_stack_entries = 85; + break; + case CHIP_PALM: + num_ps_gprs = 93; + num_vs_gprs = 46; + num_temp_gprs = 4; + num_gs_gprs = 31; + num_es_gprs = 31; + num_hs_gprs = 23; + num_ls_gprs = 23; + num_ps_threads = 96; + num_vs_threads = 16; + num_gs_threads = 16; + num_es_threads = 16; + num_hs_threads = 16; + num_ls_threads = 16; + num_ps_stack_entries = 42; + num_vs_stack_entries = 42; + num_gs_stack_entries = 42; + num_es_stack_entries = 42; + num_hs_stack_entries = 42; + num_ls_stack_entries = 42; + break; + case CHIP_SUMO: + num_ps_gprs = 93; + num_vs_gprs = 46; + num_temp_gprs = 4; + num_gs_gprs = 31; + num_es_gprs = 31; + num_hs_gprs = 23; + num_ls_gprs = 23; + num_ps_threads = 96; + num_vs_threads = 25; + num_gs_threads = 25; + num_es_threads = 25; + num_hs_threads = 25; + num_ls_threads = 25; + num_ps_stack_entries = 42; + num_vs_stack_entries = 42; + num_gs_stack_entries = 42; + num_es_stack_entries = 42; + num_hs_stack_entries = 42; + num_ls_stack_entries = 42; + break; + case CHIP_SUMO2: + num_ps_gprs = 93; + num_vs_gprs = 46; + num_temp_gprs = 4; + num_gs_gprs = 31; + num_es_gprs = 31; + num_hs_gprs = 23; + num_ls_gprs = 23; + num_ps_threads = 96; + num_vs_threads = 25; + num_gs_threads = 25; + num_es_threads = 25; + num_hs_threads = 25; + num_ls_threads = 25; + num_ps_stack_entries = 85; + num_vs_stack_entries = 85; + num_gs_stack_entries = 85; + num_es_stack_entries = 85; + num_hs_stack_entries = 85; + num_ls_stack_entries = 85; + break; + case CHIP_BARTS: + num_ps_gprs = 93; + num_vs_gprs = 46; + num_temp_gprs = 4; + num_gs_gprs = 31; + num_es_gprs = 31; + num_hs_gprs = 23; + num_ls_gprs = 23; + num_ps_threads = 128; + num_vs_threads = 20; + num_gs_threads = 20; + num_es_threads = 20; + num_hs_threads = 20; + num_ls_threads = 20; + num_ps_stack_entries = 85; + num_vs_stack_entries = 85; + num_gs_stack_entries = 85; + num_es_stack_entries = 85; + num_hs_stack_entries = 85; + num_ls_stack_entries = 85; + break; + case CHIP_TURKS: + num_ps_gprs = 93; + num_vs_gprs = 46; + num_temp_gprs = 4; + num_gs_gprs = 31; + num_es_gprs = 31; + num_hs_gprs = 23; + num_ls_gprs = 23; + num_ps_threads = 128; + num_vs_threads = 20; + num_gs_threads = 20; + num_es_threads = 20; + num_hs_threads = 20; + num_ls_threads = 20; + num_ps_stack_entries = 42; + num_vs_stack_entries = 42; + num_gs_stack_entries = 42; + num_es_stack_entries = 42; + num_hs_stack_entries = 42; + num_ls_stack_entries = 42; + break; + case CHIP_CAICOS: + num_ps_gprs = 93; + num_vs_gprs = 46; + num_temp_gprs = 4; + num_gs_gprs = 31; + num_es_gprs = 31; + num_hs_gprs = 23; + num_ls_gprs = 23; + num_ps_threads = 128; + num_vs_threads = 10; + num_gs_threads = 10; + num_es_threads = 10; + num_hs_threads = 10; + num_ls_threads = 10; + num_ps_stack_entries = 42; + num_vs_stack_entries = 42; + num_gs_stack_entries = 42; + num_es_stack_entries = 42; + num_hs_stack_entries = 42; + num_ls_stack_entries = 42; + break; + } - /* SQ config */ - radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 11)); - radeon_ring_write(rdev, (SQ_CONFIG - PACKET3_SET_CONFIG_REG_START) >> 2); - radeon_ring_write(rdev, sq_config); - radeon_ring_write(rdev, sq_gpr_resource_mgmt_1); - radeon_ring_write(rdev, sq_gpr_resource_mgmt_2); - radeon_ring_write(rdev, sq_gpr_resource_mgmt_3); - radeon_ring_write(rdev, 0); - radeon_ring_write(rdev, 0); - radeon_ring_write(rdev, sq_thread_resource_mgmt); - radeon_ring_write(rdev, sq_thread_resource_mgmt_2); - radeon_ring_write(rdev, sq_stack_resource_mgmt_1); - radeon_ring_write(rdev, sq_stack_resource_mgmt_2); - radeon_ring_write(rdev, sq_stack_resource_mgmt_3); + if ((rdev->family == CHIP_CEDAR) || + (rdev->family == CHIP_PALM) || + (rdev->family == CHIP_SUMO) || + (rdev->family == CHIP_SUMO2) || + (rdev->family == CHIP_CAICOS)) + sq_config = 0; + else + sq_config = VC_ENABLE; + + sq_config |= (EXPORT_SRC_C | + CS_PRIO(0) | + LS_PRIO(0) | + HS_PRIO(0) | + PS_PRIO(0) | + VS_PRIO(1) | + GS_PRIO(2) | + ES_PRIO(3)); + + sq_gpr_resource_mgmt_1 = (NUM_PS_GPRS(num_ps_gprs) | + NUM_VS_GPRS(num_vs_gprs) | + NUM_CLAUSE_TEMP_GPRS(num_temp_gprs)); + sq_gpr_resource_mgmt_2 = (NUM_GS_GPRS(num_gs_gprs) | + NUM_ES_GPRS(num_es_gprs)); + sq_gpr_resource_mgmt_3 = (NUM_HS_GPRS(num_hs_gprs) | + NUM_LS_GPRS(num_ls_gprs)); + sq_thread_resource_mgmt = (NUM_PS_THREADS(num_ps_threads) | + NUM_VS_THREADS(num_vs_threads) | + NUM_GS_THREADS(num_gs_threads) | + NUM_ES_THREADS(num_es_threads)); + sq_thread_resource_mgmt_2 = (NUM_HS_THREADS(num_hs_threads) | + NUM_LS_THREADS(num_ls_threads)); + sq_stack_resource_mgmt_1 = (NUM_PS_STACK_ENTRIES(num_ps_stack_entries) | + NUM_VS_STACK_ENTRIES(num_vs_stack_entries)); + sq_stack_resource_mgmt_2 = (NUM_GS_STACK_ENTRIES(num_gs_stack_entries) | + NUM_ES_STACK_ENTRIES(num_es_stack_entries)); + sq_stack_resource_mgmt_3 = (NUM_HS_STACK_ENTRIES(num_hs_stack_entries) | + NUM_LS_STACK_ENTRIES(num_ls_stack_entries)); + + /* disable dyn gprs */ + radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1)); + radeon_ring_write(rdev, (SQ_DYN_GPR_CNTL_PS_FLUSH_REQ - PACKET3_SET_CONFIG_REG_START) >> 2); + radeon_ring_write(rdev, 0); + + /* SQ config */ + radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 11)); + radeon_ring_write(rdev, (SQ_CONFIG - PACKET3_SET_CONFIG_REG_START) >> 2); + radeon_ring_write(rdev, sq_config); + radeon_ring_write(rdev, sq_gpr_resource_mgmt_1); + radeon_ring_write(rdev, sq_gpr_resource_mgmt_2); + radeon_ring_write(rdev, sq_gpr_resource_mgmt_3); + radeon_ring_write(rdev, 0); + radeon_ring_write(rdev, 0); + radeon_ring_write(rdev, sq_thread_resource_mgmt); + radeon_ring_write(rdev, sq_thread_resource_mgmt_2); + radeon_ring_write(rdev, sq_stack_resource_mgmt_1); + radeon_ring_write(rdev, sq_stack_resource_mgmt_2); + radeon_ring_write(rdev, sq_stack_resource_mgmt_3); + } /* CONTEXT_CONTROL */ radeon_ring_write(rdev, 0xc0012800); @@ -560,7 +619,10 @@ int evergreen_blit_init(struct radeon_device *rdev) mutex_init(&rdev->r600_blit.mutex); rdev->r600_blit.state_offset = 0; - rdev->r600_blit.state_len = evergreen_default_size; + if (rdev->family < CHIP_CAYMAN) + rdev->r600_blit.state_len = evergreen_default_size; + else + rdev->r600_blit.state_len = cayman_default_size; dwords = rdev->r600_blit.state_len; while (dwords & 0xf) { @@ -572,11 +634,17 @@ int evergreen_blit_init(struct radeon_device *rdev) obj_size = ALIGN(obj_size, 256); rdev->r600_blit.vs_offset = obj_size; - obj_size += evergreen_vs_size * 4; + if (rdev->family < CHIP_CAYMAN) + obj_size += evergreen_vs_size * 4; + else + obj_size += cayman_vs_size * 4; obj_size = ALIGN(obj_size, 256); rdev->r600_blit.ps_offset = obj_size; - obj_size += evergreen_ps_size * 4; + if (rdev->family < CHIP_CAYMAN) + obj_size += evergreen_ps_size * 4; + else + obj_size += cayman_ps_size * 4; obj_size = ALIGN(obj_size, 256); r = radeon_bo_create(rdev, obj_size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, @@ -599,16 +667,29 @@ int evergreen_blit_init(struct radeon_device *rdev) return r; } - memcpy_toio(ptr + rdev->r600_blit.state_offset, - evergreen_default_state, rdev->r600_blit.state_len * 4); - - if (num_packet2s) - memcpy_toio(ptr + rdev->r600_blit.state_offset + (rdev->r600_blit.state_len * 4), - packet2s, num_packet2s * 4); - for (i = 0; i < evergreen_vs_size; i++) - *(u32 *)((unsigned long)ptr + rdev->r600_blit.vs_offset + i * 4) = cpu_to_le32(evergreen_vs[i]); - for (i = 0; i < evergreen_ps_size; i++) - *(u32 *)((unsigned long)ptr + rdev->r600_blit.ps_offset + i * 4) = cpu_to_le32(evergreen_ps[i]); + if (rdev->family < CHIP_CAYMAN) { + memcpy_toio(ptr + rdev->r600_blit.state_offset, + evergreen_default_state, rdev->r600_blit.state_len * 4); + + if (num_packet2s) + memcpy_toio(ptr + rdev->r600_blit.state_offset + (rdev->r600_blit.state_len * 4), + packet2s, num_packet2s * 4); + for (i = 0; i < evergreen_vs_size; i++) + *(u32 *)((unsigned long)ptr + rdev->r600_blit.vs_offset + i * 4) = cpu_to_le32(evergreen_vs[i]); + for (i = 0; i < evergreen_ps_size; i++) + *(u32 *)((unsigned long)ptr + rdev->r600_blit.ps_offset + i * 4) = cpu_to_le32(evergreen_ps[i]); + } else { + memcpy_toio(ptr + rdev->r600_blit.state_offset, + cayman_default_state, rdev->r600_blit.state_len * 4); + + if (num_packet2s) + memcpy_toio(ptr + rdev->r600_blit.state_offset + (rdev->r600_blit.state_len * 4), + packet2s, num_packet2s * 4); + for (i = 0; i < cayman_vs_size; i++) + *(u32 *)((unsigned long)ptr + rdev->r600_blit.vs_offset + i * 4) = cpu_to_le32(cayman_vs[i]); + for (i = 0; i < cayman_ps_size; i++) + *(u32 *)((unsigned long)ptr + rdev->r600_blit.ps_offset + i * 4) = cpu_to_le32(cayman_ps[i]); + } radeon_bo_kunmap(rdev->r600_blit.shader_obj); radeon_bo_unreserve(rdev->r600_blit.shader_obj); diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index fc40e0cc345..1636e344982 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -64,6 +64,8 @@ #define GB_BACKEND_MAP 0x98FC #define DMIF_ADDR_CONFIG 0xBD4 #define HDP_ADDR_CONFIG 0x2F48 +#define HDP_MISC_CNTL 0x2F4C +#define HDP_FLUSH_INVALIDATE_CACHE (1 << 0) #define CC_SYS_RB_BACKEND_DISABLE 0x3F88 #define GC_USER_RB_BACKEND_DISABLE 0x9B7C @@ -166,10 +168,16 @@ #define SE_DB_BUSY (1 << 30) #define SE_CB_BUSY (1 << 31) /* evergreen */ +#define CG_THERMAL_CTRL 0x72c +#define TOFFSET_MASK 0x00003FE0 +#define TOFFSET_SHIFT 5 #define CG_MULT_THERMAL_STATUS 0x740 #define ASIC_T(x) ((x) << 16) -#define ASIC_T_MASK 0x7FF0000 +#define ASIC_T_MASK 0x07FF0000 #define ASIC_T_SHIFT 16 +#define CG_TS0_STATUS 0x760 +#define TS0_ADC_DOUT_MASK 0x000003FF +#define TS0_ADC_DOUT_SHIFT 0 /* APU */ #define CG_THERMAL_STATUS 0x678 diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 3d8a7634bbe..16caafeadf5 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -417,7 +417,7 @@ static u32 cayman_get_tile_pipe_to_backend_map(struct radeon_device *rdev, num_shader_engines = 1; if (num_shader_engines > rdev->config.cayman.max_shader_engines) num_shader_engines = rdev->config.cayman.max_shader_engines; - if (num_backends_per_asic > num_shader_engines) + if (num_backends_per_asic < num_shader_engines) num_backends_per_asic = num_shader_engines; if (num_backends_per_asic > (rdev->config.cayman.max_backends_per_se * num_shader_engines)) num_backends_per_asic = rdev->config.cayman.max_backends_per_se * num_shader_engines; @@ -829,7 +829,7 @@ static void cayman_gpu_init(struct radeon_device *rdev) rdev->config.cayman.tile_config |= ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4; rdev->config.cayman.tile_config |= - (gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT; + ((gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT) << 8; rdev->config.cayman.tile_config |= ((gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT) << 12; @@ -931,6 +931,10 @@ static void cayman_gpu_init(struct radeon_device *rdev) WREG32(CB_PERF_CTR3_SEL_0, 0); WREG32(CB_PERF_CTR3_SEL_1, 0); + tmp = RREG32(HDP_MISC_CNTL); + tmp |= HDP_FLUSH_INVALIDATE_CACHE; + WREG32(HDP_MISC_CNTL, tmp); + hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL); WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl); @@ -1383,14 +1387,12 @@ static int cayman_startup(struct radeon_device *rdev) return r; cayman_gpu_init(rdev); -#if 0 - r = cayman_blit_init(rdev); + r = evergreen_blit_init(rdev); if (r) { - cayman_blit_fini(rdev); + evergreen_blit_fini(rdev); rdev->asic->copy = NULL; dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r); } -#endif /* allocate wb buffer */ r = radeon_wb_init(rdev); @@ -1448,7 +1450,7 @@ int cayman_resume(struct radeon_device *rdev) int cayman_suspend(struct radeon_device *rdev) { - /* int r; */ + int r; /* FIXME: we should wait for ring to be empty */ cayman_cp_enable(rdev, false); @@ -1457,14 +1459,13 @@ int cayman_suspend(struct radeon_device *rdev) radeon_wb_disable(rdev); cayman_pcie_gart_disable(rdev); -#if 0 /* unpin shaders bo */ r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); if (likely(r == 0)) { radeon_bo_unpin(rdev->r600_blit.shader_obj); radeon_bo_unreserve(rdev->r600_blit.shader_obj); } -#endif + return 0; } @@ -1576,7 +1577,7 @@ int cayman_init(struct radeon_device *rdev) void cayman_fini(struct radeon_device *rdev) { - /* cayman_blit_fini(rdev); */ + evergreen_blit_fini(rdev); cayman_cp_fini(rdev); r600_irq_fini(rdev); radeon_wb_fini(rdev); diff --git a/drivers/gpu/drm/radeon/nid.h b/drivers/gpu/drm/radeon/nid.h index 0f9a08b53fb..9736746da2d 100644 --- a/drivers/gpu/drm/radeon/nid.h +++ b/drivers/gpu/drm/radeon/nid.h @@ -136,6 +136,8 @@ #define HDP_NONSURFACE_INFO 0x2C08 #define HDP_NONSURFACE_SIZE 0x2C0C #define HDP_ADDR_CONFIG 0x2F48 +#define HDP_MISC_CNTL 0x2F4C +#define HDP_FLUSH_INVALIDATE_CACHE (1 << 0) #define CC_SYS_RB_BACKEND_DISABLE 0x3F88 #define GC_USER_SYS_RB_BACKEND_DISABLE 0x3F8C @@ -351,7 +353,7 @@ #define MULTI_GPU_TILE_SIZE_MASK 0x03000000 #define MULTI_GPU_TILE_SIZE_SHIFT 24 #define ROW_SIZE(x) ((x) << 28) -#define ROW_SIZE_MASK 0x30000007 +#define ROW_SIZE_MASK 0x30000000 #define ROW_SIZE_SHIFT 28 #define NUM_LOWER_PIPES(x) ((x) << 30) #define NUM_LOWER_PIPES_MASK 0x40000000 diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 6f27593901c..d74d4d71437 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -87,6 +87,10 @@ MODULE_FIRMWARE("radeon/CYPRESS_rlc.bin"); MODULE_FIRMWARE("radeon/PALM_pfp.bin"); MODULE_FIRMWARE("radeon/PALM_me.bin"); MODULE_FIRMWARE("radeon/SUMO_rlc.bin"); +MODULE_FIRMWARE("radeon/SUMO_pfp.bin"); +MODULE_FIRMWARE("radeon/SUMO_me.bin"); +MODULE_FIRMWARE("radeon/SUMO2_pfp.bin"); +MODULE_FIRMWARE("radeon/SUMO2_me.bin"); int r600_debugfs_mc_info_init(struct radeon_device *rdev); @@ -2024,6 +2028,14 @@ int r600_init_microcode(struct radeon_device *rdev) chip_name = "PALM"; rlc_chip_name = "SUMO"; break; + case CHIP_SUMO: + chip_name = "SUMO"; + rlc_chip_name = "SUMO"; + break; + case CHIP_SUMO2: + chip_name = "SUMO2"; + rlc_chip_name = "SUMO"; + break; default: BUG(); } diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index fd18be9871a..909bda8dd55 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -71,20 +71,21 @@ struct r600_cs_track { u64 db_bo_mc; }; -#define FMT_8_BIT(fmt, vc) [fmt] = { 1, 1, 1, vc } -#define FMT_16_BIT(fmt, vc) [fmt] = { 1, 1, 2, vc } -#define FMT_24_BIT(fmt) [fmt] = { 1, 1, 3, 0 } -#define FMT_32_BIT(fmt, vc) [fmt] = { 1, 1, 4, vc } -#define FMT_48_BIT(fmt) [fmt] = { 1, 1, 6, 0 } -#define FMT_64_BIT(fmt, vc) [fmt] = { 1, 1, 8, vc } -#define FMT_96_BIT(fmt) [fmt] = { 1, 1, 12, 0 } -#define FMT_128_BIT(fmt, vc) [fmt] = { 1, 1, 16, vc } +#define FMT_8_BIT(fmt, vc) [fmt] = { 1, 1, 1, vc, CHIP_R600 } +#define FMT_16_BIT(fmt, vc) [fmt] = { 1, 1, 2, vc, CHIP_R600 } +#define FMT_24_BIT(fmt) [fmt] = { 1, 1, 3, 0, CHIP_R600 } +#define FMT_32_BIT(fmt, vc) [fmt] = { 1, 1, 4, vc, CHIP_R600 } +#define FMT_48_BIT(fmt) [fmt] = { 1, 1, 6, 0, CHIP_R600 } +#define FMT_64_BIT(fmt, vc) [fmt] = { 1, 1, 8, vc, CHIP_R600 } +#define FMT_96_BIT(fmt) [fmt] = { 1, 1, 12, 0, CHIP_R600 } +#define FMT_128_BIT(fmt, vc) [fmt] = { 1, 1, 16,vc, CHIP_R600 } struct gpu_formats { unsigned blockwidth; unsigned blockheight; unsigned blocksize; unsigned valid_color; + enum radeon_family min_family; }; static const struct gpu_formats color_formats_table[] = { @@ -154,7 +155,11 @@ static const struct gpu_formats color_formats_table[] = { [V_038004_FMT_BC3] = { 4, 4, 16, 0 }, [V_038004_FMT_BC4] = { 4, 4, 8, 0 }, [V_038004_FMT_BC5] = { 4, 4, 16, 0}, + [V_038004_FMT_BC6] = { 4, 4, 16, 0, CHIP_CEDAR}, /* Evergreen-only */ + [V_038004_FMT_BC7] = { 4, 4, 16, 0, CHIP_CEDAR}, /* Evergreen-only */ + /* The other Evergreen formats */ + [V_038004_FMT_32_AS_32_32_32_32] = { 1, 1, 4, 0, CHIP_CEDAR}, }; static inline bool fmt_is_valid_color(u32 format) @@ -168,11 +173,14 @@ static inline bool fmt_is_valid_color(u32 format) return false; } -static inline bool fmt_is_valid_texture(u32 format) +static inline bool fmt_is_valid_texture(u32 format, enum radeon_family family) { if (format >= ARRAY_SIZE(color_formats_table)) return false; + if (family < color_formats_table[format].min_family) + return false; + if (color_formats_table[format].blockwidth > 0) return true; @@ -1325,7 +1333,7 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 i return -EINVAL; } format = G_038004_DATA_FORMAT(word1); - if (!fmt_is_valid_texture(format)) { + if (!fmt_is_valid_texture(format, p->family)) { dev_warn(p->dev, "%s:%d texture invalid format %d\n", __func__, __LINE__, format); return -EINVAL; diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index b2b944bcd05..f140a0d5cb5 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -1309,6 +1309,9 @@ #define V_038004_FMT_BC3 0x00000033 #define V_038004_FMT_BC4 0x00000034 #define V_038004_FMT_BC5 0x00000035 +#define V_038004_FMT_BC6 0x00000036 +#define V_038004_FMT_BC7 0x00000037 +#define V_038004_FMT_32_AS_32_32_32_32 0x00000038 #define R_038010_SQ_TEX_RESOURCE_WORD4_0 0x038010 #define S_038010_FORMAT_COMP_X(x) (((x) & 0x3) << 0) #define G_038010_FORMAT_COMP_X(x) (((x) >> 0) & 0x3) diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index ca576191d05..9bd162fc9b0 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -782,6 +782,7 @@ static struct radeon_asic evergreen_asic = { .hpd_fini = &evergreen_hpd_fini, .hpd_sense = &evergreen_hpd_sense, .hpd_set_polarity = &evergreen_hpd_set_polarity, + .ioctl_wait_idle = r600_ioctl_wait_idle, .gui_idle = &r600_gui_idle, .pm_misc = &evergreen_pm_misc, .pm_prepare = &evergreen_pm_prepare, @@ -828,6 +829,7 @@ static struct radeon_asic sumo_asic = { .hpd_fini = &evergreen_hpd_fini, .hpd_sense = &evergreen_hpd_sense, .hpd_set_polarity = &evergreen_hpd_set_polarity, + .ioctl_wait_idle = r600_ioctl_wait_idle, .gui_idle = &r600_gui_idle, .pm_misc = &evergreen_pm_misc, .pm_prepare = &evergreen_pm_prepare, @@ -874,6 +876,7 @@ static struct radeon_asic btc_asic = { .hpd_fini = &evergreen_hpd_fini, .hpd_sense = &evergreen_hpd_sense, .hpd_set_polarity = &evergreen_hpd_set_polarity, + .ioctl_wait_idle = r600_ioctl_wait_idle, .gui_idle = &r600_gui_idle, .pm_misc = &evergreen_pm_misc, .pm_prepare = &evergreen_pm_prepare, @@ -903,9 +906,9 @@ static struct radeon_asic cayman_asic = { .get_vblank_counter = &evergreen_get_vblank_counter, .fence_ring_emit = &r600_fence_ring_emit, .cs_parse = &evergreen_cs_parse, - .copy_blit = NULL, - .copy_dma = NULL, - .copy = NULL, + .copy_blit = &evergreen_copy_blit, + .copy_dma = &evergreen_copy_blit, + .copy = &evergreen_copy_blit, .get_engine_clock = &radeon_atom_get_engine_clock, .set_engine_clock = &radeon_atom_set_engine_clock, .get_memory_clock = &radeon_atom_get_memory_clock, @@ -920,6 +923,7 @@ static struct radeon_asic cayman_asic = { .hpd_fini = &evergreen_hpd_fini, .hpd_sense = &evergreen_hpd_sense, .hpd_set_polarity = &evergreen_hpd_set_polarity, + .ioctl_wait_idle = r600_ioctl_wait_idle, .gui_idle = &r600_gui_idle, .pm_misc = &evergreen_pm_misc, .pm_prepare = &evergreen_pm_prepare, @@ -1016,6 +1020,8 @@ int radeon_asic_init(struct radeon_device *rdev) rdev->asic = &evergreen_asic; break; case CHIP_PALM: + case CHIP_SUMO: + case CHIP_SUMO2: rdev->asic = &sumo_asic; break; case CHIP_BARTS: diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 8caf546c8e9..5b991f7c6e2 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -505,12 +505,18 @@ static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rde * DDC_VGA = RADEON_GPIO_VGA_DDC * DDC_LCD = RADEON_GPIOPAD_MASK * DDC_GPIO = RADEON_MDGPIO_MASK - * r1xx/r2xx + * r1xx * DDC_MONID = RADEON_GPIO_MONID * DDC_CRT2 = RADEON_GPIO_CRT2_DDC - * r3xx + * r200 * DDC_MONID = RADEON_GPIO_MONID * DDC_CRT2 = RADEON_GPIO_DVI_DDC + * r300/r350 + * DDC_MONID = RADEON_GPIO_DVI_DDC + * DDC_CRT2 = RADEON_GPIO_DVI_DDC + * rv2xx/rv3xx + * DDC_MONID = RADEON_GPIO_MONID + * DDC_CRT2 = RADEON_GPIO_MONID * rs3xx/rs4xx * DDC_MONID = RADEON_GPIOPAD_MASK * DDC_CRT2 = RADEON_GPIO_MONID @@ -537,17 +543,26 @@ static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rde rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480) ddc_line = RADEON_GPIOPAD_MASK; - else + else if (rdev->family == CHIP_R300 || + rdev->family == CHIP_R350) { + ddc_line = RADEON_GPIO_DVI_DDC; + ddc = DDC_DVI; + } else ddc_line = RADEON_GPIO_MONID; break; case DDC_CRT2: - if (rdev->family == CHIP_RS300 || - rdev->family == CHIP_RS400 || - rdev->family == CHIP_RS480) - ddc_line = RADEON_GPIO_MONID; - else if (rdev->family >= CHIP_R300) { + if (rdev->family == CHIP_R200 || + rdev->family == CHIP_R300 || + rdev->family == CHIP_R350) { ddc_line = RADEON_GPIO_DVI_DDC; ddc = DDC_DVI; + } else if (rdev->family == CHIP_RS300 || + rdev->family == CHIP_RS400 || + rdev->family == CHIP_RS480) + ddc_line = RADEON_GPIO_MONID; + else if (rdev->family >= CHIP_RV350) { + ddc_line = RADEON_GPIO_MONID; + ddc = DDC_MONID; } else ddc_line = RADEON_GPIO_CRT2_DDC; break; @@ -709,26 +724,42 @@ void radeon_combios_i2c_init(struct radeon_device *rdev) struct drm_device *dev = rdev->ddev; struct radeon_i2c_bus_rec i2c; + /* actual hw pads + * r1xx/rs2xx/rs3xx + * 0x60, 0x64, 0x68, 0x6c, gpiopads, mm + * r200 + * 0x60, 0x64, 0x68, mm + * r300/r350 + * 0x60, 0x64, mm + * rv2xx/rv3xx/rs4xx + * 0x60, 0x64, 0x68, gpiopads, mm + */ + /* 0x60 */ i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); rdev->i2c_bus[0] = radeon_i2c_create(dev, &i2c, "DVI_DDC"); - + /* 0x64 */ i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); rdev->i2c_bus[1] = radeon_i2c_create(dev, &i2c, "VGA_DDC"); + /* mm i2c */ i2c.valid = true; i2c.hw_capable = true; i2c.mm_i2c = true; i2c.i2c_id = 0xa0; rdev->i2c_bus[2] = radeon_i2c_create(dev, &i2c, "MM_I2C"); - if (rdev->family == CHIP_RS300 || - rdev->family == CHIP_RS400 || - rdev->family == CHIP_RS480) { + if (rdev->family == CHIP_R300 || + rdev->family == CHIP_R350) { + /* only 2 sw i2c pads */ + } else if (rdev->family == CHIP_RS300 || + rdev->family == CHIP_RS400 || + rdev->family == CHIP_RS480) { u16 offset; u8 id, blocks, clk, data; int i; + /* 0x68 */ i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0); rdev->i2c_bus[3] = radeon_i2c_create(dev, &i2c, "MONID"); @@ -740,6 +771,7 @@ void radeon_combios_i2c_init(struct radeon_device *rdev) if (id == 136) { clk = RBIOS8(offset + 3 + (i * 5) + 3); data = RBIOS8(offset + 3 + (i * 5) + 4); + /* gpiopad */ i2c = combios_setup_i2c_bus(rdev, DDC_MONID, (1 << clk), (1 << data)); rdev->i2c_bus[4] = radeon_i2c_create(dev, &i2c, "GPIOPAD_MASK"); @@ -747,14 +779,15 @@ void radeon_combios_i2c_init(struct radeon_device *rdev) } } } - - } else if (rdev->family >= CHIP_R300) { + } else if (rdev->family >= CHIP_R200) { + /* 0x68 */ i2c = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0); rdev->i2c_bus[3] = radeon_i2c_create(dev, &i2c, "MONID"); } else { + /* 0x68 */ i2c = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0); rdev->i2c_bus[3] = radeon_i2c_create(dev, &i2c, "MONID"); - + /* 0x6c */ i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0); rdev->i2c_bus[4] = radeon_i2c_create(dev, &i2c, "CRT2_DDC"); } @@ -2504,6 +2537,12 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) return true; } +static const char *thermal_controller_names[] = { + "NONE", + "lm63", + "adm1032", +}; + void radeon_combios_get_power_modes(struct radeon_device *rdev) { struct drm_device *dev = rdev->ddev; @@ -2524,6 +2563,54 @@ void radeon_combios_get_power_modes(struct radeon_device *rdev) return; } + /* check for a thermal chip */ + offset = combios_get_table_offset(dev, COMBIOS_OVERDRIVE_INFO_TABLE); + if (offset) { + u8 thermal_controller = 0, gpio = 0, i2c_addr = 0, clk_bit = 0, data_bit = 0; + struct radeon_i2c_bus_rec i2c_bus; + + rev = RBIOS8(offset); + + if (rev == 0) { + thermal_controller = RBIOS8(offset + 3); + gpio = RBIOS8(offset + 4) & 0x3f; + i2c_addr = RBIOS8(offset + 5); + } else if (rev == 1) { + thermal_controller = RBIOS8(offset + 4); + gpio = RBIOS8(offset + 5) & 0x3f; + i2c_addr = RBIOS8(offset + 6); + } else if (rev == 2) { + thermal_controller = RBIOS8(offset + 4); + gpio = RBIOS8(offset + 5) & 0x3f; + i2c_addr = RBIOS8(offset + 6); + clk_bit = RBIOS8(offset + 0xa); + data_bit = RBIOS8(offset + 0xb); + } + if ((thermal_controller > 0) && (thermal_controller < 3)) { + DRM_INFO("Possible %s thermal controller at 0x%02x\n", + thermal_controller_names[thermal_controller], + i2c_addr >> 1); + if (gpio == DDC_LCD) { + /* MM i2c */ + i2c_bus.valid = true; + i2c_bus.hw_capable = true; + i2c_bus.mm_i2c = true; + i2c_bus.i2c_id = 0xa0; + } else if (gpio == DDC_GPIO) + i2c_bus = combios_setup_i2c_bus(rdev, gpio, 1 << clk_bit, 1 << data_bit); + else + i2c_bus = combios_setup_i2c_bus(rdev, gpio, 0, 0); + rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); + if (rdev->pm.i2c_bus) { + struct i2c_board_info info = { }; + const char *name = thermal_controller_names[thermal_controller]; + info.addr = i2c_addr >> 1; + strlcpy(info.type, name, sizeof(info.type)); + i2c_new_device(&rdev->pm.i2c_bus->adapter, &info); + } + } + } + if (rdev->flags & RADEON_IS_MOBILITY) { offset = combios_get_table_offset(dev, COMBIOS_POWERPLAY_INFO_TABLE); if (offset) { diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 5f45fa12bb8..ee1dccb3fec 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -50,20 +50,21 @@ void radeon_connector_hotplug(struct drm_connector *connector) struct radeon_device *rdev = dev->dev_private; struct radeon_connector *radeon_connector = to_radeon_connector(connector); - if (radeon_connector->hpd.hpd != RADEON_HPD_NONE) - radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); - - if ((connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) || - (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) { - if ((radeon_dp_getsinktype(radeon_connector) == CONNECTOR_OBJECT_ID_DISPLAYPORT) || - (radeon_dp_getsinktype(radeon_connector) == CONNECTOR_OBJECT_ID_eDP)) { - if (radeon_dp_needs_link_train(radeon_connector)) { - if (connector->encoder) - dp_link_train(connector->encoder, connector); - } - } - } + radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); + + /* powering up/down the eDP panel generates hpd events which + * can interfere with modesetting. + */ + if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) + return; + /* pre-r600 did not always have the hpd pins mapped accurately to connectors */ + if (rdev->family >= CHIP_R600) { + if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) + drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); + else + drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); + } } static void radeon_property_change_mode(struct drm_encoder *encoder) @@ -1054,23 +1055,124 @@ static int radeon_dp_get_modes(struct drm_connector *connector) int ret; if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { + struct drm_encoder *encoder; + struct drm_display_mode *mode; + if (!radeon_dig_connector->edp_on) atombios_set_edp_panel_power(connector, ATOM_TRANSMITTER_ACTION_POWER_ON); - } - ret = radeon_ddc_get_modes(radeon_connector); - if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { + ret = radeon_ddc_get_modes(radeon_connector); if (!radeon_dig_connector->edp_on) atombios_set_edp_panel_power(connector, ATOM_TRANSMITTER_ACTION_POWER_OFF); - } + + if (ret > 0) { + encoder = radeon_best_single_encoder(connector); + if (encoder) { + radeon_fixup_lvds_native_mode(encoder, connector); + /* add scaled modes */ + radeon_add_common_modes(encoder, connector); + } + return ret; + } + + encoder = radeon_best_single_encoder(connector); + if (!encoder) + return 0; + + /* we have no EDID modes */ + mode = radeon_fp_native_mode(encoder); + if (mode) { + ret = 1; + drm_mode_probed_add(connector, mode); + /* add the width/height from vbios tables if available */ + connector->display_info.width_mm = mode->width_mm; + connector->display_info.height_mm = mode->height_mm; + /* add scaled modes */ + radeon_add_common_modes(encoder, connector); + } + } else + ret = radeon_ddc_get_modes(radeon_connector); return ret; } +bool radeon_connector_encoder_is_dp_bridge(struct drm_connector *connector) +{ + struct drm_mode_object *obj; + struct drm_encoder *encoder; + struct radeon_encoder *radeon_encoder; + int i; + bool found = false; + + for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { + if (connector->encoder_ids[i] == 0) + break; + + obj = drm_mode_object_find(connector->dev, connector->encoder_ids[i], DRM_MODE_OBJECT_ENCODER); + if (!obj) + continue; + + encoder = obj_to_encoder(obj); + radeon_encoder = to_radeon_encoder(encoder); + + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_TRAVIS: + case ENCODER_OBJECT_ID_NUTMEG: + found = true; + break; + default: + break; + } + } + + return found; +} + +bool radeon_connector_encoder_is_hbr2(struct drm_connector *connector) +{ + struct drm_mode_object *obj; + struct drm_encoder *encoder; + struct radeon_encoder *radeon_encoder; + int i; + bool found = false; + + for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { + if (connector->encoder_ids[i] == 0) + break; + + obj = drm_mode_object_find(connector->dev, connector->encoder_ids[i], DRM_MODE_OBJECT_ENCODER); + if (!obj) + continue; + + encoder = obj_to_encoder(obj); + radeon_encoder = to_radeon_encoder(encoder); + if (radeon_encoder->caps & ATOM_ENCODER_CAP_RECORD_HBR2) + found = true; + } + + return found; +} + +bool radeon_connector_is_dp12_capable(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct radeon_device *rdev = dev->dev_private; + + if (ASIC_IS_DCE5(rdev) && + (rdev->clock.dp_extclk >= 53900) && + radeon_connector_encoder_is_hbr2(connector)) { + return true; + } + + return false; +} + static enum drm_connector_status radeon_dp_detect(struct drm_connector *connector, bool force) { + struct drm_device *dev = connector->dev; + struct radeon_device *rdev = dev->dev_private; struct radeon_connector *radeon_connector = to_radeon_connector(connector); enum drm_connector_status ret = connector_status_disconnected; struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv; @@ -1081,6 +1183,15 @@ radeon_dp_detect(struct drm_connector *connector, bool force) } if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { + struct drm_encoder *encoder = radeon_best_single_encoder(connector); + if (encoder) { + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_display_mode *native_mode = &radeon_encoder->native_mode; + + /* check if panel is valid */ + if (native_mode->hdisplay >= 320 && native_mode->vdisplay >= 240) + ret = connector_status_connected; + } /* eDP is always DP */ radeon_dig_connector->dp_sink_type = CONNECTOR_OBJECT_ID_DISPLAYPORT; if (!radeon_dig_connector->edp_on) @@ -1093,12 +1204,18 @@ radeon_dp_detect(struct drm_connector *connector, bool force) ATOM_TRANSMITTER_ACTION_POWER_OFF); } else { radeon_dig_connector->dp_sink_type = radeon_dp_getsinktype(radeon_connector); - if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) { - if (radeon_dp_getdpcd(radeon_connector)) - ret = connector_status_connected; + if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) { + ret = connector_status_connected; + if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) + radeon_dp_getdpcd(radeon_connector); } else { - if (radeon_ddc_probe(radeon_connector)) - ret = connector_status_connected; + if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) { + if (radeon_dp_getdpcd(radeon_connector)) + ret = connector_status_connected; + } else { + if (radeon_ddc_probe(radeon_connector)) + ret = connector_status_connected; + } } } @@ -1114,11 +1231,38 @@ static int radeon_dp_mode_valid(struct drm_connector *connector, /* XXX check mode bandwidth */ - if ((radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || - (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) - return radeon_dp_mode_valid_helper(radeon_connector, mode); - else + if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { + struct drm_encoder *encoder = radeon_best_single_encoder(connector); + + if ((mode->hdisplay < 320) || (mode->vdisplay < 240)) + return MODE_PANEL; + + if (encoder) { + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_display_mode *native_mode = &radeon_encoder->native_mode; + + /* AVIVO hardware supports downscaling modes larger than the panel + * to the panel size, but I'm not sure this is desirable. + */ + if ((mode->hdisplay > native_mode->hdisplay) || + (mode->vdisplay > native_mode->vdisplay)) + return MODE_PANEL; + + /* if scaling is disabled, block non-native modes */ + if (radeon_encoder->rmx_type == RMX_OFF) { + if ((mode->hdisplay != native_mode->hdisplay) || + (mode->vdisplay != native_mode->vdisplay)) + return MODE_PANEL; + } + } return MODE_OK; + } else { + if ((radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || + (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) + return radeon_dp_mode_valid_helper(connector, mode); + else + return MODE_OK; + } } struct drm_connector_helper_funcs radeon_dp_connector_helper_funcs = { @@ -1151,8 +1295,11 @@ radeon_add_atom_connector(struct drm_device *dev, struct drm_connector *connector; struct radeon_connector *radeon_connector; struct radeon_connector_atom_dig *radeon_dig_connector; + struct drm_encoder *encoder; + struct radeon_encoder *radeon_encoder; uint32_t subpixel_order = SubPixelNone; bool shared_ddc = false; + bool is_dp_bridge = false; if (connector_type == DRM_MODE_CONNECTOR_Unknown) return; @@ -1184,6 +1331,21 @@ radeon_add_atom_connector(struct drm_device *dev, } } + /* check if it's a dp bridge */ + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + radeon_encoder = to_radeon_encoder(encoder); + if (radeon_encoder->devices & supported_device) { + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_TRAVIS: + case ENCODER_OBJECT_ID_NUTMEG: + is_dp_bridge = true; + break; + default: + break; + } + } + } + radeon_connector = kzalloc(sizeof(struct radeon_connector), GFP_KERNEL); if (!radeon_connector) return; @@ -1201,61 +1363,39 @@ radeon_add_atom_connector(struct drm_device *dev, if (!radeon_connector->router_bus) DRM_ERROR("Failed to assign router i2c bus! Check dmesg for i2c errors.\n"); } - switch (connector_type) { - case DRM_MODE_CONNECTOR_VGA: - drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); - drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); - if (i2c_bus->valid) { - radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); - if (!radeon_connector->ddc_bus) - DRM_ERROR("VGA: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); - } - radeon_connector->dac_load_detect = true; - drm_connector_attach_property(&radeon_connector->base, - rdev->mode_info.load_detect_property, - 1); - /* no HPD on analog connectors */ - radeon_connector->hpd.hpd = RADEON_HPD_NONE; - connector->polled = DRM_CONNECTOR_POLL_CONNECT; - connector->interlace_allowed = true; - connector->doublescan_allowed = true; - break; - case DRM_MODE_CONNECTOR_DVIA: - drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); - drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); - if (i2c_bus->valid) { - radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); - if (!radeon_connector->ddc_bus) - DRM_ERROR("DVIA: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); - } - radeon_connector->dac_load_detect = true; - drm_connector_attach_property(&radeon_connector->base, - rdev->mode_info.load_detect_property, - 1); - /* no HPD on analog connectors */ - radeon_connector->hpd.hpd = RADEON_HPD_NONE; - connector->interlace_allowed = true; - connector->doublescan_allowed = true; - break; - case DRM_MODE_CONNECTOR_DVII: - case DRM_MODE_CONNECTOR_DVID: + + if (is_dp_bridge) { radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); if (!radeon_dig_connector) goto failed; radeon_dig_connector->igp_lane_info = igp_lane_info; radeon_connector->con_priv = radeon_dig_connector; - drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); - drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); + drm_connector_init(dev, &radeon_connector->base, &radeon_dp_connector_funcs, connector_type); + drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs); if (i2c_bus->valid) { + /* add DP i2c bus */ + if (connector_type == DRM_MODE_CONNECTOR_eDP) + radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "eDP-auxch"); + else + radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch"); + if (!radeon_dig_connector->dp_i2c_bus) + DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n"); radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); if (!radeon_connector->ddc_bus) - DRM_ERROR("DVI: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); + DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); } - subpixel_order = SubPixelHorizontalRGB; - drm_connector_attach_property(&radeon_connector->base, - rdev->mode_info.coherent_mode_property, - 1); - if (ASIC_IS_AVIVO(rdev)) { + switch (connector_type) { + case DRM_MODE_CONNECTOR_VGA: + case DRM_MODE_CONNECTOR_DVIA: + default: + connector->interlace_allowed = true; + connector->doublescan_allowed = true; + break; + case DRM_MODE_CONNECTOR_DVII: + case DRM_MODE_CONNECTOR_DVID: + case DRM_MODE_CONNECTOR_HDMIA: + case DRM_MODE_CONNECTOR_HDMIB: + case DRM_MODE_CONNECTOR_DisplayPort: drm_connector_attach_property(&radeon_connector->base, rdev->mode_info.underscan_property, UNDERSCAN_OFF); @@ -1265,131 +1405,234 @@ radeon_add_atom_connector(struct drm_device *dev, drm_connector_attach_property(&radeon_connector->base, rdev->mode_info.underscan_vborder_property, 0); + subpixel_order = SubPixelHorizontalRGB; + connector->interlace_allowed = true; + if (connector_type == DRM_MODE_CONNECTOR_HDMIB) + connector->doublescan_allowed = true; + else + connector->doublescan_allowed = false; + break; + case DRM_MODE_CONNECTOR_LVDS: + case DRM_MODE_CONNECTOR_eDP: + drm_connector_attach_property(&radeon_connector->base, + dev->mode_config.scaling_mode_property, + DRM_MODE_SCALE_FULLSCREEN); + subpixel_order = SubPixelHorizontalRGB; + connector->interlace_allowed = false; + connector->doublescan_allowed = false; + break; } - if (connector_type == DRM_MODE_CONNECTOR_DVII) { + } else { + switch (connector_type) { + case DRM_MODE_CONNECTOR_VGA: + drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); + drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); + if (i2c_bus->valid) { + radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); + if (!radeon_connector->ddc_bus) + DRM_ERROR("VGA: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); + } radeon_connector->dac_load_detect = true; drm_connector_attach_property(&radeon_connector->base, rdev->mode_info.load_detect_property, 1); - } - connector->interlace_allowed = true; - if (connector_type == DRM_MODE_CONNECTOR_DVII) + /* no HPD on analog connectors */ + radeon_connector->hpd.hpd = RADEON_HPD_NONE; + connector->polled = DRM_CONNECTOR_POLL_CONNECT; + connector->interlace_allowed = true; connector->doublescan_allowed = true; - else - connector->doublescan_allowed = false; - break; - case DRM_MODE_CONNECTOR_HDMIA: - case DRM_MODE_CONNECTOR_HDMIB: - radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); - if (!radeon_dig_connector) - goto failed; - radeon_dig_connector->igp_lane_info = igp_lane_info; - radeon_connector->con_priv = radeon_dig_connector; - drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); - drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); - if (i2c_bus->valid) { - radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); - if (!radeon_connector->ddc_bus) - DRM_ERROR("HDMI: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); - } - drm_connector_attach_property(&radeon_connector->base, - rdev->mode_info.coherent_mode_property, - 1); - if (ASIC_IS_AVIVO(rdev)) { + break; + case DRM_MODE_CONNECTOR_DVIA: + drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); + drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); + if (i2c_bus->valid) { + radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); + if (!radeon_connector->ddc_bus) + DRM_ERROR("DVIA: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); + } + radeon_connector->dac_load_detect = true; drm_connector_attach_property(&radeon_connector->base, - rdev->mode_info.underscan_property, - UNDERSCAN_OFF); + rdev->mode_info.load_detect_property, + 1); + /* no HPD on analog connectors */ + radeon_connector->hpd.hpd = RADEON_HPD_NONE; + connector->interlace_allowed = true; + connector->doublescan_allowed = true; + break; + case DRM_MODE_CONNECTOR_DVII: + case DRM_MODE_CONNECTOR_DVID: + radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); + if (!radeon_dig_connector) + goto failed; + radeon_dig_connector->igp_lane_info = igp_lane_info; + radeon_connector->con_priv = radeon_dig_connector; + drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); + drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); + if (i2c_bus->valid) { + radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); + if (!radeon_connector->ddc_bus) + DRM_ERROR("DVI: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); + } + subpixel_order = SubPixelHorizontalRGB; drm_connector_attach_property(&radeon_connector->base, - rdev->mode_info.underscan_hborder_property, - 0); + rdev->mode_info.coherent_mode_property, + 1); + if (ASIC_IS_AVIVO(rdev)) { + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.underscan_property, + UNDERSCAN_OFF); + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.underscan_hborder_property, + 0); + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.underscan_vborder_property, + 0); + } + if (connector_type == DRM_MODE_CONNECTOR_DVII) { + radeon_connector->dac_load_detect = true; + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.load_detect_property, + 1); + } + connector->interlace_allowed = true; + if (connector_type == DRM_MODE_CONNECTOR_DVII) + connector->doublescan_allowed = true; + else + connector->doublescan_allowed = false; + break; + case DRM_MODE_CONNECTOR_HDMIA: + case DRM_MODE_CONNECTOR_HDMIB: + radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); + if (!radeon_dig_connector) + goto failed; + radeon_dig_connector->igp_lane_info = igp_lane_info; + radeon_connector->con_priv = radeon_dig_connector; + drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); + drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); + if (i2c_bus->valid) { + radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); + if (!radeon_connector->ddc_bus) + DRM_ERROR("HDMI: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); + } drm_connector_attach_property(&radeon_connector->base, - rdev->mode_info.underscan_vborder_property, - 0); - } - subpixel_order = SubPixelHorizontalRGB; - connector->interlace_allowed = true; - if (connector_type == DRM_MODE_CONNECTOR_HDMIB) - connector->doublescan_allowed = true; - else - connector->doublescan_allowed = false; - break; - case DRM_MODE_CONNECTOR_DisplayPort: - case DRM_MODE_CONNECTOR_eDP: - radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); - if (!radeon_dig_connector) - goto failed; - radeon_dig_connector->igp_lane_info = igp_lane_info; - radeon_connector->con_priv = radeon_dig_connector; - drm_connector_init(dev, &radeon_connector->base, &radeon_dp_connector_funcs, connector_type); - drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs); - if (i2c_bus->valid) { - /* add DP i2c bus */ - if (connector_type == DRM_MODE_CONNECTOR_eDP) - radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "eDP-auxch"); + rdev->mode_info.coherent_mode_property, + 1); + if (ASIC_IS_AVIVO(rdev)) { + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.underscan_property, + UNDERSCAN_OFF); + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.underscan_hborder_property, + 0); + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.underscan_vborder_property, + 0); + } + subpixel_order = SubPixelHorizontalRGB; + connector->interlace_allowed = true; + if (connector_type == DRM_MODE_CONNECTOR_HDMIB) + connector->doublescan_allowed = true; else + connector->doublescan_allowed = false; + break; + case DRM_MODE_CONNECTOR_DisplayPort: + radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); + if (!radeon_dig_connector) + goto failed; + radeon_dig_connector->igp_lane_info = igp_lane_info; + radeon_connector->con_priv = radeon_dig_connector; + drm_connector_init(dev, &radeon_connector->base, &radeon_dp_connector_funcs, connector_type); + drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs); + if (i2c_bus->valid) { + /* add DP i2c bus */ radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch"); - if (!radeon_dig_connector->dp_i2c_bus) - DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n"); - radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); - if (!radeon_connector->ddc_bus) - DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); - } - subpixel_order = SubPixelHorizontalRGB; - drm_connector_attach_property(&radeon_connector->base, - rdev->mode_info.coherent_mode_property, - 1); - if (ASIC_IS_AVIVO(rdev)) { + if (!radeon_dig_connector->dp_i2c_bus) + DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n"); + radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); + if (!radeon_connector->ddc_bus) + DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); + } + subpixel_order = SubPixelHorizontalRGB; drm_connector_attach_property(&radeon_connector->base, - rdev->mode_info.underscan_property, - UNDERSCAN_OFF); + rdev->mode_info.coherent_mode_property, + 1); + if (ASIC_IS_AVIVO(rdev)) { + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.underscan_property, + UNDERSCAN_OFF); + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.underscan_hborder_property, + 0); + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.underscan_vborder_property, + 0); + } + connector->interlace_allowed = true; + /* in theory with a DP to VGA converter... */ + connector->doublescan_allowed = false; + break; + case DRM_MODE_CONNECTOR_eDP: + radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); + if (!radeon_dig_connector) + goto failed; + radeon_dig_connector->igp_lane_info = igp_lane_info; + radeon_connector->con_priv = radeon_dig_connector; + drm_connector_init(dev, &radeon_connector->base, &radeon_dp_connector_funcs, connector_type); + drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs); + if (i2c_bus->valid) { + /* add DP i2c bus */ + radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "eDP-auxch"); + if (!radeon_dig_connector->dp_i2c_bus) + DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n"); + radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); + if (!radeon_connector->ddc_bus) + DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); + } drm_connector_attach_property(&radeon_connector->base, - rdev->mode_info.underscan_hborder_property, - 0); + dev->mode_config.scaling_mode_property, + DRM_MODE_SCALE_FULLSCREEN); + subpixel_order = SubPixelHorizontalRGB; + connector->interlace_allowed = false; + connector->doublescan_allowed = false; + break; + case DRM_MODE_CONNECTOR_SVIDEO: + case DRM_MODE_CONNECTOR_Composite: + case DRM_MODE_CONNECTOR_9PinDIN: + drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type); + drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs); + radeon_connector->dac_load_detect = true; drm_connector_attach_property(&radeon_connector->base, - rdev->mode_info.underscan_vborder_property, - 0); - } - connector->interlace_allowed = true; - /* in theory with a DP to VGA converter... */ - connector->doublescan_allowed = false; - break; - case DRM_MODE_CONNECTOR_SVIDEO: - case DRM_MODE_CONNECTOR_Composite: - case DRM_MODE_CONNECTOR_9PinDIN: - drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type); - drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs); - radeon_connector->dac_load_detect = true; - drm_connector_attach_property(&radeon_connector->base, - rdev->mode_info.load_detect_property, - 1); - drm_connector_attach_property(&radeon_connector->base, - rdev->mode_info.tv_std_property, - radeon_atombios_get_tv_info(rdev)); - /* no HPD on analog connectors */ - radeon_connector->hpd.hpd = RADEON_HPD_NONE; - connector->interlace_allowed = false; - connector->doublescan_allowed = false; - break; - case DRM_MODE_CONNECTOR_LVDS: - radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); - if (!radeon_dig_connector) - goto failed; - radeon_dig_connector->igp_lane_info = igp_lane_info; - radeon_connector->con_priv = radeon_dig_connector; - drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); - drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs); - if (i2c_bus->valid) { - radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); - if (!radeon_connector->ddc_bus) - DRM_ERROR("LVDS: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); + rdev->mode_info.load_detect_property, + 1); + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.tv_std_property, + radeon_atombios_get_tv_info(rdev)); + /* no HPD on analog connectors */ + radeon_connector->hpd.hpd = RADEON_HPD_NONE; + connector->interlace_allowed = false; + connector->doublescan_allowed = false; + break; + case DRM_MODE_CONNECTOR_LVDS: + radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); + if (!radeon_dig_connector) + goto failed; + radeon_dig_connector->igp_lane_info = igp_lane_info; + radeon_connector->con_priv = radeon_dig_connector; + drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); + drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs); + if (i2c_bus->valid) { + radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); + if (!radeon_connector->ddc_bus) + DRM_ERROR("LVDS: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); + } + drm_connector_attach_property(&radeon_connector->base, + dev->mode_config.scaling_mode_property, + DRM_MODE_SCALE_FULLSCREEN); + subpixel_order = SubPixelHorizontalRGB; + connector->interlace_allowed = false; + connector->doublescan_allowed = false; + break; } - drm_connector_attach_property(&radeon_connector->base, - dev->mode_config.scaling_mode_property, - DRM_MODE_SCALE_FULLSCREEN); - subpixel_order = SubPixelHorizontalRGB; - connector->interlace_allowed = false; - connector->doublescan_allowed = false; - break; } if (radeon_connector->hpd.hpd == RADEON_HPD_NONE) { diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index 8c191694187..fae00c0d75a 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -228,6 +228,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) parser.filp = filp; parser.rdev = rdev; parser.dev = rdev->dev; + parser.family = rdev->family; r = radeon_cs_parser_init(&parser, data); if (r) { DRM_ERROR("Failed to initialize parser !\n"); diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 890217e678d..e680501c78e 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -82,6 +82,8 @@ static const char radeon_family_name[][16] = { "CYPRESS", "HEMLOCK", "PALM", + "SUMO", + "SUMO2", "BARTS", "TURKS", "CAICOS", @@ -752,6 +754,7 @@ int radeon_device_init(struct radeon_device *rdev, dma_bits = rdev->need_dma32 ? 32 : 40; r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(dma_bits)); if (r) { + rdev->need_dma32 = true; printk(KERN_WARNING "radeon: No suitable DMA available.\n"); } @@ -923,6 +926,9 @@ int radeon_resume_kms(struct drm_device *dev) radeon_fbdev_set_suspend(rdev, 0); console_unlock(); + /* init dig PHYs */ + if (rdev->is_atom_bios) + radeon_atom_encoder_init(rdev); /* reset hpd state */ radeon_hpd_init(rdev); /* blat the mode back in */ diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index bdbab5c43bd..292f73f0ddb 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -264,6 +264,8 @@ static void radeon_unpin_work_func(struct work_struct *__work) radeon_bo_unreserve(work->old_rbo); } else DRM_ERROR("failed to reserve buffer after flip\n"); + + drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base); kfree(work); } @@ -371,6 +373,8 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc, 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; INIT_WORK(&work->work, radeon_unpin_work_func); @@ -378,12 +382,9 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc, /* We borrow the event spin lock for protecting unpin_work */ spin_lock_irqsave(&dev->event_lock, flags); if (radeon_crtc->unpin_work) { - spin_unlock_irqrestore(&dev->event_lock, flags); - kfree(work); - radeon_fence_unref(&fence); - DRM_DEBUG_DRIVER("flip queue: crtc already busy\n"); - return -EBUSY; + r = -EBUSY; + goto unlock_free; } radeon_crtc->unpin_work = work; radeon_crtc->deferred_flip_completion = 0; @@ -497,6 +498,8 @@ pflip_cleanup1: pflip_cleanup: spin_lock_irqsave(&dev->event_lock, flags); radeon_crtc->unpin_work = NULL; +unlock_free: + drm_gem_object_unreference_unlocked(old_radeon_fb->obj); spin_unlock_irqrestore(&dev->event_lock, flags); radeon_fence_unref(&fence); kfree(work); @@ -1087,8 +1090,9 @@ void radeon_compute_pll_legacy(struct radeon_pll *pll, *frac_fb_div_p = best_frac_feedback_div; *ref_div_p = best_ref_div; *post_div_p = best_post_div; - DRM_DEBUG_KMS("%d %d, pll dividers - fb: %d.%d ref: %d, post %d\n", - freq, best_freq / 1000, best_feedback_div, best_frac_feedback_div, + DRM_DEBUG_KMS("%lld %d, pll dividers - fb: %d.%d ref: %d, post %d\n", + (long long)freq, + best_freq / 1000, best_feedback_div, best_frac_feedback_div, best_ref_div, best_post_div); } @@ -1344,6 +1348,11 @@ int radeon_modeset_init(struct radeon_device *rdev) if (!ret) { return ret; } + + /* init dig PHYs */ + if (rdev->is_atom_bios) + radeon_atom_encoder_init(rdev); + /* initialize hpd */ radeon_hpd_init(rdev); diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 63d2de8771d..73dfbe8e5f9 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -50,9 +50,10 @@ * 2.7.0 - fixups for r600 2D tiling support. (no external ABI change), add eg dyn gpr regs * 2.8.0 - pageflip support, r500 US_FORMAT regs. r500 ARGB2101010 colorbuf, r300->r500 CMASK, clock crystal query * 2.9.0 - r600 tiling (s3tc,rgtc) working, SET_PREDICATION packet 3 on r600 + eg, backend query + * 2.10.0 - fusion 2D tiling */ #define KMS_DRIVER_MAJOR 2 -#define KMS_DRIVER_MINOR 9 +#define KMS_DRIVER_MINOR 10 #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); @@ -112,7 +113,7 @@ int radeon_benchmarking = 0; int radeon_testing = 0; int radeon_connector_table = 0; int radeon_tv = 1; -int radeon_audio = 1; +int radeon_audio = 0; int radeon_disp_priority = 0; int radeon_hw_i2c = 0; int radeon_pcie_gen2 = 0; @@ -150,7 +151,7 @@ module_param_named(connector_table, radeon_connector_table, int, 0444); MODULE_PARM_DESC(tv, "TV enable (0 = disable)"); module_param_named(tv, radeon_tv, int, 0444); -MODULE_PARM_DESC(audio, "Audio enable (0 = disable)"); +MODULE_PARM_DESC(audio, "Audio enable (1 = enable)"); module_param_named(audio, radeon_audio, int, 0444); MODULE_PARM_DESC(disp_priority, "Display Priority (0 = auto, 1 = normal, 2 = high)"); diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index b4274883227..03f124d626c 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -229,6 +229,22 @@ radeon_get_connector_for_encoder(struct drm_encoder *encoder) return NULL; } +static struct drm_connector * +radeon_get_connector_for_encoder_init(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_connector *connector; + struct radeon_connector *radeon_connector; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + radeon_connector = to_radeon_connector(connector); + if (radeon_encoder->devices & radeon_connector->devices) + return connector; + } + return NULL; +} + struct drm_encoder *radeon_atom_get_external_encoder(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; @@ -250,6 +266,25 @@ struct drm_encoder *radeon_atom_get_external_encoder(struct drm_encoder *encoder return NULL; } +bool radeon_encoder_is_dp_bridge(struct drm_encoder *encoder) +{ + struct drm_encoder *other_encoder = radeon_atom_get_external_encoder(encoder); + + if (other_encoder) { + struct radeon_encoder *radeon_encoder = to_radeon_encoder(other_encoder); + + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_TRAVIS: + case ENCODER_OBJECT_ID_NUTMEG: + return true; + default: + return false; + } + } + + return false; +} + void radeon_panel_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *adjusted_mode) { @@ -621,6 +656,10 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) struct radeon_connector *radeon_connector; struct radeon_connector_atom_dig *dig_connector; + /* dp bridges are always DP */ + if (radeon_encoder_is_dp_bridge(encoder)) + return ATOM_ENCODER_MODE_DP; + connector = radeon_get_connector_for_encoder(encoder); if (!connector) { switch (radeon_encoder->encoder_id) { @@ -668,7 +707,6 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) return ATOM_ENCODER_MODE_LVDS; break; case DRM_MODE_CONNECTOR_DisplayPort: - case DRM_MODE_CONNECTOR_eDP: dig_connector = radeon_connector->con_priv; if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) @@ -682,6 +720,8 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) } else return ATOM_ENCODER_MODE_DVI; break; + case DRM_MODE_CONNECTOR_eDP: + return ATOM_ENCODER_MODE_DP; case DRM_MODE_CONNECTOR_DVIA: case DRM_MODE_CONNECTOR_VGA: return ATOM_ENCODER_MODE_CRT; @@ -747,7 +787,7 @@ union dig_encoder_control { }; void -atombios_dig_encoder_setup(struct drm_encoder *encoder, int action) +atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode) { struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; @@ -760,6 +800,7 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action) int dp_clock = 0; int dp_lane_count = 0; int hpd_id = RADEON_HPD_NONE; + int bpc = 8; if (connector) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); @@ -769,6 +810,7 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action) dp_clock = dig_connector->dp_clock; dp_lane_count = dig_connector->dp_lane_count; hpd_id = radeon_connector->hpd.hpd; + bpc = connector->display_info.bpc; } /* no dig encoder assigned */ @@ -791,7 +833,10 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action) args.v1.ucAction = action; args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); - args.v1.ucEncoderMode = atombios_get_encoder_mode(encoder); + if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE) + args.v3.ucPanelMode = panel_mode; + else + args.v1.ucEncoderMode = atombios_get_encoder_mode(encoder); if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) || (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST)) @@ -810,7 +855,27 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action) args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_5_40GHZ; } args.v4.acConfig.ucDigSel = dig->dig_encoder; - args.v4.ucBitPerColor = PANEL_8BIT_PER_COLOR; + switch (bpc) { + case 0: + args.v4.ucBitPerColor = PANEL_BPC_UNDEFINE; + break; + case 6: + args.v4.ucBitPerColor = PANEL_6BIT_PER_COLOR; + break; + case 8: + default: + args.v4.ucBitPerColor = PANEL_8BIT_PER_COLOR; + break; + case 10: + args.v4.ucBitPerColor = PANEL_10BIT_PER_COLOR; + break; + case 12: + args.v4.ucBitPerColor = PANEL_12BIT_PER_COLOR; + break; + case 16: + args.v4.ucBitPerColor = PANEL_16BIT_PER_COLOR; + break; + } if (hpd_id == RADEON_HPD_NONE) args.v4.ucHPD_ID = 0; else @@ -819,7 +884,27 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action) if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) && (dp_clock == 270000)) args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ; args.v3.acConfig.ucDigSel = dig->dig_encoder; - args.v3.ucBitPerColor = PANEL_8BIT_PER_COLOR; + switch (bpc) { + case 0: + args.v3.ucBitPerColor = PANEL_BPC_UNDEFINE; + break; + case 6: + args.v3.ucBitPerColor = PANEL_6BIT_PER_COLOR; + break; + case 8: + default: + args.v3.ucBitPerColor = PANEL_8BIT_PER_COLOR; + break; + case 10: + args.v3.ucBitPerColor = PANEL_10BIT_PER_COLOR; + break; + case 12: + args.v3.ucBitPerColor = PANEL_12BIT_PER_COLOR; + break; + case 16: + args.v3.ucBitPerColor = PANEL_16BIT_PER_COLOR; + break; + } } else { if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) && (dp_clock == 270000)) args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; @@ -859,7 +944,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t 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); + struct drm_connector *connector; union dig_transmitter_control args; int index = 0; uint8_t frev, crev; @@ -869,6 +954,16 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t int dp_lane_count = 0; int connector_object_id = 0; int igp_lane_info = 0; + int dig_encoder = dig->dig_encoder; + + if (action == ATOM_TRANSMITTER_ACTION_INIT) { + connector = radeon_get_connector_for_encoder_init(encoder); + /* just needed to avoid bailing in the encoder check. the encoder + * isn't used for init + */ + dig_encoder = 0; + } else + connector = radeon_get_connector_for_encoder(encoder); if (connector) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); @@ -883,7 +978,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t } /* no dig encoder assigned */ - if (dig->dig_encoder == -1) + if (dig_encoder == -1) return; if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) @@ -931,10 +1026,10 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t else args.v3.ucLaneNum = 4; - if (dig->linkb) { + if (dig->linkb) args.v3.acConfig.ucLinkSel = 1; + if (dig_encoder & 1) args.v3.acConfig.ucEncoderSel = 1; - } /* Select the PLL for the PHY * DP PHY should be clocked from external src if there is @@ -946,11 +1041,16 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t } if (ASIC_IS_DCE5(rdev)) { - if (is_dp && rdev->clock.dp_extclk) - args.v4.acConfig.ucRefClkSource = 3; /* external src */ - else + /* On DCE5 DCPLL usually generates the DP ref clock */ + if (is_dp) { + if (rdev->clock.dp_extclk) + args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_EXTCLK; + else + args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_DCPLL; + } else args.v4.acConfig.ucRefClkSource = pll_id; } else { + /* On DCE4, if there is an external clock, it generates the DP ref clock */ if (is_dp && rdev->clock.dp_extclk) args.v3.acConfig.ucRefClkSource = 2; /* external src */ else @@ -978,7 +1078,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t args.v3.acConfig.fDualLinkConnector = 1; } } else if (ASIC_IS_DCE32(rdev)) { - args.v2.acConfig.ucEncoderSel = dig->dig_encoder; + args.v2.acConfig.ucEncoderSel = dig_encoder; if (dig->linkb) args.v2.acConfig.ucLinkSel = 1; @@ -1005,7 +1105,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t } else { args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL; - if (dig->dig_encoder) + if (dig_encoder) args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER; else args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER; @@ -1047,7 +1147,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); } -void +bool atombios_set_edp_panel_power(struct drm_connector *connector, int action) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); @@ -1058,23 +1158,37 @@ atombios_set_edp_panel_power(struct drm_connector *connector, int action) uint8_t frev, crev; if (connector->connector_type != DRM_MODE_CONNECTOR_eDP) - return; + goto done; if (!ASIC_IS_DCE4(rdev)) - return; + goto done; if ((action != ATOM_TRANSMITTER_ACTION_POWER_ON) && (action != ATOM_TRANSMITTER_ACTION_POWER_OFF)) - return; + goto done; if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) - return; + goto done; memset(&args, 0, sizeof(args)); args.v1.ucAction = action; atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + + /* wait for the panel to power up */ + if (action == ATOM_TRANSMITTER_ACTION_POWER_ON) { + int i; + + for (i = 0; i < 300; i++) { + if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) + return true; + mdelay(1); + } + return false; + } +done: + return true; } union external_encoder_control { @@ -1092,13 +1206,19 @@ atombios_external_encoder_setup(struct drm_encoder *encoder, struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder *ext_radeon_encoder = to_radeon_encoder(ext_encoder); union external_encoder_control args; - struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); + struct drm_connector *connector; int index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl); u8 frev, crev; int dp_clock = 0; int dp_lane_count = 0; int connector_object_id = 0; u32 ext_enum = (ext_radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT; + int bpc = 8; + + if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT) + connector = radeon_get_connector_for_encoder_init(encoder); + else + connector = radeon_get_connector_for_encoder(encoder); if (connector) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); @@ -1109,6 +1229,7 @@ atombios_external_encoder_setup(struct drm_encoder *encoder, dp_lane_count = dig_connector->dp_lane_count; connector_object_id = (radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; + bpc = connector->display_info.bpc; } memset(&args, 0, sizeof(args)); @@ -1166,7 +1287,27 @@ atombios_external_encoder_setup(struct drm_encoder *encoder, args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER3; break; } - args.v3.sExtEncoder.ucBitPerColor = PANEL_8BIT_PER_COLOR; + switch (bpc) { + case 0: + args.v3.sExtEncoder.ucBitPerColor = PANEL_BPC_UNDEFINE; + break; + case 6: + args.v3.sExtEncoder.ucBitPerColor = PANEL_6BIT_PER_COLOR; + break; + case 8: + default: + args.v3.sExtEncoder.ucBitPerColor = PANEL_8BIT_PER_COLOR; + break; + case 10: + args.v3.sExtEncoder.ucBitPerColor = PANEL_10BIT_PER_COLOR; + break; + case 12: + args.v3.sExtEncoder.ucBitPerColor = PANEL_12BIT_PER_COLOR; + break; + case 16: + args.v3.sExtEncoder.ucBitPerColor = PANEL_16BIT_PER_COLOR; + break; + } break; default: DRM_ERROR("Unknown table version: %d, %d\n", frev, crev); @@ -1307,9 +1448,11 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode) ATOM_TRANSMITTER_ACTION_POWER_ON); radeon_dig_connector->edp_on = true; } - dp_link_train(encoder, connector); if (ASIC_IS_DCE4(rdev)) - atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON); + atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0); + radeon_dp_link_train(encoder, connector); + if (ASIC_IS_DCE4(rdev)) + atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0); } if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0); @@ -1322,7 +1465,7 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode) struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); if (ASIC_IS_DCE4(rdev)) - atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF); + atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0); if (connector && (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); @@ -1601,12 +1744,9 @@ static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder) /* DCE4/5 */ if (ASIC_IS_DCE4(rdev)) { dig = radeon_encoder->enc_priv; - if (ASIC_IS_DCE41(rdev)) { - if (dig->linkb) - return 1; - else - return 0; - } else { + if (ASIC_IS_DCE41(rdev)) + return radeon_crtc->crtc_id; + else { switch (radeon_encoder->encoder_id) { case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: if (dig->linkb) @@ -1662,6 +1802,34 @@ static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder) return 1; } +/* This only needs to be called once at startup */ +void +radeon_atom_encoder_init(struct radeon_device *rdev) +{ + struct drm_device *dev = rdev->ddev; + struct drm_encoder *encoder; + + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder); + + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0); + break; + default: + break; + } + + if (ext_encoder && ASIC_IS_DCE41(rdev)) + atombios_external_encoder_setup(encoder, ext_encoder, + EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT); + } +} + static void radeon_atom_encoder_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, @@ -1696,19 +1864,17 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, /* disable the transmitter */ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); /* setup and enable the encoder */ - atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP); + atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); - /* init and enable the transmitter */ - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0); + /* enable the transmitter */ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); } else { /* disable the encoder and transmitter */ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); - atombios_dig_encoder_setup(encoder, ATOM_DISABLE); + atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0); /* setup and enable the encoder and transmitter */ - atombios_dig_encoder_setup(encoder, ATOM_ENABLE); - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0); + atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0); atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); } @@ -1733,12 +1899,10 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, } if (ext_encoder) { - if (ASIC_IS_DCE41(rdev)) { - atombios_external_encoder_setup(encoder, ext_encoder, - EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT); + if (ASIC_IS_DCE41(rdev)) atombios_external_encoder_setup(encoder, ext_encoder, EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP); - } else + else atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE); } @@ -1845,8 +2009,9 @@ static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); - if (radeon_encoder->active_device & - (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) { + if ((radeon_encoder->active_device & + (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) || + radeon_encoder_is_dp_bridge(encoder)) { struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; if (dig) dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder); @@ -1855,11 +2020,17 @@ static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) radeon_atom_output_lock(encoder, true); radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); - /* select the clock/data port if it uses a router */ if (connector) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); + + /* select the clock/data port if it uses a router */ if (radeon_connector->router.cd_valid) radeon_router_select_cd_port(radeon_connector); + + /* turn eDP panel on for mode set */ + if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) + atombios_set_edp_panel_power(connector, + ATOM_TRANSMITTER_ACTION_POWER_ON); } /* this is needed for the pll/ss setup to work correctly in some cases */ @@ -1914,7 +2085,7 @@ static void radeon_atom_encoder_disable(struct drm_encoder *encoder) else { /* disable the encoder and transmitter */ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); - atombios_dig_encoder_setup(encoder, ATOM_DISABLE); + atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0); } break; case ENCODER_OBJECT_ID_INTERNAL_DDI: @@ -2116,8 +2287,6 @@ radeon_add_atom_encoder(struct drm_device *dev, } else { drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS); radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder); - if (ASIC_IS_AVIVO(rdev)) - radeon_encoder->underscan_type = UNDERSCAN_AUTO; } drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs); break; @@ -2150,8 +2319,6 @@ radeon_add_atom_encoder(struct drm_device *dev, } else { drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS); radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder); - if (ASIC_IS_AVIVO(rdev)) - radeon_encoder->underscan_type = UNDERSCAN_AUTO; } drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs); break; diff --git a/drivers/gpu/drm/radeon/radeon_family.h b/drivers/gpu/drm/radeon/radeon_family.h index 6f1d9e563e7..ec2f1ea84f8 100644 --- a/drivers/gpu/drm/radeon/radeon_family.h +++ b/drivers/gpu/drm/radeon/radeon_family.h @@ -81,6 +81,8 @@ enum radeon_family { CHIP_CYPRESS, CHIP_HEMLOCK, CHIP_PALM, + CHIP_SUMO, + CHIP_SUMO2, CHIP_BARTS, CHIP_TURKS, CHIP_CAICOS, diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c index 983cbac75af..781196db792 100644 --- a/drivers/gpu/drm/radeon/radeon_i2c.c +++ b/drivers/gpu/drm/radeon/radeon_i2c.c @@ -888,6 +888,7 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev, i2c->rec = *rec; i2c->adapter.owner = THIS_MODULE; + i2c->adapter.class = I2C_CLASS_DDC; i2c->dev = dev; i2c_set_adapdata(&i2c->adapter, i2c); if (rec->mm_i2c || @@ -947,6 +948,7 @@ struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev, i2c->rec = *rec; i2c->adapter.owner = THIS_MODULE; + i2c->adapter.class = I2C_CLASS_DDC; i2c->dev = dev; snprintf(i2c->adapter.name, sizeof(i2c->adapter.name), "Radeon aux bus %s", name); diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 9c57538231d..977a341266b 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -464,22 +464,27 @@ radeon_atombios_get_tv_info(struct radeon_device *rdev); extern struct drm_connector * radeon_get_connector_for_encoder(struct drm_encoder *encoder); +extern bool radeon_encoder_is_dp_bridge(struct drm_encoder *encoder); +extern bool radeon_connector_encoder_is_dp_bridge(struct drm_connector *connector); +extern bool radeon_connector_encoder_is_hbr2(struct drm_connector *connector); +extern bool radeon_connector_is_dp12_capable(struct drm_connector *connector); + extern void radeon_connector_hotplug(struct drm_connector *connector); -extern bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector); -extern int radeon_dp_mode_valid_helper(struct radeon_connector *radeon_connector, +extern int radeon_dp_mode_valid_helper(struct drm_connector *connector, struct drm_display_mode *mode); extern void radeon_dp_set_link_config(struct drm_connector *connector, struct drm_display_mode *mode); -extern void dp_link_train(struct drm_encoder *encoder, - struct drm_connector *connector); +extern void radeon_dp_link_train(struct drm_encoder *encoder, + struct drm_connector *connector); extern u8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector); extern bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector); -extern void atombios_dig_encoder_setup(struct drm_encoder *encoder, int action); +extern void atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode); +extern void radeon_atom_encoder_init(struct radeon_device *rdev); extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set); extern int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, - uint8_t write_byte, uint8_t *read_byte); + u8 write_byte, u8 *read_byte); extern void radeon_i2c_init(struct radeon_device *rdev); extern void radeon_i2c_fini(struct radeon_device *rdev); @@ -545,7 +550,7 @@ struct drm_encoder *radeon_encoder_legacy_tmds_ext_add(struct drm_device *dev, i extern void atombios_dvo_setup(struct drm_encoder *encoder, int action); extern void atombios_digital_setup(struct drm_encoder *encoder, int action); extern int atombios_get_encoder_mode(struct drm_encoder *encoder); -extern void atombios_set_edp_panel_power(struct drm_connector *connector, int action); +extern bool atombios_set_edp_panel_power(struct drm_connector *connector, int action); extern void radeon_encoder_set_active_device(struct drm_encoder *encoder); extern void radeon_crtc_load_lut(struct drm_crtc *crtc); diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 86eda1ea94d..aaa19dc418a 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -487,6 +487,7 @@ static int radeon_hwmon_init(struct radeon_device *rdev) case THERMAL_TYPE_RV6XX: case THERMAL_TYPE_RV770: case THERMAL_TYPE_EVERGREEN: + case THERMAL_TYPE_NI: case THERMAL_TYPE_SUMO: rdev->pm.int_hwmon_dev = hwmon_device_register(rdev->dev); if (IS_ERR(rdev->pm.int_hwmon_dev)) { diff --git a/drivers/gpu/drm/radeon/reg_srcs/r600 b/drivers/gpu/drm/radeon/reg_srcs/r600 index 92f1900dc7c..ea49752ee99 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/r600 +++ b/drivers/gpu/drm/radeon/reg_srcs/r600 @@ -758,6 +758,5 @@ r600 0x9400 0x00009714 VC_ENHANCE 0x00009830 DB_DEBUG 0x00009838 DB_WATERMARKS -0x00028D28 DB_SRESULTS_COMPARE_STATE0 0x00028D44 DB_ALPHA_TO_MASK 0x00009700 VC_CNTL |