summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/tegra/dc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/tegra/dc.c')
-rw-r--r--drivers/gpu/drm/tegra/dc.c82
1 files changed, 80 insertions, 2 deletions
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index 386f3b4b0094..9684109de6cc 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -225,6 +225,79 @@ void tegra_dc_disable_vblank(struct tegra_dc *dc)
spin_unlock_irqrestore(&dc->lock, flags);
}
+static int tegra_dc_cursor_set2(struct drm_crtc *crtc, struct drm_file *file,
+ uint32_t handle, uint32_t width,
+ uint32_t height, int32_t hot_x, int32_t hot_y)
+{
+ struct tegra_dc *dc = to_tegra_dc(crtc);
+ struct drm_gem_object *gem;
+ struct tegra_bo *bo = NULL;
+ unsigned long value;
+ int ret = 0;
+
+ dev_dbg(dc->dev, "> %s(crtc=%p, file=%p, handle=%x, width=%u, height=%u, hot_x=%d, hot_y=%d)\n",
+ __func__, crtc, file, handle, width, height, hot_x, hot_y);
+
+ if (handle) {
+ gem = drm_gem_object_lookup(crtc->dev, file, handle);
+ if (!gem) {
+ ret = -ENOENT;
+ goto out;
+ }
+
+ bo = to_tegra_bo(gem);
+ }
+
+ if (bo) {
+ value = (0 << 28) | (1 << 24) | bo->paddr >> 10;
+ tegra_dc_writel(dc, bo->paddr, DC_DISP_CURSOR_START_ADDR);
+
+ value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
+ value |= CURSOR_ENABLE;
+ tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
+
+ value = tegra_dc_readl(dc, DC_DISP_BLEND_CURSOR_CONTROL);
+ value |= (1 << 24);
+ value &= ~(3 << 16);
+ value &= ~(3 << 8);
+ value &= ~0xff;
+ tegra_dc_writel(dc, value, DC_DISP_BLEND_CURSOR_CONTROL);
+ } else {
+ value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
+ value &= ~CURSOR_ENABLE;
+ tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
+ }
+
+ tegra_dc_writel(dc, 1 << 15, DC_CMD_STATE_CONTROL);
+ tegra_dc_writel(dc, 1 << 7, DC_CMD_STATE_CONTROL);
+
+ tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
+ tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
+
+out:
+ dev_dbg(dc->dev, "< %s() = %d\n", __func__, ret);
+ return ret;
+}
+
+static int tegra_dc_cursor_move(struct drm_crtc *crtc, int x, int y)
+{
+ struct tegra_dc *dc = to_tegra_dc(crtc);
+ int ret = 0;
+
+ dev_dbg(dc->dev, "> %s(crtc=%p, x=%d, y=%d)\n", __func__, crtc, x, y);
+
+ tegra_dc_writel(dc, (x << 16) | y, DC_DISP_CURSOR_POSITION);
+
+ tegra_dc_writel(dc, 1 << 15, DC_CMD_STATE_CONTROL);
+ tegra_dc_writel(dc, 1 << 7, DC_CMD_STATE_CONTROL);
+
+ tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
+ tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
+
+ dev_dbg(dc->dev, "< %s() = %d\n", __func__, ret);
+ return ret;
+}
+
static void tegra_dc_finish_page_flip(struct tegra_dc *dc)
{
struct drm_device *drm = dc->base.dev;
@@ -301,6 +374,8 @@ static void tegra_dc_destroy(struct drm_crtc *crtc)
}
static const struct drm_crtc_funcs tegra_crtc_funcs = {
+ .cursor_set2 = tegra_dc_cursor_set2,
+ .cursor_move = tegra_dc_cursor_move,
.page_flip = tegra_dc_page_flip,
.set_config = drm_crtc_helper_set_config,
.destroy = tegra_dc_destroy,
@@ -1100,8 +1175,6 @@ static int tegra_dc_init(struct host1x_client *client)
struct tegra_dc *dc = host1x_client_to_dc(client);
int err;
- dc->pipe = tegra->drm->mode_config.num_crtc;
-
drm_crtc_init(tegra->drm, &dc->base, &tegra_crtc_funcs);
drm_mode_crtc_set_gamma_size(&dc->base, 256);
drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs);
@@ -1228,6 +1301,11 @@ static int tegra_dc_probe(struct platform_device *pdev)
if (IS_ERR(dc->regs))
return PTR_ERR(dc->regs);
+ if (regs->start == 0x54200000)
+ dc->pipe = 0;
+ else
+ dc->pipe = 1;
+
dc->irq = platform_get_irq(pdev, 0);
if (dc->irq < 0) {
dev_err(&pdev->dev, "failed to get IRQ\n");