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)
|
||||
{
|
||||
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_PERFCNT4_HI));
|
||||
}
|
||||
|
|
|
@ -1062,6 +1062,7 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
|
|||
|
||||
#define NOA_DATA _MMIO(0x986C)
|
||||
#define NOA_WRITE _MMIO(0x9888)
|
||||
#define GEN10_NOA_WRITE_HIGH _MMIO(0x9884)
|
||||
|
||||
#define _GEN7_PIPEA_DE_LOAD_SL 0x70068
|
||||
#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 i;
|
||||
u32 *dmc_payload;
|
||||
size_t fsize;
|
||||
|
||||
if (!fw)
|
||||
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*/
|
||||
css_header = (struct intel_css_header *)fw->data;
|
||||
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*/
|
||||
dmc_offset *= 4;
|
||||
readcount += dmc_offset;
|
||||
fsize += dmc_offset;
|
||||
if (fsize > fw->size)
|
||||
goto error_truncated;
|
||||
|
||||
/* Extract dmc_header information. */
|
||||
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. */
|
||||
nbytes = dmc_header->fw_size * 4;
|
||||
fsize += nbytes;
|
||||
if (fsize > fw->size)
|
||||
goto error_truncated;
|
||||
|
||||
if (nbytes > csr->max_fw_size) {
|
||||
DRM_ERROR("DMC FW too big (%u bytes)\n", nbytes);
|
||||
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);
|
||||
|
||||
error_truncated:
|
||||
DRM_ERROR("Truncated DMC firmware, rejecting.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
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_XBGR8888, .depth = 24, .num_planes = 2, .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_ABGR8888, .depth = 32, .num_planes = 2, .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, },
|
||||
{ .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 2,
|
||||
.cpp = { 4, 1, }, .hsub = 8, .vsub = 16, },
|
||||
{ .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 2,
|
||||
.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 *
|
||||
|
@ -11942,7 +11946,7 @@ intel_modeset_pipe_config(struct drm_crtc *crtc,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool intel_fuzzy_clock_check(int clock1, int clock2)
|
||||
bool intel_fuzzy_clock_check(int clock1, int clock2)
|
||||
{
|
||||
int diff;
|
||||
|
||||
|
|
|
@ -1742,6 +1742,7 @@ int vlv_force_pll_on(struct drm_i915_private *dev_priv, enum pipe pipe,
|
|||
const struct dpll *dpll);
|
||||
void vlv_force_pll_off(struct drm_i915_private *dev_priv, enum pipe pipe);
|
||||
int lpt_get_iclkip(struct drm_i915_private *dev_priv);
|
||||
bool intel_fuzzy_clock_check(int clock1, int clock2);
|
||||
|
||||
/* modesetting asserts */
|
||||
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) {
|
||||
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) {
|
||||
DRM_ERROR("Burst mode freq is less than computed\n");
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
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) {
|
||||
/* done in crtc_mode_set as the dpll_md reg must be written early */
|
||||
} 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)
|
||||
pipe_config->limited_color_range = true;
|
||||
|
||||
if (sdvox & SDVO_AUDIO_ENABLE)
|
||||
pipe_config->has_audio = true;
|
||||
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;
|
||||
}
|
||||
|
||||
if (intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_ENCODE,
|
||||
&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);
|
||||
}
|
||||
|
||||
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,
|
||||
const struct intel_crtc_state *old_crtc_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);
|
||||
u32 temp;
|
||||
|
||||
if (old_crtc_state->has_audio)
|
||||
intel_sdvo_disable_audio(intel_sdvo);
|
||||
|
||||
intel_sdvo_set_active_outputs(intel_sdvo, 0);
|
||||
if (0)
|
||||
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,
|
||||
DRM_MODE_DPMS_ON);
|
||||
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
|
||||
|
@ -2603,7 +2642,6 @@ static bool
|
|||
intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
|
||||
{
|
||||
struct drm_encoder *encoder = &intel_sdvo->base.base;
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->dev);
|
||||
struct drm_connector *connector;
|
||||
struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
|
||||
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;
|
||||
connector->connector_type = DRM_MODE_CONNECTOR_DVID;
|
||||
|
||||
/* gen3 doesn't do the hdmi bits in the SDVO register */
|
||||
if (INTEL_GEN(dev_priv) >= 4 &&
|
||||
intel_sdvo_is_hdmi_connector(intel_sdvo, device)) {
|
||||
if (intel_sdvo_is_hdmi_connector(intel_sdvo, device)) {
|
||||
connector->connector_type = DRM_MODE_CONNECTOR_HDMIA;
|
||||
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_SET_AUDIO_STAT 0x91
|
||||
#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_HBUF_INDEX_ELD 0
|
||||
#define SDVO_HBUF_INDEX_AVI_IF 1
|
||||
|
|
Loading…
Reference in New Issue