diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c index c89db60dc86e..3ff8b7044ff9 100644 --- a/arch/arm/mach-rockchip/rockchip.c +++ b/arch/arm/mach-rockchip/rockchip.c @@ -62,6 +62,7 @@ static const char * const rockchip_board_dt_compat[] = { "rockchip,rk3188", "rockchip,rk3228", "rockchip,rk3288", + "rockchip,rv1103", "rockchip,rv1106", "rockchip,rv1108", NULL, diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c index 968fd14c1bc2..48d19850be78 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c @@ -246,6 +246,7 @@ struct dw_mipi_dsi2 { union phy_configure_opts phy_opts; bool disable_hold_mode; + bool auto_calc_mode; bool c_option; bool scrambling_en; unsigned int slice_width; @@ -270,7 +271,7 @@ struct dw_mipi_dsi2 { u32 lanes; u32 format; unsigned long mode_flags; - + u64 mipi_pixel_rate; const struct dw_mipi_dsi2_plat_data *pdata; struct rockchip_drm_sub_dev sub_dev; @@ -609,9 +610,8 @@ static void dw_mipi_dsi2_phy_clk_mode_cfg(struct dw_mipi_dsi2 *dsi2) static void dw_mipi_dsi2_phy_ratio_cfg(struct dw_mipi_dsi2 *dsi2) { - struct drm_display_mode *mode = &dsi2->mode; u64 sys_clk = clk_get_rate(dsi2->sys_clk); - u64 pixel_clk, ipi_clk, phy_hsclk; + u64 ipi_clk, phy_hsclk; u64 tmp; /* @@ -625,9 +625,7 @@ static void dw_mipi_dsi2_phy_ratio_cfg(struct dw_mipi_dsi2 *dsi2) phy_hsclk = DIV_ROUND_CLOSEST_ULL(dsi2->lane_hs_rate * MSEC_PER_SEC, 16); /* IPI_RATIO_MAN_CFG = PHY_HSTX_CLK / IPI_CLK */ - pixel_clk = mode->crtc_clock * MSEC_PER_SEC; - ipi_clk = pixel_clk / 4; - + ipi_clk = dsi2->mipi_pixel_rate; if (!sys_clk || !ipi_clk) return; @@ -669,6 +667,10 @@ static void dw_mipi_dsi2_phy_init(struct dw_mipi_dsi2 *dsi2) { dw_mipi_dsi2_phy_mode_cfg(dsi2); dw_mipi_dsi2_phy_clk_mode_cfg(dsi2); + + if (dsi2->auto_calc_mode) + return; + dw_mipi_dsi2_phy_ratio_cfg(dsi2); dw_mipi_dsi2_lp2hs_or_hs2lp_cfg(dsi2); @@ -737,6 +739,9 @@ static void dw_mipi_dsi2_ipi_set(struct dw_mipi_dsi2 *dsi2) dw_mipi_dsi2_ipi_color_coding_cfg(dsi2); + if (dsi2->auto_calc_mode) + return; + /* * if the controller is intended to operate in data stream mode, * no more steps are required. @@ -810,7 +815,7 @@ static void dw_mipi_dsi2_pre_enable(struct dw_mipi_dsi2 *dsi2) /* there may be some timeout registers may be configured if desired */ - dw_mipi_dsi2_work_mode(dsi2, MANUAL_MODE_EN); + dw_mipi_dsi2_work_mode(dsi2, dsi2->auto_calc_mode ? 0 : MANUAL_MODE_EN); dw_mipi_dsi2_phy_init(dsi2); dw_mipi_dsi2_tx_option_set(dsi2); dw_mipi_dsi2_irq_enable(dsi2, 1); @@ -833,8 +838,20 @@ static void dw_mipi_dsi2_pre_enable(struct dw_mipi_dsi2 *dsi2) static void dw_mipi_dsi2_enable(struct dw_mipi_dsi2 *dsi2) { + u32 mode; + int ret; + dw_mipi_dsi2_ipi_set(dsi2); + if (dsi2->auto_calc_mode) { + regmap_write(dsi2->regmap, DSI2_MODE_CTRL, AUTOCALC_MODE); + ret = regmap_read_poll_timeout(dsi2->regmap, DSI2_MODE_STATUS, + mode, mode == IDLE_MODE, + 1000, MODE_STATUS_TIMEOUT_US); + if (ret < 0) + dev_err(dsi2->dev, "auto calculation training failed\n"); + } + if (dsi2->mode_flags & MIPI_DSI_MODE_VIDEO) dw_mipi_dsi2_set_vid_mode(dsi2); else @@ -844,6 +861,31 @@ static void dw_mipi_dsi2_enable(struct dw_mipi_dsi2 *dsi2) dw_mipi_dsi2_enable(dsi2->slave); } +static void dw_mipi_dsi2_get_mipi_pixel_clk(struct dw_mipi_dsi2 *dsi2, + struct rockchip_crtc_state *s) +{ + struct drm_display_mode *mode = &dsi2->mode; + u8 k = dsi2->slave ? 2 : 1; + + /* 1.When MIPI works in uncompressed mode: + * (Video Timing Pixel Rate)/(4)=(MIPI Pixel ClockxK)=(dclk_out×K)=dclk_core + * 2.When MIPI works in compressed mode: + * MIPI Pixel Clock = cds_clk / 2 + * MIPI is configured as double channel display mode, K=2, otherwise K=1. + */ + if (dsi2->dsc_enable) { + dsi2->mipi_pixel_rate = s->dsc_cds_clk_rate / 2; + if (dsi2->slave) + dsi2->slave->mipi_pixel_rate = dsi2->mipi_pixel_rate; + + return; + } + + dsi2->mipi_pixel_rate = (mode->crtc_clock * MSEC_PER_SEC) / (4 * k); + if (dsi2->slave) + dsi2->slave->mipi_pixel_rate = dsi2->mipi_pixel_rate; +} + static int dw_mipi_dsi2_encoder_mode_set(struct dw_mipi_dsi2 *dsi2, struct drm_atomic_state *state) { @@ -851,6 +893,7 @@ static int dw_mipi_dsi2_encoder_mode_set(struct dw_mipi_dsi2 *dsi2, struct drm_connector *connector; struct drm_connector_state *conn_state; struct drm_crtc_state *crtc_state; + struct rockchip_crtc_state *vcstate; const struct drm_display_mode *adjusted_mode; struct drm_display_mode *mode = &dsi2->mode; @@ -868,6 +911,7 @@ static int dw_mipi_dsi2_encoder_mode_set(struct dw_mipi_dsi2 *dsi2, return -ENODEV; } + vcstate = to_rockchip_crtc_state(crtc_state); adjusted_mode = &crtc_state->adjusted_mode; drm_mode_copy(mode, adjusted_mode); @@ -877,6 +921,8 @@ static int dw_mipi_dsi2_encoder_mode_set(struct dw_mipi_dsi2 *dsi2, if (dsi2->slave) drm_mode_copy(&dsi2->slave->mode, mode); + dw_mipi_dsi2_get_mipi_pixel_clk(dsi2, vcstate); + return 0; } @@ -1167,6 +1213,7 @@ static int dw_mipi_dsi2_dual_channel_probe(struct dw_mipi_dsi2 *dsi2) dsi2->slave->master = dsi2; dsi2->lanes /= 2; + dsi2->slave->auto_calc_mode = dsi2->auto_calc_mode; dsi2->slave->lanes = dsi2->lanes; dsi2->slave->channel = dsi2->channel; dsi2->slave->format = dsi2->format; @@ -1642,6 +1689,9 @@ static int dw_mipi_dsi2_probe(struct platform_device *pdev) dsi2->pdata = of_device_get_match_data(dev); platform_set_drvdata(pdev, dsi2); + if (device_property_read_bool(dev, "auto-calculation-mode")) + dsi2->auto_calc_mode = true; + if (device_property_read_bool(dev, "disable-hold-mode")) dsi2->disable_hold_mode = true; diff --git a/drivers/video/rockchip/vtunnel/rkvtunnel.c b/drivers/video/rockchip/vtunnel/rkvtunnel.c index a2ce451b7cda..2068e3f05357 100644 --- a/drivers/video/rockchip/vtunnel/rkvtunnel.c +++ b/drivers/video/rockchip/vtunnel/rkvtunnel.c @@ -72,7 +72,6 @@ struct rkvt_dev { char *dev_name; int inst_id_generator; atomic64_t cid_generator; - atomic64_t buf_id_generator; struct dentry *debug_root; }; @@ -123,6 +122,8 @@ struct rkvt_instance { DECLARE_KFIFO_PTR(fifo_to_producer, struct rkvt_buffer*); struct rkvt_buffer vt_buffers[RKVT_POOL_SIZE]; + + atomic64_t buf_id_generator; }; static unsigned int vt_dev_dbg; @@ -740,10 +741,10 @@ rkvt_reset_proc(struct rkvt_ctrl_data *data, struct rkvt_session *session) mutex_lock(&inst->lock); rkvt_inst_clear_consumer(inst); rkvt_inst_clear_producer(inst); - read_buf_id = atomic64_read(&vt_dev->buf_id_generator); + read_buf_id = atomic64_read(&inst->buf_id_generator); read_buf_id += 0x100; read_buf_id &= ~0xff; - atomic64_set(&vt_dev->buf_id_generator, read_buf_id); + atomic64_set(&inst->buf_id_generator, read_buf_id); mutex_unlock(&inst->lock); rkvt_inst_put(inst); @@ -950,7 +951,7 @@ rkvt_queue_buf(struct rkvt_buf_data *data, struct rkvt_session *session) // buffer id is empty, generate a new id if (base->buffer_id == 0) - base->buffer_id = atomic64_inc_return(&vt_dev->buf_id_generator); + base->buffer_id = atomic64_inc_return(&inst->buf_id_generator); buffer->base = *base; buffer->base.buf_status = RKVT_BUF_QUEUE; buffer->session_pro = session; @@ -1234,7 +1235,7 @@ rkvt_release_buf(struct rkvt_buf_data *data, struct rkvt_session *session) buffer->base.buf_status = RKVT_BUF_RELEASE; mutex_lock(&inst->lock); - read_buf_id = atomic64_read(&vt_dev->buf_id_generator); + read_buf_id = atomic64_read(&inst->buf_id_generator); /* if producer has disconnect */ if (!inst->producer) { rkvt_dbg(RKVT_DBG_BUFFERS, "VTRB [%d], buffer no producer\n", inst->id); @@ -1298,7 +1299,7 @@ rkvt_cancel_buf(struct rkvt_buf_data *data, struct rkvt_session *session) } // buffer id is empty, generate a new id if (buf_base->buffer_id == 0) - buf_base->buffer_id = atomic64_inc_return(&vt_dev->buf_id_generator); + buf_base->buffer_id = atomic64_inc_return(&inst->buf_id_generator); buffer->base = *buf_base; buffer->base.buf_status = RKVT_BUF_RELEASE; buffer->session_pro = session;