Commit 9595930d authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-misc-fixes-2020-11-26' of ssh://git.freedesktop.org/git/drm/drm-misc into drm-fixes

A bunch of fixes for vc4 fixing some coexistence issue between wifi and
HDMI, unsupported modes, and vblank timeouts, a fix for ast to reload
the gamma LUT after changing the plane format and a double-free fix for
nouveau
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Maxime Ripard <maxime@cerno.tech>
Link: https://patchwork.freedesktop.org/patch/msgid/20201126085450.r3i7wvj7pizsa4l6@gilmour
parents d45618c2 2be65641
...@@ -76,6 +76,12 @@ properties: ...@@ -76,6 +76,12 @@ properties:
resets: resets:
maxItems: 1 maxItems: 1
wifi-2.4ghz-coexistence:
type: boolean
description: >
Should the pixel frequencies in the WiFi frequencies range be
avoided?
required: required:
- compatible - compatible
- reg - reg
......
...@@ -742,7 +742,6 @@ static void ast_crtc_dpms(struct drm_crtc *crtc, int mode) ...@@ -742,7 +742,6 @@ static void ast_crtc_dpms(struct drm_crtc *crtc, int mode)
case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_SUSPEND:
if (ast->tx_chip_type == AST_TX_DP501) if (ast->tx_chip_type == AST_TX_DP501)
ast_set_dp501_video_output(crtc->dev, 1); ast_set_dp501_video_output(crtc->dev, 1);
ast_crtc_load_lut(ast, crtc);
break; break;
case DRM_MODE_DPMS_OFF: case DRM_MODE_DPMS_OFF:
if (ast->tx_chip_type == AST_TX_DP501) if (ast->tx_chip_type == AST_TX_DP501)
...@@ -777,6 +776,21 @@ static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc, ...@@ -777,6 +776,21 @@ static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc,
return 0; return 0;
} }
static void
ast_crtc_helper_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state)
{
struct ast_private *ast = to_ast_private(crtc->dev);
struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc->state);
struct ast_crtc_state *old_ast_crtc_state = to_ast_crtc_state(old_crtc_state);
/*
* The gamma LUT has to be reloaded after changing the primary
* plane's color format.
*/
if (old_ast_crtc_state->format != ast_crtc_state->format)
ast_crtc_load_lut(ast, crtc);
}
static void static void
ast_crtc_helper_atomic_enable(struct drm_crtc *crtc, ast_crtc_helper_atomic_enable(struct drm_crtc *crtc,
struct drm_crtc_state *old_crtc_state) struct drm_crtc_state *old_crtc_state)
...@@ -830,6 +844,7 @@ ast_crtc_helper_atomic_disable(struct drm_crtc *crtc, ...@@ -830,6 +844,7 @@ ast_crtc_helper_atomic_disable(struct drm_crtc *crtc,
static const struct drm_crtc_helper_funcs ast_crtc_helper_funcs = { static const struct drm_crtc_helper_funcs ast_crtc_helper_funcs = {
.atomic_check = ast_crtc_helper_atomic_check, .atomic_check = ast_crtc_helper_atomic_check,
.atomic_flush = ast_crtc_helper_atomic_flush,
.atomic_enable = ast_crtc_helper_atomic_enable, .atomic_enable = ast_crtc_helper_atomic_enable,
.atomic_disable = ast_crtc_helper_atomic_disable, .atomic_disable = ast_crtc_helper_atomic_disable,
}; };
......
...@@ -558,8 +558,10 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan, ...@@ -558,8 +558,10 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan,
NV_PRINTK(err, cli, "validating bo list\n"); NV_PRINTK(err, cli, "validating bo list\n");
validate_fini(op, chan, NULL, NULL); validate_fini(op, chan, NULL, NULL);
return ret; return ret;
} else if (ret > 0) {
*apply_relocs = true;
} }
*apply_relocs = ret;
return 0; return 0;
} }
...@@ -662,7 +664,6 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli, ...@@ -662,7 +664,6 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli,
nouveau_bo_wr32(nvbo, r->reloc_bo_offset >> 2, data); nouveau_bo_wr32(nvbo, r->reloc_bo_offset >> 2, data);
} }
u_free(reloc);
return ret; return ret;
} }
...@@ -872,9 +873,10 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, ...@@ -872,9 +873,10 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
break; break;
} }
} }
u_free(reloc);
} }
out_prevalid: out_prevalid:
if (!IS_ERR(reloc))
u_free(reloc);
u_free(bo); u_free(bo);
u_free(push); u_free(push);
......
...@@ -219,6 +219,7 @@ struct vc4_dev { ...@@ -219,6 +219,7 @@ struct vc4_dev {
struct drm_modeset_lock ctm_state_lock; struct drm_modeset_lock ctm_state_lock;
struct drm_private_obj ctm_manager; struct drm_private_obj ctm_manager;
struct drm_private_obj hvs_channels;
struct drm_private_obj load_tracker; struct drm_private_obj load_tracker;
/* List of vc4_debugfs_info_entry for adding to debugfs once /* List of vc4_debugfs_info_entry for adding to debugfs once
...@@ -531,6 +532,9 @@ struct vc4_crtc_state { ...@@ -531,6 +532,9 @@ struct vc4_crtc_state {
unsigned int top; unsigned int top;
unsigned int bottom; unsigned int bottom;
} margins; } margins;
/* Transitional state below, only valid during atomic commits */
bool update_muxing;
}; };
#define VC4_HVS_CHANNEL_DISABLED ((unsigned int)-1) #define VC4_HVS_CHANNEL_DISABLED ((unsigned int)-1)
......
...@@ -760,12 +760,54 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) ...@@ -760,12 +760,54 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
{ {
} }
#define WIFI_2_4GHz_CH1_MIN_FREQ 2400000000ULL
#define WIFI_2_4GHz_CH1_MAX_FREQ 2422000000ULL
static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
{
struct drm_display_mode *mode = &crtc_state->adjusted_mode;
struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
unsigned long long pixel_rate = mode->clock * 1000;
unsigned long long tmds_rate;
if (vc4_hdmi->variant->unsupported_odd_h_timings &&
((mode->hdisplay % 2) || (mode->hsync_start % 2) ||
(mode->hsync_end % 2) || (mode->htotal % 2)))
return -EINVAL;
/*
* The 1440p@60 pixel rate is in the same range than the first
* WiFi channel (between 2.4GHz and 2.422GHz with 22MHz
* bandwidth). Slightly lower the frequency to bring it out of
* the WiFi range.
*/
tmds_rate = pixel_rate * 10;
if (vc4_hdmi->disable_wifi_frequencies &&
(tmds_rate >= WIFI_2_4GHz_CH1_MIN_FREQ &&
tmds_rate <= WIFI_2_4GHz_CH1_MAX_FREQ)) {
mode->clock = 238560;
pixel_rate = mode->clock * 1000;
}
if (pixel_rate > vc4_hdmi->variant->max_pixel_clock)
return -EINVAL;
return 0;
}
static enum drm_mode_status static enum drm_mode_status
vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder, vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
const struct drm_display_mode *mode) const struct drm_display_mode *mode)
{ {
struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
if (vc4_hdmi->variant->unsupported_odd_h_timings &&
((mode->hdisplay % 2) || (mode->hsync_start % 2) ||
(mode->hsync_end % 2) || (mode->htotal % 2)))
return MODE_H_ILLEGAL;
if ((mode->clock * 1000) > vc4_hdmi->variant->max_pixel_clock) if ((mode->clock * 1000) > vc4_hdmi->variant->max_pixel_clock)
return MODE_CLOCK_HIGH; return MODE_CLOCK_HIGH;
...@@ -773,6 +815,7 @@ vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder, ...@@ -773,6 +815,7 @@ vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
} }
static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = { static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = {
.atomic_check = vc4_hdmi_encoder_atomic_check,
.mode_valid = vc4_hdmi_encoder_mode_valid, .mode_valid = vc4_hdmi_encoder_mode_valid,
.disable = vc4_hdmi_encoder_disable, .disable = vc4_hdmi_encoder_disable,
.enable = vc4_hdmi_encoder_enable, .enable = vc4_hdmi_encoder_enable,
...@@ -1694,6 +1737,9 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) ...@@ -1694,6 +1737,9 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
vc4_hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW; vc4_hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW;
} }
vc4_hdmi->disable_wifi_frequencies =
of_property_read_bool(dev->of_node, "wifi-2.4ghz-coexistence");
pm_runtime_enable(dev); pm_runtime_enable(dev);
drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS); drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
...@@ -1817,6 +1863,7 @@ static const struct vc4_hdmi_variant bcm2711_hdmi0_variant = { ...@@ -1817,6 +1863,7 @@ static const struct vc4_hdmi_variant bcm2711_hdmi0_variant = {
PHY_LANE_2, PHY_LANE_2,
PHY_LANE_CK, PHY_LANE_CK,
}, },
.unsupported_odd_h_timings = true,
.init_resources = vc5_hdmi_init_resources, .init_resources = vc5_hdmi_init_resources,
.csc_setup = vc5_hdmi_csc_setup, .csc_setup = vc5_hdmi_csc_setup,
...@@ -1842,6 +1889,7 @@ static const struct vc4_hdmi_variant bcm2711_hdmi1_variant = { ...@@ -1842,6 +1889,7 @@ static const struct vc4_hdmi_variant bcm2711_hdmi1_variant = {
PHY_LANE_CK, PHY_LANE_CK,
PHY_LANE_2, PHY_LANE_2,
}, },
.unsupported_odd_h_timings = true,
.init_resources = vc5_hdmi_init_resources, .init_resources = vc5_hdmi_init_resources,
.csc_setup = vc5_hdmi_csc_setup, .csc_setup = vc5_hdmi_csc_setup,
......
...@@ -62,6 +62,9 @@ struct vc4_hdmi_variant { ...@@ -62,6 +62,9 @@ struct vc4_hdmi_variant {
*/ */
enum vc4_hdmi_phy_channel phy_lane_mapping[4]; enum vc4_hdmi_phy_channel phy_lane_mapping[4];
/* The BCM2711 cannot deal with odd horizontal pixel timings */
bool unsupported_odd_h_timings;
/* Callback to get the resources (memory region, interrupts, /* Callback to get the resources (memory region, interrupts,
* clocks, etc) for that variant. * clocks, etc) for that variant.
*/ */
...@@ -139,6 +142,14 @@ struct vc4_hdmi { ...@@ -139,6 +142,14 @@ struct vc4_hdmi {
int hpd_gpio; int hpd_gpio;
bool hpd_active_low; bool hpd_active_low;
/*
* On some systems (like the RPi4), some modes are in the same
* frequency range than the WiFi channels (1440p@60Hz for
* example). Should we take evasive actions because that system
* has a wifi adapter?
*/
bool disable_wifi_frequencies;
struct cec_adapter *cec_adap; struct cec_adapter *cec_adap;
struct cec_msg cec_rx_msg; struct cec_msg cec_rx_msg;
bool cec_tx_ok; bool cec_tx_ok;
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment