summaryrefslogtreecommitdiff
path: root/bsp/rockchip/dm/graphic/framebuffer/fb-vop2.h
blob: 10bc6eb3de7b138a39c559cff0a012d27b8ab376 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
/*
 * Copyright (c) 2006-2023, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2023-09-23     GuEe-GUI     first version
 */

#ifndef __FB_VOP2_H__
#define __FB_VOP2_H__

#include "rockchip-display.h"

#define VOP2FB_CURSOR_W                 64
#define VOP2FB_CURSOR_H                 64

#define VOP2FB_OVERLAY_MAX              6
#define VOP2FB_VP_MAX                   4

/* System */
#define VOP2_REG_CFG_DONE               0x000
#define VOP2_CFG_DONE_EN                RT_BIT(15)

#define VOP2_EN_MASK                    1

/* Cluster layer (RK3568 layout) */
#define VOP2_CLUSTER0_BASE              0x1000
#define VOP2_CLUSTER_STRIDE             0x200

#define VOP2_CLUSTER_WIN0_CTRL0         0x00
#define VOP2_CLUSTER_WIN0_CTRL2         0x08
#define VOP2_CLUSTER_WIN0_YRGB_MST      0x10
#define VOP2_CLUSTER_WIN0_VIR           0x18
#define VOP2_CLUSTER_WIN0_ACT_INFO      0x20
#define VOP2_CLUSTER_WIN0_DSP_INFO      0x24
#define VOP2_CLUSTER_WIN0_DSP_ST        0x28
#define VOP2_CLUSTER_CTRL               0x100
#define VOP2_CLUSTER_EN_SHIFT           0

#define VOP2_CLUSTER_AXI_ID_SHIFT       13
#define VOP2_CLUSTER_AXI_YRGB_ID_SHIFT  0
#define VOP2_CLUSTER_AXI_UV_ID_SHIFT    5
#define VOP2_CLUSTER_AXI_YRGB_ID_MASK   0x1f
#define VOP2_CLUSTER_AXI_UV_ID_MASK     0x1f
#define VOP2_CLUSTER_AXI_ID_MASK        0x1

/* Esmart / Smart shared region layout */
#define VOP2_ESMART0_BASE               0x1800
#define VOP2_SMART0_BASE                0x1C00
#define VOP2_ESMART_STRIDE              0x200
#define VOP2_SMART_STRIDE               0x200

#define VOP2_ESMART_CTRL0               0x00
#define VOP2_ESMART_AXI_CTRL            0x08
#define VOP2_ESMART_CTRL1               0x04
#define VOP2_ESMART_AXI_ID_SHIFT        1
#define VOP2_ESMART_AXI_YRGB_ID_SHIFT   0
#define VOP2_ESMART_AXI_UV_ID_SHIFT     12
#define VOP2_ESMART_AXI_ID_MASK         0x1
#define VOP2_ESMART_AXI_YRGB_ID_MASK    0x1f
#define VOP2_ESMART_AXI_UV_ID_MASK      0x1f
#define VOP2_RGB2YUV_EN_SHIFT           1
#define VOP2_CSC_MODE_SHIFT             2
#define VOP2_CSC_MODE_MASK              0x3

#define VOP2_REGION0_CTRL               0x10
#define VOP2_REGION0_YRGB_MST           0x14
#define VOP2_REGION0_CBR_MST            0x18
#define VOP2_REGION0_VIR                0x1c
#define VOP2_REGION0_ACT_INFO           0x20
#define VOP2_REGION0_DSP_INFO           0x24
#define VOP2_REGION0_DSP_ST             0x28
#define VOP2_REGION0_SCL_CTRL           0x30
#define VOP2_REGION0_SCL_FACTOR_YRGB    0x34
#define VOP2_REGION0_SCL_FACTOR_CBR     0x38
#define VOP2_REGION0_SCL_OFFSET         0x3c
#define VOP2_YMIRROR_EN_SHIFT           31

#define VOP2_WIN_EN_SHIFT               0
#define VOP2_WIN_FORMAT_MASK            0x1f
#define VOP2_WIN_FORMAT_SHIFT           1
#define VOP2_REGION0_DITHER_UP_EN_SHIFT 12
#define VOP2_REGION0_RB_SWAP_SHIFT      14
#define VOP2_YRGB_GT2_SHIFT             8
#define VOP2_YRGB_GT4_SHIFT             9

enum vop2fb_soc
{
    VOP2FB_SOC_RK3568 = 0,
    VOP2FB_SOC_RK3588,
    VOP2FB_SOC_RK3528,
    VOP2FB_SOC_RK3562,
    VOP2FB_SOC_RK3576,
};

enum vop2fb_layer_type
{
    VOP2FB_LAYER_CLUSTER = 0,
    VOP2FB_LAYER_ESMART,
    VOP2FB_LAYER_SMART,
};

enum vop2fb_hw_format
{
    VOP2FB_FMT_ARGB8888 = 0,
    VOP2FB_FMT_RGB888,
    VOP2FB_FMT_RGB565,
};

enum vop2fb_output_if
{
    VOP2FB_OUTPUT_NONE = 0,
    VOP2FB_OUTPUT_HDMI,
    VOP2FB_OUTPUT_EDP,
    VOP2FB_OUTPUT_MIPI0,
    VOP2FB_OUTPUT_MIPI1,
    VOP2FB_OUTPUT_LVDS,
    VOP2FB_OUTPUT_RGB,
};

struct vop2fb_win_desc
{
    const char *name;
    enum vop2fb_layer_type type;
    rt_uint32_t base_offset;
    rt_uint8_t layer_sel_id;
    rt_uint8_t win_sel_port_offset;
    rt_uint8_t z_order;
    rt_uint8_t axi_id;
    rt_uint8_t axi_yrgb_id;
    rt_uint8_t axi_uv_id;
    rt_int8_t plane_id;
    rt_uint32_t mix_alpha_reg;
};

struct vop2fb_soc_data
{
    enum vop2fb_soc soc;
    const char *version;
    rt_size_t reg_size;
    rt_size_t regbak_words;
    const struct vop2fb_win_desc *primary;
    const struct vop2fb_win_desc *cursor;
    const struct vop2fb_win_desc *overlays;
    rt_size_t overlay_count;
    const struct vop2fb_win_desc *const *route_windows;
    rt_size_t route_window_count;
    rt_bool_t axi_config;
    rt_bool_t irq_by_vp;
    rt_uint32_t vp_count;
};

struct vop2fb;

struct vop2fb_plane_priv
{
    struct vop2fb *vfb;
    const struct vop2fb_win_desc *desc;
    rt_ubase_t dma_handle;
    rt_ubase_t dma_flags;
    rt_uint32_t pan_offset;
    rt_uint32_t vp_id;
    rt_bool_t enabled;
};

struct vop2fb_vp_state
{
    struct display_timing timing;
    enum vop2fb_output_if output_if;
    const struct vop2fb_win_desc *scanout;
    struct vop2fb *vfb;
    struct rt_graphic_device auxiliary;
    struct rt_graphic_device *graphic;
    struct rt_graphic_plane *primary;
    rt_atomic_t vsync;
    struct rt_semaphore vsync_sem;
    struct rt_mutex vsync_lock;
    rt_uint32_t vp_id;
    rt_bool_t mode_valid;
    rt_bool_t enabled;
    rt_bool_t dclk_enabled;
    rt_bool_t ipc_ready;
    rt_bool_t registered;
};

struct vop2fb
{
    struct rt_graphic_device parent;
    struct rt_device *dev;

    const struct vop2fb_soc_data *soc;

    void *regs;
    rt_uint32_t *regsbak;

    rt_uint32_t display_w;
    rt_uint32_t display_h;
    rt_uint32_t vp_id;

    rt_uint32_t hw_format;
    enum vop2fb_output_if output_if;

    struct display_timing output_tim;
    rt_bool_t output_tim_valid;
    struct vop2fb_vp_state vp[VOP2FB_VP_MAX];
    rt_uint32_t configured_vp_mask;
    rt_uint32_t active_vp_mask;

    rt_bool_t clk_enabled;
    struct rt_clk_array *clks;
    struct rt_spinlock reg_lock;

    int irq;
    rt_uint32_t post_buf_empty_count[VOP2FB_VP_MAX];
    rt_uint32_t axi_bus_error_count[2];

    struct rt_graphic_plane *primary;
    struct rt_graphic_plane *cursor;
    struct rt_graphic_plane *overlays[VOP2FB_OVERLAY_MAX];
    rt_size_t overlay_count;

    rt_bool_t registered;
    rt_bool_t powered;
};

rt_uint32_t vop2fb_mode_to_hw(rt_uint32_t mode);
rt_uint32_t vop2fb_hw_to_bpp(rt_uint32_t hw_fmt);

rt_inline void vop2fb_reg_write(struct vop2fb *vfb, rt_uint32_t offset, rt_uint32_t v)
{
    rt_uint32_t idx = offset >> 2;

    HWREG32((rt_uint8_t *)vfb->regs + offset) = v;

    if (vfb->regsbak && idx < vfb->soc->regbak_words)
    {
        vfb->regsbak[idx] = v;
    }
}

rt_inline void vop2fb_mask_write(struct vop2fb *vfb, rt_uint32_t offset,
        rt_uint32_t mask, rt_uint32_t shift, rt_uint32_t v)
{
    rt_uint32_t idx = offset >> 2;
    rt_uint32_t cached, newv;

    if (!mask || !vfb->regsbak || idx >= vfb->soc->regbak_words)
    {
        return;
    }

    cached = vfb->regsbak[idx];
    newv = (cached & ~(mask << shift)) | ((v & mask) << shift);
    vop2fb_reg_write(vfb, offset, newv);
}

rt_inline rt_uint32_t vop2fb_cfg_done_pending(struct vop2fb *vfb)
{
    /*
     * RK3568 VP done bits have no hiword write mask.  Preserve any update
     * that another VP has queued but has not latched at frame start yet.
     */
    if (vfb && vfb->regs && vfb->soc &&
            vfb->soc->soc == VOP2FB_SOC_RK3568)
    {
        return HWREG32((rt_uint8_t *)vfb->regs + VOP2_REG_CFG_DONE) & 0x7;
    }

    return 0;
}

rt_inline rt_uint32_t vop2fb_cfg_done_vp_val(struct vop2fb *vfb, rt_uint32_t vp)
{
    if (vfb && vfb->soc && vfb->soc->soc == VOP2FB_SOC_RK3568)
    {
        return VOP2_CFG_DONE_EN | RT_BIT(vp) | vop2fb_cfg_done_pending(vfb);
    }

    return VOP2_CFG_DONE_EN | RT_BIT(vp) | (RT_BIT(vp) << 16);
}

rt_inline rt_uint32_t vop2fb_cfg_done_val(struct vop2fb *vfb)
{
    return vop2fb_cfg_done_vp_val(vfb, vfb->vp_id);
}

rt_inline rt_uint32_t vop2fb_cfg_done_mask_val(struct vop2fb *vfb,
        rt_uint32_t vp_mask)
{
    if (vfb && vfb->soc && vfb->soc->soc == VOP2FB_SOC_RK3568)
    {
        return VOP2_CFG_DONE_EN | vp_mask | vop2fb_cfg_done_pending(vfb);
    }

    return VOP2_CFG_DONE_EN | vp_mask | (vp_mask << 16);
}

#endif /* __FB_VOP2_H__ */