Skip to content

Commit

Permalink
Merge tag 'drm/tegra/for-4.15-rc1' of git://anongit.freedesktop.org/t…
Browse files Browse the repository at this point in the history
…egra/linux into drm-next

drm/tegra: Changes for v4.15-rc1

This contains a bit of cleanup and some minor fixes for the host1x and
Tegra DRM drivers. There's also some more preparatory work for Tegra186
support which I'm not quite ready to send upstream because the GPIO
driver needed for HDMI support has been stuck for months, and we can't
do much without it. Hopefully that driver will land in v4.15, which
would mean we could go ahead with Tegra186 display support in v4.16.

* tag 'drm/tegra/for-4.15-rc1' of git://anongit.freedesktop.org/tegra/linux: (21 commits)
  drm/tegra: hdmi: Add cec-notifier support
  drm/tegra: dc: Perform a complete reset sequence
  drm/tegra: dc: Make sure to set the module clock rate
  drm/tegra: dc: Simplify atomic plane helper functions
  drm/tegra: dc: Move some declarations to dc.h
  drm/tegra: vic: Use of_device_get_match_data()
  drm/tegra: sor: Use of_device_get_match_data()
  drm/tegra: hdmi: Use of_device_get_match_data()
  drm/tegra: dc: Use of_device_get_match_data()
  drm/tegra: Use u64_to_user_ptr helper
  gpu: host1x: Fix incorrect comment for channel_request
  gpu: host1x: Disassemble more instructions
  gpu: host1x: Improve debug disassembly formatting
  gpu: host1x: Enable gather filter
  gpu: host1x: Enable Tegra186 syncpoint protection
  gpu: host1x: Call of_dma_configure() after setting bus
  drm/tegra: Add Tegra186 support for VIC
  gpu: host1x: Add Tegra186 support
  dt-bindings: host1x: Add Tegra186 information
  gpu: host1x: syncpt: Request syncpoints per client
  ...
  • Loading branch information
Dave Airlie committed Oct 24, 2017
2 parents 3064abf + fb83be8 commit 3b677e4
Show file tree
Hide file tree
Showing 41 changed files with 1,334 additions and 399 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ NVIDIA Tegra host1x
Required properties:
- compatible: "nvidia,tegra<chip>-host1x"
- reg: Physical base address and length of the controller's registers.
For pre-Tegra186, one entry describing the whole register area.
For Tegra186, one entry for each entry in reg-names:
"vm" - VM region assigned to Linux
"hypervisor" - Hypervisor region (only if Linux acts as hypervisor)
- interrupts: The interrupt outputs from the controller.
- #address-cells: The number of cells used to represent physical base addresses
in the host1x address space. Should be 1.
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/tegra/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ config DRM_TEGRA
select DRM_PANEL
select TEGRA_HOST1X
select IOMMU_IOVA if IOMMU_SUPPORT
select CEC_CORE if CEC_NOTIFIER
help
Choose this option if you have an NVIDIA Tegra SoC.

Expand Down
84 changes: 38 additions & 46 deletions drivers/gpu/drm/tegra/dc.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <linux/clk.h>
#include <linux/debugfs.h>
#include <linux/iommu.h>
#include <linux/of_device.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>

Expand All @@ -23,16 +24,6 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_plane_helper.h>

struct tegra_dc_soc_info {
bool supports_border_color;
bool supports_interlacing;
bool supports_cursor;
bool supports_block_linear;
unsigned int pitch_align;
bool has_powergate;
bool broken_reset;
};

struct tegra_plane {
struct drm_plane base;
unsigned int index;
Expand Down Expand Up @@ -559,14 +550,21 @@ static int tegra_plane_atomic_check(struct drm_plane *plane,
return 0;
}

static void tegra_dc_disable_window(struct tegra_dc *dc, int index)
static void tegra_plane_atomic_disable(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
struct tegra_dc *dc = to_tegra_dc(old_state->crtc);
struct tegra_plane *p = to_tegra_plane(plane);
unsigned long flags;
u32 value;

/* rien ne va plus */
if (!old_state || !old_state->crtc)
return;

spin_lock_irqsave(&dc->lock, flags);

value = WINDOW_A_SELECT << index;
value = WINDOW_A_SELECT << p->index;
tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER);

value = tegra_dc_readl(dc, DC_WIN_WIN_OPTIONS);
Expand All @@ -591,7 +589,7 @@ static void tegra_plane_atomic_update(struct drm_plane *plane,
return;

if (!plane->state->visible)
return tegra_dc_disable_window(dc, p->index);
return tegra_plane_atomic_disable(plane, old_state);

memset(&window, 0, sizeof(window));
window.src.x = plane->state->src.x1 >> 16;
Expand Down Expand Up @@ -627,25 +625,10 @@ static void tegra_plane_atomic_update(struct drm_plane *plane,
tegra_dc_setup_window(dc, p->index, &window);
}

static void tegra_plane_atomic_disable(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
struct tegra_plane *p = to_tegra_plane(plane);
struct tegra_dc *dc;

/* rien ne va plus */
if (!old_state || !old_state->crtc)
return;

dc = to_tegra_dc(old_state->crtc);

tegra_dc_disable_window(dc, p->index);
}

static const struct drm_plane_helper_funcs tegra_primary_plane_helper_funcs = {
static const struct drm_plane_helper_funcs tegra_plane_helper_funcs = {
.atomic_check = tegra_plane_atomic_check,
.atomic_update = tegra_plane_atomic_update,
.atomic_disable = tegra_plane_atomic_disable,
.atomic_update = tegra_plane_atomic_update,
};

static struct drm_plane *tegra_dc_primary_plane_create(struct drm_device *drm,
Expand Down Expand Up @@ -685,7 +668,7 @@ static struct drm_plane *tegra_dc_primary_plane_create(struct drm_device *drm,
return ERR_PTR(err);
}

drm_plane_helper_add(&plane->base, &tegra_primary_plane_helper_funcs);
drm_plane_helper_add(&plane->base, &tegra_plane_helper_funcs);

return &plane->base;
}
Expand Down Expand Up @@ -880,12 +863,6 @@ static const uint32_t tegra_overlay_plane_formats[] = {
DRM_FORMAT_YUV422,
};

static const struct drm_plane_helper_funcs tegra_overlay_plane_helper_funcs = {
.atomic_check = tegra_plane_atomic_check,
.atomic_update = tegra_plane_atomic_update,
.atomic_disable = tegra_plane_atomic_disable,
};

static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm,
struct tegra_dc *dc,
unsigned int index)
Expand Down Expand Up @@ -913,7 +890,7 @@ static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm,
return ERR_PTR(err);
}

drm_plane_helper_add(&plane->base, &tegra_overlay_plane_helper_funcs);
drm_plane_helper_add(&plane->base, &tegra_plane_helper_funcs);

return &plane->base;
}
Expand Down Expand Up @@ -1161,6 +1138,11 @@ static void tegra_dc_commit_state(struct tegra_dc *dc,

value = SHIFT_CLK_DIVIDER(state->div) | PIXEL_CLK_DIVIDER_PCD1;
tegra_dc_writel(dc, value, DC_DISP_DISP_CLOCK_CONTROL);

err = clk_set_rate(dc->clk, state->pclk);
if (err < 0)
dev_err(dc->dev, "failed to set clock %pC to %lu Hz: %d\n",
dc->clk, state->pclk, err);
}

static void tegra_dc_stop(struct tegra_dc *dc)
Expand Down Expand Up @@ -1756,7 +1738,7 @@ static int tegra_dc_init(struct host1x_client *client)
struct drm_plane *cursor = NULL;
int err;

dc->syncpt = host1x_syncpt_request(dc->dev, flags);
dc->syncpt = host1x_syncpt_request(client, flags);
if (!dc->syncpt)
dev_warn(dc->dev, "failed to allocate syncpoint\n");

Expand Down Expand Up @@ -1985,7 +1967,6 @@ static int tegra_dc_parse_dt(struct tegra_dc *dc)

static int tegra_dc_probe(struct platform_device *pdev)
{
const struct of_device_id *id;
struct resource *regs;
struct tegra_dc *dc;
int err;
Expand All @@ -1994,14 +1975,11 @@ static int tegra_dc_probe(struct platform_device *pdev)
if (!dc)
return -ENOMEM;

id = of_match_node(tegra_dc_of_match, pdev->dev.of_node);
if (!id)
return -ENODEV;
dc->soc = of_device_get_match_data(&pdev->dev);

spin_lock_init(&dc->lock);
INIT_LIST_HEAD(&dc->list);
dc->dev = &pdev->dev;
dc->soc = id->data;

err = tegra_dc_parse_dt(dc);
if (err < 0)
Expand All @@ -2019,8 +1997,22 @@ static int tegra_dc_probe(struct platform_device *pdev)
return PTR_ERR(dc->rst);
}

if (!dc->soc->broken_reset)
reset_control_assert(dc->rst);
/* assert reset and disable clock */
if (!dc->soc->broken_reset) {
err = clk_prepare_enable(dc->clk);
if (err < 0)
return err;

usleep_range(2000, 4000);

err = reset_control_assert(dc->rst);
if (err < 0)
return err;

usleep_range(2000, 4000);

clk_disable_unprepare(dc->clk);
}

if (dc->soc->has_powergate) {
if (dc->pipe == 0)
Expand Down
120 changes: 120 additions & 0 deletions drivers/gpu/drm/tegra/dc.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,126 @@
#ifndef TEGRA_DC_H
#define TEGRA_DC_H 1

#include <linux/host1x.h>

#include <drm/drm_crtc.h>

#include "drm.h"

struct tegra_output;

struct tegra_dc_stats {
unsigned long frames;
unsigned long vblank;
unsigned long underflow;
unsigned long overflow;
};

struct tegra_dc_soc_info {
bool supports_border_color;
bool supports_interlacing;
bool supports_cursor;
bool supports_block_linear;
unsigned int pitch_align;
bool has_powergate;
bool broken_reset;
};

struct tegra_dc {
struct host1x_client client;
struct host1x_syncpt *syncpt;
struct device *dev;
spinlock_t lock;

struct drm_crtc base;
unsigned int powergate;
int pipe;

struct clk *clk;
struct reset_control *rst;
void __iomem *regs;
int irq;

struct tegra_output *rgb;

struct tegra_dc_stats stats;
struct list_head list;

struct drm_info_list *debugfs_files;
struct drm_minor *minor;
struct dentry *debugfs;

/* page-flip handling */
struct drm_pending_vblank_event *event;

const struct tegra_dc_soc_info *soc;

struct iommu_domain *domain;
};

static inline struct tegra_dc *
host1x_client_to_dc(struct host1x_client *client)
{
return container_of(client, struct tegra_dc, client);
}

static inline struct tegra_dc *to_tegra_dc(struct drm_crtc *crtc)
{
return crtc ? container_of(crtc, struct tegra_dc, base) : NULL;
}

static inline void tegra_dc_writel(struct tegra_dc *dc, u32 value,
unsigned int offset)
{
trace_dc_writel(dc->dev, offset, value);
writel(value, dc->regs + (offset << 2));
}

static inline u32 tegra_dc_readl(struct tegra_dc *dc, unsigned int offset)
{
u32 value = readl(dc->regs + (offset << 2));

trace_dc_readl(dc->dev, offset, value);

return value;
}

struct tegra_dc_window {
struct {
unsigned int x;
unsigned int y;
unsigned int w;
unsigned int h;
} src;
struct {
unsigned int x;
unsigned int y;
unsigned int w;
unsigned int h;
} dst;
unsigned int bits_per_pixel;
unsigned int stride[2];
unsigned long base[3];
bool bottom_up;

struct tegra_bo_tiling tiling;
u32 format;
u32 swap;
};

/* from dc.c */
void tegra_dc_commit(struct tegra_dc *dc);
int tegra_dc_state_setup_clock(struct tegra_dc *dc,
struct drm_crtc_state *crtc_state,
struct clk *clk, unsigned long pclk,
unsigned int div);

/* from rgb.c */
int tegra_dc_rgb_probe(struct tegra_dc *dc);
int tegra_dc_rgb_remove(struct tegra_dc *dc);
int tegra_dc_rgb_init(struct drm_device *drm, struct tegra_dc *dc);
int tegra_dc_rgb_exit(struct tegra_dc *dc);

#define DC_CMD_GENERAL_INCR_SYNCPT 0x000
#define DC_CMD_GENERAL_INCR_SYNCPT_CNTRL 0x001
#define SYNCPT_CNTRL_NO_STALL (1 << 8)
Expand Down
Loading

0 comments on commit 3b677e4

Please sign in to comment.