Narender Ankam | c7ce0b0 | 2020-03-16 17:40:34 +0530 | [diff] [blame] | 1 | /* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. |
Lloyd Atkinson | 09fed91 | 2016-06-24 18:14:13 -0400 | [diff] [blame] | 2 | * |
| 3 | * This program is free software; you can redistribute it and/or modify |
| 4 | * it under the terms of the GNU General Public License version 2 and |
| 5 | * only version 2 as published by the Free Software Foundation. |
| 6 | * |
| 7 | * This program is distributed in the hope that it will be useful, |
| 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 10 | * GNU General Public License for more details. |
Lloyd Atkinson | 09fed91 | 2016-06-24 18:14:13 -0400 | [diff] [blame] | 11 | */ |
| 12 | |
Clarence Ip | 19af136 | 2016-09-23 14:57:51 -0400 | [diff] [blame] | 13 | #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__ |
Lloyd Atkinson | 09fed91 | 2016-06-24 18:14:13 -0400 | [diff] [blame] | 14 | #include "sde_encoder_phys.h" |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 15 | #include "sde_hw_interrupts.h" |
Alan Kwong | f5dd86c | 2016-08-09 18:08:17 -0400 | [diff] [blame] | 16 | #include "sde_core_irq.h" |
Clarence Ip | c475b08 | 2016-06-26 09:27:23 -0400 | [diff] [blame] | 17 | #include "sde_formats.h" |
Jeykumar Sankaran | 5c2f070 | 2017-03-09 18:03:15 -0800 | [diff] [blame] | 18 | #include "dsi_display.h" |
Veera Sundaram Sankaran | a90e139 | 2017-07-06 15:00:09 -0700 | [diff] [blame] | 19 | #include "sde_trace.h" |
Lloyd Atkinson | 09fed91 | 2016-06-24 18:14:13 -0400 | [diff] [blame] | 20 | |
Clarence Ip | 19af136 | 2016-09-23 14:57:51 -0400 | [diff] [blame] | 21 | #define SDE_DEBUG_VIDENC(e, fmt, ...) SDE_DEBUG("enc%d intf%d " fmt, \ |
| 22 | (e) && (e)->base.parent ? \ |
| 23 | (e)->base.parent->base.id : -1, \ |
| 24 | (e) && (e)->hw_intf ? \ |
| 25 | (e)->hw_intf->idx - INTF_0 : -1, ##__VA_ARGS__) |
| 26 | |
| 27 | #define SDE_ERROR_VIDENC(e, fmt, ...) SDE_ERROR("enc%d intf%d " fmt, \ |
| 28 | (e) && (e)->base.parent ? \ |
| 29 | (e)->base.parent->base.id : -1, \ |
| 30 | (e) && (e)->hw_intf ? \ |
| 31 | (e)->hw_intf->idx - INTF_0 : -1, ##__VA_ARGS__) |
| 32 | |
Lloyd Atkinson | 09fed91 | 2016-06-24 18:14:13 -0400 | [diff] [blame] | 33 | #define to_sde_encoder_phys_vid(x) \ |
| 34 | container_of(x, struct sde_encoder_phys_vid, base) |
| 35 | |
Clarence Ip | 569d5af | 2017-10-14 21:09:01 -0400 | [diff] [blame] | 36 | /* maximum number of consecutive kickoff errors */ |
| 37 | #define KICKOFF_MAX_ERRORS 2 |
| 38 | |
Sandeep Panda | 11b20d8 | 2017-06-19 12:57:27 +0530 | [diff] [blame] | 39 | /* Poll time to do recovery during active region */ |
| 40 | #define POLL_TIME_USEC_FOR_LN_CNT 500 |
| 41 | #define MAX_POLL_CNT 10 |
| 42 | |
Raviteja Tamatam | 5a10dd1 | 2018-06-29 16:19:06 +0530 | [diff] [blame] | 43 | static bool _sde_encoder_phys_is_ppsplit(struct sde_encoder_phys *phys_enc) |
| 44 | { |
| 45 | enum sde_rm_topology_name topology; |
| 46 | |
| 47 | if (!phys_enc) |
| 48 | return false; |
| 49 | |
| 50 | topology = sde_connector_get_topology_name(phys_enc->connector); |
| 51 | if (topology == SDE_RM_TOPOLOGY_PPSPLIT) |
| 52 | return true; |
| 53 | |
| 54 | return false; |
| 55 | } |
| 56 | |
Ben Chan | 78647cd | 2016-06-26 22:02:47 -0400 | [diff] [blame] | 57 | static bool sde_encoder_phys_vid_is_master( |
| 58 | struct sde_encoder_phys *phys_enc) |
| 59 | { |
Lloyd Atkinson | e5c2c0b | 2016-07-05 12:23:29 -0400 | [diff] [blame] | 60 | bool ret = false; |
| 61 | |
| 62 | if (phys_enc->split_role != ENC_ROLE_SLAVE) |
| 63 | ret = true; |
Ben Chan | 78647cd | 2016-06-26 22:02:47 -0400 | [diff] [blame] | 64 | |
| 65 | return ret; |
| 66 | } |
| 67 | |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 68 | static void drm_mode_to_intf_timing_params( |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 69 | const struct sde_encoder_phys_vid *vid_enc, |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 70 | const struct drm_display_mode *mode, |
| 71 | struct intf_timing_params *timing) |
Lloyd Atkinson | 09fed91 | 2016-06-24 18:14:13 -0400 | [diff] [blame] | 72 | { |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 73 | memset(timing, 0, sizeof(*timing)); |
Veera Sundaram Sankaran | 3677471 | 2017-06-26 14:33:33 -0700 | [diff] [blame] | 74 | |
| 75 | if ((mode->htotal < mode->hsync_end) |
| 76 | || (mode->hsync_start < mode->hdisplay) |
| 77 | || (mode->vtotal < mode->vsync_end) |
| 78 | || (mode->vsync_start < mode->vdisplay) |
| 79 | || (mode->hsync_end < mode->hsync_start) |
| 80 | || (mode->vsync_end < mode->vsync_start)) { |
| 81 | SDE_ERROR( |
| 82 | "invalid params - hstart:%d,hend:%d,htot:%d,hdisplay:%d\n", |
| 83 | mode->hsync_start, mode->hsync_end, |
| 84 | mode->htotal, mode->hdisplay); |
| 85 | SDE_ERROR("vstart:%d,vend:%d,vtot:%d,vdisplay:%d\n", |
| 86 | mode->vsync_start, mode->vsync_end, |
| 87 | mode->vtotal, mode->vdisplay); |
| 88 | return; |
| 89 | } |
| 90 | |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 91 | /* |
| 92 | * https://www.kernel.org/doc/htmldocs/drm/ch02s05.html |
| 93 | * Active Region Front Porch Sync Back Porch |
| 94 | * <-----------------><------------><-----><-----------> |
| 95 | * <- [hv]display ---> |
| 96 | * <--------- [hv]sync_start ------> |
| 97 | * <----------------- [hv]sync_end -------> |
| 98 | * <---------------------------- [hv]total -------------> |
| 99 | */ |
| 100 | timing->width = mode->hdisplay; /* active width */ |
Jeykumar Sankaran | 5c2f070 | 2017-03-09 18:03:15 -0800 | [diff] [blame] | 101 | if (vid_enc->base.comp_type == MSM_DISPLAY_COMPRESSION_DSC) |
| 102 | timing->width = DIV_ROUND_UP(timing->width, 3); |
| 103 | |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 104 | timing->height = mode->vdisplay; /* active height */ |
| 105 | timing->xres = timing->width; |
| 106 | timing->yres = timing->height; |
| 107 | timing->h_back_porch = mode->htotal - mode->hsync_end; |
| 108 | timing->h_front_porch = mode->hsync_start - mode->hdisplay; |
| 109 | timing->v_back_porch = mode->vtotal - mode->vsync_end; |
| 110 | timing->v_front_porch = mode->vsync_start - mode->vdisplay; |
| 111 | timing->hsync_pulse_width = mode->hsync_end - mode->hsync_start; |
| 112 | timing->vsync_pulse_width = mode->vsync_end - mode->vsync_start; |
| 113 | timing->hsync_polarity = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0; |
| 114 | timing->vsync_polarity = (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0; |
| 115 | timing->border_clr = 0; |
| 116 | timing->underflow_clr = 0xff; |
| 117 | timing->hsync_skew = mode->hskew; |
Kalyan Thota | 6a9f3b7 | 2018-01-18 18:00:02 +0530 | [diff] [blame] | 118 | timing->v_front_porch_fixed = vid_enc->base.vfp_cached; |
Lloyd Atkinson | 09fed91 | 2016-06-24 18:14:13 -0400 | [diff] [blame] | 119 | |
| 120 | /* DSI controller cannot handle active-low sync signals. */ |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 121 | if (vid_enc->hw_intf->cap->type == INTF_DSI) { |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 122 | timing->hsync_polarity = 0; |
| 123 | timing->vsync_polarity = 0; |
Lloyd Atkinson | 09fed91 | 2016-06-24 18:14:13 -0400 | [diff] [blame] | 124 | } |
| 125 | |
| 126 | /* |
| 127 | * For edp only: |
| 128 | * DISPLAY_V_START = (VBP * HCYCLE) + HBP |
| 129 | * DISPLAY_V_END = (VBP + VACTIVE) * HCYCLE - 1 - HFP |
| 130 | */ |
| 131 | /* |
| 132 | * if (vid_enc->hw->cap->type == INTF_EDP) { |
| 133 | * display_v_start += mode->htotal - mode->hsync_start; |
| 134 | * display_v_end -= mode->hsync_start - mode->hdisplay; |
| 135 | * } |
| 136 | */ |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 137 | } |
| 138 | |
| 139 | static inline u32 get_horizontal_total(const struct intf_timing_params *timing) |
| 140 | { |
| 141 | u32 active = timing->xres; |
| 142 | u32 inactive = |
| 143 | timing->h_back_porch + timing->h_front_porch + |
| 144 | timing->hsync_pulse_width; |
| 145 | return active + inactive; |
| 146 | } |
| 147 | |
Kalyan Thota | 6a9f3b7 | 2018-01-18 18:00:02 +0530 | [diff] [blame] | 148 | static inline u32 get_vertical_total(const struct intf_timing_params *timing, |
| 149 | bool use_fixed_vfp) |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 150 | { |
Kalyan Thota | 6a9f3b7 | 2018-01-18 18:00:02 +0530 | [diff] [blame] | 151 | u32 inactive; |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 152 | u32 active = timing->yres; |
Kalyan Thota | 6a9f3b7 | 2018-01-18 18:00:02 +0530 | [diff] [blame] | 153 | u32 v_front_porch = use_fixed_vfp ? |
| 154 | timing->v_front_porch_fixed : timing->v_front_porch; |
| 155 | |
| 156 | inactive = timing->v_back_porch + v_front_porch + |
| 157 | timing->vsync_pulse_width; |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 158 | return active + inactive; |
| 159 | } |
| 160 | |
| 161 | /* |
| 162 | * programmable_fetch_get_num_lines: |
| 163 | * Number of fetch lines in vertical front porch |
| 164 | * @timing: Pointer to the intf timing information for the requested mode |
| 165 | * |
| 166 | * Returns the number of fetch lines in vertical front porch at which mdp |
| 167 | * can start fetching the next frame. |
| 168 | * |
| 169 | * Number of needed prefetch lines is anything that cannot be absorbed in the |
| 170 | * start of frame time (back porch + vsync pulse width). |
| 171 | * |
| 172 | * Some panels have very large VFP, however we only need a total number of |
| 173 | * lines based on the chip worst case latencies. |
| 174 | */ |
| 175 | static u32 programmable_fetch_get_num_lines( |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 176 | struct sde_encoder_phys_vid *vid_enc, |
Kalyan Thota | 6a9f3b7 | 2018-01-18 18:00:02 +0530 | [diff] [blame] | 177 | const struct intf_timing_params *timing, |
| 178 | bool use_fixed_vfp) |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 179 | { |
| 180 | u32 worst_case_needed_lines = |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 181 | vid_enc->hw_intf->cap->prog_fetch_lines_worst_case; |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 182 | u32 start_of_frame_lines = |
| 183 | timing->v_back_porch + timing->vsync_pulse_width; |
| 184 | u32 needed_vfp_lines = worst_case_needed_lines - start_of_frame_lines; |
| 185 | u32 actual_vfp_lines = 0; |
Kalyan Thota | 6a9f3b7 | 2018-01-18 18:00:02 +0530 | [diff] [blame] | 186 | u32 v_front_porch = use_fixed_vfp ? |
| 187 | timing->v_front_porch_fixed : timing->v_front_porch; |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 188 | |
| 189 | /* Fetch must be outside active lines, otherwise undefined. */ |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 190 | if (start_of_frame_lines >= worst_case_needed_lines) { |
Clarence Ip | 19af136 | 2016-09-23 14:57:51 -0400 | [diff] [blame] | 191 | SDE_DEBUG_VIDENC(vid_enc, |
| 192 | "prog fetch is not needed, large vbp+vsw\n"); |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 193 | actual_vfp_lines = 0; |
Kalyan Thota | 6a9f3b7 | 2018-01-18 18:00:02 +0530 | [diff] [blame] | 194 | } else if (v_front_porch < needed_vfp_lines) { |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 195 | /* Warn fetch needed, but not enough porch in panel config */ |
| 196 | pr_warn_once |
Lloyd Atkinson | e5c2c0b | 2016-07-05 12:23:29 -0400 | [diff] [blame] | 197 | ("low vbp+vfp may lead to perf issues in some cases\n"); |
Clarence Ip | 19af136 | 2016-09-23 14:57:51 -0400 | [diff] [blame] | 198 | SDE_DEBUG_VIDENC(vid_enc, |
| 199 | "less vfp than fetch req, using entire vfp\n"); |
Kalyan Thota | 6a9f3b7 | 2018-01-18 18:00:02 +0530 | [diff] [blame] | 200 | actual_vfp_lines = v_front_porch; |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 201 | } else { |
Clarence Ip | 19af136 | 2016-09-23 14:57:51 -0400 | [diff] [blame] | 202 | SDE_DEBUG_VIDENC(vid_enc, "room in vfp for needed prefetch\n"); |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 203 | actual_vfp_lines = needed_vfp_lines; |
| 204 | } |
| 205 | |
Clarence Ip | 19af136 | 2016-09-23 14:57:51 -0400 | [diff] [blame] | 206 | SDE_DEBUG_VIDENC(vid_enc, |
| 207 | "v_front_porch %u v_back_porch %u vsync_pulse_width %u\n", |
Kalyan Thota | 6a9f3b7 | 2018-01-18 18:00:02 +0530 | [diff] [blame] | 208 | v_front_porch, timing->v_back_porch, |
Clarence Ip | 19af136 | 2016-09-23 14:57:51 -0400 | [diff] [blame] | 209 | timing->vsync_pulse_width); |
| 210 | SDE_DEBUG_VIDENC(vid_enc, |
| 211 | "wc_lines %u needed_vfp_lines %u actual_vfp_lines %u\n", |
| 212 | worst_case_needed_lines, needed_vfp_lines, actual_vfp_lines); |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 213 | |
| 214 | return actual_vfp_lines; |
| 215 | } |
| 216 | |
| 217 | /* |
| 218 | * programmable_fetch_config: Programs HW to prefetch lines by offsetting |
| 219 | * the start of fetch into the vertical front porch for cases where the |
| 220 | * vsync pulse width and vertical back porch time is insufficient |
| 221 | * |
| 222 | * Gets # of lines to pre-fetch, then calculate VSYNC counter value. |
| 223 | * HW layer requires VSYNC counter of first pixel of tgt VFP line. |
| 224 | * |
| 225 | * @timing: Pointer to the intf timing information for the requested mode |
| 226 | */ |
| 227 | static void programmable_fetch_config(struct sde_encoder_phys *phys_enc, |
| 228 | const struct intf_timing_params *timing) |
| 229 | { |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 230 | struct sde_encoder_phys_vid *vid_enc = |
| 231 | to_sde_encoder_phys_vid(phys_enc); |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 232 | struct intf_prog_fetch f = { 0 }; |
| 233 | u32 vfp_fetch_lines = 0; |
| 234 | u32 horiz_total = 0; |
| 235 | u32 vert_total = 0; |
| 236 | u32 vfp_fetch_start_vsync_counter = 0; |
| 237 | unsigned long lock_flags; |
| 238 | |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 239 | if (WARN_ON_ONCE(!vid_enc->hw_intf->ops.setup_prg_fetch)) |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 240 | return; |
| 241 | |
Kalyan Thota | 6a9f3b7 | 2018-01-18 18:00:02 +0530 | [diff] [blame] | 242 | vfp_fetch_lines = programmable_fetch_get_num_lines(vid_enc, |
| 243 | timing, true); |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 244 | if (vfp_fetch_lines) { |
Kalyan Thota | 6a9f3b7 | 2018-01-18 18:00:02 +0530 | [diff] [blame] | 245 | vert_total = get_vertical_total(timing, true); |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 246 | horiz_total = get_horizontal_total(timing); |
| 247 | vfp_fetch_start_vsync_counter = |
| 248 | (vert_total - vfp_fetch_lines) * horiz_total + 1; |
| 249 | f.enable = 1; |
| 250 | f.fetch_start = vfp_fetch_start_vsync_counter; |
| 251 | } |
| 252 | |
Clarence Ip | 19af136 | 2016-09-23 14:57:51 -0400 | [diff] [blame] | 253 | SDE_DEBUG_VIDENC(vid_enc, |
| 254 | "vfp_fetch_lines %u vfp_fetch_start_vsync_counter %u\n", |
| 255 | vfp_fetch_lines, vfp_fetch_start_vsync_counter); |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 256 | |
Lloyd Atkinson | 7d07094 | 2016-07-26 18:35:12 -0400 | [diff] [blame] | 257 | spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags); |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 258 | vid_enc->hw_intf->ops.setup_prg_fetch(vid_enc->hw_intf, &f); |
Lloyd Atkinson | 7d07094 | 2016-07-26 18:35:12 -0400 | [diff] [blame] | 259 | spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags); |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 260 | } |
| 261 | |
Alan Kwong | 4aacd53 | 2017-02-04 18:51:33 -0800 | [diff] [blame] | 262 | /* |
| 263 | * programmable_rot_fetch_config: Programs ROT to prefetch lines by offsetting |
| 264 | * the start of fetch into the vertical front porch for cases where the |
| 265 | * vsync pulse width and vertical back porch time is insufficient |
| 266 | * |
| 267 | * Gets # of lines to pre-fetch, then calculate VSYNC counter value. |
| 268 | * HW layer requires VSYNC counter of first pixel of tgt VFP line. |
| 269 | * @phys_enc: Pointer to physical encoder |
| 270 | * @rot_fetch_lines: number of line to prefill, or 0 to disable |
Jayant Shekhar | 98e78a8 | 2018-01-12 17:50:55 +0530 | [diff] [blame] | 271 | * @is_primary: set true if the display is primary display |
Alan Kwong | 4aacd53 | 2017-02-04 18:51:33 -0800 | [diff] [blame] | 272 | */ |
| 273 | static void programmable_rot_fetch_config(struct sde_encoder_phys *phys_enc, |
Jayant Shekhar | 98e78a8 | 2018-01-12 17:50:55 +0530 | [diff] [blame] | 274 | u32 rot_fetch_lines, u32 is_primary) |
Alan Kwong | 4aacd53 | 2017-02-04 18:51:33 -0800 | [diff] [blame] | 275 | { |
| 276 | struct sde_encoder_phys_vid *vid_enc = |
| 277 | to_sde_encoder_phys_vid(phys_enc); |
| 278 | struct intf_prog_fetch f = { 0 }; |
Clarence Ip | 4990353 | 2017-04-24 11:50:09 -0700 | [diff] [blame] | 279 | struct intf_timing_params *timing; |
Alan Kwong | 4aacd53 | 2017-02-04 18:51:33 -0800 | [diff] [blame] | 280 | u32 vfp_fetch_lines = 0; |
| 281 | u32 horiz_total = 0; |
| 282 | u32 vert_total = 0; |
| 283 | u32 rot_fetch_start_vsync_counter = 0; |
Clarence Ip | 7eb9045 | 2017-05-23 11:41:19 -0400 | [diff] [blame] | 284 | u32 flush_mask = 0; |
Alan Kwong | 4aacd53 | 2017-02-04 18:51:33 -0800 | [diff] [blame] | 285 | unsigned long lock_flags; |
| 286 | |
Clarence Ip | 7eb9045 | 2017-05-23 11:41:19 -0400 | [diff] [blame] | 287 | if (!phys_enc || !vid_enc->hw_intf || !phys_enc->hw_ctl || |
| 288 | !phys_enc->hw_ctl->ops.get_bitmask_intf || |
| 289 | !phys_enc->hw_ctl->ops.update_pending_flush || |
Jeykumar Sankaran | d920ec7 | 2017-11-18 20:01:39 -0800 | [diff] [blame] | 290 | !vid_enc->hw_intf->ops.setup_rot_start || |
Jayant Shekhar | 98e78a8 | 2018-01-12 17:50:55 +0530 | [diff] [blame] | 291 | !phys_enc->sde_kms || |
| 292 | !is_primary) |
Alan Kwong | 4aacd53 | 2017-02-04 18:51:33 -0800 | [diff] [blame] | 293 | return; |
| 294 | |
Clarence Ip | 4990353 | 2017-04-24 11:50:09 -0700 | [diff] [blame] | 295 | timing = &vid_enc->timing_params; |
Kalyan Thota | 6a9f3b7 | 2018-01-18 18:00:02 +0530 | [diff] [blame] | 296 | vfp_fetch_lines = programmable_fetch_get_num_lines(vid_enc, |
| 297 | timing, true); |
Alan Kwong | d970060 | 2017-12-07 17:43:25 -0500 | [diff] [blame] | 298 | if (rot_fetch_lines) { |
Kalyan Thota | 6a9f3b7 | 2018-01-18 18:00:02 +0530 | [diff] [blame] | 299 | vert_total = get_vertical_total(timing, true); |
Alan Kwong | 4aacd53 | 2017-02-04 18:51:33 -0800 | [diff] [blame] | 300 | horiz_total = get_horizontal_total(timing); |
| 301 | if (vert_total >= (vfp_fetch_lines + rot_fetch_lines)) { |
| 302 | rot_fetch_start_vsync_counter = |
| 303 | (vert_total - vfp_fetch_lines - rot_fetch_lines) * |
| 304 | horiz_total + 1; |
| 305 | f.enable = 1; |
| 306 | f.fetch_start = rot_fetch_start_vsync_counter; |
Alan Kwong | d970060 | 2017-12-07 17:43:25 -0500 | [diff] [blame] | 307 | } else { |
| 308 | SDE_ERROR_VIDENC(vid_enc, |
| 309 | "vert_total %u rot_fetch_lines %u vfp_fetch_lines %u\n", |
| 310 | vert_total, rot_fetch_lines, vfp_fetch_lines); |
| 311 | SDE_EVT32(DRMID(phys_enc->parent), vert_total, |
| 312 | rot_fetch_lines, vfp_fetch_lines, |
| 313 | SDE_EVTLOG_ERROR); |
Alan Kwong | 4aacd53 | 2017-02-04 18:51:33 -0800 | [diff] [blame] | 314 | } |
| 315 | } |
| 316 | |
Alan Kwong | f5fd32b | 2017-08-18 11:24:31 -0400 | [diff] [blame] | 317 | /* return if rot_fetch does not change since last update */ |
| 318 | if (vid_enc->rot_fetch_valid && |
| 319 | !memcmp(&vid_enc->rot_fetch, &f, sizeof(f))) |
| 320 | return; |
| 321 | |
Alan Kwong | 4aacd53 | 2017-02-04 18:51:33 -0800 | [diff] [blame] | 322 | SDE_DEBUG_VIDENC(vid_enc, |
Alan Kwong | d268181 | 2017-08-27 21:24:43 -0400 | [diff] [blame] | 323 | "rot_fetch_lines %u vfp_fetch_lines %u rot_fetch_start_vsync_counter %u\n", |
| 324 | rot_fetch_lines, vfp_fetch_lines, |
| 325 | rot_fetch_start_vsync_counter); |
Alan Kwong | 4aacd53 | 2017-02-04 18:51:33 -0800 | [diff] [blame] | 326 | |
Jeykumar Sankaran | d920ec7 | 2017-11-18 20:01:39 -0800 | [diff] [blame] | 327 | if (!phys_enc->sde_kms->splash_data.cont_splash_en) { |
Alan Kwong | 052fb6b | 2018-01-05 13:37:34 -0500 | [diff] [blame] | 328 | SDE_EVT32(DRMID(phys_enc->parent), f.enable, f.fetch_start); |
| 329 | |
Raviteja Tamatam | 5a10dd1 | 2018-06-29 16:19:06 +0530 | [diff] [blame] | 330 | if (!_sde_encoder_phys_is_ppsplit(phys_enc) || |
| 331 | sde_encoder_phys_vid_is_master(phys_enc)) { |
| 332 | phys_enc->hw_ctl->ops.get_bitmask_intf( |
| 333 | phys_enc->hw_ctl, &flush_mask, |
| 334 | vid_enc->hw_intf->idx); |
| 335 | phys_enc->hw_ctl->ops.update_pending_flush( |
| 336 | phys_enc->hw_ctl, flush_mask); |
| 337 | } |
Jeykumar Sankaran | d920ec7 | 2017-11-18 20:01:39 -0800 | [diff] [blame] | 338 | spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags); |
| 339 | vid_enc->hw_intf->ops.setup_rot_start(vid_enc->hw_intf, &f); |
| 340 | spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags); |
Alan Kwong | f5fd32b | 2017-08-18 11:24:31 -0400 | [diff] [blame] | 341 | |
Alan Kwong | 052fb6b | 2018-01-05 13:37:34 -0500 | [diff] [blame] | 342 | vid_enc->rot_fetch = f; |
| 343 | vid_enc->rot_fetch_valid = true; |
| 344 | } |
Alan Kwong | 4aacd53 | 2017-02-04 18:51:33 -0800 | [diff] [blame] | 345 | } |
| 346 | |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 347 | static bool sde_encoder_phys_vid_mode_fixup( |
| 348 | struct sde_encoder_phys *phys_enc, |
| 349 | const struct drm_display_mode *mode, |
Lloyd Atkinson | af7952d | 2016-06-26 22:41:26 -0400 | [diff] [blame] | 350 | struct drm_display_mode *adj_mode) |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 351 | { |
Clarence Ip | 19af136 | 2016-09-23 14:57:51 -0400 | [diff] [blame] | 352 | if (phys_enc) |
| 353 | SDE_DEBUG_VIDENC(to_sde_encoder_phys_vid(phys_enc), "\n"); |
Lloyd Atkinson | 09fed91 | 2016-06-24 18:14:13 -0400 | [diff] [blame] | 354 | |
| 355 | /* |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 356 | * Modifying mode has consequences when the mode comes back to us |
Lloyd Atkinson | 09fed91 | 2016-06-24 18:14:13 -0400 | [diff] [blame] | 357 | */ |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 358 | return true; |
| 359 | } |
| 360 | |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 361 | static void sde_encoder_phys_vid_setup_timing_engine( |
| 362 | struct sde_encoder_phys *phys_enc) |
| 363 | { |
Dhaval Patel | 7961352 | 2016-10-25 23:18:48 -0700 | [diff] [blame] | 364 | struct sde_encoder_phys_vid *vid_enc; |
| 365 | struct drm_display_mode mode; |
Lloyd Atkinson | e5c2c0b | 2016-07-05 12:23:29 -0400 | [diff] [blame] | 366 | struct intf_timing_params timing_params = { 0 }; |
Lloyd Atkinson | 9a67349 | 2016-07-05 11:41:57 -0400 | [diff] [blame] | 367 | const struct sde_format *fmt = NULL; |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 368 | u32 fmt_fourcc = DRM_FORMAT_RGB888; |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 369 | unsigned long lock_flags; |
| 370 | struct sde_hw_intf_cfg intf_cfg = { 0 }; |
| 371 | |
Jeykumar Sankaran | d920ec7 | 2017-11-18 20:01:39 -0800 | [diff] [blame] | 372 | if (!phys_enc || !phys_enc->sde_kms || !phys_enc->hw_ctl || |
| 373 | !phys_enc->hw_ctl->ops.setup_intf_cfg) { |
Clarence Ip | 19af136 | 2016-09-23 14:57:51 -0400 | [diff] [blame] | 374 | SDE_ERROR("invalid encoder %d\n", phys_enc != 0); |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 375 | return; |
Clarence Ip | 19af136 | 2016-09-23 14:57:51 -0400 | [diff] [blame] | 376 | } |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 377 | |
Dhaval Patel | 7961352 | 2016-10-25 23:18:48 -0700 | [diff] [blame] | 378 | mode = phys_enc->cached_mode; |
| 379 | vid_enc = to_sde_encoder_phys_vid(phys_enc); |
| 380 | if (!vid_enc->hw_intf->ops.setup_timing_gen) { |
| 381 | SDE_ERROR("timing engine setup is not supported\n"); |
| 382 | return; |
| 383 | } |
| 384 | |
Clarence Ip | 19af136 | 2016-09-23 14:57:51 -0400 | [diff] [blame] | 385 | SDE_DEBUG_VIDENC(vid_enc, "enabling mode:\n"); |
Lloyd Atkinson | af7952d | 2016-06-26 22:41:26 -0400 | [diff] [blame] | 386 | drm_mode_debug_printmodeline(&mode); |
Lloyd Atkinson | 09fed91 | 2016-06-24 18:14:13 -0400 | [diff] [blame] | 387 | |
Chirag Khurana | ed859f5 | 2019-11-20 18:18:12 +0530 | [diff] [blame] | 388 | if (phys_enc->split_role != ENC_ROLE_SOLO || |
| 389 | (mode.private_flags & MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420)) { |
Lloyd Atkinson | af7952d | 2016-06-26 22:41:26 -0400 | [diff] [blame] | 390 | mode.hdisplay >>= 1; |
| 391 | mode.htotal >>= 1; |
| 392 | mode.hsync_start >>= 1; |
| 393 | mode.hsync_end >>= 1; |
Chirag Khurana | ed859f5 | 2019-11-20 18:18:12 +0530 | [diff] [blame] | 394 | mode.hskew >>= 1; |
Lloyd Atkinson | e5c2c0b | 2016-07-05 12:23:29 -0400 | [diff] [blame] | 395 | |
Clarence Ip | 19af136 | 2016-09-23 14:57:51 -0400 | [diff] [blame] | 396 | SDE_DEBUG_VIDENC(vid_enc, |
Chirag Khurana | ed859f5 | 2019-11-20 18:18:12 +0530 | [diff] [blame] | 397 | "split_role %d, halve horizontal %d %d %d %d %d\n", |
Clarence Ip | 19af136 | 2016-09-23 14:57:51 -0400 | [diff] [blame] | 398 | phys_enc->split_role, |
| 399 | mode.hdisplay, mode.htotal, |
Chirag Khurana | ed859f5 | 2019-11-20 18:18:12 +0530 | [diff] [blame] | 400 | mode.hsync_start, mode.hsync_end, |
| 401 | mode.hskew); |
Lloyd Atkinson | e5c2c0b | 2016-07-05 12:23:29 -0400 | [diff] [blame] | 402 | } |
| 403 | |
Kalyan Thota | 6a9f3b7 | 2018-01-18 18:00:02 +0530 | [diff] [blame] | 404 | if (!phys_enc->vfp_cached) { |
| 405 | phys_enc->vfp_cached = |
| 406 | sde_connector_get_panel_vfp(phys_enc->connector, &mode); |
| 407 | if (phys_enc->vfp_cached <= 0) |
| 408 | phys_enc->vfp_cached = mode.vsync_start - mode.vdisplay; |
| 409 | } |
| 410 | |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 411 | drm_mode_to_intf_timing_params(vid_enc, &mode, &timing_params); |
Lloyd Atkinson | e5c2c0b | 2016-07-05 12:23:29 -0400 | [diff] [blame] | 412 | |
Jeykumar Sankaran | d920ec7 | 2017-11-18 20:01:39 -0800 | [diff] [blame] | 413 | vid_enc->timing_params = timing_params; |
| 414 | |
| 415 | if (phys_enc->sde_kms->splash_data.cont_splash_en) { |
| 416 | SDE_DEBUG_VIDENC(vid_enc, |
| 417 | "skipping intf programming since cont splash is enabled\n"); |
| 418 | return; |
| 419 | } |
| 420 | |
Lloyd Atkinson | 9a67349 | 2016-07-05 11:41:57 -0400 | [diff] [blame] | 421 | fmt = sde_get_sde_format(fmt_fourcc); |
Clarence Ip | 19af136 | 2016-09-23 14:57:51 -0400 | [diff] [blame] | 422 | SDE_DEBUG_VIDENC(vid_enc, "fmt_fourcc 0x%X\n", fmt_fourcc); |
Lloyd Atkinson | 09fed91 | 2016-06-24 18:14:13 -0400 | [diff] [blame] | 423 | |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 424 | intf_cfg.intf = vid_enc->hw_intf->idx; |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 425 | intf_cfg.intf_mode_sel = SDE_CTL_MODE_SEL_VID; |
| 426 | intf_cfg.stream_sel = 0; /* Don't care value for video mode */ |
Lloyd Atkinson | 55987b0 | 2016-08-16 16:57:46 -0400 | [diff] [blame] | 427 | intf_cfg.mode_3d = sde_encoder_helper_get_3d_blend_mode(phys_enc); |
Lloyd Atkinson | 09fed91 | 2016-06-24 18:14:13 -0400 | [diff] [blame] | 428 | |
Lloyd Atkinson | 7d07094 | 2016-07-26 18:35:12 -0400 | [diff] [blame] | 429 | spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags); |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 430 | vid_enc->hw_intf->ops.setup_timing_gen(vid_enc->hw_intf, |
Lloyd Atkinson | 9a67349 | 2016-07-05 11:41:57 -0400 | [diff] [blame] | 431 | &timing_params, fmt); |
Lloyd Atkinson | 09fed91 | 2016-06-24 18:14:13 -0400 | [diff] [blame] | 432 | phys_enc->hw_ctl->ops.setup_intf_cfg(phys_enc->hw_ctl, &intf_cfg); |
Lloyd Atkinson | 7d07094 | 2016-07-26 18:35:12 -0400 | [diff] [blame] | 433 | spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags); |
Lloyd Atkinson | e5c2c0b | 2016-07-05 12:23:29 -0400 | [diff] [blame] | 434 | programmable_fetch_config(phys_enc, &timing_params); |
Lloyd Atkinson | 09fed91 | 2016-06-24 18:14:13 -0400 | [diff] [blame] | 435 | } |
| 436 | |
Ben Chan | 78647cd | 2016-06-26 22:02:47 -0400 | [diff] [blame] | 437 | static void sde_encoder_phys_vid_vblank_irq(void *arg, int irq_idx) |
Lloyd Atkinson | 09fed91 | 2016-06-24 18:14:13 -0400 | [diff] [blame] | 438 | { |
Lloyd Atkinson | 05ef823 | 2017-03-08 16:35:36 -0500 | [diff] [blame] | 439 | struct sde_encoder_phys *phys_enc = arg; |
| 440 | struct sde_encoder_phys_vid *vid_enc = |
| 441 | to_sde_encoder_phys_vid(phys_enc); |
Lloyd Atkinson | 6340a37 | 2017-04-05 13:04:22 -0700 | [diff] [blame] | 442 | struct sde_hw_ctl *hw_ctl; |
Lloyd Atkinson | 7d07094 | 2016-07-26 18:35:12 -0400 | [diff] [blame] | 443 | unsigned long lock_flags; |
Clarence Ip | a1b52e7 | 2018-01-15 17:04:16 -0500 | [diff] [blame] | 444 | u32 flush_register = ~0; |
Clarence Ip | 75fe4a1 | 2017-12-22 12:14:51 -0500 | [diff] [blame] | 445 | u32 reset_status = 0; |
Lloyd Atkinson | 6340a37 | 2017-04-05 13:04:22 -0700 | [diff] [blame] | 446 | int new_cnt = -1, old_cnt = -1; |
Veera Sundaram Sankaran | 675ff62 | 2017-06-21 21:44:46 -0700 | [diff] [blame] | 447 | u32 event = 0; |
Lloyd Atkinson | 09fed91 | 2016-06-24 18:14:13 -0400 | [diff] [blame] | 448 | |
Lloyd Atkinson | 05ef823 | 2017-03-08 16:35:36 -0500 | [diff] [blame] | 449 | if (!phys_enc) |
Clarence Ip | 19af136 | 2016-09-23 14:57:51 -0400 | [diff] [blame] | 450 | return; |
| 451 | |
Lloyd Atkinson | 6340a37 | 2017-04-05 13:04:22 -0700 | [diff] [blame] | 452 | hw_ctl = phys_enc->hw_ctl; |
Lloyd Atkinson | 6a5359d | 2017-06-21 10:18:08 -0400 | [diff] [blame] | 453 | if (!hw_ctl) |
| 454 | return; |
| 455 | |
Veera Sundaram Sankaran | a90e139 | 2017-07-06 15:00:09 -0700 | [diff] [blame] | 456 | SDE_ATRACE_BEGIN("vblank_irq"); |
Lloyd Atkinson | 6340a37 | 2017-04-05 13:04:22 -0700 | [diff] [blame] | 457 | |
Lloyd Atkinson | 6340a37 | 2017-04-05 13:04:22 -0700 | [diff] [blame] | 458 | /* |
| 459 | * only decrement the pending flush count if we've actually flushed |
| 460 | * hardware. due to sw irq latency, vblank may have already happened |
| 461 | * so we need to double-check with hw that it accepted the flush bits |
| 462 | */ |
Lloyd Atkinson | 7d07094 | 2016-07-26 18:35:12 -0400 | [diff] [blame] | 463 | spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags); |
Clarence Ip | a1b52e7 | 2018-01-15 17:04:16 -0500 | [diff] [blame] | 464 | |
| 465 | old_cnt = atomic_read(&phys_enc->pending_kickoff_cnt); |
| 466 | |
Lloyd Atkinson | 6340a37 | 2017-04-05 13:04:22 -0700 | [diff] [blame] | 467 | if (hw_ctl && hw_ctl->ops.get_flush_register) |
| 468 | flush_register = hw_ctl->ops.get_flush_register(hw_ctl); |
| 469 | |
Clarence Ip | a1b52e7 | 2018-01-15 17:04:16 -0500 | [diff] [blame] | 470 | if (flush_register) |
| 471 | goto not_flushed; |
Clarence Ip | 75fe4a1 | 2017-12-22 12:14:51 -0500 | [diff] [blame] | 472 | |
Clarence Ip | a1b52e7 | 2018-01-15 17:04:16 -0500 | [diff] [blame] | 473 | new_cnt = atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0); |
| 474 | |
| 475 | /* signal only for master, where there is a pending kickoff */ |
| 476 | if (sde_encoder_phys_vid_is_master(phys_enc)) { |
| 477 | if (atomic_add_unless(&phys_enc->pending_retire_fence_cnt, |
| 478 | -1, 0)) |
| 479 | event |= SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE | |
| 480 | SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE; |
| 481 | } |
| 482 | |
| 483 | not_flushed: |
Clarence Ip | 75fe4a1 | 2017-12-22 12:14:51 -0500 | [diff] [blame] | 484 | if (hw_ctl && hw_ctl->ops.get_reset) |
| 485 | reset_status = hw_ctl->ops.get_reset(hw_ctl); |
| 486 | |
Lloyd Atkinson | 7d07094 | 2016-07-26 18:35:12 -0400 | [diff] [blame] | 487 | spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags); |
| 488 | |
Clarence Ip | a1b52e7 | 2018-01-15 17:04:16 -0500 | [diff] [blame] | 489 | if (event && phys_enc->parent_ops.handle_frame_done) |
| 490 | phys_enc->parent_ops.handle_frame_done(phys_enc->parent, |
| 491 | phys_enc, event); |
| 492 | |
| 493 | if (phys_enc->parent_ops.handle_vblank_virt) |
| 494 | phys_enc->parent_ops.handle_vblank_virt(phys_enc->parent, |
| 495 | phys_enc); |
| 496 | |
Lloyd Atkinson | 6340a37 | 2017-04-05 13:04:22 -0700 | [diff] [blame] | 497 | SDE_EVT32_IRQ(DRMID(phys_enc->parent), vid_enc->hw_intf->idx - INTF_0, |
Clarence Ip | 75fe4a1 | 2017-12-22 12:14:51 -0500 | [diff] [blame] | 498 | old_cnt, new_cnt, reset_status ? SDE_EVTLOG_ERROR : 0, |
| 499 | flush_register, event); |
Lloyd Atkinson | 6340a37 | 2017-04-05 13:04:22 -0700 | [diff] [blame] | 500 | |
Lloyd Atkinson | 7d07094 | 2016-07-26 18:35:12 -0400 | [diff] [blame] | 501 | /* Signal any waiting atomic commit thread */ |
| 502 | wake_up_all(&phys_enc->pending_kickoff_wq); |
Veera Sundaram Sankaran | a90e139 | 2017-07-06 15:00:09 -0700 | [diff] [blame] | 503 | SDE_ATRACE_END("vblank_irq"); |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 504 | } |
| 505 | |
Dhaval Patel | 81e8788 | 2016-10-19 21:41:56 -0700 | [diff] [blame] | 506 | static void sde_encoder_phys_vid_underrun_irq(void *arg, int irq_idx) |
| 507 | { |
Lloyd Atkinson | 05ef823 | 2017-03-08 16:35:36 -0500 | [diff] [blame] | 508 | struct sde_encoder_phys *phys_enc = arg; |
Dhaval Patel | 81e8788 | 2016-10-19 21:41:56 -0700 | [diff] [blame] | 509 | |
Lloyd Atkinson | 05ef823 | 2017-03-08 16:35:36 -0500 | [diff] [blame] | 510 | if (!phys_enc) |
Dhaval Patel | 81e8788 | 2016-10-19 21:41:56 -0700 | [diff] [blame] | 511 | return; |
| 512 | |
Dhaval Patel | 81e8788 | 2016-10-19 21:41:56 -0700 | [diff] [blame] | 513 | if (phys_enc->parent_ops.handle_underrun_virt) |
| 514 | phys_enc->parent_ops.handle_underrun_virt(phys_enc->parent, |
| 515 | phys_enc); |
| 516 | } |
| 517 | |
Ingrid Gallardo | 1afd2c1 | 2017-08-17 16:24:35 -0700 | [diff] [blame] | 518 | static bool _sde_encoder_phys_is_dual_ctl(struct sde_encoder_phys *phys_enc) |
| 519 | { |
| 520 | enum sde_rm_topology_name topology; |
| 521 | |
| 522 | if (!phys_enc) |
| 523 | return false; |
| 524 | |
| 525 | topology = sde_connector_get_topology_name(phys_enc->connector); |
| 526 | if ((topology == SDE_RM_TOPOLOGY_DUALPIPE_DSC) || |
Kalyan Thota | 27ec06c | 2019-03-18 13:19:59 +0530 | [diff] [blame] | 527 | (topology == SDE_RM_TOPOLOGY_DUALPIPE) || |
| 528 | (topology == SDE_RM_TOPOLOGY_QUADPIPE_3DMERGE) || |
| 529 | (topology == SDE_RM_TOPOLOGY_QUADPIPE_DSCMERGE) || |
| 530 | (topology == SDE_RM_TOPOLOGY_QUADPIPE_3DMERGE_DSC)) |
Ingrid Gallardo | 1afd2c1 | 2017-08-17 16:24:35 -0700 | [diff] [blame] | 531 | return true; |
| 532 | |
| 533 | return false; |
| 534 | } |
| 535 | |
Clarence Ip | 8e69ad0 | 2016-12-09 09:43:57 -0500 | [diff] [blame] | 536 | static bool sde_encoder_phys_vid_needs_single_flush( |
Clarence Ip | 110d15c | 2016-08-16 14:44:41 -0400 | [diff] [blame] | 537 | struct sde_encoder_phys *phys_enc) |
| 538 | { |
Ingrid Gallardo | 72cd163 | 2018-02-28 15:26:37 -0800 | [diff] [blame] | 539 | return phys_enc && ( |
| 540 | phys_enc->cont_splash_settings ? |
| 541 | phys_enc->cont_splash_single_flush : |
| 542 | (_sde_encoder_phys_is_ppsplit(phys_enc) || |
| 543 | _sde_encoder_phys_is_dual_ctl(phys_enc))); |
Clarence Ip | 110d15c | 2016-08-16 14:44:41 -0400 | [diff] [blame] | 544 | } |
| 545 | |
Lloyd Atkinson | 05ef823 | 2017-03-08 16:35:36 -0500 | [diff] [blame] | 546 | static void _sde_encoder_phys_vid_setup_irq_hw_idx( |
| 547 | struct sde_encoder_phys *phys_enc) |
Ben Chan | 78647cd | 2016-06-26 22:02:47 -0400 | [diff] [blame] | 548 | { |
Lloyd Atkinson | 05ef823 | 2017-03-08 16:35:36 -0500 | [diff] [blame] | 549 | struct sde_encoder_irq *irq; |
Ben Chan | 78647cd | 2016-06-26 22:02:47 -0400 | [diff] [blame] | 550 | |
Raviteja Tamatam | 68892de | 2017-06-20 04:47:19 +0530 | [diff] [blame] | 551 | /* |
| 552 | * Initialize irq->hw_idx only when irq is not registered. |
| 553 | * Prevent invalidating irq->irq_idx as modeset may be |
| 554 | * called many times during dfps. |
| 555 | */ |
| 556 | |
Lloyd Atkinson | 05ef823 | 2017-03-08 16:35:36 -0500 | [diff] [blame] | 557 | irq = &phys_enc->irq[INTR_IDX_VSYNC]; |
Raviteja Tamatam | 68892de | 2017-06-20 04:47:19 +0530 | [diff] [blame] | 558 | if (irq->irq_idx < 0) |
| 559 | irq->hw_idx = phys_enc->intf_idx; |
Clarence Ip | 19af136 | 2016-09-23 14:57:51 -0400 | [diff] [blame] | 560 | |
Lloyd Atkinson | 05ef823 | 2017-03-08 16:35:36 -0500 | [diff] [blame] | 561 | irq = &phys_enc->irq[INTR_IDX_UNDERRUN]; |
Raviteja Tamatam | 68892de | 2017-06-20 04:47:19 +0530 | [diff] [blame] | 562 | if (irq->irq_idx < 0) |
| 563 | irq->hw_idx = phys_enc->intf_idx; |
Lloyd Atkinson | 09fed91 | 2016-06-24 18:14:13 -0400 | [diff] [blame] | 564 | } |
| 565 | |
Chandan Uddaraju | 3f2cf42 | 2017-06-15 15:37:39 -0700 | [diff] [blame] | 566 | static void sde_encoder_phys_vid_cont_splash_mode_set( |
| 567 | struct sde_encoder_phys *phys_enc, |
| 568 | struct drm_display_mode *adj_mode) |
| 569 | { |
| 570 | if (!phys_enc || !adj_mode) { |
| 571 | SDE_ERROR("invalid args\n"); |
| 572 | return; |
| 573 | } |
| 574 | |
| 575 | phys_enc->cached_mode = *adj_mode; |
| 576 | phys_enc->enable_state = SDE_ENC_ENABLED; |
| 577 | |
| 578 | _sde_encoder_phys_vid_setup_irq_hw_idx(phys_enc); |
| 579 | } |
| 580 | |
Lloyd Atkinson | af7952d | 2016-06-26 22:41:26 -0400 | [diff] [blame] | 581 | static void sde_encoder_phys_vid_mode_set( |
| 582 | struct sde_encoder_phys *phys_enc, |
| 583 | struct drm_display_mode *mode, |
| 584 | struct drm_display_mode *adj_mode) |
| 585 | { |
Clarence Ip | 8e69ad0 | 2016-12-09 09:43:57 -0500 | [diff] [blame] | 586 | struct sde_rm *rm; |
Lloyd Atkinson | 11f3444 | 2016-08-11 11:19:52 -0400 | [diff] [blame] | 587 | struct sde_rm_hw_iter iter; |
| 588 | int i, instance; |
Dhaval Patel | 7961352 | 2016-10-25 23:18:48 -0700 | [diff] [blame] | 589 | struct sde_encoder_phys_vid *vid_enc; |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 590 | |
Clarence Ip | 8e69ad0 | 2016-12-09 09:43:57 -0500 | [diff] [blame] | 591 | if (!phys_enc || !phys_enc->sde_kms) { |
Veera Sundaram Sankaran | 3677471 | 2017-06-26 14:33:33 -0700 | [diff] [blame] | 592 | SDE_ERROR("invalid encoder/kms\n"); |
Clarence Ip | 19af136 | 2016-09-23 14:57:51 -0400 | [diff] [blame] | 593 | return; |
| 594 | } |
| 595 | |
Chirag Khurana | ed859f5 | 2019-11-20 18:18:12 +0530 | [diff] [blame] | 596 | phys_enc->hw_ctl = NULL; |
| 597 | phys_enc->hw_cdm = NULL; |
| 598 | |
Clarence Ip | 8e69ad0 | 2016-12-09 09:43:57 -0500 | [diff] [blame] | 599 | rm = &phys_enc->sde_kms->rm; |
Dhaval Patel | 7961352 | 2016-10-25 23:18:48 -0700 | [diff] [blame] | 600 | vid_enc = to_sde_encoder_phys_vid(phys_enc); |
Veera Sundaram Sankaran | 3677471 | 2017-06-26 14:33:33 -0700 | [diff] [blame] | 601 | |
| 602 | if (adj_mode) { |
| 603 | phys_enc->cached_mode = *adj_mode; |
| 604 | drm_mode_debug_printmodeline(adj_mode); |
| 605 | SDE_DEBUG_VIDENC(vid_enc, "caching mode:\n"); |
| 606 | } |
Lloyd Atkinson | 11f3444 | 2016-08-11 11:19:52 -0400 | [diff] [blame] | 607 | |
| 608 | instance = phys_enc->split_role == ENC_ROLE_SLAVE ? 1 : 0; |
| 609 | |
| 610 | /* Retrieve previously allocated HW Resources. Shouldn't fail */ |
| 611 | sde_rm_init_hw_iter(&iter, phys_enc->parent->base.id, SDE_HW_BLK_CTL); |
| 612 | for (i = 0; i <= instance; i++) { |
Clarence Ip | 8e69ad0 | 2016-12-09 09:43:57 -0500 | [diff] [blame] | 613 | if (sde_rm_get_hw(rm, &iter)) |
| 614 | phys_enc->hw_ctl = (struct sde_hw_ctl *)iter.hw; |
Lloyd Atkinson | 11f3444 | 2016-08-11 11:19:52 -0400 | [diff] [blame] | 615 | } |
Lloyd Atkinson | 11f3444 | 2016-08-11 11:19:52 -0400 | [diff] [blame] | 616 | if (IS_ERR_OR_NULL(phys_enc->hw_ctl)) { |
Clarence Ip | 19af136 | 2016-09-23 14:57:51 -0400 | [diff] [blame] | 617 | SDE_ERROR_VIDENC(vid_enc, "failed to init ctl, %ld\n", |
| 618 | PTR_ERR(phys_enc->hw_ctl)); |
Lloyd Atkinson | 11f3444 | 2016-08-11 11:19:52 -0400 | [diff] [blame] | 619 | phys_enc->hw_ctl = NULL; |
| 620 | return; |
| 621 | } |
Lloyd Atkinson | 05ef823 | 2017-03-08 16:35:36 -0500 | [diff] [blame] | 622 | |
| 623 | _sde_encoder_phys_vid_setup_irq_hw_idx(phys_enc); |
Chirag Khurana | ed859f5 | 2019-11-20 18:18:12 +0530 | [diff] [blame] | 624 | |
| 625 | /* CDM is optional */ |
| 626 | sde_rm_init_hw_iter(&iter, phys_enc->parent->base.id, SDE_HW_BLK_CDM); |
| 627 | for (i = 0; i <= instance; i++) { |
| 628 | sde_rm_get_hw(rm, &iter); |
| 629 | if (i == instance) |
| 630 | phys_enc->hw_cdm = (struct sde_hw_cdm *) iter.hw; |
| 631 | } |
| 632 | |
| 633 | if (IS_ERR(phys_enc->hw_cdm)) { |
| 634 | SDE_ERROR("CDM required but not allocated: %ld\n", |
| 635 | PTR_ERR(phys_enc->hw_cdm)); |
| 636 | phys_enc->hw_cdm = NULL; |
| 637 | } |
Lloyd Atkinson | af7952d | 2016-06-26 22:41:26 -0400 | [diff] [blame] | 638 | } |
| 639 | |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 640 | static int sde_encoder_phys_vid_control_vblank_irq( |
| 641 | struct sde_encoder_phys *phys_enc, |
| 642 | bool enable) |
| 643 | { |
| 644 | int ret = 0; |
Dhaval Patel | 7961352 | 2016-10-25 23:18:48 -0700 | [diff] [blame] | 645 | struct sde_encoder_phys_vid *vid_enc; |
Dhaval Patel | e17e0ee | 2017-08-23 18:01:42 -0700 | [diff] [blame] | 646 | int refcount; |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 647 | |
Clarence Ip | 19af136 | 2016-09-23 14:57:51 -0400 | [diff] [blame] | 648 | if (!phys_enc) { |
| 649 | SDE_ERROR("invalid encoder\n"); |
| 650 | return -EINVAL; |
| 651 | } |
| 652 | |
Raviteja Tamatam | 3ea60b8 | 2018-04-27 15:41:18 +0530 | [diff] [blame] | 653 | mutex_lock(phys_enc->vblank_ctl_lock); |
Dhaval Patel | e17e0ee | 2017-08-23 18:01:42 -0700 | [diff] [blame] | 654 | refcount = atomic_read(&phys_enc->vblank_refcount); |
Dhaval Patel | 7961352 | 2016-10-25 23:18:48 -0700 | [diff] [blame] | 655 | vid_enc = to_sde_encoder_phys_vid(phys_enc); |
| 656 | |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 657 | /* Slave encoders don't report vblank */ |
Alan Kwong | baa5635 | 2016-10-04 09:38:11 -0400 | [diff] [blame] | 658 | if (!sde_encoder_phys_vid_is_master(phys_enc)) |
Dhaval Patel | e17e0ee | 2017-08-23 18:01:42 -0700 | [diff] [blame] | 659 | goto end; |
| 660 | |
| 661 | /* protect against negative */ |
| 662 | if (!enable && refcount == 0) { |
| 663 | ret = -EINVAL; |
| 664 | goto end; |
| 665 | } |
Alan Kwong | baa5635 | 2016-10-04 09:38:11 -0400 | [diff] [blame] | 666 | |
| 667 | SDE_DEBUG_VIDENC(vid_enc, "[%pS] enable=%d/%d\n", |
| 668 | __builtin_return_address(0), |
| 669 | enable, atomic_read(&phys_enc->vblank_refcount)); |
| 670 | |
Lloyd Atkinson | 5d40d31 | 2016-09-06 08:34:13 -0400 | [diff] [blame] | 671 | SDE_EVT32(DRMID(phys_enc->parent), enable, |
Alan Kwong | baa5635 | 2016-10-04 09:38:11 -0400 | [diff] [blame] | 672 | atomic_read(&phys_enc->vblank_refcount)); |
| 673 | |
Jayant Shekhar | 3136b28 | 2018-05-04 10:55:15 +0530 | [diff] [blame] | 674 | if (enable && atomic_inc_return(&phys_enc->vblank_refcount) == 1) { |
Lloyd Atkinson | 05ef823 | 2017-03-08 16:35:36 -0500 | [diff] [blame] | 675 | ret = sde_encoder_helper_register_irq(phys_enc, INTR_IDX_VSYNC); |
Jayant Shekhar | 3136b28 | 2018-05-04 10:55:15 +0530 | [diff] [blame] | 676 | if (ret) |
| 677 | atomic_dec_return(&phys_enc->vblank_refcount); |
| 678 | } else if (!enable && |
| 679 | atomic_dec_return(&phys_enc->vblank_refcount) == 0) { |
Lloyd Atkinson | 05ef823 | 2017-03-08 16:35:36 -0500 | [diff] [blame] | 680 | ret = sde_encoder_helper_unregister_irq(phys_enc, |
| 681 | INTR_IDX_VSYNC); |
Jayant Shekhar | 3136b28 | 2018-05-04 10:55:15 +0530 | [diff] [blame] | 682 | if (ret) |
| 683 | atomic_inc_return(&phys_enc->vblank_refcount); |
| 684 | } |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 685 | |
Dhaval Patel | e17e0ee | 2017-08-23 18:01:42 -0700 | [diff] [blame] | 686 | end: |
| 687 | if (ret) { |
Clarence Ip | 19af136 | 2016-09-23 14:57:51 -0400 | [diff] [blame] | 688 | SDE_ERROR_VIDENC(vid_enc, |
| 689 | "control vblank irq error %d, enable %d\n", |
| 690 | ret, enable); |
Dhaval Patel | e17e0ee | 2017-08-23 18:01:42 -0700 | [diff] [blame] | 691 | SDE_EVT32(DRMID(phys_enc->parent), |
| 692 | vid_enc->hw_intf->idx - INTF_0, |
| 693 | enable, refcount, SDE_EVTLOG_ERROR); |
| 694 | } |
Raviteja Tamatam | 3ea60b8 | 2018-04-27 15:41:18 +0530 | [diff] [blame] | 695 | mutex_unlock(phys_enc->vblank_ctl_lock); |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 696 | return ret; |
| 697 | } |
| 698 | |
Ingrid Gallardo | 61210ea | 2017-10-17 17:29:31 -0700 | [diff] [blame] | 699 | static bool sde_encoder_phys_vid_wait_dma_trigger( |
| 700 | struct sde_encoder_phys *phys_enc) |
| 701 | { |
| 702 | struct sde_encoder_phys_vid *vid_enc; |
| 703 | struct sde_hw_intf *intf; |
| 704 | struct sde_hw_ctl *ctl; |
| 705 | struct intf_status status; |
| 706 | |
| 707 | if (!phys_enc) { |
| 708 | SDE_ERROR("invalid encoder\n"); |
| 709 | return false; |
| 710 | } |
| 711 | |
| 712 | vid_enc = to_sde_encoder_phys_vid(phys_enc); |
| 713 | intf = vid_enc->hw_intf; |
| 714 | ctl = phys_enc->hw_ctl; |
| 715 | if (!vid_enc->hw_intf || !phys_enc->hw_ctl) { |
| 716 | SDE_ERROR("invalid hw_intf %d hw_ctl %d\n", |
| 717 | vid_enc->hw_intf != NULL, phys_enc->hw_ctl != NULL); |
| 718 | return false; |
| 719 | } |
| 720 | |
| 721 | if (!intf->ops.get_status) |
| 722 | return false; |
| 723 | |
| 724 | intf->ops.get_status(intf, &status); |
| 725 | |
| 726 | /* if interface is not enabled, return true to wait for dma trigger */ |
| 727 | return status.is_en ? false : true; |
| 728 | } |
| 729 | |
Lloyd Atkinson | e5c2c0b | 2016-07-05 12:23:29 -0400 | [diff] [blame] | 730 | static void sde_encoder_phys_vid_enable(struct sde_encoder_phys *phys_enc) |
| 731 | { |
Alan Kwong | 67a3f79 | 2016-11-01 23:16:53 -0400 | [diff] [blame] | 732 | struct msm_drm_private *priv; |
Dhaval Patel | 7961352 | 2016-10-25 23:18:48 -0700 | [diff] [blame] | 733 | struct sde_encoder_phys_vid *vid_enc; |
| 734 | struct sde_hw_intf *intf; |
| 735 | struct sde_hw_ctl *ctl; |
Chirag Khurana | ed859f5 | 2019-11-20 18:18:12 +0530 | [diff] [blame] | 736 | struct sde_hw_cdm *hw_cdm = NULL; |
| 737 | struct drm_display_mode mode; |
| 738 | const struct sde_format *fmt = NULL; |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 739 | u32 flush_mask = 0; |
Lloyd Atkinson | 09fed91 | 2016-06-24 18:14:13 -0400 | [diff] [blame] | 740 | |
Alan Kwong | 67a3f79 | 2016-11-01 23:16:53 -0400 | [diff] [blame] | 741 | if (!phys_enc || !phys_enc->parent || !phys_enc->parent->dev || |
Jeykumar Sankaran | d920ec7 | 2017-11-18 20:01:39 -0800 | [diff] [blame] | 742 | !phys_enc->parent->dev->dev_private || |
| 743 | !phys_enc->sde_kms) { |
Alan Kwong | 67a3f79 | 2016-11-01 23:16:53 -0400 | [diff] [blame] | 744 | SDE_ERROR("invalid encoder/device\n"); |
Clarence Ip | 19af136 | 2016-09-23 14:57:51 -0400 | [diff] [blame] | 745 | return; |
Dhaval Patel | 7961352 | 2016-10-25 23:18:48 -0700 | [diff] [blame] | 746 | } |
Chirag Khurana | ed859f5 | 2019-11-20 18:18:12 +0530 | [diff] [blame] | 747 | hw_cdm = phys_enc->hw_cdm; |
Alan Kwong | 67a3f79 | 2016-11-01 23:16:53 -0400 | [diff] [blame] | 748 | priv = phys_enc->parent->dev->dev_private; |
Chirag Khurana | ed859f5 | 2019-11-20 18:18:12 +0530 | [diff] [blame] | 749 | mode = phys_enc->cached_mode; |
Dhaval Patel | 7961352 | 2016-10-25 23:18:48 -0700 | [diff] [blame] | 750 | |
| 751 | vid_enc = to_sde_encoder_phys_vid(phys_enc); |
| 752 | intf = vid_enc->hw_intf; |
| 753 | ctl = phys_enc->hw_ctl; |
| 754 | if (!vid_enc->hw_intf || !phys_enc->hw_ctl) { |
Clarence Ip | 19af136 | 2016-09-23 14:57:51 -0400 | [diff] [blame] | 755 | SDE_ERROR("invalid hw_intf %d hw_ctl %d\n", |
| 756 | vid_enc->hw_intf != 0, phys_enc->hw_ctl != 0); |
Lloyd Atkinson | 11f3444 | 2016-08-11 11:19:52 -0400 | [diff] [blame] | 757 | return; |
| 758 | } |
| 759 | |
Clarence Ip | 19af136 | 2016-09-23 14:57:51 -0400 | [diff] [blame] | 760 | SDE_DEBUG_VIDENC(vid_enc, "\n"); |
Lloyd Atkinson | 09fed91 | 2016-06-24 18:14:13 -0400 | [diff] [blame] | 761 | |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 762 | if (WARN_ON(!vid_enc->hw_intf->ops.enable_timing)) |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 763 | return; |
| 764 | |
Alan Kwong | f5fd32b | 2017-08-18 11:24:31 -0400 | [diff] [blame] | 765 | /* reset state variables until after first update */ |
| 766 | vid_enc->rot_fetch_valid = false; |
| 767 | |
Jeykumar Sankaran | d920ec7 | 2017-11-18 20:01:39 -0800 | [diff] [blame] | 768 | if (!phys_enc->sde_kms->splash_data.cont_splash_en) |
| 769 | sde_encoder_helper_split_config(phys_enc, |
| 770 | vid_enc->hw_intf->idx); |
Lloyd Atkinson | e5c2c0b | 2016-07-05 12:23:29 -0400 | [diff] [blame] | 771 | |
Lloyd Atkinson | 09fed91 | 2016-06-24 18:14:13 -0400 | [diff] [blame] | 772 | sde_encoder_phys_vid_setup_timing_engine(phys_enc); |
Clarence Ip | f99ccea | 2016-07-05 11:41:07 -0400 | [diff] [blame] | 773 | |
Ingrid Gallardo | 821985b | 2017-05-31 16:50:52 -0700 | [diff] [blame] | 774 | /* |
Krishna Manikandan | cdf394e | 2018-09-20 14:32:48 +0530 | [diff] [blame] | 775 | * For pp-split, skip setting the flush bit for the slave intf, |
| 776 | * since both intfs use same ctl and HW will only flush the master. |
Ingrid Gallardo | 821985b | 2017-05-31 16:50:52 -0700 | [diff] [blame] | 777 | */ |
Krishna Manikandan | cdf394e | 2018-09-20 14:32:48 +0530 | [diff] [blame] | 778 | if (_sde_encoder_phys_is_ppsplit(phys_enc) && |
Ingrid Gallardo | 821985b | 2017-05-31 16:50:52 -0700 | [diff] [blame] | 779 | !sde_encoder_phys_vid_is_master(phys_enc)) |
| 780 | goto skip_flush; |
| 781 | |
Jeykumar Sankaran | d920ec7 | 2017-11-18 20:01:39 -0800 | [diff] [blame] | 782 | /** |
| 783 | * skip flushing intf during cont. splash handoff since bootloader |
| 784 | * has already enabled the hardware and is single buffered. |
| 785 | */ |
| 786 | |
| 787 | if (phys_enc->sde_kms->splash_data.cont_splash_en) { |
| 788 | SDE_DEBUG_VIDENC(vid_enc, |
| 789 | "skipping intf flush bit set as cont. splash is enabled\n"); |
| 790 | goto skip_flush; |
| 791 | } |
| 792 | |
Chirag Khurana | ed859f5 | 2019-11-20 18:18:12 +0530 | [diff] [blame] | 793 | if (mode.private_flags & MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420) |
| 794 | fmt = sde_get_sde_format(DRM_FORMAT_YUV420); |
Narender Ankam | 08247f7 | 2019-12-23 18:57:49 +0530 | [diff] [blame] | 795 | else if (mode.private_flags & MSM_MODE_FLAG_COLOR_FORMAT_YCBCR422) |
| 796 | fmt = sde_get_sde_format(DRM_FORMAT_NV61); |
Chirag Khurana | ed859f5 | 2019-11-20 18:18:12 +0530 | [diff] [blame] | 797 | |
| 798 | if (fmt) { |
| 799 | struct sde_rect hdmi_roi; |
| 800 | |
| 801 | hdmi_roi.w = mode.hdisplay; |
| 802 | hdmi_roi.h = mode.vdisplay; |
| 803 | sde_encoder_phys_setup_cdm(phys_enc, fmt, |
| 804 | CDM_CDWN_OUTPUT_HDMI, &hdmi_roi); |
| 805 | } |
| 806 | |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 807 | ctl->ops.get_bitmask_intf(ctl, &flush_mask, intf->idx); |
Chirag Khurana | ed859f5 | 2019-11-20 18:18:12 +0530 | [diff] [blame] | 808 | if (ctl->ops.get_bitmask_cdm && hw_cdm) |
| 809 | ctl->ops.get_bitmask_cdm(ctl, &flush_mask, hw_cdm->idx); |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 810 | ctl->ops.update_pending_flush(ctl, flush_mask); |
Lloyd Atkinson | 09fed91 | 2016-06-24 18:14:13 -0400 | [diff] [blame] | 811 | |
Ingrid Gallardo | 821985b | 2017-05-31 16:50:52 -0700 | [diff] [blame] | 812 | skip_flush: |
Clarence Ip | 19af136 | 2016-09-23 14:57:51 -0400 | [diff] [blame] | 813 | SDE_DEBUG_VIDENC(vid_enc, "update pending flush ctl %d flush_mask %x\n", |
| 814 | ctl->idx - CTL_0, flush_mask); |
Lloyd Atkinson | 11f3444 | 2016-08-11 11:19:52 -0400 | [diff] [blame] | 815 | |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 816 | /* ctl_flush & timing engine enable will be triggered by framework */ |
| 817 | if (phys_enc->enable_state == SDE_ENC_DISABLED) |
| 818 | phys_enc->enable_state = SDE_ENC_ENABLING; |
Dhaval Patel | 81e8788 | 2016-10-19 21:41:56 -0700 | [diff] [blame] | 819 | |
Dhaval Patel | 81e8788 | 2016-10-19 21:41:56 -0700 | [diff] [blame] | 820 | return; |
Lloyd Atkinson | 09fed91 | 2016-06-24 18:14:13 -0400 | [diff] [blame] | 821 | } |
| 822 | |
Lloyd Atkinson | 09fed91 | 2016-06-24 18:14:13 -0400 | [diff] [blame] | 823 | static void sde_encoder_phys_vid_destroy(struct sde_encoder_phys *phys_enc) |
| 824 | { |
Dhaval Patel | 7961352 | 2016-10-25 23:18:48 -0700 | [diff] [blame] | 825 | struct sde_encoder_phys_vid *vid_enc; |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 826 | |
Clarence Ip | 19af136 | 2016-09-23 14:57:51 -0400 | [diff] [blame] | 827 | if (!phys_enc) { |
| 828 | SDE_ERROR("invalid encoder\n"); |
| 829 | return; |
| 830 | } |
Dhaval Patel | 7961352 | 2016-10-25 23:18:48 -0700 | [diff] [blame] | 831 | |
| 832 | vid_enc = to_sde_encoder_phys_vid(phys_enc); |
Clarence Ip | 19af136 | 2016-09-23 14:57:51 -0400 | [diff] [blame] | 833 | SDE_DEBUG_VIDENC(vid_enc, "\n"); |
Lloyd Atkinson | 09fed91 | 2016-06-24 18:14:13 -0400 | [diff] [blame] | 834 | kfree(vid_enc); |
| 835 | } |
| 836 | |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 837 | static void sde_encoder_phys_vid_get_hw_resources( |
| 838 | struct sde_encoder_phys *phys_enc, |
Lloyd Atkinson | 11f3444 | 2016-08-11 11:19:52 -0400 | [diff] [blame] | 839 | struct sde_encoder_hw_resources *hw_res, |
| 840 | struct drm_connector_state *conn_state) |
Lloyd Atkinson | 09fed91 | 2016-06-24 18:14:13 -0400 | [diff] [blame] | 841 | { |
Dhaval Patel | 7961352 | 2016-10-25 23:18:48 -0700 | [diff] [blame] | 842 | struct sde_encoder_phys_vid *vid_enc; |
Narender Ankam | c7ce0b0 | 2020-03-16 17:40:34 +0530 | [diff] [blame] | 843 | struct sde_mdss_cfg *vid_catalog; |
Abhijit Kulkarni | 40e3816 | 2016-06-26 22:12:09 -0400 | [diff] [blame] | 844 | |
Dhaval Patel | 7961352 | 2016-10-25 23:18:48 -0700 | [diff] [blame] | 845 | if (!phys_enc || !hw_res) { |
Clarence Ip | 19af136 | 2016-09-23 14:57:51 -0400 | [diff] [blame] | 846 | SDE_ERROR("invalid arg(s), enc %d hw_res %d conn_state %d\n", |
Narender Ankam | c7ce0b0 | 2020-03-16 17:40:34 +0530 | [diff] [blame] | 847 | phys_enc != NULL, hw_res != NULL, conn_state != NULL); |
Clarence Ip | 19af136 | 2016-09-23 14:57:51 -0400 | [diff] [blame] | 848 | return; |
| 849 | } |
Dhaval Patel | 7961352 | 2016-10-25 23:18:48 -0700 | [diff] [blame] | 850 | |
Narender Ankam | c7ce0b0 | 2020-03-16 17:40:34 +0530 | [diff] [blame] | 851 | vid_catalog = phys_enc->sde_kms->catalog; |
Dhaval Patel | 7961352 | 2016-10-25 23:18:48 -0700 | [diff] [blame] | 852 | vid_enc = to_sde_encoder_phys_vid(phys_enc); |
Narender Ankam | c7ce0b0 | 2020-03-16 17:40:34 +0530 | [diff] [blame] | 853 | if (!vid_enc->hw_intf || !vid_catalog) { |
| 854 | SDE_ERROR("invalid arg(s), hw_intf %d vid_catalog %d\n", |
| 855 | vid_enc->hw_intf != NULL, vid_catalog != NULL); |
Dhaval Patel | 7961352 | 2016-10-25 23:18:48 -0700 | [diff] [blame] | 856 | return; |
| 857 | } |
| 858 | |
Clarence Ip | 19af136 | 2016-09-23 14:57:51 -0400 | [diff] [blame] | 859 | SDE_DEBUG_VIDENC(vid_enc, "\n"); |
Narender Ankam | c7ce0b0 | 2020-03-16 17:40:34 +0530 | [diff] [blame] | 860 | if (vid_enc->hw_intf->idx > INTF_MAX) { |
| 861 | SDE_ERROR("invalid arg(s), idx %d\n", |
| 862 | vid_enc->hw_intf->idx); |
| 863 | return; |
| 864 | } |
Lloyd Atkinson | 11f3444 | 2016-08-11 11:19:52 -0400 | [diff] [blame] | 865 | hw_res->intfs[vid_enc->hw_intf->idx - INTF_0] = INTF_MODE_VIDEO; |
Narender Ankam | c7ce0b0 | 2020-03-16 17:40:34 +0530 | [diff] [blame] | 866 | |
| 867 | if (vid_catalog->intf[vid_enc->hw_intf->idx - INTF_0].type |
| 868 | == INTF_DP) |
| 869 | hw_res->needs_cdm = true; |
Chirag Khurana | ed859f5 | 2019-11-20 18:18:12 +0530 | [diff] [blame] | 870 | SDE_DEBUG_DRIVER("[vid] needs_cdm=%d\n", hw_res->needs_cdm); |
Abhijit Kulkarni | 40e3816 | 2016-06-26 22:12:09 -0400 | [diff] [blame] | 871 | } |
| 872 | |
Lloyd Atkinson | f68a213 | 2017-07-17 10:16:30 -0400 | [diff] [blame] | 873 | static int _sde_encoder_phys_vid_wait_for_vblank( |
Alan Kwong | 628d19e | 2016-10-31 13:50:13 -0400 | [diff] [blame] | 874 | struct sde_encoder_phys *phys_enc, bool notify) |
Abhijit Kulkarni | 40e3816 | 2016-06-26 22:12:09 -0400 | [diff] [blame] | 875 | { |
Veera Sundaram Sankaran | 3677471 | 2017-06-26 14:33:33 -0700 | [diff] [blame] | 876 | struct sde_encoder_wait_info wait_info; |
Veera Sundaram Sankaran | 4bbd621 | 2017-10-17 17:47:32 -0700 | [diff] [blame] | 877 | int ret = 0; |
| 878 | u32 event = 0; |
Lloyd Atkinson | e5c2c0b | 2016-07-05 12:23:29 -0400 | [diff] [blame] | 879 | |
Veera Sundaram Sankaran | 3677471 | 2017-06-26 14:33:33 -0700 | [diff] [blame] | 880 | if (!phys_enc) { |
| 881 | pr_err("invalid encoder\n"); |
| 882 | return -EINVAL; |
| 883 | } |
| 884 | |
| 885 | wait_info.wq = &phys_enc->pending_kickoff_wq; |
| 886 | wait_info.atomic_cnt = &phys_enc->pending_kickoff_cnt; |
| 887 | wait_info.timeout_ms = KICKOFF_TIMEOUT_MS; |
| 888 | |
Alan Kwong | 628d19e | 2016-10-31 13:50:13 -0400 | [diff] [blame] | 889 | if (!sde_encoder_phys_vid_is_master(phys_enc)) { |
Ingrid Gallardo | 821985b | 2017-05-31 16:50:52 -0700 | [diff] [blame] | 890 | /* signal done for slave video encoder, unless it is pp-split */ |
Veera Sundaram Sankaran | 4bbd621 | 2017-10-17 17:47:32 -0700 | [diff] [blame] | 891 | if (!_sde_encoder_phys_is_ppsplit(phys_enc) && notify) { |
| 892 | event = SDE_ENCODER_FRAME_EVENT_DONE; |
| 893 | goto end; |
| 894 | } |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 895 | return 0; |
Alan Kwong | 628d19e | 2016-10-31 13:50:13 -0400 | [diff] [blame] | 896 | } |
Lloyd Atkinson | e5c2c0b | 2016-07-05 12:23:29 -0400 | [diff] [blame] | 897 | |
Lloyd Atkinson | 7d07094 | 2016-07-26 18:35:12 -0400 | [diff] [blame] | 898 | /* Wait for kickoff to complete */ |
Lloyd Atkinson | 05ef823 | 2017-03-08 16:35:36 -0500 | [diff] [blame] | 899 | ret = sde_encoder_helper_wait_for_irq(phys_enc, INTR_IDX_VSYNC, |
| 900 | &wait_info); |
Lloyd Atkinson | e5c2c0b | 2016-07-05 12:23:29 -0400 | [diff] [blame] | 901 | |
Veera Sundaram Sankaran | 4bbd621 | 2017-10-17 17:47:32 -0700 | [diff] [blame] | 902 | if (ret == -ETIMEDOUT) |
| 903 | event = SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE |
| 904 | | SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE |
| 905 | | SDE_ENCODER_FRAME_EVENT_ERROR; |
| 906 | else if (!ret && notify) |
| 907 | event = SDE_ENCODER_FRAME_EVENT_DONE; |
| 908 | |
| 909 | end: |
| 910 | SDE_EVT32(DRMID(phys_enc->parent), event, notify, ret, |
| 911 | ret ? SDE_EVTLOG_FATAL : 0); |
| 912 | if (phys_enc->parent_ops.handle_frame_done && event) |
Lloyd Atkinson | 05ef823 | 2017-03-08 16:35:36 -0500 | [diff] [blame] | 913 | phys_enc->parent_ops.handle_frame_done( |
| 914 | phys_enc->parent, phys_enc, |
Kalyan Thota | 9391e56 | 2018-04-11 17:26:26 +0530 | [diff] [blame] | 915 | event); |
Lloyd Atkinson | 05ef823 | 2017-03-08 16:35:36 -0500 | [diff] [blame] | 916 | return ret; |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 917 | } |
| 918 | |
Lloyd Atkinson | f68a213 | 2017-07-17 10:16:30 -0400 | [diff] [blame] | 919 | static int sde_encoder_phys_vid_wait_for_vblank( |
Alan Kwong | 628d19e | 2016-10-31 13:50:13 -0400 | [diff] [blame] | 920 | struct sde_encoder_phys *phys_enc) |
| 921 | { |
Lloyd Atkinson | f68a213 | 2017-07-17 10:16:30 -0400 | [diff] [blame] | 922 | return _sde_encoder_phys_vid_wait_for_vblank(phys_enc, true); |
Alan Kwong | 628d19e | 2016-10-31 13:50:13 -0400 | [diff] [blame] | 923 | } |
| 924 | |
Clarence Ip | 85f4f453 | 2017-10-04 12:10:13 -0400 | [diff] [blame] | 925 | static int sde_encoder_phys_vid_prepare_for_kickoff( |
Alan Kwong | 4aacd53 | 2017-02-04 18:51:33 -0800 | [diff] [blame] | 926 | struct sde_encoder_phys *phys_enc, |
| 927 | struct sde_encoder_kickoff_params *params) |
Lloyd Atkinson | 6cc9de3 | 2016-11-17 17:56:13 -0500 | [diff] [blame] | 928 | { |
| 929 | struct sde_encoder_phys_vid *vid_enc; |
| 930 | struct sde_hw_ctl *ctl; |
| 931 | int rc; |
| 932 | |
Clarence Ip | 85f4f453 | 2017-10-04 12:10:13 -0400 | [diff] [blame] | 933 | if (!phys_enc || !params || !phys_enc->hw_ctl) { |
Alan Kwong | 4aacd53 | 2017-02-04 18:51:33 -0800 | [diff] [blame] | 934 | SDE_ERROR("invalid encoder/parameters\n"); |
Clarence Ip | 85f4f453 | 2017-10-04 12:10:13 -0400 | [diff] [blame] | 935 | return -EINVAL; |
Lloyd Atkinson | 6cc9de3 | 2016-11-17 17:56:13 -0500 | [diff] [blame] | 936 | } |
| 937 | vid_enc = to_sde_encoder_phys_vid(phys_enc); |
| 938 | |
| 939 | ctl = phys_enc->hw_ctl; |
Clarence Ip | 85f4f453 | 2017-10-04 12:10:13 -0400 | [diff] [blame] | 940 | if (!ctl->ops.wait_reset_status) |
| 941 | return 0; |
Lloyd Atkinson | 6cc9de3 | 2016-11-17 17:56:13 -0500 | [diff] [blame] | 942 | |
| 943 | /* |
| 944 | * hw supports hardware initiated ctl reset, so before we kickoff a new |
| 945 | * frame, need to check and wait for hw initiated ctl reset completion |
| 946 | */ |
| 947 | rc = ctl->ops.wait_reset_status(ctl); |
| 948 | if (rc) { |
| 949 | SDE_ERROR_VIDENC(vid_enc, "ctl %d reset failure: %d\n", |
| 950 | ctl->idx, rc); |
Clarence Ip | 569d5af | 2017-10-14 21:09:01 -0400 | [diff] [blame] | 951 | |
| 952 | ++vid_enc->error_count; |
| 953 | if (vid_enc->error_count >= KICKOFF_MAX_ERRORS) { |
| 954 | vid_enc->error_count = KICKOFF_MAX_ERRORS; |
| 955 | |
Clarence Ip | 569d5af | 2017-10-14 21:09:01 -0400 | [diff] [blame] | 956 | SDE_DBG_DUMP("panic"); |
Clarence Ip | 569d5af | 2017-10-14 21:09:01 -0400 | [diff] [blame] | 957 | } else if (vid_enc->error_count == 1) { |
| 958 | SDE_EVT32(DRMID(phys_enc->parent), SDE_EVTLOG_FATAL); |
Clarence Ip | 569d5af | 2017-10-14 21:09:01 -0400 | [diff] [blame] | 959 | } |
| 960 | |
| 961 | /* request a ctl reset before the next flush */ |
| 962 | phys_enc->enable_state = SDE_ENC_ERR_NEEDS_HW_RESET; |
| 963 | } else { |
| 964 | vid_enc->error_count = 0; |
Lloyd Atkinson | 6cc9de3 | 2016-11-17 17:56:13 -0500 | [diff] [blame] | 965 | } |
Alan Kwong | 4aacd53 | 2017-02-04 18:51:33 -0800 | [diff] [blame] | 966 | |
Jayant Shekhar | 98e78a8 | 2018-01-12 17:50:55 +0530 | [diff] [blame] | 967 | programmable_rot_fetch_config(phys_enc, |
| 968 | params->inline_rotate_prefill, params->is_primary); |
Clarence Ip | 85f4f453 | 2017-10-04 12:10:13 -0400 | [diff] [blame] | 969 | |
| 970 | return rc; |
Lloyd Atkinson | 6cc9de3 | 2016-11-17 17:56:13 -0500 | [diff] [blame] | 971 | } |
| 972 | |
Lloyd Atkinson | 7d07094 | 2016-07-26 18:35:12 -0400 | [diff] [blame] | 973 | static void sde_encoder_phys_vid_disable(struct sde_encoder_phys *phys_enc) |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 974 | { |
Alan Kwong | 67a3f79 | 2016-11-01 23:16:53 -0400 | [diff] [blame] | 975 | struct msm_drm_private *priv; |
Lloyd Atkinson | 7d07094 | 2016-07-26 18:35:12 -0400 | [diff] [blame] | 976 | struct sde_encoder_phys_vid *vid_enc; |
| 977 | unsigned long lock_flags; |
| 978 | int ret; |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 979 | |
Alan Kwong | 67a3f79 | 2016-11-01 23:16:53 -0400 | [diff] [blame] | 980 | if (!phys_enc || !phys_enc->parent || !phys_enc->parent->dev || |
| 981 | !phys_enc->parent->dev->dev_private) { |
| 982 | SDE_ERROR("invalid encoder/device\n"); |
Lloyd Atkinson | 7d07094 | 2016-07-26 18:35:12 -0400 | [diff] [blame] | 983 | return; |
| 984 | } |
Alan Kwong | 67a3f79 | 2016-11-01 23:16:53 -0400 | [diff] [blame] | 985 | priv = phys_enc->parent->dev->dev_private; |
Lloyd Atkinson | 7d07094 | 2016-07-26 18:35:12 -0400 | [diff] [blame] | 986 | |
| 987 | vid_enc = to_sde_encoder_phys_vid(phys_enc); |
| 988 | if (!vid_enc->hw_intf || !phys_enc->hw_ctl) { |
| 989 | SDE_ERROR("invalid hw_intf %d hw_ctl %d\n", |
| 990 | vid_enc->hw_intf != 0, phys_enc->hw_ctl != 0); |
| 991 | return; |
| 992 | } |
| 993 | |
| 994 | SDE_DEBUG_VIDENC(vid_enc, "\n"); |
| 995 | |
| 996 | if (WARN_ON(!vid_enc->hw_intf->ops.enable_timing)) |
| 997 | return; |
| 998 | |
| 999 | if (phys_enc->enable_state == SDE_ENC_DISABLED) { |
| 1000 | SDE_ERROR("already disabled\n"); |
| 1001 | return; |
| 1002 | } |
| 1003 | |
| 1004 | spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags); |
| 1005 | vid_enc->hw_intf->ops.enable_timing(vid_enc->hw_intf, 0); |
| 1006 | if (sde_encoder_phys_vid_is_master(phys_enc)) |
| 1007 | sde_encoder_phys_inc_pending(phys_enc); |
| 1008 | spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags); |
| 1009 | |
Clarence Ip | ed3327b | 2017-11-01 13:13:58 -0400 | [diff] [blame] | 1010 | if (!sde_encoder_phys_vid_is_master(phys_enc)) |
| 1011 | goto exit; |
| 1012 | |
Lloyd Atkinson | 7d07094 | 2016-07-26 18:35:12 -0400 | [diff] [blame] | 1013 | /* |
| 1014 | * Wait for a vsync so we know the ENABLE=0 latched before |
| 1015 | * the (connector) source of the vsync's gets disabled, |
| 1016 | * otherwise we end up in a funny state if we re-enable |
| 1017 | * before the disable latches, which results that some of |
| 1018 | * the settings changes for the new modeset (like new |
| 1019 | * scanout buffer) don't latch properly.. |
| 1020 | */ |
Clarence Ip | ed3327b | 2017-11-01 13:13:58 -0400 | [diff] [blame] | 1021 | ret = sde_encoder_phys_vid_control_vblank_irq(phys_enc, true); |
| 1022 | if (ret) { |
| 1023 | SDE_ERROR_VIDENC(vid_enc, |
| 1024 | "failed to enable vblank irq: %d\n", |
| 1025 | ret); |
| 1026 | SDE_EVT32(DRMID(phys_enc->parent), |
| 1027 | vid_enc->hw_intf->idx - INTF_0, ret, |
| 1028 | SDE_EVTLOG_FUNC_CASE1, |
| 1029 | SDE_EVTLOG_ERROR); |
| 1030 | } else { |
Lloyd Atkinson | f68a213 | 2017-07-17 10:16:30 -0400 | [diff] [blame] | 1031 | ret = _sde_encoder_phys_vid_wait_for_vblank(phys_enc, false); |
Lloyd Atkinson | 7d07094 | 2016-07-26 18:35:12 -0400 | [diff] [blame] | 1032 | if (ret) { |
| 1033 | atomic_set(&phys_enc->pending_kickoff_cnt, 0); |
| 1034 | SDE_ERROR_VIDENC(vid_enc, |
| 1035 | "failure waiting for disable: %d\n", |
| 1036 | ret); |
| 1037 | SDE_EVT32(DRMID(phys_enc->parent), |
Clarence Ip | ed3327b | 2017-11-01 13:13:58 -0400 | [diff] [blame] | 1038 | vid_enc->hw_intf->idx - INTF_0, ret, |
| 1039 | SDE_EVTLOG_FUNC_CASE2, |
| 1040 | SDE_EVTLOG_ERROR); |
Lloyd Atkinson | 7d07094 | 2016-07-26 18:35:12 -0400 | [diff] [blame] | 1041 | } |
Clarence Ip | ed3327b | 2017-11-01 13:13:58 -0400 | [diff] [blame] | 1042 | sde_encoder_phys_vid_control_vblank_irq(phys_enc, false); |
Lloyd Atkinson | 7d07094 | 2016-07-26 18:35:12 -0400 | [diff] [blame] | 1043 | } |
Chirag Khurana | ed859f5 | 2019-11-20 18:18:12 +0530 | [diff] [blame] | 1044 | |
| 1045 | if (phys_enc->hw_cdm && phys_enc->hw_cdm->ops.disable) { |
| 1046 | SDE_DEBUG_DRIVER("[cdm_disable]\n"); |
| 1047 | phys_enc->hw_cdm->ops.disable(phys_enc->hw_cdm); |
| 1048 | } |
Clarence Ip | ed3327b | 2017-11-01 13:13:58 -0400 | [diff] [blame] | 1049 | exit: |
Kalyan Thota | 6a9f3b7 | 2018-01-18 18:00:02 +0530 | [diff] [blame] | 1050 | phys_enc->vfp_cached = 0; |
Lloyd Atkinson | 7d07094 | 2016-07-26 18:35:12 -0400 | [diff] [blame] | 1051 | phys_enc->enable_state = SDE_ENC_DISABLED; |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 1052 | } |
| 1053 | |
| 1054 | static void sde_encoder_phys_vid_handle_post_kickoff( |
| 1055 | struct sde_encoder_phys *phys_enc) |
| 1056 | { |
| 1057 | unsigned long lock_flags; |
Dhaval Patel | 7961352 | 2016-10-25 23:18:48 -0700 | [diff] [blame] | 1058 | struct sde_encoder_phys_vid *vid_enc; |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 1059 | |
Clarence Ip | 19af136 | 2016-09-23 14:57:51 -0400 | [diff] [blame] | 1060 | if (!phys_enc) { |
| 1061 | SDE_ERROR("invalid encoder\n"); |
| 1062 | return; |
| 1063 | } |
Dhaval Patel | 7961352 | 2016-10-25 23:18:48 -0700 | [diff] [blame] | 1064 | |
| 1065 | vid_enc = to_sde_encoder_phys_vid(phys_enc); |
Clarence Ip | 19af136 | 2016-09-23 14:57:51 -0400 | [diff] [blame] | 1066 | SDE_DEBUG_VIDENC(vid_enc, "enable_state %d\n", phys_enc->enable_state); |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 1067 | |
| 1068 | /* |
| 1069 | * Video mode must flush CTL before enabling timing engine |
| 1070 | * Video encoders need to turn on their interfaces now |
| 1071 | */ |
| 1072 | if (phys_enc->enable_state == SDE_ENC_ENABLING) { |
Lloyd Atkinson | 7d07094 | 2016-07-26 18:35:12 -0400 | [diff] [blame] | 1073 | SDE_EVT32(DRMID(phys_enc->parent), |
| 1074 | vid_enc->hw_intf->idx - INTF_0); |
| 1075 | spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags); |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 1076 | vid_enc->hw_intf->ops.enable_timing(vid_enc->hw_intf, 1); |
Lloyd Atkinson | 7d07094 | 2016-07-26 18:35:12 -0400 | [diff] [blame] | 1077 | spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags); |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 1078 | phys_enc->enable_state = SDE_ENC_ENABLED; |
| 1079 | } |
Abhijit Kulkarni | 40e3816 | 2016-06-26 22:12:09 -0400 | [diff] [blame] | 1080 | } |
| 1081 | |
Dhaval Patel | e17e0ee | 2017-08-23 18:01:42 -0700 | [diff] [blame] | 1082 | static void sde_encoder_phys_vid_irq_control(struct sde_encoder_phys *phys_enc, |
| 1083 | bool enable) |
| 1084 | { |
| 1085 | struct sde_encoder_phys_vid *vid_enc; |
| 1086 | int ret; |
| 1087 | |
| 1088 | if (!phys_enc) |
| 1089 | return; |
| 1090 | |
| 1091 | vid_enc = to_sde_encoder_phys_vid(phys_enc); |
| 1092 | |
| 1093 | SDE_EVT32(DRMID(phys_enc->parent), vid_enc->hw_intf->idx - INTF_0, |
| 1094 | enable, atomic_read(&phys_enc->vblank_refcount)); |
| 1095 | |
| 1096 | if (enable) { |
| 1097 | ret = sde_encoder_phys_vid_control_vblank_irq(phys_enc, true); |
| 1098 | if (ret) |
| 1099 | return; |
| 1100 | |
| 1101 | sde_encoder_helper_register_irq(phys_enc, INTR_IDX_UNDERRUN); |
| 1102 | } else { |
| 1103 | sde_encoder_phys_vid_control_vblank_irq(phys_enc, false); |
| 1104 | sde_encoder_helper_unregister_irq(phys_enc, INTR_IDX_UNDERRUN); |
| 1105 | } |
| 1106 | } |
| 1107 | |
Jayant Shekhar | 1d50ed2 | 2016-11-04 18:41:12 +0530 | [diff] [blame] | 1108 | static void sde_encoder_phys_vid_setup_misr(struct sde_encoder_phys *phys_enc, |
Dhaval Patel | f9245d6 | 2017-03-28 16:24:00 -0700 | [diff] [blame] | 1109 | bool enable, u32 frame_count) |
Jayant Shekhar | 1d50ed2 | 2016-11-04 18:41:12 +0530 | [diff] [blame] | 1110 | { |
Dhaval Patel | f9245d6 | 2017-03-28 16:24:00 -0700 | [diff] [blame] | 1111 | struct sde_encoder_phys_vid *vid_enc; |
Jayant Shekhar | 1d50ed2 | 2016-11-04 18:41:12 +0530 | [diff] [blame] | 1112 | |
Dhaval Patel | f9245d6 | 2017-03-28 16:24:00 -0700 | [diff] [blame] | 1113 | if (!phys_enc) |
| 1114 | return; |
| 1115 | vid_enc = to_sde_encoder_phys_vid(phys_enc); |
| 1116 | |
| 1117 | if (vid_enc->hw_intf && vid_enc->hw_intf->ops.setup_misr) |
| 1118 | vid_enc->hw_intf->ops.setup_misr(vid_enc->hw_intf, |
| 1119 | enable, frame_count); |
Jayant Shekhar | 1d50ed2 | 2016-11-04 18:41:12 +0530 | [diff] [blame] | 1120 | } |
| 1121 | |
Dhaval Patel | f9245d6 | 2017-03-28 16:24:00 -0700 | [diff] [blame] | 1122 | static u32 sde_encoder_phys_vid_collect_misr(struct sde_encoder_phys *phys_enc) |
Jayant Shekhar | 1d50ed2 | 2016-11-04 18:41:12 +0530 | [diff] [blame] | 1123 | { |
Dhaval Patel | f9245d6 | 2017-03-28 16:24:00 -0700 | [diff] [blame] | 1124 | struct sde_encoder_phys_vid *vid_enc; |
Jayant Shekhar | 1d50ed2 | 2016-11-04 18:41:12 +0530 | [diff] [blame] | 1125 | |
Dhaval Patel | f9245d6 | 2017-03-28 16:24:00 -0700 | [diff] [blame] | 1126 | if (!phys_enc) |
| 1127 | return 0; |
| 1128 | vid_enc = to_sde_encoder_phys_vid(phys_enc); |
| 1129 | |
| 1130 | return vid_enc->hw_intf && vid_enc->hw_intf->ops.collect_misr ? |
| 1131 | vid_enc->hw_intf->ops.collect_misr(vid_enc->hw_intf) : 0; |
Jayant Shekhar | 1d50ed2 | 2016-11-04 18:41:12 +0530 | [diff] [blame] | 1132 | } |
| 1133 | |
Benjamin Chan | 9cd866d | 2017-08-15 14:56:34 -0400 | [diff] [blame] | 1134 | static int sde_encoder_phys_vid_get_line_count( |
| 1135 | struct sde_encoder_phys *phys_enc) |
| 1136 | { |
| 1137 | struct sde_encoder_phys_vid *vid_enc; |
| 1138 | |
| 1139 | if (!phys_enc) |
| 1140 | return -EINVAL; |
| 1141 | |
| 1142 | if (!sde_encoder_phys_vid_is_master(phys_enc)) |
| 1143 | return -EINVAL; |
| 1144 | |
| 1145 | vid_enc = to_sde_encoder_phys_vid(phys_enc); |
| 1146 | if (!vid_enc->hw_intf || !vid_enc->hw_intf->ops.get_line_count) |
| 1147 | return -EINVAL; |
| 1148 | |
| 1149 | return vid_enc->hw_intf->ops.get_line_count(vid_enc->hw_intf); |
| 1150 | } |
| 1151 | |
Sandeep Panda | 11b20d8 | 2017-06-19 12:57:27 +0530 | [diff] [blame] | 1152 | static int sde_encoder_phys_vid_wait_for_active( |
| 1153 | struct sde_encoder_phys *phys_enc) |
| 1154 | { |
| 1155 | struct drm_display_mode mode; |
| 1156 | struct sde_encoder_phys_vid *vid_enc; |
| 1157 | u32 ln_cnt, min_ln_cnt, active_lns_cnt; |
| 1158 | u32 clk_period, time_of_line; |
| 1159 | u32 delay, retry = MAX_POLL_CNT; |
| 1160 | |
| 1161 | vid_enc = to_sde_encoder_phys_vid(phys_enc); |
| 1162 | |
| 1163 | if (!vid_enc->hw_intf || !vid_enc->hw_intf->ops.get_line_count) { |
| 1164 | SDE_ERROR_VIDENC(vid_enc, "invalid vid_enc params\n"); |
| 1165 | return -EINVAL; |
| 1166 | } |
| 1167 | |
| 1168 | mode = phys_enc->cached_mode; |
| 1169 | |
| 1170 | /* |
| 1171 | * calculate clk_period as pico second to maintain good |
| 1172 | * accuracy with high pclk rate and this number is in 17 bit |
| 1173 | * range. |
| 1174 | */ |
| 1175 | clk_period = DIV_ROUND_UP_ULL(1000000000, mode.clock); |
| 1176 | if (!clk_period) { |
| 1177 | SDE_ERROR_VIDENC(vid_enc, "Unable to calculate clock period\n"); |
| 1178 | return -EINVAL; |
| 1179 | } |
| 1180 | |
| 1181 | min_ln_cnt = (mode.vtotal - mode.vsync_start) + |
| 1182 | (mode.vsync_end - mode.vsync_start); |
| 1183 | active_lns_cnt = mode.vdisplay; |
| 1184 | time_of_line = mode.htotal * clk_period; |
| 1185 | |
| 1186 | /* delay in micro seconds */ |
| 1187 | delay = (time_of_line * (min_ln_cnt + |
| 1188 | (mode.vsync_start - mode.vdisplay))) / 1000000; |
| 1189 | |
| 1190 | /* |
| 1191 | * Wait for max delay before |
| 1192 | * polling to check active region |
| 1193 | */ |
| 1194 | if (delay > POLL_TIME_USEC_FOR_LN_CNT) |
| 1195 | delay = POLL_TIME_USEC_FOR_LN_CNT; |
| 1196 | |
| 1197 | while (retry) { |
| 1198 | ln_cnt = vid_enc->hw_intf->ops.get_line_count(vid_enc->hw_intf); |
| 1199 | |
| 1200 | if ((ln_cnt >= min_ln_cnt) && |
| 1201 | (ln_cnt < (active_lns_cnt + min_ln_cnt))) { |
| 1202 | SDE_DEBUG_VIDENC(vid_enc, |
| 1203 | "Needed lines left line_cnt=%d\n", |
| 1204 | ln_cnt); |
| 1205 | return 0; |
| 1206 | } |
| 1207 | |
| 1208 | SDE_ERROR_VIDENC(vid_enc, "line count is less. line_cnt = %d\n", |
| 1209 | ln_cnt); |
| 1210 | /* Add delay so that line count is in active region */ |
| 1211 | udelay(delay); |
| 1212 | retry--; |
| 1213 | } |
| 1214 | |
| 1215 | return -EINVAL; |
| 1216 | } |
| 1217 | |
Lloyd Atkinson | e5c2c0b | 2016-07-05 12:23:29 -0400 | [diff] [blame] | 1218 | static void sde_encoder_phys_vid_init_ops(struct sde_encoder_phys_ops *ops) |
Abhijit Kulkarni | 40e3816 | 2016-06-26 22:12:09 -0400 | [diff] [blame] | 1219 | { |
Lloyd Atkinson | e5c2c0b | 2016-07-05 12:23:29 -0400 | [diff] [blame] | 1220 | ops->is_master = sde_encoder_phys_vid_is_master; |
Lloyd Atkinson | 09fed91 | 2016-06-24 18:14:13 -0400 | [diff] [blame] | 1221 | ops->mode_set = sde_encoder_phys_vid_mode_set; |
Chandan Uddaraju | 3f2cf42 | 2017-06-15 15:37:39 -0700 | [diff] [blame] | 1222 | ops->cont_splash_mode_set = sde_encoder_phys_vid_cont_splash_mode_set; |
Lloyd Atkinson | 09fed91 | 2016-06-24 18:14:13 -0400 | [diff] [blame] | 1223 | ops->mode_fixup = sde_encoder_phys_vid_mode_fixup; |
| 1224 | ops->enable = sde_encoder_phys_vid_enable; |
| 1225 | ops->disable = sde_encoder_phys_vid_disable; |
| 1226 | ops->destroy = sde_encoder_phys_vid_destroy; |
| 1227 | ops->get_hw_resources = sde_encoder_phys_vid_get_hw_resources; |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 1228 | ops->control_vblank_irq = sde_encoder_phys_vid_control_vblank_irq; |
Lloyd Atkinson | f68a213 | 2017-07-17 10:16:30 -0400 | [diff] [blame] | 1229 | ops->wait_for_commit_done = sde_encoder_phys_vid_wait_for_vblank; |
| 1230 | ops->wait_for_vblank = sde_encoder_phys_vid_wait_for_vblank; |
| 1231 | ops->wait_for_tx_complete = sde_encoder_phys_vid_wait_for_vblank; |
Dhaval Patel | e17e0ee | 2017-08-23 18:01:42 -0700 | [diff] [blame] | 1232 | ops->irq_control = sde_encoder_phys_vid_irq_control; |
Lloyd Atkinson | 6cc9de3 | 2016-11-17 17:56:13 -0500 | [diff] [blame] | 1233 | ops->prepare_for_kickoff = sde_encoder_phys_vid_prepare_for_kickoff; |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 1234 | ops->handle_post_kickoff = sde_encoder_phys_vid_handle_post_kickoff; |
Clarence Ip | 8e69ad0 | 2016-12-09 09:43:57 -0500 | [diff] [blame] | 1235 | ops->needs_single_flush = sde_encoder_phys_vid_needs_single_flush; |
Jayant Shekhar | 1d50ed2 | 2016-11-04 18:41:12 +0530 | [diff] [blame] | 1236 | ops->setup_misr = sde_encoder_phys_vid_setup_misr; |
| 1237 | ops->collect_misr = sde_encoder_phys_vid_collect_misr; |
Alan Kwong | 4212dd4 | 2017-09-19 17:22:33 -0400 | [diff] [blame] | 1238 | ops->trigger_flush = sde_encoder_helper_trigger_flush; |
Lloyd Atkinson | 8c49c58 | 2016-11-18 14:23:54 -0500 | [diff] [blame] | 1239 | ops->hw_reset = sde_encoder_helper_hw_reset; |
Benjamin Chan | 9cd866d | 2017-08-15 14:56:34 -0400 | [diff] [blame] | 1240 | ops->get_line_count = sde_encoder_phys_vid_get_line_count; |
Clarence Ip | 5e3df1d | 2017-11-07 21:28:25 -0500 | [diff] [blame] | 1241 | ops->get_wr_line_count = sde_encoder_phys_vid_get_line_count; |
Ingrid Gallardo | 61210ea | 2017-10-17 17:29:31 -0700 | [diff] [blame] | 1242 | ops->wait_dma_trigger = sde_encoder_phys_vid_wait_dma_trigger; |
Sandeep Panda | 11b20d8 | 2017-06-19 12:57:27 +0530 | [diff] [blame] | 1243 | ops->wait_for_active = sde_encoder_phys_vid_wait_for_active; |
Lloyd Atkinson | 09fed91 | 2016-06-24 18:14:13 -0400 | [diff] [blame] | 1244 | } |
| 1245 | |
Lloyd Atkinson | f30546e | 2016-06-26 10:08:25 -0400 | [diff] [blame] | 1246 | struct sde_encoder_phys *sde_encoder_phys_vid_init( |
Lloyd Atkinson | 6ef6cb5 | 2016-07-06 11:49:18 -0400 | [diff] [blame] | 1247 | struct sde_enc_phys_init_params *p) |
Lloyd Atkinson | 09fed91 | 2016-06-24 18:14:13 -0400 | [diff] [blame] | 1248 | { |
| 1249 | struct sde_encoder_phys *phys_enc = NULL; |
| 1250 | struct sde_encoder_phys_vid *vid_enc = NULL; |
Lloyd Atkinson | 11f3444 | 2016-08-11 11:19:52 -0400 | [diff] [blame] | 1251 | struct sde_rm_hw_iter iter; |
| 1252 | struct sde_hw_mdp *hw_mdp; |
Lloyd Atkinson | 05ef823 | 2017-03-08 16:35:36 -0500 | [diff] [blame] | 1253 | struct sde_encoder_irq *irq; |
Alan Kwong | a172ef5 | 2016-09-27 00:29:10 -0400 | [diff] [blame] | 1254 | int i, ret = 0; |
Lloyd Atkinson | 09fed91 | 2016-06-24 18:14:13 -0400 | [diff] [blame] | 1255 | |
Clarence Ip | 19af136 | 2016-09-23 14:57:51 -0400 | [diff] [blame] | 1256 | if (!p) { |
| 1257 | ret = -EINVAL; |
| 1258 | goto fail; |
| 1259 | } |
Lloyd Atkinson | 09fed91 | 2016-06-24 18:14:13 -0400 | [diff] [blame] | 1260 | |
| 1261 | vid_enc = kzalloc(sizeof(*vid_enc), GFP_KERNEL); |
| 1262 | if (!vid_enc) { |
| 1263 | ret = -ENOMEM; |
| 1264 | goto fail; |
| 1265 | } |
Ben Chan | 78647cd | 2016-06-26 22:02:47 -0400 | [diff] [blame] | 1266 | |
Lloyd Atkinson | 09fed91 | 2016-06-24 18:14:13 -0400 | [diff] [blame] | 1267 | phys_enc = &vid_enc->base; |
| 1268 | |
Lloyd Atkinson | 11f3444 | 2016-08-11 11:19:52 -0400 | [diff] [blame] | 1269 | hw_mdp = sde_rm_get_mdp(&p->sde_kms->rm); |
| 1270 | if (IS_ERR_OR_NULL(hw_mdp)) { |
| 1271 | ret = PTR_ERR(hw_mdp); |
| 1272 | SDE_ERROR("failed to get mdptop\n"); |
Lloyd Atkinson | e5c2c0b | 2016-07-05 12:23:29 -0400 | [diff] [blame] | 1273 | goto fail; |
| 1274 | } |
Lloyd Atkinson | 11f3444 | 2016-08-11 11:19:52 -0400 | [diff] [blame] | 1275 | phys_enc->hw_mdptop = hw_mdp; |
Dhaval Patel | 81e8788 | 2016-10-19 21:41:56 -0700 | [diff] [blame] | 1276 | phys_enc->intf_idx = p->intf_idx; |
Lloyd Atkinson | e5c2c0b | 2016-07-05 12:23:29 -0400 | [diff] [blame] | 1277 | |
Lloyd Atkinson | 11f3444 | 2016-08-11 11:19:52 -0400 | [diff] [blame] | 1278 | /** |
| 1279 | * hw_intf resource permanently assigned to this encoder |
| 1280 | * Other resources allocated at atomic commit time by use case |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 1281 | */ |
Lloyd Atkinson | 11f3444 | 2016-08-11 11:19:52 -0400 | [diff] [blame] | 1282 | sde_rm_init_hw_iter(&iter, 0, SDE_HW_BLK_INTF); |
| 1283 | while (sde_rm_get_hw(&p->sde_kms->rm, &iter)) { |
| 1284 | struct sde_hw_intf *hw_intf = (struct sde_hw_intf *)iter.hw; |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 1285 | |
Lloyd Atkinson | 11f3444 | 2016-08-11 11:19:52 -0400 | [diff] [blame] | 1286 | if (hw_intf->idx == p->intf_idx) { |
| 1287 | vid_enc->hw_intf = hw_intf; |
| 1288 | break; |
| 1289 | } |
| 1290 | } |
| 1291 | |
| 1292 | if (!vid_enc->hw_intf) { |
| 1293 | ret = -EINVAL; |
Clarence Ip | 19af136 | 2016-09-23 14:57:51 -0400 | [diff] [blame] | 1294 | SDE_ERROR("failed to get hw_intf\n"); |
Lloyd Atkinson | 09fed91 | 2016-06-24 18:14:13 -0400 | [diff] [blame] | 1295 | goto fail; |
| 1296 | } |
| 1297 | |
Clarence Ip | 19af136 | 2016-09-23 14:57:51 -0400 | [diff] [blame] | 1298 | SDE_DEBUG_VIDENC(vid_enc, "\n"); |
| 1299 | |
Lloyd Atkinson | e5c2c0b | 2016-07-05 12:23:29 -0400 | [diff] [blame] | 1300 | sde_encoder_phys_vid_init_ops(&phys_enc->ops); |
Lloyd Atkinson | 6ef6cb5 | 2016-07-06 11:49:18 -0400 | [diff] [blame] | 1301 | phys_enc->parent = p->parent; |
| 1302 | phys_enc->parent_ops = p->parent_ops; |
| 1303 | phys_enc->sde_kms = p->sde_kms; |
| 1304 | phys_enc->split_role = p->split_role; |
Clarence Ip | 0352198 | 2016-08-26 10:49:47 -0400 | [diff] [blame] | 1305 | phys_enc->intf_mode = INTF_MODE_VIDEO; |
Lloyd Atkinson | 7d07094 | 2016-07-26 18:35:12 -0400 | [diff] [blame] | 1306 | phys_enc->enc_spinlock = p->enc_spinlock; |
Raviteja Tamatam | 3ea60b8 | 2018-04-27 15:41:18 +0530 | [diff] [blame] | 1307 | phys_enc->vblank_ctl_lock = p->vblank_ctl_lock; |
Jeykumar Sankaran | 5c2f070 | 2017-03-09 18:03:15 -0800 | [diff] [blame] | 1308 | phys_enc->comp_type = p->comp_type; |
Lloyd Atkinson | 05ef823 | 2017-03-08 16:35:36 -0500 | [diff] [blame] | 1309 | for (i = 0; i < INTR_IDX_MAX; i++) { |
| 1310 | irq = &phys_enc->irq[i]; |
| 1311 | INIT_LIST_HEAD(&irq->cb.list); |
| 1312 | irq->irq_idx = -EINVAL; |
| 1313 | irq->hw_idx = -EINVAL; |
| 1314 | irq->cb.arg = phys_enc; |
| 1315 | } |
| 1316 | |
| 1317 | irq = &phys_enc->irq[INTR_IDX_VSYNC]; |
| 1318 | irq->name = "vsync_irq"; |
| 1319 | irq->intr_type = SDE_IRQ_TYPE_INTF_VSYNC; |
| 1320 | irq->intr_idx = INTR_IDX_VSYNC; |
| 1321 | irq->cb.func = sde_encoder_phys_vid_vblank_irq; |
| 1322 | |
| 1323 | irq = &phys_enc->irq[INTR_IDX_UNDERRUN]; |
| 1324 | irq->name = "underrun"; |
| 1325 | irq->intr_type = SDE_IRQ_TYPE_INTF_UNDER_RUN; |
| 1326 | irq->intr_idx = INTR_IDX_UNDERRUN; |
| 1327 | irq->cb.func = sde_encoder_phys_vid_underrun_irq; |
| 1328 | |
Alan Kwong | baa5635 | 2016-10-04 09:38:11 -0400 | [diff] [blame] | 1329 | atomic_set(&phys_enc->vblank_refcount, 0); |
Lloyd Atkinson | 7d07094 | 2016-07-26 18:35:12 -0400 | [diff] [blame] | 1330 | atomic_set(&phys_enc->pending_kickoff_cnt, 0); |
Veera Sundaram Sankaran | 675ff62 | 2017-06-21 21:44:46 -0700 | [diff] [blame] | 1331 | atomic_set(&phys_enc->pending_retire_fence_cnt, 0); |
Lloyd Atkinson | 7d07094 | 2016-07-26 18:35:12 -0400 | [diff] [blame] | 1332 | init_waitqueue_head(&phys_enc->pending_kickoff_wq); |
Lloyd Atkinson | 5d72278 | 2016-05-30 14:09:41 -0400 | [diff] [blame] | 1333 | phys_enc->enable_state = SDE_ENC_DISABLED; |
| 1334 | |
Dhaval Patel | 81e8788 | 2016-10-19 21:41:56 -0700 | [diff] [blame] | 1335 | SDE_DEBUG_VIDENC(vid_enc, "created intf idx:%d\n", p->intf_idx); |
Lloyd Atkinson | 09fed91 | 2016-06-24 18:14:13 -0400 | [diff] [blame] | 1336 | |
| 1337 | return phys_enc; |
| 1338 | |
| 1339 | fail: |
Clarence Ip | 19af136 | 2016-09-23 14:57:51 -0400 | [diff] [blame] | 1340 | SDE_ERROR("failed to create encoder\n"); |
Lloyd Atkinson | 09fed91 | 2016-06-24 18:14:13 -0400 | [diff] [blame] | 1341 | if (vid_enc) |
| 1342 | sde_encoder_phys_vid_destroy(phys_enc); |
| 1343 | |
| 1344 | return ERR_PTR(ret); |
| 1345 | } |