blob: f60d01d6307c9ed9b6983be1baaf1065315b3a9c [file] [log] [blame]
/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
/*
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
*/
#ifndef __MESON_VPU_TOPOLOGY_H
#define __MESON_VPU_TOPOLOGY_H
#include <linux/kfifo.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <dt-bindings/display/meson-drm-ids.h>
#include "meson_vpu_reg.h"
#include "meson_drv.h"
#include "meson_vpu_util.h"
#define MESON_OSD1 0
#define MESON_OSD2 1
#define MESON_OSD3 2
#define MESON_MAX_OSDS 4
#define MESON_MAX_VIDEO 2
#define MESON_MAX_OSD_BLEND 3
#define MESON_MAX_OSD_TO_VPP 2
#define MESON_MAX_SCALERS 4
#define MESON_MAX_BLOCKS 32
#define MESON_BLOCK_MAX_INPUTS 6
#define MESON_BLOCK_MAX_OUTPUTS 3
#define MESON_BLOCK_MAX_NAME_LEN 32
/*ratio base for scaler calc;maybe need bigger than 1000*/
#define RATIO_BASE 1000
#define MESON_OSD_INPUT_W_LIMIT 3840
#define MESON_OSD_INPUT_H_LIMIT 2160
#define MAX_DIN_NUM 4
#define MAX_DOUT_NUM 2
#define VP_MAP_STRUCT_SIZE 120
#define BUFFER_NUM 4
#define MAX_DFS_PATH_NUM 2
/*
*according to reg description,scale down limit shold be 4bits=16
*but test result is 10,it will display abnormal if bigger than 10.xx
*have not get more info from others,so config it as 10 right now.
*Todo:if you make sure and test okay,you can rechange it.
*/
#define MESON_OSD_SCLAE_DOWN_LIMIT 10
#define MESON_OSD_SCLAE_UP_LIMIT ((1 << 24) - 1)
/*
*MESON_DRM_VERSION_V0:support modetest and atomictest,
*backup last commit state
*MESON_DRM_VERSION_V1:support atomictest,
*don't support modetest,don't backup last commit state
*/
#define MESON_DRM_VERSION_V0 0
#define SCALER_RATIO_X_CALC_DONE BIT(0)
#define SCALER_RATIO_Y_CALC_DONE BIT(1)
#define SCALER_IN_W_CALC_DONE BIT(2)
#define SCALER_IN_H_CALC_DONE BIT(3)
#define SCALER_OUT_W_CALC_DONE BIT(4)
#define SCALER_OUT_H_CALC_DONE BIT(5)
#define SCALER_INPUT_WIDTH_CHANGED BIT(0)
#define SCALER_INPUT_HEIGHT_CHANGED BIT(1)
#define SCALER_OUTPUT_WIDTH_CHANGED BIT(2)
#define SCALER_OUTPUT_HEIGHT_CHANGED BIT(3)
#define SCALER_OUTPUT_SCAN_MODE_CHANGED BIT(4)
enum meson_vpu_blk_type {
MESON_BLK_OSD = 0,
MESON_BLK_AFBC,
MESON_BLK_SCALER,
MESON_BLK_OSDBLEND,
MESON_BLK_HDR,
MESON_BLK_DOVI,
MESON_BLK_VPPBLEND,
MESON_BLK_VIDEO,
};
struct meson_vpu_pipeline;
struct meson_vpu_block;
struct meson_vpu_block_state;
struct meson_vpu_pipeline_state;
/* vpu block ops */
struct meson_vpu_block_ops {
int (*check_state)(struct meson_vpu_block *vblk,
struct meson_vpu_block_state *state,
struct meson_vpu_pipeline_state *mvps);
void (*update_state)(struct meson_vpu_block *vblk,
struct meson_vpu_block_state *state);
void (*enable)(struct meson_vpu_block *vblk);
void (*disable)(struct meson_vpu_block *vblk);
void (*dump_register)(struct meson_vpu_block *vblk,
struct seq_file *seq);
void (*init)(struct meson_vpu_block *vblk);
void (*fini)(struct meson_vpu_block *vblk);
};
struct meson_vpu_block_link {
struct meson_vpu_block *link;
u8 id;
u8 port;
int edges_active;
int edges_visited;
};
/* vpu block */
struct meson_vpu_block {
struct drm_private_obj obj;
char name[MESON_BLOCK_MAX_NAME_LEN];
enum meson_vpu_blk_type type;
u8 id;
u8 index;
u8 max_inputs;
u8 max_outputs;
u8 avail_inputs;
u8 avail_outputs;
unsigned long inputs_mask;
unsigned long outputs_mask;
struct meson_vpu_block_link inputs[MESON_BLOCK_MAX_INPUTS];
struct meson_vpu_block_link outputs[MESON_BLOCK_MAX_OUTPUTS];
struct meson_vpu_block_ops *ops;
struct meson_vpu_pipeline *pipeline;
};
struct meson_vpu_block_state {
struct drm_private_state obj;
struct meson_vpu_block *pblk;
u32 inputs_mask;
u32 inputs_changed;
u32 outputs_changed;
u32 checked;
u32 state_changed;
struct meson_vpu_block_link inputs[MESON_BLOCK_MAX_INPUTS];
struct meson_vpu_block_link outputs[MESON_BLOCK_MAX_OUTPUTS];
int in_stack;
int active;
};
struct meson_vpu_osd_layer_info {
u32 src_x;
u32 src_y;
u32 src_w;
u32 src_h;
u32 dst_w;
u32 dst_h;
int dst_x;
int dst_y;
u32 fb_w;
u32 fb_h;
u32 zorder;
u32 byte_stride;
u32 pixel_format;
u64 phy_addr;
u32 plane_index;
u32 uhd_plane_index;
u32 enable;
u32 ratio_x;/*input_w/output_w*/
u32 afbc_inter_format;
u32 afbc_en;
u32 fb_size;
u32 pixel_blend;
u32 rotation;
u32 blend_bypass;
u32 global_alpha;
u32 scaling_filter;
};
struct meson_vpu_osd {
struct meson_vpu_block base;
struct osd_mif_reg_s *reg;
};
struct meson_vpu_osd_state {
struct meson_vpu_block_state base;
u64 phy_addr;
u32 index;
u32 enable;
u32 color_key_enable;
u32 dimm_enable;
u32 mode_3d_enable;
u32 color_key;
u32 alpha;
u32 global_alpha;
u32 dimm_color;
u32 pixel_format;
u32 zorder;
u32 byte_stride;
u32 src_x;
u32 src_y;
u32 src_w;
u32 src_h;
u32 dst_w;
u32 dst_h;
int dst_x;
int dst_y;
int s_mode;
int r_mode;
u32 plane_index;
u32 fb_size;
u32 pixel_blend;
u32 afbc_en;
u32 rotation;
u32 blend_bypass;
};
struct meson_vpu_video_layer_info {
u32 src_x;
u32 src_y;
u32 src_w;
u32 src_h;
u32 dst_w;
u32 dst_h;
int dst_x;
int dst_y;
u32 zorder;
u32 byte_stride;
u32 pixel_format;
u64 phy_addr[2];
u32 plane_index;
u32 enable;
u32 ratio_x;/*input_w/output_w*/
u32 fb_size[2];
u32 pixel_blend;
struct vframe_s *vf;
struct dma_buf *dmabuf;
u32 vfm_mode;
bool is_uvm;
};
struct meson_vpu_video {
struct meson_vpu_block base;
struct vframe_provider_s vprov;
char vfm_map_id[VP_MAP_STRUCT_SIZE];
char vfm_map_chain[VP_MAP_STRUCT_SIZE];
DECLARE_KFIFO(ready_q, struct vframe_s *, BUFFER_NUM);
DECLARE_KFIFO(free_q, struct vframe_s *, BUFFER_NUM);
DECLARE_KFIFO(display_q, struct vframe_s *, BUFFER_NUM);
struct vframe_s vframe[BUFFER_NUM];
u32 video_path_reg;
u32 vfm_mode;
bool video_enabled;
struct dma_fence *fence;
struct list_head vfm_node[MESON_MAX_VIDEO];
};
struct meson_vpu_video_state {
struct meson_vpu_block_state base;
u32 index;
u32 enable;
u32 color_key_enable;
u32 dimm_enable;
u32 mode_3d_enable;
u32 color_key;
u32 alpha;
u32 global_alpha;
u32 dimm_color;
u32 phy_addr[2];
u32 pixel_format;
u32 zorder;
u32 byte_stride;
u32 src_x;
u32 src_y;
u32 src_w;
u32 src_h;
u32 dst_w;
u32 dst_h;
int dst_x;
int dst_y;
int s_mode;
int r_mode;
u32 plane_index;
u32 fb_size[2];
u32 pixel_blend;
u32 afbc_en;
struct vframe_s *vf;
struct dma_buf *dmabuf;
bool is_uvm;
};
struct meson_vpu_afbc {
struct meson_vpu_block base;
struct afbc_osd_reg_s *afbc_regs;
struct afbc_status_reg_s *status_regs;
};
struct meson_vpu_afbc_state {
struct meson_vpu_block_state base;
u32 format;
u32 inter_format;
};
struct meson_vpu_scaler {
struct meson_vpu_block base;
struct osd_scaler_reg_s *reg;
u32 linebuffer;/*base pixel*/
u32 bank_length;/*base line*/
};
struct meson_vpu_scaler_state {
struct meson_vpu_block_state base;
u32 free_scale_mode;
u32 input_width;
u32 input_height;
u32 output_width;
u32 output_height;
u32 ratio_x;
u32 ratio_y;
u32 scan_mode_out;
u32 state_changed;
u32 free_scale_enable;
u32 scaler_filter_mode;
};
struct meson_vpu_scaler_param {
u32 input_width;
u32 input_height;
u32 output_width;
u32 output_height;
//u32 ratio_x;
//u32 ratio_y;
u32 ratio_w_num;
u32 ratio_w_den;
u32 ratio_h_num;
u32 ratio_h_den;
/*calc_done_mask:
*bit0:ratio_x,
*bit1:ratio_y
*bit2:input_width
*bit3:input_height
*bit4:output_width
*bit5:output_height
*/
u32 calc_done_mask;
/*
*bit0:plane0
*bit1:plane1
*bit2:plane2
*bit*:plane*
*/
u32 plane_mask;
u32 enable;
u32 before_osdblend;
};
struct meson_vpu_osdblend {
struct meson_vpu_block base;
struct osdblend_reg_s *reg;
};
struct meson_vpu_osdblend_state {
struct meson_vpu_block_state base;
u32 input_num;
/*bit0/bit1/bit2-->osd0/osd1/osd2*/
u32 input_osd_mask;
/*Din mask:bit0:DIN0;bit1:DIN1;bit2:DIN2;bit3:DIN3*/
u32 input_mask;
/*Din0~3 select which input channel or osd(0/1/2)*/
u32 din_channel_mux[MAX_DIN_NUM];
/*osd(0/1/2) go through osdblend to dout0 or dout1*/
u32 dout_mux[MAX_DIN_NUM];
/*scope position before mux,tied with osd0/osd1/osd2*/
struct osd_scope_s din_channel_scope[MAX_DIN_NUM];
/*sub-blend0 and sub-blend1 size*/
u32 input_width[MESON_MAX_OSD_BLEND];
u32 input_height[MESON_MAX_OSD_BLEND];
/*0:din0-->blend0;1:din0-->Dout0,bypass OsdBlend*/
u32 din0_switch;
/*0:din3-->blend1;1:din3-->Dout1,bypass OsdBlend*/
u32 din3_switch;
/*0:blend1-->blend2;1:blend1-->Dout1,bypass Blend2*/
u32 blend1_switch;
};
struct meson_vpu_hdr {
struct meson_vpu_block base;
};
struct meson_vpu_hdr_state {
struct meson_vpu_block_state base;
};
struct meson_vpu_dolby {
struct meson_vpu_block base;
};
struct meson_vpu_dolby_state {
struct meson_vpu_block_state base;
};
struct meson_vpu_postblend {
struct meson_vpu_block base;
struct postblend_reg_s *reg;
};
struct meson_vpu_postblend_state {
struct meson_vpu_block_state base;
struct osd_scope_s postblend_scope[MESON_MAX_OSD_TO_VPP];
};
/* vpu pipeline */
struct meson_vpu_pipeline {
struct drm_private_obj obj;
struct drm_display_mode mode;
struct meson_vpu_osd *osds[MESON_MAX_OSDS];
struct meson_vpu_video *video[MESON_MAX_VIDEO];
struct meson_vpu_afbc *afbc_osds[MESON_MAX_OSDS];
struct meson_vpu_scaler *scalers[MESON_MAX_SCALERS];
struct meson_vpu_osdblend *osdblend;
struct meson_vpu_hdr *hdr;
struct meson_vpu_dolby *dolby;
struct meson_vpu_postblend *postblend;
struct meson_vpu_pipeline_state *state;
u32 num_osds;
u32 num_video;
u32 num_afbc_osds;
u32 num_scalers;
u8 osd_version;
struct drm_crtc *crtc;
struct meson_vpu_block **mvbs;
int num_blocks;
};
struct meson_vpu_common_state {
u32 color_format;
u64 block_mask;
};
struct meson_vpu_stack {
int num_blocks;
int top;
struct meson_vpu_block *stack[MESON_MAX_BLOCKS];
};
struct meson_vpu_traverse {
struct meson_vpu_block *path[MAX_DFS_PATH_NUM][MESON_MAX_BLOCKS];
int num_path;
};
struct meson_vpu_pipeline_state {
struct drm_private_state obj;
struct meson_vpu_common_state common_cfg;
struct meson_vpu_pipeline *pipeline;
u64 enable_blocks;
struct meson_vpu_osd_layer_info plane_info[MESON_MAX_OSDS];
struct meson_vpu_video_layer_info video_plane_info[MESON_MAX_VIDEO];
u32 num_plane;
u32 num_plane_video;
/*min --> max*/
u32 zorder_plane_index[MESON_MAX_OSDS];
u32 ratio_plane_index[MESON_MAX_OSDS];
struct meson_vpu_scaler_param scaler_param[MESON_MAX_SCALERS];
/*pre_osd_scope is before DIN*/
struct osd_scope_s osd_scope_pre[MAX_DIN_NUM];
/*some traverse help structure*/
struct meson_vpu_stack osd_stack[MESON_MAX_OSDS];
/*store traverse result for every path*/
struct meson_vpu_traverse osd_traverse[MESON_MAX_OSDS];
u32 plane_index[MESON_MAX_OSDS];
u32 video_plane_index[MESON_MAX_VIDEO];
u32 din_index[MAX_DIN_NUM];
u32 dout_index[MAX_DIN_NUM];
u32 scaler_cnt[MAX_DIN_NUM];
struct meson_vpu_block *scale_blk[MESON_MAX_OSDS][MESON_MAX_SCALERS];
u32 dout_zorder[MAX_DOUT_NUM];
u32 global_afbc;
};
#define to_osd_block(x) container_of(x, struct meson_vpu_osd, base)
#define to_afbc_block(x) container_of(x, struct meson_vpu_afbc, base)
#define to_scaler_block(x) container_of(x, struct meson_vpu_scaler, base)
#define to_osdblend_block(x) container_of(x, struct meson_vpu_osdblend, base)
#define to_hdr_block(x) container_of(x, struct meson_vpu_hdr, base)
#define to_dolby_block(x) container_of(x, struct meson_vpu_dolby, base)
#define to_postblend_block(x) container_of(x, struct meson_vpu_postblend, base)
#define to_video_block(x) container_of(x, struct meson_vpu_video, base)
#define to_osd_state(x) container_of(x, struct meson_vpu_osd_state, base)
#define to_afbc_state(x) container_of(x, struct meson_vpu_afbc_state, base)
#define to_scaler_state(x) container_of(x, struct meson_vpu_scaler_state, base)
#define to_osdblend_state(x) container_of(x, \
struct meson_vpu_osdblend_state, base)
#define to_hdr_state(x) container_of(x, struct meson_vpu_hdr_state, base)
#define to_dolby_state(x) container_of(x, struct meson_vpu_dolby_state, base)
#define to_postblend_state(x) container_of(x, \
struct meson_vpu_postblend_state, base)
#define to_video_state(x) container_of(x, struct meson_vpu_video_state, base)
#define priv_to_block(x) container_of(x, struct meson_vpu_block, obj)
#define priv_to_block_state(x) container_of(x, \
struct meson_vpu_block_state, obj)
#define priv_to_pipeline(x) container_of(x, struct meson_vpu_pipeline, obj)
#define priv_to_pipeline_state(x) container_of(x, \
struct meson_vpu_pipeline_state, obj)
int vpu_pipeline_video_check(struct meson_vpu_pipeline *pipeline,
struct drm_atomic_state *state);
int vpu_pipeline_video_update(struct meson_vpu_pipeline *pipeline,
struct drm_atomic_state *old_state);
int vpu_pipeline_osd_check(struct meson_vpu_pipeline *pipeline,
struct drm_atomic_state *state);
int vpu_pipeline_osd_update(struct meson_vpu_pipeline *pipeline,
struct drm_atomic_state *old_state);
int vpu_topology_init(struct platform_device *pdev, struct meson_drm *private);
int vpu_pipeline_check(struct meson_vpu_pipeline *pipeline,
struct drm_atomic_state *state);
int vpu_video_plane_update(struct meson_vpu_pipeline *pipeline,
struct drm_atomic_state *old_state, int plane_index);
int vpu_osd_pipeline_update(struct meson_vpu_pipeline *pipeline,
struct drm_atomic_state *old_state);
void vpu_pipeline_init(struct meson_vpu_pipeline *pipeline);
void vpu_pipeline_fini(struct meson_vpu_pipeline *pipeline);
/* meson_vpu_pipeline_private.c */
struct meson_vpu_block_state *
meson_vpu_block_get_state(struct meson_vpu_block *block,
struct drm_atomic_state *state);
struct meson_vpu_pipeline_state *
meson_vpu_pipeline_get_state(struct meson_vpu_pipeline *pipeline,
struct drm_atomic_state *state);
int meson_vpu_block_state_init(struct meson_drm *private,
struct meson_vpu_pipeline *pipeline);
#ifdef MESON_DRM_VERSION_V0
void meson_vpu_pipeline_atomic_backup_state(struct meson_vpu_pipeline_state *mvps);
#endif
int combination_traverse(struct meson_vpu_pipeline_state *mvps,
struct drm_atomic_state *state);
int vpu_pipeline_traverse(struct meson_vpu_pipeline_state *mvps,
struct drm_atomic_state *state);
int vpu_pipeline_check_osdblend(u32 *out_port, int num_planes,
struct meson_vpu_pipeline_state *mvps,
struct drm_atomic_state *state);
int vpu_video_pipeline_check_block(struct meson_vpu_pipeline_state *mvps,
struct drm_atomic_state *state);
void vpu_pipeline_check_finish_reg(void);
extern struct meson_vpu_block_ops video_ops;
extern struct meson_vpu_block_ops osd_ops;
extern struct meson_vpu_block_ops afbc_ops;
extern struct meson_vpu_block_ops scaler_ops;
extern struct meson_vpu_block_ops osdblend_ops;
extern struct meson_vpu_block_ops hdr_ops;
extern struct meson_vpu_block_ops dolby_ops;
extern struct meson_vpu_block_ops postblend_ops;
#ifdef CONFIG_DEBUG_FS
extern u32 overwrite_reg[256];
extern u32 overwrite_val[256];
extern int overwrite_enable;
extern int reg_num;
#endif
#endif