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
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
|
||||
|
||||
rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
|
||||
rockchip_drm_gem.o rockchip_drm_vop.o
|
||||
rockchip_drm_gem.o rockchip_drm_psr.o rockchip_drm_vop.o
|
||||
rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
|
||||
|
||||
obj-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
|
||||
|
@@ -32,6 +32,7 @@
|
||||
#include <drm/bridge/analogix_dp.h>
|
||||
|
||||
#include "rockchip_drm_drv.h"
|
||||
#include "rockchip_drm_psr.h"
|
||||
#include "rockchip_drm_vop.h"
|
||||
|
||||
#define RK3288_GRF_SOC_CON6 0x25c
|
||||
@@ -41,6 +42,8 @@
|
||||
|
||||
#define HIWORD_UPDATE(val, mask) (val | (mask) << 16)
|
||||
|
||||
#define PSR_WAIT_LINE_FLAG_TIMEOUT_MS 100
|
||||
|
||||
#define to_dp(nm) container_of(nm, struct rockchip_dp_device, nm)
|
||||
|
||||
/**
|
||||
@@ -68,11 +71,62 @@ struct rockchip_dp_device {
|
||||
struct regmap *grf;
|
||||
struct reset_control *rst;
|
||||
|
||||
struct work_struct psr_work;
|
||||
spinlock_t psr_lock;
|
||||
unsigned int psr_state;
|
||||
|
||||
const struct rockchip_dp_chip_data *data;
|
||||
|
||||
struct analogix_dp_plat_data plat_data;
|
||||
};
|
||||
|
||||
static void analogix_dp_psr_set(struct drm_encoder *encoder, bool enabled)
|
||||
{
|
||||
struct rockchip_dp_device *dp = to_dp(encoder);
|
||||
unsigned long flags;
|
||||
|
||||
dev_dbg(dp->dev, "%s PSR...\n", enabled ? "Entry" : "Exit");
|
||||
|
||||
spin_lock_irqsave(&dp->psr_lock, flags);
|
||||
if (enabled)
|
||||
dp->psr_state = EDP_VSC_PSR_STATE_ACTIVE;
|
||||
else
|
||||
dp->psr_state = ~EDP_VSC_PSR_STATE_ACTIVE;
|
||||
|
||||
schedule_work(&dp->psr_work);
|
||||
spin_unlock_irqrestore(&dp->psr_lock, flags);
|
||||
}
|
||||
|
||||
static void analogix_dp_psr_work(struct work_struct *work)
|
||||
{
|
||||
struct rockchip_dp_device *dp =
|
||||
container_of(work, typeof(*dp), psr_work);
|
||||
struct drm_crtc *crtc = dp->encoder.crtc;
|
||||
int psr_state = dp->psr_state;
|
||||
int vact_end;
|
||||
int ret;
|
||||
unsigned long flags;
|
||||
|
||||
if (!crtc)
|
||||
return;
|
||||
|
||||
vact_end = crtc->mode.vtotal - crtc->mode.vsync_start + crtc->mode.vdisplay;
|
||||
|
||||
ret = rockchip_drm_wait_line_flag(dp->encoder.crtc, vact_end,
|
||||
PSR_WAIT_LINE_FLAG_TIMEOUT_MS);
|
||||
if (ret) {
|
||||
dev_err(dp->dev, "line flag interrupt did not arrive\n");
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&dp->psr_lock, flags);
|
||||
if (psr_state == EDP_VSC_PSR_STATE_ACTIVE)
|
||||
analogix_dp_enable_psr(dp->dev);
|
||||
else
|
||||
analogix_dp_disable_psr(dp->dev);
|
||||
spin_unlock_irqrestore(&dp->psr_lock, flags);
|
||||
}
|
||||
|
||||
static int rockchip_dp_pre_init(struct rockchip_dp_device *dp)
|
||||
{
|
||||
reset_control_assert(dp->rst);
|
||||
@@ -87,6 +141,8 @@ static int rockchip_dp_poweron(struct analogix_dp_plat_data *plat_data)
|
||||
struct rockchip_dp_device *dp = to_dp(plat_data);
|
||||
int ret;
|
||||
|
||||
cancel_work_sync(&dp->psr_work);
|
||||
|
||||
ret = clk_prepare_enable(dp->pclk);
|
||||
if (ret < 0) {
|
||||
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,
|
||||
dp->plat_data.power_off = rockchip_dp_powerdown;
|
||||
dp->plat_data.get_modes = rockchip_dp_get_modes;
|
||||
|
||||
spin_lock_init(&dp->psr_lock);
|
||||
dp->psr_state = ~EDP_VSC_PSR_STATE_ACTIVE;
|
||||
INIT_WORK(&dp->psr_work, analogix_dp_psr_work);
|
||||
|
||||
rockchip_drm_psr_register(&dp->encoder, analogix_dp_psr_set);
|
||||
|
||||
return analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data);
|
||||
}
|
||||
|
||||
static void rockchip_dp_unbind(struct device *dev, struct device *master,
|
||||
void *data)
|
||||
{
|
||||
struct rockchip_dp_device *dp = dev_get_drvdata(dev);
|
||||
|
||||
rockchip_drm_psr_unregister(&dp->encoder);
|
||||
|
||||
return analogix_dp_unbind(dev, master, data);
|
||||
}
|
||||
|
||||
@@ -381,10 +447,8 @@ static int rockchip_dp_probe(struct platform_device *pdev)
|
||||
|
||||
panel = of_drm_find_panel(panel_node);
|
||||
of_node_put(panel_node);
|
||||
if (!panel) {
|
||||
DRM_ERROR("failed to find panel\n");
|
||||
if (!panel)
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
}
|
||||
|
||||
dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);
|
||||
|
@@ -156,6 +156,9 @@ static int rockchip_drm_bind(struct device *dev)
|
||||
|
||||
drm_dev->dev_private = private;
|
||||
|
||||
INIT_LIST_HEAD(&private->psr_list);
|
||||
spin_lock_init(&private->psr_list_lock);
|
||||
|
||||
drm_mode_config_init(drm_dev);
|
||||
|
||||
rockchip_drm_mode_config_init(drm_dev);
|
||||
|
@@ -61,6 +61,9 @@ struct rockchip_drm_private {
|
||||
struct drm_gem_object *fbdev_bo;
|
||||
const struct rockchip_crtc_funcs *crtc_funcs[ROCKCHIP_MAX_CRTC];
|
||||
struct drm_atomic_state *state;
|
||||
|
||||
struct list_head psr_list;
|
||||
spinlock_t psr_list_lock;
|
||||
};
|
||||
|
||||
int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
|
||||
@@ -70,4 +73,7 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
|
||||
struct device *dev);
|
||||
void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
|
||||
struct device *dev);
|
||||
int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num,
|
||||
unsigned int mstimeout);
|
||||
|
||||
#endif /* _ROCKCHIP_DRM_DRV_H_ */
|
||||
|
@@ -22,6 +22,7 @@
|
||||
#include "rockchip_drm_drv.h"
|
||||
#include "rockchip_drm_fb.h"
|
||||
#include "rockchip_drm_gem.h"
|
||||
#include "rockchip_drm_psr.h"
|
||||
|
||||
#define to_rockchip_fb(x) container_of(x, struct rockchip_drm_fb, fb)
|
||||
|
||||
@@ -63,9 +64,20 @@ static int rockchip_drm_fb_create_handle(struct drm_framebuffer *fb,
|
||||
rockchip_fb->obj[0], handle);
|
||||
}
|
||||
|
||||
static int rockchip_drm_fb_dirty(struct drm_framebuffer *fb,
|
||||
struct drm_file *file,
|
||||
unsigned int flags, unsigned int color,
|
||||
struct drm_clip_rect *clips,
|
||||
unsigned int num_clips)
|
||||
{
|
||||
rockchip_drm_psr_flush(fb->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_framebuffer_funcs rockchip_drm_fb_funcs = {
|
||||
.destroy = rockchip_drm_fb_destroy,
|
||||
.create_handle = rockchip_drm_fb_create_handle,
|
||||
.dirty = rockchip_drm_fb_dirty,
|
||||
};
|
||||
|
||||
static struct rockchip_drm_fb *
|
||||
|
245
drivers/gpu/drm/rockchip/rockchip_drm_psr.c
Normal file
245
drivers/gpu/drm/rockchip/rockchip_drm_psr.c
Normal file
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
* Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
|
||||
* Author: Yakir Yang <ykk@rock-chips.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
|
||||
#include "rockchip_drm_drv.h"
|
||||
#include "rockchip_drm_psr.h"
|
||||
|
||||
#define PSR_FLUSH_TIMEOUT msecs_to_jiffies(3000) /* 3 seconds */
|
||||
|
||||
enum psr_state {
|
||||
PSR_FLUSH,
|
||||
PSR_ENABLE,
|
||||
PSR_DISABLE,
|
||||
};
|
||||
|
||||
struct psr_drv {
|
||||
struct list_head list;
|
||||
struct drm_encoder *encoder;
|
||||
|
||||
spinlock_t lock;
|
||||
enum psr_state state;
|
||||
|
||||
struct timer_list flush_timer;
|
||||
|
||||
void (*set)(struct drm_encoder *encoder, bool enable);
|
||||
};
|
||||
|
||||
static struct psr_drv *find_psr_by_crtc(struct drm_crtc *crtc)
|
||||
{
|
||||
struct rockchip_drm_private *drm_drv = crtc->dev->dev_private;
|
||||
struct psr_drv *psr;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&drm_drv->psr_list_lock, flags);
|
||||
list_for_each_entry(psr, &drm_drv->psr_list, list) {
|
||||
if (psr->encoder->crtc == crtc)
|
||||
goto out;
|
||||
}
|
||||
psr = ERR_PTR(-ENODEV);
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(&drm_drv->psr_list_lock, flags);
|
||||
return psr;
|
||||
}
|
||||
|
||||
static void psr_set_state_locked(struct psr_drv *psr, enum psr_state state)
|
||||
{
|
||||
/*
|
||||
* Allowed finite state machine:
|
||||
*
|
||||
* PSR_ENABLE < = = = = = > PSR_FLUSH
|
||||
* | ^ |
|
||||
* | | |
|
||||
* v | |
|
||||
* PSR_DISABLE < - - - - - - - - -
|
||||
*/
|
||||
if (state == psr->state)
|
||||
return;
|
||||
|
||||
/* Requesting a flush when disabled is a noop */
|
||||
if (state == PSR_FLUSH && psr->state == PSR_DISABLE)
|
||||
return;
|
||||
|
||||
psr->state = state;
|
||||
|
||||
/* Already disabled in flush, change the state, but not the hardware */
|
||||
if (state == PSR_DISABLE && psr->state == PSR_FLUSH)
|
||||
return;
|
||||
|
||||
/* Actually commit the state change to hardware */
|
||||
switch (psr->state) {
|
||||
case PSR_ENABLE:
|
||||
psr->set(psr->encoder, true);
|
||||
break;
|
||||
|
||||
case PSR_DISABLE:
|
||||
case PSR_FLUSH:
|
||||
psr->set(psr->encoder, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void psr_set_state(struct psr_drv *psr, enum psr_state state)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&psr->lock, flags);
|
||||
psr_set_state_locked(psr, state);
|
||||
spin_unlock_irqrestore(&psr->lock, flags);
|
||||
}
|
||||
|
||||
static void psr_flush_handler(unsigned long data)
|
||||
{
|
||||
struct psr_drv *psr = (struct psr_drv *)data;
|
||||
unsigned long flags;
|
||||
|
||||
/* If the state has changed since we initiated the flush, do nothing */
|
||||
spin_lock_irqsave(&psr->lock, flags);
|
||||
if (psr->state == PSR_FLUSH)
|
||||
psr_set_state_locked(psr, PSR_ENABLE);
|
||||
spin_unlock_irqrestore(&psr->lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* rockchip_drm_psr_enable - enable the encoder PSR which bind to given CRTC
|
||||
* @crtc: CRTC to obtain the PSR encoder
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, negative errno on failure.
|
||||
*/
|
||||
int rockchip_drm_psr_enable(struct drm_crtc *crtc)
|
||||
{
|
||||
struct psr_drv *psr = find_psr_by_crtc(crtc);
|
||||
|
||||
if (IS_ERR(psr))
|
||||
return PTR_ERR(psr);
|
||||
|
||||
psr_set_state(psr, PSR_ENABLE);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(rockchip_drm_psr_enable);
|
||||
|
||||
/**
|
||||
* rockchip_drm_psr_disable - disable the encoder PSR which bind to given CRTC
|
||||
* @crtc: CRTC to obtain the PSR encoder
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, negative errno on failure.
|
||||
*/
|
||||
int rockchip_drm_psr_disable(struct drm_crtc *crtc)
|
||||
{
|
||||
struct psr_drv *psr = find_psr_by_crtc(crtc);
|
||||
|
||||
if (IS_ERR(psr))
|
||||
return PTR_ERR(psr);
|
||||
|
||||
psr_set_state(psr, PSR_DISABLE);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(rockchip_drm_psr_disable);
|
||||
|
||||
/**
|
||||
* rockchip_drm_psr_flush - force to flush all registered PSR encoders
|
||||
* @dev: drm device
|
||||
*
|
||||
* Disable the PSR function for all registered encoders, and then enable the
|
||||
* PSR function back after PSR_FLUSH_TIMEOUT. If encoder PSR state have been
|
||||
* changed during flush time, then keep the state no change after flush
|
||||
* timeout.
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, negative errno on failure.
|
||||
*/
|
||||
void rockchip_drm_psr_flush(struct drm_device *dev)
|
||||
{
|
||||
struct rockchip_drm_private *drm_drv = dev->dev_private;
|
||||
struct psr_drv *psr;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&drm_drv->psr_list_lock, flags);
|
||||
list_for_each_entry(psr, &drm_drv->psr_list, list) {
|
||||
mod_timer(&psr->flush_timer,
|
||||
round_jiffies_up(jiffies + PSR_FLUSH_TIMEOUT));
|
||||
|
||||
psr_set_state(psr, PSR_FLUSH);
|
||||
}
|
||||
spin_unlock_irqrestore(&drm_drv->psr_list_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(rockchip_drm_psr_flush);
|
||||
|
||||
/**
|
||||
* rockchip_drm_psr_register - register encoder to psr driver
|
||||
* @encoder: encoder that obtain the PSR function
|
||||
* @psr_set: call back to set PSR state
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, negative errno on failure.
|
||||
*/
|
||||
int rockchip_drm_psr_register(struct drm_encoder *encoder,
|
||||
void (*psr_set)(struct drm_encoder *, bool enable))
|
||||
{
|
||||
struct rockchip_drm_private *drm_drv = encoder->dev->dev_private;
|
||||
struct psr_drv *psr;
|
||||
unsigned long flags;
|
||||
|
||||
if (!encoder || !psr_set)
|
||||
return -EINVAL;
|
||||
|
||||
psr = kzalloc(sizeof(struct psr_drv), GFP_KERNEL);
|
||||
if (!psr)
|
||||
return -ENOMEM;
|
||||
|
||||
setup_timer(&psr->flush_timer, psr_flush_handler, (unsigned long)psr);
|
||||
spin_lock_init(&psr->lock);
|
||||
|
||||
psr->state = PSR_DISABLE;
|
||||
psr->encoder = encoder;
|
||||
psr->set = psr_set;
|
||||
|
||||
spin_lock_irqsave(&drm_drv->psr_list_lock, flags);
|
||||
list_add_tail(&psr->list, &drm_drv->psr_list);
|
||||
spin_unlock_irqrestore(&drm_drv->psr_list_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(rockchip_drm_psr_register);
|
||||
|
||||
/**
|
||||
* rockchip_drm_psr_unregister - unregister encoder to psr driver
|
||||
* @encoder: encoder that obtain the PSR function
|
||||
* @psr_set: call back to set PSR state
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, negative errno on failure.
|
||||
*/
|
||||
void rockchip_drm_psr_unregister(struct drm_encoder *encoder)
|
||||
{
|
||||
struct rockchip_drm_private *drm_drv = encoder->dev->dev_private;
|
||||
struct psr_drv *psr, *n;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&drm_drv->psr_list_lock, flags);
|
||||
list_for_each_entry_safe(psr, n, &drm_drv->psr_list, list) {
|
||||
if (psr->encoder == encoder) {
|
||||
del_timer(&psr->flush_timer);
|
||||
list_del(&psr->list);
|
||||
kfree(psr);
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&drm_drv->psr_list_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(rockchip_drm_psr_unregister);
|
26
drivers/gpu/drm/rockchip/rockchip_drm_psr.h
Normal file
26
drivers/gpu/drm/rockchip/rockchip_drm_psr.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
|
||||
* Author: Yakir Yang <ykk@rock-chips.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __ROCKCHIP_DRM_PSR___
|
||||
#define __ROCKCHIP_DRM_PSR___
|
||||
|
||||
void rockchip_drm_psr_flush(struct drm_device *dev);
|
||||
int rockchip_drm_psr_enable(struct drm_crtc *crtc);
|
||||
int rockchip_drm_psr_disable(struct drm_crtc *crtc);
|
||||
|
||||
int rockchip_drm_psr_register(struct drm_encoder *encoder,
|
||||
void (*psr_set)(struct drm_encoder *, bool enable));
|
||||
void rockchip_drm_psr_unregister(struct drm_encoder *encoder);
|
||||
|
||||
#endif /* __ROCKCHIP_DRM_PSR__ */
|
@@ -34,17 +34,21 @@
|
||||
#include "rockchip_drm_drv.h"
|
||||
#include "rockchip_drm_gem.h"
|
||||
#include "rockchip_drm_fb.h"
|
||||
#include "rockchip_drm_psr.h"
|
||||
#include "rockchip_drm_vop.h"
|
||||
|
||||
#define __REG_SET_RELAXED(x, off, mask, shift, v) \
|
||||
vop_mask_write_relaxed(x, off, (mask) << shift, (v) << shift)
|
||||
#define __REG_SET_NORMAL(x, off, mask, shift, v) \
|
||||
vop_mask_write(x, off, (mask) << shift, (v) << shift)
|
||||
#define __REG_SET_RELAXED(x, off, mask, shift, v, write_mask) \
|
||||
vop_mask_write(x, off, mask, shift, v, write_mask, true)
|
||||
|
||||
#define __REG_SET_NORMAL(x, off, mask, shift, v, write_mask) \
|
||||
vop_mask_write(x, off, mask, shift, v, write_mask, false)
|
||||
|
||||
#define REG_SET(x, base, reg, v, mode) \
|
||||
__REG_SET_##mode(x, base + reg.offset, reg.mask, reg.shift, v)
|
||||
__REG_SET_##mode(x, base + reg.offset, \
|
||||
reg.mask, reg.shift, v, reg.write_mask)
|
||||
#define REG_SET_MASK(x, base, reg, mask, v, mode) \
|
||||
__REG_SET_##mode(x, base + reg.offset, mask, reg.shift, v)
|
||||
__REG_SET_##mode(x, base + reg.offset, \
|
||||
mask, reg.shift, v, reg.write_mask)
|
||||
|
||||
#define VOP_WIN_SET(x, win, name, v) \
|
||||
REG_SET(x, win->base, win->phy->name, v, RELAXED)
|
||||
@@ -106,6 +110,7 @@ struct vop {
|
||||
struct device *dev;
|
||||
struct drm_device *drm_dev;
|
||||
bool is_enabled;
|
||||
bool vblank_active;
|
||||
|
||||
/* mutex vsync_ work */
|
||||
struct mutex vsync_mutex;
|
||||
@@ -116,6 +121,8 @@ struct vop {
|
||||
/* protected by dev->event_lock */
|
||||
struct drm_pending_vblank_event *event;
|
||||
|
||||
struct completion line_flag_completion;
|
||||
|
||||
const struct vop_data *data;
|
||||
|
||||
uint32_t *regsbak;
|
||||
@@ -162,27 +169,25 @@ static inline uint32_t vop_read_reg(struct vop *vop, uint32_t base,
|
||||
}
|
||||
|
||||
static inline void vop_mask_write(struct vop *vop, uint32_t offset,
|
||||
uint32_t mask, uint32_t v)
|
||||
uint32_t mask, uint32_t shift, uint32_t v,
|
||||
bool write_mask, bool relaxed)
|
||||
{
|
||||
if (mask) {
|
||||
if (!mask)
|
||||
return;
|
||||
|
||||
if (write_mask) {
|
||||
v = ((v << shift) & 0xffff) | (mask << (shift + 16));
|
||||
} else {
|
||||
uint32_t cached_val = vop->regsbak[offset >> 2];
|
||||
|
||||
cached_val = (cached_val & ~mask) | v;
|
||||
writel(cached_val, vop->regs + offset);
|
||||
vop->regsbak[offset >> 2] = cached_val;
|
||||
v = (cached_val & ~(mask << shift)) | ((v & mask) << shift);
|
||||
vop->regsbak[offset >> 2] = v;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void vop_mask_write_relaxed(struct vop *vop, uint32_t offset,
|
||||
uint32_t mask, uint32_t v)
|
||||
{
|
||||
if (mask) {
|
||||
uint32_t cached_val = vop->regsbak[offset >> 2];
|
||||
|
||||
cached_val = (cached_val & ~mask) | v;
|
||||
writel_relaxed(cached_val, vop->regs + offset);
|
||||
vop->regsbak[offset >> 2] = cached_val;
|
||||
}
|
||||
if (relaxed)
|
||||
writel_relaxed(v, vop->regs + offset);
|
||||
else
|
||||
writel(v, vop->regs + offset);
|
||||
}
|
||||
|
||||
static 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)
|
||||
spin_unlock_irqrestore(&vop->irq_lock, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* (1) each frame starts at the start of the Vsync pulse which is signaled by
|
||||
* the "FRAME_SYNC" interrupt.
|
||||
* (2) the active data region of each frame ends at dsp_vact_end
|
||||
* (3) we should program this same number (dsp_vact_end) into dsp_line_frag_num,
|
||||
* to get "LINE_FLAG" interrupt at the end of the active on screen data.
|
||||
*
|
||||
* VOP_INTR_CTRL0.dsp_line_frag_num = VOP_DSP_VACT_ST_END.dsp_vact_end
|
||||
* Interrupts
|
||||
* LINE_FLAG -------------------------------+
|
||||
* FRAME_SYNC ----+ |
|
||||
* | |
|
||||
* v v
|
||||
* | Vsync | Vbp | Vactive | Vfp |
|
||||
* ^ ^ ^ ^
|
||||
* | | | |
|
||||
* | | | |
|
||||
* dsp_vs_end ------------+ | | | VOP_DSP_VTOTAL_VS_END
|
||||
* dsp_vact_start --------------+ | | VOP_DSP_VACT_ST_END
|
||||
* dsp_vact_end ----------------------------+ | VOP_DSP_VACT_ST_END
|
||||
* dsp_total -------------------------------------+ VOP_DSP_VTOTAL_VS_END
|
||||
*/
|
||||
static bool vop_line_flag_irq_is_enabled(struct vop *vop)
|
||||
{
|
||||
uint32_t line_flag_irq;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&vop->irq_lock, flags);
|
||||
|
||||
line_flag_irq = VOP_INTR_GET_TYPE(vop, enable, LINE_FLAG_INTR);
|
||||
|
||||
spin_unlock_irqrestore(&vop->irq_lock, flags);
|
||||
|
||||
return !!line_flag_irq;
|
||||
}
|
||||
|
||||
static void vop_line_flag_irq_enable(struct vop *vop, int line_num)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (WARN_ON(!vop->is_enabled))
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&vop->irq_lock, flags);
|
||||
|
||||
VOP_CTRL_SET(vop, line_flag_num[0], line_num);
|
||||
VOP_INTR_SET_TYPE(vop, enable, LINE_FLAG_INTR, 1);
|
||||
|
||||
spin_unlock_irqrestore(&vop->irq_lock, flags);
|
||||
}
|
||||
|
||||
static void vop_line_flag_irq_disable(struct vop *vop)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (WARN_ON(!vop->is_enabled))
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&vop->irq_lock, flags);
|
||||
|
||||
VOP_INTR_SET_TYPE(vop, enable, LINE_FLAG_INTR, 0);
|
||||
|
||||
spin_unlock_irqrestore(&vop->irq_lock, flags);
|
||||
}
|
||||
|
||||
static int vop_enable(struct drm_crtc *crtc)
|
||||
{
|
||||
struct vop *vop = to_vop(crtc);
|
||||
@@ -849,6 +919,8 @@ static int vop_crtc_enable_vblank(struct drm_crtc *crtc)
|
||||
|
||||
spin_unlock_irqrestore(&vop->irq_lock, flags);
|
||||
|
||||
rockchip_drm_psr_disable(&vop->crtc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -865,6 +937,8 @@ static void vop_crtc_disable_vblank(struct drm_crtc *crtc)
|
||||
VOP_INTR_SET_TYPE(vop, enable, FS_INTR, 0);
|
||||
|
||||
spin_unlock_irqrestore(&vop->irq_lock, flags);
|
||||
|
||||
rockchip_drm_psr_enable(&vop->crtc);
|
||||
}
|
||||
|
||||
static void vop_crtc_wait_for_update(struct drm_crtc *crtc)
|
||||
@@ -908,7 +982,7 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
|
||||
u16 vsync_len = adjusted_mode->vsync_end - adjusted_mode->vsync_start;
|
||||
u16 vact_st = adjusted_mode->vtotal - adjusted_mode->vsync_start;
|
||||
u16 vact_end = vact_st + vdisplay;
|
||||
uint32_t val;
|
||||
uint32_t pin_pol, val;
|
||||
int ret;
|
||||
|
||||
WARN_ON(vop->event);
|
||||
@@ -955,21 +1029,26 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
|
||||
vop_dsp_hold_valid_irq_disable(vop);
|
||||
}
|
||||
|
||||
val = 0x8;
|
||||
val |= (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : 1;
|
||||
val |= (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : (1 << 1);
|
||||
VOP_CTRL_SET(vop, pin_pol, val);
|
||||
pin_pol = 0x8;
|
||||
pin_pol |= (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : 1;
|
||||
pin_pol |= (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : (1 << 1);
|
||||
VOP_CTRL_SET(vop, pin_pol, pin_pol);
|
||||
|
||||
switch (s->output_type) {
|
||||
case DRM_MODE_CONNECTOR_LVDS:
|
||||
VOP_CTRL_SET(vop, rgb_en, 1);
|
||||
VOP_CTRL_SET(vop, rgb_pin_pol, pin_pol);
|
||||
break;
|
||||
case DRM_MODE_CONNECTOR_eDP:
|
||||
VOP_CTRL_SET(vop, edp_pin_pol, pin_pol);
|
||||
VOP_CTRL_SET(vop, edp_en, 1);
|
||||
break;
|
||||
case DRM_MODE_CONNECTOR_HDMIA:
|
||||
VOP_CTRL_SET(vop, hdmi_pin_pol, pin_pol);
|
||||
VOP_CTRL_SET(vop, hdmi_en, 1);
|
||||
break;
|
||||
case DRM_MODE_CONNECTOR_DSI:
|
||||
VOP_CTRL_SET(vop, mipi_pin_pol, pin_pol);
|
||||
VOP_CTRL_SET(vop, mipi_en, 1);
|
||||
break;
|
||||
default:
|
||||
@@ -1016,10 +1095,11 @@ static void vop_crtc_atomic_begin(struct drm_crtc *crtc,
|
||||
struct vop *vop = to_vop(crtc);
|
||||
|
||||
spin_lock_irq(&crtc->dev->event_lock);
|
||||
if (crtc->state->event) {
|
||||
WARN_ON(drm_crtc_vblank_get(crtc) != 0);
|
||||
WARN_ON(vop->event);
|
||||
vop->vblank_active = true;
|
||||
WARN_ON(drm_crtc_vblank_get(crtc) != 0);
|
||||
WARN_ON(vop->event);
|
||||
|
||||
if (crtc->state->event) {
|
||||
vop->event = crtc->state->event;
|
||||
crtc->state->event = NULL;
|
||||
}
|
||||
@@ -1106,12 +1186,14 @@ static void vop_handle_vblank(struct vop *vop)
|
||||
|
||||
spin_lock_irqsave(&drm->event_lock, flags);
|
||||
if (vop->event) {
|
||||
|
||||
drm_crtc_send_vblank_event(crtc, vop->event);
|
||||
drm_crtc_vblank_put(crtc);
|
||||
vop->event = NULL;
|
||||
|
||||
}
|
||||
if (vop->vblank_active) {
|
||||
vop->vblank_active = false;
|
||||
drm_crtc_vblank_put(crtc);
|
||||
}
|
||||
spin_unlock_irqrestore(&drm->event_lock, flags);
|
||||
|
||||
if (!completion_done(&vop->wait_update_complete))
|
||||
@@ -1149,6 +1231,12 @@ static irqreturn_t vop_isr(int irq, void *data)
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
|
||||
if (active_irqs & LINE_FLAG_INTR) {
|
||||
complete(&vop->line_flag_completion);
|
||||
active_irqs &= ~LINE_FLAG_INTR;
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
|
||||
if (active_irqs & FS_INTR) {
|
||||
drm_crtc_handle_vblank(crtc);
|
||||
vop_handle_vblank(vop);
|
||||
@@ -1250,6 +1338,7 @@ static int vop_create_crtc(struct vop *vop)
|
||||
|
||||
init_completion(&vop->dsp_hold_completion);
|
||||
init_completion(&vop->wait_update_complete);
|
||||
init_completion(&vop->line_flag_completion);
|
||||
crtc->port = port;
|
||||
rockchip_register_crtc_funcs(crtc, &private_crtc_funcs);
|
||||
|
||||
@@ -1377,6 +1466,7 @@ static int vop_initial(struct vop *vop)
|
||||
clk_disable(vop->aclk);
|
||||
|
||||
vop->is_enabled = false;
|
||||
vop->vblank_active = false;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -1406,6 +1496,49 @@ static void vop_win_init(struct vop *vop)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* rockchip_drm_wait_line_flag - acqiure the give line flag event
|
||||
* @crtc: CRTC to enable line flag
|
||||
* @line_num: interested line number
|
||||
* @mstimeout: millisecond for timeout
|
||||
*
|
||||
* Driver would hold here until the interested line flag interrupt have
|
||||
* happened or timeout to wait.
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, negative errno on failure.
|
||||
*/
|
||||
int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num,
|
||||
unsigned int mstimeout)
|
||||
{
|
||||
struct vop *vop = to_vop(crtc);
|
||||
unsigned long jiffies_left;
|
||||
|
||||
if (!crtc || !vop->is_enabled)
|
||||
return -ENODEV;
|
||||
|
||||
if (line_num > crtc->mode.vtotal || mstimeout <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (vop_line_flag_irq_is_enabled(vop))
|
||||
return -EBUSY;
|
||||
|
||||
reinit_completion(&vop->line_flag_completion);
|
||||
vop_line_flag_irq_enable(vop, line_num);
|
||||
|
||||
jiffies_left = wait_for_completion_timeout(&vop->line_flag_completion,
|
||||
msecs_to_jiffies(mstimeout));
|
||||
vop_line_flag_irq_disable(vop);
|
||||
|
||||
if (jiffies_left == 0) {
|
||||
dev_err(vop->dev, "Timeout waiting for IRQ\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(rockchip_drm_wait_line_flag);
|
||||
|
||||
static int vop_bind(struct device *dev, struct device *master, void *data)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
@@ -1474,6 +1607,7 @@ static int vop_bind(struct device *dev, struct device *master, void *data)
|
||||
return ret;
|
||||
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -33,6 +33,7 @@ struct vop_reg {
|
||||
uint32_t offset;
|
||||
uint32_t shift;
|
||||
uint32_t mask;
|
||||
bool write_mask;
|
||||
};
|
||||
|
||||
struct vop_ctrl {
|
||||
@@ -48,6 +49,10 @@ struct vop_ctrl {
|
||||
struct vop_reg dither_down;
|
||||
struct vop_reg dither_up;
|
||||
struct vop_reg pin_pol;
|
||||
struct vop_reg rgb_pin_pol;
|
||||
struct vop_reg hdmi_pin_pol;
|
||||
struct vop_reg edp_pin_pol;
|
||||
struct vop_reg mipi_pin_pol;
|
||||
|
||||
struct vop_reg htotal_pw;
|
||||
struct vop_reg hact_st_end;
|
||||
@@ -56,6 +61,8 @@ struct vop_ctrl {
|
||||
struct vop_reg hpost_st_end;
|
||||
struct vop_reg vpost_st_end;
|
||||
|
||||
struct vop_reg line_flag_num[2];
|
||||
|
||||
struct vop_reg cfg_done;
|
||||
};
|
||||
|
||||
|
@@ -23,7 +23,14 @@
|
||||
#define VOP_REG(off, _mask, s) \
|
||||
{.offset = off, \
|
||||
.mask = _mask, \
|
||||
.shift = s,}
|
||||
.shift = s, \
|
||||
.write_mask = false,}
|
||||
|
||||
#define VOP_REG_MASK(off, _mask, s) \
|
||||
{.offset = off, \
|
||||
.mask = _mask, \
|
||||
.shift = s, \
|
||||
.write_mask = true,}
|
||||
|
||||
static const uint32_t formats_win_full[] = {
|
||||
DRM_FORMAT_XRGB8888,
|
||||
@@ -50,6 +57,89 @@ static const uint32_t formats_win_lite[] = {
|
||||
DRM_FORMAT_BGR565,
|
||||
};
|
||||
|
||||
static const struct vop_scl_regs rk3036_win_scl = {
|
||||
.scale_yrgb_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
|
||||
.scale_yrgb_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
|
||||
.scale_cbcr_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
|
||||
.scale_cbcr_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
|
||||
};
|
||||
|
||||
static const struct vop_win_phy rk3036_win0_data = {
|
||||
.scl = &rk3036_win_scl,
|
||||
.data_formats = formats_win_full,
|
||||
.nformats = ARRAY_SIZE(formats_win_full),
|
||||
.enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 0),
|
||||
.format = VOP_REG(RK3036_SYS_CTRL, 0x7, 3),
|
||||
.rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 15),
|
||||
.act_info = VOP_REG(RK3036_WIN0_ACT_INFO, 0x1fff1fff, 0),
|
||||
.dsp_info = VOP_REG(RK3036_WIN0_DSP_INFO, 0x0fff0fff, 0),
|
||||
.dsp_st = VOP_REG(RK3036_WIN0_DSP_ST, 0x1fff1fff, 0),
|
||||
.yrgb_mst = VOP_REG(RK3036_WIN0_YRGB_MST, 0xffffffff, 0),
|
||||
.uv_mst = VOP_REG(RK3036_WIN0_CBR_MST, 0xffffffff, 0),
|
||||
.yrgb_vir = VOP_REG(RK3036_WIN0_VIR, 0xffff, 0),
|
||||
.uv_vir = VOP_REG(RK3036_WIN0_VIR, 0x1fff, 16),
|
||||
};
|
||||
|
||||
static const struct vop_win_phy rk3036_win1_data = {
|
||||
.data_formats = formats_win_lite,
|
||||
.nformats = ARRAY_SIZE(formats_win_lite),
|
||||
.enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 1),
|
||||
.format = VOP_REG(RK3036_SYS_CTRL, 0x7, 6),
|
||||
.rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 19),
|
||||
.act_info = VOP_REG(RK3036_WIN1_ACT_INFO, 0x1fff1fff, 0),
|
||||
.dsp_info = VOP_REG(RK3036_WIN1_DSP_INFO, 0x0fff0fff, 0),
|
||||
.dsp_st = VOP_REG(RK3036_WIN1_DSP_ST, 0x1fff1fff, 0),
|
||||
.yrgb_mst = VOP_REG(RK3036_WIN1_MST, 0xffffffff, 0),
|
||||
.yrgb_vir = VOP_REG(RK3036_WIN1_VIR, 0xffff, 0),
|
||||
};
|
||||
|
||||
static const struct vop_win_data rk3036_vop_win_data[] = {
|
||||
{ .base = 0x00, .phy = &rk3036_win0_data,
|
||||
.type = DRM_PLANE_TYPE_PRIMARY },
|
||||
{ .base = 0x00, .phy = &rk3036_win1_data,
|
||||
.type = DRM_PLANE_TYPE_CURSOR },
|
||||
};
|
||||
|
||||
static const int rk3036_vop_intrs[] = {
|
||||
DSP_HOLD_VALID_INTR,
|
||||
FS_INTR,
|
||||
LINE_FLAG_INTR,
|
||||
BUS_ERROR_INTR,
|
||||
};
|
||||
|
||||
static const struct vop_intr rk3036_intr = {
|
||||
.intrs = rk3036_vop_intrs,
|
||||
.nintrs = ARRAY_SIZE(rk3036_vop_intrs),
|
||||
.status = VOP_REG(RK3036_INT_STATUS, 0xf, 0),
|
||||
.enable = VOP_REG(RK3036_INT_STATUS, 0xf, 4),
|
||||
.clear = VOP_REG(RK3036_INT_STATUS, 0xf, 8),
|
||||
};
|
||||
|
||||
static const struct vop_ctrl rk3036_ctrl_data = {
|
||||
.standby = VOP_REG(RK3036_SYS_CTRL, 0x1, 30),
|
||||
.out_mode = VOP_REG(RK3036_DSP_CTRL0, 0xf, 0),
|
||||
.pin_pol = VOP_REG(RK3036_DSP_CTRL0, 0xf, 4),
|
||||
.htotal_pw = VOP_REG(RK3036_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
|
||||
.hact_st_end = VOP_REG(RK3036_DSP_HACT_ST_END, 0x1fff1fff, 0),
|
||||
.vtotal_pw = VOP_REG(RK3036_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
|
||||
.vact_st_end = VOP_REG(RK3036_DSP_VACT_ST_END, 0x1fff1fff, 0),
|
||||
.line_flag_num[0] = VOP_REG(RK3036_INT_STATUS, 0xfff, 12),
|
||||
.cfg_done = VOP_REG(RK3036_REG_CFG_DONE, 0x1, 0),
|
||||
};
|
||||
|
||||
static const struct vop_reg_data rk3036_vop_init_reg_table[] = {
|
||||
{RK3036_DSP_CTRL1, 0x00000000},
|
||||
};
|
||||
|
||||
static const struct vop_data rk3036_vop = {
|
||||
.init_table = rk3036_vop_init_reg_table,
|
||||
.table_size = ARRAY_SIZE(rk3036_vop_init_reg_table),
|
||||
.ctrl = &rk3036_ctrl_data,
|
||||
.intr = &rk3036_intr,
|
||||
.win = rk3036_vop_win_data,
|
||||
.win_size = ARRAY_SIZE(rk3036_vop_win_data),
|
||||
};
|
||||
|
||||
static const struct vop_scl_extension rk3288_win_full_scl_ext = {
|
||||
.cbcr_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 31),
|
||||
.cbcr_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 30),
|
||||
@@ -133,6 +223,7 @@ static const struct vop_ctrl rk3288_ctrl_data = {
|
||||
.vact_st_end = VOP_REG(RK3288_DSP_VACT_ST_END, 0x1fff1fff, 0),
|
||||
.hpost_st_end = VOP_REG(RK3288_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
|
||||
.vpost_st_end = VOP_REG(RK3288_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
|
||||
.line_flag_num[0] = VOP_REG(RK3288_INTR_CTRL0, 0x1fff, 12),
|
||||
.cfg_done = VOP_REG(RK3288_REG_CFG_DONE, 0x1, 0),
|
||||
};
|
||||
|
||||
@@ -190,93 +281,104 @@ static const struct vop_data rk3288_vop = {
|
||||
.win_size = ARRAY_SIZE(rk3288_vop_win_data),
|
||||
};
|
||||
|
||||
static const struct vop_scl_regs rk3036_win_scl = {
|
||||
.scale_yrgb_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
|
||||
.scale_yrgb_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
|
||||
.scale_cbcr_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
|
||||
.scale_cbcr_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
|
||||
static const struct vop_ctrl rk3399_ctrl_data = {
|
||||
.standby = VOP_REG(RK3399_SYS_CTRL, 0x1, 22),
|
||||
.gate_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 23),
|
||||
.rgb_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 12),
|
||||
.hdmi_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 13),
|
||||
.edp_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 14),
|
||||
.mipi_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 15),
|
||||
.dither_down = VOP_REG(RK3399_DSP_CTRL1, 0xf, 1),
|
||||
.dither_up = VOP_REG(RK3399_DSP_CTRL1, 0x1, 6),
|
||||
.data_blank = VOP_REG(RK3399_DSP_CTRL0, 0x1, 19),
|
||||
.out_mode = VOP_REG(RK3399_DSP_CTRL0, 0xf, 0),
|
||||
.rgb_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 16),
|
||||
.hdmi_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 20),
|
||||
.edp_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 24),
|
||||
.mipi_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 28),
|
||||
.htotal_pw = VOP_REG(RK3399_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
|
||||
.hact_st_end = VOP_REG(RK3399_DSP_HACT_ST_END, 0x1fff1fff, 0),
|
||||
.vtotal_pw = VOP_REG(RK3399_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
|
||||
.vact_st_end = VOP_REG(RK3399_DSP_VACT_ST_END, 0x1fff1fff, 0),
|
||||
.hpost_st_end = VOP_REG(RK3399_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
|
||||
.vpost_st_end = VOP_REG(RK3399_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
|
||||
.line_flag_num[0] = VOP_REG(RK3399_LINE_FLAG, 0xffff, 0),
|
||||
.line_flag_num[1] = VOP_REG(RK3399_LINE_FLAG, 0xffff, 16),
|
||||
.cfg_done = VOP_REG_MASK(RK3399_REG_CFG_DONE, 0x1, 0),
|
||||
};
|
||||
|
||||
static const struct vop_win_phy rk3036_win0_data = {
|
||||
.scl = &rk3036_win_scl,
|
||||
.data_formats = formats_win_full,
|
||||
.nformats = ARRAY_SIZE(formats_win_full),
|
||||
.enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 0),
|
||||
.format = VOP_REG(RK3036_SYS_CTRL, 0x7, 3),
|
||||
.rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 15),
|
||||
.act_info = VOP_REG(RK3036_WIN0_ACT_INFO, 0x1fff1fff, 0),
|
||||
.dsp_info = VOP_REG(RK3036_WIN0_DSP_INFO, 0x0fff0fff, 0),
|
||||
.dsp_st = VOP_REG(RK3036_WIN0_DSP_ST, 0x1fff1fff, 0),
|
||||
.yrgb_mst = VOP_REG(RK3036_WIN0_YRGB_MST, 0xffffffff, 0),
|
||||
.uv_mst = VOP_REG(RK3036_WIN0_CBR_MST, 0xffffffff, 0),
|
||||
.yrgb_vir = VOP_REG(RK3036_WIN0_VIR, 0xffff, 0),
|
||||
.uv_vir = VOP_REG(RK3036_WIN0_VIR, 0x1fff, 16),
|
||||
};
|
||||
|
||||
static const struct vop_win_phy rk3036_win1_data = {
|
||||
.data_formats = formats_win_lite,
|
||||
.nformats = ARRAY_SIZE(formats_win_lite),
|
||||
.enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 1),
|
||||
.format = VOP_REG(RK3036_SYS_CTRL, 0x7, 6),
|
||||
.rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 19),
|
||||
.act_info = VOP_REG(RK3036_WIN1_ACT_INFO, 0x1fff1fff, 0),
|
||||
.dsp_info = VOP_REG(RK3036_WIN1_DSP_INFO, 0x0fff0fff, 0),
|
||||
.dsp_st = VOP_REG(RK3036_WIN1_DSP_ST, 0x1fff1fff, 0),
|
||||
.yrgb_mst = VOP_REG(RK3036_WIN1_MST, 0xffffffff, 0),
|
||||
.yrgb_vir = VOP_REG(RK3036_WIN1_VIR, 0xffff, 0),
|
||||
};
|
||||
|
||||
static const struct vop_win_data rk3036_vop_win_data[] = {
|
||||
{ .base = 0x00, .phy = &rk3036_win0_data,
|
||||
.type = DRM_PLANE_TYPE_PRIMARY },
|
||||
{ .base = 0x00, .phy = &rk3036_win1_data,
|
||||
.type = DRM_PLANE_TYPE_CURSOR },
|
||||
};
|
||||
|
||||
static const int rk3036_vop_intrs[] = {
|
||||
DSP_HOLD_VALID_INTR,
|
||||
static const int rk3399_vop_intrs[] = {
|
||||
FS_INTR,
|
||||
0, 0,
|
||||
LINE_FLAG_INTR,
|
||||
0,
|
||||
BUS_ERROR_INTR,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
DSP_HOLD_VALID_INTR,
|
||||
};
|
||||
|
||||
static const struct vop_intr rk3036_intr = {
|
||||
.intrs = rk3036_vop_intrs,
|
||||
.nintrs = ARRAY_SIZE(rk3036_vop_intrs),
|
||||
.status = VOP_REG(RK3036_INT_STATUS, 0xf, 0),
|
||||
.enable = VOP_REG(RK3036_INT_STATUS, 0xf, 4),
|
||||
.clear = VOP_REG(RK3036_INT_STATUS, 0xf, 8),
|
||||
static const struct vop_intr rk3399_vop_intr = {
|
||||
.intrs = rk3399_vop_intrs,
|
||||
.nintrs = ARRAY_SIZE(rk3399_vop_intrs),
|
||||
.status = VOP_REG_MASK(RK3399_INTR_STATUS0, 0xffff, 0),
|
||||
.enable = VOP_REG_MASK(RK3399_INTR_EN0, 0xffff, 0),
|
||||
.clear = VOP_REG_MASK(RK3399_INTR_CLEAR0, 0xffff, 0),
|
||||
};
|
||||
|
||||
static const struct vop_ctrl rk3036_ctrl_data = {
|
||||
.standby = VOP_REG(RK3036_SYS_CTRL, 0x1, 30),
|
||||
.out_mode = VOP_REG(RK3036_DSP_CTRL0, 0xf, 0),
|
||||
.pin_pol = VOP_REG(RK3036_DSP_CTRL0, 0xf, 4),
|
||||
.htotal_pw = VOP_REG(RK3036_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
|
||||
.hact_st_end = VOP_REG(RK3036_DSP_HACT_ST_END, 0x1fff1fff, 0),
|
||||
.vtotal_pw = VOP_REG(RK3036_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
|
||||
.vact_st_end = VOP_REG(RK3036_DSP_VACT_ST_END, 0x1fff1fff, 0),
|
||||
.cfg_done = VOP_REG(RK3036_REG_CFG_DONE, 0x1, 0),
|
||||
static const struct vop_reg_data rk3399_init_reg_table[] = {
|
||||
{RK3399_SYS_CTRL, 0x2000f800},
|
||||
{RK3399_DSP_CTRL0, 0x00000000},
|
||||
{RK3399_WIN0_CTRL0, 0x00000080},
|
||||
{RK3399_WIN1_CTRL0, 0x00000080},
|
||||
/* TODO: Win2/3 support multiple area function, but we haven't found
|
||||
* a suitable way to use it yet, so let's just use them as other windows
|
||||
* with only area 0 enabled.
|
||||
*/
|
||||
{RK3399_WIN2_CTRL0, 0x00000010},
|
||||
{RK3399_WIN3_CTRL0, 0x00000010},
|
||||
};
|
||||
|
||||
static const struct vop_reg_data rk3036_vop_init_reg_table[] = {
|
||||
{RK3036_DSP_CTRL1, 0x00000000},
|
||||
static const struct vop_data rk3399_vop_big = {
|
||||
.init_table = rk3399_init_reg_table,
|
||||
.table_size = ARRAY_SIZE(rk3399_init_reg_table),
|
||||
.intr = &rk3399_vop_intr,
|
||||
.ctrl = &rk3399_ctrl_data,
|
||||
/*
|
||||
* rk3399 vop big windows register layout is same as rk3288.
|
||||
*/
|
||||
.win = rk3288_vop_win_data,
|
||||
.win_size = ARRAY_SIZE(rk3288_vop_win_data),
|
||||
};
|
||||
|
||||
static const struct vop_data rk3036_vop = {
|
||||
.init_table = rk3036_vop_init_reg_table,
|
||||
.table_size = ARRAY_SIZE(rk3036_vop_init_reg_table),
|
||||
.ctrl = &rk3036_ctrl_data,
|
||||
.intr = &rk3036_intr,
|
||||
.win = rk3036_vop_win_data,
|
||||
.win_size = ARRAY_SIZE(rk3036_vop_win_data),
|
||||
static const struct vop_win_data rk3399_vop_lit_win_data[] = {
|
||||
{ .base = 0x00, .phy = &rk3288_win01_data,
|
||||
.type = DRM_PLANE_TYPE_PRIMARY },
|
||||
{ .base = 0x00, .phy = &rk3288_win23_data,
|
||||
.type = DRM_PLANE_TYPE_CURSOR},
|
||||
};
|
||||
|
||||
static const struct vop_data rk3399_vop_lit = {
|
||||
.init_table = rk3399_init_reg_table,
|
||||
.table_size = ARRAY_SIZE(rk3399_init_reg_table),
|
||||
.intr = &rk3399_vop_intr,
|
||||
.ctrl = &rk3399_ctrl_data,
|
||||
/*
|
||||
* rk3399 vop lit windows register layout is same as rk3288,
|
||||
* but cut off the win1 and win3 windows.
|
||||
*/
|
||||
.win = rk3399_vop_lit_win_data,
|
||||
.win_size = ARRAY_SIZE(rk3399_vop_lit_win_data),
|
||||
};
|
||||
|
||||
static const struct of_device_id vop_driver_dt_match[] = {
|
||||
{ .compatible = "rockchip,rk3288-vop",
|
||||
.data = &rk3288_vop },
|
||||
{ .compatible = "rockchip,rk3036-vop",
|
||||
.data = &rk3036_vop },
|
||||
{ .compatible = "rockchip,rk3288-vop",
|
||||
.data = &rk3288_vop },
|
||||
{ .compatible = "rockchip,rk3399-vop-big",
|
||||
.data = &rk3399_vop_big },
|
||||
{ .compatible = "rockchip,rk3399-vop-lit",
|
||||
.data = &rk3399_vop_lit },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, vop_driver_dt_match);
|
||||
|
@@ -166,4 +166,197 @@
|
||||
#define RK3036_HWC_LUT_ADDR 0x800
|
||||
/* rk3036 register definition end */
|
||||
|
||||
/* rk3399 register definition */
|
||||
#define RK3399_REG_CFG_DONE 0x00000
|
||||
#define RK3399_VERSION_INFO 0x00004
|
||||
#define RK3399_SYS_CTRL 0x00008
|
||||
#define RK3399_SYS_CTRL1 0x0000c
|
||||
#define RK3399_DSP_CTRL0 0x00010
|
||||
#define RK3399_DSP_CTRL1 0x00014
|
||||
#define RK3399_DSP_BG 0x00018
|
||||
#define RK3399_MCU_CTRL 0x0001c
|
||||
#define RK3399_WB_CTRL0 0x00020
|
||||
#define RK3399_WB_CTRL1 0x00024
|
||||
#define RK3399_WB_YRGB_MST 0x00028
|
||||
#define RK3399_WB_CBR_MST 0x0002c
|
||||
#define RK3399_WIN0_CTRL0 0x00030
|
||||
#define RK3399_WIN0_CTRL1 0x00034
|
||||
#define RK3399_WIN0_COLOR_KEY 0x00038
|
||||
#define RK3399_WIN0_VIR 0x0003c
|
||||
#define RK3399_WIN0_YRGB_MST 0x00040
|
||||
#define RK3399_WIN0_CBR_MST 0x00044
|
||||
#define RK3399_WIN0_ACT_INFO 0x00048
|
||||
#define RK3399_WIN0_DSP_INFO 0x0004c
|
||||
#define RK3399_WIN0_DSP_ST 0x00050
|
||||
#define RK3399_WIN0_SCL_FACTOR_YRGB 0x00054
|
||||
#define RK3399_WIN0_SCL_FACTOR_CBR 0x00058
|
||||
#define RK3399_WIN0_SCL_OFFSET 0x0005c
|
||||
#define RK3399_WIN0_SRC_ALPHA_CTRL 0x00060
|
||||
#define RK3399_WIN0_DST_ALPHA_CTRL 0x00064
|
||||
#define RK3399_WIN0_FADING_CTRL 0x00068
|
||||
#define RK3399_WIN0_CTRL2 0x0006c
|
||||
#define RK3399_WIN1_CTRL0 0x00070
|
||||
#define RK3399_WIN1_CTRL1 0x00074
|
||||
#define RK3399_WIN1_COLOR_KEY 0x00078
|
||||
#define RK3399_WIN1_VIR 0x0007c
|
||||
#define RK3399_WIN1_YRGB_MST 0x00080
|
||||
#define RK3399_WIN1_CBR_MST 0x00084
|
||||
#define RK3399_WIN1_ACT_INFO 0x00088
|
||||
#define RK3399_WIN1_DSP_INFO 0x0008c
|
||||
#define RK3399_WIN1_DSP_ST 0x00090
|
||||
#define RK3399_WIN1_SCL_FACTOR_YRGB 0x00094
|
||||
#define RK3399_WIN1_SCL_FACTOR_CBR 0x00098
|
||||
#define RK3399_WIN1_SCL_OFFSET 0x0009c
|
||||
#define RK3399_WIN1_SRC_ALPHA_CTRL 0x000a0
|
||||
#define RK3399_WIN1_DST_ALPHA_CTRL 0x000a4
|
||||
#define RK3399_WIN1_FADING_CTRL 0x000a8
|
||||
#define RK3399_WIN1_CTRL2 0x000ac
|
||||
#define RK3399_WIN2_CTRL0 0x000b0
|
||||
#define RK3399_WIN2_CTRL1 0x000b4
|
||||
#define RK3399_WIN2_VIR0_1 0x000b8
|
||||
#define RK3399_WIN2_VIR2_3 0x000bc
|
||||
#define RK3399_WIN2_MST0 0x000c0
|
||||
#define RK3399_WIN2_DSP_INFO0 0x000c4
|
||||
#define RK3399_WIN2_DSP_ST0 0x000c8
|
||||
#define RK3399_WIN2_COLOR_KEY 0x000cc
|
||||
#define RK3399_WIN2_MST1 0x000d0
|
||||
#define RK3399_WIN2_DSP_INFO1 0x000d4
|
||||
#define RK3399_WIN2_DSP_ST1 0x000d8
|
||||
#define RK3399_WIN2_SRC_ALPHA_CTRL 0x000dc
|
||||
#define RK3399_WIN2_MST2 0x000e0
|
||||
#define RK3399_WIN2_DSP_INFO2 0x000e4
|
||||
#define RK3399_WIN2_DSP_ST2 0x000e8
|
||||
#define RK3399_WIN2_DST_ALPHA_CTRL 0x000ec
|
||||
#define RK3399_WIN2_MST3 0x000f0
|
||||
#define RK3399_WIN2_DSP_INFO3 0x000f4
|
||||
#define RK3399_WIN2_DSP_ST3 0x000f8
|
||||
#define RK3399_WIN2_FADING_CTRL 0x000fc
|
||||
#define RK3399_WIN3_CTRL0 0x00100
|
||||
#define RK3399_WIN3_CTRL1 0x00104
|
||||
#define RK3399_WIN3_VIR0_1 0x00108
|
||||
#define RK3399_WIN3_VIR2_3 0x0010c
|
||||
#define RK3399_WIN3_MST0 0x00110
|
||||
#define RK3399_WIN3_DSP_INFO0 0x00114
|
||||
#define RK3399_WIN3_DSP_ST0 0x00118
|
||||
#define RK3399_WIN3_COLOR_KEY 0x0011c
|
||||
#define RK3399_WIN3_MST1 0x00120
|
||||
#define RK3399_WIN3_DSP_INFO1 0x00124
|
||||
#define RK3399_WIN3_DSP_ST1 0x00128
|
||||
#define RK3399_WIN3_SRC_ALPHA_CTRL 0x0012c
|
||||
#define RK3399_WIN3_MST2 0x00130
|
||||
#define RK3399_WIN3_DSP_INFO2 0x00134
|
||||
#define RK3399_WIN3_DSP_ST2 0x00138
|
||||
#define RK3399_WIN3_DST_ALPHA_CTRL 0x0013c
|
||||
#define RK3399_WIN3_MST3 0x00140
|
||||
#define RK3399_WIN3_DSP_INFO3 0x00144
|
||||
#define RK3399_WIN3_DSP_ST3 0x00148
|
||||
#define RK3399_WIN3_FADING_CTRL 0x0014c
|
||||
#define RK3399_HWC_CTRL0 0x00150
|
||||
#define RK3399_HWC_CTRL1 0x00154
|
||||
#define RK3399_HWC_MST 0x00158
|
||||
#define RK3399_HWC_DSP_ST 0x0015c
|
||||
#define RK3399_HWC_SRC_ALPHA_CTRL 0x00160
|
||||
#define RK3399_HWC_DST_ALPHA_CTRL 0x00164
|
||||
#define RK3399_HWC_FADING_CTRL 0x00168
|
||||
#define RK3399_HWC_RESERVED1 0x0016c
|
||||
#define RK3399_POST_DSP_HACT_INFO 0x00170
|
||||
#define RK3399_POST_DSP_VACT_INFO 0x00174
|
||||
#define RK3399_POST_SCL_FACTOR_YRGB 0x00178
|
||||
#define RK3399_POST_RESERVED 0x0017c
|
||||
#define RK3399_POST_SCL_CTRL 0x00180
|
||||
#define RK3399_POST_DSP_VACT_INFO_F1 0x00184
|
||||
#define RK3399_DSP_HTOTAL_HS_END 0x00188
|
||||
#define RK3399_DSP_HACT_ST_END 0x0018c
|
||||
#define RK3399_DSP_VTOTAL_VS_END 0x00190
|
||||
#define RK3399_DSP_VACT_ST_END 0x00194
|
||||
#define RK3399_DSP_VS_ST_END_F1 0x00198
|
||||
#define RK3399_DSP_VACT_ST_END_F1 0x0019c
|
||||
#define RK3399_PWM_CTRL 0x001a0
|
||||
#define RK3399_PWM_PERIOD_HPR 0x001a4
|
||||
#define RK3399_PWM_DUTY_LPR 0x001a8
|
||||
#define RK3399_PWM_CNT 0x001ac
|
||||
#define RK3399_BCSH_COLOR_BAR 0x001b0
|
||||
#define RK3399_BCSH_BCS 0x001b4
|
||||
#define RK3399_BCSH_H 0x001b8
|
||||
#define RK3399_BCSH_CTRL 0x001bc
|
||||
#define RK3399_CABC_CTRL0 0x001c0
|
||||
#define RK3399_CABC_CTRL1 0x001c4
|
||||
#define RK3399_CABC_CTRL2 0x001c8
|
||||
#define RK3399_CABC_CTRL3 0x001cc
|
||||
#define RK3399_CABC_GAUSS_LINE0_0 0x001d0
|
||||
#define RK3399_CABC_GAUSS_LINE0_1 0x001d4
|
||||
#define RK3399_CABC_GAUSS_LINE1_0 0x001d8
|
||||
#define RK3399_CABC_GAUSS_LINE1_1 0x001dc
|
||||
#define RK3399_CABC_GAUSS_LINE2_0 0x001e0
|
||||
#define RK3399_CABC_GAUSS_LINE2_1 0x001e4
|
||||
#define RK3399_FRC_LOWER01_0 0x001e8
|
||||
#define RK3399_FRC_LOWER01_1 0x001ec
|
||||
#define RK3399_FRC_LOWER10_0 0x001f0
|
||||
#define RK3399_FRC_LOWER10_1 0x001f4
|
||||
#define RK3399_FRC_LOWER11_0 0x001f8
|
||||
#define RK3399_FRC_LOWER11_1 0x001fc
|
||||
#define RK3399_AFBCD0_CTRL 0x00200
|
||||
#define RK3399_AFBCD0_HDR_PTR 0x00204
|
||||
#define RK3399_AFBCD0_PIC_SIZE 0x00208
|
||||
#define RK3399_AFBCD0_STATUS 0x0020c
|
||||
#define RK3399_AFBCD1_CTRL 0x00220
|
||||
#define RK3399_AFBCD1_HDR_PTR 0x00224
|
||||
#define RK3399_AFBCD1_PIC_SIZE 0x00228
|
||||
#define RK3399_AFBCD1_STATUS 0x0022c
|
||||
#define RK3399_AFBCD2_CTRL 0x00240
|
||||
#define RK3399_AFBCD2_HDR_PTR 0x00244
|
||||
#define RK3399_AFBCD2_PIC_SIZE 0x00248
|
||||
#define RK3399_AFBCD2_STATUS 0x0024c
|
||||
#define RK3399_AFBCD3_CTRL 0x00260
|
||||
#define RK3399_AFBCD3_HDR_PTR 0x00264
|
||||
#define RK3399_AFBCD3_PIC_SIZE 0x00268
|
||||
#define RK3399_AFBCD3_STATUS 0x0026c
|
||||
#define RK3399_INTR_EN0 0x00280
|
||||
#define RK3399_INTR_CLEAR0 0x00284
|
||||
#define RK3399_INTR_STATUS0 0x00288
|
||||
#define RK3399_INTR_RAW_STATUS0 0x0028c
|
||||
#define RK3399_INTR_EN1 0x00290
|
||||
#define RK3399_INTR_CLEAR1 0x00294
|
||||
#define RK3399_INTR_STATUS1 0x00298
|
||||
#define RK3399_INTR_RAW_STATUS1 0x0029c
|
||||
#define RK3399_LINE_FLAG 0x002a0
|
||||
#define RK3399_VOP_STATUS 0x002a4
|
||||
#define RK3399_BLANKING_VALUE 0x002a8
|
||||
#define RK3399_MCU_BYPASS_PORT 0x002ac
|
||||
#define RK3399_WIN0_DSP_BG 0x002b0
|
||||
#define RK3399_WIN1_DSP_BG 0x002b4
|
||||
#define RK3399_WIN2_DSP_BG 0x002b8
|
||||
#define RK3399_WIN3_DSP_BG 0x002bc
|
||||
#define RK3399_YUV2YUV_WIN 0x002c0
|
||||
#define RK3399_YUV2YUV_POST 0x002c4
|
||||
#define RK3399_AUTO_GATING_EN 0x002cc
|
||||
#define RK3399_WIN0_CSC_COE 0x003a0
|
||||
#define RK3399_WIN1_CSC_COE 0x003c0
|
||||
#define RK3399_WIN2_CSC_COE 0x003e0
|
||||
#define RK3399_WIN3_CSC_COE 0x00400
|
||||
#define RK3399_HWC_CSC_COE 0x00420
|
||||
#define RK3399_BCSH_R2Y_CSC_COE 0x00440
|
||||
#define RK3399_BCSH_Y2R_CSC_COE 0x00460
|
||||
#define RK3399_POST_YUV2YUV_Y2R_COE 0x00480
|
||||
#define RK3399_POST_YUV2YUV_3X3_COE 0x004a0
|
||||
#define RK3399_POST_YUV2YUV_R2Y_COE 0x004c0
|
||||
#define RK3399_WIN0_YUV2YUV_Y2R 0x004e0
|
||||
#define RK3399_WIN0_YUV2YUV_3X3 0x00500
|
||||
#define RK3399_WIN0_YUV2YUV_R2Y 0x00520
|
||||
#define RK3399_WIN1_YUV2YUV_Y2R 0x00540
|
||||
#define RK3399_WIN1_YUV2YUV_3X3 0x00560
|
||||
#define RK3399_WIN1_YUV2YUV_R2Y 0x00580
|
||||
#define RK3399_WIN2_YUV2YUV_Y2R 0x005a0
|
||||
#define RK3399_WIN2_YUV2YUV_3X3 0x005c0
|
||||
#define RK3399_WIN2_YUV2YUV_R2Y 0x005e0
|
||||
#define RK3399_WIN3_YUV2YUV_Y2R 0x00600
|
||||
#define RK3399_WIN3_YUV2YUV_3X3 0x00620
|
||||
#define RK3399_WIN3_YUV2YUV_R2Y 0x00640
|
||||
#define RK3399_WIN2_LUT_ADDR 0x01000
|
||||
#define RK3399_WIN3_LUT_ADDR 0x01400
|
||||
#define RK3399_HWC_LUT_ADDR 0x01800
|
||||
#define RK3399_CABC_GAMMA_LUT_ADDR 0x01c00
|
||||
#define RK3399_GAMMA_LUT_ADDR 0x02000
|
||||
/* rk3399 register definition end */
|
||||
|
||||
#endif /* _ROCKCHIP_VOP_REG_H */
|
||||
|
Reference in New Issue
Block a user