]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/gpu/drm/amd/display/dc/core/dc_stream.c
drm/amd/display: Rename dc_stream to dc_stream_state
[mirror_ubuntu-bionic-kernel.git] / drivers / gpu / drm / amd / display / dc / core / dc_stream.c
CommitLineData
4562236b
HW
1/*
2 * Copyright 2012-15 Advanced Micro Devices, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: AMD
23 *
24 */
25
26#include "dm_services.h"
27#include "dc.h"
28#include "core_types.h"
29#include "resource.h"
ab2541b6
AC
30#include "ipp.h"
31#include "timing_generator.h"
4562236b 32
4562236b
HW
33/*******************************************************************************
34 * Private functions
35 ******************************************************************************/
36
0971c40e 37static bool construct(struct dc_stream_state *stream,
b73a22d3 38 struct dc_sink *dc_sink_data)
4562236b
HW
39{
40 uint32_t i = 0;
41
b73a22d3 42 stream->sink = dc_sink_data;
4562236b 43 stream->ctx = stream->sink->ctx;
4fa086b9 44 stream->sink = dc_sink_data;
4562236b
HW
45
46 dc_sink_retain(dc_sink_data);
47
48 /* Copy audio modes */
49 /* TODO - Remove this translation */
50 for (i = 0; i < (dc_sink_data->edid_caps.audio_mode_count); i++)
51 {
4fa086b9
LSL
52 stream->audio_info.modes[i].channel_count = dc_sink_data->edid_caps.audio_modes[i].channel_count;
53 stream->audio_info.modes[i].format_code = dc_sink_data->edid_caps.audio_modes[i].format_code;
54 stream->audio_info.modes[i].sample_rates.all = dc_sink_data->edid_caps.audio_modes[i].sample_rate;
55 stream->audio_info.modes[i].sample_size = dc_sink_data->edid_caps.audio_modes[i].sample_size;
4562236b 56 }
4fa086b9
LSL
57 stream->audio_info.mode_count = dc_sink_data->edid_caps.audio_mode_count;
58 stream->audio_info.audio_latency = dc_sink_data->edid_caps.audio_latency;
59 stream->audio_info.video_latency = dc_sink_data->edid_caps.video_latency;
4562236b 60 memmove(
4fa086b9 61 stream->audio_info.display_name,
4562236b
HW
62 dc_sink_data->edid_caps.display_name,
63 AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS);
4fa086b9
LSL
64 stream->audio_info.manufacture_id = dc_sink_data->edid_caps.manufacturer_id;
65 stream->audio_info.product_id = dc_sink_data->edid_caps.product_id;
66 stream->audio_info.flags.all = dc_sink_data->edid_caps.speaker_flags;
4562236b 67
8c895313 68 if (dc_sink_data->dc_container_id != NULL) {
69 struct dc_container_id *dc_container_id = dc_sink_data->dc_container_id;
70
4fa086b9
LSL
71 stream->audio_info.port_id[0] = dc_container_id->portId[0];
72 stream->audio_info.port_id[1] = dc_container_id->portId[1];
8c895313 73 } else {
74 /* TODO - WindowDM has implemented,
75 other DMs need Unhardcode port_id */
4fa086b9
LSL
76 stream->audio_info.port_id[0] = 0x5558859e;
77 stream->audio_info.port_id[1] = 0xd989449;
8c895313 78 }
4562236b
HW
79
80 /* EDID CAP translation for HDMI 2.0 */
4fa086b9 81 stream->timing.flags.LTE_340MCSC_SCRAMBLE = dc_sink_data->edid_caps.lte_340mcsc_scramble;
4562236b 82
d0778ebf 83 stream->status.link = stream->sink->link;
4562236b
HW
84 return true;
85}
86
0971c40e 87static void destruct(struct dc_stream_state *stream)
4562236b 88{
b73a22d3 89 dc_sink_release(stream->sink);
4fa086b9 90 if (stream->out_transfer_func != NULL) {
90e508ba 91 dc_transfer_func_release(
4fa086b9
LSL
92 stream->out_transfer_func);
93 stream->out_transfer_func = NULL;
80bd2096 94 }
4562236b
HW
95}
96
0971c40e 97void dc_stream_retain(struct dc_stream_state *stream)
4562236b 98{
db96c69e
AG
99
100 ASSERT(stream->ref_count > 0);
4562236b
HW
101 stream->ref_count++;
102}
103
0971c40e 104void dc_stream_release(struct dc_stream_state *stream)
4562236b 105{
4562236b 106
a989ab08 107 if (stream != NULL) {
db96c69e 108 ASSERT(stream->ref_count > 0);
4562236b
HW
109 stream->ref_count--;
110
111 if (stream->ref_count == 0) {
a989ab08 112 destruct(stream);
4562236b
HW
113 dm_free(stream);
114 }
115 }
116}
117
0971c40e 118struct dc_stream_state *dc_create_stream_for_sink(
b73a22d3 119 struct dc_sink *sink)
4562236b 120{
0971c40e 121 struct dc_stream_state *stream;
4562236b
HW
122
123 if (sink == NULL)
124 goto alloc_fail;
125
0971c40e 126 stream = dm_alloc(sizeof(struct dc_stream_state));
4562236b
HW
127
128 if (NULL == stream)
129 goto alloc_fail;
130
a989ab08 131 if (false == construct(stream, sink))
4562236b
HW
132 goto construct_fail;
133
db96c69e 134 stream->ref_count++;
4562236b 135
a989ab08 136 return stream;
4562236b
HW
137
138construct_fail:
139 dm_free(stream);
140
141alloc_fail:
142 return NULL;
143}
ab2541b6 144
e12cfcb1 145struct dc_stream_status *dc_stream_get_status(
0971c40e 146 struct dc_stream_state *stream)
ab2541b6
AC
147{
148 uint8_t i;
ab2541b6
AC
149 struct core_dc *dc = DC_TO_CORE(stream->ctx->dc);
150
e2c7bb12
HW
151 for (i = 0; i < dc->current_context->stream_count; i++) {
152 if (stream == dc->current_context->streams[i]) {
ab2541b6 153 return &dc->current_context->stream_status[i];
e2c7bb12
HW
154 }
155 }
ab2541b6
AC
156
157 return NULL;
158}
159
160/**
161 * Update the cursor attributes and set cursor surface address
162 */
163bool dc_stream_set_cursor_attributes(
0971c40e 164 const struct dc_stream_state *stream,
ab2541b6
AC
165 const struct dc_cursor_attributes *attributes)
166{
167 int i;
ab2541b6
AC
168 struct core_dc *core_dc;
169 struct resource_context *res_ctx;
ab2541b6 170
4fa086b9 171 if (NULL == stream) {
ab2541b6
AC
172 dm_error("DC: dc_stream is NULL!\n");
173 return false;
174 }
175 if (NULL == attributes) {
176 dm_error("DC: attributes is NULL!\n");
177 return false;
178 }
179
ab2541b6
AC
180 core_dc = DC_TO_CORE(stream->ctx->dc);
181 res_ctx = &core_dc->current_context->res_ctx;
182
183 for (i = 0; i < MAX_PIPES; i++) {
184 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
185
beb16b6a
DL
186 if (pipe_ctx->stream != stream || !pipe_ctx->ipp)
187 continue;
188 if (pipe_ctx->top_pipe && pipe_ctx->surface != pipe_ctx->top_pipe->surface)
189 continue;
ab2541b6 190
beb16b6a
DL
191 pipe_ctx->ipp->funcs->ipp_cursor_set_attributes(
192 pipe_ctx->ipp, attributes);
ab2541b6
AC
193 }
194
beb16b6a 195 return true;
ab2541b6
AC
196}
197
198bool dc_stream_set_cursor_position(
0971c40e 199 struct dc_stream_state *stream,
beb16b6a 200 const struct dc_cursor_position *position)
ab2541b6
AC
201{
202 int i;
ab2541b6
AC
203 struct core_dc *core_dc;
204 struct resource_context *res_ctx;
ab2541b6 205
4fa086b9 206 if (NULL == stream) {
ab2541b6
AC
207 dm_error("DC: dc_stream is NULL!\n");
208 return false;
209 }
210
211 if (NULL == position) {
212 dm_error("DC: cursor position is NULL!\n");
213 return false;
214 }
215
ab2541b6
AC
216 core_dc = DC_TO_CORE(stream->ctx->dc);
217 res_ctx = &core_dc->current_context->res_ctx;
218
219 for (i = 0; i < MAX_PIPES; i++) {
220 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
beb16b6a
DL
221 struct input_pixel_processor *ipp = pipe_ctx->ipp;
222 struct dc_cursor_position pos_cpy = *position;
223 struct dc_cursor_mi_param param = {
4fa086b9 224 .pixel_clk_khz = stream->timing.pix_clk_khz,
a2b8659d 225 .ref_clk_khz = core_dc->res_pool->ref_clock_inKhz,
beb16b6a
DL
226 .viewport_x_start = pipe_ctx->scl_data.viewport.x,
227 .viewport_width = pipe_ctx->scl_data.viewport.width,
228 .h_scale_ratio = pipe_ctx->scl_data.ratios.horz
229 };
230
231 if (pipe_ctx->stream != stream ||
232 !pipe_ctx->ipp || !pipe_ctx->surface)
233 continue;
ab2541b6 234
e12cfcb1 235 if (pipe_ctx->surface->address.type
cf4cde2b
YS
236 == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE)
237 pos_cpy.enable = false;
238
beb16b6a
DL
239 if (pipe_ctx->top_pipe && pipe_ctx->surface != pipe_ctx->top_pipe->surface)
240 pos_cpy.enable = false;
241
242 ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, &param);
ab2541b6
AC
243 }
244
beb16b6a 245 return true;
ab2541b6
AC
246}
247
0971c40e 248uint32_t dc_stream_get_vblank_counter(const struct dc_stream_state *stream)
ab2541b6
AC
249{
250 uint8_t i;
ab2541b6
AC
251 struct core_dc *core_dc = DC_TO_CORE(stream->ctx->dc);
252 struct resource_context *res_ctx =
253 &core_dc->current_context->res_ctx;
254
255 for (i = 0; i < MAX_PIPES; i++) {
256 struct timing_generator *tg = res_ctx->pipe_ctx[i].tg;
257
258 if (res_ctx->pipe_ctx[i].stream != stream)
259 continue;
260
261 return tg->funcs->get_frame_count(tg);
262 }
263
264 return 0;
265}
266
0971c40e 267bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream,
81c50963
ST
268 uint32_t *v_blank_start,
269 uint32_t *v_blank_end,
270 uint32_t *h_position,
271 uint32_t *v_position)
ab2541b6
AC
272{
273 uint8_t i;
81c50963 274 bool ret = false;
ab2541b6
AC
275 struct core_dc *core_dc = DC_TO_CORE(stream->ctx->dc);
276 struct resource_context *res_ctx =
277 &core_dc->current_context->res_ctx;
278
279 for (i = 0; i < MAX_PIPES; i++) {
280 struct timing_generator *tg = res_ctx->pipe_ctx[i].tg;
281
282 if (res_ctx->pipe_ctx[i].stream != stream)
283 continue;
284
81c50963
ST
285 tg->funcs->get_scanoutpos(tg,
286 v_blank_start,
287 v_blank_end,
288 h_position,
289 v_position);
290
291 ret = true;
292 break;
ab2541b6
AC
293 }
294
81c50963 295 return ret;
ab2541b6
AC
296}
297
298
299void dc_stream_log(
0971c40e 300 const struct dc_stream_state *stream,
ab2541b6
AC
301 struct dal_logger *dm_logger,
302 enum dc_log_type log_type)
303{
ab2541b6
AC
304
305 dm_logger_write(dm_logger,
306 log_type,
4b679bc3 307 "core_stream 0x%x: src: %d, %d, %d, %d; dst: %d, %d, %d, %d, colorSpace:%d\n",
4fa086b9
LSL
308 stream,
309 stream->src.x,
310 stream->src.y,
311 stream->src.width,
312 stream->src.height,
313 stream->dst.x,
314 stream->dst.y,
315 stream->dst.width,
316 stream->dst.height,
317 stream->output_color_space);
ab2541b6
AC
318 dm_logger_write(dm_logger,
319 log_type,
4b679bc3 320 "\tpix_clk_khz: %d, h_total: %d, v_total: %d, pixelencoder:%d, displaycolorDepth:%d\n",
4fa086b9
LSL
321 stream->timing.pix_clk_khz,
322 stream->timing.h_total,
323 stream->timing.v_total,
324 stream->timing.pixel_encoding,
325 stream->timing.display_color_depth);
ab2541b6
AC
326 dm_logger_write(dm_logger,
327 log_type,
328 "\tsink name: %s, serial: %d\n",
4fa086b9
LSL
329 stream->sink->edid_caps.display_name,
330 stream->sink->edid_caps.serial_number);
ab2541b6
AC
331 dm_logger_write(dm_logger,
332 log_type,
333 "\tlink: %d\n",
4fa086b9 334 stream->sink->link->link_index);
ab2541b6 335}