aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/rockchip
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2016-08-24 22:35:35 -0400
committerDave Airlie <airlied@redhat.com>2016-08-24 22:35:35 -0400
commit78acdd4a7e5a5de56c4ac1e10390a98b7c605ed6 (patch)
tree1825104346edc7eeb41bad49c64a3692c26e3efd /drivers/gpu/drm/rockchip
parent0d42204f374380b6334de7dd2fe7e7d795250290 (diff)
parent808263393198b9b0f9d53b9983330fb4298851ec (diff)
Merge branch 'for-next' of git://people.freedesktop.org/~seanpaul/dogwood into drm-next
This pull request contains the following rockchip drm changes: - Introduce support for rk3399 vop/crtc - Add PSR framework to the rockchip driver - Implement PSR in the rockchip analogix edp driver - Fix panel on/off in analogix to avoid damaging panels - Some miscellaneous fixes to clean up logs and code readability * 'for-next' of git://people.freedesktop.org/~seanpaul/dogwood: drm/rockchip: analogix_dp: drop unnecessary probe deferral "error" print drm/rockchip: Enable vblank without event drm/rockchip: Improve analogix-dp psr handling drm/rockchip: A couple small fixes to psr drm/rockchip: Use a spinlock to protect psr state drm/rockchip: Don't use a delayed worker for psr state changes drm/rockchip: Convert psr_list_mutex to spinlock and use it drm/rockchip: analogix_dp: implement PSR function drm/bridge: analogix_dp: add the PSR function support drm/rockchip: add an common abstracted PSR driver drm/rockchip: vop: export line flag function drm/bridge: analogix_dp: Ensure the panel is properly prepared/unprepared dt-bindings: add compatible strings for big/little rockchip vops dt-bindings: sort Rockchip vop compatible by chip's number drm/rockchip: vop: add rk3399 vop support drm/rockchip: vop: introduce VOP_REG_MASK drm/rockchip: sort registers define by chip's number
Diffstat (limited to 'drivers/gpu/drm/rockchip')
-rw-r--r--drivers/gpu/drm/rockchip/Makefile2
-rw-r--r--drivers/gpu/drm/rockchip/analogix_dp-rockchip.c70
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_drv.c3
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_drv.h6
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_fb.c12
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_psr.c245
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_psr.h26
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop.c198
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop.h7
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_vop_reg.c242
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_vop_reg.h193
11 files changed, 898 insertions, 106 deletions
diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile
index 05d07138a2b2..9746365694ba 100644
--- a/drivers/gpu/drm/rockchip/Makefile
+++ b/drivers/gpu/drm/rockchip/Makefile
@@ -3,7 +3,7 @@
3# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. 3# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
4 4
5rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \ 5rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
6 rockchip_drm_gem.o rockchip_drm_vop.o 6 rockchip_drm_gem.o rockchip_drm_psr.o rockchip_drm_vop.o
7rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o 7rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
8 8
9obj-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o 9obj-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index 0e63ee25bef8..e83be157cc2a 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -32,6 +32,7 @@
32#include <drm/bridge/analogix_dp.h> 32#include <drm/bridge/analogix_dp.h>
33 33
34#include "rockchip_drm_drv.h" 34#include "rockchip_drm_drv.h"
35#include "rockchip_drm_psr.h"
35#include "rockchip_drm_vop.h" 36#include "rockchip_drm_vop.h"
36 37
37#define RK3288_GRF_SOC_CON6 0x25c 38#define RK3288_GRF_SOC_CON6 0x25c
@@ -41,6 +42,8 @@
41 42
42#define HIWORD_UPDATE(val, mask) (val | (mask) << 16) 43#define HIWORD_UPDATE(val, mask) (val | (mask) << 16)
43 44
45#define PSR_WAIT_LINE_FLAG_TIMEOUT_MS 100
46
44#define to_dp(nm) container_of(nm, struct rockchip_dp_device, nm) 47#define to_dp(nm) container_of(nm, struct rockchip_dp_device, nm)
45 48
46/** 49/**
@@ -68,11 +71,62 @@ struct rockchip_dp_device {
68 struct regmap *grf; 71 struct regmap *grf;
69 struct reset_control *rst; 72 struct reset_control *rst;
70 73
74 struct work_struct psr_work;
75 spinlock_t psr_lock;
76 unsigned int psr_state;
77
71 const struct rockchip_dp_chip_data *data; 78 const struct rockchip_dp_chip_data *data;
72 79
73 struct analogix_dp_plat_data plat_data; 80 struct analogix_dp_plat_data plat_data;
74}; 81};
75 82
83static void analogix_dp_psr_set(struct drm_encoder *encoder, bool enabled)
84{
85 struct rockchip_dp_device *dp = to_dp(encoder);
86 unsigned long flags;
87
88 dev_dbg(dp->dev, "%s PSR...\n", enabled ? "Entry" : "Exit");
89
90 spin_lock_irqsave(&dp->psr_lock, flags);
91 if (enabled)
92 dp->psr_state = EDP_VSC_PSR_STATE_ACTIVE;
93 else
94 dp->psr_state = ~EDP_VSC_PSR_STATE_ACTIVE;
95
96 schedule_work(&dp->psr_work);
97 spin_unlock_irqrestore(&dp->psr_lock, flags);
98}
99
100static void analogix_dp_psr_work(struct work_struct *work)
101{
102 struct rockchip_dp_device *dp =
103 container_of(work, typeof(*dp), psr_work);
104 struct drm_crtc *crtc = dp->encoder.crtc;
105 int psr_state = dp->psr_state;
106 int vact_end;
107 int ret;
108 unsigned long flags;
109
110 if (!crtc)
111 return;
112
113 vact_end = crtc->mode.vtotal - crtc->mode.vsync_start + crtc->mode.vdisplay;
114
115 ret = rockchip_drm_wait_line_flag(dp->encoder.crtc, vact_end,
116 PSR_WAIT_LINE_FLAG_TIMEOUT_MS);
117 if (ret) {
118 dev_err(dp->dev, "line flag interrupt did not arrive\n");
119 return;
120 }
121
122 spin_lock_irqsave(&dp->psr_lock, flags);
123 if (psr_state == EDP_VSC_PSR_STATE_ACTIVE)
124 analogix_dp_enable_psr(dp->dev);
125 else
126 analogix_dp_disable_psr(dp->dev);
127 spin_unlock_irqrestore(&dp->psr_lock, flags);
128}
129
76static int rockchip_dp_pre_init(struct rockchip_dp_device *dp) 130static int rockchip_dp_pre_init(struct rockchip_dp_device *dp)
77{ 131{
78 reset_control_assert(dp->rst); 132 reset_control_assert(dp->rst);
@@ -87,6 +141,8 @@ static int rockchip_dp_poweron(struct analogix_dp_plat_data *plat_data)
87 struct rockchip_dp_device *dp = to_dp(plat_data); 141 struct rockchip_dp_device *dp = to_dp(plat_data);
88 int ret; 142 int ret;
89 143
144 cancel_work_sync(&dp->psr_work);
145
90 ret = clk_prepare_enable(dp->pclk); 146 ret = clk_prepare_enable(dp->pclk);
91 if (ret < 0) { 147 if (ret < 0) {
92 dev_err(dp->dev, "failed to enable pclk %d\n", ret); 148 dev_err(dp->dev, "failed to enable pclk %d\n", ret);
@@ -342,12 +398,22 @@ static int rockchip_dp_bind(struct device *dev, struct device *master,
342 dp->plat_data.power_off = rockchip_dp_powerdown; 398 dp->plat_data.power_off = rockchip_dp_powerdown;
343 dp->plat_data.get_modes = rockchip_dp_get_modes; 399 dp->plat_data.get_modes = rockchip_dp_get_modes;
344 400
401 spin_lock_init(&dp->psr_lock);
402 dp->psr_state = ~EDP_VSC_PSR_STATE_ACTIVE;
403 INIT_WORK(&dp->psr_work, analogix_dp_psr_work);
404
405 rockchip_drm_psr_register(&dp->encoder, analogix_dp_psr_set);
406
345 return analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data); 407 return analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data);
346} 408}
347 409
348static void rockchip_dp_unbind(struct device *dev, struct device *master, 410static void rockchip_dp_unbind(struct device *dev, struct device *master,
349 void *data) 411 void *data)
350{ 412{
413 struct rockchip_dp_device *dp = dev_get_drvdata(dev);
414
415 rockchip_drm_psr_unregister(&dp->encoder);
416
351 return analogix_dp_unbind(dev, master, data); 417 return analogix_dp_unbind(dev, master, data);
352} 418}
353 419
@@ -381,10 +447,8 @@ static int rockchip_dp_probe(struct platform_device *pdev)
381 447
382 panel = of_drm_find_panel(panel_node); 448 panel = of_drm_find_panel(panel_node);
383 of_node_put(panel_node); 449 of_node_put(panel_node);
384 if (!panel) { 450 if (!panel)
385 DRM_ERROR("failed to find panel\n");
386 return -EPROBE_DEFER; 451 return -EPROBE_DEFER;
387 }
388 } 452 }
389 453
390 dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL); 454 dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index a822d49a255a..76eaf1de52e4 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -156,6 +156,9 @@ static int rockchip_drm_bind(struct device *dev)
156 156
157 drm_dev->dev_private = private; 157 drm_dev->dev_private = private;
158 158
159 INIT_LIST_HEAD(&private->psr_list);
160 spin_lock_init(&private->psr_list_lock);
161
159 drm_mode_config_init(drm_dev); 162 drm_mode_config_init(drm_dev);
160 163
161 rockchip_drm_mode_config_init(drm_dev); 164 rockchip_drm_mode_config_init(drm_dev);
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index ea3932940061..5c698456aa1c 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -61,6 +61,9 @@ struct rockchip_drm_private {
61 struct drm_gem_object *fbdev_bo; 61 struct drm_gem_object *fbdev_bo;
62 const struct rockchip_crtc_funcs *crtc_funcs[ROCKCHIP_MAX_CRTC]; 62 const struct rockchip_crtc_funcs *crtc_funcs[ROCKCHIP_MAX_CRTC];
63 struct drm_atomic_state *state; 63 struct drm_atomic_state *state;
64
65 struct list_head psr_list;
66 spinlock_t psr_list_lock;
64}; 67};
65 68
66int rockchip_register_crtc_funcs(struct drm_crtc *crtc, 69int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
@@ -70,4 +73,7 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
70 struct device *dev); 73 struct device *dev);
71void rockchip_drm_dma_detach_device(struct drm_device *drm_dev, 74void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
72 struct device *dev); 75 struct device *dev);
76int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num,
77 unsigned int mstimeout);
78
73#endif /* _ROCKCHIP_DRM_DRV_H_ */ 79#endif /* _ROCKCHIP_DRM_DRV_H_ */
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
index 55c52734c52d..ba45d9d8bb62 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
@@ -22,6 +22,7 @@
22#include "rockchip_drm_drv.h" 22#include "rockchip_drm_drv.h"
23#include "rockchip_drm_fb.h" 23#include "rockchip_drm_fb.h"
24#include "rockchip_drm_gem.h" 24#include "rockchip_drm_gem.h"
25#include "rockchip_drm_psr.h"
25 26
26#define to_rockchip_fb(x) container_of(x, struct rockchip_drm_fb, fb) 27#define to_rockchip_fb(x) container_of(x, struct rockchip_drm_fb, fb)
27 28
@@ -63,9 +64,20 @@ static int rockchip_drm_fb_create_handle(struct drm_framebuffer *fb,
63 rockchip_fb->obj[0], handle); 64 rockchip_fb->obj[0], handle);
64} 65}
65 66
67static int rockchip_drm_fb_dirty(struct drm_framebuffer *fb,
68 struct drm_file *file,
69 unsigned int flags, unsigned int color,
70 struct drm_clip_rect *clips,
71 unsigned int num_clips)
72{
73 rockchip_drm_psr_flush(fb->dev);
74 return 0;
75}
76
66static const struct drm_framebuffer_funcs rockchip_drm_fb_funcs = { 77static const struct drm_framebuffer_funcs rockchip_drm_fb_funcs = {
67 .destroy = rockchip_drm_fb_destroy, 78 .destroy = rockchip_drm_fb_destroy,
68 .create_handle = rockchip_drm_fb_create_handle, 79 .create_handle = rockchip_drm_fb_create_handle,
80 .dirty = rockchip_drm_fb_dirty,
69}; 81};
70 82
71static struct rockchip_drm_fb * 83static struct rockchip_drm_fb *
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
new file mode 100644
index 000000000000..c6ac5d01c8e4
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
@@ -0,0 +1,245 @@
1/*
2 * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
3 * Author: Yakir Yang <ykk@rock-chips.com>
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#include <drm/drmP.h>
16#include <drm/drm_crtc_helper.h>
17
18#include "rockchip_drm_drv.h"
19#include "rockchip_drm_psr.h"
20
21#define PSR_FLUSH_TIMEOUT msecs_to_jiffies(3000) /* 3 seconds */
22
23enum psr_state {
24 PSR_FLUSH,
25 PSR_ENABLE,
26 PSR_DISABLE,
27};
28
29struct psr_drv {
30 struct list_head list;
31 struct drm_encoder *encoder;
32
33 spinlock_t lock;
34 enum psr_state state;
35
36 struct timer_list flush_timer;
37
38 void (*set)(struct drm_encoder *encoder, bool enable);
39};
40
41static struct psr_drv *find_psr_by_crtc(struct drm_crtc *crtc)
42{
43 struct rockchip_drm_private *drm_drv = crtc->dev->dev_private;
44 struct psr_drv *psr;
45 unsigned long flags;
46
47 spin_lock_irqsave(&drm_drv->psr_list_lock, flags);
48 list_for_each_entry(psr, &drm_drv->psr_list, list) {
49 if (psr->encoder->crtc == crtc)
50 goto out;
51 }
52 psr = ERR_PTR(-ENODEV);
53
54out:
55 spin_unlock_irqrestore(&drm_drv->psr_list_lock, flags);
56 return psr;
57}
58
59static void psr_set_state_locked(struct psr_drv *psr, enum psr_state state)
60{
61 /*
62 * Allowed finite state machine:
63 *
64 * PSR_ENABLE < = = = = = > PSR_FLUSH
65 * | ^ |
66 * | | |
67 * v | |
68 * PSR_DISABLE < - - - - - - - - -
69 */
70 if (state == psr->state)
71 return;
72
73 /* Requesting a flush when disabled is a noop */
74 if (state == PSR_FLUSH && psr->state == PSR_DISABLE)
75 return;
76
77 psr->state = state;
78
79 /* Already disabled in flush, change the state, but not the hardware */
80 if (state == PSR_DISABLE && psr->state == PSR_FLUSH)
81 return;
82
83 /* Actually commit the state change to hardware */
84 switch (psr->state) {
85 case PSR_ENABLE:
86 psr->set(psr->encoder, true);
87 break;
88
89 case PSR_DISABLE:
90 case PSR_FLUSH:
91 psr->set(psr->encoder, false);
92 break;
93 }
94}
95
96static void psr_set_state(struct psr_drv *psr, enum psr_state state)
97{
98 unsigned long flags;
99
100 spin_lock_irqsave(&psr->lock, flags);
101 psr_set_state_locked(psr, state);
102 spin_unlock_irqrestore(&psr->lock, flags);
103}
104
105static void psr_flush_handler(unsigned long data)
106{
107 struct psr_drv *psr = (struct psr_drv *)data;
108 unsigned long flags;
109
110 /* If the state has changed since we initiated the flush, do nothing */
111 spin_lock_irqsave(&psr->lock, flags);
112 if (psr->state == PSR_FLUSH)
113 psr_set_state_locked(psr, PSR_ENABLE);
114 spin_unlock_irqrestore(&psr->lock, flags);
115}
116
117/**
118 * rockchip_drm_psr_enable - enable the encoder PSR which bind to given CRTC
119 * @crtc: CRTC to obtain the PSR encoder
120 *
121 * Returns:
122 * Zero on success, negative errno on failure.
123 */
124int rockchip_drm_psr_enable(struct drm_crtc *crtc)
125{
126 struct psr_drv *psr = find_psr_by_crtc(crtc);
127
128 if (IS_ERR(psr))
129 return PTR_ERR(psr);
130
131 psr_set_state(psr, PSR_ENABLE);
132 return 0;
133}
134EXPORT_SYMBOL(rockchip_drm_psr_enable);
135
136/**
137 * rockchip_drm_psr_disable - disable the encoder PSR which bind to given CRTC
138 * @crtc: CRTC to obtain the PSR encoder
139 *
140 * Returns:
141 * Zero on success, negative errno on failure.
142 */
143int rockchip_drm_psr_disable(struct drm_crtc *crtc)
144{
145 struct psr_drv *psr = find_psr_by_crtc(crtc);
146
147 if (IS_ERR(psr))
148 return PTR_ERR(psr);
149
150 psr_set_state(psr, PSR_DISABLE);
151 return 0;
152}
153EXPORT_SYMBOL(rockchip_drm_psr_disable);
154
155/**
156 * rockchip_drm_psr_flush - force to flush all registered PSR encoders
157 * @dev: drm device
158 *
159 * Disable the PSR function for all registered encoders, and then enable the
160 * PSR function back after PSR_FLUSH_TIMEOUT. If encoder PSR state have been
161 * changed during flush time, then keep the state no change after flush
162 * timeout.
163 *
164 * Returns:
165 * Zero on success, negative errno on failure.
166 */
167void rockchip_drm_psr_flush(struct drm_device *dev)
168{
169 struct rockchip_drm_private *drm_drv = dev->dev_private;
170 struct psr_drv *psr;
171 unsigned long flags;
172
173 spin_lock_irqsave(&drm_drv->psr_list_lock, flags);
174 list_for_each_entry(psr, &drm_drv->psr_list, list) {
175 mod_timer(&psr->flush_timer,
176 round_jiffies_up(jiffies + PSR_FLUSH_TIMEOUT));
177
178 psr_set_state(psr, PSR_FLUSH);
179 }
180 spin_unlock_irqrestore(&drm_drv->psr_list_lock, flags);
181}
182EXPORT_SYMBOL(rockchip_drm_psr_flush);
183
184/**
185 * rockchip_drm_psr_register - register encoder to psr driver
186 * @encoder: encoder that obtain the PSR function
187 * @psr_set: call back to set PSR state
188 *
189 * Returns:
190 * Zero on success, negative errno on failure.
191 */
192int rockchip_drm_psr_register(struct drm_encoder *encoder,
193 void (*psr_set)(struct drm_encoder *, bool enable))
194{
195 struct rockchip_drm_private *drm_drv = encoder->dev->dev_private;
196 struct psr_drv *psr;
197 unsigned long flags;
198
199 if (!encoder || !psr_set)
200 return -EINVAL;
201
202 psr = kzalloc(sizeof(struct psr_drv), GFP_KERNEL);
203 if (!psr)
204 return -ENOMEM;
205
206 setup_timer(&psr->flush_timer, psr_flush_handler, (unsigned long)psr);
207 spin_lock_init(&psr->lock);
208
209 psr->state = PSR_DISABLE;
210 psr->encoder = encoder;
211 psr->set = psr_set;
212
213 spin_lock_irqsave(&drm_drv->psr_list_lock, flags);
214 list_add_tail(&psr->list, &drm_drv->psr_list);
215 spin_unlock_irqrestore(&drm_drv->psr_list_lock, flags);
216
217 return 0;
218}
219EXPORT_SYMBOL(rockchip_drm_psr_register);
220
221/**
222 * rockchip_drm_psr_unregister - unregister encoder to psr driver
223 * @encoder: encoder that obtain the PSR function
224 * @psr_set: call back to set PSR state
225 *
226 * Returns:
227 * Zero on success, negative errno on failure.
228 */
229void rockchip_drm_psr_unregister(struct drm_encoder *encoder)
230{
231 struct rockchip_drm_private *drm_drv = encoder->dev->dev_private;
232 struct psr_drv *psr, *n;
233 unsigned long flags;
234
235 spin_lock_irqsave(&drm_drv->psr_list_lock, flags);
236 list_for_each_entry_safe(psr, n, &drm_drv->psr_list, list) {
237 if (psr->encoder == encoder) {
238 del_timer(&psr->flush_timer);
239 list_del(&psr->list);
240 kfree(psr);
241 }
242 }
243 spin_unlock_irqrestore(&drm_drv->psr_list_lock, flags);
244}
245EXPORT_SYMBOL(rockchip_drm_psr_unregister);
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.h b/drivers/gpu/drm/rockchip/rockchip_drm_psr.h
new file mode 100644
index 000000000000..c35b68873a30
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_psr.h
@@ -0,0 +1,26 @@
1/*
2 * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
3 * Author: Yakir Yang <ykk@rock-chips.com>
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#ifndef __ROCKCHIP_DRM_PSR___
16#define __ROCKCHIP_DRM_PSR___
17
18void rockchip_drm_psr_flush(struct drm_device *dev);
19int rockchip_drm_psr_enable(struct drm_crtc *crtc);
20int rockchip_drm_psr_disable(struct drm_crtc *crtc);
21
22int rockchip_drm_psr_register(struct drm_encoder *encoder,
23 void (*psr_set)(struct drm_encoder *, bool enable));
24void rockchip_drm_psr_unregister(struct drm_encoder *encoder);
25
26#endif /* __ROCKCHIP_DRM_PSR__ */
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index efbc41ad83b6..d486049f9722 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -34,17 +34,21 @@
34#include "rockchip_drm_drv.h" 34#include "rockchip_drm_drv.h"
35#include "rockchip_drm_gem.h" 35#include "rockchip_drm_gem.h"
36#include "rockchip_drm_fb.h" 36#include "rockchip_drm_fb.h"
37#include "rockchip_drm_psr.h"
37#include "rockchip_drm_vop.h" 38#include "rockchip_drm_vop.h"
38 39
39#define __REG_SET_RELAXED(x, off, mask, shift, v) \ 40#define __REG_SET_RELAXED(x, off, mask, shift, v, write_mask) \
40 vop_mask_write_relaxed(x, off, (mask) << shift, (v) << shift) 41 vop_mask_write(x, off, mask, shift, v, write_mask, true)
41#define __REG_SET_NORMAL(x, off, mask, shift, v) \ 42
42 vop_mask_write(x, off, (mask) << shift, (v) << shift) 43#define __REG_SET_NORMAL(x, off, mask, shift, v, write_mask) \
44 vop_mask_write(x, off, mask, shift, v, write_mask, false)
43 45
44#define REG_SET(x, base, reg, v, mode) \ 46#define REG_SET(x, base, reg, v, mode) \
45 __REG_SET_##mode(x, base + reg.offset, reg.mask, reg.shift, v) 47 __REG_SET_##mode(x, base + reg.offset, \
48 reg.mask, reg.shift, v, reg.write_mask)
46#define REG_SET_MASK(x, base, reg, mask, v, mode) \ 49#define REG_SET_MASK(x, base, reg, mask, v, mode) \
47 __REG_SET_##mode(x, base + reg.offset, mask, reg.shift, v) 50 __REG_SET_##mode(x, base + reg.offset, \
51 mask, reg.shift, v, reg.write_mask)
48 52
49#define VOP_WIN_SET(x, win, name, v) \ 53#define VOP_WIN_SET(x, win, name, v) \
50 REG_SET(x, win->base, win->phy->name, v, RELAXED) 54 REG_SET(x, win->base, win->phy->name, v, RELAXED)
@@ -106,6 +110,7 @@ struct vop {
106 struct device *dev; 110 struct device *dev;
107 struct drm_device *drm_dev; 111 struct drm_device *drm_dev;
108 bool is_enabled; 112 bool is_enabled;
113 bool vblank_active;
109 114
110 /* mutex vsync_ work */ 115 /* mutex vsync_ work */
111 struct mutex vsync_mutex; 116 struct mutex vsync_mutex;
@@ -116,6 +121,8 @@ struct vop {
116 /* protected by dev->event_lock */ 121 /* protected by dev->event_lock */
117 struct drm_pending_vblank_event *event; 122 struct drm_pending_vblank_event *event;
118 123
124 struct completion line_flag_completion;
125
119 const struct vop_data *data; 126 const struct vop_data *data;
120 127
121 uint32_t *regsbak; 128 uint32_t *regsbak;
@@ -162,27 +169,25 @@ static inline uint32_t vop_read_reg(struct vop *vop, uint32_t base,
162} 169}
163 170
164static inline void vop_mask_write(struct vop *vop, uint32_t offset, 171static inline void vop_mask_write(struct vop *vop, uint32_t offset,
165 uint32_t mask, uint32_t v) 172 uint32_t mask, uint32_t shift, uint32_t v,
173 bool write_mask, bool relaxed)
166{ 174{
167 if (mask) { 175 if (!mask)
168 uint32_t cached_val = vop->regsbak[offset >> 2]; 176 return;
169
170 cached_val = (cached_val & ~mask) | v;
171 writel(cached_val, vop->regs + offset);
172 vop->regsbak[offset >> 2] = cached_val;
173 }
174}
175 177
176static inline void vop_mask_write_relaxed(struct vop *vop, uint32_t offset, 178 if (write_mask) {
177 uint32_t mask, uint32_t v) 179 v = ((v << shift) & 0xffff) | (mask << (shift + 16));
178{ 180 } else {
179 if (mask) {
180 uint32_t cached_val = vop->regsbak[offset >> 2]; 181 uint32_t cached_val = vop->regsbak[offset >> 2];
181 182
182 cached_val = (cached_val & ~mask) | v; 183 v = (cached_val & ~(mask << shift)) | ((v & mask) << shift);
183 writel_relaxed(cached_val, vop->regs + offset); 184 vop->regsbak[offset >> 2] = v;
184 vop->regsbak[offset >> 2] = cached_val;
185 } 185 }
186
187 if (relaxed)
188 writel_relaxed(v, vop->regs + offset);
189 else
190 writel(v, vop->regs + offset);
186} 191}
187 192
188static inline uint32_t vop_get_intr_type(struct vop *vop, 193static inline uint32_t vop_get_intr_type(struct vop *vop,
@@ -428,6 +433,71 @@ static void vop_dsp_hold_valid_irq_disable(struct vop *vop)
428 spin_unlock_irqrestore(&vop->irq_lock, flags); 433 spin_unlock_irqrestore(&vop->irq_lock, flags);
429} 434}
430 435
436/*
437 * (1) each frame starts at the start of the Vsync pulse which is signaled by
438 * the "FRAME_SYNC" interrupt.
439 * (2) the active data region of each frame ends at dsp_vact_end
440 * (3) we should program this same number (dsp_vact_end) into dsp_line_frag_num,
441 * to get "LINE_FLAG" interrupt at the end of the active on screen data.
442 *
443 * VOP_INTR_CTRL0.dsp_line_frag_num = VOP_DSP_VACT_ST_END.dsp_vact_end
444 * Interrupts
445 * LINE_FLAG -------------------------------+
446 * FRAME_SYNC ----+ |
447 * | |
448 * v v
449 * | Vsync | Vbp | Vactive | Vfp |
450 * ^ ^ ^ ^
451 * | | | |
452 * | | | |
453 * dsp_vs_end ------------+ | | | VOP_DSP_VTOTAL_VS_END
454 * dsp_vact_start --------------+ | | VOP_DSP_VACT_ST_END
455 * dsp_vact_end ----------------------------+ | VOP_DSP_VACT_ST_END
456 * dsp_total -------------------------------------+ VOP_DSP_VTOTAL_VS_END
457 */
458static bool vop_line_flag_irq_is_enabled(struct vop *vop)
459{
460 uint32_t line_flag_irq;
461 unsigned long flags;
462
463 spin_lock_irqsave(&vop->irq_lock, flags);
464
465 line_flag_irq = VOP_INTR_GET_TYPE(vop, enable, LINE_FLAG_INTR);
466
467 spin_unlock_irqrestore(&vop->irq_lock, flags);
468
469 return !!line_flag_irq;
470}
471
472static void vop_line_flag_irq_enable(struct vop *vop, int line_num)
473{
474 unsigned long flags;
475
476 if (WARN_ON(!vop->is_enabled))
477 return;
478
479 spin_lock_irqsave(&vop->irq_lock, flags);
480
481 VOP_CTRL_SET(vop, line_flag_num[0], line_num);
482 VOP_INTR_SET_TYPE(vop, enable, LINE_FLAG_INTR, 1);
483
484 spin_unlock_irqrestore(&vop->irq_lock, flags);
485}
486
487static void vop_line_flag_irq_disable(struct vop *vop)
488{
489 unsigned long flags;
490
491 if (WARN_ON(!vop->is_enabled))
492 return;
493
494 spin_lock_irqsave(&vop->irq_lock, flags);
495
496 VOP_INTR_SET_TYPE(vop, enable, LINE_FLAG_INTR, 0);
497
498 spin_unlock_irqrestore(&vop->irq_lock, flags);
499}
500
431static int vop_enable(struct drm_crtc *crtc) 501static int vop_enable(struct drm_crtc *crtc)
432{ 502{
433 struct vop *vop = to_vop(crtc); 503 struct vop *vop = to_vop(crtc);
@@ -849,6 +919,8 @@ static int vop_crtc_enable_vblank(struct drm_crtc *crtc)
849 919
850 spin_unlock_irqrestore(&vop->irq_lock, flags); 920 spin_unlock_irqrestore(&vop->irq_lock, flags);
851 921
922 rockchip_drm_psr_disable(&vop->crtc);
923
852 return 0; 924 return 0;
853} 925}
854 926
@@ -865,6 +937,8 @@ static void vop_crtc_disable_vblank(struct drm_crtc *crtc)
865 VOP_INTR_SET_TYPE(vop, enable, FS_INTR, 0); 937 VOP_INTR_SET_TYPE(vop, enable, FS_INTR, 0);
866 938
867 spin_unlock_irqrestore(&vop->irq_lock, flags); 939 spin_unlock_irqrestore(&vop->irq_lock, flags);
940
941 rockchip_drm_psr_enable(&vop->crtc);
868} 942}
869 943
870static void vop_crtc_wait_for_update(struct drm_crtc *crtc) 944static void vop_crtc_wait_for_update(struct drm_crtc *crtc)
@@ -908,7 +982,7 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
908 u16 vsync_len = adjusted_mode->vsync_end - adjusted_mode->vsync_start; 982 u16 vsync_len = adjusted_mode->vsync_end - adjusted_mode->vsync_start;
909 u16 vact_st = adjusted_mode->vtotal - adjusted_mode->vsync_start; 983 u16 vact_st = adjusted_mode->vtotal - adjusted_mode->vsync_start;
910 u16 vact_end = vact_st + vdisplay; 984 u16 vact_end = vact_st + vdisplay;
911 uint32_t val; 985 uint32_t pin_pol, val;
912 int ret; 986 int ret;
913 987
914 WARN_ON(vop->event); 988 WARN_ON(vop->event);
@@ -955,21 +1029,26 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
955 vop_dsp_hold_valid_irq_disable(vop); 1029 vop_dsp_hold_valid_irq_disable(vop);
956 } 1030 }
957 1031
958 val = 0x8; 1032 pin_pol = 0x8;
959 val |= (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : 1; 1033 pin_pol |= (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : 1;
960 val |= (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : (1 << 1); 1034 pin_pol |= (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : (1 << 1);
961 VOP_CTRL_SET(vop, pin_pol, val); 1035 VOP_CTRL_SET(vop, pin_pol, pin_pol);
1036
962 switch (s->output_type) { 1037 switch (s->output_type) {
963 case DRM_MODE_CONNECTOR_LVDS: 1038 case DRM_MODE_CONNECTOR_LVDS:
964 VOP_CTRL_SET(vop, rgb_en, 1); 1039 VOP_CTRL_SET(vop, rgb_en, 1);
1040 VOP_CTRL_SET(vop, rgb_pin_pol, pin_pol);
965 break; 1041 break;
966 case DRM_MODE_CONNECTOR_eDP: 1042 case DRM_MODE_CONNECTOR_eDP:
1043 VOP_CTRL_SET(vop, edp_pin_pol, pin_pol);
967 VOP_CTRL_SET(vop, edp_en, 1); 1044 VOP_CTRL_SET(vop, edp_en, 1);
968 break; 1045 break;
969 case DRM_MODE_CONNECTOR_HDMIA: 1046 case DRM_MODE_CONNECTOR_HDMIA:
1047 VOP_CTRL_SET(vop, hdmi_pin_pol, pin_pol);
970 VOP_CTRL_SET(vop, hdmi_en, 1); 1048 VOP_CTRL_SET(vop, hdmi_en, 1);
971 break; 1049 break;
972 case DRM_MODE_CONNECTOR_DSI: 1050 case DRM_MODE_CONNECTOR_DSI:
1051 VOP_CTRL_SET(vop, mipi_pin_pol, pin_pol);
973 VOP_CTRL_SET(vop, mipi_en, 1); 1052 VOP_CTRL_SET(vop, mipi_en, 1);
974 break; 1053 break;
975 default: 1054 default:
@@ -1016,10 +1095,11 @@ static void vop_crtc_atomic_begin(struct drm_crtc *crtc,
1016 struct vop *vop = to_vop(crtc); 1095 struct vop *vop = to_vop(crtc);
1017 1096
1018 spin_lock_irq(&crtc->dev->event_lock); 1097 spin_lock_irq(&crtc->dev->event_lock);
1019 if (crtc->state->event) { 1098 vop->vblank_active = true;
1020 WARN_ON(drm_crtc_vblank_get(crtc) != 0); 1099 WARN_ON(drm_crtc_vblank_get(crtc) != 0);
1021 WARN_ON(vop->event); 1100 WARN_ON(vop->event);
1022 1101
1102 if (crtc->state->event) {
1023 vop->event = crtc->state->event; 1103 vop->event = crtc->state->event;
1024 crtc->state->event = NULL; 1104 crtc->state->event = NULL;
1025 } 1105 }
@@ -1106,12 +1186,14 @@ static void vop_handle_vblank(struct vop *vop)
1106 1186
1107 spin_lock_irqsave(&drm->event_lock, flags); 1187 spin_lock_irqsave(&drm->event_lock, flags);
1108 if (vop->event) { 1188 if (vop->event) {
1109
1110 drm_crtc_send_vblank_event(crtc, vop->event); 1189 drm_crtc_send_vblank_event(crtc, vop->event);
1111 drm_crtc_vblank_put(crtc);
1112 vop->event = NULL; 1190 vop->event = NULL;
1113 1191
1114 } 1192 }
1193 if (vop->vblank_active) {
1194 vop->vblank_active = false;
1195 drm_crtc_vblank_put(crtc);
1196 }
1115 spin_unlock_irqrestore(&drm->event_lock, flags); 1197 spin_unlock_irqrestore(&drm->event_lock, flags);
1116 1198
1117 if (!completion_done(&vop->wait_update_complete)) 1199 if (!completion_done(&vop->wait_update_complete))
@@ -1149,6 +1231,12 @@ static irqreturn_t vop_isr(int irq, void *data)
1149 ret = IRQ_HANDLED; 1231 ret = IRQ_HANDLED;
1150 } 1232 }
1151 1233
1234 if (active_irqs & LINE_FLAG_INTR) {
1235 complete(&vop->line_flag_completion);
1236 active_irqs &= ~LINE_FLAG_INTR;
1237 ret = IRQ_HANDLED;
1238 }
1239
1152 if (active_irqs & FS_INTR) { 1240 if (active_irqs & FS_INTR) {
1153 drm_crtc_handle_vblank(crtc); 1241 drm_crtc_handle_vblank(crtc);
1154 vop_handle_vblank(vop); 1242 vop_handle_vblank(vop);
@@ -1250,6 +1338,7 @@ static int vop_create_crtc(struct vop *vop)
1250 1338
1251 init_completion(&vop->dsp_hold_completion); 1339 init_completion(&vop->dsp_hold_completion);
1252 init_completion(&vop->wait_update_complete); 1340 init_completion(&vop->wait_update_complete);
1341 init_completion(&vop->line_flag_completion);
1253 crtc->port = port; 1342 crtc->port = port;
1254 rockchip_register_crtc_funcs(crtc, &private_crtc_funcs); 1343 rockchip_register_crtc_funcs(crtc, &private_crtc_funcs);
1255 1344
@@ -1377,6 +1466,7 @@ static int vop_initial(struct vop *vop)
1377 clk_disable(vop->aclk); 1466 clk_disable(vop->aclk);
1378 1467
1379 vop->is_enabled = false; 1468 vop->is_enabled = false;
1469 vop->vblank_active = false;
1380 1470
1381 return 0; 1471 return 0;
1382 1472
@@ -1406,6 +1496,49 @@ static void vop_win_init(struct vop *vop)
1406 } 1496 }
1407} 1497}
1408 1498
1499/**
1500 * rockchip_drm_wait_line_flag - acqiure the give line flag event
1501 * @crtc: CRTC to enable line flag
1502 * @line_num: interested line number
1503 * @mstimeout: millisecond for timeout
1504 *
1505 * Driver would hold here until the interested line flag interrupt have
1506 * happened or timeout to wait.
1507 *
1508 * Returns:
1509 * Zero on success, negative errno on failure.
1510 */
1511int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num,
1512 unsigned int mstimeout)
1513{
1514 struct vop *vop = to_vop(crtc);
1515 unsigned long jiffies_left;
1516
1517 if (!crtc || !vop->is_enabled)
1518 return -ENODEV;
1519
1520 if (line_num > crtc->mode.vtotal || mstimeout <= 0)
1521 return -EINVAL;
1522
1523 if (vop_line_flag_irq_is_enabled(vop))
1524 return -EBUSY;
1525
1526 reinit_completion(&vop->line_flag_completion);
1527 vop_line_flag_irq_enable(vop, line_num);
1528
1529 jiffies_left = wait_for_completion_timeout(&vop->line_flag_completion,
1530 msecs_to_jiffies(mstimeout));
1531 vop_line_flag_irq_disable(vop);
1532
1533 if (jiffies_left == 0) {
1534 dev_err(vop->dev, "Timeout waiting for IRQ\n");
1535 return -ETIMEDOUT;
1536 }
1537
1538 return 0;
1539}
1540EXPORT_SYMBOL(rockchip_drm_wait_line_flag);
1541
1409static int vop_bind(struct device *dev, struct device *master, void *data) 1542static int vop_bind(struct device *dev, struct device *master, void *data)
1410{ 1543{
1411 struct platform_device *pdev = to_platform_device(dev); 1544 struct platform_device *pdev = to_platform_device(dev);
@@ -1474,6 +1607,7 @@ static int vop_bind(struct device *dev, struct device *master, void *data)
1474 return ret; 1607 return ret;
1475 1608
1476 pm_runtime_enable(&pdev->dev); 1609 pm_runtime_enable(&pdev->dev);
1610
1477 return 0; 1611 return 0;
1478} 1612}
1479 1613
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
index 071ff0be7a95..1dbc52615257 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
@@ -33,6 +33,7 @@ struct vop_reg {
33 uint32_t offset; 33 uint32_t offset;
34 uint32_t shift; 34 uint32_t shift;
35 uint32_t mask; 35 uint32_t mask;
36 bool write_mask;
36}; 37};
37 38
38struct vop_ctrl { 39struct vop_ctrl {
@@ -48,6 +49,10 @@ struct vop_ctrl {
48 struct vop_reg dither_down; 49 struct vop_reg dither_down;
49 struct vop_reg dither_up; 50 struct vop_reg dither_up;
50 struct vop_reg pin_pol; 51 struct vop_reg pin_pol;
52 struct vop_reg rgb_pin_pol;
53 struct vop_reg hdmi_pin_pol;
54 struct vop_reg edp_pin_pol;
55 struct vop_reg mipi_pin_pol;
51 56
52 struct vop_reg htotal_pw; 57 struct vop_reg htotal_pw;
53 struct vop_reg hact_st_end; 58 struct vop_reg hact_st_end;
@@ -56,6 +61,8 @@ struct vop_ctrl {
56 struct vop_reg hpost_st_end; 61 struct vop_reg hpost_st_end;
57 struct vop_reg vpost_st_end; 62 struct vop_reg vpost_st_end;
58 63
64 struct vop_reg line_flag_num[2];
65
59 struct vop_reg cfg_done; 66 struct vop_reg cfg_done;
60}; 67};
61 68
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
index b7f59c443730..35c51f3402f2 100644
--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
@@ -23,7 +23,14 @@
23#define VOP_REG(off, _mask, s) \ 23#define VOP_REG(off, _mask, s) \
24 {.offset = off, \ 24 {.offset = off, \
25 .mask = _mask, \ 25 .mask = _mask, \
26 .shift = s,} 26 .shift = s, \
27 .write_mask = false,}
28
29#define VOP_REG_MASK(off, _mask, s) \
30 {.offset = off, \
31 .mask = _mask, \
32 .shift = s, \
33 .write_mask = true,}
27 34
28static const uint32_t formats_win_full[] = { 35static const uint32_t formats_win_full[] = {
29 DRM_FORMAT_XRGB8888, 36 DRM_FORMAT_XRGB8888,
@@ -50,6 +57,89 @@ static const uint32_t formats_win_lite[] = {
50 DRM_FORMAT_BGR565, 57 DRM_FORMAT_BGR565,
51}; 58};
52 59
60static const struct vop_scl_regs rk3036_win_scl = {
61 .scale_yrgb_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
62 .scale_yrgb_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
63 .scale_cbcr_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
64 .scale_cbcr_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
65};
66
67static const struct vop_win_phy rk3036_win0_data = {
68 .scl = &rk3036_win_scl,
69 .data_formats = formats_win_full,
70 .nformats = ARRAY_SIZE(formats_win_full),
71 .enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 0),
72 .format = VOP_REG(RK3036_SYS_CTRL, 0x7, 3),
73 .rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 15),
74 .act_info = VOP_REG(RK3036_WIN0_ACT_INFO, 0x1fff1fff, 0),
75 .dsp_info = VOP_REG(RK3036_WIN0_DSP_INFO, 0x0fff0fff, 0),
76 .dsp_st = VOP_REG(RK3036_WIN0_DSP_ST, 0x1fff1fff, 0),
77 .yrgb_mst = VOP_REG(RK3036_WIN0_YRGB_MST, 0xffffffff, 0),
78 .uv_mst = VOP_REG(RK3036_WIN0_CBR_MST, 0xffffffff, 0),
79 .yrgb_vir = VOP_REG(RK3036_WIN0_VIR, 0xffff, 0),
80 .uv_vir = VOP_REG(RK3036_WIN0_VIR, 0x1fff, 16),
81};
82
83static const struct vop_win_phy rk3036_win1_data = {
84 .data_formats = formats_win_lite,
85 .nformats = ARRAY_SIZE(formats_win_lite),
86 .enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 1),
87 .format = VOP_REG(RK3036_SYS_CTRL, 0x7, 6),
88 .rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 19),
89 .act_info = VOP_REG(RK3036_WIN1_ACT_INFO, 0x1fff1fff, 0),
90 .dsp_info = VOP_REG(RK3036_WIN1_DSP_INFO, 0x0fff0fff, 0),
91 .dsp_st = VOP_REG(RK3036_WIN1_DSP_ST, 0x1fff1fff, 0),
92 .yrgb_mst = VOP_REG(RK3036_WIN1_MST, 0xffffffff, 0),
93 .yrgb_vir = VOP_REG(RK3036_WIN1_VIR, 0xffff, 0),
94};
95
96static const struct vop_win_data rk3036_vop_win_data[] = {
97 { .base = 0x00, .phy = &rk3036_win0_data,
98 .type = DRM_PLANE_TYPE_PRIMARY },
99 { .base = 0x00, .phy = &rk3036_win1_data,
100 .type = DRM_PLANE_TYPE_CURSOR },
101};
102
103static const int rk3036_vop_intrs[] = {
104 DSP_HOLD_VALID_INTR,
105 FS_INTR,
106 LINE_FLAG_INTR,
107 BUS_ERROR_INTR,
108};
109
110static const struct vop_intr rk3036_intr = {
111 .intrs = rk3036_vop_intrs,
112 .nintrs = ARRAY_SIZE(rk3036_vop_intrs),
113 .status = VOP_REG(RK3036_INT_STATUS, 0xf, 0),
114 .enable = VOP_REG(RK3036_INT_STATUS, 0xf, 4),
115 .clear = VOP_REG(RK3036_INT_STATUS, 0xf, 8),
116};
117
118static const struct vop_ctrl rk3036_ctrl_data = {
119 .standby = VOP_REG(RK3036_SYS_CTRL, 0x1, 30),
120 .out_mode = VOP_REG(RK3036_DSP_CTRL0, 0xf, 0),
121 .pin_pol = VOP_REG(RK3036_DSP_CTRL0, 0xf, 4),
122 .htotal_pw = VOP_REG(RK3036_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
123 .hact_st_end = VOP_REG(RK3036_DSP_HACT_ST_END, 0x1fff1fff, 0),
124 .vtotal_pw = VOP_REG(RK3036_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
125 .vact_st_end = VOP_REG(RK3036_DSP_VACT_ST_END, 0x1fff1fff, 0),
126 .line_flag_num[0] = VOP_REG(RK3036_INT_STATUS, 0xfff, 12),
127 .cfg_done = VOP_REG(RK3036_REG_CFG_DONE, 0x1, 0),
128};
129
130static const struct vop_reg_data rk3036_vop_init_reg_table[] = {
131 {RK3036_DSP_CTRL1, 0x00000000},
132};
133
134static const struct vop_data rk3036_vop = {
135 .init_table = rk3036_vop_init_reg_table,
136 .table_size = ARRAY_SIZE(rk3036_vop_init_reg_table),
137 .ctrl = &rk3036_ctrl_data,
138 .intr = &rk3036_intr,
139 .win = rk3036_vop_win_data,
140 .win_size = ARRAY_SIZE(rk3036_vop_win_data),
141};
142
53static const struct vop_scl_extension rk3288_win_full_scl_ext = { 143static const struct vop_scl_extension rk3288_win_full_scl_ext = {
54 .cbcr_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 31), 144 .cbcr_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 31),
55 .cbcr_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 30), 145 .cbcr_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 30),
@@ -133,6 +223,7 @@ static const struct vop_ctrl rk3288_ctrl_data = {
133 .vact_st_end = VOP_REG(RK3288_DSP_VACT_ST_END, 0x1fff1fff, 0), 223 .vact_st_end = VOP_REG(RK3288_DSP_VACT_ST_END, 0x1fff1fff, 0),
134 .hpost_st_end = VOP_REG(RK3288_POST_DSP_HACT_INFO, 0x1fff1fff, 0), 224 .hpost_st_end = VOP_REG(RK3288_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
135 .vpost_st_end = VOP_REG(RK3288_POST_DSP_VACT_INFO, 0x1fff1fff, 0), 225 .vpost_st_end = VOP_REG(RK3288_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
226 .line_flag_num[0] = VOP_REG(RK3288_INTR_CTRL0, 0x1fff, 12),
136 .cfg_done = VOP_REG(RK3288_REG_CFG_DONE, 0x1, 0), 227 .cfg_done = VOP_REG(RK3288_REG_CFG_DONE, 0x1, 0),
137}; 228};
138 229
@@ -190,93 +281,104 @@ static const struct vop_data rk3288_vop = {
190 .win_size = ARRAY_SIZE(rk3288_vop_win_data), 281 .win_size = ARRAY_SIZE(rk3288_vop_win_data),
191}; 282};
192 283
193static const struct vop_scl_regs rk3036_win_scl = { 284static const struct vop_ctrl rk3399_ctrl_data = {
194 .scale_yrgb_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0), 285 .standby = VOP_REG(RK3399_SYS_CTRL, 0x1, 22),
195 .scale_yrgb_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 16), 286 .gate_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 23),
196 .scale_cbcr_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0), 287 .rgb_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 12),
197 .scale_cbcr_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 16), 288 .hdmi_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 13),
198}; 289 .edp_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 14),
199 290 .mipi_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 15),
200static const struct vop_win_phy rk3036_win0_data = { 291 .dither_down = VOP_REG(RK3399_DSP_CTRL1, 0xf, 1),
201 .scl = &rk3036_win_scl, 292 .dither_up = VOP_REG(RK3399_DSP_CTRL1, 0x1, 6),
202 .data_formats = formats_win_full, 293 .data_blank = VOP_REG(RK3399_DSP_CTRL0, 0x1, 19),
203 .nformats = ARRAY_SIZE(formats_win_full), 294 .out_mode = VOP_REG(RK3399_DSP_CTRL0, 0xf, 0),
204 .enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 0), 295 .rgb_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 16),
205 .format = VOP_REG(RK3036_SYS_CTRL, 0x7, 3), 296 .hdmi_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 20),
206 .rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 15), 297 .edp_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 24),
207 .act_info = VOP_REG(RK3036_WIN0_ACT_INFO, 0x1fff1fff, 0), 298 .mipi_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 28),
208 .dsp_info = VOP_REG(RK3036_WIN0_DSP_INFO, 0x0fff0fff, 0), 299 .htotal_pw = VOP_REG(RK3399_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
209 .dsp_st = VOP_REG(RK3036_WIN0_DSP_ST, 0x1fff1fff, 0), 300 .hact_st_end = VOP_REG(RK3399_DSP_HACT_ST_END, 0x1fff1fff, 0),
210 .yrgb_mst = VOP_REG(RK3036_WIN0_YRGB_MST, 0xffffffff, 0), 301 .vtotal_pw = VOP_REG(RK3399_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
211 .uv_mst = VOP_REG(RK3036_WIN0_CBR_MST, 0xffffffff, 0), 302 .vact_st_end = VOP_REG(RK3399_DSP_VACT_ST_END, 0x1fff1fff, 0),
212 .yrgb_vir = VOP_REG(RK3036_WIN0_VIR, 0xffff, 0), 303 .hpost_st_end = VOP_REG(RK3399_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
213 .uv_vir = VOP_REG(RK3036_WIN0_VIR, 0x1fff, 16), 304 .vpost_st_end = VOP_REG(RK3399_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
305 .line_flag_num[0] = VOP_REG(RK3399_LINE_FLAG, 0xffff, 0),
306 .line_flag_num[1] = VOP_REG(RK3399_LINE_FLAG, 0xffff, 16),
307 .cfg_done = VOP_REG_MASK(RK3399_REG_CFG_DONE, 0x1, 0),
214}; 308};
215 309
216static const struct vop_win_phy rk3036_win1_data = { 310static const int rk3399_vop_intrs[] = {
217 .data_formats = formats_win_lite,
218 .nformats = ARRAY_SIZE(formats_win_lite),
219 .enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 1),
220 .format = VOP_REG(RK3036_SYS_CTRL, 0x7, 6),
221 .rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 19),
222 .act_info = VOP_REG(RK3036_WIN1_ACT_INFO, 0x1fff1fff, 0),
223 .dsp_info = VOP_REG(RK3036_WIN1_DSP_INFO, 0x0fff0fff, 0),
224 .dsp_st = VOP_REG(RK3036_WIN1_DSP_ST, 0x1fff1fff, 0),
225 .yrgb_mst = VOP_REG(RK3036_WIN1_MST, 0xffffffff, 0),
226 .yrgb_vir = VOP_REG(RK3036_WIN1_VIR, 0xffff, 0),
227};
228
229static const struct vop_win_data rk3036_vop_win_data[] = {
230 { .base = 0x00, .phy = &rk3036_win0_data,
231 .type = DRM_PLANE_TYPE_PRIMARY },
232 { .base = 0x00, .phy = &rk3036_win1_data,
233 .type = DRM_PLANE_TYPE_CURSOR },
234};
235
236static const int rk3036_vop_intrs[] = {
237 DSP_HOLD_VALID_INTR,
238 FS_INTR, 311 FS_INTR,
312 0, 0,
239 LINE_FLAG_INTR, 313 LINE_FLAG_INTR,
314 0,
240 BUS_ERROR_INTR, 315 BUS_ERROR_INTR,
316 0, 0, 0, 0, 0, 0, 0,
317 DSP_HOLD_VALID_INTR,
241}; 318};
242 319
243static const struct vop_intr rk3036_intr = { 320static const struct vop_intr rk3399_vop_intr = {
244 .intrs = rk3036_vop_intrs, 321 .intrs = rk3399_vop_intrs,
245 .nintrs = ARRAY_SIZE(rk3036_vop_intrs), 322 .nintrs = ARRAY_SIZE(rk3399_vop_intrs),
246 .status = VOP_REG(RK3036_INT_STATUS, 0xf, 0), 323 .status = VOP_REG_MASK(RK3399_INTR_STATUS0, 0xffff, 0),
247 .enable = VOP_REG(RK3036_INT_STATUS, 0xf, 4), 324 .enable = VOP_REG_MASK(RK3399_INTR_EN0, 0xffff, 0),
248 .clear = VOP_REG(RK3036_INT_STATUS, 0xf, 8), 325 .clear = VOP_REG_MASK(RK3399_INTR_CLEAR0, 0xffff, 0),
249}; 326};
250 327
251static const struct vop_ctrl rk3036_ctrl_data = { 328static const struct vop_reg_data rk3399_init_reg_table[] = {
252 .standby = VOP_REG(RK3036_SYS_CTRL, 0x1, 30), 329 {RK3399_SYS_CTRL, 0x2000f800},
253 .out_mode = VOP_REG(RK3036_DSP_CTRL0, 0xf, 0), 330 {RK3399_DSP_CTRL0, 0x00000000},
254 .pin_pol = VOP_REG(RK3036_DSP_CTRL0, 0xf, 4), 331 {RK3399_WIN0_CTRL0, 0x00000080},
255 .htotal_pw = VOP_REG(RK3036_DSP_HTOTAL_HS_END, 0x1fff1fff, 0), 332 {RK3399_WIN1_CTRL0, 0x00000080},
256 .hact_st_end = VOP_REG(RK3036_DSP_HACT_ST_END, 0x1fff1fff, 0), 333 /* TODO: Win2/3 support multiple area function, but we haven't found
257 .vtotal_pw = VOP_REG(RK3036_DSP_VTOTAL_VS_END, 0x1fff1fff, 0), 334 * a suitable way to use it yet, so let's just use them as other windows
258 .vact_st_end = VOP_REG(RK3036_DSP_VACT_ST_END, 0x1fff1fff, 0), 335 * with only area 0 enabled.
259 .cfg_done = VOP_REG(RK3036_REG_CFG_DONE, 0x1, 0), 336 */
337 {RK3399_WIN2_CTRL0, 0x00000010},
338 {RK3399_WIN3_CTRL0, 0x00000010},
260}; 339};
261 340
262static const struct vop_reg_data rk3036_vop_init_reg_table[] = { 341static const struct vop_data rk3399_vop_big = {
263 {RK3036_DSP_CTRL1, 0x00000000}, 342 .init_table = rk3399_init_reg_table,
343 .table_size = ARRAY_SIZE(rk3399_init_reg_table),
344 .intr = &rk3399_vop_intr,
345 .ctrl = &rk3399_ctrl_data,
346 /*
347 * rk3399 vop big windows register layout is same as rk3288.
348 */
349 .win = rk3288_vop_win_data,
350 .win_size = ARRAY_SIZE(rk3288_vop_win_data),
264}; 351};
265 352
266static const struct vop_data rk3036_vop = { 353static const struct vop_win_data rk3399_vop_lit_win_data[] = {
267 .init_table = rk3036_vop_init_reg_table, 354 { .base = 0x00, .phy = &rk3288_win01_data,
268 .table_size = ARRAY_SIZE(rk3036_vop_init_reg_table), 355 .type = DRM_PLANE_TYPE_PRIMARY },
269 .ctrl = &rk3036_ctrl_data, 356 { .base = 0x00, .phy = &rk3288_win23_data,
270 .intr = &rk3036_intr, 357 .type = DRM_PLANE_TYPE_CURSOR},
271 .win = rk3036_vop_win_data, 358};
272 .win_size = ARRAY_SIZE(rk3036_vop_win_data), 359
360static const struct vop_data rk3399_vop_lit = {
361 .init_table = rk3399_init_reg_table,
362 .table_size = ARRAY_SIZE(rk3399_init_reg_table),
363 .intr = &rk3399_vop_intr,
364 .ctrl = &rk3399_ctrl_data,
365 /*
366 * rk3399 vop lit windows register layout is same as rk3288,
367 * but cut off the win1 and win3 windows.
368 */
369 .win = rk3399_vop_lit_win_data,
370 .win_size = ARRAY_SIZE(rk3399_vop_lit_win_data),
273}; 371};
274 372
275static const struct of_device_id vop_driver_dt_match[] = { 373static const struct of_device_id vop_driver_dt_match[] = {
276 { .compatible = "rockchip,rk3288-vop",
277 .data = &rk3288_vop },
278 { .compatible = "rockchip,rk3036-vop", 374 { .compatible = "rockchip,rk3036-vop",
279 .data = &rk3036_vop }, 375 .data = &rk3036_vop },
376 { .compatible = "rockchip,rk3288-vop",
377 .data = &rk3288_vop },
378 { .compatible = "rockchip,rk3399-vop-big",
379 .data = &rk3399_vop_big },
380 { .compatible = "rockchip,rk3399-vop-lit",
381 .data = &rk3399_vop_lit },
280 {}, 382 {},
281}; 383};
282MODULE_DEVICE_TABLE(of, vop_driver_dt_match); 384MODULE_DEVICE_TABLE(of, vop_driver_dt_match);
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.h b/drivers/gpu/drm/rockchip/rockchip_vop_reg.h
index d4b46cba2f26..cd197260ece5 100644
--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.h
+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.h
@@ -166,4 +166,197 @@
166#define RK3036_HWC_LUT_ADDR 0x800 166#define RK3036_HWC_LUT_ADDR 0x800
167/* rk3036 register definition end */ 167/* rk3036 register definition end */
168 168
169/* rk3399 register definition */
170#define RK3399_REG_CFG_DONE 0x00000
171#define RK3399_VERSION_INFO 0x00004
172#define RK3399_SYS_CTRL 0x00008
173#define RK3399_SYS_CTRL1 0x0000c
174#define RK3399_DSP_CTRL0 0x00010
175#define RK3399_DSP_CTRL1 0x00014
176#define RK3399_DSP_BG 0x00018
177#define RK3399_MCU_CTRL 0x0001c
178#define RK3399_WB_CTRL0 0x00020
179#define RK3399_WB_CTRL1 0x00024
180#define RK3399_WB_YRGB_MST 0x00028
181#define RK3399_WB_CBR_MST 0x0002c
182#define RK3399_WIN0_CTRL0 0x00030
183#define RK3399_WIN0_CTRL1 0x00034
184#define RK3399_WIN0_COLOR_KEY 0x00038
185#define RK3399_WIN0_VIR 0x0003c
186#define RK3399_WIN0_YRGB_MST 0x00040
187#define RK3399_WIN0_CBR_MST 0x00044
188#define RK3399_WIN0_ACT_INFO 0x00048
189#define RK3399_WIN0_DSP_INFO 0x0004c
190#define RK3399_WIN0_DSP_ST 0x00050
191#define RK3399_WIN0_SCL_FACTOR_YRGB 0x00054
192#define RK3399_WIN0_SCL_FACTOR_CBR 0x00058
193#define RK3399_WIN0_SCL_OFFSET 0x0005c
194#define RK3399_WIN0_SRC_ALPHA_CTRL 0x00060
195#define RK3399_WIN0_DST_ALPHA_CTRL 0x00064
196#define RK3399_WIN0_FADING_CTRL 0x00068
197#define RK3399_WIN0_CTRL2 0x0006c
198#define RK3399_WIN1_CTRL0 0x00070
199#define RK3399_WIN1_CTRL1 0x00074
200#define RK3399_WIN1_COLOR_KEY 0x00078
201#define RK3399_WIN1_VIR 0x0007c
202#define RK3399_WIN1_YRGB_MST 0x00080
203#define RK3399_WIN1_CBR_MST 0x00084
204#define RK3399_WIN1_ACT_INFO 0x00088
205#define RK3399_WIN1_DSP_INFO 0x0008c
206#define RK3399_WIN1_DSP_ST 0x00090
207#define RK3399_WIN1_SCL_FACTOR_YRGB 0x00094
208#define RK3399_WIN1_SCL_FACTOR_CBR 0x00098
209#define RK3399_WIN1_SCL_OFFSET 0x0009c
210#define RK3399_WIN1_SRC_ALPHA_CTRL 0x000a0
211#define RK3399_WIN1_DST_ALPHA_CTRL 0x000a4
212#define RK3399_WIN1_FADING_CTRL 0x000a8
213#define RK3399_WIN1_CTRL2 0x000ac
214#define RK3399_WIN2_CTRL0 0x000b0
215#define RK3399_WIN2_CTRL1 0x000b4
216#define RK3399_WIN2_VIR0_1 0x000b8
217#define RK3399_WIN2_VIR2_3 0x000bc
218#define RK3399_WIN2_MST0 0x000c0
219#define RK3399_WIN2_DSP_INFO0 0x000c4
220#define RK3399_WIN2_DSP_ST0 0x000c8
221#define RK3399_WIN2_COLOR_KEY 0x000cc
222#define RK3399_WIN2_MST1 0x000d0
223#define RK3399_WIN2_DSP_INFO1 0x000d4
224#define RK3399_WIN2_DSP_ST1 0x000d8
225#define RK3399_WIN2_SRC_ALPHA_CTRL 0x000dc
226#define RK3399_WIN2_MST2 0x000e0
227#define RK3399_WIN2_DSP_INFO2 0x000e4
228#define RK3399_WIN2_DSP_ST2 0x000e8
229#define RK3399_WIN2_DST_ALPHA_CTRL 0x000ec
230#define RK3399_WIN2_MST3 0x000f0
231#define RK3399_WIN2_DSP_INFO3 0x000f4
232#define RK3399_WIN2_DSP_ST3 0x000f8
233#define RK3399_WIN2_FADING_CTRL 0x000fc
234#define RK3399_WIN3_CTRL0 0x00100
235#define RK3399_WIN3_CTRL1 0x00104
236#define RK3399_WIN3_VIR0_1 0x00108
237#define RK3399_WIN3_VIR2_3 0x0010c
238#define RK3399_WIN3_MST0 0x00110
239#define RK3399_WIN3_DSP_INFO0 0x00114
240#define RK3399_WIN3_DSP_ST0 0x00118
241#define RK3399_WIN3_COLOR_KEY 0x0011c
242#define RK3399_WIN3_MST1 0x00120
243#define RK3399_WIN3_DSP_INFO1 0x00124
244#define RK3399_WIN3_DSP_ST1 0x00128
245#define RK3399_WIN3_SRC_ALPHA_CTRL 0x0012c
246#define RK3399_WIN3_MST2 0x00130
247#define RK3399_WIN3_DSP_INFO2 0x00134
248#define RK3399_WIN3_DSP_ST2 0x00138
249#define RK3399_WIN3_DST_ALPHA_CTRL 0x0013c
250#define RK3399_WIN3_MST3 0x00140
251#define RK3399_WIN3_DSP_INFO3 0x00144
252#define RK3399_WIN3_DSP_ST3 0x00148
253#define RK3399_WIN3_FADING_CTRL 0x0014c
254#define RK3399_HWC_CTRL0 0x00150
255#define RK3399_HWC_CTRL1 0x00154
256#define RK3399_HWC_MST 0x00158
257#define RK3399_HWC_DSP_ST 0x0015c
258#define RK3399_HWC_SRC_ALPHA_CTRL 0x00160
259#define RK3399_HWC_DST_ALPHA_CTRL 0x00164
260#define RK3399_HWC_FADING_CTRL 0x00168
261#define RK3399_HWC_RESERVED1 0x0016c
262#define RK3399_POST_DSP_HACT_INFO 0x00170
263#define RK3399_POST_DSP_VACT_INFO 0x00174
264#define RK3399_POST_SCL_FACTOR_YRGB 0x00178
265#define RK3399_POST_RESERVED 0x0017c
266#define RK3399_POST_SCL_CTRL 0x00180
267#define RK3399_POST_DSP_VACT_INFO_F1 0x00184
268#define RK3399_DSP_HTOTAL_HS_END 0x00188
269#define RK3399_DSP_HACT_ST_END 0x0018c
270#define RK3399_DSP_VTOTAL_VS_END 0x00190
271#define RK3399_DSP_VACT_ST_END 0x00194
272#define RK3399_DSP_VS_ST_END_F1 0x00198
273#define RK3399_DSP_VACT_ST_END_F1 0x0019c
274#define RK3399_PWM_CTRL 0x001a0
275#define RK3399_PWM_PERIOD_HPR 0x001a4
276#define RK3399_PWM_DUTY_LPR 0x001a8
277#define RK3399_PWM_CNT 0x001ac
278#define RK3399_BCSH_COLOR_BAR 0x001b0
279#define RK3399_BCSH_BCS 0x001b4
280#define RK3399_BCSH_H 0x001b8
281#define RK3399_BCSH_CTRL 0x001bc
282#define RK3399_CABC_CTRL0 0x001c0
283#define RK3399_CABC_CTRL1 0x001c4
284#define RK3399_CABC_CTRL2 0x001c8
285#define RK3399_CABC_CTRL3 0x001cc
286#define RK3399_CABC_GAUSS_LINE0_0 0x001d0
287#define RK3399_CABC_GAUSS_LINE0_1 0x001d4
288#define RK3399_CABC_GAUSS_LINE1_0 0x001d8
289#define RK3399_CABC_GAUSS_LINE1_1 0x001dc
290#define RK3399_CABC_GAUSS_LINE2_0 0x001e0
291#define RK3399_CABC_GAUSS_LINE2_1 0x001e4
292#define RK3399_FRC_LOWER01_0 0x001e8
293#define RK3399_FRC_LOWER01_1 0x001ec
294#define RK3399_FRC_LOWER10_0 0x001f0
295#define RK3399_FRC_LOWER10_1 0x001f4
296#define RK3399_FRC_LOWER11_0 0x001f8
297#define RK3399_FRC_LOWER11_1 0x001fc
298#define RK3399_AFBCD0_CTRL 0x00200
299#define RK3399_AFBCD0_HDR_PTR 0x00204
300#define RK3399_AFBCD0_PIC_SIZE 0x00208
301#define RK3399_AFBCD0_STATUS 0x0020c
302#define RK3399_AFBCD1_CTRL 0x00220
303#define RK3399_AFBCD1_HDR_PTR 0x00224
304#define RK3399_AFBCD1_PIC_SIZE 0x00228
305#define RK3399_AFBCD1_STATUS 0x0022c
306#define RK3399_AFBCD2_CTRL 0x00240
307#define RK3399_AFBCD2_HDR_PTR 0x00244
308#define RK3399_AFBCD2_PIC_SIZE 0x00248
309#define RK3399_AFBCD2_STATUS 0x0024c
310#define RK3399_AFBCD3_CTRL 0x00260
311#define RK3399_AFBCD3_HDR_PTR 0x00264
312#define RK3399_AFBCD3_PIC_SIZE 0x00268
313#define RK3399_AFBCD3_STATUS 0x0026c
314#define RK3399_INTR_EN0 0x00280
315#define RK3399_INTR_CLEAR0 0x00284
316#define RK3399_INTR_STATUS0 0x00288
317#define RK3399_INTR_RAW_STATUS0 0x0028c
318#define RK3399_INTR_EN1 0x00290
319#define RK3399_INTR_CLEAR1 0x00294
320#define RK3399_INTR_STATUS1 0x00298
321#define RK3399_INTR_RAW_STATUS1 0x0029c
322#define RK3399_LINE_FLAG 0x002a0
323#define RK3399_VOP_STATUS 0x002a4
324#define RK3399_BLANKING_VALUE 0x002a8
325#define RK3399_MCU_BYPASS_PORT 0x002ac
326#define RK3399_WIN0_DSP_BG 0x002b0
327#define RK3399_WIN1_DSP_BG 0x002b4
328#define RK3399_WIN2_DSP_BG 0x002b8
329#define RK3399_WIN3_DSP_BG 0x002bc
330#define RK3399_YUV2YUV_WIN 0x002c0
331#define RK3399_YUV2YUV_POST 0x002c4
332#define RK3399_AUTO_GATING_EN 0x002cc
333#define RK3399_WIN0_CSC_COE 0x003a0
334#define RK3399_WIN1_CSC_COE 0x003c0
335#define RK3399_WIN2_CSC_COE 0x003e0
336#define RK3399_WIN3_CSC_COE 0x00400
337#define RK3399_HWC_CSC_COE 0x00420
338#define RK3399_BCSH_R2Y_CSC_COE 0x00440
339#define RK3399_BCSH_Y2R_CSC_COE 0x00460
340#define RK3399_POST_YUV2YUV_Y2R_COE 0x00480
341#define RK3399_POST_YUV2YUV_3X3_COE 0x004a0
342#define RK3399_POST_YUV2YUV_R2Y_COE 0x004c0
343#define RK3399_WIN0_YUV2YUV_Y2R 0x004e0
344#define RK3399_WIN0_YUV2YUV_3X3 0x00500
345#define RK3399_WIN0_YUV2YUV_R2Y 0x00520
346#define RK3399_WIN1_YUV2YUV_Y2R 0x00540
347#define RK3399_WIN1_YUV2YUV_3X3 0x00560
348#define RK3399_WIN1_YUV2YUV_R2Y 0x00580
349#define RK3399_WIN2_YUV2YUV_Y2R 0x005a0
350#define RK3399_WIN2_YUV2YUV_3X3 0x005c0
351#define RK3399_WIN2_YUV2YUV_R2Y 0x005e0
352#define RK3399_WIN3_YUV2YUV_Y2R 0x00600
353#define RK3399_WIN3_YUV2YUV_3X3 0x00620
354#define RK3399_WIN3_YUV2YUV_R2Y 0x00640
355#define RK3399_WIN2_LUT_ADDR 0x01000
356#define RK3399_WIN3_LUT_ADDR 0x01400
357#define RK3399_HWC_LUT_ADDR 0x01800
358#define RK3399_CABC_GAMMA_LUT_ADDR 0x01c00
359#define RK3399_GAMMA_LUT_ADDR 0x02000
360/* rk3399 register definition end */
361
169#endif /* _ROCKCHIP_VOP_REG_H */ 362#endif /* _ROCKCHIP_VOP_REG_H */