1d722e3fbSopenharmony_ci/*
2d722e3fbSopenharmony_ci * Copyright © 2018 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#include <errno.h>
24d722e3fbSopenharmony_ci#include <stdio.h> /* XXX remove */
25d722e3fbSopenharmony_ci#include <stdlib.h>
26d722e3fbSopenharmony_ci
27d722e3fbSopenharmony_ci#include "util_math.h"
28d722e3fbSopenharmony_ci
29d722e3fbSopenharmony_ci#include "tegra.h"
30d722e3fbSopenharmony_ci#include "host1x.h"
31d722e3fbSopenharmony_ci#include "vic.h"
32d722e3fbSopenharmony_ci
33d722e3fbSopenharmony_ci#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
34d722e3fbSopenharmony_ci
35d722e3fbSopenharmony_ciconst struct vic_format_info *vic_format_get_info(unsigned int format)
36d722e3fbSopenharmony_ci{
37d722e3fbSopenharmony_ci    static const struct vic_format_info formats[] = {
38d722e3fbSopenharmony_ci        { .format = VIC_PIXEL_FORMAT_A8R8G8B8, .cpp = 4 },
39d722e3fbSopenharmony_ci    };
40d722e3fbSopenharmony_ci    unsigned int i;
41d722e3fbSopenharmony_ci
42d722e3fbSopenharmony_ci    for (i = 0; i < ARRAY_SIZE(formats); i++) {
43d722e3fbSopenharmony_ci        if (formats[i].format == format)
44d722e3fbSopenharmony_ci            return &formats[i];
45d722e3fbSopenharmony_ci    }
46d722e3fbSopenharmony_ci
47d722e3fbSopenharmony_ci    return 0;
48d722e3fbSopenharmony_ci}
49d722e3fbSopenharmony_ci
50d722e3fbSopenharmony_ciint vic_image_new(struct vic *vic, unsigned int width, unsigned int height,
51d722e3fbSopenharmony_ci                  unsigned int format, unsigned int kind, uint32_t flags,
52d722e3fbSopenharmony_ci                  struct vic_image **imagep)
53d722e3fbSopenharmony_ci{
54d722e3fbSopenharmony_ci    const struct vic_format_info *info = vic_format_get_info(format);
55d722e3fbSopenharmony_ci    struct vic_image *image;
56d722e3fbSopenharmony_ci    int err;
57d722e3fbSopenharmony_ci
58d722e3fbSopenharmony_ci    if (!info)
59d722e3fbSopenharmony_ci        return -EINVAL;
60d722e3fbSopenharmony_ci
61d722e3fbSopenharmony_ci    image = calloc(1, sizeof(*image));
62d722e3fbSopenharmony_ci    if (!image)
63d722e3fbSopenharmony_ci        return -ENOMEM;
64d722e3fbSopenharmony_ci
65d722e3fbSopenharmony_ci    if (kind == VIC_BLK_KIND_PITCH)
66d722e3fbSopenharmony_ci        image->align = 256;
67d722e3fbSopenharmony_ci    else
68d722e3fbSopenharmony_ci        image->align = 256; /* XXX */
69d722e3fbSopenharmony_ci
70d722e3fbSopenharmony_ci    image->width = width;
71d722e3fbSopenharmony_ci    image->stride = ALIGN(width, image->align);
72d722e3fbSopenharmony_ci    image->pitch = image->stride * info->cpp;
73d722e3fbSopenharmony_ci    image->height = height;
74d722e3fbSopenharmony_ci    image->format = format;
75d722e3fbSopenharmony_ci    image->kind = kind;
76d722e3fbSopenharmony_ci
77d722e3fbSopenharmony_ci    image->size = image->pitch * image->height;
78d722e3fbSopenharmony_ci
79d722e3fbSopenharmony_ci    printf("image: %ux%u align: %zu stride: %u pitch: %u size: %zu\n",
80d722e3fbSopenharmony_ci           image->width, image->height, image->align, image->stride,
81d722e3fbSopenharmony_ci           image->pitch, image->size);
82d722e3fbSopenharmony_ci
83d722e3fbSopenharmony_ci    err = drm_tegra_bo_new(vic->drm, 0, image->size, &image->bo);
84d722e3fbSopenharmony_ci    if (err < 0) {
85d722e3fbSopenharmony_ci        free(image);
86d722e3fbSopenharmony_ci        return err;
87d722e3fbSopenharmony_ci    }
88d722e3fbSopenharmony_ci
89d722e3fbSopenharmony_ci    err = drm_tegra_channel_map(vic->channel, image->bo, flags, &image->map);
90d722e3fbSopenharmony_ci    if (err < 0) {
91d722e3fbSopenharmony_ci        drm_tegra_bo_unref(image->bo);
92d722e3fbSopenharmony_ci        free(image);
93d722e3fbSopenharmony_ci        return err;
94d722e3fbSopenharmony_ci    }
95d722e3fbSopenharmony_ci
96d722e3fbSopenharmony_ci    *imagep = image;
97d722e3fbSopenharmony_ci    return 0;
98d722e3fbSopenharmony_ci}
99d722e3fbSopenharmony_ci
100d722e3fbSopenharmony_civoid vic_image_free(struct vic_image *image)
101d722e3fbSopenharmony_ci{
102d722e3fbSopenharmony_ci    if (image) {
103d722e3fbSopenharmony_ci        drm_tegra_channel_unmap(image->map);
104d722e3fbSopenharmony_ci        drm_tegra_bo_unref(image->bo);
105d722e3fbSopenharmony_ci        free(image);
106d722e3fbSopenharmony_ci    }
107d722e3fbSopenharmony_ci}
108d722e3fbSopenharmony_ci
109d722e3fbSopenharmony_civoid vic_image_dump(struct vic_image *image, FILE *fp)
110d722e3fbSopenharmony_ci{
111d722e3fbSopenharmony_ci    unsigned int i, j;
112d722e3fbSopenharmony_ci    void *ptr;
113d722e3fbSopenharmony_ci    int err;
114d722e3fbSopenharmony_ci
115d722e3fbSopenharmony_ci    err = drm_tegra_bo_map(image->bo, &ptr);
116d722e3fbSopenharmony_ci    if (err < 0)
117d722e3fbSopenharmony_ci        return;
118d722e3fbSopenharmony_ci
119d722e3fbSopenharmony_ci    for (j = 0; j < image->height; j++) {
120d722e3fbSopenharmony_ci        uint32_t *pixels = (uint32_t *)((unsigned long)ptr + j * image->pitch);
121d722e3fbSopenharmony_ci
122d722e3fbSopenharmony_ci        printf("   ");
123d722e3fbSopenharmony_ci
124d722e3fbSopenharmony_ci        for (i = 0; i < image->width; i++)
125d722e3fbSopenharmony_ci            printf(" %08x", pixels[i]);
126d722e3fbSopenharmony_ci
127d722e3fbSopenharmony_ci        printf("\n");
128d722e3fbSopenharmony_ci    }
129d722e3fbSopenharmony_ci
130d722e3fbSopenharmony_ci    drm_tegra_bo_unmap(image->bo);
131d722e3fbSopenharmony_ci}
132d722e3fbSopenharmony_ci
133d722e3fbSopenharmony_ci/* from vic30.c */
134d722e3fbSopenharmony_ciint vic30_new(struct drm_tegra *drm, struct drm_tegra_channel *channel,
135d722e3fbSopenharmony_ci              struct vic **vicp);
136d722e3fbSopenharmony_ci
137d722e3fbSopenharmony_ci/* from vic40.c */
138d722e3fbSopenharmony_ciint vic40_new(struct drm_tegra *drm, struct drm_tegra_channel *channel,
139d722e3fbSopenharmony_ci              struct vic **vicp);
140d722e3fbSopenharmony_ci
141d722e3fbSopenharmony_ci/* from vic41.c */
142d722e3fbSopenharmony_ciint vic41_new(struct drm_tegra *drm, struct drm_tegra_channel *channel,
143d722e3fbSopenharmony_ci              struct vic **vicp);
144d722e3fbSopenharmony_ci
145d722e3fbSopenharmony_ci/* from vic42.c */
146d722e3fbSopenharmony_ciint vic42_new(struct drm_tegra *drm, struct drm_tegra_channel *channel,
147d722e3fbSopenharmony_ci              struct vic **vicp);
148d722e3fbSopenharmony_ci
149d722e3fbSopenharmony_ciint vic_new(struct drm_tegra *drm, struct drm_tegra_channel *channel,
150d722e3fbSopenharmony_ci            struct vic **vicp)
151d722e3fbSopenharmony_ci{
152d722e3fbSopenharmony_ci    unsigned int version;
153d722e3fbSopenharmony_ci
154d722e3fbSopenharmony_ci    version = drm_tegra_channel_get_version(channel);
155d722e3fbSopenharmony_ci
156d722e3fbSopenharmony_ci    switch (version) {
157d722e3fbSopenharmony_ci    case 0x40:
158d722e3fbSopenharmony_ci        return vic30_new(drm, channel, vicp);
159d722e3fbSopenharmony_ci
160d722e3fbSopenharmony_ci    case 0x21:
161d722e3fbSopenharmony_ci        return vic40_new(drm, channel, vicp);
162d722e3fbSopenharmony_ci
163d722e3fbSopenharmony_ci    case 0x18:
164d722e3fbSopenharmony_ci        return vic41_new(drm, channel, vicp);
165d722e3fbSopenharmony_ci
166d722e3fbSopenharmony_ci    case 0x19:
167d722e3fbSopenharmony_ci        return vic42_new(drm, channel, vicp);
168d722e3fbSopenharmony_ci    }
169d722e3fbSopenharmony_ci
170d722e3fbSopenharmony_ci    return -ENOTSUP;
171d722e3fbSopenharmony_ci}
172d722e3fbSopenharmony_ci
173d722e3fbSopenharmony_civoid vic_free(struct vic *vic)
174d722e3fbSopenharmony_ci{
175d722e3fbSopenharmony_ci    if (vic)
176d722e3fbSopenharmony_ci        vic->ops->free(vic);
177d722e3fbSopenharmony_ci}
178d722e3fbSopenharmony_ci
179d722e3fbSopenharmony_ciint vic_clear(struct vic *vic, struct vic_image *output, unsigned int alpha,
180d722e3fbSopenharmony_ci              unsigned int red, unsigned int green, unsigned int blue)
181d722e3fbSopenharmony_ci{
182d722e3fbSopenharmony_ci    return vic->ops->fill(vic, output, 0, 0, output->width - 1,
183d722e3fbSopenharmony_ci                          output->height - 1, alpha, red, green, blue);
184d722e3fbSopenharmony_ci}
185