2 * Copyright 2012-15 Advanced Micro Devices, Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
26 #include "dm_services.h"
28 #include "core_types.h"
31 #include "timing_generator.h"
33 /*******************************************************************************
35 ******************************************************************************/
37 static bool construct(struct dc_stream_state
*stream
,
38 struct dc_sink
*dc_sink_data
)
42 stream
->sink
= dc_sink_data
;
43 stream
->ctx
= stream
->sink
->ctx
;
44 stream
->sink
= dc_sink_data
;
46 dc_sink_retain(dc_sink_data
);
48 /* Copy audio modes */
49 /* TODO - Remove this translation */
50 for (i
= 0; i
< (dc_sink_data
->edid_caps
.audio_mode_count
); i
++)
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
;
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
;
61 stream
->audio_info
.display_name
,
62 dc_sink_data
->edid_caps
.display_name
,
63 AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS
);
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
;
68 if (dc_sink_data
->dc_container_id
!= NULL
) {
69 struct dc_container_id
*dc_container_id
= dc_sink_data
->dc_container_id
;
71 stream
->audio_info
.port_id
[0] = dc_container_id
->portId
[0];
72 stream
->audio_info
.port_id
[1] = dc_container_id
->portId
[1];
74 /* TODO - WindowDM has implemented,
75 other DMs need Unhardcode port_id */
76 stream
->audio_info
.port_id
[0] = 0x5558859e;
77 stream
->audio_info
.port_id
[1] = 0xd989449;
80 /* EDID CAP translation for HDMI 2.0 */
81 stream
->timing
.flags
.LTE_340MCSC_SCRAMBLE
= dc_sink_data
->edid_caps
.lte_340mcsc_scramble
;
83 stream
->status
.link
= stream
->sink
->link
;
87 static void destruct(struct dc_stream_state
*stream
)
89 dc_sink_release(stream
->sink
);
90 if (stream
->out_transfer_func
!= NULL
) {
91 dc_transfer_func_release(
92 stream
->out_transfer_func
);
93 stream
->out_transfer_func
= NULL
;
97 void dc_stream_retain(struct dc_stream_state
*stream
)
100 ASSERT(stream
->ref_count
> 0);
104 void dc_stream_release(struct dc_stream_state
*stream
)
107 if (stream
!= NULL
) {
108 ASSERT(stream
->ref_count
> 0);
111 if (stream
->ref_count
== 0) {
118 struct dc_stream_state
*dc_create_stream_for_sink(
119 struct dc_sink
*sink
)
121 struct dc_stream_state
*stream
;
126 stream
= dm_alloc(sizeof(struct dc_stream_state
));
131 if (false == construct(stream
, sink
))
145 struct dc_stream_status
*dc_stream_get_status(
146 struct dc_stream_state
*stream
)
149 struct core_dc
*dc
= DC_TO_CORE(stream
->ctx
->dc
);
151 for (i
= 0; i
< dc
->current_context
->stream_count
; i
++) {
152 if (stream
== dc
->current_context
->streams
[i
]) {
153 return &dc
->current_context
->stream_status
[i
];
161 * Update the cursor attributes and set cursor surface address
163 bool dc_stream_set_cursor_attributes(
164 const struct dc_stream_state
*stream
,
165 const struct dc_cursor_attributes
*attributes
)
168 struct core_dc
*core_dc
;
169 struct resource_context
*res_ctx
;
171 if (NULL
== stream
) {
172 dm_error("DC: dc_stream is NULL!\n");
175 if (NULL
== attributes
) {
176 dm_error("DC: attributes is NULL!\n");
180 core_dc
= DC_TO_CORE(stream
->ctx
->dc
);
181 res_ctx
= &core_dc
->current_context
->res_ctx
;
183 for (i
= 0; i
< MAX_PIPES
; i
++) {
184 struct pipe_ctx
*pipe_ctx
= &res_ctx
->pipe_ctx
[i
];
186 if (pipe_ctx
->stream
!= stream
|| !pipe_ctx
->ipp
)
188 if (pipe_ctx
->top_pipe
&& pipe_ctx
->plane_state
!= pipe_ctx
->top_pipe
->plane_state
)
191 pipe_ctx
->ipp
->funcs
->ipp_cursor_set_attributes(
192 pipe_ctx
->ipp
, attributes
);
198 bool dc_stream_set_cursor_position(
199 struct dc_stream_state
*stream
,
200 const struct dc_cursor_position
*position
)
203 struct core_dc
*core_dc
;
204 struct resource_context
*res_ctx
;
206 if (NULL
== stream
) {
207 dm_error("DC: dc_stream is NULL!\n");
211 if (NULL
== position
) {
212 dm_error("DC: cursor position is NULL!\n");
216 core_dc
= DC_TO_CORE(stream
->ctx
->dc
);
217 res_ctx
= &core_dc
->current_context
->res_ctx
;
219 for (i
= 0; i
< MAX_PIPES
; i
++) {
220 struct pipe_ctx
*pipe_ctx
= &res_ctx
->pipe_ctx
[i
];
221 struct input_pixel_processor
*ipp
= pipe_ctx
->ipp
;
222 struct dc_cursor_position pos_cpy
= *position
;
223 struct dc_cursor_mi_param param
= {
224 .pixel_clk_khz
= stream
->timing
.pix_clk_khz
,
225 .ref_clk_khz
= core_dc
->res_pool
->ref_clock_inKhz
,
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
231 if (pipe_ctx
->stream
!= stream
||
232 !pipe_ctx
->ipp
|| !pipe_ctx
->plane_state
)
235 if (pipe_ctx
->plane_state
->address
.type
236 == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE
)
237 pos_cpy
.enable
= false;
239 if (pipe_ctx
->top_pipe
&& pipe_ctx
->plane_state
!= pipe_ctx
->top_pipe
->plane_state
)
240 pos_cpy
.enable
= false;
242 ipp
->funcs
->ipp_cursor_set_position(ipp
, &pos_cpy
, ¶m
);
248 uint32_t dc_stream_get_vblank_counter(const struct dc_stream_state
*stream
)
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
;
255 for (i
= 0; i
< MAX_PIPES
; i
++) {
256 struct timing_generator
*tg
= res_ctx
->pipe_ctx
[i
].tg
;
258 if (res_ctx
->pipe_ctx
[i
].stream
!= stream
)
261 return tg
->funcs
->get_frame_count(tg
);
267 bool dc_stream_get_scanoutpos(const struct dc_stream_state
*stream
,
268 uint32_t *v_blank_start
,
269 uint32_t *v_blank_end
,
270 uint32_t *h_position
,
271 uint32_t *v_position
)
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
;
279 for (i
= 0; i
< MAX_PIPES
; i
++) {
280 struct timing_generator
*tg
= res_ctx
->pipe_ctx
[i
].tg
;
282 if (res_ctx
->pipe_ctx
[i
].stream
!= stream
)
285 tg
->funcs
->get_scanoutpos(tg
,
300 const struct dc_stream_state
*stream
,
301 struct dal_logger
*dm_logger
,
302 enum dc_log_type log_type
)
305 dm_logger_write(dm_logger
,
307 "core_stream 0x%x: src: %d, %d, %d, %d; dst: %d, %d, %d, %d, colorSpace:%d\n",
317 stream
->output_color_space
);
318 dm_logger_write(dm_logger
,
320 "\tpix_clk_khz: %d, h_total: %d, v_total: %d, pixelencoder:%d, displaycolorDepth:%d\n",
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
);
326 dm_logger_write(dm_logger
,
328 "\tsink name: %s, serial: %d\n",
329 stream
->sink
->edid_caps
.display_name
,
330 stream
->sink
->edid_caps
.serial_number
);
331 dm_logger_write(dm_logger
,
334 stream
->sink
->link
->link_index
);