powerpc/mm: Pass node id into create_section_mapping
[linux-2.6-microblaze.git] / drivers / gpu / drm / amd / display / dc / core / dc_stream.c
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"
30 #include "ipp.h"
31 #include "timing_generator.h"
32
33 /*******************************************************************************
34  * Private functions
35  ******************************************************************************/
36 #define TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST 297000
37 static void update_stream_signal(struct dc_stream_state *stream)
38 {
39
40         struct dc_sink *dc_sink = stream->sink;
41
42         if (dc_sink->sink_signal == SIGNAL_TYPE_NONE)
43                 stream->signal = stream->sink->link->connector_signal;
44         else
45                 stream->signal = dc_sink->sink_signal;
46
47         if (dc_is_dvi_signal(stream->signal)) {
48                 if (stream->timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST &&
49                         stream->sink->sink_signal != SIGNAL_TYPE_DVI_SINGLE_LINK)
50                         stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK;
51                 else
52                         stream->signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
53         }
54 }
55
56 static void construct(struct dc_stream_state *stream,
57         struct dc_sink *dc_sink_data)
58 {
59         uint32_t i = 0;
60
61         stream->sink = dc_sink_data;
62         stream->ctx = stream->sink->ctx;
63
64         dc_sink_retain(dc_sink_data);
65
66         /* Copy audio modes */
67         /* TODO - Remove this translation */
68         for (i = 0; i < (dc_sink_data->edid_caps.audio_mode_count); i++)
69         {
70                 stream->audio_info.modes[i].channel_count = dc_sink_data->edid_caps.audio_modes[i].channel_count;
71                 stream->audio_info.modes[i].format_code = dc_sink_data->edid_caps.audio_modes[i].format_code;
72                 stream->audio_info.modes[i].sample_rates.all = dc_sink_data->edid_caps.audio_modes[i].sample_rate;
73                 stream->audio_info.modes[i].sample_size = dc_sink_data->edid_caps.audio_modes[i].sample_size;
74         }
75         stream->audio_info.mode_count = dc_sink_data->edid_caps.audio_mode_count;
76         stream->audio_info.audio_latency = dc_sink_data->edid_caps.audio_latency;
77         stream->audio_info.video_latency = dc_sink_data->edid_caps.video_latency;
78         memmove(
79                 stream->audio_info.display_name,
80                 dc_sink_data->edid_caps.display_name,
81                 AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS);
82         stream->audio_info.manufacture_id = dc_sink_data->edid_caps.manufacturer_id;
83         stream->audio_info.product_id = dc_sink_data->edid_caps.product_id;
84         stream->audio_info.flags.all = dc_sink_data->edid_caps.speaker_flags;
85
86         if (dc_sink_data->dc_container_id != NULL) {
87                 struct dc_container_id *dc_container_id = dc_sink_data->dc_container_id;
88
89                 stream->audio_info.port_id[0] = dc_container_id->portId[0];
90                 stream->audio_info.port_id[1] = dc_container_id->portId[1];
91         } else {
92                 /* TODO - WindowDM has implemented,
93                 other DMs need Unhardcode port_id */
94                 stream->audio_info.port_id[0] = 0x5558859e;
95                 stream->audio_info.port_id[1] = 0xd989449;
96         }
97
98         /* EDID CAP translation for HDMI 2.0 */
99         stream->timing.flags.LTE_340MCSC_SCRAMBLE = dc_sink_data->edid_caps.lte_340mcsc_scramble;
100
101         stream->status.link = stream->sink->link;
102
103         update_stream_signal(stream);
104 }
105
106 static void destruct(struct dc_stream_state *stream)
107 {
108         dc_sink_release(stream->sink);
109         if (stream->out_transfer_func != NULL) {
110                 dc_transfer_func_release(
111                                 stream->out_transfer_func);
112                 stream->out_transfer_func = NULL;
113         }
114 }
115
116 void dc_stream_retain(struct dc_stream_state *stream)
117 {
118         kref_get(&stream->refcount);
119 }
120
121 static void dc_stream_free(struct kref *kref)
122 {
123         struct dc_stream_state *stream = container_of(kref, struct dc_stream_state, refcount);
124
125         destruct(stream);
126         kfree(stream);
127 }
128
129 void dc_stream_release(struct dc_stream_state *stream)
130 {
131         if (stream != NULL) {
132                 kref_put(&stream->refcount, dc_stream_free);
133         }
134 }
135
136 struct dc_stream_state *dc_create_stream_for_sink(
137                 struct dc_sink *sink)
138 {
139         struct dc_stream_state *stream;
140
141         if (sink == NULL)
142                 return NULL;
143
144         stream = kzalloc(sizeof(struct dc_stream_state), GFP_KERNEL);
145         if (stream == NULL)
146                 return NULL;
147
148         construct(stream, sink);
149
150         kref_init(&stream->refcount);
151
152         return stream;
153 }
154
155 struct dc_stream_status *dc_stream_get_status(
156         struct dc_stream_state *stream)
157 {
158         uint8_t i;
159         struct dc  *dc = stream->ctx->dc;
160
161         for (i = 0; i < dc->current_state->stream_count; i++) {
162                 if (stream == dc->current_state->streams[i])
163                         return &dc->current_state->stream_status[i];
164         }
165
166         return NULL;
167 }
168
169 /**
170  * Update the cursor attributes and set cursor surface address
171  */
172 bool dc_stream_set_cursor_attributes(
173         struct dc_stream_state *stream,
174         const struct dc_cursor_attributes *attributes)
175 {
176         int i;
177         struct dc  *core_dc;
178         struct resource_context *res_ctx;
179
180         if (NULL == stream) {
181                 dm_error("DC: dc_stream is NULL!\n");
182                 return false;
183         }
184         if (NULL == attributes) {
185                 dm_error("DC: attributes is NULL!\n");
186                 return false;
187         }
188
189         if (attributes->address.quad_part == 0) {
190                 dm_output_to_console("DC: Cursor address is 0!\n");
191                 return false;
192         }
193
194         core_dc = stream->ctx->dc;
195         res_ctx = &core_dc->current_state->res_ctx;
196
197         for (i = 0; i < MAX_PIPES; i++) {
198                 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
199
200                 if (pipe_ctx->stream != stream || (!pipe_ctx->plane_res.xfm && !pipe_ctx->plane_res.dpp))
201                         continue;
202                 if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state)
203                         continue;
204
205
206                 if (pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes != NULL)
207                         pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes(
208                                                 pipe_ctx->plane_res.ipp, attributes);
209
210                 if (pipe_ctx->plane_res.hubp != NULL &&
211                                 pipe_ctx->plane_res.hubp->funcs->set_cursor_attributes != NULL)
212                         pipe_ctx->plane_res.hubp->funcs->set_cursor_attributes(
213                                         pipe_ctx->plane_res.hubp, attributes);
214
215                 if (pipe_ctx->plane_res.mi != NULL &&
216                                 pipe_ctx->plane_res.mi->funcs->set_cursor_attributes != NULL)
217                         pipe_ctx->plane_res.mi->funcs->set_cursor_attributes(
218                                         pipe_ctx->plane_res.mi, attributes);
219
220
221                 if (pipe_ctx->plane_res.xfm != NULL &&
222                                 pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes != NULL)
223                         pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes(
224                                 pipe_ctx->plane_res.xfm, attributes);
225
226                 if (pipe_ctx->plane_res.dpp != NULL &&
227                                 pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes != NULL)
228                         pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes(
229                                 pipe_ctx->plane_res.dpp, attributes->color_format);
230         }
231
232         stream->cursor_attributes = *attributes;
233
234         return true;
235 }
236
237 bool dc_stream_set_cursor_position(
238         struct dc_stream_state *stream,
239         const struct dc_cursor_position *position)
240 {
241         int i;
242         struct dc  *core_dc;
243         struct resource_context *res_ctx;
244
245         if (NULL == stream) {
246                 dm_error("DC: dc_stream is NULL!\n");
247                 return false;
248         }
249
250         if (NULL == position) {
251                 dm_error("DC: cursor position is NULL!\n");
252                 return false;
253         }
254
255         core_dc = stream->ctx->dc;
256         res_ctx = &core_dc->current_state->res_ctx;
257
258         for (i = 0; i < MAX_PIPES; i++) {
259                 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
260                 struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp;
261                 struct mem_input *mi = pipe_ctx->plane_res.mi;
262                 struct hubp *hubp = pipe_ctx->plane_res.hubp;
263                 struct dpp *dpp = pipe_ctx->plane_res.dpp;
264                 struct dc_cursor_position pos_cpy = *position;
265                 struct dc_cursor_mi_param param = {
266                         .pixel_clk_khz = stream->timing.pix_clk_khz,
267                         .ref_clk_khz = core_dc->res_pool->ref_clock_inKhz,
268                         .viewport_x_start = pipe_ctx->plane_res.scl_data.viewport.x,
269                         .viewport_width = pipe_ctx->plane_res.scl_data.viewport.width,
270                         .h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz
271                 };
272
273                 if (pipe_ctx->stream != stream ||
274                                 (!pipe_ctx->plane_res.mi  && !pipe_ctx->plane_res.hubp) ||
275                                 !pipe_ctx->plane_state ||
276                                 (!pipe_ctx->plane_res.xfm && !pipe_ctx->plane_res.dpp))
277                         continue;
278
279                 if (pipe_ctx->plane_state->address.type
280                                 == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE)
281                         pos_cpy.enable = false;
282
283                 if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state)
284                         pos_cpy.enable = false;
285
286
287                 if (ipp != NULL && ipp->funcs->ipp_cursor_set_position != NULL)
288                         ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, &param);
289
290                 if (mi != NULL && mi->funcs->set_cursor_position != NULL)
291                         mi->funcs->set_cursor_position(mi, &pos_cpy, &param);
292
293                 if (!hubp)
294                         continue;
295
296                 if (hubp->funcs->set_cursor_position != NULL)
297                         hubp->funcs->set_cursor_position(hubp, &pos_cpy, &param);
298
299                 if (dpp != NULL && dpp->funcs->set_cursor_position != NULL)
300                         dpp->funcs->set_cursor_position(dpp, &pos_cpy, &param, hubp->curs_attr.width);
301
302         }
303
304         stream->cursor_position = *position;
305
306         return true;
307 }
308
309 uint32_t dc_stream_get_vblank_counter(const struct dc_stream_state *stream)
310 {
311         uint8_t i;
312         struct dc  *core_dc = stream->ctx->dc;
313         struct resource_context *res_ctx =
314                 &core_dc->current_state->res_ctx;
315
316         for (i = 0; i < MAX_PIPES; i++) {
317                 struct timing_generator *tg = res_ctx->pipe_ctx[i].stream_res.tg;
318
319                 if (res_ctx->pipe_ctx[i].stream != stream)
320                         continue;
321
322                 return tg->funcs->get_frame_count(tg);
323         }
324
325         return 0;
326 }
327
328 bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream,
329                                   uint32_t *v_blank_start,
330                                   uint32_t *v_blank_end,
331                                   uint32_t *h_position,
332                                   uint32_t *v_position)
333 {
334         uint8_t i;
335         bool ret = false;
336         struct dc  *core_dc = stream->ctx->dc;
337         struct resource_context *res_ctx =
338                 &core_dc->current_state->res_ctx;
339
340         for (i = 0; i < MAX_PIPES; i++) {
341                 struct timing_generator *tg = res_ctx->pipe_ctx[i].stream_res.tg;
342
343                 if (res_ctx->pipe_ctx[i].stream != stream)
344                         continue;
345
346                 tg->funcs->get_scanoutpos(tg,
347                                           v_blank_start,
348                                           v_blank_end,
349                                           h_position,
350                                           v_position);
351
352                 ret = true;
353                 break;
354         }
355
356         return ret;
357 }
358
359
360 void dc_stream_log(
361         const struct dc_stream_state *stream,
362         struct dal_logger *dm_logger,
363         enum dc_log_type log_type)
364 {
365
366         dm_logger_write(dm_logger,
367                         log_type,
368                         "core_stream 0x%x: src: %d, %d, %d, %d; dst: %d, %d, %d, %d, colorSpace:%d\n",
369                         stream,
370                         stream->src.x,
371                         stream->src.y,
372                         stream->src.width,
373                         stream->src.height,
374                         stream->dst.x,
375                         stream->dst.y,
376                         stream->dst.width,
377                         stream->dst.height,
378                         stream->output_color_space);
379         dm_logger_write(dm_logger,
380                         log_type,
381                         "\tpix_clk_khz: %d, h_total: %d, v_total: %d, pixelencoder:%d, displaycolorDepth:%d\n",
382                         stream->timing.pix_clk_khz,
383                         stream->timing.h_total,
384                         stream->timing.v_total,
385                         stream->timing.pixel_encoding,
386                         stream->timing.display_color_depth);
387         dm_logger_write(dm_logger,
388                         log_type,
389                         "\tsink name: %s, serial: %d\n",
390                         stream->sink->edid_caps.display_name,
391                         stream->sink->edid_caps.serial_number);
392         dm_logger_write(dm_logger,
393                         log_type,
394                         "\tlink: %d\n",
395                         stream->sink->link->link_index);
396 }