1d722e3fbSopenharmony_ci/*
2d722e3fbSopenharmony_ci * Copyright © 2014 NVIDIA Corporation
3d722e3fbSopenharmony_ci *
4d722e3fbSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5d722e3fbSopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6d722e3fbSopenharmony_ci * to deal in the Software without restriction, including without limitation
7d722e3fbSopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8d722e3fbSopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9d722e3fbSopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10d722e3fbSopenharmony_ci *
11d722e3fbSopenharmony_ci * The above copyright notice and this permission notice shall be included in
12d722e3fbSopenharmony_ci * all copies or substantial portions of the Software.
13d722e3fbSopenharmony_ci *
14d722e3fbSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15d722e3fbSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16d722e3fbSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17d722e3fbSopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18d722e3fbSopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19d722e3fbSopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20d722e3fbSopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
21d722e3fbSopenharmony_ci */
22d722e3fbSopenharmony_ci
23d722e3fbSopenharmony_ci#ifdef HAVE_CONFIG_H
24d722e3fbSopenharmony_ci#  include "config.h"
25d722e3fbSopenharmony_ci#endif
26d722e3fbSopenharmony_ci
27d722e3fbSopenharmony_ci#include <errno.h>
28d722e3fbSopenharmony_ci#include <stdio.h>
29d722e3fbSopenharmony_ci
30d722e3fbSopenharmony_ci#include "drm-test-tegra.h"
31d722e3fbSopenharmony_ci#include "tegra.h"
32d722e3fbSopenharmony_ci
33d722e3fbSopenharmony_ciint drm_tegra_gr2d_open(struct drm_tegra *drm, struct drm_tegra_gr2d **gr2dp)
34d722e3fbSopenharmony_ci{
35d722e3fbSopenharmony_ci    struct drm_tegra_gr2d *gr2d;
36d722e3fbSopenharmony_ci    int err;
37d722e3fbSopenharmony_ci
38d722e3fbSopenharmony_ci    gr2d = calloc(1, sizeof(*gr2d));
39d722e3fbSopenharmony_ci    if (!gr2d)
40d722e3fbSopenharmony_ci        return -ENOMEM;
41d722e3fbSopenharmony_ci
42d722e3fbSopenharmony_ci    gr2d->drm = drm;
43d722e3fbSopenharmony_ci
44d722e3fbSopenharmony_ci    err = drm_tegra_channel_open(drm, DRM_TEGRA_GR2D, &gr2d->channel);
45d722e3fbSopenharmony_ci    if (err < 0) {
46d722e3fbSopenharmony_ci        free(gr2d);
47d722e3fbSopenharmony_ci        return err;
48d722e3fbSopenharmony_ci    }
49d722e3fbSopenharmony_ci
50d722e3fbSopenharmony_ci    *gr2dp = gr2d;
51d722e3fbSopenharmony_ci
52d722e3fbSopenharmony_ci    return 0;
53d722e3fbSopenharmony_ci}
54d722e3fbSopenharmony_ci
55d722e3fbSopenharmony_ciint drm_tegra_gr2d_close(struct drm_tegra_gr2d *gr2d)
56d722e3fbSopenharmony_ci{
57d722e3fbSopenharmony_ci    if (!gr2d)
58d722e3fbSopenharmony_ci        return -EINVAL;
59d722e3fbSopenharmony_ci
60d722e3fbSopenharmony_ci    drm_tegra_channel_close(gr2d->channel);
61d722e3fbSopenharmony_ci    free(gr2d);
62d722e3fbSopenharmony_ci
63d722e3fbSopenharmony_ci    return 0;
64d722e3fbSopenharmony_ci}
65d722e3fbSopenharmony_ci
66d722e3fbSopenharmony_ciint drm_tegra_gr2d_fill(struct drm_tegra_gr2d *gr2d, struct drm_framebuffer *fb,
67d722e3fbSopenharmony_ci                        unsigned int x, unsigned int y, unsigned int width,
68d722e3fbSopenharmony_ci                        unsigned int height, uint32_t color)
69d722e3fbSopenharmony_ci{
70d722e3fbSopenharmony_ci    struct drm_tegra_bo *fbo = fb->data;
71d722e3fbSopenharmony_ci    struct drm_tegra_pushbuf *pushbuf;
72d722e3fbSopenharmony_ci    struct drm_tegra_mapping *map;
73d722e3fbSopenharmony_ci    struct drm_tegra_job *job;
74d722e3fbSopenharmony_ci    uint32_t *ptr;
75d722e3fbSopenharmony_ci    int err;
76d722e3fbSopenharmony_ci
77d722e3fbSopenharmony_ci    err = drm_tegra_job_new(gr2d->channel, &job);
78d722e3fbSopenharmony_ci    if (err < 0)
79d722e3fbSopenharmony_ci        return err;
80d722e3fbSopenharmony_ci
81d722e3fbSopenharmony_ci    err = drm_tegra_channel_map(gr2d->channel, fbo, 0, &map);
82d722e3fbSopenharmony_ci    if (err < 0)
83d722e3fbSopenharmony_ci        return err;
84d722e3fbSopenharmony_ci
85d722e3fbSopenharmony_ci    err = drm_tegra_job_get_pushbuf(job, &pushbuf);
86d722e3fbSopenharmony_ci    if (err < 0)
87d722e3fbSopenharmony_ci        return err;
88d722e3fbSopenharmony_ci
89d722e3fbSopenharmony_ci    err = drm_tegra_pushbuf_begin(pushbuf, 32, &ptr);
90d722e3fbSopenharmony_ci    if (err < 0)
91d722e3fbSopenharmony_ci        return err;
92d722e3fbSopenharmony_ci
93d722e3fbSopenharmony_ci    *ptr++ = HOST1X_OPCODE_SETCL(0, HOST1X_CLASS_GR2D, 0);
94d722e3fbSopenharmony_ci
95d722e3fbSopenharmony_ci    *ptr++ = HOST1X_OPCODE_MASK(0x9, 0x9);
96d722e3fbSopenharmony_ci    *ptr++ = 0x0000003a;
97d722e3fbSopenharmony_ci    *ptr++ = 0x00000000;
98d722e3fbSopenharmony_ci
99d722e3fbSopenharmony_ci    *ptr++ = HOST1X_OPCODE_MASK(0x1e, 0x7);
100d722e3fbSopenharmony_ci    *ptr++ = 0x00000000;
101d722e3fbSopenharmony_ci    *ptr++ = (2 << 16) | (1 << 6) | (1 << 2);
102d722e3fbSopenharmony_ci    *ptr++ = 0x000000cc;
103d722e3fbSopenharmony_ci
104d722e3fbSopenharmony_ci    *ptr++ = HOST1X_OPCODE_MASK(0x2b, 0x9);
105d722e3fbSopenharmony_ci
106d722e3fbSopenharmony_ci    /* relocate destination buffer */
107d722e3fbSopenharmony_ci    err = drm_tegra_pushbuf_relocate(pushbuf, &ptr, map, 0, 0, 0);
108d722e3fbSopenharmony_ci    if (err < 0) {
109d722e3fbSopenharmony_ci        fprintf(stderr, "failed to relocate buffer object: %d\n", err);
110d722e3fbSopenharmony_ci        return err;
111d722e3fbSopenharmony_ci    }
112d722e3fbSopenharmony_ci
113d722e3fbSopenharmony_ci    *ptr++ = fb->pitch;
114d722e3fbSopenharmony_ci
115d722e3fbSopenharmony_ci    *ptr++ = HOST1X_OPCODE_NONINCR(0x35, 1);
116d722e3fbSopenharmony_ci    *ptr++ = color;
117d722e3fbSopenharmony_ci
118d722e3fbSopenharmony_ci    *ptr++ = HOST1X_OPCODE_NONINCR(0x46, 1);
119d722e3fbSopenharmony_ci    *ptr++ = 0x00000000;
120d722e3fbSopenharmony_ci
121d722e3fbSopenharmony_ci    *ptr++ = HOST1X_OPCODE_MASK(0x38, 0x5);
122d722e3fbSopenharmony_ci    *ptr++ = height << 16 | width;
123d722e3fbSopenharmony_ci    *ptr++ = y << 16 | x;
124d722e3fbSopenharmony_ci
125d722e3fbSopenharmony_ci    err = drm_tegra_pushbuf_end(pushbuf, ptr);
126d722e3fbSopenharmony_ci    if (err < 0) {
127d722e3fbSopenharmony_ci        fprintf(stderr, "failed to update push buffer: %d\n", -err);
128d722e3fbSopenharmony_ci        return err;
129d722e3fbSopenharmony_ci    }
130d722e3fbSopenharmony_ci
131d722e3fbSopenharmony_ci    err = drm_tegra_job_submit(job, NULL);
132d722e3fbSopenharmony_ci    if (err < 0) {
133d722e3fbSopenharmony_ci        fprintf(stderr, "failed to submit job: %d\n", err);
134d722e3fbSopenharmony_ci        return err;
135d722e3fbSopenharmony_ci    }
136d722e3fbSopenharmony_ci
137d722e3fbSopenharmony_ci    err = drm_tegra_job_wait(job, 0);
138d722e3fbSopenharmony_ci    if (err < 0) {
139d722e3fbSopenharmony_ci        fprintf(stderr, "failed to wait for fence: %d\n", err);
140d722e3fbSopenharmony_ci        return err;
141d722e3fbSopenharmony_ci    }
142d722e3fbSopenharmony_ci
143d722e3fbSopenharmony_ci    drm_tegra_channel_unmap(map);
144d722e3fbSopenharmony_ci    drm_tegra_job_free(job);
145d722e3fbSopenharmony_ci
146d722e3fbSopenharmony_ci    return 0;
147d722e3fbSopenharmony_ci}
148