mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-10 23:20:05 +00:00
Merge tag 'drm-intel-fixes-2019-06-13' of git://anongit.freedesktop.org/drm/drm-intel into drm-fixes
drm/i915 fixes for v5.2-rc5: - Fix DMC firmware input validation to avoid buffer overflow - Fix perf register access whitelist for userspace - Fix DSI panel on GPD MicroPC - Fix per-pixel alpha with CCS - Fix HDMI audio for SDVO Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> From: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/87y325x22w.fsf@intel.com
This commit is contained in:
commit
febe80307d
@ -3005,6 +3005,7 @@ static bool gen8_is_valid_mux_addr(struct drm_i915_private *dev_priv, u32 addr)
|
|||||||
static bool gen10_is_valid_mux_addr(struct drm_i915_private *dev_priv, u32 addr)
|
static bool gen10_is_valid_mux_addr(struct drm_i915_private *dev_priv, u32 addr)
|
||||||
{
|
{
|
||||||
return gen8_is_valid_mux_addr(dev_priv, addr) ||
|
return gen8_is_valid_mux_addr(dev_priv, addr) ||
|
||||||
|
addr == i915_mmio_reg_offset(GEN10_NOA_WRITE_HIGH) ||
|
||||||
(addr >= i915_mmio_reg_offset(OA_PERFCNT3_LO) &&
|
(addr >= i915_mmio_reg_offset(OA_PERFCNT3_LO) &&
|
||||||
addr <= i915_mmio_reg_offset(OA_PERFCNT4_HI));
|
addr <= i915_mmio_reg_offset(OA_PERFCNT4_HI));
|
||||||
}
|
}
|
||||||
|
@ -1062,6 +1062,7 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
|
|||||||
|
|
||||||
#define NOA_DATA _MMIO(0x986C)
|
#define NOA_DATA _MMIO(0x986C)
|
||||||
#define NOA_WRITE _MMIO(0x9888)
|
#define NOA_WRITE _MMIO(0x9888)
|
||||||
|
#define GEN10_NOA_WRITE_HIGH _MMIO(0x9884)
|
||||||
|
|
||||||
#define _GEN7_PIPEA_DE_LOAD_SL 0x70068
|
#define _GEN7_PIPEA_DE_LOAD_SL 0x70068
|
||||||
#define _GEN7_PIPEB_DE_LOAD_SL 0x71068
|
#define _GEN7_PIPEB_DE_LOAD_SL 0x71068
|
||||||
|
@ -303,10 +303,17 @@ static u32 *parse_csr_fw(struct drm_i915_private *dev_priv,
|
|||||||
u32 dmc_offset = CSR_DEFAULT_FW_OFFSET, readcount = 0, nbytes;
|
u32 dmc_offset = CSR_DEFAULT_FW_OFFSET, readcount = 0, nbytes;
|
||||||
u32 i;
|
u32 i;
|
||||||
u32 *dmc_payload;
|
u32 *dmc_payload;
|
||||||
|
size_t fsize;
|
||||||
|
|
||||||
if (!fw)
|
if (!fw)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
fsize = sizeof(struct intel_css_header) +
|
||||||
|
sizeof(struct intel_package_header) +
|
||||||
|
sizeof(struct intel_dmc_header);
|
||||||
|
if (fsize > fw->size)
|
||||||
|
goto error_truncated;
|
||||||
|
|
||||||
/* Extract CSS Header information*/
|
/* Extract CSS Header information*/
|
||||||
css_header = (struct intel_css_header *)fw->data;
|
css_header = (struct intel_css_header *)fw->data;
|
||||||
if (sizeof(struct intel_css_header) !=
|
if (sizeof(struct intel_css_header) !=
|
||||||
@ -366,6 +373,9 @@ static u32 *parse_csr_fw(struct drm_i915_private *dev_priv,
|
|||||||
/* Convert dmc_offset into number of bytes. By default it is in dwords*/
|
/* Convert dmc_offset into number of bytes. By default it is in dwords*/
|
||||||
dmc_offset *= 4;
|
dmc_offset *= 4;
|
||||||
readcount += dmc_offset;
|
readcount += dmc_offset;
|
||||||
|
fsize += dmc_offset;
|
||||||
|
if (fsize > fw->size)
|
||||||
|
goto error_truncated;
|
||||||
|
|
||||||
/* Extract dmc_header information. */
|
/* Extract dmc_header information. */
|
||||||
dmc_header = (struct intel_dmc_header *)&fw->data[readcount];
|
dmc_header = (struct intel_dmc_header *)&fw->data[readcount];
|
||||||
@ -397,6 +407,10 @@ static u32 *parse_csr_fw(struct drm_i915_private *dev_priv,
|
|||||||
|
|
||||||
/* fw_size is in dwords, so multiplied by 4 to convert into bytes. */
|
/* fw_size is in dwords, so multiplied by 4 to convert into bytes. */
|
||||||
nbytes = dmc_header->fw_size * 4;
|
nbytes = dmc_header->fw_size * 4;
|
||||||
|
fsize += nbytes;
|
||||||
|
if (fsize > fw->size)
|
||||||
|
goto error_truncated;
|
||||||
|
|
||||||
if (nbytes > csr->max_fw_size) {
|
if (nbytes > csr->max_fw_size) {
|
||||||
DRM_ERROR("DMC FW too big (%u bytes)\n", nbytes);
|
DRM_ERROR("DMC FW too big (%u bytes)\n", nbytes);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -410,6 +424,10 @@ static u32 *parse_csr_fw(struct drm_i915_private *dev_priv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
return memcpy(dmc_payload, &fw->data[readcount], nbytes);
|
return memcpy(dmc_payload, &fw->data[readcount], nbytes);
|
||||||
|
|
||||||
|
error_truncated:
|
||||||
|
DRM_ERROR("Truncated DMC firmware, rejecting.\n");
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void intel_csr_runtime_pm_get(struct drm_i915_private *dev_priv)
|
static void intel_csr_runtime_pm_get(struct drm_i915_private *dev_priv)
|
||||||
|
@ -2432,10 +2432,14 @@ static unsigned int intel_fb_modifier_to_tiling(u64 fb_modifier)
|
|||||||
* main surface.
|
* main surface.
|
||||||
*/
|
*/
|
||||||
static const struct drm_format_info ccs_formats[] = {
|
static const struct drm_format_info ccs_formats[] = {
|
||||||
{ .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 2, .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, },
|
{ .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 2,
|
||||||
{ .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 2, .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, },
|
.cpp = { 4, 1, }, .hsub = 8, .vsub = 16, },
|
||||||
{ .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 2, .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, },
|
{ .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 2,
|
||||||
{ .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 2, .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, },
|
.cpp = { 4, 1, }, .hsub = 8, .vsub = 16, },
|
||||||
|
{ .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 2,
|
||||||
|
.cpp = { 4, 1, }, .hsub = 8, .vsub = 16, .has_alpha = true, },
|
||||||
|
{ .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 2,
|
||||||
|
.cpp = { 4, 1, }, .hsub = 8, .vsub = 16, .has_alpha = true, },
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct drm_format_info *
|
static const struct drm_format_info *
|
||||||
@ -11942,7 +11946,7 @@ encoder_retry:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool intel_fuzzy_clock_check(int clock1, int clock2)
|
bool intel_fuzzy_clock_check(int clock1, int clock2)
|
||||||
{
|
{
|
||||||
int diff;
|
int diff;
|
||||||
|
|
||||||
|
@ -1742,6 +1742,7 @@ int vlv_force_pll_on(struct drm_i915_private *dev_priv, enum pipe pipe,
|
|||||||
const struct dpll *dpll);
|
const struct dpll *dpll);
|
||||||
void vlv_force_pll_off(struct drm_i915_private *dev_priv, enum pipe pipe);
|
void vlv_force_pll_off(struct drm_i915_private *dev_priv, enum pipe pipe);
|
||||||
int lpt_get_iclkip(struct drm_i915_private *dev_priv);
|
int lpt_get_iclkip(struct drm_i915_private *dev_priv);
|
||||||
|
bool intel_fuzzy_clock_check(int clock1, int clock2);
|
||||||
|
|
||||||
/* modesetting asserts */
|
/* modesetting asserts */
|
||||||
void assert_panel_unlocked(struct drm_i915_private *dev_priv,
|
void assert_panel_unlocked(struct drm_i915_private *dev_priv,
|
||||||
|
@ -853,6 +853,17 @@ bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id)
|
|||||||
if (mipi_config->target_burst_mode_freq) {
|
if (mipi_config->target_burst_mode_freq) {
|
||||||
u32 bitrate = intel_dsi_bitrate(intel_dsi);
|
u32 bitrate = intel_dsi_bitrate(intel_dsi);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sometimes the VBT contains a slightly lower clock,
|
||||||
|
* then the bitrate we have calculated, in this case
|
||||||
|
* just replace it with the calculated bitrate.
|
||||||
|
*/
|
||||||
|
if (mipi_config->target_burst_mode_freq < bitrate &&
|
||||||
|
intel_fuzzy_clock_check(
|
||||||
|
mipi_config->target_burst_mode_freq,
|
||||||
|
bitrate))
|
||||||
|
mipi_config->target_burst_mode_freq = bitrate;
|
||||||
|
|
||||||
if (mipi_config->target_burst_mode_freq < bitrate) {
|
if (mipi_config->target_burst_mode_freq < bitrate) {
|
||||||
DRM_ERROR("Burst mode freq is less than computed\n");
|
DRM_ERROR("Burst mode freq is less than computed\n");
|
||||||
return false;
|
return false;
|
||||||
|
@ -916,6 +916,13 @@ static bool intel_sdvo_set_colorimetry(struct intel_sdvo *intel_sdvo,
|
|||||||
return intel_sdvo_set_value(intel_sdvo, SDVO_CMD_SET_COLORIMETRY, &mode, 1);
|
return intel_sdvo_set_value(intel_sdvo, SDVO_CMD_SET_COLORIMETRY, &mode, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool intel_sdvo_set_audio_state(struct intel_sdvo *intel_sdvo,
|
||||||
|
u8 audio_state)
|
||||||
|
{
|
||||||
|
return intel_sdvo_set_value(intel_sdvo, SDVO_CMD_SET_AUDIO_STAT,
|
||||||
|
&audio_state, 1);
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo)
|
static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo)
|
||||||
{
|
{
|
||||||
@ -1487,11 +1494,6 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder,
|
|||||||
else
|
else
|
||||||
sdvox |= SDVO_PIPE_SEL(crtc->pipe);
|
sdvox |= SDVO_PIPE_SEL(crtc->pipe);
|
||||||
|
|
||||||
if (crtc_state->has_audio) {
|
|
||||||
WARN_ON_ONCE(INTEL_GEN(dev_priv) < 4);
|
|
||||||
sdvox |= SDVO_AUDIO_ENABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (INTEL_GEN(dev_priv) >= 4) {
|
if (INTEL_GEN(dev_priv) >= 4) {
|
||||||
/* done in crtc_mode_set as the dpll_md reg must be written early */
|
/* done in crtc_mode_set as the dpll_md reg must be written early */
|
||||||
} else if (IS_I945G(dev_priv) || IS_I945GM(dev_priv) ||
|
} else if (IS_I945G(dev_priv) || IS_I945GM(dev_priv) ||
|
||||||
@ -1635,8 +1637,13 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder,
|
|||||||
if (sdvox & HDMI_COLOR_RANGE_16_235)
|
if (sdvox & HDMI_COLOR_RANGE_16_235)
|
||||||
pipe_config->limited_color_range = true;
|
pipe_config->limited_color_range = true;
|
||||||
|
|
||||||
if (sdvox & SDVO_AUDIO_ENABLE)
|
if (intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_AUDIO_STAT,
|
||||||
|
&val, 1)) {
|
||||||
|
u8 mask = SDVO_AUDIO_ELD_VALID | SDVO_AUDIO_PRESENCE_DETECT;
|
||||||
|
|
||||||
|
if ((val & mask) == mask)
|
||||||
pipe_config->has_audio = true;
|
pipe_config->has_audio = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_ENCODE,
|
if (intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_ENCODE,
|
||||||
&val, 1)) {
|
&val, 1)) {
|
||||||
@ -1647,6 +1654,32 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder,
|
|||||||
intel_sdvo_get_avi_infoframe(intel_sdvo, pipe_config);
|
intel_sdvo_get_avi_infoframe(intel_sdvo, pipe_config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void intel_sdvo_disable_audio(struct intel_sdvo *intel_sdvo)
|
||||||
|
{
|
||||||
|
intel_sdvo_set_audio_state(intel_sdvo, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void intel_sdvo_enable_audio(struct intel_sdvo *intel_sdvo,
|
||||||
|
const struct intel_crtc_state *crtc_state,
|
||||||
|
const struct drm_connector_state *conn_state)
|
||||||
|
{
|
||||||
|
const struct drm_display_mode *adjusted_mode =
|
||||||
|
&crtc_state->base.adjusted_mode;
|
||||||
|
struct drm_connector *connector = conn_state->connector;
|
||||||
|
u8 *eld = connector->eld;
|
||||||
|
|
||||||
|
eld[6] = drm_av_sync_delay(connector, adjusted_mode) / 2;
|
||||||
|
|
||||||
|
intel_sdvo_set_audio_state(intel_sdvo, 0);
|
||||||
|
|
||||||
|
intel_sdvo_write_infoframe(intel_sdvo, SDVO_HBUF_INDEX_ELD,
|
||||||
|
SDVO_HBUF_TX_DISABLED,
|
||||||
|
eld, drm_eld_size(eld));
|
||||||
|
|
||||||
|
intel_sdvo_set_audio_state(intel_sdvo, SDVO_AUDIO_ELD_VALID |
|
||||||
|
SDVO_AUDIO_PRESENCE_DETECT);
|
||||||
|
}
|
||||||
|
|
||||||
static void intel_disable_sdvo(struct intel_encoder *encoder,
|
static void intel_disable_sdvo(struct intel_encoder *encoder,
|
||||||
const struct intel_crtc_state *old_crtc_state,
|
const struct intel_crtc_state *old_crtc_state,
|
||||||
const struct drm_connector_state *conn_state)
|
const struct drm_connector_state *conn_state)
|
||||||
@ -1656,6 +1689,9 @@ static void intel_disable_sdvo(struct intel_encoder *encoder,
|
|||||||
struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc);
|
struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc);
|
||||||
u32 temp;
|
u32 temp;
|
||||||
|
|
||||||
|
if (old_crtc_state->has_audio)
|
||||||
|
intel_sdvo_disable_audio(intel_sdvo);
|
||||||
|
|
||||||
intel_sdvo_set_active_outputs(intel_sdvo, 0);
|
intel_sdvo_set_active_outputs(intel_sdvo, 0);
|
||||||
if (0)
|
if (0)
|
||||||
intel_sdvo_set_encoder_power_state(intel_sdvo,
|
intel_sdvo_set_encoder_power_state(intel_sdvo,
|
||||||
@ -1741,6 +1777,9 @@ static void intel_enable_sdvo(struct intel_encoder *encoder,
|
|||||||
intel_sdvo_set_encoder_power_state(intel_sdvo,
|
intel_sdvo_set_encoder_power_state(intel_sdvo,
|
||||||
DRM_MODE_DPMS_ON);
|
DRM_MODE_DPMS_ON);
|
||||||
intel_sdvo_set_active_outputs(intel_sdvo, intel_sdvo->attached_output);
|
intel_sdvo_set_active_outputs(intel_sdvo, intel_sdvo->attached_output);
|
||||||
|
|
||||||
|
if (pipe_config->has_audio)
|
||||||
|
intel_sdvo_enable_audio(intel_sdvo, pipe_config, conn_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum drm_mode_status
|
static enum drm_mode_status
|
||||||
@ -2603,7 +2642,6 @@ static bool
|
|||||||
intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
|
intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
|
||||||
{
|
{
|
||||||
struct drm_encoder *encoder = &intel_sdvo->base.base;
|
struct drm_encoder *encoder = &intel_sdvo->base.base;
|
||||||
struct drm_i915_private *dev_priv = to_i915(encoder->dev);
|
|
||||||
struct drm_connector *connector;
|
struct drm_connector *connector;
|
||||||
struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
|
struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
|
||||||
struct intel_connector *intel_connector;
|
struct intel_connector *intel_connector;
|
||||||
@ -2640,9 +2678,7 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
|
|||||||
encoder->encoder_type = DRM_MODE_ENCODER_TMDS;
|
encoder->encoder_type = DRM_MODE_ENCODER_TMDS;
|
||||||
connector->connector_type = DRM_MODE_CONNECTOR_DVID;
|
connector->connector_type = DRM_MODE_CONNECTOR_DVID;
|
||||||
|
|
||||||
/* gen3 doesn't do the hdmi bits in the SDVO register */
|
if (intel_sdvo_is_hdmi_connector(intel_sdvo, device)) {
|
||||||
if (INTEL_GEN(dev_priv) >= 4 &&
|
|
||||||
intel_sdvo_is_hdmi_connector(intel_sdvo, device)) {
|
|
||||||
connector->connector_type = DRM_MODE_CONNECTOR_HDMIA;
|
connector->connector_type = DRM_MODE_CONNECTOR_HDMIA;
|
||||||
intel_sdvo_connector->is_hdmi = true;
|
intel_sdvo_connector->is_hdmi = true;
|
||||||
}
|
}
|
||||||
|
@ -707,6 +707,9 @@ struct intel_sdvo_enhancements_arg {
|
|||||||
#define SDVO_CMD_GET_AUDIO_ENCRYPT_PREFER 0x90
|
#define SDVO_CMD_GET_AUDIO_ENCRYPT_PREFER 0x90
|
||||||
#define SDVO_CMD_SET_AUDIO_STAT 0x91
|
#define SDVO_CMD_SET_AUDIO_STAT 0x91
|
||||||
#define SDVO_CMD_GET_AUDIO_STAT 0x92
|
#define SDVO_CMD_GET_AUDIO_STAT 0x92
|
||||||
|
#define SDVO_AUDIO_ELD_VALID (1 << 0)
|
||||||
|
#define SDVO_AUDIO_PRESENCE_DETECT (1 << 1)
|
||||||
|
#define SDVO_AUDIO_CP_READY (1 << 2)
|
||||||
#define SDVO_CMD_SET_HBUF_INDEX 0x93
|
#define SDVO_CMD_SET_HBUF_INDEX 0x93
|
||||||
#define SDVO_HBUF_INDEX_ELD 0
|
#define SDVO_HBUF_INDEX_ELD 0
|
||||||
#define SDVO_HBUF_INDEX_AVI_IF 1
|
#define SDVO_HBUF_INDEX_AVI_IF 1
|
||||||
|
Loading…
x
Reference in New Issue
Block a user