mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 19:08:57 +09:00
drm/rockchip: vop2: Add vop2 internal pd support for rk3588
There are 7 internal power domains on rk3588 vop: Cluster0/1/2/3 each have one, and Cluster0 power domain act as parent pd of Cluster1/2/3. Esmart0/1/2/3 share on pd. DSC_8K/DSC_4K each have one. Signed-off-by: Andy Yan <andy.yan@rock-chips.com> Change-Id: If2c3c79980d2690761d12e64a486aca9be992e4b
This commit is contained in:
@@ -35,7 +35,7 @@
|
||||
#define VOP_FEATURE_ALPHA_HDR10 BIT(3)
|
||||
#define VOP_FEATURE_ALPHA_NEXT_HDR BIT(4)
|
||||
/* a feature to splice two windows and two vps to support resolution > 4096 */
|
||||
#define VOP_FEATURE_SPLICE BIT(5)
|
||||
#define VOP_FEATURE_SPLICE BIT(5)
|
||||
|
||||
#define VOP_FEATURE_OUTPUT_10BIT VOP_FEATURE_OUTPUT_RGB10
|
||||
|
||||
@@ -97,6 +97,19 @@ enum vop2_win_dly_mode {
|
||||
VOP2_DLY_MODE_MAX,
|
||||
};
|
||||
|
||||
/*
|
||||
* vop2 internal power domain id,
|
||||
* should be all none zero, 0 will be
|
||||
* treat as invalid;
|
||||
*/
|
||||
#define VOP2_PD_CLUSTER0 BIT(0)
|
||||
#define VOP2_PD_CLUSTER1 BIT(1)
|
||||
#define VOP2_PD_CLUSTER2 BIT(2)
|
||||
#define VOP2_PD_CLUSTER3 BIT(3)
|
||||
#define VOP2_PD_ESMART0 BIT(4)
|
||||
#define VOP2_PD_DSC_8K BIT(5)
|
||||
#define VOP2_PD_DSC_4K BIT(6)
|
||||
|
||||
#define DSP_BG_SWAP 0x1
|
||||
#define DSP_RB_SWAP 0x2
|
||||
#define DSP_RG_SWAP 0x4
|
||||
@@ -657,6 +670,11 @@ struct vop2_video_port_regs {
|
||||
struct vop_reg splice_en;
|
||||
};
|
||||
|
||||
struct vop2_power_domain_regs {
|
||||
struct vop_reg pd;
|
||||
struct vop_reg status;
|
||||
};
|
||||
|
||||
struct vop2_dsc_regs {
|
||||
struct vop_reg rst_deassert;
|
||||
struct vop_reg port_mux;
|
||||
@@ -678,6 +696,12 @@ struct vop2_wb_regs {
|
||||
struct vop_reg axi_uv_id;
|
||||
};
|
||||
|
||||
struct vop2_power_domain_data {
|
||||
uint8_t id;
|
||||
uint8_t parent_id;
|
||||
const struct vop2_power_domain_regs *regs;
|
||||
};
|
||||
|
||||
/*
|
||||
* connector interface(RGB/HDMI/eDP/DP/MIPI) data
|
||||
*/
|
||||
@@ -698,6 +722,7 @@ struct vop2_win_data {
|
||||
const char *name;
|
||||
uint8_t phys_id;
|
||||
uint8_t splice_win_id;
|
||||
uint8_t pd_id;
|
||||
|
||||
uint32_t base;
|
||||
enum drm_plane_type type;
|
||||
@@ -731,6 +756,7 @@ struct vop2_win_data {
|
||||
|
||||
struct vop2_dsc_data {
|
||||
char id;
|
||||
uint8_t pd_id;
|
||||
const struct vop2_dsc_regs *regs;
|
||||
};
|
||||
|
||||
@@ -924,6 +950,8 @@ struct vop2_data {
|
||||
uint8_t nr_axi_intr;
|
||||
uint8_t nr_gammas;
|
||||
uint8_t nr_conns;
|
||||
uint8_t nr_pds;
|
||||
bool delayed_pd;
|
||||
const struct vop_intr *axi_intr;
|
||||
const struct vop2_ctrl *ctrl;
|
||||
const struct vop2_dsc_data *dsc;
|
||||
@@ -932,6 +960,7 @@ struct vop2_data {
|
||||
const struct vop2_connector_if_data *conn;
|
||||
const struct vop2_wb_data *wb;
|
||||
const struct vop2_layer_data *layer;
|
||||
const struct vop2_power_domain_data *pd;
|
||||
const struct vop_csc_table *csc_table;
|
||||
const struct vop_hdr_table *hdr_table;
|
||||
const struct vop_grf_ctrl *grf_ctrl;
|
||||
|
||||
@@ -199,6 +199,26 @@ enum vop2_layer_phy_id {
|
||||
ROCKCHIP_VOP2_PHY_ID_INVALID = -1,
|
||||
};
|
||||
|
||||
struct vop2_power_domain {
|
||||
struct vop2_power_domain *parent;
|
||||
struct vop2 *vop2;
|
||||
/*
|
||||
* @lock: protect power up/down procedure.
|
||||
* power on take effect immediately,
|
||||
* power down take effect by vsync.
|
||||
* we must check power_domain_status register
|
||||
* to make sure the power domain is down before
|
||||
* send a power on request.
|
||||
*
|
||||
*/
|
||||
struct mutex lock;
|
||||
unsigned int ref_count;
|
||||
bool on;
|
||||
const struct vop2_power_domain_data *data;
|
||||
struct list_head list;
|
||||
struct delayed_work power_off_work;
|
||||
};
|
||||
|
||||
struct vop2_zpos {
|
||||
struct drm_plane *plane;
|
||||
int win_phys_id;
|
||||
@@ -308,6 +328,10 @@ struct vop2_win {
|
||||
|
||||
uint8_t splice_win_id;
|
||||
|
||||
struct vop2_power_domain *pd;
|
||||
|
||||
bool enabled;
|
||||
|
||||
/**
|
||||
* @phys_id: physical id for cluster0/1, esmart0/1, smart0/1
|
||||
* Will be used as a identification for some register
|
||||
@@ -419,6 +443,7 @@ struct vop2_wb {
|
||||
struct vop2_dsc {
|
||||
uint8_t id;
|
||||
const struct vop2_dsc_regs *regs;
|
||||
struct vop2_power_domain *pd;
|
||||
};
|
||||
|
||||
enum vop2_wb_format {
|
||||
@@ -643,6 +668,7 @@ struct vop2 {
|
||||
|
||||
/* list_head of internal clk */
|
||||
struct list_head clk_list_head;
|
||||
struct list_head pd_list_head;
|
||||
|
||||
struct vop2_layer layers[ROCKCHIP_MAX_LAYER];
|
||||
/* must put at the end of the struct */
|
||||
@@ -870,6 +896,18 @@ static struct vop2_win *vop2_find_win_by_phys_id(struct vop2 *vop2, uint8_t phys
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct vop2_power_domain *vop2_find_pd_by_id(struct vop2 *vop2, uint8_t id)
|
||||
{
|
||||
struct vop2_power_domain *pd, *n;
|
||||
|
||||
list_for_each_entry_safe(pd, n, &vop2->pd_list_head, list) {
|
||||
if (pd->data->id == id)
|
||||
return pd;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const struct vop2_connector_if_data *vop2_find_connector_if_data(struct vop2 *vop2, int id)
|
||||
{
|
||||
const struct vop2_connector_if_data *if_data;
|
||||
@@ -1218,6 +1256,119 @@ static inline void vop2_cfg_done(struct drm_crtc *crtc)
|
||||
return rk3588_vop2_cfg_done(crtc);
|
||||
}
|
||||
|
||||
static uint32_t vop2_power_domain_status(struct vop2_power_domain *pd)
|
||||
{
|
||||
struct vop2 *vop2 = pd->vop2;
|
||||
|
||||
return vop2_read_reg(vop2, 0, &pd->data->regs->status);
|
||||
|
||||
}
|
||||
|
||||
static void vop2_wait_power_domain_off(struct vop2_power_domain *pd)
|
||||
{
|
||||
struct vop2 *vop2 = pd->vop2;
|
||||
int val;
|
||||
int ret;
|
||||
|
||||
ret = readx_poll_timeout(vop2_power_domain_status, pd, val, val, 100, 50 * 1000);
|
||||
|
||||
if (ret)
|
||||
DRM_DEV_ERROR(vop2->dev, "wait pd off timeout\n");
|
||||
}
|
||||
|
||||
static void vop2_wait_power_domain_on(struct vop2_power_domain *pd)
|
||||
{
|
||||
struct vop2 *vop2 = pd->vop2;
|
||||
int val;
|
||||
int ret;
|
||||
|
||||
ret = readx_poll_timeout_atomic(vop2_power_domain_status, pd, val, !val, 0, 50 * 1000);
|
||||
if (ret)
|
||||
DRM_DEV_ERROR(vop2->dev, "wait pd on timeout\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Power domain on take effect immediately
|
||||
*/
|
||||
static void vop2_power_domain_on(struct vop2_power_domain *pd)
|
||||
{
|
||||
struct vop2 *vop2 = pd->vop2;
|
||||
|
||||
if (!pd->on) {
|
||||
vop2_wait_power_domain_off(pd);
|
||||
VOP_MODULE_SET(vop2, pd->data, pd, 0);
|
||||
vop2_wait_power_domain_on(pd);
|
||||
pd->on = true;
|
||||
dev_dbg(vop2->dev, "pd%d on\n", pd->data->id);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Power domain off take effect by vsync.
|
||||
*/
|
||||
static void vop2_power_domain_off(struct vop2_power_domain *pd)
|
||||
{
|
||||
struct vop2 *vop2 = pd->vop2;
|
||||
|
||||
dev_dbg(vop2->dev, "pd%d off\n", pd->data->id);
|
||||
pd->on = false;
|
||||
VOP_MODULE_SET(vop2, pd->data, pd, 1);
|
||||
}
|
||||
|
||||
static void vop2_power_domain_get(struct vop2_power_domain *pd)
|
||||
{
|
||||
mutex_lock(&pd->lock);
|
||||
if (pd->parent)
|
||||
vop2_power_domain_get(pd->parent);
|
||||
if (pd->ref_count == 0) {
|
||||
if (pd->vop2->data->delayed_pd)
|
||||
cancel_delayed_work(&pd->power_off_work);
|
||||
vop2_power_domain_on(pd);
|
||||
}
|
||||
pd->ref_count++;
|
||||
mutex_unlock(&pd->lock);
|
||||
}
|
||||
|
||||
static void vop2_power_domain_put(struct vop2_power_domain *pd)
|
||||
{
|
||||
mutex_lock(&pd->lock);
|
||||
if (--pd->ref_count == 0) {
|
||||
if (pd->vop2->data->delayed_pd)
|
||||
schedule_delayed_work(&pd->power_off_work, msecs_to_jiffies(2500));
|
||||
else
|
||||
vop2_power_domain_off(pd);
|
||||
}
|
||||
|
||||
if (pd->parent)
|
||||
vop2_power_domain_put(pd->parent);
|
||||
mutex_unlock(&pd->lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called if the pd ref_count reach 0 after 2.5
|
||||
* seconds.
|
||||
*/
|
||||
static void vop2_power_domain_off_work(struct work_struct *work)
|
||||
{
|
||||
struct vop2_power_domain *pd;
|
||||
|
||||
pd = container_of(to_delayed_work(work), struct vop2_power_domain, power_off_work);
|
||||
|
||||
mutex_lock(&pd->lock);
|
||||
if (pd->ref_count == 0)
|
||||
vop2_power_domain_off(pd);
|
||||
mutex_unlock(&pd->lock);
|
||||
}
|
||||
|
||||
static void vop2_win_enable(struct vop2_win *win)
|
||||
{
|
||||
if (!win->enabled) {
|
||||
if (win->pd)
|
||||
vop2_power_domain_get(win->pd);
|
||||
win->enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void vop2_win_multi_area_disable(struct vop2_win *parent)
|
||||
{
|
||||
struct vop2 *vop2 = parent->vop2;
|
||||
@@ -1238,27 +1389,33 @@ static void vop2_win_disable(struct vop2_win *win)
|
||||
win->left_win = NULL;
|
||||
win->splice_win = NULL;
|
||||
win->splice_mode_right = false;
|
||||
VOP_WIN_SET(vop2, win, enable, 0);
|
||||
if (win->feature & WIN_FEATURE_CLUSTER_MAIN) {
|
||||
struct vop2_win *sub_win;
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < vop2->registered_num_wins; i++) {
|
||||
sub_win = &vop2->win[i];
|
||||
if (win->enabled) {
|
||||
VOP_WIN_SET(vop2, win, enable, 0);
|
||||
if (win->feature & WIN_FEATURE_CLUSTER_MAIN) {
|
||||
struct vop2_win *sub_win;
|
||||
int i = 0;
|
||||
|
||||
if ((sub_win->phys_id == win->phys_id) &&
|
||||
(sub_win->feature & WIN_FEATURE_CLUSTER_SUB))
|
||||
VOP_WIN_SET(vop2, sub_win, enable, 0);
|
||||
for (i = 0; i < vop2->registered_num_wins; i++) {
|
||||
sub_win = &vop2->win[i];
|
||||
|
||||
if ((sub_win->phys_id == win->phys_id) &&
|
||||
(sub_win->feature & WIN_FEATURE_CLUSTER_SUB))
|
||||
VOP_WIN_SET(vop2, sub_win, enable, 0);
|
||||
}
|
||||
|
||||
VOP_CLUSTER_SET(vop2, win, enable, 0);
|
||||
}
|
||||
|
||||
VOP_CLUSTER_SET(vop2, win, enable, 0);
|
||||
/*
|
||||
* disable all other multi area win if we want disable area0 here
|
||||
*/
|
||||
if (!win->parent && (win->feature & WIN_FEATURE_MULTI_AREA))
|
||||
vop2_win_multi_area_disable(win);
|
||||
if (win->pd)
|
||||
vop2_power_domain_put(win->pd);
|
||||
win->enabled = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* disable all other multi area win if we want disable area0 here
|
||||
*/
|
||||
if (!win->parent && (win->feature & WIN_FEATURE_MULTI_AREA))
|
||||
vop2_win_multi_area_disable(win);
|
||||
}
|
||||
|
||||
static inline void vop2_write_lut(struct vop2 *vop2, uint32_t offset, uint32_t v)
|
||||
@@ -2760,8 +2917,6 @@ static void rk3588_vop2_regsbak(struct vop2 *vop2)
|
||||
uint32_t *base = vop2->regs;
|
||||
int i = 0;
|
||||
|
||||
vop2_writel(vop2, RK3568_SYS_PD_CTRL, 0);
|
||||
|
||||
/*
|
||||
* No need to backup DSC/GAMMA_LUT/BPP_LUT/MMU
|
||||
*/
|
||||
@@ -2769,6 +2924,15 @@ static void rk3588_vop2_regsbak(struct vop2 *vop2)
|
||||
vop2->regsbak[i] = base[i];
|
||||
}
|
||||
|
||||
static void vop2_power_domain_init(struct vop2 *vop2)
|
||||
{
|
||||
struct vop2_power_domain *pd, *n;
|
||||
|
||||
list_for_each_entry_safe(pd, n, &vop2->pd_list_head, list) {
|
||||
vop2_power_domain_on(pd);
|
||||
}
|
||||
}
|
||||
|
||||
static void vop2_initial(struct drm_crtc *crtc)
|
||||
{
|
||||
struct vop2_video_port *vp = to_vop2_video_port(crtc);
|
||||
@@ -2797,6 +2961,8 @@ static void vop2_initial(struct drm_crtc *crtc)
|
||||
if (vop2_soc_is_rk3566())
|
||||
VOP_CTRL_SET(vop2, otp_en, 1);
|
||||
|
||||
vop2_power_domain_init(vop2);
|
||||
|
||||
/* dsc must deassert rst before its register can accessed */
|
||||
for (i = 0; i < vop2_data->nr_dscs; i++) {
|
||||
dsc = &vop2->dscs[i];
|
||||
@@ -3385,6 +3551,7 @@ static void vop2_win_atomic_update(struct vop2_win *win, struct drm_rect *src, s
|
||||
|
||||
afbc_half_block_en = vop2_afbc_half_block_enable(vpstate);
|
||||
|
||||
vop2_win_enable(win);
|
||||
spin_lock(&vop2->reg_lock);
|
||||
DRM_DEV_DEBUG(vop2->dev, "vp%d update %s[%dx%d->%dx%d@%dx%d] fmt[%.4s_%s] addr[%pad]\n",
|
||||
vp->id, win->name, actual_w, actual_h, dsp_w, dsp_h,
|
||||
@@ -7085,6 +7252,37 @@ static void vop2_destroy_crtc(struct drm_crtc *crtc)
|
||||
drm_flip_work_cleanup(&vp->fb_unref_work);
|
||||
}
|
||||
|
||||
static int vop2_pd_data_init(struct vop2 *vop2)
|
||||
{
|
||||
const struct vop2_data *vop2_data = vop2->data;
|
||||
const struct vop2_power_domain_data *pd_data;
|
||||
struct vop2_power_domain *pd;
|
||||
int i;
|
||||
|
||||
INIT_LIST_HEAD(&vop2->pd_list_head);
|
||||
|
||||
for (i = 0; i < vop2_data->nr_pds; i++) {
|
||||
pd_data = &vop2_data->pd[i];
|
||||
pd = devm_kzalloc(vop2->dev, sizeof(*pd), GFP_KERNEL);
|
||||
if (!pd)
|
||||
return -ENOMEM;
|
||||
pd->vop2 = vop2;
|
||||
pd->data = pd_data;
|
||||
mutex_init(&pd->lock);
|
||||
list_add_tail(&pd->list, &vop2->pd_list_head);
|
||||
INIT_DELAYED_WORK(&pd->power_off_work, vop2_power_domain_off_work);
|
||||
if (pd_data->parent_id) {
|
||||
pd->parent = vop2_find_pd_by_id(vop2, pd_data->parent_id);
|
||||
if (!pd->parent) {
|
||||
DRM_DEV_ERROR(vop2->dev, "no parent pd find for pd%d\n", pd->data->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vop2_dsc_data_init(struct vop2 *vop2)
|
||||
{
|
||||
const struct vop2_data *vop2_data = vop2->data;
|
||||
@@ -7097,6 +7295,8 @@ static void vop2_dsc_data_init(struct vop2 *vop2)
|
||||
dsc_data = &vop2_data->dsc[i];
|
||||
dsc->id = dsc_data->id;
|
||||
dsc->regs = dsc_data->regs;
|
||||
if (dsc_data->pd_id)
|
||||
dsc->pd = vop2_find_pd_by_id(vop2, dsc_data->pd_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7141,6 +7341,9 @@ static int vop2_win_init(struct vop2 *vop2)
|
||||
win->zpos = i;
|
||||
win->vop2 = vop2;
|
||||
|
||||
if (win_data->pd_id)
|
||||
win->pd = vop2_find_pd_by_id(vop2, win_data->pd_id);
|
||||
|
||||
num_wins++;
|
||||
|
||||
if (!vop2->support_multi_area)
|
||||
@@ -7248,6 +7451,10 @@ static int vop2_bind(struct device *dev, struct device *master, void *data)
|
||||
vop2->support_multi_area = of_property_read_bool(dev->of_node, "support-multi-area");
|
||||
vop2->disable_afbc_win = of_property_read_bool(dev->of_node, "disable-afbc-win");
|
||||
|
||||
ret = vop2_pd_data_init(vop2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = vop2_win_init(vop2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -464,10 +464,13 @@ static const struct vop2_dsc_data rk3588_vop_dsc_data[] = {
|
||||
{
|
||||
.id = 0,
|
||||
.regs = &rk3588_vop_dsc0_regs,
|
||||
.pd_id = VOP2_PD_DSC_8K,
|
||||
},
|
||||
|
||||
{
|
||||
.id = 1,
|
||||
.regs = &rk3588_vop_dsc1_regs,
|
||||
.pd_id = VOP2_PD_DSC_4K,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1783,6 +1786,90 @@ static const struct vop2_win_data rk3568_vop_win_data[] = {
|
||||
},
|
||||
};
|
||||
|
||||
const struct vop2_power_domain_regs rk3588_cluster0_pd_regs = {
|
||||
.pd = VOP_REG(RK3568_SYS_PD_CTRL, 0x1, 0),
|
||||
.status = VOP_REG(RK3568_SYS_STATUS0, 0x1, 8),
|
||||
};
|
||||
|
||||
const struct vop2_power_domain_regs rk3588_cluster1_pd_regs = {
|
||||
.pd = VOP_REG(RK3568_SYS_PD_CTRL, 0x1, 1),
|
||||
.status = VOP_REG(RK3568_SYS_STATUS0, 0x1, 9),
|
||||
};
|
||||
|
||||
const struct vop2_power_domain_regs rk3588_cluster2_pd_regs = {
|
||||
.pd = VOP_REG(RK3568_SYS_PD_CTRL, 0x1, 2),
|
||||
.status = VOP_REG(RK3568_SYS_STATUS0, 0x1, 10),
|
||||
};
|
||||
|
||||
const struct vop2_power_domain_regs rk3588_cluster3_pd_regs = {
|
||||
.pd = VOP_REG(RK3568_SYS_PD_CTRL, 0x1, 3),
|
||||
.status = VOP_REG(RK3568_SYS_STATUS0, 0x1, 11),
|
||||
};
|
||||
|
||||
const struct vop2_power_domain_regs rk3588_esmart_pd_regs = {
|
||||
.pd = VOP_REG(RK3568_SYS_PD_CTRL, 0x1, 7),
|
||||
.status = VOP_REG(RK3568_SYS_STATUS0, 0x1, 15),
|
||||
};
|
||||
|
||||
const struct vop2_power_domain_regs rk3588_dsc_8k_pd_regs = {
|
||||
.pd = VOP_REG(RK3568_SYS_PD_CTRL, 0x1, 5),
|
||||
.status = VOP_REG(RK3568_SYS_STATUS0, 0x1, 13),
|
||||
};
|
||||
|
||||
const struct vop2_power_domain_regs rk3588_dsc_4k_pd_regs = {
|
||||
.pd = VOP_REG(RK3568_SYS_PD_CTRL, 0x1, 6),
|
||||
.status = VOP_REG(RK3568_SYS_STATUS0, 0x1, 14),
|
||||
};
|
||||
|
||||
/*
|
||||
* There are 7 internal power domains on rk3588 vop,
|
||||
* Cluster0/1/2/3 each have on pd, and PD_CLUSTER0 as parent,
|
||||
* that means PD_CLUSTER0 should turn on first before
|
||||
* PD_CLUSTER1/2/3 turn on.
|
||||
*
|
||||
* Esmart0/1/2/3 share one pd PD_ESMART0.
|
||||
* DSC_8K/DSC_4K each have on pd.
|
||||
*/
|
||||
static const struct vop2_power_domain_data rk3588_vop_pd_data[] = {
|
||||
{
|
||||
.id = VOP2_PD_CLUSTER0,
|
||||
.regs = &rk3588_cluster0_pd_regs,
|
||||
},
|
||||
|
||||
{
|
||||
.id = VOP2_PD_CLUSTER1,
|
||||
.parent_id = VOP2_PD_CLUSTER0,
|
||||
.regs = &rk3588_cluster1_pd_regs,
|
||||
},
|
||||
|
||||
{
|
||||
.id = VOP2_PD_CLUSTER2,
|
||||
.parent_id = VOP2_PD_CLUSTER0,
|
||||
.regs = &rk3588_cluster0_pd_regs,
|
||||
},
|
||||
|
||||
{
|
||||
.id = VOP2_PD_CLUSTER3,
|
||||
.parent_id = VOP2_PD_CLUSTER0,
|
||||
.regs = &rk3588_cluster1_pd_regs,
|
||||
},
|
||||
|
||||
{
|
||||
.id = VOP2_PD_ESMART0,
|
||||
.regs = &rk3588_esmart_pd_regs,
|
||||
},
|
||||
|
||||
{
|
||||
.id = VOP2_PD_DSC_8K,
|
||||
.regs = &rk3588_dsc_8k_pd_regs,
|
||||
},
|
||||
|
||||
{
|
||||
.id = VOP2_PD_DSC_4K,
|
||||
.regs = &rk3588_dsc_4k_pd_regs,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* rk3588 vop with 4 cluster, 4 esmart win.
|
||||
* Every cluster can work as 4K win or split into two win.
|
||||
@@ -1817,6 +1904,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = {
|
||||
.vsu_filter_mode = VOP2_SCALE_UP_BIL,
|
||||
.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
|
||||
.regs = &rk3568_cluster0_win_data,
|
||||
.pd_id = VOP2_PD_CLUSTER0,
|
||||
.max_upscale_factor = 4,
|
||||
.max_downscale_factor = 4,
|
||||
.dly = { 4, 26, 29 },
|
||||
@@ -1859,6 +1947,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = {
|
||||
.vsu_filter_mode = VOP2_SCALE_UP_BIL,
|
||||
.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
|
||||
.regs = &rk3568_cluster1_win_data,
|
||||
.pd_id = VOP2_PD_CLUSTER1,
|
||||
.type = DRM_PLANE_TYPE_OVERLAY,
|
||||
.max_upscale_factor = 4,
|
||||
.max_downscale_factor = 4,
|
||||
@@ -1889,6 +1978,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = {
|
||||
{
|
||||
.name = "Cluster2-win0",
|
||||
.phys_id = ROCKCHIP_VOP2_CLUSTER2,
|
||||
.pd_id = VOP2_PD_CLUSTER2,
|
||||
.splice_win_id = ROCKCHIP_VOP2_CLUSTER3,
|
||||
.base = 0x00,
|
||||
.formats = formats_win_full_10bit,
|
||||
@@ -1932,6 +2022,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = {
|
||||
{
|
||||
.name = "Cluster3-win0",
|
||||
.phys_id = ROCKCHIP_VOP2_CLUSTER3,
|
||||
.pd_id = VOP2_PD_CLUSTER3,
|
||||
.base = 0x00,
|
||||
.formats = formats_win_full_10bit,
|
||||
.nformats = ARRAY_SIZE(formats_win_full_10bit),
|
||||
@@ -1974,6 +2065,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = {
|
||||
{
|
||||
.name = "Esmart0-win0",
|
||||
.phys_id = ROCKCHIP_VOP2_ESMART0,
|
||||
.pd_id = VOP2_PD_ESMART0,
|
||||
.splice_win_id = ROCKCHIP_VOP2_ESMART1,
|
||||
.formats = formats_win_full_10bit,
|
||||
.nformats = ARRAY_SIZE(formats_win_full_10bit),
|
||||
@@ -1998,6 +2090,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = {
|
||||
{
|
||||
.name = "Esmart2-win0",
|
||||
.phys_id = ROCKCHIP_VOP2_ESMART2,
|
||||
.pd_id = VOP2_PD_ESMART0,
|
||||
.splice_win_id = ROCKCHIP_VOP2_ESMART3,
|
||||
.base = 0x400,
|
||||
.formats = formats_win_full_10bit,
|
||||
@@ -2022,6 +2115,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = {
|
||||
{
|
||||
.name = "Esmart1-win0",
|
||||
.phys_id = ROCKCHIP_VOP2_ESMART1,
|
||||
.pd_id = VOP2_PD_ESMART0,
|
||||
.formats = formats_win_full_10bit,
|
||||
.nformats = ARRAY_SIZE(formats_win_full_10bit),
|
||||
.format_modifiers = format_modifiers,
|
||||
@@ -2044,6 +2138,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = {
|
||||
{
|
||||
.name = "Esmart3-win0",
|
||||
.phys_id = ROCKCHIP_VOP2_ESMART3,
|
||||
.pd_id = VOP2_PD_ESMART0,
|
||||
.formats = formats_win_full_10bit,
|
||||
.nformats = ARRAY_SIZE(formats_win_full_10bit),
|
||||
.format_modifiers = format_modifiers,
|
||||
@@ -2235,6 +2330,7 @@ static const struct vop2_data rk3588_vop = {
|
||||
.nr_vps = 4,
|
||||
.nr_mixers = 7,
|
||||
.nr_layers = 8,
|
||||
.nr_pds = 7,
|
||||
.max_input = { 8192, 4320 },
|
||||
.max_output = { 4096, 2304 },
|
||||
.ctrl = &rk3588_vop_ctrl,
|
||||
@@ -2248,6 +2344,8 @@ static const struct vop2_data rk3588_vop = {
|
||||
.layer = rk3568_vop_layers,
|
||||
.win = rk3588_vop_win_data,
|
||||
.win_size = ARRAY_SIZE(rk3588_vop_win_data),
|
||||
.pd = rk3588_vop_pd_data,
|
||||
.nr_pds = ARRAY_SIZE(rk3588_vop_pd_data),
|
||||
};
|
||||
|
||||
static const struct of_device_id vop2_dt_match[] = {
|
||||
|
||||
@@ -1055,9 +1055,12 @@
|
||||
#define RK3568_WB_XSCAL_FACTOR 0x44
|
||||
#define RK3568_WB_YRGB_MST 0x48
|
||||
#define RK3568_WB_CBR_MST 0x4C
|
||||
#define RK3568_OTP_WIN_EN 0x050
|
||||
#define RK3568_LUT_PORT_SEL 0x058
|
||||
#define RK3568_SYS_STATUS0 0x060
|
||||
#define RK3568_OTP_WIN_EN 0x50
|
||||
#define RK3568_LUT_PORT_SEL 0x58
|
||||
#define RK3568_SYS_STATUS0 0x60
|
||||
#define RK3568_SYS_STATUS1 0x64
|
||||
#define RK3568_SYS_STATUS2 0x68
|
||||
#define RK3568_SYS_STATUS3 0x6C
|
||||
#define RK3568_VP0_LINE_FLAG 0x70
|
||||
#define RK3568_VP1_LINE_FLAG 0x74
|
||||
#define RK3568_VP2_LINE_FLAG 0x78
|
||||
|
||||
Reference in New Issue
Block a user