Line data Source code
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 "reg_helper.h"
27 : #include "dcn201_optc.h"
28 : #include "dcn10/dcn10_optc.h"
29 : #include "dc.h"
30 :
31 : #define REG(reg)\
32 : optc1->tg_regs->reg
33 :
34 : #define CTX \
35 : optc1->base.ctx
36 :
37 : #undef FN
38 : #define FN(reg_name, field_name) \
39 : optc1->tg_shift->field_name, optc1->tg_mask->field_name
40 :
41 : /*TEMP: Need to figure out inheritance model here.*/
42 0 : bool optc201_is_two_pixels_per_containter(const struct dc_crtc_timing *timing)
43 : {
44 0 : return optc1_is_two_pixels_per_containter(timing);
45 : }
46 :
47 0 : static void optc201_triplebuffer_lock(struct timing_generator *optc)
48 : {
49 0 : struct optc *optc1 = DCN10TG_FROM_TG(optc);
50 :
51 0 : REG_SET(OTG_GLOBAL_CONTROL0, 0,
52 : OTG_MASTER_UPDATE_LOCK_SEL, optc->inst);
53 0 : REG_SET(OTG_VUPDATE_KEEPOUT, 0,
54 : OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, 1);
55 0 : REG_SET(OTG_MASTER_UPDATE_LOCK, 0,
56 : OTG_MASTER_UPDATE_LOCK, 1);
57 :
58 0 : if (optc->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS)
59 0 : REG_WAIT(OTG_MASTER_UPDATE_LOCK,
60 : UPDATE_LOCK_STATUS, 1,
61 : 1, 10);
62 0 : }
63 :
64 0 : static void optc201_triplebuffer_unlock(struct timing_generator *optc)
65 : {
66 0 : struct optc *optc1 = DCN10TG_FROM_TG(optc);
67 :
68 0 : REG_SET(OTG_MASTER_UPDATE_LOCK, 0,
69 : OTG_MASTER_UPDATE_LOCK, 0);
70 0 : REG_SET(OTG_VUPDATE_KEEPOUT, 0,
71 : OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, 0);
72 :
73 0 : }
74 :
75 0 : static bool optc201_validate_timing(
76 : struct timing_generator *optc,
77 : const struct dc_crtc_timing *timing)
78 : {
79 : uint32_t v_blank;
80 : uint32_t h_blank;
81 : uint32_t min_v_blank;
82 0 : struct optc *optc1 = DCN10TG_FROM_TG(optc);
83 :
84 0 : ASSERT(timing != NULL);
85 :
86 0 : v_blank = (timing->v_total - timing->v_addressable -
87 0 : timing->v_border_top - timing->v_border_bottom);
88 :
89 0 : h_blank = (timing->h_total - timing->h_addressable -
90 0 : timing->h_border_right -
91 0 : timing->h_border_left);
92 :
93 0 : if (timing->timing_3d_format != TIMING_3D_FORMAT_NONE &&
94 0 : timing->timing_3d_format != TIMING_3D_FORMAT_HW_FRAME_PACKING &&
95 0 : timing->timing_3d_format != TIMING_3D_FORMAT_TOP_AND_BOTTOM &&
96 0 : timing->timing_3d_format != TIMING_3D_FORMAT_SIDE_BY_SIDE &&
97 0 : timing->timing_3d_format != TIMING_3D_FORMAT_FRAME_ALTERNATE &&
98 : timing->timing_3d_format != TIMING_3D_FORMAT_INBAND_FA)
99 : return false;
100 :
101 : /* Check maximum number of pixels supported by Timing Generator
102 : * (Currently will never fail, in order to fail needs display which
103 : * needs more than 8192 horizontal and
104 : * more than 8192 vertical total pixels)
105 : */
106 0 : if (timing->h_total > optc1->max_h_total ||
107 0 : timing->v_total > optc1->max_v_total)
108 : return false;
109 :
110 0 : if (h_blank < optc1->min_h_blank)
111 : return false;
112 :
113 0 : if (timing->h_sync_width < optc1->min_h_sync_width ||
114 0 : timing->v_sync_width < optc1->min_v_sync_width)
115 : return false;
116 :
117 0 : min_v_blank = timing->flags.INTERLACE?optc1->min_v_blank_interlace:optc1->min_v_blank;
118 :
119 0 : if (v_blank < min_v_blank)
120 : return false;
121 :
122 0 : return true;
123 :
124 : }
125 :
126 0 : static void optc201_get_optc_source(struct timing_generator *optc,
127 : uint32_t *num_of_src_opp,
128 : uint32_t *src_opp_id_0,
129 : uint32_t *src_opp_id_1)
130 : {
131 0 : struct optc *optc1 = DCN10TG_FROM_TG(optc);
132 :
133 0 : REG_GET(OPTC_DATA_SOURCE_SELECT,
134 : OPTC_SEG0_SRC_SEL, src_opp_id_0);
135 :
136 0 : *num_of_src_opp = 1;
137 0 : }
138 :
139 : static struct timing_generator_funcs dcn201_tg_funcs = {
140 : .validate_timing = optc201_validate_timing,
141 : .program_timing = optc1_program_timing,
142 : .setup_vertical_interrupt0 = optc1_setup_vertical_interrupt0,
143 : .setup_vertical_interrupt1 = optc1_setup_vertical_interrupt1,
144 : .setup_vertical_interrupt2 = optc1_setup_vertical_interrupt2,
145 : .program_global_sync = optc1_program_global_sync,
146 : .enable_crtc = optc2_enable_crtc,
147 : .disable_crtc = optc1_disable_crtc,
148 : /* used by enable_timing_synchronization. Not need for FPGA */
149 : .is_counter_moving = optc1_is_counter_moving,
150 : .get_position = optc1_get_position,
151 : .get_frame_count = optc1_get_vblank_counter,
152 : .get_scanoutpos = optc1_get_crtc_scanoutpos,
153 : .get_otg_active_size = optc1_get_otg_active_size,
154 : .set_early_control = optc1_set_early_control,
155 : /* used by enable_timing_synchronization. Not need for FPGA */
156 : .wait_for_state = optc1_wait_for_state,
157 : .set_blank = optc1_set_blank,
158 : .is_blanked = optc1_is_blanked,
159 : .set_blank_color = optc1_program_blank_color,
160 : .did_triggered_reset_occur = optc1_did_triggered_reset_occur,
161 : .enable_reset_trigger = optc1_enable_reset_trigger,
162 : .enable_crtc_reset = optc1_enable_crtc_reset,
163 : .disable_reset_trigger = optc1_disable_reset_trigger,
164 : .triplebuffer_lock = optc201_triplebuffer_lock,
165 : .triplebuffer_unlock = optc201_triplebuffer_unlock,
166 : .lock = optc1_lock,
167 : .unlock = optc1_unlock,
168 : .enable_optc_clock = optc1_enable_optc_clock,
169 : .set_drr = optc1_set_drr,
170 : .get_last_used_drr_vtotal = NULL,
171 : .set_vtotal_min_max = optc1_set_vtotal_min_max,
172 : .set_static_screen_control = optc1_set_static_screen_control,
173 : .program_stereo = optc1_program_stereo,
174 : .is_stereo_left_eye = optc1_is_stereo_left_eye,
175 : .set_blank_data_double_buffer = optc1_set_blank_data_double_buffer,
176 : .tg_init = optc1_tg_init,
177 : .is_tg_enabled = optc1_is_tg_enabled,
178 : .is_optc_underflow_occurred = optc1_is_optc_underflow_occurred,
179 : .clear_optc_underflow = optc1_clear_optc_underflow,
180 : .get_crc = optc1_get_crc,
181 : .configure_crc = optc2_configure_crc,
182 : .set_dsc_config = optc2_set_dsc_config,
183 : .set_dwb_source = NULL,
184 : .get_optc_source = optc201_get_optc_source,
185 : .set_vtg_params = optc1_set_vtg_params,
186 : .program_manual_trigger = optc2_program_manual_trigger,
187 : .setup_manual_trigger = optc2_setup_manual_trigger,
188 : .get_hw_timing = optc1_get_hw_timing,
189 : };
190 :
191 0 : void dcn201_timing_generator_init(struct optc *optc1)
192 : {
193 0 : optc1->base.funcs = &dcn201_tg_funcs;
194 :
195 0 : optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1;
196 0 : optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1;
197 :
198 0 : optc1->min_h_blank = 32;
199 0 : optc1->min_v_blank = 3;
200 0 : optc1->min_v_blank_interlace = 5;
201 0 : optc1->min_h_sync_width = 8;
202 0 : optc1->min_v_sync_width = 1;
203 0 : }
|