Benjamin Chan | 99eb63b | 2016-12-21 15:45:26 -0500 | [diff] [blame^] | 1 | /* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. |
Alan Kwong | 9487de2 | 2016-01-16 22:06:36 -0500 | [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. |
| 11 | * |
| 12 | */ |
| 13 | |
| 14 | #ifndef _SDE_ROTATOR_R3_INTERNAL_H |
| 15 | #define _SDE_ROTATOR_R3_INTERNAL_H |
| 16 | |
| 17 | #include "sde_rotator_core.h" |
| 18 | |
| 19 | struct sde_hw_rotator; |
| 20 | struct sde_hw_rotator_context; |
| 21 | |
| 22 | /** |
| 23 | * Flags |
| 24 | */ |
| 25 | #define SDE_ROT_FLAG_SECURE_OVERLAY_SESSION 0x1 |
| 26 | #define SDE_ROT_FLAG_FLIP_LR 0x2 |
| 27 | #define SDE_ROT_FLAG_FLIP_UD 0x4 |
| 28 | #define SDE_ROT_FLAG_SOURCE_ROTATED_90 0x8 |
| 29 | #define SDE_ROT_FLAG_ROT_90 0x10 |
| 30 | #define SDE_ROT_FLAG_DEINTERLACE 0x20 |
Abhijit Kulkarni | 298c823 | 2016-09-26 22:32:10 -0700 | [diff] [blame] | 31 | #define SDE_ROT_FLAG_SECURE_CAMERA_SESSION 0x40 |
Alan Kwong | 9487de2 | 2016-01-16 22:06:36 -0500 | [diff] [blame] | 32 | |
| 33 | /** |
| 34 | * General defines |
| 35 | */ |
| 36 | #define SDE_HW_ROT_REGDMA_RAM_SIZE 1024 |
| 37 | #define SDE_HW_ROT_REGDMA_TOTAL_CTX 8 |
| 38 | #define SDE_HW_ROT_REGDMA_SEG_MASK (SDE_HW_ROT_REGDMA_TOTAL_CTX - 1) |
| 39 | #define SDE_HW_ROT_REGDMA_SEG_SIZE \ |
| 40 | (SDE_HW_ROT_REGDMA_RAM_SIZE / SDE_HW_ROT_REGDMA_TOTAL_CTX) |
| 41 | #define SDE_REGDMA_SWTS_MASK 0x00000FFF |
| 42 | #define SDE_REGDMA_SWTS_SHIFT 12 |
| 43 | |
| 44 | enum sde_rot_queue_prio { |
| 45 | ROT_QUEUE_HIGH_PRIORITY, |
| 46 | ROT_QUEUE_LOW_PRIORITY, |
| 47 | ROT_QUEUE_MAX |
| 48 | }; |
| 49 | |
| 50 | enum sde_rot_angle { |
| 51 | ROT_ANGLE_0, |
| 52 | ROT_ANGLE_90, |
| 53 | ROT_ANGEL_MAX |
| 54 | }; |
| 55 | |
| 56 | enum sde_rotator_regdma_mode { |
| 57 | ROT_REGDMA_OFF, |
| 58 | ROT_REGDMA_ON, |
| 59 | ROT_REGDMA_MAX |
| 60 | }; |
| 61 | |
| 62 | /** |
| 63 | * struct sde_hw_rot_sspp_cfg: Rotator SSPP Configration description |
| 64 | * @src: source surface information |
| 65 | * @src_rect: src ROI, caller takes into account the different operations |
| 66 | * such as decimation, flip etc to program this field |
| 67 | * @addr: source surface address |
| 68 | */ |
| 69 | struct sde_hw_rot_sspp_cfg { |
| 70 | struct sde_mdp_format_params *fmt; |
| 71 | struct sde_mdp_plane_sizes src_plane; |
| 72 | struct sde_rect *src_rect; |
| 73 | struct sde_mdp_data *data; |
| 74 | u32 img_width; |
| 75 | u32 img_height; |
Benjamin Chan | 99eb63b | 2016-12-21 15:45:26 -0500 | [diff] [blame^] | 76 | u32 fps; |
| 77 | u64 bw; |
Alan Kwong | 9487de2 | 2016-01-16 22:06:36 -0500 | [diff] [blame] | 78 | }; |
| 79 | |
| 80 | |
| 81 | |
| 82 | /** |
| 83 | * struct sde_hw_rot_wb_cfg: Rotator WB Configration description |
| 84 | * @dest: destination surface information |
| 85 | * @dest_rect: dest ROI, caller takes into account the different operations |
| 86 | * such as decimation, flip etc to program this field |
| 87 | * @addr: destination surface address |
| 88 | */ |
| 89 | struct sde_hw_rot_wb_cfg { |
| 90 | struct sde_mdp_format_params *fmt; |
| 91 | struct sde_mdp_plane_sizes dst_plane; |
| 92 | struct sde_rect *dst_rect; |
| 93 | struct sde_mdp_data *data; |
| 94 | u32 img_width; |
| 95 | u32 img_height; |
| 96 | u32 v_downscale_factor; |
| 97 | u32 h_downscale_factor; |
Benjamin Chan | 99eb63b | 2016-12-21 15:45:26 -0500 | [diff] [blame^] | 98 | u32 fps; |
| 99 | u64 bw; |
Alan Kwong | 9487de2 | 2016-01-16 22:06:36 -0500 | [diff] [blame] | 100 | }; |
| 101 | |
| 102 | |
| 103 | |
| 104 | /** |
| 105 | * |
| 106 | * struct sde_hw_rotator_ops: Interface to the Rotator Hw driver functions |
| 107 | * |
| 108 | * Pre-requsises: |
| 109 | * - Caller must call the init function to get the rotator context |
| 110 | * - These functions will be called after clocks are enabled |
| 111 | */ |
| 112 | struct sde_hw_rotator_ops { |
| 113 | /** |
| 114 | * setup_rotator_fetchengine(): |
| 115 | * Setup Source format |
| 116 | * Setup Source dimension/cropping rectangle (ROI) |
| 117 | * Setup Source surface base address and stride |
| 118 | * Setup fetch engine op mode (linear/tiled/compression/...) |
| 119 | * @ctx: Rotator context created in sde_hw_rotator_config |
| 120 | * @queue_id: Select either low / high priority queue |
| 121 | * @cfg: Rotator Fetch engine configuration parameters |
| 122 | * @danger_lut: Danger LUT setting |
| 123 | * @safe_lut: Safe LUT setting |
Benjamin Chan | fb6faa3 | 2016-08-16 17:21:01 -0400 | [diff] [blame] | 124 | * @dnsc_factor_w: Downscale factor for width |
| 125 | * @dnsc_factor_h: Downscale factor for height |
Alan Kwong | 9487de2 | 2016-01-16 22:06:36 -0500 | [diff] [blame] | 126 | * @flags: Specific config flag, see SDE_ROT_FLAG_ for details |
| 127 | */ |
| 128 | void (*setup_rotator_fetchengine)( |
| 129 | struct sde_hw_rotator_context *ctx, |
| 130 | enum sde_rot_queue_prio queue_id, |
| 131 | struct sde_hw_rot_sspp_cfg *cfg, |
| 132 | u32 danger_lut, |
| 133 | u32 safe_lut, |
Benjamin Chan | fb6faa3 | 2016-08-16 17:21:01 -0400 | [diff] [blame] | 134 | u32 dnsc_factor_w, |
| 135 | u32 dnsc_factor_h, |
Alan Kwong | 9487de2 | 2016-01-16 22:06:36 -0500 | [diff] [blame] | 136 | u32 flags); |
| 137 | |
| 138 | /** |
| 139 | * setup_rotator_wbengine(): |
| 140 | * Setup destination formats |
| 141 | * Setup destination dimension/cropping rectangle (ROI) |
| 142 | * Setup destination surface base address and strides |
| 143 | * Setup writeback engine op mode (linear/tiled/compression) |
| 144 | * @ctx: Rotator context created in sde_hw_rotator_config |
| 145 | * @queue_id: Select either low / high priority queue |
| 146 | * @cfg: Rotator WriteBack engine configuration parameters |
| 147 | * @flags: Specific config flag, see SDE_ROT_FLAG_ for details |
| 148 | */ |
| 149 | void (*setup_rotator_wbengine)( |
| 150 | struct sde_hw_rotator_context *ctx, |
| 151 | enum sde_rot_queue_prio queue_id, |
| 152 | struct sde_hw_rot_wb_cfg *cfg, |
| 153 | u32 flags); |
| 154 | |
| 155 | /** |
| 156 | * start_rotator(): |
| 157 | * Kick start rotator operation based on cached setup parameters |
| 158 | * REGDMA commands will get generated at this points |
| 159 | * @ctx: Rotator context |
| 160 | * @queue_id: Select either low / high priority queue |
| 161 | * Returns: unique job timestamp per submit. Used for tracking |
| 162 | * rotator finished job. |
| 163 | */ |
| 164 | u32 (*start_rotator)( |
| 165 | struct sde_hw_rotator_context *ctx, |
| 166 | enum sde_rot_queue_prio queue_id); |
| 167 | |
| 168 | /** |
| 169 | * wait_rotator_done(): |
| 170 | * Notify Rotator HAL layer previously submitted job finished. |
| 171 | * A job timestamp will return to caller. |
| 172 | * @ctx: Rotator context |
| 173 | * @flags: Reserved |
| 174 | * Returns: job timestamp for tracking purpose |
| 175 | * |
| 176 | */ |
| 177 | u32 (*wait_rotator_done)( |
| 178 | struct sde_hw_rotator_context *ctx, |
| 179 | enum sde_rot_queue_prio queue_id, |
| 180 | u32 flags); |
| 181 | }; |
| 182 | |
| 183 | /** |
| 184 | * struct sde_dbg_buf : Debug buffer used by debugfs |
| 185 | * @vaddr: VA address mapped from dma buffer |
| 186 | * @dmabuf: DMA buffer |
| 187 | * @buflen: Length of DMA buffer |
| 188 | * @width: pixel width of buffer |
| 189 | * @height: pixel height of buffer |
| 190 | */ |
| 191 | struct sde_dbg_buf { |
| 192 | void *vaddr; |
| 193 | struct dma_buf *dmabuf; |
| 194 | unsigned long buflen; |
| 195 | u32 width; |
| 196 | u32 height; |
| 197 | }; |
| 198 | |
| 199 | /** |
| 200 | * struct sde_hw_rotator_context : Each rotator context ties to each priority |
| 201 | * queue. Max number of concurrent contexts in regdma is limited to regdma |
| 202 | * ram segment size allocation. Each rotator context can be any priority. A |
| 203 | * incrementatl timestamp is used to identify and assigne to each context. |
| 204 | */ |
| 205 | struct sde_hw_rotator_context { |
| 206 | struct sde_hw_rotator *rot; |
| 207 | struct sde_rot_hw_resource *hwres; |
| 208 | enum sde_rot_queue_prio q_id; |
| 209 | u32 session_id; |
| 210 | u32 *regdma_base; |
| 211 | u32 *regdma_wrptr; |
| 212 | u32 timestamp; |
| 213 | struct completion rot_comp; |
Alan Kwong | 818b7fc | 2016-07-24 22:07:41 -0400 | [diff] [blame] | 214 | wait_queue_head_t regdma_waitq; |
Alan Kwong | 9487de2 | 2016-01-16 22:06:36 -0500 | [diff] [blame] | 215 | struct sde_dbg_buf src_dbgbuf; |
| 216 | struct sde_dbg_buf dst_dbgbuf; |
| 217 | u32 last_regdma_isr_status; |
| 218 | u32 last_regdma_timestamp; |
| 219 | dma_addr_t ts_addr; |
| 220 | bool is_secure; |
Benjamin Chan | 99eb63b | 2016-12-21 15:45:26 -0500 | [diff] [blame^] | 221 | bool is_traffic_shaping; |
Alan Kwong | 9487de2 | 2016-01-16 22:06:36 -0500 | [diff] [blame] | 222 | }; |
| 223 | |
| 224 | /** |
| 225 | * struct sde_hw_rotator_resource_info : Each rotator resource ties to each |
| 226 | * priority queue |
| 227 | */ |
| 228 | struct sde_hw_rotator_resource_info { |
| 229 | struct sde_hw_rotator *rot; |
| 230 | struct sde_rot_hw_resource hw; |
| 231 | }; |
| 232 | |
| 233 | /** |
| 234 | * struct sde_hw_rotator : Rotator description |
| 235 | * @hw: mdp register mapped offset |
| 236 | * @ops: pointer to operations possible for the rotator HW |
| 237 | */ |
| 238 | struct sde_hw_rotator { |
| 239 | /* base */ |
| 240 | char __iomem *mdss_base; |
| 241 | |
| 242 | /* Platform device from upper manager */ |
| 243 | struct platform_device *pdev; |
| 244 | |
| 245 | /* Ops */ |
| 246 | struct sde_hw_rotator_ops ops; |
| 247 | |
| 248 | /* Cmd Queue */ |
| 249 | u32 cmd_queue[SDE_HW_ROT_REGDMA_RAM_SIZE]; |
| 250 | |
| 251 | /* Cmd Queue Write Ptr */ |
| 252 | u32 *cmd_wr_ptr[ROT_QUEUE_MAX][SDE_HW_ROT_REGDMA_TOTAL_CTX]; |
| 253 | |
| 254 | /* Rotator Context */ |
| 255 | struct sde_hw_rotator_context |
| 256 | *rotCtx[ROT_QUEUE_MAX][SDE_HW_ROT_REGDMA_TOTAL_CTX]; |
| 257 | |
| 258 | /* Cmd timestamp sequence for different priority*/ |
| 259 | atomic_t timestamp[ROT_QUEUE_MAX]; |
| 260 | |
| 261 | /* regdma mode */ |
| 262 | enum sde_rotator_regdma_mode mode; |
| 263 | |
| 264 | /* logical interrupt number */ |
| 265 | int irq_num; |
Alan Kwong | 818b7fc | 2016-07-24 22:07:41 -0400 | [diff] [blame] | 266 | atomic_t irq_enabled; |
Alan Kwong | 9487de2 | 2016-01-16 22:06:36 -0500 | [diff] [blame] | 267 | |
| 268 | /* internal ION memory for SW timestamp */ |
| 269 | struct ion_client *iclient; |
| 270 | struct sde_mdp_img_data swts_buf; |
| 271 | void *swts_buffer; |
| 272 | |
| 273 | u32 highest_bank; |
Alan Kwong | 9487de2 | 2016-01-16 22:06:36 -0500 | [diff] [blame] | 274 | |
Alan Kwong | 9487de2 | 2016-01-16 22:06:36 -0500 | [diff] [blame] | 275 | spinlock_t rotctx_lock; |
| 276 | spinlock_t rotisr_lock; |
| 277 | |
| 278 | bool dbgmem; |
Benjamin Chan | 0f9e61d | 2016-09-16 16:01:09 -0400 | [diff] [blame] | 279 | bool reset_hw_ts; |
| 280 | u32 last_hw_ts; |
Alan Kwong | 9487de2 | 2016-01-16 22:06:36 -0500 | [diff] [blame] | 281 | }; |
| 282 | |
| 283 | /** |
| 284 | * sde_hw_rotator_get_regdma_ctxidx(): regdma segment index is based on |
| 285 | * timestamp. For non-regdma, just return 0 (i.e. first index) |
| 286 | * @ctx: Rotator Context |
| 287 | * return: regdma segment index |
| 288 | */ |
| 289 | static inline u32 sde_hw_rotator_get_regdma_ctxidx( |
| 290 | struct sde_hw_rotator_context *ctx) |
| 291 | { |
| 292 | if (ctx->rot->mode == ROT_REGDMA_OFF) |
| 293 | return 0; |
| 294 | else |
| 295 | return ctx->timestamp & SDE_HW_ROT_REGDMA_SEG_MASK; |
| 296 | } |
| 297 | |
| 298 | /** |
| 299 | * sde_hw_rotator_get_regdma_segment_base: return the base pointe of current |
| 300 | * regdma command buffer |
| 301 | * @ctx: Rotator Context |
| 302 | * return: base segment address |
| 303 | */ |
| 304 | static inline u32 *sde_hw_rotator_get_regdma_segment_base( |
| 305 | struct sde_hw_rotator_context *ctx) |
| 306 | { |
| 307 | SDEROT_DBG("regdma base @slot[%d]: %p\n", |
| 308 | sde_hw_rotator_get_regdma_ctxidx(ctx), |
| 309 | ctx->regdma_base); |
| 310 | |
| 311 | return ctx->regdma_base; |
| 312 | } |
| 313 | |
| 314 | /** |
| 315 | * sde_hw_rotator_get_regdma_segment(): return current regdma command buffer |
| 316 | * pointer for current regdma segment. |
| 317 | * @ctx: Rotator Context |
| 318 | * return: segment address |
| 319 | */ |
| 320 | static inline u32 *sde_hw_rotator_get_regdma_segment( |
| 321 | struct sde_hw_rotator_context *ctx) |
| 322 | { |
| 323 | u32 idx = sde_hw_rotator_get_regdma_ctxidx(ctx); |
| 324 | u32 *addr = ctx->regdma_wrptr; |
| 325 | |
| 326 | SDEROT_DBG("regdma slot[%d] ==> %p\n", idx, addr); |
| 327 | return addr; |
| 328 | } |
| 329 | |
| 330 | /** |
| 331 | * sde_hw_rotator_put_regdma_segment(): update current regdma command buffer |
| 332 | * pointer for current regdma segment |
| 333 | * @ctx: Rotator Context |
| 334 | * @wrptr: current regdma segment location |
| 335 | */ |
| 336 | static inline void sde_hw_rotator_put_regdma_segment( |
| 337 | struct sde_hw_rotator_context *ctx, |
| 338 | u32 *wrptr) |
| 339 | { |
| 340 | u32 idx = sde_hw_rotator_get_regdma_ctxidx(ctx); |
| 341 | |
| 342 | ctx->regdma_wrptr = wrptr; |
| 343 | SDEROT_DBG("regdma slot[%d] <== %p\n", idx, wrptr); |
| 344 | } |
| 345 | |
| 346 | /** |
| 347 | * sde_hw_rotator_put_ctx(): Storing rotator context according to its |
| 348 | * timestamp. |
| 349 | */ |
| 350 | static inline void sde_hw_rotator_put_ctx(struct sde_hw_rotator_context *ctx) |
| 351 | { |
| 352 | struct sde_hw_rotator *rot = ctx->rot; |
| 353 | u32 idx = sde_hw_rotator_get_regdma_ctxidx(ctx); |
Benjamin Chan | c3e185f | 2016-11-08 21:48:21 -0500 | [diff] [blame] | 354 | unsigned long flags; |
Alan Kwong | 9487de2 | 2016-01-16 22:06:36 -0500 | [diff] [blame] | 355 | |
Benjamin Chan | c3e185f | 2016-11-08 21:48:21 -0500 | [diff] [blame] | 356 | spin_lock_irqsave(&rot->rotisr_lock, flags); |
Alan Kwong | 9487de2 | 2016-01-16 22:06:36 -0500 | [diff] [blame] | 357 | rot->rotCtx[ctx->q_id][idx] = ctx; |
Benjamin Chan | c3e185f | 2016-11-08 21:48:21 -0500 | [diff] [blame] | 358 | spin_unlock_irqrestore(&rot->rotisr_lock, flags); |
| 359 | |
Alan Kwong | 9487de2 | 2016-01-16 22:06:36 -0500 | [diff] [blame] | 360 | SDEROT_DBG("rotCtx[%d][%d] <== ctx:%p | session-id:%d\n", |
| 361 | ctx->q_id, idx, ctx, ctx->session_id); |
| 362 | } |
| 363 | |
Benjamin Chan | c3e185f | 2016-11-08 21:48:21 -0500 | [diff] [blame] | 364 | /** |
| 365 | * sde_hw_rotator_clr_ctx(): Clearing rotator context according to its |
| 366 | * timestamp. |
| 367 | */ |
| 368 | static inline void sde_hw_rotator_clr_ctx(struct sde_hw_rotator_context *ctx) |
| 369 | { |
| 370 | struct sde_hw_rotator *rot = ctx->rot; |
| 371 | u32 idx = sde_hw_rotator_get_regdma_ctxidx(ctx); |
| 372 | unsigned long flags; |
| 373 | |
| 374 | spin_lock_irqsave(&rot->rotisr_lock, flags); |
| 375 | rot->rotCtx[ctx->q_id][idx] = NULL; |
| 376 | spin_unlock_irqrestore(&rot->rotisr_lock, flags); |
| 377 | |
| 378 | SDEROT_DBG("rotCtx[%d][%d] <== null | session-id:%d\n", |
| 379 | ctx->q_id, idx, ctx->session_id); |
| 380 | } |
| 381 | |
Alan Kwong | 9487de2 | 2016-01-16 22:06:36 -0500 | [diff] [blame] | 382 | #endif /*_SDE_ROTATOR_R3_INTERNAL_H */ |