提交 64ccccf8 编写于 作者: L Linus Torvalds

Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux

Pull drm fixes from Dave Airlie:
 "Radeon, nouveau, exynos, intel, mgag200..

  Not all strictly regressions but there was probably only one patch I'd
  have really left out and it didn't seem worth respinning exynos to
  avoid it, the line change count is quite low.

   radeon: regressions + more dynamic powermanagement fixes, since DPM
     is a new feature, and off by default I'd prefer to keep merging
     fixes since it has a large userbase already and I'd like to keep
     them on mainline

   nouveau: is mostly regression fixes

   i915: is a regression fix since Daniel is on holidays I've merged it.

   mgag200: I've picked a bunch of targetted fixes from a big bunch of
     distro patches,

   exynos: build fixes mostly, one regression fix

  I expect things will slow right down now, I may send on the intel
  early quirk from Jesse separatly, since I think the x86 maintainers
  acked it"

* 'drm-fixes' of git://people.freedesktop.org/~airlied/linux: (37 commits)
  drm/i915: fix missed hunk after GT access breakage
  drm/radeon/dpm: re-enable cac control on SI
  drm/radeon/dpm: fix calculations in si_calculate_leakage_for_v_and_t_formula
  drm: fix 64 bit drm fixed point helpers
  drm/radeon/atom: initialize more atom interpretor elements to 0
  drm/nouveau: fix semaphore dmabuf obj
  drm/nouveau/vm: make vm refcount into a kref
  drm/nv31/mpeg: don't recognize nv3x cards as having nv44 graph class
  drm/nv40/mpeg: write magic value to channel object to make it work
  drm/nouveau: fix size check for cards without vm
  drm/nv50-/disp: remove dcb_outp_match call, and related variables
  drm/nva3-/disp: fix hda eld writing, needs to be padded
  drm/nv31/mpeg: fix mpeg engine initialization
  drm/nv50/mc: include vp in the fb error reporting mask
  drm/nouveau: fix null pointer dereference in poll_changed
  drm/nv50/gpio: post-nv92 cards have 32 interrupt lines
  drm/nvc0/fb: take lock in nvc0_ram_put()
  drm/nouveau/core: xtensa firmware size needs to be 0x40000 no matter what
  drm/mgag200: Fix LUT programming for 16bpp
  drm/mgag200: Fix framebuffer pitch calculation
  ...
......@@ -15,7 +15,6 @@
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include "exynos_drm_drv.h"
......
......@@ -12,7 +12,6 @@
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
......
......@@ -14,7 +14,6 @@
#include <drm/drmP.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/of_device.h>
......@@ -130,7 +129,6 @@ static const struct of_device_id fimd_driver_dt_match[] = {
.data = &exynos5_fimd_driver_data },
{},
};
MODULE_DEVICE_TABLE(of, fimd_driver_dt_match);
#endif
static inline struct fimd_driver_data *drm_fimd_get_driver_data(
......@@ -1082,7 +1080,6 @@ static struct platform_device_id fimd_driver_ids[] = {
},
{},
};
MODULE_DEVICE_TABLE(platform, fimd_driver_ids);
static const struct dev_pm_ops fimd_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(fimd_suspend, fimd_resume)
......
......@@ -8,7 +8,6 @@
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/interrupt.h>
......@@ -806,9 +805,20 @@ static void g2d_dma_start(struct g2d_data *g2d,
struct g2d_cmdlist_node *node =
list_first_entry(&runqueue_node->run_cmdlist,
struct g2d_cmdlist_node, list);
int ret;
ret = pm_runtime_get_sync(g2d->dev);
if (ret < 0) {
dev_warn(g2d->dev, "failed pm power on.\n");
return;
}
pm_runtime_get_sync(g2d->dev);
clk_enable(g2d->gate_clk);
ret = clk_prepare_enable(g2d->gate_clk);
if (ret < 0) {
dev_warn(g2d->dev, "failed to enable clock.\n");
pm_runtime_put_sync(g2d->dev);
return;
}
writel_relaxed(node->dma_addr, g2d->regs + G2D_DMA_SFR_BASE_ADDR);
writel_relaxed(G2D_DMA_START, g2d->regs + G2D_DMA_COMMAND);
......@@ -861,7 +871,7 @@ static void g2d_runqueue_worker(struct work_struct *work)
runqueue_work);
mutex_lock(&g2d->runqueue_mutex);
clk_disable(g2d->gate_clk);
clk_disable_unprepare(g2d->gate_clk);
pm_runtime_put_sync(g2d->dev);
complete(&g2d->runqueue_node->complete);
......@@ -1521,7 +1531,6 @@ static const struct of_device_id exynos_g2d_match[] = {
{ .compatible = "samsung,exynos5250-g2d" },
{},
};
MODULE_DEVICE_TABLE(of, exynos_g2d_match);
#endif
struct platform_driver g2d_driver = {
......
......@@ -12,7 +12,6 @@
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/pm_runtime.h>
......
......@@ -15,7 +15,6 @@
#include <linux/kernel.h>
#include <linux/wait.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
......
......@@ -12,7 +12,6 @@
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/types.h>
#include <linux/clk.h>
......@@ -342,10 +341,10 @@ int exynos_drm_ipp_get_property(struct drm_device *drm_dev, void *data,
*/
ippdrv = ipp_find_obj(&ctx->ipp_idr, &ctx->ipp_lock,
prop_list->ipp_id);
if (!ippdrv) {
if (IS_ERR(ippdrv)) {
DRM_ERROR("not found ipp%d driver.\n",
prop_list->ipp_id);
return -EINVAL;
return PTR_ERR(ippdrv);
}
prop_list = ippdrv->prop_list;
......@@ -970,9 +969,9 @@ int exynos_drm_ipp_queue_buf(struct drm_device *drm_dev, void *data,
/* find command node */
c_node = ipp_find_obj(&ctx->prop_idr, &ctx->prop_lock,
qbuf->prop_id);
if (!c_node) {
if (IS_ERR(c_node)) {
DRM_ERROR("failed to get command node.\n");
return -EFAULT;
return PTR_ERR(c_node);
}
/* buffer control */
......@@ -1106,9 +1105,9 @@ int exynos_drm_ipp_cmd_ctrl(struct drm_device *drm_dev, void *data,
c_node = ipp_find_obj(&ctx->prop_idr, &ctx->prop_lock,
cmd_ctrl->prop_id);
if (!c_node) {
if (IS_ERR(c_node)) {
DRM_ERROR("invalid command node list.\n");
return -EINVAL;
return PTR_ERR(c_node);
}
if (!exynos_drm_ipp_check_valid(ippdrv->dev, cmd_ctrl->ctrl,
......
......@@ -10,7 +10,6 @@
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/io.h>
......
......@@ -13,7 +13,6 @@
#include <drm/drmP.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <drm/exynos_drm.h>
......
......@@ -24,7 +24,6 @@
#include <linux/spinlock.h>
#include <linux/wait.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
......
......@@ -15,7 +15,6 @@
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include "exynos_drm_drv.h"
#include "exynos_hdmi.h"
......
......@@ -23,7 +23,6 @@
#include <linux/spinlock.h>
#include <linux/wait.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
......
......@@ -1594,6 +1594,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
intel_detect_pch(dev);
intel_irq_init(dev);
intel_pm_init(dev);
intel_gt_sanitize(dev);
intel_gt_init(dev);
......
......@@ -1582,6 +1582,7 @@ void i915_hangcheck_elapsed(unsigned long data);
void i915_handle_error(struct drm_device *dev, bool wedged);
extern void intel_irq_init(struct drm_device *dev);
extern void intel_pm_init(struct drm_device *dev);
extern void intel_hpd_init(struct drm_device *dev);
extern void intel_gt_init(struct drm_device *dev);
extern void intel_gt_sanitize(struct drm_device *dev);
......
......@@ -5536,6 +5536,12 @@ void intel_gt_init(struct drm_device *dev)
dev_priv->gt.force_wake_get = __gen6_gt_force_wake_get;
dev_priv->gt.force_wake_put = __gen6_gt_force_wake_put;
}
}
void intel_pm_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
INIT_DELAYED_WORK(&dev_priv->rps.delayed_resume_work,
intel_gen6_powersave_work);
}
......
......@@ -29,6 +29,7 @@ static void mga_crtc_load_lut(struct drm_crtc *crtc)
struct mga_crtc *mga_crtc = to_mga_crtc(crtc);
struct drm_device *dev = crtc->dev;
struct mga_device *mdev = dev->dev_private;
struct drm_framebuffer *fb = crtc->fb;
int i;
if (!crtc->enabled)
......@@ -36,6 +37,28 @@ static void mga_crtc_load_lut(struct drm_crtc *crtc)
WREG8(DAC_INDEX + MGA1064_INDEX, 0);
if (fb && fb->bits_per_pixel == 16) {
int inc = (fb->depth == 15) ? 8 : 4;
u8 r, b;
for (i = 0; i < MGAG200_LUT_SIZE; i += inc) {
if (fb->depth == 16) {
if (i > (MGAG200_LUT_SIZE >> 1)) {
r = b = 0;
} else {
r = mga_crtc->lut_r[i << 1];
b = mga_crtc->lut_b[i << 1];
}
} else {
r = mga_crtc->lut_r[i];
b = mga_crtc->lut_b[i];
}
/* VGA registers */
WREG8(DAC_INDEX + MGA1064_COL_PAL, r);
WREG8(DAC_INDEX + MGA1064_COL_PAL, mga_crtc->lut_g[i]);
WREG8(DAC_INDEX + MGA1064_COL_PAL, b);
}
return;
}
for (i = 0; i < MGAG200_LUT_SIZE; i++) {
/* VGA registers */
WREG8(DAC_INDEX + MGA1064_COL_PAL, mga_crtc->lut_r[i]);
......@@ -877,7 +900,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
pitch = crtc->fb->pitches[0] / (crtc->fb->bits_per_pixel / 8);
if (crtc->fb->bits_per_pixel == 24)
pitch = pitch >> (4 - bppshift);
pitch = (pitch * 3) >> (4 - bppshift);
else
pitch = pitch >> (4 - bppshift);
......@@ -1251,6 +1274,24 @@ static void mga_crtc_destroy(struct drm_crtc *crtc)
kfree(mga_crtc);
}
static void mga_crtc_disable(struct drm_crtc *crtc)
{
int ret;
DRM_DEBUG_KMS("\n");
mga_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
if (crtc->fb) {
struct mga_framebuffer *mga_fb = to_mga_framebuffer(crtc->fb);
struct drm_gem_object *obj = mga_fb->obj;
struct mgag200_bo *bo = gem_to_mga_bo(obj);
ret = mgag200_bo_reserve(bo, false);
if (ret)
return;
mgag200_bo_push_sysram(bo);
mgag200_bo_unreserve(bo);
}
crtc->fb = NULL;
}
/* These provide the minimum set of functions required to handle a CRTC */
static const struct drm_crtc_funcs mga_crtc_funcs = {
.cursor_set = mga_crtc_cursor_set,
......@@ -1261,6 +1302,7 @@ static const struct drm_crtc_funcs mga_crtc_funcs = {
};
static const struct drm_crtc_helper_funcs mga_helper_funcs = {
.disable = mga_crtc_disable,
.dpms = mga_crtc_dpms,
.mode_fixup = mga_crtc_mode_fixup,
.mode_set = mga_crtc_mode_set,
......@@ -1581,6 +1623,8 @@ static struct drm_connector *mga_vga_init(struct drm_device *dev)
drm_connector_helper_add(connector, &mga_vga_connector_helper_funcs);
drm_sysfs_connector_add(connector);
mga_connector->i2c = mgag200_i2c_create(dev);
if (!mga_connector->i2c)
DRM_ERROR("failed to add ddc bus\n");
......
......@@ -353,6 +353,7 @@ int mgag200_bo_pin(struct mgag200_bo *bo, u32 pl_flag, u64 *gpu_addr)
bo->pin_count++;
if (gpu_addr)
*gpu_addr = mgag200_bo_gpu_offset(bo);
return 0;
}
mgag200_ttm_placement(bo, pl_flag);
......
......@@ -36,6 +36,8 @@ nva3_hda_eld(struct nv50_disp_priv *priv, int or, u8 *data, u32 size)
if (data && data[0]) {
for (i = 0; i < size; i++)
nv_wr32(priv, 0x61c440 + soff, (i << 8) | data[i]);
for (; i < 0x60; i++)
nv_wr32(priv, 0x61c440 + soff, (i << 8));
nv_mask(priv, 0x61c448 + soff, 0x80000003, 0x80000003);
} else
if (data) {
......
......@@ -41,6 +41,8 @@ nvd0_hda_eld(struct nv50_disp_priv *priv, int or, u8 *data, u32 size)
if (data && data[0]) {
for (i = 0; i < size; i++)
nv_wr32(priv, 0x10ec00 + soff, (i << 8) | data[i]);
for (; i < 0x60; i++)
nv_wr32(priv, 0x10ec00 + soff, (i << 8));
nv_mask(priv, 0x10ec10 + soff, 0x80000003, 0x80000003);
} else
if (data) {
......
......@@ -47,14 +47,8 @@ int
nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size)
{
struct nv50_disp_priv *priv = (void *)object->engine;
struct nouveau_bios *bios = nouveau_bios(priv);
const u16 type = (mthd & NV50_DISP_SOR_MTHD_TYPE) >> 12;
const u8 head = (mthd & NV50_DISP_SOR_MTHD_HEAD) >> 3;
const u8 link = (mthd & NV50_DISP_SOR_MTHD_LINK) >> 2;
const u8 or = (mthd & NV50_DISP_SOR_MTHD_OR);
const u16 mask = (0x0100 << head) | (0x0040 << link) | (0x0001 << or);
struct dcb_output outp;
u8 ver, hdr;
u32 data;
int ret = -EINVAL;
......@@ -62,8 +56,6 @@ nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size)
return -EINVAL;
data = *(u32 *)args;
if (type && !dcb_outp_match(bios, type, mask, &ver, &hdr, &outp))
return -ENODEV;
switch (mthd & ~0x3f) {
case NV50_DISP_SOR_PWR:
......
......@@ -265,8 +265,8 @@ nv31_mpeg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
int
nv31_mpeg_init(struct nouveau_object *object)
{
struct nouveau_engine *engine = nv_engine(object->engine);
struct nv31_mpeg_priv *priv = (void *)engine;
struct nouveau_engine *engine = nv_engine(object);
struct nv31_mpeg_priv *priv = (void *)object;
struct nouveau_fb *pfb = nouveau_fb(object);
int ret, i;
......@@ -284,7 +284,10 @@ nv31_mpeg_init(struct nouveau_object *object)
/* PMPEG init */
nv_wr32(priv, 0x00b32c, 0x00000000);
nv_wr32(priv, 0x00b314, 0x00000100);
nv_wr32(priv, 0x00b220, nv44_graph_class(priv) ? 0x00000044 : 0x00000031);
if (nv_device(priv)->chipset >= 0x40 && nv44_graph_class(priv))
nv_wr32(priv, 0x00b220, 0x00000044);
else
nv_wr32(priv, 0x00b220, 0x00000031);
nv_wr32(priv, 0x00b300, 0x02001ec1);
nv_mask(priv, 0x00b32c, 0x00000001, 0x00000001);
......
......@@ -61,6 +61,7 @@ nv40_mpeg_context_ctor(struct nouveau_object *parent,
if (ret)
return ret;
nv_wo32(&chan->base.base, 0x78, 0x02001ec1);
return 0;
}
......
......@@ -118,7 +118,13 @@ _nouveau_xtensa_init(struct nouveau_object *object)
return ret;
}
ret = nouveau_gpuobj_new(object, NULL, fw->size, 0x1000, 0,
if (fw->size > 0x40000) {
nv_warn(xtensa, "firmware %s too large\n", name);
release_firmware(fw);
return -EINVAL;
}
ret = nouveau_gpuobj_new(object, NULL, 0x40000, 0x1000, 0,
&xtensa->gpu_fw);
if (ret) {
release_firmware(fw);
......
......@@ -55,7 +55,7 @@ struct nouveau_vma {
struct nouveau_vm {
struct nouveau_vmmgr *vmm;
struct nouveau_mm mm;
int refcount;
struct kref refcount;
struct list_head pgd_list;
atomic_t engref[NVDEV_SUBDEV_NR];
......
......@@ -81,7 +81,7 @@ void nv44_fb_tile_prog(struct nouveau_fb *, int, struct nouveau_fb_tile *);
void nv46_fb_tile_init(struct nouveau_fb *, int i, u32 addr, u32 size,
u32 pitch, u32 flags, struct nouveau_fb_tile *);
void nv50_ram_put(struct nouveau_fb *, struct nouveau_mem **);
void __nv50_ram_put(struct nouveau_fb *, struct nouveau_mem *);
extern int nv50_fb_memtype[0x80];
#endif
......@@ -27,17 +27,10 @@
#include "priv.h"
void
nv50_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem)
__nv50_ram_put(struct nouveau_fb *pfb, struct nouveau_mem *mem)
{
struct nouveau_mm_node *this;
struct nouveau_mem *mem;
mem = *pmem;
*pmem = NULL;
if (unlikely(mem == NULL))
return;
mutex_lock(&pfb->base.mutex);
while (!list_empty(&mem->regions)) {
this = list_first_entry(&mem->regions, typeof(*this), rl_entry);
......@@ -46,6 +39,19 @@ nv50_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem)
}
nouveau_mm_free(&pfb->tags, &mem->tag);
}
void
nv50_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem)
{
struct nouveau_mem *mem = *pmem;
*pmem = NULL;
if (unlikely(mem == NULL))
return;
mutex_lock(&pfb->base.mutex);
__nv50_ram_put(pfb, mem);
mutex_unlock(&pfb->base.mutex);
kfree(mem);
......
......@@ -33,11 +33,19 @@ void
nvc0_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem)
{
struct nouveau_ltcg *ltcg = nouveau_ltcg(pfb);
struct nouveau_mem *mem = *pmem;
if ((*pmem)->tag)
ltcg->tags_free(ltcg, &(*pmem)->tag);
*pmem = NULL;
if (unlikely(mem == NULL))
return;
nv50_ram_put(pfb, pmem);
mutex_lock(&pfb->base.mutex);
if (mem->tag)
ltcg->tags_free(ltcg, &mem->tag);
__nv50_ram_put(pfb, mem);
mutex_unlock(&pfb->base.mutex);
kfree(mem);
}
int
......
......@@ -103,7 +103,7 @@ nv50_gpio_intr(struct nouveau_subdev *subdev)
int i;
intr0 = nv_rd32(priv, 0xe054) & nv_rd32(priv, 0xe050);
if (nv_device(priv)->chipset >= 0x90)
if (nv_device(priv)->chipset > 0x92)
intr1 = nv_rd32(priv, 0xe074) & nv_rd32(priv, 0xe070);
hi = (intr0 & 0x0000ffff) | (intr1 << 16);
......@@ -115,7 +115,7 @@ nv50_gpio_intr(struct nouveau_subdev *subdev)
}
nv_wr32(priv, 0xe054, intr0);
if (nv_device(priv)->chipset >= 0x90)
if (nv_device(priv)->chipset > 0x92)
nv_wr32(priv, 0xe074, intr1);
}
......@@ -146,7 +146,7 @@ nv50_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
int ret;
ret = nouveau_gpio_create(parent, engine, oclass,
nv_device(parent)->chipset >= 0x90 ? 32 : 16,
nv_device(parent)->chipset > 0x92 ? 32 : 16,
&priv);
*pobject = nv_object(priv);
if (ret)
......@@ -182,7 +182,7 @@ nv50_gpio_init(struct nouveau_object *object)
/* disable, and ack any pending gpio interrupts */
nv_wr32(priv, 0xe050, 0x00000000);
nv_wr32(priv, 0xe054, 0xffffffff);
if (nv_device(priv)->chipset >= 0x90) {
if (nv_device(priv)->chipset > 0x92) {
nv_wr32(priv, 0xe070, 0x00000000);
nv_wr32(priv, 0xe074, 0xffffffff);
}
......@@ -195,7 +195,7 @@ nv50_gpio_fini(struct nouveau_object *object, bool suspend)
{
struct nv50_gpio_priv *priv = (void *)object;
nv_wr32(priv, 0xe050, 0x00000000);
if (nv_device(priv)->chipset >= 0x90)
if (nv_device(priv)->chipset > 0x92)
nv_wr32(priv, 0xe070, 0x00000000);
return nouveau_gpio_fini(&priv->base, suspend);
}
......
......@@ -41,7 +41,7 @@ nv50_mc_intr[] = {
{ 0x04000000, NVDEV_ENGINE_DISP },
{ 0x10000000, NVDEV_SUBDEV_BUS },
{ 0x80000000, NVDEV_ENGINE_SW },
{ 0x0000d101, NVDEV_SUBDEV_FB },
{ 0x0002d101, NVDEV_SUBDEV_FB },
{},
};
......
......@@ -361,7 +361,7 @@ nouveau_vm_create(struct nouveau_vmmgr *vmm, u64 offset, u64 length,
INIT_LIST_HEAD(&vm->pgd_list);
vm->vmm = vmm;
vm->refcount = 1;
kref_init(&vm->refcount);
vm->fpde = offset >> (vmm->pgt_bits + 12);
vm->lpde = (offset + length - 1) >> (vmm->pgt_bits + 12);
......@@ -441,8 +441,9 @@ nouveau_vm_unlink(struct nouveau_vm *vm, struct nouveau_gpuobj *mpgd)
}
static void
nouveau_vm_del(struct nouveau_vm *vm)
nouveau_vm_del(struct kref *kref)
{
struct nouveau_vm *vm = container_of(kref, typeof(*vm), refcount);
struct nouveau_vm_pgd *vpgd, *tmp;
list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) {
......@@ -458,27 +459,19 @@ int
nouveau_vm_ref(struct nouveau_vm *ref, struct nouveau_vm **ptr,
struct nouveau_gpuobj *pgd)
{
struct nouveau_vm *vm;
int ret;
vm = ref;
if (vm) {
ret = nouveau_vm_link(vm, pgd);
if (ref) {
int ret = nouveau_vm_link(ref, pgd);
if (ret)
return ret;
vm->refcount++;
kref_get(&ref->refcount);
}
vm = *ptr;
*ptr = ref;
if (vm) {
nouveau_vm_unlink(vm, pgd);
if (--vm->refcount == 0)
nouveau_vm_del(vm);
if (*ptr) {
nouveau_vm_unlink(*ptr, pgd);
kref_put(&(*ptr)->refcount, nouveau_vm_del);
}
*ptr = ref;
return 0;
}
......@@ -198,7 +198,12 @@ nouveau_bo_new(struct drm_device *dev, int size, int align,
size_t acc_size;
int ret;
int type = ttm_bo_type_device;
int max_size = INT_MAX & ~((1 << drm->client.base.vm->vmm->lpg_shift) - 1);
int lpg_shift = 12;
int max_size;
if (drm->client.base.vm)
lpg_shift = drm->client.base.vm->vmm->lpg_shift;
max_size = INT_MAX & ~((1 << lpg_shift) - 1);
if (size <= 0 || size > max_size) {
nv_warn(drm, "skipped size %x\n", (u32)size);
......
......@@ -398,7 +398,8 @@ void
nouveau_fbcon_output_poll_changed(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_drm(dev);
drm_fb_helper_hotplug_event(&drm->fbcon->helper);
if (drm->fbcon)
drm_fb_helper_hotplug_event(&drm->fbcon->helper);
}
static int
......
......@@ -76,7 +76,7 @@ nv17_fence_context_new(struct nouveau_channel *chan)
struct ttm_mem_reg *mem = &priv->bo->bo.mem;
struct nouveau_object *object;
u32 start = mem->start * PAGE_SIZE;
u32 limit = mem->start + mem->size - 1;
u32 limit = start + mem->size - 1;
int ret = 0;
fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL);
......
......@@ -39,6 +39,8 @@ nv50_fence_context_new(struct nouveau_channel *chan)
struct nv10_fence_chan *fctx;
struct ttm_mem_reg *mem = &priv->bo->bo.mem;
struct nouveau_object *object;
u32 start = mem->start * PAGE_SIZE;
u32 limit = start + mem->size - 1;
int ret, i;
fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL);
......@@ -51,26 +53,28 @@ nv50_fence_context_new(struct nouveau_channel *chan)
fctx->base.sync = nv17_fence_sync;
ret = nouveau_object_new(nv_object(chan->cli), chan->handle,
NvSema, 0x0002,
NvSema, 0x003d,
&(struct nv_dma_class) {
.flags = NV_DMA_TARGET_VRAM |
NV_DMA_ACCESS_RDWR,
.start = mem->start * PAGE_SIZE,
.limit = mem->size - 1,
.start = start,
.limit = limit,
}, sizeof(struct nv_dma_class),
&object);
/* dma objects for display sync channel semaphore blocks */
for (i = 0; !ret && i < dev->mode_config.num_crtc; i++) {
struct nouveau_bo *bo = nv50_display_crtc_sema(dev, i);
u32 start = bo->bo.mem.start * PAGE_SIZE;
u32 limit = start + bo->bo.mem.size - 1;
ret = nouveau_object_new(nv_object(chan->cli), chan->handle,
NvEvoSema0 + i, 0x003d,
&(struct nv_dma_class) {
.flags = NV_DMA_TARGET_VRAM |
NV_DMA_ACCESS_RDWR,
.start = bo->bo.offset,
.limit = bo->bo.offset + 0xfff,
.start = start,
.limit = limit,
}, sizeof(struct nv_dma_class),
&object);
}
......
......@@ -1222,12 +1222,17 @@ int atom_execute_table(struct atom_context *ctx, int index, uint32_t * params)
int r;
mutex_lock(&ctx->mutex);
/* reset data block */
ctx->data_block = 0;
/* reset reg block */
ctx->reg_block = 0;
/* reset fb window */
ctx->fb_base = 0;
/* reset io mode */
ctx->io_mode = ATOM_IO_MM;
/* reset divmul */
ctx->divmul[0] = 0;
ctx->divmul[1] = 0;
r = atom_execute_table_locked(ctx, index, params);
mutex_unlock(&ctx->mutex);
return r;
......
......@@ -157,9 +157,9 @@ static void evergreen_audio_set_dto(struct drm_encoder *encoder, u32 clock)
* number (coefficient of two integer numbers. DCCG_AUDIO_DTOx_PHASE
* is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator
*/
WREG32(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL(radeon_crtc->crtc_id));
WREG32(DCCG_AUDIO_DTO0_PHASE, base_rate * 100);
WREG32(DCCG_AUDIO_DTO0_MODULE, clock * 100);
WREG32(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL(radeon_crtc->crtc_id));
}
......
......@@ -1054,10 +1054,6 @@ static int ni_restrict_performance_levels_before_switch(struct radeon_device *rd
int ni_dpm_force_performance_level(struct radeon_device *rdev,
enum radeon_dpm_forced_level level)
{
struct radeon_ps *rps = rdev->pm.dpm.current_ps;
struct ni_ps *ps = ni_get_ps(rps);
u32 levels;
if (level == RADEON_DPM_FORCED_LEVEL_HIGH) {
if (ni_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetEnabledLevels, 0) != PPSMC_Result_OK)
return -EINVAL;
......@@ -1068,8 +1064,7 @@ int ni_dpm_force_performance_level(struct radeon_device *rdev,
if (ni_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetForcedLevels, 0) != PPSMC_Result_OK)
return -EINVAL;
levels = ps->performance_level_count - 1;
if (ni_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetEnabledLevels, levels) != PPSMC_Result_OK)
if (ni_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetEnabledLevels, 1) != PPSMC_Result_OK)
return -EINVAL;
} else if (level == RADEON_DPM_FORCED_LEVEL_AUTO) {
if (ni_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetForcedLevels, 0) != PPSMC_Result_OK)
......
......@@ -2782,7 +2782,7 @@ int radeon_atom_get_clock_dividers(struct radeon_device *rdev,
ATOM_PLL_CNTL_FLAG_PLL_POST_DIV_EN) ? true : false;
dividers->enable_dithen = (args.v3.ucCntlFlag &
ATOM_PLL_CNTL_FLAG_FRACTION_DISABLE) ? false : true;
dividers->fb_div = le16_to_cpu(args.v3.ulFbDiv.usFbDiv);
dividers->whole_fb_div = le16_to_cpu(args.v3.ulFbDiv.usFbDiv);
dividers->frac_fb_div = le16_to_cpu(args.v3.ulFbDiv.usFbDivFrac);
dividers->ref_div = args.v3.ucRefDiv;
dividers->vco_mode = (args.v3.ucCntlFlag &
......
......@@ -5215,14 +5215,12 @@ static void si_enable_mc_ls(struct radeon_device *rdev,
static void si_init_cg(struct radeon_device *rdev)
{
bool has_uvd = true;
si_enable_mgcg(rdev, true);
si_enable_cgcg(rdev, true);
si_enable_cgcg(rdev, false);
/* disable MC LS on Tahiti */
if (rdev->family == CHIP_TAHITI)
si_enable_mc_ls(rdev, false);
if (has_uvd) {
if (rdev->has_uvd) {
si_enable_uvd_mgcg(rdev, true);
si_init_uvd_internal_cg(rdev);
}
......@@ -5230,9 +5228,7 @@ static void si_init_cg(struct radeon_device *rdev)
static void si_fini_cg(struct radeon_device *rdev)
{
bool has_uvd = true;
if (has_uvd)
if (rdev->has_uvd)
si_enable_uvd_mgcg(rdev, false);
si_enable_cgcg(rdev, false);
si_enable_mgcg(rdev, false);
......@@ -5241,11 +5237,11 @@ static void si_fini_cg(struct radeon_device *rdev)
static void si_init_pg(struct radeon_device *rdev)
{
bool has_pg = false;
#if 0
/* only cape verde supports PG */
if (rdev->family == CHIP_VERDE)
has_pg = true;
#endif
if (has_pg) {
si_init_ao_cu_mask(rdev);
si_init_dma_pg(rdev);
......
......@@ -37,8 +37,6 @@
#define SMC_RAM_END 0x20000
#define DDR3_DRAM_ROWS 0x2000
#define SCLK_MIN_DEEPSLEEP_FREQ 1350
static const struct si_cac_config_reg cac_weights_tahiti[] =
......@@ -1767,8 +1765,9 @@ static void si_calculate_leakage_for_v_and_t_formula(const struct ni_leakage_coe
{
s64 kt, kv, leakage_w, i_leakage, vddc;
s64 temperature, t_slope, t_intercept, av, bv, t_ref;
s64 tmp;
i_leakage = drm_int2fixp(ileakage / 100);
i_leakage = drm_int2fixp(ileakage) / 100;
vddc = div64_s64(drm_int2fixp(v), 1000);
temperature = div64_s64(drm_int2fixp(t), 1000);
......@@ -1778,8 +1777,9 @@ static void si_calculate_leakage_for_v_and_t_formula(const struct ni_leakage_coe
bv = div64_s64(drm_int2fixp(coeff->bv), 100000000);
t_ref = drm_int2fixp(coeff->t_ref);
kt = drm_fixp_div(drm_fixp_exp(drm_fixp_mul(drm_fixp_mul(t_slope, vddc) + t_intercept, temperature)),
drm_fixp_exp(drm_fixp_mul(drm_fixp_mul(t_slope, vddc) + t_intercept, t_ref)));
tmp = drm_fixp_mul(t_slope, vddc) + t_intercept;
kt = drm_fixp_exp(drm_fixp_mul(tmp, temperature));
kt = drm_fixp_div(kt, drm_fixp_exp(drm_fixp_mul(tmp, t_ref)));
kv = drm_fixp_mul(av, drm_fixp_exp(drm_fixp_mul(bv, vddc)));
leakage_w = drm_fixp_mul(drm_fixp_mul(drm_fixp_mul(i_leakage, kt), kv), vddc);
......@@ -1931,6 +1931,7 @@ static void si_initialize_powertune_defaults(struct radeon_device *rdev)
si_pi->cac_override = cac_override_pitcairn;
si_pi->powertune_data = &powertune_data_pitcairn;
si_pi->dte_data = dte_data_pitcairn;
break;
}
} else if (rdev->family == CHIP_VERDE) {
si_pi->lcac_config = lcac_cape_verde;
......@@ -1941,6 +1942,7 @@ static void si_initialize_powertune_defaults(struct radeon_device *rdev)
case 0x683B:
case 0x683F:
case 0x6829:
case 0x6835:
si_pi->cac_weights = cac_weights_cape_verde_pro;
si_pi->dte_data = dte_data_cape_verde;
break;
......@@ -3237,10 +3239,10 @@ int si_dpm_force_performance_level(struct radeon_device *rdev,
{
struct radeon_ps *rps = rdev->pm.dpm.current_ps;
struct ni_ps *ps = ni_get_ps(rps);
u32 levels;
u32 levels = ps->performance_level_count;
if (level == RADEON_DPM_FORCED_LEVEL_HIGH) {
if (si_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetEnabledLevels, 0) != PPSMC_Result_OK)
if (si_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetEnabledLevels, levels) != PPSMC_Result_OK)
return -EINVAL;
if (si_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetForcedLevels, 1) != PPSMC_Result_OK)
......@@ -3249,14 +3251,13 @@ int si_dpm_force_performance_level(struct radeon_device *rdev,
if (si_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetForcedLevels, 0) != PPSMC_Result_OK)
return -EINVAL;
levels = ps->performance_level_count - 1;
if (si_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetEnabledLevels, levels) != PPSMC_Result_OK)
if (si_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetEnabledLevels, 1) != PPSMC_Result_OK)
return -EINVAL;
} else if (level == RADEON_DPM_FORCED_LEVEL_AUTO) {
if (si_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetForcedLevels, 0) != PPSMC_Result_OK)
return -EINVAL;
if (si_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetEnabledLevels, 0) != PPSMC_Result_OK)
if (si_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetEnabledLevels, levels) != PPSMC_Result_OK)
return -EINVAL;
}
......@@ -3620,8 +3621,12 @@ static void si_enable_display_gap(struct radeon_device *rdev)
{
u32 tmp = RREG32(CG_DISPLAY_GAP_CNTL);
tmp &= ~(DISP1_GAP_MASK | DISP2_GAP_MASK);
tmp |= (DISP1_GAP(R600_PM_DISPLAY_GAP_IGNORE) |
DISP2_GAP(R600_PM_DISPLAY_GAP_IGNORE));
tmp &= ~(DISP1_GAP_MCHG_MASK | DISP2_GAP_MCHG_MASK);
tmp |= (DISP1_GAP_MCHG(R600_PM_DISPLAY_GAP_IGNORE) |
tmp |= (DISP1_GAP_MCHG(R600_PM_DISPLAY_GAP_VBLANK) |
DISP2_GAP_MCHG(R600_PM_DISPLAY_GAP_IGNORE));
WREG32(CG_DISPLAY_GAP_CNTL, tmp);
}
......@@ -4036,16 +4041,15 @@ static int si_force_switch_to_arb_f0(struct radeon_device *rdev)
static u32 si_calculate_memory_refresh_rate(struct radeon_device *rdev,
u32 engine_clock)
{
struct rv7xx_power_info *pi = rv770_get_pi(rdev);
u32 dram_rows;
u32 dram_refresh_rate;
u32 mc_arb_rfsh_rate;
u32 tmp = (RREG32(MC_ARB_RAMCFG) & NOOFROWS_MASK) >> NOOFROWS_SHIFT;
if (pi->mem_gddr5)
dram_rows = 1 << (tmp + 10);
if (tmp >= 4)
dram_rows = 16384;
else
dram_rows = DDR3_DRAM_ROWS;
dram_rows = 1 << (tmp + 10);
dram_refresh_rate = 1 << ((RREG32(MC_SEQ_MISC0) & 0x3) + 3);
mc_arb_rfsh_rate = ((engine_clock * 10) * dram_refresh_rate / dram_rows - 32) / 64;
......@@ -6013,16 +6017,11 @@ int si_dpm_set_power_state(struct radeon_device *rdev)
return ret;
}
#if 0
/* XXX */
ret = si_dpm_force_performance_level(rdev, RADEON_DPM_FORCED_LEVEL_AUTO);
if (ret) {
DRM_ERROR("si_dpm_force_performance_level failed\n");
return ret;
}
#else
rdev->pm.dpm.forced_level = RADEON_DPM_FORCED_LEVEL_AUTO;
#endif
return 0;
}
......
......@@ -84,12 +84,12 @@ static inline int drm_fixp2int(int64_t a)
return ((s64)a) >> DRM_FIXED_POINT;
}
static inline s64 drm_fixp_msbset(int64_t a)
static inline unsigned drm_fixp_msbset(int64_t a)
{
unsigned shift, sign = (a >> 63) & 1;
for (shift = 62; shift > 0; --shift)
if ((a >> shift) != sign)
if (((a >> shift) & 1) != sign)
return shift;
return 0;
......@@ -100,9 +100,9 @@ static inline s64 drm_fixp_mul(s64 a, s64 b)
unsigned shift = drm_fixp_msbset(a) + drm_fixp_msbset(b);
s64 result;
if (shift > 63) {
shift = shift - 63;
a >>= shift >> 1;
if (shift > 61) {
shift = shift - 61;
a >>= (shift >> 1) + (shift & 1);
b >>= shift >> 1;
} else
shift = 0;
......@@ -120,7 +120,7 @@ static inline s64 drm_fixp_mul(s64 a, s64 b)
static inline s64 drm_fixp_div(s64 a, s64 b)
{
unsigned shift = 63 - drm_fixp_msbset(a);
unsigned shift = 62 - drm_fixp_msbset(a);
s64 result;
a <<= shift;
......@@ -154,7 +154,7 @@ static inline s64 drm_fixp_exp(s64 x)
}
if (x < 0)
sum = drm_fixp_div(1, sum);
sum = drm_fixp_div(DRM_FIXED_ONE, sum);
return sum;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册