mirror of
https://github.com/torvalds/linux.git
synced 2026-04-28 11:32:28 -04:00
Merge tag 'drm-misc-next-2019-04-04' of git://anongit.freedesktop.org/drm/drm-misc into drm-next
drm-misc-next for 5.2: UAPI Changes: -syncobj: Add TIMELINE_WAIT|QUERY|TRANSFER|TIMELINE_SIGNAL ioctls (Chunming) -Clarify that 1.0 can be represented by drm_color_lut (Daniel) Cross-subsystem Changes: -dt-bindings: Add binding for rk3066 hdmi (Johan) -dt-bindings: Add binding for Feiyang FY07024DI26A30-D panel (Jagan) -dt-bindings: Add Rocktech vendor prefix and jh057n00900 panel bindings (Guido) -MAINTAINERS: Add lima and ASPEED entries (Joel & Qiang) Core Changes: -memory: use dma_alloc_coherent when mem encryption is active (Christian) -dma_buf: add support for a dma_fence chain (Christian) -shmem_gem: fix off-by-one bug in new shmem gem helpers (Dan) Driver Changes: -rockchip: Add support for rk3066 hdmi (Johan) -ASPEED: Add driver supporting ASPEED BMC display controller to drm (Joel) -lima: Add driver supporting Arm Mali4xx gpus to drm (Qiang) -vc4/v3d: Various cleanups and improved error handling (Eric) -panel: Add support for Feiyang FY07024DI26A30-D MIPI-DSI panel (Jagan) -panel: Add support for Rocktech jh057n00900 MIPI-DSI panel (Guido) Cc: Johan Jonker <jbx6244@gmail.com> Cc: Christian König <christian.koenig@amd.com> Cc: Chunming Zhou <david1.zhou@amd.com> Cc: Dan Carpenter <dan.carpenter@oracle.com> Cc: Eric Anholt <eric@anholt.net> Cc: Qiang Yu <yuq825@gmail.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Jagan Teki <jagan@amarulasolutions.com> Cc: Guido Günther <agx@sigxcpu.org> Cc: Joel Stanley <joel@jms.id.au> [airlied: fixed XA limit build breakage, Rodrigo also submitted the same patch, but I squashed it in the merge.] Signed-off-by: Dave Airlie <airlied@redhat.com> From: Sean Paul <sean@poorly.run> Link: https://patchwork.freedesktop.org/patch/msgid/20190404201016.GA139524@art_vandelay
This commit is contained in:
@@ -40,7 +40,7 @@ static bool is_user_label(int label)
|
||||
return label >= VC4_BO_TYPE_COUNT;
|
||||
}
|
||||
|
||||
static void vc4_bo_stats_dump(struct vc4_dev *vc4)
|
||||
static void vc4_bo_stats_print(struct drm_printer *p, struct vc4_dev *vc4)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -48,58 +48,35 @@ static void vc4_bo_stats_dump(struct vc4_dev *vc4)
|
||||
if (!vc4->bo_labels[i].num_allocated)
|
||||
continue;
|
||||
|
||||
DRM_INFO("%30s: %6dkb BOs (%d)\n",
|
||||
vc4->bo_labels[i].name,
|
||||
vc4->bo_labels[i].size_allocated / 1024,
|
||||
vc4->bo_labels[i].num_allocated);
|
||||
}
|
||||
|
||||
mutex_lock(&vc4->purgeable.lock);
|
||||
if (vc4->purgeable.num)
|
||||
DRM_INFO("%30s: %6zdkb BOs (%d)\n", "userspace BO cache",
|
||||
vc4->purgeable.size / 1024, vc4->purgeable.num);
|
||||
|
||||
if (vc4->purgeable.purged_num)
|
||||
DRM_INFO("%30s: %6zdkb BOs (%d)\n", "total purged BO",
|
||||
vc4->purgeable.purged_size / 1024,
|
||||
vc4->purgeable.purged_num);
|
||||
mutex_unlock(&vc4->purgeable.lock);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
int vc4_bo_stats_debugfs(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *)m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
struct vc4_dev *vc4 = to_vc4_dev(dev);
|
||||
int i;
|
||||
|
||||
mutex_lock(&vc4->bo_lock);
|
||||
for (i = 0; i < vc4->num_labels; i++) {
|
||||
if (!vc4->bo_labels[i].num_allocated)
|
||||
continue;
|
||||
|
||||
seq_printf(m, "%30s: %6dkb BOs (%d)\n",
|
||||
drm_printf(p, "%30s: %6dkb BOs (%d)\n",
|
||||
vc4->bo_labels[i].name,
|
||||
vc4->bo_labels[i].size_allocated / 1024,
|
||||
vc4->bo_labels[i].num_allocated);
|
||||
}
|
||||
mutex_unlock(&vc4->bo_lock);
|
||||
|
||||
mutex_lock(&vc4->purgeable.lock);
|
||||
if (vc4->purgeable.num)
|
||||
seq_printf(m, "%30s: %6zdkb BOs (%d)\n", "userspace BO cache",
|
||||
drm_printf(p, "%30s: %6zdkb BOs (%d)\n", "userspace BO cache",
|
||||
vc4->purgeable.size / 1024, vc4->purgeable.num);
|
||||
|
||||
if (vc4->purgeable.purged_num)
|
||||
seq_printf(m, "%30s: %6zdkb BOs (%d)\n", "total purged BO",
|
||||
drm_printf(p, "%30s: %6zdkb BOs (%d)\n", "total purged BO",
|
||||
vc4->purgeable.purged_size / 1024,
|
||||
vc4->purgeable.purged_num);
|
||||
mutex_unlock(&vc4->purgeable.lock);
|
||||
}
|
||||
|
||||
static int vc4_bo_stats_debugfs(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *)m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
struct vc4_dev *vc4 = to_vc4_dev(dev);
|
||||
struct drm_printer p = drm_seq_file_printer(m);
|
||||
|
||||
vc4_bo_stats_print(&p, vc4);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Takes ownership of *name and returns the appropriate slot for it in
|
||||
* the bo_labels[] array, extending it as necessary.
|
||||
@@ -475,8 +452,9 @@ struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t unaligned_size,
|
||||
}
|
||||
|
||||
if (IS_ERR(cma_obj)) {
|
||||
struct drm_printer p = drm_info_printer(vc4->dev->dev);
|
||||
DRM_ERROR("Failed to allocate from CMA:\n");
|
||||
vc4_bo_stats_dump(vc4);
|
||||
vc4_bo_stats_print(&p, vc4);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
bo = to_vc4_bo(&cma_obj->base);
|
||||
@@ -1025,6 +1003,8 @@ int vc4_bo_cache_init(struct drm_device *dev)
|
||||
|
||||
mutex_init(&vc4->bo_lock);
|
||||
|
||||
vc4_debugfs_add_file(dev, "bo_stats", vc4_bo_stats_debugfs, NULL);
|
||||
|
||||
INIT_LIST_HEAD(&vc4->bo_cache.time_list);
|
||||
|
||||
INIT_WORK(&vc4->bo_cache.time_work, vc4_bo_cache_time_work);
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_atomic_uapi.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <linux/clk.h>
|
||||
#include <drm/drm_fb_cma_helper.h>
|
||||
@@ -67,67 +68,22 @@ to_vc4_crtc_state(struct drm_crtc_state *crtc_state)
|
||||
#define CRTC_WRITE(offset, val) writel(val, vc4_crtc->regs + (offset))
|
||||
#define CRTC_READ(offset) readl(vc4_crtc->regs + (offset))
|
||||
|
||||
#define CRTC_REG(reg) { reg, #reg }
|
||||
static const struct {
|
||||
u32 reg;
|
||||
const char *name;
|
||||
} crtc_regs[] = {
|
||||
CRTC_REG(PV_CONTROL),
|
||||
CRTC_REG(PV_V_CONTROL),
|
||||
CRTC_REG(PV_VSYNCD_EVEN),
|
||||
CRTC_REG(PV_HORZA),
|
||||
CRTC_REG(PV_HORZB),
|
||||
CRTC_REG(PV_VERTA),
|
||||
CRTC_REG(PV_VERTB),
|
||||
CRTC_REG(PV_VERTA_EVEN),
|
||||
CRTC_REG(PV_VERTB_EVEN),
|
||||
CRTC_REG(PV_INTEN),
|
||||
CRTC_REG(PV_INTSTAT),
|
||||
CRTC_REG(PV_STAT),
|
||||
CRTC_REG(PV_HACT_ACT),
|
||||
static const struct debugfs_reg32 crtc_regs[] = {
|
||||
VC4_REG32(PV_CONTROL),
|
||||
VC4_REG32(PV_V_CONTROL),
|
||||
VC4_REG32(PV_VSYNCD_EVEN),
|
||||
VC4_REG32(PV_HORZA),
|
||||
VC4_REG32(PV_HORZB),
|
||||
VC4_REG32(PV_VERTA),
|
||||
VC4_REG32(PV_VERTB),
|
||||
VC4_REG32(PV_VERTA_EVEN),
|
||||
VC4_REG32(PV_VERTB_EVEN),
|
||||
VC4_REG32(PV_INTEN),
|
||||
VC4_REG32(PV_INTSTAT),
|
||||
VC4_REG32(PV_STAT),
|
||||
VC4_REG32(PV_HACT_ACT),
|
||||
};
|
||||
|
||||
static void vc4_crtc_dump_regs(struct vc4_crtc *vc4_crtc)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(crtc_regs); i++) {
|
||||
DRM_INFO("0x%04x (%s): 0x%08x\n",
|
||||
crtc_regs[i].reg, crtc_regs[i].name,
|
||||
CRTC_READ(crtc_regs[i].reg));
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
int vc4_crtc_debugfs_regs(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *)m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
int crtc_index = (uintptr_t)node->info_ent->data;
|
||||
struct drm_crtc *crtc;
|
||||
struct vc4_crtc *vc4_crtc;
|
||||
int i;
|
||||
|
||||
i = 0;
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
if (i == crtc_index)
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
if (!crtc)
|
||||
return 0;
|
||||
vc4_crtc = to_vc4_crtc(crtc);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(crtc_regs); i++) {
|
||||
seq_printf(m, "%s (0x%04x): 0x%08x\n",
|
||||
crtc_regs[i].name, crtc_regs[i].reg,
|
||||
CRTC_READ(crtc_regs[i].reg));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id,
|
||||
bool in_vblank_irq, int *vpos, int *hpos,
|
||||
ktime_t *stime, ktime_t *etime,
|
||||
@@ -434,8 +390,10 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
|
||||
bool debug_dump_regs = false;
|
||||
|
||||
if (debug_dump_regs) {
|
||||
DRM_INFO("CRTC %d regs before:\n", drm_crtc_index(crtc));
|
||||
vc4_crtc_dump_regs(vc4_crtc);
|
||||
struct drm_printer p = drm_info_printer(&vc4_crtc->pdev->dev);
|
||||
dev_info(&vc4_crtc->pdev->dev, "CRTC %d regs before:\n",
|
||||
drm_crtc_index(crtc));
|
||||
drm_print_regset32(&p, &vc4_crtc->regset);
|
||||
}
|
||||
|
||||
if (vc4_crtc->channel == 2) {
|
||||
@@ -476,8 +434,10 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
|
||||
vc4_crtc_lut_load(crtc);
|
||||
|
||||
if (debug_dump_regs) {
|
||||
DRM_INFO("CRTC %d regs after:\n", drm_crtc_index(crtc));
|
||||
vc4_crtc_dump_regs(vc4_crtc);
|
||||
struct drm_printer p = drm_info_printer(&vc4_crtc->pdev->dev);
|
||||
dev_info(&vc4_crtc->pdev->dev, "CRTC %d regs after:\n",
|
||||
drm_crtc_index(crtc));
|
||||
drm_print_regset32(&p, &vc4_crtc->regset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1083,6 +1043,7 @@ static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
|
||||
|
||||
static const struct vc4_crtc_data pv0_data = {
|
||||
.hvs_channel = 0,
|
||||
.debugfs_name = "crtc0_regs",
|
||||
.encoder_types = {
|
||||
[PV_CONTROL_CLK_SELECT_DSI] = VC4_ENCODER_TYPE_DSI0,
|
||||
[PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_DPI,
|
||||
@@ -1091,6 +1052,7 @@ static const struct vc4_crtc_data pv0_data = {
|
||||
|
||||
static const struct vc4_crtc_data pv1_data = {
|
||||
.hvs_channel = 2,
|
||||
.debugfs_name = "crtc1_regs",
|
||||
.encoder_types = {
|
||||
[PV_CONTROL_CLK_SELECT_DSI] = VC4_ENCODER_TYPE_DSI1,
|
||||
[PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_SMI,
|
||||
@@ -1099,6 +1061,7 @@ static const struct vc4_crtc_data pv1_data = {
|
||||
|
||||
static const struct vc4_crtc_data pv2_data = {
|
||||
.hvs_channel = 1,
|
||||
.debugfs_name = "crtc2_regs",
|
||||
.encoder_types = {
|
||||
[PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_HDMI,
|
||||
[PV_CONTROL_CLK_SELECT_VEC] = VC4_ENCODER_TYPE_VEC,
|
||||
@@ -1177,11 +1140,16 @@ static int vc4_crtc_bind(struct device *dev, struct device *master, void *data)
|
||||
if (!match)
|
||||
return -ENODEV;
|
||||
vc4_crtc->data = match->data;
|
||||
vc4_crtc->pdev = pdev;
|
||||
|
||||
vc4_crtc->regs = vc4_ioremap_regs(pdev, 0);
|
||||
if (IS_ERR(vc4_crtc->regs))
|
||||
return PTR_ERR(vc4_crtc->regs);
|
||||
|
||||
vc4_crtc->regset.base = vc4_crtc->regs;
|
||||
vc4_crtc->regset.regs = crtc_regs;
|
||||
vc4_crtc->regset.nregs = ARRAY_SIZE(crtc_regs);
|
||||
|
||||
/* For now, we create just the primary and the legacy cursor
|
||||
* planes. We should be able to stack more planes on easily,
|
||||
* but to do that we would need to compute the bandwidth
|
||||
@@ -1255,6 +1223,9 @@ static int vc4_crtc_bind(struct device *dev, struct device *master, void *data)
|
||||
|
||||
platform_set_drvdata(pdev, vc4_crtc);
|
||||
|
||||
vc4_debugfs_add_regset32(drm, vc4_crtc->data->debugfs_name,
|
||||
&vc4_crtc->regset);
|
||||
|
||||
return 0;
|
||||
|
||||
err_destroy_planes:
|
||||
|
||||
@@ -15,28 +15,20 @@
|
||||
#include "vc4_drv.h"
|
||||
#include "vc4_regs.h"
|
||||
|
||||
static const struct drm_info_list vc4_debugfs_list[] = {
|
||||
{"bo_stats", vc4_bo_stats_debugfs, 0},
|
||||
{"dpi_regs", vc4_dpi_debugfs_regs, 0},
|
||||
{"dsi1_regs", vc4_dsi_debugfs_regs, 0, (void *)(uintptr_t)1},
|
||||
{"hdmi_regs", vc4_hdmi_debugfs_regs, 0},
|
||||
{"vec_regs", vc4_vec_debugfs_regs, 0},
|
||||
{"txp_regs", vc4_txp_debugfs_regs, 0},
|
||||
{"hvs_regs", vc4_hvs_debugfs_regs, 0},
|
||||
{"hvs_underrun", vc4_hvs_debugfs_underrun, 0},
|
||||
{"crtc0_regs", vc4_crtc_debugfs_regs, 0, (void *)(uintptr_t)0},
|
||||
{"crtc1_regs", vc4_crtc_debugfs_regs, 0, (void *)(uintptr_t)1},
|
||||
{"crtc2_regs", vc4_crtc_debugfs_regs, 0, (void *)(uintptr_t)2},
|
||||
{"v3d_ident", vc4_v3d_debugfs_ident, 0},
|
||||
{"v3d_regs", vc4_v3d_debugfs_regs, 0},
|
||||
struct vc4_debugfs_info_entry {
|
||||
struct list_head link;
|
||||
struct drm_info_list info;
|
||||
};
|
||||
|
||||
#define VC4_DEBUGFS_ENTRIES ARRAY_SIZE(vc4_debugfs_list)
|
||||
|
||||
/**
|
||||
* Called at drm_dev_register() time on each of the minors registered
|
||||
* by the DRM device, to attach the debugfs files.
|
||||
*/
|
||||
int
|
||||
vc4_debugfs_init(struct drm_minor *minor)
|
||||
{
|
||||
struct vc4_dev *vc4 = to_vc4_dev(minor->dev);
|
||||
struct vc4_debugfs_info_entry *entry;
|
||||
struct dentry *dentry;
|
||||
|
||||
dentry = debugfs_create_bool("hvs_load_tracker", S_IRUGO | S_IWUSR,
|
||||
@@ -45,6 +37,60 @@ vc4_debugfs_init(struct drm_minor *minor)
|
||||
if (!dentry)
|
||||
return -ENOMEM;
|
||||
|
||||
return drm_debugfs_create_files(vc4_debugfs_list, VC4_DEBUGFS_ENTRIES,
|
||||
minor->debugfs_root, minor);
|
||||
list_for_each_entry(entry, &vc4->debugfs_list, link) {
|
||||
int ret = drm_debugfs_create_files(&entry->info, 1,
|
||||
minor->debugfs_root, minor);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vc4_debugfs_regset32(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *)m->private;
|
||||
struct debugfs_regset32 *regset = node->info_ent->data;
|
||||
struct drm_printer p = drm_seq_file_printer(m);
|
||||
|
||||
drm_print_regset32(&p, regset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a debugfs file with a callback function for a vc4 component.
|
||||
*
|
||||
* This is like drm_debugfs_create_files(), but that can only be
|
||||
* called a given DRM minor, while the various VC4 components want to
|
||||
* register their debugfs files during the component bind process. We
|
||||
* track the request and delay it to be called on each minor during
|
||||
* vc4_debugfs_init().
|
||||
*/
|
||||
void vc4_debugfs_add_file(struct drm_device *dev,
|
||||
const char *name,
|
||||
int (*show)(struct seq_file*, void*),
|
||||
void *data)
|
||||
{
|
||||
struct vc4_dev *vc4 = to_vc4_dev(dev);
|
||||
|
||||
struct vc4_debugfs_info_entry *entry =
|
||||
devm_kzalloc(dev->dev, sizeof(*entry), GFP_KERNEL);
|
||||
|
||||
if (!entry)
|
||||
return;
|
||||
|
||||
entry->info.name = name;
|
||||
entry->info.show = show;
|
||||
entry->info.data = data;
|
||||
|
||||
list_add(&entry->link, &vc4->debugfs_list);
|
||||
}
|
||||
|
||||
void vc4_debugfs_add_regset32(struct drm_device *drm,
|
||||
const char *name,
|
||||
struct debugfs_regset32 *regset)
|
||||
{
|
||||
vc4_debugfs_add_file(drm, name, vc4_debugfs_regset32, regset);
|
||||
}
|
||||
|
||||
@@ -101,6 +101,8 @@ struct vc4_dpi {
|
||||
|
||||
struct clk *pixel_clock;
|
||||
struct clk *core_clock;
|
||||
|
||||
struct debugfs_regset32 regset;
|
||||
};
|
||||
|
||||
#define DPI_READ(offset) readl(dpi->regs + (offset))
|
||||
@@ -118,37 +120,11 @@ to_vc4_dpi_encoder(struct drm_encoder *encoder)
|
||||
return container_of(encoder, struct vc4_dpi_encoder, base.base);
|
||||
}
|
||||
|
||||
#define DPI_REG(reg) { reg, #reg }
|
||||
static const struct {
|
||||
u32 reg;
|
||||
const char *name;
|
||||
} dpi_regs[] = {
|
||||
DPI_REG(DPI_C),
|
||||
DPI_REG(DPI_ID),
|
||||
static const struct debugfs_reg32 dpi_regs[] = {
|
||||
VC4_REG32(DPI_C),
|
||||
VC4_REG32(DPI_ID),
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
int vc4_dpi_debugfs_regs(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *)m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
struct vc4_dev *vc4 = to_vc4_dev(dev);
|
||||
struct vc4_dpi *dpi = vc4->dpi;
|
||||
int i;
|
||||
|
||||
if (!dpi)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dpi_regs); i++) {
|
||||
seq_printf(m, "%s (0x%04x): 0x%08x\n",
|
||||
dpi_regs[i].name, dpi_regs[i].reg,
|
||||
DPI_READ(dpi_regs[i].reg));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct drm_encoder_funcs vc4_dpi_encoder_funcs = {
|
||||
.destroy = drm_encoder_cleanup,
|
||||
};
|
||||
@@ -314,6 +290,9 @@ static int vc4_dpi_bind(struct device *dev, struct device *master, void *data)
|
||||
dpi->regs = vc4_ioremap_regs(pdev, 0);
|
||||
if (IS_ERR(dpi->regs))
|
||||
return PTR_ERR(dpi->regs);
|
||||
dpi->regset.base = dpi->regs;
|
||||
dpi->regset.regs = dpi_regs;
|
||||
dpi->regset.nregs = ARRAY_SIZE(dpi_regs);
|
||||
|
||||
if (DPI_READ(DPI_ID) != DPI_ID_VALUE) {
|
||||
dev_err(dev, "Port returned 0x%08x for ID instead of 0x%08x\n",
|
||||
@@ -352,6 +331,8 @@ static int vc4_dpi_bind(struct device *dev, struct device *master, void *data)
|
||||
|
||||
vc4->dpi = dpi;
|
||||
|
||||
vc4_debugfs_add_regset32(drm, "dpi_regs", &dpi->regset);
|
||||
|
||||
return 0;
|
||||
|
||||
err_destroy_encoder:
|
||||
|
||||
@@ -72,30 +72,30 @@ static int vc4_get_param_ioctl(struct drm_device *dev, void *data,
|
||||
if (args->pad != 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (!vc4->v3d)
|
||||
return -ENODEV;
|
||||
|
||||
switch (args->param) {
|
||||
case DRM_VC4_PARAM_V3D_IDENT0:
|
||||
ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev);
|
||||
if (ret < 0)
|
||||
ret = vc4_v3d_pm_get(vc4);
|
||||
if (ret)
|
||||
return ret;
|
||||
args->value = V3D_READ(V3D_IDENT0);
|
||||
pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev);
|
||||
pm_runtime_put_autosuspend(&vc4->v3d->pdev->dev);
|
||||
vc4_v3d_pm_put(vc4);
|
||||
break;
|
||||
case DRM_VC4_PARAM_V3D_IDENT1:
|
||||
ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev);
|
||||
if (ret < 0)
|
||||
ret = vc4_v3d_pm_get(vc4);
|
||||
if (ret)
|
||||
return ret;
|
||||
args->value = V3D_READ(V3D_IDENT1);
|
||||
pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev);
|
||||
pm_runtime_put_autosuspend(&vc4->v3d->pdev->dev);
|
||||
vc4_v3d_pm_put(vc4);
|
||||
break;
|
||||
case DRM_VC4_PARAM_V3D_IDENT2:
|
||||
ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev);
|
||||
if (ret < 0)
|
||||
ret = vc4_v3d_pm_get(vc4);
|
||||
if (ret)
|
||||
return ret;
|
||||
args->value = V3D_READ(V3D_IDENT2);
|
||||
pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev);
|
||||
pm_runtime_put_autosuspend(&vc4->v3d->pdev->dev);
|
||||
vc4_v3d_pm_put(vc4);
|
||||
break;
|
||||
case DRM_VC4_PARAM_SUPPORTS_BRANCHES:
|
||||
case DRM_VC4_PARAM_SUPPORTS_ETC1:
|
||||
@@ -251,6 +251,7 @@ static int vc4_drm_bind(struct device *dev)
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct drm_device *drm;
|
||||
struct vc4_dev *vc4;
|
||||
struct device_node *node;
|
||||
int ret = 0;
|
||||
|
||||
dev->coherent_dma_mask = DMA_BIT_MASK(32);
|
||||
@@ -259,12 +260,19 @@ static int vc4_drm_bind(struct device *dev)
|
||||
if (!vc4)
|
||||
return -ENOMEM;
|
||||
|
||||
/* If VC4 V3D is missing, don't advertise render nodes. */
|
||||
node = of_find_matching_node_and_match(NULL, vc4_v3d_dt_match, NULL);
|
||||
if (!node || !of_device_is_available(node))
|
||||
vc4_drm_driver.driver_features &= ~DRIVER_RENDER;
|
||||
of_node_put(node);
|
||||
|
||||
drm = drm_dev_alloc(&vc4_drm_driver, dev);
|
||||
if (IS_ERR(drm))
|
||||
return PTR_ERR(drm);
|
||||
platform_set_drvdata(pdev, drm);
|
||||
vc4->dev = drm;
|
||||
drm->dev_private = vc4;
|
||||
INIT_LIST_HEAD(&vc4->debugfs_list);
|
||||
|
||||
ret = vc4_bo_cache_init(drm);
|
||||
if (ret)
|
||||
@@ -280,11 +288,13 @@ static int vc4_drm_bind(struct device *dev)
|
||||
|
||||
drm_fb_helper_remove_conflicting_framebuffers(NULL, "vc4drmfb", false);
|
||||
|
||||
ret = drm_dev_register(drm, 0);
|
||||
ret = vc4_kms_load(drm);
|
||||
if (ret < 0)
|
||||
goto unbind_all;
|
||||
|
||||
vc4_kms_load(drm);
|
||||
ret = drm_dev_register(drm, 0);
|
||||
if (ret < 0)
|
||||
goto unbind_all;
|
||||
|
||||
drm_fbdev_generic_setup(drm, 16);
|
||||
|
||||
|
||||
@@ -211,6 +211,11 @@ struct vc4_dev {
|
||||
struct drm_modeset_lock ctm_state_lock;
|
||||
struct drm_private_obj ctm_manager;
|
||||
struct drm_private_obj load_tracker;
|
||||
|
||||
/* List of vc4_debugfs_info_entry for adding to debugfs once
|
||||
* the minor is available (after drm_dev_register()).
|
||||
*/
|
||||
struct list_head debugfs_list;
|
||||
};
|
||||
|
||||
static inline struct vc4_dev *
|
||||
@@ -296,6 +301,7 @@ struct vc4_v3d {
|
||||
struct platform_device *pdev;
|
||||
void __iomem *regs;
|
||||
struct clk *clk;
|
||||
struct debugfs_regset32 regset;
|
||||
};
|
||||
|
||||
struct vc4_hvs {
|
||||
@@ -312,6 +318,7 @@ struct vc4_hvs {
|
||||
spinlock_t mm_lock;
|
||||
|
||||
struct drm_mm_node mitchell_netravali_filter;
|
||||
struct debugfs_regset32 regset;
|
||||
};
|
||||
|
||||
struct vc4_plane {
|
||||
@@ -427,10 +434,12 @@ struct vc4_crtc_data {
|
||||
int hvs_channel;
|
||||
|
||||
enum vc4_encoder_type encoder_types[4];
|
||||
const char *debugfs_name;
|
||||
};
|
||||
|
||||
struct vc4_crtc {
|
||||
struct drm_crtc base;
|
||||
struct platform_device *pdev;
|
||||
const struct vc4_crtc_data *data;
|
||||
void __iomem *regs;
|
||||
|
||||
@@ -447,6 +456,8 @@ struct vc4_crtc {
|
||||
u32 cob_size;
|
||||
|
||||
struct drm_pending_vblank_event *event;
|
||||
|
||||
struct debugfs_regset32 regset;
|
||||
};
|
||||
|
||||
static inline struct vc4_crtc *
|
||||
@@ -460,6 +471,8 @@ to_vc4_crtc(struct drm_crtc *crtc)
|
||||
#define HVS_READ(offset) readl(vc4->hvs->regs + offset)
|
||||
#define HVS_WRITE(offset, val) writel(val, vc4->hvs->regs + offset)
|
||||
|
||||
#define VC4_REG32(reg) { .name = #reg, .offset = reg }
|
||||
|
||||
struct vc4_exec_info {
|
||||
/* Sequence number for this bin/render job. */
|
||||
uint64_t seqno;
|
||||
@@ -708,7 +721,6 @@ struct drm_gem_object *vc4_prime_import_sg_table(struct drm_device *dev,
|
||||
void *vc4_prime_vmap(struct drm_gem_object *obj);
|
||||
int vc4_bo_cache_init(struct drm_device *dev);
|
||||
void vc4_bo_cache_destroy(struct drm_device *dev);
|
||||
int vc4_bo_stats_debugfs(struct seq_file *m, void *arg);
|
||||
int vc4_bo_inc_usecnt(struct vc4_bo *bo);
|
||||
void vc4_bo_dec_usecnt(struct vc4_bo *bo);
|
||||
void vc4_bo_add_to_purgeable_pool(struct vc4_bo *bo);
|
||||
@@ -716,7 +728,6 @@ void vc4_bo_remove_from_purgeable_pool(struct vc4_bo *bo);
|
||||
|
||||
/* vc4_crtc.c */
|
||||
extern struct platform_driver vc4_crtc_driver;
|
||||
int vc4_crtc_debugfs_regs(struct seq_file *m, void *arg);
|
||||
bool vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id,
|
||||
bool in_vblank_irq, int *vpos, int *hpos,
|
||||
ktime_t *stime, ktime_t *etime,
|
||||
@@ -729,17 +740,37 @@ void vc4_crtc_get_margins(struct drm_crtc_state *state,
|
||||
|
||||
/* vc4_debugfs.c */
|
||||
int vc4_debugfs_init(struct drm_minor *minor);
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
void vc4_debugfs_add_file(struct drm_device *drm,
|
||||
const char *filename,
|
||||
int (*show)(struct seq_file*, void*),
|
||||
void *data);
|
||||
void vc4_debugfs_add_regset32(struct drm_device *drm,
|
||||
const char *filename,
|
||||
struct debugfs_regset32 *regset);
|
||||
#else
|
||||
static inline void vc4_debugfs_add_file(struct drm_device *drm,
|
||||
const char *filename,
|
||||
int (*show)(struct seq_file*, void*),
|
||||
void *data)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void vc4_debugfs_add_regset32(struct drm_device *drm,
|
||||
const char *filename,
|
||||
struct debugfs_regset32 *regset)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/* vc4_drv.c */
|
||||
void __iomem *vc4_ioremap_regs(struct platform_device *dev, int index);
|
||||
|
||||
/* vc4_dpi.c */
|
||||
extern struct platform_driver vc4_dpi_driver;
|
||||
int vc4_dpi_debugfs_regs(struct seq_file *m, void *unused);
|
||||
|
||||
/* vc4_dsi.c */
|
||||
extern struct platform_driver vc4_dsi_driver;
|
||||
int vc4_dsi_debugfs_regs(struct seq_file *m, void *unused);
|
||||
|
||||
/* vc4_fence.c */
|
||||
extern const struct dma_fence_ops vc4_fence_ops;
|
||||
@@ -767,15 +798,12 @@ int vc4_gem_madvise_ioctl(struct drm_device *dev, void *data,
|
||||
|
||||
/* vc4_hdmi.c */
|
||||
extern struct platform_driver vc4_hdmi_driver;
|
||||
int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused);
|
||||
|
||||
/* vc4_vec.c */
|
||||
extern struct platform_driver vc4_vec_driver;
|
||||
int vc4_vec_debugfs_regs(struct seq_file *m, void *unused);
|
||||
|
||||
/* vc4_txp.c */
|
||||
extern struct platform_driver vc4_txp_driver;
|
||||
int vc4_txp_debugfs_regs(struct seq_file *m, void *unused);
|
||||
|
||||
/* vc4_irq.c */
|
||||
irqreturn_t vc4_irq(int irq, void *arg);
|
||||
@@ -787,8 +815,6 @@ void vc4_irq_reset(struct drm_device *dev);
|
||||
/* vc4_hvs.c */
|
||||
extern struct platform_driver vc4_hvs_driver;
|
||||
void vc4_hvs_dump_state(struct drm_device *dev);
|
||||
int vc4_hvs_debugfs_regs(struct seq_file *m, void *unused);
|
||||
int vc4_hvs_debugfs_underrun(struct seq_file *m, void *unused);
|
||||
void vc4_hvs_unmask_underrun(struct drm_device *dev, int channel);
|
||||
void vc4_hvs_mask_underrun(struct drm_device *dev, int channel);
|
||||
|
||||
@@ -805,9 +831,10 @@ void vc4_plane_async_set_fb(struct drm_plane *plane,
|
||||
|
||||
/* vc4_v3d.c */
|
||||
extern struct platform_driver vc4_v3d_driver;
|
||||
int vc4_v3d_debugfs_ident(struct seq_file *m, void *unused);
|
||||
int vc4_v3d_debugfs_regs(struct seq_file *m, void *unused);
|
||||
extern const struct of_device_id vc4_v3d_dt_match[];
|
||||
int vc4_v3d_get_bin_slot(struct vc4_dev *vc4);
|
||||
int vc4_v3d_pm_get(struct vc4_dev *vc4);
|
||||
void vc4_v3d_pm_put(struct vc4_dev *vc4);
|
||||
|
||||
/* vc4_validate.c */
|
||||
int
|
||||
|
||||
@@ -545,6 +545,8 @@ struct vc4_dsi {
|
||||
|
||||
struct completion xfer_completion;
|
||||
int xfer_result;
|
||||
|
||||
struct debugfs_regset32 regset;
|
||||
};
|
||||
|
||||
#define host_to_dsi(host) container_of(host, struct vc4_dsi, dsi_host)
|
||||
@@ -605,113 +607,56 @@ to_vc4_dsi_encoder(struct drm_encoder *encoder)
|
||||
return container_of(encoder, struct vc4_dsi_encoder, base.base);
|
||||
}
|
||||
|
||||
#define DSI_REG(reg) { reg, #reg }
|
||||
static const struct {
|
||||
u32 reg;
|
||||
const char *name;
|
||||
} dsi0_regs[] = {
|
||||
DSI_REG(DSI0_CTRL),
|
||||
DSI_REG(DSI0_STAT),
|
||||
DSI_REG(DSI0_HSTX_TO_CNT),
|
||||
DSI_REG(DSI0_LPRX_TO_CNT),
|
||||
DSI_REG(DSI0_TA_TO_CNT),
|
||||
DSI_REG(DSI0_PR_TO_CNT),
|
||||
DSI_REG(DSI0_DISP0_CTRL),
|
||||
DSI_REG(DSI0_DISP1_CTRL),
|
||||
DSI_REG(DSI0_INT_STAT),
|
||||
DSI_REG(DSI0_INT_EN),
|
||||
DSI_REG(DSI0_PHYC),
|
||||
DSI_REG(DSI0_HS_CLT0),
|
||||
DSI_REG(DSI0_HS_CLT1),
|
||||
DSI_REG(DSI0_HS_CLT2),
|
||||
DSI_REG(DSI0_HS_DLT3),
|
||||
DSI_REG(DSI0_HS_DLT4),
|
||||
DSI_REG(DSI0_HS_DLT5),
|
||||
DSI_REG(DSI0_HS_DLT6),
|
||||
DSI_REG(DSI0_HS_DLT7),
|
||||
DSI_REG(DSI0_PHY_AFEC0),
|
||||
DSI_REG(DSI0_PHY_AFEC1),
|
||||
DSI_REG(DSI0_ID),
|
||||
static const struct debugfs_reg32 dsi0_regs[] = {
|
||||
VC4_REG32(DSI0_CTRL),
|
||||
VC4_REG32(DSI0_STAT),
|
||||
VC4_REG32(DSI0_HSTX_TO_CNT),
|
||||
VC4_REG32(DSI0_LPRX_TO_CNT),
|
||||
VC4_REG32(DSI0_TA_TO_CNT),
|
||||
VC4_REG32(DSI0_PR_TO_CNT),
|
||||
VC4_REG32(DSI0_DISP0_CTRL),
|
||||
VC4_REG32(DSI0_DISP1_CTRL),
|
||||
VC4_REG32(DSI0_INT_STAT),
|
||||
VC4_REG32(DSI0_INT_EN),
|
||||
VC4_REG32(DSI0_PHYC),
|
||||
VC4_REG32(DSI0_HS_CLT0),
|
||||
VC4_REG32(DSI0_HS_CLT1),
|
||||
VC4_REG32(DSI0_HS_CLT2),
|
||||
VC4_REG32(DSI0_HS_DLT3),
|
||||
VC4_REG32(DSI0_HS_DLT4),
|
||||
VC4_REG32(DSI0_HS_DLT5),
|
||||
VC4_REG32(DSI0_HS_DLT6),
|
||||
VC4_REG32(DSI0_HS_DLT7),
|
||||
VC4_REG32(DSI0_PHY_AFEC0),
|
||||
VC4_REG32(DSI0_PHY_AFEC1),
|
||||
VC4_REG32(DSI0_ID),
|
||||
};
|
||||
|
||||
static const struct {
|
||||
u32 reg;
|
||||
const char *name;
|
||||
} dsi1_regs[] = {
|
||||
DSI_REG(DSI1_CTRL),
|
||||
DSI_REG(DSI1_STAT),
|
||||
DSI_REG(DSI1_HSTX_TO_CNT),
|
||||
DSI_REG(DSI1_LPRX_TO_CNT),
|
||||
DSI_REG(DSI1_TA_TO_CNT),
|
||||
DSI_REG(DSI1_PR_TO_CNT),
|
||||
DSI_REG(DSI1_DISP0_CTRL),
|
||||
DSI_REG(DSI1_DISP1_CTRL),
|
||||
DSI_REG(DSI1_INT_STAT),
|
||||
DSI_REG(DSI1_INT_EN),
|
||||
DSI_REG(DSI1_PHYC),
|
||||
DSI_REG(DSI1_HS_CLT0),
|
||||
DSI_REG(DSI1_HS_CLT1),
|
||||
DSI_REG(DSI1_HS_CLT2),
|
||||
DSI_REG(DSI1_HS_DLT3),
|
||||
DSI_REG(DSI1_HS_DLT4),
|
||||
DSI_REG(DSI1_HS_DLT5),
|
||||
DSI_REG(DSI1_HS_DLT6),
|
||||
DSI_REG(DSI1_HS_DLT7),
|
||||
DSI_REG(DSI1_PHY_AFEC0),
|
||||
DSI_REG(DSI1_PHY_AFEC1),
|
||||
DSI_REG(DSI1_ID),
|
||||
static const struct debugfs_reg32 dsi1_regs[] = {
|
||||
VC4_REG32(DSI1_CTRL),
|
||||
VC4_REG32(DSI1_STAT),
|
||||
VC4_REG32(DSI1_HSTX_TO_CNT),
|
||||
VC4_REG32(DSI1_LPRX_TO_CNT),
|
||||
VC4_REG32(DSI1_TA_TO_CNT),
|
||||
VC4_REG32(DSI1_PR_TO_CNT),
|
||||
VC4_REG32(DSI1_DISP0_CTRL),
|
||||
VC4_REG32(DSI1_DISP1_CTRL),
|
||||
VC4_REG32(DSI1_INT_STAT),
|
||||
VC4_REG32(DSI1_INT_EN),
|
||||
VC4_REG32(DSI1_PHYC),
|
||||
VC4_REG32(DSI1_HS_CLT0),
|
||||
VC4_REG32(DSI1_HS_CLT1),
|
||||
VC4_REG32(DSI1_HS_CLT2),
|
||||
VC4_REG32(DSI1_HS_DLT3),
|
||||
VC4_REG32(DSI1_HS_DLT4),
|
||||
VC4_REG32(DSI1_HS_DLT5),
|
||||
VC4_REG32(DSI1_HS_DLT6),
|
||||
VC4_REG32(DSI1_HS_DLT7),
|
||||
VC4_REG32(DSI1_PHY_AFEC0),
|
||||
VC4_REG32(DSI1_PHY_AFEC1),
|
||||
VC4_REG32(DSI1_ID),
|
||||
};
|
||||
|
||||
static void vc4_dsi_dump_regs(struct vc4_dsi *dsi)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (dsi->port == 0) {
|
||||
for (i = 0; i < ARRAY_SIZE(dsi0_regs); i++) {
|
||||
DRM_INFO("0x%04x (%s): 0x%08x\n",
|
||||
dsi0_regs[i].reg, dsi0_regs[i].name,
|
||||
DSI_READ(dsi0_regs[i].reg));
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < ARRAY_SIZE(dsi1_regs); i++) {
|
||||
DRM_INFO("0x%04x (%s): 0x%08x\n",
|
||||
dsi1_regs[i].reg, dsi1_regs[i].name,
|
||||
DSI_READ(dsi1_regs[i].reg));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
int vc4_dsi_debugfs_regs(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *)m->private;
|
||||
struct drm_device *drm = node->minor->dev;
|
||||
struct vc4_dev *vc4 = to_vc4_dev(drm);
|
||||
int dsi_index = (uintptr_t)node->info_ent->data;
|
||||
struct vc4_dsi *dsi = (dsi_index == 1 ? vc4->dsi1 : NULL);
|
||||
int i;
|
||||
|
||||
if (!dsi)
|
||||
return 0;
|
||||
|
||||
if (dsi->port == 0) {
|
||||
for (i = 0; i < ARRAY_SIZE(dsi0_regs); i++) {
|
||||
seq_printf(m, "0x%04x (%s): 0x%08x\n",
|
||||
dsi0_regs[i].reg, dsi0_regs[i].name,
|
||||
DSI_READ(dsi0_regs[i].reg));
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < ARRAY_SIZE(dsi1_regs); i++) {
|
||||
seq_printf(m, "0x%04x (%s): 0x%08x\n",
|
||||
dsi1_regs[i].reg, dsi1_regs[i].name,
|
||||
DSI_READ(dsi1_regs[i].reg));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void vc4_dsi_encoder_destroy(struct drm_encoder *encoder)
|
||||
{
|
||||
drm_encoder_cleanup(encoder);
|
||||
@@ -900,8 +845,9 @@ static void vc4_dsi_encoder_enable(struct drm_encoder *encoder)
|
||||
}
|
||||
|
||||
if (debug_dump_regs) {
|
||||
DRM_INFO("DSI regs before:\n");
|
||||
vc4_dsi_dump_regs(dsi);
|
||||
struct drm_printer p = drm_info_printer(&dsi->pdev->dev);
|
||||
dev_info(&dsi->pdev->dev, "DSI regs before:\n");
|
||||
drm_print_regset32(&p, &dsi->regset);
|
||||
}
|
||||
|
||||
/* Round up the clk_set_rate() request slightly, since
|
||||
@@ -1135,8 +1081,9 @@ static void vc4_dsi_encoder_enable(struct drm_encoder *encoder)
|
||||
drm_bridge_enable(dsi->bridge);
|
||||
|
||||
if (debug_dump_regs) {
|
||||
DRM_INFO("DSI regs after:\n");
|
||||
vc4_dsi_dump_regs(dsi);
|
||||
struct drm_printer p = drm_info_printer(&dsi->pdev->dev);
|
||||
dev_info(&dsi->pdev->dev, "DSI regs after:\n");
|
||||
drm_print_regset32(&p, &dsi->regset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1527,6 +1474,15 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data)
|
||||
if (IS_ERR(dsi->regs))
|
||||
return PTR_ERR(dsi->regs);
|
||||
|
||||
dsi->regset.base = dsi->regs;
|
||||
if (dsi->port == 0) {
|
||||
dsi->regset.regs = dsi0_regs;
|
||||
dsi->regset.nregs = ARRAY_SIZE(dsi0_regs);
|
||||
} else {
|
||||
dsi->regset.regs = dsi1_regs;
|
||||
dsi->regset.nregs = ARRAY_SIZE(dsi1_regs);
|
||||
}
|
||||
|
||||
if (DSI_PORT_READ(ID) != DSI_ID_VALUE) {
|
||||
dev_err(dev, "Port returned 0x%08x for ID instead of 0x%08x\n",
|
||||
DSI_PORT_READ(ID), DSI_ID_VALUE);
|
||||
@@ -1662,6 +1618,11 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data)
|
||||
*/
|
||||
dsi->encoder->bridge = NULL;
|
||||
|
||||
if (dsi->port == 0)
|
||||
vc4_debugfs_add_regset32(drm, "dsi0_regs", &dsi->regset);
|
||||
else
|
||||
vc4_debugfs_add_regset32(drm, "dsi1_regs", &dsi->regset);
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -74,6 +74,11 @@ vc4_get_hang_state_ioctl(struct drm_device *dev, void *data,
|
||||
u32 i;
|
||||
int ret = 0;
|
||||
|
||||
if (!vc4->v3d) {
|
||||
DRM_DEBUG("VC4_GET_HANG_STATE with no VC4 V3D probed\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&vc4->job_lock, irqflags);
|
||||
kernel_state = vc4->hang_state;
|
||||
if (!kernel_state) {
|
||||
@@ -964,12 +969,7 @@ vc4_complete_exec(struct drm_device *dev, struct vc4_exec_info *exec)
|
||||
/* Release the reference we had on the perf monitor. */
|
||||
vc4_perfmon_put(exec->perfmon);
|
||||
|
||||
mutex_lock(&vc4->power_lock);
|
||||
if (--vc4->power_refcount == 0) {
|
||||
pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev);
|
||||
pm_runtime_put_autosuspend(&vc4->v3d->pdev->dev);
|
||||
}
|
||||
mutex_unlock(&vc4->power_lock);
|
||||
vc4_v3d_pm_put(vc4);
|
||||
|
||||
kfree(exec);
|
||||
}
|
||||
@@ -1124,6 +1124,11 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data,
|
||||
struct dma_fence *in_fence;
|
||||
int ret = 0;
|
||||
|
||||
if (!vc4->v3d) {
|
||||
DRM_DEBUG("VC4_SUBMIT_CL with no VC4 V3D probed\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if ((args->flags & ~(VC4_SUBMIT_CL_USE_CLEAR_COLOR |
|
||||
VC4_SUBMIT_CL_FIXED_RCL_ORDER |
|
||||
VC4_SUBMIT_CL_RCL_ORDER_INCREASING_X |
|
||||
@@ -1143,17 +1148,11 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mutex_lock(&vc4->power_lock);
|
||||
if (vc4->power_refcount++ == 0) {
|
||||
ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev);
|
||||
if (ret < 0) {
|
||||
mutex_unlock(&vc4->power_lock);
|
||||
vc4->power_refcount--;
|
||||
kfree(exec);
|
||||
return ret;
|
||||
}
|
||||
ret = vc4_v3d_pm_get(vc4);
|
||||
if (ret) {
|
||||
kfree(exec);
|
||||
return ret;
|
||||
}
|
||||
mutex_unlock(&vc4->power_lock);
|
||||
|
||||
exec->args = args;
|
||||
INIT_LIST_HEAD(&exec->unref_list);
|
||||
|
||||
@@ -97,6 +97,9 @@ struct vc4_hdmi {
|
||||
|
||||
struct clk *pixel_clock;
|
||||
struct clk *hsm_clock;
|
||||
|
||||
struct debugfs_regset32 hdmi_regset;
|
||||
struct debugfs_regset32 hd_regset;
|
||||
};
|
||||
|
||||
#define HDMI_READ(offset) readl(vc4->hdmi->hdmicore_regs + offset)
|
||||
@@ -134,103 +137,69 @@ to_vc4_hdmi_connector(struct drm_connector *connector)
|
||||
return container_of(connector, struct vc4_hdmi_connector, base);
|
||||
}
|
||||
|
||||
#define HDMI_REG(reg) { reg, #reg }
|
||||
static const struct {
|
||||
u32 reg;
|
||||
const char *name;
|
||||
} hdmi_regs[] = {
|
||||
HDMI_REG(VC4_HDMI_CORE_REV),
|
||||
HDMI_REG(VC4_HDMI_SW_RESET_CONTROL),
|
||||
HDMI_REG(VC4_HDMI_HOTPLUG_INT),
|
||||
HDMI_REG(VC4_HDMI_HOTPLUG),
|
||||
HDMI_REG(VC4_HDMI_MAI_CHANNEL_MAP),
|
||||
HDMI_REG(VC4_HDMI_MAI_CONFIG),
|
||||
HDMI_REG(VC4_HDMI_MAI_FORMAT),
|
||||
HDMI_REG(VC4_HDMI_AUDIO_PACKET_CONFIG),
|
||||
HDMI_REG(VC4_HDMI_RAM_PACKET_CONFIG),
|
||||
HDMI_REG(VC4_HDMI_HORZA),
|
||||
HDMI_REG(VC4_HDMI_HORZB),
|
||||
HDMI_REG(VC4_HDMI_FIFO_CTL),
|
||||
HDMI_REG(VC4_HDMI_SCHEDULER_CONTROL),
|
||||
HDMI_REG(VC4_HDMI_VERTA0),
|
||||
HDMI_REG(VC4_HDMI_VERTA1),
|
||||
HDMI_REG(VC4_HDMI_VERTB0),
|
||||
HDMI_REG(VC4_HDMI_VERTB1),
|
||||
HDMI_REG(VC4_HDMI_TX_PHY_RESET_CTL),
|
||||
HDMI_REG(VC4_HDMI_TX_PHY_CTL0),
|
||||
static const struct debugfs_reg32 hdmi_regs[] = {
|
||||
VC4_REG32(VC4_HDMI_CORE_REV),
|
||||
VC4_REG32(VC4_HDMI_SW_RESET_CONTROL),
|
||||
VC4_REG32(VC4_HDMI_HOTPLUG_INT),
|
||||
VC4_REG32(VC4_HDMI_HOTPLUG),
|
||||
VC4_REG32(VC4_HDMI_MAI_CHANNEL_MAP),
|
||||
VC4_REG32(VC4_HDMI_MAI_CONFIG),
|
||||
VC4_REG32(VC4_HDMI_MAI_FORMAT),
|
||||
VC4_REG32(VC4_HDMI_AUDIO_PACKET_CONFIG),
|
||||
VC4_REG32(VC4_HDMI_RAM_PACKET_CONFIG),
|
||||
VC4_REG32(VC4_HDMI_HORZA),
|
||||
VC4_REG32(VC4_HDMI_HORZB),
|
||||
VC4_REG32(VC4_HDMI_FIFO_CTL),
|
||||
VC4_REG32(VC4_HDMI_SCHEDULER_CONTROL),
|
||||
VC4_REG32(VC4_HDMI_VERTA0),
|
||||
VC4_REG32(VC4_HDMI_VERTA1),
|
||||
VC4_REG32(VC4_HDMI_VERTB0),
|
||||
VC4_REG32(VC4_HDMI_VERTB1),
|
||||
VC4_REG32(VC4_HDMI_TX_PHY_RESET_CTL),
|
||||
VC4_REG32(VC4_HDMI_TX_PHY_CTL0),
|
||||
|
||||
HDMI_REG(VC4_HDMI_CEC_CNTRL_1),
|
||||
HDMI_REG(VC4_HDMI_CEC_CNTRL_2),
|
||||
HDMI_REG(VC4_HDMI_CEC_CNTRL_3),
|
||||
HDMI_REG(VC4_HDMI_CEC_CNTRL_4),
|
||||
HDMI_REG(VC4_HDMI_CEC_CNTRL_5),
|
||||
HDMI_REG(VC4_HDMI_CPU_STATUS),
|
||||
HDMI_REG(VC4_HDMI_CPU_MASK_STATUS),
|
||||
VC4_REG32(VC4_HDMI_CEC_CNTRL_1),
|
||||
VC4_REG32(VC4_HDMI_CEC_CNTRL_2),
|
||||
VC4_REG32(VC4_HDMI_CEC_CNTRL_3),
|
||||
VC4_REG32(VC4_HDMI_CEC_CNTRL_4),
|
||||
VC4_REG32(VC4_HDMI_CEC_CNTRL_5),
|
||||
VC4_REG32(VC4_HDMI_CPU_STATUS),
|
||||
VC4_REG32(VC4_HDMI_CPU_MASK_STATUS),
|
||||
|
||||
HDMI_REG(VC4_HDMI_CEC_RX_DATA_1),
|
||||
HDMI_REG(VC4_HDMI_CEC_RX_DATA_2),
|
||||
HDMI_REG(VC4_HDMI_CEC_RX_DATA_3),
|
||||
HDMI_REG(VC4_HDMI_CEC_RX_DATA_4),
|
||||
HDMI_REG(VC4_HDMI_CEC_TX_DATA_1),
|
||||
HDMI_REG(VC4_HDMI_CEC_TX_DATA_2),
|
||||
HDMI_REG(VC4_HDMI_CEC_TX_DATA_3),
|
||||
HDMI_REG(VC4_HDMI_CEC_TX_DATA_4),
|
||||
VC4_REG32(VC4_HDMI_CEC_RX_DATA_1),
|
||||
VC4_REG32(VC4_HDMI_CEC_RX_DATA_2),
|
||||
VC4_REG32(VC4_HDMI_CEC_RX_DATA_3),
|
||||
VC4_REG32(VC4_HDMI_CEC_RX_DATA_4),
|
||||
VC4_REG32(VC4_HDMI_CEC_TX_DATA_1),
|
||||
VC4_REG32(VC4_HDMI_CEC_TX_DATA_2),
|
||||
VC4_REG32(VC4_HDMI_CEC_TX_DATA_3),
|
||||
VC4_REG32(VC4_HDMI_CEC_TX_DATA_4),
|
||||
};
|
||||
|
||||
static const struct {
|
||||
u32 reg;
|
||||
const char *name;
|
||||
} hd_regs[] = {
|
||||
HDMI_REG(VC4_HD_M_CTL),
|
||||
HDMI_REG(VC4_HD_MAI_CTL),
|
||||
HDMI_REG(VC4_HD_MAI_THR),
|
||||
HDMI_REG(VC4_HD_MAI_FMT),
|
||||
HDMI_REG(VC4_HD_MAI_SMP),
|
||||
HDMI_REG(VC4_HD_VID_CTL),
|
||||
HDMI_REG(VC4_HD_CSC_CTL),
|
||||
HDMI_REG(VC4_HD_FRAME_COUNT),
|
||||
static const struct debugfs_reg32 hd_regs[] = {
|
||||
VC4_REG32(VC4_HD_M_CTL),
|
||||
VC4_REG32(VC4_HD_MAI_CTL),
|
||||
VC4_REG32(VC4_HD_MAI_THR),
|
||||
VC4_REG32(VC4_HD_MAI_FMT),
|
||||
VC4_REG32(VC4_HD_MAI_SMP),
|
||||
VC4_REG32(VC4_HD_VID_CTL),
|
||||
VC4_REG32(VC4_HD_CSC_CTL),
|
||||
VC4_REG32(VC4_HD_FRAME_COUNT),
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
|
||||
static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *)m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
struct vc4_dev *vc4 = to_vc4_dev(dev);
|
||||
int i;
|
||||
struct vc4_hdmi *hdmi = vc4->hdmi;
|
||||
struct drm_printer p = drm_seq_file_printer(m);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(hdmi_regs); i++) {
|
||||
seq_printf(m, "%s (0x%04x): 0x%08x\n",
|
||||
hdmi_regs[i].name, hdmi_regs[i].reg,
|
||||
HDMI_READ(hdmi_regs[i].reg));
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(hd_regs); i++) {
|
||||
seq_printf(m, "%s (0x%04x): 0x%08x\n",
|
||||
hd_regs[i].name, hd_regs[i].reg,
|
||||
HD_READ(hd_regs[i].reg));
|
||||
}
|
||||
drm_print_regset32(&p, &hdmi->hdmi_regset);
|
||||
drm_print_regset32(&p, &hdmi->hd_regset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_DEBUG_FS */
|
||||
|
||||
static void vc4_hdmi_dump_regs(struct drm_device *dev)
|
||||
{
|
||||
struct vc4_dev *vc4 = to_vc4_dev(dev);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(hdmi_regs); i++) {
|
||||
DRM_INFO("0x%04x (%s): 0x%08x\n",
|
||||
hdmi_regs[i].reg, hdmi_regs[i].name,
|
||||
HDMI_READ(hdmi_regs[i].reg));
|
||||
}
|
||||
for (i = 0; i < ARRAY_SIZE(hd_regs); i++) {
|
||||
DRM_INFO("0x%04x (%s): 0x%08x\n",
|
||||
hd_regs[i].reg, hd_regs[i].name,
|
||||
HD_READ(hd_regs[i].reg));
|
||||
}
|
||||
}
|
||||
|
||||
static enum drm_connector_status
|
||||
vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
|
||||
@@ -561,8 +530,11 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
|
||||
HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0);
|
||||
|
||||
if (debug_dump_regs) {
|
||||
DRM_INFO("HDMI regs before:\n");
|
||||
vc4_hdmi_dump_regs(dev);
|
||||
struct drm_printer p = drm_info_printer(&hdmi->pdev->dev);
|
||||
|
||||
dev_info(&hdmi->pdev->dev, "HDMI regs before:\n");
|
||||
drm_print_regset32(&p, &hdmi->hdmi_regset);
|
||||
drm_print_regset32(&p, &hdmi->hd_regset);
|
||||
}
|
||||
|
||||
HD_WRITE(VC4_HD_VID_CTL, 0);
|
||||
@@ -637,8 +609,11 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
|
||||
HDMI_WRITE(VC4_HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
|
||||
|
||||
if (debug_dump_regs) {
|
||||
DRM_INFO("HDMI regs after:\n");
|
||||
vc4_hdmi_dump_regs(dev);
|
||||
struct drm_printer p = drm_info_printer(&hdmi->pdev->dev);
|
||||
|
||||
dev_info(&hdmi->pdev->dev, "HDMI regs after:\n");
|
||||
drm_print_regset32(&p, &hdmi->hdmi_regset);
|
||||
drm_print_regset32(&p, &hdmi->hd_regset);
|
||||
}
|
||||
|
||||
HD_WRITE(VC4_HD_VID_CTL,
|
||||
@@ -1333,6 +1308,13 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
|
||||
if (IS_ERR(hdmi->hd_regs))
|
||||
return PTR_ERR(hdmi->hd_regs);
|
||||
|
||||
hdmi->hdmi_regset.base = hdmi->hdmicore_regs;
|
||||
hdmi->hdmi_regset.regs = hdmi_regs;
|
||||
hdmi->hdmi_regset.nregs = ARRAY_SIZE(hdmi_regs);
|
||||
hdmi->hd_regset.base = hdmi->hd_regs;
|
||||
hdmi->hd_regset.regs = hd_regs;
|
||||
hdmi->hd_regset.nregs = ARRAY_SIZE(hd_regs);
|
||||
|
||||
hdmi->pixel_clock = devm_clk_get(dev, "pixel");
|
||||
if (IS_ERR(hdmi->pixel_clock)) {
|
||||
DRM_ERROR("Failed to get pixel clock\n");
|
||||
@@ -1448,6 +1430,8 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
|
||||
if (ret)
|
||||
goto err_destroy_encoder;
|
||||
|
||||
vc4_debugfs_add_file(drm, "hdmi_regs", vc4_hdmi_debugfs_regs, hdmi);
|
||||
|
||||
return 0;
|
||||
|
||||
#ifdef CONFIG_DRM_VC4_HDMI_CEC
|
||||
|
||||
@@ -27,54 +27,47 @@
|
||||
#include "vc4_drv.h"
|
||||
#include "vc4_regs.h"
|
||||
|
||||
#define HVS_REG(reg) { reg, #reg }
|
||||
static const struct {
|
||||
u32 reg;
|
||||
const char *name;
|
||||
} hvs_regs[] = {
|
||||
HVS_REG(SCALER_DISPCTRL),
|
||||
HVS_REG(SCALER_DISPSTAT),
|
||||
HVS_REG(SCALER_DISPID),
|
||||
HVS_REG(SCALER_DISPECTRL),
|
||||
HVS_REG(SCALER_DISPPROF),
|
||||
HVS_REG(SCALER_DISPDITHER),
|
||||
HVS_REG(SCALER_DISPEOLN),
|
||||
HVS_REG(SCALER_DISPLIST0),
|
||||
HVS_REG(SCALER_DISPLIST1),
|
||||
HVS_REG(SCALER_DISPLIST2),
|
||||
HVS_REG(SCALER_DISPLSTAT),
|
||||
HVS_REG(SCALER_DISPLACT0),
|
||||
HVS_REG(SCALER_DISPLACT1),
|
||||
HVS_REG(SCALER_DISPLACT2),
|
||||
HVS_REG(SCALER_DISPCTRL0),
|
||||
HVS_REG(SCALER_DISPBKGND0),
|
||||
HVS_REG(SCALER_DISPSTAT0),
|
||||
HVS_REG(SCALER_DISPBASE0),
|
||||
HVS_REG(SCALER_DISPCTRL1),
|
||||
HVS_REG(SCALER_DISPBKGND1),
|
||||
HVS_REG(SCALER_DISPSTAT1),
|
||||
HVS_REG(SCALER_DISPBASE1),
|
||||
HVS_REG(SCALER_DISPCTRL2),
|
||||
HVS_REG(SCALER_DISPBKGND2),
|
||||
HVS_REG(SCALER_DISPSTAT2),
|
||||
HVS_REG(SCALER_DISPBASE2),
|
||||
HVS_REG(SCALER_DISPALPHA2),
|
||||
HVS_REG(SCALER_OLEDOFFS),
|
||||
HVS_REG(SCALER_OLEDCOEF0),
|
||||
HVS_REG(SCALER_OLEDCOEF1),
|
||||
HVS_REG(SCALER_OLEDCOEF2),
|
||||
static const struct debugfs_reg32 hvs_regs[] = {
|
||||
VC4_REG32(SCALER_DISPCTRL),
|
||||
VC4_REG32(SCALER_DISPSTAT),
|
||||
VC4_REG32(SCALER_DISPID),
|
||||
VC4_REG32(SCALER_DISPECTRL),
|
||||
VC4_REG32(SCALER_DISPPROF),
|
||||
VC4_REG32(SCALER_DISPDITHER),
|
||||
VC4_REG32(SCALER_DISPEOLN),
|
||||
VC4_REG32(SCALER_DISPLIST0),
|
||||
VC4_REG32(SCALER_DISPLIST1),
|
||||
VC4_REG32(SCALER_DISPLIST2),
|
||||
VC4_REG32(SCALER_DISPLSTAT),
|
||||
VC4_REG32(SCALER_DISPLACT0),
|
||||
VC4_REG32(SCALER_DISPLACT1),
|
||||
VC4_REG32(SCALER_DISPLACT2),
|
||||
VC4_REG32(SCALER_DISPCTRL0),
|
||||
VC4_REG32(SCALER_DISPBKGND0),
|
||||
VC4_REG32(SCALER_DISPSTAT0),
|
||||
VC4_REG32(SCALER_DISPBASE0),
|
||||
VC4_REG32(SCALER_DISPCTRL1),
|
||||
VC4_REG32(SCALER_DISPBKGND1),
|
||||
VC4_REG32(SCALER_DISPSTAT1),
|
||||
VC4_REG32(SCALER_DISPBASE1),
|
||||
VC4_REG32(SCALER_DISPCTRL2),
|
||||
VC4_REG32(SCALER_DISPBKGND2),
|
||||
VC4_REG32(SCALER_DISPSTAT2),
|
||||
VC4_REG32(SCALER_DISPBASE2),
|
||||
VC4_REG32(SCALER_DISPALPHA2),
|
||||
VC4_REG32(SCALER_OLEDOFFS),
|
||||
VC4_REG32(SCALER_OLEDCOEF0),
|
||||
VC4_REG32(SCALER_OLEDCOEF1),
|
||||
VC4_REG32(SCALER_OLEDCOEF2),
|
||||
};
|
||||
|
||||
void vc4_hvs_dump_state(struct drm_device *dev)
|
||||
{
|
||||
struct vc4_dev *vc4 = to_vc4_dev(dev);
|
||||
struct drm_printer p = drm_info_printer(&vc4->hvs->pdev->dev);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(hvs_regs); i++) {
|
||||
DRM_INFO("0x%04x (%s): 0x%08x\n",
|
||||
hvs_regs[i].reg, hvs_regs[i].name,
|
||||
HVS_READ(hvs_regs[i].reg));
|
||||
}
|
||||
drm_print_regset32(&p, &vc4->hvs->regset);
|
||||
|
||||
DRM_INFO("HVS ctx:\n");
|
||||
for (i = 0; i < 64; i += 4) {
|
||||
@@ -87,24 +80,7 @@ void vc4_hvs_dump_state(struct drm_device *dev)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
int vc4_hvs_debugfs_regs(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *)m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
struct vc4_dev *vc4 = to_vc4_dev(dev);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(hvs_regs); i++) {
|
||||
seq_printf(m, "%s (0x%04x): 0x%08x\n",
|
||||
hvs_regs[i].name, hvs_regs[i].reg,
|
||||
HVS_READ(hvs_regs[i].reg));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vc4_hvs_debugfs_underrun(struct seq_file *m, void *data)
|
||||
static int vc4_hvs_debugfs_underrun(struct seq_file *m, void *data)
|
||||
{
|
||||
struct drm_info_node *node = m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
@@ -115,7 +91,6 @@ int vc4_hvs_debugfs_underrun(struct seq_file *m, void *data)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* The filter kernel is composed of dwords each containing 3 9-bit
|
||||
* signed integers packed next to each other.
|
||||
@@ -259,6 +234,10 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
|
||||
if (IS_ERR(hvs->regs))
|
||||
return PTR_ERR(hvs->regs);
|
||||
|
||||
hvs->regset.base = hvs->regs;
|
||||
hvs->regset.regs = hvs_regs;
|
||||
hvs->regset.nregs = ARRAY_SIZE(hvs_regs);
|
||||
|
||||
hvs->dlist = hvs->regs + SCALER_DLIST_START;
|
||||
|
||||
spin_lock_init(&hvs->mm_lock);
|
||||
@@ -323,6 +302,10 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
vc4_debugfs_add_regset32(drm, "hvs_regs", &hvs->regset);
|
||||
vc4_debugfs_add_file(drm, "hvs_underrun", vc4_hvs_debugfs_underrun,
|
||||
NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -229,6 +229,9 @@ vc4_irq_preinstall(struct drm_device *dev)
|
||||
{
|
||||
struct vc4_dev *vc4 = to_vc4_dev(dev);
|
||||
|
||||
if (!vc4->v3d)
|
||||
return;
|
||||
|
||||
init_waitqueue_head(&vc4->job_wait_queue);
|
||||
INIT_WORK(&vc4->overflow_mem_work, vc4_overflow_mem_work);
|
||||
|
||||
@@ -243,6 +246,9 @@ vc4_irq_postinstall(struct drm_device *dev)
|
||||
{
|
||||
struct vc4_dev *vc4 = to_vc4_dev(dev);
|
||||
|
||||
if (!vc4->v3d)
|
||||
return 0;
|
||||
|
||||
/* Enable both the render done and out of memory interrupts. */
|
||||
V3D_WRITE(V3D_INTENA, V3D_DRIVER_IRQS);
|
||||
|
||||
@@ -254,6 +260,9 @@ vc4_irq_uninstall(struct drm_device *dev)
|
||||
{
|
||||
struct vc4_dev *vc4 = to_vc4_dev(dev);
|
||||
|
||||
if (!vc4->v3d)
|
||||
return;
|
||||
|
||||
/* Disable sending interrupts for our driver's IRQs. */
|
||||
V3D_WRITE(V3D_INTDIS, V3D_DRIVER_IRQS);
|
||||
|
||||
|
||||
@@ -525,6 +525,7 @@ int vc4_kms_load(struct drm_device *dev)
|
||||
/* Set support for vblank irq fast disable, before drm_vblank_init() */
|
||||
dev->vblank_disable_immediate = true;
|
||||
|
||||
dev->irq_enabled = true;
|
||||
ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
|
||||
if (ret < 0) {
|
||||
dev_err(dev->dev, "failed to initialize vblank\n");
|
||||
|
||||
@@ -100,12 +100,18 @@ void vc4_perfmon_close_file(struct vc4_file *vc4file)
|
||||
int vc4_perfmon_create_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct vc4_dev *vc4 = to_vc4_dev(dev);
|
||||
struct vc4_file *vc4file = file_priv->driver_priv;
|
||||
struct drm_vc4_perfmon_create *req = data;
|
||||
struct vc4_perfmon *perfmon;
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
if (!vc4->v3d) {
|
||||
DRM_DEBUG("Creating perfmon no VC4 V3D probed\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Number of monitored counters cannot exceed HW limits. */
|
||||
if (req->ncounters > DRM_VC4_MAX_PERF_COUNTERS ||
|
||||
!req->ncounters)
|
||||
@@ -146,10 +152,16 @@ int vc4_perfmon_create_ioctl(struct drm_device *dev, void *data,
|
||||
int vc4_perfmon_destroy_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct vc4_dev *vc4 = to_vc4_dev(dev);
|
||||
struct vc4_file *vc4file = file_priv->driver_priv;
|
||||
struct drm_vc4_perfmon_destroy *req = data;
|
||||
struct vc4_perfmon *perfmon;
|
||||
|
||||
if (!vc4->v3d) {
|
||||
DRM_DEBUG("Destroying perfmon no VC4 V3D probed\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
mutex_lock(&vc4file->perfmon.lock);
|
||||
perfmon = idr_remove(&vc4file->perfmon.idr, req->id);
|
||||
mutex_unlock(&vc4file->perfmon.lock);
|
||||
@@ -164,11 +176,17 @@ int vc4_perfmon_destroy_ioctl(struct drm_device *dev, void *data,
|
||||
int vc4_perfmon_get_values_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct vc4_dev *vc4 = to_vc4_dev(dev);
|
||||
struct vc4_file *vc4file = file_priv->driver_priv;
|
||||
struct drm_vc4_perfmon_get_values *req = data;
|
||||
struct vc4_perfmon *perfmon;
|
||||
int ret;
|
||||
|
||||
if (!vc4->v3d) {
|
||||
DRM_DEBUG("Getting perfmon no VC4 V3D probed\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
mutex_lock(&vc4file->perfmon.lock);
|
||||
perfmon = idr_find(&vc4file->perfmon.idr, req->id);
|
||||
vc4_perfmon_get(perfmon);
|
||||
|
||||
@@ -148,6 +148,12 @@ static void emit_tile(struct vc4_exec_info *exec,
|
||||
}
|
||||
|
||||
if (setup->zs_read) {
|
||||
if (setup->color_read) {
|
||||
/* Exec previous load. */
|
||||
vc4_tile_coordinates(setup, x, y);
|
||||
vc4_store_before_load(setup);
|
||||
}
|
||||
|
||||
if (args->zs_read.flags &
|
||||
VC4_SUBMIT_RCL_SURFACE_READ_IS_FULL_RES) {
|
||||
rcl_u8(setup, VC4_PACKET_LOAD_FULL_RES_TILE_BUFFER);
|
||||
@@ -156,12 +162,6 @@ static void emit_tile(struct vc4_exec_info *exec,
|
||||
&args->zs_read, x, y) |
|
||||
VC4_LOADSTORE_FULL_RES_DISABLE_COLOR);
|
||||
} else {
|
||||
if (setup->color_read) {
|
||||
/* Exec previous load. */
|
||||
vc4_tile_coordinates(setup, x, y);
|
||||
vc4_store_before_load(setup);
|
||||
}
|
||||
|
||||
rcl_u8(setup, VC4_PACKET_LOAD_TILE_BUFFER_GENERAL);
|
||||
rcl_u16(setup, args->zs_read.bits);
|
||||
rcl_u32(setup, setup->zs_read->paddr +
|
||||
@@ -291,16 +291,15 @@ static int vc4_create_rcl_bo(struct drm_device *dev, struct vc4_exec_info *exec,
|
||||
}
|
||||
}
|
||||
if (setup->zs_read) {
|
||||
if (setup->color_read) {
|
||||
loop_body_size += VC4_PACKET_TILE_COORDINATES_SIZE;
|
||||
loop_body_size += VC4_PACKET_STORE_TILE_BUFFER_GENERAL_SIZE;
|
||||
}
|
||||
|
||||
if (args->zs_read.flags &
|
||||
VC4_SUBMIT_RCL_SURFACE_READ_IS_FULL_RES) {
|
||||
loop_body_size += VC4_PACKET_LOAD_FULL_RES_TILE_BUFFER_SIZE;
|
||||
} else {
|
||||
if (setup->color_read &&
|
||||
!(args->color_read.flags &
|
||||
VC4_SUBMIT_RCL_SURFACE_READ_IS_FULL_RES)) {
|
||||
loop_body_size += VC4_PACKET_TILE_COORDINATES_SIZE;
|
||||
loop_body_size += VC4_PACKET_STORE_TILE_BUFFER_GENERAL_SIZE;
|
||||
}
|
||||
loop_body_size += VC4_PACKET_LOAD_TILE_BUFFER_GENERAL_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,6 +148,7 @@ struct vc4_txp {
|
||||
struct drm_writeback_connector connector;
|
||||
|
||||
void __iomem *regs;
|
||||
struct debugfs_regset32 regset;
|
||||
};
|
||||
|
||||
static inline struct vc4_txp *encoder_to_vc4_txp(struct drm_encoder *encoder)
|
||||
@@ -160,40 +161,14 @@ static inline struct vc4_txp *connector_to_vc4_txp(struct drm_connector *conn)
|
||||
return container_of(conn, struct vc4_txp, connector.base);
|
||||
}
|
||||
|
||||
#define TXP_REG(reg) { reg, #reg }
|
||||
static const struct {
|
||||
u32 reg;
|
||||
const char *name;
|
||||
} txp_regs[] = {
|
||||
TXP_REG(TXP_DST_PTR),
|
||||
TXP_REG(TXP_DST_PITCH),
|
||||
TXP_REG(TXP_DIM),
|
||||
TXP_REG(TXP_DST_CTRL),
|
||||
TXP_REG(TXP_PROGRESS),
|
||||
static const struct debugfs_reg32 txp_regs[] = {
|
||||
VC4_REG32(TXP_DST_PTR),
|
||||
VC4_REG32(TXP_DST_PITCH),
|
||||
VC4_REG32(TXP_DIM),
|
||||
VC4_REG32(TXP_DST_CTRL),
|
||||
VC4_REG32(TXP_PROGRESS),
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
int vc4_txp_debugfs_regs(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *)m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
struct vc4_dev *vc4 = to_vc4_dev(dev);
|
||||
struct vc4_txp *txp = vc4->txp;
|
||||
int i;
|
||||
|
||||
if (!txp)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(txp_regs); i++) {
|
||||
seq_printf(m, "%s (0x%04x): 0x%08x\n",
|
||||
txp_regs[i].name, txp_regs[i].reg,
|
||||
TXP_READ(txp_regs[i].reg));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int vc4_txp_connector_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
@@ -410,6 +385,9 @@ static int vc4_txp_bind(struct device *dev, struct device *master, void *data)
|
||||
txp->regs = vc4_ioremap_regs(pdev, 0);
|
||||
if (IS_ERR(txp->regs))
|
||||
return PTR_ERR(txp->regs);
|
||||
txp->regset.base = txp->regs;
|
||||
txp->regset.regs = txp_regs;
|
||||
txp->regset.nregs = ARRAY_SIZE(txp_regs);
|
||||
|
||||
drm_connector_helper_add(&txp->connector.base,
|
||||
&vc4_txp_connector_helper_funcs);
|
||||
@@ -428,6 +406,8 @@ static int vc4_txp_bind(struct device *dev, struct device *master, void *data)
|
||||
dev_set_drvdata(dev, txp);
|
||||
vc4->txp = txp;
|
||||
|
||||
vc4_debugfs_add_regset32(drm, "txp_regs", &txp->regset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,129 +22,145 @@
|
||||
#include "vc4_drv.h"
|
||||
#include "vc4_regs.h"
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
#define REGDEF(reg) { reg, #reg }
|
||||
static const struct {
|
||||
uint32_t reg;
|
||||
const char *name;
|
||||
} vc4_reg_defs[] = {
|
||||
REGDEF(V3D_IDENT0),
|
||||
REGDEF(V3D_IDENT1),
|
||||
REGDEF(V3D_IDENT2),
|
||||
REGDEF(V3D_SCRATCH),
|
||||
REGDEF(V3D_L2CACTL),
|
||||
REGDEF(V3D_SLCACTL),
|
||||
REGDEF(V3D_INTCTL),
|
||||
REGDEF(V3D_INTENA),
|
||||
REGDEF(V3D_INTDIS),
|
||||
REGDEF(V3D_CT0CS),
|
||||
REGDEF(V3D_CT1CS),
|
||||
REGDEF(V3D_CT0EA),
|
||||
REGDEF(V3D_CT1EA),
|
||||
REGDEF(V3D_CT0CA),
|
||||
REGDEF(V3D_CT1CA),
|
||||
REGDEF(V3D_CT00RA0),
|
||||
REGDEF(V3D_CT01RA0),
|
||||
REGDEF(V3D_CT0LC),
|
||||
REGDEF(V3D_CT1LC),
|
||||
REGDEF(V3D_CT0PC),
|
||||
REGDEF(V3D_CT1PC),
|
||||
REGDEF(V3D_PCS),
|
||||
REGDEF(V3D_BFC),
|
||||
REGDEF(V3D_RFC),
|
||||
REGDEF(V3D_BPCA),
|
||||
REGDEF(V3D_BPCS),
|
||||
REGDEF(V3D_BPOA),
|
||||
REGDEF(V3D_BPOS),
|
||||
REGDEF(V3D_BXCF),
|
||||
REGDEF(V3D_SQRSV0),
|
||||
REGDEF(V3D_SQRSV1),
|
||||
REGDEF(V3D_SQCNTL),
|
||||
REGDEF(V3D_SRQPC),
|
||||
REGDEF(V3D_SRQUA),
|
||||
REGDEF(V3D_SRQUL),
|
||||
REGDEF(V3D_SRQCS),
|
||||
REGDEF(V3D_VPACNTL),
|
||||
REGDEF(V3D_VPMBASE),
|
||||
REGDEF(V3D_PCTRC),
|
||||
REGDEF(V3D_PCTRE),
|
||||
REGDEF(V3D_PCTR(0)),
|
||||
REGDEF(V3D_PCTRS(0)),
|
||||
REGDEF(V3D_PCTR(1)),
|
||||
REGDEF(V3D_PCTRS(1)),
|
||||
REGDEF(V3D_PCTR(2)),
|
||||
REGDEF(V3D_PCTRS(2)),
|
||||
REGDEF(V3D_PCTR(3)),
|
||||
REGDEF(V3D_PCTRS(3)),
|
||||
REGDEF(V3D_PCTR(4)),
|
||||
REGDEF(V3D_PCTRS(4)),
|
||||
REGDEF(V3D_PCTR(5)),
|
||||
REGDEF(V3D_PCTRS(5)),
|
||||
REGDEF(V3D_PCTR(6)),
|
||||
REGDEF(V3D_PCTRS(6)),
|
||||
REGDEF(V3D_PCTR(7)),
|
||||
REGDEF(V3D_PCTRS(7)),
|
||||
REGDEF(V3D_PCTR(8)),
|
||||
REGDEF(V3D_PCTRS(8)),
|
||||
REGDEF(V3D_PCTR(9)),
|
||||
REGDEF(V3D_PCTRS(9)),
|
||||
REGDEF(V3D_PCTR(10)),
|
||||
REGDEF(V3D_PCTRS(10)),
|
||||
REGDEF(V3D_PCTR(11)),
|
||||
REGDEF(V3D_PCTRS(11)),
|
||||
REGDEF(V3D_PCTR(12)),
|
||||
REGDEF(V3D_PCTRS(12)),
|
||||
REGDEF(V3D_PCTR(13)),
|
||||
REGDEF(V3D_PCTRS(13)),
|
||||
REGDEF(V3D_PCTR(14)),
|
||||
REGDEF(V3D_PCTRS(14)),
|
||||
REGDEF(V3D_PCTR(15)),
|
||||
REGDEF(V3D_PCTRS(15)),
|
||||
REGDEF(V3D_DBGE),
|
||||
REGDEF(V3D_FDBGO),
|
||||
REGDEF(V3D_FDBGB),
|
||||
REGDEF(V3D_FDBGR),
|
||||
REGDEF(V3D_FDBGS),
|
||||
REGDEF(V3D_ERRSTAT),
|
||||
static const struct debugfs_reg32 v3d_regs[] = {
|
||||
VC4_REG32(V3D_IDENT0),
|
||||
VC4_REG32(V3D_IDENT1),
|
||||
VC4_REG32(V3D_IDENT2),
|
||||
VC4_REG32(V3D_SCRATCH),
|
||||
VC4_REG32(V3D_L2CACTL),
|
||||
VC4_REG32(V3D_SLCACTL),
|
||||
VC4_REG32(V3D_INTCTL),
|
||||
VC4_REG32(V3D_INTENA),
|
||||
VC4_REG32(V3D_INTDIS),
|
||||
VC4_REG32(V3D_CT0CS),
|
||||
VC4_REG32(V3D_CT1CS),
|
||||
VC4_REG32(V3D_CT0EA),
|
||||
VC4_REG32(V3D_CT1EA),
|
||||
VC4_REG32(V3D_CT0CA),
|
||||
VC4_REG32(V3D_CT1CA),
|
||||
VC4_REG32(V3D_CT00RA0),
|
||||
VC4_REG32(V3D_CT01RA0),
|
||||
VC4_REG32(V3D_CT0LC),
|
||||
VC4_REG32(V3D_CT1LC),
|
||||
VC4_REG32(V3D_CT0PC),
|
||||
VC4_REG32(V3D_CT1PC),
|
||||
VC4_REG32(V3D_PCS),
|
||||
VC4_REG32(V3D_BFC),
|
||||
VC4_REG32(V3D_RFC),
|
||||
VC4_REG32(V3D_BPCA),
|
||||
VC4_REG32(V3D_BPCS),
|
||||
VC4_REG32(V3D_BPOA),
|
||||
VC4_REG32(V3D_BPOS),
|
||||
VC4_REG32(V3D_BXCF),
|
||||
VC4_REG32(V3D_SQRSV0),
|
||||
VC4_REG32(V3D_SQRSV1),
|
||||
VC4_REG32(V3D_SQCNTL),
|
||||
VC4_REG32(V3D_SRQPC),
|
||||
VC4_REG32(V3D_SRQUA),
|
||||
VC4_REG32(V3D_SRQUL),
|
||||
VC4_REG32(V3D_SRQCS),
|
||||
VC4_REG32(V3D_VPACNTL),
|
||||
VC4_REG32(V3D_VPMBASE),
|
||||
VC4_REG32(V3D_PCTRC),
|
||||
VC4_REG32(V3D_PCTRE),
|
||||
VC4_REG32(V3D_PCTR(0)),
|
||||
VC4_REG32(V3D_PCTRS(0)),
|
||||
VC4_REG32(V3D_PCTR(1)),
|
||||
VC4_REG32(V3D_PCTRS(1)),
|
||||
VC4_REG32(V3D_PCTR(2)),
|
||||
VC4_REG32(V3D_PCTRS(2)),
|
||||
VC4_REG32(V3D_PCTR(3)),
|
||||
VC4_REG32(V3D_PCTRS(3)),
|
||||
VC4_REG32(V3D_PCTR(4)),
|
||||
VC4_REG32(V3D_PCTRS(4)),
|
||||
VC4_REG32(V3D_PCTR(5)),
|
||||
VC4_REG32(V3D_PCTRS(5)),
|
||||
VC4_REG32(V3D_PCTR(6)),
|
||||
VC4_REG32(V3D_PCTRS(6)),
|
||||
VC4_REG32(V3D_PCTR(7)),
|
||||
VC4_REG32(V3D_PCTRS(7)),
|
||||
VC4_REG32(V3D_PCTR(8)),
|
||||
VC4_REG32(V3D_PCTRS(8)),
|
||||
VC4_REG32(V3D_PCTR(9)),
|
||||
VC4_REG32(V3D_PCTRS(9)),
|
||||
VC4_REG32(V3D_PCTR(10)),
|
||||
VC4_REG32(V3D_PCTRS(10)),
|
||||
VC4_REG32(V3D_PCTR(11)),
|
||||
VC4_REG32(V3D_PCTRS(11)),
|
||||
VC4_REG32(V3D_PCTR(12)),
|
||||
VC4_REG32(V3D_PCTRS(12)),
|
||||
VC4_REG32(V3D_PCTR(13)),
|
||||
VC4_REG32(V3D_PCTRS(13)),
|
||||
VC4_REG32(V3D_PCTR(14)),
|
||||
VC4_REG32(V3D_PCTRS(14)),
|
||||
VC4_REG32(V3D_PCTR(15)),
|
||||
VC4_REG32(V3D_PCTRS(15)),
|
||||
VC4_REG32(V3D_DBGE),
|
||||
VC4_REG32(V3D_FDBGO),
|
||||
VC4_REG32(V3D_FDBGB),
|
||||
VC4_REG32(V3D_FDBGR),
|
||||
VC4_REG32(V3D_FDBGS),
|
||||
VC4_REG32(V3D_ERRSTAT),
|
||||
};
|
||||
|
||||
int vc4_v3d_debugfs_regs(struct seq_file *m, void *unused)
|
||||
static int vc4_v3d_debugfs_ident(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *)m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
struct vc4_dev *vc4 = to_vc4_dev(dev);
|
||||
int i;
|
||||
int ret = vc4_v3d_pm_get(vc4);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(vc4_reg_defs); i++) {
|
||||
seq_printf(m, "%s (0x%04x): 0x%08x\n",
|
||||
vc4_reg_defs[i].name, vc4_reg_defs[i].reg,
|
||||
V3D_READ(vc4_reg_defs[i].reg));
|
||||
if (ret == 0) {
|
||||
uint32_t ident1 = V3D_READ(V3D_IDENT1);
|
||||
uint32_t nslc = VC4_GET_FIELD(ident1, V3D_IDENT1_NSLC);
|
||||
uint32_t tups = VC4_GET_FIELD(ident1, V3D_IDENT1_TUPS);
|
||||
uint32_t qups = VC4_GET_FIELD(ident1, V3D_IDENT1_QUPS);
|
||||
|
||||
seq_printf(m, "Revision: %d\n",
|
||||
VC4_GET_FIELD(ident1, V3D_IDENT1_REV));
|
||||
seq_printf(m, "Slices: %d\n", nslc);
|
||||
seq_printf(m, "TMUs: %d\n", nslc * tups);
|
||||
seq_printf(m, "QPUs: %d\n", nslc * qups);
|
||||
seq_printf(m, "Semaphores: %d\n",
|
||||
VC4_GET_FIELD(ident1, V3D_IDENT1_NSEM));
|
||||
vc4_v3d_pm_put(vc4);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vc4_v3d_debugfs_ident(struct seq_file *m, void *unused)
|
||||
/**
|
||||
* Wraps pm_runtime_get_sync() in a refcount, so that we can reliably
|
||||
* get the pm_runtime refcount to 0 in vc4_reset().
|
||||
*/
|
||||
int
|
||||
vc4_v3d_pm_get(struct vc4_dev *vc4)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *)m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
struct vc4_dev *vc4 = to_vc4_dev(dev);
|
||||
uint32_t ident1 = V3D_READ(V3D_IDENT1);
|
||||
uint32_t nslc = VC4_GET_FIELD(ident1, V3D_IDENT1_NSLC);
|
||||
uint32_t tups = VC4_GET_FIELD(ident1, V3D_IDENT1_TUPS);
|
||||
uint32_t qups = VC4_GET_FIELD(ident1, V3D_IDENT1_QUPS);
|
||||
mutex_lock(&vc4->power_lock);
|
||||
if (vc4->power_refcount++ == 0) {
|
||||
int ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev);
|
||||
|
||||
seq_printf(m, "Revision: %d\n",
|
||||
VC4_GET_FIELD(ident1, V3D_IDENT1_REV));
|
||||
seq_printf(m, "Slices: %d\n", nslc);
|
||||
seq_printf(m, "TMUs: %d\n", nslc * tups);
|
||||
seq_printf(m, "QPUs: %d\n", nslc * qups);
|
||||
seq_printf(m, "Semaphores: %d\n",
|
||||
VC4_GET_FIELD(ident1, V3D_IDENT1_NSEM));
|
||||
if (ret < 0) {
|
||||
vc4->power_refcount--;
|
||||
mutex_unlock(&vc4->power_lock);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&vc4->power_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_DEBUG_FS */
|
||||
|
||||
void
|
||||
vc4_v3d_pm_put(struct vc4_dev *vc4)
|
||||
{
|
||||
mutex_lock(&vc4->power_lock);
|
||||
if (--vc4->power_refcount == 0) {
|
||||
pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev);
|
||||
pm_runtime_put_autosuspend(&vc4->v3d->pdev->dev);
|
||||
}
|
||||
mutex_unlock(&vc4->power_lock);
|
||||
}
|
||||
|
||||
static void vc4_v3d_init_hw(struct drm_device *dev)
|
||||
{
|
||||
@@ -354,6 +370,9 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data)
|
||||
v3d->regs = vc4_ioremap_regs(pdev, 0);
|
||||
if (IS_ERR(v3d->regs))
|
||||
return PTR_ERR(v3d->regs);
|
||||
v3d->regset.base = v3d->regs;
|
||||
v3d->regset.regs = v3d_regs;
|
||||
v3d->regset.nregs = ARRAY_SIZE(v3d_regs);
|
||||
|
||||
vc4->v3d = v3d;
|
||||
v3d->vc4 = vc4;
|
||||
@@ -409,6 +428,9 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data)
|
||||
pm_runtime_set_autosuspend_delay(dev, 40); /* a little over 2 frames. */
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
vc4_debugfs_add_file(drm, "v3d_ident", vc4_v3d_debugfs_ident, NULL);
|
||||
vc4_debugfs_add_regset32(drm, "v3d_regs", &v3d->regset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -452,7 +474,7 @@ static int vc4_v3d_dev_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id vc4_v3d_dt_match[] = {
|
||||
const struct of_device_id vc4_v3d_dt_match[] = {
|
||||
{ .compatible = "brcm,bcm2835-v3d" },
|
||||
{ .compatible = "brcm,cygnus-v3d" },
|
||||
{ .compatible = "brcm,vc4-v3d" },
|
||||
|
||||
@@ -176,6 +176,8 @@ struct vc4_vec {
|
||||
struct clk *clock;
|
||||
|
||||
const struct vc4_vec_tv_mode *tv_mode;
|
||||
|
||||
struct debugfs_regset32 regset;
|
||||
};
|
||||
|
||||
#define VEC_READ(offset) readl(vec->regs + (offset))
|
||||
@@ -223,59 +225,33 @@ struct vc4_vec_tv_mode {
|
||||
void (*mode_set)(struct vc4_vec *vec);
|
||||
};
|
||||
|
||||
#define VEC_REG(reg) { reg, #reg }
|
||||
static const struct {
|
||||
u32 reg;
|
||||
const char *name;
|
||||
} vec_regs[] = {
|
||||
VEC_REG(VEC_WSE_CONTROL),
|
||||
VEC_REG(VEC_WSE_WSS_DATA),
|
||||
VEC_REG(VEC_WSE_VPS_DATA1),
|
||||
VEC_REG(VEC_WSE_VPS_CONTROL),
|
||||
VEC_REG(VEC_REVID),
|
||||
VEC_REG(VEC_CONFIG0),
|
||||
VEC_REG(VEC_SCHPH),
|
||||
VEC_REG(VEC_CLMP0_START),
|
||||
VEC_REG(VEC_CLMP0_END),
|
||||
VEC_REG(VEC_FREQ3_2),
|
||||
VEC_REG(VEC_FREQ1_0),
|
||||
VEC_REG(VEC_CONFIG1),
|
||||
VEC_REG(VEC_CONFIG2),
|
||||
VEC_REG(VEC_INTERRUPT_CONTROL),
|
||||
VEC_REG(VEC_INTERRUPT_STATUS),
|
||||
VEC_REG(VEC_FCW_SECAM_B),
|
||||
VEC_REG(VEC_SECAM_GAIN_VAL),
|
||||
VEC_REG(VEC_CONFIG3),
|
||||
VEC_REG(VEC_STATUS0),
|
||||
VEC_REG(VEC_MASK0),
|
||||
VEC_REG(VEC_CFG),
|
||||
VEC_REG(VEC_DAC_TEST),
|
||||
VEC_REG(VEC_DAC_CONFIG),
|
||||
VEC_REG(VEC_DAC_MISC),
|
||||
static const struct debugfs_reg32 vec_regs[] = {
|
||||
VC4_REG32(VEC_WSE_CONTROL),
|
||||
VC4_REG32(VEC_WSE_WSS_DATA),
|
||||
VC4_REG32(VEC_WSE_VPS_DATA1),
|
||||
VC4_REG32(VEC_WSE_VPS_CONTROL),
|
||||
VC4_REG32(VEC_REVID),
|
||||
VC4_REG32(VEC_CONFIG0),
|
||||
VC4_REG32(VEC_SCHPH),
|
||||
VC4_REG32(VEC_CLMP0_START),
|
||||
VC4_REG32(VEC_CLMP0_END),
|
||||
VC4_REG32(VEC_FREQ3_2),
|
||||
VC4_REG32(VEC_FREQ1_0),
|
||||
VC4_REG32(VEC_CONFIG1),
|
||||
VC4_REG32(VEC_CONFIG2),
|
||||
VC4_REG32(VEC_INTERRUPT_CONTROL),
|
||||
VC4_REG32(VEC_INTERRUPT_STATUS),
|
||||
VC4_REG32(VEC_FCW_SECAM_B),
|
||||
VC4_REG32(VEC_SECAM_GAIN_VAL),
|
||||
VC4_REG32(VEC_CONFIG3),
|
||||
VC4_REG32(VEC_STATUS0),
|
||||
VC4_REG32(VEC_MASK0),
|
||||
VC4_REG32(VEC_CFG),
|
||||
VC4_REG32(VEC_DAC_TEST),
|
||||
VC4_REG32(VEC_DAC_CONFIG),
|
||||
VC4_REG32(VEC_DAC_MISC),
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
int vc4_vec_debugfs_regs(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *)m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
struct vc4_dev *vc4 = to_vc4_dev(dev);
|
||||
struct vc4_vec *vec = vc4->vec;
|
||||
int i;
|
||||
|
||||
if (!vec)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(vec_regs); i++) {
|
||||
seq_printf(m, "%s (0x%04x): 0x%08x\n",
|
||||
vec_regs[i].name, vec_regs[i].reg,
|
||||
VEC_READ(vec_regs[i].reg));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void vc4_vec_ntsc_mode_set(struct vc4_vec *vec)
|
||||
{
|
||||
VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_NTSC_STD | VEC_CONFIG0_PDEN);
|
||||
@@ -587,6 +563,9 @@ static int vc4_vec_bind(struct device *dev, struct device *master, void *data)
|
||||
vec->regs = vc4_ioremap_regs(pdev, 0);
|
||||
if (IS_ERR(vec->regs))
|
||||
return PTR_ERR(vec->regs);
|
||||
vec->regset.base = vec->regs;
|
||||
vec->regset.regs = vec_regs;
|
||||
vec->regset.nregs = ARRAY_SIZE(vec_regs);
|
||||
|
||||
vec->clock = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(vec->clock)) {
|
||||
@@ -612,6 +591,8 @@ static int vc4_vec_bind(struct device *dev, struct device *master, void *data)
|
||||
|
||||
vc4->vec = vec;
|
||||
|
||||
vc4_debugfs_add_regset32(drm, "vec_regs", &vec->regset);
|
||||
|
||||
return 0;
|
||||
|
||||
err_destroy_encoder:
|
||||
|
||||
Reference in New Issue
Block a user