1848b8605Smrg/**************************************************************************
2848b8605Smrg *
3848b8605Smrg * Copyright 2011 Advanced Micro Devices, Inc.
4848b8605Smrg * All Rights Reserved.
5848b8605Smrg *
6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
7848b8605Smrg * copy of this software and associated documentation files (the
8848b8605Smrg * "Software"), to deal in the Software without restriction, including
9848b8605Smrg * without limitation the rights to use, copy, modify, merge, publish,
10848b8605Smrg * distribute, sub license, and/or sell copies of the Software, and to
11848b8605Smrg * permit persons to whom the Software is furnished to do so, subject to
12848b8605Smrg * the following conditions:
13848b8605Smrg *
14848b8605Smrg * The above copyright notice and this permission notice (including the
15848b8605Smrg * next paragraph) shall be included in all copies or substantial portions
16848b8605Smrg * of the Software.
17848b8605Smrg *
18848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20848b8605Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21848b8605Smrg * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
22848b8605Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23848b8605Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24848b8605Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25848b8605Smrg *
26848b8605Smrg **************************************************************************/
27848b8605Smrg
28848b8605Smrg/*
29848b8605Smrg * Authors:
30848b8605Smrg *      Christian König <christian.koenig@amd.com>
31848b8605Smrg *
32848b8605Smrg */
33848b8605Smrg
34848b8605Smrg#include <sys/types.h>
35848b8605Smrg#include <assert.h>
36848b8605Smrg#include <errno.h>
37848b8605Smrg#include <unistd.h>
38848b8605Smrg
39848b8605Smrg#include "pipe/p_video_codec.h"
40848b8605Smrg
41848b8605Smrg#include "util/u_memory.h"
42848b8605Smrg#include "util/u_video.h"
43848b8605Smrg
44848b8605Smrg#include "vl/vl_defines.h"
45848b8605Smrg#include "vl/vl_mpeg12_decoder.h"
46848b8605Smrg
47848b8605Smrg#include "r600_pipe.h"
48b8e80941Smrg#include "radeon_video.h"
49b8e80941Smrg#include "radeon_uvd.h"
50b8e80941Smrg#include "radeon_vce.h"
51848b8605Smrg#include "r600d.h"
52848b8605Smrg
53b8e80941Smrg#define R600_UVD_ENABLE_TILING 0
54b8e80941Smrg
55848b8605Smrg/**
56848b8605Smrg * creates an video buffer with an UVD compatible memory layout
57848b8605Smrg */
58848b8605Smrgstruct pipe_video_buffer *r600_video_buffer_create(struct pipe_context *pipe,
59848b8605Smrg						   const struct pipe_video_buffer *tmpl)
60848b8605Smrg{
61848b8605Smrg	struct r600_context *ctx = (struct r600_context *)pipe;
62848b8605Smrg	struct r600_texture *resources[VL_NUM_COMPONENTS] = {};
63b8e80941Smrg	struct radeon_surf* surfaces[VL_NUM_COMPONENTS] = {};
64848b8605Smrg	struct pb_buffer **pbs[VL_NUM_COMPONENTS] = {};
65848b8605Smrg	const enum pipe_format *resource_formats;
66848b8605Smrg	struct pipe_video_buffer template;
67848b8605Smrg	struct pipe_resource templ;
68848b8605Smrg	unsigned i, array_size;
69848b8605Smrg
70848b8605Smrg	assert(pipe);
71848b8605Smrg
72848b8605Smrg	/* first create the needed resources as "normal" textures */
73848b8605Smrg	resource_formats = vl_video_buffer_formats(pipe->screen, tmpl->buffer_format);
74848b8605Smrg	if (!resource_formats)
75848b8605Smrg		return NULL;
76848b8605Smrg
77848b8605Smrg	array_size = tmpl->interlaced ? 2 : 1;
78848b8605Smrg	template = *tmpl;
79848b8605Smrg	template.width = align(tmpl->width, VL_MACROBLOCK_WIDTH);
80848b8605Smrg	template.height = align(tmpl->height / array_size, VL_MACROBLOCK_HEIGHT);
81848b8605Smrg
82848b8605Smrg	vl_video_buffer_template(&templ, &template, resource_formats[0], 1, array_size, PIPE_USAGE_DEFAULT, 0);
83b8e80941Smrg	if (ctx->b.chip_class < EVERGREEN || tmpl->interlaced || !R600_UVD_ENABLE_TILING)
84848b8605Smrg		templ.bind = PIPE_BIND_LINEAR;
85848b8605Smrg	resources[0] = (struct r600_texture *)
86848b8605Smrg		pipe->screen->resource_create(pipe->screen, &templ);
87848b8605Smrg	if (!resources[0])
88848b8605Smrg		goto error;
89848b8605Smrg
90848b8605Smrg	if (resource_formats[1] != PIPE_FORMAT_NONE) {
91848b8605Smrg		vl_video_buffer_template(&templ, &template, resource_formats[1], 1, array_size, PIPE_USAGE_DEFAULT, 1);
92b8e80941Smrg		if (ctx->b.chip_class < EVERGREEN || tmpl->interlaced || !R600_UVD_ENABLE_TILING)
93848b8605Smrg			templ.bind = PIPE_BIND_LINEAR;
94848b8605Smrg		resources[1] = (struct r600_texture *)
95848b8605Smrg			pipe->screen->resource_create(pipe->screen, &templ);
96848b8605Smrg		if (!resources[1])
97848b8605Smrg			goto error;
98848b8605Smrg	}
99848b8605Smrg
100848b8605Smrg	if (resource_formats[2] != PIPE_FORMAT_NONE) {
101848b8605Smrg		vl_video_buffer_template(&templ, &template, resource_formats[2], 1, array_size, PIPE_USAGE_DEFAULT, 2);
102b8e80941Smrg		if (ctx->b.chip_class < EVERGREEN || tmpl->interlaced || !R600_UVD_ENABLE_TILING)
103848b8605Smrg			templ.bind = PIPE_BIND_LINEAR;
104848b8605Smrg		resources[2] = (struct r600_texture *)
105848b8605Smrg			pipe->screen->resource_create(pipe->screen, &templ);
106848b8605Smrg		if (!resources[2])
107848b8605Smrg			goto error;
108848b8605Smrg	}
109848b8605Smrg
110848b8605Smrg	for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
111848b8605Smrg		if (!resources[i])
112848b8605Smrg			continue;
113848b8605Smrg
114848b8605Smrg		pbs[i] = &resources[i]->resource.buf;
115848b8605Smrg		surfaces[i] = &resources[i]->surface;
116848b8605Smrg	}
117848b8605Smrg
118b8e80941Smrg	rvid_join_surfaces(&ctx->b, pbs, surfaces);
119848b8605Smrg
120848b8605Smrg	for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
121848b8605Smrg		if (!resources[i])
122848b8605Smrg			continue;
123848b8605Smrg
124b8e80941Smrg		/* reset the address */
125848b8605Smrg		resources[i]->resource.gpu_address = ctx->b.ws->buffer_get_virtual_address(
126b8e80941Smrg			resources[i]->resource.buf);
127848b8605Smrg	}
128848b8605Smrg
129848b8605Smrg	template.height *= array_size;
130848b8605Smrg	return vl_video_buffer_create_ex2(pipe, &template, (struct pipe_resource **)resources);
131848b8605Smrg
132848b8605Smrgerror:
133848b8605Smrg	for (i = 0; i < VL_NUM_COMPONENTS; ++i)
134b8e80941Smrg		r600_texture_reference(&resources[i], NULL);
135848b8605Smrg
136848b8605Smrg	return NULL;
137848b8605Smrg}
138848b8605Smrg
139848b8605Smrg/* hw encode the number of memory banks */
140848b8605Smrgstatic uint32_t eg_num_banks(uint32_t nbanks)
141848b8605Smrg{
142848b8605Smrg	switch (nbanks) {
143848b8605Smrg	case 2:
144848b8605Smrg		return 0;
145848b8605Smrg	case 4:
146848b8605Smrg		return 1;
147848b8605Smrg	case 8:
148848b8605Smrg	default:
149848b8605Smrg		return 2;
150848b8605Smrg	case 16:
151848b8605Smrg		return 3;
152848b8605Smrg	}
153848b8605Smrg}
154848b8605Smrg
155848b8605Smrg/* set the decoding target buffer offsets */
156b8e80941Smrgstatic struct pb_buffer* r600_uvd_set_dtb(struct ruvd_msg *msg, struct vl_video_buffer *buf)
157848b8605Smrg{
158848b8605Smrg	struct r600_screen *rscreen = (struct r600_screen*)buf->base.context->screen;
159848b8605Smrg	struct r600_texture *luma = (struct r600_texture *)buf->resources[0];
160848b8605Smrg	struct r600_texture *chroma = (struct r600_texture *)buf->resources[1];
161848b8605Smrg
162848b8605Smrg	msg->body.decode.dt_field_mode = buf->base.interlaced;
163b8e80941Smrg	msg->body.decode.dt_surf_tile_config |= RUVD_NUM_BANKS(eg_num_banks(rscreen->b.info.r600_num_banks));
164848b8605Smrg
165848b8605Smrg	ruvd_set_dt_surfaces(msg, &luma->surface, &chroma->surface);
166848b8605Smrg
167b8e80941Smrg	return luma->resource.buf;
168b8e80941Smrg}
169b8e80941Smrg
170b8e80941Smrg/* get the radeon resources for VCE */
171b8e80941Smrgstatic void r600_vce_get_buffer(struct pipe_resource *resource,
172b8e80941Smrg				struct pb_buffer **handle,
173b8e80941Smrg				struct radeon_surf **surface)
174b8e80941Smrg{
175b8e80941Smrg	struct r600_texture *res = (struct r600_texture *)resource;
176b8e80941Smrg
177b8e80941Smrg	if (handle)
178b8e80941Smrg		*handle = res->resource.buf;
179b8e80941Smrg
180b8e80941Smrg	if (surface)
181b8e80941Smrg		*surface = &res->surface;
182848b8605Smrg}
183848b8605Smrg
184848b8605Smrg/* create decoder */
185848b8605Smrgstruct pipe_video_codec *r600_uvd_create_decoder(struct pipe_context *context,
186b8e80941Smrg						 const struct pipe_video_codec *templat)
187848b8605Smrg{
188b8e80941Smrg	struct r600_context *ctx = (struct r600_context *)context;
189b8e80941Smrg
190b8e80941Smrg        if (templat->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE)
191b8e80941Smrg                return rvce_create_encoder(context, templat, ctx->b.ws, r600_vce_get_buffer);
192b8e80941Smrg
193848b8605Smrg	return ruvd_create_decoder(context, templat, r600_uvd_set_dtb);
194848b8605Smrg}
195