23b65c3a24
git-subtree-dir: techpack/display git-subtree-mainline:2d46776923
git-subtree-split:64f31403b4
Change-Id: I7f4c42a3ba6b11a8db861cdd171a52d8f58f2e06
453 lines
13 KiB
C
453 lines
13 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/*
|
|
* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
|
|
*/
|
|
|
|
#ifndef _SDE_ROTATOR_R3_INTERNAL_H
|
|
#define _SDE_ROTATOR_R3_INTERNAL_H
|
|
|
|
#include "sde_rotator_core.h"
|
|
|
|
struct sde_hw_rotator;
|
|
struct sde_hw_rotator_context;
|
|
|
|
/**
|
|
* Flags
|
|
*/
|
|
#define SDE_ROT_FLAG_SECURE_OVERLAY_SESSION 0x1
|
|
#define SDE_ROT_FLAG_FLIP_LR 0x2
|
|
#define SDE_ROT_FLAG_FLIP_UD 0x4
|
|
#define SDE_ROT_FLAG_SOURCE_ROTATED_90 0x8
|
|
#define SDE_ROT_FLAG_ROT_90 0x10
|
|
#define SDE_ROT_FLAG_DEINTERLACE 0x20
|
|
#define SDE_ROT_FLAG_SECURE_CAMERA_SESSION 0x40
|
|
|
|
/**
|
|
* General defines
|
|
*/
|
|
#define SDE_HW_ROT_REGDMA_RAM_SIZE 1024
|
|
#define SDE_HW_ROT_REGDMA_TOTAL_CTX 8
|
|
#define SDE_HW_ROT_REGDMA_SEG_MASK (SDE_HW_ROT_REGDMA_TOTAL_CTX - 1)
|
|
#define SDE_HW_ROT_REGDMA_SEG_SIZE \
|
|
(SDE_HW_ROT_REGDMA_RAM_SIZE / SDE_HW_ROT_REGDMA_TOTAL_CTX)
|
|
#define SDE_REGDMA_SWTS_MASK 0x00000FFF
|
|
#define SDE_REGDMA_SWTS_SHIFT 12
|
|
|
|
enum sde_rot_queue_prio {
|
|
ROT_QUEUE_HIGH_PRIORITY,
|
|
ROT_QUEUE_LOW_PRIORITY,
|
|
ROT_QUEUE_MAX
|
|
};
|
|
|
|
enum sde_rot_angle {
|
|
ROT_ANGLE_0,
|
|
ROT_ANGLE_90,
|
|
ROT_ANGEL_MAX
|
|
};
|
|
|
|
enum sde_rotator_regdma_mode {
|
|
ROT_REGDMA_OFF,
|
|
ROT_REGDMA_ON,
|
|
ROT_REGDMA_MAX
|
|
};
|
|
|
|
/**
|
|
* struct sde_hw_rot_sspp_cfg: Rotator SSPP Configration description
|
|
* @src: source surface information
|
|
* @src_rect: src ROI, caller takes into account the different operations
|
|
* such as decimation, flip etc to program this field
|
|
* @addr: source surface address
|
|
*/
|
|
struct sde_hw_rot_sspp_cfg {
|
|
struct sde_mdp_format_params *fmt;
|
|
struct sde_mdp_plane_sizes src_plane;
|
|
struct sde_rect *src_rect;
|
|
struct sde_mdp_data *data;
|
|
u32 img_width;
|
|
u32 img_height;
|
|
u32 fps;
|
|
u64 bw;
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
* struct sde_hw_rot_wb_cfg: Rotator WB Configration description
|
|
* @dest: destination surface information
|
|
* @dest_rect: dest ROI, caller takes into account the different operations
|
|
* such as decimation, flip etc to program this field
|
|
* @addr: destination surface address
|
|
* @prefill_bw: prefill bandwidth in Bps
|
|
*/
|
|
struct sde_hw_rot_wb_cfg {
|
|
struct sde_mdp_format_params *fmt;
|
|
struct sde_mdp_plane_sizes dst_plane;
|
|
struct sde_rect *dst_rect;
|
|
struct sde_mdp_data *data;
|
|
u32 img_width;
|
|
u32 img_height;
|
|
u32 v_downscale_factor;
|
|
u32 h_downscale_factor;
|
|
u32 fps;
|
|
u64 bw;
|
|
u64 prefill_bw;
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
*
|
|
* struct sde_hw_rotator_ops: Interface to the Rotator Hw driver functions
|
|
*
|
|
* Pre-requsises:
|
|
* - Caller must call the init function to get the rotator context
|
|
* - These functions will be called after clocks are enabled
|
|
*/
|
|
struct sde_hw_rotator_ops {
|
|
/**
|
|
* setup_rotator_fetchengine():
|
|
* Setup Source format
|
|
* Setup Source dimension/cropping rectangle (ROI)
|
|
* Setup Source surface base address and stride
|
|
* Setup fetch engine op mode (linear/tiled/compression/...)
|
|
* @ctx: Rotator context created in sde_hw_rotator_config
|
|
* @queue_id: Select either low / high priority queue
|
|
* @cfg: Rotator Fetch engine configuration parameters
|
|
* @danger_lut: Danger LUT setting
|
|
* @safe_lut: Safe LUT setting
|
|
* @dnsc_factor_w: Downscale factor for width
|
|
* @dnsc_factor_h: Downscale factor for height
|
|
* @flags: Specific config flag, see SDE_ROT_FLAG_ for details
|
|
*/
|
|
void (*setup_rotator_fetchengine)(
|
|
struct sde_hw_rotator_context *ctx,
|
|
enum sde_rot_queue_prio queue_id,
|
|
struct sde_hw_rot_sspp_cfg *cfg,
|
|
u32 danger_lut,
|
|
u32 safe_lut,
|
|
u32 dnsc_factor_w,
|
|
u32 dnsc_factor_h,
|
|
u32 flags);
|
|
|
|
/**
|
|
* setup_rotator_wbengine():
|
|
* Setup destination formats
|
|
* Setup destination dimension/cropping rectangle (ROI)
|
|
* Setup destination surface base address and strides
|
|
* Setup writeback engine op mode (linear/tiled/compression)
|
|
* @ctx: Rotator context created in sde_hw_rotator_config
|
|
* @queue_id: Select either low / high priority queue
|
|
* @cfg: Rotator WriteBack engine configuration parameters
|
|
* @flags: Specific config flag, see SDE_ROT_FLAG_ for details
|
|
*/
|
|
void (*setup_rotator_wbengine)(
|
|
struct sde_hw_rotator_context *ctx,
|
|
enum sde_rot_queue_prio queue_id,
|
|
struct sde_hw_rot_wb_cfg *cfg,
|
|
u32 flags);
|
|
|
|
/**
|
|
* start_rotator():
|
|
* Kick start rotator operation based on cached setup parameters
|
|
* REGDMA commands will get generated at this points
|
|
* @ctx: Rotator context
|
|
* @queue_id: Select either low / high priority queue
|
|
* Returns: unique job timestamp per submit. Used for tracking
|
|
* rotator finished job.
|
|
*/
|
|
u32 (*start_rotator)(
|
|
struct sde_hw_rotator_context *ctx,
|
|
enum sde_rot_queue_prio queue_id);
|
|
|
|
/**
|
|
* wait_rotator_done():
|
|
* Notify Rotator HAL layer previously submitted job finished.
|
|
* A job timestamp will return to caller.
|
|
* @ctx: Rotator context
|
|
* @flags: Reserved
|
|
* Returns: job timestamp for tracking purpose
|
|
*
|
|
*/
|
|
u32 (*wait_rotator_done)(
|
|
struct sde_hw_rotator_context *ctx,
|
|
enum sde_rot_queue_prio queue_id,
|
|
u32 flags);
|
|
|
|
/**
|
|
* get_pending_ts():
|
|
* Obtain current active timestamp from rotator hw
|
|
* @rot: HW Rotator structure
|
|
* @ctx: Rotator context
|
|
* @ts: current timestamp return from rot hw
|
|
* Returns: true if context has pending requests
|
|
*/
|
|
int (*get_pending_ts)(
|
|
struct sde_hw_rotator *rot,
|
|
struct sde_hw_rotator_context *ctx,
|
|
u32 *ts);
|
|
|
|
/**
|
|
* update_ts():
|
|
* Update rotator timestmap with given value
|
|
* @rot: HW Rotator structure
|
|
* @q_id: rotator queue id
|
|
* @ts: new timestamp for rotator
|
|
*/
|
|
void (*update_ts)(
|
|
struct sde_hw_rotator *rot,
|
|
u32 q_id,
|
|
u32 ts);
|
|
};
|
|
|
|
/**
|
|
* struct sde_dbg_buf : Debug buffer used by debugfs
|
|
* @vaddr: VA address mapped from dma buffer
|
|
* @dmabuf: DMA buffer
|
|
* @buflen: Length of DMA buffer
|
|
* @width: pixel width of buffer
|
|
* @height: pixel height of buffer
|
|
*/
|
|
struct sde_dbg_buf {
|
|
void *vaddr;
|
|
struct dma_buf *dmabuf;
|
|
unsigned long buflen;
|
|
u32 width;
|
|
u32 height;
|
|
};
|
|
|
|
/**
|
|
* struct sde_hw_rotator_context : Each rotator context ties to each priority
|
|
* queue. Max number of concurrent contexts in regdma is limited to regdma
|
|
* ram segment size allocation. Each rotator context can be any priority. A
|
|
* incremental timestamp is used to identify and assigned to each context.
|
|
* @list: list of pending context
|
|
* @sequence_id: unique sequence identifier for rotation request
|
|
* @sbuf_mode: true if stream buffer is requested
|
|
* @start_ctrl: start control register update value
|
|
* @sys_cache_mode: sys cache mode register update value
|
|
* @op_mode: rot top op mode selection
|
|
* @last_entry: pointer to last configured entry (for debugging purposes)
|
|
*/
|
|
struct sde_hw_rotator_context {
|
|
struct list_head list;
|
|
struct sde_hw_rotator *rot;
|
|
struct sde_rot_hw_resource *hwres;
|
|
enum sde_rot_queue_prio q_id;
|
|
u32 session_id;
|
|
u32 sequence_id;
|
|
char __iomem *regdma_base;
|
|
char __iomem *regdma_wrptr;
|
|
u32 timestamp;
|
|
struct completion rot_comp;
|
|
wait_queue_head_t regdma_waitq;
|
|
struct sde_dbg_buf src_dbgbuf;
|
|
struct sde_dbg_buf dst_dbgbuf;
|
|
u32 last_regdma_isr_status;
|
|
u32 last_regdma_timestamp;
|
|
dma_addr_t ts_addr;
|
|
bool is_secure;
|
|
bool is_traffic_shaping;
|
|
bool sbuf_mode;
|
|
bool abort;
|
|
u32 start_ctrl;
|
|
u32 sys_cache_mode;
|
|
u32 op_mode;
|
|
struct sde_rot_entry *last_entry;
|
|
};
|
|
|
|
/**
|
|
* struct sde_hw_rotator_resource_info : Each rotator resource ties to each
|
|
* priority queue
|
|
*/
|
|
struct sde_hw_rotator_resource_info {
|
|
struct sde_hw_rotator *rot;
|
|
struct sde_rot_hw_resource hw;
|
|
};
|
|
|
|
/**
|
|
* struct sde_hw_rotator : Rotator description
|
|
* @hw: mdp register mapped offset
|
|
* @ops: pointer to operations possible for the rotator HW
|
|
* @highest_bank: highest bank size of memory
|
|
* @ubwc_malsize: ubwc minimum allowable length
|
|
* @ubwc_swizzle: ubwc swizzle enable
|
|
* @sbuf_headroom: stream buffer headroom in lines
|
|
* @solid_fill: true if solid fill is requested
|
|
* @constant_color: solid fill constant color
|
|
* @sbuf_ctx: list of active sbuf context in FIFO order
|
|
* @vid_trigger: video mode trigger select
|
|
* @cmd_trigger: command mode trigger select
|
|
* @inpixfmts: array of supported input pixel formats fourcc per mode
|
|
* @num_inpixfmt: size of the supported input pixel format array per mode
|
|
* @outpixfmts: array of supported output pixel formats in fourcc per mode
|
|
* @num_outpixfmt: size of the supported output pixel formats array per mode
|
|
* @downscale_caps: capability string of scaling
|
|
* @maxlinewidth: maximum line width supported
|
|
*/
|
|
struct sde_hw_rotator {
|
|
/* base */
|
|
char __iomem *mdss_base;
|
|
|
|
/* Platform device from upper manager */
|
|
struct platform_device *pdev;
|
|
|
|
/* Ops */
|
|
struct sde_hw_rotator_ops ops;
|
|
|
|
/* Cmd Queue */
|
|
u32 cmd_queue[SDE_HW_ROT_REGDMA_RAM_SIZE];
|
|
|
|
/* Cmd Queue Write Ptr */
|
|
char __iomem *cmd_wr_ptr[ROT_QUEUE_MAX][SDE_HW_ROT_REGDMA_TOTAL_CTX];
|
|
|
|
/* Rotator Context */
|
|
struct sde_hw_rotator_context
|
|
*rotCtx[ROT_QUEUE_MAX][SDE_HW_ROT_REGDMA_TOTAL_CTX];
|
|
|
|
/* Cmd timestamp sequence for different priority*/
|
|
atomic_t timestamp[ROT_QUEUE_MAX];
|
|
|
|
/* regdma mode */
|
|
enum sde_rotator_regdma_mode mode;
|
|
|
|
/* logical interrupt number */
|
|
int irq_num;
|
|
atomic_t irq_enabled;
|
|
|
|
/* internal ION memory for SW timestamp */
|
|
struct ion_client *iclient;
|
|
struct sde_mdp_img_data swts_buf;
|
|
void *swts_buffer;
|
|
|
|
u32 highest_bank;
|
|
u32 ubwc_malsize;
|
|
u32 ubwc_swizzle;
|
|
u32 sbuf_headroom;
|
|
u32 solid_fill;
|
|
u32 constant_color;
|
|
|
|
spinlock_t rotctx_lock;
|
|
spinlock_t rotisr_lock;
|
|
|
|
bool dbgmem;
|
|
bool reset_hw_ts;
|
|
u32 last_hwts[ROT_QUEUE_MAX];
|
|
u32 koff_timeout;
|
|
u32 vid_trigger;
|
|
u32 cmd_trigger;
|
|
|
|
struct list_head sbuf_ctx[ROT_QUEUE_MAX];
|
|
|
|
const u32 *inpixfmts[SDE_ROTATOR_MODE_MAX];
|
|
u32 num_inpixfmt[SDE_ROTATOR_MODE_MAX];
|
|
const u32 *outpixfmts[SDE_ROTATOR_MODE_MAX];
|
|
u32 num_outpixfmt[SDE_ROTATOR_MODE_MAX];
|
|
const char *downscale_caps;
|
|
u32 maxlinewidth;
|
|
};
|
|
|
|
/**
|
|
* sde_hw_rotator_get_regdma_ctxidx(): regdma segment index is based on
|
|
* timestamp. For non-regdma, just return 0 (i.e. first index)
|
|
* @ctx: Rotator Context
|
|
* return: regdma segment index
|
|
*/
|
|
static inline u32 sde_hw_rotator_get_regdma_ctxidx(
|
|
struct sde_hw_rotator_context *ctx)
|
|
{
|
|
if (ctx->rot->mode == ROT_REGDMA_OFF)
|
|
return 0;
|
|
else
|
|
return ctx->timestamp & SDE_HW_ROT_REGDMA_SEG_MASK;
|
|
}
|
|
|
|
/**
|
|
* sde_hw_rotator_get_regdma_segment_base: return the base pointe of current
|
|
* regdma command buffer
|
|
* @ctx: Rotator Context
|
|
* return: base segment address
|
|
*/
|
|
static inline char __iomem *sde_hw_rotator_get_regdma_segment_base(
|
|
struct sde_hw_rotator_context *ctx)
|
|
{
|
|
SDEROT_DBG("regdma base @slot[%d]: %pK\n",
|
|
sde_hw_rotator_get_regdma_ctxidx(ctx),
|
|
ctx->regdma_base);
|
|
|
|
return ctx->regdma_base;
|
|
}
|
|
|
|
/**
|
|
* sde_hw_rotator_get_regdma_segment(): return current regdma command buffer
|
|
* pointer for current regdma segment.
|
|
* @ctx: Rotator Context
|
|
* return: segment address
|
|
*/
|
|
static inline char __iomem *sde_hw_rotator_get_regdma_segment(
|
|
struct sde_hw_rotator_context *ctx)
|
|
{
|
|
u32 idx = sde_hw_rotator_get_regdma_ctxidx(ctx);
|
|
char __iomem *addr = ctx->regdma_wrptr;
|
|
|
|
SDEROT_DBG("regdma slot[%d] ==> %pK\n", idx, addr);
|
|
return addr;
|
|
}
|
|
|
|
/**
|
|
* sde_hw_rotator_put_regdma_segment(): update current regdma command buffer
|
|
* pointer for current regdma segment
|
|
* @ctx: Rotator Context
|
|
* @wrptr: current regdma segment location
|
|
*/
|
|
static inline void sde_hw_rotator_put_regdma_segment(
|
|
struct sde_hw_rotator_context *ctx,
|
|
char __iomem *wrptr)
|
|
{
|
|
u32 idx = sde_hw_rotator_get_regdma_ctxidx(ctx);
|
|
|
|
ctx->regdma_wrptr = wrptr;
|
|
SDEROT_DBG("regdma slot[%d] <== %pK\n", idx, wrptr);
|
|
}
|
|
|
|
/**
|
|
* sde_hw_rotator_put_ctx(): Storing rotator context according to its
|
|
* timestamp.
|
|
*/
|
|
static inline void sde_hw_rotator_put_ctx(struct sde_hw_rotator_context *ctx)
|
|
{
|
|
struct sde_hw_rotator *rot = ctx->rot;
|
|
u32 idx = sde_hw_rotator_get_regdma_ctxidx(ctx);
|
|
unsigned long flags;
|
|
|
|
spin_lock_irqsave(&rot->rotisr_lock, flags);
|
|
rot->rotCtx[ctx->q_id][idx] = ctx;
|
|
if (ctx->sbuf_mode)
|
|
list_add_tail(&ctx->list, &rot->sbuf_ctx[ctx->q_id]);
|
|
spin_unlock_irqrestore(&rot->rotisr_lock, flags);
|
|
|
|
SDEROT_DBG("rotCtx[%d][%d] <== ctx:%pK | session-id:%d\n",
|
|
ctx->q_id, idx, ctx, ctx->session_id);
|
|
}
|
|
|
|
/**
|
|
* sde_hw_rotator_clr_ctx(): Clearing rotator context according to its
|
|
* timestamp.
|
|
*/
|
|
static inline void sde_hw_rotator_clr_ctx(struct sde_hw_rotator_context *ctx)
|
|
{
|
|
struct sde_hw_rotator *rot = ctx->rot;
|
|
u32 idx = sde_hw_rotator_get_regdma_ctxidx(ctx);
|
|
unsigned long flags;
|
|
|
|
spin_lock_irqsave(&rot->rotisr_lock, flags);
|
|
rot->rotCtx[ctx->q_id][idx] = NULL;
|
|
if (ctx->sbuf_mode)
|
|
list_del_init(&ctx->list);
|
|
spin_unlock_irqrestore(&rot->rotisr_lock, flags);
|
|
|
|
SDEROT_DBG("rotCtx[%d][%d] <== null | session-id:%d\n",
|
|
ctx->q_id, idx, ctx->session_id);
|
|
}
|
|
|
|
#endif /*_SDE_ROTATOR_R3_INTERNAL_H */
|