Merge commit '34c17d0724d5e26a4efda23502cfbbb612bcb994'

* commit '34c17d0724d5e26a4efda23502cfbbb612bcb994':
  drm/rockchip: vop2: Support invalid phy id for vop2_plane_id_to_string
  media: rockchip: vpss: online support 8k
  arm64: dts: rockchip: rk3576: enable VOP aclk auto cs
  drm/rockchip: vop2: add support dynamic adjust vop aclk auto cs div
  drm/rockchip: analogix_dp: add support for color format yuv444/yuv422
  video: rockchip: rga3: modify workaround for RK3576 issue
  pinctrl: rockchip: Fix iterator 'j' not incremented in rk_iomux_set()
  input: touchscreen: ft5726: Fix abnormal sleep power
  drm/rockchip: vop: Fix mixing irqsave and irq in vop_crtc_atomic_flush()
  media: i2c: rk628: fix YUV format color range detect

Change-Id: I70a19db1e092a5397c73710bd5fb8ccaa47ef02e
This commit is contained in:
Tao Huang
2024-06-21 19:29:12 +08:00
28 changed files with 1246 additions and 333 deletions

View File

@@ -2777,6 +2777,8 @@
rockchip,aclk-reset-mode-rates = <594000000>;
rockchip,aclk-advanced-mode-rates = <702000000>;
operating-points-v2 = <&vop_opp_table>;
rockchip,csu = <&csu CSU_VOP_ACLK>;
rockchip,csu-names = "aclk";
iommus = <&vop_mmu>;
power-domains = <&power RK3576_PD_VOP>;
rockchip,grf = <&sys_grf>;

View File

@@ -54,23 +54,52 @@ struct bridge_init {
struct device_node *node;
};
static const struct analogix_dp_output_format possible_output_fmts[] = {
{ MEDIA_BUS_FMT_RGB101010_1X30, DRM_COLOR_FORMAT_RGB444, 10 },
{ MEDIA_BUS_FMT_RGB888_1X24, DRM_COLOR_FORMAT_RGB444, 8 },
{ MEDIA_BUS_FMT_RGB666_1X24_CPADHI, DRM_COLOR_FORMAT_RGB444, 6 },
{ MEDIA_BUS_FMT_YUV10_1X30, DRM_COLOR_FORMAT_YCBCR444, 10 },
{ MEDIA_BUS_FMT_YUV8_1X24, DRM_COLOR_FORMAT_YCBCR444, 8},
{ MEDIA_BUS_FMT_YUYV10_1X20, DRM_COLOR_FORMAT_YCBCR422, 10 },
{ MEDIA_BUS_FMT_YUYV8_1X16, DRM_COLOR_FORMAT_YCBCR422, 8 },
};
static u8 analogix_dp_get_output_bpp(const struct analogix_dp_output_format *fmt)
{
switch (fmt->color_format) {
case DRM_COLOR_FORMAT_YCBCR422:
return fmt->bpc * 2;
case DRM_COLOR_FORMAT_RGB444:
case DRM_COLOR_FORMAT_YCBCR444:
default:
return fmt->bpc * 3;
}
}
const struct analogix_dp_output_format *analogix_dp_get_output_format(u32 bus_format)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE(possible_output_fmts); i++)
if (possible_output_fmts[i].bus_format == bus_format)
return &possible_output_fmts[i];
return &possible_output_fmts[1];
}
EXPORT_SYMBOL_GPL(analogix_dp_get_output_format);
static void analogix_dp_bridge_mode_set(struct drm_bridge *bridge,
const struct drm_display_mode *adj_mode);
static bool analogix_dp_bandwidth_ok(struct analogix_dp_device *dp,
const struct drm_display_mode *mode,
const struct drm_display_mode *mode, u32 bpp,
unsigned int rate, unsigned int lanes)
{
const struct drm_display_info *info;
u32 max_bw, req_bw, bpp = 24;
u32 max_bw, req_bw;
if (dp->plat_data->skip_connector)
return true;
info = &dp->connector.display_info;
if (info->bpc)
bpp = 3 * info->bpc;
req_bw = mode->crtc_clock * bpp / 8;
max_bw = lanes * rate;
if (req_bw > max_bw)
@@ -691,8 +720,9 @@ static u8 analogix_dp_select_link_rate_from_table(struct analogix_dp_device *dp)
for (i = 0; i < dp->nr_link_rate_table; i++) {
bw_code = drm_dp_link_rate_to_bw_code(dp->link_rate_table[i]);
if (!analogix_dp_bandwidth_ok(dp, &dp->video_info.mode, dp->link_rate_table[i],
dp->link_train.lane_count))
if (!analogix_dp_bandwidth_ok(dp, &dp->video_info.mode,
analogix_dp_get_output_bpp(dp->output_fmt),
dp->link_rate_table[i], dp->link_train.lane_count))
continue;
if (dp->link_rate_table[i] <= max_link_rate &&
@@ -832,7 +862,7 @@ static int analogix_dp_full_link_train(struct analogix_dp_device *dp,
return -EINVAL;
}
if (!analogix_dp_bandwidth_ok(dp, &video->mode,
if (!analogix_dp_bandwidth_ok(dp, &video->mode, analogix_dp_get_output_bpp(dp->output_fmt),
drm_dp_bw_code_to_link_rate(dp->link_train.link_rate),
dp->link_train.lane_count)) {
dev_err(dp->dev, "bandwidth overflow\n");
@@ -1746,6 +1776,12 @@ analogix_dp_bridge_atomic_pre_enable(struct drm_bridge *bridge,
struct analogix_dp_device *dp = bridge->driver_private;
struct drm_crtc *crtc;
struct drm_crtc_state *old_crtc_state, *new_crtc_state;
struct drm_bridge_state *new_bridge_state;
new_bridge_state = drm_atomic_get_new_bridge_state(old_state, bridge);
if (WARN_ON(!new_bridge_state))
return;
dp->output_fmt = analogix_dp_get_output_format(new_bridge_state->output_bus_cfg.format);
crtc = analogix_dp_get_new_crtc(dp, old_state);
if (!crtc)
@@ -1967,7 +2003,6 @@ static void analogix_dp_bridge_mode_set(struct drm_bridge *bridge,
const struct drm_display_mode *adj_mode)
{
struct analogix_dp_device *dp = bridge->driver_private;
struct drm_display_info *display_info = &dp->connector.display_info;
struct video_info *video = &dp->video_info;
struct drm_display_mode *mode = &video->mode;
struct device_node *dp_node = dp->dev->of_node;
@@ -1998,7 +2033,7 @@ static void analogix_dp_bridge_mode_set(struct drm_bridge *bridge,
video->dynamic_range = VESA;
/* Input vide bpc and color_formats */
switch (display_info->bpc) {
switch (dp->output_fmt->bpc) {
case 12:
video->color_depth = COLOR_12;
break;
@@ -2015,10 +2050,10 @@ static void analogix_dp_bridge_mode_set(struct drm_bridge *bridge,
video->color_depth = COLOR_8;
break;
}
if (display_info->color_formats & DRM_COLOR_FORMAT_YCBCR444) {
if (dp->output_fmt->color_format == DRM_COLOR_FORMAT_YCBCR444) {
video->color_space = COLOR_YCBCR444;
video->ycbcr_coeff = COLOR_YCBCR709;
} else if (display_info->color_formats & DRM_COLOR_FORMAT_YCBCR422) {
} else if (dp->output_fmt->color_format == DRM_COLOR_FORMAT_YCBCR422) {
video->color_space = COLOR_YCBCR422;
video->ycbcr_coeff = COLOR_YCBCR709;
} else {
@@ -2057,18 +2092,26 @@ analogix_dp_bridge_mode_valid(struct drm_bridge *bridge,
struct analogix_dp_device *dp = bridge->driver_private;
struct drm_display_mode m;
u32 max_link_rate, max_lane_count;
u32 min_bpp;
drm_mode_copy(&m, mode);
if (dp->plat_data->split_mode || dp->plat_data->dual_connector_split)
dp->plat_data->convert_to_origin_mode(&m);
if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422)
min_bpp = 16;
else if (info->color_formats & DRM_COLOR_FORMAT_RGB444)
min_bpp = 18;
else
min_bpp = 24;
max_link_rate = min_t(u32, dp->video_info.max_link_rate,
dp->link_train.link_rate);
max_lane_count = min_t(u32, dp->video_info.max_lane_count,
dp->link_train.lane_count);
if (analogix_dp_link_config_validate(max_link_rate, max_lane_count) &&
!analogix_dp_bandwidth_ok(dp, &m,
!analogix_dp_bandwidth_ok(dp, &m, min_bpp,
drm_dp_bw_code_to_link_rate(max_link_rate),
max_lane_count))
return MODE_BAD;
@@ -2076,10 +2119,67 @@ analogix_dp_bridge_mode_valid(struct drm_bridge *bridge,
return MODE_OK;
}
static u32 *analogix_dp_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge,
struct drm_bridge_state *bridge_state,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state,
unsigned int *num_output_fmts)
{
struct analogix_dp_device *dp = bridge->driver_private;
struct drm_display_info *di = &dp->connector.display_info;
u32 *output_fmts;
unsigned int i, j = 0;
if (dp->plat_data->panel) {
*num_output_fmts = 1;
output_fmts = kzalloc(sizeof(*output_fmts), GFP_KERNEL);
if (!output_fmts)
return NULL;
if (di->num_bus_formats && di->bus_formats)
output_fmts[0] = di->bus_formats[0];
else
output_fmts[0] = MEDIA_BUS_FMT_RGB888_1X24;
return output_fmts;
}
*num_output_fmts = 0;
output_fmts = kcalloc(ARRAY_SIZE(possible_output_fmts), sizeof(*output_fmts), GFP_KERNEL);
if (!output_fmts)
return NULL;
for (i = 0; i < ARRAY_SIZE(possible_output_fmts); i++) {
const struct analogix_dp_output_format *fmt = &possible_output_fmts[i];
if (fmt->bpc > conn_state->max_bpc || fmt->bpc > dp->plat_data->max_bpc)
continue;
if (!(di->color_formats & fmt->color_format))
continue;
if (!analogix_dp_bandwidth_ok(dp, &crtc_state->mode,
analogix_dp_get_output_bpp(fmt),
drm_dp_bw_code_to_link_rate(dp->link_train.link_rate),
dp->link_train.lane_count))
continue;
output_fmts[j++] = fmt->bus_format;
}
*num_output_fmts = j;
return output_fmts;
}
static const struct drm_bridge_funcs analogix_dp_bridge_funcs = {
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
.atomic_reset = drm_atomic_helper_bridge_reset,
.atomic_get_input_bus_fmts = drm_atomic_helper_bridge_propagate_bus_fmt,
.atomic_get_output_bus_fmts = analogix_dp_bridge_atomic_get_output_bus_fmts,
.atomic_pre_enable = analogix_dp_bridge_atomic_pre_enable,
.atomic_enable = analogix_dp_bridge_atomic_enable,
.atomic_disable = analogix_dp_bridge_atomic_disable,

View File

@@ -206,6 +206,8 @@ struct analogix_dp_device {
struct analogix_dp_compliance compliance;
u32 split_area;
const struct analogix_dp_output_format *output_fmt;
};
/* analogix_dp_reg.c */

View File

@@ -70,6 +70,8 @@ struct rockchip_dp_chip_data {
bool ssc;
bool audio;
bool split_mode;
bool format_yuv;
u8 max_bpc;
};
struct rockchip_dp_device {
@@ -230,15 +232,16 @@ static int rockchip_dp_powerdown(struct analogix_dp_plat_data *plat_data)
static int rockchip_dp_get_modes(struct analogix_dp_plat_data *plat_data,
struct drm_connector *connector)
{
struct rockchip_dp_device *dp = pdata_encoder_to_dp(plat_data);
struct drm_display_info *di = &connector->display_info;
/* VOP couldn't output YUV video format for eDP rightly */
u32 mask = DRM_COLOR_FORMAT_YCBCR444 | DRM_COLOR_FORMAT_YCBCR422;
if ((di->color_formats & mask)) {
DRM_DEBUG_KMS("Swapping display color format from YUV to RGB\n");
di->color_formats &= ~mask;
di->color_formats |= DRM_COLOR_FORMAT_RGB444;
di->bpc = 8;
if (!dp->data->format_yuv) {
if ((di->color_formats & mask)) {
DRM_DEBUG_KMS("Swapping display color format from YUV to RGB\n");
di->color_formats &= ~mask;
di->color_formats |= DRM_COLOR_FORMAT_RGB444;
}
}
return 0;
@@ -463,12 +466,19 @@ rockchip_dp_drm_encoder_atomic_check(struct drm_encoder *encoder,
struct rockchip_dp_device *dp = encoder_to_dp(encoder);
struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
struct drm_display_info *di = &conn_state->connector->display_info;
struct drm_bridge_state *new_bridge_state;
struct drm_bridge *bridge;
const struct analogix_dp_output_format *output_fmt;
int refresh_rate;
if (di->num_bus_formats)
s->bus_format = di->bus_formats[0];
else
s->bus_format = MEDIA_BUS_FMT_RGB888_1X24;
bridge = drm_bridge_chain_get_first_bridge(encoder);
new_bridge_state = drm_atomic_get_new_bridge_state(conn_state->state, bridge);
if (!new_bridge_state)
return 0;
dev_dbg(dp->dev, "input format 0x%04x, output format 0x%04x\n",
new_bridge_state->input_bus_cfg.format,
new_bridge_state->output_bus_cfg.format);
/*
* The hardware IC designed that VOP must output the RGB10 video
@@ -477,8 +487,17 @@ rockchip_dp_drm_encoder_atomic_check(struct drm_encoder *encoder,
* controller, that's why we need to hardcode the VOP output mode
* to RGA10 here.
*/
s->output_mode = ROCKCHIP_OUT_MODE_AAAA;
output_fmt = analogix_dp_get_output_format(new_bridge_state->output_bus_cfg.format);
switch (output_fmt->color_format) {
case DRM_COLOR_FORMAT_YCBCR422:
s->output_mode = ROCKCHIP_OUT_MODE_YUV422;
break;
case DRM_COLOR_FORMAT_RGB444:
case DRM_COLOR_FORMAT_YCBCR444:
default:
s->output_mode = ROCKCHIP_OUT_MODE_AAAA;
break;
}
s->output_type = DRM_MODE_CONNECTOR_eDP;
if (dp->plat_data.split_mode) {
s->output_flags |= ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE;
@@ -495,12 +514,16 @@ rockchip_dp_drm_encoder_atomic_check(struct drm_encoder *encoder,
s->output_if |= dp->id ? VOP_OUTPUT_IF_eDP1 : VOP_OUTPUT_IF_eDP0;
}
s->output_bpc = di->bpc;
s->bus_format = output_fmt->bus_format;
s->output_bpc = output_fmt->bpc;
s->bus_flags = di->bus_flags;
s->tv_state = &conn_state->tv;
s->eotf = HDMI_EOTF_TRADITIONAL_GAMMA_SDR;
s->color_encoding = DRM_COLOR_YCBCR_BT709;
s->color_range = DRM_COLOR_YCBCR_FULL_RANGE;
if (output_fmt->color_format == DRM_COLOR_FORMAT_RGB444)
s->color_range = DRM_COLOR_YCBCR_FULL_RANGE;
else
s->color_range = DRM_COLOR_YCBCR_LIMITED_RANGE;
/**
* It's priority to user rate range define in dtsi.
*/
@@ -707,6 +730,7 @@ static int rockchip_dp_probe(struct platform_device *pdev)
dp->adp = ERR_PTR(-ENODEV);
dp->data = &dp_data[id];
dp->plat_data.ssc = dp->data->ssc;
dp->plat_data.max_bpc = dp->data->max_bpc ? dp->data->max_bpc : 8;
dp->plat_data.panel = panel;
dp->plat_data.dev_type = dp->data->chip_type;
dp->plat_data.power_on_start = rockchip_dp_poweron_start;
@@ -863,6 +887,8 @@ static const struct rockchip_dp_chip_data rk3576_edp[] = {
.ssc = true,
.audio = true,
.split_mode = true,
.format_yuv = true,
.max_bpc = 10,
},
{ /* sentinel */ }
};
@@ -876,6 +902,8 @@ static const struct rockchip_dp_chip_data rk3588_edp[] = {
.ssc = true,
.audio = true,
.split_mode = true,
.format_yuv = true,
.max_bpc = 10,
},
{
.chip_type = RK3588_EDP,
@@ -885,6 +913,8 @@ static const struct rockchip_dp_chip_data rk3588_edp[] = {
.ssc = true,
.audio = true,
.split_mode = true,
.format_yuv = true,
.max_bpc = 10,
},
{ /* sentinel */ }
};

View File

@@ -506,7 +506,7 @@ struct rockchip_crtc_funcs {
void (*crtc_output_post_enable)(struct drm_crtc *crtc, int intf);
void (*crtc_output_pre_disable)(struct drm_crtc *crtc, int intf);
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);
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);
};

View File

@@ -202,14 +202,14 @@ static int rockchip_drm_aclk_adjust(struct drm_device *dev,
if (vop_bw_info->plane_num_4k || crtc_num > 1 ||
crtc->state->adjusted_mode.crtc_hdisplay > 2560 ||
crtc->state->adjusted_mode.crtc_vdisplay > 2560) {
funcs->set_aclk(crtc, ROCKCHIP_VOP_ACLK_ADVANCED_MODE);
funcs->set_aclk(crtc, ROCKCHIP_VOP_ACLK_ADVANCED_MODE, vop_bw_info);
priv->aclk_adjust_frame_num = 2;
} else {
if (priv->aclk_adjust_frame_num >= 1) {
funcs->set_aclk(crtc, ROCKCHIP_VOP_ACLK_ADVANCED_MODE);
funcs->set_aclk(crtc, ROCKCHIP_VOP_ACLK_ADVANCED_MODE, vop_bw_info);
priv->aclk_adjust_frame_num--;
} else {
funcs->set_aclk(crtc, ROCKCHIP_VOP_ACLK_NORMAL_MODE);
funcs->set_aclk(crtc, ROCKCHIP_VOP_ACLK_NORMAL_MODE, vop_bw_info);
}
}
}

View File

@@ -4351,7 +4351,7 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc,
*/
vop_wait_for_irq_handler(vop);
spin_lock_irq(&crtc->dev->event_lock);
spin_lock_irqsave(&crtc->dev->event_lock, flags);
if (crtc->state->event) {
WARN_ON(drm_crtc_vblank_get(crtc) != 0);
WARN_ON(vop->event);
@@ -4359,7 +4359,7 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc,
vop->event = crtc->state->event;
crtc->state->event = NULL;
}
spin_unlock_irq(&crtc->dev->event_lock);
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
for_each_old_plane_in_state(old_state, plane, old_plane_state, i) {
if (!old_plane_state->fb)

View File

@@ -968,6 +968,8 @@ struct vop2 {
u32 aclk_mode_rate[ROCKCHIP_VOP_ACLK_MAX_MODE];
#endif
/* aclk auto cs div */
u32 csu_div;
/* must put at the end of the struct */
struct vop2_win win[];
};
@@ -1016,7 +1018,6 @@ static const struct drm_bus_format_enum_list drm_bus_format_enum_list[] = {
};
static DRM_ENUM_NAME_FN(drm_get_bus_format_name, drm_bus_format_enum_list)
static int vop2_devfreq_set_aclk(struct drm_crtc *crtc, enum rockchip_drm_vop_aclk_mode aclk_mode);
static inline struct vop2_video_port *to_vop2_video_port(struct drm_crtc *crtc)
{
@@ -1306,6 +1307,99 @@ static struct drm_crtc *vop2_find_crtc_by_plane_mask(struct vop2 *vop2, uint8_t
return NULL;
}
static u32 rk3562_vop2_get_csu_div(struct drm_crtc *crtc)
{
struct vop2_video_port *vp = to_vop2_video_port(crtc);
unsigned long aclk_rate = 0, dclk_rate = 0;
u32 csu_div;
aclk_rate = clk_get_rate(vp->vop2->aclk);
dclk_rate = clk_get_rate(vp->dclk);
if (!dclk_rate)
return 0;
/* aclk > 1/2 * dclk */
csu_div = (aclk_rate - 1) * 2 / dclk_rate;
return csu_div;
}
static u32 rk3576_vop2_get_csu_div(struct drm_crtc *crtc, struct dmcfreq_vop_info *vop_bw_info)
{
struct vop2_video_port *vp = to_vop2_video_port(crtc);
struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
u32 csu_div;
if (vp->vop2->aclk_mode == ROCKCHIP_VOP_ACLK_NORMAL_MODE) {
if (adjusted_mode->crtc_clock < 250000) {
if (vop_bw_info->plane_num == 1)
csu_div = 3;
else if (vop_bw_info->plane_num == 2)
csu_div = 2;
else
csu_div = 1;
} else {
csu_div = 1;
}
} else {
csu_div = 1;
}
return csu_div;
}
static int vop2_set_aclk_rate(struct drm_crtc *crtc,
enum rockchip_drm_vop_aclk_mode aclk_mode,
struct dmcfreq_vop_info *vop_bw_info)
{
struct vop2_video_port *vp = to_vop2_video_port(crtc);
struct vop2 *vop2 = vp->vop2;
struct drm_crtc *first_active_crtc = NULL;
int i = 0, ret = 0;
u32 csu_div = 0;
/* all vp/crtc share one vop aclk, so only need to set once */
for (i = 0; i < vop2->data->nr_vps; i++) {
if (vop2->vps[i].rockchip_crtc.crtc.state &&
vop2->vps[i].rockchip_crtc.crtc.state->active) {
first_active_crtc = &vop2->vps[i].rockchip_crtc.crtc;
break;
}
}
if (first_active_crtc != crtc)
return 0;
vop2->aclk_target_freq = vop2->aclk_mode_rate[aclk_mode];
#ifdef CONFIG_PM_DEVFREQ
if (vop2->devfreq) {
mutex_lock(&vop2->devfreq->lock);
ret = update_devfreq(vop2->devfreq);
mutex_unlock(&vop2->devfreq->lock);
if (ret)
dev_err(vop2->dev, "failed to set rate %lu\n", vop2->aclk_target_freq);
}
#endif
vop2->aclk_mode = aclk_mode;
if (vop2->csu_aclk && vop_bw_info) {
if (vop2->version == VOP_VERSION_RK3562)
csu_div = rk3562_vop2_get_csu_div(crtc);
else
csu_div = rk3576_vop2_get_csu_div(crtc, vop_bw_info);
if (csu_div != vop2->csu_div) {
rockchip_csu_set_div(vop2->csu_aclk, csu_div);
rockchip_drm_dbg(vop2->dev, VOP_DEBUG_CLK,
"Set aclk auto cs div from %d to %d, aclk rate:%ld, aclk mode:%d\n",
vop2->csu_div, csu_div, clk_get_rate(vop2->aclk),
vop2->aclk_mode);
}
vop2->csu_div = csu_div;
}
return 0;
}
static int vop2_clk_reset(struct reset_control *rstc)
{
int ret;
@@ -4453,7 +4547,7 @@ static void vop2_disable(struct drm_crtc *crtc)
VOP_CTRL_SET(vop2, dma_stop, 1);
if (vop2->aclk_mode_rate[ROCKCHIP_VOP_ACLK_RESET_MODE] &&
clk_get_rate(vop2->aclk) > vop2->aclk_mode_rate[ROCKCHIP_VOP_ACLK_RESET_MODE])
vop2_devfreq_set_aclk(crtc, ROCKCHIP_VOP_ACLK_RESET_MODE);
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;
}
@@ -6949,27 +7043,6 @@ static int vop2_crtc_get_inital_acm_info(struct drm_crtc *crtc)
return 0;
}
static void vop2_crtc_csu_set_rate(struct drm_crtc *crtc)
{
struct vop2_video_port *vp = to_vop2_video_port(crtc);
struct vop2 *vop2 = vp->vop2;
unsigned long aclk_rate = 0, dclk_rate = 0;
u32 csu_div = 0;
if (!vop2->csu_aclk)
return;
aclk_rate = clk_get_rate(vop2->aclk);
dclk_rate = clk_get_rate(vp->dclk);
if (!dclk_rate || !aclk_rate)
return;
/* aclk > 1/2 * dclk */
csu_div = (aclk_rate - 1) * 2 / dclk_rate;
rockchip_csu_set_div(vop2->csu_aclk, csu_div);
}
static int vop2_crtc_loader_protect(struct drm_crtc *crtc, bool on, void *data)
{
struct vop2_video_port *vp = to_vop2_video_port(crtc);
@@ -7049,8 +7122,6 @@ static int vop2_crtc_loader_protect(struct drm_crtc *crtc, bool on, void *data)
cubic_lut_mst = cubic_lut->offset + private->cubic_lut_dma_addr;
VOP_MODULE_SET(vop2, vp, cubic_lut_mst, cubic_lut_mst);
}
vop2_crtc_csu_set_rate(crtc);
} else {
vop2_crtc_atomic_disable(crtc, NULL);
}
@@ -7847,7 +7918,7 @@ static const struct rockchip_crtc_funcs private_crtc_funcs = {
.crtc_output_post_enable = vop2_crtc_output_post_enable,
.crtc_output_pre_disable = vop2_crtc_output_pre_disable,
.crtc_set_color_bar = vop2_crtc_set_color_bar,
.set_aclk = vop2_devfreq_set_aclk,
.set_aclk = vop2_set_aclk_rate,
.get_crc = vop2_crtc_get_crc,
};
@@ -9482,7 +9553,6 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_sta
if (is_vop3(vop2))
vop3_setup_pipe_dly(vp, NULL);
vop2_crtc_csu_set_rate(crtc);
vop2_crtc_setup_output_mode(crtc);
vop2_cfg_done(crtc);
@@ -11719,12 +11789,12 @@ static void vop2_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_stat
VOP_CTRL_SET(vop2, dma_stop, 1);
if (vop2->aclk_mode_rate[ROCKCHIP_VOP_ACLK_RESET_MODE] &&
clk_get_rate(vop2->aclk) > vop2->aclk_mode_rate[ROCKCHIP_VOP_ACLK_RESET_MODE]) {
vop2_devfreq_set_aclk(crtc, ROCKCHIP_VOP_ACLK_RESET_MODE);
vop2_set_aclk_rate(crtc, ROCKCHIP_VOP_ACLK_RESET_MODE, NULL);
enter_vop_aclk_reset_mode = true;
}
ret = rockchip_drm_dma_attach_device(vop2->drm_dev, vop2->dev);
if (enter_vop_aclk_reset_mode)
vop2_devfreq_set_aclk(crtc, aclk_mode);
vop2_set_aclk_rate(crtc, aclk_mode, NULL);
if (ret) {
vop2->is_iommu_enabled = false;
vop2_disable_all_planes_for_crtc(crtc);
@@ -13758,6 +13828,9 @@ static char *vop2_plane_mask_to_string(unsigned long mask)
static inline const char *vop2_plane_id_to_string(unsigned long phy)
{
if (phy == ROCKCHIP_VOP2_PHY_ID_INVALID)
return "INVALID";
if (WARN_ON(phy >= ARRAY_SIZE(vop2_layer_name_list)))
return NULL;
@@ -13892,39 +13965,6 @@ static struct devfreq_governor devfreq_vop2_ondemand = {
.event_handler = devfreq_vop2_ondemand_handler,
};
static int vop2_devfreq_set_aclk(struct drm_crtc *crtc, enum rockchip_drm_vop_aclk_mode aclk_mode)
{
struct vop2_video_port *vp = to_vop2_video_port(crtc);
struct vop2 *vop2 = vp->vop2;
struct drm_crtc *first_active_crtc = NULL;
int i = 0, ret = 0;
if (!vop2->devfreq)
return 0;
/* all vp/crtc share one vop aclk, so only need to set once */
for (i = 0; i < vop2->data->nr_vps; i++) {
if (vop2->vps[i].rockchip_crtc.crtc.state &&
vop2->vps[i].rockchip_crtc.crtc.state->active) {
first_active_crtc = &vop2->vps[i].rockchip_crtc.crtc;
break;
}
}
if (first_active_crtc != crtc)
return 0;
vop2->aclk_target_freq = vop2->aclk_mode_rate[aclk_mode];
mutex_lock(&vop2->devfreq->lock);
ret = update_devfreq(vop2->devfreq);
mutex_unlock(&vop2->devfreq->lock);
if (ret)
dev_err(vop2->dev, "failed to set rate %lu\n", vop2->aclk_target_freq);
vop2->aclk_mode = aclk_mode;
return 0;
}
static int vop2_devfreq_target(struct device *dev, unsigned long *freq,
u32 flags)
{
@@ -14074,11 +14114,6 @@ static void rockchip_vop2_devfreq_uninit(struct vop2 *vop2)
rockchip_uninit_opp_table(vop2->dev, &vop2->opp_info);
}
#else
static inline int vop2_devfreq_set_aclk(struct drm_crtc *crtc, enum rockchip_drm_vop_aclk_mode aclk_mode)
{
return 0;
}
static inline int rockchip_vop2_devfreq_init(struct vop2 *vop2)
{
return 0;

View File

@@ -208,7 +208,7 @@
* enable it when customer need control TP power
* default: disable
*/
#define FTS_POWER_SOURCE_CUST_EN 1
#define FTS_POWER_SOURCE_CUST_EN 0
/****************************************************/

View File

@@ -76,8 +76,8 @@ static const struct regmap_range rk628_hdmirx_readable_ranges[] = {
regmap_reg_range(HDMI_RX_PDEC_STS, HDMI_RX_PDEC_STS),
regmap_reg_range(HDMI_RX_PDEC_GCP_AVMUTE, HDMI_RX_PDEC_GCP_AVMUTE),
regmap_reg_range(HDMI_RX_PDEC_ACR_CTS, HDMI_RX_PDEC_ACR_N),
regmap_reg_range(HDMI_RX_PDEC_AVI_HB, HDMI_RX_PDEC_AVI_PB),
regmap_reg_range(HDMI_RX_PDEC_AIF_CTRL, HDMI_RX_PDEC_AIF_PB0),
regmap_reg_range(HDMI_RX_PDEC_AVI_PB, HDMI_RX_PDEC_AVI_PB),
regmap_reg_range(HDMI_RX_HDMI20_CONTROL, HDMI_RX_CHLOCK_CONFIG),
regmap_reg_range(HDMI_RX_SCDC_REGS0, HDMI_RX_SCDC_REGS2),
regmap_reg_range(HDMI_RX_SCDC_WRDATA0, HDMI_RX_SCDC_WRDATA0),

View File

@@ -71,6 +71,11 @@ enum hdmirx_pix_fmt {
HDMIRX_YUV420 = 3,
};
enum hdmirx_ycc_range {
HDMIRX_YCC_LIMIT,
HDMIRX_YCC_FULL,
};
static const char * const bus_format_str[] = {
"RGB",
"YUV422",
@@ -1759,13 +1764,23 @@ EXPORT_SYMBOL(rk628_hdmirx_get_timings);
u8 rk628_hdmirx_get_range(struct rk628 *rk628)
{
u8 color_range;
u32 val, vic, fmt;
u8 color_range, yuv_range;
u32 val, vic, fmt, avi_hb;
rk628_i2c_read(rk628, HDMI_RX_PDEC_AVI_PB, &val);
rk628_i2c_read(rk628, HDMI_RX_PDEC_AVI_HB, &avi_hb);
color_range = (val & RGB_COLORRANGE_MASK) >> 18;
yuv_range = (avi_hb & YUV_COLORRANGE_MASK) >> 30;
vic = (val & VID_IDENT_CODE_MASK) >> 24;
fmt = (val & VIDEO_FORMAT_MASK) >> 5;
if (fmt != HDMIRX_RGB888) {
if (yuv_range == HDMIRX_YCC_LIMIT)
color_range = HDMIRX_LIMIT_RANGE;
else if (yuv_range == HDMIRX_YCC_FULL)
color_range = HDMIRX_FULL_RANGE;
else
color_range = HDMIRX_DEFAULT_RANGE;
}
if (fmt == HDMIRX_RGB888 && color_range == HDMIRX_DEFAULT_RANGE) {
(vic) ?
(color_range = HDMIRX_LIMIT_RANGE) :

View File

@@ -267,6 +267,7 @@
#define VIDEO_FORMAT_MASK GENMASK(6, 5)
#define VIDEO_FORMAT(x) UPDATE(x, 6, 5)
#define RGB_COLORRANGE_MASK GENMASK(19, 18)
#define YUV_COLORRANGE_MASK GENMASK(31, 30)
#define RGB_COLORRANGE(x) UPDATE(x, 19, 18)
#define ACT_INFO_PRESENT_MASK BIT(4)
#define HDMI_RX_PDEC_ACR_CTS (HDMI_RX_BASE + 0x0390)

View File

@@ -435,9 +435,6 @@ int rkisp_stream_frame_start(struct rkisp_device *dev, u32 isp_mis)
rkisp_dvbm_event(dev, CIF_ISP_V_START);
rkisp_bridge_update_mi(dev, isp_mis);
if (dev->isp_ver == ISP_V39)
rkisp_sditf_sof(dev, isp_mis);
for (i = 0; i < RKISP_MAX_STREAM; i++) {
if (i == RKISP_STREAM_VIR || i == RKISP_STREAM_LUMA)
continue;

View File

@@ -96,6 +96,7 @@ void rkisp_sditf_sof(struct rkisp_device *dev, u32 irq)
return;
info.irq = irq;
rkisp_dmarx_get_frame(dev, &info.seq, NULL, &info.timestamp, true);
info.unite_index = dev->unite_index;
v4l2_subdev_call(sditf->remote_sd, core, ioctl, RKISP_VPSS_CMD_SOF, &info);
}
@@ -106,8 +107,18 @@ static long rkisp_sditf_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *ar
switch (cmd) {
case RKISP_VPSS_CMD_EOF:
if (*(int *)arg) {
sditf->is_on = false;
sditf->isp->irq_ends_mask &= ~ISP_FRAME_VPSS;
}
rkisp_check_idle(sditf->isp, ISP_FRAME_VPSS);
break;
case RKISP_VPSS_GET_UNITE_MODE:
if (sditf->isp->unite_div == ISP_UNITE_DIV2)
*(unsigned int *)arg = sditf->isp->unite_div;
else
*(unsigned int *)arg = 0;
break;
default:
ret = -ENOIOCTLCMD;
}

View File

@@ -8,12 +8,17 @@
_IOW('V', BASE_VIDIOC_PRIVATE + 0, struct rkisp_vpss_sof)
#define RKISP_VPSS_CMD_EOF \
_IO('V', BASE_VIDIOC_PRIVATE + 1)
_IOW('V', BASE_VIDIOC_PRIVATE + 1, int)
#define RKISP_VPSS_GET_UNITE_MODE \
_IOR('V', BASE_VIDIOC_PRIVATE + 2, unsigned int)
struct rkisp_vpss_sof {
u32 irq;
u32 seq;
u64 timestamp;
u32 unite_index;
u32 reserved;
};
#endif

View File

@@ -660,6 +660,9 @@ void rkisp_trigger_read_back(struct rkisp_device *dev, u8 dma2frm, u32 mode, boo
rkisp_stream_frame_start(dev, 0);
}
if (dev->isp_ver == ISP_V39)
rkisp_sditf_sof(dev, 0);
if (!hw->is_single) {
/* multi sensor need to reset isp resize mode if scale up */
val = 0;
@@ -1148,6 +1151,9 @@ void rkisp_check_idle(struct rkisp_device *dev, u32 irq)
u32 state = dev->isp_state;
struct rkisp_stream *s;
if (dev->sditf_dev && !dev->sditf_dev->is_on)
dev->isp_state = ISP_STOP;
for (val = 0; val < RKISP_STREAM_VIR; val++) {
s = &dev->cap_dev.stream[val];
dev->isp_state = ISP_STOP;
@@ -4453,6 +4459,8 @@ void rkisp_isp_isr(unsigned int isp_mis,
dev->isp_sdev.frm_timestamp = rkisp_time_get_ns(dev);
rkisp_isp_queue_event_sof(&dev->isp_sdev);
rkisp_stream_frame_start(dev, isp_mis);
if (dev->isp_ver == ISP_V39)
rkisp_sditf_sof(dev, isp_mis);
rkisp_rockit_frame_start(dev);
}
vs_skip:
@@ -4617,6 +4625,8 @@ vs_skip:
rkisp_isp_queue_event_sof(&dev->isp_sdev);
rkisp_stream_frame_start(dev, isp_mis);
rkisp_rockit_frame_start(dev);
if (dev->isp_ver == ISP_V39)
rkisp_sditf_sof(dev, isp_mis);
}
if (isp_mis & ISP3X_OUT_FRM_QUARTER) {

View File

@@ -9,49 +9,70 @@
#include "dev.h"
#include "regs.h"
void rkvpss_write(struct rkvpss_device *dev, u32 reg, u32 val)
{
u32 *mem = dev->sw_base_addr + reg;
u32 *flag = dev->sw_base_addr + reg + RKVPSS_SW_REG_SIZE;
void rkvpss_idx_write(struct rkvpss_device *dev, u32 reg, u32 val, int idx)
{
u32 *mem, *flag, offset = idx * RKVPSS_SW_REG_SIZE_MAX;
if (!dev->unite_mode)
offset = 0;
mem = dev->sw_base_addr + reg + offset;
flag = dev->sw_base_addr + reg + RKVPSS_SW_REG_SIZE + offset;
*mem = val;
*flag = RKVPSS_REG_CACHE;
if (dev->hw_dev->is_single)
if (dev->hw_dev->is_single && !dev->unite_mode)
rkvpss_hw_write(dev->hw_dev, reg, val);
}
u32 rkvpss_read(struct rkvpss_device *dev, u32 reg)
void rkvpss_unite_write(struct rkvpss_device *dev, u32 reg, u32 val)
{
u32 val;
rkvpss_idx_write(dev, reg, val, VPSS_UNITE_LEFT);
if (dev->unite_mode)
rkvpss_idx_write(dev, reg, val, VPSS_UNITE_RIGHT);
}
if (dev->hw_dev->is_single)
u32 rkvpss_idx_read(struct rkvpss_device *dev, u32 reg, int idx)
{
u32 val, offset = idx * RKVPSS_SW_REG_SIZE_MAX;
if (!dev->unite_mode)
offset = 0;
if (dev->hw_dev->is_single && !dev->unite_mode)
val = rkvpss_hw_read(dev->hw_dev, reg);
else
val = *(u32 *)(dev->sw_base_addr + reg);
val = *(u32 *)(dev->sw_base_addr + reg + offset);
return val;
}
void rkvpss_set_bits(struct rkvpss_device *dev, u32 reg, u32 mask, u32 val)
void rkvpss_idx_set_bits(struct rkvpss_device *dev, u32 reg, u32 mask, u32 val, int idx)
{
u32 *mem = dev->sw_base_addr + reg;
u32 *flag = dev->sw_base_addr + reg + RKVPSS_SW_REG_SIZE;
u32 tmp = rkvpss_idx_read(dev, reg, idx) & ~mask;
*mem &= ~mask;
*mem |= val;
*flag = RKVPSS_REG_CACHE;
if (dev->hw_dev->is_single)
rkvpss_hw_set_bits(dev->hw_dev, reg, mask, val);
rkvpss_idx_write(dev, reg, val | tmp, idx);
}
void rkvpss_clear_bits(struct rkvpss_device *dev, u32 reg, u32 mask)
void rkvpss_unite_set_bits(struct rkvpss_device *dev, u32 reg, u32 mask, u32 val)
{
u32 *mem = dev->sw_base_addr + reg;
u32 *flag = dev->sw_base_addr + reg + RKVPSS_SW_REG_SIZE;
rkvpss_idx_set_bits(dev, reg, mask, val, VPSS_UNITE_LEFT);
if (dev->unite_mode)
rkvpss_idx_set_bits(dev, reg, mask, val, VPSS_UNITE_RIGHT);
}
*mem &= ~mask;
*flag = RKVPSS_REG_CACHE;
if (dev->hw_dev->is_single)
rkvpss_hw_clear_bits(dev->hw_dev, reg, mask);
void rkvpss_idx_clear_bits(struct rkvpss_device *dev, u32 reg, u32 mask, int idx)
{
u32 tmp = rkvpss_idx_read(dev, reg, idx);
rkvpss_idx_write(dev, reg, tmp & ~mask, idx);
}
void rkvpss_unite_clear_bits(struct rkvpss_device *dev, u32 reg, u32 mask)
{
rkvpss_idx_clear_bits(dev, reg, mask, VPSS_UNITE_LEFT);
if (dev->unite_mode)
rkvpss_idx_clear_bits(dev, reg, mask, VPSS_UNITE_RIGHT);
}
void rkvpss_update_regs(struct rkvpss_device *dev, u32 start, u32 end)
@@ -69,6 +90,13 @@ void rkvpss_update_regs(struct rkvpss_device *dev, u32 start, u32 end)
u32 *val = dev->sw_base_addr + i;
u32 *flag = dev->sw_base_addr + i + RKVPSS_SW_REG_SIZE;
if (dev->unite_mode &&
((!dev->mir_en && dev->unite_index == VPSS_UNITE_RIGHT) ||
(dev->mir_en && dev->unite_index == VPSS_UNITE_LEFT))) {
val += (RKVPSS_SW_REG_SIZE_MAX / 4);
flag += (RKVPSS_SW_REG_SIZE_MAX / 4);
}
if (*flag != RKVPSS_REG_CACHE)
continue;
@@ -86,6 +114,8 @@ void rkvpss_update_regs(struct rkvpss_device *dev, u32 start, u32 end)
}
}
writel(*val, base + i);
if (i == RKVPSS_MI_WR_INIT)
writel(*val, base + i);
if (IS_SYNC_REG(i))
spin_unlock_irqrestore(&hw->reg_lock, lock_flags);
}

View File

@@ -14,6 +14,7 @@
#include <media/videobuf2-v4l2.h>
#include "../isp/isp_vpss.h"
#include <linux/rk-camera-module.h>
#define RKVPSS_PLANE_Y 0
#define RKVPSS_PLANE_UV 1
@@ -90,10 +91,13 @@ static inline struct vb2_queue *to_vb2_queue(struct file *file)
extern int rkvpss_debug;
extern struct platform_driver rkvpss_plat_drv;
void rkvpss_write(struct rkvpss_device *dev, u32 reg, u32 val);
void rkvpss_set_bits(struct rkvpss_device *dev, u32 reg, u32 mask, u32 val);
u32 rkvpss_read(struct rkvpss_device *dev, u32 reg);
void rkvpss_clear_bits(struct rkvpss_device *dev, u32 reg, u32 mask);
void rkvpss_idx_write(struct rkvpss_device *dev, u32 reg, u32 val, int idx);
void rkvpss_unite_write(struct rkvpss_device *dev, u32 reg, u32 val);
void rkvpss_idx_set_bits(struct rkvpss_device *dev, u32 reg, u32 mask, u32 val, int idx);
void rkvpss_unite_set_bits(struct rkvpss_device *dev, u32 reg, u32 mask, u32 val);
u32 rkvpss_idx_read(struct rkvpss_device *dev, u32 reg, int idx);
void rkvpss_idx_clear_bits(struct rkvpss_device *dev, u32 reg, u32 mask, int idx);
void rkvpss_unite_clear_bits(struct rkvpss_device *dev, u32 reg, u32 mask);
void rkvpss_update_regs(struct rkvpss_device *dev, u32 start, u32 end);
int rkvpss_attach_hw(struct rkvpss_device *vpss);

View File

@@ -75,6 +75,9 @@ int rkvpss_pipeline_stream(struct rkvpss_device *dev, bool on)
(!on && atomic_dec_return(&dev->pipe_stream_cnt) > 0))
return 0;
v4l2_dbg(1, rkvpss_debug, &dev->v4l2_dev,
"%s on:%d\n", __func__, on);
if (on) {
ret = v4l2_subdev_call(&dev->vpss_sdev.sd, video, s_stream, true);
if (ret < 0)
@@ -84,7 +87,12 @@ int rkvpss_pipeline_stream(struct rkvpss_device *dev, bool on)
v4l2_subdev_call(&dev->vpss_sdev.sd, video, s_stream, false);
goto err;
}
dev->stopping = false;
} else {
dev->stopping = true;
ret = wait_event_timeout(dev->stop_done, !dev->stopping, msecs_to_jiffies(300));
if (!ret)
v4l2_warn(&dev->v4l2_dev, "%s timeout\n", __func__);
v4l2_subdev_call(dev->remote_sd, video, s_stream, false);
v4l2_subdev_call(&dev->vpss_sdev.sd, video, s_stream, false);
}
@@ -256,7 +264,7 @@ static int rkvpss_plat_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct v4l2_device *v4l2_dev;
struct rkvpss_device *vpss_dev;
int ret;
int ret, mult = 2;
sprintf(rkvpss_version, "v%02x.%02x.%02x",
RKVPSS_DRIVER_VERSION >> 16,
@@ -268,7 +276,7 @@ static int rkvpss_plat_probe(struct platform_device *pdev)
vpss_dev = devm_kzalloc(dev, sizeof(*vpss_dev), GFP_KERNEL);
if (!vpss_dev)
return -ENOMEM;
vpss_dev->sw_base_addr = devm_kzalloc(dev, RKVPSS_SW_REG_SIZE_MAX, GFP_KERNEL);
vpss_dev->sw_base_addr = devm_kzalloc(dev, RKVPSS_SW_REG_SIZE_MAX * mult, GFP_KERNEL);
if (!vpss_dev->sw_base_addr)
return -ENOMEM;
@@ -314,6 +322,7 @@ static int rkvpss_plat_probe(struct platform_device *pdev)
rkvpss_proc_init(vpss_dev);
pm_runtime_enable(&pdev->dev);
vpss_dev->is_probe_end = true;
init_waitqueue_head(&vpss_dev->stop_done);
return 0;
err_unreg_media_dev:

View File

@@ -29,6 +29,12 @@ enum {
T_CMD_END,
};
enum {
VPSS_UNITE_LEFT = 0,
VPSS_UNITE_RIGHT,
VPSS_UNITE_MAX,
};
struct rkvpss_rdbk_info {
u64 timestamp;
u64 seq;
@@ -65,6 +71,12 @@ struct rkvpss_device {
bool mir_en;
bool cmsc_upd;
u32 unite_mode;
u8 unite_index;
bool stopping;
wait_queue_head_t stop_done;
unsigned int irq_ends;
unsigned int irq_ends_mask;
bool is_probe_end;
};

View File

@@ -665,8 +665,11 @@ static irqreturn_t mi_irq_hdl(int irq, void *ctx)
mis_val = rkvpss_hw_read(hw_dev, RKVPSS_MI_MIS);
if (mis_val) {
if (mis_val & RKVPSS_MI_BUS_ERR)
dev_err(dev, "axi bus error\n");
rkvpss_hw_write(hw_dev, RKVPSS_MI_ICR, mis_val);
rkvpss_mi_isr(vpss, mis_val);
if (vpss)
rkvpss_mi_isr(vpss, mis_val);
}
return IRQ_HANDLED;
}

File diff suppressed because it is too large Load Diff

View File

@@ -120,6 +120,20 @@ struct frame_debug_info {
u32 frameloss;
};
struct rkvpss_online_unite_params {
u32 y_w_fac;
u32 c_w_fac;
u32 y_h_fac;
u32 c_h_fac;
u32 y_w_phase;
u32 c_w_phase;
u32 quad_crop_w;
u32 scl_in_crop_w_y;
u32 scl_in_crop_w_c;
u32 right_scl_need_size_y;
u32 right_scl_need_size_c;
};
/* struct rkvpss_stream - VPSS stream video device
* id: stream video identify
* buf_queue: queued buffer list
@@ -154,6 +168,7 @@ struct rkvpss_stream {
struct v4l2_rect crop;
struct v4l2_pix_format_mplane out_fmt;
struct frame_debug_info dbg;
struct rkvpss_online_unite_params unite_params;
int id;
bool streaming;

View File

@@ -148,8 +148,8 @@ static int rkvpss_sd_s_stream(struct v4l2_subdev *sd, int on)
"s_stream on:%d %dx%d\n", on, w, h);
if (!on) {
rkvpss_clear_bits(dev, RKVPSS_VPSS_ONLINE, RKVPSS_ONLINE_MODE_MASK);
rkvpss_clear_bits(dev, RKVPSS_VPSS_IMSC, RKVPSS_ISP_ALL_FRM_END);
rkvpss_unite_clear_bits(dev, RKVPSS_VPSS_ONLINE, RKVPSS_ONLINE_MODE_MASK);
rkvpss_unite_clear_bits(dev, RKVPSS_VPSS_IMSC, RKVPSS_ISP_ALL_FRM_END);
sdev->state = VPSS_STOP;
atomic_dec(&dev->hw_dev->refcnt);
return 0;
@@ -158,18 +158,23 @@ static int rkvpss_sd_s_stream(struct v4l2_subdev *sd, int on)
sdev->frame_seq = -1;
sdev->frame_timestamp = 0;
dev->isr_cnt = 0;
dev->irq_ends = 0;
atomic_inc(&dev->hw_dev->refcnt);
dev->cmsc_upd = true;
rkvpss_cmsc_config(dev, true);
rkvpss_write(dev, RKVPSS_VPSS_ONLINE2_SIZE, h << 16 | w);
if (dev->unite_mode)
w = w / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL;
rkvpss_unite_write(dev, RKVPSS_VPSS_ONLINE2_SIZE, h << 16 | w);
val = RKVPSS_CFG_FORCE_UPD | RKVPSS_CFG_GEN_UPD | RKVPSS_MIR_GEN_UPD;
if (!dev->hw_dev->is_ofl_cmsc)
val |= RKVPSS_MIR_FORCE_UPD;
rkvpss_write(dev, RKVPSS_VPSS_UPDATE, val);
rkvpss_unite_write(dev, RKVPSS_VPSS_UPDATE, val);
rkvpss_set_bits(dev, RKVPSS_VPSS_IMSC, 0, RKVPSS_ISP_ALL_FRM_END);
rkvpss_unite_set_bits(dev, RKVPSS_VPSS_IMSC, 0, RKVPSS_ISP_ALL_FRM_END);
sdev->state |= VPSS_START;
return 0;
}
@@ -209,6 +214,8 @@ static int rkvpss_sd_s_power(struct v4l2_subdev *sd, int on)
return ret;
}
}
v4l2_subdev_call(dev->remote_sd, core, ioctl, RKISP_VPSS_GET_UNITE_MODE,
&dev->unite_mode);
ret = pm_runtime_get_sync(dev->dev);
if (ret < 0) {
v4l2_err(&dev->v4l2_dev,
@@ -232,11 +239,17 @@ static int rkvpss_sof(struct rkvpss_subdev *sdev, struct rkisp_vpss_sof *info)
struct rkvpss_hw_dev *hw = dev->hw_dev;
struct rkvpss_stream *stream;
int i;
u32 vpss_online, val = 0;
if (!info)
return -EINVAL;
sdev->frame_seq = info->seq;
sdev->frame_timestamp = info->timestamp;
dev->unite_index = info->unite_index;
v4l2_dbg(3, rkvpss_debug, &dev->v4l2_dev,
"%s unite_mode:%u, unite_indev:%u\n", __func__,
dev->unite_mode, dev->unite_index);
rkvpss_cmsc_config(dev, !info->irq);
for (i = 0; i < RKVPSS_OUTPUT_MAX; i++) {
@@ -247,7 +260,7 @@ static int rkvpss_sof(struct rkvpss_subdev *sdev, struct rkisp_vpss_sof *info)
stream->ops->frame_start(stream, info->irq);
}
if (!info->irq && !hw->is_single) {
if (!info->irq && (!hw->is_single || dev->unite_mode)) {
hw->cur_dev_id = dev->dev_id;
rkvpss_update_regs(dev, RKVPSS_VPSS_CTRL, RKVPSS_VPSS_ONLINE2_SIZE);
rkvpss_update_regs(dev, RKVPSS_VPSS_IRQ_CFG, RKVPSS_VPSS_IMSC);
@@ -262,7 +275,7 @@ static int rkvpss_sof(struct rkvpss_subdev *sdev, struct rkisp_vpss_sof *info)
rkvpss_update_regs(dev, RKVPSS_MI_WR_WRAP_CTRL, RKVPSS_MI_IMSC);
rkvpss_update_regs(dev, RKVPSS_MI_CHN0_WR_CTRL, RKVPSS_MI_CHN3_WR_LINE_CNT);
rkvpss_update_regs(dev, RKVPSS_MI_WR_CTRL, RKVPSS_MI_WR_INIT);
rkvpss_update_regs(dev, RKVPSS_MI_WR_CTRL, RKVPSS_MI_WR_CTRL);
rkvpss_update_regs(dev, RKVPSS_SCALE3_CTRL, RKVPSS_SCALE3_UPDATE);
rkvpss_update_regs(dev, RKVPSS_SCALE2_CTRL, RKVPSS_SCALE2_UPDATE);
rkvpss_update_regs(dev, RKVPSS_SCALE1_CTRL, RKVPSS_SCALE1_UPDATE);
@@ -270,6 +283,23 @@ static int rkvpss_sof(struct rkvpss_subdev *sdev, struct rkisp_vpss_sof *info)
rkvpss_update_regs(dev, RKVPSS_CROP1_CTRL, RKVPSS_CROP1_UPDATE);
rkvpss_update_regs(dev, RKVPSS_CMSC_CTRL, RKVPSS_CMSC_UPDATE);
rkvpss_update_regs(dev, RKVPSS_VPSS_UPDATE, RKVPSS_VPSS_UPDATE);
/* force update mi write */
vpss_online = rkvpss_hw_read(hw, RKVPSS_VPSS_ONLINE);
for (i = 0; i < RKVPSS_OUTPUT_MAX; i++) {
if (((vpss_online >> (2 * i)) & 0x3) == 0x2)
val |= BIT(i);
}
rkvpss_unite_write(dev, RKVPSS_MI_WR_INIT, val << 4);
rkvpss_update_regs(dev, RKVPSS_MI_WR_INIT, RKVPSS_MI_WR_INIT);
}
dev->irq_ends_mask = VPSS_FRAME_END;
for (i = 0; i < RKVPSS_OUTPUT_MAX; i++) {
if (hw->is_ofl_ch[i])
continue;
if (rkvpss_hw_read(dev->hw_dev, RKVPSS_MI_CHN0_WR_CTRL_SHD + i * 0x100) & 0x1)
dev->irq_ends_mask |= BIT(i+3);
}
return 0;
}
@@ -342,6 +372,54 @@ static void rkvpss_subdev_default_fmt(struct rkvpss_subdev *sdev)
out_fmt->height = RKVPSS_DEFAULT_HEIGHT;
}
static void rkvpss_end_notify_isp(struct rkvpss_device *dev)
{
int stopping;
v4l2_dbg(3, rkvpss_debug, &dev->v4l2_dev,
"%s stopping:%d unite_index:%d\n", __func__, dev->stopping, dev->unite_index);
if (dev->stopping) {
if (dev->unite_mode) {
if (dev->unite_index == VPSS_UNITE_LEFT) {
stopping = 0;
v4l2_subdev_call(dev->remote_sd, core, ioctl, RKISP_VPSS_CMD_EOF,
&stopping);
} else {
dev->stopping = false;
wake_up(&dev->stop_done);
stopping = 1;
v4l2_subdev_call(dev->remote_sd, core, ioctl, RKISP_VPSS_CMD_EOF,
&stopping);
}
} else {
dev->stopping = false;
wake_up(&dev->stop_done);
stopping = 1;
v4l2_subdev_call(dev->remote_sd, core, ioctl, RKISP_VPSS_CMD_EOF,
&stopping);
}
} else {
stopping = 0;
v4l2_subdev_call(dev->remote_sd, core, ioctl, RKISP_VPSS_CMD_EOF, &stopping);
}
}
void rkvpss_check_idle(struct rkvpss_device *dev, u32 irq)
{
dev->irq_ends |= (irq & dev->irq_ends_mask);
v4l2_dbg(3, rkvpss_debug, &dev->v4l2_dev,
"%s irq:0x%x ends:0x%x mask:0x%x\n",
__func__, irq, dev->irq_ends, dev->irq_ends_mask);
if ((dev->irq_ends & dev->irq_ends_mask) != dev->irq_ends_mask)
return;
dev->irq_ends = 0;
rkvpss_end_notify_isp(dev);
}
int rkvpss_register_subdev(struct rkvpss_device *dev,
struct v4l2_device *v4l2_dev)
{

View File

@@ -18,6 +18,11 @@ enum rkvpss_state {
VPSS_STOP = 0,
VPSS_FS = BIT(0),
VPSS_FE = BIT(1),
VPSS_FRAME_END = BIT(2),
VPSS_FRAME_SCL0 = BIT(3),
VPSS_FRAME_SCL1 = BIT(4),
VPSS_FRAME_SCL2 = BIT(5),
VPSS_FRAME_SCL3 = BIT(6),
VPSS_START = BIT(8),
VPSS_RX_START = BIT(9),
@@ -46,4 +51,5 @@ struct rkvpss_subdev {
int rkvpss_register_subdev(struct rkvpss_device *dev,
struct v4l2_device *v4l2_dev);
void rkvpss_unregister_subdev(struct rkvpss_device *dev);
void rkvpss_check_idle(struct rkvpss_device *dev, u32 irq);
#endif

View File

@@ -5416,8 +5416,8 @@ int rk_iomux_set(int bank, int pin, int mux)
mutex_lock(&iomux_lock);
for (i = 0; i < info->ngroups; i++) {
grp = &info->groups[i];
for (j = 0; j < grp->npins; i++) {
if (grp->pins[i] == (gpio->pin_base + pin)) {
for (j = 0; j < grp->npins; j++) {
if (grp->pins[j] == (gpio->pin_base + pin)) {
cfg = grp->data;
break;
}

View File

@@ -2889,7 +2889,6 @@ static void rga2_set_reg_full_csc(struct rga_job *job, struct rga_scheduler_t *s
static int rga2_set_reg(struct rga_job *job, struct rga_scheduler_t *scheduler)
{
int i;
int cur_num;
bool master_mode_en;
uint32_t sys_ctrl;
uint32_t *cmd;
@@ -2930,10 +2929,8 @@ static int rga2_set_reg(struct rga_job *job, struct rga_scheduler_t *scheduler)
* when RGA is running continuously, disabling auto_rst
* requires resetting core_clk.
*/
cur_num = (rga_read(RGA2_STATUS1, scheduler) & m_RGA2_STATUS1_SW_CMD_CUR_NUM) >> 8;
if (cur_num > 0)
rga_write(m_RGA2_SYS_CTRL_AUTO_CKG | m_RGA2_SYS_CTRL_CCLK_SRESET_P,
RGA2_SYS_CTRL, scheduler);
rga_write(m_RGA2_SYS_CTRL_AUTO_CKG | m_RGA2_SYS_CTRL_CCLK_SRESET_P,
RGA2_SYS_CTRL, scheduler);
} else {
sys_ctrl |= m_RGA2_SYS_CTRL_AUTO_RST;
}
@@ -2966,8 +2963,6 @@ static int rga2_set_reg(struct rga_job *job, struct rga_scheduler_t *scheduler)
for (i = 0; i <= 32; i++)
rga_write(cmd[i], 0x100 + i * 4, scheduler);
rga_write(rga_read(RGA2_CMD_CTRL, scheduler) | m_RGA2_CMD_CTRL_CMD_LINE_ST_P,
RGA2_CMD_CTRL, scheduler);
rga_write(sys_ctrl, RGA2_SYS_CTRL, scheduler);
}

View File

@@ -51,6 +51,8 @@ struct analogix_dp_plat_data {
bool dual_connector_split;
bool left_display;
u8 max_bpc;
struct analogix_dp_device *left;
struct analogix_dp_device *right;
@@ -66,6 +68,12 @@ struct analogix_dp_plat_data {
void (*convert_to_origin_mode)(struct drm_display_mode *);
};
struct analogix_dp_output_format {
u32 bus_format;
u32 color_format;
u8 bpc;
};
int analogix_dp_resume(struct analogix_dp_device *dp);
int analogix_dp_suspend(struct analogix_dp_device *dp);
int analogix_dp_runtime_resume(struct analogix_dp_device *dp);
@@ -89,5 +97,6 @@ int analogix_dp_audio_get_eld(struct analogix_dp_device *dp,
u8 *buf, size_t len);
int analogix_dp_loader_protect(struct analogix_dp_device *dp);
void analogix_dp_disable(struct analogix_dp_device *dp);
const struct analogix_dp_output_format *analogix_dp_get_output_format(u32 bus_format);
#endif /* _ANALOGIX_DP_H_ */