mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-10 04:48:04 +09:00
Merge commit '8f92481f41b7570445e85deeb2cb92b9f5864b55'
* commit '8f92481f41b7570445e85deeb2cb92b9f5864b55': media: i2c: cam-tb-setup: add rockit_en_mcu flag media: i2c: cam-tb-setup: add more cmdline parameters for dual camera media: i2c: cam-tb-setup: rk_cam_skip_frame_interval modified to rk_cam_skip media: i2c: cam-tb-setup: enable by VIDEO_ROCKCHIP_THUNDER_BOOT_SETUP mmc: debugfs: Allow more host caps to be moodified drm/rockchip: vop2: Request userspace reset if there is a post_buf_empty strom in non-overlay mode drm/rockchip: vop2: Report POST_BUF_EMPTY event to userspace drm/rockchip: Report drm error event to userspace drm/rockchip: vop2: Avoid call clk_get_rate from vop2_crtc_debugfs_dump when in interrupt context drm/rockchip: dw-dp: enable phy when hpd irq coming drm/rockchip: dw-dp: get eotf type before use it rockchip/drm: dw-dp: dump some info when can't get bus format Revert "drm/rockchip: dw-dp: reset dp controller status" Revert "drm/rockchip: dw-dp: filtering unexpected hotplug event." ARM: dts: rockchip: rk3502: Fix rockchip,temp-freq-table for cpu0_opp_table MALI: bifrost: Sync mali_kbase_mem_linux.c to the status in 'develop-6.1-android14' Change-Id: I077e315e93f33196f06f1307c418de4b241ce2fa
This commit is contained in:
@@ -218,6 +218,7 @@
|
||||
|
||||
rockchip,temp-freq-table = <
|
||||
85000 1008000
|
||||
100000 600000
|
||||
>;
|
||||
|
||||
rockchip,pvtm-voltage-sel = <
|
||||
|
||||
@@ -3814,26 +3814,6 @@ static void dw_dp_link_disable(struct dw_dp *dp)
|
||||
link->train.channel_equalized = false;
|
||||
}
|
||||
|
||||
static void dw_dp_reset(struct dw_dp *dp)
|
||||
{
|
||||
int val;
|
||||
|
||||
disable_irq(dp->irq);
|
||||
regmap_update_bits(dp->regmap, DPTX_SOFT_RESET_CTRL, CONTROLLER_RESET,
|
||||
FIELD_PREP(CONTROLLER_RESET, 1));
|
||||
udelay(100);
|
||||
regmap_update_bits(dp->regmap, DPTX_SOFT_RESET_CTRL, CONTROLLER_RESET,
|
||||
FIELD_PREP(CONTROLLER_RESET, 0));
|
||||
|
||||
dw_dp_init(dp);
|
||||
if (!dp->hpd_gpio) {
|
||||
regmap_read_poll_timeout(dp->regmap, DPTX_HPD_STATUS, val,
|
||||
FIELD_GET(HPD_HOT_PLUG, val), 200, 200000);
|
||||
regmap_write(dp->regmap, DPTX_HPD_STATUS, HPD_HOT_PLUG);
|
||||
}
|
||||
enable_irq(dp->irq);
|
||||
}
|
||||
|
||||
static void dw_dp_mst_encoder_atomic_disable(struct drm_encoder *encoder,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
@@ -3886,10 +3866,8 @@ static void dw_dp_mst_encoder_atomic_disable(struct drm_encoder *encoder,
|
||||
drm_dp_send_power_updown_phy(&dp->mst_mgr, mst_conn->port, false);
|
||||
|
||||
dw_dp_video_disable(dp, mst_enc->stream_id);
|
||||
if (!dp->active_mst_links) {
|
||||
if (!dp->active_mst_links)
|
||||
dw_dp_link_disable(dp);
|
||||
dw_dp_reset(dp);
|
||||
}
|
||||
|
||||
pm_runtime_mark_last_busy(dp->dev);
|
||||
pm_runtime_put_autosuspend(dp->dev);
|
||||
@@ -4470,7 +4448,6 @@ static void dw_dp_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
dw_dp_video_disable(dp, 0);
|
||||
dw_dp_link_disable(dp);
|
||||
bitmap_zero(dp->sdp_reg_bank, SDP_REG_BANK_SIZE);
|
||||
dw_dp_reset(dp);
|
||||
|
||||
extcon_set_state_sync(dp->audio->extcon, EXTCON_DISP_DP, false);
|
||||
dw_dp_audio_handle_plugged_change(dp->audio, false);
|
||||
@@ -4605,6 +4582,8 @@ static u32 *dw_dp_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge,
|
||||
u32 *output_fmts;
|
||||
unsigned int i, j = 0;
|
||||
|
||||
dp->eotf_type = dw_dp_get_eotf(conn_state);
|
||||
|
||||
if (dp->split_mode || dp->dual_connector_split)
|
||||
drm_mode_convert_to_origin_mode(&mode);
|
||||
|
||||
@@ -4675,6 +4654,14 @@ static u32 *dw_dp_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge,
|
||||
|
||||
*num_output_fmts = j;
|
||||
|
||||
if (*num_output_fmts == 0) {
|
||||
dev_warn(dp->dev, "here is not satisfied the require bus format\n");
|
||||
dev_info(dp->dev,
|
||||
"max bpc:%d, max fmt:%x, lanes:%d, rate:%d, bpc:%d, fmt:%d, eotf:%d\n",
|
||||
conn_state->max_bpc, di->color_formats, link->lanes, link->max_rate,
|
||||
dp_state->bpc, dp_state->color_format, dp->eotf_type);
|
||||
}
|
||||
|
||||
return output_fmts;
|
||||
}
|
||||
|
||||
@@ -5009,24 +4996,30 @@ static void dw_dp_hpd_work(struct work_struct *work)
|
||||
dev_dbg(dp->dev, "got hpd irq - %s\n", long_hpd ? "long" : "short");
|
||||
|
||||
if (!long_hpd) {
|
||||
phy_power_on(dp->phy);
|
||||
if (dp->is_mst) {
|
||||
dw_dp_check_mst_status(dp);
|
||||
phy_power_off(dp->phy);
|
||||
return;
|
||||
}
|
||||
|
||||
if (dw_dp_hpd_short_pulse(dp))
|
||||
if (dw_dp_hpd_short_pulse(dp)) {
|
||||
phy_power_off(dp->phy);
|
||||
return;
|
||||
}
|
||||
|
||||
if (dp->compliance.test_active &&
|
||||
dp->compliance.test_type == DP_TEST_LINK_PHY_TEST_PATTERN) {
|
||||
dw_dp_phy_test(dp);
|
||||
/* just do the PHY test and nothing else */
|
||||
phy_power_off(dp->phy);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = dw_dp_link_retrain(dp);
|
||||
if (ret)
|
||||
dev_warn(dp->dev, "Retrain link failed\n");
|
||||
phy_power_off(dp->phy);
|
||||
} else {
|
||||
drm_helper_hpd_irq_event(dp->bridge.dev);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,9 @@
|
||||
#include <linux/component.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/iommu.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/of_reserved_mem.h>
|
||||
#include <uapi/linux/sched/types.h>
|
||||
|
||||
#include <drm/drm_aperture.h>
|
||||
#include <drm/drm_debugfs.h>
|
||||
@@ -1370,6 +1372,28 @@ void rockchip_unregister_crtc_funcs(struct drm_crtc *crtc)
|
||||
priv->crtc_funcs[pipe] = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* a high frequency of page faults will follow up, if
|
||||
* there is a iommu fault, so it's better to limit the
|
||||
* registers dump frequency to save log buffer
|
||||
*
|
||||
* Report no more than once every 10s, give userspace time
|
||||
* to do recovery process, as for a serdes based display
|
||||
* pipeline, the disable/enable time may very long.
|
||||
*/
|
||||
static DEFINE_RATELIMIT_STATE(fault_handler_rate, 10 * HZ, 1);
|
||||
|
||||
static int fault_handler_rate_limit(void)
|
||||
{
|
||||
return __ratelimit(&fault_handler_rate);
|
||||
}
|
||||
|
||||
void rockchip_drm_reset_iommu_fault_handler_rate_limit(void)
|
||||
{
|
||||
fault_handler_rate.begin = 0;
|
||||
fault_handler_rate.printed = 0;
|
||||
}
|
||||
|
||||
static int rockchip_drm_fault_handler(struct iommu_domain *iommu,
|
||||
struct device *dev,
|
||||
unsigned long iova, int flags, void *arg)
|
||||
@@ -1377,11 +1401,27 @@ static int rockchip_drm_fault_handler(struct iommu_domain *iommu,
|
||||
struct drm_device *drm_dev = arg;
|
||||
struct rockchip_drm_private *priv = drm_dev->dev_private;
|
||||
struct drm_crtc *crtc;
|
||||
bool handled = false;
|
||||
|
||||
DRM_ERROR("iommu fault handler flags: 0x%x: count: %lld\n",
|
||||
flags, ++priv->iommu_fault_count);
|
||||
|
||||
if (!fault_handler_rate_limit())
|
||||
return 0;
|
||||
|
||||
DRM_ERROR("iommu fault handler flags: 0x%x\n", flags);
|
||||
drm_for_each_crtc(crtc, drm_dev) {
|
||||
int pipe = drm_crtc_index(crtc);
|
||||
|
||||
/*
|
||||
* Only need to call iommu fault handler once for one iommu fault
|
||||
*/
|
||||
if (priv->crtc_funcs[pipe] &&
|
||||
priv->crtc_funcs[pipe]->iommu_fault_handler &&
|
||||
!handled) {
|
||||
priv->crtc_funcs[pipe]->iommu_fault_handler(crtc, iommu);
|
||||
handled = true;
|
||||
}
|
||||
|
||||
if (priv->crtc_funcs[pipe] &&
|
||||
priv->crtc_funcs[pipe]->regs_dump)
|
||||
priv->crtc_funcs[pipe]->regs_dump(crtc, NULL);
|
||||
@@ -1784,6 +1824,111 @@ static void rockchip_drm_sysfs_fini(struct drm_device *drm_dev)
|
||||
}
|
||||
}
|
||||
|
||||
void rockchip_drm_send_error_event(struct rockchip_drm_private *priv,
|
||||
enum rockchip_drm_error_event_type event)
|
||||
{
|
||||
struct rockchip_drm_error_event *error_event = &priv->error_event;
|
||||
struct drm_event_vblank *e;
|
||||
struct timespec64 tv;
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* Maybe the error thread has not be created.
|
||||
*/
|
||||
if (IS_ERR_OR_NULL(priv->error_event.thread))
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&error_event->lock, flags);
|
||||
tv = ktime_to_timespec64(ktime_get());
|
||||
e = &error_event->event;
|
||||
e->base.type = event;
|
||||
e->base.length = sizeof(*e);
|
||||
e->tv_sec = tv.tv_sec;
|
||||
e->tv_usec = tv.tv_nsec / 1000;
|
||||
e->sequence++;
|
||||
error_event->error_state = true;
|
||||
spin_unlock_irqrestore(&error_event->lock, flags);
|
||||
|
||||
wake_up_interruptible_all(&error_event->wait);
|
||||
}
|
||||
|
||||
static int rockchip_drm_error_event_thread(void *data)
|
||||
{
|
||||
struct drm_device *drm_dev = data;
|
||||
struct rockchip_drm_private *priv = drm_dev->dev_private;
|
||||
struct rockchip_drm_error_event *error_event = &priv->error_event;
|
||||
struct drm_event_vblank *e;
|
||||
int ret = 0;
|
||||
int cnt = 0;
|
||||
|
||||
while (!kthread_should_stop()) {
|
||||
e = &error_event->event;
|
||||
|
||||
error_event->error_state = false;
|
||||
ret = wait_event_interruptible(error_event->wait, error_event->error_state);
|
||||
if (!ret) {
|
||||
sysfs_notify(&drm_dev->dev->kobj, NULL, "error_event");
|
||||
drm_info(drm_dev, "rockchipdrm send_error_event_type: 0x%x, count:%d\n",
|
||||
e->base.type, ++cnt);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t rockchip_drm_error_event_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct drm_device *drm_dev = dev_get_drvdata(dev);
|
||||
struct rockchip_drm_private *priv = drm_dev->dev_private;
|
||||
struct rockchip_drm_error_event *error_event = &priv->error_event;
|
||||
struct drm_event_vblank *e;
|
||||
uint32_t length = sizeof(*e);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&error_event->lock, flags);
|
||||
e = &error_event->event;
|
||||
memcpy(buf, e, length);
|
||||
spin_unlock_irqrestore(&error_event->lock, flags);
|
||||
|
||||
return length;
|
||||
}
|
||||
static DEVICE_ATTR(error_event, 0444, rockchip_drm_error_event_show, NULL);
|
||||
|
||||
static void rockchip_drm_error_event_init(struct drm_device *drm_dev)
|
||||
{
|
||||
struct rockchip_drm_private *priv = drm_dev->dev_private;
|
||||
struct sched_param sched_param = { .sched_priority = MAX_RT_PRIO - 1 };
|
||||
int ret;
|
||||
|
||||
ret = device_create_file(drm_dev->dev, &dev_attr_error_event);
|
||||
if (ret) {
|
||||
dev_warn(drm_dev->dev, "failed to create vcnt event file\n");
|
||||
return;
|
||||
}
|
||||
|
||||
init_waitqueue_head(&priv->error_event.wait);
|
||||
spin_lock_init(&priv->error_event.lock);
|
||||
priv->error_event.thread = kthread_run(rockchip_drm_error_event_thread,
|
||||
drm_dev, "display-error-event-thread");
|
||||
if (IS_ERR(priv->error_event.thread)) {
|
||||
priv->error_event.thread = NULL;
|
||||
drm_err(drm_dev, "failed to run display error_event thread\n");
|
||||
} else {
|
||||
sched_setscheduler(priv->error_event.thread, SCHED_FIFO, &sched_param);
|
||||
drm_info(drm_dev, "run display error_event monitor\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void rockchip_drm_error_event_fini(struct drm_device *drm_dev)
|
||||
{
|
||||
struct rockchip_drm_private *priv = drm_dev->dev_private;
|
||||
|
||||
if (priv->error_event.thread)
|
||||
kthread_stop(priv->error_event.thread);
|
||||
device_remove_file(drm_dev->dev, &dev_attr_error_event);
|
||||
}
|
||||
|
||||
static int rockchip_drm_bind(struct device *dev)
|
||||
{
|
||||
struct drm_device *drm_dev;
|
||||
@@ -1891,6 +2036,8 @@ static int rockchip_drm_bind(struct device *dev)
|
||||
if (ret)
|
||||
goto err_drm_fbdev_fini;
|
||||
|
||||
rockchip_drm_error_event_init(drm_dev);
|
||||
|
||||
return 0;
|
||||
err_drm_fbdev_fini:
|
||||
rockchip_drm_fbdev_fini(drm_dev);
|
||||
@@ -1915,6 +2062,7 @@ static void rockchip_drm_unbind(struct device *dev)
|
||||
{
|
||||
struct drm_device *drm_dev = dev_get_drvdata(dev);
|
||||
|
||||
rockchip_drm_error_event_fini(drm_dev);
|
||||
rockchip_drm_sysfs_fini(drm_dev);
|
||||
rockchip_drm_fbdev_fini(drm_dev);
|
||||
drm_dev_unregister(drm_dev);
|
||||
|
||||
@@ -349,6 +349,15 @@ struct rockchip_drm_vcnt {
|
||||
int pipe;
|
||||
};
|
||||
|
||||
struct rockchip_drm_error_event {
|
||||
wait_queue_head_t wait;
|
||||
struct task_struct *thread;
|
||||
struct list_head event_list;
|
||||
struct drm_event_vblank event;
|
||||
bool error_state;
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
struct rockchip_logo {
|
||||
dma_addr_t dma_addr;
|
||||
struct drm_mm_node logo_reserved_node;
|
||||
@@ -511,6 +520,7 @@ struct rockchip_crtc_funcs {
|
||||
int (*crtc_set_color_bar)(struct drm_crtc *crtc, enum rockchip_color_bar_mode mode);
|
||||
int (*set_aclk)(struct drm_crtc *crtc, enum rockchip_drm_vop_aclk_mode aclk_mode, struct dmcfreq_vop_info *vop_bw_info);
|
||||
int (*get_crc)(struct drm_crtc *crtc);
|
||||
void (*iommu_fault_handler)(struct drm_crtc *crtc, struct iommu_domain *iommu);
|
||||
};
|
||||
|
||||
struct rockchip_dclk_pll {
|
||||
@@ -558,6 +568,8 @@ struct rockchip_drm_private {
|
||||
|
||||
const struct rockchip_crtc_funcs *crtc_funcs[ROCKCHIP_MAX_CRTC];
|
||||
|
||||
uint64_t iommu_fault_count;
|
||||
|
||||
struct rockchip_dclk_pll default_pll;
|
||||
struct rockchip_dclk_pll hdmi_pll;
|
||||
|
||||
@@ -568,6 +580,8 @@ struct rockchip_drm_private {
|
||||
struct mutex ovl_lock;
|
||||
|
||||
struct rockchip_drm_vcnt vcnt[ROCKCHIP_MAX_CRTC];
|
||||
struct rockchip_drm_error_event error_event;
|
||||
|
||||
/**
|
||||
* @loader_protect
|
||||
* ignore restore_fbdev_mode_atomic when in logo on state
|
||||
@@ -647,6 +661,9 @@ int rockchip_drm_dclk_set_rate(u32 version, struct clk *dclk, unsigned long rate
|
||||
bool rockchip_drm_is_afbc(struct drm_plane *plane, u64 modifier);
|
||||
bool rockchip_drm_is_rfbc(struct drm_plane *plane, u64 modifier);
|
||||
const char *rockchip_drm_modifier_to_string(uint64_t modifier);
|
||||
void rockchip_drm_reset_iommu_fault_handler_rate_limit(void);
|
||||
void rockchip_drm_send_error_event(struct rockchip_drm_private *priv,
|
||||
enum rockchip_drm_error_event_type event);
|
||||
|
||||
__printf(3, 4)
|
||||
void rockchip_drm_dbg(const struct device *dev,
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/fixp-arith.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
@@ -817,6 +818,11 @@ struct vop2_video_port {
|
||||
*/
|
||||
bool has_extra_layer;
|
||||
|
||||
/**
|
||||
* @has_scale_down_layer: use layer for scale down
|
||||
*/
|
||||
bool has_scale_down_layer;
|
||||
|
||||
/**
|
||||
* @crc_frame_num: calc crc frame num
|
||||
*/
|
||||
@@ -840,6 +846,11 @@ struct vop2_resource {
|
||||
void __iomem *regs;
|
||||
};
|
||||
|
||||
struct vop2_err_event {
|
||||
u64 count;
|
||||
unsigned long begin;
|
||||
};
|
||||
|
||||
struct vop2 {
|
||||
u32 version;
|
||||
struct device *dev;
|
||||
@@ -882,6 +893,16 @@ struct vop2 {
|
||||
*/
|
||||
bool skip_ref_fb;
|
||||
|
||||
/*
|
||||
* report iommu fault event to userspace
|
||||
*/
|
||||
bool report_iommu_fault;
|
||||
|
||||
/*
|
||||
* report post buf empty error event to userspace
|
||||
*/
|
||||
bool report_post_buf_empty;
|
||||
|
||||
bool loader_protect;
|
||||
|
||||
bool aclk_rate_reset;
|
||||
@@ -962,6 +983,9 @@ struct vop2 {
|
||||
unsigned long aclk_target_freq;
|
||||
u32 aclk_mode_rate[ROCKCHIP_VOP_ACLK_MAX_MODE];
|
||||
#endif
|
||||
bool iommu_fault_in_progress;
|
||||
|
||||
struct vop2_err_event post_buf_empty;
|
||||
|
||||
/* aclk auto cs div */
|
||||
u32 csu_div;
|
||||
@@ -2903,6 +2927,8 @@ static void vop2_setup_scale(struct vop2 *vop2, struct vop2_win *win,
|
||||
const struct vop2_win_data *win_data = &vop2_data->win[win->win_id];
|
||||
struct vop2_plane_state *vpstate = to_vop2_plane_state(pstate);
|
||||
struct drm_framebuffer *fb = pstate->fb;
|
||||
struct drm_crtc *crtc = pstate->crtc;
|
||||
struct vop2_video_port *vp = to_vop2_video_port(crtc);
|
||||
uint32_t pixel_format = fb->format->format;
|
||||
const struct drm_format_info *info = drm_format_info(pixel_format);
|
||||
uint8_t hsub = info->hsub;
|
||||
@@ -2975,6 +3001,9 @@ static void vop2_setup_scale(struct vop2 *vop2, struct vop2_win *win,
|
||||
yrgb_hor_scl_mode = scl_get_scl_mode(src_w, dst_w);
|
||||
yrgb_ver_scl_mode = scl_get_scl_mode(src_h, dst_h);
|
||||
|
||||
if (yrgb_hor_scl_mode == SCALE_DOWN || yrgb_ver_scl_mode == SCALE_DOWN)
|
||||
vp->has_scale_down_layer = true;
|
||||
|
||||
if (yrgb_hor_scl_mode == SCALE_UP)
|
||||
hscl_filter_mode = win_data->hsu_filter_mode;
|
||||
else
|
||||
@@ -4267,6 +4296,87 @@ static int vop3_get_esmart_lb_mode(struct vop2 *vop2)
|
||||
return vop2->data->esmart_lb_mode_map[0].lb_map_value;
|
||||
}
|
||||
|
||||
static bool vop2_non_overlay_mode(struct vop2 *vop2)
|
||||
{
|
||||
struct vop2_video_port *vp;
|
||||
int i;
|
||||
bool non_ovl_mode = true;
|
||||
|
||||
for (i = 0; i < vop2->data->nr_vps; i++) {
|
||||
vp = &vop2->vps[i];
|
||||
if (vp->nr_layers > 1 || vp->has_scale_down_layer) {
|
||||
non_ovl_mode = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return non_ovl_mode;
|
||||
}
|
||||
|
||||
/*
|
||||
* POST_BUF_EMPTY will cause hundreds thousands of interrupts strom per
|
||||
* second.
|
||||
*/
|
||||
|
||||
#define POST_BUF_EMPTY_COUNT_PER_MINUTE 100
|
||||
static DEFINE_RATELIMIT_STATE(post_buf_empty_handler_rate, 5 * HZ, 10);
|
||||
|
||||
static int vop2_post_buf_empty_handler_rate_limit(void)
|
||||
{
|
||||
return __ratelimit(&post_buf_empty_handler_rate);
|
||||
}
|
||||
|
||||
static void vop2_reset_post_buf_empty_handler_rate_limit(struct vop2 *vop2)
|
||||
{
|
||||
vop2->post_buf_empty.begin = 0;
|
||||
vop2->post_buf_empty.count = 0;
|
||||
}
|
||||
|
||||
static void vop2_handle_post_buf_empty(struct drm_crtc *crtc)
|
||||
{
|
||||
struct vop2_video_port *vp = to_vop2_video_port(crtc);
|
||||
struct vop2 *vop2 = vp->vop2;
|
||||
struct rockchip_drm_private *private = vop2->drm_dev->dev_private;
|
||||
struct vop2_err_event *event = &vop2->post_buf_empty;
|
||||
enum rockchip_drm_error_event_type type;
|
||||
|
||||
if (!vop2->report_post_buf_empty)
|
||||
return;
|
||||
|
||||
/*
|
||||
* No need to handle POST_BUF_EMPTY if we are in iommu fault,
|
||||
* because we will try to recovery from the iommu fault handle
|
||||
*/
|
||||
if (vop2->iommu_fault_in_progress)
|
||||
return;
|
||||
|
||||
if (!event->begin)
|
||||
event->begin = jiffies;
|
||||
|
||||
if (vop2_post_buf_empty_handler_rate_limit())
|
||||
event->count++;
|
||||
|
||||
if (time_is_before_jiffies(event->begin + 60 * HZ)) {
|
||||
if (event->count >= POST_BUF_EMPTY_COUNT_PER_MINUTE) {
|
||||
/*
|
||||
* Request userspace disable then enable all display
|
||||
* pipeline if still POST_BUF_EMPTY in non-overlay
|
||||
* and non-scale mode
|
||||
*/
|
||||
if (vop2_non_overlay_mode(vop2))
|
||||
type = ROCKCHIP_DRM_ERROR_EVENT_REQUEST_RESET;
|
||||
else
|
||||
type = ROCKCHIP_DRM_ERROR_EVENT_POST_BUF_EMPTY;
|
||||
rockchip_drm_send_error_event(private, type);
|
||||
}
|
||||
|
||||
DRM_DEV_ERROR(vop2->dev, "post_buf_err event count: %lld\n", event->count);
|
||||
|
||||
event->begin = 0;
|
||||
event->count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void vop2_initial(struct drm_crtc *crtc)
|
||||
{
|
||||
struct vop2_video_port *vp = to_vop2_video_port(crtc);
|
||||
@@ -4290,6 +4400,8 @@ static void vop2_initial(struct drm_crtc *crtc)
|
||||
return;
|
||||
}
|
||||
|
||||
vop2->aclk_current_freq = clk_get_rate(vop2->aclk);
|
||||
|
||||
if (vop2_soc_is_rk3566())
|
||||
VOP_CTRL_SET(vop2, otp_en, 1);
|
||||
|
||||
@@ -4603,6 +4715,14 @@ static void vop2_disable(struct drm_crtc *crtc)
|
||||
vop2_set_aclk_rate(crtc, ROCKCHIP_VOP_ACLK_RESET_MODE, NULL);
|
||||
rockchip_drm_dma_detach_device(vop2->drm_dev, vop2->dev);
|
||||
vop2->is_iommu_enabled = false;
|
||||
vop2->iommu_fault_in_progress = false;
|
||||
/*
|
||||
* Reset fault handler rate limit state, so that we can
|
||||
* immediately report the error event again if an error occurs
|
||||
* shortly after the recovery(Disable then enable) process done.
|
||||
*/
|
||||
rockchip_drm_reset_iommu_fault_handler_rate_limit();
|
||||
vop2_reset_post_buf_empty_handler_rate_limit(vop2);
|
||||
}
|
||||
if (vop2->version == VOP_VERSION_RK3588 || vop2->version == VOP_VERSION_RK3576)
|
||||
vop2_power_off_all_pd(vop2);
|
||||
@@ -7219,12 +7339,22 @@ static int vop2_crtc_debugfs_dump(struct drm_crtc *crtc, struct seq_file *s)
|
||||
struct rockchip_crtc_state *state = to_rockchip_crtc_state(crtc->state);
|
||||
bool interlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
|
||||
struct drm_plane *plane;
|
||||
unsigned long aclk_rate;
|
||||
|
||||
DEBUG_PRINT("Video Port%d: %s\n", vp->id, crtc_state->active ? "ACTIVE" : "DISABLED");
|
||||
|
||||
if (!crtc_state->active)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* clk_get_rate can't run in interrupt context,
|
||||
* for example, called from iommu fault handler
|
||||
*/
|
||||
if (!s)
|
||||
aclk_rate = vop2->aclk_current_freq;
|
||||
else
|
||||
aclk_rate = clk_get_rate(vop2->aclk);
|
||||
|
||||
vop2_dump_connector_on_crtc(crtc, s);
|
||||
DEBUG_PRINT("\tbus_format[%x]: %s\n", state->bus_format,
|
||||
drm_get_bus_format_name(state->bus_format));
|
||||
@@ -7238,7 +7368,7 @@ static int vop2_crtc_debugfs_dump(struct drm_crtc *crtc, struct seq_file *s)
|
||||
mode->hdisplay, mode->vdisplay, interlaced ? "i" : "p",
|
||||
drm_mode_vrefresh(mode));
|
||||
DEBUG_PRINT("\tdclk[%d kHz] real_dclk[%d kHz] aclk[%ld kHz] type[%x] flag[%x]\n",
|
||||
mode->clock, mode->crtc_clock, clk_get_rate(vop2->aclk) / 1000,
|
||||
mode->clock, mode->crtc_clock, aclk_rate / 1000,
|
||||
mode->type, mode->flags);
|
||||
DEBUG_PRINT("\tH: %d %d %d %d\n", mode->hdisplay, mode->hsync_start,
|
||||
mode->hsync_end, mode->htotal);
|
||||
@@ -7946,6 +8076,21 @@ static int vop2_crtc_get_crc(struct drm_crtc *crtc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vop2_iommu_fault_handler(struct drm_crtc *crtc, struct iommu_domain *iommu)
|
||||
{
|
||||
struct vop2_video_port *vp = to_vop2_video_port(crtc);
|
||||
struct vop2 *vop2 = vp->vop2;
|
||||
struct drm_device *drm_dev = vop2->drm_dev;
|
||||
struct rockchip_drm_private *private = drm_dev->dev_private;
|
||||
|
||||
if (!vop2->report_iommu_fault)
|
||||
return;
|
||||
|
||||
vop2->iommu_fault_in_progress = true;
|
||||
|
||||
rockchip_drm_send_error_event(private, ROCKCHIP_DRM_ERROR_EVENT_IOMMU_FAULT);
|
||||
}
|
||||
|
||||
static const struct rockchip_crtc_funcs private_crtc_funcs = {
|
||||
.loader_protect = vop2_crtc_loader_protect,
|
||||
.cancel_pending_vblank = vop2_crtc_cancel_pending_vblank,
|
||||
@@ -7967,6 +8112,7 @@ static const struct rockchip_crtc_funcs private_crtc_funcs = {
|
||||
.crtc_set_color_bar = vop2_crtc_set_color_bar,
|
||||
.set_aclk = vop2_set_aclk_rate,
|
||||
.get_crc = vop2_crtc_get_crc,
|
||||
.iommu_fault_handler = vop2_iommu_fault_handler,
|
||||
};
|
||||
|
||||
static bool vop2_crtc_mode_fixup(struct drm_crtc *crtc,
|
||||
@@ -11259,6 +11405,8 @@ static void vop2_crtc_atomic_begin(struct drm_crtc *crtc, struct drm_atomic_stat
|
||||
}
|
||||
vp->hdr10_at_splice_mode = hdr10_at_splice_mode;
|
||||
|
||||
vp->has_scale_down_layer = false;
|
||||
|
||||
rockchip_drm_dbg(vop2->dev, VOP_DEBUG_OVERLAY, "vp%d: %d windows, active layers %d",
|
||||
vp->id, hweight32(vp->win_mask), nr_layers);
|
||||
if (nr_layers) {
|
||||
@@ -12553,10 +12701,7 @@ static irqreturn_t vop2_isr(int irq, void *data)
|
||||
#define ERROR_HANDLER(x) \
|
||||
do { \
|
||||
if (active_irqs & x##_INTR) {\
|
||||
if (x##_INTR == POST_BUF_EMPTY_INTR) \
|
||||
DRM_DEV_ERROR_RATELIMITED(vop2->dev, #x " irq err at vp%d\n", vp->id); \
|
||||
else \
|
||||
DRM_DEV_ERROR_RATELIMITED(vop2->dev, #x " irq err\n"); \
|
||||
DRM_DEV_ERROR_RATELIMITED(vop2->dev, #x " irq err\n"); \
|
||||
active_irqs &= ~x##_INTR; \
|
||||
ret = IRQ_HANDLED; \
|
||||
} \
|
||||
@@ -12629,7 +12774,12 @@ static irqreturn_t vop2_isr(int irq, void *data)
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
|
||||
ERROR_HANDLER(POST_BUF_EMPTY);
|
||||
if (active_irqs & POST_BUF_EMPTY_INTR) {
|
||||
vop2_handle_post_buf_empty(crtc);
|
||||
DRM_DEV_ERROR_RATELIMITED(vop2->dev, "POST_BUF_EMPTY irq err at vp%d\n", vp->id);
|
||||
active_irqs &= ~POST_BUF_EMPTY_INTR;
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/* Unhandled irqs are spurious. */
|
||||
if (active_irqs)
|
||||
@@ -14332,6 +14482,8 @@ static int vop2_bind(struct device *dev, struct device *master, void *data)
|
||||
vop2->disable_afbc_win = of_property_read_bool(dev->of_node, "disable-afbc-win");
|
||||
vop2->disable_win_move = of_property_read_bool(dev->of_node, "disable-win-move");
|
||||
vop2->skip_ref_fb = of_property_read_bool(dev->of_node, "skip-ref-fb");
|
||||
vop2->report_iommu_fault = of_property_read_bool(dev->of_node, "rockchip,report-iommu-fault");
|
||||
vop2->report_post_buf_empty = of_property_read_bool(dev->of_node, "rockchip,report-post-buf-empty");
|
||||
if (!is_vop3(vop2) ||
|
||||
vop2->version == VOP_VERSION_RK3528 || vop2->version == VOP_VERSION_RK3562)
|
||||
vop2->merge_irq = true;
|
||||
|
||||
@@ -11,6 +11,12 @@ config VIDEO_CAM_SLEEP_WAKEUP
|
||||
help
|
||||
Support for sensor sleep and wake up.
|
||||
|
||||
config VIDEO_ROCKCHIP_THUNDER_BOOT_SETUP
|
||||
bool "Enable camera Thunderboot setup function"
|
||||
depends on ROCKCHIP_THUNDER_BOOT
|
||||
help
|
||||
Say y if you need camera Thunderboot setup functions.
|
||||
|
||||
comment "IR I2C driver auto-selected by 'Autoselect ancillary drivers'"
|
||||
depends on MEDIA_SUBDRV_AUTOSELECT && I2C && RC_CORE
|
||||
|
||||
|
||||
@@ -206,7 +206,7 @@ obj-$(CONFIG_VIDEO_RDACM21) += rdacm21.o
|
||||
obj-$(CONFIG_VIDEO_RJ54N1) += rj54n1cb0c.o
|
||||
obj-$(CONFIG_VIDEO_RK628) += rk628/
|
||||
obj-$(CONFIG_VIDEO_RK_IRCUT) += rk_ircut.o
|
||||
obj-$(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) += cam-tb-setup.o
|
||||
obj-$(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_SETUP) += cam-tb-setup.o
|
||||
obj-$(CONFIG_VIDEO_S5C73M3) += s5c73m3/
|
||||
obj-$(CONFIG_VIDEO_S5K3L6XX) += s5k3l6xx.o
|
||||
obj-$(CONFIG_VIDEO_S5K3L8XX) += s5k3l8xx.o
|
||||
|
||||
@@ -6,116 +6,37 @@
|
||||
#include <linux/kernel.h>
|
||||
#include "cam-tb-setup.h"
|
||||
|
||||
static u32 rk_cam_w;
|
||||
static u32 rk_cam_h;
|
||||
static u32 rk_cam_hdr;
|
||||
static u32 rk_cam_fps;
|
||||
static u32 rk_cam_skip_frame_interval;
|
||||
|
||||
static int __init rk_cam_w_setup(char *str)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long val = 0;
|
||||
#define DEFINE_CAM_TB_PARAM(para) \
|
||||
static u32 para; \
|
||||
static int __init para##_setup(char *str) \
|
||||
{ \
|
||||
int ret = 0; \
|
||||
unsigned long val = 0; \
|
||||
ret = kstrtoul(str, 0, &val); \
|
||||
if (!ret) \
|
||||
para = (u32)val; \
|
||||
else \
|
||||
pr_err("get "#para" fail\n"); \
|
||||
return 0; \
|
||||
} \
|
||||
u32 get_##para(void) \
|
||||
{ \
|
||||
return para; \
|
||||
} \
|
||||
EXPORT_SYMBOL(get_##para); \
|
||||
__setup(#para"=", para##_setup)
|
||||
|
||||
ret = kstrtoul(str, 0, &val);
|
||||
if (!ret)
|
||||
rk_cam_w = (u32)val;
|
||||
else
|
||||
pr_err("get rk_cam_w fail\n");
|
||||
DEFINE_CAM_TB_PARAM(rk_cam_w);
|
||||
DEFINE_CAM_TB_PARAM(rk_cam_h);
|
||||
DEFINE_CAM_TB_PARAM(rk_cam_hdr);
|
||||
DEFINE_CAM_TB_PARAM(rk_cam_fps);
|
||||
DEFINE_CAM_TB_PARAM(rk_cam1_max_fps);
|
||||
DEFINE_CAM_TB_PARAM(rk_cam2_w);
|
||||
DEFINE_CAM_TB_PARAM(rk_cam2_h);
|
||||
DEFINE_CAM_TB_PARAM(rk_cam2_hdr);
|
||||
DEFINE_CAM_TB_PARAM(rk_cam2_fps);
|
||||
DEFINE_CAM_TB_PARAM(rk_cam2_max_fps);
|
||||
DEFINE_CAM_TB_PARAM(rk_cam_skip);
|
||||
DEFINE_CAM_TB_PARAM(rockit_en_mcu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 get_rk_cam_w(void)
|
||||
{
|
||||
return rk_cam_w;
|
||||
}
|
||||
EXPORT_SYMBOL(get_rk_cam_w);
|
||||
|
||||
static int __init rk_cam_h_setup(char *str)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long val = 0;
|
||||
|
||||
ret = kstrtoul(str, 0, &val);
|
||||
if (!ret)
|
||||
rk_cam_h = (u32)val;
|
||||
else
|
||||
pr_err("get rk_cam_h fail\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 get_rk_cam_h(void)
|
||||
{
|
||||
return rk_cam_h;
|
||||
}
|
||||
EXPORT_SYMBOL(get_rk_cam_h);
|
||||
|
||||
static int __init rk_cam_hdr_setup(char *str)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long val = 0;
|
||||
|
||||
ret = kstrtoul(str, 0, &val);
|
||||
if (!ret)
|
||||
rk_cam_hdr = (u32)val;
|
||||
else
|
||||
pr_err("get rk_cam_hdr fail\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 get_rk_cam_hdr(void)
|
||||
{
|
||||
return rk_cam_hdr;
|
||||
}
|
||||
EXPORT_SYMBOL(get_rk_cam_hdr);
|
||||
|
||||
static int __init __maybe_unused rk_cam_fps_setup(char *str)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long val = 0;
|
||||
|
||||
ret = kstrtoul(str, 0, &val);
|
||||
if (!ret)
|
||||
rk_cam_fps = (u32)val;
|
||||
else
|
||||
pr_err("get rk_cam_fps fail\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 get_rk_cam_fps(void)
|
||||
{
|
||||
return rk_cam_fps;
|
||||
}
|
||||
EXPORT_SYMBOL(get_rk_cam_fps);
|
||||
|
||||
static int __init __maybe_unused rk_cam_skip_frame_interval_setup(char *str)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long val = 0;
|
||||
|
||||
ret = kstrtoul(str, 0, &val);
|
||||
if (!ret) {
|
||||
rk_cam_skip_frame_interval = (u32)val;
|
||||
} else {
|
||||
rk_cam_skip_frame_interval = 0;
|
||||
pr_err("get rk_cam_skip_frame_interval fail\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 get_rk_cam_skip_frame_interval(void)
|
||||
{
|
||||
return rk_cam_skip_frame_interval;
|
||||
}
|
||||
EXPORT_SYMBOL(get_rk_cam_skip_frame_interval);
|
||||
|
||||
__setup("rk_cam_w=", rk_cam_w_setup);
|
||||
__setup("rk_cam_h=", rk_cam_h_setup);
|
||||
__setup("rk_cam_hdr=", rk_cam_hdr_setup);
|
||||
__setup("rk_cam_fps=", rk_cam_fps_setup);
|
||||
__setup("rk_cam_skip_frame_interval=", rk_cam_skip_frame_interval_setup);
|
||||
|
||||
@@ -3,36 +3,28 @@
|
||||
|
||||
#ifndef CAM_TB_SETUP_H
|
||||
#define CAM_TB_SETUP_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#ifdef CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP
|
||||
u32 get_rk_cam_w(void);
|
||||
u32 get_rk_cam_h(void);
|
||||
u32 get_rk_cam_hdr(void);
|
||||
u32 get_rk_cam_fps(void);
|
||||
u32 get_rk_cam_skip_frame_interval(void);
|
||||
#ifdef CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_SETUP
|
||||
#define EXTERN_CAM_TB_PARAM(para) u32 get_##para(void)
|
||||
#else
|
||||
static inline u32 get_rk_cam_w(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline u32 get_rk_cam_h(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline u32 get_rk_cam_hdr(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline u32 get_rk_cam_fps(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline u32 get_rk_cam_skip_frame_interval(void)
|
||||
{
|
||||
return 0;
|
||||
#define EXTERN_CAM_TB_PARAM(para) \
|
||||
static inline u32 get_##para(void) \
|
||||
{ \
|
||||
return 0; \
|
||||
}
|
||||
#endif
|
||||
|
||||
EXTERN_CAM_TB_PARAM(rk_cam_w);
|
||||
EXTERN_CAM_TB_PARAM(rk_cam_h);
|
||||
EXTERN_CAM_TB_PARAM(rk_cam_hdr);
|
||||
EXTERN_CAM_TB_PARAM(rk_cam_fps);
|
||||
EXTERN_CAM_TB_PARAM(rk_cam1_max_fps);
|
||||
EXTERN_CAM_TB_PARAM(rk_cam2_w);
|
||||
EXTERN_CAM_TB_PARAM(rk_cam2_h);
|
||||
EXTERN_CAM_TB_PARAM(rk_cam2_hdr);
|
||||
EXTERN_CAM_TB_PARAM(rk_cam2_fps);
|
||||
EXTERN_CAM_TB_PARAM(rk_cam2_max_fps);
|
||||
EXTERN_CAM_TB_PARAM(rk_cam_skip);
|
||||
EXTERN_CAM_TB_PARAM(rockit_en_mcu);
|
||||
#endif
|
||||
|
||||
@@ -8288,7 +8288,7 @@ void rkcif_stream_init(struct rkcif_device *dev, u32 id)
|
||||
init_completion(&stream->stop_complete);
|
||||
init_completion(&stream->start_complete);
|
||||
stream->is_wait_stop_complete = false;
|
||||
stream->thunderboot_skip_interval = get_rk_cam_skip_frame_interval();
|
||||
stream->thunderboot_skip_interval = get_rk_cam_skip();
|
||||
atomic_set(&stream->sub_stream_buf_cnt, 0);
|
||||
spin_lock_init(&stream->fence_lock);
|
||||
rkcif_fence_context_init(&stream->fence_ctx);
|
||||
|
||||
@@ -315,7 +315,10 @@ static int mmc_caps_set(void *data, u64 val)
|
||||
MMC_CAP_SD_HIGHSPEED |
|
||||
MMC_CAP_MMC_HIGHSPEED |
|
||||
MMC_CAP_UHS |
|
||||
MMC_CAP_DDR;
|
||||
MMC_CAP_DDR |
|
||||
MMC_CAP_4_BIT_DATA |
|
||||
MMC_CAP_8_BIT_DATA |
|
||||
MMC_CAP_CMD23;
|
||||
|
||||
if (diff & ~allowed)
|
||||
return -EINVAL;
|
||||
@@ -327,7 +330,10 @@ static int mmc_caps_set(void *data, u64 val)
|
||||
|
||||
static int mmc_caps2_set(void *data, u64 val)
|
||||
{
|
||||
u32 allowed = MMC_CAP2_HSX00_1_8V | MMC_CAP2_HSX00_1_2V;
|
||||
u32 allowed = MMC_CAP2_HSX00_1_8V |
|
||||
MMC_CAP2_HSX00_1_2V |
|
||||
MMC_CAP2_CQE |
|
||||
MMC_CAP2_CQE_DCMD;
|
||||
u32 *caps = data;
|
||||
u32 diff = *caps ^ val;
|
||||
|
||||
|
||||
@@ -111,6 +111,12 @@ enum rockchip_cabc_mode {
|
||||
ROCKCHIP_DRM_CABC_MODE_USERSPACE,
|
||||
};
|
||||
|
||||
enum rockchip_drm_error_event_type {
|
||||
ROCKCHIP_DRM_ERROR_EVENT_IOMMU_FAULT = (1 << 0),
|
||||
ROCKCHIP_DRM_ERROR_EVENT_POST_BUF_EMPTY = (1 << 1),
|
||||
ROCKCHIP_DRM_ERROR_EVENT_REQUEST_RESET = (1 << 2),
|
||||
};
|
||||
|
||||
#define DRM_ROCKCHIP_GEM_CREATE 0x00
|
||||
#define DRM_ROCKCHIP_GEM_MAP_OFFSET 0x01
|
||||
#define DRM_ROCKCHIP_GEM_CPU_ACQUIRE 0x02
|
||||
|
||||
Reference in New Issue
Block a user