blob: 5502cc09ae1911c528e2e4dfea9a2e04e8c035e5 [file] [log] [blame]
Benjamin Chan99eb63b2016-12-21 15:45:26 -05001/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
Alan Kwong9487de22016-01-16 22:06:36 -05002 *
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
19struct sde_hw_rotator;
20struct 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 Kulkarni298c8232016-09-26 22:32:10 -070031#define SDE_ROT_FLAG_SECURE_CAMERA_SESSION 0x40
Alan Kwong9487de22016-01-16 22:06:36 -050032
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
44enum sde_rot_queue_prio {
45 ROT_QUEUE_HIGH_PRIORITY,
46 ROT_QUEUE_LOW_PRIORITY,
47 ROT_QUEUE_MAX
48};
49
50enum sde_rot_angle {
51 ROT_ANGLE_0,
52 ROT_ANGLE_90,
53 ROT_ANGEL_MAX
54};
55
56enum 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 */
69struct 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 Chan99eb63b2016-12-21 15:45:26 -050076 u32 fps;
77 u64 bw;
Alan Kwong9487de22016-01-16 22:06:36 -050078};
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 */
89struct 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 Chan99eb63b2016-12-21 15:45:26 -050098 u32 fps;
99 u64 bw;
Alan Kwong9487de22016-01-16 22:06:36 -0500100};
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 */
112struct 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 Chanfb6faa32016-08-16 17:21:01 -0400124 * @dnsc_factor_w: Downscale factor for width
125 * @dnsc_factor_h: Downscale factor for height
Alan Kwong9487de22016-01-16 22:06:36 -0500126 * @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 Chanfb6faa32016-08-16 17:21:01 -0400134 u32 dnsc_factor_w,
135 u32 dnsc_factor_h,
Alan Kwong9487de22016-01-16 22:06:36 -0500136 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 */
191struct 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 */
205struct 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 Kwong818b7fc2016-07-24 22:07:41 -0400214 wait_queue_head_t regdma_waitq;
Alan Kwong9487de22016-01-16 22:06:36 -0500215 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 Chan99eb63b2016-12-21 15:45:26 -0500221 bool is_traffic_shaping;
Alan Kwong9487de22016-01-16 22:06:36 -0500222};
223
224/**
225 * struct sde_hw_rotator_resource_info : Each rotator resource ties to each
226 * priority queue
227 */
228struct 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 */
238struct 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 Kwong818b7fc2016-07-24 22:07:41 -0400266 atomic_t irq_enabled;
Alan Kwong9487de22016-01-16 22:06:36 -0500267
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 Kwong9487de22016-01-16 22:06:36 -0500274
Alan Kwong9487de22016-01-16 22:06:36 -0500275 spinlock_t rotctx_lock;
276 spinlock_t rotisr_lock;
277
278 bool dbgmem;
Benjamin Chan0f9e61d2016-09-16 16:01:09 -0400279 bool reset_hw_ts;
280 u32 last_hw_ts;
Alan Kwong9487de22016-01-16 22:06:36 -0500281};
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 */
289static 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 */
304static 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 */
320static 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 */
336static 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 */
350static 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 Chanc3e185f2016-11-08 21:48:21 -0500354 unsigned long flags;
Alan Kwong9487de22016-01-16 22:06:36 -0500355
Benjamin Chanc3e185f2016-11-08 21:48:21 -0500356 spin_lock_irqsave(&rot->rotisr_lock, flags);
Alan Kwong9487de22016-01-16 22:06:36 -0500357 rot->rotCtx[ctx->q_id][idx] = ctx;
Benjamin Chanc3e185f2016-11-08 21:48:21 -0500358 spin_unlock_irqrestore(&rot->rotisr_lock, flags);
359
Alan Kwong9487de22016-01-16 22:06:36 -0500360 SDEROT_DBG("rotCtx[%d][%d] <== ctx:%p | session-id:%d\n",
361 ctx->q_id, idx, ctx, ctx->session_id);
362}
363
Benjamin Chanc3e185f2016-11-08 21:48:21 -0500364/**
365 * sde_hw_rotator_clr_ctx(): Clearing rotator context according to its
366 * timestamp.
367 */
368static 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 Kwong9487de22016-01-16 22:06:36 -0500382#endif /*_SDE_ROTATOR_R3_INTERNAL_H */