Message ID | 20150625081103.GO14570@boom (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Looks fine to me. Reviewed-by: Antti Koskipää <antti.koskipaa@linux.intel.com> On 06/25/2015 11:11 AM, David Weinehall wrote: > This patch adds support for 0.85V VccIO on Skylake Y, > separate buffer translation tables for Skylake U, > and support for I_boost for the entries that needs this. > > Changes in v2: > * Refactored the code a bit to move all DDI signal level setup to > intel_ddi.c > > Issue: VIZ-5677 > Signed-off-by: David Weinehall <david.weinehall@linux.intel.com> > --- > drivers/gpu/drm/i915/i915_drv.h | 8 + > drivers/gpu/drm/i915/i915_reg.h | 12 + > drivers/gpu/drm/i915/intel_ddi.c | 507 ++++++++++++++++++++++++++++++--------- > drivers/gpu/drm/i915/intel_dp.c | 104 +------- > drivers/gpu/drm/i915/intel_drv.h | 3 +- > 5 files changed, 421 insertions(+), 213 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > index 491ef0cfcb0b..09a57a584f5f 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -2415,6 +2415,14 @@ struct drm_i915_cmd_table { > /* ULX machines are also considered ULT. */ > #define IS_HSW_ULX(dev) (INTEL_DEVID(dev) == 0x0A0E || \ > INTEL_DEVID(dev) == 0x0A1E) > +#define IS_SKL_ULT(dev) (INTEL_DEVID(dev) == 0x1906 || \ > + INTEL_DEVID(dev) == 0x1913 || \ > + INTEL_DEVID(dev) == 0x1916 || \ > + INTEL_DEVID(dev) == 0x1921 || \ > + INTEL_DEVID(dev) == 0x1926) > +#define IS_SKL_ULX(dev) (INTEL_DEVID(dev) == 0x190E || \ > + INTEL_DEVID(dev) == 0x1915 || \ > + INTEL_DEVID(dev) == 0x191E) > #define IS_PRELIMINARY_HW(intel_info) ((intel_info)->is_preliminary) > > #define SKL_REVID_A0 (0x0) > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h > index 0b979ad16d41..fb63ead2b8eb 100644 > --- a/drivers/gpu/drm/i915/i915_reg.h > +++ b/drivers/gpu/drm/i915/i915_reg.h > @@ -1382,6 +1382,18 @@ enum skl_disp_power_wells { > _PORT_TX_DW14_LN0_C) + \ > _BXT_LANE_OFFSET(lane)) > > +/* UAIMI scratch pad register 1 */ > +#define UAIMI_SPR1 0x4F074 > +/* SKL VccIO mask */ > +#define SKL_VCCIO_MASK 0x1 > +/* SKL balance leg register */ > +#define DISPIO_CR_TX_BMU_CR0 0x6C00C > +/* I_boost values */ > +#define BALANCE_LEG_SHIFT(port) (8+3*(port)) > +#define BALANCE_LEG_MASK(port) (7<<(8+3*(port))) > +/* Balance leg disable bits */ > +#define BALANCE_LEG_DISABLE_SHIFT 23 > + > /* > * Fence registers > */ > diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c > index 31b29e8781ac..08f89299b572 100644 > --- a/drivers/gpu/drm/i915/intel_ddi.c > +++ b/drivers/gpu/drm/i915/intel_ddi.c > @@ -31,6 +31,7 @@ > struct ddi_buf_trans { > u32 trans1; /* balance leg enable, de-emph level */ > u32 trans2; /* vref sel, vswing */ > + u8 i_boost; /* SKL: I_boost; valid: 0x0, 0x1, 0x3, 0x7 */ > }; > > /* HDMI/DVI modes ignore everything but the last 2 items. So we share > @@ -38,134 +39,213 @@ struct ddi_buf_trans { > * automatically adapt to HDMI connections as well > */ > static const struct ddi_buf_trans hsw_ddi_translations_dp[] = { > - { 0x00FFFFFF, 0x0006000E }, > - { 0x00D75FFF, 0x0005000A }, > - { 0x00C30FFF, 0x00040006 }, > - { 0x80AAAFFF, 0x000B0000 }, > - { 0x00FFFFFF, 0x0005000A }, > - { 0x00D75FFF, 0x000C0004 }, > - { 0x80C30FFF, 0x000B0000 }, > - { 0x00FFFFFF, 0x00040006 }, > - { 0x80D75FFF, 0x000B0000 }, > + { 0x00FFFFFF, 0x0006000E, 0x0 }, > + { 0x00D75FFF, 0x0005000A, 0x0 }, > + { 0x00C30FFF, 0x00040006, 0x0 }, > + { 0x80AAAFFF, 0x000B0000, 0x0 }, > + { 0x00FFFFFF, 0x0005000A, 0x0 }, > + { 0x00D75FFF, 0x000C0004, 0x0 }, > + { 0x80C30FFF, 0x000B0000, 0x0 }, > + { 0x00FFFFFF, 0x00040006, 0x0 }, > + { 0x80D75FFF, 0x000B0000, 0x0 }, > }; > > static const struct ddi_buf_trans hsw_ddi_translations_fdi[] = { > - { 0x00FFFFFF, 0x0007000E }, > - { 0x00D75FFF, 0x000F000A }, > - { 0x00C30FFF, 0x00060006 }, > - { 0x00AAAFFF, 0x001E0000 }, > - { 0x00FFFFFF, 0x000F000A }, > - { 0x00D75FFF, 0x00160004 }, > - { 0x00C30FFF, 0x001E0000 }, > - { 0x00FFFFFF, 0x00060006 }, > - { 0x00D75FFF, 0x001E0000 }, > + { 0x00FFFFFF, 0x0007000E, 0x0 }, > + { 0x00D75FFF, 0x000F000A, 0x0 }, > + { 0x00C30FFF, 0x00060006, 0x0 }, > + { 0x00AAAFFF, 0x001E0000, 0x0 }, > + { 0x00FFFFFF, 0x000F000A, 0x0 }, > + { 0x00D75FFF, 0x00160004, 0x0 }, > + { 0x00C30FFF, 0x001E0000, 0x0 }, > + { 0x00FFFFFF, 0x00060006, 0x0 }, > + { 0x00D75FFF, 0x001E0000, 0x0 }, > }; > > static const struct ddi_buf_trans hsw_ddi_translations_hdmi[] = { > /* Idx NT mV d T mV d db */ > - { 0x00FFFFFF, 0x0006000E }, /* 0: 400 400 0 */ > - { 0x00E79FFF, 0x000E000C }, /* 1: 400 500 2 */ > - { 0x00D75FFF, 0x0005000A }, /* 2: 400 600 3.5 */ > - { 0x00FFFFFF, 0x0005000A }, /* 3: 600 600 0 */ > - { 0x00E79FFF, 0x001D0007 }, /* 4: 600 750 2 */ > - { 0x00D75FFF, 0x000C0004 }, /* 5: 600 900 3.5 */ > - { 0x00FFFFFF, 0x00040006 }, /* 6: 800 800 0 */ > - { 0x80E79FFF, 0x00030002 }, /* 7: 800 1000 2 */ > - { 0x00FFFFFF, 0x00140005 }, /* 8: 850 850 0 */ > - { 0x00FFFFFF, 0x000C0004 }, /* 9: 900 900 0 */ > - { 0x00FFFFFF, 0x001C0003 }, /* 10: 950 950 0 */ > - { 0x80FFFFFF, 0x00030002 }, /* 11: 1000 1000 0 */ > + { 0x00FFFFFF, 0x0006000E, 0x0 },/* 0: 400 400 0 */ > + { 0x00E79FFF, 0x000E000C, 0x0 },/* 1: 400 500 2 */ > + { 0x00D75FFF, 0x0005000A, 0x0 },/* 2: 400 600 3.5 */ > + { 0x00FFFFFF, 0x0005000A, 0x0 },/* 3: 600 600 0 */ > + { 0x00E79FFF, 0x001D0007, 0x0 },/* 4: 600 750 2 */ > + { 0x00D75FFF, 0x000C0004, 0x0 },/* 5: 600 900 3.5 */ > + { 0x00FFFFFF, 0x00040006, 0x0 },/* 6: 800 800 0 */ > + { 0x80E79FFF, 0x00030002, 0x0 },/* 7: 800 1000 2 */ > + { 0x00FFFFFF, 0x00140005, 0x0 },/* 8: 850 850 0 */ > + { 0x00FFFFFF, 0x000C0004, 0x0 },/* 9: 900 900 0 */ > + { 0x00FFFFFF, 0x001C0003, 0x0 },/* 10: 950 950 0 */ > + { 0x80FFFFFF, 0x00030002, 0x0 },/* 11: 1000 1000 0 */ > }; > > static const struct ddi_buf_trans bdw_ddi_translations_edp[] = { > - { 0x00FFFFFF, 0x00000012 }, > - { 0x00EBAFFF, 0x00020011 }, > - { 0x00C71FFF, 0x0006000F }, > - { 0x00AAAFFF, 0x000E000A }, > - { 0x00FFFFFF, 0x00020011 }, > - { 0x00DB6FFF, 0x0005000F }, > - { 0x00BEEFFF, 0x000A000C }, > - { 0x00FFFFFF, 0x0005000F }, > - { 0x00DB6FFF, 0x000A000C }, > + { 0x00FFFFFF, 0x00000012, 0x0 }, > + { 0x00EBAFFF, 0x00020011, 0x0 }, > + { 0x00C71FFF, 0x0006000F, 0x0 }, > + { 0x00AAAFFF, 0x000E000A, 0x0 }, > + { 0x00FFFFFF, 0x00020011, 0x0 }, > + { 0x00DB6FFF, 0x0005000F, 0x0 }, > + { 0x00BEEFFF, 0x000A000C, 0x0 }, > + { 0x00FFFFFF, 0x0005000F, 0x0 }, > + { 0x00DB6FFF, 0x000A000C, 0x0 }, > }; > > static const struct ddi_buf_trans bdw_ddi_translations_dp[] = { > - { 0x00FFFFFF, 0x0007000E }, > - { 0x00D75FFF, 0x000E000A }, > - { 0x00BEFFFF, 0x00140006 }, > - { 0x80B2CFFF, 0x001B0002 }, > - { 0x00FFFFFF, 0x000E000A }, > - { 0x00DB6FFF, 0x00160005 }, > - { 0x80C71FFF, 0x001A0002 }, > - { 0x00F7DFFF, 0x00180004 }, > - { 0x80D75FFF, 0x001B0002 }, > + { 0x00FFFFFF, 0x0007000E, 0x0 }, > + { 0x00D75FFF, 0x000E000A, 0x0 }, > + { 0x00BEFFFF, 0x00140006, 0x0 }, > + { 0x80B2CFFF, 0x001B0002, 0x0 }, > + { 0x00FFFFFF, 0x000E000A, 0x0 }, > + { 0x00DB6FFF, 0x00160005, 0x0 }, > + { 0x80C71FFF, 0x001A0002, 0x0 }, > + { 0x00F7DFFF, 0x00180004, 0x0 }, > + { 0x80D75FFF, 0x001B0002, 0x0 }, > }; > > static const struct ddi_buf_trans bdw_ddi_translations_fdi[] = { > - { 0x00FFFFFF, 0x0001000E }, > - { 0x00D75FFF, 0x0004000A }, > - { 0x00C30FFF, 0x00070006 }, > - { 0x00AAAFFF, 0x000C0000 }, > - { 0x00FFFFFF, 0x0004000A }, > - { 0x00D75FFF, 0x00090004 }, > - { 0x00C30FFF, 0x000C0000 }, > - { 0x00FFFFFF, 0x00070006 }, > - { 0x00D75FFF, 0x000C0000 }, > + { 0x00FFFFFF, 0x0001000E, 0x0 }, > + { 0x00D75FFF, 0x0004000A, 0x0 }, > + { 0x00C30FFF, 0x00070006, 0x0 }, > + { 0x00AAAFFF, 0x000C0000, 0x0 }, > + { 0x00FFFFFF, 0x0004000A, 0x0 }, > + { 0x00D75FFF, 0x00090004, 0x0 }, > + { 0x00C30FFF, 0x000C0000, 0x0 }, > + { 0x00FFFFFF, 0x00070006, 0x0 }, > + { 0x00D75FFF, 0x000C0000, 0x0 }, > }; > > static const struct ddi_buf_trans bdw_ddi_translations_hdmi[] = { > /* Idx NT mV d T mV df db */ > - { 0x00FFFFFF, 0x0007000E }, /* 0: 400 400 0 */ > - { 0x00D75FFF, 0x000E000A }, /* 1: 400 600 3.5 */ > - { 0x00BEFFFF, 0x00140006 }, /* 2: 400 800 6 */ > - { 0x00FFFFFF, 0x0009000D }, /* 3: 450 450 0 */ > - { 0x00FFFFFF, 0x000E000A }, /* 4: 600 600 0 */ > - { 0x00D7FFFF, 0x00140006 }, /* 5: 600 800 2.5 */ > - { 0x80CB2FFF, 0x001B0002 }, /* 6: 600 1000 4.5 */ > - { 0x00FFFFFF, 0x00140006 }, /* 7: 800 800 0 */ > - { 0x80E79FFF, 0x001B0002 }, /* 8: 800 1000 2 */ > - { 0x80FFFFFF, 0x001B0002 }, /* 9: 1000 1000 0 */ > + { 0x00FFFFFF, 0x0007000E, 0x0 },/* 0: 400 400 0 */ > + { 0x00D75FFF, 0x000E000A, 0x0 },/* 1: 400 600 3.5 */ > + { 0x00BEFFFF, 0x00140006, 0x0 },/* 2: 400 800 6 */ > + { 0x00FFFFFF, 0x0009000D, 0x0 },/* 3: 450 450 0 */ > + { 0x00FFFFFF, 0x000E000A, 0x0 },/* 4: 600 600 0 */ > + { 0x00D7FFFF, 0x00140006, 0x0 },/* 5: 600 800 2.5 */ > + { 0x80CB2FFF, 0x001B0002, 0x0 },/* 6: 600 1000 4.5 */ > + { 0x00FFFFFF, 0x00140006, 0x0 },/* 7: 800 800 0 */ > + { 0x80E79FFF, 0x001B0002, 0x0 },/* 8: 800 1000 2 */ > + { 0x80FFFFFF, 0x001B0002, 0x0 },/* 9: 1000 1000 0 */ > }; > > +/* Skylake H, S, and Skylake Y with 0.95V VccIO */ > static const struct ddi_buf_trans skl_ddi_translations_dp[] = { > - { 0x00000018, 0x000000a2 }, > - { 0x00004014, 0x0000009B }, > - { 0x00006012, 0x00000088 }, > - { 0x00008010, 0x00000087 }, > - { 0x00000018, 0x0000009B }, > - { 0x00004014, 0x00000088 }, > - { 0x00006012, 0x00000087 }, > - { 0x00000018, 0x00000088 }, > - { 0x00004014, 0x00000087 }, > + { 0x00002016, 0x000000A0, 0x0 }, > + { 0x00005012, 0x0000009B, 0x0 }, > + { 0x00007011, 0x00000088, 0x0 }, > + { 0x00009010, 0x000000C7, 0x0 }, > + { 0x00002016, 0x0000009B, 0x0 }, > + { 0x00005012, 0x00000088, 0x0 }, > + { 0x00007011, 0x000000C7, 0x0 }, > + { 0x00002016, 0x000000DF, 0x0 }, > + { 0x00005012, 0x000000C7, 0x0 }, > }; > > -/* eDP 1.4 low vswing translation parameters */ > +/* Skylake U */ > +static const struct ddi_buf_trans skl_u_ddi_translations_dp[] = { > + { 0x00002016, 0x000000A2, 0x0 }, > + { 0x00005012, 0x00000088, 0x0 }, > + { 0x00007011, 0x00000087, 0x0 }, > + { 0x80009010, 0x000000C7, 0x1 }, /* Uses I_boost */ > + { 0x00002016, 0x0000009D, 0x0 }, > + { 0x00005012, 0x000000C7, 0x0 }, > + { 0x00007011, 0x000000C7, 0x0 }, > + { 0x00002016, 0x00000088, 0x0 }, > + { 0x00005012, 0x000000C7, 0x0 }, > +}; > + > +/* Skylake Y with 0.85V VccIO */ > +static const struct ddi_buf_trans skl_y_085v_ddi_translations_dp[] = { > + { 0x00000018, 0x000000A2, 0x0 }, > + { 0x00005012, 0x00000088, 0x0 }, > + { 0x00007011, 0x00000087, 0x0 }, > + { 0x80009010, 0x000000C7, 0x1 }, /* Uses I_boost */ > + { 0x00000018, 0x0000009D, 0x0 }, > + { 0x00005012, 0x000000C7, 0x0 }, > + { 0x00007011, 0x000000C7, 0x0 }, > + { 0x00000018, 0x00000088, 0x0 }, > + { 0x00005012, 0x000000C7, 0x0 }, > +}; > + > +/* > + * Skylake H and S, and Skylake Y with 0.95V VccIO > + * eDP 1.4 low vswing translation parameters > + */ > static const struct ddi_buf_trans skl_ddi_translations_edp[] = { > - { 0x00000018, 0x000000a8 }, > - { 0x00002016, 0x000000ab }, > - { 0x00006012, 0x000000a2 }, > - { 0x00008010, 0x00000088 }, > - { 0x00000018, 0x000000ab }, > - { 0x00004014, 0x000000a2 }, > - { 0x00006012, 0x000000a6 }, > - { 0x00000018, 0x000000a2 }, > - { 0x00005013, 0x0000009c }, > - { 0x00000018, 0x00000088 }, > + { 0x00000018, 0x000000A8, 0x0 }, > + { 0x00004013, 0x000000A9, 0x0 }, > + { 0x00007011, 0x000000A2, 0x0 }, > + { 0x00009010, 0x0000009C, 0x0 }, > + { 0x00000018, 0x000000A9, 0x0 }, > + { 0x00006013, 0x000000A2, 0x0 }, > + { 0x00007011, 0x000000A6, 0x0 }, > + { 0x00000018, 0x000000AB, 0x0 }, > + { 0x00007013, 0x0000009F, 0x0 }, > + { 0x00000018, 0x000000DF, 0x0 }, > +}; > + > +/* > + * Skylake U > + * eDP 1.4 low vswing translation parameters > + */ > +static const struct ddi_buf_trans skl_u_ddi_translations_edp[] = { > + { 0x00000018, 0x000000A8, 0x0 }, > + { 0x00004013, 0x000000A9, 0x0 }, > + { 0x00007011, 0x000000A2, 0x0 }, > + { 0x00009010, 0x0000009C, 0x0 }, > + { 0x00000018, 0x000000A9, 0x0 }, > + { 0x00006013, 0x000000A2, 0x0 }, > + { 0x00007011, 0x000000A6, 0x0 }, > + { 0x00002016, 0x000000AB, 0x0 }, > + { 0x00005013, 0x0000009F, 0x0 }, > + { 0x00000018, 0x000000DF, 0x0 }, > }; > > +/* > + * Skylake Y with 0.95V VccIO > + * eDP 1.4 low vswing translation parameters > + */ > +static const struct ddi_buf_trans skl_y_085v_ddi_translations_edp[] = { > + { 0x00000018, 0x000000A8, 0x0 }, > + { 0x00004013, 0x000000AB, 0x0 }, > + { 0x00007011, 0x000000A4, 0x0 }, > + { 0x00009010, 0x000000DF, 0x0 }, > + { 0x00000018, 0x000000AA, 0x0 }, > + { 0x00006013, 0x000000A4, 0x0 }, > + { 0x00007011, 0x0000009D, 0x0 }, > + { 0x00000018, 0x000000A0, 0x0 }, > + { 0x00006012, 0x000000DF, 0x0 }, > + { 0x00000018, 0x0000008A, 0x0 }, > +}; > > +/* Skylake H, S and U, and Skylake Y with 0.95V VccIO */ > static const struct ddi_buf_trans skl_ddi_translations_hdmi[] = { > - { 0x00000018, 0x000000ac }, > - { 0x00005012, 0x0000009d }, > - { 0x00007011, 0x00000088 }, > - { 0x00000018, 0x000000a1 }, > - { 0x00000018, 0x00000098 }, > - { 0x00004013, 0x00000088 }, > - { 0x00006012, 0x00000087 }, > - { 0x00000018, 0x000000df }, > - { 0x00003015, 0x00000087 }, > - { 0x00003015, 0x000000c7 }, > - { 0x00000018, 0x000000c7 }, > + { 0x00000018, 0x000000AC, 0x0 }, > + { 0x00005012, 0x0000009D, 0x0 }, > + { 0x00007011, 0x00000088, 0x0 }, > + { 0x00000018, 0x000000A1, 0x0 }, > + { 0x00000018, 0x00000098, 0x0 }, > + { 0x00004013, 0x00000088, 0x0 }, > + { 0x00006012, 0x00000087, 0x0 }, > + { 0x00000018, 0x000000DF, 0x0 }, > + { 0x00003015, 0x00000087, 0x0 }, /* Default */ > + { 0x00003015, 0x000000C7, 0x0 }, > + { 0x00000018, 0x000000C7, 0x0 }, > +}; > + > +/* Skylake Y with 0.85V VccIO */ > +static const struct ddi_buf_trans skl_y_085v_ddi_translations_hdmi[] = { > + { 0x00000018, 0x000000A1, 0x0 }, > + { 0x00005012, 0x000000DF, 0x0 }, > + { 0x00007011, 0x00000084, 0x0 }, > + { 0x00000018, 0x000000A4, 0x0 }, > + { 0x00000018, 0x0000009D, 0x0 }, > + { 0x00004013, 0x00000080, 0x0 }, > + { 0x00006013, 0x000000C7, 0x0 }, > + { 0x00000018, 0x0000008A, 0x0 }, > + { 0x00003015, 0x000000C7, 0x0 }, /* Default */ > + { 0x80003015, 0x000000C7, 0x7 }, /* Uses I_boost */ > + { 0x00000018, 0x000000C7, 0x0 }, > }; > > struct bxt_ddi_buf_trans { > @@ -190,7 +270,7 @@ static const struct bxt_ddi_buf_trans bxt_ddi_translations_dp[] = { > { 154, 0x9A, 0, 64, false }, /* 6: 600 6 */ > { 102, 0x9A, 0, 128, false }, /* 7: 800 0 */ > { 154, 0x9A, 0, 85, false }, /* 8: 800 3.5 */ > - { 154, 0x9A, 1, 128, false }, /* 9: 1200 0 */ > + { 154, 0x9A, 1, 128, false }, /* 9: 1200 0 */ > }; > > /* BSpec has 2 recommended values - entries 0 and 8. > @@ -210,6 +290,9 @@ static const struct bxt_ddi_buf_trans bxt_ddi_translations_hdmi[] = { > { 154, 0x9A, 1, 128, true }, /* 9: 1200 0 */ > }; > > +static void bxt_ddi_vswing_sequence(struct drm_device *dev, u32 level, > + enum port port, int type); > + > static void ddi_get_encoder_port(struct intel_encoder *intel_encoder, > struct intel_digital_port **dig_port, > enum port *port) > @@ -249,6 +332,99 @@ intel_dig_port_supports_hdmi(const struct intel_digital_port *intel_dig_port) > return intel_dig_port->hdmi.hdmi_reg; > } > > +static const struct ddi_buf_trans *skl_get_buf_trans_dp(struct drm_device *dev, > + int *n_entries) > +{ > + struct drm_i915_private *dev_priv = dev->dev_private; > + const struct ddi_buf_trans *ddi_translations; > + static int is_095v = -1; > + > + if (is_095v == -1) { > + u32 spr1 = I915_READ(UAIMI_SPR1); > + is_095v = spr1 & SKL_VCCIO_MASK; > + } > + > + if (IS_SKL_ULX(dev) && !is_095v) { > + ddi_translations = skl_y_085v_ddi_translations_dp; > + *n_entries = ARRAY_SIZE(skl_y_085v_ddi_translations_dp); > + } else if (IS_SKL_ULT(dev)) { > + ddi_translations = skl_u_ddi_translations_dp; > + *n_entries = ARRAY_SIZE(skl_u_ddi_translations_dp); > + } else { > + ddi_translations = skl_ddi_translations_dp; > + *n_entries = ARRAY_SIZE(skl_ddi_translations_dp); > + } > + > + return ddi_translations; > +} > + > +static const struct ddi_buf_trans *skl_get_buf_trans_edp(struct drm_device *dev, > + int *n_entries) > +{ > + struct drm_i915_private *dev_priv = dev->dev_private; > + const struct ddi_buf_trans *ddi_translations; > + static int is_095v = -1; > + > + if (is_095v == -1) { > + u32 spr1 = I915_READ(UAIMI_SPR1); > + is_095v = spr1 & SKL_VCCIO_MASK; > + } > + > + if (IS_SKL_ULX(dev) && !is_095v) { > + if (dev_priv->edp_low_vswing) { > + ddi_translations = skl_y_085v_ddi_translations_edp; > + *n_entries = > + ARRAY_SIZE(skl_y_085v_ddi_translations_edp); > + } else { > + ddi_translations = skl_y_085v_ddi_translations_dp; > + *n_entries = > + ARRAY_SIZE(skl_y_085v_ddi_translations_dp); > + } > + } else if (IS_SKL_ULT(dev)) { > + if (dev_priv->edp_low_vswing) { > + ddi_translations = skl_u_ddi_translations_edp; > + *n_entries = ARRAY_SIZE(skl_u_ddi_translations_edp); > + } else { > + ddi_translations = skl_u_ddi_translations_dp; > + *n_entries = ARRAY_SIZE(skl_u_ddi_translations_dp); > + } > + } else { > + if (dev_priv->edp_low_vswing) { > + ddi_translations = skl_ddi_translations_edp; > + *n_entries = ARRAY_SIZE(skl_ddi_translations_edp); > + } else { > + ddi_translations = skl_ddi_translations_dp; > + *n_entries = ARRAY_SIZE(skl_ddi_translations_dp); > + } > + } > + > + return ddi_translations; > +} > + > +static const struct ddi_buf_trans * > +skl_get_buf_trans_hdmi(struct drm_device *dev, > + int *n_entries) > +{ > + struct drm_i915_private *dev_priv = dev->dev_private; > + const struct ddi_buf_trans *ddi_translations; > + static int is_095v = -1; > + > + if (is_095v == -1) { > + u32 spr1 = I915_READ(UAIMI_SPR1); > + is_095v = spr1 & SKL_VCCIO_MASK; > + } > + > + if (IS_SKL_ULX(dev) && !is_095v) { > + ddi_translations = skl_y_085v_ddi_translations_hdmi; > + *n_entries = ARRAY_SIZE(skl_y_085v_ddi_translations_hdmi); > + } else { > + ddi_translations = skl_ddi_translations_hdmi; > + *n_entries = ARRAY_SIZE(skl_ddi_translations_hdmi); > + } > + > + return ddi_translations; > +} > + > /* > * Starting with Haswell, DDI port buffers must be programmed with correct > * values in advance. The buffer values are different for FDI and DP modes, > @@ -279,20 +455,13 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port, > INTEL_OUTPUT_HDMI); > return; > } else if (IS_SKYLAKE(dev)) { > - ddi_translations_fdi = NULL; > - ddi_translations_dp = skl_ddi_translations_dp; > - n_dp_entries = ARRAY_SIZE(skl_ddi_translations_dp); > - if (dev_priv->edp_low_vswing) { > - ddi_translations_edp = skl_ddi_translations_edp; > - n_edp_entries = ARRAY_SIZE(skl_ddi_translations_edp); > - } else { > - ddi_translations_edp = skl_ddi_translations_dp; > - n_edp_entries = ARRAY_SIZE(skl_ddi_translations_dp); > - } > - > - ddi_translations_hdmi = skl_ddi_translations_hdmi; > - n_hdmi_entries = ARRAY_SIZE(skl_ddi_translations_hdmi); > - hdmi_default_entry = 7; > + ddi_translations_dp = > + skl_get_buf_trans_dp(dev, &n_dp_entries); > + ddi_translations_edp = > + skl_get_buf_trans_edp(dev, &n_edp_entries); > + ddi_translations_hdmi = > + skl_get_buf_trans_hdmi(dev, &n_hdmi_entries); > + hdmi_default_entry = 8; > } else if (IS_BROADWELL(dev)) { > ddi_translations_fdi = bdw_ddi_translations_fdi; > ddi_translations_dp = bdw_ddi_translations_dp; > @@ -1806,8 +1975,49 @@ void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc) > TRANS_CLK_SEL_DISABLED); > } > > -void bxt_ddi_vswing_sequence(struct drm_device *dev, u32 level, > - enum port port, int type) > +static void skl_ddi_set_iboost(struct drm_device *dev, u32 level, > + enum port port, int type) > +{ > + struct drm_i915_private *dev_priv = dev->dev_private; > + const struct ddi_buf_trans *ddi_translations; > + uint8_t iboost; > + int n_entries; > + u32 reg; > + > + if (type == INTEL_OUTPUT_DISPLAYPORT) { > + ddi_translations = skl_get_buf_trans_dp(dev, &n_entries); > + iboost = ddi_translations[port].i_boost; > + } else if (type == INTEL_OUTPUT_EDP) { > + ddi_translations = skl_get_buf_trans_edp(dev, &n_entries); > + iboost = ddi_translations[port].i_boost; > + } else if (type == INTEL_OUTPUT_HDMI) { > + ddi_translations = skl_get_buf_trans_hdmi(dev, &n_entries); > + iboost = ddi_translations[port].i_boost; > + } else { > + return; > + } > + > + /* Make sure that the requested I_boost is valid */ > + if (iboost && iboost != 0x1 && iboost != 0x3 && iboost != 0x7) { > + DRM_ERROR("Invalid I_boost value %u\n", iboost); > + return; > + } > + > + reg = I915_READ(DISPIO_CR_TX_BMU_CR0); > + reg &= ~BALANCE_LEG_MASK(port); > + reg &= ~(1 << (BALANCE_LEG_DISABLE_SHIFT + port)); > + > + if (iboost) { > + reg |= iboost << BALANCE_LEG_SHIFT(port); > + } else { > + reg |= 1 << (BALANCE_LEG_DISABLE_SHIFT + port); > + } > + > + I915_WRITE(DISPIO_CR_TX_BMU_CR0, reg); > +} > + > +static void bxt_ddi_vswing_sequence(struct drm_device *dev, u32 level, > + enum port port, int type) > { > struct drm_i915_private *dev_priv = dev->dev_private; > const struct bxt_ddi_buf_trans *ddi_translations; > @@ -1867,6 +2077,73 @@ void bxt_ddi_vswing_sequence(struct drm_device *dev, u32 level, > I915_WRITE(BXT_PORT_PCS_DW10_GRP(port), val); > } > > +static uint32_t translate_signal_level(int signal_levels) > +{ > + uint32_t level; > + > + switch (signal_levels) { > + default: > + DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level: " > + "0x%x\n", signal_levels); > + case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0: > + level = 0; > + break; > + case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_1: > + level = 1; > + break; > + case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_2: > + level = 2; > + break; > + case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_3: > + level = 3; > + break; > + > + case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_0: > + level = 4; > + break; > + case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_1: > + level = 5; > + break; > + case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_2: > + level = 6; > + break; > + > + case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_0: > + level = 7; > + break; > + case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_1: > + level = 8; > + break; > + > + case DP_TRAIN_VOLTAGE_SWING_LEVEL_3 | DP_TRAIN_PRE_EMPH_LEVEL_0: > + level = 9; > + break; > + } > + > + return level; > +} > + > +uint32_t ddi_signal_levels(struct intel_dp *intel_dp) > +{ > + struct intel_digital_port *dport = dp_to_dig_port(intel_dp); > + struct drm_device *dev = dport->base.base.dev; > + struct intel_encoder *encoder = &dport->base; > + uint8_t train_set = intel_dp->train_set[0]; > + int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK | > + DP_TRAIN_PRE_EMPHASIS_MASK); > + enum port port = dport->port; > + uint32_t level; > + > + level = translate_signal_level(signal_levels); > + > + if (IS_SKYLAKE(dev)) > + skl_ddi_set_iboost(dev, level, port, encoder->type); > + else if (IS_BROXTON(dev)) > + bxt_ddi_vswing_sequence(dev, level, port, encoder->type); > + > + return DDI_BUF_TRANS_SELECT(level); > +} > + > static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder) > { > struct drm_encoder *encoder = &intel_encoder->base; > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c > index f52eef138247..041e2d6dcc56 100644 > --- a/drivers/gpu/drm/i915/intel_dp.c > +++ b/drivers/gpu/drm/i915/intel_dp.c > @@ -3417,92 +3417,6 @@ gen7_edp_signal_levels(uint8_t train_set) > } > } > > -/* Gen7.5's (HSW) DP voltage swing and pre-emphasis control */ > -static uint32_t > -hsw_signal_levels(uint8_t train_set) > -{ > - int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK | > - DP_TRAIN_PRE_EMPHASIS_MASK); > - switch (signal_levels) { > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0: > - return DDI_BUF_TRANS_SELECT(0); > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_1: > - return DDI_BUF_TRANS_SELECT(1); > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_2: > - return DDI_BUF_TRANS_SELECT(2); > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_3: > - return DDI_BUF_TRANS_SELECT(3); > - > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_0: > - return DDI_BUF_TRANS_SELECT(4); > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_1: > - return DDI_BUF_TRANS_SELECT(5); > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_2: > - return DDI_BUF_TRANS_SELECT(6); > - > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_0: > - return DDI_BUF_TRANS_SELECT(7); > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_1: > - return DDI_BUF_TRANS_SELECT(8); > - > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_3 | DP_TRAIN_PRE_EMPH_LEVEL_0: > - return DDI_BUF_TRANS_SELECT(9); > - default: > - DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level:" > - "0x%x\n", signal_levels); > - return DDI_BUF_TRANS_SELECT(0); > - } > -} > - > -static void bxt_signal_levels(struct intel_dp *intel_dp) > -{ > - struct intel_digital_port *dport = dp_to_dig_port(intel_dp); > - enum port port = dport->port; > - struct drm_device *dev = dport->base.base.dev; > - struct intel_encoder *encoder = &dport->base; > - uint8_t train_set = intel_dp->train_set[0]; > - uint32_t level = 0; > - > - int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK | > - DP_TRAIN_PRE_EMPHASIS_MASK); > - switch (signal_levels) { > - default: > - DRM_DEBUG_KMS("Unsupported voltage swing/pre-emph level\n"); > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0: > - level = 0; > - break; > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_1: > - level = 1; > - break; > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_2: > - level = 2; > - break; > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_3: > - level = 3; > - break; > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_0: > - level = 4; > - break; > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_1: > - level = 5; > - break; > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_2: > - level = 6; > - break; > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_0: > - level = 7; > - break; > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_1: > - level = 8; > - break; > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_3 | DP_TRAIN_PRE_EMPH_LEVEL_0: > - level = 9; > - break; > - } > - > - bxt_ddi_vswing_sequence(dev, level, port, encoder->type); > -} > - > /* Properly updates "DP" with the correct signal levels. */ > static void > intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP) > @@ -3510,22 +3424,20 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP) > struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); > enum port port = intel_dig_port->port; > struct drm_device *dev = intel_dig_port->base.base.dev; > - uint32_t signal_levels, mask; > + uint32_t signal_levels, mask = 0; > uint8_t train_set = intel_dp->train_set[0]; > > - if (IS_BROXTON(dev)) { > - signal_levels = 0; > - bxt_signal_levels(intel_dp); > - mask = 0; > - } else if (HAS_DDI(dev)) { > - signal_levels = hsw_signal_levels(train_set); > - mask = DDI_BUF_EMP_MASK; > + if (HAS_DDI(dev)) { > + signal_levels = ddi_signal_levels(intel_dp); > + > + if (IS_BROXTON(dev)) > + signal_levels = 0; > + else > + mask = DDI_BUF_EMP_MASK; > } else if (IS_CHERRYVIEW(dev)) { > signal_levels = chv_signal_levels(intel_dp); > - mask = 0; > } else if (IS_VALLEYVIEW(dev)) { > signal_levels = vlv_signal_levels(intel_dp); > - mask = 0; > } else if (IS_GEN7(dev) && port == PORT_A) { > signal_levels = gen7_edp_signal_levels(train_set); > mask = EDP_LINK_TRAIN_VOL_EMP_MASK_IVB; > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h > index bcafefcf048b..c6cbe8c602f9 100644 > --- a/drivers/gpu/drm/i915/intel_drv.h > +++ b/drivers/gpu/drm/i915/intel_drv.h > @@ -950,8 +950,7 @@ void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder); > void intel_ddi_clock_get(struct intel_encoder *encoder, > struct intel_crtc_state *pipe_config); > void intel_ddi_set_vc_payload_alloc(struct drm_crtc *crtc, bool state); > -void bxt_ddi_vswing_sequence(struct drm_device *dev, u32 level, > - enum port port, int type); > +uint32_t ddi_signal_levels(struct intel_dp *intel_dp); > > /* intel_frontbuffer.c */ > void intel_fb_obj_invalidate(struct drm_i915_gem_object *obj, >
On Mon, Jun 29, 2015 at 01:35:06PM +0300, Antti Koskipää wrote: > Looks fine to me. > > Reviewed-by: Antti Koskipää <antti.koskipaa@linux.intel.com> > > > On 06/25/2015 11:11 AM, David Weinehall wrote: > > This patch adds support for 0.85V VccIO on Skylake Y, > > separate buffer translation tables for Skylake U, > > and support for I_boost for the entries that needs this. > > > > Changes in v2: > > * Refactored the code a bit to move all DDI signal level setup to > > intel_ddi.c For next time around please split out refactoring from actual code changes, makes it a pain to review. And if this blows up in a regression that's really annoying. Also please head checkpatch's suggestions a bit more, I fixed that up when applying. -Daniel > > > > Issue: VIZ-5677 > > Signed-off-by: David Weinehall <david.weinehall@linux.intel.com> > > --- > > drivers/gpu/drm/i915/i915_drv.h | 8 + > > drivers/gpu/drm/i915/i915_reg.h | 12 + > > drivers/gpu/drm/i915/intel_ddi.c | 507 ++++++++++++++++++++++++++++++--------- > > drivers/gpu/drm/i915/intel_dp.c | 104 +------- > > drivers/gpu/drm/i915/intel_drv.h | 3 +- > > 5 files changed, 421 insertions(+), 213 deletions(-) > > > > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > > index 491ef0cfcb0b..09a57a584f5f 100644 > > --- a/drivers/gpu/drm/i915/i915_drv.h > > +++ b/drivers/gpu/drm/i915/i915_drv.h > > @@ -2415,6 +2415,14 @@ struct drm_i915_cmd_table { > > /* ULX machines are also considered ULT. */ > > #define IS_HSW_ULX(dev) (INTEL_DEVID(dev) == 0x0A0E || \ > > INTEL_DEVID(dev) == 0x0A1E) > > +#define IS_SKL_ULT(dev) (INTEL_DEVID(dev) == 0x1906 || \ > > + INTEL_DEVID(dev) == 0x1913 || \ > > + INTEL_DEVID(dev) == 0x1916 || \ > > + INTEL_DEVID(dev) == 0x1921 || \ > > + INTEL_DEVID(dev) == 0x1926) > > +#define IS_SKL_ULX(dev) (INTEL_DEVID(dev) == 0x190E || \ > > + INTEL_DEVID(dev) == 0x1915 || \ > > + INTEL_DEVID(dev) == 0x191E) > > #define IS_PRELIMINARY_HW(intel_info) ((intel_info)->is_preliminary) > > > > #define SKL_REVID_A0 (0x0) > > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h > > index 0b979ad16d41..fb63ead2b8eb 100644 > > --- a/drivers/gpu/drm/i915/i915_reg.h > > +++ b/drivers/gpu/drm/i915/i915_reg.h > > @@ -1382,6 +1382,18 @@ enum skl_disp_power_wells { > > _PORT_TX_DW14_LN0_C) + \ > > _BXT_LANE_OFFSET(lane)) > > > > +/* UAIMI scratch pad register 1 */ > > +#define UAIMI_SPR1 0x4F074 > > +/* SKL VccIO mask */ > > +#define SKL_VCCIO_MASK 0x1 > > +/* SKL balance leg register */ > > +#define DISPIO_CR_TX_BMU_CR0 0x6C00C > > +/* I_boost values */ > > +#define BALANCE_LEG_SHIFT(port) (8+3*(port)) > > +#define BALANCE_LEG_MASK(port) (7<<(8+3*(port))) > > +/* Balance leg disable bits */ > > +#define BALANCE_LEG_DISABLE_SHIFT 23 > > + > > /* > > * Fence registers > > */ > > diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c > > index 31b29e8781ac..08f89299b572 100644 > > --- a/drivers/gpu/drm/i915/intel_ddi.c > > +++ b/drivers/gpu/drm/i915/intel_ddi.c > > @@ -31,6 +31,7 @@ > > struct ddi_buf_trans { > > u32 trans1; /* balance leg enable, de-emph level */ > > u32 trans2; /* vref sel, vswing */ > > + u8 i_boost; /* SKL: I_boost; valid: 0x0, 0x1, 0x3, 0x7 */ > > }; > > > > /* HDMI/DVI modes ignore everything but the last 2 items. So we share > > @@ -38,134 +39,213 @@ struct ddi_buf_trans { > > * automatically adapt to HDMI connections as well > > */ > > static const struct ddi_buf_trans hsw_ddi_translations_dp[] = { > > - { 0x00FFFFFF, 0x0006000E }, > > - { 0x00D75FFF, 0x0005000A }, > > - { 0x00C30FFF, 0x00040006 }, > > - { 0x80AAAFFF, 0x000B0000 }, > > - { 0x00FFFFFF, 0x0005000A }, > > - { 0x00D75FFF, 0x000C0004 }, > > - { 0x80C30FFF, 0x000B0000 }, > > - { 0x00FFFFFF, 0x00040006 }, > > - { 0x80D75FFF, 0x000B0000 }, > > + { 0x00FFFFFF, 0x0006000E, 0x0 }, > > + { 0x00D75FFF, 0x0005000A, 0x0 }, > > + { 0x00C30FFF, 0x00040006, 0x0 }, > > + { 0x80AAAFFF, 0x000B0000, 0x0 }, > > + { 0x00FFFFFF, 0x0005000A, 0x0 }, > > + { 0x00D75FFF, 0x000C0004, 0x0 }, > > + { 0x80C30FFF, 0x000B0000, 0x0 }, > > + { 0x00FFFFFF, 0x00040006, 0x0 }, > > + { 0x80D75FFF, 0x000B0000, 0x0 }, > > }; > > > > static const struct ddi_buf_trans hsw_ddi_translations_fdi[] = { > > - { 0x00FFFFFF, 0x0007000E }, > > - { 0x00D75FFF, 0x000F000A }, > > - { 0x00C30FFF, 0x00060006 }, > > - { 0x00AAAFFF, 0x001E0000 }, > > - { 0x00FFFFFF, 0x000F000A }, > > - { 0x00D75FFF, 0x00160004 }, > > - { 0x00C30FFF, 0x001E0000 }, > > - { 0x00FFFFFF, 0x00060006 }, > > - { 0x00D75FFF, 0x001E0000 }, > > + { 0x00FFFFFF, 0x0007000E, 0x0 }, > > + { 0x00D75FFF, 0x000F000A, 0x0 }, > > + { 0x00C30FFF, 0x00060006, 0x0 }, > > + { 0x00AAAFFF, 0x001E0000, 0x0 }, > > + { 0x00FFFFFF, 0x000F000A, 0x0 }, > > + { 0x00D75FFF, 0x00160004, 0x0 }, > > + { 0x00C30FFF, 0x001E0000, 0x0 }, > > + { 0x00FFFFFF, 0x00060006, 0x0 }, > > + { 0x00D75FFF, 0x001E0000, 0x0 }, > > }; > > > > static const struct ddi_buf_trans hsw_ddi_translations_hdmi[] = { > > /* Idx NT mV d T mV d db */ > > - { 0x00FFFFFF, 0x0006000E }, /* 0: 400 400 0 */ > > - { 0x00E79FFF, 0x000E000C }, /* 1: 400 500 2 */ > > - { 0x00D75FFF, 0x0005000A }, /* 2: 400 600 3.5 */ > > - { 0x00FFFFFF, 0x0005000A }, /* 3: 600 600 0 */ > > - { 0x00E79FFF, 0x001D0007 }, /* 4: 600 750 2 */ > > - { 0x00D75FFF, 0x000C0004 }, /* 5: 600 900 3.5 */ > > - { 0x00FFFFFF, 0x00040006 }, /* 6: 800 800 0 */ > > - { 0x80E79FFF, 0x00030002 }, /* 7: 800 1000 2 */ > > - { 0x00FFFFFF, 0x00140005 }, /* 8: 850 850 0 */ > > - { 0x00FFFFFF, 0x000C0004 }, /* 9: 900 900 0 */ > > - { 0x00FFFFFF, 0x001C0003 }, /* 10: 950 950 0 */ > > - { 0x80FFFFFF, 0x00030002 }, /* 11: 1000 1000 0 */ > > + { 0x00FFFFFF, 0x0006000E, 0x0 },/* 0: 400 400 0 */ > > + { 0x00E79FFF, 0x000E000C, 0x0 },/* 1: 400 500 2 */ > > + { 0x00D75FFF, 0x0005000A, 0x0 },/* 2: 400 600 3.5 */ > > + { 0x00FFFFFF, 0x0005000A, 0x0 },/* 3: 600 600 0 */ > > + { 0x00E79FFF, 0x001D0007, 0x0 },/* 4: 600 750 2 */ > > + { 0x00D75FFF, 0x000C0004, 0x0 },/* 5: 600 900 3.5 */ > > + { 0x00FFFFFF, 0x00040006, 0x0 },/* 6: 800 800 0 */ > > + { 0x80E79FFF, 0x00030002, 0x0 },/* 7: 800 1000 2 */ > > + { 0x00FFFFFF, 0x00140005, 0x0 },/* 8: 850 850 0 */ > > + { 0x00FFFFFF, 0x000C0004, 0x0 },/* 9: 900 900 0 */ > > + { 0x00FFFFFF, 0x001C0003, 0x0 },/* 10: 950 950 0 */ > > + { 0x80FFFFFF, 0x00030002, 0x0 },/* 11: 1000 1000 0 */ > > }; > > > > static const struct ddi_buf_trans bdw_ddi_translations_edp[] = { > > - { 0x00FFFFFF, 0x00000012 }, > > - { 0x00EBAFFF, 0x00020011 }, > > - { 0x00C71FFF, 0x0006000F }, > > - { 0x00AAAFFF, 0x000E000A }, > > - { 0x00FFFFFF, 0x00020011 }, > > - { 0x00DB6FFF, 0x0005000F }, > > - { 0x00BEEFFF, 0x000A000C }, > > - { 0x00FFFFFF, 0x0005000F }, > > - { 0x00DB6FFF, 0x000A000C }, > > + { 0x00FFFFFF, 0x00000012, 0x0 }, > > + { 0x00EBAFFF, 0x00020011, 0x0 }, > > + { 0x00C71FFF, 0x0006000F, 0x0 }, > > + { 0x00AAAFFF, 0x000E000A, 0x0 }, > > + { 0x00FFFFFF, 0x00020011, 0x0 }, > > + { 0x00DB6FFF, 0x0005000F, 0x0 }, > > + { 0x00BEEFFF, 0x000A000C, 0x0 }, > > + { 0x00FFFFFF, 0x0005000F, 0x0 }, > > + { 0x00DB6FFF, 0x000A000C, 0x0 }, > > }; > > > > static const struct ddi_buf_trans bdw_ddi_translations_dp[] = { > > - { 0x00FFFFFF, 0x0007000E }, > > - { 0x00D75FFF, 0x000E000A }, > > - { 0x00BEFFFF, 0x00140006 }, > > - { 0x80B2CFFF, 0x001B0002 }, > > - { 0x00FFFFFF, 0x000E000A }, > > - { 0x00DB6FFF, 0x00160005 }, > > - { 0x80C71FFF, 0x001A0002 }, > > - { 0x00F7DFFF, 0x00180004 }, > > - { 0x80D75FFF, 0x001B0002 }, > > + { 0x00FFFFFF, 0x0007000E, 0x0 }, > > + { 0x00D75FFF, 0x000E000A, 0x0 }, > > + { 0x00BEFFFF, 0x00140006, 0x0 }, > > + { 0x80B2CFFF, 0x001B0002, 0x0 }, > > + { 0x00FFFFFF, 0x000E000A, 0x0 }, > > + { 0x00DB6FFF, 0x00160005, 0x0 }, > > + { 0x80C71FFF, 0x001A0002, 0x0 }, > > + { 0x00F7DFFF, 0x00180004, 0x0 }, > > + { 0x80D75FFF, 0x001B0002, 0x0 }, > > }; > > > > static const struct ddi_buf_trans bdw_ddi_translations_fdi[] = { > > - { 0x00FFFFFF, 0x0001000E }, > > - { 0x00D75FFF, 0x0004000A }, > > - { 0x00C30FFF, 0x00070006 }, > > - { 0x00AAAFFF, 0x000C0000 }, > > - { 0x00FFFFFF, 0x0004000A }, > > - { 0x00D75FFF, 0x00090004 }, > > - { 0x00C30FFF, 0x000C0000 }, > > - { 0x00FFFFFF, 0x00070006 }, > > - { 0x00D75FFF, 0x000C0000 }, > > + { 0x00FFFFFF, 0x0001000E, 0x0 }, > > + { 0x00D75FFF, 0x0004000A, 0x0 }, > > + { 0x00C30FFF, 0x00070006, 0x0 }, > > + { 0x00AAAFFF, 0x000C0000, 0x0 }, > > + { 0x00FFFFFF, 0x0004000A, 0x0 }, > > + { 0x00D75FFF, 0x00090004, 0x0 }, > > + { 0x00C30FFF, 0x000C0000, 0x0 }, > > + { 0x00FFFFFF, 0x00070006, 0x0 }, > > + { 0x00D75FFF, 0x000C0000, 0x0 }, > > }; > > > > static const struct ddi_buf_trans bdw_ddi_translations_hdmi[] = { > > /* Idx NT mV d T mV df db */ > > - { 0x00FFFFFF, 0x0007000E }, /* 0: 400 400 0 */ > > - { 0x00D75FFF, 0x000E000A }, /* 1: 400 600 3.5 */ > > - { 0x00BEFFFF, 0x00140006 }, /* 2: 400 800 6 */ > > - { 0x00FFFFFF, 0x0009000D }, /* 3: 450 450 0 */ > > - { 0x00FFFFFF, 0x000E000A }, /* 4: 600 600 0 */ > > - { 0x00D7FFFF, 0x00140006 }, /* 5: 600 800 2.5 */ > > - { 0x80CB2FFF, 0x001B0002 }, /* 6: 600 1000 4.5 */ > > - { 0x00FFFFFF, 0x00140006 }, /* 7: 800 800 0 */ > > - { 0x80E79FFF, 0x001B0002 }, /* 8: 800 1000 2 */ > > - { 0x80FFFFFF, 0x001B0002 }, /* 9: 1000 1000 0 */ > > + { 0x00FFFFFF, 0x0007000E, 0x0 },/* 0: 400 400 0 */ > > + { 0x00D75FFF, 0x000E000A, 0x0 },/* 1: 400 600 3.5 */ > > + { 0x00BEFFFF, 0x00140006, 0x0 },/* 2: 400 800 6 */ > > + { 0x00FFFFFF, 0x0009000D, 0x0 },/* 3: 450 450 0 */ > > + { 0x00FFFFFF, 0x000E000A, 0x0 },/* 4: 600 600 0 */ > > + { 0x00D7FFFF, 0x00140006, 0x0 },/* 5: 600 800 2.5 */ > > + { 0x80CB2FFF, 0x001B0002, 0x0 },/* 6: 600 1000 4.5 */ > > + { 0x00FFFFFF, 0x00140006, 0x0 },/* 7: 800 800 0 */ > > + { 0x80E79FFF, 0x001B0002, 0x0 },/* 8: 800 1000 2 */ > > + { 0x80FFFFFF, 0x001B0002, 0x0 },/* 9: 1000 1000 0 */ > > }; > > > > +/* Skylake H, S, and Skylake Y with 0.95V VccIO */ > > static const struct ddi_buf_trans skl_ddi_translations_dp[] = { > > - { 0x00000018, 0x000000a2 }, > > - { 0x00004014, 0x0000009B }, > > - { 0x00006012, 0x00000088 }, > > - { 0x00008010, 0x00000087 }, > > - { 0x00000018, 0x0000009B }, > > - { 0x00004014, 0x00000088 }, > > - { 0x00006012, 0x00000087 }, > > - { 0x00000018, 0x00000088 }, > > - { 0x00004014, 0x00000087 }, > > + { 0x00002016, 0x000000A0, 0x0 }, > > + { 0x00005012, 0x0000009B, 0x0 }, > > + { 0x00007011, 0x00000088, 0x0 }, > > + { 0x00009010, 0x000000C7, 0x0 }, > > + { 0x00002016, 0x0000009B, 0x0 }, > > + { 0x00005012, 0x00000088, 0x0 }, > > + { 0x00007011, 0x000000C7, 0x0 }, > > + { 0x00002016, 0x000000DF, 0x0 }, > > + { 0x00005012, 0x000000C7, 0x0 }, > > }; > > > > -/* eDP 1.4 low vswing translation parameters */ > > +/* Skylake U */ > > +static const struct ddi_buf_trans skl_u_ddi_translations_dp[] = { > > + { 0x00002016, 0x000000A2, 0x0 }, > > + { 0x00005012, 0x00000088, 0x0 }, > > + { 0x00007011, 0x00000087, 0x0 }, > > + { 0x80009010, 0x000000C7, 0x1 }, /* Uses I_boost */ > > + { 0x00002016, 0x0000009D, 0x0 }, > > + { 0x00005012, 0x000000C7, 0x0 }, > > + { 0x00007011, 0x000000C7, 0x0 }, > > + { 0x00002016, 0x00000088, 0x0 }, > > + { 0x00005012, 0x000000C7, 0x0 }, > > +}; > > + > > +/* Skylake Y with 0.85V VccIO */ > > +static const struct ddi_buf_trans skl_y_085v_ddi_translations_dp[] = { > > + { 0x00000018, 0x000000A2, 0x0 }, > > + { 0x00005012, 0x00000088, 0x0 }, > > + { 0x00007011, 0x00000087, 0x0 }, > > + { 0x80009010, 0x000000C7, 0x1 }, /* Uses I_boost */ > > + { 0x00000018, 0x0000009D, 0x0 }, > > + { 0x00005012, 0x000000C7, 0x0 }, > > + { 0x00007011, 0x000000C7, 0x0 }, > > + { 0x00000018, 0x00000088, 0x0 }, > > + { 0x00005012, 0x000000C7, 0x0 }, > > +}; > > + > > +/* > > + * Skylake H and S, and Skylake Y with 0.95V VccIO > > + * eDP 1.4 low vswing translation parameters > > + */ > > static const struct ddi_buf_trans skl_ddi_translations_edp[] = { > > - { 0x00000018, 0x000000a8 }, > > - { 0x00002016, 0x000000ab }, > > - { 0x00006012, 0x000000a2 }, > > - { 0x00008010, 0x00000088 }, > > - { 0x00000018, 0x000000ab }, > > - { 0x00004014, 0x000000a2 }, > > - { 0x00006012, 0x000000a6 }, > > - { 0x00000018, 0x000000a2 }, > > - { 0x00005013, 0x0000009c }, > > - { 0x00000018, 0x00000088 }, > > + { 0x00000018, 0x000000A8, 0x0 }, > > + { 0x00004013, 0x000000A9, 0x0 }, > > + { 0x00007011, 0x000000A2, 0x0 }, > > + { 0x00009010, 0x0000009C, 0x0 }, > > + { 0x00000018, 0x000000A9, 0x0 }, > > + { 0x00006013, 0x000000A2, 0x0 }, > > + { 0x00007011, 0x000000A6, 0x0 }, > > + { 0x00000018, 0x000000AB, 0x0 }, > > + { 0x00007013, 0x0000009F, 0x0 }, > > + { 0x00000018, 0x000000DF, 0x0 }, > > +}; > > + > > +/* > > + * Skylake U > > + * eDP 1.4 low vswing translation parameters > > + */ > > +static const struct ddi_buf_trans skl_u_ddi_translations_edp[] = { > > + { 0x00000018, 0x000000A8, 0x0 }, > > + { 0x00004013, 0x000000A9, 0x0 }, > > + { 0x00007011, 0x000000A2, 0x0 }, > > + { 0x00009010, 0x0000009C, 0x0 }, > > + { 0x00000018, 0x000000A9, 0x0 }, > > + { 0x00006013, 0x000000A2, 0x0 }, > > + { 0x00007011, 0x000000A6, 0x0 }, > > + { 0x00002016, 0x000000AB, 0x0 }, > > + { 0x00005013, 0x0000009F, 0x0 }, > > + { 0x00000018, 0x000000DF, 0x0 }, > > }; > > > > +/* > > + * Skylake Y with 0.95V VccIO > > + * eDP 1.4 low vswing translation parameters > > + */ > > +static const struct ddi_buf_trans skl_y_085v_ddi_translations_edp[] = { > > + { 0x00000018, 0x000000A8, 0x0 }, > > + { 0x00004013, 0x000000AB, 0x0 }, > > + { 0x00007011, 0x000000A4, 0x0 }, > > + { 0x00009010, 0x000000DF, 0x0 }, > > + { 0x00000018, 0x000000AA, 0x0 }, > > + { 0x00006013, 0x000000A4, 0x0 }, > > + { 0x00007011, 0x0000009D, 0x0 }, > > + { 0x00000018, 0x000000A0, 0x0 }, > > + { 0x00006012, 0x000000DF, 0x0 }, > > + { 0x00000018, 0x0000008A, 0x0 }, > > +}; > > > > +/* Skylake H, S and U, and Skylake Y with 0.95V VccIO */ > > static const struct ddi_buf_trans skl_ddi_translations_hdmi[] = { > > - { 0x00000018, 0x000000ac }, > > - { 0x00005012, 0x0000009d }, > > - { 0x00007011, 0x00000088 }, > > - { 0x00000018, 0x000000a1 }, > > - { 0x00000018, 0x00000098 }, > > - { 0x00004013, 0x00000088 }, > > - { 0x00006012, 0x00000087 }, > > - { 0x00000018, 0x000000df }, > > - { 0x00003015, 0x00000087 }, > > - { 0x00003015, 0x000000c7 }, > > - { 0x00000018, 0x000000c7 }, > > + { 0x00000018, 0x000000AC, 0x0 }, > > + { 0x00005012, 0x0000009D, 0x0 }, > > + { 0x00007011, 0x00000088, 0x0 }, > > + { 0x00000018, 0x000000A1, 0x0 }, > > + { 0x00000018, 0x00000098, 0x0 }, > > + { 0x00004013, 0x00000088, 0x0 }, > > + { 0x00006012, 0x00000087, 0x0 }, > > + { 0x00000018, 0x000000DF, 0x0 }, > > + { 0x00003015, 0x00000087, 0x0 }, /* Default */ > > + { 0x00003015, 0x000000C7, 0x0 }, > > + { 0x00000018, 0x000000C7, 0x0 }, > > +}; > > + > > +/* Skylake Y with 0.85V VccIO */ > > +static const struct ddi_buf_trans skl_y_085v_ddi_translations_hdmi[] = { > > + { 0x00000018, 0x000000A1, 0x0 }, > > + { 0x00005012, 0x000000DF, 0x0 }, > > + { 0x00007011, 0x00000084, 0x0 }, > > + { 0x00000018, 0x000000A4, 0x0 }, > > + { 0x00000018, 0x0000009D, 0x0 }, > > + { 0x00004013, 0x00000080, 0x0 }, > > + { 0x00006013, 0x000000C7, 0x0 }, > > + { 0x00000018, 0x0000008A, 0x0 }, > > + { 0x00003015, 0x000000C7, 0x0 }, /* Default */ > > + { 0x80003015, 0x000000C7, 0x7 }, /* Uses I_boost */ > > + { 0x00000018, 0x000000C7, 0x0 }, > > }; > > > > struct bxt_ddi_buf_trans { > > @@ -190,7 +270,7 @@ static const struct bxt_ddi_buf_trans bxt_ddi_translations_dp[] = { > > { 154, 0x9A, 0, 64, false }, /* 6: 600 6 */ > > { 102, 0x9A, 0, 128, false }, /* 7: 800 0 */ > > { 154, 0x9A, 0, 85, false }, /* 8: 800 3.5 */ > > - { 154, 0x9A, 1, 128, false }, /* 9: 1200 0 */ > > + { 154, 0x9A, 1, 128, false }, /* 9: 1200 0 */ > > }; > > > > /* BSpec has 2 recommended values - entries 0 and 8. > > @@ -210,6 +290,9 @@ static const struct bxt_ddi_buf_trans bxt_ddi_translations_hdmi[] = { > > { 154, 0x9A, 1, 128, true }, /* 9: 1200 0 */ > > }; > > > > +static void bxt_ddi_vswing_sequence(struct drm_device *dev, u32 level, > > + enum port port, int type); > > + > > static void ddi_get_encoder_port(struct intel_encoder *intel_encoder, > > struct intel_digital_port **dig_port, > > enum port *port) > > @@ -249,6 +332,99 @@ intel_dig_port_supports_hdmi(const struct intel_digital_port *intel_dig_port) > > return intel_dig_port->hdmi.hdmi_reg; > > } > > > > +static const struct ddi_buf_trans *skl_get_buf_trans_dp(struct drm_device *dev, > > + int *n_entries) > > +{ > > + struct drm_i915_private *dev_priv = dev->dev_private; > > + const struct ddi_buf_trans *ddi_translations; > > + static int is_095v = -1; > > + > > + if (is_095v == -1) { > > + u32 spr1 = I915_READ(UAIMI_SPR1); > > + is_095v = spr1 & SKL_VCCIO_MASK; > > + } > > + > > + if (IS_SKL_ULX(dev) && !is_095v) { > > + ddi_translations = skl_y_085v_ddi_translations_dp; > > + *n_entries = ARRAY_SIZE(skl_y_085v_ddi_translations_dp); > > + } else if (IS_SKL_ULT(dev)) { > > + ddi_translations = skl_u_ddi_translations_dp; > > + *n_entries = ARRAY_SIZE(skl_u_ddi_translations_dp); > > + } else { > > + ddi_translations = skl_ddi_translations_dp; > > + *n_entries = ARRAY_SIZE(skl_ddi_translations_dp); > > + } > > + > > + return ddi_translations; > > +} > > + > > +static const struct ddi_buf_trans *skl_get_buf_trans_edp(struct drm_device *dev, > > + int *n_entries) > > +{ > > + struct drm_i915_private *dev_priv = dev->dev_private; > > + const struct ddi_buf_trans *ddi_translations; > > + static int is_095v = -1; > > + > > + if (is_095v == -1) { > > + u32 spr1 = I915_READ(UAIMI_SPR1); > > + is_095v = spr1 & SKL_VCCIO_MASK; > > + } > > + > > + if (IS_SKL_ULX(dev) && !is_095v) { > > + if (dev_priv->edp_low_vswing) { > > + ddi_translations = skl_y_085v_ddi_translations_edp; > > + *n_entries = > > + ARRAY_SIZE(skl_y_085v_ddi_translations_edp); > > + } else { > > + ddi_translations = skl_y_085v_ddi_translations_dp; > > + *n_entries = > > + ARRAY_SIZE(skl_y_085v_ddi_translations_dp); > > + } > > + } else if (IS_SKL_ULT(dev)) { > > + if (dev_priv->edp_low_vswing) { > > + ddi_translations = skl_u_ddi_translations_edp; > > + *n_entries = ARRAY_SIZE(skl_u_ddi_translations_edp); > > + } else { > > + ddi_translations = skl_u_ddi_translations_dp; > > + *n_entries = ARRAY_SIZE(skl_u_ddi_translations_dp); > > + } > > + } else { > > + if (dev_priv->edp_low_vswing) { > > + ddi_translations = skl_ddi_translations_edp; > > + *n_entries = ARRAY_SIZE(skl_ddi_translations_edp); > > + } else { > > + ddi_translations = skl_ddi_translations_dp; > > + *n_entries = ARRAY_SIZE(skl_ddi_translations_dp); > > + } > > + } > > + > > + return ddi_translations; > > +} > > + > > +static const struct ddi_buf_trans * > > +skl_get_buf_trans_hdmi(struct drm_device *dev, > > + int *n_entries) > > +{ > > + struct drm_i915_private *dev_priv = dev->dev_private; > > + const struct ddi_buf_trans *ddi_translations; > > + static int is_095v = -1; > > + > > + if (is_095v == -1) { > > + u32 spr1 = I915_READ(UAIMI_SPR1); > > + is_095v = spr1 & SKL_VCCIO_MASK; > > + } > > + > > + if (IS_SKL_ULX(dev) && !is_095v) { > > + ddi_translations = skl_y_085v_ddi_translations_hdmi; > > + *n_entries = ARRAY_SIZE(skl_y_085v_ddi_translations_hdmi); > > + } else { > > + ddi_translations = skl_ddi_translations_hdmi; > > + *n_entries = ARRAY_SIZE(skl_ddi_translations_hdmi); > > + } > > + > > + return ddi_translations; > > +} > > + > > /* > > * Starting with Haswell, DDI port buffers must be programmed with correct > > * values in advance. The buffer values are different for FDI and DP modes, > > @@ -279,20 +455,13 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port, > > INTEL_OUTPUT_HDMI); > > return; > > } else if (IS_SKYLAKE(dev)) { > > - ddi_translations_fdi = NULL; > > - ddi_translations_dp = skl_ddi_translations_dp; > > - n_dp_entries = ARRAY_SIZE(skl_ddi_translations_dp); > > - if (dev_priv->edp_low_vswing) { > > - ddi_translations_edp = skl_ddi_translations_edp; > > - n_edp_entries = ARRAY_SIZE(skl_ddi_translations_edp); > > - } else { > > - ddi_translations_edp = skl_ddi_translations_dp; > > - n_edp_entries = ARRAY_SIZE(skl_ddi_translations_dp); > > - } > > - > > - ddi_translations_hdmi = skl_ddi_translations_hdmi; > > - n_hdmi_entries = ARRAY_SIZE(skl_ddi_translations_hdmi); > > - hdmi_default_entry = 7; > > + ddi_translations_dp = > > + skl_get_buf_trans_dp(dev, &n_dp_entries); > > + ddi_translations_edp = > > + skl_get_buf_trans_edp(dev, &n_edp_entries); > > + ddi_translations_hdmi = > > + skl_get_buf_trans_hdmi(dev, &n_hdmi_entries); > > + hdmi_default_entry = 8; > > } else if (IS_BROADWELL(dev)) { > > ddi_translations_fdi = bdw_ddi_translations_fdi; > > ddi_translations_dp = bdw_ddi_translations_dp; > > @@ -1806,8 +1975,49 @@ void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc) > > TRANS_CLK_SEL_DISABLED); > > } > > > > -void bxt_ddi_vswing_sequence(struct drm_device *dev, u32 level, > > - enum port port, int type) > > +static void skl_ddi_set_iboost(struct drm_device *dev, u32 level, > > + enum port port, int type) > > +{ > > + struct drm_i915_private *dev_priv = dev->dev_private; > > + const struct ddi_buf_trans *ddi_translations; > > + uint8_t iboost; > > + int n_entries; > > + u32 reg; > > + > > + if (type == INTEL_OUTPUT_DISPLAYPORT) { > > + ddi_translations = skl_get_buf_trans_dp(dev, &n_entries); > > + iboost = ddi_translations[port].i_boost; > > + } else if (type == INTEL_OUTPUT_EDP) { > > + ddi_translations = skl_get_buf_trans_edp(dev, &n_entries); > > + iboost = ddi_translations[port].i_boost; > > + } else if (type == INTEL_OUTPUT_HDMI) { > > + ddi_translations = skl_get_buf_trans_hdmi(dev, &n_entries); > > + iboost = ddi_translations[port].i_boost; > > + } else { > > + return; > > + } > > + > > + /* Make sure that the requested I_boost is valid */ > > + if (iboost && iboost != 0x1 && iboost != 0x3 && iboost != 0x7) { > > + DRM_ERROR("Invalid I_boost value %u\n", iboost); > > + return; > > + } > > + > > + reg = I915_READ(DISPIO_CR_TX_BMU_CR0); > > + reg &= ~BALANCE_LEG_MASK(port); > > + reg &= ~(1 << (BALANCE_LEG_DISABLE_SHIFT + port)); > > + > > + if (iboost) { > > + reg |= iboost << BALANCE_LEG_SHIFT(port); > > + } else { > > + reg |= 1 << (BALANCE_LEG_DISABLE_SHIFT + port); > > + } > > + > > + I915_WRITE(DISPIO_CR_TX_BMU_CR0, reg); > > +} > > + > > +static void bxt_ddi_vswing_sequence(struct drm_device *dev, u32 level, > > + enum port port, int type) > > { > > struct drm_i915_private *dev_priv = dev->dev_private; > > const struct bxt_ddi_buf_trans *ddi_translations; > > @@ -1867,6 +2077,73 @@ void bxt_ddi_vswing_sequence(struct drm_device *dev, u32 level, > > I915_WRITE(BXT_PORT_PCS_DW10_GRP(port), val); > > } > > > > +static uint32_t translate_signal_level(int signal_levels) > > +{ > > + uint32_t level; > > + > > + switch (signal_levels) { > > + default: > > + DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level: " > > + "0x%x\n", signal_levels); > > + case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0: > > + level = 0; > > + break; > > + case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_1: > > + level = 1; > > + break; > > + case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_2: > > + level = 2; > > + break; > > + case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_3: > > + level = 3; > > + break; > > + > > + case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_0: > > + level = 4; > > + break; > > + case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_1: > > + level = 5; > > + break; > > + case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_2: > > + level = 6; > > + break; > > + > > + case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_0: > > + level = 7; > > + break; > > + case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_1: > > + level = 8; > > + break; > > + > > + case DP_TRAIN_VOLTAGE_SWING_LEVEL_3 | DP_TRAIN_PRE_EMPH_LEVEL_0: > > + level = 9; > > + break; > > + } > > + > > + return level; > > +} > > + > > +uint32_t ddi_signal_levels(struct intel_dp *intel_dp) > > +{ > > + struct intel_digital_port *dport = dp_to_dig_port(intel_dp); > > + struct drm_device *dev = dport->base.base.dev; > > + struct intel_encoder *encoder = &dport->base; > > + uint8_t train_set = intel_dp->train_set[0]; > > + int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK | > > + DP_TRAIN_PRE_EMPHASIS_MASK); > > + enum port port = dport->port; > > + uint32_t level; > > + > > + level = translate_signal_level(signal_levels); > > + > > + if (IS_SKYLAKE(dev)) > > + skl_ddi_set_iboost(dev, level, port, encoder->type); > > + else if (IS_BROXTON(dev)) > > + bxt_ddi_vswing_sequence(dev, level, port, encoder->type); > > + > > + return DDI_BUF_TRANS_SELECT(level); > > +} > > + > > static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder) > > { > > struct drm_encoder *encoder = &intel_encoder->base; > > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c > > index f52eef138247..041e2d6dcc56 100644 > > --- a/drivers/gpu/drm/i915/intel_dp.c > > +++ b/drivers/gpu/drm/i915/intel_dp.c > > @@ -3417,92 +3417,6 @@ gen7_edp_signal_levels(uint8_t train_set) > > } > > } > > > > -/* Gen7.5's (HSW) DP voltage swing and pre-emphasis control */ > > -static uint32_t > > -hsw_signal_levels(uint8_t train_set) > > -{ > > - int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK | > > - DP_TRAIN_PRE_EMPHASIS_MASK); > > - switch (signal_levels) { > > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0: > > - return DDI_BUF_TRANS_SELECT(0); > > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_1: > > - return DDI_BUF_TRANS_SELECT(1); > > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_2: > > - return DDI_BUF_TRANS_SELECT(2); > > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_3: > > - return DDI_BUF_TRANS_SELECT(3); > > - > > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_0: > > - return DDI_BUF_TRANS_SELECT(4); > > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_1: > > - return DDI_BUF_TRANS_SELECT(5); > > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_2: > > - return DDI_BUF_TRANS_SELECT(6); > > - > > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_0: > > - return DDI_BUF_TRANS_SELECT(7); > > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_1: > > - return DDI_BUF_TRANS_SELECT(8); > > - > > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_3 | DP_TRAIN_PRE_EMPH_LEVEL_0: > > - return DDI_BUF_TRANS_SELECT(9); > > - default: > > - DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level:" > > - "0x%x\n", signal_levels); > > - return DDI_BUF_TRANS_SELECT(0); > > - } > > -} > > - > > -static void bxt_signal_levels(struct intel_dp *intel_dp) > > -{ > > - struct intel_digital_port *dport = dp_to_dig_port(intel_dp); > > - enum port port = dport->port; > > - struct drm_device *dev = dport->base.base.dev; > > - struct intel_encoder *encoder = &dport->base; > > - uint8_t train_set = intel_dp->train_set[0]; > > - uint32_t level = 0; > > - > > - int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK | > > - DP_TRAIN_PRE_EMPHASIS_MASK); > > - switch (signal_levels) { > > - default: > > - DRM_DEBUG_KMS("Unsupported voltage swing/pre-emph level\n"); > > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0: > > - level = 0; > > - break; > > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_1: > > - level = 1; > > - break; > > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_2: > > - level = 2; > > - break; > > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_3: > > - level = 3; > > - break; > > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_0: > > - level = 4; > > - break; > > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_1: > > - level = 5; > > - break; > > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_2: > > - level = 6; > > - break; > > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_0: > > - level = 7; > > - break; > > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_1: > > - level = 8; > > - break; > > - case DP_TRAIN_VOLTAGE_SWING_LEVEL_3 | DP_TRAIN_PRE_EMPH_LEVEL_0: > > - level = 9; > > - break; > > - } > > - > > - bxt_ddi_vswing_sequence(dev, level, port, encoder->type); > > -} > > - > > /* Properly updates "DP" with the correct signal levels. */ > > static void > > intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP) > > @@ -3510,22 +3424,20 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP) > > struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); > > enum port port = intel_dig_port->port; > > struct drm_device *dev = intel_dig_port->base.base.dev; > > - uint32_t signal_levels, mask; > > + uint32_t signal_levels, mask = 0; > > uint8_t train_set = intel_dp->train_set[0]; > > > > - if (IS_BROXTON(dev)) { > > - signal_levels = 0; > > - bxt_signal_levels(intel_dp); > > - mask = 0; > > - } else if (HAS_DDI(dev)) { > > - signal_levels = hsw_signal_levels(train_set); > > - mask = DDI_BUF_EMP_MASK; > > + if (HAS_DDI(dev)) { > > + signal_levels = ddi_signal_levels(intel_dp); > > + > > + if (IS_BROXTON(dev)) > > + signal_levels = 0; > > + else > > + mask = DDI_BUF_EMP_MASK; > > } else if (IS_CHERRYVIEW(dev)) { > > signal_levels = chv_signal_levels(intel_dp); > > - mask = 0; > > } else if (IS_VALLEYVIEW(dev)) { > > signal_levels = vlv_signal_levels(intel_dp); > > - mask = 0; > > } else if (IS_GEN7(dev) && port == PORT_A) { > > signal_levels = gen7_edp_signal_levels(train_set); > > mask = EDP_LINK_TRAIN_VOL_EMP_MASK_IVB; > > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h > > index bcafefcf048b..c6cbe8c602f9 100644 > > --- a/drivers/gpu/drm/i915/intel_drv.h > > +++ b/drivers/gpu/drm/i915/intel_drv.h > > @@ -950,8 +950,7 @@ void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder); > > void intel_ddi_clock_get(struct intel_encoder *encoder, > > struct intel_crtc_state *pipe_config); > > void intel_ddi_set_vc_payload_alloc(struct drm_crtc *crtc, bool state); > > -void bxt_ddi_vswing_sequence(struct drm_device *dev, u32 level, > > - enum port port, int type); > > +uint32_t ddi_signal_levels(struct intel_dp *intel_dp); > > > > /* intel_frontbuffer.c */ > > void intel_fb_obj_invalidate(struct drm_i915_gem_object *obj, > > > > -- > - Antti > > _______________________________________________ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
On Mon, Jun 29, 2015 at 06:12:54PM +0200, Daniel Vetter wrote: > On Mon, Jun 29, 2015 at 01:35:06PM +0300, Antti Koskipää wrote: > > Looks fine to me. > > > > Reviewed-by: Antti Koskipää <antti.koskipaa@linux.intel.com> > > > > > > On 06/25/2015 11:11 AM, David Weinehall wrote: > > > This patch adds support for 0.85V VccIO on Skylake Y, > > > separate buffer translation tables for Skylake U, > > > and support for I_boost for the entries that needs this. > > > > > > Changes in v2: > > > * Refactored the code a bit to move all DDI signal level setup to > > > intel_ddi.c > > For next time around please split out refactoring from actual code > changes, makes it a pain to review. And if this blows up in a > regression that's really annoying. Also please head checkpatch's > suggestions a bit more, I fixed that up when applying. OK, noted. Kind regards, David
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 491ef0cfcb0b..09a57a584f5f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2415,6 +2415,14 @@ struct drm_i915_cmd_table { /* ULX machines are also considered ULT. */ #define IS_HSW_ULX(dev) (INTEL_DEVID(dev) == 0x0A0E || \ INTEL_DEVID(dev) == 0x0A1E) +#define IS_SKL_ULT(dev) (INTEL_DEVID(dev) == 0x1906 || \ + INTEL_DEVID(dev) == 0x1913 || \ + INTEL_DEVID(dev) == 0x1916 || \ + INTEL_DEVID(dev) == 0x1921 || \ + INTEL_DEVID(dev) == 0x1926) +#define IS_SKL_ULX(dev) (INTEL_DEVID(dev) == 0x190E || \ + INTEL_DEVID(dev) == 0x1915 || \ + INTEL_DEVID(dev) == 0x191E) #define IS_PRELIMINARY_HW(intel_info) ((intel_info)->is_preliminary) #define SKL_REVID_A0 (0x0) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 0b979ad16d41..fb63ead2b8eb 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1382,6 +1382,18 @@ enum skl_disp_power_wells { _PORT_TX_DW14_LN0_C) + \ _BXT_LANE_OFFSET(lane)) +/* UAIMI scratch pad register 1 */ +#define UAIMI_SPR1 0x4F074 +/* SKL VccIO mask */ +#define SKL_VCCIO_MASK 0x1 +/* SKL balance leg register */ +#define DISPIO_CR_TX_BMU_CR0 0x6C00C +/* I_boost values */ +#define BALANCE_LEG_SHIFT(port) (8+3*(port)) +#define BALANCE_LEG_MASK(port) (7<<(8+3*(port))) +/* Balance leg disable bits */ +#define BALANCE_LEG_DISABLE_SHIFT 23 + /* * Fence registers */ diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 31b29e8781ac..08f89299b572 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -31,6 +31,7 @@ struct ddi_buf_trans { u32 trans1; /* balance leg enable, de-emph level */ u32 trans2; /* vref sel, vswing */ + u8 i_boost; /* SKL: I_boost; valid: 0x0, 0x1, 0x3, 0x7 */ }; /* HDMI/DVI modes ignore everything but the last 2 items. So we share @@ -38,134 +39,213 @@ struct ddi_buf_trans { * automatically adapt to HDMI connections as well */ static const struct ddi_buf_trans hsw_ddi_translations_dp[] = { - { 0x00FFFFFF, 0x0006000E }, - { 0x00D75FFF, 0x0005000A }, - { 0x00C30FFF, 0x00040006 }, - { 0x80AAAFFF, 0x000B0000 }, - { 0x00FFFFFF, 0x0005000A }, - { 0x00D75FFF, 0x000C0004 }, - { 0x80C30FFF, 0x000B0000 }, - { 0x00FFFFFF, 0x00040006 }, - { 0x80D75FFF, 0x000B0000 }, + { 0x00FFFFFF, 0x0006000E, 0x0 }, + { 0x00D75FFF, 0x0005000A, 0x0 }, + { 0x00C30FFF, 0x00040006, 0x0 }, + { 0x80AAAFFF, 0x000B0000, 0x0 }, + { 0x00FFFFFF, 0x0005000A, 0x0 }, + { 0x00D75FFF, 0x000C0004, 0x0 }, + { 0x80C30FFF, 0x000B0000, 0x0 }, + { 0x00FFFFFF, 0x00040006, 0x0 }, + { 0x80D75FFF, 0x000B0000, 0x0 }, }; static const struct ddi_buf_trans hsw_ddi_translations_fdi[] = { - { 0x00FFFFFF, 0x0007000E }, - { 0x00D75FFF, 0x000F000A }, - { 0x00C30FFF, 0x00060006 }, - { 0x00AAAFFF, 0x001E0000 }, - { 0x00FFFFFF, 0x000F000A }, - { 0x00D75FFF, 0x00160004 }, - { 0x00C30FFF, 0x001E0000 }, - { 0x00FFFFFF, 0x00060006 }, - { 0x00D75FFF, 0x001E0000 }, + { 0x00FFFFFF, 0x0007000E, 0x0 }, + { 0x00D75FFF, 0x000F000A, 0x0 }, + { 0x00C30FFF, 0x00060006, 0x0 }, + { 0x00AAAFFF, 0x001E0000, 0x0 }, + { 0x00FFFFFF, 0x000F000A, 0x0 }, + { 0x00D75FFF, 0x00160004, 0x0 }, + { 0x00C30FFF, 0x001E0000, 0x0 }, + { 0x00FFFFFF, 0x00060006, 0x0 }, + { 0x00D75FFF, 0x001E0000, 0x0 }, }; static const struct ddi_buf_trans hsw_ddi_translations_hdmi[] = { /* Idx NT mV d T mV d db */ - { 0x00FFFFFF, 0x0006000E }, /* 0: 400 400 0 */ - { 0x00E79FFF, 0x000E000C }, /* 1: 400 500 2 */ - { 0x00D75FFF, 0x0005000A }, /* 2: 400 600 3.5 */ - { 0x00FFFFFF, 0x0005000A }, /* 3: 600 600 0 */ - { 0x00E79FFF, 0x001D0007 }, /* 4: 600 750 2 */ - { 0x00D75FFF, 0x000C0004 }, /* 5: 600 900 3.5 */ - { 0x00FFFFFF, 0x00040006 }, /* 6: 800 800 0 */ - { 0x80E79FFF, 0x00030002 }, /* 7: 800 1000 2 */ - { 0x00FFFFFF, 0x00140005 }, /* 8: 850 850 0 */ - { 0x00FFFFFF, 0x000C0004 }, /* 9: 900 900 0 */ - { 0x00FFFFFF, 0x001C0003 }, /* 10: 950 950 0 */ - { 0x80FFFFFF, 0x00030002 }, /* 11: 1000 1000 0 */ + { 0x00FFFFFF, 0x0006000E, 0x0 },/* 0: 400 400 0 */ + { 0x00E79FFF, 0x000E000C, 0x0 },/* 1: 400 500 2 */ + { 0x00D75FFF, 0x0005000A, 0x0 },/* 2: 400 600 3.5 */ + { 0x00FFFFFF, 0x0005000A, 0x0 },/* 3: 600 600 0 */ + { 0x00E79FFF, 0x001D0007, 0x0 },/* 4: 600 750 2 */ + { 0x00D75FFF, 0x000C0004, 0x0 },/* 5: 600 900 3.5 */ + { 0x00FFFFFF, 0x00040006, 0x0 },/* 6: 800 800 0 */ + { 0x80E79FFF, 0x00030002, 0x0 },/* 7: 800 1000 2 */ + { 0x00FFFFFF, 0x00140005, 0x0 },/* 8: 850 850 0 */ + { 0x00FFFFFF, 0x000C0004, 0x0 },/* 9: 900 900 0 */ + { 0x00FFFFFF, 0x001C0003, 0x0 },/* 10: 950 950 0 */ + { 0x80FFFFFF, 0x00030002, 0x0 },/* 11: 1000 1000 0 */ }; static const struct ddi_buf_trans bdw_ddi_translations_edp[] = { - { 0x00FFFFFF, 0x00000012 }, - { 0x00EBAFFF, 0x00020011 }, - { 0x00C71FFF, 0x0006000F }, - { 0x00AAAFFF, 0x000E000A }, - { 0x00FFFFFF, 0x00020011 }, - { 0x00DB6FFF, 0x0005000F }, - { 0x00BEEFFF, 0x000A000C }, - { 0x00FFFFFF, 0x0005000F }, - { 0x00DB6FFF, 0x000A000C }, + { 0x00FFFFFF, 0x00000012, 0x0 }, + { 0x00EBAFFF, 0x00020011, 0x0 }, + { 0x00C71FFF, 0x0006000F, 0x0 }, + { 0x00AAAFFF, 0x000E000A, 0x0 }, + { 0x00FFFFFF, 0x00020011, 0x0 }, + { 0x00DB6FFF, 0x0005000F, 0x0 }, + { 0x00BEEFFF, 0x000A000C, 0x0 }, + { 0x00FFFFFF, 0x0005000F, 0x0 }, + { 0x00DB6FFF, 0x000A000C, 0x0 }, }; static const struct ddi_buf_trans bdw_ddi_translations_dp[] = { - { 0x00FFFFFF, 0x0007000E }, - { 0x00D75FFF, 0x000E000A }, - { 0x00BEFFFF, 0x00140006 }, - { 0x80B2CFFF, 0x001B0002 }, - { 0x00FFFFFF, 0x000E000A }, - { 0x00DB6FFF, 0x00160005 }, - { 0x80C71FFF, 0x001A0002 }, - { 0x00F7DFFF, 0x00180004 }, - { 0x80D75FFF, 0x001B0002 }, + { 0x00FFFFFF, 0x0007000E, 0x0 }, + { 0x00D75FFF, 0x000E000A, 0x0 }, + { 0x00BEFFFF, 0x00140006, 0x0 }, + { 0x80B2CFFF, 0x001B0002, 0x0 }, + { 0x00FFFFFF, 0x000E000A, 0x0 }, + { 0x00DB6FFF, 0x00160005, 0x0 }, + { 0x80C71FFF, 0x001A0002, 0x0 }, + { 0x00F7DFFF, 0x00180004, 0x0 }, + { 0x80D75FFF, 0x001B0002, 0x0 }, }; static const struct ddi_buf_trans bdw_ddi_translations_fdi[] = { - { 0x00FFFFFF, 0x0001000E }, - { 0x00D75FFF, 0x0004000A }, - { 0x00C30FFF, 0x00070006 }, - { 0x00AAAFFF, 0x000C0000 }, - { 0x00FFFFFF, 0x0004000A }, - { 0x00D75FFF, 0x00090004 }, - { 0x00C30FFF, 0x000C0000 }, - { 0x00FFFFFF, 0x00070006 }, - { 0x00D75FFF, 0x000C0000 }, + { 0x00FFFFFF, 0x0001000E, 0x0 }, + { 0x00D75FFF, 0x0004000A, 0x0 }, + { 0x00C30FFF, 0x00070006, 0x0 }, + { 0x00AAAFFF, 0x000C0000, 0x0 }, + { 0x00FFFFFF, 0x0004000A, 0x0 }, + { 0x00D75FFF, 0x00090004, 0x0 }, + { 0x00C30FFF, 0x000C0000, 0x0 }, + { 0x00FFFFFF, 0x00070006, 0x0 }, + { 0x00D75FFF, 0x000C0000, 0x0 }, }; static const struct ddi_buf_trans bdw_ddi_translations_hdmi[] = { /* Idx NT mV d T mV df db */ - { 0x00FFFFFF, 0x0007000E }, /* 0: 400 400 0 */ - { 0x00D75FFF, 0x000E000A }, /* 1: 400 600 3.5 */ - { 0x00BEFFFF, 0x00140006 }, /* 2: 400 800 6 */ - { 0x00FFFFFF, 0x0009000D }, /* 3: 450 450 0 */ - { 0x00FFFFFF, 0x000E000A }, /* 4: 600 600 0 */ - { 0x00D7FFFF, 0x00140006 }, /* 5: 600 800 2.5 */ - { 0x80CB2FFF, 0x001B0002 }, /* 6: 600 1000 4.5 */ - { 0x00FFFFFF, 0x00140006 }, /* 7: 800 800 0 */ - { 0x80E79FFF, 0x001B0002 }, /* 8: 800 1000 2 */ - { 0x80FFFFFF, 0x001B0002 }, /* 9: 1000 1000 0 */ + { 0x00FFFFFF, 0x0007000E, 0x0 },/* 0: 400 400 0 */ + { 0x00D75FFF, 0x000E000A, 0x0 },/* 1: 400 600 3.5 */ + { 0x00BEFFFF, 0x00140006, 0x0 },/* 2: 400 800 6 */ + { 0x00FFFFFF, 0x0009000D, 0x0 },/* 3: 450 450 0 */ + { 0x00FFFFFF, 0x000E000A, 0x0 },/* 4: 600 600 0 */ + { 0x00D7FFFF, 0x00140006, 0x0 },/* 5: 600 800 2.5 */ + { 0x80CB2FFF, 0x001B0002, 0x0 },/* 6: 600 1000 4.5 */ + { 0x00FFFFFF, 0x00140006, 0x0 },/* 7: 800 800 0 */ + { 0x80E79FFF, 0x001B0002, 0x0 },/* 8: 800 1000 2 */ + { 0x80FFFFFF, 0x001B0002, 0x0 },/* 9: 1000 1000 0 */ }; +/* Skylake H, S, and Skylake Y with 0.95V VccIO */ static const struct ddi_buf_trans skl_ddi_translations_dp[] = { - { 0x00000018, 0x000000a2 }, - { 0x00004014, 0x0000009B }, - { 0x00006012, 0x00000088 }, - { 0x00008010, 0x00000087 }, - { 0x00000018, 0x0000009B }, - { 0x00004014, 0x00000088 }, - { 0x00006012, 0x00000087 }, - { 0x00000018, 0x00000088 }, - { 0x00004014, 0x00000087 }, + { 0x00002016, 0x000000A0, 0x0 }, + { 0x00005012, 0x0000009B, 0x0 }, + { 0x00007011, 0x00000088, 0x0 }, + { 0x00009010, 0x000000C7, 0x0 }, + { 0x00002016, 0x0000009B, 0x0 }, + { 0x00005012, 0x00000088, 0x0 }, + { 0x00007011, 0x000000C7, 0x0 }, + { 0x00002016, 0x000000DF, 0x0 }, + { 0x00005012, 0x000000C7, 0x0 }, }; -/* eDP 1.4 low vswing translation parameters */ +/* Skylake U */ +static const struct ddi_buf_trans skl_u_ddi_translations_dp[] = { + { 0x00002016, 0x000000A2, 0x0 }, + { 0x00005012, 0x00000088, 0x0 }, + { 0x00007011, 0x00000087, 0x0 }, + { 0x80009010, 0x000000C7, 0x1 }, /* Uses I_boost */ + { 0x00002016, 0x0000009D, 0x0 }, + { 0x00005012, 0x000000C7, 0x0 }, + { 0x00007011, 0x000000C7, 0x0 }, + { 0x00002016, 0x00000088, 0x0 }, + { 0x00005012, 0x000000C7, 0x0 }, +}; + +/* Skylake Y with 0.85V VccIO */ +static const struct ddi_buf_trans skl_y_085v_ddi_translations_dp[] = { + { 0x00000018, 0x000000A2, 0x0 }, + { 0x00005012, 0x00000088, 0x0 }, + { 0x00007011, 0x00000087, 0x0 }, + { 0x80009010, 0x000000C7, 0x1 }, /* Uses I_boost */ + { 0x00000018, 0x0000009D, 0x0 }, + { 0x00005012, 0x000000C7, 0x0 }, + { 0x00007011, 0x000000C7, 0x0 }, + { 0x00000018, 0x00000088, 0x0 }, + { 0x00005012, 0x000000C7, 0x0 }, +}; + +/* + * Skylake H and S, and Skylake Y with 0.95V VccIO + * eDP 1.4 low vswing translation parameters + */ static const struct ddi_buf_trans skl_ddi_translations_edp[] = { - { 0x00000018, 0x000000a8 }, - { 0x00002016, 0x000000ab }, - { 0x00006012, 0x000000a2 }, - { 0x00008010, 0x00000088 }, - { 0x00000018, 0x000000ab }, - { 0x00004014, 0x000000a2 }, - { 0x00006012, 0x000000a6 }, - { 0x00000018, 0x000000a2 }, - { 0x00005013, 0x0000009c }, - { 0x00000018, 0x00000088 }, + { 0x00000018, 0x000000A8, 0x0 }, + { 0x00004013, 0x000000A9, 0x0 }, + { 0x00007011, 0x000000A2, 0x0 }, + { 0x00009010, 0x0000009C, 0x0 }, + { 0x00000018, 0x000000A9, 0x0 }, + { 0x00006013, 0x000000A2, 0x0 }, + { 0x00007011, 0x000000A6, 0x0 }, + { 0x00000018, 0x000000AB, 0x0 }, + { 0x00007013, 0x0000009F, 0x0 }, + { 0x00000018, 0x000000DF, 0x0 }, +}; + +/* + * Skylake U + * eDP 1.4 low vswing translation parameters + */ +static const struct ddi_buf_trans skl_u_ddi_translations_edp[] = { + { 0x00000018, 0x000000A8, 0x0 }, + { 0x00004013, 0x000000A9, 0x0 }, + { 0x00007011, 0x000000A2, 0x0 }, + { 0x00009010, 0x0000009C, 0x0 }, + { 0x00000018, 0x000000A9, 0x0 }, + { 0x00006013, 0x000000A2, 0x0 }, + { 0x00007011, 0x000000A6, 0x0 }, + { 0x00002016, 0x000000AB, 0x0 }, + { 0x00005013, 0x0000009F, 0x0 }, + { 0x00000018, 0x000000DF, 0x0 }, }; +/* + * Skylake Y with 0.95V VccIO + * eDP 1.4 low vswing translation parameters + */ +static const struct ddi_buf_trans skl_y_085v_ddi_translations_edp[] = { + { 0x00000018, 0x000000A8, 0x0 }, + { 0x00004013, 0x000000AB, 0x0 }, + { 0x00007011, 0x000000A4, 0x0 }, + { 0x00009010, 0x000000DF, 0x0 }, + { 0x00000018, 0x000000AA, 0x0 }, + { 0x00006013, 0x000000A4, 0x0 }, + { 0x00007011, 0x0000009D, 0x0 }, + { 0x00000018, 0x000000A0, 0x0 }, + { 0x00006012, 0x000000DF, 0x0 }, + { 0x00000018, 0x0000008A, 0x0 }, +}; +/* Skylake H, S and U, and Skylake Y with 0.95V VccIO */ static const struct ddi_buf_trans skl_ddi_translations_hdmi[] = { - { 0x00000018, 0x000000ac }, - { 0x00005012, 0x0000009d }, - { 0x00007011, 0x00000088 }, - { 0x00000018, 0x000000a1 }, - { 0x00000018, 0x00000098 }, - { 0x00004013, 0x00000088 }, - { 0x00006012, 0x00000087 }, - { 0x00000018, 0x000000df }, - { 0x00003015, 0x00000087 }, - { 0x00003015, 0x000000c7 }, - { 0x00000018, 0x000000c7 }, + { 0x00000018, 0x000000AC, 0x0 }, + { 0x00005012, 0x0000009D, 0x0 }, + { 0x00007011, 0x00000088, 0x0 }, + { 0x00000018, 0x000000A1, 0x0 }, + { 0x00000018, 0x00000098, 0x0 }, + { 0x00004013, 0x00000088, 0x0 }, + { 0x00006012, 0x00000087, 0x0 }, + { 0x00000018, 0x000000DF, 0x0 }, + { 0x00003015, 0x00000087, 0x0 }, /* Default */ + { 0x00003015, 0x000000C7, 0x0 }, + { 0x00000018, 0x000000C7, 0x0 }, +}; + +/* Skylake Y with 0.85V VccIO */ +static const struct ddi_buf_trans skl_y_085v_ddi_translations_hdmi[] = { + { 0x00000018, 0x000000A1, 0x0 }, + { 0x00005012, 0x000000DF, 0x0 }, + { 0x00007011, 0x00000084, 0x0 }, + { 0x00000018, 0x000000A4, 0x0 }, + { 0x00000018, 0x0000009D, 0x0 }, + { 0x00004013, 0x00000080, 0x0 }, + { 0x00006013, 0x000000C7, 0x0 }, + { 0x00000018, 0x0000008A, 0x0 }, + { 0x00003015, 0x000000C7, 0x0 }, /* Default */ + { 0x80003015, 0x000000C7, 0x7 }, /* Uses I_boost */ + { 0x00000018, 0x000000C7, 0x0 }, }; struct bxt_ddi_buf_trans { @@ -190,7 +270,7 @@ static const struct bxt_ddi_buf_trans bxt_ddi_translations_dp[] = { { 154, 0x9A, 0, 64, false }, /* 6: 600 6 */ { 102, 0x9A, 0, 128, false }, /* 7: 800 0 */ { 154, 0x9A, 0, 85, false }, /* 8: 800 3.5 */ - { 154, 0x9A, 1, 128, false }, /* 9: 1200 0 */ + { 154, 0x9A, 1, 128, false }, /* 9: 1200 0 */ }; /* BSpec has 2 recommended values - entries 0 and 8. @@ -210,6 +290,9 @@ static const struct bxt_ddi_buf_trans bxt_ddi_translations_hdmi[] = { { 154, 0x9A, 1, 128, true }, /* 9: 1200 0 */ }; +static void bxt_ddi_vswing_sequence(struct drm_device *dev, u32 level, + enum port port, int type); + static void ddi_get_encoder_port(struct intel_encoder *intel_encoder, struct intel_digital_port **dig_port, enum port *port) @@ -249,6 +332,99 @@ intel_dig_port_supports_hdmi(const struct intel_digital_port *intel_dig_port) return intel_dig_port->hdmi.hdmi_reg; } +static const struct ddi_buf_trans *skl_get_buf_trans_dp(struct drm_device *dev, + int *n_entries) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + const struct ddi_buf_trans *ddi_translations; + static int is_095v = -1; + + if (is_095v == -1) { + u32 spr1 = I915_READ(UAIMI_SPR1); + is_095v = spr1 & SKL_VCCIO_MASK; + } + + if (IS_SKL_ULX(dev) && !is_095v) { + ddi_translations = skl_y_085v_ddi_translations_dp; + *n_entries = ARRAY_SIZE(skl_y_085v_ddi_translations_dp); + } else if (IS_SKL_ULT(dev)) { + ddi_translations = skl_u_ddi_translations_dp; + *n_entries = ARRAY_SIZE(skl_u_ddi_translations_dp); + } else { + ddi_translations = skl_ddi_translations_dp; + *n_entries = ARRAY_SIZE(skl_ddi_translations_dp); + } + + return ddi_translations; +} + +static const struct ddi_buf_trans *skl_get_buf_trans_edp(struct drm_device *dev, + int *n_entries) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + const struct ddi_buf_trans *ddi_translations; + static int is_095v = -1; + + if (is_095v == -1) { + u32 spr1 = I915_READ(UAIMI_SPR1); + is_095v = spr1 & SKL_VCCIO_MASK; + } + + if (IS_SKL_ULX(dev) && !is_095v) { + if (dev_priv->edp_low_vswing) { + ddi_translations = skl_y_085v_ddi_translations_edp; + *n_entries = + ARRAY_SIZE(skl_y_085v_ddi_translations_edp); + } else { + ddi_translations = skl_y_085v_ddi_translations_dp; + *n_entries = + ARRAY_SIZE(skl_y_085v_ddi_translations_dp); + } + } else if (IS_SKL_ULT(dev)) { + if (dev_priv->edp_low_vswing) { + ddi_translations = skl_u_ddi_translations_edp; + *n_entries = ARRAY_SIZE(skl_u_ddi_translations_edp); + } else { + ddi_translations = skl_u_ddi_translations_dp; + *n_entries = ARRAY_SIZE(skl_u_ddi_translations_dp); + } + } else { + if (dev_priv->edp_low_vswing) { + ddi_translations = skl_ddi_translations_edp; + *n_entries = ARRAY_SIZE(skl_ddi_translations_edp); + } else { + ddi_translations = skl_ddi_translations_dp; + *n_entries = ARRAY_SIZE(skl_ddi_translations_dp); + } + } + + return ddi_translations; +} + +static const struct ddi_buf_trans * +skl_get_buf_trans_hdmi(struct drm_device *dev, + int *n_entries) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + const struct ddi_buf_trans *ddi_translations; + static int is_095v = -1; + + if (is_095v == -1) { + u32 spr1 = I915_READ(UAIMI_SPR1); + is_095v = spr1 & SKL_VCCIO_MASK; + } + + if (IS_SKL_ULX(dev) && !is_095v) { + ddi_translations = skl_y_085v_ddi_translations_hdmi; + *n_entries = ARRAY_SIZE(skl_y_085v_ddi_translations_hdmi); + } else { + ddi_translations = skl_ddi_translations_hdmi; + *n_entries = ARRAY_SIZE(skl_ddi_translations_hdmi); + } + + return ddi_translations; +} + /* * Starting with Haswell, DDI port buffers must be programmed with correct * values in advance. The buffer values are different for FDI and DP modes, @@ -279,20 +455,13 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port, INTEL_OUTPUT_HDMI); return; } else if (IS_SKYLAKE(dev)) { - ddi_translations_fdi = NULL; - ddi_translations_dp = skl_ddi_translations_dp; - n_dp_entries = ARRAY_SIZE(skl_ddi_translations_dp); - if (dev_priv->edp_low_vswing) { - ddi_translations_edp = skl_ddi_translations_edp; - n_edp_entries = ARRAY_SIZE(skl_ddi_translations_edp); - } else { - ddi_translations_edp = skl_ddi_translations_dp; - n_edp_entries = ARRAY_SIZE(skl_ddi_translations_dp); - } - - ddi_translations_hdmi = skl_ddi_translations_hdmi; - n_hdmi_entries = ARRAY_SIZE(skl_ddi_translations_hdmi); - hdmi_default_entry = 7; + ddi_translations_dp = + skl_get_buf_trans_dp(dev, &n_dp_entries); + ddi_translations_edp = + skl_get_buf_trans_edp(dev, &n_edp_entries); + ddi_translations_hdmi = + skl_get_buf_trans_hdmi(dev, &n_hdmi_entries); + hdmi_default_entry = 8; } else if (IS_BROADWELL(dev)) { ddi_translations_fdi = bdw_ddi_translations_fdi; ddi_translations_dp = bdw_ddi_translations_dp; @@ -1806,8 +1975,49 @@ void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc) TRANS_CLK_SEL_DISABLED); } -void bxt_ddi_vswing_sequence(struct drm_device *dev, u32 level, - enum port port, int type) +static void skl_ddi_set_iboost(struct drm_device *dev, u32 level, + enum port port, int type) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + const struct ddi_buf_trans *ddi_translations; + uint8_t iboost; + int n_entries; + u32 reg; + + if (type == INTEL_OUTPUT_DISPLAYPORT) { + ddi_translations = skl_get_buf_trans_dp(dev, &n_entries); + iboost = ddi_translations[port].i_boost; + } else if (type == INTEL_OUTPUT_EDP) { + ddi_translations = skl_get_buf_trans_edp(dev, &n_entries); + iboost = ddi_translations[port].i_boost; + } else if (type == INTEL_OUTPUT_HDMI) { + ddi_translations = skl_get_buf_trans_hdmi(dev, &n_entries); + iboost = ddi_translations[port].i_boost; + } else { + return; + } + + /* Make sure that the requested I_boost is valid */ + if (iboost && iboost != 0x1 && iboost != 0x3 && iboost != 0x7) { + DRM_ERROR("Invalid I_boost value %u\n", iboost); + return; + } + + reg = I915_READ(DISPIO_CR_TX_BMU_CR0); + reg &= ~BALANCE_LEG_MASK(port); + reg &= ~(1 << (BALANCE_LEG_DISABLE_SHIFT + port)); + + if (iboost) { + reg |= iboost << BALANCE_LEG_SHIFT(port); + } else { + reg |= 1 << (BALANCE_LEG_DISABLE_SHIFT + port); + } + + I915_WRITE(DISPIO_CR_TX_BMU_CR0, reg); +} + +static void bxt_ddi_vswing_sequence(struct drm_device *dev, u32 level, + enum port port, int type) { struct drm_i915_private *dev_priv = dev->dev_private; const struct bxt_ddi_buf_trans *ddi_translations; @@ -1867,6 +2077,73 @@ void bxt_ddi_vswing_sequence(struct drm_device *dev, u32 level, I915_WRITE(BXT_PORT_PCS_DW10_GRP(port), val); } +static uint32_t translate_signal_level(int signal_levels) +{ + uint32_t level; + + switch (signal_levels) { + default: + DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level: " + "0x%x\n", signal_levels); + case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0: + level = 0; + break; + case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_1: + level = 1; + break; + case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_2: + level = 2; + break; + case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_3: + level = 3; + break; + + case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_0: + level = 4; + break; + case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_1: + level = 5; + break; + case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_2: + level = 6; + break; + + case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_0: + level = 7; + break; + case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_1: + level = 8; + break; + + case DP_TRAIN_VOLTAGE_SWING_LEVEL_3 | DP_TRAIN_PRE_EMPH_LEVEL_0: + level = 9; + break; + } + + return level; +} + +uint32_t ddi_signal_levels(struct intel_dp *intel_dp) +{ + struct intel_digital_port *dport = dp_to_dig_port(intel_dp); + struct drm_device *dev = dport->base.base.dev; + struct intel_encoder *encoder = &dport->base; + uint8_t train_set = intel_dp->train_set[0]; + int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK | + DP_TRAIN_PRE_EMPHASIS_MASK); + enum port port = dport->port; + uint32_t level; + + level = translate_signal_level(signal_levels); + + if (IS_SKYLAKE(dev)) + skl_ddi_set_iboost(dev, level, port, encoder->type); + else if (IS_BROXTON(dev)) + bxt_ddi_vswing_sequence(dev, level, port, encoder->type); + + return DDI_BUF_TRANS_SELECT(level); +} + static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder) { struct drm_encoder *encoder = &intel_encoder->base; diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index f52eef138247..041e2d6dcc56 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -3417,92 +3417,6 @@ gen7_edp_signal_levels(uint8_t train_set) } } -/* Gen7.5's (HSW) DP voltage swing and pre-emphasis control */ -static uint32_t -hsw_signal_levels(uint8_t train_set) -{ - int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK | - DP_TRAIN_PRE_EMPHASIS_MASK); - switch (signal_levels) { - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0: - return DDI_BUF_TRANS_SELECT(0); - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_1: - return DDI_BUF_TRANS_SELECT(1); - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_2: - return DDI_BUF_TRANS_SELECT(2); - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_3: - return DDI_BUF_TRANS_SELECT(3); - - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_0: - return DDI_BUF_TRANS_SELECT(4); - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_1: - return DDI_BUF_TRANS_SELECT(5); - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_2: - return DDI_BUF_TRANS_SELECT(6); - - case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_0: - return DDI_BUF_TRANS_SELECT(7); - case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_1: - return DDI_BUF_TRANS_SELECT(8); - - case DP_TRAIN_VOLTAGE_SWING_LEVEL_3 | DP_TRAIN_PRE_EMPH_LEVEL_0: - return DDI_BUF_TRANS_SELECT(9); - default: - DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level:" - "0x%x\n", signal_levels); - return DDI_BUF_TRANS_SELECT(0); - } -} - -static void bxt_signal_levels(struct intel_dp *intel_dp) -{ - struct intel_digital_port *dport = dp_to_dig_port(intel_dp); - enum port port = dport->port; - struct drm_device *dev = dport->base.base.dev; - struct intel_encoder *encoder = &dport->base; - uint8_t train_set = intel_dp->train_set[0]; - uint32_t level = 0; - - int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK | - DP_TRAIN_PRE_EMPHASIS_MASK); - switch (signal_levels) { - default: - DRM_DEBUG_KMS("Unsupported voltage swing/pre-emph level\n"); - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0: - level = 0; - break; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_1: - level = 1; - break; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_2: - level = 2; - break; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_3: - level = 3; - break; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_0: - level = 4; - break; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_1: - level = 5; - break; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_2: - level = 6; - break; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_0: - level = 7; - break; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_1: - level = 8; - break; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_3 | DP_TRAIN_PRE_EMPH_LEVEL_0: - level = 9; - break; - } - - bxt_ddi_vswing_sequence(dev, level, port, encoder->type); -} - /* Properly updates "DP" with the correct signal levels. */ static void intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP) @@ -3510,22 +3424,20 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP) struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); enum port port = intel_dig_port->port; struct drm_device *dev = intel_dig_port->base.base.dev; - uint32_t signal_levels, mask; + uint32_t signal_levels, mask = 0; uint8_t train_set = intel_dp->train_set[0]; - if (IS_BROXTON(dev)) { - signal_levels = 0; - bxt_signal_levels(intel_dp); - mask = 0; - } else if (HAS_DDI(dev)) { - signal_levels = hsw_signal_levels(train_set); - mask = DDI_BUF_EMP_MASK; + if (HAS_DDI(dev)) { + signal_levels = ddi_signal_levels(intel_dp); + + if (IS_BROXTON(dev)) + signal_levels = 0; + else + mask = DDI_BUF_EMP_MASK; } else if (IS_CHERRYVIEW(dev)) { signal_levels = chv_signal_levels(intel_dp); - mask = 0; } else if (IS_VALLEYVIEW(dev)) { signal_levels = vlv_signal_levels(intel_dp); - mask = 0; } else if (IS_GEN7(dev) && port == PORT_A) { signal_levels = gen7_edp_signal_levels(train_set); mask = EDP_LINK_TRAIN_VOL_EMP_MASK_IVB; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index bcafefcf048b..c6cbe8c602f9 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -950,8 +950,7 @@ void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder); void intel_ddi_clock_get(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config); void intel_ddi_set_vc_payload_alloc(struct drm_crtc *crtc, bool state); -void bxt_ddi_vswing_sequence(struct drm_device *dev, u32 level, - enum port port, int type); +uint32_t ddi_signal_levels(struct intel_dp *intel_dp); /* intel_frontbuffer.c */ void intel_fb_obj_invalidate(struct drm_i915_gem_object *obj,
This patch adds support for 0.85V VccIO on Skylake Y, separate buffer translation tables for Skylake U, and support for I_boost for the entries that needs this. Changes in v2: * Refactored the code a bit to move all DDI signal level setup to intel_ddi.c Issue: VIZ-5677 Signed-off-by: David Weinehall <david.weinehall@linux.intel.com> --- drivers/gpu/drm/i915/i915_drv.h | 8 + drivers/gpu/drm/i915/i915_reg.h | 12 + drivers/gpu/drm/i915/intel_ddi.c | 507 ++++++++++++++++++++++++++++++--------- drivers/gpu/drm/i915/intel_dp.c | 104 +------- drivers/gpu/drm/i915/intel_drv.h | 3 +- 5 files changed, 421 insertions(+), 213 deletions(-)