Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux
Pull drm gixes from Dave Airlie: - exynos: infinite loop regressions fixed - i915: one regression - radeon: one race condition on monitor probing - noveau: two regressions - tegra: one vblank regression fix * 'drm-fixes' of git://people.freedesktop.org/~airlied/linux: drm/tegra: dc: Add missing call to drm_vblank_on() drm/nouveau/nv50/disp: Fix modeset on G94 drm/gk20a/fb: fix setting of large page size bit drm/radeon: add locking around atombios scratch space usage drm/i915: Fix obj->map_and_fenceable across tiling changes drm/exynos: fix possible infinite loop issue drm/exynos: g2d: fix null pointer dereference drm/exynos: resolve infinite loop issue on non multi-platform drm/exynos: resolve infinite loop issue on multi-platform
This commit is contained in:
commit
e061167151
|
@ -495,6 +495,12 @@ static struct component_match *exynos_drm_match_add(struct device *dev)
|
|||
|
||||
mutex_lock(&drm_component_lock);
|
||||
|
||||
/* Do not retry to probe if there is no any kms driver regitered. */
|
||||
if (list_empty(&drm_component_list)) {
|
||||
mutex_unlock(&drm_component_lock);
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
list_for_each_entry(cdev, &drm_component_list, list) {
|
||||
/*
|
||||
* Add components to master only in case that crtc and
|
||||
|
@ -585,10 +591,21 @@ static int exynos_drm_platform_probe(struct platform_device *pdev)
|
|||
goto err_unregister_mixer_drv;
|
||||
#endif
|
||||
|
||||
match = exynos_drm_match_add(&pdev->dev);
|
||||
if (IS_ERR(match)) {
|
||||
ret = PTR_ERR(match);
|
||||
goto err_unregister_hdmi_drv;
|
||||
}
|
||||
|
||||
ret = component_master_add_with_match(&pdev->dev, &exynos_drm_ops,
|
||||
match);
|
||||
if (ret < 0)
|
||||
goto err_unregister_hdmi_drv;
|
||||
|
||||
#ifdef CONFIG_DRM_EXYNOS_G2D
|
||||
ret = platform_driver_register(&g2d_driver);
|
||||
if (ret < 0)
|
||||
goto err_unregister_hdmi_drv;
|
||||
goto err_del_component_master;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DRM_EXYNOS_FIMC
|
||||
|
@ -619,23 +636,9 @@ static int exynos_drm_platform_probe(struct platform_device *pdev)
|
|||
goto err_unregister_ipp_drv;
|
||||
#endif
|
||||
|
||||
match = exynos_drm_match_add(&pdev->dev);
|
||||
if (IS_ERR(match)) {
|
||||
ret = PTR_ERR(match);
|
||||
goto err_unregister_resources;
|
||||
}
|
||||
|
||||
ret = component_master_add_with_match(&pdev->dev, &exynos_drm_ops,
|
||||
match);
|
||||
if (ret < 0)
|
||||
goto err_unregister_resources;
|
||||
|
||||
return ret;
|
||||
|
||||
err_unregister_resources:
|
||||
|
||||
#ifdef CONFIG_DRM_EXYNOS_IPP
|
||||
exynos_platform_device_ipp_unregister();
|
||||
err_unregister_ipp_drv:
|
||||
platform_driver_unregister(&ipp_driver);
|
||||
err_unregister_gsc_drv:
|
||||
|
@ -658,9 +661,11 @@ err_unregister_g2d_drv:
|
|||
|
||||
#ifdef CONFIG_DRM_EXYNOS_G2D
|
||||
platform_driver_unregister(&g2d_driver);
|
||||
err_unregister_hdmi_drv:
|
||||
err_del_component_master:
|
||||
#endif
|
||||
component_master_del(&pdev->dev, &exynos_drm_ops);
|
||||
|
||||
err_unregister_hdmi_drv:
|
||||
#ifdef CONFIG_DRM_EXYNOS_HDMI
|
||||
platform_driver_unregister(&hdmi_driver);
|
||||
err_unregister_mixer_drv:
|
||||
|
@ -741,6 +746,18 @@ static int exynos_drm_init(void)
|
|||
{
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Register device object only in case of Exynos SoC.
|
||||
*
|
||||
* Below codes resolves temporarily infinite loop issue incurred
|
||||
* by Exynos drm driver when using multi-platform kernel.
|
||||
* So these codes will be replaced with more generic way later.
|
||||
*/
|
||||
if (!of_machine_is_compatible("samsung,exynos3") &&
|
||||
!of_machine_is_compatible("samsung,exynos4") &&
|
||||
!of_machine_is_compatible("samsung,exynos5"))
|
||||
return -ENODEV;
|
||||
|
||||
exynos_drm_pdev = platform_device_register_simple("exynos-drm", -1,
|
||||
NULL, 0);
|
||||
if (IS_ERR(exynos_drm_pdev))
|
||||
|
|
|
@ -302,9 +302,12 @@ static void g2d_fini_cmdlist(struct g2d_data *g2d)
|
|||
struct exynos_drm_subdrv *subdrv = &g2d->subdrv;
|
||||
|
||||
kfree(g2d->cmdlist_node);
|
||||
dma_free_attrs(subdrv->drm_dev->dev, G2D_CMDLIST_POOL_SIZE,
|
||||
g2d->cmdlist_pool_virt,
|
||||
g2d->cmdlist_pool, &g2d->cmdlist_dma_attrs);
|
||||
|
||||
if (g2d->cmdlist_pool_virt && g2d->cmdlist_pool) {
|
||||
dma_free_attrs(subdrv->drm_dev->dev, G2D_CMDLIST_POOL_SIZE,
|
||||
g2d->cmdlist_pool_virt,
|
||||
g2d->cmdlist_pool, &g2d->cmdlist_dma_attrs);
|
||||
}
|
||||
}
|
||||
|
||||
static struct g2d_cmdlist_node *g2d_get_cmdlist(struct g2d_data *g2d)
|
||||
|
|
|
@ -364,22 +364,9 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
|
|||
* has to also include the unfenced register the GPU uses
|
||||
* whilst executing a fenced command for an untiled object.
|
||||
*/
|
||||
|
||||
obj->map_and_fenceable =
|
||||
!i915_gem_obj_ggtt_bound(obj) ||
|
||||
(i915_gem_obj_ggtt_offset(obj) +
|
||||
obj->base.size <= dev_priv->gtt.mappable_end &&
|
||||
i915_gem_object_fence_ok(obj, args->tiling_mode));
|
||||
|
||||
/* Rebind if we need a change of alignment */
|
||||
if (!obj->map_and_fenceable) {
|
||||
u32 unfenced_align =
|
||||
i915_gem_get_gtt_alignment(dev, obj->base.size,
|
||||
args->tiling_mode,
|
||||
false);
|
||||
if (i915_gem_obj_ggtt_offset(obj) & (unfenced_align - 1))
|
||||
ret = i915_gem_object_ggtt_unbind(obj);
|
||||
}
|
||||
if (obj->map_and_fenceable &&
|
||||
!i915_gem_object_fence_ok(obj, args->tiling_mode))
|
||||
ret = i915_gem_object_ggtt_unbind(obj);
|
||||
|
||||
if (ret == 0) {
|
||||
obj->fence_dirty =
|
||||
|
|
|
@ -26,6 +26,20 @@ struct gk20a_fb_priv {
|
|||
struct nouveau_fb base;
|
||||
};
|
||||
|
||||
static int
|
||||
gk20a_fb_init(struct nouveau_object *object)
|
||||
{
|
||||
struct gk20a_fb_priv *priv = (void *)object;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fb_init(&priv->base);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
nv_mask(priv, 0x100c80, 0x00000001, 0x00000000); /* 128KiB lpg */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
gk20a_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
struct nouveau_oclass *oclass, void *data, u32 size,
|
||||
|
@ -48,7 +62,7 @@ gk20a_fb_oclass = &(struct nouveau_fb_impl) {
|
|||
.base.ofuncs = &(struct nouveau_ofuncs) {
|
||||
.ctor = gk20a_fb_ctor,
|
||||
.dtor = _nouveau_fb_dtor,
|
||||
.init = _nouveau_fb_init,
|
||||
.init = gk20a_fb_init,
|
||||
.fini = _nouveau_fb_fini,
|
||||
},
|
||||
.memtype = nvc0_fb_memtype_valid,
|
||||
|
|
|
@ -790,6 +790,22 @@ nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, bool update)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nv50_crtc_set_raster_vblank_dmi(struct nouveau_crtc *nv_crtc, u32 usec)
|
||||
{
|
||||
struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev);
|
||||
u32 *push;
|
||||
|
||||
push = evo_wait(mast, 8);
|
||||
if (!push)
|
||||
return -ENOMEM;
|
||||
|
||||
evo_mthd(push, 0x0828 + (nv_crtc->index * 0x400), 1);
|
||||
evo_data(push, usec);
|
||||
evo_kick(push, mast);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nv50_crtc_set_color_vibrance(struct nouveau_crtc *nv_crtc, bool update)
|
||||
{
|
||||
|
@ -1104,14 +1120,14 @@ nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode,
|
|||
evo_mthd(push, 0x0804 + (nv_crtc->index * 0x400), 2);
|
||||
evo_data(push, 0x00800000 | mode->clock);
|
||||
evo_data(push, (ilace == 2) ? 2 : 0);
|
||||
evo_mthd(push, 0x0810 + (nv_crtc->index * 0x400), 8);
|
||||
evo_mthd(push, 0x0810 + (nv_crtc->index * 0x400), 6);
|
||||
evo_data(push, 0x00000000);
|
||||
evo_data(push, (vactive << 16) | hactive);
|
||||
evo_data(push, ( vsynce << 16) | hsynce);
|
||||
evo_data(push, (vblanke << 16) | hblanke);
|
||||
evo_data(push, (vblanks << 16) | hblanks);
|
||||
evo_data(push, (vblan2e << 16) | vblan2s);
|
||||
evo_data(push, vblankus);
|
||||
evo_mthd(push, 0x082c + (nv_crtc->index * 0x400), 1);
|
||||
evo_data(push, 0x00000000);
|
||||
evo_mthd(push, 0x0900 + (nv_crtc->index * 0x400), 2);
|
||||
evo_data(push, 0x00000311);
|
||||
|
@ -1141,6 +1157,11 @@ nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode,
|
|||
nv_connector = nouveau_crtc_connector_get(nv_crtc);
|
||||
nv50_crtc_set_dither(nv_crtc, false);
|
||||
nv50_crtc_set_scale(nv_crtc, false);
|
||||
|
||||
/* G94 only accepts this after setting scale */
|
||||
if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA)
|
||||
nv50_crtc_set_raster_vblank_dmi(nv_crtc, vblankus);
|
||||
|
||||
nv50_crtc_set_color_vibrance(nv_crtc, false);
|
||||
nv50_crtc_set_image(nv_crtc, crtc->primary->fb, x, y, false);
|
||||
return 0;
|
||||
|
|
|
@ -1217,7 +1217,7 @@ free:
|
|||
return ret;
|
||||
}
|
||||
|
||||
int atom_execute_table(struct atom_context *ctx, int index, uint32_t * params)
|
||||
int atom_execute_table_scratch_unlocked(struct atom_context *ctx, int index, uint32_t * params)
|
||||
{
|
||||
int r;
|
||||
|
||||
|
@ -1238,6 +1238,15 @@ int atom_execute_table(struct atom_context *ctx, int index, uint32_t * params)
|
|||
return r;
|
||||
}
|
||||
|
||||
int atom_execute_table(struct atom_context *ctx, int index, uint32_t * params)
|
||||
{
|
||||
int r;
|
||||
mutex_lock(&ctx->scratch_mutex);
|
||||
r = atom_execute_table_scratch_unlocked(ctx, index, params);
|
||||
mutex_unlock(&ctx->scratch_mutex);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int atom_iio_len[] = { 1, 2, 3, 3, 3, 3, 4, 4, 4, 3 };
|
||||
|
||||
static void atom_index_iio(struct atom_context *ctx, int base)
|
||||
|
|
|
@ -125,6 +125,7 @@ struct card_info {
|
|||
struct atom_context {
|
||||
struct card_info *card;
|
||||
struct mutex mutex;
|
||||
struct mutex scratch_mutex;
|
||||
void *bios;
|
||||
uint32_t cmd_table, data_table;
|
||||
uint16_t *iio;
|
||||
|
@ -145,6 +146,7 @@ extern int atom_debug;
|
|||
|
||||
struct atom_context *atom_parse(struct card_info *, void *);
|
||||
int atom_execute_table(struct atom_context *, int, uint32_t *);
|
||||
int atom_execute_table_scratch_unlocked(struct atom_context *, int, uint32_t *);
|
||||
int atom_asic_init(struct atom_context *);
|
||||
void atom_destroy(struct atom_context *);
|
||||
bool atom_parse_data_header(struct atom_context *ctx, int index, uint16_t *size,
|
||||
|
|
|
@ -100,6 +100,7 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan,
|
|||
memset(&args, 0, sizeof(args));
|
||||
|
||||
mutex_lock(&chan->mutex);
|
||||
mutex_lock(&rdev->mode_info.atom_context->scratch_mutex);
|
||||
|
||||
base = (unsigned char *)(rdev->mode_info.atom_context->scratch + 1);
|
||||
|
||||
|
@ -113,7 +114,7 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan,
|
|||
if (ASIC_IS_DCE4(rdev))
|
||||
args.v2.ucHPD_ID = chan->rec.hpd;
|
||||
|
||||
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
|
||||
atom_execute_table_scratch_unlocked(rdev->mode_info.atom_context, index, (uint32_t *)&args);
|
||||
|
||||
*ack = args.v1.ucReplyStatus;
|
||||
|
||||
|
@ -147,6 +148,7 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan,
|
|||
|
||||
r = recv_bytes;
|
||||
done:
|
||||
mutex_unlock(&rdev->mode_info.atom_context->scratch_mutex);
|
||||
mutex_unlock(&chan->mutex);
|
||||
|
||||
return r;
|
||||
|
|
|
@ -48,6 +48,7 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan,
|
|||
memset(&args, 0, sizeof(args));
|
||||
|
||||
mutex_lock(&chan->mutex);
|
||||
mutex_lock(&rdev->mode_info.atom_context->scratch_mutex);
|
||||
|
||||
base = (unsigned char *)rdev->mode_info.atom_context->scratch;
|
||||
|
||||
|
@ -82,7 +83,7 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan,
|
|||
args.ucSlaveAddr = slave_addr << 1;
|
||||
args.ucLineNumber = chan->rec.i2c_id;
|
||||
|
||||
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
|
||||
atom_execute_table_scratch_unlocked(rdev->mode_info.atom_context, index, (uint32_t *)&args);
|
||||
|
||||
/* error */
|
||||
if (args.ucStatus != HW_ASSISTED_I2C_STATUS_SUCCESS) {
|
||||
|
@ -95,6 +96,7 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan,
|
|||
radeon_atom_copy_swap(buf, base, num, false);
|
||||
|
||||
done:
|
||||
mutex_unlock(&rdev->mode_info.atom_context->scratch_mutex);
|
||||
mutex_unlock(&chan->mutex);
|
||||
|
||||
return r;
|
||||
|
|
|
@ -952,6 +952,7 @@ int radeon_atombios_init(struct radeon_device *rdev)
|
|||
}
|
||||
|
||||
mutex_init(&rdev->mode_info.atom_context->mutex);
|
||||
mutex_init(&rdev->mode_info.atom_context->scratch_mutex);
|
||||
radeon_atom_initialize_bios_scratch_regs(rdev->ddev);
|
||||
atom_allocate_fb_scratch(rdev->mode_info.atom_context);
|
||||
return 0;
|
||||
|
|
|
@ -736,7 +736,6 @@ static const struct drm_crtc_funcs tegra_crtc_funcs = {
|
|||
|
||||
static void tegra_crtc_disable(struct drm_crtc *crtc)
|
||||
{
|
||||
struct tegra_dc *dc = to_tegra_dc(crtc);
|
||||
struct drm_device *drm = crtc->dev;
|
||||
struct drm_plane *plane;
|
||||
|
||||
|
@ -752,7 +751,7 @@ static void tegra_crtc_disable(struct drm_crtc *crtc)
|
|||
}
|
||||
}
|
||||
|
||||
drm_vblank_off(drm, dc->pipe);
|
||||
drm_crtc_vblank_off(crtc);
|
||||
}
|
||||
|
||||
static bool tegra_crtc_mode_fixup(struct drm_crtc *crtc,
|
||||
|
@ -841,8 +840,6 @@ static int tegra_crtc_mode_set(struct drm_crtc *crtc,
|
|||
u32 value;
|
||||
int err;
|
||||
|
||||
drm_vblank_pre_modeset(crtc->dev, dc->pipe);
|
||||
|
||||
err = tegra_crtc_setup_clk(crtc, mode);
|
||||
if (err) {
|
||||
dev_err(dc->dev, "failed to setup clock for CRTC: %d\n", err);
|
||||
|
@ -896,6 +893,8 @@ static void tegra_crtc_prepare(struct drm_crtc *crtc)
|
|||
unsigned int syncpt;
|
||||
unsigned long value;
|
||||
|
||||
drm_crtc_vblank_off(crtc);
|
||||
|
||||
/* hardware initialization */
|
||||
reset_control_deassert(dc->rst);
|
||||
usleep_range(10000, 20000);
|
||||
|
@ -943,7 +942,7 @@ static void tegra_crtc_commit(struct drm_crtc *crtc)
|
|||
value = GENERAL_ACT_REQ | WIN_A_ACT_REQ;
|
||||
tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
|
||||
|
||||
drm_vblank_post_modeset(crtc->dev, dc->pipe);
|
||||
drm_crtc_vblank_on(crtc);
|
||||
}
|
||||
|
||||
static void tegra_crtc_load_lut(struct drm_crtc *crtc)
|
||||
|
|
Loading…
Reference in a new issue