Commit c2f3850d authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'drm-fixes-2020-07-29' of git://anongit.freedesktop.org/drm/drm into master

Pull drm fixes from Dave Airlie:
 "The nouveau fixes missed the last pull by a few hours, and we had a
  few arm driver/panel/bridge fixes come in.

  This is possibly a bit more than I'm comfortable sending at this
  stage, but I've looked at each patch, the core + nouveau patches fix
  regressions, and the arm related ones are all around screens turning
  on and working, and are mostly trivial patches, the line count is
  mostly in comments.

  core:
   - fix possible use-after-free

  drm_fb_helper:
   - regression fix to use memcpy_io on bochs' sparc64

  nouveau:
   - format modifiers fixes
   - HDA regression fix
   - turing modesetting race fix

  of:
   - fix a double free

  dbi:
   - fix SPI Type 1 transfer

  mcde:
   - fix screen stability crash

  panel:
   - panel: fix display noise on auo,kd101n80-45na
   - panel: delay HPD checks for boe_nv133fhm_n61

  bridge:
   - bridge: drop connector check in nwl-dsi bridge
   - bridge: set proper bridge type for adv7511"

* tag 'drm-fixes-2020-07-29' of git://anongit.freedesktop.org/drm/drm:
  drm: hold gem reference until object is no longer accessed
  drm/dbi: Fix SPI Type 1 (9-bit) transfer
  drm/drm_fb_helper: fix fbdev with sparc64
  drm/mcde: Fix stability issue
  drm/bridge: nwl-dsi: Drop DRM_BRIDGE_ATTACH_NO_CONNECTOR check.
  drm/panel: Fix auo, kd101n80-45na horizontal noise on edges of panel
  drm: panel: simple: Delay HPD checking on boe_nv133fhm_n61 for 15 ms
  drm/bridge/adv7511: set the bridge type properly
  drm: of: Fix double-free bug
  drm/nouveau/fbcon: zero-initialise the mode_cmd2 structure
  drm/nouveau/fbcon: fix module unload when fbcon init has failed for some reason
  drm/nouveau/kms/tu102: wait for core update to complete when assigning windows
  drm/nouveau/kms/gf100: use correct format modifiers
  drm/nouveau/disp/gm200-: fix regression from HDA SOR selection changes
parents f227e3ec a4a2739b
...@@ -146,6 +146,7 @@ int bochs_kms_init(struct bochs_device *bochs) ...@@ -146,6 +146,7 @@ int bochs_kms_init(struct bochs_device *bochs)
bochs->dev->mode_config.preferred_depth = 24; bochs->dev->mode_config.preferred_depth = 24;
bochs->dev->mode_config.prefer_shadow = 0; bochs->dev->mode_config.prefer_shadow = 0;
bochs->dev->mode_config.prefer_shadow_fbdev = 1; bochs->dev->mode_config.prefer_shadow_fbdev = 1;
bochs->dev->mode_config.fbdev_use_iomem = true;
bochs->dev->mode_config.quirk_addfb_prefer_host_byte_order = true; bochs->dev->mode_config.quirk_addfb_prefer_host_byte_order = true;
bochs->dev->mode_config.funcs = &bochs_mode_funcs; bochs->dev->mode_config.funcs = &bochs_mode_funcs;
......
...@@ -1224,6 +1224,7 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id) ...@@ -1224,6 +1224,7 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
adv7511->bridge.funcs = &adv7511_bridge_funcs; adv7511->bridge.funcs = &adv7511_bridge_funcs;
adv7511->bridge.of_node = dev->of_node; adv7511->bridge.of_node = dev->of_node;
adv7511->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
drm_bridge_add(&adv7511->bridge); drm_bridge_add(&adv7511->bridge);
......
...@@ -917,11 +917,6 @@ static int nwl_dsi_bridge_attach(struct drm_bridge *bridge, ...@@ -917,11 +917,6 @@ static int nwl_dsi_bridge_attach(struct drm_bridge *bridge,
struct drm_panel *panel; struct drm_panel *panel;
int ret; int ret;
if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {
DRM_ERROR("Fix bridge driver to make connector optional!");
return -EINVAL;
}
ret = drm_of_find_panel_or_bridge(dsi->dev->of_node, 1, 0, &panel, ret = drm_of_find_panel_or_bridge(dsi->dev->of_node, 1, 0, &panel,
&panel_bridge); &panel_bridge);
if (ret) if (ret)
......
...@@ -399,7 +399,11 @@ static void drm_fb_helper_dirty_blit_real(struct drm_fb_helper *fb_helper, ...@@ -399,7 +399,11 @@ static void drm_fb_helper_dirty_blit_real(struct drm_fb_helper *fb_helper,
unsigned int y; unsigned int y;
for (y = clip->y1; y < clip->y2; y++) { for (y = clip->y1; y < clip->y2; y++) {
if (!fb_helper->dev->mode_config.fbdev_use_iomem)
memcpy(dst, src, len); memcpy(dst, src, len);
else
memcpy_toio((void __iomem *)dst, src, len);
src += fb->pitches[0]; src += fb->pitches[0];
dst += fb->pitches[0]; dst += fb->pitches[0];
} }
......
...@@ -871,9 +871,6 @@ drm_gem_flink_ioctl(struct drm_device *dev, void *data, ...@@ -871,9 +871,6 @@ drm_gem_flink_ioctl(struct drm_device *dev, void *data,
* @file_priv: drm file-private structure * @file_priv: drm file-private structure
* *
* Open an object using the global name, returning a handle and the size. * Open an object using the global name, returning a handle and the size.
*
* This handle (of course) holds a reference to the object, so the object
* will not go away until the handle is deleted.
*/ */
int int
drm_gem_open_ioctl(struct drm_device *dev, void *data, drm_gem_open_ioctl(struct drm_device *dev, void *data,
...@@ -898,14 +895,15 @@ drm_gem_open_ioctl(struct drm_device *dev, void *data, ...@@ -898,14 +895,15 @@ drm_gem_open_ioctl(struct drm_device *dev, void *data,
/* drm_gem_handle_create_tail unlocks dev->object_name_lock. */ /* drm_gem_handle_create_tail unlocks dev->object_name_lock. */
ret = drm_gem_handle_create_tail(file_priv, obj, &handle); ret = drm_gem_handle_create_tail(file_priv, obj, &handle);
drm_gem_object_put_unlocked(obj);
if (ret) if (ret)
return ret; goto err;
args->handle = handle; args->handle = handle;
args->size = obj->size; args->size = obj->size;
return 0; err:
drm_gem_object_put_unlocked(obj);
return ret;
} }
/** /**
......
...@@ -923,7 +923,7 @@ static int mipi_dbi_spi1_transfer(struct mipi_dbi *dbi, int dc, ...@@ -923,7 +923,7 @@ static int mipi_dbi_spi1_transfer(struct mipi_dbi *dbi, int dc,
} }
} }
tr.len = chunk; tr.len = chunk * 2;
len -= chunk; len -= chunk;
ret = spi_sync(spi, &m); ret = spi_sync(spi, &m);
......
...@@ -322,11 +322,9 @@ static int drm_of_lvds_get_remote_pixels_type( ...@@ -322,11 +322,9 @@ static int drm_of_lvds_get_remote_pixels_type(
* configurations by passing the endpoints explicitly to * configurations by passing the endpoints explicitly to
* drm_of_lvds_get_dual_link_pixel_order(). * drm_of_lvds_get_dual_link_pixel_order().
*/ */
if (!current_pt || pixels_type != current_pt) { if (!current_pt || pixels_type != current_pt)
of_node_put(remote_port);
return -EINVAL; return -EINVAL;
} }
}
return pixels_type; return pixels_type;
} }
......
...@@ -1060,9 +1060,14 @@ static void mcde_display_update(struct drm_simple_display_pipe *pipe, ...@@ -1060,9 +1060,14 @@ static void mcde_display_update(struct drm_simple_display_pipe *pipe,
*/ */
if (fb) { if (fb) {
mcde_set_extsrc(mcde, drm_fb_cma_get_gem_addr(fb, pstate, 0)); mcde_set_extsrc(mcde, drm_fb_cma_get_gem_addr(fb, pstate, 0));
if (!mcde->video_mode) if (!mcde->video_mode) {
/* Send a single frame using software sync */ /*
* Send a single frame using software sync if the flow
* is not active yet.
*/
if (mcde->flow_active == 0)
mcde_display_send_one_frame(mcde); mcde_display_send_one_frame(mcde);
}
dev_info_once(mcde->dev, "sent first display update\n"); dev_info_once(mcde->dev, "sent first display update\n");
} else { } else {
/* /*
......
...@@ -2073,7 +2073,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) ...@@ -2073,7 +2073,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
*/ */
if (core->assign_windows) { if (core->assign_windows) {
core->func->wndw.owner(core); core->func->wndw.owner(core);
core->func->update(core, interlock, false); nv50_disp_atomic_commit_core(state, interlock);
core->assign_windows = false; core->assign_windows = false;
interlock[NV50_DISP_INTERLOCK_CORE] = 0; interlock[NV50_DISP_INTERLOCK_CORE] = 0;
} }
...@@ -2506,7 +2506,7 @@ nv50_display_create(struct drm_device *dev) ...@@ -2506,7 +2506,7 @@ nv50_display_create(struct drm_device *dev)
if (disp->disp->object.oclass >= TU102_DISP) if (disp->disp->object.oclass >= TU102_DISP)
nouveau_display(dev)->format_modifiers = wndwc57e_modifiers; nouveau_display(dev)->format_modifiers = wndwc57e_modifiers;
else else
if (disp->disp->object.oclass >= GF110_DISP) if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_FERMI)
nouveau_display(dev)->format_modifiers = disp90xx_modifiers; nouveau_display(dev)->format_modifiers = disp90xx_modifiers;
else else
nouveau_display(dev)->format_modifiers = disp50xx_modifiers; nouveau_display(dev)->format_modifiers = disp50xx_modifiers;
......
...@@ -315,7 +315,7 @@ nouveau_fbcon_create(struct drm_fb_helper *helper, ...@@ -315,7 +315,7 @@ nouveau_fbcon_create(struct drm_fb_helper *helper,
struct drm_framebuffer *fb; struct drm_framebuffer *fb;
struct nouveau_channel *chan; struct nouveau_channel *chan;
struct nouveau_bo *nvbo; struct nouveau_bo *nvbo;
struct drm_mode_fb_cmd2 mode_cmd; struct drm_mode_fb_cmd2 mode_cmd = {};
int ret; int ret;
mode_cmd.width = sizes->surface_width; mode_cmd.width = sizes->surface_width;
...@@ -590,6 +590,7 @@ nouveau_fbcon_init(struct drm_device *dev) ...@@ -590,6 +590,7 @@ nouveau_fbcon_init(struct drm_device *dev)
drm_fb_helper_fini(&fbcon->helper); drm_fb_helper_fini(&fbcon->helper);
free: free:
kfree(fbcon); kfree(fbcon);
drm->fbcon = NULL;
return ret; return ret;
} }
......
...@@ -117,15 +117,6 @@ nvkm_outp_acquire_hda(struct nvkm_outp *outp, enum nvkm_ior_type type, ...@@ -117,15 +117,6 @@ nvkm_outp_acquire_hda(struct nvkm_outp *outp, enum nvkm_ior_type type,
{ {
struct nvkm_ior *ior; struct nvkm_ior *ior;
/* First preference is to reuse the OR that is currently armed
* on HW, if any, in order to prevent unnecessary switching.
*/
list_for_each_entry(ior, &outp->disp->ior, head) {
if (!ior->identity && !!ior->func->hda.hpd == hda &&
!ior->asy.outp && ior->arm.outp == outp)
return nvkm_outp_acquire_ior(outp, user, ior);
}
/* Failing that, a completely unused OR is the next best thing. */ /* Failing that, a completely unused OR is the next best thing. */
list_for_each_entry(ior, &outp->disp->ior, head) { list_for_each_entry(ior, &outp->disp->ior, head) {
if (!ior->identity && !!ior->func->hda.hpd == hda && if (!ior->identity && !!ior->func->hda.hpd == hda &&
...@@ -173,6 +164,27 @@ nvkm_outp_acquire(struct nvkm_outp *outp, u8 user, bool hda) ...@@ -173,6 +164,27 @@ nvkm_outp_acquire(struct nvkm_outp *outp, u8 user, bool hda)
return nvkm_outp_acquire_ior(outp, user, ior); return nvkm_outp_acquire_ior(outp, user, ior);
} }
/* First preference is to reuse the OR that is currently armed
* on HW, if any, in order to prevent unnecessary switching.
*/
list_for_each_entry(ior, &outp->disp->ior, head) {
if (!ior->identity && !ior->asy.outp && ior->arm.outp == outp) {
/*XXX: For various complicated reasons, we can't outright switch
* the boot-time OR on the first modeset without some fairly
* invasive changes.
*
* The systems that were fixed by modifying the OR selection
* code to account for HDA support shouldn't regress here as
* the HDA-enabled ORs match the relevant output's pad macro
* index, and the firmware seems to select an OR this way.
*
* This warning is to make it obvious if that proves wrong.
*/
WARN_ON(hda && !ior->func->hda.hpd);
return nvkm_outp_acquire_ior(outp, user, ior);
}
}
/* If we don't need HDA, first try to acquire an OR that doesn't /* If we don't need HDA, first try to acquire an OR that doesn't
* support it to leave free the ones that do. * support it to leave free the ones that do.
*/ */
......
...@@ -615,9 +615,9 @@ static const struct panel_desc boe_tv101wum_nl6_desc = { ...@@ -615,9 +615,9 @@ static const struct panel_desc boe_tv101wum_nl6_desc = {
static const struct drm_display_mode auo_kd101n80_45na_default_mode = { static const struct drm_display_mode auo_kd101n80_45na_default_mode = {
.clock = 157000, .clock = 157000,
.hdisplay = 1200, .hdisplay = 1200,
.hsync_start = 1200 + 80, .hsync_start = 1200 + 60,
.hsync_end = 1200 + 80 + 24, .hsync_end = 1200 + 60 + 24,
.htotal = 1200 + 80 + 24 + 36, .htotal = 1200 + 60 + 24 + 56,
.vdisplay = 1920, .vdisplay = 1920,
.vsync_start = 1920 + 16, .vsync_start = 1920 + 16,
.vsync_end = 1920 + 16 + 4, .vsync_end = 1920 + 16 + 4,
......
...@@ -1250,7 +1250,21 @@ static const struct panel_desc boe_nv133fhm_n61 = { ...@@ -1250,7 +1250,21 @@ static const struct panel_desc boe_nv133fhm_n61 = {
.height = 165, .height = 165,
}, },
.delay = { .delay = {
.hpd_absent_delay = 200, /*
* When power is first given to the panel there's a short
* spike on the HPD line. It was explained that this spike
* was until the TCON data download was complete. On
* one system this was measured at 8 ms. We'll put 15 ms
* in the prepare delay just to be safe and take it away
* from the hpd_absent_delay (which would otherwise be 200 ms)
* to handle this. That means:
* - If HPD isn't hooked up you still have 200 ms delay.
* - If HPD is hooked up we won't try to look at it for the
* first 15 ms.
*/
.prepare = 15,
.hpd_absent_delay = 185,
.unprepare = 500, .unprepare = 500,
}, },
.bus_format = MEDIA_BUS_FMT_RGB888_1X24, .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
......
...@@ -865,6 +865,18 @@ struct drm_mode_config { ...@@ -865,6 +865,18 @@ struct drm_mode_config {
*/ */
bool prefer_shadow_fbdev; bool prefer_shadow_fbdev;
/**
* @fbdev_use_iomem:
*
* Set to true if framebuffer reside in iomem.
* When set to true memcpy_toio() is used when copying the framebuffer in
* drm_fb_helper.drm_fb_helper_dirty_blit_real().
*
* FIXME: This should be replaced with a per-mapping is_iomem
* flag (like ttm does), and then used everywhere in fbdev code.
*/
bool fbdev_use_iomem;
/** /**
* @quirk_addfb_prefer_xbgr_30bpp: * @quirk_addfb_prefer_xbgr_30bpp:
* *
......
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